UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2017 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 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 // TODO: implement 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 void ui_selection_settext(UiSelection *sel, char *str, int len) { 61 // TODO: handle error? 62 gtk_selection_data_set_text(sel->data, str, len); 63 } 64 65 void ui_selection_seturis(UiSelection *sel, char **uris, int nelm) { 66 char **uriarray = calloc(nelm+1, sizeof(char*)); 67 for(int i=0;i<nelm;i++) { 68 uriarray[i] = uris[i]; 69 } 70 uriarray[nelm] = NULL; 71 gtk_selection_data_set_uris(sel->data, uriarray); 72 } 73 74 char* ui_selection_gettext(UiSelection *sel) { 75 guchar *text = gtk_selection_data_get_text(sel->data); 76 if(text) { 77 char *textcp = strdup((char*)text); 78 g_free(text); 79 return textcp; 80 } 81 return NULL; 82 } 83 84 char** ui_selection_geturis(UiSelection *sel, size_t *nelm) { 85 gchar **uris = gtk_selection_data_get_uris(sel->data); 86 if(uris) { 87 size_t al = 32; 88 char **array = malloc(al * sizeof(char*)); 89 size_t i = 0; 90 while(uris[i] != NULL) { 91 if(i >= al) { 92 al *= 2; 93 array = realloc(array, al * sizeof(char*)); 94 } 95 array[i] = strdup((char*)uris[i]); 96 i++; 97 } 98 *nelm = i; 99 g_strfreev(uris); 100 return array; 101 } 102 return NULL; 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