1 | /* |
---|
2 | * This file is taken from the Project Athena Zephyr Notification System. |
---|
3 | * It is one of the source files comprising zwgc, the Zephyr WindowGram |
---|
4 | * client. |
---|
5 | * |
---|
6 | * Created by: Marc Horowitz <marc@athena.mit.edu> |
---|
7 | * |
---|
8 | * $Id: xselect.c,v 1.3 1999-02-22 18:16:35 danw Exp $ |
---|
9 | * |
---|
10 | * Copyright 1990, 1991 by the Massachusetts Institute of Technology. |
---|
11 | * |
---|
12 | * For copying and distribution information, please see the file |
---|
13 | * <mit-copyright.h>. |
---|
14 | * |
---|
15 | */ |
---|
16 | |
---|
17 | #if (!defined(lint)) && (!defined(SABER)) |
---|
18 | static char rcsid[] = |
---|
19 | "$Id: xselect.c,v 1.3 1999-02-22 18:16:35 danw Exp $"; |
---|
20 | #endif |
---|
21 | |
---|
22 | #include "mit-copyright.h" |
---|
23 | |
---|
24 | /* xselect.c - ICCCM compliant cut-and-paste */ |
---|
25 | |
---|
26 | #include <stdio.h> |
---|
27 | #include <string.h> |
---|
28 | #include <X11/Xlib.h> |
---|
29 | #include <X11/Xproto.h> |
---|
30 | #include <X11/Xatom.h> |
---|
31 | #include "xselect.h" |
---|
32 | |
---|
33 | static Time ownership_start = CurrentTime; |
---|
34 | static Time ownership_end = CurrentTime; |
---|
35 | static Atom ZA_TARGETS,ZA_MULTIPLE,ZA_TIMESTAMP,ZA_ATOM_PAIR; |
---|
36 | |
---|
37 | static struct _ZAtom { |
---|
38 | Atom *patom; |
---|
39 | char *name; |
---|
40 | } ZAtom[] = { |
---|
41 | {&ZA_TARGETS,"TARGETS"}, |
---|
42 | {&ZA_MULTIPLE,"MULTIPLE"}, |
---|
43 | {&ZA_TIMESTAMP,"TIMESTAMP"}, |
---|
44 | {&ZA_ATOM_PAIR,"ATOM_PAIR"} |
---|
45 | }; |
---|
46 | #define NumZAtoms (sizeof(ZAtom)/sizeof(struct _ZAtom)) |
---|
47 | |
---|
48 | /* internal static functions */ |
---|
49 | |
---|
50 | static void xselNotify(dpy,selreq,property) |
---|
51 | Display *dpy; |
---|
52 | XSelectionRequestEvent *selreq; |
---|
53 | Atom property; |
---|
54 | { |
---|
55 | XSelectionEvent ev; |
---|
56 | |
---|
57 | ev.type=SelectionNotify; |
---|
58 | ev.requestor=selreq->requestor; |
---|
59 | ev.selection=selreq->selection; |
---|
60 | ev.target=selreq->target; |
---|
61 | ev.property=property; |
---|
62 | ev.time=selreq->time; |
---|
63 | |
---|
64 | XSendEvent(dpy,ev.requestor,False,0,(XEvent *) &ev); |
---|
65 | } |
---|
66 | |
---|
67 | /* pRequestAtoms and RequestAtoms should have the same size. */ |
---|
68 | static Atom *pRequestAtoms[] = { |
---|
69 | &ZA_TARGETS,&ZA_MULTIPLE,&ZA_TIMESTAMP,NULL |
---|
70 | }; |
---|
71 | static Atom RequestAtoms[] = { |
---|
72 | None,None,None,XA_STRING |
---|
73 | }; |
---|
74 | #define NumRequestAtoms (sizeof(RequestAtoms)/sizeof(Atom)) |
---|
75 | #define PROP(prop,targ) ((prop)!=None?(prop):(targ)) |
---|
76 | #define ChangeProp(type,format,data,size) \ |
---|
77 | XChangeProperty(dpy,w,PROP(property,target),(type),(format), \ |
---|
78 | PropModeReplace, (unsigned char *) (data),(size)) |
---|
79 | |
---|
80 | static void xselSetProperties(dpy,w,property,target,selreq, selected) |
---|
81 | Display *dpy; |
---|
82 | Window w; |
---|
83 | Atom property,target; |
---|
84 | XSelectionRequestEvent *selreq; |
---|
85 | char *selected; |
---|
86 | { |
---|
87 | if (target==ZA_TARGETS) { |
---|
88 | |
---|
89 | ChangeProp(XA_ATOM,32,RequestAtoms,NumRequestAtoms); |
---|
90 | XSync(dpy,0); |
---|
91 | } else if (target==ZA_MULTIPLE) { |
---|
92 | Atom atype; |
---|
93 | int aformat; |
---|
94 | Atom *alist; |
---|
95 | unsigned long alistsize,i; |
---|
96 | |
---|
97 | XGetWindowProperty(dpy,w,property,0L,0L,False,ZA_ATOM_PAIR,&atype, |
---|
98 | &aformat,&i,&alistsize,(unsigned char **) &alist); |
---|
99 | |
---|
100 | if (alistsize) |
---|
101 | XGetWindowProperty(dpy,w,property,0L,alistsize/sizeof(Atom),False, |
---|
102 | ZA_ATOM_PAIR,&atype,&aformat,&alistsize,&i, |
---|
103 | (unsigned char **) &alist); |
---|
104 | |
---|
105 | alistsize/=(sizeof(Atom)/4); |
---|
106 | for (i=0;i<alistsize;i+=2) |
---|
107 | xselSetProperties(dpy,w,alist[i+1],alist[i],selreq,selected); |
---|
108 | |
---|
109 | XFree((char *) alist); |
---|
110 | } else if (target==ZA_TIMESTAMP) { |
---|
111 | ChangeProp(XA_INTEGER,32,&ownership_start,1); |
---|
112 | XSync(dpy,0); |
---|
113 | } else if (target==XA_STRING) { |
---|
114 | ChangeProp(XA_STRING,8,selected,strlen(selected)); |
---|
115 | XSync(dpy,0); |
---|
116 | } |
---|
117 | |
---|
118 | xselNotify(dpy,selreq,property); |
---|
119 | } |
---|
120 | |
---|
121 | /* global functions */ |
---|
122 | |
---|
123 | void xselInitAtoms(dpy) |
---|
124 | Display *dpy; |
---|
125 | { |
---|
126 | int i; |
---|
127 | |
---|
128 | for (i=0;i<NumZAtoms;i++) |
---|
129 | *(ZAtom[i].patom)=XInternAtom(dpy,ZAtom[i].name,False); |
---|
130 | for (i=0;i<NumRequestAtoms;i++) |
---|
131 | if (pRequestAtoms[i]) |
---|
132 | RequestAtoms[i] = *(pRequestAtoms[i]); |
---|
133 | } |
---|
134 | |
---|
135 | int xselGetOwnership(dpy,w,time) |
---|
136 | Display *dpy; |
---|
137 | Window w; |
---|
138 | Time time; |
---|
139 | { |
---|
140 | int temp; |
---|
141 | |
---|
142 | XSetSelectionOwner(dpy,XA_PRIMARY,w,time); |
---|
143 | temp=(w == XGetSelectionOwner(dpy,XA_PRIMARY)); |
---|
144 | |
---|
145 | if (temp) |
---|
146 | ownership_start = time; |
---|
147 | |
---|
148 | return(temp); |
---|
149 | } |
---|
150 | |
---|
151 | /* Get the selection. Return !0 if success, 0 if fail */ |
---|
152 | int xselProcessSelection(dpy,w,event,selected) |
---|
153 | Display *dpy; |
---|
154 | Window w; /* ARGSUSED */ |
---|
155 | XEvent *event; |
---|
156 | char *selected; |
---|
157 | { |
---|
158 | XSelectionRequestEvent *selreq = &(event->xselectionrequest); |
---|
159 | |
---|
160 | #ifdef DEBUG |
---|
161 | if ((selreq->owner != w) || (selreq->selection != XA_PRIMARY)) |
---|
162 | fprintf(stderr,"SelectionRequest event has bogus field values\n"); |
---|
163 | #endif |
---|
164 | |
---|
165 | if ((ownership_start == CurrentTime) || |
---|
166 | ((selreq->time != CurrentTime) && |
---|
167 | (selreq->time < ownership_start) || |
---|
168 | ((ownership_end != CurrentTime) && |
---|
169 | (ownership_end > ownership_start) && |
---|
170 | (selreq->time > ownership_end)))) |
---|
171 | xselNotify(dpy,selreq,None); |
---|
172 | else |
---|
173 | xselSetProperties(dpy,selreq->requestor,selreq->property,selreq->target, |
---|
174 | selreq,selected); |
---|
175 | |
---|
176 | return(1); |
---|
177 | } |
---|
178 | |
---|
179 | void xselOwnershipLost(time) |
---|
180 | Time time; |
---|
181 | { |
---|
182 | ownership_end = time; |
---|
183 | } |
---|
184 | |
---|
185 | void xselGiveUpOwnership(dpy,w) |
---|
186 | Display *dpy; |
---|
187 | Window w; /* ARGSUSED */ |
---|
188 | { |
---|
189 | XSetSelectionOwner(dpy,XA_PRIMARY,None,ownership_start); |
---|
190 | |
---|
191 | ownership_end=ownership_start; /* Is this right? what should I use? */ |
---|
192 | } |
---|