/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 383 - (show 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 /* -*- 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