/[rdesktop]/sourceforge.net/trunk/rdesktop/cliprdr.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /sourceforge.net/trunk/rdesktop/cliprdr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 383 - (hide annotations)
Fri Jun 6 09:20:53 2003 UTC (21 years ago) by forsberg
File MIME type: text/plain
File size: 9049 byte(s)
Initial revision

1 forsberg 383 /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.
3     Protocol services - Clipboard functions
4     Copyright (C) Erik Forsberg <forsberg@cendio.se> 2003
5    
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10    
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     GNU General Public License for more details.
15    
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19     */
20    
21     #include <X11/Xlib.h>
22     #include <X11/Xatom.h>
23     #include "rdesktop.h"
24    
25     extern BOOL encryption;
26     extern Display *display;
27     extern Window wnd;
28     extern Time last_keyrelease;
29    
30     static Atom clipboard_atom, primary_atom, targets_atom, timestamp_atom;
31     static cliprdr_dataformat *server_formats = NULL;
32     static uint16 num_server_formats = 0;
33    
34     static void
35     cliprdr_print_server_formats(void)
36     {
37     #ifdef WITH_DEBUG_CLIPBOARD
38     cliprdr_dataformat *this;
39     uint16 i = 0;
40     this = server_formats;
41     DEBUG_CLIPBOARD(("There should be %d server formats.\n", num_server_formats));
42     while (NULL != this)
43     {
44     DEBUG_CLIPBOARD(("Format code %d\n", this->identifier));
45     i++;
46     this = this->next;
47     }
48     DEBUG_CLIPBOARD(("There was %d server formats.\n", i));
49     #endif
50     }
51    
52     void
53     cliprdr_handle_SelectionNotify(void)
54     {
55     DEBUG_CLIPBOARD(("cliprdr_handle_SelectionNotify\n"));
56     }
57    
58     void
59     cliprdr_handle_SelectionClear(void)
60     {
61     DEBUG_CLIPBOARD(("cliprdr_handle_SelectionClear\n"));
62     }
63    
64     void print_X_error(int res)
65     {
66     switch(res) {
67     case Success:
68     DEBUG_CLIPBOARD(("Success\n"));
69     break;
70    
71     case BadAtom:
72     DEBUG_CLIPBOARD(("BadAtom\n"));
73     break;
74    
75     case BadRequest:
76     DEBUG_CLIPBOARD(("BadRequest\n"));
77     break;
78    
79     case BadAlloc:
80     DEBUG_CLIPBOARD(("BadAlloc\n"));
81     break;
82    
83     case BadMatch:
84     DEBUG_CLIPBOARD(("BadMatch\n"));
85     break;
86    
87     case BadValue:
88     DEBUG_CLIPBOARD(("BadValue\n"));
89     break;
90    
91     case BadWindow:
92     DEBUG_CLIPBOARD(("BadWindo\n"));
93     break;
94    
95     default:
96     DEBUG_CLIPBOARD(("Unknown X error code %d\n", res));
97     }
98     }
99    
100     void
101     cliprdr_handle_SelectionRequest(XSelectionRequestEvent *xevent)
102     {
103    
104     Atom type_return;
105     Atom *targets;
106     int format_return;
107     long nitems_return;
108     long bytes_after_return;
109     char **prop_return;
110     int res;
111    
112     XSelectionEvent xev;
113     DEBUG_CLIPBOARD(("cliprdr_handle_SelectionRequest\n"));
114     DEBUG_CLIPBOARD(("Requestor window id 0x%x ", xevent->requestor));
115     if (clipboard_atom == xevent->selection) {
116     DEBUG_CLIPBOARD(("wants CLIPBOARD\n"));
117     }
118     if (primary_atom == xevent->selection) {
119     DEBUG_CLIPBOARD(("wants PRIMARY\n"));
120     }
121     DEBUG_CLIPBOARD(("Target is %s (0x%x), property is %s (0x%x)\n",
122     XGetAtomName(display, xevent->target),
123     xevent->target,
124     XGetAtomName(display, xevent->property),
125     xevent->property));
126    
127     xev.type = SelectionNotify;
128     xev.serial = 0;
129     xev.send_event = True;
130     xev.requestor = xevent->requestor;
131     xev.selection = xevent->selection;
132     xev.target = xevent->target;
133     xev.property = xevent->property;
134     xev.time = xevent->time;
135    
136     if (targets_atom == xevent->target)
137     {
138     DEBUG_CLIPBOARD(("TARGETS requested, sending list..\n"));
139     targets = xmalloc(4*sizeof(Atom));
140     targets[0] = xevent->target;
141     targets[1] = XInternAtom(display, "TEXT", True);
142     targets[2] = XInternAtom(display, "UTF8_STRING", True);
143     targets[3] = XInternAtom(display, "TIMESTAMP", True);
144     res = XChangeProperty(display,
145     xevent->requestor,
146     xevent->property,
147     XA_ATOM,
148     32,
149     PropModeAppend,
150     (unsigned char *)targets,
151     3);
152     DEBUG_CLIPBOARD(("res after XChangeProperty is "));
153     print_X_error(res);
154    
155     res = XSendEvent(display,
156     xevent->requestor,
157     False,
158     NoEventMask,
159     (XEvent *)&xev);
160     return;
161     } else if (timestamp_atom == xevent->target)
162     {
163     DEBUG_CLIPBOARD(("TIMESTAMP requested... sending 0x%x\n",
164     last_keyrelease));
165     res = XChangeProperty(display,
166     xevent->requestor,
167     xevent->property,
168     XA_INTEGER,
169     32,
170     PropModeAppend,
171     (unsigned char *)&last_keyrelease,
172     1);
173     res = XSendEvent(display,
174     xevent->requestor,
175     False,
176     NoEventMask,
177     (XEvent *)&xev);
178     } else /* Some other target */
179     {
180     res = XChangeProperty(display,
181     xevent->requestor,
182     xevent->property,
183     XInternAtom(display, "STRING", False),
184     8,
185     PropModeAppend,
186     "krattoflabkat",
187     13);
188    
189     DEBUG_CLIPBOARD(("res after XChangeProperty is "));
190     print_X_error(res);
191    
192     xev.type = SelectionNotify;
193     xev.serial = 0;
194     xev.send_event = True;
195     xev.requestor = xevent->requestor;
196     xev.selection = xevent->selection;
197     xev.target = xevent->target;
198     xev.property = xevent->property;
199     xev.time = xevent->time;
200    
201     res = XSendEvent(display,
202     xevent->requestor,
203     False,
204     NoEventMask,
205     (XEvent *)&xev);
206    
207     DEBUG_CLIPBOARD(("res after XSendEvent is "));
208     print_X_error(res);
209     }
210     }
211    
212    
213     static void
214     cliprdr_register_server_formats(STREAM s)
215     {
216     uint32 remaining_length, pad;
217     uint16 num_formats;
218     cliprdr_dataformat *this, *next;
219    
220     DEBUG_CLIPBOARD(("cliprdr_register_server_formats\n"));
221     in_uint32_le(s, remaining_length);
222    
223     num_formats = remaining_length / 36;
224     if (NULL != server_formats) {
225     this = server_formats;
226     next = this->next;
227     while (NULL != next) {
228     xfree(this);
229     this = NULL;
230     this = next;
231     next = this->next;
232     }
233     }
234     this = xmalloc(sizeof(cliprdr_dataformat));
235     this->next = NULL;
236     server_formats = this;
237     num_server_formats = num_formats;
238     while (1 < num_formats) {
239     in_uint32_le(s, this->identifier);
240     in_uint8a(s, this->textual_description, 32);
241     DEBUG_CLIPBOARD(("Stored format description with numeric id %d\n", this->identifier));
242     this-> next = xmalloc(sizeof(cliprdr_dataformat));
243     this = this->next;
244     num_formats--;
245     }
246     in_uint32_le(s, this->identifier);
247     DEBUG_CLIPBOARD(("Stored format description with numeric id %d\n", this->identifier));
248     in_uint8a(s, this->textual_description, 32);
249     this -> next = NULL;
250     in_uint32_le(s, pad);
251     cliprdr_print_server_formats();
252     }
253    
254     static void
255     cliprdr_select_X_clipboards(void)
256     {
257     XSetSelectionOwner(display, primary_atom, wnd, last_keyrelease);
258     if (wnd != XGetSelectionOwner(display, primary_atom))
259     {
260     warning("Failed to aquire ownership of PRIMARY clipboard\n");
261     }
262     XSetSelectionOwner(display, clipboard_atom, wnd, CurrentTime);
263     if (wnd != XGetSelectionOwner(display, clipboard_atom))
264     {
265     warning("Failed to aquire ownership of CLIPBOARD clipboard\n");
266     }
267    
268     }
269    
270     static void
271     cliprdr_send_format_announce(void)
272     {
273     STREAM s;
274     int number_of_formats = 1;
275     s = sec_init(encryption ? SEC_ENCRYPT : 0, number_of_formats*36+12+4+4);
276     out_uint32_le(s, number_of_formats*36+12);
277     out_uint32_le(s, 0x13);
278     out_uint16_le(s, 2);
279     out_uint16_le(s, 0);
280     out_uint32_le(s, number_of_formats*36);
281    
282     out_uint32_le(s, 0xd); // FIXME: This is a rather bogus unicode text description..
283     // rdp_out_unistr(s, "", 16);
284     out_uint8s(s, 32);
285    
286     out_uint32_le(s, 0);
287    
288     s_mark_end(s);
289     sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0, 1005); // FIXME: Don't hardcode channel!
290     }
291    
292    
293     static void
294     cliprdr_handle_first_handshake(STREAM s)
295     {
296     uint32 remaining_length, pad;
297     in_uint32_le(s, remaining_length);
298     in_uint32_le(s, pad);
299     DEBUG_CLIPBOARD(("Remaining length in first handshake frm server is %d, pad is %d\n",
300     remaining_length, pad));
301     cliprdr_send_format_announce();
302     }
303    
304     void cliprdr_callback(STREAM s)
305     {
306     uint32 length, flags;
307     uint16 ptype0, ptype1;
308     DEBUG_CLIPBOARD(("cliprdr_callback called, clipboard data:\n"));
309     #ifdef WITH_DEBUG_CLIPBOARD
310     hexdump(s->p, s->end - s->p);
311     #endif
312     in_uint32_le(s, length);
313     in_uint32_le(s, flags);
314    
315     DEBUG_CLIPBOARD(("length is %d, flags are %d\n", length, flags));
316    
317     if (flags & 0x03 || flags & 0x01) /* Single-write op or first-packet-of-several op */
318     {
319     in_uint16_le(s, ptype0);
320     in_uint16_le(s, ptype1);
321     DEBUG_CLIPBOARD(("ptype0 is %d, ptype1 is %d\n", ptype0, ptype1));
322     if (1 == ptype0 && 0 == ptype1) {
323     cliprdr_handle_first_handshake(s);
324     return;
325     } else if (3 == ptype0 && 1 == ptype1)
326     {
327     // Acknowledgment on our format announce. Do we care? Not right now.
328     // There is a strange pad in this packet that we might need some time,
329     // but probably not.
330     DEBUG_CLIPBOARD(("Received format announce ACK\n"));
331     return;
332     } else if (2 == ptype0 && 0 == ptype1)
333     {
334     cliprdr_register_server_formats(s);
335     cliprdr_select_X_clipboards();
336     return;
337     }
338    
339     }
340     }
341    
342     void cliprdr_init(void)
343     {
344     primary_atom = XInternAtom(display, "PRIMARY", False);
345     clipboard_atom = XInternAtom(display, "CLIPBOARD", False);
346     targets_atom = XInternAtom(display, "TARGETS", True);
347     timestamp_atom = XInternAtom(display, "TIMESTAMP", True);
348     }

  ViewVC Help
Powered by ViewVC 1.1.26