st

Kris's build of st
git clone git clone https://git.krisyotam.com/krisyotam/st.git
Log | Files | Refs | README | LICENSE

drag-n-drop.c (4285B)


      1 const char XdndVersion = 5;
      2 
      3 void
      4 xdndsel(XEvent *e)
      5 {
      6 	char* data;
      7 	unsigned long result;
      8 
      9 	Atom actualType;
     10 	int32_t actualFormat;
     11 	unsigned long bytesAfter;
     12 	XEvent reply = { ClientMessage };
     13 
     14 	reply.xclient.window = xw.XdndSourceWin;
     15 	reply.xclient.format = 32;
     16 	reply.xclient.data.l[0] = (long) xw.win;
     17 	reply.xclient.data.l[2] = 0;
     18 	reply.xclient.data.l[3] = 0;
     19 
     20 	XGetWindowProperty((Display*) xw.dpy, e->xselection.requestor,
     21 			e->xselection.property, 0, LONG_MAX, False,
     22 			e->xselection.target, &actualType, &actualFormat, &result,
     23 			&bytesAfter, (unsigned char**) &data);
     24 
     25 	if (result == 0)
     26 		return;
     27 
     28 	if (data) {
     29 		xdndpastedata(data);
     30 		XFree(data);
     31 	}
     32 
     33 	if (xw.XdndSourceVersion >= 2) {
     34 		reply.xclient.message_type = xw.XdndFinished;
     35 		reply.xclient.data.l[1] = result;
     36 		reply.xclient.data.l[2] = xw.XdndActionCopy;
     37 
     38 		XSendEvent((Display*) xw.dpy, xw.XdndSourceWin, False, NoEventMask,
     39 			 	&reply);
     40 		XFlush((Display*) xw.dpy);
     41 	}
     42 }
     43 
     44 int
     45 xdndurldecode(char *src, char *dest)
     46 {
     47 	char c;
     48 	int i = 0;
     49 
     50 	while (*src) {
     51 		if (*src == '%' && HEX_TO_INT(src[1]) != -1 && HEX_TO_INT(src[2]) != -1) {
     52 			/* handle %xx escape sequences in url e.g. %20 == ' ' */
     53 			c = (char)((HEX_TO_INT(src[1]) << 4) | HEX_TO_INT(src[2]));
     54 			src += 3;
     55 		} else {
     56 			c = *src++;
     57 		}
     58 		if (strchr(xdndescchar, c) != NULL) {
     59 			*dest++ = '\\';
     60 			i++;
     61 		}
     62 		*dest++ = c;
     63 		i++;
     64 	}
     65 	*dest++ = ' ';
     66 	*dest = '\0';
     67 	return i + 1;
     68 }
     69 
     70 void
     71 xdndpastedata(char *data)
     72 {
     73 	char *pastedata, *t;
     74 	int i = 0;
     75 
     76 	pastedata = (char *)malloc(strlen(data) * 2 + 1);
     77 	*pastedata = '\0';
     78 
     79 	t = strtok(data, "\n\r");
     80 	while(t != NULL) {
     81 		/* Remove 'file://' prefix if it exists */
     82 		if (strncmp(data, "file://", 7) == 0) {
     83 			t += 7;
     84 		}
     85 		i += xdndurldecode(t, pastedata + i);
     86 		t = strtok(NULL, "\n\r");
     87 	}
     88 
     89 	xsetsel(pastedata);
     90 	selpaste(0);
     91 }
     92 
     93 void
     94 xdndenter(XEvent *e)
     95 {
     96 	unsigned long count;
     97 	Atom* formats;
     98 	Atom real_formats[6];
     99 	Bool list;
    100 	Atom actualType;
    101 	int32_t actualFormat;
    102 	unsigned long bytesAfter;
    103 	unsigned long i;
    104 
    105 	list = e->xclient.data.l[1] & 1;
    106 
    107 	if (list) {
    108 		XGetWindowProperty((Display*) xw.dpy,
    109 			xw.XdndSourceWin,
    110 			xw.XdndTypeList,
    111 			0,
    112 			LONG_MAX,
    113 			False,
    114 			4,
    115 			&actualType,
    116 			&actualFormat,
    117 			&count,
    118 			&bytesAfter,
    119 			(unsigned char**) &formats);
    120 	} else {
    121 		count = 0;
    122 
    123 		if (e->xclient.data.l[2] != None)
    124 			real_formats[count++] = e->xclient.data.l[2];
    125 		if (e->xclient.data.l[3] != None)
    126 			real_formats[count++] = e->xclient.data.l[3];
    127 		if (e->xclient.data.l[4] != None)
    128 			real_formats[count++] = e->xclient.data.l[4];
    129 
    130 		formats = real_formats;
    131 	}
    132 
    133 	for (i = 0; i < count; i++) {
    134 		if (formats[i] == xw.XtextUriList || formats[i] == xw.XtextPlain) {
    135 			xw.XdndSourceFormat = formats[i];
    136 			break;
    137 		}
    138 	}
    139 
    140 	if (list)
    141 		XFree(formats);
    142 }
    143 
    144 void
    145 xdndpos(XEvent *e)
    146 {
    147 	const int32_t xabs = (e->xclient.data.l[2] >> 16) & 0xffff;
    148 	const int32_t yabs = (e->xclient.data.l[2]) & 0xffff;
    149 	Window dummy;
    150 	int32_t xpos, ypos;
    151 	XEvent reply = { ClientMessage };
    152 
    153 	reply.xclient.window = xw.XdndSourceWin;
    154 	reply.xclient.format = 32;
    155 	reply.xclient.data.l[0] = (long) xw.win;
    156 	reply.xclient.data.l[2] = 0;
    157 	reply.xclient.data.l[3] = 0;
    158 
    159 	XTranslateCoordinates((Display*) xw.dpy,
    160 		XDefaultRootWindow((Display*) xw.dpy),
    161 		(Window) xw.win,
    162 		xabs, yabs,
    163 		&xpos, &ypos,
    164 		&dummy);
    165 
    166 	reply.xclient.message_type = xw.XdndStatus;
    167 
    168 	if (xw.XdndSourceFormat) {
    169 		reply.xclient.data.l[1] = 1;
    170 		if (xw.XdndSourceVersion >= 2)
    171 			reply.xclient.data.l[4] = xw.XdndActionCopy;
    172 	}
    173 
    174 	XSendEvent((Display*) xw.dpy, xw.XdndSourceWin, False, NoEventMask,
    175 			&reply);
    176 	XFlush((Display*) xw.dpy);
    177 }
    178 
    179 void
    180 xdnddrop(XEvent *e)
    181 {
    182 	Time time = CurrentTime;
    183 	XEvent reply = { ClientMessage };
    184 
    185 	reply.xclient.window = xw.XdndSourceWin;
    186 	reply.xclient.format = 32;
    187 	reply.xclient.data.l[0] = (long) xw.win;
    188 	reply.xclient.data.l[2] = 0;
    189 	reply.xclient.data.l[3] = 0;
    190 
    191 	if (xw.XdndSourceFormat) {
    192 		if (xw.XdndSourceVersion >= 1)
    193 			time = e->xclient.data.l[2];
    194 
    195 		XConvertSelection((Display*) xw.dpy, xw.XdndSelection,
    196 				xw.XdndSourceFormat, xw.XdndSelection, (Window) xw.win, time);
    197 	} else if (xw.XdndSourceVersion >= 2) {
    198 		reply.xclient.message_type = xw.XdndFinished;
    199 
    200 		XSendEvent((Display*) xw.dpy, xw.XdndSourceWin,
    201 				False, NoEventMask, &reply);
    202 		XFlush((Display*) xw.dpy);
    203 	}
    204 }