diff options
author | Matthias Clasen <maclas@gmx.de> | 2004-07-17 04:58:02 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2004-07-17 04:58:02 +0000 |
commit | fb881018542b3b567177d0a1063d9169b17bab48 (patch) | |
tree | 29a44f0aab7f4b3bc18b41f11eaf1df401c43695 /gtk/gtkselection.c | |
parent | a5638e82e8f5bef394166fecd997752204299155 (diff) | |
download | gtk+-fb881018542b3b567177d0a1063d9169b17bab48.tar.gz |
Support text/plain selection target (#55117, Owen Taylor)
Sat Jul 17 00:48:27 2004 Matthias Clasen <maclas@gmx.de>
Support text/plain selection target (#55117, Owen Taylor)
* gtk/gtkselection.h:
* gtk/gtkdnd.h:
* gtk/gtkselection.c (gtk_target_list_add_text_targets):
* gtk/gtkdnd.c (gtk_drag_dest_add_text_targets):
* gtk/gtkdnd.c (gtk_drag_source_add_text_targets): New
functions to facilitate handling of text targets.
* gtk/gtkentry.c:
* gtk/gtktextview.c: Use the new text target handling
functions instead of hardwiring the list of supported
text targets everywhere.
* gtk/gtkselection.c (gtk_selection_data_get_text):
(gtk_selection_data_set_text):
Support the targets text/plain, text/plain?charset=utf-8
and text/plain?charset=<LOCALE-CHARSET> as outlined in
#55117:
For text/plain send only ASCII, but accept 8-bit text
and treat it as ISO-8859-1 as specified by the Xdnd spec.
Always send CRLF terminators. Accept either and convert
into the native terminator for the platform.
Diffstat (limited to 'gtk/gtkselection.c')
-rw-r--r-- | gtk/gtkselection.c | 245 |
1 files changed, 223 insertions, 22 deletions
diff --git a/gtk/gtkselection.c b/gtk/gtkselection.c index a33e63a25c..ad52fe619e 100644 --- a/gtk/gtkselection.c +++ b/gtk/gtkselection.c @@ -222,9 +222,9 @@ gtk_target_list_unref (GtkTargetList *list) void gtk_target_list_add (GtkTargetList *list, - GdkAtom target, - guint flags, - guint info) + GdkAtom target, + guint flags, + guint info) { GtkTargetPair *pair; @@ -238,6 +238,61 @@ gtk_target_list_add (GtkTargetList *list, list->list = g_list_append (list->list, pair); } +static GdkAtom utf8_atom; +static GdkAtom text_atom; +static GdkAtom ctext_atom; +static GdkAtom text_plain_atom; +static GdkAtom text_plain_utf8_atom; +static GdkAtom text_plain_locale_atom; + +static void +init_atoms (void) +{ + gchar *tmp; + const gchar *charset; + + if (!utf8_atom) + { + utf8_atom = gdk_atom_intern ("UTF8_STRING", FALSE); + text_atom = gdk_atom_intern ("TEXT", FALSE); + ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE); + text_plain_atom = gdk_atom_intern ("text/plain", FALSE); + text_plain_utf8_atom = gdk_atom_intern ("text/plain;charset=utf-8", FALSE); + g_get_charset (&charset); + tmp = g_strdup_printf ("text/plain;charset=%s", charset); + text_plain_locale_atom = gdk_atom_intern (tmp, FALSE); + g_free (tmp); + } +} + +/** + * gtk_target_list_add_text_targets: + * @list: a #GtkTargetList + * + * Adds the text targets supported by #GtkSelection to + * the target list. The targets are added with both flags + * and info being zero. + * + * Since: 2.6 + **/ +void +gtk_target_list_add_text_targets (GtkTargetList *list) +{ + g_return_if_fail (list != NULL); + + init_atoms (); + + /* Keep in sync with gtk_selection_data_targets_include_text() + */ + gtk_target_list_add (list, utf8_atom, 0, 0); + gtk_target_list_add (list, ctext_atom, 0, 0); + gtk_target_list_add (list, text_atom, 0, 0); + gtk_target_list_add (list, GDK_TARGET_STRING, 0, 0); + gtk_target_list_add (list, text_plain_utf8_atom, 0, 0); + gtk_target_list_add (list, text_plain_locale_atom, 0, 0); + gtk_target_list_add (list, text_plain_atom, 0, 0); +} + void gtk_target_list_add_table (GtkTargetList *list, const GtkTargetEntry *targets, @@ -803,21 +858,6 @@ gtk_selection_data_set (GtkSelectionData *selection_data, selection_data->length = length; } -static GdkAtom utf8_atom; -static GdkAtom text_atom; -static GdkAtom ctext_atom; - -static void -init_atoms (void) -{ - if (!utf8_atom) - { - utf8_atom = gdk_atom_intern ("UTF8_STRING", FALSE); - text_atom = gdk_atom_intern ("TEXT", FALSE); - ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE); - } -} - static gboolean selection_set_string (GtkSelectionData *selection_data, const gchar *str, @@ -867,6 +907,149 @@ selection_set_compound_text (GtkSelectionData *selection_data, return result; } +/* Normalize \r and \n into \r\n + */ +static gchar * +normalize_to_crlf (const gchar *str, + gint len) +{ + GString *result = g_string_sized_new (len); + const gchar *p = str; + + while (1) + { + if (*p == '\n') + g_string_append_c (result, '\r'); + + if (*p == '\r') + { + g_string_append_c (result, *p); + p++; + if (*p != '\n') + g_string_append_c (result, '\n'); + } + + if (*p == '\0') + break; + + g_string_append_c (result, *p); + p++; + } + + return g_string_free (result, FALSE); +} + +/* Normalize \r and \r\n into \n + */ +static gchar * +normalize_to_lf (gchar *str, + gint len) +{ + GString *result = g_string_sized_new (len); + const gchar *p = str; + + while (1) + { + if (*p == '\r') + { + p++; + if (*p != '\n') + g_string_append_c (result, '\n'); + } + + if (*p == '\0') + break; + + g_string_append_c (result, *p); + p++; + } + + return g_string_free (result, FALSE); +} + +static gboolean +selection_set_text_plain (GtkSelectionData *selection_data, + const gchar *str, + gint len) +{ + const gchar *charset = NULL; + gchar *result; + GError *error = NULL; + + result = normalize_to_crlf (str, len); + if (selection_data->target == text_plain_atom) + charset = "ASCII"; + else if (selection_data->target == text_plain_locale_atom) + g_get_charset (&charset); + + if (charset) + { + gchar *tmp = result; + result = g_convert_with_fallback (tmp, -1, + charset, "UTF-8", + NULL, NULL, NULL, &error); + g_free (tmp); + } + + if (!result) + { + g_warning ("Error converting from UTF-8 to %s: %s", + charset, error->message); + g_error_free (error); + + return FALSE; + } + + gtk_selection_data_set (selection_data, + selection_data->target, + 8, result, strlen (result)); + g_free (result); + + return TRUE; +} + +static gchar * +selection_get_text_plain (GtkSelectionData *selection_data) +{ + const gchar *charset = NULL; + gchar *str, *result; + gint len; + GError *error = NULL; + + str = g_strdup (selection_data->data); + len = selection_data->length; + + if (selection_data->type == text_plain_atom) + charset = "ISO-8859-1"; + else if (selection_data->type == text_plain_locale_atom) + g_get_charset (&charset); + + if (charset) + { + gchar *tmp = str; + str = g_convert_with_fallback (tmp, len, + charset, "UTF-8", + NULL, NULL, &len, &error); + g_free (tmp); + } + + if (!str) + { + g_warning ("Error converting from %s to UTF-8: %s", + charset, error->message); + g_error_free (error); + + return NULL; + } + + + result = normalize_to_lf (str, len); + + g_free (str); + + return result; +} + /** * gtk_selection_data_set_text: * @selection_data: a #GtkSelectionData @@ -909,6 +1092,12 @@ gtk_selection_data_set_text (GtkSelectionData *selection_data, else if (selection_data->target == text_atom) return selection_set_string (selection_data, str, len); } + else if (selection_data->target == text_plain_atom || + selection_data->target == text_plain_utf8_atom || + selection_data->target == text_plain_locale_atom) + { + return selection_set_text_plain (selection_data, str, len); + } return FALSE; } @@ -951,6 +1140,13 @@ gtk_selection_data_get_text (GtkSelectionData *selection_data) g_free (list[i]); g_free (list); } + else if (selection_data->length >= 0 && + (selection_data->type == text_plain_atom || + selection_data->type == text_plain_utf8_atom || + selection_data->type == text_plain_locale_atom)) + { + result = selection_get_text_plain (selection_data); + } return result; } @@ -1016,14 +1212,19 @@ gtk_selection_data_targets_include_text (GtkSelectionData *selection_data) gint i; gboolean result = FALSE; + init_atoms (); + if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets)) { for (i=0; i < n_targets; i++) { - if (targets[i] == gdk_atom_intern ("STRING", FALSE) || - targets[i] == gdk_atom_intern ("TEXT", FALSE) || - targets[i] == gdk_atom_intern ("COMPOUND_TEXT", FALSE) || - targets[i] == gdk_atom_intern ("UTF8_STRING", FALSE)) + if (targets[i] == utf8_atom || + targets[i] == text_atom || + targets[i] == GDK_TARGET_STRING || + targets[i] == ctext_atom || + targets[i] == text_plain_atom || + targets[i] == text_plain_utf8_atom || + targets[i] == text_plain_locale_atom) result = TRUE; } |