# 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;
};
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);
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] = {
};
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
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;
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;
}
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){
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;
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");
}
}
+
static int
targets_converter(char *target, void *data, int size,
void **data_ret, int *size_ret,
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;
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,
found:
if (j == CNP_N_ATOMS)
{
- printf("No matching type found\n");
+ cnp_debug("No matching type found\n");
return 0;
}
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);
}
+/**
+ * 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), "<item absize=240x180 href=%s>",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,
{
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;
}
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 *
int i;
if (!p) return NULL;
- q = malloc(strlen(p));
+ q = malloc(strlen(p) + 1);
if (!q) return NULL;
ret = q;
} 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)
q = ret = malloc(l + 1);
- /* Second pass: Count characters */
+ /* Second pass: Change characters */
for (p = start ; *p ; )
{
for (i = 0 ; i < N_ESCAPES ; i ++)