afb1b8c9a721186fd2d0c2ae39e5584d1a29f577
[framework/uifw/ecore.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 Eina_Bool _ecore_xcb_selection_converter_text(char         *target,
8                                                      void         *data,
9                                                      int           size,
10                                                      void        **data_ret,
11                                                      int          *size_ret,
12                                                      Ecore_X_Atom *type,
13                                                      int          *size_type);
14 static void *_ecore_xcb_selection_parser_text(const char *target __UNUSED__,
15                                               void       *data,
16                                               int         size,
17                                               int         format __UNUSED__);
18 static void *_ecore_xcb_selection_parser_files(const char *target,
19                                                void       *data,
20                                                int         size,
21                                                int         format __UNUSED__);
22 static void *_ecore_xcb_selection_parser_targets(const char *target __UNUSED__,
23                                                  void       *data,
24                                                  int         size,
25                                                  int         format __UNUSED__);
26
27 //static int _ecore_xcb_selection_data_free(void *data);
28 static int       _ecore_xcb_selection_data_text_free(void *data);
29 static int       _ecore_xcb_selection_data_targets_free(void *data);
30 static int       _ecore_xcb_selection_data_files_free(void *data);
31 static int       _ecore_xcb_selection_data_default_free(void *data);
32 static Eina_Bool _ecore_xcb_selection_set(Ecore_X_Window win,
33                                           const void    *data,
34                                           int            size,
35                                           Ecore_X_Atom   selection);
36 static void _ecore_xcb_selection_request(Ecore_X_Window win,
37                                          Ecore_X_Atom   selection,
38                                          const char    *target);
39 static Ecore_X_Atom _ecore_xcb_selection_target_atom_get(const char *target);
40
41 /* local variables */
42 static Ecore_X_Selection_Intern _selections[4];
43 static Ecore_X_Selection_Converter *_converters = NULL;
44 static Ecore_X_Selection_Parser *_parsers = NULL;
45
46 /* local functions */
47 void
48 _ecore_xcb_selection_init(void)
49 {
50    LOGFN(__FILE__, __LINE__, __FUNCTION__);
51
52    memset(_selections, 0, sizeof(_selections));
53
54    /* init converters */
55    ecore_x_selection_converter_atom_add(ECORE_X_ATOM_TEXT,
56                                         _ecore_xcb_selection_converter_text);
57    ecore_x_selection_converter_atom_add(ECORE_X_ATOM_UTF8_STRING,
58                                         _ecore_xcb_selection_converter_text);
59    ecore_x_selection_converter_atom_add(ECORE_X_ATOM_COMPOUND_TEXT,
60                                         _ecore_xcb_selection_converter_text);
61    ecore_x_selection_converter_atom_add(ECORE_X_ATOM_STRING,
62                                         _ecore_xcb_selection_converter_text);
63
64    /* init parsers */
65    ecore_x_selection_parser_add("text/plain",
66                                 _ecore_xcb_selection_parser_text);
67    ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_UTF8_STRING,
68                                 _ecore_xcb_selection_parser_text);
69    ecore_x_selection_parser_add("text/uri-list",
70                                 _ecore_xcb_selection_parser_files);
71    ecore_x_selection_parser_add("_NETSCAPE_URL",
72                                 _ecore_xcb_selection_parser_files);
73    ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_TARGETS,
74                                 _ecore_xcb_selection_parser_targets);
75 }
76
77 void
78 _ecore_xcb_selection_shutdown(void)
79 {
80    Ecore_X_Selection_Converter *cnv;
81    Ecore_X_Selection_Parser *prs;
82
83    LOGFN(__FILE__, __LINE__, __FUNCTION__);
84
85    /* free selection converters */
86    cnv = _converters;
87    while (cnv)
88      {
89         Ecore_X_Selection_Converter *tmp;
90
91         tmp = cnv->next;
92         free(cnv);
93         cnv = tmp;
94      }
95    _converters = NULL;
96
97    /* free parsers */
98    prs = _parsers;
99    while (prs)
100      {
101         Ecore_X_Selection_Parser *tmp;
102
103         tmp = prs;
104         prs = prs->next;
105         free(tmp->target);
106         free(tmp);
107      }
108    _parsers = NULL;
109 }
110
111 /* public functions */
112 EAPI void
113 ecore_x_selection_converter_atom_add(Ecore_X_Atom                                          target,
114                                      Eina_Bool                                             (*func)(char *target,
115                                                                              void         *data,
116                                                                              int           size,
117                                                                              void        **data_ret,
118                                                                              int          *size_ret,
119                                                                              Ecore_X_Atom *type,
120                                                                              int          *size_type))
121 {
122    Ecore_X_Selection_Converter *cnv;
123
124    LOGFN(__FILE__, __LINE__, __FUNCTION__);
125
126    cnv = _converters;
127    if (_converters)
128      {
129         while (1)
130           {
131              if (cnv->target == target)
132                {
133                   cnv->convert = func;
134                   return;
135                }
136              if (cnv->next)
137                cnv = cnv->next;
138              else
139                break;
140           }
141         cnv->next = calloc(1, sizeof(Ecore_X_Selection_Converter));
142         if (!cnv->next) return;
143         cnv = cnv->next;
144      }
145    else
146      {
147         _converters = calloc(1, sizeof(Ecore_X_Selection_Converter));
148         if (!_converters) return;
149         cnv = _converters;
150      }
151    cnv->target = target;
152    cnv->convert = func;
153 }
154
155 EAPI void
156 ecore_x_selection_converter_add(char                                                 *target,
157                                 Eina_Bool                                             (*func)(char *target,
158                                                                         void         *data,
159                                                                         int           size,
160                                                                         void        **date_ret,
161                                                                         int          *size_ret,
162                                                                         Ecore_X_Atom *atom_ret,
163                                                                         int          *ret))
164 {
165    Ecore_X_Atom atarget;
166
167    LOGFN(__FILE__, __LINE__, __FUNCTION__);
168
169    if ((!func) || (!target)) return;
170    atarget = _ecore_xcb_selection_target_atom_get(target);
171    ecore_x_selection_converter_atom_add(atarget, func);
172 }
173
174 EAPI void
175 ecore_x_selection_converter_del(char *target)
176 {
177    Ecore_X_Atom atarget;
178
179    LOGFN(__FILE__, __LINE__, __FUNCTION__);
180
181    if (!target) return;
182    atarget = _ecore_xcb_selection_target_atom_get(target);
183    ecore_x_selection_converter_atom_del(atarget);
184 }
185
186 EAPI void
187 ecore_x_selection_converter_atom_del(Ecore_X_Atom target)
188 {
189    Ecore_X_Selection_Converter *conv, *pconv = NULL;
190
191    LOGFN(__FILE__, __LINE__, __FUNCTION__);
192
193    conv = _converters;
194    while (conv)
195      {
196         if (conv->target == target)
197           {
198              if (pconv)
199                pconv->next = conv->next;
200              else
201                _converters = conv->next;
202              free(conv);
203              return;
204           }
205         pconv = conv;
206         conv = conv->next;
207      }
208 }
209
210 EAPI void
211 ecore_x_selection_parser_add(const char *target,
212                              void *(*func)(const char *target, void *data, int size, int format))
213 {
214    Ecore_X_Selection_Parser *prs;
215
216    LOGFN(__FILE__, __LINE__, __FUNCTION__);
217
218    if (!target) return;
219    prs = _parsers;
220    if (prs)
221      {
222         while (prs->next)
223           {
224              if (!strcmp(prs->target, target))
225                {
226                   prs->parse = func;
227                   return;
228                }
229              prs = prs->next;
230           }
231         prs->next = calloc(1, sizeof(Ecore_X_Selection_Parser));
232         prs = prs->next;
233      }
234    else
235      {
236         _parsers = calloc(1, sizeof(Ecore_X_Selection_Parser));
237         prs = _parsers;
238      }
239    prs->target = strdup(target);
240    prs->parse = func;
241 }
242
243 EAPI void
244 ecore_x_selection_parser_del(const char *target)
245 {
246    Ecore_X_Selection_Parser *prs, *pprs = NULL;
247
248    LOGFN(__FILE__, __LINE__, __FUNCTION__);
249
250    if (!target) return;
251
252    prs = _parsers;
253    while (prs)
254      {
255         if (!strcmp(prs->target, target))
256           {
257              if (pprs)
258                pprs->next = prs->next;
259              else
260                _parsers = prs->next;
261              free(prs->target);
262              free(prs);
263              return;
264           }
265         pprs = prs;
266         prs = prs->next;
267      }
268 }
269
270 /**
271  * Claim ownership of the PRIMARY selection and set its data.
272  * @param w    The window to which this selection belongs
273  * @param data The data associated with the selection
274  * @param size The size of the data buffer in bytes
275  * @return     Returns 1 if the ownership of the selection was successfully
276  *             claimed, or 0 if unsuccessful.
277  */
278 EAPI Eina_Bool
279 ecore_x_selection_primary_set(Ecore_X_Window win,
280                               const void    *data,
281                               int            size)
282 {
283    LOGFN(__FILE__, __LINE__, __FUNCTION__);
284
285    return _ecore_xcb_selection_set(win, data, size,
286                                    ECORE_X_ATOM_SELECTION_PRIMARY);
287 }
288
289 /**
290  * Release ownership of the primary selection
291  * @return     Returns 1 if the selection was successfully cleared,
292  *             or 0 if unsuccessful.
293  */
294 EAPI Eina_Bool
295 ecore_x_selection_primary_clear(void)
296 {
297    LOGFN(__FILE__, __LINE__, __FUNCTION__);
298
299    return _ecore_xcb_selection_set(XCB_NONE, NULL, 0,
300                                    ECORE_X_ATOM_SELECTION_PRIMARY);
301 }
302
303 EAPI void
304 ecore_x_selection_primary_request(Ecore_X_Window win,
305                                   const char    *target)
306 {
307    LOGFN(__FILE__, __LINE__, __FUNCTION__);
308
309    _ecore_xcb_selection_request(win, ECORE_X_ATOM_SELECTION_PRIMARY, target);
310 }
311
312 /**
313  * Claim ownership of the SECONDARY selection and set its data.
314  * @param w    The window to which this selection belongs
315  * @param data The data associated with the selection
316  * @param size The size of the data buffer in bytes
317  * @return     Returns 1 if the ownership of the selection was successfully
318  *             claimed, or 0 if unsuccessful.
319  */
320 EAPI Eina_Bool
321 ecore_x_selection_secondary_set(Ecore_X_Window win,
322                                 const void    *data,
323                                 int            size)
324 {
325    LOGFN(__FILE__, __LINE__, __FUNCTION__);
326
327    return _ecore_xcb_selection_set(win, data, size,
328                                    ECORE_X_ATOM_SELECTION_SECONDARY);
329 }
330
331 /**
332  * Release ownership of the secondary selection
333  * @return     Returns 1 if the selection was successfully cleared,
334  *             or 0 if unsuccessful.
335  */
336 EAPI Eina_Bool
337 ecore_x_selection_secondary_clear(void)
338 {
339    LOGFN(__FILE__, __LINE__, __FUNCTION__);
340
341    return _ecore_xcb_selection_set(XCB_NONE, NULL, 0,
342                                    ECORE_X_ATOM_SELECTION_SECONDARY);
343 }
344
345 EAPI void
346 ecore_x_selection_secondary_request(Ecore_X_Window win,
347                                     const char    *target)
348 {
349    LOGFN(__FILE__, __LINE__, __FUNCTION__);
350
351    _ecore_xcb_selection_request(win, ECORE_X_ATOM_SELECTION_SECONDARY, target);
352 }
353
354 /**
355  * Claim ownership of the XDND selection and set its data.
356  * @param w    The window to which this selection belongs
357  * @param data The data associated with the selection
358  * @param size The size of the data buffer in bytes
359  * @return     Returns 1 if the ownership of the selection was successfully
360  *             claimed, or 0 if unsuccessful.
361  */
362 EAPI Eina_Bool
363 ecore_x_selection_xdnd_set(Ecore_X_Window win,
364                            const void    *data,
365                            int            size)
366 {
367    LOGFN(__FILE__, __LINE__, __FUNCTION__);
368
369    return _ecore_xcb_selection_set(win, data, size,
370                                    ECORE_X_ATOM_SELECTION_XDND);
371 }
372
373 /**
374  * Release ownership of the XDND selection
375  * @return     Returns 1 if the selection was successfully cleared,
376  *             or 0 if unsuccessful.
377  */
378 EAPI Eina_Bool
379 ecore_x_selection_xdnd_clear(void)
380 {
381    LOGFN(__FILE__, __LINE__, __FUNCTION__);
382
383    return _ecore_xcb_selection_set(XCB_NONE, NULL, 0,
384                                    ECORE_X_ATOM_SELECTION_XDND);
385 }
386
387 EAPI void
388 ecore_x_selection_xdnd_request(Ecore_X_Window win,
389                                const char    *target)
390 {
391    Ecore_X_Atom atom;
392    Ecore_X_DND_Target *_target;
393
394    LOGFN(__FILE__, __LINE__, __FUNCTION__);
395    CHECK_XCB_CONN;
396
397    _target = _ecore_xcb_dnd_target_get();
398    atom = _ecore_xcb_selection_target_atom_get(target);
399
400    xcb_convert_selection(_ecore_xcb_conn, win, ECORE_X_ATOM_SELECTION_XDND,
401                          atom, ECORE_X_ATOM_SELECTION_PROP_XDND, _target->time);
402 }
403
404 /**
405  * Claim ownership of the CLIPBOARD selection and set its data.
406  * @param w    The window to which this selection belongs
407  * @param data The data associated with the selection
408  * @param size The size of the data buffer in bytes
409  * @return     Returns 1 if the ownership of the selection was successfully
410  *             claimed, or 0 if unsuccessful.
411  *
412  * Get the converted data from a previous CLIPBOARD selection
413  * request. The buffer must be freed when done with.
414  */
415 EAPI Eina_Bool
416 ecore_x_selection_clipboard_set(Ecore_X_Window win,
417                                 const void    *data,
418                                 int            size)
419 {
420    LOGFN(__FILE__, __LINE__, __FUNCTION__);
421
422    return _ecore_xcb_selection_set(win, data, size,
423                                    ECORE_X_ATOM_SELECTION_CLIPBOARD);
424 }
425
426 /**
427  * Release ownership of the clipboard selection
428  * @return     Returns 1 if the selection was successfully cleared,
429  *             or 0 if unsuccessful.
430  */
431 EAPI Eina_Bool
432 ecore_x_selection_clipboard_clear(void)
433 {
434    LOGFN(__FILE__, __LINE__, __FUNCTION__);
435
436    return _ecore_xcb_selection_set(XCB_NONE, NULL, 0,
437                                    ECORE_X_ATOM_SELECTION_CLIPBOARD);
438 }
439
440 EAPI void
441 ecore_x_selection_clipboard_request(Ecore_X_Window win,
442                                     const char    *target)
443 {
444    LOGFN(__FILE__, __LINE__, __FUNCTION__);
445
446    _ecore_xcb_selection_request(win, ECORE_X_ATOM_SELECTION_CLIPBOARD, target);
447 }
448
449 EAPI Eina_Bool
450 ecore_x_selection_convert(Ecore_X_Atom  selection,
451                           Ecore_X_Atom  target,
452                           void        **data_ret,
453                           int          *size,
454                           Ecore_X_Atom *targtype,
455                           int          *typesize)
456 {
457    Ecore_X_Selection_Intern *sel;
458    Ecore_X_Selection_Converter *cnv;
459    void *data;
460    char *tgt_str;
461
462    LOGFN(__FILE__, __LINE__, __FUNCTION__);
463
464    sel = _ecore_xcb_selection_get(selection);
465    tgt_str = _ecore_xcb_selection_target_get(target);
466
467    for (cnv = _converters; cnv; cnv = cnv->next)
468      {
469         if (cnv->target == target)
470           {
471              int r = 0;
472
473              r = cnv->convert(tgt_str, sel->data, sel->length, &data, size,
474                               targtype, typesize);
475              free(tgt_str);
476              if (r)
477                {
478                   if (data_ret) *data_ret = data;
479                   return r;
480                }
481              else
482                return EINA_FALSE;
483           }
484      }
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 (data)
628      {
629         unsigned char *buff = NULL;
630
631         _selections[in].win = win;
632         _selections[in].selection = selection;
633         _selections[in].length = size;
634         _selections[in].time = _ecore_xcb_events_last_time_get();
635
636         buff = malloc(size);
637         if (!buff) return EINA_FALSE;
638         memcpy(buff, data, size);
639         _selections[in].data = buff;
640      }
641    else if (_selections[in].data)
642      {
643         free(_selections[in].data);
644         memset(&_selections[in], 0, sizeof(Ecore_X_Selection_Data));
645      }
646
647    return EINA_TRUE;
648 }
649
650 static void
651 _ecore_xcb_selection_request(Ecore_X_Window win,
652                              Ecore_X_Atom   selection,
653                              const char    *target)
654 {
655    Ecore_X_Atom atarget, prop;
656
657    LOGFN(__FILE__, __LINE__, __FUNCTION__);
658    CHECK_XCB_CONN;
659
660    if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
661      prop = ECORE_X_ATOM_SELECTION_PROP_PRIMARY;
662    else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
663      prop = ECORE_X_ATOM_SELECTION_PROP_SECONDARY;
664    else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
665      prop = ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD;
666    else
667      return;
668
669    atarget = _ecore_xcb_selection_target_atom_get(target);
670
671    xcb_convert_selection(_ecore_xcb_conn, win, selection, atarget, prop,
672                          XCB_CURRENT_TIME);
673 }
674
675 static Eina_Bool
676 _ecore_xcb_selection_converter_text(char         *target,
677                                     void         *data,
678                                     int           size,
679                                     void        **data_ret,
680                                     int          *size_ret,
681                                     Ecore_X_Atom *type __UNUSED__,
682                                     int          *size_type __UNUSED__)
683 {
684    Ecore_Xcb_Encoding_Style style;
685    Ecore_Xcb_Textproperty ret;
686    char *str;
687
688    LOGFN(__FILE__, __LINE__, __FUNCTION__);
689    CHECK_XCB_CONN;
690
691    if ((!data) || (!size)) return EINA_FALSE;
692
693    if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
694      style = XcbTextStyle;
695    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
696      style = XcbCompoundTextStyle;
697    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
698      style = XcbStringStyle;
699 #ifdef HAVE_ICONV
700    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
701      style = XcbUTF8StringStyle;
702 #endif
703    else
704      return EINA_FALSE;
705
706    str = alloca(size + 1);
707    memcpy(str, data, size);
708    str[size] = '\0';
709
710 #ifdef HAVE_ICONV
711    if (_ecore_xcb_utf8_textlist_to_textproperty(&str, 1, style, &ret))
712      {
713         int size = 0;
714
715         size = (strlen((char *)ret.value) + 1);
716         *data_ret = malloc(size);
717         if (!*data_ret) return EINA_FALSE;
718         memcpy(*data_ret, ret.value, size);
719         *size_ret = size;
720         if (ret.value) free(ret.value);
721         return EINA_TRUE;
722      }
723 #else
724    if (_ecore_xcb_mb_textlist_to_textproperty(&str, 1, style, &ret))
725      {
726         int size = 0;
727
728         size = (strlen((char *)ret.value) + 1);
729         *data_ret = malloc(size);
730         if (!*data_ret) return EINA_FALSE;
731         memcpy(*data_ret, ret.value, size);
732         *size_ret = size;
733         if (ret.value) free(ret.value);
734         return EINA_TRUE;
735      }
736 #endif
737    else
738      return EINA_TRUE;
739 }
740
741 static void *
742 _ecore_xcb_selection_parser_text(const char *target __UNUSED__,
743                                  void       *data,
744                                  int         size,
745                                  int         format __UNUSED__)
746 {
747    Ecore_X_Selection_Data_Text *sel;
748    unsigned char *_data;
749    void *t;
750
751    LOGFN(__FILE__, __LINE__, __FUNCTION__);
752
753    if (!(_data = data)) return NULL;
754
755    sel = calloc(1, sizeof(Ecore_X_Selection_Data_Text));
756    if (!sel) return NULL;
757
758    if (_data[size - 1])
759      {
760         size++;
761         t = realloc(_data, size);
762         if (!t)
763           {
764              free(sel);
765              return NULL;
766           }
767         _data = t;
768         _data[size - 1] = 0;
769      }
770    sel->text = (char *)_data;
771    ECORE_XCB_SELECTION_DATA(sel)->length = size;
772    ECORE_XCB_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TEXT;
773    ECORE_XCB_SELECTION_DATA(sel)->data = _data;
774    ECORE_XCB_SELECTION_DATA(sel)->free = _ecore_xcb_selection_data_text_free;
775    return sel;
776 }
777
778 static void *
779 _ecore_xcb_selection_parser_files(const char *target,
780                                   void       *data,
781                                   int         size,
782                                   int         format __UNUSED__)
783 {
784    Ecore_X_Selection_Data_Files *sel;
785    char *_data, *tmp, *t, **t2;
786    int i = 0, is = 0;
787
788    LOGFN(__FILE__, __LINE__, __FUNCTION__);
789
790    if ((strcmp(target, "text/uri-list")) &&
791        (strcmp(target, "_NETSCAPE_URL"))) return NULL;
792
793    if (!(_data = data)) return NULL;
794
795    sel = calloc(1, sizeof(Ecore_X_Selection_Data_Files));
796    if (!sel) return NULL;
797
798    ECORE_XCB_SELECTION_DATA(sel)->free = _ecore_xcb_selection_data_files_free;
799
800    if (_data[size - 1])
801      {
802         size++;
803         t = realloc(_data, size);
804         if (!t)
805           {
806              free(sel);
807              return NULL;
808           }
809         _data = t;
810         _data[size - 1] = 0;
811      }
812
813    tmp = malloc(size);
814    if (!tmp)
815      {
816         free(sel);
817         return NULL;
818      }
819
820    while ((is < size) && (_data[is]))
821      {
822         if ((i == 0) && (_data[is] == '#'))
823           {
824              for (; ((_data[is]) && (_data[is] != '\n')); is++) ;
825           }
826         else
827           {
828              if ((_data[is] != '\r') && (_data[is] != '\n'))
829                tmp[i++] = _data[is++];
830              else
831                {
832                   while ((_data[is] == '\r') || (_data[is] == '\n'))
833                     is++;
834                   tmp[i] = 0;
835                   sel->num_files++;
836                   t2 = realloc(sel->files, sel->num_files * sizeof(char *));
837                   if (t2)
838                     {
839                        sel->files = t2;
840                        sel->files[sel->num_files - 1] = strdup(tmp);
841                     }
842                   tmp[0] = 0;
843                   i = 0;
844                }
845           }
846      }
847    if (i > 0)
848      {
849         tmp[i] = 0;
850         sel->num_files++;
851         t2 = realloc(sel->files, sel->num_files * sizeof(char *));
852         if (t2)
853           {
854              sel->files = t2;
855              sel->files[sel->num_files - 1] = strdup(tmp);
856           }
857      }
858    if (tmp) free(tmp);
859    if (_data) free(_data);
860
861    ECORE_XCB_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_FILES;
862    ECORE_XCB_SELECTION_DATA(sel)->length = sel->num_files;
863
864    return ECORE_XCB_SELECTION_DATA(sel);
865 }
866
867 static void *
868 _ecore_xcb_selection_parser_targets(const char *target __UNUSED__,
869                                     void       *data,
870                                     int         size,
871                                     int         format __UNUSED__)
872 {
873    Ecore_X_Selection_Data_Targets *sel;
874    unsigned long *targets;
875    int i = 0;
876
877    LOGFN(__FILE__, __LINE__, __FUNCTION__);
878    CHECK_XCB_CONN;
879
880    if (!(targets = (unsigned long *)data)) return NULL;
881
882    sel = calloc(1, sizeof(Ecore_X_Selection_Data_Targets));
883    if (!sel) return NULL;
884
885    sel->num_targets = (size - 2);
886    sel->targets = malloc((size - 2) * sizeof(char *));
887    if (!sel->targets)
888      {
889         free(sel);
890         return NULL;
891      }
892
893    for (i = 2; i < size; i++)
894      {
895         xcb_get_atom_name_cookie_t cookie;
896         xcb_get_atom_name_reply_t *reply;
897         char *name = NULL;
898         int len = 0;
899
900         cookie = xcb_get_atom_name_unchecked(_ecore_xcb_conn, targets[i]);
901         reply = xcb_get_atom_name_reply(_ecore_xcb_conn, cookie, NULL);
902         if (reply)
903           {
904              len = xcb_get_atom_name_name_length(reply);
905              name = (char *)malloc(sizeof(char) * (len + 1));
906              if (name)
907                {
908                   memcpy(name, xcb_get_atom_name_name(reply), len);
909                   name[len] = '\0';
910                   sel->targets[i - 2] = name;
911                }
912              free(reply);
913           }
914      }
915
916    ECORE_XCB_SELECTION_DATA(sel)->free =
917      _ecore_xcb_selection_data_targets_free;
918    ECORE_XCB_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TARGETS;
919    ECORE_XCB_SELECTION_DATA(sel)->length = size;
920    ECORE_XCB_SELECTION_DATA(sel)->data = data;
921
922    return sel;
923 }
924
925 /*
926    static int
927    _ecore_xcb_selection_data_free(void *data)
928    {
929    Ecore_X_Selection_Data *sel;
930
931    LOGFN(__FILE__, __LINE__, __FUNCTION__);
932
933    if (!(sel = data)) return 0;
934    if (sel->data) free(sel->data);
935    free(sel);
936    return 1;
937    }
938  */
939
940 static int
941 _ecore_xcb_selection_data_text_free(void *data)
942 {
943    Ecore_X_Selection_Data_Text *sel;
944
945    LOGFN(__FILE__, __LINE__, __FUNCTION__);
946
947    if (!(sel = data)) return 0;
948    if (sel->text) free(sel->text);
949    free(sel);
950    return 1;
951 }
952
953 static int
954 _ecore_xcb_selection_data_targets_free(void *data)
955 {
956    Ecore_X_Selection_Data_Targets *sel;
957
958    LOGFN(__FILE__, __LINE__, __FUNCTION__);
959
960    if (!(sel = data)) return 0;
961    if (sel->targets) free(sel->targets);
962    free(ECORE_XCB_SELECTION_DATA(sel)->data);
963    free(sel);
964    return 1;
965 }
966
967 static int
968 _ecore_xcb_selection_data_files_free(void *data)
969 {
970    Ecore_X_Selection_Data_Files *sel;
971
972    LOGFN(__FILE__, __LINE__, __FUNCTION__);
973
974    if (!(sel = data)) return 0;
975    if (sel->files)
976      {
977         int i = 0;
978
979         for (i = 0; i < sel->num_files; i++)
980           if (sel->files[i]) free(sel->files[i]);
981         if (sel->files) free(sel->files);
982      }
983    free(sel);
984    return 0;
985 }
986
987 static int
988 _ecore_xcb_selection_data_default_free(void *data)
989 {
990    Ecore_X_Selection_Data *sel;
991
992    if (!(sel = data)) return 1;
993    free(sel->data);
994    free(sel);
995    return 1;
996 }
997
998 static Ecore_X_Atom
999 _ecore_xcb_selection_target_atom_get(const char *target)
1000 {
1001    Ecore_X_Atom x_target;
1002
1003    if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
1004      x_target = ECORE_X_ATOM_TEXT;
1005    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
1006      x_target = ECORE_X_ATOM_COMPOUND_TEXT;
1007    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
1008      x_target = ECORE_X_ATOM_STRING;
1009    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
1010      x_target = ECORE_X_ATOM_UTF8_STRING;
1011    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_FILENAME))
1012      x_target = ECORE_X_ATOM_FILE_NAME;
1013    else
1014      x_target = ecore_x_atom_get(target);
1015
1016    return x_target;
1017 }
1018
1019 char *
1020 _ecore_xcb_selection_target_get(Ecore_X_Atom target)
1021 {
1022    if (target == ECORE_X_ATOM_FILE_NAME)
1023      return strdup(ECORE_X_SELECTION_TARGET_FILENAME);
1024    else if (target == ECORE_X_ATOM_STRING)
1025      return strdup(ECORE_X_SELECTION_TARGET_STRING);
1026    else if (target == ECORE_X_ATOM_UTF8_STRING)
1027      return strdup(ECORE_X_SELECTION_TARGET_UTF8_STRING);
1028    else if (target == ECORE_X_ATOM_TEXT)
1029      return strdup(ECORE_X_SELECTION_TARGET_TEXT);
1030    else
1031      return ecore_x_atom_name_get(target);
1032 }
1033