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