29 #include <stdio.h> |
29 #include <stdio.h> |
30 #include <stdlib.h> |
30 #include <stdlib.h> |
31 #include <string.h> |
31 #include <string.h> |
32 |
32 |
33 #include "dnd.h" |
33 #include "dnd.h" |
34 #include <ucx/buffer.h> |
34 #include <cx/buffer.h> |
|
35 #include <cx/array_list.h> |
35 |
36 |
36 #ifdef UI_GTK2LEGACY |
37 #ifdef UI_GTK2LEGACY |
37 static gboolean selection_data_set_uris(GtkSelectionData *selection_data, char **uris) { |
38 static gboolean selection_data_set_uris(GtkSelectionData *selection_data, char **uris) { |
38 UcxBuffer *buf = ucx_buffer_new(NULL, 1024, UCX_BUFFER_AUTOEXTEND); |
39 CxBuffer *buf = cxBufferCreate(NULL, 1024, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND); |
39 char *uri; |
40 char *uri; |
40 int i = 0; |
41 int i = 0; |
41 while((uri = uris[i]) != NULL) { |
42 while((uri = uris[i]) != NULL) { |
42 ucx_buffer_puts(buf, uri); |
43 cxBufferPutString(buf, uri); |
43 ucx_buffer_puts(buf, "\r\n"); |
44 cxBufferPutString(buf, "\r\n"); |
44 } |
45 } |
45 GdkAtom type = gdk_atom_intern("text/uri-list", FALSE); |
46 GdkAtom type = gdk_atom_intern("text/uri-list", FALSE); |
46 gtk_selection_data_set(selection_data, type, 8, (guchar*)buf->space, buf->pos); |
47 gtk_selection_data_set(selection_data, type, 8, (guchar*)buf->space, buf->pos); |
47 ucx_buffer_free(buf); |
48 cxBufferFree(buf); |
48 return TRUE; |
49 return TRUE; |
49 } |
50 } |
50 static char** selection_data_get_uris(GtkSelectionData *selection_data) { |
51 static char** selection_data_get_uris(GtkSelectionData *selection_data) { |
51 // TODO: implement |
52 // TODO: implement |
52 return NULL; |
53 return NULL; |
53 } |
54 } |
54 #define gtk_selection_data_set_uris selection_data_set_uris |
55 #define gtk_selection_data_set_uris selection_data_set_uris |
55 #define gtk_selection_data_get_uris selection_data_get_uris |
56 #define gtk_selection_data_get_uris selection_data_get_uris |
56 #endif |
57 #endif |
57 |
58 |
|
59 /* |
58 void ui_selection_settext(UiSelection *sel, char *str, int len) { |
60 void ui_selection_settext(UiSelection *sel, char *str, int len) { |
59 // TODO: handle error? |
61 // TODO: handle error? |
60 gtk_selection_data_set_text(sel->data, str, len); |
62 gtk_selection_data_set_text(sel->data, str, len); |
61 } |
63 } |
62 |
64 |
97 g_strfreev(uris); |
99 g_strfreev(uris); |
98 return array; |
100 return array; |
99 } |
101 } |
100 return NULL; |
102 return NULL; |
101 } |
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 |