X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkselection.c;h=b76090be200499f7ef0b1e96d4157ee2b7d7d56a;hb=a8698a24c7a53fe4d34211053529f14747f7ce5f;hp=139a4567a9ea578b30a8e4809e9b89c604dabff6;hpb=af89d145f72d824ee7ff757faca012550c50f349;p=~andy%2Fgtk diff --git a/gtk/gtkselection.c b/gtk/gtkselection.c index 139a4567a..b76090be2 100644 --- a/gtk/gtkselection.c +++ b/gtk/gtkselection.c @@ -58,6 +58,7 @@ #include "gtkmain.h" #include "gtkselection.h" +#include "gtktextbufferrichtext.h" #include "gtkintl.h" #include "gdk-pixbuf/gdk-pixbuf.h" @@ -151,8 +152,8 @@ struct _GtkRetrievalInfo /* Local Functions */ static void gtk_selection_init (void); -static gint gtk_selection_incr_timeout (GtkIncrInfo *info); -static gint gtk_selection_retrieval_timeout (GtkRetrievalInfo *info); +static gboolean gtk_selection_incr_timeout (GtkIncrInfo *info); +static gboolean gtk_selection_retrieval_timeout (GtkRetrievalInfo *info); static void gtk_selection_retrieval_report (GtkRetrievalInfo *info, GdkAtom type, gint format, @@ -213,13 +214,16 @@ gtk_target_list_new (const GtkTargetEntry *targets, * * Increases the reference count of a #GtkTargetList by one. * + * Return value: the passed in #GtkTargetList. **/ -void +GtkTargetList * gtk_target_list_ref (GtkTargetList *list) { - g_return_if_fail (list != NULL); + g_return_val_if_fail (list != NULL, NULL); list->ref_count++; + + return list; } /** @@ -338,6 +342,45 @@ gtk_target_list_add_text_targets (GtkTargetList *list, gtk_target_list_add (list, text_plain_atom, 0, info); } +/** + * gtk_target_list_add_rich_text_targets: + * @list: a #GtkTargetList + * @info: an ID that will be passed back to the application + * @deserializable: if %TRUE, then deserializable rich text formats + * will be added, serializable formats otherwise. + * @buffer: a #GtkTextBuffer. + * + * Appends the rich text targets registered with + * gtk_text_buffer_register_serialize_format() or + * gtk_text_buffer_register_deserialize_format() to the target list. All + * targets are added with the same @info. + * + * Since: 2.10 + **/ +void +gtk_target_list_add_rich_text_targets (GtkTargetList *list, + guint info, + gboolean deserializable, + GtkTextBuffer *buffer) +{ + GdkAtom *atoms; + gint n_atoms; + gint i; + + g_return_if_fail (list != NULL); + g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer)); + + if (deserializable) + atoms = gtk_text_buffer_get_deserialize_formats (buffer, &n_atoms); + else + atoms = gtk_text_buffer_get_serialize_formats (buffer, &n_atoms); + + for (i = 0; i < n_atoms; i++) + gtk_target_list_add (list, atoms[i], 0, info); + + g_free (atoms); +} + /** * gtk_target_list_add_image_targets: * @list: a #GtkTargetList @@ -514,6 +557,72 @@ gtk_target_list_find (GtkTargetList *list, return FALSE; } +/** + * gtk_target_table_new_from_list: + * @list: a #GtkTargetList + * @n_targets: return location for the number ot targets in the table + * + * This function creates an #GtkTargetEntry array that contains the + * same targets as the passed %list. The returned table is newly + * allocated and should be freed using gtk_target_table_free() when no + * longer needed. + * + * Return value: the new table. + * + * Since: 2.10 + **/ +GtkTargetEntry * +gtk_target_table_new_from_list (GtkTargetList *list, + gint *n_targets) +{ + GtkTargetEntry *targets; + GList *tmp_list; + gint i; + + g_return_val_if_fail (list != NULL, NULL); + g_return_val_if_fail (n_targets != NULL, NULL); + + *n_targets = g_list_length (list->list); + targets = g_new0 (GtkTargetEntry, *n_targets); + + for (i = 0, tmp_list = list->list; + i < *n_targets; + i++, tmp_list = g_list_next (tmp_list)) + { + GtkTargetPair *pair = tmp_list->data; + + targets[i].target = gdk_atom_name (pair->target); + targets[i].flags = pair->flags; + targets[i].info = pair->info; + } + + return targets; +} + +/** + * gtk_target_table_free: + * @targets: a #GtkTargetEntry array + * @n_targets: the number of entries in the array + * + * This function frees a target table as returned by + * gtk_target_table_new_from_list() + * + * Since: 2.10 + **/ +void +gtk_target_table_free (GtkTargetEntry *targets, + gint n_targets) +{ + gint i; + + g_return_if_fail (targets == NULL || n_targets > 0); + + for (i = 0; i < n_targets; i++) + g_free (targets[i].target); + + g_free (targets); +} + /** * gtk_selection_owner_set_for_display: * @display: the #Gdkdisplay where the selection is set @@ -981,7 +1090,8 @@ gtk_selection_convert (GtkWidget *widget, current_retrievals = g_list_append (current_retrievals, info); gdk_selection_convert (widget->window, selection, target, time_); - g_timeout_add (1000, (GSourceFunc) gtk_selection_retrieval_timeout, info); + gdk_threads_add_timeout (1000, + (GSourceFunc) gtk_selection_retrieval_timeout, info); return TRUE; } @@ -1006,8 +1116,7 @@ gtk_selection_data_set (GtkSelectionData *selection_data, const guchar *data, gint length) { - if (selection_data->data) - g_free (selection_data->data); + g_free (selection_data->data); selection_data->type = type; selection_data->format = format; @@ -1166,8 +1275,8 @@ selection_set_text_plain (GtkSelectionData *selection_data, if (!result) { - g_warning ("Error converting from UTF-8 to %s: %s", - charset, error->message); + g_warning ("Error converting from %s to %s: %s", + "UTF-8", charset, error->message); g_error_free (error); return FALSE; @@ -1201,14 +1310,14 @@ selection_get_text_plain (GtkSelectionData *selection_data) { gchar *tmp = str; str = g_convert_with_fallback (tmp, len, - charset, "UTF-8", + "UTF-8", charset, NULL, NULL, &len, &error); g_free (tmp); if (!str) { - g_warning ("Error converting from %s to UTF-8: %s", - charset, error->message); + g_warning ("Error converting from %s to %s: %s", + charset, "UTF-8", error->message); g_error_free (error); return NULL; @@ -1216,7 +1325,8 @@ selection_get_text_plain (GtkSelectionData *selection_data) } else if (!g_utf8_validate (str, -1, NULL)) { - g_warning ("Error converting from text/plain;charset=utf-8 to UTF-8"); + g_warning ("Error converting from %s to %s: %s", + "text/plain;charset=utf-8", "UTF-8", "invalid UTF-8"); g_free (str); return NULL; @@ -1416,16 +1526,16 @@ gtk_selection_data_get_pixbuf (GtkSelectionData *selection_data) { loader = gdk_pixbuf_loader_new (); - if (gdk_pixbuf_loader_write (loader, - selection_data->data, - selection_data->length, - NULL)) - result = gdk_pixbuf_loader_get_pixbuf (loader); + gdk_pixbuf_loader_write (loader, + selection_data->data, + selection_data->length, + NULL); + gdk_pixbuf_loader_close (loader, NULL); + result = gdk_pixbuf_loader_get_pixbuf (loader); if (result) g_object_ref (result); - gdk_pixbuf_loader_close (loader, NULL); g_object_unref (loader); } @@ -1477,6 +1587,8 @@ gtk_selection_data_set_uris (GtkSelectionData *selection_data, text_uri_list_atom, 8, (guchar *)result, length); + g_free (result); + return TRUE; } } @@ -1508,7 +1620,6 @@ gtk_selection_data_get_uris (GtkSelectionData *selection_data) selection_data->type == text_uri_list_atom) { gchar **list; - gint i; gint count = gdk_text_property_to_utf8_list_for_display (selection_data->display, utf8_atom, selection_data->format, @@ -1518,9 +1629,7 @@ gtk_selection_data_get_uris (GtkSelectionData *selection_data) if (count > 0) result = g_uri_list_extract_uris (list[0]); - for (i = 1; i < count; i++) - g_free (list[i]); - g_free (list); + g_strfreev (list); } return result; @@ -1591,6 +1700,9 @@ gtk_targets_include_text (GdkAtom *targets, /* Keep in sync with gtk_target_list_add_text_targets() */ + + init_atoms (); + for (i = 0; i < n_targets; i++) { if (targets[i] == utf8_atom || @@ -1608,7 +1720,56 @@ gtk_targets_include_text (GdkAtom *targets, return result; } - + +/** + * gtk_targets_include_rich_text: + * @targets: an array of #GdkAtoms + * @n_targets: the length of @targets + * @buffer: a #GtkTextBuffer + * + * Determines if any of the targets in @targets can be used to + * provide rich text. + * + * Return value: %TRUE if @targets include a suitable target for rich text, + * otherwise %FALSE. + * + * Since: 2.10 + **/ +gboolean +gtk_targets_include_rich_text (GdkAtom *targets, + gint n_targets, + GtkTextBuffer *buffer) +{ + GdkAtom *rich_targets; + gint n_rich_targets; + gint i, j; + gboolean result = FALSE; + + g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE); + + init_atoms (); + + rich_targets = gtk_text_buffer_get_deserialize_formats (buffer, + &n_rich_targets); + + for (i = 0; i < n_targets; i++) + { + for (j = 0; j < n_rich_targets; j++) + { + if (targets[i] == rich_targets[j]) + { + result = TRUE; + goto done; + } + } + } + + done: + g_free (rich_targets); + + return result; +} + /** * gtk_selection_data_targets_include_text: * @selection_data: a #GtkSelectionData object @@ -1638,6 +1799,42 @@ gtk_selection_data_targets_include_text (GtkSelectionData *selection_data) return result; } +/** + * gtk_selection_data_targets_include_rich_text: + * @selection_data: a #GtkSelectionData object + * @buffer: a #GtkTextBuffer + * + * Given a #GtkSelectionData object holding a list of targets, + * determines if any of the targets in @targets can be used to + * provide rich text. + * + * Return value: %TRUE if @selection_data holds a list of targets, + * and a suitable target for rich text is included, + * otherwise %FALSE. + * + * Since: 2.10 + **/ +gboolean +gtk_selection_data_targets_include_rich_text (GtkSelectionData *selection_data, + GtkTextBuffer *buffer) +{ + GdkAtom *targets; + gint n_targets; + gboolean result = FALSE; + + g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE); + + init_atoms (); + + if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets)) + { + result = gtk_targets_include_rich_text (targets, n_targets, buffer); + g_free (targets); + } + + return result; +} + /** * gtk_targets_include_image: * @targets: an array of #GdkAtoms @@ -1738,6 +1935,9 @@ gtk_targets_include_uri (GdkAtom *targets, /* Keep in sync with gtk_target_list_add_uri_targets() */ + + init_atoms (); + for (i = 0; i < n_targets; i++) { if (targets[i] == text_uri_list_atom) @@ -1813,7 +2013,7 @@ gtk_selection_init (void) * * Since: 2.2 * - * Deprecated: Instead of calling this function, chain up from + * Deprecated: 2.4: Instead of calling this function, chain up from * your selection_clear_event handler. Calling this function * from any other context is illegal. **/ @@ -1931,6 +2131,7 @@ _gtk_selection_request (GtkWidget *widget, event->time); g_free (mult_atoms); g_free (info); + gdk_error_trap_pop (); return TRUE; } gdk_error_trap_pop (); @@ -1953,6 +2154,8 @@ _gtk_selection_request (GtkWidget *widget, info->conversions[i].property = gdk_x11_xatom_to_atom_for_display (display, ((glong *)mult_atoms)[2*i + 1]); } + + g_free (mult_atoms); } else #endif @@ -1965,6 +2168,8 @@ _gtk_selection_request (GtkWidget *widget, info->conversions[i].target = ((GdkAtom *)mult_atoms)[2*i]; info->conversions[i].property = ((GdkAtom *)mult_atoms)[2*i+1]; } + + g_free (mult_atoms); } } else /* only a single conversion */ @@ -2058,7 +2263,7 @@ _gtk_selection_request (GtkWidget *widget, gdk_window_get_events (info->requestor) | GDK_PROPERTY_CHANGE_MASK); current_incrs = g_list_append (current_incrs, info); - g_timeout_add (1000, (GSourceFunc) gtk_selection_incr_timeout, info); + gdk_threads_add_timeout (1000, (GSourceFunc) gtk_selection_incr_timeout, info); } /* If it was a MULTIPLE request, set the property to indicate which @@ -2247,8 +2452,6 @@ gtk_selection_incr_timeout (GtkIncrInfo *info) GList *tmp_list; gboolean retval; - GDK_THREADS_ENTER (); - /* Determine if retrieval has finished by checking if it still in list of pending retrievals */ @@ -2284,8 +2487,6 @@ gtk_selection_incr_timeout (GtkIncrInfo *info) retval = TRUE; /* timeout will happen again */ } - GDK_THREADS_LEAVE (); - return retval; } @@ -2491,14 +2692,12 @@ _gtk_selection_property_notify (GtkWidget *widget, * results: *************************************************************/ -static gint +static gboolean gtk_selection_retrieval_timeout (GtkRetrievalInfo *info) { GList *tmp_list; gboolean retval; - GDK_THREADS_ENTER (); - /* Determine if retrieval has finished by checking if it still in list of pending retrievals */ @@ -2532,8 +2731,6 @@ gtk_selection_retrieval_timeout (GtkRetrievalInfo *info) retval = TRUE; /* timeout will happen again */ } - GDK_THREADS_LEAVE (); - return retval; } @@ -2735,8 +2932,7 @@ gtk_selection_data_free (GtkSelectionData *data) { g_return_if_fail (data != NULL); - if (data->data) - g_free (data->data); + g_free (data->data); g_free (data); } @@ -2754,6 +2950,19 @@ gtk_selection_data_get_type (void) return our_type; } +GType +gtk_target_list_get_type (void) +{ + static GType our_type = 0; + + if (our_type == 0) + our_type = g_boxed_type_register_static (I_("GtkTargetList"), + (GBoxedCopyFunc) gtk_target_list_ref, + (GBoxedFreeFunc) gtk_target_list_unref); + + return our_type; +} + static int gtk_selection_bytes_per_item (gint format) {