From b182a275f6ae505198dc9afebd8625737dc70125 Mon Sep 17 00:00:00 2001 From: Brett Nash Date: Wed, 30 Jun 2010 13:20:58 +0000 Subject: [PATCH] Improvements to cut and paste. SVN revision: 49947 --- src/lib/elm_cnp_helper.c | 412 ++++++++++++++++++++++++++++++++++----- src/lib/elm_icon.c | 2 + 2 files changed, 364 insertions(+), 50 deletions(-) diff --git a/src/lib/elm_cnp_helper.c b/src/lib/elm_cnp_helper.c index 0a5dabe42..d59836c5f 100644 --- a/src/lib/elm_cnp_helper.c +++ b/src/lib/elm_cnp_helper.c @@ -14,19 +14,35 @@ # define ARRAYINIT(foo) [foo]= +#define DEBUGON 1 + +#if DEBUGON +#define cnp_debug(x...) printf(__FILE__": " x) +#else +#define cnp_debug(x...) +#endif + enum { - CNP_ATOM_TARGETS = 0, - CNP_ATOM_XEDJE, - CNP_ATOM_text_html_utf8, - CNP_ATOM_text_html, - CNP_ATOM_UTF8STRING, - CNP_ATOM_STRING, - CNP_ATOM_TEXT, - CNP_ATOM_text_plain_utf8, - CNP_ATOM_text_plain, - - CNP_N_ATOMS, + CNP_ATOM_TARGETS = 0, + CNP_ATOM_text_uri, + CNP_ATOM_image_png, + CNP_ATOM_XELM, + CNP_ATOM_text_html_utf8, + CNP_ATOM_text_html, + CNP_ATOM_UTF8STRING, + CNP_ATOM_STRING, + CNP_ATOM_TEXT, + CNP_ATOM_text_plain_utf8, + CNP_ATOM_text_plain, + + CNP_N_ATOMS, +}; +struct pasteimage { + Evas_Object *entry; + const char *tag; + const char *file; + Evas_Object *img; }; @@ -68,10 +84,13 @@ static const struct escapes { static Eina_Bool _elm_cnp_init(void); static Eina_Bool selection_clear(void *udata __UNUSED__, int type, void *event); +//static Eina_Bool selection_request(void *udata __UNUSED__, int type, void *event); static Eina_Bool selection_notify(void *udata __UNUSED__, int type, void *event); static char *remove_tags(const char *p, int *len); static char *mark_up(const char *start, int *lenp); +static Evas_Object *image_provider(void *images, Evas_Object *entry, const char *item); + typedef int (*converter_fn)(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize); @@ -79,41 +98,125 @@ static int targets_converter(char *target, void *data, int size, void **data_ret static int text_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize); static int html_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize); static int edje_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize); +static int uri_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize); +static int png_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize); +/* FIXME: Which way should this be: Notify or response */ typedef int (*response_handler)(struct _elm_cnp_selection *sel, Ecore_X_Event_Selection_Notify *); static int response_handler_targets(struct _elm_cnp_selection *sel, Ecore_X_Event_Selection_Notify *); -static int response_handler_text(struct _elm_cnp_selection *sel, + +typedef int (*notify_handler)(struct _elm_cnp_selection *sel, Ecore_X_Event_Selection_Notify *); +static int notify_handler_targets(struct _elm_cnp_selection *sel, + Ecore_X_Event_Selection_Notify *notify); +static int notify_handler_text(struct _elm_cnp_selection *sel, + Ecore_X_Event_Selection_Notify *notify); +static int notify_handler_png(struct _elm_cnp_selection *sel, + Ecore_X_Event_Selection_Notify *notify); +static int notify_handler_uri(struct _elm_cnp_selection *sel, + Ecore_X_Event_Selection_Notify *notify); + static struct { const char *name; enum _elm_sel_format formats; + /* Called by ecore to do conversion */ converter_fn converter; response_handler response; + notify_handler notify; + /* Atom */ Ecore_X_Atom atom; } atoms[CNP_N_ATOMS] = { - ARRAYINIT(CNP_ATOM_TARGETS) { "TARGETS", - (enum _elm_sel_format)-1, targets_converter, - response_handler_targets, 0 }, - ARRAYINIT(CNP_ATOM_XEDJE) { "application/x-edje-string", - ELM_SEL_MARKUP, edje_converter, NULL, 0}, - ARRAYINIT(CNP_ATOM_text_html_utf8) { "text/html;charset=utf-8", - ELM_SEL_MARKUP, html_converter, NULL, 0 }, - ARRAYINIT(CNP_ATOM_text_html) { "text/html", ELM_SEL_MARKUP, - html_converter, NULL, 0 }, - ARRAYINIT(CNP_ATOM_UTF8STRING) { "UTF8_STRING", ELM_SEL_MARKUP, - text_converter, response_handler_text, 0 }, - ARRAYINIT(CNP_ATOM_STRING) { "STRING", ELM_SEL_MARKUP, - text_converter, response_handler_text, 0 }, - ARRAYINIT(CNP_ATOM_TEXT) { "TEXT", ELM_SEL_MARKUP, - text_converter, response_handler_text, 0 }, - ARRAYINIT(CNP_ATOM_text_plain_utf8) { "text/plain;charset=ut-8", - ELM_SEL_MARKUP, text_converter, - response_handler_text, 0 }, - ARRAYINIT(CNP_ATOM_text_plain) { "text/plain", ELM_SEL_MARKUP, - text_converter, response_handler_text, 0 }, + [CNP_ATOM_TARGETS] = { + "TARGETS", + (enum _elm_sel_format)-1, + targets_converter, + response_handler_targets, + notify_handler_targets, + 0 + }, + [CNP_ATOM_XELM] = { + "application/x-elementary-markup", + ELM_SEL_MARKUP, + edje_converter, + NULL, + NULL, + 0 + }, + [CNP_ATOM_text_uri] = { + "text/uri", + ELM_SEL_MARKUP | ELM_SEL_IMAGE, /* Either images or entries */ + uri_converter, + NULL, + notify_handler_uri, + 0 + }, + [CNP_ATOM_image_png] = { + "image/png", + ELM_SEL_IMAGE | ELM_SEL_IMAGE, + png_converter, + NULL, + notify_handler_png, + 0 + }, + [CNP_ATOM_text_html_utf8] = { + "text/html;charset=utf-8", + ELM_SEL_MARKUP, + html_converter, + NULL, + NULL, + 0 + }, + [CNP_ATOM_text_html] = { + "text/html", + ELM_SEL_MARKUP, + html_converter, + NULL, + NULL, + 0 + }, + [CNP_ATOM_UTF8STRING] = { + "UTF8_STRING", + ELM_SEL_MARKUP, + text_converter, + NULL, + notify_handler_text, + 0 + }, + [CNP_ATOM_STRING] = { + "STRING", + ELM_SEL_MARKUP | ELM_SEL_IMAGE, + text_converter, + NULL, + notify_handler_text, + 0 + }, + [CNP_ATOM_TEXT] = { + "TEXT", + ELM_SEL_MARKUP | ELM_SEL_IMAGE, + text_converter, + NULL, + NULL, + 0 + }, + [CNP_ATOM_text_plain_utf8] = { + "text/plain;charset=ut-8", + ELM_SEL_MARKUP, + text_converter, + NULL, + NULL, + 0 + }, + [CNP_ATOM_text_plain] = { + "text/plain", + ELM_SEL_MARKUP, + text_converter, + NULL, + NULL, + 0 + }, }; static struct _elm_cnp_selection selections[ELM_SEL_MAX] = { @@ -141,7 +244,10 @@ static struct _elm_cnp_selection selections[ELM_SEL_MAX] = { }; static int _elm_cnp_init_count = 0; + /* Gah... who left this out of XAtoms.h */ +static Ecore_X_Atom clipboard_atom; +Eina_List *pastedimages; #endif @@ -154,16 +260,18 @@ elm_selection_set(enum _elm_sel_type selection, Evas_Object *widget, if ((unsigned int)selection >= (unsigned int)ELM_SEL_MAX) return EINA_FALSE; if (!_elm_cnp_init_count) _elm_cnp_init(); - if (!selbuf) return elm_selection_clear(selection, widget); + if (!selbuf && format != ELM_SEL_IMAGE) + return elm_selection_clear(selection, widget); sel = selections + selection; sel->active = 1; sel->widget = widget; - sel->set(elm_win_xwindow_get(elm_widget_top_get(widget)), - &selection, sizeof(int)); + + sel->set(elm_win_xwindow_get(widget),&selection,sizeof(enum _elm_sel_type)); sel->format = format; - sel->selbuf = strdup(selbuf); + sel->selbuf = selbuf ? strdup(selbuf) : NULL; + return EINA_TRUE; #else return EINA_FALSE; @@ -233,10 +341,10 @@ _elm_cnp_init(void){ ecore_x_selection_converter_atom_add(atoms[i].atom, atoms[i].converter); } + clipboard_atom = ecore_x_atom_get("CLIPBOARD"); ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, selection_clear,NULL); ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY,selection_notify,NULL); - return EINA_TRUE; } @@ -261,8 +369,51 @@ selection_clear(void *udata __UNUSED__, int type, void *event){ return ECORE_CALLBACK_PASS_ON; } +#if 0 /** - * Response to a selection notify + * Response to a selection request + */ +static Eina_Bool +selection_request(void *udata __UNUSED__, int type, void *event){ + Ecore_X_Event_Selection_Request *ev = event; + struct _elm_cnp_selection *sel; + int i; +printf("selection request callback: %d\n",ev->selection); +printf("selection request callback: %d\n",ev->target); + + if (ev->selection == clipboard_atom){ + sel = selections + ELM_SEL_CLIPBOARD; + } else if (ev->selection == XA_PRIMARY){ + sel = selections + ELM_SEL_PRIMARY; + } else if (ev->selection == XA_SECONDARY){ + sel = selections + ELM_SEL_SECONDARY; + } else { + return ECORE_CALLBACK_PASS_ON; + } + return ECORE_CALLBACK_PASS_ON; + + for (i = 0 ; i < CNP_N_ATOMS ; i ++) + { + if (ev->target == atoms[i].atom) + { + if (atoms[i].response){ + atoms[i].response(sel, ev); + } else { + printf("Ignored: No handler!\n"); + } + } + } + + return ECORE_CALLBACK_PASS_ON; +} +#endif + + +/* + * Response to a selection notify: + * - So we have asked for the selection list. + * - If it's the targets list, parse it, and fire of what we want, + * else it's the data we want. */ static Eina_Bool selection_notify(void *udata __UNUSED__, int type, void *event){ @@ -270,6 +421,7 @@ selection_notify(void *udata __UNUSED__, int type, void *event){ struct _elm_cnp_selection *sel; int i; + cnp_debug("selection notify callback: %d\n",ev->selection); switch (ev->selection){ case ECORE_X_SELECTION_CLIPBOARD: sel = selections + ELM_SEL_CLIPBOARD; @@ -284,13 +436,15 @@ selection_notify(void *udata __UNUSED__, int type, void *event){ default: return ECORE_CALLBACK_PASS_ON; } + cnp_debug("Target is %s\n",ev->target); for (i = 0 ; i < CNP_N_ATOMS ; i ++) { if (strcmp(ev->target, atoms[i].name) == 0) { - if (atoms[i].response){ - atoms[i].response(sel, ev); + if (atoms[i].notify){ + cnp_debug("Found something: %s\n", atoms[i].name); + atoms[i].notify(sel, ev); } else { printf("Ignored: No handler!\n"); } @@ -301,6 +455,7 @@ selection_notify(void *udata __UNUSED__, int type, void *event){ } + static int targets_converter(char *target, void *data, int size, void **data_ret, int *size_ret, @@ -319,7 +474,7 @@ targets_converter(char *target, void *data, int size, aret = malloc(sizeof(Ecore_X_Atom) * count); for (i = 0, count = 0 ; i < CNP_N_ATOMS ; i ++) - if (sel->format && atoms[i].formats) + if (sel->format & atoms[i].formats) aret[count ++] = atoms[i].atom; if (data_ret) *data_ret = aret; @@ -330,6 +485,51 @@ targets_converter(char *target, void *data, int size, return 1; } +static int +png_converter(char *target, void *data, int size, + void **data_ret, int *size_ret, + Ecore_X_Atom *ttype, int *typesize){ + + return 1; +} + +/* + * Callback to handle a targets response on a selection request: + * So pick the format we'd like; and then request it. + */ +static int +notify_handler_targets(struct _elm_cnp_selection *sel, + Ecore_X_Event_Selection_Notify *notify){ + Ecore_X_Selection_Data_Targets *targets; + Ecore_X_Atom *atomlist; + int i,j; + + targets = notify->data; + atomlist = (Ecore_X_Atom *)(targets->data.data); + + for (j = 1; j < CNP_N_ATOMS ; j ++) + { + cnp_debug("\t%s %d\n",atoms[j].name, atoms[j].atom); + if (!(atoms[j].formats & sel->requestformat)) continue; + for (i = 0 ; i < targets->data.length ; i ++) + { + if (atoms[j].atom == atomlist[i]) + { + cnp_debug("Atom %s matches\n",atoms[j].name); + goto done; + } + } + } + + cnp_debug("Couldn't find anything that matches\n"); + return ECORE_CALLBACK_PASS_ON; + + done: + cnp_debug("Sending request for %s\n",atoms[j].name); + sel->request(elm_win_xwindow_get(sel->requestwidget), atoms[j].name); + + return ECORE_CALLBACK_PASS_ON; +} static int response_handler_targets(struct _elm_cnp_selection *sel, @@ -360,7 +560,7 @@ response_handler_targets(struct _elm_cnp_selection *sel, found: if (j == CNP_N_ATOMS) { - printf("No matching type found\n"); + cnp_debug("No matching type found\n"); return 0; } @@ -371,14 +571,15 @@ response_handler_targets(struct _elm_cnp_selection *sel, return 0; } + static int -response_handler_text(struct _elm_cnp_selection *sel, +notify_handler_text(struct _elm_cnp_selection *sel, Ecore_X_Event_Selection_Notify *notify){ - Ecore_X_Selection_Data_Text *text; + Ecore_X_Selection_Data *data; char *str; - text = notify->data; - str = mark_up(text->text, NULL); + data = notify->data; + str = mark_up((char*)data->data, NULL); elm_entry_entry_insert(sel->requestwidget, str); free(str); @@ -386,6 +587,51 @@ response_handler_text(struct _elm_cnp_selection *sel, } +/** + * So someone is pasting an image into my entry or widget... + */ +static int +notify_handler_uri(struct _elm_cnp_selection *sel, + Ecore_X_Event_Selection_Notify *notify) +{ + Ecore_X_Selection_Data *data; + struct pasteimage *pi; + char entrytag[100]; + char *p; + + data = notify->data; + p = (char *)data->data; + cnp_debug("Got %s\n",p); + if (strncmp(p,"file://",7) != 0){ + cnp_debug("Doesn't start with ;file; %s\n",p); + return 0; + } + + p += strlen("file://"); + + pi = calloc(1,sizeof(struct pasteimage)); + snprintf(entrytag, sizeof(entrytag), "pasteimage-%p",pi); + pi->tag = strdup(entrytag); + pi->file = strndup(p,data->length - strlen("file://")); + + elm_entry_item_provider_append(sel->requestwidget, image_provider, pi); + pastedimages = eina_list_append(pastedimages, pi); + + snprintf(entrytag, sizeof(entrytag), "",pi->tag); + elm_entry_entry_insert(sel->requestwidget, entrytag); + + return 0; +} + +static int +notify_handler_png(struct _elm_cnp_selection *sel, + Ecore_X_Event_Selection_Notify *notify) +{ + cnp_debug("got a png!\n"); + return 0; +} + + static int text_converter(char *target, void *data, int size, void **data_ret, int *size_ret, @@ -397,7 +643,17 @@ text_converter(char *target, void *data, int size, { return 1; } - *data_ret = remove_tags(sel->selbuf, size_ret); + + if (sel->format == ELM_SEL_MARKUP){ + *data_ret = remove_tags(sel->selbuf, size_ret); + } else if (sel->format == ELM_SEL_IMAGE){ + cnp_debug("Image %s\n",evas_object_type_get(sel->widget)); + cnp_debug("Elm type: %s\n",elm_object_widget_type_get(sel->widget)); + evas_object_image_file_get(elm_photocam_internal_image_get(sel->widget), (const char **)data_ret, NULL); + if (!*data_ret) *data_ret = strdup("No file"); + else *data_ret = strdup(*data_ret); + *size_ret = strlen(*data_ret); + } return 1; } @@ -425,6 +681,61 @@ html_converter(char *target, void *data, int size, void **data_ret, int *size_re return 1; } +static int +uri_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize){ + + struct _elm_cnp_selection *sel; + sel = selections + *(int *)data; + cnp_debug("Uri converter\n"); + if (data_ret) *data_ret = strdup(sel->selbuf); + if (size_ret) *size_ret = strlen(sel->selbuf); + return 1; +} + + +/* + * Image paste provide + */ + +/* FIXME: Should add provider for each pated item: Use data to store it + * much easier */ +static Evas_Object * +image_provider(void *images, Evas_Object *entry, const char *item) +{ + struct pasteimage *pi; + Eina_List *l; + + cnp_debug("image provider for %s called\n",item); + EINA_LIST_FOREACH(pastedimages, l, pi) + { + cnp_debug("is it %s?\n",pi->tag); + if (strcmp(pi->tag,item) == 0){ + /* Found it */ + Evas_Object *o; + o = evas_object_image_filled_add(evas_object_evas_get(entry)); + /* FIXME: Handle eets */ + cnp_debug("file is %s (object is %p)\n",pi->file,o); + evas_object_image_file_set(o, pi->file, NULL); + evas_object_show(o); + return o; + } + } + return NULL; +} + +static void +entry_deleted(void *images, Evas *e, Evas_Object *entry, void *unused) +{ + struct pasteimage *pi; + Eina_List *l,*next; + + EINA_LIST_FOREACH_SAFE(pastedimages, l, next, pi) + { + if (pi->entry == entry){ + pastedimages = eina_list_remove_list(pastedimages, l); + } + } +} static char * @@ -433,7 +744,7 @@ remove_tags(const char *p, int *len){ int i; if (!p) return NULL; - q = malloc(strlen(p)); + q = malloc(strlen(p) + 1); if (!q) return NULL; ret = q; @@ -450,10 +761,11 @@ remove_tags(const char *p, int *len){ } else if (*p == '&') { p ++; for (i = 0 ; i < N_ESCAPES ; i ++){ - if (strncmp(p,escapes[i].escape, strlen(escapes[i].escape))){ + if (!strncmp(p,escapes[i].escape, strlen(escapes[i].escape))){ p += strlen(escapes[i].escape); *q = escapes[i].value; q ++; + break; } } if (i == N_ESCAPES) @@ -489,7 +801,7 @@ mark_up(const char *start, int *lenp){ q = ret = malloc(l + 1); - /* Second pass: Count characters */ + /* Second pass: Change characters */ for (p = start ; *p ; ) { for (i = 0 ; i < N_ESCAPES ; i ++) diff --git a/src/lib/elm_icon.c b/src/lib/elm_icon.c index c4ae4b61b..a34a872f7 100644 --- a/src/lib/elm_icon.c +++ b/src/lib/elm_icon.c @@ -288,3 +288,5 @@ elm_icon_prescale_set(Evas_Object *obj, int size) if (!wd) return; _els_smart_icon_scale_size_set(wd->img, size); } + + -- 2.34.1