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