efl/legacy/ecore/src/lib/ecore_x/ecore_x_selection.c

601 lines
15 KiB
C
Raw Normal View History

2005-02-10 04:27:13 -08:00
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#include "Ecore.h"
#include "ecore_x_private.h"
#include "Ecore_X.h"
#include "Ecore_X_Atoms.h"
2005-03-23 02:53:34 -08:00
static Ecore_X_Selection_Data selections[4];
static Ecore_X_Selection_Data request_data[4];
2004-02-04 09:43:41 -08:00
static Ecore_X_Selection_Converter *converters = NULL;
static int _ecore_x_selection_converter_text(char *target, void *data, int size, void **data_ret, int *size_ret);
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,
2005-02-10 04:27:13 -08:00
_ecore_x_selection_converter_text);
#ifdef X_HAVE_UTF8_STRING
ecore_x_selection_converter_atom_add(ECORE_X_ATOM_UTF8_STRING,
2005-02-10 04:27:13 -08:00
_ecore_x_selection_converter_text);
#endif
ecore_x_selection_converter_atom_add(ECORE_X_ATOM_COMPOUND_TEXT,
2005-02-10 04:27:13 -08:00
_ecore_x_selection_converter_text);
ecore_x_selection_converter_atom_add(ECORE_X_ATOM_STRING,
2005-02-10 04:27:13 -08:00
_ecore_x_selection_converter_text);
2004-02-04 09:43:41 -08:00
}
void
_ecore_x_selection_shutdown(void)
{
2005-02-10 04:27:13 -08:00
Ecore_X_Selection_Converter *cnv = converters, *tmp;
2004-02-04 09:43:41 -08:00
2005-02-10 04:27:13 -08:00
if (!converters)
return;
2004-02-04 09:43:41 -08:00
2005-02-10 04:27:13 -08:00
/* free the selection converters */
2005-03-23 02:53:34 -08:00
while (cnv)
{
2005-02-10 04:27:13 -08:00
tmp = cnv->next;
free(cnv);
cnv = tmp;
2005-03-23 02:53:34 -08:00
}
2004-02-04 09:43:41 -08:00
2005-02-10 04:27:13 -08:00
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)
2005-03-23 02:53:34 -08:00
i = 0;
else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
2005-03-23 02:53:34 -08:00
i = 1;
else if (selection == ECORE_X_ATOM_SELECTION_XDND)
2005-03-23 02:53:34 -08:00
i = 2;
else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
2005-03-23 02:53:34 -08:00
i = 3;
else
2005-03-23 02:53:34 -08:00
return;
if (!request_data[i].data || !request_data[i].length)
2005-03-23 02:53:34 -08:00
{
*len = 0;
*buf = NULL;
return;
}
data = malloc(request_data[i].length);
memcpy(data, request_data[i].data, request_data[i].length);
*len = request_data[i].length;
*buf = data;
return;
}
2004-01-16 16:52:22 -08:00
/**
* 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);
}
2004-01-16 16:52:22 -08:00
/**
* 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);
}
2004-01-16 16:52:22 -08:00
/**
* 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)
2005-03-23 02:53:34 -08:00
i = 0;
else if (data.selection == ECORE_X_ATOM_SELECTION_SECONDARY)
2005-03-23 02:53:34 -08:00
i = 1;
else if (data.selection == ECORE_X_ATOM_SELECTION_XDND)
2005-03-23 02:53:34 -08:00
i = 2;
else if (data.selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
2005-03-23 02:53:34 -08:00
i = 3;
else
2005-03-23 02:53:34 -08:00
return;
request_data[i] = data;
}
Ecore_X_Selection_Data *
_ecore_x_selection_get(Atom selection)
{
if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
2005-03-23 02:53:34 -08:00
return &selections[0];
else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
2005-03-23 02:53:34 -08:00
return &selections[1];
else if (selection == ECORE_X_ATOM_SELECTION_XDND)
return &selections[2];
else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD)
2005-03-23 02:53:34 -08:00
return &selections[3];
else
2005-03-23 02:53:34 -08:00
return NULL;
}
int
_ecore_x_selection_set(Window w, unsigned char *data, int size, Atom selection)
{
int in;
unsigned char *buf = NULL;
XSetSelectionOwner(_ecore_x_disp, selection, w, _ecore_x_event_last_time);
if (XGetSelectionOwner(_ecore_x_disp, selection) != w)
2005-03-23 02:53:34 -08:00
return 0;
if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
2005-03-23 02:53:34 -08:00
in = 0;
else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
2005-03-23 02:53:34 -08:00
in = 1;
else if (selection == ECORE_X_ATOM_SELECTION_XDND)
in = 2;
else
2005-03-23 02:53:34 -08:00
in = 3;
if (data)
2005-03-23 02:53:34 -08:00
{
selections[in].win = w;
selections[in].selection = selection;
selections[in].length = size;
selections[in].time = _ecore_x_event_last_time;
buf = malloc(size);
memcpy(buf, data, size);
selections[in].data = buf;
}
else
2005-03-23 02:53:34 -08:00
{
if (selections[in].data)
{
free(selections[in].data);
memset(&selections[in], 0, sizeof(Ecore_X_Selection_Data));
}
}
return 1;
}
2004-01-16 16:52:22 -08:00
/**
* Claim ownership of the PRIMARY selection and set its data.
* @param w The window to which this selection belongs
* @param data The data associated with the selection
* @param size The size of the data buffer in bytes
* @return Returns 1 if the ownership of the selection was successfully
* claimed, or 0 if unsuccessful.
*/
int
ecore_x_selection_primary_set(Ecore_X_Window w, unsigned char *data, int size)
{
return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_PRIMARY);
}
2004-01-16 16:52:22 -08:00
/**
* Release ownership of the primary selection
* @return Returns 1 if the selection was successfully cleared,
* or 0 if unsuccessful.
*
*/
int
ecore_x_selection_primary_clear(void)
{
return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_PRIMARY);
}
2004-01-16 16:52:22 -08:00
/**
* Claim ownership of the SECONDARY selection and set its data.
* @param w The window to which this selection belongs
* @param data The data associated with the selection
* @param size The size of the data buffer in bytes
* @return Returns 1 if the ownership of the selection was successfully
* claimed, or 0 if unsuccessful.
*/
int
ecore_x_selection_secondary_set(Ecore_X_Window w, unsigned char *data, int size)
{
return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_SECONDARY);
}
2004-01-16 16:52:22 -08:00
/**
* Release ownership of the secondary selection
* @return Returns 1 if the selection was successfully cleared,
* or 0 if unsuccessful.
*
*/
int
ecore_x_selection_secondary_clear(void)
{
return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_SECONDARY);
}
2005-03-23 02:53:34 -08:00
/**
* Claim ownership of the XDND selection and set its data.
* @param w The window to which this selection belongs
* @param data The data associated with the selection
* @param size The size of the data buffer in bytes
* @return Returns 1 if the ownership of the selection was successfully
* claimed, or 0 if unsuccessful.
*/
int
ecore_x_selection_xdnd_set(Ecore_X_Window w, unsigned char *data, int size)
{
return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_XDND);
}
/**
* Release ownership of the XDND selection
* @return Returns 1 if the selection was successfully cleared,
* or 0 if unsuccessful.
*
*/
int
ecore_x_selection_xdnd_clear(void)
{
return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_XDND);
}
2004-01-16 16:52:22 -08:00
/**
* Claim ownership of the CLIPBOARD selection and set its data.
* @param w The window to which this selection belongs
* @param data The data associated with the selection
* @param size The size of the data buffer in bytes
* @return Returns 1 if the ownership of the selection was successfully
* claimed, or 0 if unsuccessful.
*
* Get the converted data from a previous CLIPBOARD selection
* request. The buffer must be freed when done with.
*/
int
ecore_x_selection_clipboard_set(Ecore_X_Window w, unsigned char *data, int size)
{
return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_CLIPBOARD);
}
2004-01-16 16:52:22 -08:00
/**
* Release ownership of the clipboard selection
* @return Returns 1 if the selection was successfully cleared,
* or 0 if unsuccessful.
*
*/
int
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)
{
Atom x_target;
2005-03-23 02:53:34 -08:00
if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
2005-03-23 02:53:34 -08:00
x_target = ECORE_X_ATOM_TEXT;
else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
2005-03-23 02:53:34 -08:00
x_target = ECORE_X_ATOM_COMPOUND_TEXT;
else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
2005-03-23 02:53:34 -08:00
x_target = ECORE_X_ATOM_STRING;
else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
2005-03-23 02:53:34 -08:00
x_target = ECORE_X_ATOM_UTF8_STRING;
else if (!strcmp(target, ECORE_X_SELECTION_TARGET_FILENAME))
2005-03-23 02:53:34 -08:00
x_target = ECORE_X_ATOM_FILE_NAME;
else
2005-03-23 02:53:34 -08:00
{
char *atom_name;
atom_name = malloc(strlen(target) + 4);
sprintf(atom_name, "_E_%s", target);
x_target = XInternAtom(_ecore_x_disp, atom_name, False);
free(atom_name);
}
return x_target;
}
char *
_ecore_x_selection_target_get(Atom target)
{
if (target == ECORE_X_ATOM_FILE_NAME)
2005-03-23 02:53:34 -08:00
return strdup(ECORE_X_SELECTION_TARGET_FILENAME);
else if (target == ECORE_X_ATOM_STRING)
2005-03-23 02:53:34 -08:00
return strdup(ECORE_X_SELECTION_TARGET_STRING);
else if (target == ECORE_X_ATOM_UTF8_STRING)
2005-03-23 02:53:34 -08:00
return strdup(ECORE_X_SELECTION_TARGET_UTF8_STRING);
else if (target == ECORE_X_ATOM_TEXT)
2005-03-23 02:53:34 -08:00
return strdup(ECORE_X_SELECTION_TARGET_TEXT);
else
return NULL;
}
static void
_ecore_x_selection_request(Ecore_X_Window w, Ecore_X_Atom selection, char *target_str)
{
Ecore_X_Atom target, prop;
target = _ecore_x_selection_target_atom_get(target_str);
2005-03-23 02:53:34 -08:00
if (selection == ECORE_X_ATOM_SELECTION_PRIMARY)
2005-03-23 02:53:34 -08:00
prop = ECORE_X_ATOM_SELECTION_PROP_PRIMARY;
else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY)
2005-03-23 02:53:34 -08:00
prop = ECORE_X_ATOM_SELECTION_PROP_SECONDARY;
else
2005-03-23 02:53:34 -08:00
prop = ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD;
XConvertSelection(_ecore_x_disp, selection, target, prop,
2005-03-23 02:53:34 -08:00
w, _ecore_x_event_last_time);
}
void
ecore_x_selection_primary_request(Ecore_X_Window w, char *target)
{
_ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_PRIMARY, target);
}
void
ecore_x_selection_secondary_request(Ecore_X_Window w, char *target)
{
_ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_SECONDARY, target);
}
2005-03-23 02:53:34 -08:00
void
ecore_x_selection_xdnd_request(Ecore_X_Window w, char *target)
{
Ecore_X_Atom atom;
atom = ecore_x_atom_get(target);
XConvertSelection(_ecore_x_disp, ECORE_X_ATOM_SELECTION_XDND, atom,
ECORE_X_ATOM_SELECTION_PROP_XDND, w,
_ecore_x_event_last_time);
}
void
ecore_x_selection_clipboard_request(Ecore_X_Window w, char *target)
{
_ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_CLIPBOARD, target);
}
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))
{
Ecore_X_Selection_Converter *cnv;
cnv = converters;
if (converters)
2005-02-10 04:27:13 -08:00
{
while (1)
{
if (cnv->target == target)
{
cnv->convert = func;
return;
}
if (cnv->next)
cnv = cnv->next;
else
break;
}
cnv->next = calloc(1, sizeof(Ecore_X_Selection_Converter));
cnv = cnv->next;
2005-03-23 02:53:34 -08:00
}
else
{
converters = calloc(1, sizeof(Ecore_X_Selection_Converter));
cnv = converters;
2005-02-10 04:27:13 -08:00
}
cnv->target = 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))
{
Ecore_X_Atom x_target;
2005-03-23 02:53:34 -08:00
if (!func || !target)
2005-03-23 02:53:34 -08:00
return;
x_target = _ecore_x_selection_target_atom_get(target);
2005-03-23 02:53:34 -08:00
ecore_x_selection_converter_atom_add(x_target, func);
}
void
ecore_x_selection_converter_atom_del(Ecore_X_Atom target)
{
Ecore_X_Selection_Converter *cnv, *prev_cnv;
2005-03-23 02:53:34 -08:00
prev_cnv = NULL;
cnv = converters;
2005-03-23 02:53:34 -08:00
while (cnv)
2005-02-10 04:27:13 -08:00
{
if (cnv->target == target)
{
2005-03-23 02:53:34 -08:00
if ((target == ECORE_X_ATOM_TEXT) ||
(target == ECORE_X_ATOM_COMPOUND_TEXT) ||
(target == ECORE_X_ATOM_STRING))
2005-02-10 04:27:13 -08:00
{
cnv->convert = _ecore_x_selection_converter_text;
}
else
{
if (prev_cnv)
2005-02-10 04:27:13 -08:00
prev_cnv->next = cnv->next;
else
converters = NULL; /* This was the only converter */
free(cnv);
}
return;
}
prev_cnv = cnv;
cnv = cnv->next;
}
}
void
ecore_x_selection_converter_del(char *target)
{
Ecore_X_Atom x_target;
2005-03-23 02:53:34 -08:00
if (!target)
2005-03-23 02:53:34 -08:00
return;
x_target = _ecore_x_selection_target_atom_get(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_Data *sel;
Ecore_X_Selection_Converter *cnv;
void *data;
int size;
char *tgt_str;
sel = _ecore_x_selection_get(selection);
tgt_str = _ecore_x_selection_target_get(target);
2005-03-23 02:53:34 -08:00
if (tgt_str)
2005-02-10 04:27:13 -08:00
{
for (cnv = converters; cnv; cnv = cnv->next)
2005-02-10 04:27:13 -08:00
{
if (cnv->target == target)
2005-02-10 04:27:13 -08:00
{
int r;
r = cnv->convert(tgt_str, sel->data, sel->length, &data, &size);
if (r)
{
*data_ret = data;
return r;
}
else
return 0;
2005-02-10 04:27:13 -08:00
}
}
free(tgt_str);
}
else
{
*data_ret = malloc(sel->length);
memcpy(*data_ret, sel->data, sel->length);
return 1;
}
return 0;
}
/* TODO: We need to work out a mechanism for automatic conversion to any requested
* locale using Ecore_Txt functions */
/* Converter for standard non-utf8 text targets */
2005-03-23 02:53:34 -08:00
static int
_ecore_x_selection_converter_text(char *target, void *data, int size, void **data_ret, int *size_ret)
{
XTextProperty text_prop;
char *mystr;
XICCEncodingStyle style;
2005-03-23 02:53:34 -08:00
if (!data || !size)
2005-03-23 02:53:34 -08:00
return 0;
if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT))
2005-03-23 02:53:34 -08:00
style = XTextStyle;
else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT))
2005-03-23 02:53:34 -08:00
style = XCompoundTextStyle;
else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING))
2005-03-23 02:53:34 -08:00
style = XStringStyle;
#ifdef X_HAVE_UTF8_STRING
else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING))
2005-03-23 02:53:34 -08:00
style = XUTF8StringStyle;
#endif
else
2005-03-23 02:53:34 -08:00
return 0;
2005-02-10 04:27:13 -08:00
if (!(mystr = strdup(data)))
2005-03-23 02:53:34 -08:00
return 0;
if (XmbTextListToTextProperty(_ecore_x_disp, &mystr, 1, style, &text_prop) == Success)
2005-02-10 04:27:13 -08:00
{
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
2005-02-10 04:27:13 -08:00
{
free(mystr);
return 0;
}
}