1 /* $XConsortium: recv.c /main/5 1995/07/15 20:38:46 drk $ */
2 /*
3  * Motif
4  *
5  * Copyright (c) 1987-2012, The Open Group. All rights reserved.
6  *
7  * These libraries and programs are free software; you can
8  * redistribute them and/or modify them under the terms of the GNU
9  * Lesser General Public License as published by the Free Software
10  * Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  *
13  * These libraries and programs are distributed in the hope that
14  * they will be useful, but WITHOUT ANY WARRANTY; without even the
15  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16  * PURPOSE. See the GNU Lesser General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with these librararies and programs; if not, write
21  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
22  * Floor, Boston, MA 02110-1301 USA
23  *
24  */
25 /*
26  * HISTORY
27  */
28 
29 #include "wsm_proto.h"
30 #include "utm_send.h"
31 #include <X11/Xatom.h>
32 #include <Xm/TransferP.h>	/* for XmeNamedSource() */
33 
34 #ifdef JUNK
35 static Boolean ConvertProc(
36 Widget, Atom *, Atom *, XtPointer, unsigned long, int, Atom *,
37 XtPointer *, unsigned long *, int *
38 );
39 #endif /* JUNK */
40 
41 extern Time GetTimestamp (Display *dpy);
42 
43 
44 /*	Function Name: WSMDefaultOwnSelection
45  *	Description: This is the default routine that owns the proper
46  * 		     selection and the processes incomming messages
47  *                   from the Wsm protocol.
48  *	Arguments: w - A widget on the screen we want to own the
49  *                     WSM or WM selection for.
50  *                     NOTE: THIS MUST HAVE A XmNconvertCallback RESOURCE!
51  *                 client_type - The type of client we are.
52  *                 request_callback - The callback call when a message
53  *                                    is received.
54  *                 request_data - Data passed to the request callback.
55  *	Returns: True if no one currently owns the selection and I have
56  *               taken ownership.
57  *
58  * NOTE: The reply that is filled in by the application programmer is
59  *       passed to FreeReply, so that memory may be freed.  If you
60  *       want to take advantage of this, check wsm_proto.h or free.c
61  *       to see what is freed for each type of protocol request, and
62  *       then set the reply->any.allocated field to True to activate
63  *       automatic memory freeing.
64  */
65 
66 Boolean
WSMDefaultOwnSelection(Widget w,WSMClientType client_type,WSMRequestCallbackFunc request_callback,XtPointer request_data)67 WSMDefaultOwnSelection(Widget w, WSMClientType client_type,
68 		       WSMRequestCallbackFunc request_callback,
69 		       XtPointer request_data)
70 {
71     Time time;
72     Display *dpy = XtDisplay(w);
73     Atom own_selection =
74 	_WSMGetSelectionAtom(dpy,
75 			     XScreenNumberOfScreen(XtScreen(w)), client_type);
76 
77     if (XGetSelectionOwner(dpy, own_selection) != None) {
78 	/*
79 	 * Someone out there already owns this selection, we should give
80 	 * up and return.
81 	 */
82 
83         fprintf(stderr,"Error - Someone out there already owns this selection.\n");
84 
85 	return(False);
86     }
87 
88     if (!XtIsRealized(w)) {
89 	fprintf(stderr, "%s must be realized, and is not.\n",
90 		"Programmer Error: Widget passed to WSMDefaultOwnSelection");
91 	return(False);
92     }
93 
94     WSMRegisterRequestCallback(XtDisplay(w),
95  			       XScreenNumberOfScreen(XtScreen(w)),
96  			       request_callback, request_data);
97 
98     /*
99      * NOTE - w MUST have its XmNconvertCallback set properly,
100      *        otherwise, no conversions will be handled!
101      */
102     time = GetTimestamp(XtDisplay(w)); /* CurrentTime or Zero is a no-no!*/
103     XmeNamedSource(w, own_selection, time);
104 
105     return(True);
106 }
107 
108 /*	Function Name: WSMRegisterRequestCallback
109  *	Description: Registers the callback that will be called when
110  *                   a request comes in on the WSM protocol.
111  *	Arguments: disp - The display.
112  *                 scr_num - The Screen number.
113  *                 callback, data - The proc to register and the data
114  *                                  to send to it.
115  *	Returns: none.
116  *
117  * NOTE: The reply that is filled in by the application programmer is
118  *       passed to FreeReply, so that memory may be freed.  If you
119  *       want to take advantage of this, check wsm_proto.h or free.c
120  *       to see what is freed for each type of protocol request, and
121  *       then set the reply->any.allocated field to True to activate
122  *       automatic memory freeing.
123  */
124 
125 void
WSMRegisterRequestCallback(Display * disp,int scr_num,WSMRequestCallbackFunc callback,XtPointer data)126 WSMRegisterRequestCallback(Display *disp, int scr_num,
127 			   WSMRequestCallbackFunc callback, XtPointer data)
128 {
129     WSMScreenInfo *scr_info;
130 
131     scr_info = _WSMGetScreenInfo(disp, scr_num);
132 
133     /*
134      * Since only one client can own a particular selection, we can hang
135      * this data off of the screen data structure.  This is necessary because
136      * No data is passed to the ConvertProc by Xm or Xt.
137      *
138      * NOTE: We do not need to have room for one callback for the WSM and
139      *       one for the WM, since any given client will be one or the other,
140      *       not both.
141      */
142 
143     scr_info->request_callback = callback;
144     scr_info->request_data = data;
145 }
146 
147 
148 /*	Function Name: WSMIsKnownTarget
149  *	Description: Returns True if this target is part of the WSM protocol.
150  *	Arguments: w - Any widget on the screen of the client
151  *                     we are talking to.
152  *                 target - the target to check if part of the protocol.
153  *	Returns:  True if this target is part of the WSM protocol.
154  *
155  * NOTE: This could be extended to know about extensions.
156  */
157 
158 Boolean
WSMIsKnownTarget(Widget w,Atom target)159 WSMIsKnownTarget(Widget w, Atom target)
160 {
161     WSMDispInfo * disp_info = _WSMGetDispInfo(XtDisplay(w));
162 
163     /*
164      * Can't switch on dynamic data, sigh...
165      */
166 
167     if (disp_info->connect == target)
168 	return(True);
169     if (disp_info->extensions == target)
170 	return(True);
171     if (disp_info->config_fmt == target)
172 	return(True);
173     if (disp_info->get_state == target)
174 	return(True);
175     if (disp_info->set_state == target)
176 	return(True);
177     if (disp_info->reg_window == target)
178 	return(True);
179     if (disp_info->get_background == target)
180 	return(True);
181     if (disp_info->set_background == target)
182 	return(True);
183     if (disp_info->wm_windows == target)
184 	return(True);
185     if (disp_info->wm_focus == target)
186 	return(True);
187     if (disp_info->wm_pointer == target)
188 	return(True);
189 
190     return(False);
191 }
192 
193 /*	Function Name: WSMGetTargetList
194  *	Description: Returns the list of targets understood by the WSM
195  *                   protocol.
196  *	Arguments: w - Any widget on the same screen as the client we
197  *                     are talking to.
198  *                 include_defaults - Whether or not to include the
199  *                                    targets TIMESTAMP, MULTIPLE, and TARGETS.
200  *                                    in the returned list.
201  * RETURNED        len_ret - The number of atoms returned.
202  *	Returns: The targets atom list.  This list has been allocated with
203  *               XtMalloc, and must be free'd by the caller.
204  */
205 
206 Atom *
WSMGetTargetList(Widget w,Boolean include_defaults,unsigned long * len_ret)207 WSMGetTargetList(Widget w, Boolean include_defaults, unsigned long *len_ret)
208 {
209     WSMDispInfo *disp_info = _WSMGetDispInfo(XtDisplay(w));
210     register int i;
211     Atom *list;
212 
213     *len_ret = NUM_WSM_TARGETS;
214     if (include_defaults)
215 	*len_ret += NUM_EXTRA_TARGETS;
216 
217     list = (Atom *) XtMalloc(sizeof(Atom) * (*len_ret));
218 
219     i = 0;
220     list[i++] = disp_info->connect;
221     list[i++] = disp_info->extensions;
222     list[i++] = disp_info->config_fmt;
223     list[i++] = disp_info->get_state;
224     list[i++] = disp_info->set_state;
225     list[i++] = disp_info->reg_window;
226     list[i++] = disp_info->get_background;
227     list[i++] = disp_info->set_background;
228     list[i++] = disp_info->wm_windows;
229     list[i++] = disp_info->wm_focus;
230     list[i++] = disp_info->wm_pointer;
231     if (include_defaults) {
232 	list[i++] = disp_info->targets;
233 	list[i++] = disp_info->multiple;
234 	list[i++] = disp_info->timestamp;
235     }
236 
237     return(list);
238 }
239 
240 /*	Function Name: WSMProcessProtoTarget
241  *	Description: Unpacks the data sent across to us that matches the
242  *                   target, then calls the request_callback proceedure.
243  *	Arguments: w - Any widget that is on the same screen as the
244  *                     client that we are talking to.
245  *                 target - The target that defines which request this is.
246  *                 input, input_len, input_fmt - The input data.
247  *                 return_type - This is always set to the target IFF we
248  *                               know how to process this request.
249  *                 output, output_len, output_fmt - The data to send back
250  *                                                  to the requester.
251  *	Returns: True if we know how to process this message and there
252  *               are no errors
253  */
254 
255 Boolean
WSMProcessProtoTarget(Widget w,Atom target,XtPointer input,unsigned long input_len,int input_fmt,Atom * return_type,XtPointer * output,unsigned long * output_len,int * output_fmt)256 WSMProcessProtoTarget(Widget w, Atom target, XtPointer input,
257 		      unsigned long input_len, int input_fmt,
258 		      Atom *return_type, XtPointer *output,
259 		      unsigned long *output_len, int *output_fmt)
260 {
261     Display *dpy;
262     int scr_num;
263     WSMScreenInfo *screen_info;
264     WSMRequest request;
265     WSMReply reply;
266 
267     /*
268      * Check the Target to make sure it is valid.
269      * Check the format to make sure it is WSM_PROTO_FMT.
270      */
271 
272     if (!WSMIsKnownTarget(w, target))
273 	return(False);
274 
275     if (input_fmt != WSM_PROTO_FMT) {
276 	fprintf(stderr, "Format of the request must be %d\n", WSM_PROTO_FMT);
277 	return(False);
278     }
279 
280     dpy = XtDisplay(w);
281     scr_num = XScreenNumberOfScreen(XtScreen(w));
282 
283     /*
284      * Unpack up the request from the wire.
285      */
286 
287     _WSMUnpackRequest(dpy, scr_num, (MessageData) input, input_len,
288 		      _WSMTargetToReqType(dpy, target), &request);
289 
290     /*
291      * Call the app's callback function to process the request.
292      */
293 
294     screen_info = _WSMGetScreenInfo(dpy, scr_num);
295     reply.any.type = request.any.type;
296     reply.any.allocated = False;
297     (*screen_info->request_callback)(w, screen_info->request_data,
298 				     &request, &reply);
299     /*
300      * Pack up the reply and send it back.
301      */
302 
303     *output = (XtPointer) _WSMPackReply(dpy, scr_num, &reply, output_len);
304     *output_fmt = WSM_PROTO_FMT;
305     *return_type = target;	/* Is this the right return type? */
306 
307     FreeRequest(&request);
308     FreeReply(&reply);
309 
310     return(TRUE);
311 }
312 
313 /************************************************************
314  *
315  *  Internal routines.
316  *
317  ************************************************************/
318 
319 
320 #ifdef JUNK
321 /*================================================================*
322  | The following functions are used to handle selection/UTM       |
323  | conversion requests that are received by the selection OWNER.  |
324  *================================================================*/
325 
326 
327 /*----------------------------------------------------------------*
328  |                          UTMConvertProc                        |
329  | This is the UTM conversion proc called when a request comes in |
330  | for the selection owner.                                       |
331  |                                                                |
332  | NOTE - This function MUST have been set up as the callback for |
333  |        the utm widget's XmNconvertCallback procedure!          |
334  |                                                                |
335  | Arguments: w - The widget making the request.                  |
336  |            clientData - not used.                              |
337  |            callData - the UTM convert callback structure.      |
338  *----------------------------------------------------------------*/
339 static void
UTMConvertProc(Widget w,XtPointer clientData,XtPointer callData)340 UTMConvertProc(Widget w, XtPointer clientData, XtPointer callData)
341 {
342   int scr = XScreenNumberOfScreen(XtScreen(w));
343   XmConvertCallbackStruct *ccs = (XmConvertCallbackStruct *)callData;
344   Atom lose_sel = XInternAtom(XtDisplay(w), "_MOTIF_LOSE_SELECTION", False);
345   WSMScreenInfo *scrInfo = _WSMGetScreenInfo(XtDisplay(w), scr);
346 
347   /*
348    * Check if the callback was invoked for the right reason.
349    * The reason field is not set to anything interresting by the transfer
350    * code, so check the selection.
351    */
352   if ((!ccs) || ((ccs->selection != scrInfo->wm_selection) &&
353 		 (ccs->selection != scrInfo->wsm_selection)))
354     return;
355 
356   if (ccs->target == lose_sel)
357     {
358       /* Done with the conversion - free any data used. */
359     }
360 
361   /*
362    * Handle a conversion request with parameter data.
363    */
364   else
365     {
366       ConvertProc (w, &(ccs->selection), &(ccs->target),
367 		   ccs->parm,
368 		   ccs->parm_length,
369 		   ccs->parm_format,
370 		   &(ccs->type),
371 		   &(ccs->value),
372 		   &(ccs->length),
373 		   &(ccs->format));
374     }
375 }
376 
377 
378 
379 /*	Function Name: ConvertProc
380  *	Description: This is the conversion proc. called when a request
381  *                   comes in that we need to process.
382  *	Arguments: w - The widget that owns the selection?
383  *                 selection - The selection to be converted.
384  *                 target - The target to convert.
385  *                 return_type - The type of the return stream.
386  *                 output - The output data stream.
387  *                 output_len - The length of the output stream.
388  *                 output_fmt - The format of the output stream.
389  *	Returns: True if we can convert the selection, False otherwise.
390  */
391 
392 /*ARGSUSED*/
393 static Boolean
ConvertProc(Widget w,Atom * selection,Atom * target,XtPointer input,unsigned long input_len,int input_fmt,Atom * return_type,XtPointer * output,unsigned long * output_len,int * output_fmt)394 ConvertProc(Widget w, Atom *selection, Atom *target,
395 	    XtPointer input, unsigned long input_len, int input_fmt,
396 	    Atom *return_type, XtPointer *output, unsigned long *output_len,
397 	    int *output_fmt)
398 {
399     WSMDispInfo *disp_info;
400 
401     /* set up some defaults. selection code doesn't like garbage! */
402     *output = NULL;
403     *output_len = 0;
404     *output_fmt = 8;
405 
406     disp_info = _WSMGetDispInfo(XtDisplay(w));
407 
408     /*
409      * Since this function is only registered for one selection, I am going
410      * to assume that the intrinsics didn't give me the wrong thing.
411      */
412 
413     if (*target == disp_info->targets) {
414 	*return_type = XA_STRING;
415 	*output = (XtPointer) WSMGetTargetList(w, TRUE, output_len);
416 	*output_fmt = 32;
417 	return(True);
418     }
419     /*
420      * Intrinsics will handle MULTIPLE and TIMESTAMP for me.
421      */
422 
423     if (WSMProcessProtoTarget(w, *target, input, input_len, input_fmt,
424 			      return_type, output, output_len, output_fmt))
425     {
426 	return(TRUE);
427     }
428 
429     return(False);		/* unknown type, returning... */
430 }
431 #endif /*JUNK*/
432