444 lines
13 KiB
Diff
444 lines
13 KiB
Diff
--- gtk+-2.6.4/gtk/gtktextbuffer.c 2004-11-01 21:57:13.000000000 +0200
|
|
+++ gtk+-2.6.4/gtk/gtktextbuffer.c 2005-04-06 16:19:38.023757872 +0300
|
|
@@ -1,5 +1,6 @@
|
|
/* GTK - The GIMP Toolkit
|
|
* gtktextbuffer.c Copyright (C) 2000 Red Hat, Inc.
|
|
+ * Copyright (C) 2004 Nokia Corporation
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
@@ -39,6 +40,17 @@
|
|
#include "gtktextbtree.h"
|
|
#include "gtktextiterprivate.h"
|
|
#include "gtkintl.h"
|
|
+#include "gtktextbufferserialize.h"
|
|
+
|
|
+#define GTK_TEXT_BUFFER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_TEXT_BUFFER, GtkTextBufferPrivate))
|
|
+
|
|
+typedef struct _GtkTextBufferPrivate GtkTextBufferPrivate;
|
|
+
|
|
+struct _GtkTextBufferPrivate
|
|
+{
|
|
+ gboolean can_paste_rich_text;
|
|
+ gchar *rich_text_format;
|
|
+};
|
|
|
|
typedef struct _ClipboardRequest ClipboardRequest;
|
|
|
|
@@ -71,7 +83,10 @@
|
|
PROP_0,
|
|
|
|
/* Construct */
|
|
- PROP_TAG_TABLE
|
|
+ PROP_TAG_TABLE,
|
|
+
|
|
+ PROP_CAN_PASTE_RICH_TEXT,
|
|
+ PROP_RICH_TEXT_FORMAT
|
|
};
|
|
|
|
enum {
|
|
@@ -79,6 +94,8 @@
|
|
TARGET_TEXT,
|
|
TARGET_COMPOUND_TEXT,
|
|
TARGET_UTF8_STRING,
|
|
+ TARGET_TEXT_VIEW_MARKUP,
|
|
+ TARGET_TEXT_VIEW_RICH_TEXT_FORMAT,
|
|
TARGET_TEXT_BUFFER_CONTENTS
|
|
};
|
|
|
|
@@ -185,7 +202,20 @@
|
|
P_("Text Tag Table"),
|
|
GTK_TYPE_TEXT_TAG_TABLE,
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
|
+ g_object_class_install_property (object_class,
|
|
+ PROP_CAN_PASTE_RICH_TEXT,
|
|
+ g_param_spec_boolean ("can_paste_rich_text",
|
|
+ P_("Can paste rich text"),
|
|
+ P_("Whether it should be possible to paste rich text to the buffer"),
|
|
+ FALSE, G_PARAM_READWRITE));
|
|
+ g_object_class_install_property (object_class,
|
|
+ PROP_RICH_TEXT_FORMAT,
|
|
+ g_param_spec_string ("rich_text_format",
|
|
+ P_("Rich Text Format"),
|
|
+ P_("Name of a collection of tags that the text view supports"),
|
|
+ NULL, G_PARAM_READWRITE));
|
|
|
|
+
|
|
signals[INSERT_TEXT] =
|
|
g_signal_new ("insert_text",
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
@@ -335,7 +365,9 @@
|
|
NULL, NULL,
|
|
_gtk_marshal_VOID__VOID,
|
|
G_TYPE_NONE,
|
|
- 0);
|
|
+ 0);
|
|
+
|
|
+ g_type_class_add_private (object_class, sizeof (GtkTextBufferPrivate));
|
|
}
|
|
|
|
static void
|
|
@@ -385,7 +417,12 @@
|
|
case PROP_TAG_TABLE:
|
|
set_table (text_buffer, g_value_get_object (value));
|
|
break;
|
|
-
|
|
+ case PROP_CAN_PASTE_RICH_TEXT:
|
|
+ gtk_text_buffer_set_can_paste_rich_text (text_buffer, g_value_get_boolean (value));
|
|
+ break;
|
|
+ case PROP_RICH_TEXT_FORMAT:
|
|
+ gtk_text_buffer_set_rich_text_format (text_buffer, g_value_get_string (value));
|
|
+ break;
|
|
default:
|
|
break;
|
|
}
|
|
@@ -406,7 +443,14 @@
|
|
case PROP_TAG_TABLE:
|
|
g_value_set_object (value, get_table (text_buffer));
|
|
break;
|
|
-
|
|
+ case PROP_CAN_PASTE_RICH_TEXT:
|
|
+ g_value_set_boolean (value,
|
|
+ gtk_text_buffer_get_can_paste_rich_text (text_buffer));
|
|
+ break;
|
|
+ case PROP_RICH_TEXT_FORMAT:
|
|
+ g_value_set_string (value,
|
|
+ gtk_text_buffer_get_rich_text_format (text_buffer));
|
|
+ break;
|
|
default:
|
|
break;
|
|
}
|
|
@@ -434,11 +478,14 @@
|
|
gtk_text_buffer_finalize (GObject *object)
|
|
{
|
|
GtkTextBuffer *buffer;
|
|
+ GtkTextBufferPrivate *priv;
|
|
|
|
buffer = GTK_TEXT_BUFFER (object);
|
|
|
|
remove_all_selection_clipboards (buffer);
|
|
|
|
+ priv = GTK_TEXT_BUFFER_GET_PRIVATE (buffer);
|
|
+
|
|
if (buffer->tag_table)
|
|
{
|
|
_gtk_text_tag_table_remove_buffer (buffer->tag_table, buffer);
|
|
@@ -456,7 +503,9 @@
|
|
free_log_attr_cache (buffer->log_attr_cache);
|
|
|
|
buffer->log_attr_cache = NULL;
|
|
-
|
|
+
|
|
+ g_free (priv->rich_text_format);
|
|
+
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
}
|
|
|
|
@@ -2738,8 +2787,7 @@
|
|
|
|
if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
|
|
{
|
|
- if (selection_data->target ==
|
|
- gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE))
|
|
+ if (info == TARGET_TEXT_BUFFER_CONTENTS)
|
|
{
|
|
/* Provide the address of the buffer; this will only be
|
|
* used within-process
|
|
@@ -2750,6 +2798,32 @@
|
|
(void*)&buffer,
|
|
sizeof (buffer));
|
|
}
|
|
+ else if (info == TARGET_TEXT_VIEW_MARKUP)
|
|
+ {
|
|
+ gchar *str;
|
|
+ gint len;
|
|
+
|
|
+ str = gtk_text_buffer_serialize_rich_text (buffer, &start, &end, &len);
|
|
+
|
|
+ gtk_selection_data_set (selection_data,
|
|
+ gdk_atom_intern ("application/x-gtk-text-view-markup", FALSE),
|
|
+ 8, /* bytes */
|
|
+ str, len);
|
|
+ g_free (str);
|
|
+ }
|
|
+ else if (info == TARGET_TEXT_VIEW_RICH_TEXT_FORMAT)
|
|
+ {
|
|
+ gint len;
|
|
+ gchar *format;
|
|
+
|
|
+ format = g_object_get_data (G_OBJECT (buffer), "gtk-text-buffer-clipboard-format");
|
|
+ len = format ? strlen (format) : -1;
|
|
+
|
|
+ gtk_selection_data_set (selection_data,
|
|
+ gdk_atom_intern ("application/x-gtk-text-view-rich-text-format", FALSE),
|
|
+ 8, /* bytes */
|
|
+ format, len);
|
|
+ }
|
|
else
|
|
{
|
|
gchar *str;
|
|
@@ -2765,10 +2839,16 @@
|
|
create_clipboard_contents_buffer (GtkTextBuffer *buffer)
|
|
{
|
|
GtkTextBuffer *contents;
|
|
+ gchar *format;
|
|
|
|
contents = gtk_text_buffer_new (gtk_text_buffer_get_tag_table (buffer));
|
|
|
|
+ format = GTK_TEXT_BUFFER_GET_PRIVATE (buffer)->rich_text_format;
|
|
+
|
|
g_object_set_data (G_OBJECT (contents), "gtk-text-buffer-clipboard", GINT_TO_POINTER (1));
|
|
+
|
|
+ g_object_set_data_full (G_OBJECT (contents), "gtk-text-buffer-clipboard-format",
|
|
+ format ? g_strdup (format) : NULL, g_free);
|
|
|
|
return contents;
|
|
}
|
|
@@ -2786,8 +2866,7 @@
|
|
|
|
g_assert (contents); /* This should never be called unless we own the clipboard */
|
|
|
|
- if (selection_data->target ==
|
|
- gdk_atom_intern ("GTK_TEXT_BUFFER_CONTENTS", FALSE))
|
|
+ if (info == TARGET_TEXT_BUFFER_CONTENTS)
|
|
{
|
|
/* Provide the address of the clipboard buffer; this will only
|
|
* be used within-process. OK to supply a NULL value for contents.
|
|
@@ -2798,6 +2877,35 @@
|
|
(void*)&contents,
|
|
sizeof (contents));
|
|
}
|
|
+ else if (info == TARGET_TEXT_VIEW_MARKUP)
|
|
+ {
|
|
+ gchar *str;
|
|
+ gint *len;
|
|
+ GtkTextIter start, end;
|
|
+
|
|
+ gtk_text_buffer_get_bounds (contents, &start, &end);
|
|
+
|
|
+ str = gtk_text_buffer_serialize_rich_text (contents, &start, &end, &len);
|
|
+
|
|
+ gtk_selection_data_set (selection_data,
|
|
+ gdk_atom_intern ("application/x-gtk-text-view-markup", FALSE),
|
|
+ 8, /* bytes */
|
|
+ str, len);
|
|
+ g_free (str);
|
|
+ }
|
|
+ else if (info == TARGET_TEXT_VIEW_RICH_TEXT_FORMAT)
|
|
+ {
|
|
+ gint len;
|
|
+ gchar *format;
|
|
+
|
|
+ format = g_object_get_data (G_OBJECT (contents), "gtk-text-buffer-clipboard-format");
|
|
+ len = format ? strlen (format) : -1;
|
|
+
|
|
+ gtk_selection_data_set (selection_data,
|
|
+ gdk_atom_intern ("application/x-gtk-text-view-rich-text-format", FALSE),
|
|
+ 8, /* bytes */
|
|
+ format, len);
|
|
+ }
|
|
else
|
|
{
|
|
gchar *str;
|
|
@@ -2992,6 +3100,54 @@
|
|
#endif
|
|
|
|
static void
|
|
+clipboard_text_view_markup_received (GtkClipboard *clipboard,
|
|
+ GtkSelectionData *selection_data,
|
|
+ gpointer data)
|
|
+{
|
|
+ ClipboardRequest *request_data = data;
|
|
+ GtkTextIter insert_point;
|
|
+ gboolean retval = TRUE;
|
|
+ GError *error = NULL;
|
|
+ GtkTextBufferPrivate *priv;
|
|
+
|
|
+ priv = GTK_TEXT_BUFFER_GET_PRIVATE (request_data->buffer);
|
|
+
|
|
+ if (selection_data->target ==
|
|
+ gdk_atom_intern ("application/x-gtk-text-view-markup", FALSE))
|
|
+ {
|
|
+ pre_paste_prep (request_data, &insert_point);
|
|
+
|
|
+ if (request_data->interactive)
|
|
+ gtk_text_buffer_begin_user_action (request_data->buffer);
|
|
+
|
|
+ if (!request_data->interactive ||
|
|
+ gtk_text_iter_can_insert (&insert_point, request_data->default_editable))
|
|
+ retval = gtk_text_buffer_deserialize_rich_text (request_data->buffer,
|
|
+ &insert_point,
|
|
+ selection_data->data, selection_data->length,
|
|
+ priv->rich_text_format == NULL, &error);
|
|
+
|
|
+ if (!retval)
|
|
+ {
|
|
+ g_warning ("error pasting: %s\n", error->message);
|
|
+ }
|
|
+
|
|
+ if (request_data->interactive)
|
|
+ gtk_text_buffer_end_user_action (request_data->buffer);
|
|
+
|
|
+ if (retval) {
|
|
+ post_paste_cleanup (request_data);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* Request the text selection instead */
|
|
+ gtk_clipboard_request_text (clipboard,
|
|
+ clipboard_text_received,
|
|
+ data);
|
|
+}
|
|
+
|
|
+static void
|
|
paste_from_buffer (ClipboardRequest *request_data,
|
|
GtkTextBuffer *src_buffer,
|
|
const GtkTextIter *start,
|
|
@@ -3029,6 +3185,35 @@
|
|
g_free (request_data);
|
|
}
|
|
|
|
+static gboolean
|
|
+formats_match (GtkClipboard *clipboard, const gchar *format)
|
|
+{
|
|
+ GtkSelectionData *data;
|
|
+ gchar *tmp;
|
|
+ gboolean retval;
|
|
+
|
|
+ if (!format)
|
|
+ return TRUE;
|
|
+
|
|
+ data = gtk_clipboard_wait_for_contents (clipboard,
|
|
+ gdk_atom_intern ("application/x-gtk-text-view-rich-text-format", FALSE));
|
|
+
|
|
+ if (data->length <= 0)
|
|
+ retval = FALSE;
|
|
+ else
|
|
+ {
|
|
+ tmp = g_strndup (data->data, data->length);
|
|
+
|
|
+ retval = (strcmp (tmp, format) == 0);
|
|
+
|
|
+ g_free (tmp);
|
|
+ }
|
|
+
|
|
+ gtk_selection_data_free (data);
|
|
+
|
|
+ return retval;
|
|
+}
|
|
+
|
|
static void
|
|
clipboard_clipboard_buffer_received (GtkClipboard *clipboard,
|
|
GtkSelectionData *selection_data,
|
|
@@ -3036,6 +3221,7 @@
|
|
{
|
|
ClipboardRequest *request_data = data;
|
|
GtkTextBuffer *src_buffer;
|
|
+ GtkTextBufferPrivate *priv;
|
|
|
|
src_buffer = selection_data_get_buffer (selection_data, request_data);
|
|
|
|
@@ -3059,10 +3245,19 @@
|
|
}
|
|
else
|
|
{
|
|
- /* Request the text selection instead */
|
|
- gtk_clipboard_request_text (clipboard,
|
|
- clipboard_text_received,
|
|
- data);
|
|
+ priv = GTK_TEXT_BUFFER_GET_PRIVATE (request_data->buffer);
|
|
+
|
|
+ if (priv->can_paste_rich_text &&
|
|
+ formats_match (clipboard, priv->rich_text_format))
|
|
+ /* Request markup */
|
|
+ gtk_clipboard_request_contents (clipboard,
|
|
+ gdk_atom_intern ("application/x-gtk-text-view-markup", FALSE),
|
|
+ clipboard_text_view_markup_received, data);
|
|
+ else
|
|
+ /* Request the text selection instead */
|
|
+ gtk_clipboard_request_text (clipboard,
|
|
+ clipboard_text_received,
|
|
+ data);
|
|
}
|
|
}
|
|
|
|
@@ -3071,6 +3266,8 @@
|
|
{ "TEXT", 0, TARGET_TEXT },
|
|
{ "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT },
|
|
{ "UTF8_STRING", 0, TARGET_UTF8_STRING },
|
|
+ { "application/x-gtk-text-view-markup", 0, TARGET_TEXT_VIEW_MARKUP },
|
|
+ { "application/x-gtk-text-view-rich-text-format", 0, TARGET_TEXT_VIEW_RICH_TEXT_FORMAT },
|
|
{ "GTK_TEXT_BUFFER_CONTENTS", 0, TARGET_TEXT_BUFFER_CONTENTS }
|
|
};
|
|
|
|
@@ -3591,6 +3788,68 @@
|
|
}
|
|
}
|
|
|
|
+void
|
|
+gtk_text_buffer_set_can_paste_rich_text (GtkTextBuffer *buffer,
|
|
+ gboolean can_paste_rich_text)
|
|
+{
|
|
+ GtkTextBufferPrivate *priv;
|
|
+
|
|
+ g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
|
|
+
|
|
+ priv = GTK_TEXT_BUFFER_GET_PRIVATE (buffer);
|
|
+
|
|
+ can_paste_rich_text = (can_paste_rich_text != FALSE);
|
|
+
|
|
+ if (priv->can_paste_rich_text != can_paste_rich_text)
|
|
+ {
|
|
+ priv->can_paste_rich_text = can_paste_rich_text;
|
|
+
|
|
+ g_object_notify (G_OBJECT (buffer), "can_paste_rich_text");
|
|
+ }
|
|
+}
|
|
+
|
|
+gboolean
|
|
+gtk_text_buffer_get_can_paste_rich_text (GtkTextBuffer *buffer)
|
|
+{
|
|
+ GtkTextBufferPrivate *priv;
|
|
+
|
|
+ g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
|
|
+
|
|
+ priv = GTK_TEXT_BUFFER_GET_PRIVATE (buffer);
|
|
+
|
|
+ return priv->can_paste_rich_text;
|
|
+}
|
|
+
|
|
+void
|
|
+gtk_text_buffer_set_rich_text_format (GtkTextBuffer *buffer,
|
|
+ const gchar *format)
|
|
+{
|
|
+ gchar *new_format;
|
|
+ GtkTextBufferPrivate *priv;
|
|
+
|
|
+ g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
|
|
+
|
|
+ priv = GTK_TEXT_BUFFER_GET_PRIVATE (buffer);
|
|
+
|
|
+ new_format = g_strdup (format);
|
|
+ g_free (priv->rich_text_format);
|
|
+
|
|
+ priv->rich_text_format = new_format;
|
|
+ g_object_notify (G_OBJECT (buffer), "rich_text_format");
|
|
+}
|
|
+
|
|
+G_CONST_RETURN gchar *
|
|
+gtk_text_buffer_get_rich_text_format (GtkTextBuffer *buffer)
|
|
+{
|
|
+ GtkTextBufferPrivate *priv;
|
|
+
|
|
+ g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
|
|
+
|
|
+ priv = GTK_TEXT_BUFFER_GET_PRIVATE (buffer);
|
|
+
|
|
+ return priv->rich_text_format;
|
|
+}
|
|
+
|
|
/*
|
|
* Logical attribute cache
|
|
*/
|