--- sourceforge.net/trunk/rdesktop/xclip.c 2004/06/04 08:42:11 707 +++ sourceforge.net/trunk/rdesktop/xclip.c 2005/11/09 15:15:28 1026 @@ -36,6 +36,9 @@ static int have_primary = 0; static int rdesktop_is_selection_owner = 0; +static int g_waiting_for_INCR = 0; +static uint8 *g_clip_buffer = 0; +static uint32 g_clip_buflen = 0; /* Replace CR-LF to LF (well, rather removing all CR:s) This is done in-place. The length is updated. Handles embedded nulls */ @@ -101,10 +104,12 @@ XSendEvent(g_display, req->requestor, False, NoEventMask, &xev); } +#ifndef MAKE_PROTO void xclip_handle_SelectionNotify(XSelectionEvent * event) { unsigned long nitems, bytes_left; + XWindowAttributes wa; Atom type, best_target, text_target; Atom *supported_targets; int res, i, format; @@ -122,7 +127,7 @@ goto fail; res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom, - 0, XMaxRequestSize(g_display), True, AnyPropertyType, + 0, XMaxRequestSize(g_display), False, AnyPropertyType, &type, &format, &nitems, &bytes_left, &data); if (res != Success) @@ -131,6 +136,24 @@ goto fail; } + + if (type == incr_atom) + { + DEBUG_CLIPBOARD(("Received INCR.\n")); + + XGetWindowAttributes(g_display, g_wnd, &wa); + if ((wa.your_event_mask | PropertyChangeMask) != wa.your_event_mask) + { + XSelectInput(g_display, g_wnd, (wa.your_event_mask | PropertyChangeMask)); + } + XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom); + XFree(data); + g_waiting_for_INCR = 1; + return; + } + + XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom); + /* Negotiate target format */ if (event->target == targets_atom) { @@ -159,12 +182,6 @@ return; } - if (type == incr_atom) - { - warning("We don't support INCR transfers at this time. Try cutting less data.\n"); - goto fail; - } - /* Translate linebreaks, but only if not getting data from other rdesktop instance */ if (event->target != rdesktop_clipboard_formats_atom) @@ -184,10 +201,12 @@ XFree(data); if (!rdesktop_is_selection_owner) - cliprdr_send_text_format_announce(); + cliprdr_send_simple_native_format_announce(CF_TEXT); return; - fail: + fail: + XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom); + XFree(data); cliprdr_send_data(NULL, 0); } @@ -240,17 +259,78 @@ DEBUG_CLIPBOARD(("xclip_handle_SelectionClear\n")); have_primary = 0; XDeleteProperty(g_display, DefaultRootWindow(g_display), rdesktop_clipboard_formats_atom); - cliprdr_send_text_format_announce(); + cliprdr_send_simple_native_format_announce(CF_TEXT); } void xclip_handle_PropertyNotify(XPropertyEvent * event) { - unsigned long nitems, bytes_left; + unsigned long nitems; + unsigned long offset = 0; + unsigned long bytes_left = 1; int format, res; + XWindowAttributes wa; uint8 *data; Atom type; + if (event->state == PropertyNewValue && g_waiting_for_INCR) + { + DEBUG_CLIPBOARD(("x_clip_handle_PropertyNotify: g_waiting_for_INCR != 0\n")); + + while (bytes_left > 0) { + if ((XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom, offset, + 4096L, False, AnyPropertyType, + &type, &format, &nitems, &bytes_left, &data) != Success)) + { + XFree(data); + return; + } + + if (nitems == 0) + { + XGetWindowAttributes(g_display, g_wnd, &wa); + XSelectInput(g_display, g_wnd, (wa.your_event_mask ^ PropertyChangeMask)); + XFree(data); + g_waiting_for_INCR = 0; + + if (g_clip_buflen > 0) + { + cliprdr_send_data(g_clip_buffer, g_clip_buflen + 1); + + if (!rdesktop_is_selection_owner) + cliprdr_send_simple_native_format_announce(CF_TEXT); + + xfree(g_clip_buffer); + g_clip_buffer = 0; + g_clip_buflen = 0; + } + } + else + { + uint8 *translated_data; + uint32 length = nitems; + uint8 *tmp; + + offset += (length/4); + DEBUG_CLIPBOARD(("Translating linebreaks before sending data\n")); + translated_data = lf2crlf(data, &length); + + tmp = xmalloc(length + g_clip_buflen); + strncpy((char *) tmp, (char *) g_clip_buffer, g_clip_buflen); + xfree(g_clip_buffer); + + strncpy((char *) (tmp + g_clip_buflen), (char *) translated_data, length); + xfree(translated_data); + + g_clip_buffer = tmp; + g_clip_buflen += length; + + XFree(data); + } + } + XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom); + } + if (event->atom != rdesktop_clipboard_formats_atom) return; @@ -273,9 +353,10 @@ } /* PropertyDelete, or XGetWindowProperty failed */ - cliprdr_send_text_format_announce(); + cliprdr_send_simple_native_format_announce(CF_TEXT); rdesktop_is_selection_owner = 0; } +#endif void @@ -361,7 +442,7 @@ void ui_clip_sync(void) { - cliprdr_send_text_format_announce(); + cliprdr_send_simple_native_format_announce(CF_TEXT); }