1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "dnd.h"
34 #include <cx/buffer.h>
35 #include <cx/array_list.h>
36
37 #ifdef UI_GTK2LEGACY
38 static gboolean selection_data_set_uris(GtkSelectionData *selection_data,
char **uris) {
39 CxBuffer *buf = cxBufferCreate(
NULL,
1024, cxDefaultAllocator,
CX_BUFFER_FREE_CONTENTS|
CX_BUFFER_AUTO_EXTEND);
40 char *uri;
41 int i =
0;
42 while((uri = uris[i]) !=
NULL) {
43 cxBufferPutString(buf, uri);
44 cxBufferPutString(buf,
"\r\n");
45 }
46 GdkAtom type = gdk_atom_intern(
"text/uri-list",
FALSE);
47 gtk_selection_data_set(selection_data, type,
8, (guchar*)buf->space, buf->pos);
48 cxBufferFree(buf);
49 return TRUE;
50 }
51 static char** selection_data_get_uris(GtkSelectionData *selection_data) {
52
53 return NULL;
54 }
55 #define gtk_selection_data_set_uris selection_data_set_uris
56 #define gtk_selection_data_get_uris selection_data_get_uris
57 #endif
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 #if GTK_MAJOR_VERSION >=
4
107
108 void ui_selection_settext(UiDnD *sel,
char *str,
int len) {
109 if(!sel->providers) {
110 return;
111 }
112
113 if(len == -
1) {
114 len = strlen(str);
115 }
116 GBytes *bytes = g_bytes_new(str, len);
117 GdkContentProvider *provider = gdk_content_provider_new_for_bytes(
"text/plain;charset=utf-8", bytes);
118 g_bytes_unref(bytes);
119
120 cxListAdd(sel->providers, &provider);
121 }
122
123 void ui_selection_seturis(UiDnD *sel,
char **uris,
int nelm) {
124 if(!sel->providers) {
125 return;
126 }
127
128 GFile **files = calloc(nelm,
sizeof(GFile*));
129 for(
int i=
0;i<nelm;i++) {
130 GFile *file = uris[i][
0] ==
'/' ? g_file_new_for_path(uris[i]) : g_file_new_for_uri(uris[i]);
131 files[i] = file;
132 }
133 GdkFileList *list = gdk_file_list_new_from_array(files, nelm);
134
135 GdkContentProvider *provider = gdk_content_provider_new_typed(
GDK_TYPE_FILE_LIST, list);
136 cxListAdd(sel->providers, &provider);
137
138 g_slist_free_full ((GSList*)list, g_object_unref);
139 free(files);
140 }
141
142 char* ui_selection_gettext(UiDnD *sel) {
143 if(!sel->value) {
144 return NULL;
145 }
146
147 if(
G_VALUE_HOLDS(sel->value,
G_TYPE_STRING)) {
148 const char *str = g_value_get_string(sel->value);
149 return str ? strdup(str) :
NULL;
150 }
151
152 return NULL;
153 }
154
155 UiFileList ui_selection_geturis(UiDnD *sel) {
156 if(!sel->value) {
157 return (UiFileList){
NULL,
0};
158 }
159
160 if(
G_VALUE_HOLDS(sel->value,
GDK_TYPE_FILE_LIST)) {
161 GSList *list = g_value_get_boxed(sel->value);
162 if(!list) {
163 return (UiFileList){
NULL,
0};
164 }
165 guint size = g_slist_length(list);
166
167 UiFileList flist;
168 flist.nfiles = size;
169 flist.files = calloc(size,
sizeof(
char*));
170 int i=
0;
171 while(list) {
172 GFile *file = list->data;
173 char *uri = g_file_get_uri(file);
174 flist.files[i++] = strdup(uri);
175 g_free(uri);
176 list = list->next;
177 }
178 return flist;
179 }
180 return (UiFileList){
NULL,
0};
181 }
182
183
184 UiDnD* ui_create_dnd(
void) {
185 UiDnD *dnd = malloc(
sizeof(UiDnD));
186 memset(dnd,
0,
sizeof(UiDnD));
187 dnd->providers = cxArrayListCreateSimple(
sizeof(
void*),
16);
188 dnd->selected_action =
0;
189 dnd->delete =
FALSE;
190 return dnd;
191 }
192
193 void ui_dnd_free(UiDnD *dnd) {
194 cxListDestroy(dnd->providers);
195 free(dnd);
196 }
197
198 UiDnDAction ui_dnd_result(UiDnD *dnd) {
199 switch(dnd->selected_action) {
200 case 0:
return UI_DND_ACTION_NONE;
201 case GDK_ACTION_COPY:
return UI_DND_ACTION_COPY;
202 case GDK_ACTION_MOVE:
return UI_DND_ACTION_MOVE;
203 case GDK_ACTION_LINK:
return UI_DND_ACTION_LINK;
204 default:
break;
205 }
206 return UI_DND_ACTION_CUSTOM;
207 }
208
209 #else
210
211 void ui_selection_settext(UiDnD *sel,
char *str,
int len) {
212 gtk_selection_data_set_text(sel->data, str, len);
213 }
214
215 void ui_selection_seturis(UiDnD *sel,
char **uris,
int nelm) {
216 char **uriarray = calloc(nelm+
1,
sizeof(
char*));
217 for(
int i=
0;i<nelm;i++) {
218 uriarray[i] = uris[i];
219 }
220 uriarray[nelm] =
NULL;
221 gtk_selection_data_set_uris(sel->data, uriarray);
222 free(uriarray);
223 }
224
225 char* ui_selection_gettext(UiDnD *sel) {
226 if(!sel->data) {
227 return NULL;
228 }
229
230 guchar *text = gtk_selection_data_get_text(sel->data);
231 if(text) {
232 char *textcp = strdup((
char*)text);
233 g_free(text);
234 return textcp;
235 }
236 return NULL;
237 }
238
239 UiFileList ui_selection_geturis(UiDnD *sel) {
240 if(!sel->data) {
241 return (UiFileList){
NULL,
0};
242 }
243
244 gchar **uris = gtk_selection_data_get_uris(sel->data);
245 if(uris) {
246 size_t al =
32;
247 char **array = malloc(al *
sizeof(
char*));
248 size_t i =
0;
249 while(uris[i] !=
NULL) {
250 if(i >= al) {
251 al *=
2;
252 array = realloc(array, al *
sizeof(
char*));
253 }
254 array[i] = strdup((
char*)uris[i]);
255 i++;
256 }
257 g_strfreev(uris);
258 return (UiFileList){array,i};
259 }
260
261 return (UiFileList){
NULL,
0};
262 }
263
264 UiDnDAction ui_dnd_result(UiDnD *dnd) {
265 switch(dnd->selected_action) {
266 case 0:
return UI_DND_ACTION_NONE;
267 case GDK_ACTION_COPY:
return UI_DND_ACTION_COPY;
268 case GDK_ACTION_MOVE:
return UI_DND_ACTION_MOVE;
269 case GDK_ACTION_LINK:
return UI_DND_ACTION_LINK;
270 default:
break;
271 }
272 return UI_DND_ACTION_CUSTOM;
273 }
274
275
276 UiDnD* ui_create_dnd(
void) {
277 UiDnD *dnd = malloc(
sizeof(UiDnD));
278 memset(dnd,
0,
sizeof(UiDnD));
279 return dnd;
280 }
281
282 void ui_dnd_free(UiDnD *dnd) {
283 free(dnd);
284 }
285
286 #endif
287
288 UiBool ui_dnd_need_delete(UiDnD *dnd) {
289 return dnd->delete;
290 }
291
292 void ui_dnd_accept(UiDnD *dnd, UiBool accept) {
293 dnd->accept = accept;
294 }
295
296