c8922d016bd28f89601f44fe00596a398df240df
[platform/upstream/efl.git] / src / lib / ecore_x / xcb / ecore_xcb_selection.c
1 #include "ecore_xcb_private.h"
2 //#include "Ecore_X_Atoms.h"
3
4 #define ECORE_XCB_SELECTION_DATA(x) ((Ecore_X_Selection_Data *)(x))
5
6 /* local function prototypes */
7 static void *_ecore_xcb_selection_parser_text(const char *target EINA_UNUSED,
8                                               void       *data,
9                                               int         size,
10                                               int         format EINA_UNUSED);
11 static void *_ecore_xcb_selection_parser_xmozurl(const char *target EINA_UNUSED,
12                                               void       *data,
13                                               int         size,
14                                               int         format EINA_UNUSED);
15 static void *_ecore_xcb_selection_parser_files(const char *target,
16                                                void       *data,
17                                                int         size,
18                                                int         format EINA_UNUSED);
19 static void *_ecore_xcb_selection_parser_targets(const char *target EINA_UNUSED,
20                                                  void       *data,
21                                                  int         size,
22                                                  int         format EINA_UNUSED);
23
24 //static int _ecore_xcb_selection_data_free(void *data);
25 static int       _ecore_xcb_selection_data_text_free(void *data);
26 static int       _ecore_xcb_selection_data_targets_free(void *data);
27 static int       _ecore_xcb_selection_data_files_free(void *data);
28 static int       _ecore_xcb_selection_data_default_free(void *data);
29 static Eina_Bool _ecore_xcb_selection_set(Ecore_X_Window win,
30                                           const void    *data,
31                                           int            size,
32                                           Ecore_X_Atom   selection);
33 static void _ecore_xcb_selection_request(Ecore_X_Window win,
34                                          Ecore_X_Atom   selection,
35                                          const char    *target);
36 static Ecore_X_Atom _ecore_xcb_selection_target_atom_get(const char *target);
37
38 /* local variables */
39 static Ecore_X_Selection_Intern _selections[4];
40 static Ecore_X_Selection_Converter *_converters = NULL;
41 static Ecore_X_Selection_Parser *_parsers = NULL;
42
43 /* local functions */
44 void
45 _ecore_xcb_selection_init(void)
46 {
47    LOGFN(__FILE__, __LINE__, __FUNCTION__);
48
49    memset(_selections, 0, sizeof(_selections));
50
51    /* init converters */
52    ecore_x_selection_converter_atom_add(ECORE_X_ATOM_TEXT,
53                                         ecore_x_selection_converter_text);
54    ecore_x_selection_converter_atom_add(ECORE_X_ATOM_UTF8_STRING,
55                                         ecore_x_selection_converter_text);
56    ecore_x_selection_converter_atom_add(ECORE_X_ATOM_COMPOUND_TEXT,
57                                         ecore_x_selection_converter_text);
58    ecore_x_selection_converter_atom_add(ECORE_X_ATOM_STRING,
59                                         ecore_x_selection_converter_text);
60
61    /* init parsers */
62    ecore_x_selection_parser_add("text/plain",
63                                 _ecore_xcb_selection_parser_text);
64    ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_UTF8_STRING,
65                                 _ecore_xcb_selection_parser_text);
66    ecore_x_selection_parser_add("text/uri-list",
67                                 _ecore_xcb_selection_parser_files);
68    ecore_x_selection_parser_add("text/x-moz-url",
69                                 _ecore_xcb_selection_parser_xmozurl);
70    ecore_x_selection_parser_add("_NETSCAPE_URL",
71                                 _ecore_xcb_selection_parser_files);
72    ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_TARGETS,
73                                 _ecore_xcb_selection_parser_targets);
74 }
75
76 void
77 _ecore_xcb_selection_shutdown(void)
78 {
79    Ecore_X_Selection_Converter *cnv;
80    Ecore_X_Selection_Parser *prs;
81
82    LOGFN(__FILE__, __LINE__, __FUNCTION__);
83
84    /* free selection converters */
85    cnv = _converters;
86    while (cnv)
87      {
88         Ecore_X_Selection_Converter *tmp;
89
90         tmp = cnv->next;
91         free(cnv);
92         cnv = tmp;
93      }
94    _converters = NULL;
95
96    /* free parsers */
97    prs = _parsers;
98    while (prs)
99      {
100         Ecore_X_Selection_Parser *tmp;
101
102         tmp = prs;
103         prs = prs->next;
104         free(tmp->target);
105         free(tmp);
106      }
107    _parsers = NULL;
108 }
109
110 /* public functions */
111 EAPI void
112 ecore_x_selection_converter_atom_add(Ecore_X_Atom                                          target,
113                                      Eina_Bool                                             (*func)(char *target,
114                                                                              void         *data,
115                                                                              int           size,
116                                                                              void        **data_ret,
117                                                                              int          *size_ret,
118                                                                              Ecore_X_Atom *type,
119                                                                              int          *size_type))
120 {
121    Ecore_X_Selection_Converter *cnv;
122
123    LOGFN(__FILE__, __LINE__, __FUNCTION__);
124
125    cnv = _converters;
126    if (_converters)
127      {
128         while (1)
129           {
130              if (cnv->target == target)
131                {
132                   cnv->convert = func;
133                   return;
134                }
135              if (cnv->next)
136                cnv = cnv->next;
137              else
138                break;
139           }
140         cnv->next = calloc(1, sizeof(Ecore_X_Selection_Converter));
141         if (!cnv->next) return;
142         cnv = cnv->next;
143      }
144    else
145      {
146         _converters = calloc(1, sizeof(Ecore_X_Selection_Converter));
147         if (!_converters) return;
148         cnv = _converters;
149      }
150    cnv->target = target;
151    cnv->convert = func;
152 }
153
154 EAPI void
155 ecore_x_selection_converter_add(char                                                 *target,
156                                 Eina_Bool                                             (*func)(char *target,
157                                                                         void         *data,
158                                                                         int           size,
159                                                                         void        **date_ret,
160                                                                         int          *size_ret,
161                                                                         Ecore_X_Atom *atom_ret,
162                                                                         int          *ret))
163 {
164    Ecore_X_Atom atarget;
165
166    LOGFN(__FILE__, __LINE__, __FUNCTION__);
167
168    if ((!func) || (!target)) return;
169    atarget = _ecore_xcb_selection_target_atom_get(target);
170    ecore_x_selection_converter_atom_add(atarget, func);
171 }
172
173 EAPI void
174 ecore_x_selection_converter_del(char *target)
175 {
176    Ecore_X_Atom atarget;
177
178    LOGFN(__FILE__, __LINE__, __FUNCTION__);
179
180    if (!target) return;
181    atarget = _ecore_xcb_selection_target_atom_get(target);
182    ecore_x_selection_converter_atom_del(atarget);
183 }
184
185 EAPI void
186 ecore_x_selection_converter_atom_del(Ecore_X_Atom target)
187 {
188    Ecore_X_Selection_Converter *conv, *pconv = NULL;
189
190    LOGFN(__FILE__, __LINE__, __FUNCTION__);
191
192    conv = _converters;
193    while (conv)
194      {
195         if (conv->target == target)
196           {
197              if (pconv)
198                pconv->next = conv->next;
199              else
200                _converters = conv->next;
201              free(conv);
202              return;
203           }
204         pconv = conv;
205         conv = conv->next;
206      }
207 }
208
209 EAPI void
210 ecore_x_selection_parser_add(const char *target,
211                              void *(*func)(const char *target, void *data, int size, int format))
212 {
213    Ecore_X_Selection_Parser *prs;
214
215    LOGFN(__FILE__, __LINE__, __FUNCTION__);
216
217    if (!target) return;
218    prs = _parsers;
219    if (prs)
220      {
221         while (prs->next)
222           {
223              if (!strcmp(prs->target, target))
224                {
225                   prs->parse = func;
226                   return;
227                }
228              prs = prs->next;
229           }
230         prs->next = calloc(1, sizeof(Ecore_X_Selection_Parser));
231         prs = prs->next;
232      }
233    else
234      {
235         _parsers = calloc(1, sizeof(Ecore_X_Selection_Parser));
236         prs = _parsers;
237      }
238    prs->target = strdup(target);
239    prs->parse = func;
240 }
241
242 EAPI void
243 ecore_x_selection_parser_del(const char *target)
244 {
245    Ecore_X_Selection_Parser *prs, *pprs = NULL;
246
247    LOGFN(__FILE__, __LINE__, __FUNCTION__);
248
249    if (!target) return;
250
251    prs = _parsers;
252    while (prs)
253      {
254         if (!strcmp(prs->target, target))
255           {
256              if (pprs)
257                pprs->next = prs->next;
258              else
259                _parsers = prs->next;
260              free(prs->target);
261              free(prs);
262              return;
263           }
264         pprs = prs;
265         prs = prs->next;
266      }
267 }
268
269 /**
270  * Claim ownership of the PRIMARY selection and set its data.
271  * @param w    The window to which this selection belongs
272  * @param data The data associated with the selection
273  * @param size The size of the data buffer in bytes
274  * @return     Returns 1 if the ownership of the selection was successfully
275  *             claimed, or 0 if unsuccessful.
276  */
277 EAPI Eina_Bool
278 ecore_x_selection_primary_set(Ecore_X_Window win,
279                               const void    *data,
280                               int            size)
281 {
282    LOGFN(__FILE__, __LINE__, __FUNCTION__);
283
284    return _ecore_xcb_selection_set(win, data, size,
285                                    ECORE_X_ATOM_SELECTION_PRIMARY);
286 }
287
288 /**
289  * Release ownership of the primary selection
290  * @return     Returns 1 if the selection was successfully cleared,
291  *             or 0 if unsuccessful.
292  */
293 EAPI Eina_Bool
294 ecore_x_selection_primary_clear(void)
295 {
296    LOGFN(__FILE__, __LINE__, __FUNCTION__);
297
298    return _ecore_xcb_selection_set(XCB_NONE, NULL, 0,
299                                    ECORE_X_ATOM_SELECTION_PRIMARY);
300 }
301
302 EAPI void
303 ecore_x_selection_primary_request(Ecore_X_Window win,
304                                   const char    *target)
305 {
306    LOGFN(__FILE__, __LINE__, __FUNCTION__);
307
308    _ecore_xcb_selection_request(win, ECORE_X_ATOM_SELECTION_PRIMARY, target);
309 }
310
311 /**
312  * Claim ownership of the SECONDARY selection and set its data.
313  * @param w    The window to which this selection belongs
314  * @param data The data associated with the selection
315  * @param size The size of the data buffer in bytes
316  * @return     Returns 1 if the ownership of the selection was successfully
317  *             claimed, or 0 if unsuccessful.
318  */
319 EAPI Eina_Bool
320 ecore_x_selection_secondary_set(Ecore_X_Window win,
321                                 const void    *data,
322                                 int            size)
323 {
324    LOGFN(__FILE__, __LINE__, __FUNCTION__);
325
326    return _ecore_xcb_selection_set(win, data, size,
327                                    ECORE_X_ATOM_SELECTION_SECONDARY);
328 }
329
330 /**
331  * Release ownership of the secondary selection
332  * @return     Returns 1 if the selection was successfully cleared,
333  *             or 0 if unsuccessful.
334  */
335 EAPI Eina_Bool
336 ecore_x_selection_secondary_clear(void)
337 {
338    LOGFN(__FILE__, __LINE__, __FUNCTION__);
339
340    return _ecore_xcb_selection_set(XCB_NONE, NULL, 0,
341                                    ECORE_X_ATOM_SELECTION_SECONDARY);
342 }
343
344 EAPI void
345 ecore_x_selection_secondary_request(Ecore_X_Window win,
346                                     const char    *target)
347 {
348    LOGFN(__FILE__, __LINE__, __FUNCTION__);
349
350    _ecore_xcb_selection_request(win, ECORE_X_ATOM_SELECTION_SECONDARY, target);
351 }
352
353 /**
354  * Claim ownership of the XDND selection and set its data.
355  * @param w    The window to which this selection belongs
356  * @param data The data associated with the selection
357  * @param size The size of the data buffer in bytes
358  * @return     Returns 1 if the ownership of the selection was successfully
359  *             claimed, or 0 if unsuccessful.
360  */
361 EAPI Eina_Bool
362 ecore_x_selection_xdnd_set(Ecore_X_Window win,
363                            const void    *data,
364                            int            size)
365 {
366    LOGFN(__FILE__, __LINE__, __FUNCTION__);
367
368    return _ecore_xcb_selection_set(win, data, size,
369                                    ECORE_X_ATOM_SELECTION_XDND);
370 }
371
372 /**
373  * Release ownership of the XDND selection
374  * @return     Returns 1 if the selection was successfully cleared,
375  *             or 0 if unsuccessful.
376  */
377 EAPI Eina_Bool
378 ecore_x_selection_xdnd_clear(void)
379 {
380    LOGFN(__FILE__, __LINE__, __FUNCTION__);
381
382    return _ecore_xcb_selection_set(XCB_NONE, NULL, 0,
383                                    ECORE_X_ATOM_SELECTION_XDND);
384 }
385
386 EAPI void
387 ecore_x_selection_xdnd_request(Ecore_X_Window win,
388                                const char    *target)
389 {
390    Ecore_X_Atom atom;
391    Ecore_X_DND_Target *_target;
392
393    LOGFN(__FILE__, __LINE__, __FUNCTION__);
394    CHECK_XCB_CONN;
395
396    _target = _ecore_xcb_dnd_target_get();
397    atom = _ecore_xcb_selection_target_atom_get(target);
398
399    xcb_convert_selection(_ecore_xcb_conn, win, ECORE_X_ATOM_SELECTION_XDND,
400                          atom, ECORE_X_ATOM_SELECTION_PROP_XDND, _target->time);
401 }
402
403 /**
404  * Claim ownership of the CLIPBOARD selection and set its data.
405  * @param w    The window to which this selection belongs
406  * @param data The data associated with the selection
407  * @param size The size of the data buffer in bytes
408  * @return     Returns 1 if the ownership of the selection was successfully
409  *             claimed, or 0 if unsuccessful.
410  *
411  * Get the converted data from a previous CLIPBOARD selection
412  * request. The buffer must be freed when done with.
413  */
414 EAPI Eina_Bool
415 ecore_x_selection_clipboard_set(Ecore_X_Window win,
416                                 const void    *data,
417                                 int            size)
418 {
419    LOGFN(__FILE__, __LINE__, __FUNCTION__);
420
421    return _ecore_xcb_selection_set(win, data, size,
422                                    ECORE_X_ATOM_SELECTION_CLIPBOARD);
423 }
424
425 /**
426  * Release ownership of the clipboard selection
427  * @return     Returns 1 if the selection was successfully cleared,
428  *             or 0 if unsuccessful.
429  */
430 EAPI Eina_Bool
431 ecore_x_selection_clipboard_clear(void)
432 {
433    LOGFN(__FILE__, __LINE__, __FUNCTION__);
434
435    return _ecore_xcb_selection_set(XCB_NONE, NULL, 0,
436                                    ECORE_X_ATOM_SELECTION_CLIPBOARD);
437 }
438
439 EAPI void
440 ecore_x_selection_clipboard_request(Ecore_X_Window win,
441                                     const char    *target)
442 {
443    LOGFN(__FILE__, __LINE__, __FUNCTION__);
444
445    _ecore_xcb_selection_request(win, ECORE_X_ATOM_SELECTION_CLIPBOARD, target);
446 }
447
448 EAPI Eina_Bool
449 ecore_x_selection_convert(Ecore_X_Atom  selection,
450                           Ecore_X_Atom  target,
451                           void        **data_ret,
452                           int          *size,
453                           Ecore_X_Atom *targtype,
454                           int          *typesize)
455 {
456    Ecore_X_Selection_Intern *sel;
457    Ecore_X_Selection_Converter *cnv;
458    void *data = NULL;
459    char *tgt_str;
460
461    LOGFN(__FILE__, __LINE__, __FUNCTION__);
462
463    sel = _ecore_xcb_selection_get(selection);
464    tgt_str = _ecore_xcb_selection_target_get(target);
465
466    for (cnv = _converters; cnv; cnv = cnv->next)
467      {
468         if (cnv->target == target)
469           {
470              int r;
471
472              r = cnv->convert(tgt_str, sel->data, sel->length, &data, size,
473                               targtype, typesize);
474              free(tgt_str);
475              if (r)
476                {
477                   if (data_ret) *data_ret = data;
478                   return r;
479                }
480              else
481                return EINA_FALSE;
482           }
483      }
484    free(tgt_str);
485
486    return EINA_FALSE;
487 }
488
489 EAPI Eina_Bool
490 ecore_x_selection_notify_send(Ecore_X_Window requestor,
491                               Ecore_X_Atom   selection,
492                               Ecore_X_Atom   target,
493                               Ecore_X_Atom   property,
494                               Ecore_X_Time   tim)
495 {
496    xcb_selection_notify_event_t ev;
497
498    LOGFN(__FILE__, __LINE__, __FUNCTION__);
499    CHECK_XCB_CONN;
500
501    memset(&ev, 0, sizeof(xcb_selection_notify_event_t));
502
503    ev.response_type = XCB_SELECTION_NOTIFY;
504    ev.requestor = requestor;
505    ev.selection = selection;
506    ev.target = target;
507    ev.property = property;
508    ev.time = tim;
509
510    xcb_send_event(_ecore_xcb_conn, 0, requestor,
511                   XCB_EVENT_MASK_NO_EVENT, (const char *)&ev);
512 //   ecore_x_flush();
513
514    return EINA_TRUE;
515 }
516
517 EAPI void
518 ecore_x_selection_owner_set(Ecore_X_Window win,
519                             Ecore_X_Atom   atom,
520                             Ecore_X_Time   tim)
521 {
522    LOGFN(__FILE__, __LINE__, __FUNCTION__);
523    CHECK_XCB_CONN;
524
525    xcb_set_selection_owner(_ecore_xcb_conn, win, atom, tim);
526 }
527
528 EAPI Ecore_X_Window
529 ecore_x_selection_owner_get(Ecore_X_Atom atom)
530 {
531    xcb_get_selection_owner_cookie_t cookie;
532    xcb_get_selection_owner_reply_t *reply;
533    Ecore_X_Window ret;
534
535    LOGFN(__FILE__, __LINE__, __FUNCTION__);
536    CHECK_XCB_CONN;
537
538    cookie = xcb_get_selection_owner(_ecore_xcb_conn, atom);
539    reply = xcb_get_selection_owner_reply(_ecore_xcb_conn, cookie, NULL);
540    if (!reply) return 0;
541    ret = reply->owner;
542    free(reply);
543    return ret;
544 }
545
546 void *
547 _ecore_xcb_selection_parse(const char *target,
548                            void       *data,
549                            int         size,
550                            int         format)
551 {
552    Ecore_X_Selection_Parser *prs;
553    Ecore_X_Selection_Data *sel;
554
555    for (prs = _parsers; prs; prs = prs->next)
556      {
557         if (!strcmp(prs->target, target))
558           {
559              sel = prs->parse(target, data, size, format);
560              if (sel) return sel;
561           }
562      }
563
564    sel = calloc(1, sizeof(Ecore_X_Selection_Data));
565    if (!sel) return NULL;
566    sel->free = _ecore_xcb_selection_data_default_free;
567    sel->length = size;
568    sel->format = format;
569    sel->data = data;
570
571    return sel;
572 }
573
574 Ecore_X_Selection_Intern *
575 _ecore_xcb_selection_get(Ecore_X_Atom selection)
576 {
577    if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
578      return &_selections[0];
579    else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
580      return &_selections[1];
581    else if (selection == ECORE_X_ATOM_SELECTION_XDND)
582      return &_selections[2];
583    else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
584      return &_selections[3];
585    else
586      return NULL;
587 }
588
589 /* local functions */
590 static Eina_Bool
591 _ecore_xcb_selection_set(Ecore_X_Window win,
592                          const void    *data,
593                          int            size,
594                          Ecore_X_Atom   selection)
595 {
596    xcb_get_selection_owner_cookie_t cookie;
597    xcb_get_selection_owner_reply_t *reply;
598    int in = 0;
599
600    LOGFN(__FILE__, __LINE__, __FUNCTION__);
601    CHECK_XCB_CONN;
602
603    xcb_set_selection_owner(_ecore_xcb_conn, win, selection, XCB_CURRENT_TIME);
604
605    cookie = xcb_get_selection_owner(_ecore_xcb_conn, selection);
606    reply = xcb_get_selection_owner_reply(_ecore_xcb_conn, cookie, NULL);
607    if (!reply) return EINA_FALSE;
608
609    if (reply->owner != win)
610      {
611         free(reply);
612         return EINA_FALSE;
613      }
614    free(reply);
615
616    if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
617      in = 0;
618    else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
619      in = 1;
620    else if (selection == ECORE_X_ATOM_SELECTION_XDND)
621      in = 2;
622    else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
623      in = 3;
624    else
625      return EINA_FALSE;
626
627    if (_selections[in].data)
628      {
629         free(_selections[in].data);
630         memset(&_selections[in], 0, sizeof(Ecore_X_Selection_Intern));
631      }
632
633    if (data)
634      {
635         unsigned char *buff = NULL;
636
637         _selections[in].win = win;
638         _selections[in].selection = selection;
639         _selections[in].length = size;
640         _selections[in].time = _ecore_xcb_events_last_time_get();
641
642         buff = malloc(size);
643         if (!buff) return EINA_FALSE;
644         memcpy(buff, data, size);
645         _selections[in].data = buff;
646      }
647
648    return EINA_TRUE;
649 }
650
651 static void
652 _ecore_xcb_selection_request(Ecore_X_Window win,
653                              Ecore_X_Atom   selection,
654                              const char    *target)
655 {
656    Ecore_X_Atom atarget, prop;
657
658    LOGFN(__FILE__, __LINE__, __FUNCTION__);
659    CHECK_XCB_CONN;
660
661    if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
662      prop = ECORE_X_ATOM_SELECTION_PROP_PRIMARY;
663    else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
664      prop = ECORE_X_ATOM_SELECTION_PROP_SECONDARY;
665    else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
666      prop = ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD;
667    else
668      return;
669
670    atarget = _ecore_xcb_selection_target_atom_get(target);
671
672    xcb_convert_selection(_ecore_xcb_conn, win, selection, atarget, prop,
673                          XCB_CURRENT_TIME);
674 }
675
676 EAPI Eina_Bool
677 ecore_x_selection_converter_text(char         *target,
678                                  void         *data,
679                                  int           size,
680                                  void        **data_ret,
681                                  int          *size_ret,
682                                  Ecore_X_Atom *type EINA_UNUSED,
683                                  int          *size_type EINA_UNUSED)
684 {
685    Ecore_Xcb_Encoding_Style style;
686    Ecore_Xcb_Textproperty ret;
687    char *str;
688
689    LOGFN(__FILE__, __LINE__, __FUNCTION__);
690    CHECK_XCB_CONN;
691
692    if ((!data) || (!size)) return EINA_FALSE;
693
694    if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
695      style = XcbTextStyle;
696    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
697      style = XcbCompoundTextStyle;
698    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
699      style = XcbStringStyle;
700 #ifdef HAVE_ICONV
701    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
702      style = XcbUTF8StringStyle;
703 #endif
704    else
705      return EINA_FALSE;
706
707    str = alloca(size + 1);
708    memcpy(str, data, size);
709    str[size] = '\0';
710
711 #ifdef HAVE_ICONV
712    if (_ecore_xcb_utf8_textlist_to_textproperty(&str, 1, style, &ret))
713      {
714         int size = 0;
715
716         size = (strlen((char *)ret.value));
717         *data_ret = malloc(size);
718         if (!*data_ret) return EINA_FALSE;
719         memcpy(*data_ret, ret.value, size);
720         *size_ret = size;
721         if (ret.value) free(ret.value);
722         return EINA_TRUE;
723      }
724 #else
725    if (_ecore_xcb_mb_textlist_to_textproperty(&str, 1, style, &ret))
726      {
727         int size = 0;
728
729         size = (strlen((char *)ret.value));
730         *data_ret = malloc(size);
731         if (!*data_ret) return EINA_FALSE;
732         memcpy(*data_ret, ret.value, size);
733         *size_ret = size;
734         if (ret.value) free(ret.value);
735         return EINA_TRUE;
736      }
737 #endif
738    else
739      return EINA_TRUE;
740 }
741
742 static void *
743 _ecore_xcb_selection_parser_text(const char *target EINA_UNUSED,
744                                  void       *data,
745                                  int         size,
746                                  int         format EINA_UNUSED)
747 {
748    Ecore_X_Selection_Data_Text *sel;
749    unsigned char *_data;
750    void *t;
751
752    LOGFN(__FILE__, __LINE__, __FUNCTION__);
753
754    if (!(_data = data)) return NULL;
755
756    sel = calloc(1, sizeof(Ecore_X_Selection_Data_Text));
757    if (!sel) return NULL;
758
759    if (_data && _data[size - 1])
760      {
761         size++;
762         t = realloc(_data, size);
763         if (!t)
764           {
765              free(sel);
766              return NULL;
767           }
768         _data = t;
769         _data[size - 1] = 0;
770      }
771    sel->text = (char *)_data;
772    ECORE_XCB_SELECTION_DATA(sel)->length = size;
773    ECORE_XCB_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TEXT;
774    ECORE_XCB_SELECTION_DATA(sel)->data = _data;
775    ECORE_XCB_SELECTION_DATA(sel)->free = _ecore_xcb_selection_data_text_free;
776    return sel;
777 }
778
779 static int
780 _ecore_xcb_selection_data_xmozurl_free(void *data)
781 {
782    Ecore_X_Selection_Data_X_Moz_Url *sel = data;
783    char **buf;
784
785    LOGFN(__FILE__, __LINE__, __FUNCTION__);
786    if (!sel) return 0;
787
788    buf = eina_inarray_nth(sel->links, 0);
789    free(*buf);
790    eina_inarray_free(sel->links);
791    eina_inarray_free(sel->link_names);
792    free(sel);
793    return 1;
794 }
795
796 static void *
797 _ecore_xcb_selection_parser_xmozurl(const char *target EINA_UNUSED,
798                                void *_data,
799                                int size,
800                                int format EINA_UNUSED)
801 {
802    Ecore_X_Selection_Data_X_Moz_Url *sel;
803    char *prev, *n, *buf, *data = _data;
804    size_t sz;
805    int num = 0;
806
807    LOGFN(__FILE__, __LINE__, __FUNCTION__);
808
809    buf = eina_str_convert_len("UTF-16LE", "UTF-8", data, size, &sz);
810    if (!buf) return NULL;
811    sel = calloc(1, sizeof(Ecore_X_Selection_Data_X_Moz_Url));
812    if (!sel)
813      goto error_sel;
814
815    sel->links = eina_inarray_new(sizeof(char*), 0);
816    if (!sel->links)
817      goto error_links;
818
819    sel->link_names = eina_inarray_new(sizeof(char*), 0);
820    if (!sel->link_names)
821      goto error_link_names;
822    prev = buf;
823    for (n = memchr(buf, '\n', sz); n; n = memchr(prev, '\n', sz - (prev - buf)))
824      {
825         n[0] = 0;
826         if (num % 2 == 0)
827           eina_inarray_push(sel->links, &prev);
828         else
829           eina_inarray_push(sel->link_names, &prev);
830         num++;
831         prev = n + 1;
832      }
833    eina_inarray_push(sel->link_names, &prev[0]);
834
835    ECORE_XCB_SELECTION_DATA(sel)->length = size;
836    ECORE_XCB_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_X_MOZ_URL;
837    ECORE_XCB_SELECTION_DATA(sel)->data = (void*)data;
838    ECORE_XCB_SELECTION_DATA(sel)->free = _ecore_xcb_selection_data_xmozurl_free;
839    return sel;
840
841 error_link_names:
842    eina_inarray_free(sel->links);
843
844 error_links:
845    free(sel);
846
847 error_sel:
848    free(buf);
849    return NULL;
850 }
851
852 static void *
853 _ecore_xcb_selection_parser_files(const char *target,
854                                   void       *data,
855                                   int         size,
856                                   int         format EINA_UNUSED)
857 {
858    Ecore_X_Selection_Data_Files *sel;
859    char *_data, *tmp, *t, **t2;
860    int i = 0, is = 0;
861
862    LOGFN(__FILE__, __LINE__, __FUNCTION__);
863
864    if ((strcmp(target, "text/uri-list")) &&
865        (strcmp(target, "_NETSCAPE_URL"))) return NULL;
866
867    if (!(_data = data)) return NULL;
868
869    sel = calloc(1, sizeof(Ecore_X_Selection_Data_Files));
870    if (!sel) return NULL;
871
872    ECORE_XCB_SELECTION_DATA(sel)->free = _ecore_xcb_selection_data_files_free;
873
874    if (_data && _data[size - 1])
875      {
876         size++;
877         t = realloc(_data, size);
878         if (!t)
879           {
880              free(sel);
881              return NULL;
882           }
883         _data = t;
884         _data[size - 1] = 0;
885      }
886
887    tmp = malloc(size);
888    if (!tmp)
889      {
890         free(sel);
891         return NULL;
892      }
893
894    while ((is < size) && (_data[is]))
895      {
896         if ((i == 0) && (_data[is] == '#'))
897           {
898              for (; ((_data[is]) && (_data[is] != '\n')); is++) ;
899           }
900         else
901           {
902              if ((_data[is] != '\r') && (_data[is] != '\n'))
903                tmp[i++] = _data[is++];
904              else
905                {
906                   while ((_data[is] == '\r') || (_data[is] == '\n'))
907                     is++;
908                   tmp[i] = 0;
909                   sel->num_files++;
910                   t2 = realloc(sel->files, sel->num_files * sizeof(char *));
911                   if (t2)
912                     {
913                        sel->files = t2;
914                        sel->files[sel->num_files - 1] = strdup(tmp);
915                     }
916                   tmp[0] = 0;
917                   i = 0;
918                }
919           }
920      }
921    if (i > 0)
922      {
923         tmp[i] = 0;
924         sel->num_files++;
925         t2 = realloc(sel->files, sel->num_files * sizeof(char *));
926         if (t2)
927           {
928              sel->files = t2;
929              sel->files[sel->num_files - 1] = strdup(tmp);
930           }
931      }
932    if (tmp) free(tmp);
933    if (_data) free(_data);
934
935    ECORE_XCB_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_FILES;
936    ECORE_XCB_SELECTION_DATA(sel)->length = sel->num_files;
937
938    return ECORE_XCB_SELECTION_DATA(sel);
939 }
940
941 static void *
942 _ecore_xcb_selection_parser_targets(const char *target EINA_UNUSED,
943                                     void       *data,
944                                     int         size,
945                                     int         format EINA_UNUSED)
946 {
947    Ecore_X_Selection_Data_Targets *sel;
948    int *targets;
949    int i = 0;
950
951    LOGFN(__FILE__, __LINE__, __FUNCTION__);
952    CHECK_XCB_CONN;
953
954    if (!(targets = data)) return NULL;
955
956    sel = calloc(1, sizeof(Ecore_X_Selection_Data_Targets));
957    if (!sel) return NULL;
958
959    sel->num_targets = (size - 2);
960    sel->targets = malloc((size - 2) * sizeof(char *));
961    if (!sel->targets)
962      {
963         free(sel);
964         return NULL;
965      }
966
967    for (i = 2; i < size; i++)
968      {
969         xcb_get_atom_name_cookie_t cookie;
970         xcb_get_atom_name_reply_t *reply;
971         char *name = NULL;
972         int len = 0;
973
974         cookie = xcb_get_atom_name_unchecked(_ecore_xcb_conn, targets[i]);
975         reply = xcb_get_atom_name_reply(_ecore_xcb_conn, cookie, NULL);
976         if (reply)
977           {
978              len = xcb_get_atom_name_name_length(reply);
979              name = (char *)malloc(sizeof(char) * (len + 1));
980              if (name)
981                {
982                   memcpy(name, xcb_get_atom_name_name(reply), len);
983                   name[len] = '\0';
984                   sel->targets[i - 2] = name;
985                }
986              free(reply);
987           }
988      }
989
990    ECORE_XCB_SELECTION_DATA(sel)->free =
991      _ecore_xcb_selection_data_targets_free;
992    ECORE_XCB_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TARGETS;
993    ECORE_XCB_SELECTION_DATA(sel)->length = size;
994    ECORE_XCB_SELECTION_DATA(sel)->data = data;
995
996    return sel;
997 }
998
999 /*
1000    static int
1001    _ecore_xcb_selection_data_free(void *data)
1002    {
1003    Ecore_X_Selection_Data *sel;
1004
1005    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1006
1007    if (!(sel = data)) return 0;
1008    if (sel->data) free(sel->data);
1009    free(sel);
1010    return 1;
1011    }
1012  */
1013
1014 static int
1015 _ecore_xcb_selection_data_text_free(void *data)
1016 {
1017    Ecore_X_Selection_Data_Text *sel;
1018
1019    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1020
1021    if (!(sel = data)) return 0;
1022    if (sel->text) free(sel->text);
1023    free(sel);
1024    return 1;
1025 }
1026
1027 static int
1028 _ecore_xcb_selection_data_targets_free(void *data)
1029 {
1030    Ecore_X_Selection_Data_Targets *sel;
1031
1032    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1033
1034    if (!(sel = data)) return 0;
1035    if (sel->targets) free(sel->targets);
1036    free(ECORE_XCB_SELECTION_DATA(sel)->data);
1037    free(sel);
1038    return 1;
1039 }
1040
1041 static int
1042 _ecore_xcb_selection_data_files_free(void *data)
1043 {
1044    Ecore_X_Selection_Data_Files *sel;
1045
1046    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1047
1048    if (!(sel = data)) return 0;
1049    if (sel->files)
1050      {
1051         int i = 0;
1052
1053         for (i = 0; i < sel->num_files; i++)
1054           if (sel->files[i]) free(sel->files[i]);
1055         if (sel->files) free(sel->files);
1056      }
1057    free(sel);
1058    return 0;
1059 }
1060
1061 static int
1062 _ecore_xcb_selection_data_default_free(void *data)
1063 {
1064    Ecore_X_Selection_Data *sel;
1065
1066    if (!(sel = data)) return 1;
1067    free(sel->data);
1068    free(sel);
1069    return 1;
1070 }
1071
1072 static Ecore_X_Atom
1073 _ecore_xcb_selection_target_atom_get(const char *target)
1074 {
1075    Ecore_X_Atom x_target;
1076
1077    if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
1078      x_target = ECORE_X_ATOM_TEXT;
1079    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
1080      x_target = ECORE_X_ATOM_COMPOUND_TEXT;
1081    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
1082      x_target = ECORE_X_ATOM_STRING;
1083    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
1084      x_target = ECORE_X_ATOM_UTF8_STRING;
1085    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_FILENAME))
1086      x_target = ECORE_X_ATOM_FILE_NAME;
1087    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_X_MOZ_URL))
1088      x_target = ECORE_X_ATOM_X_MOZ_URL;
1089    else
1090      x_target = ecore_x_atom_get(target);
1091
1092    return x_target;
1093 }
1094
1095 char *
1096 _ecore_xcb_selection_target_get(Ecore_X_Atom target)
1097 {
1098    if (target == ECORE_X_ATOM_FILE_NAME)
1099      return strdup(ECORE_X_SELECTION_TARGET_FILENAME);
1100    else if (target == ECORE_X_ATOM_STRING)
1101      return strdup(ECORE_X_SELECTION_TARGET_STRING);
1102    else if (target == ECORE_X_ATOM_UTF8_STRING)
1103      return strdup(ECORE_X_SELECTION_TARGET_UTF8_STRING);
1104    else if (target == ECORE_X_ATOM_TEXT)
1105      return strdup(ECORE_X_SELECTION_TARGET_TEXT);
1106    else if (target == ECORE_X_ATOM_X_MOZ_URL)
1107      return strdup(ECORE_X_SELECTION_TARGET_X_MOZ_URL);
1108    else
1109      return ecore_x_atom_name_get(target);
1110 }
1111