Blame tests/testtext.c

Packit 98cdb6
/* testtext.c
Packit 98cdb6
 * Copyright (C) 2000 Red Hat, Inc
Packit 98cdb6
 * Author: Havoc Pennington
Packit 98cdb6
 *
Packit 98cdb6
 * This library is free software; you can redistribute it and/or
Packit 98cdb6
 * modify it under the terms of the GNU Library General Public
Packit 98cdb6
 * License as published by the Free Software Foundation; either
Packit 98cdb6
 * version 2 of the License, or (at your option) any later version.
Packit 98cdb6
 *
Packit 98cdb6
 * This library is distributed in the hope that it will be useful,
Packit 98cdb6
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 98cdb6
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 98cdb6
 * Library General Public License for more details.
Packit 98cdb6
 *
Packit 98cdb6
 * You should have received a copy of the GNU Library General Public
Packit 98cdb6
 * License along with this library; if not, write to the
Packit 98cdb6
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit 98cdb6
 * Boston, MA 02111-1307, USA.
Packit 98cdb6
 */
Packit 98cdb6
Packit 98cdb6
#include "config.h"
Packit 98cdb6
#include <stdio.h>
Packit 98cdb6
#include <sys/stat.h>
Packit 98cdb6
#include <errno.h>
Packit 98cdb6
#include <stdlib.h>
Packit 98cdb6
#include <string.h>
Packit 98cdb6
Packit 98cdb6
#undef GDK_DISABLE_DEPRECATED
Packit 98cdb6
#undef GTK_DISABLE_DEPRECATED
Packit 98cdb6
Packit 98cdb6
#include <gtk/gtk.h>
Packit 98cdb6
#include <gdk/gdkkeysyms.h>
Packit 98cdb6
Packit 98cdb6
#include "prop-editor.h"
Packit 98cdb6
Packit 98cdb6
typedef struct _Buffer Buffer;
Packit 98cdb6
typedef struct _View View;
Packit 98cdb6
Packit 98cdb6
static gint untitled_serial = 1;
Packit 98cdb6
Packit 98cdb6
GSList *active_window_stack = NULL;
Packit 98cdb6
Packit 98cdb6
struct _Buffer
Packit 98cdb6
{
Packit 98cdb6
  gint refcount;
Packit 98cdb6
  GtkTextBuffer *buffer;
Packit 98cdb6
  char *filename;
Packit 98cdb6
  gint untitled_serial;
Packit 98cdb6
  GtkTextTag *invisible_tag;
Packit 98cdb6
  GtkTextTag *not_editable_tag;
Packit 98cdb6
  GtkTextTag *found_text_tag;
Packit 98cdb6
  GtkTextTag *rise_tag;
Packit 98cdb6
  GtkTextTag *large_tag;
Packit 98cdb6
  GtkTextTag *indent_tag;
Packit 98cdb6
  GtkTextTag *margin_tag;
Packit 98cdb6
  GtkTextTag *custom_tabs_tag;
Packit 98cdb6
  GSList *color_tags;
Packit 98cdb6
  guint color_cycle_timeout;
Packit 98cdb6
  gdouble start_hue;
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
struct _View
Packit 98cdb6
{
Packit 98cdb6
  GtkWidget *window;
Packit 98cdb6
  GtkWidget *text_view;
Packit 98cdb6
  GtkAccelGroup *accel_group;
Packit 98cdb6
  GtkItemFactory *item_factory;
Packit 98cdb6
  Buffer *buffer;
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
static void push_active_window (GtkWindow *window);
Packit 98cdb6
static void pop_active_window (void);
Packit 98cdb6
static GtkWindow *get_active_window (void);
Packit 98cdb6
Packit 98cdb6
static Buffer * create_buffer      (void);
Packit 98cdb6
static gboolean check_buffer_saved (Buffer *buffer);
Packit 98cdb6
static gboolean save_buffer        (Buffer *buffer);
Packit 98cdb6
static gboolean save_as_buffer     (Buffer *buffer);
Packit 98cdb6
static char *   buffer_pretty_name (Buffer *buffer);
Packit 98cdb6
static void     buffer_filename_set (Buffer *buffer);
Packit 98cdb6
static void     buffer_search_forward (Buffer *buffer,
Packit 98cdb6
                                       const char *str,
Packit 98cdb6
                                       View *view);
Packit 98cdb6
static void     buffer_search_backward (Buffer *buffer,
Packit 98cdb6
                                       const char *str,
Packit 98cdb6
                                       View *view);
Packit 98cdb6
static void     buffer_set_colors      (Buffer  *buffer,
Packit 98cdb6
                                        gboolean enabled);
Packit 98cdb6
static void     buffer_cycle_colors    (Buffer  *buffer);
Packit 98cdb6
Packit 98cdb6
static View *view_from_widget (GtkWidget *widget);
Packit 98cdb6
Packit 98cdb6
static View *create_view      (Buffer *buffer);
Packit 98cdb6
static void  check_close_view (View   *view);
Packit 98cdb6
static void  close_view       (View   *view);
Packit 98cdb6
static void  view_set_title   (View   *view);
Packit 98cdb6
static void  view_init_menus  (View   *view);
Packit 98cdb6
static void  view_add_example_widgets (View *view);
Packit 98cdb6
Packit 98cdb6
GSList *buffers = NULL;
Packit 98cdb6
GSList *views = NULL;
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
push_active_window (GtkWindow *window)
Packit 98cdb6
{
Packit 98cdb6
  g_object_ref (window);
Packit 98cdb6
  active_window_stack = g_slist_prepend (active_window_stack, window);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
pop_active_window (void)
Packit 98cdb6
{
Packit 98cdb6
  g_object_unref (active_window_stack->data);
Packit 98cdb6
  active_window_stack = g_slist_delete_link (active_window_stack, active_window_stack);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static GtkWindow *
Packit 98cdb6
get_active_window (void)
Packit 98cdb6
{
Packit 98cdb6
  if (active_window_stack)
Packit 98cdb6
    return active_window_stack->data;
Packit 98cdb6
  else
Packit 98cdb6
    return NULL;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/*
Packit 98cdb6
 * Filesel utility function
Packit 98cdb6
 */
Packit 98cdb6
Packit 98cdb6
typedef gboolean (*FileselOKFunc) (const char *filename, gpointer data);
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
filesel_ok_cb (GtkWidget *button, GtkWidget *filesel)
Packit 98cdb6
{
Packit 98cdb6
  FileselOKFunc ok_func = (FileselOKFunc)g_object_get_data (G_OBJECT (filesel), "ok-func");
Packit 98cdb6
  gpointer data = g_object_get_data (G_OBJECT (filesel), "ok-data");
Packit 98cdb6
  gint *result = g_object_get_data (G_OBJECT (filesel), "ok-result");
Packit 98cdb6
  
Packit 98cdb6
  gtk_widget_hide (filesel);
Packit 98cdb6
  
Packit 98cdb6
  if ((*ok_func) (gtk_file_selection_get_filename (GTK_FILE_SELECTION (filesel)), data))
Packit 98cdb6
    {
Packit 98cdb6
      gtk_widget_destroy (filesel);
Packit 98cdb6
      *result = TRUE;
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    gtk_widget_show (filesel);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
gboolean
Packit 98cdb6
filesel_run (GtkWindow    *parent, 
Packit 98cdb6
	     const char   *title,
Packit 98cdb6
	     const char   *start_file,
Packit 98cdb6
	     FileselOKFunc func,
Packit 98cdb6
	     gpointer      data)
Packit 98cdb6
{
Packit 98cdb6
  GtkWidget *filesel = gtk_file_selection_new (title);
Packit 98cdb6
  gboolean result = FALSE;
Packit 98cdb6
Packit 98cdb6
  if (!parent)
Packit 98cdb6
    parent = get_active_window ();
Packit 98cdb6
  
Packit 98cdb6
  if (parent)
Packit 98cdb6
    gtk_window_set_transient_for (GTK_WINDOW (filesel), parent);
Packit 98cdb6
Packit 98cdb6
  if (start_file)
Packit 98cdb6
    gtk_file_selection_set_filename (GTK_FILE_SELECTION (filesel), start_file);
Packit 98cdb6
Packit 98cdb6
  
Packit 98cdb6
  g_object_set_data (G_OBJECT (filesel), "ok-func", func);
Packit 98cdb6
  g_object_set_data (G_OBJECT (filesel), "ok-data", data);
Packit 98cdb6
  g_object_set_data (G_OBJECT (filesel), "ok-result", &result);
Packit 98cdb6
Packit 98cdb6
  g_signal_connect (GTK_FILE_SELECTION (filesel)->ok_button,
Packit 98cdb6
		    "clicked",
Packit 98cdb6
		    G_CALLBACK (filesel_ok_cb), filesel);
Packit 98cdb6
  g_signal_connect_swapped (GTK_FILE_SELECTION (filesel)->cancel_button,
Packit 98cdb6
			    "clicked",
Packit 98cdb6
			    G_CALLBACK (gtk_widget_destroy), filesel);
Packit 98cdb6
Packit 98cdb6
  g_signal_connect (filesel, "destroy",
Packit 98cdb6
		    G_CALLBACK (gtk_main_quit), NULL);
Packit 98cdb6
  gtk_window_set_modal (GTK_WINDOW (filesel), TRUE);
Packit 98cdb6
Packit 98cdb6
  gtk_widget_show (filesel);
Packit 98cdb6
  gtk_main ();
Packit 98cdb6
Packit 98cdb6
  return result;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/*
Packit 98cdb6
 * MsgBox utility functions
Packit 98cdb6
 */
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
msgbox_yes_cb (GtkWidget *widget, gboolean *result)
Packit 98cdb6
{
Packit 98cdb6
  *result = 0;
Packit 98cdb6
  gtk_object_destroy (GTK_OBJECT (gtk_widget_get_toplevel (widget)));
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
msgbox_no_cb (GtkWidget *widget, gboolean *result)
Packit 98cdb6
{
Packit 98cdb6
  *result = 1;
Packit 98cdb6
  gtk_object_destroy (GTK_OBJECT (gtk_widget_get_toplevel (widget)));
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gboolean
Packit 98cdb6
msgbox_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer data)
Packit 98cdb6
{
Packit 98cdb6
  if (event->keyval == GDK_Escape)
Packit 98cdb6
    {
Packit 98cdb6
      g_signal_stop_emission_by_name (widget, "key_press_event");
Packit 98cdb6
      gtk_object_destroy (GTK_OBJECT (widget));
Packit 98cdb6
      return TRUE;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return FALSE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/* Don't copy this example, it's all crack-smoking - you can just use
Packit 98cdb6
 * GtkMessageDialog now
Packit 98cdb6
 */
Packit 98cdb6
gint
Packit 98cdb6
msgbox_run (GtkWindow  *parent,
Packit 98cdb6
	    const char *message,
Packit 98cdb6
	    const char *yes_button,
Packit 98cdb6
	    const char *no_button,
Packit 98cdb6
	    const char *cancel_button,
Packit 98cdb6
	    gint default_index)
Packit 98cdb6
{
Packit 98cdb6
  gboolean result = -1;
Packit 98cdb6
  GtkWidget *dialog;
Packit 98cdb6
  GtkWidget *button;
Packit 98cdb6
  GtkWidget *label;
Packit 98cdb6
  GtkWidget *vbox;
Packit 98cdb6
  GtkWidget *button_box;
Packit 98cdb6
  GtkWidget *separator;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (message != NULL, FALSE);
Packit 98cdb6
  g_return_val_if_fail (default_index >= 0 && default_index <= 1, FALSE);
Packit 98cdb6
Packit 98cdb6
  if (!parent)
Packit 98cdb6
    parent = get_active_window ();
Packit 98cdb6
  
Packit 98cdb6
  /* Create a dialog
Packit 98cdb6
   */
Packit 98cdb6
  dialog = gtk_window_new (GTK_WINDOW_TOPLEVEL);
Packit 98cdb6
  gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
Packit 98cdb6
  if (parent)
Packit 98cdb6
    gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
Packit 98cdb6
  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
Packit 98cdb6
Packit 98cdb6
  /* Quit our recursive main loop when the dialog is destroyed.
Packit 98cdb6
   */
Packit 98cdb6
  g_signal_connect (dialog, "destroy",
Packit 98cdb6
		    G_CALLBACK (gtk_main_quit), NULL);
Packit 98cdb6
Packit 98cdb6
  /* Catch Escape key presses and have them destroy the dialog
Packit 98cdb6
   */
Packit 98cdb6
  g_signal_connect (dialog, "key_press_event",
Packit 98cdb6
		    G_CALLBACK (msgbox_key_press_cb), NULL);
Packit 98cdb6
Packit 98cdb6
  /* Fill in the contents of the widget
Packit 98cdb6
   */
Packit 98cdb6
  vbox = gtk_vbox_new (FALSE, 0);
Packit 98cdb6
  gtk_container_add (GTK_CONTAINER (dialog), vbox);
Packit 98cdb6
  
Packit 98cdb6
  label = gtk_label_new (message);
Packit 98cdb6
  gtk_misc_set_padding (GTK_MISC (label), 12, 12);
Packit 98cdb6
  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
Packit 98cdb6
  gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
Packit 98cdb6
Packit 98cdb6
  separator = gtk_hseparator_new ();
Packit 98cdb6
  gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
Packit 98cdb6
Packit 98cdb6
  button_box = gtk_hbutton_box_new ();
Packit 98cdb6
  gtk_box_pack_start (GTK_BOX (vbox), button_box, FALSE, FALSE, 0);
Packit 98cdb6
  gtk_container_set_border_width (GTK_CONTAINER (button_box), 8);
Packit 98cdb6
  
Packit 98cdb6
Packit 98cdb6
  /* When Yes is clicked, call the msgbox_yes_cb
Packit 98cdb6
   * This sets the result variable and destroys the dialog
Packit 98cdb6
   */
Packit 98cdb6
  if (yes_button)
Packit 98cdb6
    {
Packit 98cdb6
      button = gtk_button_new_with_label (yes_button);
Packit 98cdb6
      gtk_widget_set_can_default (button, TRUE);
Packit 98cdb6
      gtk_container_add (GTK_CONTAINER (button_box), button);
Packit 98cdb6
Packit 98cdb6
      if (default_index == 0)
Packit 98cdb6
	gtk_widget_grab_default (button);
Packit 98cdb6
      
Packit 98cdb6
      g_signal_connect (button, "clicked",
Packit 98cdb6
			G_CALLBACK (msgbox_yes_cb), &result);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  /* When No is clicked, call the msgbox_no_cb
Packit 98cdb6
   * This sets the result variable and destroys the dialog
Packit 98cdb6
   */
Packit 98cdb6
  if (no_button)
Packit 98cdb6
    {
Packit 98cdb6
      button = gtk_button_new_with_label (no_button);
Packit 98cdb6
      gtk_widget_set_can_default (button, TRUE);
Packit 98cdb6
      gtk_container_add (GTK_CONTAINER (button_box), button);
Packit 98cdb6
Packit 98cdb6
      if (default_index == 0)
Packit 98cdb6
	gtk_widget_grab_default (button);
Packit 98cdb6
      
Packit 98cdb6
      g_signal_connect (button, "clicked",
Packit 98cdb6
			G_CALLBACK (msgbox_no_cb), &result);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  /* When Cancel is clicked, destroy the dialog
Packit 98cdb6
   */
Packit 98cdb6
  if (cancel_button)
Packit 98cdb6
    {
Packit 98cdb6
      button = gtk_button_new_with_label (cancel_button);
Packit 98cdb6
      gtk_widget_set_can_default (button, TRUE);
Packit 98cdb6
      gtk_container_add (GTK_CONTAINER (button_box), button);
Packit 98cdb6
      
Packit 98cdb6
      if (default_index == 1)
Packit 98cdb6
	gtk_widget_grab_default (button);
Packit 98cdb6
      
Packit 98cdb6
      g_signal_connect_swapped (button, "clicked",
Packit 98cdb6
				G_CALLBACK (gtk_object_destroy), dialog);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  gtk_widget_show_all (dialog);
Packit 98cdb6
Packit 98cdb6
  /* Run a recursive main loop until a button is clicked
Packit 98cdb6
   * or the user destroys the dialog through the window mananger */
Packit 98cdb6
  gtk_main ();
Packit 98cdb6
Packit 98cdb6
  return result;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
#ifdef DO_BLINK
Packit 98cdb6
/*
Packit 98cdb6
 * Example buffer filling code
Packit 98cdb6
 */
Packit 98cdb6
static gint
Packit 98cdb6
blink_timeout (gpointer data)
Packit 98cdb6
{
Packit 98cdb6
  GtkTextTag *tag;
Packit 98cdb6
  static gboolean flip = FALSE;
Packit 98cdb6
  
Packit 98cdb6
  tag = GTK_TEXT_TAG (data);
Packit 98cdb6
Packit 98cdb6
  g_object_set (tag,
Packit 98cdb6
                 "foreground", flip ? "blue" : "purple",
Packit 98cdb6
                 NULL);
Packit 98cdb6
Packit 98cdb6
  flip = !flip;
Packit 98cdb6
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
#endif
Packit 98cdb6
Packit 98cdb6
static gint
Packit 98cdb6
tag_event_handler (GtkTextTag *tag, GtkWidget *widget, GdkEvent *event,
Packit 98cdb6
                  const GtkTextIter *iter, gpointer user_data)
Packit 98cdb6
{
Packit 98cdb6
  gint char_index;
Packit 98cdb6
Packit 98cdb6
  char_index = gtk_text_iter_get_offset (iter);
Packit 98cdb6
  
Packit 98cdb6
  switch (event->type)
Packit 98cdb6
    {
Packit 98cdb6
    case GDK_MOTION_NOTIFY:
Packit 98cdb6
      printf ("Motion event at char %d tag `%s'\n",
Packit 98cdb6
             char_index, tag->name);
Packit 98cdb6
      break;
Packit 98cdb6
        
Packit 98cdb6
    case GDK_BUTTON_PRESS:
Packit 98cdb6
      printf ("Button press at char %d tag `%s'\n",
Packit 98cdb6
             char_index, tag->name);
Packit 98cdb6
      break;
Packit 98cdb6
        
Packit 98cdb6
    case GDK_2BUTTON_PRESS:
Packit 98cdb6
      printf ("Double click at char %d tag `%s'\n",
Packit 98cdb6
             char_index, tag->name);
Packit 98cdb6
      break;
Packit 98cdb6
        
Packit 98cdb6
    case GDK_3BUTTON_PRESS:
Packit 98cdb6
      printf ("Triple click at char %d tag `%s'\n",
Packit 98cdb6
             char_index, tag->name);
Packit 98cdb6
      break;
Packit 98cdb6
        
Packit 98cdb6
    case GDK_BUTTON_RELEASE:
Packit 98cdb6
      printf ("Button release at char %d tag `%s'\n",
Packit 98cdb6
             char_index, tag->name);
Packit 98cdb6
      break;
Packit 98cdb6
        
Packit 98cdb6
    case GDK_KEY_PRESS:
Packit 98cdb6
    case GDK_KEY_RELEASE:
Packit 98cdb6
      printf ("Key event at char %d tag `%s'\n",
Packit 98cdb6
              char_index, tag->name);
Packit 98cdb6
      break;
Packit 98cdb6
      
Packit 98cdb6
    case GDK_ENTER_NOTIFY:
Packit 98cdb6
    case GDK_LEAVE_NOTIFY:
Packit 98cdb6
    case GDK_PROPERTY_NOTIFY:
Packit 98cdb6
    case GDK_SELECTION_CLEAR:
Packit 98cdb6
    case GDK_SELECTION_REQUEST:
Packit 98cdb6
    case GDK_SELECTION_NOTIFY:
Packit 98cdb6
    case GDK_PROXIMITY_IN:
Packit 98cdb6
    case GDK_PROXIMITY_OUT:
Packit 98cdb6
    case GDK_DRAG_ENTER:
Packit 98cdb6
    case GDK_DRAG_LEAVE:
Packit 98cdb6
    case GDK_DRAG_MOTION:
Packit 98cdb6
    case GDK_DRAG_STATUS:
Packit 98cdb6
    case GDK_DROP_START:
Packit 98cdb6
    case GDK_DROP_FINISHED:
Packit 98cdb6
    default:
Packit 98cdb6
      break;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return FALSE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
setup_tag (GtkTextTag *tag)
Packit 98cdb6
{
Packit 98cdb6
  g_signal_connect (tag,
Packit 98cdb6
		    "event",
Packit 98cdb6
		    G_CALLBACK (tag_event_handler),
Packit 98cdb6
		    NULL);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static const char  *book_closed_xpm[] = {
Packit 98cdb6
"16 16 6 1",
Packit 98cdb6
"       c None s None",
Packit 98cdb6
".      c black",
Packit 98cdb6
"X      c red",
Packit 98cdb6
"o      c yellow",
Packit 98cdb6
"O      c #808080",
Packit 98cdb6
"#      c white",
Packit 98cdb6
"                ",
Packit 98cdb6
"       ..       ",
Packit 98cdb6
"     ..XX.      ",
Packit 98cdb6
"   ..XXXXX.     ",
Packit 98cdb6
" ..XXXXXXXX.    ",
Packit 98cdb6
".ooXXXXXXXXX.   ",
Packit 98cdb6
"..ooXXXXXXXXX.  ",
Packit 98cdb6
".X.ooXXXXXXXXX. ",
Packit 98cdb6
".XX.ooXXXXXX..  ",
Packit 98cdb6
" .XX.ooXXX..#O  ",
Packit 98cdb6
"  .XX.oo..##OO. ",
Packit 98cdb6
"   .XX..##OO..  ",
Packit 98cdb6
"    .X.#OO..    ",
Packit 98cdb6
"     ..O..      ",
Packit 98cdb6
"      ..        ",
Packit 98cdb6
"                "};
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
fill_example_buffer (GtkTextBuffer *buffer)
Packit 98cdb6
{
Packit 98cdb6
  GtkTextIter iter, iter2;
Packit 98cdb6
  GtkTextTag *tag;
Packit 98cdb6
  GtkTextChildAnchor *anchor;
Packit 98cdb6
  GdkColor color;
Packit 98cdb6
  GdkColor color2;
Packit 98cdb6
  GdkPixbuf *pixbuf;
Packit 98cdb6
  int i;
Packit 98cdb6
  char *str;
Packit 98cdb6
  
Packit 98cdb6
  /* FIXME this is broken if called twice on a buffer, since
Packit 98cdb6
   * we try to create tags a second time.
Packit 98cdb6
   */
Packit 98cdb6
  
Packit 98cdb6
  tag = gtk_text_buffer_create_tag (buffer, "fg_blue", NULL);
Packit 98cdb6
Packit 98cdb6
#ifdef DO_BLINK
Packit 98cdb6
  gtk_timeout_add (1000, blink_timeout, tag);
Packit 98cdb6
#endif     
Packit 98cdb6
 
Packit 98cdb6
  setup_tag (tag);
Packit 98cdb6
  
Packit 98cdb6
  color.red = color.green = 0;
Packit 98cdb6
  color.blue = 0xffff;
Packit 98cdb6
  color2.red = 0xfff;
Packit 98cdb6
  color2.blue = 0x0;
Packit 98cdb6
  color2.green = 0;
Packit 98cdb6
  g_object_set (tag,
Packit 98cdb6
                "foreground_gdk", &color,
Packit 98cdb6
                "background_gdk", &color2,
Packit 98cdb6
                "size_points", 24.0,
Packit 98cdb6
                NULL);
Packit 98cdb6
Packit 98cdb6
  tag = gtk_text_buffer_create_tag (buffer, "fg_red", NULL);
Packit 98cdb6
Packit 98cdb6
  setup_tag (tag);
Packit 98cdb6
      
Packit 98cdb6
  color.blue = color.green = 0;
Packit 98cdb6
  color.red = 0xffff;
Packit 98cdb6
  g_object_set (tag,
Packit 98cdb6
                "rise", -4 * PANGO_SCALE,
Packit 98cdb6
                "foreground_gdk", &color,
Packit 98cdb6
                NULL);
Packit 98cdb6
Packit 98cdb6
  tag = gtk_text_buffer_create_tag (buffer, "bg_green", NULL);
Packit 98cdb6
Packit 98cdb6
  setup_tag (tag);
Packit 98cdb6
      
Packit 98cdb6
  color.blue = color.red = 0;
Packit 98cdb6
  color.green = 0xffff;
Packit 98cdb6
  g_object_set (tag,
Packit 98cdb6
                "background_gdk", &color,
Packit 98cdb6
                "size_points", 10.0,
Packit 98cdb6
                NULL);
Packit 98cdb6
Packit 98cdb6
  tag = gtk_text_buffer_create_tag (buffer, "strikethrough", NULL);
Packit 98cdb6
Packit 98cdb6
  setup_tag (tag);
Packit 98cdb6
      
Packit 98cdb6
  g_object_set (tag,
Packit 98cdb6
                "strikethrough", TRUE,
Packit 98cdb6
                NULL);
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
  tag = gtk_text_buffer_create_tag (buffer, "underline", NULL);
Packit 98cdb6
Packit 98cdb6
  setup_tag (tag);
Packit 98cdb6
      
Packit 98cdb6
  g_object_set (tag,
Packit 98cdb6
                "underline", PANGO_UNDERLINE_SINGLE,
Packit 98cdb6
                NULL);
Packit 98cdb6
Packit 98cdb6
  tag = gtk_text_buffer_create_tag (buffer, "underline_error", NULL);
Packit 98cdb6
Packit 98cdb6
  setup_tag (tag);
Packit 98cdb6
      
Packit 98cdb6
  g_object_set (tag,
Packit 98cdb6
                "underline", PANGO_UNDERLINE_ERROR,
Packit 98cdb6
                NULL);
Packit 98cdb6
Packit 98cdb6
  tag = gtk_text_buffer_create_tag (buffer, "centered", NULL);
Packit 98cdb6
      
Packit 98cdb6
  g_object_set (tag,
Packit 98cdb6
                "justification", GTK_JUSTIFY_CENTER,
Packit 98cdb6
                NULL);
Packit 98cdb6
Packit 98cdb6
  tag = gtk_text_buffer_create_tag (buffer, "rtl_quote", NULL);
Packit 98cdb6
      
Packit 98cdb6
  g_object_set (tag,
Packit 98cdb6
                "wrap_mode", GTK_WRAP_WORD,
Packit 98cdb6
                "direction", GTK_TEXT_DIR_RTL,
Packit 98cdb6
                "indent", 30,
Packit 98cdb6
                "left_margin", 20,
Packit 98cdb6
                "right_margin", 20,
Packit 98cdb6
                NULL);
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
  tag = gtk_text_buffer_create_tag (buffer, "negative_indent", NULL);
Packit 98cdb6
      
Packit 98cdb6
  g_object_set (tag,
Packit 98cdb6
                "indent", -25,
Packit 98cdb6
                NULL);
Packit 98cdb6
  
Packit 98cdb6
  gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
Packit 98cdb6
Packit 98cdb6
  anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
Packit 98cdb6
Packit 98cdb6
  g_object_ref (anchor);
Packit 98cdb6
  
Packit 98cdb6
  g_object_set_data_full (G_OBJECT (buffer), "anchor", anchor,
Packit 98cdb6
                          (GDestroyNotify) g_object_unref);
Packit 98cdb6
  
Packit 98cdb6
  pixbuf = gdk_pixbuf_new_from_xpm_data (book_closed_xpm);
Packit 98cdb6
  
Packit 98cdb6
  i = 0;
Packit 98cdb6
  while (i < 100)
Packit 98cdb6
    {
Packit 98cdb6
      GtkTextMark * temp_mark;
Packit 98cdb6
      
Packit 98cdb6
      gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
Packit 98cdb6
          
Packit 98cdb6
      gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
Packit 98cdb6
          
Packit 98cdb6
      str = g_strdup_printf ("%d Hello World! blah blah blah blah blah blah blah blah blah blah blah blah\nwoo woo woo woo woo woo woo woo woo woo woo woo woo woo woo\n",
Packit 98cdb6
			    i);
Packit 98cdb6
      
Packit 98cdb6
      gtk_text_buffer_insert (buffer, &iter, str, -1);
Packit 98cdb6
Packit 98cdb6
      g_free (str);
Packit 98cdb6
      
Packit 98cdb6
      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 5);
Packit 98cdb6
          
Packit 98cdb6
      gtk_text_buffer_insert (buffer, &iter,
Packit 98cdb6
			     "(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"
Packit 98cdb6
			     /* This is UTF8 stuff, Emacs doesn't
Packit 98cdb6
				really know how to display it */
Packit 98cdb6
			     "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);
Packit 98cdb6
Packit 98cdb6
      temp_mark =
Packit 98cdb6
        gtk_text_buffer_create_mark (buffer, "tmp_mark", &iter, TRUE);
Packit 98cdb6
Packit 98cdb6
#if 1
Packit 98cdb6
      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 6);
Packit 98cdb6
      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter2, 0, 13);
Packit 98cdb6
Packit 98cdb6
      gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
Packit 98cdb6
Packit 98cdb6
      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 1, 10);
Packit 98cdb6
      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter2, 1, 16);
Packit 98cdb6
Packit 98cdb6
      gtk_text_buffer_apply_tag_by_name (buffer, "underline", &iter, &iter2);
Packit 98cdb6
Packit 98cdb6
      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 1, 4);
Packit 98cdb6
      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter2, 1, 7);
Packit 98cdb6
Packit 98cdb6
      gtk_text_buffer_apply_tag_by_name (buffer, "underline_error", &iter, &iter2);
Packit 98cdb6
Packit 98cdb6
      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 1, 14);
Packit 98cdb6
      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter2, 1, 24);
Packit 98cdb6
Packit 98cdb6
      gtk_text_buffer_apply_tag_by_name (buffer, "strikethrough", &iter, &iter2);
Packit 98cdb6
          
Packit 98cdb6
      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 9);
Packit 98cdb6
      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter2, 0, 16);
Packit 98cdb6
Packit 98cdb6
      gtk_text_buffer_apply_tag_by_name (buffer, "bg_green", &iter, &iter2);
Packit 98cdb6
  
Packit 98cdb6
      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 4, 2);
Packit 98cdb6
      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter2, 4, 10);
Packit 98cdb6
Packit 98cdb6
      gtk_text_buffer_apply_tag_by_name (buffer, "bg_green", &iter, &iter2);
Packit 98cdb6
Packit 98cdb6
      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 4, 8);
Packit 98cdb6
      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter2, 4, 15);
Packit 98cdb6
Packit 98cdb6
      gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
Packit 98cdb6
#endif
Packit 98cdb6
Packit 98cdb6
      gtk_text_buffer_get_iter_at_mark (buffer, &iter, temp_mark);
Packit 98cdb6
      gtk_text_buffer_insert (buffer, &iter, "Centered text!\n", -1);
Packit 98cdb6
	  
Packit 98cdb6
      gtk_text_buffer_get_iter_at_mark (buffer, &iter2, temp_mark);
Packit 98cdb6
      gtk_text_buffer_apply_tag_by_name (buffer, "centered", &iter2, &iter);
Packit 98cdb6
Packit 98cdb6
      gtk_text_buffer_move_mark (buffer, temp_mark, &iter);
Packit 98cdb6
      gtk_text_buffer_insert (buffer, &iter, "Word wrapped, Right-to-left Quote\n", -1);
Packit 98cdb6
      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);
Packit 98cdb6
      gtk_text_buffer_get_iter_at_mark (buffer, &iter2, temp_mark);
Packit 98cdb6
      gtk_text_buffer_apply_tag_by_name (buffer, "rtl_quote", &iter2, &iter);
Packit 98cdb6
Packit 98cdb6
      gtk_text_buffer_insert_with_tags (buffer, &iter,
Packit 98cdb6
                                        "Paragraph with negative indentation. blah blah blah blah blah. The quick brown fox jumped over the lazy dog.\n",
Packit 98cdb6
                                        -1,
Packit 98cdb6
                                        gtk_text_tag_table_lookup (gtk_text_buffer_get_tag_table (buffer),
Packit 98cdb6
                                                                   "negative_indent"),
Packit 98cdb6
                                        NULL);
Packit 98cdb6
      
Packit 98cdb6
      ++i;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  g_object_unref (pixbuf);
Packit 98cdb6
  
Packit 98cdb6
  printf ("%d lines %d chars\n",
Packit 98cdb6
          gtk_text_buffer_get_line_count (buffer),
Packit 98cdb6
          gtk_text_buffer_get_char_count (buffer));
Packit 98cdb6
Packit 98cdb6
  /* Move cursor to start */
Packit 98cdb6
  gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
Packit 98cdb6
  gtk_text_buffer_place_cursor (buffer, &iter);
Packit 98cdb6
  
Packit 98cdb6
  gtk_text_buffer_set_modified (buffer, FALSE);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
gboolean
Packit 98cdb6
fill_file_buffer (GtkTextBuffer *buffer, const char *filename)
Packit 98cdb6
{
Packit 98cdb6
  FILE* f;
Packit 98cdb6
  gchar buf[2048];
Packit 98cdb6
  gint remaining = 0;
Packit 98cdb6
  GtkTextIter iter, end;
Packit 98cdb6
Packit 98cdb6
  f = fopen (filename, "r");
Packit 98cdb6
  
Packit 98cdb6
  if (f == NULL)
Packit 98cdb6
    {
Packit 98cdb6
      gchar *err = g_strdup_printf ("Cannot open file '%s': %s",
Packit 98cdb6
				    filename, g_strerror (errno));
Packit 98cdb6
      msgbox_run (NULL, err, "OK", NULL, NULL, 0);
Packit 98cdb6
      g_free (err);
Packit 98cdb6
      return FALSE;
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
Packit 98cdb6
  while (!feof (f))
Packit 98cdb6
    {
Packit 98cdb6
      gint count;
Packit 98cdb6
      const char *leftover;
Packit 98cdb6
      int to_read = 2047  - remaining;
Packit 98cdb6
Packit 98cdb6
      count = fread (buf + remaining, 1, to_read, f);
Packit 98cdb6
      buf[count + remaining] = '\0';
Packit 98cdb6
Packit 98cdb6
      g_utf8_validate (buf, count + remaining, &leftover);
Packit 98cdb6
      
Packit 98cdb6
      g_assert (g_utf8_validate (buf, leftover - buf, NULL));
Packit 98cdb6
      gtk_text_buffer_insert (buffer, &iter, buf, leftover - buf);
Packit 98cdb6
Packit 98cdb6
      remaining = (buf + remaining + count) - leftover;
Packit 98cdb6
      g_memmove (buf, leftover, remaining);
Packit 98cdb6
Packit 98cdb6
      if (remaining > 6 || count < to_read)
Packit 98cdb6
	  break;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  if (remaining)
Packit 98cdb6
    {
Packit 98cdb6
      gchar *err = g_strdup_printf ("Invalid UTF-8 data encountered reading file '%s'", filename);
Packit 98cdb6
      msgbox_run (NULL, err, "OK", NULL, NULL, 0);
Packit 98cdb6
      g_free (err);
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  /* We had a newline in the buffer to begin with. (The buffer always contains
Packit 98cdb6
   * a newline, so we delete to the end of the buffer to clean up.
Packit 98cdb6
   */
Packit 98cdb6
  gtk_text_buffer_get_end_iter (buffer, &end;;
Packit 98cdb6
  gtk_text_buffer_delete (buffer, &iter, &end;;
Packit 98cdb6
  
Packit 98cdb6
  gtk_text_buffer_set_modified (buffer, FALSE);
Packit 98cdb6
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gint
Packit 98cdb6
delete_event_cb (GtkWidget *window, GdkEventAny *event, gpointer data)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (window);
Packit 98cdb6
Packit 98cdb6
  push_active_window (GTK_WINDOW (window));
Packit 98cdb6
  check_close_view (view);
Packit 98cdb6
  pop_active_window ();
Packit 98cdb6
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/*
Packit 98cdb6
 * Menu callbacks
Packit 98cdb6
 */
Packit 98cdb6
Packit 98cdb6
static View *
Packit 98cdb6
get_empty_view (View *view)
Packit 98cdb6
{
Packit 98cdb6
  if (!view->buffer->filename &&
Packit 98cdb6
      !gtk_text_buffer_get_modified (view->buffer->buffer))
Packit 98cdb6
    return view;
Packit 98cdb6
  else
Packit 98cdb6
    return create_view (create_buffer ());
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static View *
Packit 98cdb6
view_from_widget (GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  if (GTK_IS_MENU_ITEM (widget))
Packit 98cdb6
    {
Packit 98cdb6
      GtkItemFactory *item_factory = gtk_item_factory_from_widget (widget);
Packit 98cdb6
      return g_object_get_data (G_OBJECT (item_factory), "view");      
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    {
Packit 98cdb6
      GtkWidget *app = gtk_widget_get_toplevel (widget);
Packit 98cdb6
      return g_object_get_data (G_OBJECT (app), "view");
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_new (gpointer             callback_data,
Packit 98cdb6
	guint                callback_action,
Packit 98cdb6
	GtkWidget           *widget)
Packit 98cdb6
{
Packit 98cdb6
  create_view (create_buffer ());
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_new_view (gpointer             callback_data,
Packit 98cdb6
	     guint                callback_action,
Packit 98cdb6
	     GtkWidget           *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  
Packit 98cdb6
  create_view (view->buffer);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
gboolean
Packit 98cdb6
open_ok_func (const char *filename, gpointer data)
Packit 98cdb6
{
Packit 98cdb6
  View *view = data;
Packit 98cdb6
  View *new_view = get_empty_view (view);
Packit 98cdb6
Packit 98cdb6
  if (!fill_file_buffer (new_view->buffer->buffer, filename))
Packit 98cdb6
    {
Packit 98cdb6
      if (new_view != view)
Packit 98cdb6
	close_view (new_view);
Packit 98cdb6
      return FALSE;
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    {
Packit 98cdb6
      g_free (new_view->buffer->filename);
Packit 98cdb6
      new_view->buffer->filename = g_strdup (filename);
Packit 98cdb6
      buffer_filename_set (new_view->buffer);
Packit 98cdb6
      
Packit 98cdb6
      return TRUE;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_open (gpointer             callback_data,
Packit 98cdb6
	 guint                callback_action,
Packit 98cdb6
	 GtkWidget           *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
Packit 98cdb6
  push_active_window (GTK_WINDOW (view->window));
Packit 98cdb6
  filesel_run (NULL, "Open File", NULL, open_ok_func, view);
Packit 98cdb6
  pop_active_window ();
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_save_as (gpointer             callback_data,
Packit 98cdb6
	    guint                callback_action,
Packit 98cdb6
	    GtkWidget           *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);  
Packit 98cdb6
Packit 98cdb6
  push_active_window (GTK_WINDOW (view->window));
Packit 98cdb6
  save_as_buffer (view->buffer);
Packit 98cdb6
  pop_active_window ();
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_save (gpointer             callback_data,
Packit 98cdb6
	 guint                callback_action,
Packit 98cdb6
	 GtkWidget           *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
Packit 98cdb6
  push_active_window (GTK_WINDOW (view->window));
Packit 98cdb6
  if (!view->buffer->filename)
Packit 98cdb6
    do_save_as (callback_data, callback_action, widget);
Packit 98cdb6
  else
Packit 98cdb6
    save_buffer (view->buffer);
Packit 98cdb6
  pop_active_window ();
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_close   (gpointer             callback_data,
Packit 98cdb6
	    guint                callback_action,
Packit 98cdb6
	    GtkWidget           *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
Packit 98cdb6
  push_active_window (GTK_WINDOW (view->window));
Packit 98cdb6
  check_close_view (view);
Packit 98cdb6
  pop_active_window ();
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_exit    (gpointer             callback_data,
Packit 98cdb6
	    guint                callback_action,
Packit 98cdb6
	    GtkWidget           *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
Packit 98cdb6
  GSList *tmp_list = buffers;
Packit 98cdb6
Packit 98cdb6
  push_active_window (GTK_WINDOW (view->window));
Packit 98cdb6
  while (tmp_list)
Packit 98cdb6
    {
Packit 98cdb6
      if (!check_buffer_saved (tmp_list->data))
Packit 98cdb6
	return;
Packit 98cdb6
Packit 98cdb6
      tmp_list = tmp_list->next;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  gtk_main_quit ();
Packit 98cdb6
  pop_active_window ();
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_example (gpointer             callback_data,
Packit 98cdb6
	    guint                callback_action,
Packit 98cdb6
	    GtkWidget           *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  View *new_view;
Packit 98cdb6
Packit 98cdb6
  new_view = get_empty_view (view);
Packit 98cdb6
  
Packit 98cdb6
  fill_example_buffer (new_view->buffer->buffer);
Packit 98cdb6
Packit 98cdb6
  view_add_example_widgets (new_view);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_insert_and_scroll (gpointer             callback_data,
Packit 98cdb6
                      guint                callback_action,
Packit 98cdb6
                      GtkWidget           *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  GtkTextBuffer *buffer;
Packit 98cdb6
  GtkTextIter start, end;
Packit 98cdb6
  GtkTextMark *mark;
Packit 98cdb6
  
Packit 98cdb6
  buffer = view->buffer->buffer;
Packit 98cdb6
Packit 98cdb6
  gtk_text_buffer_get_bounds (buffer, &start, &end;;
Packit 98cdb6
  mark = gtk_text_buffer_create_mark (buffer, NULL, &end, /* right grav */ FALSE);
Packit 98cdb6
Packit 98cdb6
  gtk_text_buffer_insert (buffer, &end,
Packit 98cdb6
                          "Hello this is multiple lines of text\n"
Packit 98cdb6
                          "Line 1\n"  "Line 2\n"
Packit 98cdb6
                          "Line 3\n"  "Line 4\n"
Packit 98cdb6
                          "Line 5\n",
Packit 98cdb6
                          -1);
Packit 98cdb6
Packit 98cdb6
  gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (view->text_view), mark,
Packit 98cdb6
                                0, TRUE, 0.0, 1.0);
Packit 98cdb6
  gtk_text_buffer_delete_mark (buffer, mark);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_wrap_changed (gpointer             callback_data,
Packit 98cdb6
		 guint                callback_action,
Packit 98cdb6
		 GtkWidget           *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
Packit 98cdb6
  gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view->text_view), callback_action);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_direction_changed (gpointer             callback_data,
Packit 98cdb6
		      guint                callback_action,
Packit 98cdb6
		      GtkWidget           *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  
Packit 98cdb6
  gtk_widget_set_direction (view->text_view, callback_action);
Packit 98cdb6
  gtk_widget_queue_resize (view->text_view);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_spacing_changed (gpointer             callback_data,
Packit 98cdb6
                    guint                callback_action,
Packit 98cdb6
                    GtkWidget           *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
Packit 98cdb6
  if (callback_action)
Packit 98cdb6
    {
Packit 98cdb6
      gtk_text_view_set_pixels_above_lines (GTK_TEXT_VIEW (view->text_view),
Packit 98cdb6
                                            23);
Packit 98cdb6
      gtk_text_view_set_pixels_below_lines (GTK_TEXT_VIEW (view->text_view),
Packit 98cdb6
                                            21);
Packit 98cdb6
      gtk_text_view_set_pixels_inside_wrap (GTK_TEXT_VIEW (view->text_view),
Packit 98cdb6
                                            9);
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    {
Packit 98cdb6
      gtk_text_view_set_pixels_above_lines (GTK_TEXT_VIEW (view->text_view),
Packit 98cdb6
                                            0);
Packit 98cdb6
      gtk_text_view_set_pixels_below_lines (GTK_TEXT_VIEW (view->text_view),
Packit 98cdb6
                                            0);
Packit 98cdb6
      gtk_text_view_set_pixels_inside_wrap (GTK_TEXT_VIEW (view->text_view),
Packit 98cdb6
                                            0);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_editable_changed (gpointer callback_data,
Packit 98cdb6
                     guint callback_action,
Packit 98cdb6
                     GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
Packit 98cdb6
  gtk_text_view_set_editable (GTK_TEXT_VIEW (view->text_view), callback_action);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
change_cursor_color (GtkWidget *widget,
Packit 98cdb6
		     gboolean   set)
Packit 98cdb6
{
Packit 98cdb6
  if (set)
Packit 98cdb6
    {
Packit 98cdb6
      GdkColor red = {0, 65535, 0, 0};
Packit 98cdb6
      gtk_widget_modify_cursor (widget, &red, &red;;
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    gtk_widget_modify_cursor (widget, NULL, NULL);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_cursor_visible_changed (gpointer callback_data,
Packit 98cdb6
                           guint callback_action,
Packit 98cdb6
                           GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
Packit 98cdb6
  switch (callback_action)
Packit 98cdb6
    {
Packit 98cdb6
    case 0:
Packit 98cdb6
      gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view->text_view), FALSE);
Packit 98cdb6
      break;
Packit 98cdb6
    case 1:
Packit 98cdb6
      gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view->text_view), TRUE);
Packit 98cdb6
      change_cursor_color (view->text_view, FALSE);
Packit 98cdb6
      break;
Packit 98cdb6
    case 2:
Packit 98cdb6
      gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view->text_view), TRUE);
Packit 98cdb6
      change_cursor_color (view->text_view, TRUE);
Packit 98cdb6
      break;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_color_cycle_changed (gpointer callback_data,
Packit 98cdb6
                        guint callback_action,
Packit 98cdb6
                        GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
Packit 98cdb6
  buffer_set_colors (view->buffer, callback_action);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_apply_editable (gpointer callback_data,
Packit 98cdb6
                   guint callback_action,
Packit 98cdb6
                   GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  GtkTextIter start;
Packit 98cdb6
  GtkTextIter end;
Packit 98cdb6
  
Packit 98cdb6
  if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
Packit 98cdb6
                                            &start, &end))
Packit 98cdb6
    {
Packit 98cdb6
      if (callback_action)
Packit 98cdb6
        {
Packit 98cdb6
          gtk_text_buffer_remove_tag (view->buffer->buffer,
Packit 98cdb6
                                      view->buffer->not_editable_tag,
Packit 98cdb6
                                      &start, &end;;
Packit 98cdb6
        }
Packit 98cdb6
      else
Packit 98cdb6
        {
Packit 98cdb6
          gtk_text_buffer_apply_tag (view->buffer->buffer,
Packit 98cdb6
                                     view->buffer->not_editable_tag,
Packit 98cdb6
                                     &start, &end;;
Packit 98cdb6
        }
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_apply_invisible (gpointer callback_data,
Packit 98cdb6
                    guint callback_action,
Packit 98cdb6
                    GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  GtkTextIter start;
Packit 98cdb6
  GtkTextIter end;
Packit 98cdb6
  
Packit 98cdb6
  if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
Packit 98cdb6
                                            &start, &end))
Packit 98cdb6
    {
Packit 98cdb6
      if (callback_action)
Packit 98cdb6
        {
Packit 98cdb6
          gtk_text_buffer_remove_tag (view->buffer->buffer,
Packit 98cdb6
                                      view->buffer->invisible_tag,
Packit 98cdb6
                                      &start, &end;;
Packit 98cdb6
        }
Packit 98cdb6
      else
Packit 98cdb6
        {
Packit 98cdb6
          gtk_text_buffer_apply_tag (view->buffer->buffer,
Packit 98cdb6
                                     view->buffer->invisible_tag,
Packit 98cdb6
                                     &start, &end;;
Packit 98cdb6
        }
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_apply_rise (gpointer callback_data,
Packit 98cdb6
	       guint callback_action,
Packit 98cdb6
	       GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  GtkTextIter start;
Packit 98cdb6
  GtkTextIter end;
Packit 98cdb6
  
Packit 98cdb6
  if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
Packit 98cdb6
                                            &start, &end))
Packit 98cdb6
    {
Packit 98cdb6
      if (callback_action)
Packit 98cdb6
        {
Packit 98cdb6
          gtk_text_buffer_remove_tag (view->buffer->buffer,
Packit 98cdb6
                                      view->buffer->rise_tag,
Packit 98cdb6
                                      &start, &end;;
Packit 98cdb6
        }
Packit 98cdb6
      else
Packit 98cdb6
        {
Packit 98cdb6
          gtk_text_buffer_apply_tag (view->buffer->buffer,
Packit 98cdb6
                                     view->buffer->rise_tag,
Packit 98cdb6
                                     &start, &end;;
Packit 98cdb6
        }
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_apply_large (gpointer callback_data,
Packit 98cdb6
		guint callback_action,
Packit 98cdb6
		GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  GtkTextIter start;
Packit 98cdb6
  GtkTextIter end;
Packit 98cdb6
  
Packit 98cdb6
  if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
Packit 98cdb6
                                            &start, &end))
Packit 98cdb6
    {
Packit 98cdb6
      if (callback_action)
Packit 98cdb6
        {
Packit 98cdb6
          gtk_text_buffer_remove_tag (view->buffer->buffer,
Packit 98cdb6
                                      view->buffer->large_tag,
Packit 98cdb6
                                      &start, &end;;
Packit 98cdb6
        }
Packit 98cdb6
      else
Packit 98cdb6
        {
Packit 98cdb6
          gtk_text_buffer_apply_tag (view->buffer->buffer,
Packit 98cdb6
                                     view->buffer->large_tag,
Packit 98cdb6
                                     &start, &end;;
Packit 98cdb6
        }
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_apply_indent (gpointer callback_data,
Packit 98cdb6
		 guint callback_action,
Packit 98cdb6
		 GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  GtkTextIter start;
Packit 98cdb6
  GtkTextIter end;
Packit 98cdb6
  
Packit 98cdb6
  if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
Packit 98cdb6
                                            &start, &end))
Packit 98cdb6
    {
Packit 98cdb6
      if (callback_action)
Packit 98cdb6
        {
Packit 98cdb6
          gtk_text_buffer_remove_tag (view->buffer->buffer,
Packit 98cdb6
                                      view->buffer->indent_tag,
Packit 98cdb6
                                      &start, &end;;
Packit 98cdb6
        }
Packit 98cdb6
      else
Packit 98cdb6
        {
Packit 98cdb6
          gtk_text_buffer_apply_tag (view->buffer->buffer,
Packit 98cdb6
                                     view->buffer->indent_tag,
Packit 98cdb6
                                     &start, &end;;
Packit 98cdb6
        }
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_apply_margin (gpointer callback_data,
Packit 98cdb6
		 guint callback_action,
Packit 98cdb6
		 GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  GtkTextIter start;
Packit 98cdb6
  GtkTextIter end;
Packit 98cdb6
  
Packit 98cdb6
  if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
Packit 98cdb6
                                            &start, &end))
Packit 98cdb6
    {
Packit 98cdb6
      if (callback_action)
Packit 98cdb6
        {
Packit 98cdb6
          gtk_text_buffer_remove_tag (view->buffer->buffer,
Packit 98cdb6
                                      view->buffer->margin_tag,
Packit 98cdb6
                                      &start, &end;;
Packit 98cdb6
        }
Packit 98cdb6
      else
Packit 98cdb6
        {
Packit 98cdb6
          gtk_text_buffer_apply_tag (view->buffer->buffer,
Packit 98cdb6
                                     view->buffer->margin_tag,
Packit 98cdb6
                                     &start, &end;;
Packit 98cdb6
        }
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_apply_tabs (gpointer callback_data,
Packit 98cdb6
               guint callback_action,
Packit 98cdb6
               GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  GtkTextIter start;
Packit 98cdb6
  GtkTextIter end;
Packit 98cdb6
  
Packit 98cdb6
  if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
Packit 98cdb6
                                            &start, &end))
Packit 98cdb6
    {
Packit 98cdb6
      if (callback_action)
Packit 98cdb6
        {
Packit 98cdb6
          gtk_text_buffer_remove_tag (view->buffer->buffer,
Packit 98cdb6
                                      view->buffer->custom_tabs_tag,
Packit 98cdb6
                                      &start, &end;;
Packit 98cdb6
        }
Packit 98cdb6
      else
Packit 98cdb6
        {
Packit 98cdb6
          gtk_text_buffer_apply_tag (view->buffer->buffer,
Packit 98cdb6
                                     view->buffer->custom_tabs_tag,
Packit 98cdb6
                                     &start, &end;;
Packit 98cdb6
        }
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_apply_colors (gpointer callback_data,
Packit 98cdb6
                 guint callback_action,
Packit 98cdb6
                 GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  Buffer *buffer = view->buffer;
Packit 98cdb6
  GtkTextIter start;
Packit 98cdb6
  GtkTextIter end;
Packit 98cdb6
  
Packit 98cdb6
  if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
Packit 98cdb6
                                            &start, &end))
Packit 98cdb6
    {
Packit 98cdb6
      if (!callback_action)
Packit 98cdb6
        {
Packit 98cdb6
          GSList *tmp;
Packit 98cdb6
          
Packit 98cdb6
          tmp = buffer->color_tags;
Packit 98cdb6
          while (tmp != NULL)
Packit 98cdb6
            {
Packit 98cdb6
              gtk_text_buffer_remove_tag (view->buffer->buffer,
Packit 98cdb6
                                          tmp->data,
Packit 98cdb6
                                          &start, &end;;              
Packit 98cdb6
              tmp = g_slist_next (tmp);
Packit 98cdb6
            }
Packit 98cdb6
        }
Packit 98cdb6
      else
Packit 98cdb6
        {
Packit 98cdb6
          GSList *tmp;
Packit 98cdb6
          
Packit 98cdb6
          tmp = buffer->color_tags;
Packit 98cdb6
          while (TRUE)
Packit 98cdb6
            {
Packit 98cdb6
              GtkTextIter next;
Packit 98cdb6
              gboolean done = FALSE;
Packit 98cdb6
              
Packit 98cdb6
              next = start;
Packit 98cdb6
              gtk_text_iter_forward_char (&next;;
Packit 98cdb6
              gtk_text_iter_forward_char (&next;;
Packit 98cdb6
Packit 98cdb6
              if (gtk_text_iter_compare (&next, &end) >= 0)
Packit 98cdb6
                {
Packit 98cdb6
                  next = end;
Packit 98cdb6
                  done = TRUE;
Packit 98cdb6
                }
Packit 98cdb6
              
Packit 98cdb6
              gtk_text_buffer_apply_tag (view->buffer->buffer,
Packit 98cdb6
                                         tmp->data,
Packit 98cdb6
                                         &start, &next;;
Packit 98cdb6
Packit 98cdb6
              start = next;
Packit 98cdb6
Packit 98cdb6
              if (done)
Packit 98cdb6
                return;
Packit 98cdb6
              
Packit 98cdb6
              tmp = g_slist_next (tmp);
Packit 98cdb6
              if (tmp == NULL)
Packit 98cdb6
                tmp = buffer->color_tags;
Packit 98cdb6
            } 
Packit 98cdb6
        }
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_remove_tags (gpointer callback_data,
Packit 98cdb6
                guint callback_action,
Packit 98cdb6
                GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  GtkTextIter start;
Packit 98cdb6
  GtkTextIter end;
Packit 98cdb6
  
Packit 98cdb6
  if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
Packit 98cdb6
                                            &start, &end))
Packit 98cdb6
    {
Packit 98cdb6
      gtk_text_buffer_remove_all_tags (view->buffer->buffer,
Packit 98cdb6
                                       &start, &end;;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_properties (gpointer callback_data,
Packit 98cdb6
                guint callback_action,
Packit 98cdb6
                GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
Packit 98cdb6
  create_prop_editor (G_OBJECT (view->text_view), 0);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
rich_text_store_populate (GtkListStore  *store,
Packit 98cdb6
                          GtkTextBuffer *buffer,
Packit 98cdb6
                          gboolean       deserialize)
Packit 98cdb6
{
Packit 98cdb6
  GdkAtom *formats;
Packit 98cdb6
  gint     n_formats;
Packit 98cdb6
  gint     i;
Packit 98cdb6
Packit 98cdb6
  gtk_list_store_clear (store);
Packit 98cdb6
Packit 98cdb6
  if (deserialize)
Packit 98cdb6
    formats = gtk_text_buffer_get_deserialize_formats (buffer, &n_formats);
Packit 98cdb6
  else
Packit 98cdb6
    formats = gtk_text_buffer_get_serialize_formats (buffer, &n_formats);
Packit 98cdb6
Packit 98cdb6
  for (i = 0; i < n_formats; i++)
Packit 98cdb6
    {
Packit 98cdb6
      GtkTreeIter  iter;
Packit 98cdb6
      gchar       *mime_type;
Packit 98cdb6
      gboolean     can_create_tags = FALSE;
Packit 98cdb6
Packit 98cdb6
      mime_type = gdk_atom_name (formats[i]);
Packit 98cdb6
Packit 98cdb6
      if (deserialize)
Packit 98cdb6
        can_create_tags =
Packit 98cdb6
          gtk_text_buffer_deserialize_get_can_create_tags (buffer, formats[i]);
Packit 98cdb6
Packit 98cdb6
      gtk_list_store_append (store, &iter);
Packit 98cdb6
      gtk_list_store_set (store, &iter,
Packit 98cdb6
                          0, formats[i],
Packit 98cdb6
                          1, mime_type,
Packit 98cdb6
                          2, can_create_tags,
Packit 98cdb6
                          -1);
Packit 98cdb6
Packit 98cdb6
      g_free (mime_type);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  g_free (formats);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
rich_text_paste_target_list_notify (GtkTextBuffer    *buffer,
Packit 98cdb6
                                    const GParamSpec *pspec,
Packit 98cdb6
                                    GtkListStore     *store)
Packit 98cdb6
{
Packit 98cdb6
  rich_text_store_populate (store, buffer, TRUE);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
rich_text_copy_target_list_notify (GtkTextBuffer    *buffer,
Packit 98cdb6
                                   const GParamSpec *pspec,
Packit 98cdb6
                                   GtkListStore     *store)
Packit 98cdb6
{
Packit 98cdb6
  rich_text_store_populate (store, buffer, FALSE);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
rich_text_can_create_tags_toggled (GtkCellRendererToggle *toggle,
Packit 98cdb6
                                   const gchar           *path,
Packit 98cdb6
                                   GtkTreeModel          *model)
Packit 98cdb6
{
Packit 98cdb6
  GtkTreeIter iter;
Packit 98cdb6
Packit 98cdb6
  if (gtk_tree_model_get_iter_from_string (model, &iter, path))
Packit 98cdb6
    {
Packit 98cdb6
      GtkTextBuffer *buffer;
Packit 98cdb6
      GdkAtom        format;
Packit 98cdb6
      gboolean       can_create_tags;
Packit 98cdb6
Packit 98cdb6
      buffer = g_object_get_data (G_OBJECT (model), "buffer");
Packit 98cdb6
Packit 98cdb6
      gtk_tree_model_get (model, &iter,
Packit 98cdb6
                          0, &format,
Packit 98cdb6
                          2, &can_create_tags,
Packit 98cdb6
                          -1);
Packit 98cdb6
Packit 98cdb6
      gtk_text_buffer_deserialize_set_can_create_tags (buffer, format,
Packit 98cdb6
                                                       !can_create_tags);
Packit 98cdb6
Packit 98cdb6
      gtk_list_store_set (GTK_LIST_STORE (model), &iter,
Packit 98cdb6
                          2, !can_create_tags,
Packit 98cdb6
                          -1);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
rich_text_unregister_clicked (GtkWidget   *button,
Packit 98cdb6
                              GtkTreeView *tv)
Packit 98cdb6
{
Packit 98cdb6
  GtkTreeSelection *sel = gtk_tree_view_get_selection (tv);
Packit 98cdb6
  GtkTreeModel     *model;
Packit 98cdb6
  GtkTreeIter       iter;
Packit 98cdb6
Packit 98cdb6
  if (gtk_tree_selection_get_selected (sel, &model, &iter))
Packit 98cdb6
    {
Packit 98cdb6
      GtkTextBuffer *buffer;
Packit 98cdb6
      gboolean       deserialize;
Packit 98cdb6
      GdkAtom        format;
Packit 98cdb6
Packit 98cdb6
      buffer = g_object_get_data (G_OBJECT (model), "buffer");
Packit 98cdb6
      deserialize = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (model),
Packit 98cdb6
                                                        "deserialize"));
Packit 98cdb6
Packit 98cdb6
      gtk_tree_model_get (model, &iter,
Packit 98cdb6
                          0, &format,
Packit 98cdb6
                          -1);
Packit 98cdb6
Packit 98cdb6
      if (deserialize)
Packit 98cdb6
        gtk_text_buffer_unregister_deserialize_format (buffer, format);
Packit 98cdb6
      else
Packit 98cdb6
        gtk_text_buffer_unregister_serialize_format (buffer, format);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
rich_text_register_clicked (GtkWidget   *button,
Packit 98cdb6
                            GtkTreeView *tv)
Packit 98cdb6
{
Packit 98cdb6
  GtkWidget *dialog;
Packit 98cdb6
  GtkWidget *label;
Packit 98cdb6
  GtkWidget *entry;
Packit 98cdb6
Packit 98cdb6
  dialog = gtk_dialog_new_with_buttons ("Register new Tagset",
Packit 98cdb6
                                        GTK_WINDOW (gtk_widget_get_toplevel (button)),
Packit 98cdb6
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
Packit 98cdb6
                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
Packit 98cdb6
                                        GTK_STOCK_OK,     GTK_RESPONSE_OK,
Packit 98cdb6
                                        NULL);
Packit 98cdb6
  label = gtk_label_new ("Enter tagset name or leave blank for "
Packit 98cdb6
                         "unrestricted internal format:");
Packit 98cdb6
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), label,
Packit 98cdb6
                      FALSE, FALSE, 0);
Packit 98cdb6
Packit 98cdb6
  entry = gtk_entry_new ();
Packit 98cdb6
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), entry,
Packit 98cdb6
                      FALSE, FALSE, 0);
Packit 98cdb6
Packit 98cdb6
  gtk_widget_show_all (dialog);
Packit 98cdb6
Packit 98cdb6
  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
Packit 98cdb6
    {
Packit 98cdb6
      GtkTreeModel  *model  = gtk_tree_view_get_model (tv);
Packit 98cdb6
      GtkTextBuffer *buffer = g_object_get_data (G_OBJECT (model), "buffer");
Packit 98cdb6
      const gchar   *tagset = gtk_entry_get_text (GTK_ENTRY (entry));
Packit 98cdb6
      gboolean       deserialize;
Packit 98cdb6
Packit 98cdb6
      deserialize = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (model),
Packit 98cdb6
                                                        "deserialize"));
Packit 98cdb6
Packit 98cdb6
      if (tagset && ! strlen (tagset))
Packit 98cdb6
        tagset = NULL;
Packit 98cdb6
Packit 98cdb6
      if (deserialize)
Packit 98cdb6
        gtk_text_buffer_register_deserialize_tagset (buffer, tagset);
Packit 98cdb6
      else
Packit 98cdb6
        gtk_text_buffer_register_serialize_tagset (buffer, tagset);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  gtk_widget_destroy (dialog);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_rich_text (gpointer callback_data,
Packit 98cdb6
              guint deserialize,
Packit 98cdb6
              GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  GtkTextBuffer *buffer;
Packit 98cdb6
  GtkWidget *dialog;
Packit 98cdb6
  GtkWidget *tv;
Packit 98cdb6
  GtkWidget *sw;
Packit 98cdb6
  GtkWidget *hbox;
Packit 98cdb6
  GtkWidget *button;
Packit 98cdb6
  GtkListStore *store;
Packit 98cdb6
Packit 98cdb6
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view->text_view));
Packit 98cdb6
Packit 98cdb6
  dialog = gtk_dialog_new_with_buttons (deserialize ?
Packit 98cdb6
                                        "Rich Text Paste & Drop" :
Packit 98cdb6
                                        "Rich Text Copy & Drag",
Packit 98cdb6
                                        GTK_WINDOW (view->window),
Packit 98cdb6
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
Packit 98cdb6
                                        GTK_STOCK_CLOSE, 0,
Packit 98cdb6
                                        NULL);
Packit 98cdb6
  g_signal_connect (dialog, "response",
Packit 98cdb6
                    G_CALLBACK (gtk_widget_destroy),
Packit 98cdb6
                    NULL);
Packit 98cdb6
Packit 98cdb6
  store = gtk_list_store_new (3,
Packit 98cdb6
                              G_TYPE_POINTER,
Packit 98cdb6
                              G_TYPE_STRING,
Packit 98cdb6
                              G_TYPE_BOOLEAN);
Packit 98cdb6
Packit 98cdb6
  g_object_set_data (G_OBJECT (store), "buffer", buffer);
Packit 98cdb6
  g_object_set_data (G_OBJECT (store), "deserialize",
Packit 98cdb6
                     GUINT_TO_POINTER (deserialize));
Packit 98cdb6
Packit 98cdb6
  tv = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
Packit 98cdb6
  g_object_unref (store);
Packit 98cdb6
Packit 98cdb6
  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv),
Packit 98cdb6
                                               0, "Rich Text Format",
Packit 98cdb6
                                               gtk_cell_renderer_text_new (),
Packit 98cdb6
                                               "text", 1,
Packit 98cdb6
                                               NULL);
Packit 98cdb6
Packit 98cdb6
  if (deserialize)
Packit 98cdb6
    {
Packit 98cdb6
      GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new ();
Packit 98cdb6
Packit 98cdb6
      gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv),
Packit 98cdb6
                                                   1, "Can Create Tags",
Packit 98cdb6
                                                   renderer,
Packit 98cdb6
                                                   "active", 2,
Packit 98cdb6
                                                   NULL);
Packit 98cdb6
Packit 98cdb6
      g_signal_connect (renderer, "toggled",
Packit 98cdb6
                        G_CALLBACK (rich_text_can_create_tags_toggled),
Packit 98cdb6
                        store);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  sw = gtk_scrolled_window_new (NULL, NULL);
Packit 98cdb6
  gtk_widget_set_size_request (sw, 300, 100);
Packit 98cdb6
  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), sw);
Packit 98cdb6
Packit 98cdb6
  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), tv);
Packit 98cdb6
Packit 98cdb6
  hbox = gtk_hbox_new (FALSE, 6);
Packit 98cdb6
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox,
Packit 98cdb6
                      FALSE, FALSE, 0);
Packit 98cdb6
Packit 98cdb6
  button = gtk_button_new_with_label ("Unregister Selected Format");
Packit 98cdb6
  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
Packit 98cdb6
Packit 98cdb6
  g_signal_connect (button, "clicked",
Packit 98cdb6
                    G_CALLBACK (rich_text_unregister_clicked),
Packit 98cdb6
                    tv);
Packit 98cdb6
Packit 98cdb6
  button = gtk_button_new_with_label ("Register New Tagset\n"
Packit 98cdb6
                                      "for the Internal Format");
Packit 98cdb6
  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
Packit 98cdb6
Packit 98cdb6
  g_signal_connect (button, "clicked",
Packit 98cdb6
                    G_CALLBACK (rich_text_register_clicked),
Packit 98cdb6
                    tv);
Packit 98cdb6
Packit 98cdb6
  if (deserialize)
Packit 98cdb6
    g_signal_connect_object (buffer, "notify::paste-target-list",
Packit 98cdb6
                             G_CALLBACK (rich_text_paste_target_list_notify),
Packit 98cdb6
                             G_OBJECT (store), 0);
Packit 98cdb6
  else
Packit 98cdb6
    g_signal_connect_object (buffer, "notify::copy-target-list",
Packit 98cdb6
                             G_CALLBACK (rich_text_copy_target_list_notify),
Packit 98cdb6
                             G_OBJECT (store), 0);
Packit 98cdb6
Packit 98cdb6
  rich_text_store_populate (store, buffer, deserialize);
Packit 98cdb6
Packit 98cdb6
  gtk_widget_show_all (dialog);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
enum
Packit 98cdb6
{
Packit 98cdb6
  RESPONSE_FORWARD,
Packit 98cdb6
  RESPONSE_BACKWARD
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
dialog_response_callback (GtkWidget *dialog, gint response_id, gpointer data)
Packit 98cdb6
{
Packit 98cdb6
  GtkTextBuffer *buffer;
Packit 98cdb6
  View *view = data;
Packit 98cdb6
  GtkTextIter start, end;
Packit 98cdb6
  gchar *search_string;
Packit 98cdb6
Packit 98cdb6
  if (response_id != RESPONSE_FORWARD &&
Packit 98cdb6
      response_id != RESPONSE_BACKWARD)
Packit 98cdb6
    {
Packit 98cdb6
      gtk_widget_destroy (dialog);
Packit 98cdb6
      return;
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  buffer = g_object_get_data (G_OBJECT (dialog), "buffer");
Packit 98cdb6
Packit 98cdb6
  gtk_text_buffer_get_bounds (buffer, &start, &end;;
Packit 98cdb6
  
Packit 98cdb6
  search_string = gtk_text_iter_get_text (&start, &end;;
Packit 98cdb6
Packit 98cdb6
  g_print ("Searching for `%s'\n", search_string);
Packit 98cdb6
Packit 98cdb6
  if (response_id == RESPONSE_FORWARD)
Packit 98cdb6
    buffer_search_forward (view->buffer, search_string, view);
Packit 98cdb6
  else if (response_id == RESPONSE_BACKWARD)
Packit 98cdb6
    buffer_search_backward (view->buffer, search_string, view);
Packit 98cdb6
    
Packit 98cdb6
  g_free (search_string);
Packit 98cdb6
  
Packit 98cdb6
  gtk_widget_destroy (dialog);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_copy  (gpointer callback_data,
Packit 98cdb6
          guint callback_action,
Packit 98cdb6
          GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  GtkTextBuffer *buffer;
Packit 98cdb6
Packit 98cdb6
  buffer = view->buffer->buffer;
Packit 98cdb6
Packit 98cdb6
  gtk_text_buffer_copy_clipboard (buffer,
Packit 98cdb6
                                  gtk_clipboard_get (GDK_NONE));
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_search (gpointer callback_data,
Packit 98cdb6
           guint callback_action,
Packit 98cdb6
           GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  GtkWidget *dialog;
Packit 98cdb6
  GtkWidget *search_text;
Packit 98cdb6
  GtkTextBuffer *buffer;
Packit 98cdb6
Packit 98cdb6
  dialog = gtk_dialog_new_with_buttons ("Search",
Packit 98cdb6
                                        GTK_WINDOW (view->window),
Packit 98cdb6
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
Packit 98cdb6
                                        "Forward", RESPONSE_FORWARD,
Packit 98cdb6
                                        "Backward", RESPONSE_BACKWARD,
Packit 98cdb6
                                        GTK_STOCK_CANCEL,
Packit 98cdb6
                                        GTK_RESPONSE_NONE, NULL);
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
  buffer = gtk_text_buffer_new (NULL);
Packit 98cdb6
Packit 98cdb6
  search_text = gtk_text_view_new_with_buffer (buffer);
Packit 98cdb6
Packit 98cdb6
  g_object_unref (buffer);
Packit 98cdb6
  
Packit 98cdb6
  gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->vbox),
Packit 98cdb6
                    search_text,
Packit 98cdb6
                    TRUE, TRUE, 0);
Packit 98cdb6
Packit 98cdb6
  g_object_set_data (G_OBJECT (dialog), "buffer", buffer);
Packit 98cdb6
  
Packit 98cdb6
  g_signal_connect (dialog,
Packit 98cdb6
                    "response",
Packit 98cdb6
                    G_CALLBACK (dialog_response_callback),
Packit 98cdb6
                    view);
Packit 98cdb6
Packit 98cdb6
  gtk_widget_show (search_text);
Packit 98cdb6
Packit 98cdb6
  gtk_widget_grab_focus (search_text);
Packit 98cdb6
  
Packit 98cdb6
  gtk_widget_show_all (dialog);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_select_all (gpointer callback_data,
Packit 98cdb6
               guint callback_action,
Packit 98cdb6
               GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  GtkTextBuffer *buffer;
Packit 98cdb6
  GtkTextIter start, end;
Packit 98cdb6
Packit 98cdb6
  buffer = view->buffer->buffer;
Packit 98cdb6
Packit 98cdb6
  gtk_text_buffer_get_bounds (buffer, &start, &end;;
Packit 98cdb6
  gtk_text_buffer_select_range (buffer, &start, &end;;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
typedef struct
Packit 98cdb6
{
Packit 98cdb6
  /* position is in coordinate system of text_view_move_child */
Packit 98cdb6
  int click_x;
Packit 98cdb6
  int click_y;
Packit 98cdb6
  int start_x;
Packit 98cdb6
  int start_y;
Packit 98cdb6
  int button;
Packit 98cdb6
} ChildMoveInfo;
Packit 98cdb6
Packit 98cdb6
static gboolean
Packit 98cdb6
movable_child_callback (GtkWidget *child,
Packit 98cdb6
                        GdkEvent  *event,
Packit 98cdb6
                        gpointer   data)
Packit 98cdb6
{
Packit 98cdb6
  ChildMoveInfo *info;
Packit 98cdb6
  GtkTextView *text_view;
Packit 98cdb6
Packit 98cdb6
  text_view = GTK_TEXT_VIEW (data);
Packit 98cdb6
  
Packit 98cdb6
  g_return_val_if_fail (GTK_IS_EVENT_BOX (child), FALSE);
Packit 98cdb6
  g_return_val_if_fail (gtk_widget_get_parent (child) == GTK_WIDGET (text_view), FALSE);  
Packit 98cdb6
  
Packit 98cdb6
  info = g_object_get_data (G_OBJECT (child),
Packit 98cdb6
                            "testtext-move-info");
Packit 98cdb6
Packit 98cdb6
  if (info == NULL)
Packit 98cdb6
    {
Packit 98cdb6
      info = g_new (ChildMoveInfo, 1);      
Packit 98cdb6
      info->start_x = -1;
Packit 98cdb6
      info->start_y = -1;
Packit 98cdb6
      info->button = -1;
Packit 98cdb6
      g_object_set_data_full (G_OBJECT (child),
Packit 98cdb6
                              "testtext-move-info",
Packit 98cdb6
                              info,
Packit 98cdb6
                              g_free);
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  switch (event->type)
Packit 98cdb6
    {
Packit 98cdb6
    case GDK_BUTTON_PRESS:
Packit 98cdb6
      if (info->button < 0)
Packit 98cdb6
        {
Packit 98cdb6
          if (gdk_pointer_grab (event->button.window,
Packit 98cdb6
                                FALSE,
Packit 98cdb6
                                GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK |
Packit 98cdb6
                                GDK_BUTTON_RELEASE_MASK,
Packit 98cdb6
                                NULL,
Packit 98cdb6
                                NULL,
Packit 98cdb6
                                event->button.time) != GDK_GRAB_SUCCESS)
Packit 98cdb6
            return FALSE;
Packit 98cdb6
          
Packit 98cdb6
          info->button = event->button.button;
Packit 98cdb6
          
Packit 98cdb6
          info->start_x = child->allocation.x;
Packit 98cdb6
          info->start_y = child->allocation.y;
Packit 98cdb6
          info->click_x = child->allocation.x + event->button.x;
Packit 98cdb6
          info->click_y = child->allocation.y + event->button.y;
Packit 98cdb6
        }
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    case GDK_BUTTON_RELEASE:
Packit 98cdb6
      if (info->button < 0)
Packit 98cdb6
        return FALSE;
Packit 98cdb6
Packit 98cdb6
      if (info->button == event->button.button)
Packit 98cdb6
        {
Packit 98cdb6
          int x, y;
Packit 98cdb6
          
Packit 98cdb6
          gdk_pointer_ungrab (event->button.time);
Packit 98cdb6
          info->button = -1;
Packit 98cdb6
Packit 98cdb6
          /* convert to window coords from event box coords */
Packit 98cdb6
          x = info->start_x + (event->button.x + child->allocation.x - info->click_x);
Packit 98cdb6
          y = info->start_y + (event->button.y + child->allocation.y - info->click_y);
Packit 98cdb6
Packit 98cdb6
          gtk_text_view_move_child (text_view,
Packit 98cdb6
                                    child,
Packit 98cdb6
                                    x, y);
Packit 98cdb6
        }
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    case GDK_MOTION_NOTIFY:
Packit 98cdb6
      {
Packit 98cdb6
        int x, y;
Packit 98cdb6
        
Packit 98cdb6
        if (info->button < 0)
Packit 98cdb6
          return FALSE;
Packit 98cdb6
        
Packit 98cdb6
        gdk_window_get_pointer (child->window, &x, &y, NULL); /* ensure more events */
Packit 98cdb6
Packit 98cdb6
        /* to window coords from event box coords */
Packit 98cdb6
        x += child->allocation.x;
Packit 98cdb6
        y += child->allocation.y;
Packit 98cdb6
        
Packit 98cdb6
        x = info->start_x + (x - info->click_x);
Packit 98cdb6
        y = info->start_y + (y - info->click_y);
Packit 98cdb6
        
Packit 98cdb6
        gtk_text_view_move_child (text_view,
Packit 98cdb6
                                  child,
Packit 98cdb6
                                  x, y);
Packit 98cdb6
      }
Packit 98cdb6
      break;
Packit 98cdb6
Packit 98cdb6
    default:
Packit 98cdb6
      break;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return FALSE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
add_movable_child (GtkTextView      *text_view,
Packit 98cdb6
                   GtkTextWindowType window)
Packit 98cdb6
{
Packit 98cdb6
  GtkWidget *event_box;
Packit 98cdb6
  GtkWidget *label;
Packit 98cdb6
  GdkColor color;
Packit 98cdb6
  
Packit 98cdb6
  label = gtk_label_new ("Drag me around");  
Packit 98cdb6
  
Packit 98cdb6
  event_box = gtk_event_box_new ();
Packit 98cdb6
  gtk_widget_add_events (event_box,
Packit 98cdb6
                         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
Packit 98cdb6
                         GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
Packit 98cdb6
Packit 98cdb6
  color.red = 0xffff;
Packit 98cdb6
  color.green = color.blue = 0;
Packit 98cdb6
  gtk_widget_modify_bg (event_box, GTK_STATE_NORMAL, &color;;
Packit 98cdb6
  
Packit 98cdb6
  gtk_container_add (GTK_CONTAINER (event_box), label);
Packit 98cdb6
Packit 98cdb6
  gtk_widget_show_all (event_box);
Packit 98cdb6
Packit 98cdb6
  g_signal_connect (event_box, "event",
Packit 98cdb6
                    G_CALLBACK (movable_child_callback),
Packit 98cdb6
                    text_view);
Packit 98cdb6
Packit 98cdb6
  gtk_text_view_add_child_in_window (text_view,
Packit 98cdb6
                                     event_box,
Packit 98cdb6
                                     window,
Packit 98cdb6
                                     0, 0);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_add_children (gpointer callback_data,
Packit 98cdb6
                 guint callback_action,
Packit 98cdb6
                 GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
Packit 98cdb6
  add_movable_child (GTK_TEXT_VIEW (view->text_view),
Packit 98cdb6
                     GTK_TEXT_WINDOW_WIDGET);
Packit 98cdb6
  add_movable_child (GTK_TEXT_VIEW (view->text_view),
Packit 98cdb6
                     GTK_TEXT_WINDOW_LEFT);
Packit 98cdb6
  add_movable_child (GTK_TEXT_VIEW (view->text_view),
Packit 98cdb6
                     GTK_TEXT_WINDOW_RIGHT);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
do_add_focus_children (gpointer callback_data,
Packit 98cdb6
                       guint callback_action,
Packit 98cdb6
                       GtkWidget *widget)
Packit 98cdb6
{
Packit 98cdb6
  View *view = view_from_widget (widget);
Packit 98cdb6
  GtkWidget *child;
Packit 98cdb6
  GtkTextChildAnchor *anchor;
Packit 98cdb6
  GtkTextIter iter;
Packit 98cdb6
  GtkTextView *text_view;
Packit 98cdb6
Packit 98cdb6
  text_view = GTK_TEXT_VIEW (view->text_view);
Packit 98cdb6
  
Packit 98cdb6
  child = gtk_button_new_with_mnemonic ("Button _A in widget->window");
Packit 98cdb6
Packit 98cdb6
  gtk_text_view_add_child_in_window (text_view,
Packit 98cdb6
                                     child,
Packit 98cdb6
                                     GTK_TEXT_WINDOW_WIDGET,
Packit 98cdb6
                                     200, 200);
Packit 98cdb6
Packit 98cdb6
  child = gtk_button_new_with_mnemonic ("Button _B in widget->window");
Packit 98cdb6
Packit 98cdb6
  gtk_text_view_add_child_in_window (text_view,
Packit 98cdb6
                                     child,
Packit 98cdb6
                                     GTK_TEXT_WINDOW_WIDGET,
Packit 98cdb6
                                     350, 300);
Packit 98cdb6
Packit 98cdb6
  child = gtk_button_new_with_mnemonic ("Button _C in left window");
Packit 98cdb6
Packit 98cdb6
  gtk_text_view_add_child_in_window (text_view,
Packit 98cdb6
                                     child,
Packit 98cdb6
                                     GTK_TEXT_WINDOW_LEFT,
Packit 98cdb6
                                     0, 0);
Packit 98cdb6
Packit 98cdb6
  child = gtk_button_new_with_mnemonic ("Button _D in right window");
Packit 98cdb6
  
Packit 98cdb6
  gtk_text_view_add_child_in_window (text_view,
Packit 98cdb6
                                     child,
Packit 98cdb6
                                     GTK_TEXT_WINDOW_RIGHT,
Packit 98cdb6
                                     0, 0);
Packit 98cdb6
Packit 98cdb6
  gtk_text_buffer_get_start_iter (view->buffer->buffer, &iter);
Packit 98cdb6
  
Packit 98cdb6
  anchor = gtk_text_buffer_create_child_anchor (view->buffer->buffer, &iter);
Packit 98cdb6
Packit 98cdb6
  child = gtk_button_new_with_mnemonic ("Button _E in buffer");
Packit 98cdb6
  
Packit 98cdb6
  gtk_text_view_add_child_at_anchor (text_view, child, anchor);
Packit 98cdb6
Packit 98cdb6
  anchor = gtk_text_buffer_create_child_anchor (view->buffer->buffer, &iter);
Packit 98cdb6
Packit 98cdb6
  child = gtk_button_new_with_mnemonic ("Button _F in buffer");
Packit 98cdb6
  
Packit 98cdb6
  gtk_text_view_add_child_at_anchor (text_view, child, anchor);
Packit 98cdb6
Packit 98cdb6
  anchor = gtk_text_buffer_create_child_anchor (view->buffer->buffer, &iter);
Packit 98cdb6
Packit 98cdb6
  child = gtk_button_new_with_mnemonic ("Button _G in buffer");
Packit 98cdb6
  
Packit 98cdb6
  gtk_text_view_add_child_at_anchor (text_view, child, anchor);
Packit 98cdb6
Packit 98cdb6
  /* show all the buttons */
Packit 98cdb6
  gtk_widget_show_all (view->text_view);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
view_init_menus (View *view)
Packit 98cdb6
{
Packit 98cdb6
  GtkTextDirection direction = gtk_widget_get_direction (view->text_view);
Packit 98cdb6
  GtkWrapMode wrap_mode = gtk_text_view_get_wrap_mode (GTK_TEXT_VIEW (view->text_view));
Packit 98cdb6
  GtkWidget *menu_item = NULL;
Packit 98cdb6
Packit 98cdb6
  switch (direction)
Packit 98cdb6
    {
Packit 98cdb6
    case GTK_TEXT_DIR_LTR:
Packit 98cdb6
      menu_item = gtk_item_factory_get_widget (view->item_factory, "/Settings/Left-to-Right");
Packit 98cdb6
      break;
Packit 98cdb6
    case GTK_TEXT_DIR_RTL:
Packit 98cdb6
      menu_item = gtk_item_factory_get_widget (view->item_factory, "/Settings/Right-to-Left");
Packit 98cdb6
      break;
Packit 98cdb6
    default:
Packit 98cdb6
      break;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  if (menu_item)
Packit 98cdb6
    gtk_menu_item_activate (GTK_MENU_ITEM (menu_item));
Packit 98cdb6
Packit 98cdb6
  switch (wrap_mode)
Packit 98cdb6
    {
Packit 98cdb6
    case GTK_WRAP_NONE:
Packit 98cdb6
      menu_item = gtk_item_factory_get_widget (view->item_factory, "/Settings/Wrap Off");
Packit 98cdb6
      break;
Packit 98cdb6
    case GTK_WRAP_WORD:
Packit 98cdb6
      menu_item = gtk_item_factory_get_widget (view->item_factory, "/Settings/Wrap Words");
Packit 98cdb6
      break;
Packit 98cdb6
    case GTK_WRAP_CHAR:
Packit 98cdb6
      menu_item = gtk_item_factory_get_widget (view->item_factory, "/Settings/Wrap Chars");
Packit 98cdb6
      break;
Packit 98cdb6
    default:
Packit 98cdb6
      break;
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  if (menu_item)
Packit 98cdb6
    gtk_menu_item_activate (GTK_MENU_ITEM (menu_item));
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static GtkItemFactoryEntry menu_items[] =
Packit 98cdb6
{
Packit 98cdb6
  { "/_File",            NULL,         NULL,        0, "<Branch>" },
Packit 98cdb6
  { "/File/_New",        "<control>N", do_new,      0, NULL },
Packit 98cdb6
  { "/File/New _View",   NULL,         do_new_view, 0, NULL },
Packit 98cdb6
  { "/File/_Open",       "<control>O", do_open,     0, NULL },
Packit 98cdb6
  { "/File/_Save",       "<control>S", do_save,     0, NULL },
Packit 98cdb6
  { "/File/Save _As...", NULL,         do_save_as,  0, NULL },
Packit 98cdb6
  { "/File/sep1",        NULL,         NULL,        0, "<Separator>" },
Packit 98cdb6
  { "/File/_Close",     "<control>W" , do_close,    0, NULL },
Packit 98cdb6
  { "/File/E_xit",      "<control>Q" , do_exit,     0, NULL },
Packit 98cdb6
Packit 98cdb6
  { "/_Edit", NULL, 0, 0, "<Branch>" },
Packit 98cdb6
  { "/Edit/Copy", NULL, do_copy, 0, NULL },
Packit 98cdb6
  { "/Edit/sep1", NULL, NULL, 0, "<Separator>" },
Packit 98cdb6
  { "/Edit/Find...", NULL, do_search, 0, NULL },
Packit 98cdb6
  { "/Edit/Select All", "<control>A", do_select_all, 0, NULL }, 
Packit 98cdb6
Packit 98cdb6
  { "/_Settings",   	  NULL,         NULL,             0, "<Branch>" },
Packit 98cdb6
  { "/Settings/Wrap _Off",   NULL,      do_wrap_changed,  GTK_WRAP_NONE, "<RadioItem>" },
Packit 98cdb6
  { "/Settings/Wrap _Words", NULL,      do_wrap_changed,  GTK_WRAP_WORD, "/Settings/Wrap Off" },
Packit 98cdb6
  { "/Settings/Wrap _Chars", NULL,      do_wrap_changed,  GTK_WRAP_CHAR, "/Settings/Wrap Off" },
Packit 98cdb6
  { "/Settings/sep1",        NULL,      NULL,             0, "<Separator>" },
Packit 98cdb6
  { "/Settings/Editable", NULL,      do_editable_changed,  TRUE, "<RadioItem>" },
Packit 98cdb6
  { "/Settings/Not editable",    NULL,      do_editable_changed,  FALSE, "/Settings/Editable" },
Packit 98cdb6
  { "/Settings/sep1",        NULL,      NULL,             0, "<Separator>" },
Packit 98cdb6
Packit 98cdb6
  { "/Settings/Cursor normal",    NULL,      do_cursor_visible_changed,  1, "<RadioItem>" },
Packit 98cdb6
  { "/Settings/Cursor not visible", NULL,      do_cursor_visible_changed,  0, "/Settings/Cursor normal" },
Packit 98cdb6
  { "/Settings/Cursor colored", NULL,      do_cursor_visible_changed,  2, "/Settings/Cursor normal" },
Packit 98cdb6
  { "/Settings/sep1",        NULL,      NULL,          0, "<Separator>" },
Packit 98cdb6
  
Packit 98cdb6
  { "/Settings/Left-to-Right", NULL,    do_direction_changed,  GTK_TEXT_DIR_LTR, "<RadioItem>" },
Packit 98cdb6
  { "/Settings/Right-to-Left", NULL,    do_direction_changed,  GTK_TEXT_DIR_RTL, "/Settings/Left-to-Right" },
Packit 98cdb6
Packit 98cdb6
  { "/Settings/sep1",        NULL,      NULL,                0, "<Separator>" },
Packit 98cdb6
  { "/Settings/Sane spacing", NULL,    do_spacing_changed,  FALSE, "<RadioItem>" },
Packit 98cdb6
  { "/Settings/Funky spacing", NULL,    do_spacing_changed,  TRUE, "/Settings/Sane spacing" },
Packit 98cdb6
  { "/Settings/sep1",        NULL,      NULL,                0, "<Separator>" },
Packit 98cdb6
  { "/Settings/Don't cycle color tags", NULL,    do_color_cycle_changed,  FALSE, "<RadioItem>" },
Packit 98cdb6
  { "/Settings/Cycle colors", NULL,    do_color_cycle_changed,  TRUE, "/Settings/Don't cycle color tags" },
Packit 98cdb6
  { "/_Attributes",   	  NULL,         NULL,                0, "<Branch>" },
Packit 98cdb6
  { "/Attributes/Editable",   	  NULL,         do_apply_editable, TRUE, NULL },
Packit 98cdb6
  { "/Attributes/Not editable",   	  NULL,         do_apply_editable, FALSE, NULL },
Packit 98cdb6
  { "/Attributes/Invisible",   	  NULL,         do_apply_invisible, FALSE, NULL },
Packit 98cdb6
  { "/Attributes/Visible",   	  NULL,         do_apply_invisible, TRUE, NULL },
Packit 98cdb6
  { "/Attributes/Rise",   	  NULL,         do_apply_rise, FALSE, NULL },
Packit 98cdb6
  { "/Attributes/Large",   	  NULL,         do_apply_large, FALSE, NULL },
Packit 98cdb6
  { "/Attributes/Indent",   	  NULL,         do_apply_indent, FALSE, NULL },
Packit 98cdb6
  { "/Attributes/Margins",   	  NULL,         do_apply_margin, FALSE, NULL },
Packit 98cdb6
  { "/Attributes/Custom tabs",   	  NULL,         do_apply_tabs, FALSE, NULL },
Packit 98cdb6
  { "/Attributes/Default tabs",   	  NULL,         do_apply_tabs, TRUE, NULL },
Packit 98cdb6
  { "/Attributes/Color cycles",   	  NULL,         do_apply_colors, TRUE, NULL },
Packit 98cdb6
  { "/Attributes/No colors",   	          NULL,         do_apply_colors, FALSE, NULL },
Packit 98cdb6
  { "/Attributes/Remove all tags",        NULL, do_remove_tags, 0, NULL },
Packit 98cdb6
  { "/Attributes/Properties",             NULL, do_properties, 0, NULL },
Packit 98cdb6
  { "/Attributes/Rich Text copy & drag",  NULL, do_rich_text, 0, NULL },
Packit 98cdb6
  { "/Attributes/Rich Text paste & drop", NULL, do_rich_text, 1, NULL },
Packit 98cdb6
  { "/_Test",   	 NULL,         NULL,           0, "<Branch>" },
Packit 98cdb6
  { "/Test/_Example",  	 NULL,         do_example,  0, NULL },
Packit 98cdb6
  { "/Test/_Insert and scroll", NULL,         do_insert_and_scroll,  0, NULL },
Packit 98cdb6
  { "/Test/_Add fixed children", NULL,         do_add_children,  0, NULL },
Packit 98cdb6
  { "/Test/A_dd focusable children", NULL,    do_add_focus_children,  0, NULL },
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
static gboolean
Packit 98cdb6
save_buffer (Buffer *buffer)
Packit 98cdb6
{
Packit 98cdb6
  GtkTextIter start, end;
Packit 98cdb6
  gchar *chars;
Packit 98cdb6
  gboolean result = FALSE;
Packit 98cdb6
  gboolean have_backup = FALSE;
Packit 98cdb6
  gchar *bak_filename;
Packit 98cdb6
  FILE *file;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (buffer->filename != NULL, FALSE);
Packit 98cdb6
Packit 98cdb6
  bak_filename = g_strconcat (buffer->filename, "~", NULL);
Packit 98cdb6
  
Packit 98cdb6
  if (rename (buffer->filename, bak_filename) != 0)
Packit 98cdb6
    {
Packit 98cdb6
      if (errno != ENOENT)
Packit 98cdb6
	{
Packit 98cdb6
	  gchar *err = g_strdup_printf ("Cannot back up '%s' to '%s': %s",
Packit 98cdb6
					buffer->filename, bak_filename, g_strerror (errno));
Packit 98cdb6
	  msgbox_run (NULL, err, "OK", NULL, NULL, 0);
Packit 98cdb6
	  g_free (err);
Packit 98cdb6
          return FALSE;
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    have_backup = TRUE;
Packit 98cdb6
  
Packit 98cdb6
  file = fopen (buffer->filename, "w");
Packit 98cdb6
  if (!file)
Packit 98cdb6
    {
Packit 98cdb6
      gchar *err = g_strdup_printf ("Cannot back up '%s' to '%s': %s",
Packit 98cdb6
				    buffer->filename, bak_filename, g_strerror (errno));
Packit 98cdb6
      msgbox_run (NULL, err, "OK", NULL, NULL, 0);
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    {
Packit 98cdb6
      gtk_text_buffer_get_iter_at_offset (buffer->buffer, &start, 0);
Packit 98cdb6
      gtk_text_buffer_get_end_iter (buffer->buffer, &end;;
Packit 98cdb6
  
Packit 98cdb6
      chars = gtk_text_buffer_get_slice (buffer->buffer, &start, &end, FALSE);
Packit 98cdb6
Packit 98cdb6
      if (fputs (chars, file) == EOF ||
Packit 98cdb6
	  fclose (file) == EOF)
Packit 98cdb6
	{
Packit 98cdb6
	  gchar *err = g_strdup_printf ("Error writing to '%s': %s",
Packit 98cdb6
					buffer->filename, g_strerror (errno));
Packit 98cdb6
	  msgbox_run (NULL, err, "OK", NULL, NULL, 0);
Packit 98cdb6
	  g_free (err);
Packit 98cdb6
	}
Packit 98cdb6
      else
Packit 98cdb6
	{
Packit 98cdb6
	  /* Success
Packit 98cdb6
	   */
Packit 98cdb6
	  result = TRUE;
Packit 98cdb6
	  gtk_text_buffer_set_modified (buffer->buffer, FALSE);	  
Packit 98cdb6
	}
Packit 98cdb6
	
Packit 98cdb6
      g_free (chars);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  if (!result && have_backup)
Packit 98cdb6
    {
Packit 98cdb6
      if (rename (bak_filename, buffer->filename) != 0)
Packit 98cdb6
	{
Packit 98cdb6
	  gchar *err = g_strdup_printf ("Error restoring backup file '%s' to '%s': %s\nBackup left as '%s'",
Packit 98cdb6
					buffer->filename, bak_filename, g_strerror (errno), bak_filename);
Packit 98cdb6
	  msgbox_run (NULL, err, "OK", NULL, NULL, 0);
Packit 98cdb6
	  g_free (err);
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  g_free (bak_filename);
Packit 98cdb6
  
Packit 98cdb6
  return result;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gboolean
Packit 98cdb6
save_as_ok_func (const char *filename, gpointer data)
Packit 98cdb6
{
Packit 98cdb6
  Buffer *buffer = data;
Packit 98cdb6
  char *old_filename = buffer->filename;
Packit 98cdb6
Packit 98cdb6
  if (!buffer->filename || strcmp (filename, buffer->filename) != 0)
Packit 98cdb6
    {
Packit 98cdb6
      struct stat statbuf;
Packit 98cdb6
Packit 98cdb6
      if (stat (filename, &statbuf) == 0)
Packit 98cdb6
	{
Packit 98cdb6
	  gchar *err = g_strdup_printf ("Ovewrite existing file '%s'?", filename);
Packit 98cdb6
	  gint result = msgbox_run (NULL, err, "Yes", "No", NULL, 1);
Packit 98cdb6
	  g_free (err);
Packit 98cdb6
Packit 98cdb6
	  if (result != 0)
Packit 98cdb6
	    return FALSE;
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
  
Packit 98cdb6
  buffer->filename = g_strdup (filename);
Packit 98cdb6
Packit 98cdb6
  if (save_buffer (buffer))
Packit 98cdb6
    {
Packit 98cdb6
      g_free (old_filename);
Packit 98cdb6
      buffer_filename_set (buffer);
Packit 98cdb6
      return TRUE;
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    {
Packit 98cdb6
      g_free (buffer->filename);
Packit 98cdb6
      buffer->filename = old_filename;
Packit 98cdb6
      return FALSE;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gboolean
Packit 98cdb6
save_as_buffer (Buffer *buffer)
Packit 98cdb6
{
Packit 98cdb6
  return filesel_run (NULL, "Save File", NULL, save_as_ok_func, buffer);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gboolean
Packit 98cdb6
check_buffer_saved (Buffer *buffer)
Packit 98cdb6
{
Packit 98cdb6
  if (gtk_text_buffer_get_modified (buffer->buffer))
Packit 98cdb6
    {
Packit 98cdb6
      char *pretty_name = buffer_pretty_name (buffer);
Packit 98cdb6
      char *msg = g_strdup_printf ("Save changes to '%s'?", pretty_name);
Packit 98cdb6
      gint result;
Packit 98cdb6
      
Packit 98cdb6
      g_free (pretty_name);
Packit 98cdb6
      
Packit 98cdb6
      result = msgbox_run (NULL, msg, "Yes", "No", "Cancel", 0);
Packit 98cdb6
      g_free (msg);
Packit 98cdb6
  
Packit 98cdb6
      if (result == 0)
Packit 98cdb6
	return save_as_buffer (buffer);
Packit 98cdb6
      else if (result == 1)
Packit 98cdb6
	return TRUE;
Packit 98cdb6
      else
Packit 98cdb6
	return FALSE;
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
#define N_COLORS 16
Packit 98cdb6
Packit 98cdb6
static Buffer *
Packit 98cdb6
create_buffer (void)
Packit 98cdb6
{
Packit 98cdb6
  Buffer *buffer;
Packit 98cdb6
  PangoTabArray *tabs;
Packit 98cdb6
  gint i;
Packit 98cdb6
  
Packit 98cdb6
  buffer = g_new (Buffer, 1);
Packit 98cdb6
Packit 98cdb6
  buffer->buffer = gtk_text_buffer_new (NULL);
Packit 98cdb6
  
Packit 98cdb6
  buffer->refcount = 1;
Packit 98cdb6
  buffer->filename = NULL;
Packit 98cdb6
  buffer->untitled_serial = -1;
Packit 98cdb6
Packit 98cdb6
  buffer->color_tags = NULL;
Packit 98cdb6
  buffer->color_cycle_timeout = 0;
Packit 98cdb6
  buffer->start_hue = 0.0;
Packit 98cdb6
  
Packit 98cdb6
  i = 0;
Packit 98cdb6
  while (i < N_COLORS)
Packit 98cdb6
    {
Packit 98cdb6
      GtkTextTag *tag;
Packit 98cdb6
Packit 98cdb6
      tag = gtk_text_buffer_create_tag (buffer->buffer, NULL, NULL);
Packit 98cdb6
      
Packit 98cdb6
      buffer->color_tags = g_slist_prepend (buffer->color_tags, tag);
Packit 98cdb6
      
Packit 98cdb6
      ++i;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
#if 1  
Packit 98cdb6
  buffer->invisible_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
Packit 98cdb6
                                                      "invisible", TRUE, NULL);
Packit 98cdb6
#endif  
Packit 98cdb6
  
Packit 98cdb6
  buffer->not_editable_tag =
Packit 98cdb6
    gtk_text_buffer_create_tag (buffer->buffer, NULL,
Packit 98cdb6
                                "editable", FALSE,
Packit 98cdb6
                                "foreground", "purple", NULL);
Packit 98cdb6
Packit 98cdb6
  buffer->found_text_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
Packit 98cdb6
                                                       "foreground", "red", NULL);
Packit 98cdb6
Packit 98cdb6
  buffer->rise_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
Packit 98cdb6
						 "rise", 10 * PANGO_SCALE, NULL);
Packit 98cdb6
Packit 98cdb6
  buffer->large_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
Packit 98cdb6
						 "scale", PANGO_SCALE_X_LARGE, NULL);
Packit 98cdb6
Packit 98cdb6
  buffer->indent_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
Packit 98cdb6
						   "indent", 20, NULL);
Packit 98cdb6
Packit 98cdb6
  buffer->margin_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
Packit 98cdb6
						   "left_margin", 20, "right_margin", 20, NULL);
Packit 98cdb6
Packit 98cdb6
  tabs = pango_tab_array_new_with_positions (4,
Packit 98cdb6
                                             TRUE,
Packit 98cdb6
                                             PANGO_TAB_LEFT, 10,
Packit 98cdb6
                                             PANGO_TAB_LEFT, 30,
Packit 98cdb6
                                             PANGO_TAB_LEFT, 60,
Packit 98cdb6
                                             PANGO_TAB_LEFT, 120);
Packit 98cdb6
  
Packit 98cdb6
  buffer->custom_tabs_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
Packit 98cdb6
                                                        "tabs", tabs,
Packit 98cdb6
                                                        "foreground", "green", NULL);
Packit 98cdb6
Packit 98cdb6
  pango_tab_array_free (tabs);
Packit 98cdb6
  
Packit 98cdb6
  buffers = g_slist_prepend (buffers, buffer);
Packit 98cdb6
  
Packit 98cdb6
  return buffer;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static char *
Packit 98cdb6
buffer_pretty_name (Buffer *buffer)
Packit 98cdb6
{
Packit 98cdb6
  if (buffer->filename)
Packit 98cdb6
    {
Packit 98cdb6
      char *p;
Packit 98cdb6
      char *result = g_path_get_basename (buffer->filename);
Packit 98cdb6
      p = strchr (result, '/');
Packit 98cdb6
      if (p)
Packit 98cdb6
	*p = '\0';
Packit 98cdb6
Packit 98cdb6
      return result;
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    {
Packit 98cdb6
      if (buffer->untitled_serial == -1)
Packit 98cdb6
	buffer->untitled_serial = untitled_serial++;
Packit 98cdb6
Packit 98cdb6
      if (buffer->untitled_serial == 1)
Packit 98cdb6
	return g_strdup ("Untitled");
Packit 98cdb6
      else
Packit 98cdb6
	return g_strdup_printf ("Untitled #%d", buffer->untitled_serial);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
buffer_filename_set (Buffer *buffer)
Packit 98cdb6
{
Packit 98cdb6
  GSList *tmp_list = views;
Packit 98cdb6
Packit 98cdb6
  while (tmp_list)
Packit 98cdb6
    {
Packit 98cdb6
      View *view = tmp_list->data;
Packit 98cdb6
Packit 98cdb6
      if (view->buffer == buffer)
Packit 98cdb6
	view_set_title (view);
Packit 98cdb6
Packit 98cdb6
      tmp_list = tmp_list->next;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
buffer_search (Buffer     *buffer,
Packit 98cdb6
               const char *str,
Packit 98cdb6
               View       *view,
Packit 98cdb6
               gboolean forward)
Packit 98cdb6
{
Packit 98cdb6
  GtkTextIter iter;
Packit 98cdb6
  GtkTextIter start, end;
Packit 98cdb6
  GtkWidget *dialog;
Packit 98cdb6
  int i;
Packit 98cdb6
  
Packit 98cdb6
  /* remove tag from whole buffer */
Packit 98cdb6
  gtk_text_buffer_get_bounds (buffer->buffer, &start, &end;;
Packit 98cdb6
  gtk_text_buffer_remove_tag (buffer->buffer,  buffer->found_text_tag,
Packit 98cdb6
                              &start, &end );
Packit 98cdb6
  
Packit 98cdb6
  gtk_text_buffer_get_iter_at_mark (buffer->buffer, &iter,
Packit 98cdb6
                                    gtk_text_buffer_get_mark (buffer->buffer,
Packit 98cdb6
                                                              "insert"));
Packit 98cdb6
Packit 98cdb6
  i = 0;
Packit 98cdb6
  if (*str != '\0')
Packit 98cdb6
    {
Packit 98cdb6
      GtkTextIter match_start, match_end;
Packit 98cdb6
Packit 98cdb6
      if (forward)
Packit 98cdb6
        {
Packit 98cdb6
          while (gtk_text_iter_forward_search (&iter, str,
Packit 98cdb6
                                               GTK_TEXT_SEARCH_VISIBLE_ONLY |
Packit 98cdb6
                                               GTK_TEXT_SEARCH_TEXT_ONLY,
Packit 98cdb6
                                               &match_start, &match_end,
Packit 98cdb6
                                               NULL))
Packit 98cdb6
            {
Packit 98cdb6
              ++i;
Packit 98cdb6
              gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag,
Packit 98cdb6
                                         &match_start, &match_end);
Packit 98cdb6
              
Packit 98cdb6
              iter = match_end;
Packit 98cdb6
            }
Packit 98cdb6
        }
Packit 98cdb6
      else
Packit 98cdb6
        {
Packit 98cdb6
          while (gtk_text_iter_backward_search (&iter, str,
Packit 98cdb6
                                                GTK_TEXT_SEARCH_VISIBLE_ONLY |
Packit 98cdb6
                                                GTK_TEXT_SEARCH_TEXT_ONLY,
Packit 98cdb6
                                                &match_start, &match_end,
Packit 98cdb6
                                                NULL))
Packit 98cdb6
            {
Packit 98cdb6
              ++i;
Packit 98cdb6
              gtk_text_buffer_apply_tag (buffer->buffer, buffer->found_text_tag,
Packit 98cdb6
                                         &match_start, &match_end);
Packit 98cdb6
              
Packit 98cdb6
              iter = match_start;
Packit 98cdb6
            }
Packit 98cdb6
        }
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  dialog = gtk_message_dialog_new (GTK_WINDOW (view->window),
Packit 98cdb6
				   GTK_DIALOG_DESTROY_WITH_PARENT,
Packit 98cdb6
                                   GTK_MESSAGE_INFO,
Packit 98cdb6
                                   GTK_BUTTONS_OK,
Packit 98cdb6
                                   "%d strings found and marked in red",
Packit 98cdb6
                                   i);
Packit 98cdb6
Packit 98cdb6
  g_signal_connect_swapped (dialog,
Packit 98cdb6
                            "response",
Packit 98cdb6
                            G_CALLBACK (gtk_widget_destroy), dialog);
Packit 98cdb6
  
Packit 98cdb6
  gtk_widget_show (dialog);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
buffer_search_forward (Buffer *buffer, const char *str,
Packit 98cdb6
                       View *view)
Packit 98cdb6
{
Packit 98cdb6
  buffer_search (buffer, str, view, TRUE);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
buffer_search_backward (Buffer *buffer, const char *str,
Packit 98cdb6
                        View *view)
Packit 98cdb6
{
Packit 98cdb6
  buffer_search (buffer, str, view, FALSE);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
buffer_ref (Buffer *buffer)
Packit 98cdb6
{
Packit 98cdb6
  buffer->refcount++;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
buffer_unref (Buffer *buffer)
Packit 98cdb6
{
Packit 98cdb6
  buffer->refcount--;
Packit 98cdb6
  if (buffer->refcount == 0)
Packit 98cdb6
    {
Packit 98cdb6
      buffer_set_colors (buffer, FALSE);
Packit 98cdb6
      buffers = g_slist_remove (buffers, buffer);
Packit 98cdb6
      g_object_unref (buffer->buffer);
Packit 98cdb6
      g_free (buffer->filename);
Packit 98cdb6
      g_free (buffer);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
hsv_to_rgb (gdouble *h,
Packit 98cdb6
	    gdouble *s,
Packit 98cdb6
	    gdouble *v)
Packit 98cdb6
{
Packit 98cdb6
  gdouble hue, saturation, value;
Packit 98cdb6
  gdouble f, p, q, t;
Packit 98cdb6
Packit 98cdb6
  if (*s == 0.0)
Packit 98cdb6
    {
Packit 98cdb6
      *h = *v;
Packit 98cdb6
      *s = *v;
Packit 98cdb6
      *v = *v; /* heh */
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    {
Packit 98cdb6
      hue = *h * 6.0;
Packit 98cdb6
      saturation = *s;
Packit 98cdb6
      value = *v;
Packit 98cdb6
      
Packit 98cdb6
      if (hue >= 6.0)
Packit 98cdb6
	hue = 0.0;
Packit 98cdb6
      
Packit 98cdb6
      f = hue - (int) hue;
Packit 98cdb6
      p = value * (1.0 - saturation);
Packit 98cdb6
      q = value * (1.0 - saturation * f);
Packit 98cdb6
      t = value * (1.0 - saturation * (1.0 - f));
Packit 98cdb6
      
Packit 98cdb6
      switch ((int) hue)
Packit 98cdb6
	{
Packit 98cdb6
	case 0:
Packit 98cdb6
	  *h = value;
Packit 98cdb6
	  *s = t;
Packit 98cdb6
	  *v = p;
Packit 98cdb6
	  break;
Packit 98cdb6
	  
Packit 98cdb6
	case 1:
Packit 98cdb6
	  *h = q;
Packit 98cdb6
	  *s = value;
Packit 98cdb6
	  *v = p;
Packit 98cdb6
	  break;
Packit 98cdb6
	  
Packit 98cdb6
	case 2:
Packit 98cdb6
	  *h = p;
Packit 98cdb6
	  *s = value;
Packit 98cdb6
	  *v = t;
Packit 98cdb6
	  break;
Packit 98cdb6
	  
Packit 98cdb6
	case 3:
Packit 98cdb6
	  *h = p;
Packit 98cdb6
	  *s = q;
Packit 98cdb6
	  *v = value;
Packit 98cdb6
	  break;
Packit 98cdb6
	  
Packit 98cdb6
	case 4:
Packit 98cdb6
	  *h = t;
Packit 98cdb6
	  *s = p;
Packit 98cdb6
	  *v = value;
Packit 98cdb6
	  break;
Packit 98cdb6
	  
Packit 98cdb6
	case 5:
Packit 98cdb6
	  *h = value;
Packit 98cdb6
	  *s = p;
Packit 98cdb6
	  *v = q;
Packit 98cdb6
	  break;
Packit 98cdb6
	  
Packit 98cdb6
	default:
Packit 98cdb6
	  g_assert_not_reached ();
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
hue_to_color (gdouble   hue,
Packit 98cdb6
              GdkColor *color)
Packit 98cdb6
{
Packit 98cdb6
  gdouble h, s, v;
Packit 98cdb6
Packit 98cdb6
  h = hue;
Packit 98cdb6
  s = 1.0;
Packit 98cdb6
  v = 1.0;
Packit 98cdb6
Packit 98cdb6
  g_return_if_fail (hue <= 1.0);
Packit 98cdb6
  
Packit 98cdb6
  hsv_to_rgb (&h, &s, &v);
Packit 98cdb6
Packit 98cdb6
  color->red = h * 65535;
Packit 98cdb6
  color->green = s * 65535;
Packit 98cdb6
  color->blue = v * 65535;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
static gint
Packit 98cdb6
color_cycle_timeout (gpointer data)
Packit 98cdb6
{
Packit 98cdb6
  Buffer *buffer = data;
Packit 98cdb6
Packit 98cdb6
  buffer_cycle_colors (buffer);
Packit 98cdb6
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
buffer_set_colors (Buffer  *buffer,
Packit 98cdb6
                   gboolean enabled)
Packit 98cdb6
{
Packit 98cdb6
  GSList *tmp;
Packit 98cdb6
  gdouble hue = 0.0;
Packit 98cdb6
Packit 98cdb6
  if (enabled && buffer->color_cycle_timeout == 0)
Packit 98cdb6
    buffer->color_cycle_timeout = gdk_threads_add_timeout (200, color_cycle_timeout, buffer);
Packit 98cdb6
  else if (!enabled && buffer->color_cycle_timeout != 0)
Packit 98cdb6
    {
Packit 98cdb6
      g_source_remove (buffer->color_cycle_timeout);
Packit 98cdb6
      buffer->color_cycle_timeout = 0;
Packit 98cdb6
    }
Packit 98cdb6
    
Packit 98cdb6
  tmp = buffer->color_tags;
Packit 98cdb6
  while (tmp != NULL)
Packit 98cdb6
    {
Packit 98cdb6
      if (enabled)
Packit 98cdb6
        {
Packit 98cdb6
          GdkColor color;
Packit 98cdb6
          
Packit 98cdb6
          hue_to_color (hue, &color;;
Packit 98cdb6
Packit 98cdb6
          g_object_set (tmp->data,
Packit 98cdb6
                        "foreground_gdk", &color,
Packit 98cdb6
                        NULL);
Packit 98cdb6
        }
Packit 98cdb6
      else
Packit 98cdb6
        g_object_set (tmp->data,
Packit 98cdb6
                      "foreground_set", FALSE,
Packit 98cdb6
                      NULL);
Packit 98cdb6
Packit 98cdb6
      hue += 1.0 / N_COLORS;
Packit 98cdb6
      
Packit 98cdb6
      tmp = g_slist_next (tmp);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
buffer_cycle_colors (Buffer *buffer)
Packit 98cdb6
{
Packit 98cdb6
  GSList *tmp;
Packit 98cdb6
  gdouble hue = buffer->start_hue;
Packit 98cdb6
  
Packit 98cdb6
  tmp = buffer->color_tags;
Packit 98cdb6
  while (tmp != NULL)
Packit 98cdb6
    {
Packit 98cdb6
      GdkColor color;
Packit 98cdb6
      
Packit 98cdb6
      hue_to_color (hue, &color;;
Packit 98cdb6
      
Packit 98cdb6
      g_object_set (tmp->data,
Packit 98cdb6
                    "foreground_gdk", &color,
Packit 98cdb6
                    NULL);
Packit 98cdb6
Packit 98cdb6
      hue += 1.0 / N_COLORS;
Packit 98cdb6
      if (hue > 1.0)
Packit 98cdb6
        hue = 0.0;
Packit 98cdb6
      
Packit 98cdb6
      tmp = g_slist_next (tmp);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  buffer->start_hue += 1.0 / N_COLORS;
Packit 98cdb6
  if (buffer->start_hue > 1.0)
Packit 98cdb6
    buffer->start_hue = 0.0;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
close_view (View *view)
Packit 98cdb6
{
Packit 98cdb6
  views = g_slist_remove (views, view);
Packit 98cdb6
  buffer_unref (view->buffer);
Packit 98cdb6
  gtk_widget_destroy (view->window);
Packit 98cdb6
  g_object_unref (view->item_factory);
Packit 98cdb6
  
Packit 98cdb6
  g_free (view);
Packit 98cdb6
  
Packit 98cdb6
  if (!views)
Packit 98cdb6
    gtk_main_quit ();
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
check_close_view (View *view)
Packit 98cdb6
{
Packit 98cdb6
  if (view->buffer->refcount > 1 ||
Packit 98cdb6
      check_buffer_saved (view->buffer))
Packit 98cdb6
    close_view (view);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
view_set_title (View *view)
Packit 98cdb6
{
Packit 98cdb6
  char *pretty_name = buffer_pretty_name (view->buffer);
Packit 98cdb6
  char *title = g_strconcat ("testtext - ", pretty_name, NULL);
Packit 98cdb6
Packit 98cdb6
  gtk_window_set_title (GTK_WINDOW (view->window), title);
Packit 98cdb6
Packit 98cdb6
  g_free (pretty_name);
Packit 98cdb6
  g_free (title);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
cursor_set_callback (GtkTextBuffer     *buffer,
Packit 98cdb6
                     const GtkTextIter *location,
Packit 98cdb6
                     GtkTextMark       *mark,
Packit 98cdb6
                     gpointer           user_data)
Packit 98cdb6
{
Packit 98cdb6
  GtkTextView *text_view;
Packit 98cdb6
Packit 98cdb6
  /* Redraw tab windows if the cursor moves
Packit 98cdb6
   * on the mapped widget (windows may not exist before realization...
Packit 98cdb6
   */
Packit 98cdb6
  
Packit 98cdb6
  text_view = GTK_TEXT_VIEW (user_data);
Packit 98cdb6
  
Packit 98cdb6
  if (gtk_widget_get_mapped (GTK_WIDGET (text_view)) &&
Packit 98cdb6
      mark == gtk_text_buffer_get_insert (buffer))
Packit 98cdb6
    {
Packit 98cdb6
      GdkWindow *tab_window;
Packit 98cdb6
Packit 98cdb6
      tab_window = gtk_text_view_get_window (text_view,
Packit 98cdb6
                                             GTK_TEXT_WINDOW_TOP);
Packit 98cdb6
Packit 98cdb6
      gdk_window_invalidate_rect (tab_window, NULL, FALSE);
Packit 98cdb6
      
Packit 98cdb6
      tab_window = gtk_text_view_get_window (text_view,
Packit 98cdb6
                                             GTK_TEXT_WINDOW_BOTTOM);
Packit 98cdb6
Packit 98cdb6
      gdk_window_invalidate_rect (tab_window, NULL, FALSE);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gint
Packit 98cdb6
tab_stops_expose (GtkWidget      *widget,
Packit 98cdb6
                  GdkEventExpose *event,
Packit 98cdb6
                  gpointer        user_data)
Packit 98cdb6
{
Packit 98cdb6
  gint first_x;
Packit 98cdb6
  gint last_x;
Packit 98cdb6
  gint i;
Packit 98cdb6
  GdkWindow *top_win;
Packit 98cdb6
  GdkWindow *bottom_win;
Packit 98cdb6
  GtkTextView *text_view;
Packit 98cdb6
  GtkTextWindowType type;
Packit 98cdb6
  GdkDrawable *target;
Packit 98cdb6
  gint *positions = NULL;
Packit 98cdb6
  gint size;
Packit 98cdb6
  GtkTextAttributes *attrs;
Packit 98cdb6
  GtkTextIter insert;
Packit 98cdb6
  GtkTextBuffer *buffer;
Packit 98cdb6
  gboolean in_pixels;
Packit 98cdb6
  
Packit 98cdb6
  text_view = GTK_TEXT_VIEW (widget);
Packit 98cdb6
  
Packit 98cdb6
  /* See if this expose is on the tab stop window */
Packit 98cdb6
  top_win = gtk_text_view_get_window (text_view,
Packit 98cdb6
                                      GTK_TEXT_WINDOW_TOP);
Packit 98cdb6
Packit 98cdb6
  bottom_win = gtk_text_view_get_window (text_view,
Packit 98cdb6
                                         GTK_TEXT_WINDOW_BOTTOM);
Packit 98cdb6
Packit 98cdb6
  if (event->window == top_win)
Packit 98cdb6
    {
Packit 98cdb6
      type = GTK_TEXT_WINDOW_TOP;
Packit 98cdb6
      target = top_win;
Packit 98cdb6
    }
Packit 98cdb6
  else if (event->window == bottom_win)
Packit 98cdb6
    {
Packit 98cdb6
      type = GTK_TEXT_WINDOW_BOTTOM;
Packit 98cdb6
      target = bottom_win;
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    return FALSE;
Packit 98cdb6
  
Packit 98cdb6
  first_x = event->area.x;
Packit 98cdb6
  last_x = first_x + event->area.width;
Packit 98cdb6
Packit 98cdb6
  gtk_text_view_window_to_buffer_coords (text_view,
Packit 98cdb6
                                         type,
Packit 98cdb6
                                         first_x,
Packit 98cdb6
                                         0,
Packit 98cdb6
                                         &first_x,
Packit 98cdb6
                                         NULL);
Packit 98cdb6
Packit 98cdb6
  gtk_text_view_window_to_buffer_coords (text_view,
Packit 98cdb6
                                         type,
Packit 98cdb6
                                         last_x,
Packit 98cdb6
                                         0,
Packit 98cdb6
                                         &last_x,
Packit 98cdb6
                                         NULL);
Packit 98cdb6
Packit 98cdb6
  buffer = gtk_text_view_get_buffer (text_view);
Packit 98cdb6
Packit 98cdb6
  gtk_text_buffer_get_iter_at_mark (buffer,
Packit 98cdb6
                                    &insert,
Packit 98cdb6
                                    gtk_text_buffer_get_mark (buffer,
Packit 98cdb6
                                                              "insert"));
Packit 98cdb6
  
Packit 98cdb6
  attrs = gtk_text_attributes_new ();
Packit 98cdb6
Packit 98cdb6
  gtk_text_iter_get_attributes (&insert, attrs);
Packit 98cdb6
Packit 98cdb6
  if (attrs->tabs)
Packit 98cdb6
    {
Packit 98cdb6
      size = pango_tab_array_get_size (attrs->tabs);
Packit 98cdb6
      
Packit 98cdb6
      pango_tab_array_get_tabs (attrs->tabs,
Packit 98cdb6
                                NULL,
Packit 98cdb6
                                &positions);
Packit 98cdb6
Packit 98cdb6
      in_pixels = pango_tab_array_get_positions_in_pixels (attrs->tabs);
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    {
Packit 98cdb6
      size = 0;
Packit 98cdb6
      in_pixels = FALSE;
Packit 98cdb6
    }
Packit 98cdb6
      
Packit 98cdb6
  gtk_text_attributes_unref (attrs);
Packit 98cdb6
  
Packit 98cdb6
  i = 0;
Packit 98cdb6
  while (i < size)
Packit 98cdb6
    {
Packit 98cdb6
      gint pos;
Packit 98cdb6
Packit 98cdb6
      if (!in_pixels)
Packit 98cdb6
        positions[i] = PANGO_PIXELS (positions[i]);
Packit 98cdb6
      
Packit 98cdb6
      gtk_text_view_buffer_to_window_coords (text_view,
Packit 98cdb6
                                             type,
Packit 98cdb6
                                             positions[i],
Packit 98cdb6
                                             0,
Packit 98cdb6
                                             &pos,
Packit 98cdb6
                                             NULL);
Packit 98cdb6
      
Packit 98cdb6
      gdk_draw_line (target, 
Packit 98cdb6
                     widget->style->fg_gc [widget->state],
Packit 98cdb6
                     pos, 0,
Packit 98cdb6
                     pos, 15); 
Packit 98cdb6
      
Packit 98cdb6
      ++i;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  g_free (positions);
Packit 98cdb6
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
get_lines (GtkTextView  *text_view,
Packit 98cdb6
           gint          first_y,
Packit 98cdb6
           gint          last_y,
Packit 98cdb6
           GArray       *buffer_coords,
Packit 98cdb6
           GArray       *numbers,
Packit 98cdb6
           gint         *countp)
Packit 98cdb6
{
Packit 98cdb6
  GtkTextIter iter;
Packit 98cdb6
  gint count;
Packit 98cdb6
  gint size;  
Packit 98cdb6
Packit 98cdb6
  g_array_set_size (buffer_coords, 0);
Packit 98cdb6
  g_array_set_size (numbers, 0);
Packit 98cdb6
  
Packit 98cdb6
  /* Get iter at first y */
Packit 98cdb6
  gtk_text_view_get_line_at_y (text_view, &iter, first_y, NULL);
Packit 98cdb6
Packit 98cdb6
  /* For each iter, get its location and add it to the arrays.
Packit 98cdb6
   * Stop when we pass last_y
Packit 98cdb6
   */
Packit 98cdb6
  count = 0;
Packit 98cdb6
  size = 0;
Packit 98cdb6
Packit 98cdb6
  while (!gtk_text_iter_is_end (&iter))
Packit 98cdb6
    {
Packit 98cdb6
      gint y, height;
Packit 98cdb6
      gint line_num;
Packit 98cdb6
      
Packit 98cdb6
      gtk_text_view_get_line_yrange (text_view, &iter, &y, &height);
Packit 98cdb6
Packit 98cdb6
      g_array_append_val (buffer_coords, y);
Packit 98cdb6
      line_num = gtk_text_iter_get_line (&iter);
Packit 98cdb6
      g_array_append_val (numbers, line_num);
Packit 98cdb6
      
Packit 98cdb6
      ++count;
Packit 98cdb6
Packit 98cdb6
      if ((y + height) >= last_y)
Packit 98cdb6
        break;
Packit 98cdb6
      
Packit 98cdb6
      gtk_text_iter_forward_line (&iter);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  *countp = count;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gint
Packit 98cdb6
line_numbers_expose (GtkWidget      *widget,
Packit 98cdb6
                     GdkEventExpose *event,
Packit 98cdb6
                     gpointer        user_data)
Packit 98cdb6
{
Packit 98cdb6
  gint count;
Packit 98cdb6
  GArray *numbers;
Packit 98cdb6
  GArray *pixels;
Packit 98cdb6
  gint first_y;
Packit 98cdb6
  gint last_y;
Packit 98cdb6
  gint i;
Packit 98cdb6
  GdkWindow *left_win;
Packit 98cdb6
  GdkWindow *right_win;
Packit 98cdb6
  PangoLayout *layout;
Packit 98cdb6
  GtkTextView *text_view;
Packit 98cdb6
  GtkTextWindowType type;
Packit 98cdb6
  GdkDrawable *target;
Packit 98cdb6
  
Packit 98cdb6
  text_view = GTK_TEXT_VIEW (widget);
Packit 98cdb6
  
Packit 98cdb6
  /* See if this expose is on the line numbers window */
Packit 98cdb6
  left_win = gtk_text_view_get_window (text_view,
Packit 98cdb6
                                       GTK_TEXT_WINDOW_LEFT);
Packit 98cdb6
Packit 98cdb6
  right_win = gtk_text_view_get_window (text_view,
Packit 98cdb6
                                        GTK_TEXT_WINDOW_RIGHT);
Packit 98cdb6
Packit 98cdb6
  if (event->window == left_win)
Packit 98cdb6
    {
Packit 98cdb6
      type = GTK_TEXT_WINDOW_LEFT;
Packit 98cdb6
      target = left_win;
Packit 98cdb6
    }
Packit 98cdb6
  else if (event->window == right_win)
Packit 98cdb6
    {
Packit 98cdb6
      type = GTK_TEXT_WINDOW_RIGHT;
Packit 98cdb6
      target = right_win;
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    return FALSE;
Packit 98cdb6
  
Packit 98cdb6
  first_y = event->area.y;
Packit 98cdb6
  last_y = first_y + event->area.height;
Packit 98cdb6
Packit 98cdb6
  gtk_text_view_window_to_buffer_coords (text_view,
Packit 98cdb6
                                         type,
Packit 98cdb6
                                         0,
Packit 98cdb6
                                         first_y,
Packit 98cdb6
                                         NULL,
Packit 98cdb6
                                         &first_y);
Packit 98cdb6
Packit 98cdb6
  gtk_text_view_window_to_buffer_coords (text_view,
Packit 98cdb6
                                         type,
Packit 98cdb6
                                         0,
Packit 98cdb6
                                         last_y,
Packit 98cdb6
                                         NULL,
Packit 98cdb6
                                         &last_y);
Packit 98cdb6
Packit 98cdb6
  numbers = g_array_new (FALSE, FALSE, sizeof (gint));
Packit 98cdb6
  pixels = g_array_new (FALSE, FALSE, sizeof (gint));
Packit 98cdb6
  
Packit 98cdb6
  get_lines (text_view,
Packit 98cdb6
             first_y,
Packit 98cdb6
             last_y,
Packit 98cdb6
             pixels,
Packit 98cdb6
             numbers,
Packit 98cdb6
             &count);
Packit 98cdb6
  
Packit 98cdb6
  /* Draw fully internationalized numbers! */
Packit 98cdb6
  
Packit 98cdb6
  layout = gtk_widget_create_pango_layout (widget, "");
Packit 98cdb6
  
Packit 98cdb6
  i = 0;
Packit 98cdb6
  while (i < count)
Packit 98cdb6
    {
Packit 98cdb6
      gint pos;
Packit 98cdb6
      gchar *str;
Packit 98cdb6
      
Packit 98cdb6
      gtk_text_view_buffer_to_window_coords (text_view,
Packit 98cdb6
                                             type,
Packit 98cdb6
                                             0,
Packit 98cdb6
                                             g_array_index (pixels, gint, i),
Packit 98cdb6
                                             NULL,
Packit 98cdb6
                                             &pos;;
Packit 98cdb6
Packit 98cdb6
      str = g_strdup_printf ("%d", g_array_index (numbers, gint, i));
Packit 98cdb6
Packit 98cdb6
      pango_layout_set_text (layout, str, -1);
Packit 98cdb6
Packit 98cdb6
      gtk_paint_layout (widget->style,
Packit 98cdb6
                        target,
Packit 98cdb6
                        gtk_widget_get_state (widget),
Packit 98cdb6
                        FALSE,
Packit 98cdb6
                        NULL,
Packit 98cdb6
                        widget,
Packit 98cdb6
                        NULL,
Packit 98cdb6
                        2, pos + 2,
Packit 98cdb6
                        layout);
Packit 98cdb6
Packit 98cdb6
      g_free (str);
Packit 98cdb6
      
Packit 98cdb6
      ++i;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  g_array_free (pixels, TRUE);
Packit 98cdb6
  g_array_free (numbers, TRUE);
Packit 98cdb6
  
Packit 98cdb6
  g_object_unref (layout);
Packit 98cdb6
Packit 98cdb6
  /* don't stop emission, need to draw children */
Packit 98cdb6
  return FALSE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
selection_changed (GtkTextBuffer *buffer,
Packit 98cdb6
		   GParamSpec    *pspec,
Packit 98cdb6
		   GtkWidget     *copy_menu)
Packit 98cdb6
{
Packit 98cdb6
  gtk_widget_set_sensitive (copy_menu, gtk_text_buffer_get_has_selection (buffer));
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static View *
Packit 98cdb6
create_view (Buffer *buffer)
Packit 98cdb6
{
Packit 98cdb6
  View *view;
Packit 98cdb6
  GtkWidget *copy_menu;
Packit 98cdb6
  GtkWidget *sw;
Packit 98cdb6
  GtkWidget *vbox;
Packit 98cdb6
  
Packit 98cdb6
  view = g_new0 (View, 1);
Packit 98cdb6
  views = g_slist_prepend (views, view);
Packit 98cdb6
Packit 98cdb6
  view->buffer = buffer;
Packit 98cdb6
  buffer_ref (buffer);
Packit 98cdb6
  
Packit 98cdb6
  view->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
Packit 98cdb6
  g_object_set_data (G_OBJECT (view->window), "view", view);
Packit 98cdb6
  
Packit 98cdb6
  g_signal_connect (view->window, "delete_event",
Packit 98cdb6
		    G_CALLBACK (delete_event_cb), NULL);
Packit 98cdb6
Packit 98cdb6
  view->accel_group = gtk_accel_group_new ();
Packit 98cdb6
  view->item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", view->accel_group);
Packit 98cdb6
  g_object_set_data (G_OBJECT (view->item_factory), "view", view);
Packit 98cdb6
  
Packit 98cdb6
  gtk_item_factory_create_items (view->item_factory, G_N_ELEMENTS (menu_items), menu_items, view);
Packit 98cdb6
Packit 98cdb6
  /* make the Copy menu item sensitivity update according to the selection */
Packit 98cdb6
  copy_menu = gtk_item_factory_get_item (view->item_factory, "<main>/Edit/Copy");
Packit 98cdb6
  gtk_widget_set_sensitive (copy_menu, gtk_text_buffer_get_has_selection (view->buffer->buffer));
Packit 98cdb6
  g_signal_connect (view->buffer->buffer,
Packit 98cdb6
		    "notify::has-selection",
Packit 98cdb6
		    G_CALLBACK (selection_changed),
Packit 98cdb6
		    copy_menu);
Packit 98cdb6
Packit 98cdb6
  gtk_window_add_accel_group (GTK_WINDOW (view->window), view->accel_group);
Packit 98cdb6
Packit 98cdb6
  vbox = gtk_vbox_new (FALSE, 0);
Packit 98cdb6
  gtk_container_add (GTK_CONTAINER (view->window), vbox);
Packit 98cdb6
Packit 98cdb6
  gtk_box_pack_start (GTK_BOX (vbox),
Packit 98cdb6
		      gtk_item_factory_get_widget (view->item_factory, "<main>"),
Packit 98cdb6
		      FALSE, FALSE, 0);
Packit 98cdb6
  
Packit 98cdb6
  sw = gtk_scrolled_window_new (NULL, NULL);
Packit 98cdb6
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
Packit 98cdb6
                                 GTK_POLICY_AUTOMATIC,
Packit 98cdb6
                                 GTK_POLICY_AUTOMATIC);
Packit 98cdb6
Packit 98cdb6
  view->text_view = gtk_text_view_new_with_buffer (buffer->buffer);
Packit 98cdb6
  gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view->text_view),
Packit 98cdb6
                               GTK_WRAP_WORD);
Packit 98cdb6
Packit 98cdb6
  /* Make sure border width works, no real reason to do this other than testing */
Packit 98cdb6
  gtk_container_set_border_width (GTK_CONTAINER (view->text_view),
Packit 98cdb6
                                  10);
Packit 98cdb6
  
Packit 98cdb6
  /* Draw tab stops in the top and bottom windows. */
Packit 98cdb6
  
Packit 98cdb6
  gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (view->text_view),
Packit 98cdb6
                                        GTK_TEXT_WINDOW_TOP,
Packit 98cdb6
                                        15);
Packit 98cdb6
Packit 98cdb6
  gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (view->text_view),
Packit 98cdb6
                                        GTK_TEXT_WINDOW_BOTTOM,
Packit 98cdb6
                                        15);
Packit 98cdb6
Packit 98cdb6
  g_signal_connect (view->text_view,
Packit 98cdb6
                    "expose_event",
Packit 98cdb6
                    G_CALLBACK (tab_stops_expose),
Packit 98cdb6
                    NULL);  
Packit 98cdb6
Packit 98cdb6
  g_signal_connect (view->buffer->buffer,
Packit 98cdb6
		    "mark_set",
Packit 98cdb6
		    G_CALLBACK (cursor_set_callback),
Packit 98cdb6
		    view->text_view);
Packit 98cdb6
  
Packit 98cdb6
  /* Draw line numbers in the side windows; we should really be
Packit 98cdb6
   * more scientific about what width we set them to.
Packit 98cdb6
   */
Packit 98cdb6
  gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (view->text_view),
Packit 98cdb6
                                        GTK_TEXT_WINDOW_RIGHT,
Packit 98cdb6
                                        30);
Packit 98cdb6
  
Packit 98cdb6
  gtk_text_view_set_border_window_size (GTK_TEXT_VIEW (view->text_view),
Packit 98cdb6
                                        GTK_TEXT_WINDOW_LEFT,
Packit 98cdb6
                                        30);
Packit 98cdb6
  
Packit 98cdb6
  g_signal_connect (view->text_view,
Packit 98cdb6
                    "expose_event",
Packit 98cdb6
                    G_CALLBACK (line_numbers_expose),
Packit 98cdb6
                    NULL);
Packit 98cdb6
  
Packit 98cdb6
  gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
Packit 98cdb6
  gtk_container_add (GTK_CONTAINER (sw), view->text_view);
Packit 98cdb6
Packit 98cdb6
  gtk_window_set_default_size (GTK_WINDOW (view->window), 500, 500);
Packit 98cdb6
Packit 98cdb6
  gtk_widget_grab_focus (view->text_view);
Packit 98cdb6
Packit 98cdb6
  view_set_title (view);
Packit 98cdb6
  view_init_menus (view);
Packit 98cdb6
Packit 98cdb6
  view_add_example_widgets (view);
Packit 98cdb6
  
Packit 98cdb6
  gtk_widget_show_all (view->window);
Packit 98cdb6
  return view;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
view_add_example_widgets (View *view)
Packit 98cdb6
{
Packit 98cdb6
  GtkTextChildAnchor *anchor;
Packit 98cdb6
  Buffer *buffer;
Packit 98cdb6
Packit 98cdb6
  buffer = view->buffer;
Packit 98cdb6
  
Packit 98cdb6
  anchor = g_object_get_data (G_OBJECT (buffer->buffer),
Packit 98cdb6
                              "anchor");
Packit 98cdb6
Packit 98cdb6
  if (anchor && !gtk_text_child_anchor_get_deleted (anchor))
Packit 98cdb6
    {
Packit 98cdb6
      GtkWidget *widget;
Packit 98cdb6
Packit 98cdb6
      widget = gtk_button_new_with_label ("Foo");
Packit 98cdb6
      
Packit 98cdb6
      gtk_text_view_add_child_at_anchor (GTK_TEXT_VIEW (view->text_view),
Packit 98cdb6
                                         widget,
Packit 98cdb6
                                         anchor);
Packit 98cdb6
Packit 98cdb6
      gtk_widget_show (widget);
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
void
Packit 98cdb6
test_init (void)
Packit 98cdb6
{
Packit 98cdb6
  g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/immodules.cache", TRUE);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
int
Packit 98cdb6
main (int argc, char** argv)
Packit 98cdb6
{
Packit 98cdb6
  Buffer *buffer;
Packit 98cdb6
  View *view;
Packit 98cdb6
  int i;
Packit 98cdb6
Packit 98cdb6
  test_init ();
Packit 98cdb6
  gtk_init (&argc, &argv);
Packit 98cdb6
  
Packit 98cdb6
  buffer = create_buffer ();
Packit 98cdb6
  view = create_view (buffer);
Packit 98cdb6
  buffer_unref (buffer);
Packit 98cdb6
  
Packit 98cdb6
  push_active_window (GTK_WINDOW (view->window));
Packit 98cdb6
  for (i=1; i < argc; i++)
Packit 98cdb6
    {
Packit 98cdb6
      char *filename;
Packit 98cdb6
Packit 98cdb6
      /* Quick and dirty canonicalization - better should be in GLib
Packit 98cdb6
       */
Packit 98cdb6
Packit 98cdb6
      if (!g_path_is_absolute (argv[i]))
Packit 98cdb6
	{
Packit 98cdb6
	  char *cwd = g_get_current_dir ();
Packit 98cdb6
	  filename = g_strconcat (cwd, "/", argv[i], NULL);
Packit 98cdb6
	  g_free (cwd);
Packit 98cdb6
	}
Packit 98cdb6
      else
Packit 98cdb6
	filename = argv[i];
Packit 98cdb6
Packit 98cdb6
      open_ok_func (filename, view);
Packit 98cdb6
Packit 98cdb6
      if (filename != argv[i])
Packit 98cdb6
	g_free (filename);
Packit 98cdb6
    }
Packit 98cdb6
  pop_active_window ();
Packit 98cdb6
  
Packit 98cdb6
  gtk_main ();
Packit 98cdb6
Packit 98cdb6
  return 0;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6