ui/gtk/dnd.c

changeset 431
bb7da585debc
parent 394
bedd499b640d
child 440
7c4b9cba09ca
--- a/ui/gtk/dnd.c	Sun May 23 09:44:43 2021 +0200
+++ b/ui/gtk/dnd.c	Sat Jan 04 16:38:48 2025 +0100
@@ -31,20 +31,21 @@
 #include <string.h>
 
 #include "dnd.h"
-#include <ucx/buffer.h>
+#include <cx/buffer.h>
+#include <cx/array_list.h>
 
 #ifdef UI_GTK2LEGACY
 static gboolean selection_data_set_uris(GtkSelectionData *selection_data, char **uris) {
-    UcxBuffer *buf = ucx_buffer_new(NULL, 1024, UCX_BUFFER_AUTOEXTEND);
+    CxBuffer *buf = cxBufferCreate(NULL, 1024, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND);
     char *uri;
     int i = 0;
     while((uri = uris[i]) != NULL) {
-        ucx_buffer_puts(buf, uri);
-        ucx_buffer_puts(buf, "\r\n");
+        cxBufferPutString(buf, uri);
+        cxBufferPutString(buf, "\r\n");
     }
     GdkAtom type = gdk_atom_intern("text/uri-list", FALSE);
     gtk_selection_data_set(selection_data, type, 8, (guchar*)buf->space, buf->pos);
-    ucx_buffer_free(buf);
+    cxBufferFree(buf);
     return TRUE;
 }
 static char** selection_data_get_uris(GtkSelectionData *selection_data) {
@@ -55,6 +56,7 @@
 #define gtk_selection_data_get_uris selection_data_get_uris
 #endif
 
+/*
 void ui_selection_settext(UiSelection *sel, char *str, int len) {
     // TODO: handle error?
     gtk_selection_data_set_text(sel->data, str, len);
@@ -99,3 +101,195 @@
     }
     return NULL;
 }
+*/
+
+#if GTK_MAJOR_VERSION >= 4
+
+void ui_selection_settext(UiDnD *sel, char *str, int len) {
+    if(!sel->providers) {
+        return;
+    }
+    
+    if(len == -1) {
+        len = strlen(str);
+    }
+    GBytes *bytes = g_bytes_new(str, len);
+    GdkContentProvider *provider = gdk_content_provider_new_for_bytes("text/plain;charset=utf-8", bytes);
+    g_bytes_unref(bytes);
+    
+    cxListAdd(sel->providers, &provider);
+}
+
+void ui_selection_seturis(UiDnD *sel, char **uris, int nelm) {
+    if(!sel->providers) {
+        return;
+    }
+    
+    GFile **files = calloc(nelm, sizeof(GFile*));
+    for(int i=0;i<nelm;i++) {
+        GFile *file = uris[i][0] == '/' ? g_file_new_for_path(uris[i]) : g_file_new_for_uri(uris[i]);
+        files[i] = file;
+    }
+    GdkFileList *list = gdk_file_list_new_from_array(files, nelm);
+    
+    GdkContentProvider *provider = gdk_content_provider_new_typed(GDK_TYPE_FILE_LIST, list);
+    cxListAdd(sel->providers, &provider);
+    
+    g_slist_free_full ((GSList*)list, g_object_unref);
+    free(files);
+}
+
+char* ui_selection_gettext(UiDnD *sel) {
+    if(!sel->value) {
+        return NULL;
+    }
+    
+    if(G_VALUE_HOLDS(sel->value, G_TYPE_STRING)) {
+        const char *str = g_value_get_string(sel->value);
+        return str ? strdup(str) : NULL;
+    }
+    
+    return NULL;
+}
+
+UiFileList ui_selection_geturis(UiDnD *sel) {
+    if(!sel->value) {
+        return (UiFileList){NULL,0};
+    }
+    
+    if(G_VALUE_HOLDS(sel->value, GDK_TYPE_FILE_LIST)) {
+        GSList *list = g_value_get_boxed(sel->value);
+        if(!list) {
+            return (UiFileList){NULL,0};
+        }
+        guint size = g_slist_length(list);
+        
+        UiFileList flist;
+        flist.nfiles = size;
+        flist.files = calloc(size, sizeof(char*));
+        int i=0;
+        while(list) {
+            GFile *file = list->data;
+            char *uri = g_file_get_uri(file);
+            flist.files[i++] = strdup(uri);
+            g_free(uri);
+            list = list->next;
+        }
+        return flist;
+    }
+    return (UiFileList){NULL,0};
+}
+
+
+UiDnD* ui_create_dnd(void) {
+    UiDnD *dnd = malloc(sizeof(UiDnD));
+    memset(dnd, 0, sizeof(UiDnD));
+    dnd->providers = cxArrayListCreateSimple(sizeof(void*), 16);
+    dnd->selected_action = 0;
+    dnd->delete = FALSE;
+    return dnd;
+}
+
+void ui_dnd_free(UiDnD *dnd) {
+    cxListDestroy(dnd->providers);
+    free(dnd);
+}
+
+UiDnDAction ui_dnd_result(UiDnD *dnd) {
+    switch(dnd->selected_action) {
+        case 0: return UI_DND_ACTION_NONE;
+        case GDK_ACTION_COPY: return UI_DND_ACTION_COPY;
+        case GDK_ACTION_MOVE: return UI_DND_ACTION_MOVE;
+        case GDK_ACTION_LINK: return UI_DND_ACTION_LINK;
+        default: break;
+    }
+    return UI_DND_ACTION_CUSTOM;
+}
+
+#else
+
+void ui_selection_settext(UiDnD *sel, char *str, int len) {
+    gtk_selection_data_set_text(sel->data, str, len);
+}
+
+void ui_selection_seturis(UiDnD *sel, char **uris, int nelm) {
+    char **uriarray = calloc(nelm+1, sizeof(char*));
+    for(int i=0;i<nelm;i++) {
+        uriarray[i] = uris[i];
+    }
+    uriarray[nelm] = NULL;
+    gtk_selection_data_set_uris(sel->data, uriarray);
+    free(uriarray);
+}
+
+char* ui_selection_gettext(UiDnD *sel) {
+    if(!sel->data) {
+        return NULL;
+    }
+    
+    guchar *text = gtk_selection_data_get_text(sel->data);
+    if(text) {
+        char *textcp = strdup((char*)text);
+        g_free(text);
+        return textcp;
+    }
+    return NULL;
+}
+
+UiFileList ui_selection_geturis(UiDnD *sel) {
+    if(!sel->data) {
+        return (UiFileList){NULL,0};
+    }
+    
+    gchar **uris = gtk_selection_data_get_uris(sel->data);
+    if(uris) {
+        size_t al = 32;
+        char **array = malloc(al * sizeof(char*));
+        size_t i = 0;
+        while(uris[i] != NULL) {
+            if(i >= al) {
+                al *= 2;
+                array = realloc(array, al * sizeof(char*));
+            }
+            array[i] = strdup((char*)uris[i]);
+            i++;
+        }
+        g_strfreev(uris);
+        return (UiFileList){array,i};
+    }
+    
+    return (UiFileList){NULL,0};
+}
+
+UiDnDAction ui_dnd_result(UiDnD *dnd) {
+    switch(dnd->selected_action) {
+        case 0: return UI_DND_ACTION_NONE;
+        case GDK_ACTION_COPY: return UI_DND_ACTION_COPY;
+        case GDK_ACTION_MOVE: return UI_DND_ACTION_MOVE;
+        case GDK_ACTION_LINK: return UI_DND_ACTION_LINK;
+        default: break;
+    }
+    return UI_DND_ACTION_CUSTOM;
+}
+
+
+UiDnD* ui_create_dnd(void) {
+    UiDnD *dnd = malloc(sizeof(UiDnD));
+    memset(dnd, 0, sizeof(UiDnD));
+    return dnd;
+}
+
+void ui_dnd_free(UiDnD *dnd) {
+    free(dnd);
+}
+
+#endif
+
+UiBool ui_dnd_need_delete(UiDnD *dnd) {
+    return dnd->delete;
+}
+
+void ui_dnd_accept(UiDnD *dnd, UiBool accept) {
+    dnd->accept = accept;
+}
+

mercurial