1 ////////////////////////////////////////////////////////////////////////////////
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
);
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
);
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
];
25 static void xevtcbselnotify (XEvent
*e
) {
26 unsigned long nitems
, ofs
, rem
;
30 XSelectionEvent
*se
= (XSelectionEvent
*)e
;
36 if (curterm
== NULL
|| K8T_DATA(curterm
)->cmdline
.cmdMode
== K8T_CMDMODE_MESSAGE
) return;
37 #ifdef PASTE_SELECTION_DEBUG
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
);
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
);
73 if (se
->target
== XA_UTF8
) {
75 } else if (se
->target
== XA_STRING
) {
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");
84 for (targ
= (Atom
*)data
; nitems
> 0; --nitems
, ++targ
) {
85 #ifdef PASTE_SELECTION_DEBUG
86 fprintf(stderr
, " TGT: [%s]\n", XGetAtomName(se
->display
, *targ
));
88 if (*targ
== XA_UTF8
) rqtype
= XA_UTF8
;
89 else if (*targ
== XA_STRING
&& rqtype
== None
) rqtype
= XA_STRING
;
93 if (rqtype
!= None
) XConvertSelection(xw
.dpy
, se
->selection
, rqtype
, XA_VT_SELECTION
, xw
.win
, CurrentTime
);
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");
108 #ifdef PASTE_SELECTION_DEBUG
109 fprintf(stderr
, "nitems=%d; format=%d; rem=%d\n", (int)nitems
, format
, (int)rem
);
111 blen
= nitems
*format
/8;
114 int newsz
= blen
*4+64;
116 if (ucbufsize
< newsz
) {
117 char *n
= realloc(ucbuf
, newsz
);
119 if (n
== NULL
) { XFree(data
); break; }
124 blen
= loc2utf(ucbuf
, (const char *)data
, blen
);
130 if (K8T_DATA(curterm
)->cmdline
.cmdMode
!= K8T_CMDMODE_NONE
) {
131 tcmdput(curterm
, &K8T_DATA(curterm
)->cmdline
, str
, blen
);
133 if (nitems
*format
/8 > 0 && !wasbrk
&& K8T_ISSET(curterm
, K8T_MODE_BRACPASTE
)) {
135 k8t_ttyWriteStrNoEnc(curterm
, "\x1b[200~");
137 k8t_ttyWrite(curterm
, str
, blen
);
140 /* number of 32-bit chunks returned */
141 ofs
+= nitems
*format
/32;
143 //if (curterm != NULL) doTermWrFlush(curterm);
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
;
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
;
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);
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
;
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");