Tizen 2.1 base
[framework/uifw/ecore.git] / src / lib / ecore_x / xlib / ecore_x_selection.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif /* ifdef HAVE_CONFIG_H */
4
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include "Ecore.h"
9 #include "ecore_private.h"
10 #include "ecore_x_private.h"
11 #include "Ecore_X.h"
12 #include "Ecore_X_Atoms.h"
13
14 static Ecore_X_Selection_Intern selections[4];
15 static Ecore_X_Selection_Converter *converters = NULL;
16 static Ecore_X_Selection_Parser *parsers = NULL;
17
18 static int   _ecore_x_selection_data_default_free(void *data);
19 static void *_ecore_x_selection_parser_files(const char *target,
20                                              void *data,
21                                              int size,
22                                              int format);
23 static int   _ecore_x_selection_data_files_free(void *data);
24 static void *_ecore_x_selection_parser_text(const char *target,
25                                             void *data,
26                                             int size,
27                                             int format);
28 static int   _ecore_x_selection_data_text_free(void *data);
29 static void *_ecore_x_selection_parser_targets(const char *target,
30                                                void *data,
31                                                int size,
32                                                int format);
33 static int   _ecore_x_selection_data_targets_free(void *data);
34
35 #define ECORE_X_SELECTION_DATA(x) ((Ecore_X_Selection_Data *)(x))
36
37 void
38 _ecore_x_selection_data_init(void)
39 {
40    /* Initialize global data */
41    memset(selections, 0, sizeof(selections));
42
43    /* Initialize converters */
44    ecore_x_selection_converter_atom_add(ECORE_X_ATOM_TEXT,
45                                         ecore_x_selection_converter_text);
46 #ifdef X_HAVE_UTF8_STRING
47    ecore_x_selection_converter_atom_add(ECORE_X_ATOM_UTF8_STRING,
48                                         ecore_x_selection_converter_text);
49 #endif /* ifdef X_HAVE_UTF8_STRING */
50    ecore_x_selection_converter_atom_add(ECORE_X_ATOM_COMPOUND_TEXT,
51                                         ecore_x_selection_converter_text);
52    ecore_x_selection_converter_atom_add(ECORE_X_ATOM_STRING,
53                                         ecore_x_selection_converter_text);
54
55    /* Initialize parsers */
56    ecore_x_selection_parser_add("text/plain",
57                                 _ecore_x_selection_parser_text);
58    ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_UTF8_STRING,
59                                 _ecore_x_selection_parser_text);
60    ecore_x_selection_parser_add("text/uri-list",
61                                 _ecore_x_selection_parser_files);
62    ecore_x_selection_parser_add("_NETSCAPE_URL",
63                                 _ecore_x_selection_parser_files);
64    ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_TARGETS,
65                                 _ecore_x_selection_parser_targets);
66 }
67
68 void
69 _ecore_x_selection_shutdown(void)
70 {
71    Ecore_X_Selection_Converter *cnv;
72    Ecore_X_Selection_Parser *prs;
73
74    /* free the selection converters */
75    cnv = converters;
76    while (cnv)
77      {
78         Ecore_X_Selection_Converter *tmp;
79
80         tmp = cnv->next;
81         free(cnv);
82         cnv = tmp;
83      }
84    converters = NULL;
85
86    /* free the selection parsers */
87    prs = parsers;
88    while (prs)
89      {
90         Ecore_X_Selection_Parser *tmp;
91
92         tmp = prs;
93         prs = prs->next;
94         free(tmp->target);
95         free(tmp);
96      }
97    parsers = NULL;
98 }
99
100 Ecore_X_Selection_Intern *
101 _ecore_x_selection_get(Ecore_X_Atom selection)
102 {
103    if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
104      return &selections[0];
105    else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
106      return &selections[1];
107    else if (selection == ECORE_X_ATOM_SELECTION_XDND)
108      return &selections[2];
109    else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
110      return &selections[3];
111    else
112      return NULL;
113 }
114
115 Eina_Bool
116 _ecore_x_selection_set(Window w,
117                        const void *data,
118                        int size,
119                        Ecore_X_Atom selection)
120 {
121    int in;
122    unsigned char *buf = NULL;
123
124    XSetSelectionOwner(_ecore_x_disp, selection, w, _ecore_x_event_last_time);
125    if (XGetSelectionOwner(_ecore_x_disp, selection) != w)
126      return EINA_FALSE;
127
128    if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
129      in = 0;
130    else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
131      in = 1;
132    else if (selection == ECORE_X_ATOM_SELECTION_XDND)
133      in = 2;
134    else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
135      in = 3;
136    else
137      return EINA_FALSE;
138
139    if (data)
140      {
141         selections[in].win = w;
142         selections[in].selection = selection;
143         selections[in].length = size;
144         selections[in].time = _ecore_x_event_last_time;
145
146         buf = malloc(size);
147         if (!buf) return EINA_FALSE;
148         memcpy(buf, data, size);
149         selections[in].data = buf;
150      }
151    else if (selections[in].data)
152      {
153         free(selections[in].data);
154         memset(&selections[in], 0, sizeof(Ecore_X_Selection_Data));
155      }
156
157    return EINA_TRUE;
158 }
159
160 /**
161  * Claim ownership of the PRIMARY selection and set its data.
162  * @param w    The window to which this selection belongs
163  * @param data The data associated with the selection
164  * @param size The size of the data buffer in bytes
165  * @return     Returns 1 if the ownership of the selection was successfully
166  *             claimed, or 0 if unsuccessful.
167  */
168 EAPI Eina_Bool
169 ecore_x_selection_primary_set(Ecore_X_Window w,
170                               const void *data,
171                               int size)
172 {
173    LOGFN(__FILE__, __LINE__, __FUNCTION__);
174    return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_PRIMARY);
175 }
176
177 /**
178  * Release ownership of the primary selection
179  * @return     Returns 1 if the selection was successfully cleared,
180  *             or 0 if unsuccessful.
181  *
182  */
183 EAPI Eina_Bool
184 ecore_x_selection_primary_clear(void)
185 {
186    LOGFN(__FILE__, __LINE__, __FUNCTION__);
187    return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_PRIMARY);
188 }
189
190 /**
191  * Claim ownership of the SECONDARY selection and set its data.
192  * @param w    The window to which this selection belongs
193  * @param data The data associated with the selection
194  * @param size The size of the data buffer in bytes
195  * @return     Returns 1 if the ownership of the selection was successfully
196  *             claimed, or 0 if unsuccessful.
197  */
198 EAPI Eina_Bool
199 ecore_x_selection_secondary_set(Ecore_X_Window w,
200                                 const void *data,
201                                 int size)
202 {
203    LOGFN(__FILE__, __LINE__, __FUNCTION__);
204    return _ecore_x_selection_set(w,
205                                  data,
206                                  size,
207                                  ECORE_X_ATOM_SELECTION_SECONDARY);
208 }
209
210 /**
211  * Release ownership of the secondary selection
212  * @return     Returns 1 if the selection was successfully cleared,
213  *             or 0 if unsuccessful.
214  *
215  */
216 EAPI Eina_Bool
217 ecore_x_selection_secondary_clear(void)
218 {
219    LOGFN(__FILE__, __LINE__, __FUNCTION__);
220    return _ecore_x_selection_set(None,
221                                  NULL,
222                                  0,
223                                  ECORE_X_ATOM_SELECTION_SECONDARY);
224 }
225
226 /**
227  * Claim ownership of the XDND selection and set its data.
228  * @param w    The window to which this selection belongs
229  * @param data The data associated with the selection
230  * @param size The size of the data buffer in bytes
231  * @return     Returns 1 if the ownership of the selection was successfully
232  *             claimed, or 0 if unsuccessful.
233  */
234 EAPI Eina_Bool
235 ecore_x_selection_xdnd_set(Ecore_X_Window w,
236                            const void *data,
237                            int size)
238 {
239    LOGFN(__FILE__, __LINE__, __FUNCTION__);
240    return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_XDND);
241 }
242
243 /**
244  * Release ownership of the XDND selection
245  * @return     Returns 1 if the selection was successfully cleared,
246  *             or 0 if unsuccessful.
247  *
248  */
249 EAPI Eina_Bool
250 ecore_x_selection_xdnd_clear(void)
251 {
252    LOGFN(__FILE__, __LINE__, __FUNCTION__);
253    return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_XDND);
254 }
255
256 /**
257  * Claim ownership of the CLIPBOARD selection and set its data.
258  * @param w    The window to which this selection belongs
259  * @param data The data associated with the selection
260  * @param size The size of the data buffer in bytes
261  * @return     Returns 1 if the ownership of the selection was successfully
262  *             claimed, or 0 if unsuccessful.
263  *
264  * Get the converted data from a previous CLIPBOARD selection
265  * request. The buffer must be freed when done with.
266  */
267 EAPI Eina_Bool
268 ecore_x_selection_clipboard_set(Ecore_X_Window w,
269                                 const void *data,
270                                 int size)
271 {
272    LOGFN(__FILE__, __LINE__, __FUNCTION__);
273    return _ecore_x_selection_set(w,
274                                  data,
275                                  size,
276                                  ECORE_X_ATOM_SELECTION_CLIPBOARD);
277 }
278
279 /**
280  * Release ownership of the clipboard selection
281  * @return     Returns 1 if the selection was successfully cleared,
282  *             or 0 if unsuccessful.
283  *
284  */
285 EAPI Eina_Bool
286 ecore_x_selection_clipboard_clear(void)
287 {
288    LOGFN(__FILE__, __LINE__, __FUNCTION__);
289    return _ecore_x_selection_set(None,
290                                  NULL,
291                                  0,
292                                  ECORE_X_ATOM_SELECTION_CLIPBOARD);
293 }
294
295 Ecore_X_Atom
296 _ecore_x_selection_target_atom_get(const char *target)
297 {
298    Ecore_X_Atom x_target;
299
300    if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
301      x_target = ECORE_X_ATOM_TEXT;
302    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
303      x_target = ECORE_X_ATOM_COMPOUND_TEXT;
304    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
305      x_target = ECORE_X_ATOM_STRING;
306    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
307      x_target = ECORE_X_ATOM_UTF8_STRING;
308    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_FILENAME))
309      x_target = ECORE_X_ATOM_FILE_NAME;
310    else
311      x_target = ecore_x_atom_get(target);
312
313    return x_target;
314 }
315
316 char *
317 _ecore_x_selection_target_get(Ecore_X_Atom target)
318 {
319    /* FIXME: Should not return mem allocated with strdup or X mixed,
320     * one should use free to free, the other XFree */
321    if (target == ECORE_X_ATOM_FILE_NAME)
322      return strdup(ECORE_X_SELECTION_TARGET_FILENAME);
323    else if (target == ECORE_X_ATOM_STRING)
324      return strdup(ECORE_X_SELECTION_TARGET_STRING);
325    else if (target == ECORE_X_ATOM_UTF8_STRING)
326      return strdup(ECORE_X_SELECTION_TARGET_UTF8_STRING);
327    else if (target == ECORE_X_ATOM_TEXT)
328      return strdup(ECORE_X_SELECTION_TARGET_TEXT);
329    else
330      return XGetAtomName(_ecore_x_disp, target);
331 }
332
333 static void
334 _ecore_x_selection_request(Ecore_X_Window w,
335                            Ecore_X_Atom selection,
336                            const char *target_str)
337 {
338    Ecore_X_Atom target, prop;
339
340    target = _ecore_x_selection_target_atom_get(target_str);
341
342    if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
343      prop = ECORE_X_ATOM_SELECTION_PROP_PRIMARY;
344    else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
345      prop = ECORE_X_ATOM_SELECTION_PROP_SECONDARY;
346    else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
347      prop = ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD;
348    else
349      return;
350
351    XConvertSelection(_ecore_x_disp, selection, target, prop,
352                      w, CurrentTime);
353 }
354
355 EAPI void
356 ecore_x_selection_primary_request(Ecore_X_Window w,
357                                   const char *target)
358 {
359    LOGFN(__FILE__, __LINE__, __FUNCTION__);
360    _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_PRIMARY, target);
361 }
362
363 EAPI void
364 ecore_x_selection_secondary_request(Ecore_X_Window w,
365                                     const char *target)
366 {
367    LOGFN(__FILE__, __LINE__, __FUNCTION__);
368    _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_SECONDARY, target);
369 }
370
371 EAPI void
372 ecore_x_selection_xdnd_request(Ecore_X_Window w,
373                                const char *target)
374 {
375    Ecore_X_Atom atom;
376    Ecore_X_DND_Target *_target;
377
378    LOGFN(__FILE__, __LINE__, __FUNCTION__);
379    _target = _ecore_x_dnd_target_get();
380    atom = _ecore_x_selection_target_atom_get(target);
381    XConvertSelection(_ecore_x_disp, ECORE_X_ATOM_SELECTION_XDND, atom,
382                      ECORE_X_ATOM_SELECTION_PROP_XDND, w,
383                      _target->time);
384 }
385
386 EAPI void
387 ecore_x_selection_clipboard_request(Ecore_X_Window w,
388                                     const char *target)
389 {
390    LOGFN(__FILE__, __LINE__, __FUNCTION__);
391    _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_CLIPBOARD, target);
392 }
393
394 EAPI void
395 ecore_x_selection_converter_atom_add(Ecore_X_Atom target,
396                                      Eina_Bool (*func)(char *target,
397                                                        void *data,
398                                                        int size,
399                                                        void **data_ret,
400                                                        int *size_ret,
401                                                        Ecore_X_Atom *ttype,
402                                                        int *tsize))
403 {
404    Ecore_X_Selection_Converter *cnv;
405
406    LOGFN(__FILE__, __LINE__, __FUNCTION__);
407    cnv = converters;
408    if (converters)
409      {
410         while (1)
411           {
412              if (cnv->target == target)
413                {
414                   cnv->convert = func;
415                   return;
416                }
417
418              if (cnv->next)
419                cnv = cnv->next;
420              else
421                break;
422           }
423
424         cnv->next = calloc(1, sizeof(Ecore_X_Selection_Converter));
425         if (!cnv->next) return;
426         cnv = cnv->next;
427      }
428    else
429      {
430         converters = calloc(1, sizeof(Ecore_X_Selection_Converter));
431         if (!converters) return;
432         cnv = converters;
433      }
434
435    cnv->target = target;
436    cnv->convert = func;
437 }
438
439 EAPI void
440 ecore_x_selection_converter_add(char *target,
441                                 Eina_Bool (*func)(char *target,
442                                                   void *data,
443                                                   int size,
444                                                   void **data_ret,
445                                                   int *size_ret,
446                                                   Ecore_X_Atom *,
447                                                   int *))
448 {
449    Ecore_X_Atom x_target;
450
451    if (!func || !target)
452      return;
453
454    LOGFN(__FILE__, __LINE__, __FUNCTION__);
455    x_target = _ecore_x_selection_target_atom_get(target);
456
457    ecore_x_selection_converter_atom_add(x_target, func);
458 }
459
460 EAPI void
461 ecore_x_selection_converter_atom_del(Ecore_X_Atom target)
462 {
463    Ecore_X_Selection_Converter *cnv, *prev_cnv;
464
465    LOGFN(__FILE__, __LINE__, __FUNCTION__);
466    prev_cnv = NULL;
467    cnv = converters;
468
469    while (cnv)
470      {
471         if (cnv->target == target)
472           {
473              if (prev_cnv)
474                prev_cnv->next = cnv->next;
475              else
476                {
477                   converters = cnv->next; /* This was the first converter */
478                }
479
480              free(cnv);
481
482              return;
483           }
484
485         prev_cnv = cnv;
486         cnv = cnv->next;
487      }
488 }
489
490 EAPI void
491 ecore_x_selection_converter_del(char *target)
492 {
493    Ecore_X_Atom x_target;
494
495    if (!target)
496      return;
497
498    LOGFN(__FILE__, __LINE__, __FUNCTION__);
499    x_target = _ecore_x_selection_target_atom_get(target);
500    ecore_x_selection_converter_atom_del(x_target);
501 }
502
503 EAPI Eina_Bool
504 ecore_x_selection_notify_send(Ecore_X_Window requestor,
505                               Ecore_X_Atom selection,
506                               Ecore_X_Atom target,
507                               Ecore_X_Atom property,
508                               Ecore_X_Time tim)
509 {
510    XEvent xev;
511    XSelectionEvent xnotify;
512
513    LOGFN(__FILE__, __LINE__, __FUNCTION__);
514    xnotify.type = SelectionNotify;
515    xnotify.display = _ecore_x_disp;
516    xnotify.requestor = requestor;
517    xnotify.selection = selection;
518    xnotify.target = target;
519    xnotify.property = property;
520    xnotify.time = tim;
521    xnotify.send_event = True;
522    xnotify.serial = 0;
523
524    xev.xselection = xnotify;
525    return (XSendEvent(_ecore_x_disp, requestor, False, 0, &xev) > 0) ? EINA_TRUE : EINA_FALSE;
526 }
527
528 /* Locate and run conversion callback for specified selection target */
529 EAPI Eina_Bool
530 ecore_x_selection_convert(Ecore_X_Atom selection,
531                           Ecore_X_Atom target,
532                           void **data_ret,
533                           int *size,
534                           Ecore_X_Atom *targtype,
535                           int *typesize)
536 {
537    Ecore_X_Selection_Intern *sel;
538    Ecore_X_Selection_Converter *cnv;
539    void *data;
540    char *tgt_str;
541
542    LOGFN(__FILE__, __LINE__, __FUNCTION__);
543    sel = _ecore_x_selection_get(selection);
544    tgt_str = _ecore_x_selection_target_get(target);
545
546    for (cnv = converters; cnv; cnv = cnv->next)
547      {
548         if (cnv->target == target)
549           {
550              int r;
551              r = cnv->convert(tgt_str, sel->data, sel->length, &data, size,
552                               targtype, typesize);
553              free(tgt_str);
554              if (r)
555                {
556                   *data_ret = data;
557                   return r;
558                }
559              else
560                return EINA_FALSE;
561           }
562      }
563
564    /* ICCCM says "If the selection cannot be converted into a form based on the target (and parameters, if any), the owner should refuse the SelectionRequest as previously described." */
565    return EINA_FALSE;
566
567    /* Default, just return the data
568     * data_ret = malloc(sel->length);
569       memcpy(*data_ret, sel->data, sel->length);
570       free(tgt_str);
571       return 1;
572     */
573 }
574
575 /* TODO: We need to work out a mechanism for automatic conversion to any requested
576  * locale using Ecore_Txt functions */
577 /* Converter for standard non-utf8 text targets */
578 EAPI Eina_Bool
579 ecore_x_selection_converter_text(char *target,
580                                  void *data,
581                                  int size,
582                                  void **data_ret,
583                                  int *size_ret,
584                                  Ecore_X_Atom *targprop __UNUSED__,
585                                  int *s __UNUSED__)
586 {
587    XTextProperty text_prop;
588    char *mystr;
589    XICCEncodingStyle style;
590
591    if (!data || !size)
592      return EINA_FALSE;
593
594    LOGFN(__FILE__, __LINE__, __FUNCTION__);
595    if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
596      style = XTextStyle;
597    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
598      style = XCompoundTextStyle;
599    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
600      style = XStringStyle;
601
602 #ifdef X_HAVE_UTF8_STRING
603    else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
604      style = XUTF8StringStyle;
605 #endif /* ifdef X_HAVE_UTF8_STRING */
606    else
607      return EINA_FALSE;
608
609    mystr = alloca(size + 1);
610    memcpy(mystr, data, size);
611    mystr[size] = '\0';
612
613 #ifdef X_HAVE_UTF8_STRING
614    if (Xutf8TextListToTextProperty(_ecore_x_disp, &mystr, 1, style,
615                                    &text_prop) == Success)
616      {
617         int bufsize = strlen((char *)text_prop.value) + 1;
618         *data_ret = malloc(bufsize);
619         if (!*data_ret)
620           {
621              return EINA_FALSE;
622           }
623         memcpy(*data_ret, text_prop.value, bufsize);
624         *size_ret = bufsize;
625         XFree(text_prop.value);
626         return EINA_TRUE;
627      }
628
629 #else /* ifdef X_HAVE_UTF8_STRING */
630    if (XmbTextListToTextProperty(_ecore_x_disp, &mystr, 1, style,
631                                  &text_prop) == Success)
632      {
633         int bufsize = strlen(text_prop.value) + 1;
634         *data_ret = malloc(bufsize);
635         if (!*data_ret) return EINA_FALSE;
636         memcpy(*data_ret, text_prop.value, bufsize);
637         *size_ret = bufsize;
638         XFree(text_prop.value);
639         return EINA_TRUE;
640      }
641
642 #endif /* ifdef X_HAVE_UTF8_STRING */
643    else
644      {
645         return EINA_TRUE;
646      }
647 }
648
649 EAPI void
650 ecore_x_selection_parser_add(const char *target,
651                              void *(*func)(const char *target, void *data,
652                                            int size,
653                                            int format))
654 {
655    Ecore_X_Selection_Parser *prs;
656
657    if (!target)
658      return;
659
660    LOGFN(__FILE__, __LINE__, __FUNCTION__);
661    prs = parsers;
662    if (parsers)
663      {
664         while (prs->next)
665           {
666              if (!strcmp(prs->target, target))
667                {
668                   prs->parse = func;
669                   return;
670                }
671
672              prs = prs->next;
673           }
674
675         prs->next = calloc(1, sizeof(Ecore_X_Selection_Parser));
676         if (!prs->next) return;
677         prs = prs->next;
678      }
679    else
680      {
681         parsers = calloc(1, sizeof(Ecore_X_Selection_Parser));
682         if (!parsers) return;
683         prs = parsers;
684      }
685
686    prs->target = strdup(target);
687    prs->parse = func;
688 }
689
690 EAPI void
691 ecore_x_selection_parser_del(const char *target)
692 {
693    Ecore_X_Selection_Parser *prs, *prev_prs;
694
695    if (!target)
696      return;
697
698    LOGFN(__FILE__, __LINE__, __FUNCTION__);
699    prev_prs = NULL;
700    prs = parsers;
701
702    while (prs)
703      {
704         if (!strcmp(prs->target, target))
705           {
706              if (prev_prs)
707                prev_prs->next = prs->next;
708              else
709                {
710                   parsers = prs->next; /* This was the first parser */
711                }
712
713              free(prs->target);
714              free(prs);
715
716              return;
717           }
718
719         prev_prs = prs;
720         prs = prs->next;
721      }
722 }
723
724 /**
725  * Change the owner and last-change time for the specified selection.
726  * @param win The owner of the specified atom.
727  * @param atom The selection atom
728  * @param tim Specifies the time
729  * @since 1.1.0
730  */
731 EAPI void
732 ecore_x_selection_owner_set(Ecore_X_Window win,
733                             Ecore_X_Atom atom,
734                             Ecore_X_Time tim)
735 {
736    XSetSelectionOwner(_ecore_x_disp, atom, win, tim);
737 }
738
739 /**
740  * Return the window that currently owns the specified selection.
741  *
742  * @param atom The specified selection atom.
743  *
744  * @return The window that currently owns the specified selection.
745  * @since 1.1.0
746  */
747 EAPI Ecore_X_Window
748 ecore_x_selection_owner_get(Ecore_X_Atom atom)
749 {
750    return XGetSelectionOwner(_ecore_x_disp, atom);
751 }
752
753 /* Locate and run conversion callback for specified selection target */
754 void *
755 _ecore_x_selection_parse(const char *target,
756                          void *data,
757                          int size,
758                          int format)
759 {
760    Ecore_X_Selection_Parser *prs;
761    Ecore_X_Selection_Data *sel;
762
763    for (prs = parsers; prs; prs = prs->next)
764      {
765         if (!strcmp(prs->target, target))
766           {
767              sel = prs->parse(target, data, size, format);
768              if (sel) return sel;
769           }
770      }
771
772    /* Default, just return the data */
773    sel = calloc(1, sizeof(Ecore_X_Selection_Data));
774    if (!sel) return NULL;
775    sel->free = _ecore_x_selection_data_default_free;
776    sel->length = size;
777    sel->format = format;
778    sel->data = data;
779    return sel;
780 }
781
782 static int
783 _ecore_x_selection_data_default_free(void *data)
784 {
785    Ecore_X_Selection_Data *sel;
786
787    sel = data;
788    free(sel->data);
789    free(sel);
790    return 1;
791 }
792
793 static void *
794 _ecore_x_selection_parser_files(const char *target,
795                                 void *_data,
796                                 int size,
797                                 int format __UNUSED__)
798 {
799    Ecore_X_Selection_Data_Files *sel;
800    char *t, *data = _data;
801    int i, is;
802    char *tmp;
803    char **t2;
804
805    if (strcmp(target, "text/uri-list") &&
806        strcmp(target, "_NETSCAPE_URL"))
807      return NULL;
808
809    sel = calloc(1, sizeof(Ecore_X_Selection_Data_Files));
810    if (!sel) return NULL;
811    ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_files_free;
812
813    if (data[size - 1])
814      {
815         /* Isn't nul terminated */
816         size++;
817         t = realloc(data, size);
818         if (!t)
819           {
820              free(sel);
821              return NULL;
822           }
823         data = t;
824         data[size - 1] = 0;
825      }
826
827    tmp = malloc(size);
828    if (!tmp)
829      {
830         free(sel);
831         return NULL;
832      }
833    i = 0;
834    is = 0;
835    while ((is < size) && (data[is]))
836      {
837         if ((i == 0) && (data[is] == '#'))
838           for (; ((data[is]) && (data[is] != '\n')); is++) ;
839         else
840           {
841              if ((data[is] != '\r') &&
842                  (data[is] != '\n'))
843                tmp[i++] = data[is++];
844              else
845                {
846                   while ((data[is] == '\r') || (data[is] == '\n'))
847                     is++;
848                   tmp[i] = 0;
849                   sel->num_files++;
850                   t2 = realloc(sel->files, sel->num_files * sizeof(char *));
851                   if (t2)
852                     {
853                        sel->files = t2;
854                        sel->files[sel->num_files - 1] = strdup(tmp);
855                     }
856                   tmp[0] = 0;
857                   i = 0;
858                }
859           }
860      }
861    if (i > 0)
862      {
863         tmp[i] = 0;
864         sel->num_files++;
865         t2 = realloc(sel->files, sel->num_files * sizeof(char *));
866         if (t2)
867           {
868              sel->files = t2;
869              sel->files[sel->num_files - 1] = strdup(tmp);
870           }
871      }
872
873    free(tmp);
874    free(data);
875
876    ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_FILES;
877    ECORE_X_SELECTION_DATA(sel)->length = sel->num_files;
878
879    return ECORE_X_SELECTION_DATA(sel);
880 }
881
882 static int
883 _ecore_x_selection_data_files_free(void *data)
884 {
885    Ecore_X_Selection_Data_Files *sel;
886    int i;
887
888    sel = data;
889    if (sel->files)
890      {
891         for (i = 0; i < sel->num_files; i++)
892           free(sel->files[i]);
893         free(sel->files);
894      }
895
896    free(sel);
897    return 0;
898 }
899
900 static void *
901 _ecore_x_selection_parser_text(const char *target __UNUSED__,
902                                void *_data,
903                                int size,
904                                int format __UNUSED__)
905 {
906    Ecore_X_Selection_Data_Text *sel;
907    unsigned char *data = _data;
908    void *t;
909
910    sel = calloc(1, sizeof(Ecore_X_Selection_Data_Text));
911    if (!sel) return NULL;
912    if (data[size - 1])
913      {
914         /* Isn't nul terminated */
915         size++;
916         t = realloc(data, size);
917         if (!t)
918           {
919              free(sel);
920              return NULL;
921           }
922         data = t;
923         data[size - 1] = 0;
924      }
925
926    sel->text = (char *)data;
927    ECORE_X_SELECTION_DATA(sel)->length = size;
928    ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TEXT;
929    ECORE_X_SELECTION_DATA(sel)->data = data;
930    ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_text_free;
931    return sel;
932 }
933
934 static int
935 _ecore_x_selection_data_text_free(void *data)
936 {
937    Ecore_X_Selection_Data_Text *sel;
938
939    sel = data;
940    free(sel->text);
941    free(sel);
942    return 1;
943 }
944
945 static void *
946 _ecore_x_selection_parser_targets(const char *target __UNUSED__,
947                                   void *data,
948                                   int size,
949                                   int format __UNUSED__)
950 {
951    Ecore_X_Selection_Data_Targets *sel;
952    unsigned long *targets;
953    int i;
954
955    sel = calloc(1, sizeof(Ecore_X_Selection_Data_Targets));
956    if (!sel) return NULL;
957    targets = (unsigned long *)data;
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    for (i = 2; i < size; i++)
967      sel->targets[i - 2] = XGetAtomName(_ecore_x_disp, targets[i]);
968
969    ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_targets_free;
970    ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TARGETS;
971    ECORE_X_SELECTION_DATA(sel)->length = size;
972    ECORE_X_SELECTION_DATA(sel)->data = data;
973    return sel;
974 }
975
976 static int
977 _ecore_x_selection_data_targets_free(void *data)
978 {
979    Ecore_X_Selection_Data_Targets *sel;
980    int i;
981
982    sel = data;
983
984    if (sel->targets)
985      {
986         for (i = 0; i < sel->num_targets; i++)
987           XFree(sel->targets[i]);
988         free(sel->targets);
989      }
990
991    free(ECORE_X_SELECTION_DATA(sel)->data);
992    free(sel);
993    return 1;
994 }
995