+/* testtext.c
+ * Copyright (C) 2000 Red Hat, Inc
+ * Author: Havoc Pennington
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
#include <config.h>
#include <stdio.h>
#include <sys/stat.h>
GtkTextTag *invisible_tag;
GtkTextTag *not_editable_tag;
GtkTextTag *found_text_tag;
+ GtkTextTag *rise_tag;
+ GtkTextTag *large_tag;
+ GtkTextTag *indent_tag;
+ GtkTextTag *margin_tag;
GtkTextTag *custom_tabs_tag;
GSList *color_tags;
guint color_cycle_timeout;
}
}
+static void
+do_apply_rise (gpointer callback_data,
+ guint callback_action,
+ GtkWidget *widget)
+{
+ View *view = view_from_widget (widget);
+ GtkTextIter start;
+ GtkTextIter end;
+
+ if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
+ &start, &end))
+ {
+ if (callback_action)
+ {
+ gtk_text_buffer_remove_tag (view->buffer->buffer,
+ view->buffer->rise_tag,
+ &start, &end);
+ }
+ else
+ {
+ gtk_text_buffer_apply_tag (view->buffer->buffer,
+ view->buffer->rise_tag,
+ &start, &end);
+ }
+ }
+}
+
+static void
+do_apply_large (gpointer callback_data,
+ guint callback_action,
+ GtkWidget *widget)
+{
+ View *view = view_from_widget (widget);
+ GtkTextIter start;
+ GtkTextIter end;
+
+ if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
+ &start, &end))
+ {
+ if (callback_action)
+ {
+ gtk_text_buffer_remove_tag (view->buffer->buffer,
+ view->buffer->large_tag,
+ &start, &end);
+ }
+ else
+ {
+ gtk_text_buffer_apply_tag (view->buffer->buffer,
+ view->buffer->large_tag,
+ &start, &end);
+ }
+ }
+}
+
+static void
+do_apply_indent (gpointer callback_data,
+ guint callback_action,
+ GtkWidget *widget)
+{
+ View *view = view_from_widget (widget);
+ GtkTextIter start;
+ GtkTextIter end;
+
+ if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
+ &start, &end))
+ {
+ if (callback_action)
+ {
+ gtk_text_buffer_remove_tag (view->buffer->buffer,
+ view->buffer->indent_tag,
+ &start, &end);
+ }
+ else
+ {
+ gtk_text_buffer_apply_tag (view->buffer->buffer,
+ view->buffer->indent_tag,
+ &start, &end);
+ }
+ }
+}
+
+static void
+do_apply_margin (gpointer callback_data,
+ guint callback_action,
+ GtkWidget *widget)
+{
+ View *view = view_from_widget (widget);
+ GtkTextIter start;
+ GtkTextIter end;
+
+ if (gtk_text_buffer_get_selection_bounds (view->buffer->buffer,
+ &start, &end))
+ {
+ if (callback_action)
+ {
+ gtk_text_buffer_remove_tag (view->buffer->buffer,
+ view->buffer->margin_tag,
+ &start, &end);
+ }
+ else
+ {
+ gtk_text_buffer_apply_tag (view->buffer->buffer,
+ view->buffer->margin_tag,
+ &start, &end);
+ }
+ }
+}
+
static void
do_apply_tabs (gpointer callback_data,
guint callback_action,
create_prop_editor (G_OBJECT (view->text_view), 0);
}
+static void
+rich_text_store_populate (GtkListStore *store,
+ GtkTextBuffer *buffer,
+ gboolean deserialize)
+{
+ GdkAtom *formats;
+ gint n_formats;
+ gint i;
+
+ gtk_list_store_clear (store);
+
+ if (deserialize)
+ formats = gtk_text_buffer_get_deserialize_formats (buffer, &n_formats);
+ else
+ formats = gtk_text_buffer_get_serialize_formats (buffer, &n_formats);
+
+ for (i = 0; i < n_formats; i++)
+ {
+ GtkTreeIter iter;
+ gchar *mime_type;
+ gboolean can_create_tags = FALSE;
+
+ mime_type = gdk_atom_name (formats[i]);
+
+ if (deserialize)
+ can_create_tags =
+ gtk_text_buffer_deserialize_get_can_create_tags (buffer, formats[i]);
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ 0, formats[i],
+ 1, mime_type,
+ 2, can_create_tags,
+ -1);
+
+ g_free (mime_type);
+ }
+
+ g_free (formats);
+}
+
+static void
+rich_text_paste_target_list_notify (GtkTextBuffer *buffer,
+ const GParamSpec *pspec,
+ GtkListStore *store)
+{
+ rich_text_store_populate (store, buffer, TRUE);
+}
+
+static void
+rich_text_copy_target_list_notify (GtkTextBuffer *buffer,
+ const GParamSpec *pspec,
+ GtkListStore *store)
+{
+ rich_text_store_populate (store, buffer, FALSE);
+}
+
+static void
+rich_text_can_create_tags_toggled (GtkCellRendererToggle *toggle,
+ const gchar *path,
+ GtkTreeModel *model)
+{
+ GtkTreeIter iter;
+
+ if (gtk_tree_model_get_iter_from_string (model, &iter, path))
+ {
+ GtkTextBuffer *buffer;
+ GdkAtom format;
+ gboolean can_create_tags;
+
+ buffer = g_object_get_data (G_OBJECT (model), "buffer");
+
+ gtk_tree_model_get (model, &iter,
+ 0, &format,
+ 2, &can_create_tags,
+ -1);
+
+ gtk_text_buffer_deserialize_set_can_create_tags (buffer, format,
+ !can_create_tags);
+
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+ 2, !can_create_tags,
+ -1);
+ }
+}
+
+static void
+rich_text_unregister_clicked (GtkWidget *button,
+ GtkTreeView *tv)
+{
+ GtkTreeSelection *sel = gtk_tree_view_get_selection (tv);
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ if (gtk_tree_selection_get_selected (sel, &model, &iter))
+ {
+ GtkTextBuffer *buffer;
+ gboolean deserialize;
+ GdkAtom format;
+
+ buffer = g_object_get_data (G_OBJECT (model), "buffer");
+ deserialize = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (model),
+ "deserialize"));
+
+ gtk_tree_model_get (model, &iter,
+ 0, &format,
+ -1);
+
+ if (deserialize)
+ gtk_text_buffer_unregister_deserialize_format (buffer, format);
+ else
+ gtk_text_buffer_unregister_serialize_format (buffer, format);
+ }
+}
+
+static void
+rich_text_register_clicked (GtkWidget *button,
+ GtkTreeView *tv)
+{
+ GtkWidget *dialog;
+ GtkWidget *label;
+ GtkWidget *entry;
+
+ dialog = gtk_dialog_new_with_buttons ("Register new Tagset",
+ GTK_WINDOW (gtk_widget_get_toplevel (button)),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+ label = gtk_label_new ("Enter tagset name or leave blank for "
+ "unrestricted internal format:");
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), label,
+ FALSE, FALSE, 0);
+
+ entry = gtk_entry_new ();
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), entry,
+ FALSE, FALSE, 0);
+
+ gtk_widget_show_all (dialog);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+ {
+ GtkTreeModel *model = gtk_tree_view_get_model (tv);
+ GtkTextBuffer *buffer = g_object_get_data (G_OBJECT (model), "buffer");
+ const gchar *tagset = gtk_entry_get_text (GTK_ENTRY (entry));
+ gboolean deserialize;
+
+ deserialize = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (model),
+ "deserialize"));
+
+ if (tagset && ! strlen (tagset))
+ tagset = NULL;
+
+ if (deserialize)
+ gtk_text_buffer_register_deserialize_tagset (buffer, tagset);
+ else
+ gtk_text_buffer_register_serialize_tagset (buffer, tagset);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+do_rich_text (gpointer callback_data,
+ guint deserialize,
+ GtkWidget *widget)
+{
+ View *view = view_from_widget (widget);
+ GtkTextBuffer *buffer;
+ GtkWidget *dialog;
+ GtkWidget *tv;
+ GtkWidget *sw;
+ GtkWidget *hbox;
+ GtkWidget *button;
+ GtkListStore *store;
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view->text_view));
+
+ dialog = gtk_dialog_new_with_buttons (deserialize ?
+ "Rich Text Paste & Drop" :
+ "Rich Text Copy & Drag",
+ GTK_WINDOW (view->window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CLOSE, 0,
+ NULL);
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy),
+ NULL);
+
+ store = gtk_list_store_new (3,
+ G_TYPE_POINTER,
+ G_TYPE_STRING,
+ G_TYPE_BOOLEAN);
+
+ g_object_set_data (G_OBJECT (store), "buffer", buffer);
+ g_object_set_data (G_OBJECT (store), "deserialize",
+ GUINT_TO_POINTER (deserialize));
+
+ tv = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
+ g_object_unref (store);
+
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv),
+ 0, "Rich Text Format",
+ gtk_cell_renderer_text_new (),
+ "text", 1,
+ NULL);
+
+ if (deserialize)
+ {
+ GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new ();
+
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv),
+ 1, "Can Create Tags",
+ renderer,
+ "active", 2,
+ NULL);
+
+ g_signal_connect (renderer, "toggled",
+ G_CALLBACK (rich_text_can_create_tags_toggled),
+ store);
+ }
+
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_set_size_request (sw, 300, 100);
+ gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), sw);
+
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), tv);
+
+ hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox,
+ FALSE, FALSE, 0);
+
+ button = gtk_button_new_with_label ("Unregister Selected Format");
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (rich_text_unregister_clicked),
+ tv);
+
+ button = gtk_button_new_with_label ("Register New Tagset\n"
+ "for the Internal Format");
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (rich_text_register_clicked),
+ tv);
+
+ if (deserialize)
+ g_signal_connect_object (buffer, "notify::paste-target-list",
+ G_CALLBACK (rich_text_paste_target_list_notify),
+ G_OBJECT (store), 0);
+ else
+ g_signal_connect_object (buffer, "notify::copy-target-list",
+ G_CALLBACK (rich_text_copy_target_list_notify),
+ G_OBJECT (store), 0);
+
+ rich_text_store_populate (store, buffer, deserialize);
+
+ gtk_widget_show_all (dialog);
+}
+
enum
{
RESPONSE_FORWARD,
gtk_widget_destroy (dialog);
}
+static void
+do_copy (gpointer callback_data,
+ guint callback_action,
+ GtkWidget *widget)
+{
+ View *view = view_from_widget (widget);
+ GtkTextBuffer *buffer;
+
+ buffer = view->buffer->buffer;
+
+ gtk_text_buffer_copy_clipboard (buffer,
+ gtk_clipboard_get (GDK_NONE));
+}
+
static void
do_search (gpointer callback_data,
guint callback_action,
gtk_widget_show_all (dialog);
}
+static void
+do_select_all (gpointer callback_data,
+ guint callback_action,
+ GtkWidget *widget)
+{
+ View *view = view_from_widget (widget);
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+
+ buffer = view->buffer->buffer;
+
+ gtk_text_buffer_get_bounds (buffer, &start, &end);
+ gtk_text_buffer_select_range (buffer, &start, &end);
+}
+
typedef struct
{
/* position is in coordinate system of text_view_move_child */
static GtkItemFactoryEntry menu_items[] =
{
- { "/_File", NULL, 0, 0, "<Branch>" },
+ { "/_File", NULL, NULL, 0, "<Branch>" },
{ "/File/_New", "<control>N", do_new, 0, NULL },
{ "/File/New _View", NULL, do_new_view, 0, NULL },
{ "/File/_Open", "<control>O", do_open, 0, NULL },
{ "/File/_Save", "<control>S", do_save, 0, NULL },
{ "/File/Save _As...", NULL, do_save_as, 0, NULL },
- { "/File/sep1", NULL, 0, 0, "<Separator>" },
+ { "/File/sep1", NULL, NULL, 0, "<Separator>" },
{ "/File/_Close", "<control>W" , do_close, 0, NULL },
{ "/File/E_xit", "<control>Q" , do_exit, 0, NULL },
{ "/_Edit", NULL, 0, 0, "<Branch>" },
+ { "/Edit/Copy", NULL, do_copy, 0, NULL },
+ { "/Edit/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Edit/Find...", NULL, do_search, 0, NULL },
+ { "/Edit/Select All", "<control>A", do_select_all, 0, NULL },
- { "/_Settings", NULL, 0, 0, "<Branch>" },
+ { "/_Settings", NULL, NULL, 0, "<Branch>" },
{ "/Settings/Wrap _Off", NULL, do_wrap_changed, GTK_WRAP_NONE, "<RadioItem>" },
{ "/Settings/Wrap _Words", NULL, do_wrap_changed, GTK_WRAP_WORD, "/Settings/Wrap Off" },
{ "/Settings/Wrap _Chars", NULL, do_wrap_changed, GTK_WRAP_CHAR, "/Settings/Wrap Off" },
- { "/Settings/sep1", NULL, 0, 0, "<Separator>" },
+ { "/Settings/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Settings/Editable", NULL, do_editable_changed, TRUE, "<RadioItem>" },
{ "/Settings/Not editable", NULL, do_editable_changed, FALSE, "/Settings/Editable" },
- { "/Settings/sep1", NULL, 0, 0, "<Separator>" },
+ { "/Settings/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Settings/Cursor visible", NULL, do_cursor_visible_changed, TRUE, "<RadioItem>" },
{ "/Settings/Cursor not visible", NULL, do_cursor_visible_changed, FALSE, "/Settings/Cursor visible" },
- { "/Settings/sep1", NULL, 0, 0, "<Separator>" },
+ { "/Settings/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Settings/Left-to-Right", NULL, do_direction_changed, GTK_TEXT_DIR_LTR, "<RadioItem>" },
{ "/Settings/Right-to-Left", NULL, do_direction_changed, GTK_TEXT_DIR_RTL, "/Settings/Left-to-Right" },
- { "/Settings/sep1", NULL, 0, 0, "<Separator>" },
+ { "/Settings/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Settings/Sane spacing", NULL, do_spacing_changed, FALSE, "<RadioItem>" },
{ "/Settings/Funky spacing", NULL, do_spacing_changed, TRUE, "/Settings/Sane spacing" },
- { "/Settings/sep1", NULL, 0, 0, "<Separator>" },
+ { "/Settings/sep1", NULL, NULL, 0, "<Separator>" },
{ "/Settings/Don't cycle color tags", NULL, do_color_cycle_changed, FALSE, "<RadioItem>" },
{ "/Settings/Cycle colors", NULL, do_color_cycle_changed, TRUE, "/Settings/Don't cycle color tags" },
- { "/_Attributes", NULL, 0, 0, "<Branch>" },
+ { "/_Attributes", NULL, NULL, 0, "<Branch>" },
{ "/Attributes/Editable", NULL, do_apply_editable, TRUE, NULL },
{ "/Attributes/Not editable", NULL, do_apply_editable, FALSE, NULL },
{ "/Attributes/Invisible", NULL, do_apply_invisible, FALSE, NULL },
{ "/Attributes/Visible", NULL, do_apply_invisible, TRUE, NULL },
+ { "/Attributes/Rise", NULL, do_apply_rise, FALSE, NULL },
+ { "/Attributes/Large", NULL, do_apply_large, FALSE, NULL },
+ { "/Attributes/Indent", NULL, do_apply_indent, FALSE, NULL },
+ { "/Attributes/Margins", NULL, do_apply_margin, FALSE, NULL },
{ "/Attributes/Custom tabs", NULL, do_apply_tabs, FALSE, NULL },
{ "/Attributes/Default tabs", NULL, do_apply_tabs, TRUE, NULL },
{ "/Attributes/Color cycles", NULL, do_apply_colors, TRUE, NULL },
{ "/Attributes/No colors", NULL, do_apply_colors, FALSE, NULL },
- { "/Attributes/Remove all tags", NULL, do_remove_tags, 0, NULL },
- { "/Attributes/Properties", NULL, do_properties, 0, NULL },
- { "/_Test", NULL, 0, 0, "<Branch>" },
+ { "/Attributes/Remove all tags", NULL, do_remove_tags, 0, NULL },
+ { "/Attributes/Properties", NULL, do_properties, 0, NULL },
+ { "/Attributes/Rich Text copy & drag", NULL, do_rich_text, 0, NULL },
+ { "/Attributes/Rich Text paste & drop", NULL, do_rich_text, 1, NULL },
+ { "/_Test", NULL, NULL, 0, "<Branch>" },
{ "/Test/_Example", NULL, do_example, 0, NULL },
{ "/Test/_Insert and scroll", NULL, do_insert_and_scroll, 0, NULL },
{ "/Test/_Add fixed children", NULL, do_add_children, 0, NULL },
++i;
}
-#if 0
+#if 1
buffer->invisible_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
"invisible", TRUE, NULL);
#endif
buffer->found_text_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
"foreground", "red", NULL);
+ buffer->rise_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
+ "rise", 10 * PANGO_SCALE, NULL);
+
+ buffer->large_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
+ "scale", PANGO_SCALE_X_LARGE, NULL);
+
+ buffer->indent_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
+ "indent", 20, NULL);
+
+ buffer->margin_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
+ "left_margin", 20, "right_margin", 20, NULL);
+
tabs = pango_tab_array_new_with_positions (4,
TRUE,
PANGO_TAB_LEFT, 10,
gdouble hue = 0.0;
if (enabled && buffer->color_cycle_timeout == 0)
- buffer->color_cycle_timeout = g_timeout_add (200, color_cycle_timeout, buffer);
+ buffer->color_cycle_timeout = gdk_threads_add_timeout (200, color_cycle_timeout, buffer);
else if (!enabled && buffer->color_cycle_timeout != 0)
{
g_source_remove (buffer->color_cycle_timeout);
return FALSE;
}
+static void
+selection_changed (GtkTextBuffer *buffer,
+ GParamSpec *pspec,
+ GtkWidget *copy_menu)
+{
+ gtk_widget_set_sensitive (copy_menu, gtk_text_buffer_get_has_selection (buffer));
+}
+
static View *
create_view (Buffer *buffer)
{
View *view;
-
+ GtkWidget *copy_menu;
GtkWidget *sw;
GtkWidget *vbox;
gtk_item_factory_create_items (view->item_factory, G_N_ELEMENTS (menu_items), menu_items, view);
+ /* make the Copy menu item sensitivity update according to the selection */
+ copy_menu = gtk_item_factory_get_item (view->item_factory, "<main>/Edit/Copy");
+ gtk_widget_set_sensitive (copy_menu, gtk_text_buffer_get_has_selection (view->buffer->buffer));
+ g_signal_connect (view->buffer->buffer,
+ "notify::has-selection",
+ G_CALLBACK (selection_changed),
+ copy_menu);
+
gtk_window_add_accel_group (GTK_WINDOW (view->window), view->accel_group);
vbox = gtk_vbox_new (FALSE, 0);
}
void
-test_init ()
+test_init (void)
{
if (g_file_test ("../gdk-pixbuf/libpixbufloader-pnm.la",
G_FILE_TEST_EXISTS))