#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dnd.h"
#include <cx/buffer.h>
#include <cx/array_list.h>
#ifdef UI_GTK2LEGACY
static gboolean selection_data_set_uris(GtkSelectionData *selection_data,
char **uris) {
CxBuffer *buf = cxBufferCreate(
NULL,
1024, cxDefaultAllocator,
CX_BUFFER_FREE_CONTENTS|
CX_BUFFER_AUTO_EXTEND);
char *uri;
int i =
0;
while((uri = uris[i]) !=
NULL) {
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);
cxBufferFree(buf);
return TRUE;
}
static char** selection_data_get_uris(GtkSelectionData *selection_data) {
return NULL;
}
#define gtk_selection_data_set_uris selection_data_set_uris
#define gtk_selection_data_get_uris selection_data_get_uris
#endif
#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;
}