diff options
-rw-r--r-- | widgets/text/e-text.c | 125 | ||||
-rw-r--r-- | widgets/text/e-text.h | 5 |
2 files changed, 118 insertions, 12 deletions
diff --git a/widgets/text/e-text.c b/widgets/text/e-text.c index 921bbebf29..8d17c4b004 100644 --- a/widgets/text/e-text.c +++ b/widgets/text/e-text.c @@ -436,6 +436,10 @@ e_text_init (EText *text) text->style = E_FONT_PLAIN; text->allow_newlines = TRUE; + text->last_type_request = -1; + text->last_time_request = 0; + text->queued_requests = NULL; + e_canvas_item_set_reflow_callback(GNOME_CANVAS_ITEM(text), e_text_reflow); } @@ -3765,14 +3769,95 @@ _selection_get (GtkInvisible *invisible, } } +typedef struct { + guint32 time; + GdkAtom selection; +} SelectionAndTime; + +static const char *formats[] = {"UTF8_STRING", "UTF-8", "STRING"}; +#define E_STRING_ATOM 2 +static const int format_count = sizeof (formats) / sizeof (formats[0]); +static GdkAtom atoms[sizeof (formats) / sizeof (formats[0])]; +static int initialized = FALSE; + +static inline void +init_atoms (void) +{ + int type; + if (!initialized) { + for (type = 0; type < format_count; type++) + atoms[type] = gdk_atom_intern (formats[type], FALSE); + initialized = TRUE; + } +} + +static void +e_text_request_paste (EText *text) +{ + GdkAtom format_atom; + GtkWidget *invisible; + int type = text->last_type_request; + + init_atoms (); + + format_atom = GDK_NONE; + + while (format_atom == GDK_NONE) { + type ++; + + if (type >= format_count) { + if (text->queued_requests) { + guint32 *new_time = text->queued_requests->data; + text->queued_requests = g_list_remove_link (text->queued_requests, text->queued_requests); + text->last_time_request = *new_time; + g_free (new_time); + + type = -1; + } else { + text->last_type_request = -1; + text->last_time_request = 0; + return; + } + } + + format_atom = atoms [type]; + } + + /* And request the format target for the required selection */ + invisible = e_text_get_invisible(text); + gtk_selection_convert(invisible, + text->last_selection_request, + format_atom, + text->last_time_request); + + text->last_type_request = type; + return; +} + static void _selection_received (GtkInvisible *invisible, GtkSelectionData *selection_data, guint time, EText *text) { - if (selection_data->length < 0 || selection_data->type != GDK_SELECTION_TYPE_STRING) { + init_atoms (); + if (selection_data->length < 0) { + e_text_request_paste (text); return; + } else if (selection_data->type == atoms[E_STRING_ATOM]) { + ETextEventProcessorCommand command; + char *string; + + string = e_utf8_from_gtk_string_sized (GTK_WIDGET (GNOME_CANVAS_ITEM(text)->canvas), + selection_data->data, + selection_data->length); + command.action = E_TEP_INSERT; + command.position = E_TEP_SELECTION; + command.string = string; + command.value = strlen (string); + command.time = time; + e_text_command(text->tep, &command, text); + g_free (string); } else { ETextEventProcessorCommand command; command.action = E_TEP_INSERT; @@ -3782,6 +3867,33 @@ _selection_received (GtkInvisible *invisible, command.time = time; e_text_command(text->tep, &command, text); } + text->last_type_request = -1; + if (text->queued_requests) { + SelectionAndTime *new_request = text->queued_requests->data; + text->queued_requests = g_list_remove_link (text->queued_requests, text->queued_requests); + text->last_time_request = new_request->time; + text->last_selection_request = new_request->selection; + g_free (new_request); + e_text_request_paste (text); + } +} + + + +static void +e_text_get_selection(EText *text, GdkAtom selection, guint32 time) +{ + if (text->last_type_request == -1) { + text->last_time_request = time; + text->last_selection_request = selection; + e_text_request_paste (text); + } else { + SelectionAndTime *new_request = g_new (SelectionAndTime, 1); + new_request->time = time; + new_request->selection = selection; + /* FIXME: Queue the selection request type as well. */ + text->queued_requests = g_list_append (text->queued_requests, new_request); + } } static void @@ -3810,17 +3922,6 @@ e_text_supply_selection (EText *text, guint time, GdkAtom selection, guchar *dat text->has_selection = successful; } -static void -e_text_get_selection(EText *text, GdkAtom selection, guint32 time) -{ - GtkWidget *invisible; - invisible = e_text_get_invisible(text); - gtk_selection_convert(invisible, - selection, - GDK_SELECTION_TYPE_STRING, - time); -} - #if 0 static void e_text_real_copy_clipboard (EText *text) diff --git a/widgets/text/e-text.h b/widgets/text/e-text.h index 06ac58299e..9a5b997bba 100644 --- a/widgets/text/e-text.h +++ b/widgets/text/e-text.h @@ -224,6 +224,11 @@ struct _EText { gint dbl_timeout; /* Double click timeout */ gint tpl_timeout; /* Triple click timeout */ + + gint last_type_request; /* Last selection type requested. */ + guint32 last_time_request; /* The time of the last selection request. */ + guint32 last_selection_request; /* The time of the last selection request. */ + GList *queued_requests; /* Queued selection requests. */ }; struct _ETextClass { |