diff --git a/legacy/elementary/src/lib/elm_cnp_helper.c b/legacy/elementary/src/lib/elm_cnp_helper.c
index 220b79331c..a4ea8382d3 100644
--- a/legacy/elementary/src/lib/elm_cnp_helper.c
+++ b/legacy/elementary/src/lib/elm_cnp_helper.c
@@ -46,15 +46,22 @@ struct _elm_cnp_selection {
Ecore_X_Selection ecore_sel;
+ Evas_Object *requestwidget;
+ enum _elm_sel_format requestformat;
+
int (*set)(Ecore_X_Window, const void *data, int size);
int (*clear)(void);
+ void (*request)(Ecore_X_Window, const char *target);
};
-
+/* Optimisation: Turn this into a 256 byte table:
+ * then can lookup in one index, not N checks */
static const struct escapes {
const char *escape;
const char value;
} escapes[] = {
+ { "
", '\n' },
+ { "<\t>", '\t' },
{ "gt;", '>' },
{ "lt;", '<' },
{ "amp;",'&' },
@@ -63,41 +70,55 @@ static const struct escapes {
};
#define N_ESCAPES ((int)(sizeof(escapes)/sizeof(escapes[0])))
-typedef int (*converter_fn)(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
static Eina_Bool _elm_cnp_init(void);
static int selection_clear(void *udata __UNUSED__, int type, void *event);
+static int selection_notify(void *udata __UNUSED__, int type, void *event);
static char *remove_tags(const char *p, int *len);
+static char *mark_up(const char *start, int *lenp);
+
+
+typedef int (*converter_fn)(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
static int targets_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
static int text_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
static int html_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
static int edje_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
+typedef int (*response_handler)(struct _elm_cnp_selection *sel,
+ Ecore_X_Event_Selection_Notify *);
+static int response_handler_targets(struct _elm_cnp_selection *sel,
+ Ecore_X_Event_Selection_Notify *);
+static int response_handler_text(struct _elm_cnp_selection *sel,
+ Ecore_X_Event_Selection_Notify *);
+
static struct {
const char *name;
enum _elm_sel_format formats;
converter_fn converter;
+ response_handler response;
Ecore_X_Atom atom;
} atoms[CNP_N_ATOMS] = {
ARRAYINIT(CNP_ATOM_TARGETS) { "TARGETS",
- (enum _elm_sel_format)-1, targets_converter, 0 },
+ (enum _elm_sel_format)-1, targets_converter,
+ response_handler_targets, 0 },
ARRAYINIT(CNP_ATOM_XEDJE) { "application/x-edje-string",
- ELM_SEL_MARKUP, edje_converter, 0},
+ ELM_SEL_MARKUP, edje_converter, NULL, 0},
ARRAYINIT(CNP_ATOM_text_html_utf8) { "text/html;charset=utf-8",
- ELM_SEL_MARKUP, html_converter, 0 },
- ARRAYINIT(CNP_ATOM_text_html) { "text/html",
- ELM_SEL_MARKUP, html_converter, 0 },
- ARRAYINIT(CNP_ATOM_UTF8STRING) { "UTF8_STRING",
- ELM_SEL_MARKUP, text_converter, 0 },
- ARRAYINIT(CNP_ATOM_STRING) { "STRING",
- ELM_SEL_MARKUP, text_converter, 0 },
- ARRAYINIT(CNP_ATOM_TEXT) { "TEXT",
- ELM_SEL_MARKUP, text_converter, 0 },
+ ELM_SEL_MARKUP, html_converter, NULL, 0 },
+ ARRAYINIT(CNP_ATOM_text_html) { "text/html", ELM_SEL_MARKUP,
+ html_converter, NULL, 0 },
+ ARRAYINIT(CNP_ATOM_UTF8STRING) { "UTF8_STRING", ELM_SEL_MARKUP,
+ text_converter, response_handler_text, 0 },
+ ARRAYINIT(CNP_ATOM_STRING) { "STRING", ELM_SEL_MARKUP,
+ text_converter, response_handler_text, 0 },
+ ARRAYINIT(CNP_ATOM_TEXT) { "TEXT", ELM_SEL_MARKUP,
+ text_converter, response_handler_text, 0 },
ARRAYINIT(CNP_ATOM_text_plain_utf8) { "text/plain;charset=ut-8",
- ELM_SEL_MARKUP, text_converter, 0 },
- ARRAYINIT(CNP_ATOM_text_plain) { "text/plain",
- ELM_SEL_MARKUP, text_converter, 0 },
+ ELM_SEL_MARKUP, text_converter,
+ response_handler_text, 0 },
+ ARRAYINIT(CNP_ATOM_text_plain) { "text/plain", ELM_SEL_MARKUP,
+ text_converter, response_handler_text, 0 },
};
static struct _elm_cnp_selection selections[ELM_SEL_MAX] = {
@@ -105,19 +126,22 @@ static struct _elm_cnp_selection selections[ELM_SEL_MAX] = {
.debug = "Primary",
.ecore_sel = ECORE_X_SELECTION_PRIMARY,
.set = ecore_x_selection_primary_set,
- .clear = ecore_x_selection_primary_clear
+ .clear = ecore_x_selection_primary_clear,
+ .request = ecore_x_selection_primary_request,
},
ARRAYINIT(ELM_SEL_SECONDARY) {
.debug = "Secondary",
.ecore_sel = ECORE_X_SELECTION_SECONDARY,
.set = ecore_x_selection_secondary_set,
- .clear = ecore_x_selection_secondary_clear
+ .clear = ecore_x_selection_secondary_clear,
+ .request = ecore_x_selection_secondary_request,
},
ARRAYINIT(ELM_SEL_CLIPBOARD) {
.debug = "Clipboard",
.ecore_sel = ECORE_X_SELECTION_CLIPBOARD,
.set = ecore_x_selection_clipboard_set,
- .clear = ecore_x_selection_clipboard_clear
+ .clear = ecore_x_selection_clipboard_clear,
+ .request = ecore_x_selection_clipboard_request,
}
};
@@ -163,6 +187,26 @@ elm_selection_clear(enum _elm_sel_type selection, Evas_Object *widget){
return true;
}
+Eina_Bool
+elm_selection_get(enum _elm_sel_type selection, enum _elm_sel_format format,
+ Evas_Object *widget){
+ Evas_Object *top;
+ struct _elm_cnp_selection *sel;
+
+ if ((unsigned int)selection >= (unsigned int)ELM_SEL_MAX) return false;
+ if (!_elm_cnp_init_count) _elm_cnp_init();
+
+ sel = selections + selection;
+ top = elm_widget_top_get(widget);
+ if (!top) return false;
+
+ sel->request(elm_win_xwindow_get(top), "TARGETS");
+ sel->requestformat = format;
+ sel->requestwidget = widget;
+
+ return EINA_TRUE;
+}
+
static Eina_Bool
_elm_cnp_init(void){
int i;
@@ -176,7 +220,8 @@ _elm_cnp_init(void){
atoms[i].converter);
}
- ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, selection_clear, NULL);
+ ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, selection_clear,NULL);
+ ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY,selection_notify,NULL);
return true;
}
@@ -202,6 +247,46 @@ selection_clear(void *udata __UNUSED__, int type, void *event){
return true;
}
+/**
+ * Response to a selection notify
+ */
+static int
+selection_notify(void *udata __UNUSED__, int type, void *event){
+ Ecore_X_Event_Selection_Notify *ev = event;
+ struct _elm_cnp_selection *sel;
+ int i;
+
+ switch (ev->selection){
+ case ECORE_X_SELECTION_CLIPBOARD:
+ sel = selections + ELM_SEL_CLIPBOARD;
+ break;
+
+ case ECORE_X_SELECTION_PRIMARY:
+ sel = selections + ELM_SEL_PRIMARY;
+ break;
+ case ECORE_X_SELECTION_SECONDARY:
+ sel = selections + ELM_SEL_SECONDARY;
+ break;
+ default:
+ return 1;
+ }
+
+ for (i = 0 ; i < CNP_N_ATOMS ; i ++)
+ {
+ if (strcmp(ev->target, atoms[i].name) == 0)
+ {
+ if (atoms[i].response){
+ atoms[i].response(sel, ev);
+ } else {
+ printf("Ignored: No handler!\n");
+ }
+ }
+ }
+
+ return 1;
+}
+
+
static int
targets_converter(char *target, void *data, int size,
void **data_ret, int *size_ret,
@@ -232,6 +317,61 @@ targets_converter(char *target, void *data, int size,
}
+static int
+response_handler_targets(struct _elm_cnp_selection *sel,
+ Ecore_X_Event_Selection_Notify *notify){
+ Ecore_X_Selection_Data_Targets *targets;
+ Ecore_X_Atom *atomlist;
+ Evas_Object *top;
+ int i,j;
+ int prio, selected;
+
+ targets = notify->data;
+ atomlist = (Ecore_X_Atom *)(targets->data.data);
+
+ prio = -1;
+ selected = -1;
+ /* Start from 1: Skip targets */
+ for (j = 1 ; j < CNP_N_ATOMS ; j ++)
+ {
+ if (!(atoms[j].formats & sel->requestformat)) continue;
+ for (i = 0 ; i < targets->data.length ; i ++)
+ {
+ if (atoms[j].atom == atomlist[i] && atoms[j].response){
+ /* Found a match: Use it */
+ goto found;
+ }
+ }
+ }
+ found:
+ if (j == CNP_N_ATOMS)
+ {
+ printf("No matching type found\n");
+ return 0;
+ }
+
+ top = elm_widget_top_get(sel->requestwidget);
+ if (!top) return 0;
+
+ sel->request(elm_win_xwindow_get(top), atoms[j].name);
+ return 0;
+}
+
+static int
+response_handler_text(struct _elm_cnp_selection *sel,
+ Ecore_X_Event_Selection_Notify *notify){
+ Ecore_X_Selection_Data_Text *text;
+ char *str;
+
+ text = notify->data;
+ str = mark_up(text->text, NULL);
+ elm_entry_entry_insert(sel->requestwidget, str);
+ free(str);
+
+ return 0;
+}
+
+
static int
text_converter(char *target, void *data, int size,
void **data_ret, int *size_ret,
@@ -273,7 +413,6 @@ html_converter(char *target, void *data, int size, void **data_ret, int *size_re
-/* FIXME: Doesn't handle '' */
static char *
remove_tags(const char *p, int *len){
char *q,*ret;
@@ -312,4 +451,50 @@ remove_tags(const char *p, int *len){
return ret;
}
+/* Mark up */
+static char *
+mark_up(const char *start, int *lenp){
+ int l,i;
+ const char *p;
+ char *q,*ret;
+
+ /* First pass: Count characters */
+ for (l = 0, p = start ; *p ; p ++)
+ {
+ for (i = 0 ; i < N_ESCAPES ; i ++)
+ {
+ if (*p == escapes[i].value)
+ {
+ l += strlen(escapes[i].escape);
+ break;
+ }
+ }
+ if (i == N_ESCAPES)
+ l ++;
+ }
+
+ q = ret = malloc(l + 1);
+
+ /* Second pass: Count characters */
+ for (p = start ; *p ; )
+ {
+ for (i = 0 ; i < N_ESCAPES ; i ++)
+ {
+ if (*p == escapes[i].value)
+ {
+ strcpy(q, escapes[i].escape);
+ q += strlen(escapes[i].escape);
+ p ++;
+ break;
+ }
+ }
+ if (i == N_ESCAPES)
+ *q ++ = *p ++;
+ }
+ *q = 0;
+
+ if (lenp) *lenp = l;
+ return ret;
+}
+
/* vim: set ts=8 sw=3 sts=8 noexpandtab cino=>5n-3f0^-2{2 : */