// included by gt_demo.pas

(* Text Widget
 *
 * The GtkTextView widget displays a GtkTextBuffer. One GtkTextBuffer
 * can be displayed by multiple GtkTextViews. This demo has two views
 * displaying a single buffer, and shows off the widget's text
 * formatting features.
 *
 *)

var
  text_window,
  text_egg_window : PGtkWidget;

procedure easter_egg_callback (button  : PGtkWidget;
                               data    : gpointer); forward; cdecl;

const
  gray50_width  = 2;
  gray50_height = 2;

  gray50_bits: array [0..1] of char = (#2, #1);

procedure create_tags (buffer : PGtkTextBuffer);
var
  stipple : PGdkBitmap;

begin
  (* Create a bunch of tags. Note that it's also possible to
   * create tags with gtk_text_tag_new() then add them to the
   * tag table for the buffer, gtk_text_buffer_create_tag() is
   * just a convenience function. Also note that you don't have
   * to give tags a name; pass NULL for the name to create an
   * anonymous tag.
   *
   * In any real app, another useful optimization would be to create
   * a GtkTextTagTable in advance, and reuse the same tag table for
   * all the buffers with the same tag set, instead of creating
   * new copies of the same tags for every buffer.
   *
   * Tags are assigned default priorities in order of addition to the
   * tag table.  That is, tags created later that affect the same text
   * property affected by an earlier tag will override the earlier
   * tag.  You can modify tag priorities with
   * gtk_text_tag_set_priority().
   *)

  gtk_text_buffer_create_tag (buffer, 'heading',
                              'weight', [ PANGO_WEIGHT_BOLD,
                              'size', 15 * PANGO_SCALE,
                              NULL] );

  gtk_text_buffer_create_tag (buffer, 'italic',
                              'style', [PANGO_STYLE_ITALIC, NULL]);

  gtk_text_buffer_create_tag (buffer, 'bold',
                              'weight', [ PANGO_WEIGHT_BOLD, NULL] );

  gtk_text_buffer_create_tag (buffer, 'big',
                              (* points times the PANGO_SCALE factor *)
                              'size', [ 20 * PANGO_SCALE, NULL] );

  gtk_text_buffer_create_tag (buffer, 'xx-small',
                              'scale',[ PANGO_SCALE_XX_SMALL, NULL] );

  gtk_text_buffer_create_tag (buffer, 'x-large',
                              'scale', [ PANGO_SCALE_X_LARGE, NULL] );

  gtk_text_buffer_create_tag (buffer, 'monospace',
                              'family', [ 'monospace', NULL]);

  gtk_text_buffer_create_tag (buffer, 'blue_foreground',
                              'foreground', [ 'blue', NULL] );

  gtk_text_buffer_create_tag (buffer, 'red_background',
                              'background', [ 'red', NULL] );

  stipple := gdk_bitmap_create_from_data (NULL,
                                         gray50_bits, gray50_width,
                                         gray50_height);

  gtk_text_buffer_create_tag (buffer, 'background_stipple',
                              'background_stipple',[  stipple, NULL] );

  gtk_text_buffer_create_tag (buffer, 'foreground_stipple',
                              'foreground_stipple', [stipple, NULL]);

  g_object_unref (pGObject(stipple));

  gtk_text_buffer_create_tag (buffer, 'big_gap_before_line',
                              'pixels_above_lines', [30, NULL]);

  gtk_text_buffer_create_tag (buffer, 'big_gap_after_line',
                              'pixels_below_lines', [30, NULL]);

  gtk_text_buffer_create_tag (buffer, 'double_spaced_line',
                              'pixels_inside_wrap', [10, NULL]);

  gtk_text_buffer_create_tag (buffer, 'not_editable',
                              'editable', [FALSE, NULL]);

  gtk_text_buffer_create_tag (buffer, 'word_wrap',
                              'wrap_mode', [GTK_WRAP_WORD, NULL]);

  gtk_text_buffer_create_tag (buffer, 'char_wrap',
                              'wrap_mode', [GTK_WRAP_CHAR, NULL]);

  gtk_text_buffer_create_tag (buffer, 'no_wrap',
                              'wrap_mode', [GTK_WRAP_NONE, NULL]);

  gtk_text_buffer_create_tag (buffer, 'center',
                              'justification', [GTK_JUSTIFY_CENTER, NULL]);

  gtk_text_buffer_create_tag (buffer, 'right_justify',
                              'justification', [GTK_JUSTIFY_RIGHT, NULL]);

  gtk_text_buffer_create_tag (buffer, 'wide_margins',
                              'left_margin', [50, 'right_margin', 50,
                              NULL]);

  gtk_text_buffer_create_tag (buffer, 'strikethrough',
                              'strikethrough', [TRUE, NULL]);

  gtk_text_buffer_create_tag (buffer, 'underline',
                              'underline', [PANGO_UNDERLINE_SINGLE, NULL]);

  gtk_text_buffer_create_tag (buffer, 'double_underline',
                              'underline', [PANGO_UNDERLINE_DOUBLE, NULL]);

  gtk_text_buffer_create_tag (buffer, 'superscript',
                              'rise', [10 * PANGO_SCALE,          (* 10 pixels *)
                              'size',   8 * PANGO_SCALE,          (* 8 points *)
                              NULL]);

  gtk_text_buffer_create_tag (buffer, 'subscript',
                              'rise', [-10 * PANGO_SCALE,   (* 10 pixels *)
                              'size',    8 * PANGO_SCALE,   (* 8 points *)
                              NULL]);

  gtk_text_buffer_create_tag (buffer, 'rtl_quote',
                              'wrap_mode', [ GTK_WRAP_WORD,
                              'direction',   GTK_TEXT_DIR_RTL,
                              'indent', 30,
                              'left_margin', 20,
                              'right_margin', 20,
                              NULL]);
end;

procedure insert_text (buffer : PGtkTextBuffer);
var
  iter,
  text_start,
  text_end     : TGtkTextIter;
  pixbuf,
  scaled       : PGdkPixbuf;
  filename     : pchar;

begin
  (* demo_find_file() looks in the the current directory first,
   * so you can run gtk-demo without installing GTK, then looks
   * in the location where the file is installed.
   *)
  pixbuf := NULL;
  filename := demo_find_file ('gtk-logo-rgb.gif', NULL);

  if filename <> NULL then
    begin
      pixbuf := gdk_pixbuf_new_from_file (filename, NULL);
      g_free (filename);
    end;

  if pixbuf = NULL then
  begin
    g_error ('Failed to load image file gtk-logo-rgb.gif'#13#10);
    exit;
  end;

  scaled := gdk_pixbuf_scale_simple (pixbuf, 32, 32, GDK_INTERP_BILINEAR);
  g_object_unref (pGObject(pixbuf));
  pixbuf := scaled;

  (* get start of buffer; each insertion will revalidate the
   * iterator to point to just after the inserted text.
   *)
  gtk_text_buffer_get_iter_at_offset (buffer, @iter, 0);

  gtk_text_buffer_insert (buffer, @iter,
      'The text widget can display text with all kinds of nifty attributes. '
    + 'It also supports multiple views of the same buffer; '
    + 'this demo is showing the same buffer in two places.'#13#10#13#10, -1);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter, 'Font styles. ', -1,
                                            'heading');

  gtk_text_buffer_insert (buffer, @iter, 'For example, you can have ', -1);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'italic', -1,
                                            'italic');     // test: left out last argument " NULL "
  gtk_text_buffer_insert (buffer, @iter, ', ', -1);
  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'bold', -1,
                                            'bold');
  gtk_text_buffer_insert (buffer, @iter, ', or ', -1);
  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'monospace (typewriter)', -1,
                                            'monospace');
  gtk_text_buffer_insert (buffer, @iter, ', or ', -1);
  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'big', -1,
                                            'big');
  gtk_text_buffer_insert (buffer, @iter, ' text. ', -1);
  gtk_text_buffer_insert (buffer, @iter,
      'It''s best not to hardcode specific text sizes; '
    + 'you can use relative sizes as with CSS, such as ', -1);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'xx-small', -1,
                                            'xx-small');
  gtk_text_buffer_insert (buffer, @iter, ' or ', -1);
  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'x-large', -1,
                                            'x-large');
  gtk_text_buffer_insert (buffer, @iter,
      ' to ensure that your program properly adapts if the user '
    + ' changes the default font size.'#13#10#13#10, -1);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter, 'Colors. ', -1,
                                            'heading');

  gtk_text_buffer_insert (buffer, @iter, 'Colors such as ', -1);
  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'a blue foreground', -1,
                                            'blue_foreground');
  gtk_text_buffer_insert (buffer, @iter, ' or ', -1);
  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'a red background', -1,
                                            'red_background');
  gtk_text_buffer_insert (buffer, @iter, ' or even ', -1);
  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'a stippled red background', -1,
                                            'red_background',
                                            ['background_stipple',
                                            NULL]);

  gtk_text_buffer_insert (buffer, @iter, ' or ', -1);
  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'a stippled blue foreground on solid red background', -1,
                                            'blue_foreground',
                       ['red_background',
                                            'foreground_stipple',
                                            NULL]);
  gtk_text_buffer_insert (buffer, @iter, ' (select that to read it) can be used.'#13#10#13#10, -1);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter, 'Underline, strikethrough, and rise. ', -1,
                                            'heading');

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'Strikethrough', -1,
                                            'strikethrough');
  gtk_text_buffer_insert (buffer, @iter, ', ', -1);
  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'underline', -1,
                                            'underline');
  gtk_text_buffer_insert (buffer, @iter, ', ', -1);
  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'double underline', -1,
                                            'double_underline');
  gtk_text_buffer_insert (buffer, @iter, ', ', -1);
  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'superscript', -1,
                                            'superscript');
  gtk_text_buffer_insert (buffer, @iter, ', and ', -1);
  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'subscript', -1,
                                            'subscript');
  gtk_text_buffer_insert (buffer, @iter, ' are all supported.'#13#10#13#10, -1);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter, 'Images. ', -1,
                                            'heading');

  gtk_text_buffer_insert (buffer, @iter, 'The buffer can have images in it: ', -1);
  gtk_text_buffer_insert_pixbuf (buffer, @iter, pixbuf);
  gtk_text_buffer_insert_pixbuf (buffer, @iter, pixbuf);
  gtk_text_buffer_insert_pixbuf (buffer, @iter, pixbuf);
  gtk_text_buffer_insert (buffer, @iter, ' for example.'#13#10, -1);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter, 'Spacing. ', -1,
                                            'heading', [NULL]);

  gtk_text_buffer_insert (buffer, @iter, 'You can adjust the amount of space before each line.'#13#10, -1);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'This line has a whole lot of space before it.'#13#10, -1,
                                            'big_gap_before_line', ['wide_margins', NULL]);
  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'You can also adjust the amount of space after each line; '
                      + 'this line has a whole lot of space after it.'#13#10, -1,
                                            'big_gap_after_line', ['wide_margins', NULL]);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'You can also adjust the amount of space between wrapped lines; '
                      + 'this line has extra space between each wrapped line in the same paragraph. '
                      + 'To show off wrapping, some filler text: the quick brown fox jumped over '
                      + 'the lazy dog. Blah blah blah blah blah blah blah blah blah.'#13#10, -1,
                                            'double_spaced_line', ['wide_margins', NULL]);

  gtk_text_buffer_insert (buffer, @iter, 'Also note that those lines have extra-wide margins.'#13#10#13#10, -1);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter, 'Editability. ', -1,
                                            'heading', [NULL]);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'This line is ''locked down'' and can''t be edited by the user - '
                      + 'just try it! You can''t delete this line.'#13#10#13#10, -1,
                                            'not_editable', [NULL]);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter, 'Wrapping. ', -1,
                                            'heading', [NULL]);

  gtk_text_buffer_insert (buffer, @iter,
                          'This line (and most of the others in this buffer) is word-wrapped, '
            + 'using the proper Unicode algorithm. Word wrap should work in all '
            + 'scripts and languages that GTK+ supports. Let''s make this a long '
            + 'paragraph to demonstrate: blah blah blah blah blah blah blah blah '
            + 'blah blah blah blah blah blah blah blah blah blah blah'#13#10#13#10, -1);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
              'This line has character-based wrapping, and can wrap between '
            + 'any two character glyphs. Let''s make this a long paragraph to '
            + 'demonstrate: blah blah blah blah blah blah blah blah blah blah '
            + 'blah blah blah blah blah blah blah blah blah'#13#10#13#10, -1,
                                            'char_wrap', [NULL]);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter, PChar(
              'This line has all wrapping turned off, so it makes the horizontal '
            + 'scrollbar appear.'#13#10#13#10#13#10), -1,
                                            'no_wrap', [NULL]);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter, 'Justification. ', -1,
                                            'heading', [NULL]);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            #13#10'This line has center justification.'#13#10, -1,
                                            'center', [NULL]);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                                            'This line has right justification.'#13#10, -1,
                                            'right_justify', [NULL]);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
                    #13#10'This line has big wide margins. Text text text text text text '
        + 'text text text text text text text text text text text text text text '
        + 'text text text text text text text text text text text text text text '
        + 'text text.'#13#10, -1,'wide_margins', [NULL]);

  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter, 'Internationalization. ', -1,
                                            'heading', [NULL]);

  gtk_text_buffer_insert (buffer, @iter,
                  'You can put all sorts of Unicode text in the buffer.'#13#10#13#10
        + 'German (Deutsch Süd) Grüß Gott'#13#10
        + 'Greek (Ελληνικά) Γειά σας'#13#10
        + 'Hebrew       שלום'#13#10
        + 'Japanese (日本語)'#13#10#13#10
        + 'The widget properly handles bidirectional text, word wrapping, '
        + 'DOS/UNIX/Unicode paragraph separators, grapheme boundaries, '
        + 'and so on using the Pango internationalization framework.'#13#10, -1);

  gtk_text_buffer_insert (buffer, @iter, 'Here''s a word-wrapped quote in a right-to-left language:'#13#10, -1);
  gtk_text_buffer_insert_with_tags_by_name (buffer, @iter,
          'وقد بدأ ثلاث من أكثر المؤسسات تقدما في '
        + 'شبكة اكسيون برامجها كمنظمات لا تسعى للربح، '
        + 'ثم تحولت في السنوات الخمس الماضية إلى مؤسسات '
        + 'مالية منظمة، وباتت جزءا من النظام المالي في '
        + 'بلدانها، ولكنها تتخصص في خدمة قطاع المشروعات الصغيرة. '
        + 'وأحد أكثر هذه المؤسسات نجاحا هو »بانكوسول« '
        + 'في بوليفيا.'#13#10#13#10, -1,
                                                'rtl_quote', [NULL]);

  gtk_text_buffer_insert (buffer, @iter, 'You can put widgets in the buffer: Here''s a button: ', -1);
  gtk_text_buffer_create_child_anchor (buffer, @iter);
  gtk_text_buffer_insert (buffer, @iter, ' and a menu: ', -1);
  gtk_text_buffer_create_child_anchor (buffer, @iter);
  gtk_text_buffer_insert (buffer, @iter, ' and a scale: ', -1);
  gtk_text_buffer_create_child_anchor (buffer, @iter);
  gtk_text_buffer_insert (buffer, @iter, ' and an animation: ', -1);
  gtk_text_buffer_create_child_anchor (buffer, @iter);
  gtk_text_buffer_insert (buffer, @iter, ' finally a text entry: ', -1);
  gtk_text_buffer_create_child_anchor (buffer, @iter);
  gtk_text_buffer_insert (buffer, @iter, '.'#13#10, -1);

  gtk_text_buffer_insert (buffer, @iter,
       #13#10#13#10'This demo doesn''t demonstrate all the GtkTextBuffer features; '
     + 'it leaves out, for example: invisible/hidden text (doesn''t work in GTK 2, but planned), '
     + 'tab stops, application-drawn areas on the sides of the widget for displaying breakpoints and such...', -1);

  (* Apply word_wrap tag to whole buffer *)
  gtk_text_buffer_get_bounds (buffer, @text_start, @text_end);
  gtk_text_buffer_apply_tag_by_name (buffer, 'word_wrap', @text_start, @text_end);

  g_object_unref (pGObject(pixbuf));
end;

function find_anchor (iter : PGtkTextIter): gboolean; cdecl;

begin
  while gtk_text_iter_forward_char (iter) do
  begin
    if gtk_text_iter_get_child_anchor (iter)<> NULL then
      exit (TRUE);
  end;
end;

procedure attach_widgets (text_view : PGtkWidget);
var
  iter       : TGtkTextIter;
  buffer     : PGtkTextBuffer;
  i          : integer;

  anchor     : PGtkTextChildAnchor;
  widget,
  menu,
  menu_item  : PGtkWidget;

  filename   : pgchar;

begin
  buffer := gtk_text_view_get_buffer (pGtkTextView(text_view));

  gtk_text_buffer_get_start_iter (buffer, @iter);

  i := 0;
  while find_anchor (@iter) do
  begin
    anchor := gtk_text_iter_get_child_anchor (@iter);

    case i of
      0: begin
           widget := gtk_button_new_with_label ('Click Me');

           g_signal_connect (pGObject(widget), 'clicked',
                        TGCallback(@easter_egg_callback),
                        NULL);
         end;
      1: begin
           menu := gtk_menu_new ();

           widget := gtk_option_menu_new ();

           menu_item := gtk_menu_item_new_with_label ('Option 1');
           gtk_menu_shell_append (pGtkMenuShell(menu), menu_item);

           menu_item := gtk_menu_item_new_with_label ('Option 2');
           gtk_menu_shell_append (pGtkMenuShell(menu), menu_item);

           menu_item := gtk_menu_item_new_with_label ('Option 3');
           gtk_menu_shell_append (pGtkMenuShell(menu), menu_item);

           gtk_option_menu_set_menu (pGtkOptionMenu(widget), menu);
         end;
      2: begin
           widget := gtk_hscale_new (NULL);
           gtk_range_set_range (pGtkRange(widget), 0, 100);
           gtk_widget_set_size_request (widget, 70, -1);
         end;
      3: begin
               filename := demo_find_file ('floppybuddy.gif', NULL);
               widget := gtk_image_new_from_file (filename);
               g_free (filename);
         end;
      4: begin
          widget := gtk_entry_new ();
         end;
      else begin
          widget := NULL; (* avoids a compiler warning *)
          exit;
         end;
    end; {of case}

    if widget <> NULL then
    begin
      gtk_text_view_add_child_at_anchor (pGtkTextView(text_view), widget, anchor);
      gtk_widget_show_all (widget);
    end;

    inc(i);
  end; {of while}
end;


function do_textview       : PGtkWidget;
var
  vpaned,
  view1,
  view2,
  sw       : PGtkWidget;
  buffer   : PGtkTextBuffer;

begin
  if text_window = NULL then
  begin
    text_window := gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size (pGtkWindow(text_window), 450, 450);

    g_signal_connect (text_window, 'destroy',
                        TGCallback(@gtk_widget_destroyed), @text_window);

    gtk_window_set_title (pGtkWindow(text_window), 'TextView');
    gtk_container_set_border_width (pGtkContainer(text_window), 0);

    vpaned := gtk_vpaned_new ();
    gtk_container_set_border_width (pGtkContainer(vpaned), 5);
    gtk_container_add (pGtkContainer(text_window), vpaned);

    (* For convenience, we just use the autocreated buffer from
     * the first text view; you could also create the buffer
     * by itself with gtk_text_buffer_new(), then later create
     * a view widget.
     *)
    view1  := gtk_text_view_new ();
    buffer := gtk_text_view_get_buffer (pGtkTextView(view1));
    view2  := gtk_text_view_new_with_buffer (buffer);

    sw := gtk_scrolled_window_new (NULL, NULL);
    gtk_scrolled_window_set_policy (pGtkScrolledWindow(sw),
                      GTK_POLICY_AUTOMATIC,
                                      GTK_POLICY_AUTOMATIC);

    gtk_paned_add1 (pGtkPaned(vpaned), sw);

    gtk_container_add (pGtkContainer(sw), view1);

    sw := gtk_scrolled_window_new (NULL, NULL);
    gtk_scrolled_window_set_policy (pGtkScrolledWindow(sw),
                      GTK_POLICY_AUTOMATIC,
                                      GTK_POLICY_AUTOMATIC);
    gtk_paned_add2 (pGtkPaned(vpaned), sw);

    gtk_container_add (pGtkContainer(sw), view2);

    create_tags (buffer);
    insert_text (buffer);

    attach_widgets (view1);
    attach_widgets (view2);

    gtk_widget_show_all (vpaned);
  end;

  if not GTK_WIDGET_VISIBLE (text_window) then
    gtk_widget_show (text_window)
  else begin
    gtk_widget_destroy (text_window);
    text_window := NULL;
  end;

  do_textview := text_window;
end;

procedure recursive_attach_view (depth  : integer;
                                 view   : PGtkTextView;
                                 anchor : PGtkTextChildAnchor);
var
  child_view,
  event_box,
  align       : PGtkWidget;
  color       : TGdkColor;

begin
  if depth > 4 then
    exit;

  child_view := gtk_text_view_new_with_buffer (gtk_text_view_get_buffer (view));

  (* Event box is to add a black border around each child view *)
  event_box := gtk_event_box_new ();
  gdk_color_parse ('black', @color);
  gtk_widget_modify_bg (event_box, GTK_STATE_NORMAL, @color);

  align := gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
  gtk_container_set_border_width (pGtkContainer(align), 1);

  gtk_container_add (pGtkContainer(event_box), align);
  gtk_container_add (pGtkContainer(align), child_view);

  gtk_text_view_add_child_at_anchor (view, event_box, anchor);

  recursive_attach_view (depth + 1, pGtkTextView(child_view), anchor);
end;

procedure easter_egg_callback(button : PGtkWidget;
                              data   : gpointer); cdecl;
var
  sw,
  view   : PGtkWidget;
  buffer : PGtkTextBuffer;
  iter   : TGtkTextIter;
  anchor : PGtkTextChildAnchor;

begin
  if text_egg_window <> NULL then
  begin
    gtk_window_present (pGtkWindow(text_egg_window));
    exit;
  end;

  buffer := gtk_text_buffer_new (NULL);

  gtk_text_buffer_get_start_iter (buffer, @iter);

  gtk_text_buffer_insert (buffer, @iter,
                          'This buffer is shared by a set of nested text views.'#13#10'Nested view:'#13#10, -1);
  anchor := gtk_text_buffer_create_child_anchor (buffer, @iter);
  gtk_text_buffer_insert (buffer, @iter,
                          #13#10'Don''t do this in real applications, please.'#13#10, -1);

  view := gtk_text_view_new_with_buffer (buffer);

  recursive_attach_view (0, pGtkTextView(view), anchor);

  g_object_unref (pGObject(buffer));

  text_egg_window := gtk_window_new (GTK_WINDOW_TOPLEVEL);
  sw := gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_policy (pGtkScrolledWindow(sw),
                                  GTK_POLICY_AUTOMATIC,
                                  GTK_POLICY_AUTOMATIC);

  gtk_container_add (pGtkContainer(text_egg_window), sw);
  gtk_container_add (pGtkContainer(sw), view);

  g_object_add_weak_pointer (pGObject(text_egg_window),
                             gpointer (@text_egg_window));

  gtk_window_set_default_size (pGtkWindow(text_egg_window), 300, 400);

  gtk_widget_show_all (text_egg_window);
end;

// included by gt_demo.pas

