experimental hackfix for non-existing problem ;-)
[k8sterm.git] / src / x11evtsel.c
blob86957b2481593f8376cf20e7ea395e81043c5134
1 ////////////////////////////////////////////////////////////////////////////////
2 // selection
3 static void xfixsel (void) {
4 if (lastSelStr != NULL) {
5 XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, CurrentTime);
6 XSetSelectionOwner(xw.dpy, XA_CLIPBOARD, xw.win, CurrentTime);
7 } else {
8 if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) == xw.win) XSetSelectionOwner(xw.dpy, XA_PRIMARY, None, CurrentTime);
9 if (XGetSelectionOwner(xw.dpy, XA_CLIPBOARD) == xw.win) XSetSelectionOwner(xw.dpy, XA_CLIPBOARD, None, CurrentTime);
11 XFlush(xw.dpy);
15 static void xevtcbselclear (XEvent *e) {
16 k8t_selClear(curterm);
20 static void xevtcbselnotify (XEvent *e) {
21 unsigned long nitems, ofs, rem;
22 int format;
23 uint8_t *data;
24 Atom type;
25 XSelectionEvent *se = (XSelectionEvent *)e;
26 int isutf8;
27 int wasbrk = 0;
28 char *ucbuf = NULL;
29 int ucbufsize = 0;
31 if (curterm == NULL || K8T_DATA(curterm)->cmdline.cmdMode == K8T_CMDMODE_MESSAGE) return;
32 #ifdef PASTE_SELECTION_DEBUG
34 char *name;
36 fprintf(stderr, "selnotify!\n");
38 name = se->selection != None ? XGetAtomName(se->display, se->selection) : NULL;
39 fprintf(stderr, " selection: [%s]\n", name);
40 if (name != NULL) XFree(name);
42 name = se->target != None ? XGetAtomName(se->display, se->target) : NULL;
43 fprintf(stderr, " target: [%s]\n", name);
44 if (name != NULL) XFree(name);
46 name = se->property != None ? XGetAtomName(se->display, se->property) : NULL;
47 fprintf(stderr, " property: [%s]\n", name);
48 if (name != NULL) XFree(name);
50 #endif
52 if (se->property != XA_VT_SELECTION) return;
54 #ifdef PASTE_SELECTION_DEBUG
56 fprintf(stderr, "selection:\n");
57 fprintf(stderr, " primary: %d\n", se->selection == XA_PRIMARY);
58 fprintf(stderr, " secondary: %d\n", se->selection == XA_SECONDARY);
59 fprintf(stderr, " clipboard: %d\n", se->selection == XA_CLIPBOARD);
60 fprintf(stderr, " vtsel: %d\n", se->selection == XA_VT_SELECTION);
61 fprintf(stderr, "target:\n");
62 fprintf(stderr, " primary: %d\n", se->target == XA_PRIMARY);
63 fprintf(stderr, " secondary: %d\n", se->target == XA_SECONDARY);
64 fprintf(stderr, " clipboard: %d\n", se->target == XA_CLIPBOARD);
65 fprintf(stderr, " vtsel: %d\n", se->target == XA_VT_SELECTION);
67 #endif
68 if (se->target == XA_UTF8) {
69 isutf8 = 1;
70 } else if (se->target == XA_STRING) {
71 isutf8 = 0;
72 } else if (se->target == XA_TARGETS) {
73 Atom rqtype = None, *targ;
75 if (XGetWindowProperty(xw.dpy, xw.win, se->property, 0, 65536, False, XA_ATOM, &type, &format, &nitems, &rem, &data)) {
76 //fprintf(stderr, "no targets\n");
77 rqtype = XA_STRING;
78 } else {
79 for (targ = (Atom *)data; nitems > 0; --nitems, ++targ) {
80 #ifdef PASTE_SELECTION_DEBUG
81 fprintf(stderr, " TGT: [%s]\n", XGetAtomName(se->display, *targ));
82 #endif
83 if (*targ == XA_UTF8) rqtype = XA_UTF8;
84 else if (*targ == XA_STRING && rqtype == None) rqtype = XA_STRING;
86 XFree(data);
88 if (rqtype != None) XConvertSelection(xw.dpy, se->selection, rqtype, XA_VT_SELECTION, xw.win, CurrentTime);
89 return;
90 } else {
91 return;
94 ofs = 0;
95 do {
96 int blen;
97 char *str;
99 if (XGetWindowProperty(xw.dpy, xw.win, se->property, ofs, BUFSIZ/4, False, AnyPropertyType, &type, &format, &nitems, &rem, &data)) {
100 fprintf(stderr, "Clipboard allocation failed\n");
101 break;
103 //fprintf(stderr, "nitems=%d; format=%d; rem=%d\n", (int)nitems, format, (int)rem);
104 blen = nitems*format/8;
106 if (!isutf8) {
107 int newsz = blen*4+64;
109 if (ucbufsize < newsz) {
110 char *n = realloc(ucbuf, newsz);
112 if (n == NULL) { XFree(data); break; }
113 ucbuf = n;
114 ucbufsize = newsz;
117 blen = loc2utf(ucbuf, (const char *)data, blen);
118 str = ucbuf;
119 } else {
120 str = (char *)data;
123 if (K8T_DATA(curterm)->cmdline.cmdMode != K8T_CMDMODE_NONE) {
124 tcmdput(curterm, &K8T_DATA(curterm)->cmdline, str, blen);
125 } else {
126 if (nitems*format/8 > 0 && !wasbrk && K8T_ISSET(curterm, K8T_MODE_BRACPASTE)) {
127 wasbrk = 1;
128 k8t_ttyWriteStrNoEnc(curterm, "\x1b[200~");
130 k8t_ttyWrite(curterm, str, blen);
132 XFree(data);
133 /* number of 32-bit chunks returned */
134 ofs += nitems*format/32;
135 } while (rem > 0);
137 if (wasbrk) k8t_ttyWriteStrNoEnc(curterm, "\x1b[201~");
138 if (ucbuf != NULL) free(ucbuf);
142 static void selpaste (K8Term *term, Atom which) {
143 if (term == NULL) return;
144 if (XGetSelectionOwner(xw.dpy, which) == None) return;
145 //XConvertSelection(xw.dpy, which, term->sel.xtarget, XA_VT_SELECTION, xw.win, CurrentTime);
146 XConvertSelection(xw.dpy, which, XA_TARGETS, XA_VT_SELECTION, xw.win, CurrentTime);
148 if (which == XA_PRIMARY) selpaste(XA_SECONDARY);
149 else if (which == XA_SECONDARY) selpaste(XA_CLIPBOARD);
154 static void xevtcbselrequest (XEvent *e) {
155 XSelectionRequestEvent *xsre;
156 XSelectionEvent xev;
158 if (lastSelStr == NULL) return;
159 xsre = (XSelectionRequestEvent *)e;
160 xev.type = SelectionNotify;
161 xev.requestor = xsre->requestor;
162 xev.selection = xsre->selection;
163 xev.target = xsre->target;
164 xev.time = xsre->time;
165 /* reject */
166 xev.property = None;
167 if (xsre->target == XA_TARGETS) {
168 /* respond with the supported type */
169 Atom tlist[3] = {XA_UTF8, XA_STRING, XA_TARGETS};
171 XChangeProperty(xsre->display, xsre->requestor, xsre->property, XA_ATOM, 32, PropModeReplace, (uint8_t *)tlist, 3);
172 xev.property = xsre->property;
173 } else if (xsre->target == XA_UTF8 && lastSelStr != NULL) {
174 XChangeProperty(xsre->display, xsre->requestor, xsre->property, XA_UTF8, 8, PropModeReplace, (uint8_t *)lastSelStr, strlen(lastSelStr));
175 xev.property = xsre->property;
176 } else if (xsre->target == XA_STRING && lastSelStr != NULL) {
177 char *s = malloc(strlen(lastSelStr)*4+8);
179 if (s != NULL) {
180 int len = utf2loc(s, lastSelStr, strlen(lastSelStr));
182 XChangeProperty(xsre->display, xsre->requestor, xsre->property, XA_STRING, 8, PropModeReplace, (uint8_t *)s, len);
183 xev.property = xsre->property;
184 free(s);
187 /* all done, send a notification to the listener */
188 if (!XSendEvent(xsre->display, xsre->requestor, True, 0, (XEvent *)&xev)) fprintf(stderr, "Error sending SelectionNotify event\n");