From f07f36b661d757811ae530840cfb1c2d92d57da8 Mon Sep 17 00:00:00 2001 From: sebastid Date: Sun, 10 Apr 2005 10:20:18 +0000 Subject: [PATCH] Selection and DND update. Broke some api's, so please update. SVN revision: 14132 --- legacy/ecore/src/lib/ecore_x/Ecore_X.h | 46 +- legacy/ecore/src/lib/ecore_x/Ecore_X_Atoms.h | 1 + legacy/ecore/src/lib/ecore_x/ecore_x.c | 2 + legacy/ecore/src/lib/ecore_x/ecore_x_dnd.c | 5 +- legacy/ecore/src/lib/ecore_x/ecore_x_events.c | 122 +---- legacy/ecore/src/lib/ecore_x/ecore_x_icccm.c | 2 +- legacy/ecore/src/lib/ecore_x/ecore_x_netwm.c | 4 +- .../ecore/src/lib/ecore_x/ecore_x_private.h | 44 +- .../ecore/src/lib/ecore_x/ecore_x_selection.c | 462 ++++++++++++------ 9 files changed, 422 insertions(+), 266 deletions(-) diff --git a/legacy/ecore/src/lib/ecore_x/Ecore_X.h b/legacy/ecore/src/lib/ecore_x/Ecore_X.h index fa2732d4b5..85e25741d1 100644 --- a/legacy/ecore/src/lib/ecore_x/Ecore_X.h +++ b/legacy/ecore/src/lib/ecore_x/Ecore_X.h @@ -56,6 +56,7 @@ typedef struct _Ecore_X_Rectangle { unsigned int width, height; } Ecore_X_Rectangle; +#define ECORE_X_SELECTION_TARGET_TARGETS "TARGETS" #define ECORE_X_SELECTION_TARGET_TEXT "TEXT" #define ECORE_X_SELECTION_TARGET_COMPOUND_TEXT "COMPOUND_TEXT" #define ECORE_X_SELECTION_TARGET_STRING "STRING" @@ -170,6 +171,10 @@ typedef struct _Ecore_X_Event_Window_Mapping Ecore_X_Event_Window_Mapp typedef struct _Ecore_X_Event_Selection_Clear Ecore_X_Event_Selection_Clear; typedef struct _Ecore_X_Event_Selection_Request Ecore_X_Event_Selection_Request; typedef struct _Ecore_X_Event_Selection_Notify Ecore_X_Event_Selection_Notify; +typedef struct _Ecore_X_Selection_Data Ecore_X_Selection_Data; +typedef struct _Ecore_X_Selection_Data_Files Ecore_X_Selection_Data_Files; +typedef struct _Ecore_X_Selection_Data_Text Ecore_X_Selection_Data_Text; +typedef struct _Ecore_X_Selection_Data_Targets Ecore_X_Selection_Data_Targets; typedef struct _Ecore_X_Event_Xdnd_Enter Ecore_X_Event_Xdnd_Enter; typedef struct _Ecore_X_Event_Xdnd_Position Ecore_X_Event_Xdnd_Position; typedef struct _Ecore_X_Event_Xdnd_Status Ecore_X_Event_Xdnd_Status; @@ -450,17 +455,42 @@ struct _Ecore_X_Event_Selection_Notify Ecore_X_Time time; Ecore_X_Selection selection; char *target; - + void *data; enum { - ECORE_X_SELECTION_NONE, - ECORE_X_SELECTION_TEXT, - ECORE_X_SELECTION_FILES + ECORE_X_SELECTION_CONTENT_NONE, + ECORE_X_SELECTION_CONTENT_TEXT, + ECORE_X_SELECTION_CONTENT_FILES, + ECORE_X_SELECTION_CONTENT_TARGETS, + ECORE_X_SELECTION_CONTENT_CUSTOM } content; +}; - char *text; +struct _Ecore_X_Selection_Data +{ + unsigned char *data; + int length; - char **files; - int num_files; + int (*free)(void *data); +}; + +struct _Ecore_X_Selection_Data_Files +{ + Ecore_X_Selection_Data data; + char **files; + int num_files; +}; + +struct _Ecore_X_Selection_Data_Text +{ + Ecore_X_Selection_Data data; + char *text; +}; + +struct _Ecore_X_Selection_Data_Targets +{ + Ecore_X_Selection_Data data; + char **targets; + int num_targets; }; struct _Ecore_X_Event_Xdnd_Enter @@ -830,6 +860,8 @@ EAPI void ecore_x_selection_converter_add(char *target, int (*func)( EAPI void ecore_x_selection_converter_atom_add(Ecore_X_Atom target, int (*func)(char *target, void *data, int size, void **data_ret, int *size_ret)); EAPI void ecore_x_selection_converter_del(char *target); EAPI void ecore_x_selection_converter_atom_del(Ecore_X_Atom target); +EAPI void ecore_x_selection_parser_add(const char *target, void *(*func)(const char *target, unsigned char *data, int size)); +EAPI void ecore_x_selection_parser_del(const char *target); EAPI void ecore_x_dnd_aware_set(Ecore_X_Window win, int on); EAPI int ecore_x_dnd_version_get(Ecore_X_Window win); diff --git a/legacy/ecore/src/lib/ecore_x/Ecore_X_Atoms.h b/legacy/ecore/src/lib/ecore_x/Ecore_X_Atoms.h index 2223d61449..d591f6338a 100644 --- a/legacy/ecore/src/lib/ecore_x/Ecore_X_Atoms.h +++ b/legacy/ecore/src/lib/ecore_x/Ecore_X_Atoms.h @@ -114,6 +114,7 @@ extern Ecore_X_Atom ECORE_X_ATOM_NET_FRAME_EXTENTS; extern Ecore_X_Atom ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS; /* Selections */ +extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_TARGETS; extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_PRIMARY; extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_SECONDARY; extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_CLIPBOARD; diff --git a/legacy/ecore/src/lib/ecore_x/ecore_x.c b/legacy/ecore/src/lib/ecore_x/ecore_x.c index 169ea44864..f8fdb93d78 100644 --- a/legacy/ecore/src/lib/ecore_x/ecore_x.c +++ b/legacy/ecore/src/lib/ecore_x/ecore_x.c @@ -45,6 +45,7 @@ Ecore_X_Atom ECORE_X_ATOM_WIN_LAYER = 0; /* * Other hints. */ +Ecore_X_Atom ECORE_X_ATOM_SELECTION_TARGETS; Ecore_X_Atom ECORE_X_ATOM_SELECTION_PRIMARY = 0; Ecore_X_Atom ECORE_X_ATOM_SELECTION_SECONDARY = 0; Ecore_X_Atom ECORE_X_ATOM_SELECTION_CLIPBOARD = 0; @@ -329,6 +330,7 @@ ecore_x_init(const char *name) ecore_x_e_init(); /* This is just to be anal about naming conventions */ + ECORE_X_ATOM_SELECTION_TARGETS = XInternAtom(_ecore_x_disp, "TARGETS", False); ECORE_X_ATOM_SELECTION_PRIMARY = XA_PRIMARY; ECORE_X_ATOM_SELECTION_SECONDARY = XA_SECONDARY; ECORE_X_ATOM_SELECTION_CLIPBOARD = XInternAtom(_ecore_x_disp, "CLIPBOARD", False); diff --git a/legacy/ecore/src/lib/ecore_x/ecore_x_dnd.c b/legacy/ecore/src/lib/ecore_x/ecore_x_dnd.c index 5122f2afc1..84f33576f1 100644 --- a/legacy/ecore/src/lib/ecore_x/ecore_x_dnd.c +++ b/legacy/ecore/src/lib/ecore_x/ecore_x_dnd.c @@ -51,7 +51,7 @@ _ecore_x_dnd_shutdown(void) void ecore_x_dnd_aware_set(Ecore_X_Window win, int on) { - Atom prop_data = ECORE_X_DND_VERSION; + Ecore_X_Atom prop_data = ECORE_X_DND_VERSION; if (on) ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_AWARE, @@ -144,7 +144,7 @@ ecore_x_dnd_type_set(Ecore_X_Window win, const char *type, int on) XFree(old_data); return; } - newset = calloc(num - 1, sizeof(Atom)); + newset = calloc(num - 1, sizeof(Ecore_X_Atom)); if (!newset) { XFree(old_data); @@ -331,7 +331,6 @@ _ecore_x_dnd_drag(int x, int y) /* Send XdndLeave to current destination window if we have left it */ if ((_source->dest) && (win != _source->dest)) { - printf("source: 0x%x, dest: 0x%x\n", _source->win, _source->dest); xev.xclient.window = _source->dest; xev.xclient.message_type = ECORE_X_ATOM_XDND_LEAVE; xev.xclient.data.l[0] = _source->win; diff --git a/legacy/ecore/src/lib/ecore_x/ecore_x_events.c b/legacy/ecore/src/lib/ecore_x/ecore_x_events.c index aab8fe983a..8c92bbf607 100644 --- a/legacy/ecore/src/lib/ecore_x/ecore_x_events.c +++ b/legacy/ecore/src/lib/ecore_x/ecore_x_events.c @@ -152,22 +152,12 @@ static void _ecore_x_event_free_selection_notify(void *data __UNUSED__, void *ev) { Ecore_X_Event_Selection_Notify *e; - int i; + Ecore_X_Selection_Data *sel; e = ev; - switch (e->content) - { - case ECORE_X_SELECTION_NONE: - break; - case ECORE_X_SELECTION_FILES: - for (i = 0; i < e->num_files; i++) - free(e->files[i]); - free(e->files); - break; - case ECORE_X_SELECTION_TEXT: - free(e->text); - break; - } + sel = e->data; + if (sel->free) + sel->free(sel); free(e->target); free(e); } @@ -989,9 +979,9 @@ _ecore_x_event_handle_property_notify(XEvent *xevent) void _ecore_x_event_handle_selection_clear(XEvent *xevent) { - Ecore_X_Selection_Data *d; + Ecore_X_Selection_Intern *d; Ecore_X_Event_Selection_Clear *e; - Atom sel; + Ecore_X_Atom sel; if (!(d = _ecore_x_selection_get(xevent->xselectionclear.selection))) return; @@ -1019,7 +1009,7 @@ _ecore_x_event_handle_selection_clear(XEvent *xevent) void _ecore_x_event_handle_selection_request(XEvent *xevent) { - Ecore_X_Selection_Data *sd; + Ecore_X_Selection_Intern *sd; XSelectionEvent xnotify; XEvent xev; void *data; @@ -1067,96 +1057,37 @@ _ecore_x_event_handle_selection_notify(XEvent *xevent) { Ecore_X_Event_Selection_Notify *e; unsigned char *data = NULL; - Atom selection; + Ecore_X_Atom selection; int num_ret; - Ecore_X_Selection_Data sel_data; + + selection = xevent->xselection.selection; + + if (xevent->xselection.target == ECORE_X_ATOM_SELECTION_TARGETS) + { + if (!ecore_x_window_prop_property_get(xevent->xselection.requestor, + xevent->xselection.property, + XA_ATOM, 32, &data, &num_ret)) + return; + } + else + { + if (!ecore_x_window_prop_property_get(xevent->xselection.requestor, + xevent->xselection.property, + AnyPropertyType, 8, &data, &num_ret)) + return; + } e = calloc(1, sizeof(Ecore_X_Event_Selection_Notify)); e->win = xevent->xselection.requestor; e->time = xevent->xselection.time; e->target = _ecore_x_selection_target_get(xevent->xselection.target); - selection = xevent->xselection.selection; - - if (!ecore_x_window_prop_property_get(e->win, xevent->xselection.property, - AnyPropertyType, 8, &data, &num_ret)) - { - free(e); - return; - } - - sel_data.win = e->win; - sel_data.selection = selection; - sel_data.data = data; - sel_data.length = num_ret; - _ecore_x_selection_request_data_set(sel_data); if (selection == ECORE_X_ATOM_SELECTION_PRIMARY) e->selection = ECORE_X_SELECTION_PRIMARY; else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY) e->selection = ECORE_X_SELECTION_SECONDARY; else if (selection == ECORE_X_ATOM_SELECTION_XDND) - { - e->selection = ECORE_X_SELECTION_XDND; - if (!strcmp(e->target, "text/uri-list")) - { - int i, is; - char *tmp; - - e->content = ECORE_X_SELECTION_FILES; - - tmp = malloc(num_ret * sizeof(char)); - i = 0; - is = 0; - e->files = NULL; - while ((is < num_ret) && (data[is])) - { - if ((i == 0) && (data[is] == '#')) - { - for (; ((data[is]) && (data[is] != '\n')); is++); - } - else - { - if ((data[is] != '\r') - && (data[is] != '\n')) - { - tmp[i++] = data[is++]; - } - else - { - while ((data[is] == '\r') - || (data[is] == '\n')) - is++; - tmp[i] = 0; - e->num_files++; - e->files = realloc(e->files, e->num_files * sizeof(char *)); - e->files[e->num_files - 1] = strdup(tmp); - tmp[0] = 0; - i = 0; - } - } - } - if (i > 0) - { - tmp[i] = 0; - e->num_files++; - e->files = realloc(e->files, e->num_files * sizeof(char *)); - e->files[e->num_files - 1] = strdup(tmp); - } - free(tmp); - } - else if (!strcmp(e->target, "_NETSCAPE_URL")) - { - e->content = ECORE_X_SELECTION_FILES; - e->num_files = 1; - e->files = malloc(sizeof(char *)); - e->files[0] = data; - } - else if (!strcmp(e->target, "text/plain")) - { - e->content = ECORE_X_SELECTION_TEXT; - e->text = data; - } - } + e->selection = ECORE_X_SELECTION_XDND; else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) e->selection = ECORE_X_SELECTION_CLIPBOARD; else @@ -1164,6 +1095,7 @@ _ecore_x_event_handle_selection_notify(XEvent *xevent) free(e); return; } + e->data = _ecore_x_selection_parse(e->target, data, num_ret); ecore_event_add(ECORE_X_EVENT_SELECTION_NOTIFY, e, _ecore_x_event_free_selection_notify, NULL); } diff --git a/legacy/ecore/src/lib/ecore_x/ecore_x_icccm.c b/legacy/ecore/src/lib/ecore_x/ecore_x_icccm.c index c37fecc63f..714147019e 100644 --- a/legacy/ecore/src/lib/ecore_x/ecore_x_icccm.c +++ b/legacy/ecore/src/lib/ecore_x/ecore_x_icccm.c @@ -565,7 +565,7 @@ ecore_x_icccm_protocol_set(Ecore_X_Window win, if (on) { - Atom *new_protos = NULL; + Atom *new_protos = NULL; if (already_set) goto leave; diff --git a/legacy/ecore/src/lib/ecore_x/ecore_x_netwm.c b/legacy/ecore/src/lib/ecore_x/ecore_x_netwm.c index 15bf434dba..0eaa29fbf6 100644 --- a/legacy/ecore/src/lib/ecore_x/ecore_x_netwm.c +++ b/legacy/ecore/src/lib/ecore_x/ecore_x_netwm.c @@ -860,7 +860,7 @@ ecore_x_netwm_window_state_set(Ecore_X_Window win, Ecore_X_Window_State state, i XFree(old_data); return; } - newset = calloc(num - 1, sizeof(Atom)); + newset = calloc(num - 1, sizeof(Ecore_X_Atom)); if (!newset) { XFree(old_data); @@ -1071,7 +1071,7 @@ ecore_x_netwm_allowed_action_set(Ecore_X_Window win, Ecore_X_Action action, int XFree(old_data); return; } - newset = calloc(num - 1, sizeof(Atom)); + newset = calloc(num - 1, sizeof(Ecore_X_Atom)); if (!newset) { XFree(old_data); diff --git a/legacy/ecore/src/lib/ecore_x/ecore_x_private.h b/legacy/ecore/src/lib/ecore_x/ecore_x_private.h index c74072e869..726267819d 100644 --- a/legacy/ecore/src/lib/ecore_x/ecore_x_private.h +++ b/legacy/ecore/src/lib/ecore_x/ecore_x_private.h @@ -47,12 +47,12 @@ struct _Ecore_X_Reply void *data; }; -typedef struct _Ecore_X_Selection_Data Ecore_X_Selection_Data; +typedef struct _Ecore_X_Selection_Intern Ecore_X_Selection_Intern; -struct _Ecore_X_Selection_Data +struct _Ecore_X_Selection_Intern { - Window win; - Atom selection; + Ecore_X_Window win; + Ecore_X_Atom selection; unsigned char *data; int length; Time time; @@ -62,10 +62,19 @@ typedef struct _Ecore_X_Selection_Converter Ecore_X_Selection_Converter; struct _Ecore_X_Selection_Converter { - Atom target; - int (*convert)(char *target, void *data, int size, - void **data_ret, int *size_ret); - struct _Ecore_X_Selection_Converter *next; + Ecore_X_Atom target; + int (*convert)(char *target, void *data, int size, + void **data_ret, int *size_ret); + Ecore_X_Selection_Converter *next; +}; + +typedef struct _Ecore_X_Selection_Parser Ecore_X_Selection_Parser; + +struct _Ecore_X_Selection_Parser +{ + char *target; + void *(*parse)(const char *target, unsigned char *data, int size); + Ecore_X_Selection_Parser *next; }; typedef struct _Ecore_X_DND_Source @@ -166,15 +175,16 @@ void _ecore_x_event_handle_client_message(XEvent *xevent); void _ecore_x_event_handle_mapping_notify(XEvent *xevent); void _ecore_x_event_handle_shape_change(XEvent *xevent); -void _ecore_x_selection_data_init(void); -void _ecore_x_selection_shutdown(void); -Atom _ecore_x_selection_target_atom_get(char *target); -char *_ecore_x_selection_target_get(Atom target); -void _ecore_x_selection_request_data_set(Ecore_X_Selection_Data data); -Ecore_X_Selection_Data * - _ecore_x_selection_get(Atom selection); -int _ecore_x_selection_set(Window w, unsigned char *data, int len, Atom selection); -int _ecore_x_selection_convert(Atom selection, Atom target, void **data_ret); +void _ecore_x_selection_data_init(void); +void _ecore_x_selection_shutdown(void); +Ecore_X_Atom + _ecore_x_selection_target_atom_get(const char *target); +char *_ecore_x_selection_target_get(Ecore_X_Atom target); +Ecore_X_Selection_Intern * + _ecore_x_selection_get(Ecore_X_Atom selection); +int _ecore_x_selection_set(Window w, unsigned char *data, int len, Ecore_X_Atom selection); +int _ecore_x_selection_convert(Ecore_X_Atom selection, Ecore_X_Atom target, void **data_ret); +void *_ecore_x_selection_parse(const char *target, unsigned char *data, int size); void _ecore_x_dnd_init(void); Ecore_X_DND_Source *_ecore_x_dnd_source_get(void); diff --git a/legacy/ecore/src/lib/ecore_x/ecore_x_selection.c b/legacy/ecore/src/lib/ecore_x/ecore_x_selection.c index 904cefd1bf..5b2db7aae2 100644 --- a/legacy/ecore/src/lib/ecore_x/ecore_x_selection.c +++ b/legacy/ecore/src/lib/ecore_x/ecore_x_selection.c @@ -6,18 +6,26 @@ #include "Ecore_X.h" #include "Ecore_X_Atoms.h" -static Ecore_X_Selection_Data selections[4]; -static Ecore_X_Selection_Data request_data[4]; +static Ecore_X_Selection_Intern selections[4]; static Ecore_X_Selection_Converter *converters = NULL; +static Ecore_X_Selection_Parser *parsers = NULL; static int _ecore_x_selection_converter_text(char *target, void *data, int size, void **data_ret, int *size_ret); +static int _ecore_x_selection_data_default_free(void *data); +static void *_ecore_x_selection_parser_files(const char *target, unsigned char *data, int size); +static int _ecore_x_selection_data_files_free(void *data); +static void *_ecore_x_selection_parser_text(const char *target, unsigned char *data, int size); +static int _ecore_x_selection_data_text_free(void *data); +static void *_ecore_x_selection_parser_targets(const char *target, unsigned char *data, int size); +static int _ecore_x_selection_data_targets_free(void *data); + +#define ECORE_X_SELECTION_DATA(x) ((Ecore_X_Selection_Data *)(x)) void _ecore_x_selection_data_init(void) { /* Initialize global data */ memset(selections, 0, sizeof(selections)); - memset(request_data, 0, sizeof(request_data)); /* Initialize converters */ ecore_x_selection_converter_atom_add(ECORE_X_ATOM_TEXT, @@ -30,137 +38,54 @@ _ecore_x_selection_data_init(void) _ecore_x_selection_converter_text); ecore_x_selection_converter_atom_add(ECORE_X_ATOM_STRING, _ecore_x_selection_converter_text); + + /* Initialize parsers */ + ecore_x_selection_parser_add("text/plain", + _ecore_x_selection_parser_text); + ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_UTF8_STRING, + _ecore_x_selection_parser_text); + ecore_x_selection_parser_add("text/uri-list", + _ecore_x_selection_parser_files); + ecore_x_selection_parser_add("_NETSCAPE_URL", + _ecore_x_selection_parser_files); + ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_TARGETS, + _ecore_x_selection_parser_targets); } void _ecore_x_selection_shutdown(void) { - Ecore_X_Selection_Converter *cnv = converters, *tmp; - - if (!converters) - return; + Ecore_X_Selection_Converter *cnv; + Ecore_X_Selection_Parser *prs; /* free the selection converters */ + cnv = converters; while (cnv) - { + { + Ecore_X_Selection_Converter *tmp; + tmp = cnv->next; free(cnv); cnv = tmp; } - converters = NULL; -} -static void -_ecore_x_selection_request_data_get(Ecore_X_Atom selection, void **buf, int *len) -{ - int i; - char *data; - if (selection == ECORE_X_ATOM_SELECTION_PRIMARY) - i = 0; - else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY) - i = 1; - else if (selection == ECORE_X_ATOM_SELECTION_XDND) - i = 2; - else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) - i = 3; - else - return; - - if (!request_data[i].data || !request_data[i].length) + /* free the selection parsers */ + prs = parsers; + while (prs) { - *len = 0; - *buf = NULL; - return; + Ecore_X_Selection_Parser *tmp; + + tmp = prs; + prs = prs->next; + free(tmp->target); + free(tmp); } - - data = malloc(request_data[i].length); - memcpy(data, request_data[i].data, request_data[i].length); - *len = request_data[i].length; - *buf = data; - return; + parsers = NULL; } -/** - * Fetch the data returned by a PRIMARY selection request. - * @param buf A pointer to hold the selection data - * @param len The size of the data - * - * Get the converted data from a previous PRIMARY selection - * request. The buffer must be freed when done with. - */ -void -ecore_x_selection_primary_request_data_get(void **buf, int *len) -{ - _ecore_x_selection_request_data_get(ECORE_X_ATOM_SELECTION_PRIMARY, - buf, len); -} - -/** - * Fetch the data returned by a SECONDARY selection request. - * @param buf A pointer to hold the selection data - * @param len The size of the data - * - * Get the converted data from a previous SECONDARY selection - * request. The buffer must be freed when done with. - */ -void -ecore_x_selection_secondary_request_data_get(void **buf, int *len) -{ - _ecore_x_selection_request_data_get(ECORE_X_ATOM_SELECTION_SECONDARY, - buf, len); -} - -/** - * Fetch the data returned by a XDND selection request. - * @param buf A pointer to hold the selection data - * @param len The size of the data - * - * Get the converted data from a previous XDND selection - * request. The buffer must be freed when done with. - */ -void -ecore_x_selection_xdnd_request_data_get(void **buf, int *len) -{ - _ecore_x_selection_request_data_get(ECORE_X_ATOM_SELECTION_XDND, - buf, len); -} - -/** - * Fetch the data returned by a CLIPBOARD selection request. - * @param buf A pointer to hold the selection data - * @param len The size of the data - * - * Get the converted data from a previous CLIPBOARD selection - * request. The buffer must be freed when done with. - */ -void -ecore_x_selection_clipboard_request_data_get(void **buf, int *len) -{ - _ecore_x_selection_request_data_get(ECORE_X_ATOM_SELECTION_CLIPBOARD, - buf, len); -} - -void -_ecore_x_selection_request_data_set(Ecore_X_Selection_Data data) -{ - int i; - if (data.selection == ECORE_X_ATOM_SELECTION_PRIMARY) - i = 0; - else if (data.selection == ECORE_X_ATOM_SELECTION_SECONDARY) - i = 1; - else if (data.selection == ECORE_X_ATOM_SELECTION_XDND) - i = 2; - else if (data.selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) - i = 3; - else - return; - - request_data[i] = data; -} - -Ecore_X_Selection_Data * -_ecore_x_selection_get(Atom selection) +Ecore_X_Selection_Intern * +_ecore_x_selection_get(Ecore_X_Atom selection) { if (selection == ECORE_X_ATOM_SELECTION_PRIMARY) return &selections[0]; @@ -175,7 +100,7 @@ _ecore_x_selection_get(Atom selection) } int -_ecore_x_selection_set(Window w, unsigned char *data, int size, Atom selection) +_ecore_x_selection_set(Window w, unsigned char *data, int size, Ecore_X_Atom selection) { int in; unsigned char *buf = NULL; @@ -190,8 +115,10 @@ _ecore_x_selection_set(Window w, unsigned char *data, int size, Atom selection) in = 1; else if (selection == ECORE_X_ATOM_SELECTION_XDND) in = 2; - else + else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) in = 3; + else + return 0; if (data) { @@ -323,10 +250,10 @@ ecore_x_selection_clipboard_clear(void) return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_CLIPBOARD); } -Atom -_ecore_x_selection_target_atom_get(char *target) +Ecore_X_Atom +_ecore_x_selection_target_atom_get(const char *target) { - Atom x_target; + Ecore_X_Atom x_target; if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT)) x_target = ECORE_X_ATOM_TEXT; @@ -347,7 +274,7 @@ _ecore_x_selection_target_atom_get(char *target) } char * -_ecore_x_selection_target_get(Atom target) +_ecore_x_selection_target_get(Ecore_X_Atom target) { if (target == ECORE_X_ATOM_FILE_NAME) return strdup(ECORE_X_SELECTION_TARGET_FILENAME); @@ -372,11 +299,13 @@ _ecore_x_selection_request(Ecore_X_Window w, Ecore_X_Atom selection, char *targe prop = ECORE_X_ATOM_SELECTION_PROP_PRIMARY; else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY) prop = ECORE_X_ATOM_SELECTION_PROP_SECONDARY; - else + else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) prop = ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD; + else + return; XConvertSelection(_ecore_x_disp, selection, target, prop, - w, _ecore_x_event_last_time); + w, CurrentTime); } void @@ -444,7 +373,6 @@ ecore_x_selection_converter_atom_add(Ecore_X_Atom target, cnv->convert = func; } - void ecore_x_selection_converter_add(char *target, int (*func)(char *target, void *data, int size, void **data_ret, int *size_ret)) @@ -471,20 +399,11 @@ ecore_x_selection_converter_atom_del(Ecore_X_Atom target) { if (cnv->target == target) { - if ((target == ECORE_X_ATOM_TEXT) || - (target == ECORE_X_ATOM_COMPOUND_TEXT) || - (target == ECORE_X_ATOM_STRING)) - { - cnv->convert = _ecore_x_selection_converter_text; - } + if (prev_cnv) + prev_cnv->next = cnv->next; else - { - if (prev_cnv) - prev_cnv->next = cnv->next; - else - converters = NULL; /* This was the only converter */ - free(cnv); - } + converters = cnv->next; /* This was the first converter */ + free(cnv); return; } @@ -505,12 +424,11 @@ ecore_x_selection_converter_del(char *target) ecore_x_selection_converter_atom_del(x_target); } - /* Locate and run conversion callback for specified selection target */ int -_ecore_x_selection_convert(Atom selection, Atom target, void **data_ret) +_ecore_x_selection_convert(Ecore_X_Atom selection, Ecore_X_Atom target, void **data_ret) { - Ecore_X_Selection_Data *sel; + Ecore_X_Selection_Intern *sel; Ecore_X_Selection_Converter *cnv; void *data; int size; @@ -572,6 +490,18 @@ _ecore_x_selection_converter_text(char *target, void *data, int size, void **dat if (!(mystr = strdup(data))) return 0; +#ifdef X_HAVE_UTF8_STRING + if (Xutf8TextListToTextProperty(_ecore_x_disp, &mystr, 1, style, &text_prop) == Success) + { + int bufsize = strlen(text_prop.value) + 1; + *data_ret = malloc(bufsize); + memcpy(*data_ret, text_prop.value, bufsize); + *size_ret = bufsize; + XFree(text_prop.value); + free(mystr); + return 1; + } +#else if (XmbTextListToTextProperty(_ecore_x_disp, &mystr, 1, style, &text_prop) == Success) { int bufsize = strlen(text_prop.value) + 1; @@ -582,6 +512,7 @@ _ecore_x_selection_converter_text(char *target, void *data, int size, void **dat free(mystr); return 1; } +#endif else { free(mystr); @@ -589,4 +520,253 @@ _ecore_x_selection_converter_text(char *target, void *data, int size, void **dat } } +void +ecore_x_selection_parser_add(const char *target, + void *(*func)(const char *target, unsigned char *data, int size)) +{ + Ecore_X_Selection_Parser *prs; + if (!target) + return; + + prs = parsers; + if (parsers) + { + while (prs->next) + { + if (!strcmp(prs->target, target)) + { + prs->parse = func; + return; + } + prs = prs->next; + } + + prs->next = calloc(1, sizeof(Ecore_X_Selection_Parser)); + prs = prs->next; + } + else + { + parsers = calloc(1, sizeof(Ecore_X_Selection_Parser)); + prs = parsers; + } + prs->target = strdup(target); + prs->parse = func; +} + +void +ecore_x_selection_parser_del(const char *target) +{ + Ecore_X_Selection_Parser *prs, *prev_prs; + + if (!target) + return; + + prev_prs = NULL; + prs = parsers; + + while (prs) + { + if (!strcmp(prs->target, target)) + { + if (prev_prs) + prev_prs->next = prs->next; + else + parsers = prs->next; /* This was the first parser */ + free(prs->target); + free(prs); + + return; + } + prev_prs = prs; + prs = prs->next; + } +} + +/* Locate and run conversion callback for specified selection target */ +void * +_ecore_x_selection_parse(const char *target, unsigned char *data, int size) +{ + Ecore_X_Selection_Parser *prs; + Ecore_X_Selection_Data *sel; + + for (prs = parsers; prs; prs = prs->next) + { + if (!strcmp(prs->target, target)) + { + sel = prs->parse(target, data, size); + return sel; + } + } + + /* Default, just return the data */ + sel = calloc(1, sizeof(Ecore_X_Selection_Data)); + sel->free = _ecore_x_selection_data_default_free; + sel->length = size; + sel->data = data; + return sel; +} + +static int +_ecore_x_selection_data_default_free(void *data) +{ + Ecore_X_Selection_Data *sel; + + sel = data; + free(sel->data); + free(sel); + return 1; +} + +static void * +_ecore_x_selection_parser_files(const char *target, unsigned char *data, int size) +{ + Ecore_X_Selection_Data_Files *sel; + int i, is; + char *tmp; + + if (strcmp(target, "text/uri-list") + && strcmp(target, "_NETSCAPE_URL")) + return NULL; + + sel = calloc(1, sizeof(Ecore_X_Selection_Data_Files)); + ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_files_free; + + if (data[size - 1]) + { + /* Isn't nul terminated */ + printf("BUG: isn't nul terminated!\n"); + size++; + data = realloc(data, size); + data[size - 1] = 0; + } + + tmp = malloc(size); + i = 0; + is = 0; + while ((is < size) && (data[is])) + { + if ((i == 0) && (data[is] == '#')) + { + for (; ((data[is]) && (data[is] != '\n')); is++); + } + else + { + if ((data[is] != '\r') + && (data[is] != '\n')) + { + tmp[i++] = data[is++]; + } + else + { + while ((data[is] == '\r') + || (data[is] == '\n')) + is++; + tmp[i] = 0; + sel->num_files++; + sel->files = realloc(sel->files, sel->num_files * sizeof(char *)); + sel->files[sel->num_files - 1] = strdup(tmp); + tmp[0] = 0; + i = 0; + } + } + } + if (i > 0) + { + tmp[i] = 0; + sel->num_files++; + sel->files = realloc(sel->files, sel->num_files * sizeof(char *)); + sel->files[sel->num_files - 1] = strdup(tmp); + } + free(tmp); + free(data); + + return ECORE_X_SELECTION_DATA(sel); +} + +static int +_ecore_x_selection_data_files_free(void *data) +{ + Ecore_X_Selection_Data_Files *sel; + int i; + + sel = data; + if (sel->files) + { + for (i = 0; i < sel->num_files; i++) + free(sel->files[i]); + free(sel->files); + } + free(sel); + return 0; +} + +static void * +_ecore_x_selection_parser_text(const char *target, unsigned char *data, int size) +{ + Ecore_X_Selection_Data_Text *sel; + + sel = calloc(1, sizeof(Ecore_X_Selection_Data_Text)); + + if (data[size - 1]) + { + /* Isn't nul terminated */ + printf("BUG: isn't nul terminated!\n"); + size++; + data = realloc(data, size); + data[size - 1] = 0; + } + + sel->text = data; + ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_text_free; + return sel; +} + +static int +_ecore_x_selection_data_text_free(void *data) +{ + Ecore_X_Selection_Data_Text *sel; + + sel = data; + free(sel->text); + free(sel); + return 1; +} + +static void * +_ecore_x_selection_parser_targets(const char *target, unsigned char *data, int size) +{ + Ecore_X_Selection_Data_Targets *sel; + unsigned long *targets; + int i; + + sel = calloc(1, sizeof(Ecore_X_Selection_Data_Targets)); + targets = (unsigned long *)data; + + sel->num_targets = size - 2; + sel->targets = malloc((size - 2) * sizeof(char *)); + for (i = 2; i < size; i++) + sel->targets[i - 2] = XGetAtomName(_ecore_x_disp, targets[i]); + free(data); + + ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_targets_free; + return sel; +} + +static int +_ecore_x_selection_data_targets_free(void *data) +{ + Ecore_X_Selection_Data_Targets *sel; + int i; + + sel = data; + + if (sel->targets) + { + for (i = 0; i < sel->num_targets; i++) + XFree(sel->targets[i]); + free(sel->targets); + } + free(sel); + return 1; +}