3 #endif /* ifdef HAVE_CONFIG_H */
17 # define alloca __builtin_alloca
19 # define alloca __alloca
20 # elif defined _MSC_VER
22 # define alloca _alloca
23 # elif !defined HAVE_ALLOCA
27 void *alloca (size_t);
35 #include "ecore_private.h"
36 #include "ecore_x_private.h"
38 #include "Ecore_X_Atoms.h"
40 static Ecore_X_Selection_Intern selections[4];
41 static Ecore_X_Selection_Converter *converters = NULL;
42 static Ecore_X_Selection_Parser *parsers = NULL;
44 static Eina_Bool _ecore_x_selection_converter_text(char *target,
51 static int _ecore_x_selection_data_default_free(void *data);
52 static void *_ecore_x_selection_parser_files(const char *target,
56 static int _ecore_x_selection_data_files_free(void *data);
57 static void *_ecore_x_selection_parser_text(const char *target,
61 static int _ecore_x_selection_data_text_free(void *data);
62 static void *_ecore_x_selection_parser_targets(const char *target,
66 static int _ecore_x_selection_data_targets_free(void *data);
68 #define ECORE_X_SELECTION_DATA(x) ((Ecore_X_Selection_Data *)(x))
71 _ecore_x_selection_data_init(void)
73 /* Initialize global data */
74 memset(selections, 0, sizeof(selections));
76 /* Initialize converters */
77 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_TEXT,
78 _ecore_x_selection_converter_text);
79 #ifdef X_HAVE_UTF8_STRING
80 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_UTF8_STRING,
81 _ecore_x_selection_converter_text);
82 #endif /* ifdef X_HAVE_UTF8_STRING */
83 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_COMPOUND_TEXT,
84 _ecore_x_selection_converter_text);
85 ecore_x_selection_converter_atom_add(ECORE_X_ATOM_STRING,
86 _ecore_x_selection_converter_text);
88 /* Initialize parsers */
89 ecore_x_selection_parser_add("text/plain",
90 _ecore_x_selection_parser_text);
91 ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_UTF8_STRING,
92 _ecore_x_selection_parser_text);
93 ecore_x_selection_parser_add("text/uri-list",
94 _ecore_x_selection_parser_files);
95 ecore_x_selection_parser_add("_NETSCAPE_URL",
96 _ecore_x_selection_parser_files);
97 ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_TARGETS,
98 _ecore_x_selection_parser_targets);
102 _ecore_x_selection_shutdown(void)
104 Ecore_X_Selection_Converter *cnv;
105 Ecore_X_Selection_Parser *prs;
107 /* free the selection converters */
111 Ecore_X_Selection_Converter *tmp;
119 /* free the selection parsers */
123 Ecore_X_Selection_Parser *tmp;
133 Ecore_X_Selection_Intern *
134 _ecore_x_selection_get(Ecore_X_Atom selection)
136 if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
137 return &selections[0];
138 else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
139 return &selections[1];
140 else if (selection == ECORE_X_ATOM_SELECTION_XDND)
141 return &selections[2];
142 else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
143 return &selections[3];
149 _ecore_x_selection_set(Window w,
152 Ecore_X_Atom selection)
155 unsigned char *buf = NULL;
157 XSetSelectionOwner(_ecore_x_disp, selection, w, _ecore_x_event_last_time);
158 if (XGetSelectionOwner(_ecore_x_disp, selection) != w)
161 if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
163 else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
165 else if (selection == ECORE_X_ATOM_SELECTION_XDND)
167 else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
174 selections[in].win = w;
175 selections[in].selection = selection;
176 selections[in].length = size;
177 selections[in].time = _ecore_x_event_last_time;
180 if (!buf) return EINA_FALSE;
181 memcpy(buf, data, size);
182 selections[in].data = buf;
184 else if (selections[in].data)
186 free(selections[in].data);
187 memset(&selections[in], 0, sizeof(Ecore_X_Selection_Data));
194 * Claim ownership of the PRIMARY selection and set its data.
195 * @param w The window to which this selection belongs
196 * @param data The data associated with the selection
197 * @param size The size of the data buffer in bytes
198 * @return Returns 1 if the ownership of the selection was successfully
199 * claimed, or 0 if unsuccessful.
202 ecore_x_selection_primary_set(Ecore_X_Window w,
206 LOGFN(__FILE__, __LINE__, __FUNCTION__);
207 return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_PRIMARY);
211 * Release ownership of the primary selection
212 * @return Returns 1 if the selection was successfully cleared,
213 * or 0 if unsuccessful.
217 ecore_x_selection_primary_clear(void)
219 LOGFN(__FILE__, __LINE__, __FUNCTION__);
220 return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_PRIMARY);
224 * Claim ownership of the SECONDARY selection and set its data.
225 * @param w The window to which this selection belongs
226 * @param data The data associated with the selection
227 * @param size The size of the data buffer in bytes
228 * @return Returns 1 if the ownership of the selection was successfully
229 * claimed, or 0 if unsuccessful.
232 ecore_x_selection_secondary_set(Ecore_X_Window w,
236 LOGFN(__FILE__, __LINE__, __FUNCTION__);
237 return _ecore_x_selection_set(w,
240 ECORE_X_ATOM_SELECTION_SECONDARY);
244 * Release ownership of the secondary selection
245 * @return Returns 1 if the selection was successfully cleared,
246 * or 0 if unsuccessful.
250 ecore_x_selection_secondary_clear(void)
252 LOGFN(__FILE__, __LINE__, __FUNCTION__);
253 return _ecore_x_selection_set(None,
256 ECORE_X_ATOM_SELECTION_SECONDARY);
260 * Claim ownership of the XDND selection and set its data.
261 * @param w The window to which this selection belongs
262 * @param data The data associated with the selection
263 * @param size The size of the data buffer in bytes
264 * @return Returns 1 if the ownership of the selection was successfully
265 * claimed, or 0 if unsuccessful.
268 ecore_x_selection_xdnd_set(Ecore_X_Window w,
272 LOGFN(__FILE__, __LINE__, __FUNCTION__);
273 return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_XDND);
277 * Release ownership of the XDND selection
278 * @return Returns 1 if the selection was successfully cleared,
279 * or 0 if unsuccessful.
283 ecore_x_selection_xdnd_clear(void)
285 LOGFN(__FILE__, __LINE__, __FUNCTION__);
286 return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_XDND);
290 * Claim ownership of the CLIPBOARD selection and set its data.
291 * @param w The window to which this selection belongs
292 * @param data The data associated with the selection
293 * @param size The size of the data buffer in bytes
294 * @return Returns 1 if the ownership of the selection was successfully
295 * claimed, or 0 if unsuccessful.
297 * Get the converted data from a previous CLIPBOARD selection
298 * request. The buffer must be freed when done with.
301 ecore_x_selection_clipboard_set(Ecore_X_Window w,
305 LOGFN(__FILE__, __LINE__, __FUNCTION__);
306 return _ecore_x_selection_set(w,
309 ECORE_X_ATOM_SELECTION_CLIPBOARD);
313 * Release ownership of the clipboard selection
314 * @return Returns 1 if the selection was successfully cleared,
315 * or 0 if unsuccessful.
319 ecore_x_selection_clipboard_clear(void)
321 LOGFN(__FILE__, __LINE__, __FUNCTION__);
322 return _ecore_x_selection_set(None,
325 ECORE_X_ATOM_SELECTION_CLIPBOARD);
329 _ecore_x_selection_target_atom_get(const char *target)
331 Ecore_X_Atom x_target;
333 if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
334 x_target = ECORE_X_ATOM_TEXT;
335 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
336 x_target = ECORE_X_ATOM_COMPOUND_TEXT;
337 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
338 x_target = ECORE_X_ATOM_STRING;
339 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
340 x_target = ECORE_X_ATOM_UTF8_STRING;
341 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_FILENAME))
342 x_target = ECORE_X_ATOM_FILE_NAME;
344 x_target = ecore_x_atom_get(target);
350 _ecore_x_selection_target_get(Ecore_X_Atom target)
352 /* FIXME: Should not return mem allocated with strdup or X mixed,
353 * one should use free to free, the other XFree */
354 if (target == ECORE_X_ATOM_FILE_NAME)
355 return strdup(ECORE_X_SELECTION_TARGET_FILENAME);
356 else if (target == ECORE_X_ATOM_STRING)
357 return strdup(ECORE_X_SELECTION_TARGET_STRING);
358 else if (target == ECORE_X_ATOM_UTF8_STRING)
359 return strdup(ECORE_X_SELECTION_TARGET_UTF8_STRING);
360 else if (target == ECORE_X_ATOM_TEXT)
361 return strdup(ECORE_X_SELECTION_TARGET_TEXT);
363 return XGetAtomName(_ecore_x_disp, target);
367 _ecore_x_selection_request(Ecore_X_Window w,
368 Ecore_X_Atom selection,
369 const char *target_str)
371 Ecore_X_Atom target, prop;
373 target = _ecore_x_selection_target_atom_get(target_str);
375 if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
376 prop = ECORE_X_ATOM_SELECTION_PROP_PRIMARY;
377 else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
378 prop = ECORE_X_ATOM_SELECTION_PROP_SECONDARY;
379 else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
380 prop = ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD;
384 XConvertSelection(_ecore_x_disp, selection, target, prop,
389 ecore_x_selection_primary_request(Ecore_X_Window w,
392 LOGFN(__FILE__, __LINE__, __FUNCTION__);
393 _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_PRIMARY, target);
397 ecore_x_selection_secondary_request(Ecore_X_Window w,
400 LOGFN(__FILE__, __LINE__, __FUNCTION__);
401 _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_SECONDARY, target);
405 ecore_x_selection_xdnd_request(Ecore_X_Window w,
409 Ecore_X_DND_Target *_target;
411 LOGFN(__FILE__, __LINE__, __FUNCTION__);
412 _target = _ecore_x_dnd_target_get();
413 atom = _ecore_x_selection_target_atom_get(target);
414 XConvertSelection(_ecore_x_disp, ECORE_X_ATOM_SELECTION_XDND, atom,
415 ECORE_X_ATOM_SELECTION_PROP_XDND, w,
420 ecore_x_selection_clipboard_request(Ecore_X_Window w,
423 LOGFN(__FILE__, __LINE__, __FUNCTION__);
424 _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_CLIPBOARD, target);
428 ecore_x_selection_converter_atom_add(Ecore_X_Atom target,
429 Eina_Bool (*func)(char *target,
437 Ecore_X_Selection_Converter *cnv;
439 LOGFN(__FILE__, __LINE__, __FUNCTION__);
445 if (cnv->target == target)
457 cnv->next = calloc(1, sizeof(Ecore_X_Selection_Converter));
458 if (!cnv->next) return;
463 converters = calloc(1, sizeof(Ecore_X_Selection_Converter));
464 if (!converters) return;
468 cnv->target = target;
473 ecore_x_selection_converter_add(char *target,
474 Eina_Bool (*func)(char *target,
482 Ecore_X_Atom x_target;
484 if (!func || !target)
487 LOGFN(__FILE__, __LINE__, __FUNCTION__);
488 x_target = _ecore_x_selection_target_atom_get(target);
490 ecore_x_selection_converter_atom_add(x_target, func);
494 ecore_x_selection_converter_atom_del(Ecore_X_Atom target)
496 Ecore_X_Selection_Converter *cnv, *prev_cnv;
498 LOGFN(__FILE__, __LINE__, __FUNCTION__);
504 if (cnv->target == target)
507 prev_cnv->next = cnv->next;
510 converters = cnv->next; /* This was the first converter */
524 ecore_x_selection_converter_del(char *target)
526 Ecore_X_Atom x_target;
531 LOGFN(__FILE__, __LINE__, __FUNCTION__);
532 x_target = _ecore_x_selection_target_atom_get(target);
533 ecore_x_selection_converter_atom_del(x_target);
537 ecore_x_selection_notify_send(Ecore_X_Window requestor,
538 Ecore_X_Atom selection,
540 Ecore_X_Atom property,
544 XSelectionEvent xnotify;
546 LOGFN(__FILE__, __LINE__, __FUNCTION__);
547 xnotify.type = SelectionNotify;
548 xnotify.display = _ecore_x_disp;
549 xnotify.requestor = requestor;
550 xnotify.selection = selection;
551 xnotify.target = target;
552 xnotify.property = property;
554 xnotify.send_event = True;
557 xev.xselection = xnotify;
558 return (XSendEvent(_ecore_x_disp, requestor, False, 0, &xev) > 0) ? EINA_TRUE : EINA_FALSE;
561 /* Locate and run conversion callback for specified selection target */
563 ecore_x_selection_convert(Ecore_X_Atom selection,
567 Ecore_X_Atom *targtype,
570 Ecore_X_Selection_Intern *sel;
571 Ecore_X_Selection_Converter *cnv;
575 LOGFN(__FILE__, __LINE__, __FUNCTION__);
576 sel = _ecore_x_selection_get(selection);
577 tgt_str = _ecore_x_selection_target_get(target);
579 for (cnv = converters; cnv; cnv = cnv->next)
581 if (cnv->target == target)
585 r = cnv->convert(tgt_str, sel->data, sel->length, &data, size,
599 /* 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." */
602 /* Default, just return the data
603 * data_ret = malloc(sel->length);
604 memcpy(*data_ret, sel->data, sel->length);
610 /* TODO: We need to work out a mechanism for automatic conversion to any requested
611 * locale using Ecore_Txt functions */
612 /* Converter for standard non-utf8 text targets */
614 _ecore_x_selection_converter_text(char *target,
619 Ecore_X_Atom *targprop __UNUSED__,
622 XTextProperty text_prop;
624 XICCEncodingStyle style;
629 LOGFN(__FILE__, __LINE__, __FUNCTION__);
630 if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
632 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
633 style = XCompoundTextStyle;
634 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
635 style = XStringStyle;
637 #ifdef X_HAVE_UTF8_STRING
638 else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
639 style = XUTF8StringStyle;
640 #endif /* ifdef X_HAVE_UTF8_STRING */
644 mystr = alloca(size + 1);
645 memcpy(mystr, data, size);
648 #ifdef X_HAVE_UTF8_STRING
649 if (Xutf8TextListToTextProperty(_ecore_x_disp, &mystr, 1, style,
650 &text_prop) == Success)
652 int bufsize = strlen((char *)text_prop.value) + 1;
653 *data_ret = malloc(bufsize);
658 memcpy(*data_ret, text_prop.value, bufsize);
660 XFree(text_prop.value);
664 #else /* ifdef X_HAVE_UTF8_STRING */
665 if (XmbTextListToTextProperty(_ecore_x_disp, &mystr, 1, style,
666 &text_prop) == Success)
668 int bufsize = strlen(text_prop.value) + 1;
669 *data_ret = malloc(bufsize);
670 if (!*data_ret) return EINA_FALSE;
671 memcpy(*data_ret, text_prop.value, bufsize);
673 XFree(text_prop.value);
677 #endif /* ifdef X_HAVE_UTF8_STRING */
685 ecore_x_selection_parser_add(const char *target,
686 void *(*func)(const char *target, void *data,
690 Ecore_X_Selection_Parser *prs;
695 LOGFN(__FILE__, __LINE__, __FUNCTION__);
701 if (!strcmp(prs->target, target))
710 prs->next = calloc(1, sizeof(Ecore_X_Selection_Parser));
711 if (!prs->next) return;
716 parsers = calloc(1, sizeof(Ecore_X_Selection_Parser));
717 if (!parsers) return;
721 prs->target = strdup(target);
726 ecore_x_selection_parser_del(const char *target)
728 Ecore_X_Selection_Parser *prs, *prev_prs;
733 LOGFN(__FILE__, __LINE__, __FUNCTION__);
739 if (!strcmp(prs->target, target))
742 prev_prs->next = prs->next;
745 parsers = prs->next; /* This was the first parser */
760 * Change the owner and last-change time for the specified selection.
761 * @param win The owner of the specified atom.
762 * @param atom The selection atom
763 * @param tim Specifies the time
767 ecore_x_selection_owner_set(Ecore_X_Window win,
771 XSetSelectionOwner(_ecore_x_disp, atom, win, tim);
775 * Return the window that currently owns the specified selection.
777 * @param atom The specified selection atom.
779 * @return The window that currently owns the specified selection.
783 ecore_x_selection_owner_get(Ecore_X_Atom atom)
785 return XGetSelectionOwner(_ecore_x_disp, atom);
788 /* Locate and run conversion callback for specified selection target */
790 _ecore_x_selection_parse(const char *target,
795 Ecore_X_Selection_Parser *prs;
796 Ecore_X_Selection_Data *sel;
798 for (prs = parsers; prs; prs = prs->next)
800 if (!strcmp(prs->target, target))
802 sel = prs->parse(target, data, size, format);
807 /* Default, just return the data */
808 sel = calloc(1, sizeof(Ecore_X_Selection_Data));
809 if (!sel) return NULL;
810 sel->free = _ecore_x_selection_data_default_free;
812 sel->format = format;
818 _ecore_x_selection_data_default_free(void *data)
820 Ecore_X_Selection_Data *sel;
829 _ecore_x_selection_parser_files(const char *target,
832 int format __UNUSED__)
834 Ecore_X_Selection_Data_Files *sel;
835 char *t, *data = _data;
840 if (strcmp(target, "text/uri-list") &&
841 strcmp(target, "_NETSCAPE_URL"))
844 sel = calloc(1, sizeof(Ecore_X_Selection_Data_Files));
845 if (!sel) return NULL;
846 ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_files_free;
848 if (data && data[size - 1])
850 /* Isn't nul terminated */
852 t = realloc(data, size);
870 while ((is < size) && (data[is]))
872 if ((i == 0) && (data[is] == '#'))
873 for (; ((data[is]) && (data[is] != '\n')); is++) ;
876 if ((data[is] != '\r') &&
878 tmp[i++] = data[is++];
881 while ((data[is] == '\r') || (data[is] == '\n'))
885 t2 = realloc(sel->files, sel->num_files * sizeof(char *));
889 sel->files[sel->num_files - 1] = strdup(tmp);
900 t2 = realloc(sel->files, sel->num_files * sizeof(char *));
904 sel->files[sel->num_files - 1] = strdup(tmp);
911 ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_FILES;
912 ECORE_X_SELECTION_DATA(sel)->length = sel->num_files;
914 return ECORE_X_SELECTION_DATA(sel);
918 _ecore_x_selection_data_files_free(void *data)
920 Ecore_X_Selection_Data_Files *sel;
926 for (i = 0; i < sel->num_files; i++)
936 _ecore_x_selection_parser_text(const char *target __UNUSED__,
939 int format __UNUSED__)
941 Ecore_X_Selection_Data_Text *sel;
942 unsigned char *data = _data;
945 sel = calloc(1, sizeof(Ecore_X_Selection_Data_Text));
946 if (!sel) return NULL;
947 if (data && data[size - 1])
949 /* Isn't nul terminated */
951 t = realloc(data, size);
961 sel->text = (char *)data;
962 ECORE_X_SELECTION_DATA(sel)->length = size;
963 ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TEXT;
964 ECORE_X_SELECTION_DATA(sel)->data = data;
965 ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_text_free;
970 _ecore_x_selection_data_text_free(void *data)
972 Ecore_X_Selection_Data_Text *sel;
981 _ecore_x_selection_parser_targets(const char *target __UNUSED__,
984 int format __UNUSED__)
986 Ecore_X_Selection_Data_Targets *sel;
990 sel = calloc(1, sizeof(Ecore_X_Selection_Data_Targets));
991 if (!sel) return NULL;
994 sel->num_targets = size - 2;
995 sel->targets = malloc((size - 2) * sizeof(char *));
1001 for (i = 2; i < size; i++)
1002 sel->targets[i - 2] = XGetAtomName(_ecore_x_disp, targets[i]);
1004 ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_targets_free;
1005 ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TARGETS;
1006 ECORE_X_SELECTION_DATA(sel)->length = size;
1007 ECORE_X_SELECTION_DATA(sel)->data = data;
1012 _ecore_x_selection_data_targets_free(void *data)
1014 Ecore_X_Selection_Data_Targets *sel;
1021 for (i = 0; i < sel->num_targets; i++)
1022 XFree(sel->targets[i]);
1026 free(ECORE_X_SELECTION_DATA(sel)->data);