elementary/map - map supports language,changed
[framework/uifw/elementary.git] / src / lib / elm_cnp.c
1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4 #include <Elementary.h>
5 #include "elm_priv.h"
6 #ifdef HAVE_MMAN_H
7 # include <sys/mman.h>
8 #endif
9
10 // common stuff
11 enum
12 {
13    CNP_ATOM_TARGETS = 0,
14    CNP_ATOM_ATOM,
15    CNP_ATOM_LISTING_ATOMS = CNP_ATOM_ATOM,
16    CNP_ATOM_text_uri,
17    CNP_ATOM_text_urilist,
18    CNP_ATOM_text_x_vcard,
19    CNP_ATOM_image_png,
20    CNP_ATOM_image_jpeg,
21    CNP_ATOM_image_bmp,
22    CNP_ATOM_image_gif,
23    CNP_ATOM_image_tiff,
24    CNP_ATOM_image_svg,
25    CNP_ATOM_image_xpm,
26    CNP_ATOM_image_tga,
27    CNP_ATOM_image_ppm,
28    CNP_ATOM_XELM,
29 //   CNP_ATOM_text_html_utf8,
30 //   CNP_ATOM_text_html,
31    CNP_ATOM_UTF8STRING,
32    CNP_ATOM_STRING,
33    CNP_ATOM_COMPOUND_TEXT,
34    CNP_ATOM_TEXT,
35    CNP_ATOM_text_plain_utf8,
36    CNP_ATOM_text_plain,
37
38    CNP_N_ATOMS,
39 };
40
41 typedef struct _Tmp_Info      Tmp_Info;
42 typedef struct _Saved_Type    Saved_Type;
43 typedef struct _Cnp_Escape    Cnp_Escape;
44 typedef struct _Dropable      Dropable;
45
46 struct _Tmp_Info
47 {
48    char *filename;
49    void *map;
50    int   fd;
51    int   len;
52 };
53
54 struct _Saved_Type
55 {
56    const char  **types;
57    char         *imgfile;
58    int           ntypes;
59    int           x, y;
60    Eina_Bool     textreq: 1;
61 };
62
63 struct _Cnp_Escape
64 {
65    const char *escape;
66    const char *value;
67 };
68
69 struct _Dropable
70 {
71    Evas_Object    *obj;
72    /* FIXME: Cache window */
73    Elm_Sel_Format  types;
74    Elm_Drop_Cb     dropcb;
75    void           *cbdata;
76 };
77
78 static int _elm_cnp_init_count = 0;
79 /* Stringshared, so I can just compare pointers later */
80 static const char *text_uri;
81 /* Data for DND in progress */
82 static Saved_Type savedtypes =  { NULL, NULL, 0, 0, 0, EINA_FALSE };
83
84 /* TODO BUG: should NEVER have these as globals! They should be per context (window). */
85 static void (*dragdonecb) (void *data, Evas_Object *obj) = NULL;
86 static void *dragdonedata = NULL;
87
88 /* Drag & Drop functions */
89 /* FIXME: Way too many globals */
90 static Eina_List *drops = NULL;
91 static Evas_Object *dragwin = NULL;
92 static int _dragx = 0, _dragy = 0;
93 static Ecore_Event_Handler *handler_pos = NULL;
94 static Ecore_Event_Handler *handler_drop = NULL;
95 static Ecore_Event_Handler *handler_enter = NULL;
96 static Ecore_Event_Handler *handler_status = NULL;
97
98 static Tmp_Info  *_tempfile_new      (int size);
99 static int        _tmpinfo_free      (Tmp_Info *tmp);
100 static Eina_Bool  _pasteimage_append (char *file, Evas_Object *entry);
101 static void       _entry_insert_filter(Evas_Object *entry, char *str); // TIZEN ONLY
102
103 //#define DEBUGON 1
104 #ifdef DEBUGON
105 # define cnp_debug(x...) fprintf(stderr, __FILE__": " x)
106 #else
107 # define cnp_debug(x...) do { } while (0)
108 #endif
109
110 // x11 specific stuff
111 ////////////////////////////////////////////////////////////////////////////
112 #ifdef HAVE_ELEMENTARY_X
113 #define ARRAYINIT(foo)  [foo] =
114
115 typedef struct _X11_Cnp_Selection X11_Cnp_Selection;
116 typedef struct _X11_Cnp_Atom      X11_Cnp_Atom;
117
118 typedef Eina_Bool (*X11_Converter_Fn_Cb)     (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
119 typedef int       (*X11_Response_Handler_Cb) (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *);
120 typedef int       (*X11_Notify_Handler_Cb)   (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *);
121
122 struct _X11_Cnp_Selection
123 {
124    const char        *debug;
125    Evas_Object       *widget;
126    char              *selbuf;
127    Evas_Object       *requestwidget;
128    void              *udata;
129    Elm_Sel_Format     requestformat;
130    Elm_Drop_Cb        datacb;
131    Eina_Bool        (*set)     (Ecore_X_Window, const void *data, int size);
132    Eina_Bool        (*clear)   (void);
133    void             (*request) (Ecore_X_Window, const char *target);
134    Elm_Selection_Loss_Cb  loss_cb;
135    void                  *loss_data;
136
137    Elm_Sel_Format     format;
138    Ecore_X_Selection  ecore_sel;
139    Ecore_X_Window     xwin;
140
141    Eina_Bool          active : 1;
142 };
143
144 struct _X11_Cnp_Atom
145 {
146    const char              *name;
147    Elm_Sel_Format           formats;
148    /* Called by ecore to do conversion */
149    X11_Converter_Fn_Cb      converter;
150    X11_Response_Handler_Cb  response;
151    X11_Notify_Handler_Cb    notify;
152    /* Atom */
153    Ecore_X_Atom             atom;
154 };
155
156 static void           _x11_sel_obj_del              (void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
157 static void           _x11_sel_obj_del2             (void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
158 static Eina_Bool      _x11_selection_clear          (void *udata __UNUSED__, int type, void *event);
159 static Eina_Bool      _x11_selection_notify         (void *udata __UNUSED__, int type, void *event);
160 static Eina_Bool      _x11_targets_converter        (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
161 static Eina_Bool      _x11_text_converter           (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
162 static Eina_Bool      _x11_general_converter        (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
163 static Eina_Bool      _x11_image_converter          (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
164 static Eina_Bool      _x11_vcard_send               (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
165 //TIZEN ONLY : static Eina_Bool      _x11_is_uri_type_data         (X11_Cnp_Selection *sel __UNUSED__, Ecore_X_Event_Selection_Notify *notify);
166 static int            _x11_response_handler_targets (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *);
167 static int            _x11_notify_handler_targets   (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
168 static int            _x11_notify_handler_text      (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
169 static int            _x11_notify_handler_image     (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
170 static int            _x11_notify_handler_uri       (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
171 //static int            _x11_notify_handler_html      (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
172 static int            _x11_notify_handler_edje      (X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify); // TIZEN ONLY
173 static int            _x11_vcard_receive            (X11_Cnp_Selection *sed, Ecore_X_Event_Selection_Notify *notify);
174 static Eina_Bool      _x11_dnd_enter                (void *data __UNUSED__, int etype __UNUSED__, void *ev);
175 static Eina_Bool      _x11_dnd_drop                 (void *data __UNUSED__, int etype __UNUSED__, void *ev);
176 static Eina_Bool      _x11_dnd_position             (void *data __UNUSED__, int etype __UNUSED__, void *ev);
177 static Eina_Bool      _x11_dnd_status               (void *data __UNUSED__, int etype __UNUSED__, void *ev);
178 static void           _x11_drag_mouse_up            (void *un __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *data);
179 static void           _x11_drag_move                (void *data __UNUSED__, Ecore_X_Xdnd_Position *pos);
180
181 static Ecore_X_Window _x11_elm_widget_xwin_get           (const Evas_Object *obj);
182
183 static Eina_Bool _x11_elm_cnp_init                       (void);
184 static Eina_Bool _x11_elm_cnp_selection_set              (Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen);
185 static void      _x11_elm_cnp_selection_loss_callback_set(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection, Elm_Selection_Loss_Cb func, const void *data);
186 static Eina_Bool _x11_elm_object_cnp_selection_clear     (Evas_Object *obj, Elm_Sel_Type selection);
187 static Eina_Bool _x11_elm_cnp_selection_get              (Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata);
188 static Eina_Bool _x11_elm_drop_target_add                (Evas_Object *obj, Elm_Sel_Type format, Elm_Drop_Cb dropcb, void *cbdata);
189 static Eina_Bool _x11_elm_drop_target_del                (Evas_Object *obj);
190 static Eina_Bool _x11_elm_selection_selection_has_owner  (Evas_Object *obj __UNUSED__);
191
192 static X11_Cnp_Atom _x11_atoms[CNP_N_ATOMS] = {
193    [CNP_ATOM_TARGETS] = {
194       "TARGETS",
195       ELM_SEL_FORMAT_TARGETS,
196       _x11_targets_converter,
197       _x11_response_handler_targets,
198       _x11_notify_handler_targets,
199       0
200    },
201    [CNP_ATOM_ATOM] = {
202       "ATOM", // for opera browser
203       ELM_SEL_FORMAT_TARGETS,
204       _x11_targets_converter,
205       _x11_response_handler_targets,
206       _x11_notify_handler_targets,
207       0
208    },
209    [CNP_ATOM_XELM] =  {
210       "application/x-elementary-markup",
211       ELM_SEL_FORMAT_MARKUP,
212       _x11_general_converter,
213       NULL,
214       //NULL,                    // TIZEN ONLY
215       _x11_notify_handler_edje,  // TIZEN ONLY
216       0
217    },
218    [CNP_ATOM_text_uri] = {
219       "text/uri",
220       //ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_IMAGE, /* Either images or entries */   // TIZEN ONLY
221       ELM_SEL_FORMAT_IMAGE,      // TIZEN ONLY
222       _x11_general_converter,
223       NULL,
224       _x11_notify_handler_uri,
225       0
226    },
227    [CNP_ATOM_text_urilist] = {
228       "text/uri-list",
229       ELM_SEL_FORMAT_IMAGE,
230       _x11_general_converter,
231       NULL,
232       _x11_notify_handler_uri,
233       0
234    },
235    [CNP_ATOM_text_x_vcard] = {
236       "text/x-vcard",
237       ELM_SEL_FORMAT_VCARD,
238       _x11_vcard_send, NULL,
239       _x11_vcard_receive, 0
240    },
241    [CNP_ATOM_image_png] = {
242       "image/png",
243       ELM_SEL_FORMAT_IMAGE,
244       _x11_image_converter,
245       NULL,
246       _x11_notify_handler_image,
247       0
248    },
249    [CNP_ATOM_image_jpeg] = {
250       "image/jpeg",
251       ELM_SEL_FORMAT_IMAGE,
252       _x11_image_converter,
253       NULL,
254       _x11_notify_handler_image,/* Raw image data is the same */
255       0
256    },
257    [CNP_ATOM_image_bmp] = {
258       "image/x-ms-bmp",
259       ELM_SEL_FORMAT_IMAGE,
260       _x11_image_converter,
261       NULL,
262       _x11_notify_handler_image,/* Raw image data is the same */
263       0
264    },
265    [CNP_ATOM_image_gif] = {
266       "image/gif",
267       ELM_SEL_FORMAT_IMAGE,
268       _x11_image_converter,
269       NULL,
270       _x11_notify_handler_image,/* Raw image data is the same */
271       0
272    },
273    [CNP_ATOM_image_tiff] = {
274       "image/tiff",
275       ELM_SEL_FORMAT_IMAGE,
276       _x11_image_converter,
277       NULL,
278       _x11_notify_handler_image,/* Raw image data is the same */
279       0
280    },
281    [CNP_ATOM_image_svg] = {
282       "image/svg+xml",
283       ELM_SEL_FORMAT_IMAGE,
284       _x11_image_converter,
285       NULL,
286       _x11_notify_handler_image,/* Raw image data is the same */
287       0
288    },
289    [CNP_ATOM_image_xpm] = {
290       "image/x-xpixmap",
291       ELM_SEL_FORMAT_IMAGE,
292       _x11_image_converter,
293       NULL,
294       _x11_notify_handler_image,/* Raw image data is the same */
295       0
296    },
297    [CNP_ATOM_image_tga] = {
298       "image/x-tga",
299       ELM_SEL_FORMAT_IMAGE,
300       _x11_image_converter,
301       NULL,
302       _x11_notify_handler_image,/* Raw image data is the same */
303       0
304    },
305    [CNP_ATOM_image_ppm] = {
306       "image/x-portable-pixmap",
307       ELM_SEL_FORMAT_IMAGE,
308       _x11_image_converter,
309       NULL,
310       _x11_notify_handler_image,/* Raw image data is the same */
311       0
312    },
313 /*   
314    [CNP_ATOM_text_html_utf8] = {
315       "text/html;charset=utf-8",
316       ELM_SEL_FORMAT_HTML,
317       _x11_general_converter,
318       NULL,
319       _x11_notify_handler_html,
320       0
321    },
322    [CNP_ATOM_text_html] = {
323       "text/html",
324       ELM_SEL_FORMAT_HTML,
325       _x11_general_converter,
326       NULL,
327       _x11_notify_handler_html, // No encoding: Webkit only
328       0
329    },
330  */
331    [CNP_ATOM_UTF8STRING] = {
332       "UTF8_STRING",
333       ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
334       _x11_text_converter,
335       NULL,
336       _x11_notify_handler_text,
337       0
338    },
339    [CNP_ATOM_STRING] = {
340       "STRING",
341       ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
342       _x11_text_converter,
343       NULL,
344       _x11_notify_handler_text,
345       0
346    },
347    [CNP_ATOM_COMPOUND_TEXT] = {
348       "COMPOUND_TEXT",
349       ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
350       _x11_text_converter,
351       NULL,
352       NULL,
353       0
354    },
355    [CNP_ATOM_TEXT] = {
356       "TEXT",
357       ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
358       _x11_text_converter,
359       NULL,
360       NULL,
361       0
362    },
363    [CNP_ATOM_text_plain_utf8] = {
364       "text/plain;charset=utf-8",
365       ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
366       _x11_text_converter,
367       NULL,
368       NULL,
369       0
370    },
371    [CNP_ATOM_text_plain] = {
372       "text/plain",
373       ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
374       _x11_text_converter,
375       NULL,
376       NULL,
377       0
378    },
379 };
380
381 static X11_Cnp_Selection _x11_selections[ELM_SEL_TYPE_CLIPBOARD + 1] = {
382    ARRAYINIT(ELM_SEL_TYPE_PRIMARY) {
383       .debug = "Primary",
384         .ecore_sel = ECORE_X_SELECTION_PRIMARY,
385         .set = ecore_x_selection_primary_set,
386         .clear = ecore_x_selection_primary_clear,
387         .request = ecore_x_selection_primary_request,
388    },
389    ARRAYINIT(ELM_SEL_TYPE_SECONDARY) {
390       .debug = "Secondary",
391         .ecore_sel = ECORE_X_SELECTION_SECONDARY,
392         .set = ecore_x_selection_secondary_set,
393         .clear = ecore_x_selection_secondary_clear,
394         .request = ecore_x_selection_secondary_request,
395    },
396    ARRAYINIT(ELM_SEL_TYPE_XDND) {
397       .debug = "XDnD",
398         .ecore_sel = ECORE_X_SELECTION_XDND,
399         .request = ecore_x_selection_xdnd_request,
400    },
401    ARRAYINIT(ELM_SEL_TYPE_CLIPBOARD) {
402       .debug = "Clipboard",
403         .ecore_sel = ECORE_X_SELECTION_CLIPBOARD,
404         .set = ecore_x_selection_clipboard_set,
405         .clear = ecore_x_selection_clipboard_clear,
406         .request = ecore_x_selection_clipboard_request,
407    },
408 };
409
410 static void
411 _x11_sel_obj_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
412 {
413    X11_Cnp_Selection *sel = data;
414    if (sel->widget == obj) sel->widget = NULL;
415 }
416
417 static void
418 _x11_sel_obj_del2(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
419 {
420    X11_Cnp_Selection *sel = data;
421    if (sel->requestwidget == obj) sel->requestwidget = NULL;
422 }
423
424 static Eina_Bool
425 _x11_selection_clear(void *udata __UNUSED__, int type __UNUSED__, void *event)
426 {
427    Ecore_X_Event_Selection_Clear *ev = event;
428    X11_Cnp_Selection *sel;
429    unsigned int i;
430
431    _x11_elm_cnp_init();
432    for (i = ELM_SEL_TYPE_PRIMARY; i <= ELM_SEL_TYPE_CLIPBOARD; i++)
433      {
434         if (_x11_selections[i].ecore_sel == ev->selection) break;
435      }
436    cnp_debug("selection %d clear\n", i);
437    /* Not me... Don't care */
438    if (i > ELM_SEL_TYPE_CLIPBOARD) return ECORE_CALLBACK_PASS_ON;
439
440    sel = _x11_selections + i;
441    if (sel->loss_cb) sel->loss_cb(sel->loss_data, i);
442    if (sel->widget)
443      evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL,
444                                          _x11_sel_obj_del, sel);
445    if (sel->requestwidget)
446      evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL,
447                                          _x11_sel_obj_del2, sel);
448    sel->widget = NULL;
449    sel->requestwidget = NULL;
450    
451    sel->active = EINA_FALSE;
452    sel->widget = NULL;
453    if (sel->selbuf)
454      {
455         free(sel->selbuf);
456         sel->selbuf = NULL;
457      }
458    return ECORE_CALLBACK_PASS_ON;
459 }
460
461 /*
462  * Response to a selection notify:
463  *  - So we have asked for the selection list.
464  *  - If it's the targets list, parse it, and fire of what we want,
465  *    else it's the data we want.
466  */
467 static Eina_Bool
468 _x11_selection_notify(void *udata __UNUSED__, int type __UNUSED__, void *event)
469 {
470    Ecore_X_Event_Selection_Notify *ev = event;
471    X11_Cnp_Selection *sel;
472    int i;
473
474    cnp_debug("selection notify callback: %d\n",ev->selection);
475    switch (ev->selection)
476      {
477       case ECORE_X_SELECTION_PRIMARY:
478         sel = _x11_selections + ELM_SEL_TYPE_PRIMARY;
479         break;
480       case ECORE_X_SELECTION_SECONDARY:
481         sel = _x11_selections + ELM_SEL_TYPE_SECONDARY;
482         break;
483       case ECORE_X_SELECTION_XDND:
484         sel = _x11_selections + ELM_SEL_TYPE_XDND;
485         break;
486       case ECORE_X_SELECTION_CLIPBOARD:
487         sel = _x11_selections + ELM_SEL_TYPE_CLIPBOARD;
488         break;
489       default:
490         return ECORE_CALLBACK_PASS_ON;
491      }
492    cnp_debug("Target is %s\n", ev->target);
493    
494    for (i = 0; i < CNP_N_ATOMS; i++)
495      {
496         if (!strcmp(ev->target, _x11_atoms[i].name))
497           {
498              if (_x11_atoms[i].notify)
499                {
500                   cnp_debug("Found something: %s\n", _x11_atoms[i].name);
501                   _x11_atoms[i].notify(sel, ev);
502                }
503              else cnp_debug("Ignored: No handler!\n");
504           }
505      }
506    return ECORE_CALLBACK_PASS_ON;
507 }
508
509 static Elm_Sel_Format
510 _get_selection_type(void *data, int size)
511 {
512    if (size == sizeof(Elm_Sel_Type))
513      {
514         unsigned int seltype = *((unsigned int *)data);
515         if (seltype > ELM_SEL_TYPE_CLIPBOARD)
516           return ELM_SEL_FORMAT_NONE;
517         X11_Cnp_Selection *sel = _x11_selections + seltype;
518         if (sel->active &&
519             (sel->format >= ELM_SEL_FORMAT_TARGETS) &&
520             (sel->format <= ELM_SEL_FORMAT_HTML))
521           return sel->format;
522      }
523    return ELM_SEL_FORMAT_NONE;
524 }
525
526 static Eina_Bool
527 _x11_targets_converter(char *target __UNUSED__, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize)
528 {
529    int i, count;
530    Ecore_X_Atom *aret;
531    X11_Cnp_Selection *sel;
532    Elm_Sel_Format seltype;
533
534    if (!data_ret) return EINA_FALSE;
535    if (_get_selection_type(data, size) == ELM_SEL_FORMAT_NONE)
536      {
537         /* TODO : fallback into precise type */
538         seltype = ELM_SEL_FORMAT_TEXT;
539      }
540    else
541      {
542         sel = _x11_selections + *((int *)data);
543         seltype = sel->format;
544      }
545
546    for (i = 0, count = 0; i < CNP_N_ATOMS ; i++)
547      {
548         if (seltype & _x11_atoms[i].formats) count++;
549      }
550    aret = malloc(sizeof(Ecore_X_Atom) * count);
551    if (!aret) return EINA_FALSE;
552    for (i = 0, count = 0; i < CNP_N_ATOMS; i++)
553      {
554         if (seltype & _x11_atoms[i].formats)
555           aret[count ++] = _x11_atoms[i].atom;
556      }
557
558    *data_ret = aret;
559    if (typesize) *typesize = 32 /* urk */;
560    if (ttype) *ttype = ECORE_X_ATOM_ATOM;
561    if (size_ret) *size_ret = count;
562    return EINA_TRUE;
563 }
564
565 static Eina_Bool
566 _x11_image_converter(char *target __UNUSED__, void *data __UNUSED__, int size __UNUSED__, void **data_ret __UNUSED__, int *size_ret __UNUSED__, Ecore_X_Atom *ttype __UNUSED__, int *typesize __UNUSED__)
567 {
568    cnp_debug("Image converter called\n");
569    return EINA_TRUE;
570 }
571
572 static Eina_Bool
573 _x11_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__)
574 {
575    X11_Cnp_Selection *sel;
576
577    cnp_debug("Vcard send called\n");
578    sel = _x11_selections + *((int *)data);
579    if (data_ret) *data_ret = strdup(sel->selbuf);
580    if (size_ret) *size_ret = strlen(sel->selbuf);
581    return EINA_TRUE;
582 }
583
584 // TIZEN ONLY
585 #if 0
586 static Eina_Bool
587 _x11_is_uri_type_data(X11_Cnp_Selection *sel __UNUSED__, Ecore_X_Event_Selection_Notify *notify)
588 {
589    Ecore_X_Selection_Data *data;
590    char *p;
591
592    data = notify->data;
593    cnp_debug("data->format is %d %p %p\n", data->format, notify, data);
594    if (data->content == ECORE_X_SELECTION_CONTENT_FILES) return EINA_TRUE;
595    p = (char *)data->data;
596    if (!p) return EINA_TRUE;
597    cnp_debug("Got %s\n", p);
598    if (strncmp(p, "file://", 7))
599      {
600         if (*p != '/') return EINA_FALSE;
601      }
602    return EINA_TRUE;
603 }
604 #endif
605 //
606
607 /*
608  * Callback to handle a targets response on a selection request:
609  * So pick the format we'd like; and then request it.
610  */
611 static int
612 _x11_notify_handler_targets(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
613 {
614    Ecore_X_Selection_Data_Targets *targets;
615    Ecore_X_Atom *atomlist;
616    int i, j;
617
618    targets = notify->data;
619    atomlist = (Ecore_X_Atom *)(targets->data.data);
620    for (j = (CNP_ATOM_LISTING_ATOMS + 1); j < CNP_N_ATOMS; j++)
621      {
622         cnp_debug("\t%s %d\n", _x11_atoms[j].name, _x11_atoms[j].atom);
623         if (!(_x11_atoms[j].formats & sel->requestformat)) continue;
624         for (i = 0; i < targets->data.length; i++)
625           {
626              if ((_x11_atoms[j].atom == atomlist[i]) && (_x11_atoms[j].notify))
627                {
628 // TIZEN ONLY
629 #if 0
630                   if ((j == CNP_ATOM_text_uri) ||
631                       (j == CNP_ATOM_text_urilist))
632                     {
633                        if (!_x11_is_uri_type_data(sel, notify)) continue;
634                     }
635 #endif
636 //
637                   cnp_debug("Atom %s matches\n", _x11_atoms[j].name);
638                   goto done;
639                }
640           }
641      }
642    cnp_debug("Couldn't find anything that matches\n");
643    return ECORE_CALLBACK_PASS_ON;
644 done:
645    cnp_debug("Sending request for %s, xwin=%#llx\n",
646              _x11_atoms[j].name, (unsigned long long)sel->xwin);
647    sel->request(sel->xwin, _x11_atoms[j].name);
648    return ECORE_CALLBACK_PASS_ON;
649 }
650
651 static int
652 _x11_response_handler_targets(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
653 {
654    Ecore_X_Selection_Data_Targets *targets;
655    Ecore_X_Atom *atomlist;
656    int i, j;
657
658    targets = notify->data;
659    atomlist = (Ecore_X_Atom *)(targets->data.data);
660
661    for (j = (CNP_ATOM_LISTING_ATOMS + 1); j < CNP_N_ATOMS; j++)
662      {
663         if (!(_x11_atoms[j].formats & sel->requestformat)) continue;
664         for (i = 0; i < targets->data.length; i++)
665           {
666              if ((_x11_atoms[j].atom == atomlist[i]) &&
667                  (_x11_atoms[j].response))
668                goto found;
669           }
670      }
671    cnp_debug("No matching type found\n");
672    return 0;
673 found:
674    sel->request(sel->xwin, _x11_atoms[j].name);
675    return 0;
676 }
677
678 static int
679 _x11_notify_handler_text(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
680 {
681    Ecore_X_Selection_Data *data;
682
683    data = notify->data;
684    if (sel->datacb)
685      {
686         Elm_Selection_Data ddata;
687
688         ddata.x = ddata.y = 0;
689         ddata.format = ELM_SEL_FORMAT_TEXT;
690         ddata.data = data->data;
691         ddata.len = data->length;
692         sel->datacb(sel->udata, sel->widget, &ddata);
693      }
694    else
695      {
696         char *stripstr, *mkupstr;
697
698         stripstr = malloc(data->length + 1);
699         if (!stripstr) return 0;
700         strncpy(stripstr, (char *)data->data, data->length);
701         stripstr[data->length] = '\0';
702         cnp_debug("Notify handler text %d %d %p\n", data->format,
703                   data->length, data->data);
704         mkupstr = _elm_util_text_to_mkup((const char *)stripstr);
705         cnp_debug("String is %s (from %s)\n", stripstr, data->data);
706         /* TODO BUG: should never NEVER assume it's an elm_entry! */
707         //_elm_entry_entry_paste(sel->requestwidget, mkupstr); // TIZEN ONLY
708         // TIZEN ONLY
709         if (mkupstr)
710           _entry_insert_filter(sel->requestwidget, mkupstr);
711         else
712           _entry_insert_filter(sel->requestwidget, stripstr);
713         //
714
715         free(stripstr);
716         free(mkupstr);
717      }
718    return 0;
719 }
720
721 /**
722  * So someone is pasting an image into my entry or widget...
723  */
724 static int
725 _x11_notify_handler_uri(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
726 {
727    Ecore_X_Selection_Data *data;
728    Ecore_X_Selection_Data_Files *files;
729    char *p, *stripstr;
730
731    data = notify->data;
732    cnp_debug("data->format is %d %p %p\n", data->format, notify, data);
733    if (data->content == ECORE_X_SELECTION_CONTENT_FILES)
734      {
735         cnp_debug("got a files list\n");
736         files = notify->data;
737         if (files->num_files > 1)
738           {
739              /* Don't handle many items */
740              cnp_debug("more then one file: Bailing\n");
741              return 0;
742           }
743         stripstr = p = strdup(files->files[0]);
744      }
745    else
746      {
747         stripstr = p = malloc(data->length + 1);
748         if (!stripstr) return 0;
749         memcpy(stripstr, data->data, data->length);
750         stripstr[data->length] = 0;
751      }
752    if (!p)
753      {
754         cnp_debug("Couldn't find a file\n");
755         return 0;
756      }
757    cnp_debug("Got %s\n", p);
758
759    if (sel->datacb)
760      {
761         Elm_Selection_Data ddata;
762
763         ddata.x = ddata.y = 0;
764         ddata.format = ELM_SEL_FORMAT_IMAGE;
765         ddata.data = p;
766         ddata.len = data->length;
767         sel->datacb(sel->udata, sel->widget, &ddata);
768         free(p);
769         return 0;
770      }
771
772    if (strncmp(p, "file://", 7))
773      {
774         /* Try and continue if it looks sane */
775         if (*p != '/')
776           {
777              free(p);
778              return 0;
779           }
780      }
781    else p += strlen("file://");
782    if (savedtypes.imgfile) free(savedtypes.imgfile);
783    if (savedtypes.textreq)
784      {
785         savedtypes.textreq = 0;
786         savedtypes.imgfile = strdup(p);
787      }
788    else _pasteimage_append(p, sel->requestwidget);
789    free(stripstr);
790    return 0;
791 }
792
793 /**
794  * Just receieved an vcard, either through cut and paste, or dnd.
795  */
796 static int
797 _x11_vcard_receive(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
798 {
799    Dropable *dropable;
800    Eina_List *l;
801    Ecore_X_Selection_Data *data;
802
803    data = notify->data;
804    cnp_debug("vcard receive\n");
805    if (sel == (_x11_selections + ELM_SEL_TYPE_XDND))
806      {
807         Elm_Selection_Data ddata;
808
809         cnp_debug("drag & drop\n");
810         /* FIXME: this needs to be generic: Used for all receives */
811         EINA_LIST_FOREACH(drops, l, dropable)
812           {
813              if (dropable->obj == sel->requestwidget) break;
814           }
815         if (!dropable)
816           {
817              cnp_debug("Unable to find drop object");
818              ecore_x_dnd_send_finished();
819              return 0;
820           }
821         dropable = eina_list_data_get(l);
822         ddata.x = savedtypes.x;
823         ddata.y = savedtypes.y;
824         ddata.format = ELM_SEL_FORMAT_VCARD;
825         ddata.data = data->data;
826         ddata.len = data->length;
827         dropable->dropcb(dropable->cbdata, dropable->obj, &ddata);
828         ecore_x_dnd_send_finished();
829      }
830    else if (sel->datacb)
831      {
832         Elm_Selection_Data ddata;
833         ddata.x = ddata.y = 0;
834         ddata.format = ELM_SEL_FORMAT_VCARD;
835         ddata.data = data->data;
836         ddata.len = data->length;
837         sel->datacb(sel->udata, sel->widget, &ddata);
838      }
839    else cnp_debug("Paste request\n");
840    return 0;
841 }
842
843 static int
844 _x11_notify_handler_image(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
845 {
846    Ecore_X_Selection_Data *data;
847    Tmp_Info *tmp;
848
849    cnp_debug("got a image file!\n");
850    data = notify->data;
851
852    cnp_debug("Size if %d\n", data->length);
853    if (sel->datacb)
854      {
855         Elm_Selection_Data ddata;
856
857         ddata.x = ddata.y = 0;
858         ddata.format = ELM_SEL_FORMAT_IMAGE;
859         ddata.data = data->data;
860         ddata.len = data->length;
861         sel->datacb(sel->udata, sel->widget, &ddata);
862         return 0;
863      }
864    /* generate tmp name */
865    tmp = _tempfile_new(data->length);
866    if (!tmp) return 0;
867    memcpy(tmp->map, data->data, data->length);
868    munmap(tmp->map, data->length);
869    /* FIXME: Add to paste image data to clean up */
870    _pasteimage_append(tmp->filename, sel->requestwidget);
871    _tmpinfo_free(tmp);
872    return 0;
873 }
874
875 // TIZEN ONLY
876 static int
877 _x11_notify_handler_edje(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
878 {
879    Ecore_X_Selection_Data *data;
880
881    data = notify->data;
882
883    if (sel->datacb)
884      {
885         Elm_Selection_Data ddata;
886         ddata.x = ddata.y = 0;
887         ddata.format = ELM_SEL_FORMAT_MARKUP;
888         ddata.data = data->data;
889         ddata.len = data->length;
890         sel->datacb(sel->udata, sel->widget, &ddata);
891      }
892    else
893      {
894         char *stripstr;
895         stripstr = malloc(data->length + 1);
896         if (!stripstr) return 0;
897         strncpy(stripstr, (char *)data->data, data->length);
898         stripstr[data->length] = '\0';
899
900         _entry_insert_filter(sel->requestwidget, stripstr);
901         cnp_debug("String is %s (%d bytes)\n", stripstr, data->length);
902         free(stripstr);
903      }
904
905    return 0;
906 }
907 //
908
909 /**
910  *    Warning: Generic text/html can';t handle it sanely.
911  *    Firefox sends ucs2 (i think).
912  *       chrome sends utf8... blerg
913  */
914 /*
915 static int
916 _x11_notify_handler_html(X11_Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
917 {
918    Ecore_X_Selection_Data *data;
919
920    cnp_debug("Got some HTML: Checking encoding is useful\n");
921    data = notify->data;
922    char *stripstr = malloc(data->length + 1);
923    if (!stripstr) return 0;
924    strncpy(stripstr, (char *)data->data, data->length);
925    stripstr[data->length] = '\0';
926
927    if (sel->datacb)
928      {
929         Elm_Selection_Data ddata;
930         ddata.x = ddata.y = 0;
931         ddata.format = ELM_SEL_FORMAT_HTML;
932         ddata.data = stripstr;
933         ddata.len = data->length;
934         sel->datacb(sel->udata, sel->widget, &ddata);
935         free(stripstr);
936         return 0;
937      }
938
939    cnp_debug("String is %s (%d bytes)\n", stripstr, data->length);
940    // TODO BUG: should never NEVER assume it's an elm_entry!
941    _elm_entry_entry_paste(sel->requestwidget, stripstr);
942    free(stripstr);
943    return 0;
944 }
945 */
946
947 static Eina_Bool
948 _x11_text_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize)
949 {
950    X11_Cnp_Selection *sel;
951
952    cnp_debug("text converter\n");
953    if (_get_selection_type(data, size) == ELM_SEL_FORMAT_NONE)
954      {
955         if (data_ret)
956           {
957              *data_ret = malloc(size * sizeof(char) + 1);
958              if (!*data_ret) return EINA_FALSE;
959              memcpy(*data_ret, data, size);
960              ((char**)(data_ret))[0][size] = 0;
961           }
962         if (size_ret) *size_ret = size;
963         return EINA_TRUE;
964      }
965    sel = _x11_selections + *((int *)data);
966    if (!sel->active) return EINA_TRUE;
967
968    if ((sel->format & ELM_SEL_FORMAT_MARKUP) ||
969        (sel->format & ELM_SEL_FORMAT_HTML))
970      {
971         *data_ret = _elm_util_mkup_to_text(sel->selbuf);
972         if (size_ret) *size_ret = strlen(*data_ret);
973      }
974    else if (sel->format & ELM_SEL_FORMAT_TEXT)
975      {
976         ecore_x_selection_converter_text(target, sel->selbuf,
977                                          strlen(sel->selbuf),
978                                          data_ret, size_ret,
979                                          ttype, typesize);
980      }
981    else if (sel->format & ELM_SEL_FORMAT_IMAGE)
982      {
983         cnp_debug("Image %s\n", evas_object_type_get(sel->widget));
984         cnp_debug("Elm type: %s\n", elm_object_widget_type_get(sel->widget));
985         evas_object_image_file_get(elm_photocam_internal_image_get(sel->widget),
986                                    (const char **)data_ret, NULL);
987         if (!*data_ret) *data_ret = strdup("No file");
988         else *data_ret = strdup(*data_ret);
989         *size_ret = strlen(*data_ret);
990      }
991    return EINA_TRUE;
992 }
993
994 static Eina_Bool
995 _x11_general_converter(char *target __UNUSED__, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype __UNUSED__, int *typesize __UNUSED__)
996 {
997    if (_get_selection_type(data, size) == ELM_SEL_FORMAT_NONE)
998      {
999         if (data_ret)
1000           {
1001              *data_ret = malloc(size * sizeof(char) + 1);
1002              if (!*data_ret) return EINA_FALSE;
1003              memcpy(*data_ret, data, size);
1004              ((char**)(data_ret))[0][size] = 0;
1005           }
1006         if (size_ret) *size_ret = size;
1007      }
1008    else
1009      {
1010         X11_Cnp_Selection *sel = _x11_selections + *((int *)data);
1011         if (data_ret) *data_ret = strdup(sel->selbuf);
1012         if (size_ret) *size_ret = strlen(sel->selbuf);
1013      }
1014    return EINA_TRUE;
1015 }
1016
1017 static Eina_Bool
1018 _x11_dnd_enter(void *data __UNUSED__, int etype __UNUSED__, void *ev)
1019 {
1020    Ecore_X_Event_Xdnd_Enter *enter = ev;
1021    int i;
1022
1023    /* Skip it */
1024    cnp_debug("enter %p\n", enter);
1025    cnp_debug("enter types=%p (%d)\n", enter->types, enter->num_types);
1026    if ((!enter) || (!enter->num_types) || (!enter->types)) return EINA_TRUE;
1027
1028    cnp_debug("Types\n");
1029    savedtypes.ntypes = enter->num_types;
1030    if (savedtypes.types) free(savedtypes.types);
1031    savedtypes.types = malloc(sizeof(char *) * enter->num_types);
1032    if (!savedtypes.types) return EINA_FALSE;
1033
1034    for (i = 0; i < enter->num_types; i++)
1035      {
1036         savedtypes.types[i] = eina_stringshare_add(enter->types[i]);
1037         cnp_debug("Type is %s %p %p\n", enter->types[i],
1038                   savedtypes.types[i], text_uri);
1039         if (savedtypes.types[i] == text_uri)
1040           {
1041              /* Request it, so we know what it is */
1042              cnp_debug("Sending uri request\n");
1043              savedtypes.textreq = 1;
1044              if (savedtypes.imgfile) free(savedtypes.imgfile);
1045              savedtypes.imgfile = NULL;
1046              ecore_x_selection_xdnd_request(enter->win, text_uri);
1047           }
1048      }
1049
1050    /* FIXME: Find an object and make it current */
1051    return EINA_TRUE;
1052 }
1053
1054 static Eina_Bool
1055 _x11_dnd_drop(void *data __UNUSED__, int etype __UNUSED__, void *ev)
1056 {
1057    struct _Ecore_X_Event_Xdnd_Drop *drop;
1058    Dropable *dropable;
1059    Eina_List *l;
1060    Ecore_Evas *ee;
1061    Ecore_X_Window xwin;
1062    Elm_Selection_Data ddata;
1063    int x, y, w, h;
1064    int i, j;
1065
1066    drop = ev;
1067
1068    cnp_debug("drops %p (%d)\n", drops, eina_list_count(drops));
1069
1070    // check we still have something to drop
1071    if (!drops) return EINA_TRUE;
1072
1073    /* Find any widget in our window; then work out geometry rel to our window */
1074    for (l = drops; l; l = l->next)
1075      {
1076         dropable = l->data;
1077         xwin = _x11_elm_widget_xwin_get(dropable->obj);
1078         if (xwin == drop->win) break;
1079      }
1080    /* didn't find a window */
1081    if (!l) return EINA_TRUE;
1082
1083    /* Calculate real (widget relative) position */
1084    // - window position
1085    // - widget position
1086    ee = ecore_evas_ecore_evas_get(evas_object_evas_get(dropable->obj));
1087    ecore_evas_geometry_get(ee, &x, &y, NULL, NULL);
1088    savedtypes.x = drop->position.x - x;
1089    savedtypes.y = drop->position.y - y;
1090
1091    cnp_debug("Drop position is %d,%d\n", savedtypes.x, savedtypes.y);
1092
1093    for (; l; l = l->next)
1094      {
1095         dropable = l->data;
1096         evas_object_geometry_get(dropable->obj, &x, &y, &w, &h);
1097         if ((savedtypes.x >= x) && (savedtypes.y >= y) &&
1098             (savedtypes.x < x + w) && (savedtypes.y < y + h))
1099           break; /* found! */
1100      }
1101
1102    if (!l) return EINA_TRUE; /* didn't find one */
1103
1104    evas_object_geometry_get(dropable->obj, &x, &y, NULL, NULL);
1105    savedtypes.x -= x;
1106    savedtypes.y -= y;
1107
1108    /* Find our type from the previous list */
1109    for (i = 0; i < CNP_N_ATOMS; i++)
1110      {
1111         for (j = 0; j < savedtypes.ntypes; j++)
1112           {
1113              if (!strcmp(savedtypes.types[j], _x11_atoms[i].name)) goto found;
1114           }
1115      }
1116
1117    cnp_debug("Didn't find a target\n");
1118    return EINA_TRUE;
1119
1120 found:
1121    cnp_debug("Found a target we'd like: %s\n", _x11_atoms[i].name);
1122    cnp_debug("0x%x\n",xwin);
1123
1124    if (i == CNP_ATOM_text_urilist)
1125      {
1126         cnp_debug("We found a URI... (%scached) %s\n",
1127                   savedtypes.imgfile ? "" : "not ",
1128                   savedtypes.imgfile);
1129         if (savedtypes.imgfile)
1130           {
1131              char *entrytag;
1132              static const char *tagstring = "<item absize=240x180 href="
1133                 "file://%s></item>";
1134              ddata.x = savedtypes.x;
1135              ddata.y = savedtypes.y;
1136
1137              /* If it's markup that also supports images */
1138              if ((dropable->types & ELM_SEL_FORMAT_MARKUP) &&
1139                  (dropable->types & ELM_SEL_FORMAT_IMAGE))
1140                {
1141                   int len;
1142                   ddata.format = ELM_SEL_FORMAT_MARKUP;
1143
1144                   len = strlen(tagstring) + strlen(savedtypes.imgfile);
1145                   entrytag = alloca(len + 1);
1146                   snprintf(entrytag, len + 1, tagstring, savedtypes.imgfile);
1147                   ddata.data = entrytag;
1148                   cnp_debug("Insert %s\n", (char *)ddata.data);
1149                   dropable->dropcb(dropable->cbdata, dropable->obj, &ddata);
1150                   ecore_x_dnd_send_finished();
1151                   if (savedtypes.imgfile) free(savedtypes.imgfile);
1152                   savedtypes.imgfile = NULL;
1153
1154                   return EINA_TRUE;
1155                }
1156              else if (dropable->types & ELM_SEL_FORMAT_IMAGE)
1157                {
1158                   cnp_debug("Doing image insert (%s)\n", savedtypes.imgfile);
1159                   ddata.format = ELM_SEL_FORMAT_IMAGE;
1160                   ddata.data = (char *)savedtypes.imgfile;
1161                   dropable->dropcb(dropable->cbdata, dropable->obj, &ddata);
1162                   ecore_x_dnd_send_finished();
1163                   if (savedtypes.imgfile) free(savedtypes.imgfile);
1164                   savedtypes.imgfile = NULL;
1165
1166                   return EINA_TRUE;
1167                }
1168              else
1169                {
1170                   cnp_debug("Item doesn't support images... passing\n");
1171                   return EINA_TRUE;
1172                }
1173           }
1174         else if (savedtypes.textreq)
1175           {
1176              /* Already asked: Pretend we asked now, and paste immediately when
1177               * it comes in */
1178              savedtypes.textreq = 0;
1179              ecore_x_dnd_send_finished();
1180              return EINA_TRUE;
1181           }
1182      }
1183
1184    cnp_debug("doing a request then\n");
1185    _x11_selections[ELM_SEL_TYPE_XDND].xwin = xwin;
1186    _x11_selections[ELM_SEL_TYPE_XDND].requestwidget = dropable->obj;
1187    _x11_selections[ELM_SEL_TYPE_XDND].requestformat = ELM_SEL_FORMAT_MARKUP;
1188    _x11_selections[ELM_SEL_TYPE_XDND].active = EINA_TRUE;
1189
1190    ecore_x_selection_xdnd_request(xwin, _x11_atoms[i].name);
1191    return EINA_TRUE;
1192 }
1193
1194 static Eina_Bool
1195 _x11_dnd_position(void *data __UNUSED__, int etype __UNUSED__, void *ev)
1196 {
1197    struct _Ecore_X_Event_Xdnd_Position *pos = ev;
1198    Ecore_X_Rectangle rect;
1199
1200    /* Need to send a status back */
1201    /* FIXME: Should check I can drop here */
1202    /* FIXME: Should highlight widget */
1203    rect.x = pos->position.x - 5;
1204    rect.y = pos->position.y - 5;
1205    rect.width = 10;
1206    rect.height = 10;
1207    ecore_x_dnd_send_status(EINA_TRUE, EINA_FALSE, rect, pos->action);
1208    return EINA_TRUE;
1209 }
1210
1211 /**
1212  * When dragging this is callback response from the destination.
1213  * The important thing we care about: Can we drop; thus update cursor
1214  * appropriately.
1215  */
1216 static Eina_Bool
1217 _x11_dnd_status(void *data __UNUSED__, int etype __UNUSED__, void *ev)
1218 {
1219    struct _Ecore_X_Event_Xdnd_Status *status = ev;
1220
1221    if (!status) return EINA_TRUE;
1222
1223    /* Only thing we care about: will accept */
1224    if (status->will_accept) cnp_debug("Will accept\n");
1225    /* Won't accept */   
1226    else cnp_debug("Won't accept accept\n");
1227    return EINA_TRUE;
1228 }
1229
1230 static void
1231 _x11_drag_mouse_up(void *un __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *data)
1232 {
1233    Ecore_X_Window xwin = *((Ecore_X_Window *)data);
1234    evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_UP, _x11_drag_mouse_up);
1235    ecore_x_dnd_drop();
1236
1237    cnp_debug("mouse up, xwin=%#llx\n", (unsigned long long)xwin);
1238
1239    /* TODO BUG: should not revert to FALSE if xwin is a drop target! */
1240    ecore_x_dnd_aware_set(xwin, EINA_FALSE);
1241    if (dragdonecb)
1242      {
1243         dragdonecb(dragdonedata, _x11_selections[ELM_SEL_TYPE_XDND].widget);
1244         dragdonecb = NULL;
1245      }
1246    if (dragwin)
1247      {
1248         evas_object_del(dragwin);
1249         dragwin = NULL;
1250      }
1251 }
1252
1253 static void
1254 _x11_drag_move(void *data __UNUSED__, Ecore_X_Xdnd_Position *pos)
1255 {
1256    evas_object_move(dragwin, pos->position.x - _dragx, pos->position.y - _dragy);
1257 }
1258
1259 static Ecore_X_Window
1260 _x11_elm_widget_xwin_get(const Evas_Object *obj)
1261 {
1262    Evas_Object *top;
1263    Ecore_X_Window xwin = 0;
1264    
1265    top = elm_widget_top_get(obj);
1266    if (!top) top = elm_widget_top_get(elm_widget_parent_widget_get(obj));
1267    if (top) xwin = elm_win_xwindow_get(top);
1268    if (!xwin)
1269      {
1270         Ecore_Evas *ee;
1271         Evas *evas = evas_object_evas_get(obj);
1272         if (!evas) return 0;
1273         ee = ecore_evas_ecore_evas_get(evas);
1274         if (!ee) return 0;
1275         xwin = _elm_ee_xwin_get(ee);
1276      }
1277    return xwin;
1278 }
1279
1280 static Eina_Bool
1281 _x11_elm_cnp_init(void)
1282 {
1283    int i;
1284    static int _init_count = 0;
1285    
1286    if (_init_count > 0) return EINA_TRUE;
1287    _init_count++;
1288    for (i = 0; i < CNP_N_ATOMS; i++)
1289      {
1290         _x11_atoms[i].atom = ecore_x_atom_get(_x11_atoms[i].name);
1291         ecore_x_selection_converter_atom_add
1292           (_x11_atoms[i].atom, _x11_atoms[i].converter);
1293      }
1294    ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, _x11_selection_clear, NULL);
1295    ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, _x11_selection_notify, NULL);
1296    return EINA_TRUE;
1297 }
1298
1299 static Eina_Bool
1300 _x11_elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen)
1301 {
1302    Ecore_X_Window xwin = _x11_elm_widget_xwin_get(obj);
1303    X11_Cnp_Selection *sel;
1304
1305    _x11_elm_cnp_init();
1306    if ((!selbuf) && (format != ELM_SEL_FORMAT_IMAGE))
1307      return elm_object_cnp_selection_clear(obj, selection);
1308
1309    sel = _x11_selections + selection;
1310    if (sel->loss_cb) sel->loss_cb(sel->loss_data, selection);
1311    if (sel->widget)
1312      evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL,
1313                                          _x11_sel_obj_del, sel);
1314    sel->widget = NULL;
1315    
1316    sel->active = EINA_TRUE;
1317    sel->widget = obj;
1318    sel->xwin = xwin;
1319    sel->set(xwin, &selection, sizeof(Elm_Sel_Type));
1320    sel->format = format;
1321    sel->loss_cb = NULL;
1322    sel->loss_data = NULL;
1323
1324    evas_object_event_callback_add
1325      (sel->widget, EVAS_CALLBACK_DEL, _x11_sel_obj_del, sel);
1326    
1327    if (selbuf)
1328      {
1329         if (format == ELM_SEL_FORMAT_IMAGE)
1330           {
1331              // selbuf is actual image data, not text/string
1332              sel->selbuf = malloc(buflen);
1333              if (!sel->selbuf)
1334                {
1335                   elm_object_cnp_selection_clear(obj, selection);
1336                   return EINA_FALSE;
1337                }
1338              memcpy(sel->selbuf, selbuf, buflen);
1339           }
1340         else
1341           sel->selbuf = strdup((char*)selbuf);
1342      }
1343    else
1344      sel->selbuf = NULL;
1345
1346    return EINA_TRUE;
1347 }
1348
1349 static void
1350 _x11_elm_cnp_selection_loss_callback_set(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection, Elm_Selection_Loss_Cb func, const void *data)
1351 {
1352    X11_Cnp_Selection *sel;
1353    
1354    _x11_elm_cnp_init();
1355    sel = _x11_selections + selection;
1356    sel->loss_cb = func;
1357    sel->loss_data = (void *)data;
1358 }
1359
1360 static Eina_Bool
1361 _x11_elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection)
1362 {
1363    X11_Cnp_Selection *sel;
1364
1365    _x11_elm_cnp_init();
1366    
1367    sel = _x11_selections + selection;
1368
1369    /* No longer this selection: Consider it gone! */
1370    if ((!sel->active) || (sel->widget != obj)) return EINA_TRUE;
1371
1372    if (sel->widget)
1373      evas_object_event_callback_del_full(sel->widget, EVAS_CALLBACK_DEL,
1374                                          _x11_sel_obj_del, sel);
1375    if (sel->requestwidget)
1376      evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL,
1377                                          _x11_sel_obj_del2, sel);
1378    sel->widget = NULL;
1379    sel->requestwidget = NULL;
1380    sel->loss_cb = NULL;
1381    sel->loss_data = NULL;
1382    
1383    sel->active = EINA_FALSE;
1384    if (sel->selbuf)
1385      {
1386         free(sel->selbuf);
1387         sel->selbuf = NULL;
1388      }
1389    sel->clear();
1390
1391    return EINA_TRUE;
1392 }
1393
1394 static Eina_Bool
1395 _x11_elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection,
1396                       Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata)
1397 {
1398    Ecore_X_Window xwin = _x11_elm_widget_xwin_get(obj);
1399    X11_Cnp_Selection *sel;
1400
1401    _x11_elm_cnp_init();
1402    
1403    sel = _x11_selections + selection;
1404
1405    if (sel->requestwidget)
1406      evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL,
1407                                          _x11_sel_obj_del2, sel);
1408    sel->requestwidget = NULL;
1409    
1410    sel->requestformat = format;
1411    sel->requestwidget = obj;
1412    sel->xwin = xwin;
1413    sel->request(xwin, ECORE_X_SELECTION_TARGET_TARGETS);
1414    sel->datacb = datacb;
1415    sel->udata = udata;
1416
1417    evas_object_event_callback_add
1418      (sel->requestwidget, EVAS_CALLBACK_DEL, _x11_sel_obj_del2, sel);
1419    
1420    return EINA_TRUE;
1421 }
1422
1423 static Eina_Bool
1424 _x11_elm_drop_target_add(Evas_Object *obj, Elm_Sel_Type format,
1425                          Elm_Drop_Cb dropcb, void *cbdata)
1426 {
1427    Dropable *drop;
1428    Ecore_X_Window xwin = _x11_elm_widget_xwin_get(obj);
1429    Eina_List *item;
1430    int first;
1431
1432    _x11_elm_cnp_init();
1433    
1434    /* TODO: check if obj is already a drop target. Do not add twice! */
1435
1436    /* Is this the first? */
1437    first = (!drops) ? 1 : 0;
1438
1439    EINA_LIST_FOREACH(drops, item, drop)
1440      {
1441         if (drop->obj == obj)
1442           {
1443              /* Update: Not a new one */
1444              drop->dropcb = dropcb;
1445              drop->cbdata = cbdata;
1446              drop->types = format;
1447              return EINA_TRUE;
1448           }
1449      }
1450
1451    /* Create new drop */
1452    drop = calloc(1, sizeof(Dropable));
1453    if (!drop) return EINA_FALSE;
1454    /* FIXME: Check for eina's deranged error method */
1455    drops = eina_list_append(drops, drop);
1456
1457    if (!drops/* || or other error */)
1458      {
1459         free(drop);
1460         return EINA_FALSE;
1461      }
1462    drop->dropcb = dropcb;
1463    drop->cbdata = cbdata;
1464    drop->types = format;
1465    drop->obj = obj;
1466
1467    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
1468                                   /* I love C and varargs */
1469                                   (Evas_Object_Event_Cb)elm_drop_target_del,
1470                                   obj);
1471    /* TODO BUG: should handle dnd-aware per window, not just the first
1472     * window that requested it! */
1473    /* If not the first: We're done */
1474    if (!first) return EINA_TRUE;
1475
1476    ecore_x_dnd_aware_set(xwin, EINA_TRUE);
1477
1478    cnp_debug("Adding drop target calls xwin=%#llx\n", (unsigned long long)xwin);
1479    handler_enter = ecore_event_handler_add(ECORE_X_EVENT_XDND_ENTER,
1480                                            _x11_dnd_enter, NULL);
1481    handler_pos = ecore_event_handler_add(ECORE_X_EVENT_XDND_POSITION,
1482                                          _x11_dnd_position, NULL);
1483    handler_drop = ecore_event_handler_add(ECORE_X_EVENT_XDND_DROP,
1484                                           _x11_dnd_drop, NULL);
1485    return EINA_TRUE;
1486 }
1487
1488 static Eina_Bool
1489 _x11_elm_drop_target_del(Evas_Object *obj)
1490 {
1491    Dropable *drop,*del;
1492    Eina_List *item;
1493    Ecore_X_Window xwin;
1494
1495    _x11_elm_cnp_init();
1496    
1497    del = NULL;
1498    EINA_LIST_FOREACH(drops, item, drop)
1499      {
1500         if (drop->obj == obj)
1501           {
1502              drops = eina_list_remove_list(drops, item);
1503              del = drop;
1504              break;
1505           }
1506      }
1507    if (!del) return EINA_FALSE;
1508
1509    evas_object_event_callback_del(obj, EVAS_CALLBACK_FREE,
1510                                   (Evas_Object_Event_Cb)elm_drop_target_del);
1511    free(drop);
1512
1513    /* TODO BUG: we should handle dnd-aware per window, not just the last that reelased it */
1514
1515    /* If still drops there: All fine.. continue */
1516    if (drops) return EINA_TRUE;
1517
1518    cnp_debug("Disabling DND\n");
1519    xwin = _x11_elm_widget_xwin_get(obj);
1520    ecore_x_dnd_aware_set(xwin, EINA_FALSE);
1521
1522    ecore_event_handler_del(handler_pos);
1523    ecore_event_handler_del(handler_drop);
1524    ecore_event_handler_del(handler_enter);
1525
1526    if (savedtypes.imgfile) free(savedtypes.imgfile);
1527    savedtypes.imgfile = NULL;
1528
1529    return EINA_TRUE;
1530 }
1531
1532 static  Eina_Bool
1533 _x11_elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data, void (*dragdone) (void *data, Evas_Object *), void *donecbdata)
1534 {
1535    Ecore_X_Window xwin = _x11_elm_widget_xwin_get(obj);
1536    X11_Cnp_Selection *sel;
1537    Elm_Sel_Type xdnd = ELM_SEL_TYPE_XDND;
1538    Ecore_Evas *ee;
1539    int x, y, x2, y2, x3, y3;
1540    Evas_Object *icon;
1541    int w, h;
1542
1543    _x11_elm_cnp_init();
1544    
1545    cnp_debug("starting drag...\n");
1546
1547    if (dragwin)
1548      {
1549         cnp_debug("another obj is dragging...\n");
1550         return EINA_FALSE;
1551      }
1552
1553    ecore_x_dnd_type_set(xwin, "text/uri-list", EINA_TRUE);
1554    sel = _x11_selections + ELM_SEL_TYPE_XDND;
1555    sel->active = EINA_TRUE;
1556    sel->widget = obj;
1557    sel->format = format;
1558    sel->selbuf = data ? strdup(data) : NULL;
1559
1560    /* TODO BUG: should NEVER have these as globals! They should be per context (window). */
1561    dragdonecb = dragdone;
1562    dragdonedata = donecbdata;
1563    /* TODO BUG: should increase dnd-awareness, in case it's drop target as well. See _x11_drag_mouse_up() */
1564    ecore_x_dnd_aware_set(xwin, EINA_TRUE);
1565    ecore_x_dnd_callback_pos_update_set(_x11_drag_move, NULL);
1566    ecore_x_dnd_begin(xwin, (unsigned char *)&xdnd, sizeof(Elm_Sel_Type));
1567    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
1568                                   _x11_drag_mouse_up, (void *)(long)xwin);
1569    handler_status = ecore_event_handler_add(ECORE_X_EVENT_XDND_STATUS,
1570                                             _x11_dnd_status, NULL);
1571    dragwin = elm_win_add(NULL, "Elm Drag Object", ELM_WIN_UTILITY);
1572    elm_win_override_set(dragwin, EINA_TRUE);
1573
1574    /* FIXME: Images only */
1575    icon = elm_icon_add(dragwin);
1576    elm_image_file_set(icon, data + 7, NULL); /* 7!? "file://" */
1577    elm_win_resize_object_add(dragwin, icon);
1578    evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1579    evas_object_size_hint_align_set(icon, EVAS_HINT_FILL, EVAS_HINT_FILL);
1580
1581    /* Position subwindow appropriately */
1582    ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
1583    ecore_evas_geometry_get(ee, &x, &y, NULL, NULL);
1584    evas_object_geometry_get(obj, &x2, &y2, &w, &h);
1585    x += x2;
1586    y += y2;
1587    evas_object_move(dragwin, x, y);
1588    evas_object_resize(icon, w, h);
1589    evas_object_resize(dragwin, w, h);
1590
1591    evas_object_show(icon);
1592    evas_object_show(dragwin);
1593
1594    evas_pointer_canvas_xy_get(evas_object_evas_get(obj), &x3, &y3);
1595    _dragx = x3 - x2;
1596    _dragy = y3 - y2;
1597
1598    return EINA_TRUE;
1599 }
1600
1601 static Eina_Bool
1602 _x11_elm_selection_selection_has_owner(Evas_Object *obj __UNUSED__)
1603 {
1604    _x11_elm_cnp_init();
1605    return !!ecore_x_selection_owner_get(ECORE_X_ATOM_SELECTION_CLIPBOARD);
1606 }
1607
1608 #endif
1609
1610 #ifdef HAVE_ELEMENTARY_WAYLAND
1611 typedef struct _Wl_Cnp_Selection Wl_Cnp_Selection;
1612
1613 struct _Wl_Cnp_Selection
1614 {
1615    char *selbuf;
1616    int buflen;
1617
1618    Evas_Object *widget;
1619    Evas_Object *requestwidget;
1620 };
1621
1622 static Eina_Bool _wl_elm_cnp_init(void);
1623
1624 static Wl_Cnp_Selection wl_cnp_selection = {0, 0, NULL, NULL};
1625 static void _wl_sel_obj_del2(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
1626 static Eina_Bool _wl_elm_cnp_selection_set(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, const void *selbuf, size_t buflen);
1627 static Eina_Bool _wl_elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, Elm_Drop_Cb datacb __UNUSED__, void *udata __UNUSED__);
1628 static Eina_Bool _wl_selection_send(void *udata, int type __UNUSED__, void *event);
1629 static Eina_Bool _wl_selection_receive(void *udata, int type __UNUSED__, void *event);
1630
1631 static void
1632 _wl_sel_obj_del2(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1633 {
1634    Wl_Cnp_Selection *sel = data;
1635    if (sel->requestwidget == obj) sel->requestwidget = NULL;
1636 }
1637
1638 static Eina_Bool 
1639 _wl_elm_cnp_selection_set(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, const void *selbuf, size_t buflen)
1640 {
1641    const char *types[10] = {0, };
1642
1643    _wl_elm_cnp_init();
1644
1645    /* TODO: other EML_SEL_TYPE and ELM_SEL_FORMAT */
1646    if (ELM_SEL_TYPE_CLIPBOARD == selection) 
1647      {
1648         types[0] = "text/plain;charset=utf-8";
1649         ecore_wl_dnd_set_selection(ecore_wl_dnd_get(), types);
1650
1651         if (wl_cnp_selection.selbuf) free(wl_cnp_selection.selbuf);
1652         wl_cnp_selection.selbuf = strdup((char*)selbuf);
1653         wl_cnp_selection.buflen = buflen;
1654         return EINA_TRUE;
1655      }
1656
1657    return EINA_FALSE;
1658 }
1659
1660 static Eina_Bool 
1661 _wl_elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, Elm_Drop_Cb datacb __UNUSED__, void *udata __UNUSED__)
1662 {
1663    _wl_elm_cnp_init();
1664
1665    /* For now, just avoid overlapped request */
1666    if (wl_cnp_selection.requestwidget) return EINA_FALSE;
1667
1668    /* TODO: other EML_SEL_TYPE and ELM_SEL_FORMAT */
1669    if (ELM_SEL_TYPE_CLIPBOARD == selection)
1670      {
1671         wl_cnp_selection.requestwidget = obj;
1672         evas_object_event_callback_add(wl_cnp_selection.requestwidget, EVAS_CALLBACK_DEL,
1673                                        _wl_sel_obj_del2, &wl_cnp_selection);
1674         ecore_wl_dnd_get_selection(ecore_wl_dnd_get(), "text/plain;charset=utf-8");
1675      }
1676    return EINA_TRUE;
1677 }
1678
1679 static Eina_Bool
1680 _wl_selection_send(void *udata, int type __UNUSED__, void *event)
1681 {
1682    char *buf;
1683    int ret, len_remained;
1684    int len_written = 0;
1685    Wl_Cnp_Selection *sel = udata;
1686    Ecore_Wl_Event_Data_Source_Send *ev = event;
1687
1688    _wl_elm_cnp_init();
1689
1690    len_remained = sel->buflen;
1691    buf = sel->selbuf;
1692
1693    while (len_written < sel->buflen)
1694      {
1695         ret = write(ev->fd, buf, len_remained);
1696         if (ret == -1) break;
1697         buf += ret;
1698         len_written += ret;
1699         len_remained -= ret;
1700      }
1701
1702    close(ev->fd);
1703    return ECORE_CALLBACK_PASS_ON;
1704 }
1705
1706 static Eina_Bool
1707 _wl_selection_receive(void *udata, int type __UNUSED__, void *event)
1708 {
1709    Wl_Cnp_Selection *sel = udata;
1710    Ecore_Wl_Event_Selection_Data_Ready *ev = event;
1711
1712    _wl_elm_cnp_init();
1713
1714    if (sel->requestwidget)
1715      {
1716         if (!ev->done)
1717           {
1718              /* TODO BUG: should never NEVER assume it's an elm_entry! */
1719              _elm_entry_entry_paste(sel->requestwidget, ev->data);
1720           }
1721         else
1722           {
1723              evas_object_event_callback_del_full(sel->requestwidget, EVAS_CALLBACK_DEL,
1724                                                  _wl_sel_obj_del2, sel);
1725              sel->requestwidget = NULL;
1726           }
1727      }
1728
1729    return ECORE_CALLBACK_PASS_ON;
1730 }
1731
1732 static Eina_Bool 
1733 _wl_elm_cnp_init(void)
1734 {
1735    static int _init_count = 0;
1736
1737    if (_init_count > 0) return EINA_TRUE;
1738    _init_count++;
1739
1740    ecore_event_handler_add(ECORE_WL_EVENT_DATA_SOURCE_SEND, 
1741                            _wl_selection_send, &wl_cnp_selection);
1742    ecore_event_handler_add(ECORE_WL_EVENT_SELECTION_DATA_READY, 
1743                            _wl_selection_receive, &wl_cnp_selection);
1744
1745    return EINA_TRUE;
1746 }
1747 #endif
1748
1749
1750
1751
1752
1753
1754 ////////////////////////////////////////////////////////////////////////////
1755 // for local (Within 1 app/process) cnp (used by fb as fallback
1756 ////////////////////////////////////////////////////////////////////////////
1757 #if 1
1758 typedef struct _Local_Selinfo Local_Selinfo;
1759
1760 struct _Local_Selinfo
1761 {
1762    Elm_Sel_Format format;
1763    struct {
1764       void *buf;
1765       size_t size;
1766    } sel;
1767    struct {
1768       Evas_Object *obj;
1769       Elm_Drop_Cb func;
1770       void *data;
1771       Ecore_Job *job;
1772    } get;
1773 };
1774
1775 // for ELM_SEL_TYPE_PRIMARY, ELM_SEL_TYPE_SECONDARY, ELM_SEL_TYPE_XDND,
1776 // ELM_SEL_TYPE_CLIPBOARD
1777 static Local_Selinfo _local_selinfo[4];
1778
1779 static void       _local_get_job(void *data);
1780
1781 static Eina_Bool  _local_elm_cnp_init(void);
1782 static Eina_Bool  _local_elm_cnp_selection_set(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection, Elm_Sel_Format format, const void *selbuf, size_t buflen);
1783 static void       _local_elm_cnp_selection_loss_callback_set(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection __UNUSED__, Elm_Selection_Loss_Cb func __UNUSED__, const void *data __UNUSED__);
1784 static Eina_Bool  _local_elm_object_cnp_selection_clear(Evas_Object *obj __UNUSED__, Elm_Sel_Type selection);
1785 static Eina_Bool  _local_elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection, Elm_Sel_Format format __UNUSED__, Elm_Drop_Cb datacb, void *udata);
1786 static  Eina_Bool _local_elm_drop_target_add(Evas_Object *obj __UNUSED__, Elm_Sel_Type format __UNUSED__, Elm_Drop_Cb dropcb __UNUSED__, void *cbdata __UNUSED__);
1787 static  Eina_Bool _local_elm_drop_target_del(Evas_Object *obj __UNUSED__);
1788 static Eina_Bool  _local_elm_drag_start(Evas_Object *obj __UNUSED__, Elm_Sel_Format format __UNUSED__, const char *data __UNUSED__, void (*dragdone) (void *data, Evas_Object *) __UNUSED__, void *donecbdata __UNUSED__);
1789 static Eina_Bool  _local_elm_selection_selection_has_owner(Evas_Object *obj __UNUSED__);
1790
1791 static void
1792 _local_get_job(void *data)
1793 {
1794    Local_Selinfo *info = data;
1795    Elm_Selection_Data ev;
1796    
1797    info->get.job = NULL;
1798    ev.x = 0;
1799    ev.y = 0;
1800    ev.format = info->format;
1801    ev.data = info->sel.buf;
1802    ev.len = info->sel.size;
1803    if (info->get.func)
1804      info->get.func(info->get.data, info->get.obj, &ev);
1805 }
1806
1807 static Eina_Bool
1808 _local_elm_cnp_init(void)
1809 {
1810    static int _init_count = 0;
1811    
1812    if (_init_count > 0) return EINA_TRUE;
1813    _init_count++;
1814    memset(&(_local_selinfo), 0, sizeof(_local_selinfo));
1815    return EINA_TRUE;
1816 }
1817
1818 static Eina_Bool
1819 _local_elm_cnp_selection_set(Evas_Object *obj __UNUSED__,
1820                              Elm_Sel_Type selection, Elm_Sel_Format format,
1821                              const void *selbuf, size_t buflen)
1822 {
1823    _local_elm_cnp_init();
1824    if (_local_selinfo[selection].sel.buf)
1825      free(_local_selinfo[selection].sel.buf);
1826    _local_selinfo[selection].format = format;
1827    _local_selinfo[selection].sel.buf = malloc(buflen);
1828    if (_local_selinfo[selection].sel.buf)
1829      {
1830         memcpy(_local_selinfo[selection].sel.buf, selbuf, buflen);
1831         _local_selinfo[selection].sel.size = buflen;
1832      }
1833    else
1834      _local_selinfo[selection].sel.size = 0;
1835    return EINA_TRUE;
1836 }
1837
1838 static void
1839 _local_elm_cnp_selection_loss_callback_set(Evas_Object *obj __UNUSED__,
1840                                            Elm_Sel_Type selection __UNUSED__,
1841                                            Elm_Selection_Loss_Cb func __UNUSED__,
1842                                            const void *data __UNUSED__)
1843 {
1844    _local_elm_cnp_init();
1845    // this doesnt need to do anything as we never lose selection to anyone
1846    // as thisis local
1847 }
1848
1849 static Eina_Bool
1850 _local_elm_object_cnp_selection_clear(Evas_Object *obj __UNUSED__,
1851                                       Elm_Sel_Type selection)
1852 {
1853    _local_elm_cnp_init();
1854    if (_local_selinfo[selection].sel.buf)
1855      free(_local_selinfo[selection].sel.buf);
1856    _local_selinfo[selection].sel.buf = NULL;
1857    _local_selinfo[selection].sel.size = 0;
1858    return EINA_TRUE;
1859 }
1860
1861 static Eina_Bool
1862 _local_elm_cnp_selection_get(Evas_Object *obj,
1863                              Elm_Sel_Type selection,
1864                              Elm_Sel_Format format __UNUSED__,
1865                              Elm_Drop_Cb datacb, void *udata)
1866 {
1867    _local_elm_cnp_init();
1868    if (_local_selinfo[selection].get.job)
1869      ecore_job_del(_local_selinfo[selection].get.job);
1870    _local_selinfo[selection].get.obj = obj;
1871    _local_selinfo[selection].get.func = datacb;
1872    _local_selinfo[selection].get.data = udata;
1873    _local_selinfo[selection].get.job = 
1874      ecore_job_add(_local_get_job, &(_local_selinfo[selection]));
1875    return EINA_TRUE;
1876 }
1877
1878 static  Eina_Bool
1879 _local_elm_drop_target_add(Evas_Object *obj __UNUSED__,
1880                            Elm_Sel_Type format __UNUSED__,
1881                            Elm_Drop_Cb dropcb __UNUSED__,
1882                            void *cbdata __UNUSED__)
1883 {
1884    // XXX: implement me
1885    _local_elm_cnp_init();
1886    return EINA_FALSE;
1887 }
1888
1889 static  Eina_Bool
1890 _local_elm_drop_target_del(Evas_Object *obj __UNUSED__)
1891 {
1892    // XXX: implement me
1893    _local_elm_cnp_init();
1894    return EINA_FALSE;
1895 }
1896
1897 static Eina_Bool
1898 _local_elm_drag_start(Evas_Object *obj __UNUSED__,
1899                       Elm_Sel_Format format __UNUSED__,
1900                       const char *data __UNUSED__,
1901                       void (*dragdone) (void *data, Evas_Object *) __UNUSED__,
1902                       void *donecbdata __UNUSED__)
1903 {
1904    // XXX: implement me
1905    _local_elm_cnp_init();
1906    return EINA_FALSE;
1907 }
1908
1909 static Eina_Bool
1910 _local_elm_selection_selection_has_owner(Evas_Object *obj __UNUSED__)
1911 {
1912    _local_elm_cnp_init();
1913    if (_local_selinfo[ELM_SEL_TYPE_CLIPBOARD].sel.buf) return EINA_TRUE;
1914    return EINA_FALSE;
1915 }
1916 #endif
1917
1918
1919
1920
1921
1922
1923 // common internal funcs
1924 ////////////////////////////////////////////////////////////////////////////
1925 static Eina_Bool
1926 _elm_cnp_init(void)
1927 {
1928    if (_elm_cnp_init_count > 0) return EINA_TRUE;
1929    _elm_cnp_init_count++;
1930    text_uri = eina_stringshare_add("text/uri-list");
1931    return EINA_TRUE;
1932 }
1933
1934 /* TODO: this should not be an actual tempfile, but rather encode the object
1935  * as http://dataurl.net/ if it's an image or similar. Evas should support
1936  * decoding it as memfile. */
1937 static Tmp_Info *
1938 _tempfile_new(int size)
1939 {
1940 #ifdef HAVE_MMAN_H
1941    Tmp_Info *info;
1942    const char *tmppath;
1943    mode_t cur_umask;
1944    int len;
1945
1946    info = calloc(1, sizeof(Tmp_Info));
1947    if (!info) return NULL;
1948    tmppath = getenv("TMP");
1949    if (!tmppath) tmppath = P_tmpdir;
1950    len = snprintf(NULL, 0, "%s/%sXXXXXX", tmppath, "elmcnpitem-");
1951    if (len < 0) goto on_error;
1952    len++;
1953    info->filename = malloc(len);
1954    if (!info->filename) goto on_error;
1955    snprintf(info->filename,len,"%s/%sXXXXXX", tmppath, "elmcnpitem-");
1956    cur_umask = umask(S_IRWXO | S_IRWXG);
1957    info->fd = mkstemp(info->filename);
1958    umask(cur_umask);
1959    if (info->fd < 0) goto on_error;
1960 # ifdef __linux__
1961      {
1962         char *tmp;
1963         /* And before someone says anything see POSIX 1003.1-2008 page 400 */
1964         long pid;
1965         
1966         pid = (long)getpid();
1967         /* Use pid instead of /proc/self: That way if can be passed around */
1968         len = snprintf(NULL,0,"/proc/%li/fd/%i", pid, info->fd);
1969         len++;
1970         tmp = malloc(len);
1971         if (tmp)
1972           {
1973              snprintf(tmp,len, "/proc/%li/fd/%i", pid, info->fd);
1974              unlink(info->filename);
1975              free(info->filename);
1976              info->filename = tmp;
1977           }
1978      }
1979 # endif
1980    cnp_debug("filename is %s\n", info->filename);
1981    if (size < 1) goto on_error;
1982    /* Map it in */
1983    if (ftruncate(info->fd, size))
1984      {
1985         perror("ftruncate");
1986         goto on_error;
1987      }
1988    eina_mmap_safety_enabled_set(EINA_TRUE);
1989    info->map = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, info->fd, 0);
1990    if (info->map == MAP_FAILED)
1991      {
1992         perror("mmap");
1993         goto on_error;
1994      }
1995    return info;
1996
1997  on_error:
1998    if (info->fd > 0) close(info->fd);
1999    info->fd = -1;
2000    /* Set map to NULL and return */
2001    info->map = NULL;
2002    info->len = 0;
2003    free(info);
2004    return NULL;
2005 #else
2006    (void) size;
2007    return NULL;
2008 #endif
2009 }
2010
2011 static int
2012 _tmpinfo_free(Tmp_Info *info)
2013 {
2014    if (!info) return 0;
2015    free(info->filename);
2016    free(info);
2017    return 0;
2018 }
2019
2020 static Eina_Bool
2021 _pasteimage_append(char *file, Evas_Object *entry)
2022 {
2023    char *entrytag;
2024    int len;
2025    /* TODO BUG: shouldn't define absize=240x180. Prefer data:// instead of href:// -- may need support for evas. See  http://dataurl.net/ */
2026    static const char *tagstring = "<item absize=240x180 href=file://%s></item>";
2027
2028    if ((!file) || (!entry)) return EINA_FALSE;
2029    len = strlen(tagstring)+strlen(file);
2030    entrytag = alloca(len + 1);
2031    snprintf(entrytag, len + 1, tagstring, file);
2032    /* TODO BUG: should never NEVER assume it's an elm_entry! */
2033    _elm_entry_entry_paste(entry, entrytag);
2034    return EINA_TRUE;
2035 }
2036
2037 // TIZEN ONLY
2038 static void
2039 _entry_insert_filter(Evas_Object *entry, char *str)
2040 {
2041    if (!entry || !str)
2042      return;
2043
2044    char *insertStr = str;
2045
2046    if (elm_entry_single_line_get(entry))
2047      {
2048         Eina_Strbuf *buf = eina_strbuf_new();
2049         if (buf)
2050           {
2051              eina_strbuf_append(buf, insertStr);
2052              eina_strbuf_replace_all(buf, "<br>", "");
2053              eina_strbuf_replace_all(buf, "<br/>", "");
2054              eina_strbuf_replace_all(buf, "<ps/>", "");
2055              insertStr = eina_strbuf_string_steal(buf);
2056              eina_strbuf_free(buf);
2057           }
2058      }
2059    cnp_debug("remove break tag: %s\n", insertStr);
2060
2061    _elm_entry_entry_paste(entry, insertStr);
2062
2063    if (insertStr != str)
2064      free(insertStr);
2065 }
2066 //
2067
2068 ////////////////////////////////////////////////////////////////////////////
2069 ////////////////////////////////////////////////////////////////////////////
2070 ////////////////////////////////////////////////////////////////////////////
2071 // common exposed funcs
2072 ////////////////////////////////////////////////////////////////////////////
2073 ////////////////////////////////////////////////////////////////////////////
2074 ////////////////////////////////////////////////////////////////////////////
2075 EAPI Eina_Bool
2076 elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection,
2077                       Elm_Sel_Format format, const void *selbuf, size_t buflen)
2078 {
2079    if (selection > ELM_SEL_TYPE_CLIPBOARD) return EINA_FALSE;
2080    if (!_elm_cnp_init_count) _elm_cnp_init();
2081 #ifdef HAVE_ELEMENTARY_X
2082    if (_x11_elm_widget_xwin_get(obj))
2083      return _x11_elm_cnp_selection_set(obj, selection, format, selbuf, buflen);
2084 #endif
2085 #ifdef HAVE_ELEMENTARY_WAYLAND
2086    if (elm_win_wl_window_get(obj))
2087       return _wl_elm_cnp_selection_set(obj, selection, format, selbuf, buflen);
2088 #endif
2089    return _local_elm_cnp_selection_set(obj, selection, format, selbuf, buflen);
2090 }
2091
2092 EAPI void
2093 elm_cnp_selection_loss_callback_set(Evas_Object *obj, Elm_Sel_Type selection,
2094                                     Elm_Selection_Loss_Cb func,
2095                                     const void *data)
2096 {
2097    if (selection > ELM_SEL_TYPE_CLIPBOARD) return;
2098    if (!_elm_cnp_init_count) _elm_cnp_init();
2099 #ifdef HAVE_ELEMENTARY_X
2100    if (_x11_elm_widget_xwin_get(obj))
2101      _x11_elm_cnp_selection_loss_callback_set(obj, selection, func, data);
2102 #endif   
2103    _local_elm_cnp_selection_loss_callback_set(obj, selection, func, data);
2104 }
2105
2106 EAPI Eina_Bool
2107 elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection)
2108 {
2109    if (selection > ELM_SEL_TYPE_CLIPBOARD) return EINA_FALSE;
2110    if (!_elm_cnp_init_count) _elm_cnp_init();
2111 #ifdef HAVE_ELEMENTARY_X
2112    if (_x11_elm_widget_xwin_get(obj))
2113      return _x11_elm_object_cnp_selection_clear(obj, selection);
2114 #endif
2115    return _local_elm_object_cnp_selection_clear(obj, selection);
2116 }
2117
2118 EAPI Eina_Bool
2119 elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection,
2120                       Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata)
2121 {
2122    if (selection > ELM_SEL_TYPE_CLIPBOARD) return EINA_FALSE;
2123    if (!_elm_cnp_init_count) _elm_cnp_init();
2124 #ifdef HAVE_ELEMENTARY_X
2125    if (_x11_elm_widget_xwin_get(obj))
2126      return _x11_elm_cnp_selection_get(obj, selection, format, datacb, udata);
2127 #endif
2128 #ifdef HAVE_ELEMENTARY_WAYLAND
2129    if (elm_win_wl_window_get(obj))
2130       return _wl_elm_cnp_selection_get(obj, selection, format, datacb, udata);
2131 #endif
2132    return _local_elm_cnp_selection_get(obj, selection, format, datacb, udata);
2133 }
2134
2135 ////////////////////////////////////////////////////////////////////////////
2136
2137 /**
2138  * Add a widget as drop target.
2139  */
2140 EAPI Eina_Bool
2141 elm_drop_target_add(Evas_Object *obj, Elm_Sel_Type format,
2142                     Elm_Drop_Cb dropcb, void *cbdata)
2143 {
2144    if (!_elm_cnp_init_count) _elm_cnp_init();
2145 #ifdef HAVE_ELEMENTARY_X
2146    if (_x11_elm_widget_xwin_get(obj))
2147      return _x11_elm_drop_target_add(obj, format, dropcb, cbdata);
2148 #endif
2149    return _local_elm_drop_target_add(obj, format, dropcb, cbdata);
2150 }
2151
2152 EAPI Eina_Bool
2153 elm_drop_target_del(Evas_Object *obj)
2154 {
2155    if (!_elm_cnp_init_count) _elm_cnp_init();
2156 #ifdef HAVE_ELEMENTARY_X
2157    if (_x11_elm_widget_xwin_get(obj))
2158      return _x11_elm_drop_target_del(obj);
2159 #endif
2160    return _local_elm_drop_target_del(obj);
2161 }
2162
2163 EAPI Eina_Bool
2164 elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data, 
2165                void (*dragdone) (void *data, Evas_Object *), void *donecbdata)
2166 {
2167    if (!_elm_cnp_init_count) _elm_cnp_init();
2168 #ifdef HAVE_ELEMENTARY_X
2169    if (_x11_elm_widget_xwin_get(obj))
2170      return _x11_elm_drag_start(obj, format, data, dragdone, donecbdata);
2171 #endif
2172    return _local_elm_drag_start(obj, format, data, dragdone, donecbdata);
2173 }
2174
2175 EAPI Eina_Bool
2176 elm_selection_selection_has_owner(Evas_Object *obj)
2177 {
2178    if (!_elm_cnp_init_count) _elm_cnp_init();
2179 #ifdef HAVE_ELEMENTARY_X
2180    if (_x11_elm_widget_xwin_get(obj))
2181      return _x11_elm_selection_selection_has_owner(obj);
2182 #endif
2183 #ifdef HAVE_ELEMENTARY_WAYLAND
2184    if (elm_win_wl_window_get(obj))
2185      return ecore_wl_dnd_selection_has_owner(ecore_wl_dnd_get());
2186 #endif
2187    return _local_elm_selection_selection_has_owner(obj);
2188 }
2189
2190 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0 :*/