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