]> Pileus Git - ~andy/gtk/blobdiff - tests/testtext.c
Use gtk_box_new() instead gtk_[v|h]box_new()
[~andy/gtk] / tests / testtext.c
index 6541c438373614b1119b3034aecaa55b06bcf885..84159822ca1a92c7c131b936df7584836e32ad51 100644 (file)
@@ -1,3 +1,24 @@
+/* testtext.c
+ * Copyright (C) 2000 Red Hat, Inc
+ * Author: Havoc Pennington
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
 #include <stdio.h>
 #include <sys/stat.h>
 #include <errno.h>
@@ -25,6 +46,10 @@ struct _Buffer
   GtkTextTag *invisible_tag;
   GtkTextTag *not_editable_tag;
   GtkTextTag *found_text_tag;
+  GtkTextTag *rise_tag;
+  GtkTextTag *large_tag;
+  GtkTextTag *indent_tag;
+  GtkTextTag *margin_tag;
   GtkTextTag *custom_tabs_tag;
   GSList *color_tags;
   guint color_cycle_timeout;
@@ -75,14 +100,14 @@ GSList *views = NULL;
 static void
 push_active_window (GtkWindow *window)
 {
-  g_object_ref (G_OBJECT (window));
+  g_object_ref (window);
   active_window_stack = g_slist_prepend (active_window_stack, window);
 }
 
 static void
 pop_active_window (void)
 {
-  gtk_object_unref (active_window_stack->data);
+  g_object_unref (active_window_stack->data);
   active_window_stack = g_slist_delete_link (active_window_stack, active_window_stack);
 }
 
@@ -139,19 +164,19 @@ filesel_run (GtkWindow    *parent,
     gtk_file_selection_set_filename (GTK_FILE_SELECTION (filesel), start_file);
 
   
-  g_object_set_data (G_OBJECT (filesel), "ok-func", (gpointer)func);
+  g_object_set_data (G_OBJECT (filesel), "ok-func", func);
   g_object_set_data (G_OBJECT (filesel), "ok-data", data);
   g_object_set_data (G_OBJECT (filesel), "ok-result", &result);
 
-  gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->ok_button),
-                     "clicked",
-                     GTK_SIGNAL_FUNC (filesel_ok_cb), filesel);
-  gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (filesel)->cancel_button),
-                            "clicked",
-                            GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (filesel));
+  g_signal_connect (GTK_FILE_SELECTION (filesel)->ok_button,
+                   "clicked",
+                   G_CALLBACK (filesel_ok_cb), filesel);
+  g_signal_connect_swapped (GTK_FILE_SELECTION (filesel)->cancel_button,
+                           "clicked",
+                           G_CALLBACK (gtk_widget_destroy), filesel);
 
-  gtk_signal_connect (GTK_OBJECT (filesel), "destroy",
-                     GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
+  g_signal_connect (filesel, "destroy",
+                   G_CALLBACK (gtk_main_quit), NULL);
   gtk_window_set_modal (GTK_WINDOW (filesel), TRUE);
 
   gtk_widget_show (filesel);
@@ -168,14 +193,14 @@ static void
 msgbox_yes_cb (GtkWidget *widget, gboolean *result)
 {
   *result = 0;
-  gtk_object_destroy (GTK_OBJECT (gtk_widget_get_toplevel (widget)));
+  gtk_widget_destroy (gtk_widget_get_toplevel (widget));
 }
 
 static void
 msgbox_no_cb (GtkWidget *widget, gboolean *result)
 {
   *result = 1;
-  gtk_object_destroy (GTK_OBJECT (gtk_widget_get_toplevel (widget)));
+  gtk_widget_destroy (gtk_widget_get_toplevel (widget));
 }
 
 static gboolean
@@ -183,8 +208,8 @@ msgbox_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer data)
 {
   if (event->keyval == GDK_Escape)
     {
-      gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
-      gtk_object_destroy (GTK_OBJECT (widget));
+      g_signal_stop_emission_by_name (widget, "key_press_event");
+      gtk_widget_destroy (widget);
       return TRUE;
     }
 
@@ -226,17 +251,17 @@ msgbox_run (GtkWindow  *parent,
 
   /* Quit our recursive main loop when the dialog is destroyed.
    */
-  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
-                     GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
+  g_signal_connect (dialog, "destroy",
+                   G_CALLBACK (gtk_main_quit), NULL);
 
   /* Catch Escape key presses and have them destroy the dialog
    */
-  gtk_signal_connect (GTK_OBJECT (dialog), "key_press_event",
-                     GTK_SIGNAL_FUNC (msgbox_key_press_cb), NULL);
+  g_signal_connect (dialog, "key_press_event",
+                   G_CALLBACK (msgbox_key_press_cb), NULL);
 
   /* Fill in the contents of the widget
    */
-  vbox = gtk_vbox_new (FALSE, 0);
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
   gtk_container_add (GTK_CONTAINER (dialog), vbox);
   
   label = gtk_label_new (message);
@@ -244,10 +269,10 @@ msgbox_run (GtkWindow  *parent,
   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
   gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
 
-  separator = gtk_hseparator_new ();
+  separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
   gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
 
-  button_box = gtk_hbutton_box_new ();
+  button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
   gtk_box_pack_start (GTK_BOX (vbox), button_box, FALSE, FALSE, 0);
   gtk_container_set_border_width (GTK_CONTAINER (button_box), 8);
   
@@ -258,14 +283,14 @@ msgbox_run (GtkWindow  *parent,
   if (yes_button)
     {
       button = gtk_button_new_with_label (yes_button);
-      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+      gtk_widget_set_can_default (button, TRUE);
       gtk_container_add (GTK_CONTAINER (button_box), button);
 
       if (default_index == 0)
        gtk_widget_grab_default (button);
       
-      gtk_signal_connect (GTK_OBJECT (button), "clicked",
-                         GTK_SIGNAL_FUNC (msgbox_yes_cb), &result);
+      g_signal_connect (button, "clicked",
+                       G_CALLBACK (msgbox_yes_cb), &result);
     }
 
   /* When No is clicked, call the msgbox_no_cb
@@ -274,14 +299,14 @@ msgbox_run (GtkWindow  *parent,
   if (no_button)
     {
       button = gtk_button_new_with_label (no_button);
-      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+      gtk_widget_set_can_default (button, TRUE);
       gtk_container_add (GTK_CONTAINER (button_box), button);
 
       if (default_index == 0)
        gtk_widget_grab_default (button);
       
-      gtk_signal_connect (GTK_OBJECT (button), "clicked",
-                         GTK_SIGNAL_FUNC (msgbox_no_cb), &result);
+      g_signal_connect (button, "clicked",
+                       G_CALLBACK (msgbox_no_cb), &result);
     }
 
   /* When Cancel is clicked, destroy the dialog
@@ -289,14 +314,14 @@ msgbox_run (GtkWindow  *parent,
   if (cancel_button)
     {
       button = gtk_button_new_with_label (cancel_button);
-      GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+      gtk_widget_set_can_default (button, TRUE);
       gtk_container_add (GTK_CONTAINER (button_box), button);
       
       if (default_index == 1)
        gtk_widget_grab_default (button);
       
-      gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
-                                GTK_SIGNAL_FUNC (gtk_object_destroy), GTK_OBJECT (dialog));
+      g_signal_connect_swapped (button, "clicked",
+                               G_CALLBACK (gtk_object_destroy), dialog);
     }
 
   gtk_widget_show_all (dialog);
@@ -308,6 +333,7 @@ msgbox_run (GtkWindow  *parent,
   return result;
 }
 
+#ifdef DO_BLINK
 /*
  * Example buffer filling code
  */
@@ -319,7 +345,7 @@ blink_timeout (gpointer data)
   
   tag = GTK_TEXT_TAG (data);
 
-  g_object_set (G_OBJECT (tag),
+  g_object_set (tag,
                  "foreground", flip ? "blue" : "purple",
                  NULL);
 
@@ -327,6 +353,7 @@ blink_timeout (gpointer data)
 
   return TRUE;
 }
+#endif
 
 static gint
 tag_event_handler (GtkTextTag *tag, GtkWidget *widget, GdkEvent *event,
@@ -393,7 +420,7 @@ tag_event_handler (GtkTextTag *tag, GtkWidget *widget, GdkEvent *event,
 static void
 setup_tag (GtkTextTag *tag)
 {
-  g_signal_connect (G_OBJECT (tag),
+  g_signal_connect (tag,
                    "event",
                    G_CALLBACK (tag_event_handler),
                    NULL);
@@ -442,8 +469,10 @@ fill_example_buffer (GtkTextBuffer *buffer)
   
   tag = gtk_text_buffer_create_tag (buffer, "fg_blue", NULL);
 
-  /*       gtk_timeout_add (1000, blink_timeout, tag); */
-      
+#ifdef DO_BLINK
+  g_timeout_add (1000, (GSourceFunc)blink_timeout, tag);
+#endif     
   setup_tag (tag);
   
   color.red = color.green = 0;
@@ -451,7 +480,7 @@ fill_example_buffer (GtkTextBuffer *buffer)
   color2.red = 0xfff;
   color2.blue = 0x0;
   color2.green = 0;
-  g_object_set (G_OBJECT (tag),
+  g_object_set (tag,
                 "foreground_gdk", &color,
                 "background_gdk", &color2,
                 "size_points", 24.0,
@@ -463,7 +492,7 @@ fill_example_buffer (GtkTextBuffer *buffer)
       
   color.blue = color.green = 0;
   color.red = 0xffff;
-  g_object_set (G_OBJECT (tag),
+  g_object_set (tag,
                 "rise", -4 * PANGO_SCALE,
                 "foreground_gdk", &color,
                 NULL);
@@ -474,7 +503,7 @@ fill_example_buffer (GtkTextBuffer *buffer)
       
   color.blue = color.red = 0;
   color.green = 0xffff;
-  g_object_set (G_OBJECT (tag),
+  g_object_set (tag,
                 "background_gdk", &color,
                 "size_points", 10.0,
                 NULL);
@@ -483,7 +512,7 @@ fill_example_buffer (GtkTextBuffer *buffer)
 
   setup_tag (tag);
       
-  g_object_set (G_OBJECT (tag),
+  g_object_set (tag,
                 "strikethrough", TRUE,
                 NULL);
 
@@ -492,25 +521,27 @@ fill_example_buffer (GtkTextBuffer *buffer)
 
   setup_tag (tag);
       
-  g_object_set (G_OBJECT (tag),
+  g_object_set (tag,
                 "underline", PANGO_UNDERLINE_SINGLE,
                 NULL);
 
+  tag = gtk_text_buffer_create_tag (buffer, "underline_error", NULL);
+
   setup_tag (tag);
       
-  g_object_set (G_OBJECT (tag),
-                "underline", PANGO_UNDERLINE_SINGLE,
+  g_object_set (tag,
+                "underline", PANGO_UNDERLINE_ERROR,
                 NULL);
 
   tag = gtk_text_buffer_create_tag (buffer, "centered", NULL);
       
-  g_object_set (G_OBJECT (tag),
+  g_object_set (tag,
                 "justification", GTK_JUSTIFY_CENTER,
                 NULL);
 
   tag = gtk_text_buffer_create_tag (buffer, "rtl_quote", NULL);
       
-  g_object_set (G_OBJECT (tag),
+  g_object_set (tag,
                 "wrap_mode", GTK_WRAP_WORD,
                 "direction", GTK_TEXT_DIR_RTL,
                 "indent", 30,
@@ -521,7 +552,7 @@ fill_example_buffer (GtkTextBuffer *buffer)
 
   tag = gtk_text_buffer_create_tag (buffer, "negative_indent", NULL);
       
-  g_object_set (G_OBJECT (tag),
+  g_object_set (tag,
                 "indent", -25,
                 NULL);
   
@@ -529,7 +560,7 @@ fill_example_buffer (GtkTextBuffer *buffer)
 
   anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
 
-  g_object_ref (G_OBJECT (anchor));
+  g_object_ref (anchor);
   
   g_object_set_data_full (G_OBJECT (buffer), "anchor", anchor,
                           (GDestroyNotify) g_object_unref);
@@ -558,7 +589,7 @@ fill_example_buffer (GtkTextBuffer *buffer)
                             "(Hello World!)\nfoo foo Hello this is some text we are using to text word wrap. It has punctuation! gee; blah - hmm, great.\nnew line with a significant quantity of text on it. This line really does contain some text. More text! More text! More text!\n"
                             /* This is UTF8 stuff, Emacs doesn't
                                really know how to display it */
-                            "German (Deutsch Süd) Grüß Gott Greek (Ελληνικά) Γειά σας Hebrew(שלום) Hebrew punctuation(\xd6\xbfש\xd6\xbb\xd6\xbc\xd6\xbb\xd6\xbfל\xd6\xbcו\xd6\xbc\xd6\xbb\xd6\xbb\xd6\xbfם\xd6\xbc\xd6\xbb\xd6\xbf) Japanese (日本語) Thai (สวัสดีครับ) Thai wrong spelling (คำต่อไปนื่สะกดผิด พัั้ัั่งโกะ)\n", -1);
+                            "German (Deutsch S\303\274d) Gr\303\274\303\237 Gott Greek (\316\225\316\273\316\273\316\267\316\275\316\271\316\272\316\254) \316\223\316\265\316\271\316\254 \317\203\316\261\317\202 Hebrew(\327\251\327\234\327\225\327\235) Hebrew punctuation(\xd6\xbf\327\251\xd6\xbb\xd6\xbc\xd6\xbb\xd6\xbf\327\234\xd6\xbc\327\225\xd6\xbc\xd6\xbb\xd6\xbb\xd6\xbf\327\235\xd6\xbc\xd6\xbb\xd6\xbf) Japanese (\346\227\245\346\234\254\350\252\236) Thai (\340\270\252\340\270\247\340\270\261\340\270\252\340\270\224\340\270\265\340\270\204\340\270\243\340\270\261\340\270\232) Thai wrong spelling (\340\270\204\340\270\263\340\270\225\340\271\210\340\270\255\340\271\204\340\270\233\340\270\231\340\270\267\340\271\210\340\270\252\340\270\260\340\270\201\340\270\224\340\270\234\340\270\264\340\270\224 \340\270\236\340\270\261\340\270\261\340\271\211\340\270\261\340\270\261\340\271\210\340\270\207\340\271\202\340\270\201\340\270\260)\n", -1);
 
       temp_mark =
         gtk_text_buffer_create_mark (buffer, "tmp_mark", &iter, TRUE);
@@ -574,6 +605,11 @@ fill_example_buffer (GtkTextBuffer *buffer)
 
       gtk_text_buffer_apply_tag_by_name (buffer, "underline", &iter, &iter2);
 
+      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 1, 4);
+      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter2, 1, 7);
+
+      gtk_text_buffer_apply_tag_by_name (buffer, "underline_error", &iter, &iter2);
+
       gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 1, 14);
       gtk_text_buffer_get_iter_at_line_offset (buffer, &iter2, 1, 24);
 
@@ -603,7 +639,7 @@ fill_example_buffer (GtkTextBuffer *buffer)
 
       gtk_text_buffer_move_mark (buffer, temp_mark, &iter);
       gtk_text_buffer_insert (buffer, &iter, "Word wrapped, Right-to-left Quote\n", -1);
-      gtk_text_buffer_insert (buffer, &iter, "وقد بدأ ثلاث من أكثر المؤسسات تقدما في شبكة اكسيون برامجها كمنظمات لا تسعى للربح، ثم تحولت في السنوات الخمس الماضية إلى مؤسسات مالية منظمة، وباتت جزءا من النظام المالي في بلدانها، ولكنها تتخصص في خدمة قطاع المشروعات الصغيرة. وأحد أكثر هذه المؤسسات نجاحا هو »بانكوسول« في بوليفيا.\n", -1);
+      gtk_text_buffer_insert (buffer, &iter, "\331\210\331\202\330\257 \330\250\330\257\330\243 \330\253\331\204\330\247\330\253 \331\205\331\206 \330\243\331\203\330\253\330\261 \330\247\331\204\331\205\330\244\330\263\330\263\330\247\330\252 \330\252\331\202\330\257\331\205\330\247 \331\201\331\212 \330\264\330\250\331\203\330\251 \330\247\331\203\330\263\331\212\331\210\331\206 \330\250\330\261\330\247\331\205\330\254\331\207\330\247 \331\203\331\205\331\206\330\270\331\205\330\247\330\252 \331\204\330\247 \330\252\330\263\330\271\331\211 \331\204\331\204\330\261\330\250\330\255\330\214 \330\253\331\205 \330\252\330\255\331\210\331\204\330\252 \331\201\331\212 \330\247\331\204\330\263\331\206\331\210\330\247\330\252 \330\247\331\204\330\256\331\205\330\263 \330\247\331\204\331\205\330\247\330\266\331\212\330\251 \330\245\331\204\331\211 \331\205\330\244\330\263\330\263\330\247\330\252 \331\205\330\247\331\204\331\212\330\251 \331\205\331\206\330\270\331\205\330\251\330\214 \331\210\330\250\330\247\330\252\330\252 \330\254\330\262\330\241\330\247 \331\205\331\206 \330\247\331\204\331\206\330\270\330\247\331\205 \330\247\331\204\331\205\330\247\331\204\331\212 \331\201\331\212 \330\250\331\204\330\257\330\247\331\206\331\207\330\247\330\214 \331\210\331\204\331\203\331\206\331\207\330\247 \330\252\330\252\330\256\330\265\330\265 \331\201\331\212 \330\256\330\257\331\205\330\251 \331\202\330\267\330\247\330\271 \330\247\331\204\331\205\330\264\330\261\331\210\330\271\330\247\330\252 \330\247\331\204\330\265\330\272\331\212\330\261\330\251. \331\210\330\243\330\255\330\257 \330\243\331\203\330\253\330\261 \331\207\330\260\331\207 \330\247\331\204\331\205\330\244\330\263\330\263\330\247\330\252 \331\206\330\254\330\247\330\255\330\247 \331\207\331\210 \302\273\330\250\330\247\331\206\331\203\331\210\330\263\331\210\331\204\302\253 \331\201\331\212 \330\250\331\210\331\204\331\212\331\201\331\212\330\247.\n", -1);
       gtk_text_buffer_get_iter_at_mark (buffer, &iter2, temp_mark);
       gtk_text_buffer_apply_tag_by_name (buffer, "rtl_quote", &iter2, &iter);
 
@@ -617,7 +653,7 @@ fill_example_buffer (GtkTextBuffer *buffer)
       ++i;
     }
 
-  g_object_unref (G_OBJECT (pixbuf));
+  g_object_unref (pixbuf);
   
   printf ("%d lines %d chars\n",
           gtk_text_buffer_get_line_count (buffer),
@@ -945,6 +981,19 @@ do_editable_changed (gpointer callback_data,
   gtk_text_view_set_editable (GTK_TEXT_VIEW (view->text_view), callback_action);
 }
 
+static void
+change_cursor_color (GtkWidget *widget,
+                    gboolean   set)
+{
+  if (set)
+    {
+      GdkColor red = {0, 65535, 0, 0};
+      gtk_widget_modify_cursor (widget, &red, &red);
+    }
+  else
+    gtk_widget_modify_cursor (widget, NULL, NULL);
+}
+
 static void
 do_cursor_visible_changed (gpointer callback_data,
                            guint callback_action,
@@ -952,7 +1001,20 @@ do_cursor_visible_changed (gpointer callback_data,
 {
   View *view = view_from_widget (widget);
 
-  gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view->text_view), callback_action);
+  switch (callback_action)
+    {
+    case 0:
+      gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view->text_view), FALSE);
+      break;
+    case 1:
+      gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view->text_view), TRUE);
+      change_cursor_color (view->text_view, FALSE);
+      break;
+    case 2:
+      gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view->text_view), TRUE);
+      change_cursor_color (view->text_view, TRUE);
+      break;
+    }
 }
 
 static void
@@ -1019,6 +1081,114 @@ do_apply_invisible (gpointer callback_data,
     }
 }
 
+static void
+do_apply_rise (gpointer callback_data,
+              guint callback_action,
+              GtkWidget *widget)
+{
+  View *view = view_from_widget (widget);
+  GtkTextIter start;
+  GtkTextIter end;
+  
+  if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
+                                            &start, &end))
+    {
+      if (callback_action)
+        {
+          gtk_text_buffer_remove_tag (view->buffer->buffer,
+                                      view->buffer->rise_tag,
+                                      &start, &end);
+        }
+      else
+        {
+          gtk_text_buffer_apply_tag (view->buffer->buffer,
+                                     view->buffer->rise_tag,
+                                     &start, &end);
+        }
+    }
+}
+
+static void
+do_apply_large (gpointer callback_data,
+               guint callback_action,
+               GtkWidget *widget)
+{
+  View *view = view_from_widget (widget);
+  GtkTextIter start;
+  GtkTextIter end;
+  
+  if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
+                                            &start, &end))
+    {
+      if (callback_action)
+        {
+          gtk_text_buffer_remove_tag (view->buffer->buffer,
+                                      view->buffer->large_tag,
+                                      &start, &end);
+        }
+      else
+        {
+          gtk_text_buffer_apply_tag (view->buffer->buffer,
+                                     view->buffer->large_tag,
+                                     &start, &end);
+        }
+    }
+}
+
+static void
+do_apply_indent (gpointer callback_data,
+                guint callback_action,
+                GtkWidget *widget)
+{
+  View *view = view_from_widget (widget);
+  GtkTextIter start;
+  GtkTextIter end;
+  
+  if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
+                                            &start, &end))
+    {
+      if (callback_action)
+        {
+          gtk_text_buffer_remove_tag (view->buffer->buffer,
+                                      view->buffer->indent_tag,
+                                      &start, &end);
+        }
+      else
+        {
+          gtk_text_buffer_apply_tag (view->buffer->buffer,
+                                     view->buffer->indent_tag,
+                                     &start, &end);
+        }
+    }
+}
+
+static void
+do_apply_margin (gpointer callback_data,
+                guint callback_action,
+                GtkWidget *widget)
+{
+  View *view = view_from_widget (widget);
+  GtkTextIter start;
+  GtkTextIter end;
+  
+  if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
+                                            &start, &end))
+    {
+      if (callback_action)
+        {
+          gtk_text_buffer_remove_tag (view->buffer->buffer,
+                                      view->buffer->margin_tag,
+                                      &start, &end);
+        }
+      else
+        {
+          gtk_text_buffer_apply_tag (view->buffer->buffer,
+                                     view->buffer->margin_tag,
+                                     &start, &end);
+        }
+    }
+}
+
 static void
 do_apply_tabs (gpointer callback_data,
                guint callback_action,
@@ -1136,6 +1306,267 @@ do_properties (gpointer callback_data,
   create_prop_editor (G_OBJECT (view->text_view), 0);
 }
 
+static void
+rich_text_store_populate (GtkListStore  *store,
+                          GtkTextBuffer *buffer,
+                          gboolean       deserialize)
+{
+  GdkAtom *formats;
+  gint     n_formats;
+  gint     i;
+
+  gtk_list_store_clear (store);
+
+  if (deserialize)
+    formats = gtk_text_buffer_get_deserialize_formats (buffer, &n_formats);
+  else
+    formats = gtk_text_buffer_get_serialize_formats (buffer, &n_formats);
+
+  for (i = 0; i < n_formats; i++)
+    {
+      GtkTreeIter  iter;
+      gchar       *mime_type;
+      gboolean     can_create_tags = FALSE;
+
+      mime_type = gdk_atom_name (formats[i]);
+
+      if (deserialize)
+        can_create_tags =
+          gtk_text_buffer_deserialize_get_can_create_tags (buffer, formats[i]);
+
+      gtk_list_store_append (store, &iter);
+      gtk_list_store_set (store, &iter,
+                          0, formats[i],
+                          1, mime_type,
+                          2, can_create_tags,
+                          -1);
+
+      g_free (mime_type);
+    }
+
+  g_free (formats);
+}
+
+static void
+rich_text_paste_target_list_notify (GtkTextBuffer    *buffer,
+                                    const GParamSpec *pspec,
+                                    GtkListStore     *store)
+{
+  rich_text_store_populate (store, buffer, TRUE);
+}
+
+static void
+rich_text_copy_target_list_notify (GtkTextBuffer    *buffer,
+                                   const GParamSpec *pspec,
+                                   GtkListStore     *store)
+{
+  rich_text_store_populate (store, buffer, FALSE);
+}
+
+static void
+rich_text_can_create_tags_toggled (GtkCellRendererToggle *toggle,
+                                   const gchar           *path,
+                                   GtkTreeModel          *model)
+{
+  GtkTreeIter iter;
+
+  if (gtk_tree_model_get_iter_from_string (model, &iter, path))
+    {
+      GtkTextBuffer *buffer;
+      GdkAtom        format;
+      gboolean       can_create_tags;
+
+      buffer = g_object_get_data (G_OBJECT (model), "buffer");
+
+      gtk_tree_model_get (model, &iter,
+                          0, &format,
+                          2, &can_create_tags,
+                          -1);
+
+      gtk_text_buffer_deserialize_set_can_create_tags (buffer, format,
+                                                       !can_create_tags);
+
+      gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+                          2, !can_create_tags,
+                          -1);
+    }
+}
+
+static void
+rich_text_unregister_clicked (GtkWidget   *button,
+                              GtkTreeView *tv)
+{
+  GtkTreeSelection *sel = gtk_tree_view_get_selection (tv);
+  GtkTreeModel     *model;
+  GtkTreeIter       iter;
+
+  if (gtk_tree_selection_get_selected (sel, &model, &iter))
+    {
+      GtkTextBuffer *buffer;
+      gboolean       deserialize;
+      GdkAtom        format;
+
+      buffer = g_object_get_data (G_OBJECT (model), "buffer");
+      deserialize = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (model),
+                                                        "deserialize"));
+
+      gtk_tree_model_get (model, &iter,
+                          0, &format,
+                          -1);
+
+      if (deserialize)
+        gtk_text_buffer_unregister_deserialize_format (buffer, format);
+      else
+        gtk_text_buffer_unregister_serialize_format (buffer, format);
+    }
+}
+
+static void
+rich_text_register_clicked (GtkWidget   *button,
+                            GtkTreeView *tv)
+{
+  GtkWidget *dialog;
+  GtkWidget *label;
+  GtkWidget *entry;
+
+  dialog = gtk_dialog_new_with_buttons ("Register new Tagset",
+                                        GTK_WINDOW (gtk_widget_get_toplevel (button)),
+                                        GTK_DIALOG_DESTROY_WITH_PARENT,
+                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                        GTK_STOCK_OK,     GTK_RESPONSE_OK,
+                                        NULL);
+  label = gtk_label_new ("Enter tagset name or leave blank for "
+                         "unrestricted internal format:");
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), label,
+                      FALSE, FALSE, 0);
+
+  entry = gtk_entry_new ();
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), entry,
+                      FALSE, FALSE, 0);
+
+  gtk_widget_show_all (dialog);
+
+  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+    {
+      GtkTreeModel  *model  = gtk_tree_view_get_model (tv);
+      GtkTextBuffer *buffer = g_object_get_data (G_OBJECT (model), "buffer");
+      const gchar   *tagset = gtk_entry_get_text (GTK_ENTRY (entry));
+      gboolean       deserialize;
+
+      deserialize = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (model),
+                                                        "deserialize"));
+
+      if (tagset && ! strlen (tagset))
+        tagset = NULL;
+
+      if (deserialize)
+        gtk_text_buffer_register_deserialize_tagset (buffer, tagset);
+      else
+        gtk_text_buffer_register_serialize_tagset (buffer, tagset);
+    }
+
+  gtk_widget_destroy (dialog);
+}
+
+static void
+do_rich_text (gpointer callback_data,
+              guint deserialize,
+              GtkWidget *widget)
+{
+  View *view = view_from_widget (widget);
+  GtkTextBuffer *buffer;
+  GtkWidget *dialog;
+  GtkWidget *tv;
+  GtkWidget *sw;
+  GtkWidget *hbox;
+  GtkWidget *button;
+  GtkListStore *store;
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view->text_view));
+
+  dialog = gtk_dialog_new_with_buttons (deserialize ?
+                                        "Rich Text Paste & Drop" :
+                                        "Rich Text Copy & Drag",
+                                        GTK_WINDOW (view->window),
+                                        GTK_DIALOG_DESTROY_WITH_PARENT,
+                                        GTK_STOCK_CLOSE, 0,
+                                        NULL);
+  g_signal_connect (dialog, "response",
+                    G_CALLBACK (gtk_widget_destroy),
+                    NULL);
+
+  store = gtk_list_store_new (3,
+                              G_TYPE_POINTER,
+                              G_TYPE_STRING,
+                              G_TYPE_BOOLEAN);
+
+  g_object_set_data (G_OBJECT (store), "buffer", buffer);
+  g_object_set_data (G_OBJECT (store), "deserialize",
+                     GUINT_TO_POINTER (deserialize));
+
+  tv = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
+  g_object_unref (store);
+
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv),
+                                               0, "Rich Text Format",
+                                               gtk_cell_renderer_text_new (),
+                                               "text", 1,
+                                               NULL);
+
+  if (deserialize)
+    {
+      GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new ();
+
+      gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv),
+                                                   1, "Can Create Tags",
+                                                   renderer,
+                                                   "active", 2,
+                                                   NULL);
+
+      g_signal_connect (renderer, "toggled",
+                        G_CALLBACK (rich_text_can_create_tags_toggled),
+                        store);
+    }
+
+  sw = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_set_size_request (sw, 300, 100);
+  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), sw);
+
+  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), tv);
+
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE, 6);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox,
+                      FALSE, FALSE, 0);
+
+  button = gtk_button_new_with_label ("Unregister Selected Format");
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+  g_signal_connect (button, "clicked",
+                    G_CALLBACK (rich_text_unregister_clicked),
+                    tv);
+
+  button = gtk_button_new_with_label ("Register New Tagset\n"
+                                      "for the Internal Format");
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+  g_signal_connect (button, "clicked",
+                    G_CALLBACK (rich_text_register_clicked),
+                    tv);
+
+  if (deserialize)
+    g_signal_connect_object (buffer, "notify::paste-target-list",
+                             G_CALLBACK (rich_text_paste_target_list_notify),
+                             G_OBJECT (store), 0);
+  else
+    g_signal_connect_object (buffer, "notify::copy-target-list",
+                             G_CALLBACK (rich_text_copy_target_list_notify),
+                             G_OBJECT (store), 0);
+
+  rich_text_store_populate (store, buffer, deserialize);
+
+  gtk_widget_show_all (dialog);
+}
+
 enum
 {
   RESPONSE_FORWARD,
@@ -1175,6 +1606,20 @@ dialog_response_callback (GtkWidget *dialog, gint response_id, gpointer data)
   gtk_widget_destroy (dialog);
 }
 
+static void
+do_copy  (gpointer callback_data,
+          guint callback_action,
+          GtkWidget *widget)
+{
+  View *view = view_from_widget (widget);
+  GtkTextBuffer *buffer;
+
+  buffer = view->buffer->buffer;
+
+  gtk_text_buffer_copy_clipboard (buffer,
+                                  gtk_clipboard_get (GDK_NONE));
+}
+
 static void
 do_search (gpointer callback_data,
            guint callback_action,
@@ -1198,7 +1643,7 @@ do_search (gpointer callback_data,
 
   search_text = gtk_text_view_new_with_buffer (buffer);
 
-  g_object_unref (G_OBJECT (buffer));
+  g_object_unref (buffer);
   
   gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->vbox),
                     search_text,
@@ -1206,10 +1651,10 @@ do_search (gpointer callback_data,
 
   g_object_set_data (G_OBJECT (dialog), "buffer", buffer);
   
-  gtk_signal_connect (GTK_OBJECT (dialog),
-                      "response",
-                      GTK_SIGNAL_FUNC (dialog_response_callback),
-                      view);
+  g_signal_connect (dialog,
+                    "response",
+                    G_CALLBACK (dialog_response_callback),
+                    view);
 
   gtk_widget_show (search_text);
 
@@ -1218,6 +1663,21 @@ do_search (gpointer callback_data,
   gtk_widget_show_all (dialog);
 }
 
+static void
+do_select_all (gpointer callback_data,
+               guint callback_action,
+               GtkWidget *widget)
+{
+  View *view = view_from_widget (widget);
+  GtkTextBuffer *buffer;
+  GtkTextIter start, end;
+
+  buffer = view->buffer->buffer;
+
+  gtk_text_buffer_get_bounds (buffer, &start, &end);
+  gtk_text_buffer_select_range (buffer, &start, &end);
+}
+
 typedef struct
 {
   /* position is in coordinate system of text_view_move_child */
@@ -1352,7 +1812,7 @@ add_movable_child (GtkTextView      *text_view,
 
   gtk_widget_show_all (event_box);
 
-  g_signal_connect (G_OBJECT (event_box), "event",
+  g_signal_connect (event_box, "event",
                     G_CALLBACK (movable_child_callback),
                     text_view);
 
@@ -1485,53 +1945,63 @@ view_init_menus (View *view)
 
 static GtkItemFactoryEntry menu_items[] =
 {
-  { "/_File",            NULL,         0,           0, "<Branch>" },
+  { "/_File",            NULL,         NULL,        0, "<Branch>" },
   { "/File/_New",        "<control>N", do_new,      0, NULL },
   { "/File/New _View",   NULL,         do_new_view, 0, NULL },
   { "/File/_Open",       "<control>O", do_open,     0, NULL },
   { "/File/_Save",       "<control>S", do_save,     0, NULL },
   { "/File/Save _As...", NULL,         do_save_as,  0, NULL },
-  { "/File/sep1",        NULL,         0,           0, "<Separator>" },
+  { "/File/sep1",        NULL,         NULL,        0, "<Separator>" },
   { "/File/_Close",     "<control>W" , do_close,    0, NULL },
   { "/File/E_xit",      "<control>Q" , do_exit,     0, NULL },
 
   { "/_Edit", NULL, 0, 0, "<Branch>" },
+  { "/Edit/Copy", NULL, do_copy, 0, NULL },
+  { "/Edit/sep1", NULL, NULL, 0, "<Separator>" },
   { "/Edit/Find...", NULL, do_search, 0, NULL },
+  { "/Edit/Select All", "<control>A", do_select_all, 0, NULL }, 
 
-  { "/_Settings",        NULL,         0,                0, "<Branch>" },
+  { "/_Settings",        NULL,         NULL,             0, "<Branch>" },
   { "/Settings/Wrap _Off",   NULL,      do_wrap_changed,  GTK_WRAP_NONE, "<RadioItem>" },
   { "/Settings/Wrap _Words", NULL,      do_wrap_changed,  GTK_WRAP_WORD, "/Settings/Wrap Off" },
   { "/Settings/Wrap _Chars", NULL,      do_wrap_changed,  GTK_WRAP_CHAR, "/Settings/Wrap Off" },
-  { "/Settings/sep1",        NULL,      0,                0, "<Separator>" },
+  { "/Settings/sep1",        NULL,      NULL,             0, "<Separator>" },
   { "/Settings/Editable", NULL,      do_editable_changed,  TRUE, "<RadioItem>" },
   { "/Settings/Not editable",    NULL,      do_editable_changed,  FALSE, "/Settings/Editable" },
-  { "/Settings/sep1",        NULL,      0,                0, "<Separator>" },
+  { "/Settings/sep1",        NULL,      NULL,             0, "<Separator>" },
 
-  { "/Settings/Cursor visible",    NULL,      do_cursor_visible_changed,  TRUE, "<RadioItem>" },
-  { "/Settings/Cursor not visible", NULL,      do_cursor_visible_changed,  FALSE, "/Settings/Cursor visible" },
-  { "/Settings/sep1",        NULL,      0,                0, "<Separator>" },
+  { "/Settings/Cursor normal",    NULL,      do_cursor_visible_changed,  1, "<RadioItem>" },
+  { "/Settings/Cursor not visible", NULL,      do_cursor_visible_changed,  0, "/Settings/Cursor normal" },
+  { "/Settings/Cursor colored", NULL,      do_cursor_visible_changed,  2, "/Settings/Cursor normal" },
+  { "/Settings/sep1",        NULL,      NULL,          0, "<Separator>" },
   
   { "/Settings/Left-to-Right", NULL,    do_direction_changed,  GTK_TEXT_DIR_LTR, "<RadioItem>" },
   { "/Settings/Right-to-Left", NULL,    do_direction_changed,  GTK_TEXT_DIR_RTL, "/Settings/Left-to-Right" },
 
-  { "/Settings/sep1",        NULL,      0,                0, "<Separator>" },
+  { "/Settings/sep1",        NULL,      NULL,                0, "<Separator>" },
   { "/Settings/Sane spacing", NULL,    do_spacing_changed,  FALSE, "<RadioItem>" },
   { "/Settings/Funky spacing", NULL,    do_spacing_changed,  TRUE, "/Settings/Sane spacing" },
-  { "/Settings/sep1",        NULL,      0,                0, "<Separator>" },
+  { "/Settings/sep1",        NULL,      NULL,                0, "<Separator>" },
   { "/Settings/Don't cycle color tags", NULL,    do_color_cycle_changed,  FALSE, "<RadioItem>" },
   { "/Settings/Cycle colors", NULL,    do_color_cycle_changed,  TRUE, "/Settings/Don't cycle color tags" },
-  { "/_Attributes",      NULL,         0,                0, "<Branch>" },
+  { "/_Attributes",      NULL,         NULL,                0, "<Branch>" },
   { "/Attributes/Editable",      NULL,         do_apply_editable, TRUE, NULL },
   { "/Attributes/Not editable",          NULL,         do_apply_editable, FALSE, NULL },
   { "/Attributes/Invisible",             NULL,         do_apply_invisible, FALSE, NULL },
   { "/Attributes/Visible",       NULL,         do_apply_invisible, TRUE, NULL },
+  { "/Attributes/Rise",          NULL,         do_apply_rise, FALSE, NULL },
+  { "/Attributes/Large",         NULL,         do_apply_large, FALSE, NULL },
+  { "/Attributes/Indent",        NULL,         do_apply_indent, FALSE, NULL },
+  { "/Attributes/Margins",       NULL,         do_apply_margin, FALSE, NULL },
   { "/Attributes/Custom tabs",           NULL,         do_apply_tabs, FALSE, NULL },
   { "/Attributes/Default tabs",          NULL,         do_apply_tabs, TRUE, NULL },
   { "/Attributes/Color cycles",          NULL,         do_apply_colors, TRUE, NULL },
   { "/Attributes/No colors",                     NULL,         do_apply_colors, FALSE, NULL },
-  { "/Attributes/Remove all tags",       NULL, do_remove_tags, 0, NULL },
-  { "/Attributes/Properties",       NULL, do_properties, 0, NULL },
-  { "/_Test",           NULL,         0,           0, "<Branch>" },
+  { "/Attributes/Remove all tags",        NULL, do_remove_tags, 0, NULL },
+  { "/Attributes/Properties",             NULL, do_properties, 0, NULL },
+  { "/Attributes/Rich Text copy & drag",  NULL, do_rich_text, 0, NULL },
+  { "/Attributes/Rich Text paste & drop", NULL, do_rich_text, 1, NULL },
+  { "/_Test",           NULL,         NULL,           0, "<Branch>" },
   { "/Test/_Example",           NULL,         do_example,  0, NULL },
   { "/Test/_Insert and scroll", NULL,         do_insert_and_scroll,  0, NULL },
   { "/Test/_Add fixed children", NULL,         do_add_children,  0, NULL },
@@ -1716,7 +2186,7 @@ create_buffer (void)
       ++i;
     }
 
-#if 0  
+#if 1  
   buffer->invisible_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
                                                       "invisible", TRUE, NULL);
 #endif  
@@ -1729,6 +2199,18 @@ create_buffer (void)
   buffer->found_text_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
                                                        "foreground", "red", NULL);
 
+  buffer->rise_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
+                                                "rise", 10 * PANGO_SCALE, NULL);
+
+  buffer->large_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
+                                                "scale", PANGO_SCALE_X_LARGE, NULL);
+
+  buffer->indent_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
+                                                  "indent", 20, NULL);
+
+  buffer->margin_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
+                                                  "left_margin", 20, "right_margin", 20, NULL);
+
   tabs = pango_tab_array_new_with_positions (4,
                                              TRUE,
                                              PANGO_TAB_LEFT, 10,
@@ -1852,10 +2334,9 @@ buffer_search (Buffer     *buffer,
                                    "%d strings found and marked in red",
                                    i);
 
-  gtk_signal_connect_object (GTK_OBJECT (dialog),
-                             "response",
-                             GTK_SIGNAL_FUNC (gtk_widget_destroy),
-                             GTK_OBJECT (dialog));
+  g_signal_connect_swapped (dialog,
+                            "response",
+                            G_CALLBACK (gtk_widget_destroy), dialog);
   
   gtk_widget_show (dialog);
 }
@@ -1888,7 +2369,7 @@ buffer_unref (Buffer *buffer)
     {
       buffer_set_colors (buffer, FALSE);
       buffers = g_slist_remove (buffers, buffer);
-      g_object_unref (G_OBJECT (buffer->buffer));
+      g_object_unref (buffer->buffer);
       g_free (buffer->filename);
       g_free (buffer);
     }
@@ -2004,10 +2485,10 @@ buffer_set_colors (Buffer  *buffer,
   gdouble hue = 0.0;
 
   if (enabled && buffer->color_cycle_timeout == 0)
-    buffer->color_cycle_timeout = gtk_timeout_add (200, color_cycle_timeout, buffer);
+    buffer->color_cycle_timeout = gdk_threads_add_timeout (200, color_cycle_timeout, buffer);
   else if (!enabled && buffer->color_cycle_timeout != 0)
     {
-      gtk_timeout_remove (buffer->color_cycle_timeout);
+      g_source_remove (buffer->color_cycle_timeout);
       buffer->color_cycle_timeout = 0;
     }
     
@@ -2020,14 +2501,14 @@ buffer_set_colors (Buffer  *buffer,
           
           hue_to_color (hue, &color);
 
-          g_object_set (G_OBJECT (tmp->data),
-                          "foreground_gdk", &color,
-                          NULL);
+          g_object_set (tmp->data,
+                        "foreground_gdk", &color,
+                        NULL);
         }
       else
-        g_object_set (G_OBJECT (tmp->data),
-                        "foreground_set", FALSE,
-                        NULL);
+        g_object_set (tmp->data,
+                      "foreground_set", FALSE,
+                      NULL);
 
       hue += 1.0 / N_COLORS;
       
@@ -2048,7 +2529,7 @@ buffer_cycle_colors (Buffer *buffer)
       
       hue_to_color (hue, &color);
       
-      g_object_set (G_OBJECT (tmp->data),
+      g_object_set (tmp->data,
                     "foreground_gdk", &color,
                     NULL);
 
@@ -2070,7 +2551,7 @@ close_view (View *view)
   views = g_slist_remove (views, view);
   buffer_unref (view->buffer);
   gtk_widget_destroy (view->window);
-  g_object_unref (G_OBJECT (view->item_factory));
+  g_object_unref (view->item_factory);
   
   g_free (view);
   
@@ -2112,7 +2593,7 @@ cursor_set_callback (GtkTextBuffer     *buffer,
   
   text_view = GTK_TEXT_VIEW (user_data);
   
-  if (GTK_WIDGET_MAPPED (text_view) &&
+  if (gtk_widget_get_mapped (GTK_WIDGET (text_view)) &&
       mark == gtk_text_buffer_get_insert (buffer))
     {
       GdkWindow *tab_window;
@@ -2381,7 +2862,7 @@ line_numbers_expose (GtkWidget      *widget,
 
       gtk_paint_layout (widget->style,
                         target,
-                        GTK_WIDGET_STATE (widget),
+                        gtk_widget_get_state (widget),
                         FALSE,
                         NULL,
                         widget,
@@ -2397,17 +2878,25 @@ line_numbers_expose (GtkWidget      *widget,
   g_array_free (pixels, TRUE);
   g_array_free (numbers, TRUE);
   
-  g_object_unref (G_OBJECT (layout));
+  g_object_unref (layout);
 
   /* don't stop emission, need to draw children */
   return FALSE;
 }
 
+static void
+selection_changed (GtkTextBuffer *buffer,
+                  GParamSpec    *pspec,
+                  GtkWidget     *copy_menu)
+{
+  gtk_widget_set_sensitive (copy_menu, gtk_text_buffer_get_has_selection (buffer));
+}
+
 static View *
 create_view (Buffer *buffer)
 {
   View *view;
-  
+  GtkWidget *copy_menu;
   GtkWidget *sw;
   GtkWidget *vbox;
   
@@ -2420,8 +2909,8 @@ create_view (Buffer *buffer)
   view->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
   g_object_set_data (G_OBJECT (view->window), "view", view);
   
-  gtk_signal_connect (GTK_OBJECT (view->window), "delete_event",
-                     GTK_SIGNAL_FUNC (delete_event_cb), NULL);
+  g_signal_connect (view->window, "delete_event",
+                   G_CALLBACK (delete_event_cb), NULL);
 
   view->accel_group = gtk_accel_group_new ();
   view->item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", view->accel_group);
@@ -2429,9 +2918,17 @@ create_view (Buffer *buffer)
   
   gtk_item_factory_create_items (view->item_factory, G_N_ELEMENTS (menu_items), menu_items, view);
 
+  /* make the Copy menu item sensitivity update according to the selection */
+  copy_menu = gtk_item_factory_get_item (view->item_factory, "<main>/Edit/Copy");
+  gtk_widget_set_sensitive (copy_menu, gtk_text_buffer_get_has_selection (view->buffer->buffer));
+  g_signal_connect (view->buffer->buffer,
+                   "notify::has-selection",
+                   G_CALLBACK (selection_changed),
+                   copy_menu);
+
   gtk_window_add_accel_group (GTK_WINDOW (view->window), view->accel_group);
 
-  vbox = gtk_vbox_new (FALSE, 0);
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0);
   gtk_container_add (GTK_CONTAINER (view->window), vbox);
 
   gtk_box_pack_start (GTK_BOX (vbox),
@@ -2461,14 +2958,14 @@ create_view (Buffer *buffer)
                                         GTK_TEXT_WINDOW_BOTTOM,
                                         15);
 
-  gtk_signal_connect (GTK_OBJECT (view->text_view),
-                      "expose_event",
-                      GTK_SIGNAL_FUNC (tab_stops_expose),
-                      NULL);  
+  g_signal_connect (view->text_view,
+                    "expose_event",
+                    G_CALLBACK (tab_stops_expose),
+                    NULL);  
 
-  g_signal_connect (G_OBJECT (view->buffer->buffer),
+  g_signal_connect (view->buffer->buffer,
                    "mark_set",
-                   GTK_SIGNAL_FUNC (cursor_set_callback),
+                   G_CALLBACK (cursor_set_callback),
                    view->text_view);
   
   /* Draw line numbers in the side windows; we should really be
@@ -2482,10 +2979,10 @@ create_view (Buffer *buffer)
                                         GTK_TEXT_WINDOW_LEFT,
                                         30);
   
-  gtk_signal_connect (GTK_OBJECT (view->text_view),
-                      "expose_event",
-                      GTK_SIGNAL_FUNC (line_numbers_expose),
-                      NULL);
+  g_signal_connect (view->text_view,
+                    "expose_event",
+                    G_CALLBACK (line_numbers_expose),
+                    NULL);
   
   gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
   gtk_container_add (GTK_CONTAINER (sw), view->text_view);
@@ -2529,13 +3026,13 @@ view_add_example_widgets (View *view)
 }
 
 void
-test_init ()
+test_init (void)
 {
   if (g_file_test ("../gdk-pixbuf/libpixbufloader-pnm.la",
                   G_FILE_TEST_EXISTS))
     {
-      putenv ("GDK_PIXBUF_MODULE_FILE=../gdk-pixbuf/gdk-pixbuf.loaders");
-      putenv ("GTK_IM_MODULE_FILE=../modules/input/gtk.immodules");
+      g_setenv ("GDK_PIXBUF_MODULE_FILE", "../gdk-pixbuf/loaders.cache", TRUE);
+      g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/immodules.cache", TRUE);
     }
 }