diff --git a/kitty/dnd.c b/kitty/dnd.c index 0753de103..2fea78b06 100644 --- a/kitty/dnd.c +++ b/kitty/dnd.c @@ -859,23 +859,27 @@ drop_left_child(Window *w) { void drag_free_offer(Window *w) { - free(ds.mimes); ds.mimes = NULL; free(ds.mimes_buf); ds.mimes_buf = NULL; ds.allowed_operations = 0; ds.offer_being_built = false; + if (ds.items) { + for (size_t i=0; i < ds.num_mimes; i++) free(ds.items[i].optional_data); + free(ds.items); + } + ds.num_mimes = 0; } void drag_add_mimes(Window *w, int allowed_operations, const char *data, size_t sz, bool has_more) { -#define abrt(code) drop_send_error(w, code); drag_free_offer(w); return +#define abrt(code) { drop_send_error(w, code); drag_free_offer(w); return; } if (allowed_operations && ds.offer_being_built) drag_free_offer(w); if (allowed_operations && !ds.allowed_operations) ds.allowed_operations = allowed_operations; if (!ds.allowed_operations) { abrt(EINVAL); } ds.offer_being_built = true; size_t new_sz = ds.bufsz + sz; - if (new_sz > 1024 * 1024) { abrt(EFBIG); } + if (new_sz > 1024 * 1024) abrt(EFBIG); ds.mimes_buf = realloc(ds.mimes_buf, ds.bufsz + sz + 1); - if (!ds.mimes_buf) { abrt(ENOMEM); } + if (!ds.mimes_buf) abrt(ENOMEM); memcpy(ds.mimes_buf + ds.bufsz, data, sz); ds.bufsz = new_sz; ds.mimes_buf[ds.bufsz] = 0; @@ -886,20 +890,16 @@ drag_add_mimes(Window *w, int allowed_operations, const char *data, size_t sz, b *ptr = 0; ptr++; rough_count++; } - ds.mimes = calloc(rough_count + 1, sizeof(void*)); - if (!ds.mimes) { abrt(ENOMEM); } - ds.num_mimes = 0; - // ds.mimes_buf contains MIME strings separated by one or more NULL - // bytes and ends with a NULL byte; collect pointers to non-empty ones. + ds.items = calloc(rough_count + 2, sizeof(ds.items[0])); + if (!ds.items) abrt(ENOMEM); char *p = ds.mimes_buf, *end = ds.mimes_buf + ds.bufsz; + ds.num_mimes = 0; while (p < end) { if (*p) { if (ds.num_mimes >= rough_count + 1) break; - ds.mimes[ds.num_mimes++] = p; + ds.items[ds.num_mimes++].mime_type = p; p += strlen(p) + 1; - } else { - p++; - } + } else p++; } } #undef abrt diff --git a/kitty/state.h b/kitty/state.h index 86879b9db..7bda02504 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -233,6 +233,12 @@ typedef struct DirHandle { uint32_t id; /* handle id, 1-based; 0 = invalid */ } DirHandle; +typedef struct DragSourceItem { + const char *mime_type; + char *optional_data; + size_t data_size; +} DragSourceItem; + typedef struct Window { id_type id; bool visible; @@ -288,7 +294,8 @@ typedef struct Window { struct { bool can_offer; struct { double x, y; monotonic_t at; } initial_left_press; - char *mimes_buf; const char **mimes; size_t num_mimes, bufsz; + char *mimes_buf; size_t num_mimes, bufsz; + DragSourceItem *items; int allowed_operations; bool offer_being_built; } drag_source;