]> git.decadent.org.uk Git - ion3.git/blob - ioncore/selection.c
[svn-upgrade] Integrating new upstream version, ion3 (20070506)
[ion3.git] / ioncore / selection.c
1 /*
2  * ion/ioncore/selection.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2007. 
5  *
6  * See the included file LICENSE for details.
7  */
8
9 #include <X11/Xmd.h>
10 #include <string.h>
11
12 #include "common.h"
13 #include "global.h"
14 #include "property.h"
15 #include "xwindow.h"
16 #include <libextl/extl.h>
17
18
19 static char *selection_data=NULL;
20 static int selection_length;
21 static bool continuation_set=FALSE;
22 static ExtlFn continuation;
23
24 void ioncore_handle_selection_request(XSelectionRequestEvent *ev)
25 {
26     XSelectionEvent sev;
27     const char *p[1];
28     
29     if(selection_data==NULL)
30         return;
31     
32     p[0]=selection_data;
33     
34     xwindow_set_text_property(ev->requestor, ev->property, p, 1);
35     
36     sev.type=SelectionNotify;
37     sev.requestor=ev->requestor;
38     sev.selection=ev->selection;
39     sev.target=ev->target;
40     sev.time=ev->time;
41     sev.property=ev->property;
42     XSendEvent(ioncore_g.dpy, ev->requestor, False, 0L, (XEvent*)&sev);
43 }
44
45
46 static void ins(Window win, const char *str, int n)
47 {
48     if(!continuation_set){
49         WWindow *wwin=XWINDOW_REGION_OF_T(win, WWindow);
50         if(wwin)
51             window_insstr(wwin, str, n);
52     }else{
53         char *tmp=scopyn(str, n);
54         if(tmp!=NULL){
55             extl_call(continuation, "s", NULL, tmp);
56             free(tmp);
57         }
58     }
59 }
60
61     
62 static void insert_selection(Window win, Atom prop)
63 {
64     char **p=xwindow_get_text_property(win, prop, NULL);
65     if(p!=NULL){
66         ins(win, p[0], strlen(p[0]));
67         XFreeStringList(p);
68     }
69 }
70
71
72 static void insert_cutbuffer(Window win)
73 {
74     char *p;
75     int n;
76     
77     p=XFetchBytes(ioncore_g.dpy, &n);
78     
79     if(n<=0 || p==NULL)
80         return;
81     
82     ins(win, p, n);
83 }
84
85
86 void ioncore_handle_selection(XSelectionEvent *ev)
87 {
88     Atom prop=ev->property;
89     Window win=ev->requestor;
90     WWindow *wwin;
91     
92     if(prop==None){
93         insert_cutbuffer(win);
94     }else{
95         insert_selection(win, prop);
96         XDeleteProperty(ioncore_g.dpy, win, prop);
97     }
98     
99     if(continuation_set){
100         extl_unref_fn(continuation);
101         continuation_set=FALSE;
102     }
103 }
104
105
106 void ioncore_clear_selection()
107 {
108     if(selection_data!=NULL){
109         free(selection_data);
110         selection_data=NULL;
111     }
112 }
113
114
115 void ioncore_set_selection_n(const char *p, int n)
116 {
117     if(selection_data!=NULL)
118         free(selection_data);
119     
120     selection_data=ALLOC_N(char, n+1);
121     
122     if(selection_data==NULL)
123         return;
124     
125     memcpy(selection_data, p, n);
126     selection_data[n]='\0';
127     selection_length=n;
128     
129     XStoreBytes(ioncore_g.dpy, p, n);
130     
131     XSetSelectionOwner(ioncore_g.dpy, XA_PRIMARY,
132                        DefaultRootWindow(ioncore_g.dpy),
133                        CurrentTime);
134 }
135
136
137 /*EXTL_DOC
138  * Set primary selection and cutbuffer0 to \var{p}.
139  */
140 EXTL_EXPORT
141 void ioncore_set_selection(const char *p)
142 {
143     if(p==NULL)
144         ioncore_clear_selection();
145     else
146         ioncore_set_selection_n(p, strlen(p));
147 }
148
149
150 void ioncore_request_selection_for(Window win)
151 {
152     Atom a=XA_STRING;
153     
154     if(continuation_set){
155         extl_unref_fn(continuation);
156         continuation_set=FALSE;
157     }
158     
159     if(ioncore_g.use_mb){
160 #ifdef X_HAVE_UTF8_STRING
161         a=XInternAtom(ioncore_g.dpy, "UTF8_STRING", True);
162 #else
163         a=XInternAtom(ioncore_g.dpy, "COMPOUND_TEXT", True);
164 #endif
165     }
166     
167     XConvertSelection(ioncore_g.dpy, XA_PRIMARY, a,
168                       ioncore_g.atom_selection, win, CurrentTime);
169 }
170
171
172 /*EXTL_DOC
173  * Request (string) selection. The function \var{fn} will be called 
174  * with the selection when and if it is received.
175  */
176 EXTL_EXPORT
177 void ioncore_request_selection(ExtlFn fn)
178 {
179     assert(ioncore_g.rootwins!=NULL);
180     ioncore_request_selection_for(ioncore_g.rootwins->dummy_win);
181     continuation=extl_ref_fn(fn);
182     continuation_set=TRUE;
183 }
184