[gtkmm] Gtk::TextIter: Make a real const_iterator



commit 001e714e54b10d8bb3d7417046c6c4605b7a9b2f
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Thu Jan 12 16:46:25 2017 +0100

    Gtk::TextIter: Make a real const_iterator
    
    Make a small class hierarchy with TextIterBase, TextIter and TextConstIter.
    Define TextBuffer::iterator and TextBuffer::const_iterator aliases.
    Use const_iterator where appropriate in TextBuffer and TextView.
    Bug 142126

 gtk/src/textbuffer.ccg  |   57 ++++++-
 gtk/src/textbuffer.hg   |   71 ++++++---
 gtk/src/textiter.ccg    |   38 ++---
 gtk/src/textiter.hg     |  404 +++++++++++++++++++++++++++++++----------------
 gtk/src/textmark.ccg    |    6 +-
 gtk/src/textmark.hg     |    6 +-
 gtk/src/texttag.hg      |    2 +
 gtk/src/textview.hg     |   19 ++-
 tools/m4/convert_gtk.m4 |   12 +-
 9 files changed, 410 insertions(+), 205 deletions(-)
---
diff --git a/gtk/src/textbuffer.ccg b/gtk/src/textbuffer.ccg
index 1877004..a2bb360 100644
--- a/gtk/src/textbuffer.ccg
+++ b/gtk/src/textbuffer.ccg
@@ -37,7 +37,8 @@ static guint8* SignalProxy_Serialize(GtkTextBuffer* /* register_buffer */,
 
   try
   {
-    return (*the_slot)(Glib::wrap(content_buffer, true), Glib::wrap(start), Glib::wrap(end), *length);
+    return (*the_slot)(Glib::wrap(content_buffer, true),
+      Glib::wrap_const_iter(start), Glib::wrap_const_iter(end), *length);
   }
   catch (...)
   {
@@ -62,7 +63,8 @@ static gboolean SignalProxy_Deserialize(GtkTextBuffer* /* register_buffer */,
 
   try
   {
-    return (*the_slot)(Glib::wrap(content_buffer, true), Glib::wrap(iter), data, length, create_tags);
+    return (*the_slot)(Glib::wrap(content_buffer, true),
+      Glib::wrap_iter(iter), data, length, create_tags);
   }
   catch (Glib::Error& err)
   {
@@ -124,6 +126,11 @@ TextBuffer::iterator TextBuffer::get_iter_at_line_offset(int line_number, int ch
   return iter;
 }
 
+TextBuffer::const_iterator TextBuffer::get_iter_at_line_offset(int line_number, int char_offset) const
+{
+  return const_cast<TextBuffer*>(this)->get_iter_at_line_offset(line_number, char_offset);
+}
+
 TextBuffer::iterator TextBuffer::get_iter_at_line_index(int line_number, int byte_index)
 {
   iterator iter;
@@ -131,6 +138,11 @@ TextBuffer::iterator TextBuffer::get_iter_at_line_index(int line_number, int byt
   return iter;
 }
 
+TextBuffer::const_iterator TextBuffer::get_iter_at_line_index(int line_number, int byte_index) const
+{
+  return const_cast<TextBuffer*>(this)->get_iter_at_line_index(line_number, byte_index);
+}
+
 TextBuffer::iterator TextBuffer::get_iter_at_offset(int char_offset)
 {
   iterator iter;
@@ -138,6 +150,11 @@ TextBuffer::iterator TextBuffer::get_iter_at_offset(int char_offset)
   return iter;
 }
 
+TextBuffer::const_iterator TextBuffer::get_iter_at_offset(int char_offset) const
+{
+  return const_cast<TextBuffer*>(this)->get_iter_at_offset(char_offset);
+}
+
 TextBuffer::iterator TextBuffer::get_iter_at_line(int line_number)
 {
   iterator iter;
@@ -145,6 +162,11 @@ TextBuffer::iterator TextBuffer::get_iter_at_line(int line_number)
   return iter;
 }
 
+TextBuffer::const_iterator TextBuffer::get_iter_at_line(int line_number) const
+{
+  return const_cast<TextBuffer*>(this)->get_iter_at_line(line_number);
+}
+
 TextBuffer::iterator TextBuffer::begin()
 {
   iterator iter;
@@ -152,6 +174,11 @@ TextBuffer::iterator TextBuffer::begin()
   return iter;
 }
 
+TextBuffer::const_iterator TextBuffer::begin() const
+{
+  return const_cast<TextBuffer*>(this)->begin();
+}
+
 TextBuffer::iterator TextBuffer::end()
 {
   iterator iter;
@@ -159,11 +186,21 @@ TextBuffer::iterator TextBuffer::end()
   return iter;
 }
 
+TextBuffer::const_iterator TextBuffer::end() const
+{
+  return const_cast<TextBuffer*>(this)->end();
+}
+
 void TextBuffer::get_bounds(iterator& range_begin, iterator& range_end)
 {
   gtk_text_buffer_get_bounds(gobj(), range_begin.gobj(), range_end.gobj());
 }
 
+void TextBuffer::get_bounds(const_iterator& range_begin, const_iterator& range_end) const
+{
+  gtk_text_buffer_get_bounds(const_cast<GtkTextBuffer*>(gobj()), range_begin.gobj(), range_end.gobj());
+}
+
 TextBuffer::iterator TextBuffer::get_iter_at_mark(const Glib::RefPtr<Mark>& mark)
 {
   iterator iter;
@@ -171,6 +208,11 @@ TextBuffer::iterator TextBuffer::get_iter_at_mark(const Glib::RefPtr<Mark>& mark
   return iter;
 }
 
+TextBuffer::const_iterator TextBuffer::get_iter_at_mark(const Glib::RefPtr<Mark>& mark) const
+{
+  return const_cast<TextBuffer*>(this)->get_iter_at_mark(mark);
+}
+
 void TextBuffer::set_text(const Glib::ustring& text)
 {
   gtk_text_buffer_set_text(gobj(), text.data(), text.bytes());
@@ -435,7 +477,7 @@ TextBuffer::iterator TextBuffer::insert_markup(const iterator& pos, const char*
 }
 
 TextBuffer::iterator TextBuffer::insert(const iterator& pos,
-                                        const iterator& range_begin, const iterator& range_end)
+                                        const const_iterator& range_begin, const const_iterator& range_end)
 {
   iterator iterCopy (pos);
   gtk_text_buffer_insert_range(gobj(), iterCopy.gobj(), range_begin.gobj(), range_end.gobj());
@@ -443,8 +485,8 @@ TextBuffer::iterator TextBuffer::insert(const iterator& pos,
 }
 
 std::pair<TextBuffer::iterator,bool>
-TextBuffer::insert_interactive(const iterator& pos, const iterator& range_begin,
-                               const iterator& range_end, bool default_editable)
+TextBuffer::insert_interactive(const iterator& pos, const const_iterator& range_begin,
+                               const const_iterator& range_end, bool default_editable)
 {
   // Since we have to copy the iterator anyway we can as well create the
   // std::pair now.  That saves another copy later (mind you, TextIter is
@@ -516,6 +558,11 @@ TextBuffer::iterator TextBuffer::get_iter_at_child_anchor(const Glib::RefPtr<Chi
   return iter;
 }
 
+TextBuffer::const_iterator TextBuffer::get_iter_at_child_anchor(const Glib::RefPtr<ChildAnchor>& anchor) 
const
+{
+  return const_cast<TextBuffer*>(this)->get_iter_at_child_anchor(anchor);
+}
+
 int TextBuffer::size() const
 {
   return get_char_count();
diff --git a/gtk/src/textbuffer.hg b/gtk/src/textbuffer.hg
index 8c59989..721f251 100644
--- a/gtk/src/textbuffer.hg
+++ b/gtk/src/textbuffer.hg
@@ -36,9 +36,6 @@ _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
@@ -51,7 +48,8 @@ class TextIter;
  * 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
+ * Most text manipulation is accomplished with iterators, represented by an @link Gtk::TextIter 
iterator@endlink
+ * or a @link Gtk::ConstTextIter const_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
@@ -80,6 +78,7 @@ class TextBuffer : public Glib::Object
            gtk_text_buffer_get_iter_at_child_anchor, gtk_text_buffer_insert_markup)
 public:
   typedef TextIter iterator;
+  typedef TextConstIter const_iterator;
   typedef TextTag Tag;
   typedef TextTagTable TagTable;
   typedef TextMark Mark;
@@ -141,7 +140,6 @@ public:
    * 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);
 
@@ -150,7 +148,6 @@ public:
    *
    * @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);
 
@@ -218,7 +215,7 @@ public:
    * @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);
+  iterator insert(const iterator& pos, const const_iterator& range_begin, const const_iterator& range_end);
   _IGNORE(gtk_text_buffer_insert_range)
 
   /** Same as insert_range(), but does nothing if the insertion point isn't editable.
@@ -232,7 +229,7 @@ public:
    * @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);
+  std::pair<iterator,bool> insert_interactive(const iterator& pos, const const_iterator& range_begin, const 
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);
@@ -355,7 +352,7 @@ public:
   iterator backspace(const iterator& iter, bool interactive = true, bool default_editable = true);
   _IGNORE(gtk_text_buffer_backspace)
 
-  _WRAP_METHOD(Glib::ustring get_text(const iterator& range_start, const iterator& range_end, bool 
include_hidden_chars = true) const, gtk_text_buffer_get_text)
+  _WRAP_METHOD(Glib::ustring get_text(const const_iterator& range_start, const const_iterator& range_end, 
bool include_hidden_chars = true) const, gtk_text_buffer_get_text)
 
   /** Returns all the text in the buffer. Excludes undisplayed
    * text (text marked with tags that set the invisibility attribute) if
@@ -370,7 +367,7 @@ public:
    */
   Glib::ustring get_text(bool include_hidden_chars = true) const;
 
-  _WRAP_METHOD(Glib::ustring get_slice(const iterator& range_start, const iterator& range_end, bool 
include_hidden_chars = true) const, gtk_text_buffer_get_slice)
+  _WRAP_METHOD(Glib::ustring get_slice(const const_iterator& range_start, const const_iterator& range_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)
@@ -441,12 +438,19 @@ public:
   Glib::RefPtr<Tag> create_tag();
 
   iterator get_iter_at_line_offset(int line_number, int char_offset);
+  const_iterator get_iter_at_line_offset(int line_number, int char_offset) const;
   iterator get_iter_at_line_index(int line_number, int byte_index);
+  const_iterator get_iter_at_line_index(int line_number, int byte_index) const;
   iterator get_iter_at_offset(int char_offset);
+  const_iterator get_iter_at_offset(int char_offset) const;
   iterator get_iter_at_line(int line_number);
+  const_iterator get_iter_at_line(int line_number) const;
   iterator begin();
+  const_iterator begin() const;
   iterator end();
+  const_iterator end() const;
   void get_bounds(iterator& range_begin, iterator& range_end);
+  void get_bounds(const_iterator& range_begin, const_iterator& range_end) const;
 
   /** Get the current position of a mark.
    * @param mark The @link Gtk::TextMark Gtk::TextBuffer::Mark@endlink
@@ -454,12 +458,24 @@ public:
    */
   iterator get_iter_at_mark(const Glib::RefPtr<Mark>& mark);
 
+  /** 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.
+   */
+  const_iterator get_iter_at_mark(const Glib::RefPtr<Mark>& mark) const;
+
   /** 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);
 
+  /** 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.
+   */
+  const_iterator get_iter_at_child_anchor(const Glib::RefPtr<ChildAnchor>& anchor) const;
+
   _WRAP_METHOD(bool get_modified() const, gtk_text_buffer_get_modified)
   _WRAP_METHOD(void set_modified(bool setting = true), gtk_text_buffer_set_modified)
 
@@ -473,7 +489,8 @@ public:
   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& range_start, iterator& range_end) const, 
gtk_text_buffer_get_selection_bounds)
+  _WRAP_METHOD(bool get_selection_bounds(iterator& range_start, iterator& range_end), 
gtk_text_buffer_get_selection_bounds)
+  _WRAP_METHOD(bool get_selection_bounds(const_iterator& range_start, const_iterator& range_end) const, 
gtk_text_buffer_get_selection_bounds, constversion)
   _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)
@@ -482,20 +499,22 @@ public:
   _WRAP_METHOD(void begin_user_action(), gtk_text_buffer_begin_user_action)
   _WRAP_METHOD(void end_user_action(), gtk_text_buffer_end_user_action)
 
-  _WRAP_METHOD(Glib::RefPtr<TargetList> get_copy_target_list() const, gtk_text_buffer_get_copy_target_list, 
refreturn)
-  _WRAP_METHOD(Glib::RefPtr<TargetList> get_paste_target_list() const, 
gtk_text_buffer_get_paste_target_list, refreturn)
+  _WRAP_METHOD(Glib::RefPtr<TargetList> get_copy_target_list(), gtk_text_buffer_get_copy_target_list, 
refreturn)
+  _WRAP_METHOD(Glib::RefPtr<const TargetList> get_copy_target_list() const, 
gtk_text_buffer_get_copy_target_list, refreturn, constversion)
+  _WRAP_METHOD(Glib::RefPtr<TargetList> get_paste_target_list(), gtk_text_buffer_get_paste_target_list, 
refreturn)
+  _WRAP_METHOD(Glib::RefPtr<const TargetList> get_paste_target_list() const, 
gtk_text_buffer_get_paste_target_list, refreturn, constversion)
 
   /** For instance,<br>
-   * guint8* on_serialize(const Glib::RefPtr<TextBuffer>& content_buffer, const iterator& start, const 
iterator& end, gsize& length);
+   * guint8* on_serialize(const Glib::RefPtr<TextBuffer>& content_buffer, const const_iterator& range_start, 
const const_iterator& range_end, gsize& length);
    *
    * @param content_buffer The TextBuffer to serialize. It may be different from
    *        the TextBuffer where the serialize format is registered.
-   * @param start Start of the block of text to serialize.
-   * @param end End of the block of text to serialize.
+   * @param range_start Start of the block of text to serialize.
+   * @param range_end End of the block of text to serialize.
    * @param[out] length The length of the serialized data.
-   * @return A newly-allocated array of guint8 which contains the serialized data, or <tt>0</tt> if an error 
occurred.
+   * @return A newly-allocated array of guint8 which contains the serialized data, or <tt>nullptr</tt> if an 
error occurred.
    */
- typedef sigc::slot<guint8*(const Glib::RefPtr<TextBuffer>&, const iterator&, const iterator&, gsize&)> 
SlotSerialize;
+ typedef sigc::slot<guint8*(const Glib::RefPtr<TextBuffer>&, const const_iterator&, const const_iterator&, 
gsize&)> SlotSerialize;
 
   /** For instance,<br>
    * bool on_deserialize(const Glib::RefPtr<TextBuffer>& content_buffer, iterator& iter, const guint8* data, 
gsize length, bool create_tags);
@@ -555,9 +574,9 @@ public:
 
   _WRAP_METHOD(guint8* serialize(const Glib::RefPtr<TextBuffer>& content_buffer,
                                  const Glib::ustring& format,
-                                 const iterator& range_start,
-                                 const iterator& range_end,
-                                 gsize& length), gtk_text_buffer_serialize)
+                                 const const_iterator& range_start,
+                                 const const_iterator& range_end,
+                                 gsize& length) const, gtk_text_buffer_serialize)
 
   _WRAP_METHOD(bool deserialize(const Glib::RefPtr<TextBuffer>& content_buffer,
                                 const Glib::ustring& format,
@@ -568,20 +587,22 @@ public:
 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)')
+_CONVERSION(`GtkTextIter*',`TextBuffer::iterator&',Glib::wrap_iter($3))
 #m4end
-  _WRAP_SIGNAL(void insert(const TextBuffer::iterator& pos, const Glib::ustring& text, int bytes), 
"insert_text")
+  _WRAP_SIGNAL(void insert(TextBuffer::iterator& pos, const Glib::ustring& text, int bytes), "insert_text")
 
 #m4 _CONVERSION(`GdkPixbuf*',`const Glib::RefPtr<Gdk::Pixbuf>&', Glib::wrap($3, true))
-  _WRAP_SIGNAL(void insert_pixbuf(const TextBuffer::iterator& pos, const Glib::RefPtr<Gdk::Pixbuf>& pixbuf), 
"insert_pixbuf")
+  _WRAP_SIGNAL(void insert_pixbuf(TextBuffer::iterator& pos, const Glib::RefPtr<Gdk::Pixbuf>& pixbuf), 
"insert_pixbuf")
 
 #m4 _CONVERSION(`GtkTextChildAnchor*',`const Glib::RefPtr<ChildAnchor>&',`Glib::wrap($3, true)')
-  _WRAP_SIGNAL(void insert_child_anchor(const TextBuffer::iterator& pos, const Glib::RefPtr<ChildAnchor>& 
anchor), "insert_child_anchor")
+  _WRAP_SIGNAL(void insert_child_anchor(TextBuffer::iterator& pos, const Glib::RefPtr<ChildAnchor>& anchor), 
"insert_child_anchor")
 
-  _WRAP_SIGNAL(void erase(const TextBuffer::iterator& range_start, const TextBuffer::iterator& range_end), 
"delete_range")
+  _WRAP_SIGNAL(void erase(TextBuffer::iterator& range_start, TextBuffer::iterator& range_end), 
"delete_range")
   _WRAP_SIGNAL(void changed(), "changed")
   _WRAP_SIGNAL(void modified_changed(), "modified_changed")
 
 #m4 _CONVERSION(`GtkTextMark*',`const Glib::RefPtr<TextBuffer::Mark>&',`Glib::wrap($3, true)')
+#m4 _CONVERSION(`const GtkTextIter*',`const TextBuffer::iterator&',Glib::wrap_iter($3))
   _WRAP_SIGNAL(void mark_set(const TextBuffer::iterator& location, const Glib::RefPtr<TextBuffer::Mark>& 
mark), "mark_set")
 
 #m4 _CONVERSION(`GtkTextTag*',`const Glib::RefPtr<TextBuffer::Tag>&',`Glib::wrap($3, true)')
diff --git a/gtk/src/textiter.ccg b/gtk/src/textiter.ccg
index 7e0e1ca..1570514 100644
--- a/gtk/src/textiter.ccg
+++ b/gtk/src/textiter.ccg
@@ -16,45 +16,41 @@
  */
 
 #include <glibmm/vectorutils.h>
-
-#include <gtkmm/texttag.h>
+#include <gdkmm/pixbuf.h>
 #include <gtkmm/textbuffer.h>
+#include <gtkmm/textmark.h>
+#include <gtkmm/textchildanchor.h>
 
 namespace Gtk
 {
 
-/**** Gtk::TextIter ********************************************************/
+/**** Gtk::TextIterBase *******************************************************/
 
-bool TextIter::starts_tag() const
-{
-  return gtk_text_iter_starts_tag(const_cast<GtkTextIter*>(gobj()), nullptr /* see C docs */);
-}
+} // namespace Gtk
 
-bool TextIter::ends_tag() const
+namespace Glib
 {
-  return gtk_text_iter_ends_tag(const_cast<GtkTextIter*>(gobj()), nullptr /* see C docs */);
-}
+// Can't have overloaded functions that differ only in return type.
+// These can't be called Glib::wrap().
 
-bool TextIter::toggles_tag() const
+Gtk::TextIter& wrap_iter(GtkTextIter* object)
 {
-  return gtk_text_iter_toggles_tag(const_cast<GtkTextIter*>(gobj()), nullptr /* see C docs */);
+  return *reinterpret_cast<Gtk::TextIter*>(object);
 }
 
-bool TextIter::has_tag() const
+const Gtk::TextIter& wrap_iter(const GtkTextIter* object)
 {
-  return gtk_text_iter_has_tag(const_cast<GtkTextIter*>(gobj()), nullptr /* see C docs */);
+  return *reinterpret_cast<const Gtk::TextIter*>(object);
 }
 
-bool TextIter::forward_search(const Glib::ustring& str, TextSearchFlags flags, TextIter& match_start, 
TextIter& match_end) const
+Gtk::TextConstIter& wrap_const_iter(GtkTextIter* object)
 {
-  return gtk_text_iter_forward_search(const_cast<GtkTextIter*>(gobj()), str.c_str(), 
((GtkTextSearchFlags)(flags)), (match_start).gobj(), (match_end).gobj(), nullptr /* means end() - see C docs 
*/);
+  return *reinterpret_cast<Gtk::TextConstIter*>(object);
 }
 
-bool TextIter::backward_search(const Glib::ustring& str, TextSearchFlags flags, TextIter& match_start, 
TextIter& match_end) const
+const Gtk::TextConstIter& wrap_const_iter(const GtkTextIter* object)
 {
-  return gtk_text_iter_backward_search(const_cast<GtkTextIter*>(gobj()), str.c_str(), 
((GtkTextSearchFlags)(flags)), (match_start).gobj(), (match_end).gobj(), nullptr /* means end - see C docs 
*/);
+  return *reinterpret_cast<const Gtk::TextConstIter*>(object);
 }
 
-
-} // namespace Gtk
-
+} // namespace Glib
diff --git a/gtk/src/textiter.hg b/gtk/src/textiter.hg
index 24c515e..e3afb84 100644
--- a/gtk/src/textiter.hg
+++ b/gtk/src/textiter.hg
@@ -1,31 +1,33 @@
 /* Copyright(C) 1998-2002 The gtkmm Development Team
  *
- * This library is free software, ) you can redistribute it and/or
+ * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation, ) either
- * version 2.1 of the License, or(at your option) any later version.
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library, ) if not, write to the Free Software
+ * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 #include <vector>
-
+#include <pangomm/language.h>
 #include <glibmm/exceptionhandler.h>
-#include <gdkmm/pixbuf.h>
 #include <gtkmm/texttag.h>
-#include <gtkmm/textchildanchor.h>
 #include <gtk/gtk.h> /* we need the definition of GtkTextIter */
 
-
 _DEFS(gtkmm,gtk)
 
+namespace Gdk
+{
+class Pixbuf;
+}
+
 namespace Gtk
 {
 
@@ -34,50 +36,37 @@ _WRAP_ENUM(TextSearchFlags, GtkTextSearchFlags)
 
 class TextBuffer;
 class TextMark;
+class TextChildAnchor;
 
 //TODO: Maybe we should have separate iterators for words, lines, and sentences.
-/** Typefed as Gtk::TextBuffer::iterator.
- * An iterator represents a position between two characters in the text buffer. Iterators are not valid 
indefinitely; whenever the buffer is
- * modified in a way that affects the number of characters in the buffer, all outstanding iterators become 
invalid. (Note that
- * deleting 5 characters and then reinserting 5 still invalidates iterators, though you end up with the same 
number of characters
- * you pass through a state with a different number).
+/** Common base class of TextIter and TextConstIter.
  *
- * Because of this, 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.
- *
- * You can iterate over characters, words, lines, and sentences,
- * but operator*() and operator++() deal only in characters.
+ * You don't create objects of this base class. Objects shall be either TextIter
+ * or TextConstIter.
  *
+ * @see TextIter
  * @ingroup TextView
  */
-class TextIter
+class TextIterBase
 {
-  _CLASS_BOXEDTYPE_STATIC(TextIter, GtkTextIter)
+  _CLASS_BOXEDTYPE_STATIC(TextIterBase, GtkTextIter)
   _IGNORE(gtk_text_iter_copy, gtk_text_iter_free, gtk_text_iter_equal)
   _IGNORE(gtk_text_iter_assign)
 public:
-  typedef std::bidirectional_iterator_tag iterator_category;
-  typedef gunichar                        value_type;
-  typedef int                             difference_type;
-  typedef value_type                      reference;
-  typedef void                            pointer;
-
-  /** Alias for forward_char(). */
-  inline TextIter&      operator++();
-  inline const TextIter operator++(int);
-
-  /** Alias for backward_char(). */
-  inline TextIter&      operator--();
-  inline const TextIter operator--(int);
+  using iterator_category = std::bidirectional_iterator_tag;
+  using value_type        = gunichar;
+  using difference_type   = int;
+  using reference         = value_type;
+  using pointer           = void;
 
   /** Alias for get_char(). */
   inline value_type operator*() const;
 
-   /** Alias for !is_end()
+   /** Alias for !is_end().
    * For instance,
    * @code
-   * if(textiter)
-   *   do_something()
+   * if (textiter)
+   *   do_something();
    * @endcode
     *
     * @newin{3,22}
@@ -87,7 +76,7 @@ public:
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 
 protected:
-  template <class Predicate>
+  template <typename Predicate>
   struct PredicateAdapter
   {
     Predicate predicate_;
@@ -106,7 +95,6 @@ protected:
 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
 
 public:
-  _WRAP_METHOD(Glib::RefPtr<TextBuffer> get_buffer() const, gtk_text_iter_get_buffer, refreturn)
 
   _WRAP_METHOD(int get_offset() const, gtk_text_iter_get_offset)
   _WRAP_METHOD(int get_line() const, gtk_text_iter_get_line)
@@ -117,37 +105,17 @@ public:
   _WRAP_METHOD(int get_visible_line_index() const, gtk_text_iter_get_visible_line_index)
 
   _WRAP_METHOD(gunichar get_char() const, gtk_text_iter_get_char)
-  _WRAP_METHOD(Glib::ustring get_slice(const TextIter& end) const, gtk_text_iter_get_slice)
-  _WRAP_METHOD(Glib::ustring get_text(const TextIter& end) const, gtk_text_iter_get_text)
-  _WRAP_METHOD(Glib::ustring get_visible_slice(const TextIter& end) const, gtk_text_iter_get_visible_slice)
-  _WRAP_METHOD(Glib::ustring get_visible_text(const TextIter& end) const, gtk_text_iter_get_visible_text)
-
-  _WRAP_METHOD(Glib::RefPtr<Gdk::Pixbuf> get_pixbuf() const, gtk_text_iter_get_pixbuf, refreturn)
-#m4 _CONVERSION(`GSList*',`std::vector< Glib::RefPtr<TextMark> >',`Glib::SListHandler<Glib::RefPtr<TextMark> 
::slist_to_vector($3, Glib::OWNERSHIP_SHALLOW)')
-  _WRAP_METHOD(std::vector< Glib::RefPtr<TextMark> > get_marks(), gtk_text_iter_get_marks)
-#m4 _CONVERSION(`GSList*',`std::vector< Glib::RefPtr<const TextMark> 
',`Glib::SListHandler<Glib::RefPtr<const TextMark> >::slist_to_vector($3, Glib::OWNERSHIP_SHALLOW)')
-  _WRAP_METHOD(std::vector< Glib::RefPtr<const TextMark> > get_marks() const, gtk_text_iter_get_marks)
-
-  _WRAP_METHOD(Glib::RefPtr<TextChildAnchor> get_child_anchor(), gtk_text_iter_get_child_anchor, refreturn)
-  _WRAP_METHOD(Glib::RefPtr<const TextChildAnchor> get_child_anchor() const, gtk_text_iter_get_child_anchor, 
refreturn)
-
-#m4 _CONVERSION(`GSList*',`std::vector< Glib::RefPtr<TextTag> >',`Glib::SListHandler<Glib::RefPtr<TextTag> 
::slist_to_vector($3, Glib::OWNERSHIP_SHALLOW)')
-  _WRAP_METHOD(std::vector< Glib::RefPtr<TextTag> > get_toggled_tags(bool toggled_on = true), 
gtk_text_iter_get_toggled_tags)
-#m4 _CONVERSION(`GSList*',`std::vector< Glib::RefPtr<const TextTag> 
',`Glib::SListHandler<Glib::RefPtr<const TextTag> >::slist_to_vector($3, Glib::OWNERSHIP_SHALLOW)')
-  _WRAP_METHOD(std::vector< Glib::RefPtr<const TextTag> > get_toggled_tags(bool toggled_on = true) const, 
gtk_text_iter_get_toggled_tags)
 
-  _WRAP_METHOD(bool starts_tag(const Glib::RefPtr<const TextTag>& tag) const, gtk_text_iter_starts_tag)
-  bool starts_tag() const;
-  _WRAP_METHOD(bool ends_tag(const Glib::RefPtr<const TextTag>& tag) const, gtk_text_iter_ends_tag)
-  bool ends_tag() const;
-  _WRAP_METHOD(bool toggles_tag(const Glib::RefPtr<const TextTag>& tag) const, gtk_text_iter_toggles_tag)
-  bool toggles_tag() const;
+#m4 _CONVERSION(`const TextIterBase&', `const GtkTextIter*', __FR2P)
+  _WRAP_METHOD(Glib::ustring get_slice(const TextIterBase& end) const, gtk_text_iter_get_slice)
+  _WRAP_METHOD(Glib::ustring get_text(const TextIterBase& end) const, gtk_text_iter_get_text)
+  _WRAP_METHOD(Glib::ustring get_visible_slice(const TextIterBase& end) const, 
gtk_text_iter_get_visible_slice)
+  _WRAP_METHOD(Glib::ustring get_visible_text(const TextIterBase& end) const, gtk_text_iter_get_visible_text)
 
+  _WRAP_METHOD(bool starts_tag(const Glib::RefPtr<const TextTag>& tag = Glib::RefPtr<const TextTag>()) 
const, gtk_text_iter_starts_tag)
+  _WRAP_METHOD(bool ends_tag(const Glib::RefPtr<const TextTag>& tag = Glib::RefPtr<const TextTag>()) const, 
gtk_text_iter_ends_tag)
+  _WRAP_METHOD(bool toggles_tag(const Glib::RefPtr<const TextTag>& tag = Glib::RefPtr<const TextTag>()) 
const, gtk_text_iter_toggles_tag)
   _WRAP_METHOD(bool has_tag(const Glib::RefPtr<const TextTag>& tag) const, gtk_text_iter_has_tag)
-  bool has_tag() const;
-
-  _WRAP_METHOD(std::vector< Glib::RefPtr<TextTag> > get_tags(), gtk_text_iter_get_tags)
-  _WRAP_METHOD(std::vector< Glib::RefPtr<const TextTag> > get_tags() const, gtk_text_iter_get_tags)
 
   _WRAP_METHOD(bool editable(bool default_setting = true) const, gtk_text_iter_editable)
   _WRAP_METHOD(bool can_insert(bool default_editability = true) const, gtk_text_iter_can_insert)
@@ -184,7 +152,7 @@ public:
 
   _WRAP_METHOD(bool forward_visible_line(), gtk_text_iter_forward_visible_line)
   _WRAP_METHOD(bool backward_visible_line(), gtk_text_iter_backward_visible_line)
-  _WRAP_METHOD(bool forward_visible_line(int count), gtk_text_iter_forward_visible_lines)
+  _WRAP_METHOD(bool forward_visible_lines(int count), gtk_text_iter_forward_visible_lines)
   _WRAP_METHOD(bool backward_visible_lines(int count), gtk_text_iter_backward_visible_lines)
 
   //TODO: Now that there are so many *_visible_ versions of the methods, maybe we should
@@ -220,71 +188,161 @@ public:
   _WRAP_METHOD(void set_visible_line_offset(int char_on_line), gtk_text_iter_set_visible_line_offset)
   _WRAP_METHOD(void set_visible_line_index(int byte_on_line), gtk_text_iter_set_visible_line_index)
 
-  _WRAP_METHOD(bool forward_to_tag_toggle(const Glib::RefPtr<TextTag>& tag), 
gtk_text_iter_forward_to_tag_toggle)
-  _WRAP_METHOD(bool backward_to_tag_toggle(const Glib::RefPtr<TextTag>& tag), 
gtk_text_iter_backward_to_tag_toggle)
+  _WRAP_METHOD(bool forward_to_tag_toggle(const Glib::RefPtr<const TextTag>& tag = Glib::RefPtr<const 
TextTag>()), gtk_text_iter_forward_to_tag_toggle)
+  _WRAP_METHOD(bool backward_to_tag_toggle(const Glib::RefPtr<const TextTag>& tag = Glib::RefPtr<const 
TextTag>()), gtk_text_iter_backward_to_tag_toggle)
+
+  template <typename Predicate>
+  bool forward_find_char(const Predicate& predicate, const TextIterBase& limit);
+  template <typename Predicate>
+  bool forward_find_char(const Predicate& predicate);
+  template <typename Predicate>
+  bool backward_find_char(const Predicate& predicate, const TextIterBase& limit);
+  template <typename Predicate>
+  bool backward_find_char(const Predicate& predicate);
+
+  _WRAP_METHOD(int compare(const TextIterBase& rhs) const, gtk_text_iter_compare)
+  _WRAP_METHOD(bool in_range(const TextIterBase& start, const TextIterBase& end) const, 
gtk_text_iter_in_range)
+
+  _WRAP_EQUAL_AND_COMPARE(gtk_text_iter_equal, gtk_text_iter_compare)
+
+}; // end TextIterBase
+
+
+/** Typedefed as Gtk::TextBuffer::iterator.
+ *
+ * An iterator represents a position between two characters in the text buffer.
+ * Iterators are not valid indefinitely; whenever the buffer is modified in a way that
+ * affects the number of characters in the buffer, all outstanding iterators become invalid.
+ * (Note that deleting 5 characters and then reinserting 5 still invalidates iterators,
+ * though you end up with the same number of characters you pass through a state with
+ * a different number).
+ *
+ * Because of this, 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.
+ *
+ * You can iterate over characters, words, lines, and sentences,
+ * but operator*() and operator++() deal only in characters.
+ *
+ * @ingroup TextView
+ */
+class TextIter : public TextIterBase
+{
+  _CLASS_GENERIC(TextIter, GtkTextIter)
+public:
+  /** Alias for forward_char(). */
+  inline TextIter& operator++();
+  inline TextIter  operator++(int);
+
+  /** Alias for backward_char(). */
+  inline TextIter& operator--();
+  inline TextIter  operator--(int);
+
+  _WRAP_METHOD(Glib::RefPtr<TextBuffer> get_buffer() const, gtk_text_iter_get_buffer, refreturn)
+
+  _WRAP_METHOD(Glib::RefPtr<Gdk::Pixbuf> get_pixbuf() const, gtk_text_iter_get_pixbuf, refreturn)
+
+#m4 _CONVERSION(`GSList*',`std::vector<Glib::RefPtr<TextMark>>',`Glib::SListHandler<Glib::RefPtr<TextMark> 
::slist_to_vector($3, Glib::OWNERSHIP_SHALLOW)')
+  _WRAP_METHOD(std::vector<Glib::RefPtr<TextMark>> get_marks() const, gtk_text_iter_get_marks)
 
-  template <class Predicate> bool forward_find_char(const Predicate& predicate, const TextIter& limit);
-  template <class Predicate> bool forward_find_char(const Predicate& predicate);
-  template <class Predicate> bool backward_find_char(const Predicate& predicate, const TextIter& limit);
-  template <class Predicate> bool backward_find_char(const Predicate& predicate);
+  _WRAP_METHOD(Glib::RefPtr<TextChildAnchor> get_child_anchor() const, gtk_text_iter_get_child_anchor, 
refreturn)
 
+#m4 _CONVERSION(`GSList*',`std::vector<Glib::RefPtr<TextTag>>',`Glib::SListHandler<Glib::RefPtr<TextTag> 
::slist_to_vector($3, Glib::OWNERSHIP_SHALLOW)')
+  _WRAP_METHOD(std::vector<Glib::RefPtr<TextTag>> get_toggled_tags(bool toggled_on = true) const, 
gtk_text_iter_get_toggled_tags)
+
+  _WRAP_METHOD(std::vector<Glib::RefPtr<TextTag>> get_tags() const, gtk_text_iter_get_tags)
+
+#m4 _CONVERSION(`TextIter&', `GtkTextIter*', __FR2P)
   _WRAP_METHOD(bool forward_search(const Glib::ustring& str,
                                    TextSearchFlags flags,
                                    TextIter& match_start,
                                    TextIter& match_end,
-                                   const TextIter& limit) const, gtk_text_iter_forward_search)
-
-  /** Same as forward_search(), but searchs to the end.
-   *
-   * @param str A search string.
-   * @param flags Flags affecting how the search is done.
-   * @param match_start Return location for start of match, or <tt>0</tt>.
-   * @param match_end Return location for end of match, or <tt>0</tt>.
-   * @return Whether a match was found.
-   */
-   bool forward_search(const Glib::ustring& str, TextSearchFlags flags, TextIter& match_start, TextIter& 
match_end) const;
+                                   const TextIterBase& limit{?}) const, gtk_text_iter_forward_search)
 
   _WRAP_METHOD(bool backward_search(const Glib::ustring& str,
                                     TextSearchFlags flags,
                                     TextIter& match_start,
                                     TextIter& match_end,
-                                    const TextIter& limit) const, gtk_text_iter_backward_search)
-
-  /** Same as backward_search(), but searches to the start.
-   * @param str Search string.
-   * @param flags Bitmask of flags affecting the search.
-   * @param match_start Return location for start of match, or <tt>0</tt>.
-   * @param match_end Return location for end of match, or <tt>0</tt>.
-   * @return Whether a match was found.
-   */
-  bool backward_search(const Glib::ustring& str, TextSearchFlags flags, TextIter& match_start, TextIter& 
match_end) const;
+                                    const TextIterBase& limit{?}) const, gtk_text_iter_backward_search)
 
-  _WRAP_METHOD(int compare(const TextIter& rhs) const, gtk_text_iter_compare)
-  _WRAP_METHOD(bool in_range(const TextIter& start, const TextIter& end) const, gtk_text_iter_in_range)
   _WRAP_METHOD(void order(TextIter& second), gtk_text_iter_order)
-
-  _WRAP_EQUAL_AND_COMPARE(gtk_text_iter_equal, gtk_text_iter_compare)
 };
 
 
+/** Typedefed as Gtk::TextBuffer::const_iterator.
+ *
+ * @see TextIter
+ * @ingroup TextView
+ */
+class TextConstIter : public TextIterBase
+{
+  _CLASS_GENERIC(TextConstIter, GtkTextIter)
+public:
+  /** A TextIter can be implicitly converted to a TextConstIter.
+   */
+  inline TextConstIter(const TextIter& other) noexcept;
+
+  /** A TextIter can be assigned to a TextConstIter.
+   */
+  inline TextConstIter& operator=(const TextIter& other) noexcept;
+
+  /** Alias for forward_char(). */
+  inline TextConstIter& operator++();
+  inline TextConstIter  operator++(int);
+
+  /** Alias for backward_char(). */
+  inline TextConstIter& operator--();
+  inline TextConstIter  operator--(int);
+
+  _WRAP_METHOD(Glib::RefPtr<const TextBuffer> get_buffer() const, gtk_text_iter_get_buffer, refreturn)
+
+  _WRAP_METHOD(Glib::RefPtr<const Gdk::Pixbuf> get_pixbuf() const, gtk_text_iter_get_pixbuf, refreturn)
+
+#m4 _CONVERSION(`GSList*',`std::vector<Glib::RefPtr<const TextMark>>',`Glib::SListHandler<Glib::RefPtr<const 
TextMark> >::slist_to_vector($3, Glib::OWNERSHIP_SHALLOW)')
+  _WRAP_METHOD(std::vector<Glib::RefPtr<const TextMark>> get_marks() const, gtk_text_iter_get_marks)
+
+  _WRAP_METHOD(Glib::RefPtr<const TextChildAnchor> get_child_anchor() const, gtk_text_iter_get_child_anchor, 
refreturn)
+
+#m4 _CONVERSION(`GSList*',`std::vector<Glib::RefPtr<const TextTag>>',`Glib::SListHandler<Glib::RefPtr<const 
TextTag> >::slist_to_vector($3, Glib::OWNERSHIP_SHALLOW)')
+  _WRAP_METHOD(std::vector<Glib::RefPtr<const TextTag>> get_toggled_tags(bool toggled_on = true) const, 
gtk_text_iter_get_toggled_tags)
+
+  _WRAP_METHOD(std::vector<Glib::RefPtr<const TextTag>> get_tags() const, gtk_text_iter_get_tags)
+
+#m4 _CONVERSION(`TextConstIter&', `GtkTextIter*', __FR2P)
+  _WRAP_METHOD(bool forward_search(const Glib::ustring& str,
+                                   TextSearchFlags flags,
+                                   TextConstIter& match_start,
+                                   TextConstIter& match_end,
+                                   const TextIterBase& limit{?}) const, gtk_text_iter_forward_search)
+
+  _WRAP_METHOD(bool backward_search(const Glib::ustring& str,
+                                    TextSearchFlags flags,
+                                    TextConstIter& match_start,
+                                    TextConstIter& match_end,
+                                    const TextIterBase& limit{?}) const, gtk_text_iter_backward_search)
+
+  _WRAP_METHOD(void order(TextConstIter& second), gtk_text_iter_order)
+};
+
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 
-template <class Predicate> inline
-TextIter::PredicateAdapter<Predicate>::PredicateAdapter(const Predicate& predicate)
+/**** Gtk::TextIterBase *******************************************************/
+
+template <typename Predicate> inline
+TextIterBase::PredicateAdapter<Predicate>::PredicateAdapter(const Predicate& predicate)
 :
-  predicate_ (predicate)
+  predicate_(predicate)
 {}
 
 // static
-template <class Predicate>
-gboolean TextIter::PredicateAdapter<Predicate>::gtk_callback(gunichar uc, void* user_data)
+template <typename Predicate>
+gboolean TextIterBase::PredicateAdapter<Predicate>::gtk_callback(gunichar uc, void* user_data)
 {
   try
   {
     // This will either use Predicate::operator(), or call a function pointer.
     // The explicit conditional expression avoids relying on an implicit
     // conversion of the return type to int, which might be not available.
-    return (static_cast<TextIter::PredicateAdapter<Predicate>*>(user_data)->predicate_(uc)) ? 1 : 0;
+    return (static_cast<TextIterBase::PredicateAdapter<Predicate>*>(user_data)->predicate_(uc)) ? 1 : 0;
   }
   catch(...)
   {
@@ -294,6 +352,52 @@ gboolean TextIter::PredicateAdapter<Predicate>::gtk_callback(gunichar uc, void*
 }
 
 inline
+TextIterBase::value_type TextIterBase::operator*() const
+{
+  return get_char();
+}
+
+inline
+TextIterBase::operator bool() const
+{
+  return !is_end();
+}
+
+template <typename Predicate>
+bool TextIterBase::forward_find_char(const Predicate& predicate, const TextIterBase& limit)
+{
+  typedef TextIterBase::PredicateAdapter<Predicate> PredAdapter;
+  PredAdapter adapter(predicate);
+  return this->forward_find_char_impl(&PredAdapter::gtk_callback, &adapter, limit.gobj());
+}
+
+template <typename Predicate>
+bool TextIterBase::forward_find_char(const Predicate& predicate)
+{
+  typedef TextIterBase::PredicateAdapter<Predicate> PredAdapter;
+  PredAdapter adapter(predicate);
+  return this->forward_find_char_impl(&PredAdapter::gtk_callback, &adapter, nullptr);
+}
+
+template <typename Predicate>
+bool TextIterBase::backward_find_char(const Predicate& predicate, const TextIterBase& limit)
+{
+  typedef TextIterBase::PredicateAdapter<Predicate> PredAdapter;
+  PredAdapter adapter(predicate);
+  return this->backward_find_char_impl(&PredAdapter::gtk_callback, &adapter, limit.gobj());
+}
+
+template <typename Predicate>
+bool TextIterBase::backward_find_char(const Predicate& predicate)
+{
+  typedef TextIterBase::PredicateAdapter<Predicate> PredAdapter;
+  PredAdapter adapter(predicate);
+  return this->backward_find_char_impl(&PredAdapter::gtk_callback, &adapter, nullptr);
+}
+
+/**** Gtk::TextIter ***********************************************************/
+
+inline
 TextIter& TextIter::operator++()
 {
   forward_char();
@@ -301,9 +405,9 @@ TextIter& TextIter::operator++()
 }
 
 inline
-const TextIter TextIter::operator++(int)
+TextIter TextIter::operator++(int)
 {
-  const TextIter temp (*this);
+  const TextIter temp(*this);
   forward_char();
   return temp;
 }
@@ -316,57 +420,87 @@ TextIter& TextIter::operator--()
 }
 
 inline
-const TextIter TextIter::operator--(int)
+TextIter TextIter::operator--(int)
 {
-  const TextIter temp (*this);
+  const TextIter temp(*this);
   backward_char();
   return temp;
 }
 
-inline
-TextIter::value_type TextIter::operator*() const
+/**** Gtk::TextConstIter ******************************************************/
+
+TextConstIter::TextConstIter(const TextIter& other) noexcept
+: TextIterBase(other.gobj())
 {
-  return get_char();
 }
 
-inline
-TextIter::operator bool() const
+TextConstIter& TextConstIter::operator=(const TextIter& other) noexcept
 {
-  return !is_end();
+  gobject_ = *other.gobj();
+  return *this;
 }
 
-template <class Predicate>
-bool TextIter::forward_find_char(const Predicate& predicate, const TextIter& limit)
+inline
+TextConstIter& TextConstIter::operator++()
 {
-  typedef TextIter::PredicateAdapter<Predicate> PredAdapter;
-  PredAdapter adapter (predicate);
-  return this->forward_find_char_impl(&PredAdapter::gtk_callback, &adapter, limit.gobj());
+  forward_char();
+  return *this;
 }
 
-template <class Predicate>
-bool TextIter::forward_find_char(const Predicate& predicate)
+inline
+TextConstIter TextConstIter::operator++(int)
 {
-  typedef TextIter::PredicateAdapter<Predicate> PredAdapter;
-  PredAdapter adapter (predicate);
-  return this->forward_find_char_impl(&PredAdapter::gtk_callback, &adapter, nullptr);
+  const TextConstIter temp(*this);
+  forward_char();
+  return temp;
 }
 
-template <class Predicate>
-bool TextIter::backward_find_char(const Predicate& predicate, const TextIter& limit)
+inline
+TextConstIter& TextConstIter::operator--()
 {
-  typedef TextIter::PredicateAdapter<Predicate> PredAdapter;
-  PredAdapter adapter (predicate);
-  return this->backward_find_char_impl(&PredAdapter::gtk_callback, &adapter, limit.gobj());
+  backward_char();
+  return *this;
 }
 
-template <class Predicate>
-bool TextIter::backward_find_char(const Predicate& predicate)
+inline
+TextConstIter TextConstIter::operator--(int)
 {
-  typedef TextIter::PredicateAdapter<Predicate> PredAdapter;
-  PredAdapter adapter (predicate);
-  return this->backward_find_char_impl(&PredAdapter::gtk_callback, &adapter, nullptr);
+  const TextConstIter temp(*this);
+  backward_char();
+  return temp;
 }
 
 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
 
 } // namespace Gtk
+
+namespace Glib
+{
+// Can't have overloaded functions that differ only in return type.
+// These can't be called Glib::wrap().
+
+/** @relates Gtk::TextIter
+ * @param object The C instance
+ * @result A C++ instance that wraps this C instance.
+ */
+Gtk::TextIter& wrap_iter(GtkTextIter* object);
+
+/** @relates Gtk::TextIter
+ * @param object The C instance
+ * @result A C++ instance that wraps this C instance.
+ */
+const Gtk::TextIter& wrap_iter(const GtkTextIter* object);
+
+/** @relates Gtk::TextConstIter
+ * @param object The C instance
+ * @result A C++ instance that wraps this C instance.
+ */
+Gtk::TextConstIter& wrap_const_iter(GtkTextIter* object);
+
+/** @relates Gtk::TextConstIter
+ * @param object The C instance
+ * @result A C++ instance that wraps this C instance.
+ */
+const Gtk::TextConstIter& wrap_const_iter(const GtkTextIter* object);
+
+} // namespace Glib
diff --git a/gtk/src/textmark.ccg b/gtk/src/textmark.ccg
index 3a5e17e..aa5b74f 100644
--- a/gtk/src/textmark.ccg
+++ b/gtk/src/textmark.ccg
@@ -37,5 +37,9 @@ TextIter TextMark::get_iter()
   return get_buffer()->get_iter_at_mark(mark);
 }
 
-} //namespace Gtk
+TextConstIter TextMark::get_iter() const
+{
+  return const_cast<TextMark*>(this)->get_iter();
+}
 
+} //namespace Gtk
diff --git a/gtk/src/textmark.hg b/gtk/src/textmark.hg
index 8e85195..d159654 100644
--- a/gtk/src/textmark.hg
+++ b/gtk/src/textmark.hg
@@ -27,6 +27,7 @@ namespace Gtk
 
 class TextBuffer;
 class TextIter;
+class TextConstIter;
 
 /** Typedefed as Gtk::TextBuffer::Mark. A position in the buffer, preserved across buffer modifications.
  *
@@ -45,7 +46,8 @@ class TextIter;
  * "left" and "right" here refer to logical direction (left is the toward the start of the buffer); in some 
languages such as
  * Hebrew the logically-leftmost text is not actually on the left when displayed.
  *
- * You can convert the mark to an @link Gtk::TextIter iterator@endlink using 
Gtk::TextBuffer::get_iter_at_mark().
+ * You can convert the mark to an @link Gtk::TextIter iterator@endlink or
+ * a @link Gtk::TextConstIter const_iterator@endlink using Gtk::TextBuffer::get_iter_at_mark().
  *
  * Marks can be deleted from the buffer at any time with Gtk::TextBuffer::delete_mark(). Once deleted from 
the buffer, a mark is essentially useless.
  *
@@ -130,8 +132,8 @@ public:
   _WRAP_METHOD(Glib::RefPtr<const TextBuffer> get_buffer() const, gtk_text_mark_get_buffer, refreturn, 
constversion)
   _WRAP_METHOD(bool get_left_gravity() const, gtk_text_mark_get_left_gravity)
 
-  //TODO: Add a const overload, if we have a ConstTextIter.
   TextIter get_iter();
+  TextConstIter get_iter() const;
 
   _WRAP_PROPERTY("name", Glib::ustring)
   _WRAP_PROPERTY("left-gravity", bool)
diff --git a/gtk/src/texttag.hg b/gtk/src/texttag.hg
index ad48ddf..011ba1b 100644
--- a/gtk/src/texttag.hg
+++ b/gtk/src/texttag.hg
@@ -65,10 +65,12 @@ public:
 
   _WRAP_METHOD(int get_priority() const, gtk_text_tag_get_priority)
   _WRAP_METHOD(void set_priority(int priority), gtk_text_tag_set_priority)
+#m4 _CONVERSION(`const TextIter&',`const GtkTextIter*',__FR2P)
   _WRAP_METHOD(bool event(const Glib::RefPtr<Glib::Object>& event_object, GdkEvent* gdk_event, const 
TextIter& iter), gtk_text_tag_event)
   _WRAP_METHOD(void tag_changed(bool size_changed), gtk_text_tag_changed)
 
 #m4 _CONVERSION(`GObject*',`const Glib::RefPtr<Glib::Object>&',`Glib::wrap($3, true)')
+#m4 _CONVERSION(`const GtkTextIter*',`const TextIter&',`Glib::wrap_iter($3)')
   _WRAP_SIGNAL(bool event(const Glib::RefPtr<Glib::Object>& event_object, GdkEvent* gdk_event, const 
TextIter& iter), "event")
 
   _WRAP_PROPERTY("name", Glib::ustring) //construct-only.
diff --git a/gtk/src/textview.hg b/gtk/src/textview.hg
index 7e0ec8a..d7e0e63 100644
--- a/gtk/src/textview.hg
+++ b/gtk/src/textview.hg
@@ -23,7 +23,6 @@ _CONFIGINCLUDE(gtkmmconfig.h)
 #include <gtkmm/scrollable.h>
 #include <gtkmm/textbuffer.h>
 #include <gtkmm/textmark.h>
-#include <gtkmm/menu.h>
 
 _DEFS(gtkmm,gtk)
 _PINCLUDE(gtkmm/private/container_p.h)
@@ -101,7 +100,7 @@ public:
    */
   void scroll_to(const Glib::RefPtr<TextBuffer::Mark>& mark, double within_margin = 0);
 
- /** Scrolls the TextView so that @a iter is on the screen, in the position indicated by xalign and yalign,
+ /** Scrolls the TextView so that @a mark is on the screen, in the position indicated by xalign and yalign,
    * possibly not scrolling at all. The effective screen for purposes of this function is reduced by a 
margin of size
    * @a within_margin.
    *
@@ -123,14 +122,18 @@ public:
   _WRAP_METHOD(bool get_cursor_visible() const, gtk_text_view_get_cursor_visible)
   _WRAP_METHOD(void reset_cursor_blink(), gtk_text_view_reset_cursor_blink)
 
-  _WRAP_METHOD(void get_cursor_locations(const TextBuffer::iterator& iter,  Gdk::Rectangle& strong,  
Gdk::Rectangle& weak) const, gtk_text_view_get_cursor_locations)
+  _WRAP_METHOD(void get_cursor_locations(const TextBuffer::const_iterator& iter{?},
+    Gdk::Rectangle& strong, Gdk::Rectangle& weak) const, gtk_text_view_get_cursor_locations)
 
-  _WRAP_METHOD(void get_iter_location(const TextBuffer::iterator&  iter, Gdk::Rectangle& location) const, 
gtk_text_view_get_iter_location)
-  _WRAP_METHOD(void get_iter_at_location(TextBuffer::iterator& iter, int x, int y) const, 
gtk_text_view_get_iter_at_location)
-  _WRAP_METHOD(void get_iter_at_position(TextBuffer::iterator& iter, int& trailing, int x, int y) const, 
gtk_text_view_get_iter_at_position)
-  _WRAP_METHOD(void get_line_yrange(const TextBuffer::iterator& iter, int& y, int& height) const, 
gtk_text_view_get_line_yrange)
+  _WRAP_METHOD(void get_iter_location(const TextBuffer::const_iterator&  iter, Gdk::Rectangle& location) 
const, gtk_text_view_get_iter_location)
+  _WRAP_METHOD(void get_iter_at_location(TextBuffer::iterator& iter, int x, int y), 
gtk_text_view_get_iter_at_location)
+  _WRAP_METHOD(void get_iter_at_location(TextBuffer::const_iterator& iter, int x, int y) const, 
gtk_text_view_get_iter_at_location)
+  _WRAP_METHOD(void get_iter_at_position(TextBuffer::iterator& iter, int& trailing, int x, int y), 
gtk_text_view_get_iter_at_position)
+  _WRAP_METHOD(void get_iter_at_position(TextBuffer::const_iterator& iter, int& trailing, int x, int y) 
const, gtk_text_view_get_iter_at_position)
+  _WRAP_METHOD(void get_line_yrange(const TextBuffer::const_iterator& iter, int& y, int& height) const, 
gtk_text_view_get_line_yrange)
 
-  _WRAP_METHOD(void get_line_at_y(TextBuffer::iterator& target_iter, int y, int& line_top) const, 
gtk_text_view_get_line_at_y)
+  _WRAP_METHOD(void get_line_at_y(TextBuffer::iterator& target_iter, int y, int& line_top), 
gtk_text_view_get_line_at_y)
+  _WRAP_METHOD(void get_line_at_y(TextBuffer::const_iterator& target_iter, int y, int& line_top) const, 
gtk_text_view_get_line_at_y)
 
   _WRAP_METHOD(void buffer_to_window_coords(TextWindowType  win,
                                             int buffer_x, int buffer_y,
diff --git a/tools/m4/convert_gtk.m4 b/tools/m4/convert_gtk.m4
index 6d6d7f0..419e3da 100644
--- a/tools/m4/convert_gtk.m4
+++ b/tools/m4/convert_gtk.m4
@@ -410,12 +410,14 @@ _CONVERSION(`const Glib::RefPtr<Tag>&',`GtkTextTag*',__CONVERT_REFPTR_TO_P)
 _CONVERSION(`const Glib::RefPtr<TextBuffer::Tag>&',`GtkTextTag*',__CONVERT_REFPTR_TO_P)
 _CONVERSION(`GtkTextBuffer*',`Glib::RefPtr<TextBuffer>',`Glib::wrap($3)')
 _CONVERSION(`GtkTextBuffer*',`Glib::RefPtr<const TextBuffer>',`Glib::wrap($3)')
-_CONVERSION(`TextIter&',`GtkTextIter*',__FR2P)
 _CONVERSION(`TextBuffer::iterator&',`GtkTextIter*',__FR2P)
+_CONVERSION(`TextBuffer::const_iterator&',`GtkTextIter*',__FR2P)
 _CONVERSION(`iterator&',`GtkTextIter*',__FR2P)
-_CONVERSION(`const TextIter&',`const GtkTextIter*',__FR2P)
+_CONVERSION(`const_iterator&',`GtkTextIter*',__FR2P)
 _CONVERSION(`const TextBuffer::iterator&',`const GtkTextIter*',__FR2P)
+_CONVERSION(`const TextBuffer::const_iterator&',`const GtkTextIter*',__FR2P)
 _CONVERSION(`const iterator&',`const GtkTextIter*',__FR2P)
+_CONVERSION(`const const_iterator&',`const GtkTextIter*',__FR2P)
 _CONVERSION(`const Glib::RefPtr<TextTagTable>&',`GtkTextTagTable*',__CONVERT_REFPTR_TO_P)
 _CONVERSION(`const Glib::RefPtr<TextBuffer>&',`GtkTextBuffer*',__CONVERT_REFPTR_TO_P)
 _CONVERSION(`const Glib::RefPtr<TextChildAnchor>&',`GtkTextChildAnchor*',__CONVERT_REFPTR_TO_P)
@@ -627,12 +629,6 @@ _CONVERSION(`const Glib::RefPtr<Tooltip>&',`GtkTooltip*',__CONVERT_REFPTR_TO_P($
 # TODO: Move these to the .hg files.
 # The true here means "take reference", because the code that emits the signal does not do a ref for the 
receiving signal handler.
 # For the return values of methods, we use the optional refreturn parameter instead.
-_CONVERSION(`GtkTextIter*',`const TextIter&',Glib::wrap($3))
-_CONVERSION(`GtkTextIter*',`const TextBuffer::iterator&',Glib::wrap($3))
-_CONVERSION(`const GtkTextIter*',`const TextIter&',Glib::wrap($3))
-_CONVERSION(`const GtkTextIter*',`const TextBuffer::iterator&',Glib::wrap($3))
-_CONVERSION(`const TextIter&',`GtkTextIter*',__FCR2P)
-_CONVERSION(`const TextBuffer::iterator&',`GtkTextIter*',__FCR2P)
 _CONVERSION(`GtkTreePath*',`const TreeModel::Path&',`Gtk::TreePath($3, true)')
 _CONVERSION(`GtkTreePath*',`const Path&',`Gtk::TreePath($3, true)')
 _CONVERSION(`TreeViewColumn*',`GtkTreeViewColumn*',__FP2P)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]