CNP_ATOM_TARGETS = 0,
CNP_ATOM_text_uri,
CNP_ATOM_text_urilist,
+ CNP_ATOM_text_x_vcard,
CNP_ATOM_image_png,
CNP_ATOM_image_jpeg,
CNP_ATOM_XELM,
Evas_Object *requestwidget;
Elm_Sel_Format requestformat;
- int (*set)(Ecore_X_Window, const void *data, int size);
- int (*clear)(void);
+ Elm_Drop_Cb datacb;
+ void *udata;
+
+ Eina_Bool (*set)(Ecore_X_Window, const void *data, int size);
+ Eina_Bool (*clear)(void);
void (*request)(Ecore_X_Window, const char *target);
};
};
#define N_ESCAPES ((int)(sizeof(escapes)/sizeof(escapes[0])))
+struct tmpinfo {
+ int fd;
+ char *filename;
+ void *map;
+ int len;
+};
+
+
+static struct tmpinfo *elm_cnp_tempfile_create(int size);
+static int tmpinfo_free(struct tmpinfo *tmp);
static Eina_Bool _elm_cnp_init(void);
static Eina_Bool selection_clear(void *udata __UNUSED__, int type, void *event);
entry_deleted(void *images, Evas *e, Evas_Object *entry, void *unused);
-typedef int (*converter_fn)(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
+typedef Eina_Bool (*converter_fn)(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
-static int targets_converter(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);
+static Eina_Bool targets_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
+static Eina_Bool text_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
+static Eina_Bool html_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
+static Eina_Bool edje_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
+static Eina_Bool uri_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
+static Eina_Bool png_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
+static Eina_Bool vcard_send(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 *notify);
static int notify_handler_uri(struct _elm_cnp_selection *sel,
Ecore_X_Event_Selection_Notify *notify);
+static int notify_handler_html(struct _elm_cnp_selection *sel,
+ Ecore_X_Event_Selection_Notify *notify);
+static int vcard_receive(struct _elm_cnp_selection *sed,
+ Ecore_X_Event_Selection_Notify *notify);
static struct pasteimage *pasteimage_alloc(const char *file, int pathlen);
static bool pasteimage_append(struct pasteimage *pi, Evas_Object *entry);
notify_handler_uri,
0
},
+ [CNP_ATOM_text_x_vcard] = {
+ "text/x-vcard",
+ ELM_SEL_FORMAT_VCARD,
+ vcard_send, NULL,
+ vcard_receive, 0
+ },
[CNP_ATOM_image_png] = {
"image/png",
ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_IMAGE,
},
[CNP_ATOM_text_html_utf8] = {
"text/html;charset=utf-8",
- ELM_SEL_FORMAT_MARKUP,
+ ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
html_converter,
NULL,
- NULL,
+ notify_handler_html,
0
},
[CNP_ATOM_text_html] = {
"text/html",
- ELM_SEL_FORMAT_MARKUP,
+ ELM_SEL_FORMAT_HTML,
html_converter,
NULL,
- NULL,
+ notify_handler_html, /* No encoding: Webkit only */
0
},
[CNP_ATOM_UTF8STRING] = {
Eina_List *pastedimages;
Eina_List *providedobjs;
+
+/**
+ * Drag & Drop functions
+ */
+struct dropable {
+ Evas_Object *obj;
+ /* FIXME: Cache window */
+ Elm_Sel_Format types;
+ Elm_Drop_Cb dropcb;
+ void *cbdata;
+};
+/* FIXME: Way too many globals */
+Eina_List *drops = NULL;
+Evas_Object *dragwin;
+int _dragx, _dragy;
+Ecore_Event_Handler *handler_pos, *handler_drop, *handler_enter,
+ *handler_status;
+
+struct dropable *cur;
+
+
#endif
/* Stringshared, so I can just compare pointers later */
Eina_Bool
elm_selection_get(Elm_Sel_Type selection, Elm_Sel_Format format,
- Evas_Object *widget)
+ Evas_Object *widget, Elm_Drop_Cb datacb, void *udata)
{
#ifdef HAVE_ELEMENTARY_X
Evas_Object *top;
sel->requestformat = format;
sel->requestwidget = widget;
sel->request(elm_win_xwindow_get(top), ECORE_X_SELECTION_TARGET_TARGETS);
+ sel->datacb = datacb;
+ sel->udata = udata;
return EINA_TRUE;
#else
int i;
if (_elm_cnp_init_count ++) return EINA_TRUE;
- /* FIXME: Handle XCB */
for (i = 0 ; i < CNP_N_ATOMS ; i ++)
{
atoms[i].atom = ecore_x_atom_get(atoms[i].name);
{
if (selections[i].ecore_sel == ev->selection) break;
}
-cnp_debug("selection %d clear\n",i);
+ cnp_debug("selection %d clear\n",i);
/* Not me... Don't care */
if (i == ELM_SEL_MAX) return ECORE_CALLBACK_PASS_ON;
return ECORE_CALLBACK_PASS_ON;
}
-#if 0
-/**
- * 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:
-static int
+static Eina_Bool
targets_converter(char *target __UNUSED__, void *data, int size __UNUSED__,
void **data_ret, int *size_ret,
Ecore_X_Atom *ttype, int *typesize){
Ecore_X_Atom *aret;
struct _elm_cnp_selection *sel;
- if (!data_ret) return -1;
+ if (!data_ret) return EINA_FALSE;
sel = selections + *(int*)data;
if (ttype) *ttype = XA_ATOM;
if (size_ret) *size_ret = count;
- return 1;
+ return EINA_TRUE;
}
-static int
+static Eina_Bool
png_converter(char *target __UNUSED__, void *data, int size,
void **data_ret __UNUSED__, int *size_ret __UNUSED__,
Ecore_X_Atom *ttype __UNUSED__, int *typesize __UNUSED__)
{
cnp_debug("Png converter called\n");
- return 1;
+ return EINA_TRUE;
}
+static Eina_Bool
+vcard_send(char *target __UNUSED__, void *data __UNUSED__, int size __UNUSED__,
+ void **data_ret, int *size_ret,
+ Ecore_X_Atom *ttype __UNUSED__, int *typesize __UNUSED__)
+{
+ struct _elm_cnp_selection *sel;
+
+ cnp_debug("vcard send called\n");
+
+ sel = selections + *(int*)data;
+
+ if (data_ret) *data_ret = strdup(sel->selbuf);
+ if (size_ret) *size_ret = strlen(sel->selbuf);
+
+ return EINA_TRUE;
+}
/*
* Callback to handle a targets response on a selection request:
* So pick the format we'd like; and then request it.
Ecore_X_Atom *atomlist;
Evas_Object *top;
int i,j;
- int prio, selected;
targets = notify->data;
atomlist = (Ecore_X_Atom *)(targets->data.data);
- prio = -1;
- selected = -1;
/* Start from 1: Skip targets */
for (j = 1 ; j < CNP_N_ATOMS ; j ++)
{
if (!strstr(p,".png") && !strstr(p,".jpg"))
{
- /* FIXME: Better test: Load it in evasw & see is probably best */
cnp_debug("No png, ignoring\n");
if (savedtypes.textreq) savedtypes.textreq = 0;
return 0;
return 0;
}
+/**
+ * Just receieved an vcard, either through cut and paste, or dnd.
+ */
+static int
+vcard_receive(struct _elm_cnp_selection *sel,
+ Ecore_X_Event_Selection_Notify *notify)
+{
+ struct dropable *dropable;
+ Eina_List *l;
+ Ecore_X_Selection_Data *data;
+
+ data = notify->data;
+ cnp_debug("vcard receive\n");
+
+ if (sel == selections + ELM_SEL_XDND)
+ {
+ Elm_Selection_Data ddata;
+ cnp_debug("drag & drop\n");
+ /* FIXME: this needs to be generic: Used for all receives */
+ EINA_LIST_FOREACH(drops, l, dropable)
+ if (dropable->obj == sel->requestwidget)
+ break;
+ if (!dropable)
+ {
+ cnp_debug("Unable to find drop object");
+ ecore_x_dnd_send_finished();
+ return 0;
+ }
+ dropable = eina_list_data_get(l);
+ ddata.x = savedtypes.x;
+ ddata.y = savedtypes.y;
+ ddata.format = ELM_SEL_FORMAT_VCARD;
+ ddata.data = data->data;
+ ddata.len = data->length;
+ dropable->dropcb(dropable->cbdata, dropable->obj, &ddata);
+ ecore_x_dnd_send_finished();
+ }
+ else if (sel->datacb)
+ {
+ Elm_Selection_Data ddata;
+ ddata.x = ddata.y = 0;
+ ddata.format = ELM_SEL_FORMAT_IMAGE;
+ ddata.data = data->data;
+ ddata.len = data->length;
+ sel->datacb(sel->udata, sel->widget, &ddata);
+ }
+ else
+ {
+ cnp_debug("Paste request\n");
+ }
+
+ return 0;
+
+}
+
+
static int
-notify_handler_png(struct _elm_cnp_selection *sel __UNUSED__,
- Ecore_X_Event_Selection_Notify *notify __UNUSED__)
+notify_handler_png(struct _elm_cnp_selection *sel,
+ Ecore_X_Event_Selection_Notify *notify)
{
Ecore_X_Selection_Data *data;
- char *fname,*tmppath;
+ struct tmpinfo *tmp;
struct pasteimage *pi;
- int fd,len;
- void *map;
cnp_debug("got a png (or a jpeg)!\n");
data = notify->data;
cnp_debug("Size if %d\n",data->length);
- /* generate tmp name */
- tmppath = getenv("TMP");
- if (!tmppath) tmppath = P_tmpdir;
- if (!tmppath) tmppath = "/tmp";
- len = snprintf(NULL,0,"%s/%sXXXXXX",tmppath, "elmcnpimage-");
- if (len < 0) return 1;
- len ++;
- fname = malloc(len);
- if (!fname) return 1;
- len = snprintf(fname,len,"%s/%sXXXXXX",tmppath, "elmcnpimage-");
-
- fd = mkstemp(fname);
- if (fd < 0)
+ if (sel->datacb)
{
- free(fname);
- return 1;
+ Elm_Selection_Data ddata;
+ ddata.x = ddata.y = 0;
+ ddata.format = ELM_SEL_FORMAT_IMAGE;
+ ddata.data = data->data;
+ ddata.len = data->length;
+ sel->datacb(sel->udata, sel->widget, &ddata);
+ return 0;
}
- if (ftruncate(fd, data->length))
- {
- perror("ftruncate");
- unlink(fname);
- free(fname);
- close(fd);
- }
- map = mmap(NULL,data->length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- if (map == MAP_FAILED)
- {
- perror("mmap");
- unlink(fname);
- free(fname);
- close(fd);
- }
- memcpy(map, data->data, data->length);
- munmap(map,data->length);
- close(fd);
+ /* generate tmp name */
+ tmp = elm_cnp_tempfile_create(data->length);
+
+ memcpy(tmp->map, data->data, data->length);
- /* FIXME: add clean up function */
- // on_exit: file name + pid
- // need pid, as forked children inheret list :-(
+ munmap(tmp->map,data->length);
/* FIXME: Add to paste image data to clean up */
- pi = pasteimage_alloc(fname, data->length);
+ pi = pasteimage_alloc(tmp->filename, data->length);
pasteimage_append(pi, sel->requestwidget);
+ tmpinfo_free(tmp);
+
return 0;
}
+/**
+ * Warning: Generic text/html can';t handle it sanely.
+ * Firefox sends ucs2 (i think).
+ * chrome sends utf8... blerg
+ */
static int
+notify_handler_html(struct _elm_cnp_selection *sel,
+ Ecore_X_Event_Selection_Notify *notify){
+ Ecore_X_Selection_Data *data;
+
+ cnp_debug("Got some HTML: Checking encoding is useful\n");
+ data = notify->data;
+
+ if (sel->datacb)
+ {
+ Elm_Selection_Data ddata;
+ ddata.x = ddata.y = 0;
+ ddata.format = ELM_SEL_FORMAT_HTML;
+ ddata.data = data->data;
+ ddata.len = data->length;
+ sel->datacb(sel->udata, sel->widget, &ddata);
+ return 0;
+ }
+
+
+ cnp_debug("String is %s (%d bytes)\n",data->data,data->length);
+ elm_entry_entry_insert(sel->requestwidget, (char *)data->data);
+
+ return 0;
+}
+
+
+static Eina_Bool
text_converter(char *target __UNUSED__, void *data, int size __UNUSED__,
void **data_ret, int *size_ret,
Ecore_X_Atom *ttype __UNUSED__, int *typesize __UNUSED__)
cnp_debug("text converter\n");
sel = selections + *(int *)data;
- if (!sel->active) return 1;
+ if (!sel->active) return EINA_TRUE;
if (sel->format == ELM_SEL_FORMAT_MARKUP){
*data_ret = remove_tags(sel->selbuf, size_ret);
else *data_ret = strdup(*data_ret);
*size_ret = strlen(*data_ret);
}
- return 1;
+ return EINA_TRUE;
}
-static int
+static Eina_Bool
edje_converter(char *target __UNUSED__, void *data, int size __UNUSED__,
void **data_ret, int *size_ret, Ecore_X_Atom *ttype __UNUSED__,
int *typesize __UNUSED__)
if (data_ret) *data_ret = strdup(sel->selbuf);
if (size_ret) *size_ret = strlen(sel->selbuf);
- return 1;
+ return EINA_TRUE;
}
-static int
+static Eina_Bool
html_converter(char *target __UNUSED__, void *data, int size __UNUSED__,
void **data_ret, int *size_ret, Ecore_X_Atom *ttype __UNUSED__,
int *typesize __UNUSED__)
if (data_ret) *data_ret = strdup(sel->selbuf);
if (size_ret) *size_ret = strlen(sel->selbuf);
- return 1;
+ return EINA_TRUE;
}
-static int
+static Eina_Bool
uri_converter(char *target __UNUSED__, void *data, int size __UNUSED__,
void **data_ret, int *size_ret, Ecore_X_Atom *ttype __UNUSED__,
int *typesize __UNUSED__)
cnp_debug("Uri converter\n");
if (data_ret) *data_ret = strdup(sel->selbuf);
if (size_ret) *size_ret = strlen(sel->selbuf);
- return 1;
+ return EINA_TRUE;
}
int l,i;
const char *p;
char *q,*ret;
- char *endp = NULL;
+ const char *endp = NULL;
if (!start) return NULL;
if (inlen >= 0)
}
-/**
- * Drag & Drop functions
- */
-struct dropable {
- Evas_Object *obj;
- /* FIXME: Cache window */
- Elm_Sel_Format types;
- Elm_Drop_Cb dropcb;
- void *cbdata;
-};
-/* FIXME: Way too many globals */
-Eina_List *drops = NULL;
-Evas_Object *dragwin;
-int _dragx, _dragy;
-Ecore_Event_Handler *handler_pos, *handler_drop, *handler_enter,
- *handler_status;
-
-struct dropable *cur;
-
static Eina_Bool
_dnd_enter(void *data, int etype, void *ev)
{
int i;
/* Skip it */
- if (enter->num_types == 0 || enter->types == NULL) return true;
+ if (!enter || !enter->num_types || !enter->types) return EINA_TRUE;
cnp_debug("Types\n");
savedtypes.ntypes = enter->num_types;
if (savedtypes.types) free(savedtypes.types);
savedtypes.types = malloc(sizeof(char *) * enter->num_types);
+ if (!savedtypes.types)
+ return EINA_FALSE;
+
for (i = 0 ; i < enter->num_types ; i ++)
{
savedtypes.types[i] = eina_stringshare_add(enter->types[i]);
/* FIXME: Find an object and make it current */
- return true;
+ return EINA_TRUE;
}
static Eina_Bool
Eina_List *l;
Ecore_Evas *ee;
Ecore_X_Window xwin;
- Elm_Drop_Data ddata;
+ Elm_Selection_Data ddata;
int x,y,w,h;
int i,j;
cnp_debug("starting drag...\n");
ecore_x_dnd_type_set(xwin, "text/uri-list", 1);
- /* FIXME: just call elm_selection_set */
sel = selections + ELM_SEL_XDND;
sel->active = 1;
sel->widget = obj;
return true;
}
+static struct tmpinfo *
+elm_cnp_tempfile_create(int size){
+ struct tmpinfo *info;
+ char *tmppath;
+ int len;
+
+ info = malloc(sizeof(struct tmpinfo));
+ if (!info) return NULL;
+
+ tmppath = getenv("TMP");
+ if (!tmppath) tmppath = P_tmpdir;
+ if (!tmppath) tmppath = "/tmp";
+ len = snprintf(NULL,0,"%s/%sXXXXXX",tmppath, "elmcnpitem-");
+ if (len < 0)
+ {
+ free(info);
+ return NULL;
+ }
+ len ++;
+ info->filename = malloc(len);
+ if (!info->filename)
+ {
+ free(info);
+ return NULL;
+ }
+ snprintf(info->filename,len,"%s/%sXXXXXX",tmppath, "elmcnpitem-");
+
+ info->fd = mkstemp(info->filename);
+
+#ifdef __linux__
+ {
+ char *tmp;
+ /* And before someone says anything see POSIX 1003.1-2008 page 400 */
+ long pid;
+ pid = (long)getpid();
+ /* Use pid instead of /proc/self: That way if can be passed around */
+ len = snprintf(NULL,0,"/proc/%ld/fd/%d",pid, info->fd);
+ len ++;
+ tmp = malloc(len);
+ if (tmp)
+ {
+ snprintf(tmp,len, "/proc/%ld/fd/%d",pid, info->fd);
+ unlink(info->filename);
+ free(info->filename);
+ info->filename = tmp;
+ }
+ }
+#endif
+
+ printf("filename is %s\n",info->filename);
+ if (size < 1)
+ {
+ /* Set map to NULL and return */
+ info->map = NULL;
+ info->len = 0;
+ return info;
+ }
+
+ /* Map it in */
+ if (ftruncate(info->fd, size))
+ {
+ perror("ftruncate");
+ info->map = NULL;
+ info->len = 0;
+ return info;
+ }
+
+ info->map = mmap(NULL,size, PROT_READ|PROT_WRITE, MAP_SHARED, info->fd, 0);
+ if (info->map == MAP_FAILED)
+ {
+ perror("mmap");
+ info->map = NULL;
+ info->len = 0;
+ }
+
+ return info;
+}
+static int
+tmpinfo_free(struct tmpinfo *info)
+{
+ if (!info) return 0;
+ free(info->filename);
+ free(info);
+ return 0;
+}
#else
/* Stubs for windows */