Introduction
Introduction Statistics Contact Development Disclaimer Help
st-drag-n-drop-0.9.2.diff - sites - public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log
Files
Refs
---
st-drag-n-drop-0.9.2.diff (9102B)
---
1 diff --git a/config.def.h b/config.def.h
2 index 2cd740a..3045d0a 100644
3 --- a/config.def.h
4 +++ b/config.def.h
5 @@ -93,6 +93,13 @@ char *termname = "st-256color";
6 */
7 unsigned int tabspaces = 8;
8
9 +/*
10 + * drag and drop escape characters
11 + *
12 + * this will add a '\' before any characters specified in the string.
13 + */
14 +char *xdndescchar = " !\"#$&'()*;<>?[\\]^`{|}~";
15 +
16 /* Terminal colors (16 first used in escape sequence) */
17 static const char *colorname[] = {
18 /* 8 normal colors */
19 diff --git a/st.h b/st.h
20 index fd3b0d8..62c7405 100644
21 --- a/st.h
22 +++ b/st.h
23 @@ -20,6 +20,10 @@
24 #define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b))
25 #define IS_TRUECOL(x) (1 << 24 & (x))
26
27 +#define HEX_TO_INT(c) ((c) >= '0' && (c) <= '9' ? (c) - …
28 + (c) >= 'a' && (c) <= 'f' ? (c) - 'a' + …
29 + (c) >= 'A' && (c) <= 'F' ? (c) - 'A' + …
30 +
31 enum glyph_attribute {
32 ATTR_NULL = 0,
33 ATTR_BOLD = 1 << 0,
34 diff --git a/x.c b/x.c
35 index d73152b..1c4b9aa 100644
36 --- a/x.c
37 +++ b/x.c
38 @@ -94,6 +94,12 @@ typedef struct {
39 Drawable buf;
40 GlyphFontSpec *specbuf; /* font spec buffer used for rendering …
41 Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid;
42 + Atom XdndTypeList, XdndSelection, XdndEnter, XdndPosition, Xdnd…
43 + XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XdndAct…
44 + XdndActionLink, XdndActionAsk, XdndActionPrivate, XtextUri…
45 + XtextPlain, XdndAware;
46 + int64_t XdndSourceWin, XdndSourceVersion;
47 + int32_t XdndSourceFormat;
48 struct {
49 XIM xim;
50 XIC xic;
51 @@ -169,6 +175,9 @@ static void visibility(XEvent *);
52 static void unmap(XEvent *);
53 static void kpress(XEvent *);
54 static void cmessage(XEvent *);
55 +static void xdndenter(XEvent *);
56 +static void xdndpos(XEvent *);
57 +static void xdnddrop(XEvent *);
58 static void resize(XEvent *);
59 static void focus(XEvent *);
60 static uint buttonmask(uint);
61 @@ -178,6 +187,8 @@ static void bpress(XEvent *);
62 static void bmotion(XEvent *);
63 static void propnotify(XEvent *);
64 static void selnotify(XEvent *);
65 +static void xdndsel(XEvent *);
66 +static void xdndpastedata(char *);
67 static void selclear_(XEvent *);
68 static void selrequest(XEvent *);
69 static void setsel(char *, Time);
70 @@ -220,6 +231,7 @@ static DC dc;
71 static XWindow xw;
72 static XSelection xsel;
73 static TermWindow win;
74 +const char XdndVersion = 5;
75
76 /* Font Ring Cache */
77 enum {
78 @@ -536,6 +548,11 @@ selnotify(XEvent *e)
79 if (property == None)
80 return;
81
82 + if (property == xw.XdndSelection) {
83 + xdndsel(e);
84 + return;
85 + }
86 +
87 do {
88 if (XGetWindowProperty(xw.dpy, xw.win, property, ofs,
89 BUFSIZ/4, False, AnyPropertyTyp…
90 @@ -604,6 +621,95 @@ selnotify(XEvent *e)
91 XDeleteProperty(xw.dpy, xw.win, (int)property);
92 }
93
94 +void
95 +xdndsel(XEvent *e)
96 +{
97 + char* data;
98 + unsigned long result;
99 +
100 + Atom actualType;
101 + int32_t actualFormat;
102 + unsigned long bytesAfter;
103 + XEvent reply = { ClientMessage };
104 +
105 + reply.xclient.window = xw.XdndSourceWin;
106 + reply.xclient.format = 32;
107 + reply.xclient.data.l[0] = (long) xw.win;
108 + reply.xclient.data.l[2] = 0;
109 + reply.xclient.data.l[3] = 0;
110 +
111 + XGetWindowProperty((Display*) xw.dpy, e->xselection.requestor,
112 + e->xselection.property, 0, LONG_MAX, False,
113 + e->xselection.target, &actualType, &actualForma…
114 + &bytesAfter, (unsigned char**) &data);
115 +
116 + if (result == 0)
117 + return;
118 +
119 + if (data) {
120 + xdndpastedata(data);
121 + XFree(data);
122 + }
123 +
124 + if (xw.XdndSourceVersion >= 2) {
125 + reply.xclient.message_type = xw.XdndFinished;
126 + reply.xclient.data.l[1] = result;
127 + reply.xclient.data.l[2] = xw.XdndActionCopy;
128 +
129 + XSendEvent((Display*) xw.dpy, xw.XdndSourceWin, False, …
130 + &reply);
131 + XFlush((Display*) xw.dpy);
132 + }
133 +}
134 +
135 +int
136 +xdndurldecode(char *src, char *dest)
137 +{
138 + char c;
139 + int i = 0;
140 +
141 + while (*src) {
142 + if (*src == '%' && HEX_TO_INT(src[1]) != -1 && HEX_TO_I…
143 + /* handle %xx escape sequences in url e.g. %20 …
144 + c = (char)((HEX_TO_INT(src[1]) << 4) | HEX_TO_I…
145 + src += 3;
146 + } else {
147 + c = *src++;
148 + }
149 + if (strchr(xdndescchar, c) != NULL) {
150 + *dest++ = '\\';
151 + i++;
152 + }
153 + *dest++ = c;
154 + i++;
155 + }
156 + *dest++ = ' ';
157 + *dest = '\0';
158 + return i + 1;
159 +}
160 +
161 +void
162 +xdndpastedata(char *data)
163 +{
164 + char *pastedata, *t;
165 + int i = 0;
166 +
167 + pastedata = (char *)malloc(strlen(data) * 2 + 1);
168 + *pastedata = '\0';
169 +
170 + t = strtok(data, "\n\r");
171 + while(t != NULL) {
172 + /* remove 'file://' prefix if it exists */
173 + if (strncmp(data, "file://", 7) == 0)
174 + t += 7;
175 + i += xdndurldecode(t, pastedata + i);
176 + t = strtok(NULL, "\n\r");
177 + }
178 +
179 + xsetsel(pastedata);
180 + selpaste(0);
181 +}
182 +
183 void
184 xclipcopy(void)
185 {
186 @@ -1227,6 +1333,26 @@ xinit(int cols, int rows)
187 XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32,
188 PropModeReplace, (uchar *)&thispid, 1);
189
190 + /* Xdnd setup */
191 + xw.XdndTypeList = XInternAtom(xw.dpy, "XdndTypeList", 0);
192 + xw.XdndSelection = XInternAtom(xw.dpy, "XdndSelection", 0);
193 + xw.XdndEnter = XInternAtom(xw.dpy, "XdndEnter", 0);
194 + xw.XdndPosition = XInternAtom(xw.dpy, "XdndPosition", 0);
195 + xw.XdndStatus = XInternAtom(xw.dpy, "XdndStatus", 0);
196 + xw.XdndLeave = XInternAtom(xw.dpy, "XdndLeave", 0);
197 + xw.XdndDrop = XInternAtom(xw.dpy, "XdndDrop", 0);
198 + xw.XdndFinished = XInternAtom(xw.dpy, "XdndFinished", 0);
199 + xw.XdndActionCopy = XInternAtom(xw.dpy, "XdndActionCopy", 0);
200 + xw.XdndActionMove = XInternAtom(xw.dpy, "XdndActionMove", 0);
201 + xw.XdndActionLink = XInternAtom(xw.dpy, "XdndActionLink", 0);
202 + xw.XdndActionAsk = XInternAtom(xw.dpy, "XdndActionAsk", 0);
203 + xw.XdndActionPrivate = XInternAtom(xw.dpy, "XdndActionPrivate",…
204 + xw.XtextUriList = XInternAtom((Display*) xw.dpy, "text/uri-list…
205 + xw.XtextPlain = XInternAtom((Display*) xw.dpy, "text/plain", 0);
206 + xw.XdndAware = XInternAtom(xw.dpy, "XdndAware", 0);
207 + XChangeProperty(xw.dpy, xw.win, xw.XdndAware, 4, 32, PropModeRe…
208 + &XdndVersion, 1);
209 +
210 win.mode = MODE_NUMLOCK;
211 resettitle();
212 xhints();
213 @@ -1908,6 +2034,132 @@ cmessage(XEvent *e)
214 } else if (e->xclient.data.l[0] == xw.wmdeletewin) {
215 ttyhangup();
216 exit(0);
217 + } else if (e->xclient.message_type == xw.XdndEnter) {
218 + xw.XdndSourceWin = e->xclient.data.l[0];
219 + xw.XdndSourceVersion = e->xclient.data.l[1] >> 24;
220 + xw.XdndSourceFormat = None;
221 + if (xw.XdndSourceVersion > 5)
222 + return;
223 + xdndenter(e);
224 + } else if (e->xclient.message_type == xw.XdndPosition
225 + && xw.XdndSourceVersion <= 5) {
226 + xdndpos(e);
227 + } else if (e->xclient.message_type == xw.XdndDrop
228 + && xw.XdndSourceVersion <= 5) {
229 + xdnddrop(e);
230 + }
231 +}
232 +
233 +void
234 +xdndenter(XEvent *e)
235 +{
236 + unsigned long count;
237 + Atom* formats;
238 + Atom real_formats[6];
239 + Bool list;
240 + Atom actualType;
241 + int32_t actualFormat;
242 + unsigned long bytesAfter;
243 + unsigned long i;
244 +
245 + list = e->xclient.data.l[1] & 1;
246 +
247 + if (list) {
248 + XGetWindowProperty((Display*) xw.dpy,
249 + xw.XdndSourceWin,
250 + xw.XdndTypeList,
251 + 0,
252 + LONG_MAX,
253 + False,
254 + 4,
255 + &actualType,
256 + &actualFormat,
257 + &count,
258 + &bytesAfter,
259 + (unsigned char**) &formats);
260 + } else {
261 + count = 0;
262 +
263 + if (e->xclient.data.l[2] != None)
264 + real_formats[count++] = e->xclient.data.l[2];
265 + if (e->xclient.data.l[3] != None)
266 + real_formats[count++] = e->xclient.data.l[3];
267 + if (e->xclient.data.l[4] != None)
268 + real_formats[count++] = e->xclient.data.l[4];
269 +
270 + formats = real_formats;
271 + }
272 +
273 + for (i = 0; i < count; i++) {
274 + if (formats[i] == xw.XtextUriList || formats[i] == xw.X…
275 + xw.XdndSourceFormat = formats[i];
276 + break;
277 + }
278 + }
279 +
280 + if (list)
281 + XFree(formats);
282 +}
283 +
284 +void
285 +xdndpos(XEvent *e)
286 +{
287 + const int32_t xabs = (e->xclient.data.l[2] >> 16) & 0xffff;
288 + const int32_t yabs = (e->xclient.data.l[2]) & 0xffff;
289 + Window dummy;
290 + int32_t xpos, ypos;
291 + XEvent reply = { ClientMessage };
292 +
293 + reply.xclient.window = xw.XdndSourceWin;
294 + reply.xclient.format = 32;
295 + reply.xclient.data.l[0] = (long) xw.win;
296 + reply.xclient.data.l[2] = 0;
297 + reply.xclient.data.l[3] = 0;
298 +
299 + XTranslateCoordinates((Display*) xw.dpy,
300 + XDefaultRootWindow((Display*) xw.dpy),
301 + (Window) xw.win,
302 + xabs, yabs,
303 + &xpos, &ypos,
304 + &dummy);
305 +
306 + reply.xclient.message_type = xw.XdndStatus;
307 +
308 + if (xw.XdndSourceFormat) {
309 + reply.xclient.data.l[1] = 1;
310 + if (xw.XdndSourceVersion >= 2)
311 + reply.xclient.data.l[4] = xw.XdndActionCopy;
312 + }
313 +
314 + XSendEvent((Display*) xw.dpy, xw.XdndSourceWin, False, NoEventM…
315 + &reply);
316 + XFlush((Display*) xw.dpy);
317 +}
318 +
319 +void
320 +xdnddrop(XEvent *e)
321 +{
322 + Time time = CurrentTime;
323 + XEvent reply = { ClientMessage };
324 +
325 + reply.xclient.window = xw.XdndSourceWin;
326 + reply.xclient.format = 32;
327 + reply.xclient.data.l[0] = (long) xw.win;
328 + reply.xclient.data.l[2] = 0;
329 + reply.xclient.data.l[3] = 0;
330 +
331 + if (xw.XdndSourceFormat) {
332 + if (xw.XdndSourceVersion >= 1)
333 + time = e->xclient.data.l[2];
334 +
335 + XConvertSelection((Display*) xw.dpy, xw.XdndSelection,
336 + xw.XdndSourceFormat, xw.XdndSelection, …
337 + } else if (xw.XdndSourceVersion >= 2) {
338 + reply.xclient.message_type = xw.XdndFinished;
339 +
340 + XSendEvent((Display*) xw.dpy, xw.XdndSourceWin,
341 + False, NoEventMask, &reply);
342 + XFlush((Display*) xw.dpy);
343 }
344 }
345
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.