/[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 392 - (hide annotations)
Fri Jun 6 09:30:06 2003 UTC (21 years ago) by forsberg
File MIME type: text/plain
File size: 18286 byte(s)
Handle large clipboard transfers Windows -> X.

Still won't handle transfers that demand INCR on the X side.

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 forsberg 388 extern Time last_gesturetime;
29 forsberg 383
30 forsberg 388 // static Time selection_timestamp;
31 forsberg 383 static Atom clipboard_atom, primary_atom, targets_atom, timestamp_atom;
32 forsberg 391 static Atom rdesktop_clipboard_target_atom, incr_atom;
33 forsberg 383 static cliprdr_dataformat *server_formats = NULL;
34     static uint16 num_server_formats = 0;
35 forsberg 384 static XSelectionEvent selection_event;
36 forsberg 390 static uint16 clipboard_channelno;
37 forsberg 391 static Atom targets[NUM_TARGETS];
38 forsberg 383
39     static void
40     cliprdr_print_server_formats(void)
41     {
42     #ifdef WITH_DEBUG_CLIPBOARD
43     cliprdr_dataformat *this;
44     uint16 i = 0;
45     this = server_formats;
46     DEBUG_CLIPBOARD(("There should be %d server formats.\n", num_server_formats));
47     while (NULL != this)
48     {
49     DEBUG_CLIPBOARD(("Format code %d\n", this->identifier));
50     i++;
51     this = this->next;
52     }
53 forsberg 384 DEBUG_CLIPBOARD(("There were %d server formats.\n", i));
54 forsberg 383 #endif
55     }
56 forsberg 388 /*
57     static void
58     cliprdr_set_selection_timestamp(void)
59     {
60     XEvent xev;
61     DEBUG_CLIPBOARD(("Changing a property in order to get a timestamp\n"));
62     fflush(stdout);
63     XChangeProperty(display, wnd, rdesktop_clipboard_target_atom,
64     XA_ATOM, 32, PropModeAppend, 0, 0);
65     DEBUG_CLIPBOARD(("Waiting for PropertyChange on wnd\n"));
66     fflush(stdout);
67     XWindowEvent(display, wnd,
68     PropertyChangeMask, &xev);
69     DEBUG_CLIPBOARD(("Setting selection_timestamp\n"));
70     fflush(stdout);
71     selection_timestamp = xev.xproperty.time;
72     }
73     */
74 forsberg 383
75 forsberg 386 static void
76 forsberg 387 cliprdr_send_format_announce(void)
77     {
78 forsberg 388 DEBUG_CLIPBOARD(("Sending format announce\n"));
79    
80 forsberg 387 STREAM s;
81     int number_of_formats = 1;
82     s = sec_init(encryption ? SEC_ENCRYPT : 0, number_of_formats*36+12+4+4);
83     out_uint32_le(s, number_of_formats*36+12);
84     out_uint32_le(s, 0x13);
85     out_uint16_le(s, 2);
86     out_uint16_le(s, 0);
87     out_uint32_le(s, number_of_formats*36);
88    
89     // out_uint32_le(s, 0xd); // FIXME: This is a rather bogus unicode text description..
90     // rdp_out_unistr(s, "", 16);
91     // out_uint8s(s, 32);
92    
93    
94     out_uint32_le(s, 1); // FIXME: This is a rather bogus text description..
95     out_uint8s(s, 32);
96    
97     out_uint32_le(s, 0);
98    
99     s_mark_end(s);
100 forsberg 390 sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0,
101     clipboard_channelno);
102 forsberg 387 }
103    
104    
105     static void
106 forsberg 386 cliprdr_send_empty_datapacket(void)
107     {
108     STREAM out;
109     out = sec_init(encryption ? SEC_ENCRYPT : 0,
110     20);
111     out_uint32_le(out, 12);
112     out_uint32_le(out, 0x13);
113     out_uint16_le(out, 5);
114     out_uint16_le(out, 1);
115     out_uint32_le(out, 0);
116     /* Insert null string here? */
117     out_uint32_le(out, 0);
118     s_mark_end(out);
119    
120 forsberg 390 sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0,
121     clipboard_channelno);
122 forsberg 386 }
123    
124    
125 forsberg 383 void
126 forsberg 386 cliprdr_handle_SelectionNotify(XSelectionEvent *event)
127 forsberg 383 {
128 forsberg 386
129 forsberg 391 unsigned char *data, *datap;
130 forsberg 386 unsigned long nitems, bytes_left;
131 forsberg 391
132     unsigned long bytes_left_to_transfer;
133     int res, i;
134 forsberg 386
135     int format;
136     Atom type_return;
137     Atom best_target;
138 forsberg 391 Atom *supported_targets;
139 forsberg 386
140     STREAM out;
141    
142 forsberg 383 DEBUG_CLIPBOARD(("cliprdr_handle_SelectionNotify\n"));
143 forsberg 386
144     if (None == event->property) {
145     cliprdr_send_empty_datapacket();
146     return; /* Selection failed */
147     }
148    
149     DEBUG_CLIPBOARD(("selection: %s, target: %s, property: %s\n",
150     XGetAtomName(display, event->selection),
151     XGetAtomName(display, event->target),
152     XGetAtomName(display, event->property)));
153    
154     if (targets_atom == event->target) {
155     /* Response to TARGETS request. Let's find the target
156     we want and request that */
157     res = XGetWindowProperty(display, wnd,
158     rdesktop_clipboard_target_atom,
159     0L, 4096L, False, AnyPropertyType,
160     &type_return,
161     &format, &nitems, &bytes_left, &data);
162    
163     if (Success != res)
164     {
165     DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
166     cliprdr_send_empty_datapacket();
167     return;
168     }
169    
170     if (None == type_return)
171     /* The owner might no support TARGETS. Just try
172     STRING */
173     best_target = XA_STRING;
174     else
175     {
176     /* FIXME: We should choose format here based
177     on what the server wanted */
178 forsberg 391 supported_targets = (Atom *)data;
179     for (i=0;i<nitems;i++)
180     {
181     DEBUG_CLIPBOARD(("Target %d: %s\n",
182     i, XGetAtomName(display,
183     supported_targets[i])));
184     }
185 forsberg 386 best_target = XInternAtom(display, "TEXT", False);
186    
187    
188     }
189    
190     XConvertSelection(display, primary_atom,
191     best_target,
192     rdesktop_clipboard_target_atom,
193     wnd, event->time);
194    
195     }
196     else /* Other clipboard data */
197     {
198    
199     res = XGetWindowProperty(display, wnd,
200     rdesktop_clipboard_target_atom,
201 forsberg 391 0L, 0x1FFFFFF,
202     True, AnyPropertyType,
203 forsberg 386 &type_return,
204     &format, &nitems, &bytes_left, &data);
205    
206 forsberg 391
207     /* FIXME: We need to handle INCR as well,
208     this is a temporary solution. */
209    
210     if (incr_atom == type_return)
211     {
212     warning("We don't support INCR transfers at this time. Try cutting less data\n");
213     cliprdr_send_empty_datapacket();
214     }
215    
216    
217 forsberg 386 if (Success != res)
218     {
219     DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
220     cliprdr_send_empty_datapacket();
221     return;
222     }
223    
224 forsberg 391 DEBUG_CLIPBOARD(("Received %d bytes of clipboard data from X, there is %d remaining\n",
225     nitems, bytes_left));
226     DEBUG_CLIPBOARD(("type_return is %s\n",
227     XGetAtomName(display, type_return)));
228 forsberg 386
229 forsberg 391 datap = data;
230    
231     if (nitems+1 <= MAX_CLIPRDR_STANDALONE_DATASIZE)
232     {
233     out = sec_init(encryption ? SEC_ENCRYPT : 0,
234     20+nitems+1);
235     out_uint32_le(out, 12+nitems+1);
236     out_uint32_le(out, 0x13);
237     out_uint16_le(out, 5);
238     out_uint16_le(out, 1);
239     out_uint32_le(out, nitems+1);
240     out_uint8p(out, datap, nitems+1);
241     out_uint32_le(out, 0);
242     s_mark_end(out);
243 forsberg 386
244 forsberg 391 sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0,
245     clipboard_channelno);
246 forsberg 388
247 forsberg 391 }
248     else
249     {
250     DEBUG_CLIPBOARD(("Sending %d bytes of data\n",
251     16+MAX_CLIPRDR_STANDALONE_DATASIZE));
252     out = sec_init(encryption ? SEC_ENCRYPT : 0,
253     16+MAX_CLIPRDR_STANDALONE_DATASIZE);
254     out_uint32_le(out, nitems+12);
255     out_uint32_le(out, 0x11);
256     out_uint16_le(out, 5);
257     out_uint16_le(out, 1);
258     out_uint32_le(out, nitems);
259     out_uint8p(out, datap,
260     MAX_CLIPRDR_STANDALONE_DATASIZE);
261     s_mark_end(out);
262    
263     sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0,
264     clipboard_channelno);
265    
266     bytes_left_to_transfer = nitems - MAX_CLIPRDR_STANDALONE_DATASIZE;
267     datap+=MAX_CLIPRDR_STANDALONE_DATASIZE;
268    
269     while (bytes_left_to_transfer > MAX_CLIPRDR_STANDALONE_DATASIZE)
270     {
271     DEBUG_CLIPBOARD(("Sending %d bytes of data\n",
272     16+MAX_CLIPRDR_CONTINUATION_DATASIZE));
273     out = sec_init(encryption ? SEC_ENCRYPT : 0,
274     8+MAX_CLIPRDR_CONTINUATION_DATASIZE);
275     out_uint32_le(out, nitems);
276     out_uint32_le(out, 0x10);
277     out_uint8p(out, datap,
278     MAX_CLIPRDR_CONTINUATION_DATASIZE);
279     s_mark_end(out);
280    
281     sec_send_to_channel(out,
282     encryption ? SEC_ENCRYPT : 0,
283     clipboard_channelno);
284     bytes_left_to_transfer-= MAX_CLIPRDR_CONTINUATION_DATASIZE;
285     datap+=MAX_CLIPRDR_CONTINUATION_DATASIZE;
286    
287     }
288     DEBUG_CLIPBOARD(("Sending %d bytes of data\n",
289     12+bytes_left_to_transfer));
290     out = sec_init(encryption ? SEC_ENCRYPT : 0,
291     12+bytes_left_to_transfer);
292     out_uint32_le(out, nitems);
293     out_uint32_le(out, 0x12);
294     out_uint8p(out, datap,
295     bytes_left_to_transfer);
296     out_uint32_le(out, 0x0);
297     s_mark_end(out);
298    
299     sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0,
300     clipboard_channelno);
301    
302     }
303    
304    
305     XFree(data);
306 forsberg 388 cliprdr_send_format_announce();
307 forsberg 386
308     }
309    
310    
311 forsberg 383 }
312    
313     void
314     cliprdr_handle_SelectionClear(void)
315     {
316     DEBUG_CLIPBOARD(("cliprdr_handle_SelectionClear\n"));
317 forsberg 387 cliprdr_send_format_announce();
318 forsberg 383 }
319    
320    
321 forsberg 384 static void
322     cliprdr_request_clipboard_data(uint32 formatcode)
323     {
324     STREAM s;
325     s = sec_init(encryption ? SEC_ENCRYPT : 0, 24);
326     out_uint32_le(s, 16);
327     out_uint32_le(s, 0x13);
328     out_uint16_le(s, 4);
329     out_uint16_le(s, 0);
330     out_uint32_le(s, 4); // Remaining length
331     out_uint32_le(s, formatcode);
332     out_uint32_le(s, 0); // Unknown. Garbage pad?
333    
334     s_mark_end(s);
335    
336 forsberg 390 sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0,
337     clipboard_channelno);
338 forsberg 384 }
339    
340    
341 forsberg 383 void
342     cliprdr_handle_SelectionRequest(XSelectionRequestEvent *xevent)
343     {
344    
345     XSelectionEvent xev;
346     DEBUG_CLIPBOARD(("cliprdr_handle_SelectionRequest\n"));
347 forsberg 384 DEBUG_CLIPBOARD(("Requestor window id 0x%x ",
348     (unsigned)xevent->requestor));
349 forsberg 383 if (clipboard_atom == xevent->selection) {
350     DEBUG_CLIPBOARD(("wants CLIPBOARD\n"));
351     }
352     if (primary_atom == xevent->selection) {
353     DEBUG_CLIPBOARD(("wants PRIMARY\n"));
354     }
355     DEBUG_CLIPBOARD(("Target is %s (0x%x), property is %s (0x%x)\n",
356     XGetAtomName(display, xevent->target),
357 forsberg 384 (unsigned)xevent->target,
358 forsberg 383 XGetAtomName(display, xevent->property),
359 forsberg 384 (unsigned)xevent->property));
360 forsberg 383
361     xev.type = SelectionNotify;
362     xev.serial = 0;
363     xev.send_event = True;
364     xev.requestor = xevent->requestor;
365     xev.selection = xevent->selection;
366     xev.target = xevent->target;
367     xev.property = xevent->property;
368     xev.time = xevent->time;
369    
370     if (targets_atom == xevent->target)
371     {
372     DEBUG_CLIPBOARD(("TARGETS requested, sending list..\n"));
373 forsberg 391 XChangeProperty(display,
374     xevent->requestor,
375     xevent->property,
376     XA_ATOM,
377     32,
378     PropModeAppend,
379     (unsigned char *)&targets,
380     NUM_TARGETS);
381 forsberg 383
382 forsberg 391 XSendEvent(display,
383     xevent->requestor,
384     False,
385     NoEventMask,
386     (XEvent *)&xev);
387 forsberg 383 return;
388     } else if (timestamp_atom == xevent->target)
389     {
390 forsberg 391 XChangeProperty(display,
391     xevent->requestor,
392     xevent->property,
393     XA_INTEGER,
394     32,
395     PropModeAppend,
396     (unsigned char *)&last_gesturetime,
397     1);
398     XSendEvent(display,
399     xevent->requestor,
400     False,
401     NoEventMask,
402     (XEvent *)&xev);
403 forsberg 383 } else /* Some other target */
404     {
405 forsberg 384 cliprdr_request_clipboard_data(CF_TEXT);
406     memcpy(&selection_event, &xev, sizeof(xev));
407     /* Return and wait for data, handled by
408     cliprdr_handle_server_data */
409     }
410     }
411 forsberg 383
412    
413 forsberg 384 static void
414     cliprdr_ack_format_list(void)
415     {
416     STREAM s;
417     s = sec_init(encryption ? SEC_ENCRYPT : 0, 20);
418     out_uint32_le(s, 12);
419     out_uint32_le(s, 0x13);
420     out_uint16_le(s, 3);
421     out_uint16_le(s, 1);
422     out_uint32_le(s, 0);
423     out_uint32_le(s, 0x0000c0da);
424    
425     s_mark_end(s);
426    
427 forsberg 390 sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0,
428     clipboard_channelno);
429 forsberg 383 }
430    
431 forsberg 384
432 forsberg 383
433 forsberg 384
434    
435 forsberg 383 static void
436     cliprdr_register_server_formats(STREAM s)
437     {
438     uint32 remaining_length, pad;
439     uint16 num_formats;
440     cliprdr_dataformat *this, *next;
441    
442     DEBUG_CLIPBOARD(("cliprdr_register_server_formats\n"));
443     in_uint32_le(s, remaining_length);
444    
445     num_formats = remaining_length / 36;
446     if (NULL != server_formats) {
447     this = server_formats;
448     next = this->next;
449     while (NULL != next) {
450     xfree(this);
451     this = NULL;
452     this = next;
453     next = this->next;
454     }
455     }
456     this = xmalloc(sizeof(cliprdr_dataformat));
457     this->next = NULL;
458     server_formats = this;
459     num_server_formats = num_formats;
460     while (1 < num_formats) {
461     in_uint32_le(s, this->identifier);
462     in_uint8a(s, this->textual_description, 32);
463 forsberg 384 DEBUG_CLIPBOARD(("Stored format description with numeric id %d\n",
464     this->identifier));
465 forsberg 383 this-> next = xmalloc(sizeof(cliprdr_dataformat));
466     this = this->next;
467     num_formats--;
468     }
469     in_uint32_le(s, this->identifier);
470     DEBUG_CLIPBOARD(("Stored format description with numeric id %d\n", this->identifier));
471     in_uint8a(s, this->textual_description, 32);
472     this -> next = NULL;
473     in_uint32_le(s, pad);
474     cliprdr_print_server_formats();
475     }
476    
477     static void
478     cliprdr_select_X_clipboards(void)
479     {
480 forsberg 388 XSetSelectionOwner(display, primary_atom, wnd, last_gesturetime);
481 forsberg 383 if (wnd != XGetSelectionOwner(display, primary_atom))
482     {
483     warning("Failed to aquire ownership of PRIMARY clipboard\n");
484     }
485 forsberg 388 XSetSelectionOwner(display, clipboard_atom, wnd, last_gesturetime);
486 forsberg 383 if (wnd != XGetSelectionOwner(display, clipboard_atom))
487     {
488     warning("Failed to aquire ownership of CLIPBOARD clipboard\n");
489     }
490    
491     }
492    
493 forsberg 384
494    
495 forsberg 385
496    
497 forsberg 383 static void
498     cliprdr_handle_first_handshake(STREAM s)
499     {
500     uint32 remaining_length, pad;
501     in_uint32_le(s, remaining_length);
502     in_uint32_le(s, pad);
503     DEBUG_CLIPBOARD(("Remaining length in first handshake frm server is %d, pad is %d\n",
504     remaining_length, pad));
505     cliprdr_send_format_announce();
506     }
507    
508 forsberg 392 void cliprdr_handle_server_data(uint32 length, uint32 flags, STREAM s)
509 forsberg 384 {
510 forsberg 392 static uint32 remaining_length;
511     static char *data, *datap;
512     static uint32 bytes_left_to_read;
513     DEBUG_CLIPBOARD(("In cliprdr_handle_server_data, flags is %d\n",
514     flags));
515     if (3 == flags) /* One-op write, no packets follows */
516     {
517     in_uint32_le(s, remaining_length);
518     data = s->p;
519     } else if (1 == flags) /* First of several packets */
520     {
521     in_uint32_le(s, remaining_length);
522     DEBUG_CLIPBOARD(("Remaining length is %d\n",
523     remaining_length));
524     data = xmalloc(remaining_length);
525     datap = data;
526     DEBUG_CLIPBOARD(("Copying first %d bytes\n",
527     MAX_CLIPRDR_STANDALONE_DATASIZE));
528     memcpy(datap, s->p, MAX_CLIPRDR_STANDALONE_DATASIZE);
529    
530     datap+=MAX_CLIPRDR_STANDALONE_DATASIZE;
531     bytes_left_to_read = remaining_length-MAX_CLIPRDR_STANDALONE_DATASIZE;
532     return;
533     } else if (0 == flags)
534     {
535     DEBUG_CLIPBOARD(("Copying %d middle bytes",
536     MAX_CLIPRDR_CONTINUATION_DATASIZE));
537     memcpy(datap, s->p, MAX_CLIPRDR_CONTINUATION_DATASIZE);
538    
539     datap+=MAX_CLIPRDR_CONTINUATION_DATASIZE;
540     bytes_left_to_read-=MAX_CLIPRDR_CONTINUATION_DATASIZE;
541     return;
542     } else if (2 == flags)
543     {
544     DEBUG_CLIPBOARD(("Copying last %d bytes\n",
545     bytes_left_to_read));
546     memcpy(datap, s->p, bytes_left_to_read);
547     }
548 forsberg 388 XChangeProperty(display,
549     selection_event.requestor,
550     selection_event.property,
551     XInternAtom(display, "STRING", False),
552     8,
553     PropModeAppend,
554     data,
555 forsberg 392 remaining_length-1);
556 forsberg 384
557 forsberg 388 XSendEvent(display,
558     selection_event.requestor,
559     False,
560     NoEventMask,
561     (XEvent *)&selection_event);
562 forsberg 384
563 forsberg 392 if (flags & 0x12)
564     xfree(data);
565    
566 forsberg 384 }
567    
568 forsberg 385 void cliprdr_handle_server_data_request(STREAM s)
569     {
570 forsberg 386 Window selectionowner;
571 forsberg 385 uint32 remaining_length;
572     uint32 wanted_formatcode, pad;
573    
574     in_uint32_le(s, remaining_length);
575     in_uint32_le(s, wanted_formatcode);
576     in_uint32_le(s, pad);
577    
578     /* FIXME: Check that we support this formatcode */
579    
580     DEBUG_CLIPBOARD(("Request from server for format %d\n",
581     wanted_formatcode));
582    
583 forsberg 386 selectionowner = XGetSelectionOwner(display, primary_atom);
584 forsberg 385
585 forsberg 386 if (None != selectionowner)
586     {
587 forsberg 385
588 forsberg 386 /* FIXME: Perhaps we should check if we are the owner? */
589 forsberg 385
590 forsberg 386 XConvertSelection(display, primary_atom,
591     targets_atom,
592     rdesktop_clipboard_target_atom,
593     wnd, CurrentTime);
594    
595     /* The rest of the transfer is handled in
596     cliprdr_handle_SelectionNotify */
597    
598     } else
599 forsberg 385 {
600 forsberg 386 DEBUG_CLIPBOARD(("There were no owner for PRIMARY, sending empty string\n")); // FIXME: Should we always send an empty string?
601    
602     cliprdr_send_empty_datapacket();
603 forsberg 385 }
604 forsberg 386
605    
606 forsberg 385 }
607    
608    
609 forsberg 390 void cliprdr_callback(STREAM s, uint16 channelno)
610 forsberg 383 {
611 forsberg 389 static int failed_clipboard_acks = 0;
612     struct timeval timeval;
613 forsberg 383 uint32 length, flags;
614     uint16 ptype0, ptype1;
615 forsberg 390 clipboard_channelno = channelno;
616     DEBUG_CLIPBOARD(("cliprdr_callback called with channelno %d, clipboard data:\n", channelno));
617 forsberg 383 #ifdef WITH_DEBUG_CLIPBOARD
618 forsberg 392 // hexdump(s->p, s->end - s->p);
619 forsberg 383 #endif
620     in_uint32_le(s, length);
621     in_uint32_le(s, flags);
622    
623     DEBUG_CLIPBOARD(("length is %d, flags are %d\n", length, flags));
624    
625 forsberg 392 if (3 == flags || 1 == flags) /* Single-write op or first-packet-of-several op */
626 forsberg 383 {
627     in_uint16_le(s, ptype0);
628     in_uint16_le(s, ptype1);
629     DEBUG_CLIPBOARD(("ptype0 is %d, ptype1 is %d\n", ptype0, ptype1));
630     if (1 == ptype0 && 0 == ptype1) {
631     cliprdr_handle_first_handshake(s);
632     return;
633     } else if (3 == ptype0 && 1 == ptype1)
634     {
635     // Acknowledgment on our format announce. Do we care? Not right now.
636     // There is a strange pad in this packet that we might need some time,
637     // but probably not.
638     DEBUG_CLIPBOARD(("Received format announce ACK\n"));
639 forsberg 389 failed_clipboard_acks = 0;
640 forsberg 383 return;
641 forsberg 384
642 forsberg 389 } else if (3 == ptype0 && 2 == ptype1)
643     {
644     DEBUG_CLIPBOARD(("Received failed clipboard format announce ACK, retrying\n"));
645    
646     /* This is a fairly portable way to sleep 1/10 of
647     a second.. */
648     timeval.tv_sec = 0;
649     timeval.tv_usec = 100;
650     select(0, NULL, NULL, NULL, &timeval);
651     if (failed_clipboard_acks < 3)
652     {
653    
654     cliprdr_send_format_announce();
655     /* Make sure we don't get stuck in this loop */
656     failed_clipboard_acks++;
657     }
658     else
659     {
660     warning("Reached maximum number of clipboard format announce attempts. Pasting in Windows probably won't work well now.\n");
661     }
662 forsberg 383 } else if (2 == ptype0 && 0 == ptype1)
663     {
664     cliprdr_register_server_formats(s);
665     cliprdr_select_X_clipboards();
666 forsberg 384 cliprdr_ack_format_list();
667 forsberg 383 return;
668 forsberg 384 } else if (5 == ptype0 && 1 == ptype1)
669     {
670 forsberg 392 cliprdr_handle_server_data(length, flags, s);
671 forsberg 385 } else if (4 == ptype0 && 0 == ptype1)
672     {
673     cliprdr_handle_server_data_request(s);
674 forsberg 383 }
675 forsberg 385
676 forsberg 383
677 forsberg 392 }
678     else
679     {
680     DEBUG_CLIPBOARD(("Handling middle or last packet\n"));
681     cliprdr_handle_server_data(length, flags, s);
682 forsberg 383 }
683     }
684    
685 forsberg 384
686 forsberg 383 void cliprdr_init(void)
687     {
688     primary_atom = XInternAtom(display, "PRIMARY", False);
689     clipboard_atom = XInternAtom(display, "CLIPBOARD", False);
690 forsberg 386 targets_atom = XInternAtom(display, "TARGETS", False);
691     timestamp_atom = XInternAtom(display, "TIMESTAMP", False);
692     rdesktop_clipboard_target_atom = XInternAtom(display, "_RDESKTOP_CLIPBOARD_TARGET", False);
693 forsberg 391 incr_atom = XInternAtom(display, "INCR", False);
694     targets[0] = targets_atom;
695     targets[1] = XInternAtom(display, "TEXT", False);
696     targets[2] = XInternAtom(display, "UTF8_STRING", False);
697     targets[3] = XInternAtom(display, "text/unicode", False);
698     targets[4] = XInternAtom(display, "TIMESTAMP", False);
699     targets[5] = XInternAtom(display, "STRING", False);
700    
701 forsberg 383 }

  ViewVC Help
Powered by ViewVC 1.1.26