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
5 * Created by: Marc Horowitz <marc@athena.mit.edu>
9 * Copyright (c) 1989 by the Massachusetts Institute of Technology.
10 * For copying and distribution information, see the file
16 #if (!defined(lint) && !defined(SABER))
17 static const char rcsid_xselect_c[] = "$Id$";
20 #include <zephyr/mit-copyright.h>
22 /* xselect.c - ICCCM compliant cut-and-paste */
23 /* also includes some other ICCCMisms, such as the WM_PROTOCOL handling */
25 #ifndef X_DISPLAY_MISSING
28 #include <X11/Xproto.h>
29 #include <X11/Xatom.h>
30 #include "new_string.h"
33 extern char *getSelectedText();
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;
40 static struct _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"}
51 #define NumZAtoms (sizeof(ZAtom)/sizeof(struct _ZAtom))
53 /* internal static functions */
55 static void xselNotify(dpy,selreq,property)
57 XSelectionRequestEvent *selreq;
62 ev.type=SelectionNotify;
63 ev.requestor=selreq->requestor;
64 ev.selection=selreq->selection;
65 ev.target=selreq->target;
69 XSendEvent(dpy,ev.requestor,False,0,(XEvent *) &ev);
72 /* pRequestAtoms and RequestAtoms should have the same size. */
73 static Atom *pRequestAtoms[] = {
74 &ZA_TARGETS,&ZA_MULTIPLE,&ZA_TIMESTAMP,NULL
76 static Atom RequestAtoms[] = {
77 None,None,None,XA_STRING
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))
85 static void xselSetProperties(dpy,w,property,target,selreq)
89 XSelectionRequestEvent *selreq;
91 if (target==ZA_TARGETS) {
93 ChangeProp(XA_ATOM,32,RequestAtoms,NumRequestAtoms);
95 } else if (target==ZA_MULTIPLE) {
99 unsigned long alistsize,i;
101 XGetWindowProperty(dpy,w,property,0L,0L,False,ZA_ATOM_PAIR,&atype,
102 &aformat,&i,&alistsize,(unsigned char **) &alist);
105 XGetWindowProperty(dpy,w,property,0L,alistsize/sizeof(Atom),False,
106 ZA_ATOM_PAIR,&atype,&aformat,&alistsize,&i,
107 (unsigned char **) &alist);
109 alistsize/=(sizeof(Atom)/4);
110 for (i=0;i<alistsize;i+=2)
111 xselSetProperties(dpy,w,alist[i+1],alist[i],selreq);
113 XFree((char *) alist);
114 } else if (target==ZA_TIMESTAMP) {
115 ChangeProp(XA_INTEGER,32,&ownership_start,1);
117 } else if (target==XA_STRING) {
120 if (selected = getSelectedText()) {
121 ChangeProp(XA_STRING,8,selected,string_Length(selected));
123 /* This should only happen if the pasting client is out of
124 spec (or if this program is buggy), but it could happen */
127 "SelectionRequest event received for unowned selection: requestor wid=0x%x", w);
129 ChangeProp(XA_STRING,8,"",0);
134 xselNotify(dpy,selreq,property);
137 /* global functions */
139 void xicccmInitAtoms(dpy)
144 for (i=0;i<NumZAtoms;i++)
145 *(ZAtom[i].patom)=XInternAtom(dpy,ZAtom[i].name,False);
146 for (i=0;i<NumRequestAtoms;i++)
147 if (pRequestAtoms[i])
148 RequestAtoms[i] = *(pRequestAtoms[i]);
151 int xselGetOwnership(dpy,w,time)
158 XSetSelectionOwner(dpy,XA_PRIMARY,w,time);
159 temp=(w == XGetSelectionOwner(dpy,XA_PRIMARY));
162 ownership_start = time;
167 /* Get the selection. Return !0 if success, 0 if fail */
168 int xselProcessSelection(dpy,w,event)
173 XSelectionRequestEvent *selreq = &(event->xselectionrequest);
176 if ((selreq->owner != w) || (selreq->selection != XA_PRIMARY))
177 fprintf(stderr,"SelectionRequest event has bogus field values\n");
180 if ((ownership_start == CurrentTime) ||
181 ((selreq->time != CurrentTime) &&
182 (selreq->time < ownership_start) ||
183 ((ownership_end != CurrentTime) &&
184 (ownership_end > ownership_start) &&
185 (selreq->time > ownership_end))))
186 xselNotify(dpy,selreq,None);
188 xselSetProperties(dpy,selreq->requestor,selreq->property,selreq->target,
194 void xselOwnershipLost(time)
197 ownership_end = time;
201 void xselGiveUpOwnership(dpy,w)
205 XSetSelectionOwner(dpy,XA_PRIMARY,None,ownership_start);
207 ownership_end=ownership_start; /* Is this right? what should I use? */
210 #endif /* X_DISPLAY_MISSING */