Revert "Declaration on top"
[notion.git] / ioncore / selection.c
blob896a415bc64a3c112ec98da0fda3203e5cbf258d
1 /*
2 * ion/ioncore/selection.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <X11/Xmd.h>
10 #include <string.h>
12 #include "common.h"
13 #include "global.h"
14 #include "property.h"
15 #include "xwindow.h"
16 #include <libextl/extl.h>
19 static char *selection_data=NULL;
20 static int selection_length;
21 static bool continuation_set=FALSE;
22 static ExtlFn continuation;
24 #define CLIPATOM(X) XA_PRIMARY
26 static Atom XA_COMPOUND_TEXT(Display *unused)
28 static Atom a=None;
30 if(a==None)
31 a=XInternAtom(ioncore_g.dpy, "COMPOUND_TEXT", False);
33 return a;
37 void ioncore_handle_selection_request(XSelectionRequestEvent *ev)
39 XSelectionEvent sev;
40 XTextProperty prop;
41 const char *p[1];
42 bool ok=FALSE;
44 sev.property=None;
46 if(selection_data==NULL || ev->property==None)
47 goto refuse;
49 p[0]=selection_data;
51 if(!ioncore_g.use_mb && ev->target==XA_STRING){
52 Status st=XStringListToTextProperty((char **)p, 1, &prop);
53 ok=(st!=0);
54 }else if(ioncore_g.use_mb){
55 XICCEncodingStyle style;
57 if(ev->target==XA_STRING){
58 style=XStringStyle;
59 ok=TRUE;
60 }else if(ev->target==XA_COMPOUND_TEXT(ioncore_g.dpy)){
61 style=XCompoundTextStyle;
62 ok=TRUE;
65 if(ok){
66 int st=XmbTextListToTextProperty(ioncore_g.dpy, (char **)p, 1,
67 style, &prop);
68 ok=(st>=0);
72 if(ok){
73 XSetTextProperty(ioncore_g.dpy, ev->requestor, &prop, ev->property);
74 sev.property=ev->property;
75 XFree(prop.value);
78 refuse:
79 sev.type=SelectionNotify;
80 sev.requestor=ev->requestor;
81 sev.selection=ev->selection;
82 sev.target=ev->target;
83 sev.time=ev->time;
84 XSendEvent(ioncore_g.dpy, ev->requestor, False, 0L, (XEvent*)&sev);
88 static void ins(Window win, const char *str, int n)
90 if(!continuation_set){
91 WWindow *wwin=XWINDOW_REGION_OF_T(win, WWindow);
92 if(wwin)
93 window_insstr(wwin, str, n);
94 }else{
95 char *tmp=scopyn(str, n);
96 if(tmp!=NULL){
97 extl_call(continuation, "s", NULL, tmp);
98 free(tmp);
104 static void insert_selection(Window win, Atom prop)
106 char **p=xwindow_get_text_property(win, prop, NULL);
107 if(p!=NULL){
108 ins(win, p[0], strlen(p[0]));
109 XFreeStringList(p);
114 void ioncore_handle_selection(XSelectionEvent *ev)
116 Atom prop=ev->property;
117 Window win=ev->requestor;
118 WWindow *wwin;
120 if(prop!=None){
121 insert_selection(win, prop);
122 XDeleteProperty(ioncore_g.dpy, win, prop);
125 if(continuation_set){
126 extl_unref_fn(continuation);
127 continuation_set=FALSE;
132 void ioncore_clear_selection()
134 if(selection_data!=NULL){
135 free(selection_data);
136 selection_data=NULL;
141 void ioncore_set_selection_n(const char *p, int n)
143 if(selection_data!=NULL)
144 free(selection_data);
146 selection_data=ALLOC_N(char, n+1);
148 if(selection_data==NULL)
149 return;
151 memcpy(selection_data, p, n);
152 selection_data[n]='\0';
153 selection_length=n;
155 XSetSelectionOwner(ioncore_g.dpy, CLIPATOM(ioncore_g.dpy),
156 DefaultRootWindow(ioncore_g.dpy),
157 CurrentTime);
161 /*EXTL_DOC
162 * Set primary selection and cutbuffer0 to \var{p}.
164 EXTL_EXPORT
165 void ioncore_set_selection(const char *p)
167 if(p==NULL)
168 ioncore_clear_selection();
169 else
170 ioncore_set_selection_n(p, strlen(p));
174 void ioncore_request_selection_for(Window win)
176 Atom a=XA_STRING;
178 if(continuation_set){
179 extl_unref_fn(continuation);
180 continuation_set=FALSE;
183 if(ioncore_g.use_mb)
184 a=XA_COMPOUND_TEXT(ioncore_g.dpy);
186 XConvertSelection(ioncore_g.dpy, CLIPATOM(ioncore_g.dpy), a,
187 ioncore_g.atom_selection, win, CurrentTime);
191 /*EXTL_DOC
192 * Request (string) selection. The function \var{fn} will be called
193 * with the selection when and if it is received.
195 EXTL_EXPORT
196 void ioncore_request_selection(ExtlFn fn)
198 assert(ioncore_g.rootwins!=NULL);
199 ioncore_request_selection_for(ioncore_g.rootwins->dummy_win);
200 continuation=extl_ref_fn(fn);
201 continuation_set=TRUE;