tried to do better scrolling; don't like the result
[k8sterm.git] / src / x11evtsel.c
bloba5e6077a317c3f432168ff6b302d8b4cc99b94ad
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);
17 for (int f = 0; f < term_count; ++f) {
18 K8Term *t = term_array[f];
20 k8t_selClear(t);
25 static void xevtcbselnotify (XEvent *e) {
26 unsigned long nitems, ofs, rem;
27 int format;
28 uint8_t *data;
29 Atom type;
30 XSelectionEvent *se = (XSelectionEvent *)e;
31 int isutf8;
32 int wasbrk = 0;
33 char *ucbuf = NULL;
34 int ucbufsize = 0;
36 if (curterm == NULL || K8T_DATA(curterm)->cmdline.cmdMode == K8T_CMDMODE_MESSAGE) return;
37 #ifdef PASTE_SELECTION_DEBUG
39 char *name;
41 fprintf(stderr, "selnotify!\n");
43 name = se->selection != None ? XGetAtomName(se->display, se->selection) : NULL;
44 fprintf(stderr, " selection: [%s]\n", name);
45 if (name != NULL) XFree(name);
47 name = se->target != None ? XGetAtomName(se->display, se->target) : NULL;
48 fprintf(stderr, " target: [%s]\n", name);
49 if (name != NULL) XFree(name);
51 name = se->property != None ? XGetAtomName(se->display, se->property) : NULL;
52 fprintf(stderr, " property: [%s]\n", name);
53 if (name != NULL) XFree(name);
55 #endif
57 if (se->property != XA_VT_SELECTION) return;
59 #ifdef PASTE_SELECTION_DEBUG
61 fprintf(stderr, "selection:\n");
62 fprintf(stderr, " primary: %d\n", se->selection == XA_PRIMARY);
63 fprintf(stderr, " secondary: %d\n", se->selection == XA_SECONDARY);
64 fprintf(stderr, " clipboard: %d\n", se->selection == XA_CLIPBOARD);
65 fprintf(stderr, " vtsel: %d\n", se->selection == XA_VT_SELECTION);
66 fprintf(stderr, "target:\n");
67 fprintf(stderr, " primary: %d\n", se->target == XA_PRIMARY);
68 fprintf(stderr, " secondary: %d\n", se->target == XA_SECONDARY);
69 fprintf(stderr, " clipboard: %d\n", se->target == XA_CLIPBOARD);
70 fprintf(stderr, " vtsel: %d\n", se->target == XA_VT_SELECTION);
72 #endif
73 if (se->target == XA_UTF8) {
74 isutf8 = 1;
75 } else if (se->target == XA_STRING) {
76 isutf8 = 0;
77 } else if (se->target == XA_TARGETS) {
78 Atom rqtype = None, *targ;
80 if (XGetWindowProperty(xw.dpy, xw.win, se->property, 0, 65536, False, XA_ATOM, &type, &format, &nitems, &rem, &data)) {
81 //fprintf(stderr, "no targets\n");
82 rqtype = XA_STRING;
83 } else {
84 for (targ = (Atom *)data; nitems > 0; --nitems, ++targ) {
85 #ifdef PASTE_SELECTION_DEBUG
86 fprintf(stderr, " TGT: [%s]\n", XGetAtomName(se->display, *targ));
87 #endif
88 if (*targ == XA_UTF8) rqtype = XA_UTF8;
89 else if (*targ == XA_STRING && rqtype == None) rqtype = XA_STRING;
91 XFree(data);
93 if (rqtype != None) XConvertSelection(xw.dpy, se->selection, rqtype, XA_VT_SELECTION, xw.win, CurrentTime);
94 return;
95 } else {
96 return;
99 ofs = 0;
100 do {
101 int blen;
102 char *str;
104 if (XGetWindowProperty(xw.dpy, xw.win, se->property, ofs, BUFSIZ/4, False, AnyPropertyType, &type, &format, &nitems, &rem, &data)) {
105 fprintf(stderr, "Clipboard allocation failed\n");
106 break;
108 #ifdef PASTE_SELECTION_DEBUG
109 fprintf(stderr, "nitems=%d; format=%d; rem=%d\n", (int)nitems, format, (int)rem);
110 #endif
111 blen = nitems*format/8;
113 if (!isutf8) {
114 int newsz = blen*4+64;
116 if (ucbufsize < newsz) {
117 char *n = realloc(ucbuf, newsz);
119 if (n == NULL) { XFree(data); break; }
120 ucbuf = n;
121 ucbufsize = newsz;
124 blen = loc2utf(ucbuf, (const char *)data, blen);
125 str = ucbuf;
126 } else {
127 str = (char *)data;
130 if (K8T_DATA(curterm)->cmdline.cmdMode != K8T_CMDMODE_NONE) {
131 tcmdput(curterm, &K8T_DATA(curterm)->cmdline, str, blen);
132 } else {
133 if (nitems*format/8 > 0 && !wasbrk && K8T_ISSET(curterm, K8T_MODE_BRACPASTE)) {
134 wasbrk = 1;
135 k8t_ttyWriteStrNoEnc(curterm, "\x1b[200~");
137 k8t_ttyWrite(curterm, str, blen);
139 XFree(data);
140 /* number of 32-bit chunks returned */
141 ofs += nitems*format/32;
142 //termsDoIO(-1);
143 //if (curterm != NULL) doTermWrFlush(curterm);
144 } while (rem > 0);
146 if (wasbrk) k8t_ttyWriteStrNoEnc(curterm, "\x1b[201~");
147 if (ucbuf != NULL) free(ucbuf);
151 static void selpaste (K8Term *term, Atom which) {
152 if (term == NULL) return;
153 if (XGetSelectionOwner(xw.dpy, which) == None) return;
154 //XConvertSelection(xw.dpy, which, term->sel.xtarget, XA_VT_SELECTION, xw.win, CurrentTime);
155 XConvertSelection(xw.dpy, which, XA_TARGETS, XA_VT_SELECTION, xw.win, CurrentTime);
157 if (which == XA_PRIMARY) selpaste(XA_SECONDARY);
158 else if (which == XA_SECONDARY) selpaste(XA_CLIPBOARD);
163 static void xevtcbselrequest (XEvent *e) {
164 XSelectionRequestEvent *xsre;
165 XSelectionEvent xev;
167 if (lastSelStr == NULL) return;
168 xsre = (XSelectionRequestEvent *)e;
169 xev.type = SelectionNotify;
170 xev.requestor = xsre->requestor;
171 xev.selection = xsre->selection;
172 xev.target = xsre->target;
173 xev.time = xsre->time;
174 /* reject */
175 xev.property = None;
176 if (xsre->target == XA_TARGETS) {
177 /* respond with the supported type */
178 Atom tlist[3] = {XA_UTF8, XA_STRING, XA_TARGETS};
180 XChangeProperty(xsre->display, xsre->requestor, xsre->property, XA_ATOM, 32, PropModeReplace, (uint8_t *)tlist, 3);
181 xev.property = xsre->property;
182 } else if (xsre->target == XA_UTF8 && lastSelStr != NULL) {
183 XChangeProperty(xsre->display, xsre->requestor, xsre->property, XA_UTF8, 8, PropModeReplace, (uint8_t *)lastSelStr, strlen(lastSelStr));
184 xev.property = xsre->property;
185 } else if (xsre->target == XA_STRING && lastSelStr != NULL) {
186 char *s = malloc(strlen(lastSelStr)*4+8);
188 if (s != NULL) {
189 int len = utf2loc(s, lastSelStr, strlen(lastSelStr));
191 XChangeProperty(xsre->display, xsre->requestor, xsre->property, XA_STRING, 8, PropModeReplace, (uint8_t *)s, len);
192 xev.property = xsre->property;
193 free(s);
196 /* all done, send a notification to the listener */
197 if (!XSendEvent(xsre->display, xsre->requestor, True, 0, (XEvent *)&xev)) fprintf(stderr, "Error sending SelectionNotify event\n");