+
+static void clip_receive_text (GtkClipboard *c, const gchar *text, gpointer p)
+{
+ VikLayersPanel *vlp = p;
+ struct LatLon coord;
+ // g_print("got text: %s\n", text);
+ if (clip_parse_latlon(text, &coord)) {
+ clip_add_wp(vlp, &coord);
+ }
+}
+
+static void clip_receive_html ( GtkClipboard *c, GtkSelectionData *sd, gpointer p )
+{
+ VikLayersPanel *vlp = p;
+ gsize r, w;
+ GError *err = NULL;
+ gchar *s, *span;
+ gint tag = 0, i;
+ struct LatLon coord;
+
+ if (sd->length == -1) {
+ return;
+ }
+
+ /* - copying from Mozilla seems to give html in UTF-16. */
+ if (!(s = g_convert ( (gchar *)sd->data, sd->length, "UTF-8", "UTF-16", &r, &w, &err))) {
+ return;
+ }
+ // g_print("html is %d bytes long: %s\n", sd->length, s);
+
+ /* scrape a coordinate pasted from a geocaching.com page: look for a
+ * telltale tag if possible, and then remove tags
+ */
+ if (!(span = g_strstr_len(s, w, "<span id=\"LatLon\">"))) {
+ span = s;
+ }
+ for (i=0; i<strlen(span); i++) {
+ gchar c = span[i];
+ if (c == '<') {
+ tag++;
+ }
+ if (tag>0) {
+ span[i] = ' ';
+ }
+ if (c == '>') {
+ if (tag>0) tag--;
+ }
+ }
+ if (clip_parse_latlon(span, &coord)) {
+ clip_add_wp(vlp, &coord);
+ }
+
+ g_free(s);
+}
+
+/*
+ * deal with various data types a clipboard may hold
+ */
+void clip_receive_targets ( GtkClipboard *c, GdkAtom *a, gint n, gpointer p )
+{
+ VikLayersPanel *vlp = p;
+ gint i;
+
+ /* g_print("got targets\n"); */
+ for (i=0; i<n; i++) {
+ /* g_print(" ""%s""\n", gdk_atom_name(a[i])); */
+ if (!strcmp(gdk_atom_name(a[i]), "text/html")) {
+ gtk_clipboard_request_contents ( c, gdk_atom_intern("text/html", TRUE), clip_receive_html, vlp );
+ break;
+ }
+ if (a[i] == GDK_TARGET_STRING) {
+ gtk_clipboard_request_text ( c, clip_receive_text, vlp );
+ break;
+ }
+ if (!strcmp(gdk_atom_name(a[i]), "application/viking")) {
+ gtk_clipboard_request_contents ( c, gdk_atom_intern("application/viking", TRUE), clip_receive_viking, vlp );
+ break;
+ }
+ }
+}
+
+/*********************************************************************************
+ ** public functions **
+ *********************************************************************************/
+
+/*
+ * make a copy of selected object and associate ourselves with the clipboard
+ */
+void a_clipboard_copy_selected ( VikLayersPanel *vlp )
+{
+ VikLayer *sel = vik_layers_panel_get_selected ( vlp );
+ GtkTreeIter iter;
+ VikClipboardDataType type;
+ guint16 layer_type = 0;
+ gint subtype = 0;
+ guint8 *data = NULL;
+ guint len;
+
+ if ( ! sel )
+ return;
+
+ vik_treeview_get_selected_iter ( sel->vt, &iter );
+ layer_type = sel->type;
+
+ if ( vik_treeview_item_get_type ( sel->vt, &iter ) == VIK_TREEVIEW_TYPE_SUBLAYER ) {
+ type = VIK_CLIPBOARD_DATA_SUBLAYER;
+ if ( vik_layer_get_interface(layer_type)->copy_item) {
+ subtype = vik_treeview_item_get_data(sel->vt, &iter);
+ vik_layer_get_interface(layer_type)->copy_item(sel, subtype, vik_treeview_item_get_pointer(sel->vt, &iter), &data, &len );
+ }
+ }
+ else
+ {
+ gint ilen;
+ type = VIK_CLIPBOARD_DATA_LAYER;
+ vik_layer_marshall ( sel, &data, &ilen );
+ len = ilen;
+ }
+
+ if (data)
+ a_clipboard_copy( type, layer_type, subtype, len, data);
+
+}
+
+void a_clipboard_copy( VikClipboardDataType type, guint16 layer_type, gint subtype, guint len, guint8 * data)
+{
+ vik_clipboard_t * vc = g_malloc(sizeof(*vc) + len);
+ GtkClipboard *c = gtk_clipboard_get ( GDK_SELECTION_CLIPBOARD );
+
+ vc->type = type;
+ vc->layer_type = layer_type;
+ vc->subtype = subtype;
+ vc->len = len;
+ memcpy(vc->data, data, len);
+ g_free(data);
+ vc->pid = getpid();
+ gtk_clipboard_set_with_data ( c, target_table, G_N_ELEMENTS(target_table), clip_get, clip_clear, vc );
+}
+
+/*
+ * to deal with multiple data types, we first request the type of data on the clipboard,
+ * and handle them in the callback
+ */
+gboolean a_clipboard_paste ( VikLayersPanel *vlp )
+{
+ GtkClipboard *c = gtk_clipboard_get ( GDK_SELECTION_CLIPBOARD );
+ gtk_clipboard_request_targets ( c, clip_receive_targets, vlp );
+ return TRUE;
+}
+