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