<sect1 id="TextWidget">
  <title>Text Widget Overview</title>
  <para>
    GTK has an extremely powerful framework for multiline text editing.
    The primary objects involved in the process are <link linkend="GtkTextBuffer"><type>GtkTextBuffer</type></link>,
    which represents the text being edited, and <link linkend="GtkTextView"><type>GtkTextView</type></link>, a widget
    which can display a <link linkend="GtkTextBuffer"><type>GtkTextBuffer</type></link>. Each buffer can be displayed by
    any number of views.
  </para>
  <para>
    One of the important things to remember about text in GTK is that
    it’s in the UTF-8 encoding. This means that one character can be
    encoded as multiple bytes. Character counts are usually referred to
    as <emphasis>offsets</emphasis>, while byte counts are called
    <emphasis>indexes</emphasis>. If you confuse these two, things will
    work fine with ASCII, but as soon as your buffer contains multibyte
    characters, bad things will happen.
  </para>
  <para>
    Text in a buffer can be marked with <emphasis>tags</emphasis>. A tag
    is an attribute that can be applied to some range of text. For
    example, a tag might be called <quote>bold</quote> 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, <quote>lock</quote> a range
    of text so the user can’t edit it, or countless other things. A tag
    is represented by a <link linkend="GtkTextTag"><type>GtkTextTag</type></link> object. One <link linkend="GtkTextTag"><type>GtkTextTag</type></link> can be
    applied to any number of text ranges in any number of buffers.
  </para>
  <para>
    Each tag is stored in a <link linkend="GtkTextTagTable"><type>GtkTextTagTable</type></link>. 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.
  </para>
  <para>
    Tags can have names, which is convenient sometimes (for example, you
    can name your tag that makes things bold <quote>bold</quote>), but
    they can also be anonymous (which is convenient if you’re creating
    tags on-the-fly).
  </para>
  <para>
    Most text manipulation is accomplished with
    <emphasis>iterators</emphasis>, represented by a <link linkend="GtkTextIter"><type>GtkTextIter</type></link>. An
    iterator represents a position between two characters in the text
    buffer. <link linkend="GtkTextIter"><type>GtkTextIter</type></link> is a struct designed to be allocated on the
    stack; it’s guaranteed to be copiable by value and never contain any
    heap-allocated data. 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).
  </para>
  <para>
    Because of this, iterators can’t be used to preserve positions
    across buffer modifications. To preserve a position, the
    <link linkend="GtkTextMark"><type>GtkTextMark</type></link> object is ideal. You can think of a mark as an
    invisible cursor or insertion point; it floats in the buffer, saving
    a position. If the text surrounding the mark is deleted, the mark
    remains in the position the text once occupied; if text is inserted
    at the mark, the mark ends up either to the left or to the right of
    the new text, depending on its <emphasis>gravity</emphasis>. The
    standard text cursor in left-to-right languages is a mark with right
    gravity, because it stays to the right of inserted text.
  </para>
  <para>
    Like tags, marks can be either named or anonymous. There are two
    marks built-in to <link linkend="GtkTextBuffer"><type>GtkTextBuffer</type></link>; these are named
    <quote>insert</quote> and <quote>selection_bound</quote> and refer
    to the insertion point and the boundary of the selection which is
    not the insertion point, respectively. 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.
  </para>
  <para>
    If you want to place the cursor in response to a user action, be
    sure to use <link linkend="gtk-text-buffer-place-cursor"><function>gtk_text_buffer_place_cursor()</function></link>, which moves both at once
    without causing a temporary selection (moving one then the other
    temporarily selects the range in between the old and new positions).
  </para>
  <para>
    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 <quote></quote> is also considered a line separator.
  </para>
  <para>
    Text buffers support undo and redo if
    <link linkend="gtk-text-buffer-set-enable-undo"><function>gtk_text_buffer_set_enable_undo()</function></link> has been set to <link linkend="TRUE:CAPS"><literal>TRUE</literal></link>. Use
    <link linkend="gtk-text-buffer-undo"><function>gtk_text_buffer_undo()</function></link> or <link linkend="gtk-text-buffer-redo"><function>gtk_text_buffer_redo()</function></link> to perform the
    necessary action. Note that these operations are ignored if the
    buffer is not editable. Developers may want some operations to not
    be undoable. To do this, wrap your changes in
    <link linkend="gtk-text-buffer-begin-irreversible-action"><function>gtk_text_buffer_begin_irreversible_action()</function></link> and
    <link linkend="gtk-text-buffer-end-irreversible-action"><function>gtk_text_buffer_end_irreversible_action()</function></link>.
  </para>
  <sect2>
    <title>Simple Example</title>
    <para>
      The simplest usage of <link linkend="GtkTextView"><type>GtkTextView</type></link> might look like this:
    </para>
    <programlisting language="c">
GtkWidget *view;
GtkTextBuffer *buffer;

view = <link linkend="gtk-text-view-new"><function>gtk_text_view_new()</function></link>;

buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));

gtk_text_buffer_set_text (buffer, &quot;Hello, this is some text&quot;, -1);

/* Now you might put the view in a container and display it on the
 * screen; when the user edits the text, signals on the buffer
 * will be emitted, such as &quot;changed&quot;, &quot;insert_text&quot;, and so on.
 */
</programlisting>
    <para>
      In many cases it’s also convenient to first create the buffer with
      <link linkend="gtk-text-buffer-new"><function>gtk_text_buffer_new()</function></link>, then create a widget for that buffer with
      <link linkend="gtk-text-view-new-with-buffer"><function>gtk_text_view_new_with_buffer()</function></link>. Or you can change the buffer the
      widget displays after the widget is created with
      <link linkend="gtk-text-view-set-buffer"><function>gtk_text_view_set_buffer()</function></link>.
    </para>
  </sect2>
  <sect2>
    <title>Example of Changing Text Attributes</title>
    <para>
      The way to affect text attributes in <link linkend="GtkTextView"><type>GtkTextView</type></link> is to apply tags
      that change the attributes for a region of text. For text features
      that come from the theme — such as font and foreground color – use
      CSS to override their default values.
    </para>
    <programlisting>
GtkWidget *view;
GtkTextBuffer *buffer;
GtkTextIter start, end;
PangoFontDescription *font_desc;
GdkRGBA rgba;
GtkTextTag *tag;
GtkCssProvider *provider;
GtkStyleContext *context;

view = <link linkend="gtk-text-view-new"><function>gtk_text_view_new()</function></link>;

buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));

gtk_text_buffer_set_text (buffer, &quot;Hello, this is some text&quot;, -1);

/* Change default font and color throughout the widget */
provider = <link linkend="gtk-css-provider-new"><function>gtk_css_provider_new()</function></link>;
gtk_css_provider_load_from_data (provider,
                                 &quot;textview {&quot;
                                 &quot; font: 15 serif;&quot;
                                 &quot;  color: green;&quot;
                                 &quot;}&quot;,
                                 -1);
context = gtk_widget_get_style_context (view);
gtk_style_context_add_provider (context,
                                GTK_STYLE_PROVIDER (provider),
                                GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);

/* Change left margin throughout the widget */
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), 30);

/* Use a tag to change the color for just one part of the widget */
tag = gtk_text_buffer_create_tag (buffer, &quot;blue_foreground&quot;,
                                  &quot;foreground&quot;, &quot;blue&quot;,
                                  NULL);  
gtk_text_buffer_get_iter_at_offset (buffer, &amp;amp;start, 7);
gtk_text_buffer_get_iter_at_offset (buffer, &amp;amp;end, 12);
gtk_text_buffer_apply_tag (buffer, tag, &amp;amp;start, &amp;amp;end);
</programlisting>
    <para>
      The <literal>gtk4-demo</literal> application that comes with GTK
      contains more example code for <link linkend="GtkTextView"><type>GtkTextView</type></link>.
    </para>
  </sect2>
</sect1>
