Blame SOURCES/0003-channel-main-Convert-text-line-endings-if-necessary-.patch

4b3e03
From 28ef25781f62d6e3d96dba57a7ec772899b83661 Mon Sep 17 00:00:00 2001
4b3e03
From: Hans de Goede <hdegoede@redhat.com>
4b3e03
Date: Mon, 24 Jun 2013 14:30:43 +0200
4b3e03
Subject: [PATCH] channel-main: Convert text line-endings if necessary
4b3e03
 (rhbz#752350)
4b3e03
4b3e03
This implements line-ending conversion following the specification in the
4b3e03
commit message of spice-protocol commit 7be0e88e7e03a956b364cc847aad11b96ed4 :
4b3e03
vd_agent: Add caps for the agent to signal the guest line-ending (rhbz#752350)
4b3e03
4b3e03
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
4b3e03
(cherry picked from commit e45a446a9981ad4adaeff9c885962a8c6140333e)
4b3e03
---
4b3e03
 gtk/channel-main.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++---
4b3e03
 1 file changed, 69 insertions(+), 4 deletions(-)
4b3e03
4b3e03
diff --git a/gtk/channel-main.c b/gtk/channel-main.c
4b3e03
index b58af52..b9e0da2 100644
4b3e03
--- a/gtk/channel-main.c
4b3e03
+++ b/gtk/channel-main.c
4b3e03
@@ -1181,6 +1181,24 @@ static void agent_announce_caps(SpiceMainChannel *channel)
4b3e03
 #define HAS_CLIPBOARD_SELECTION(c) \
4b3e03
     VD_AGENT_HAS_CAPABILITY((c)->agent_caps, G_N_ELEMENTS((c)->agent_caps), VD_AGENT_CAP_CLIPBOARD_SELECTION)
4b3e03
 
4b3e03
+#define GUEST_LINEEND_LF(c) \
4b3e03
+    VD_AGENT_HAS_CAPABILITY((c)->agent_caps, G_N_ELEMENTS((c)->agent_caps), VD_AGENT_CAP_GUEST_LINEEND_LF)
4b3e03
+
4b3e03
+#define GUEST_LINEEND_CRLF(c) \
4b3e03
+    VD_AGENT_HAS_CAPABILITY((c)->agent_caps, G_N_ELEMENTS((c)->agent_caps), VD_AGENT_CAP_GUEST_LINEEND_CRLF)
4b3e03
+
4b3e03
+#ifdef G_OS_UNIX
4b3e03
+#define CLIENT_LINEEND_LF 1
4b3e03
+#else
4b3e03
+#define CLIENT_LINEEND_LF 0
4b3e03
+#endif
4b3e03
+
4b3e03
+#ifdef G_OS_WIN32
4b3e03
+#define CLIENT_LINEEND_CRLF 1
4b3e03
+#else
4b3e03
+#define CLIENT_LINEEND_CRLF 0
4b3e03
+#endif
4b3e03
+
4b3e03
 /* any context: the message is not flushed immediately,
4b3e03
    you can wakeup() the channel coroutine or send_msg_queue() */
4b3e03
 static void agent_clipboard_grab(SpiceMainChannel *channel, guint selection,
4b3e03
@@ -1751,6 +1769,29 @@ static void file_xfer_handle_status(SpiceMainChannel *channel,
4b3e03
     file_xfer_completed(task, error);
4b3e03
 }
4b3e03
 
4b3e03
+/* any context */
4b3e03
+static guchar *convert_lineend(const guchar *in, gsize *size,
4b3e03
+                               const gchar *from, const gchar *to)
4b3e03
+{
4b3e03
+    gchar *nul_terminated, **split, *out;
4b3e03
+
4b3e03
+    /* Nul-terminate */
4b3e03
+    nul_terminated = g_malloc(*size + 1);
4b3e03
+    memcpy(nul_terminated, in, *size);
4b3e03
+    nul_terminated[*size] = 0;
4b3e03
+
4b3e03
+    /* Convert */
4b3e03
+    split = g_strsplit(nul_terminated, from, -1);
4b3e03
+    out = g_strjoinv(to, split);
4b3e03
+    *size = strlen(out);
4b3e03
+
4b3e03
+    /* Clean-up */
4b3e03
+    g_strfreev(split);
4b3e03
+    g_free(nul_terminated);
4b3e03
+
4b3e03
+    return (guchar *)out;
4b3e03
+}
4b3e03
+
4b3e03
 /* coroutine context */
4b3e03
 static void main_agent_handle_msg(SpiceChannel *channel,
4b3e03
                                   VDAgentMessage *msg, gpointer payload)
4b3e03
@@ -1809,12 +1850,22 @@ static void main_agent_handle_msg(SpiceChannel *channel,
4b3e03
     case VD_AGENT_CLIPBOARD:
4b3e03
     {
4b3e03
         VDAgentClipboard *cb = payload;
4b3e03
+        guchar *data = cb->data;
4b3e03
+        gsize size = msg->size - sizeof(VDAgentClipboard);
4b3e03
+        if (cb->type == VD_AGENT_CLIPBOARD_UTF8_TEXT) {
4b3e03
+            if (GUEST_LINEEND_LF(c) && CLIENT_LINEEND_CRLF)
4b3e03
+                data = convert_lineend(data, &size, "\n", "\r\n");
4b3e03
+            if (GUEST_LINEEND_CRLF(c) && CLIENT_LINEEND_LF)
4b3e03
+                data = convert_lineend(data, &size, "\r\n", "\n");
4b3e03
+        }
4b3e03
         emit_main_context(channel, SPICE_MAIN_CLIPBOARD_SELECTION, selection,
4b3e03
-                          cb->type, cb->data, msg->size - sizeof(VDAgentClipboard));
4b3e03
+                          cb->type, data, size);
4b3e03
 
4b3e03
-       if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD)
4b3e03
+        if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD)
4b3e03
             emit_main_context(channel, SPICE_MAIN_CLIPBOARD,
4b3e03
-                              cb->type, cb->data, msg->size - sizeof(VDAgentClipboard));
4b3e03
+                              cb->type, data, size);
4b3e03
+        if (data != cb->data)
4b3e03
+            g_free(data);
4b3e03
         break;
4b3e03
     }
4b3e03
     case VD_AGENT_CLIPBOARD_GRAB:
4b3e03
@@ -2554,13 +2605,27 @@ void spice_main_clipboard_notify(SpiceMainChannel *channel,
4b3e03
  * Since: 0.6
4b3e03
  **/
4b3e03
 void spice_main_clipboard_selection_notify(SpiceMainChannel *channel, guint selection,
4b3e03
-                                           guint32 type, const guchar *data, size_t size)
4b3e03
+                                           guint32 type, const guchar *_data, size_t _size)
4b3e03
 {
4b3e03
+    const guchar *data = _data;
4b3e03
+    gsize size = _size;
4b3e03
+
4b3e03
     g_return_if_fail(channel != NULL);
4b3e03
     g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel));
4b3e03
 
4b3e03
+    SpiceMainChannelPrivate *c = channel->priv;
4b3e03
+
4b3e03
+    if (type == VD_AGENT_CLIPBOARD_UTF8_TEXT) {
4b3e03
+        if (CLIENT_LINEEND_CRLF && GUEST_LINEEND_LF(c))
4b3e03
+            data = convert_lineend(data, &size, "\r\n", "\n");
4b3e03
+        if (CLIENT_LINEEND_LF && GUEST_LINEEND_CRLF(c))
4b3e03
+            data = convert_lineend(data, &size, "\n", "\r\n");
4b3e03
+    }
4b3e03
     agent_clipboard_notify(channel, selection, type, data, size);
4b3e03
     spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE);
4b3e03
+
4b3e03
+    if (data != _data)
4b3e03
+        g_free((guchar *)data);
4b3e03
 }
4b3e03
 
4b3e03
 /**