VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedClipboard/darwin-pasteboard.cpp@ 14709

Last change on this file since 14709 was 13837, checked in by vboxsync, 16 years ago

s/%Vr\([acfs]\)/%Rr\1/g - since I'm upsetting everyone anyway, better make the most of it...

  • Property eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 11.4 KB
Line 
1/* $Id: darwin-pasteboard.cpp 13837 2008-11-05 02:54:02Z vboxsync $ */
2/** @file
3 * Shared Clipboard: Mac OS X host implementation.
4 */
5
6/*
7 * Copyright (C) 2008 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#include <Carbon/Carbon.h>
23
24#include <iprt/mem.h>
25#include <iprt/assert.h>
26#include "iprt/err.h"
27
28#define LOG_GROUP LOG_GROUP_HGCM
29#include "VBox/log.h"
30#include "VBox/HostServices/VBoxClipboardSvc.h"
31#include "clipboard-helper.h"
32
33/* For debugging */
34//#define SHOW_CLIPBOARD_CONTENT
35
36/**
37 * Initialize the global pasteboard and return a reference to it.
38 *
39 * @param pPasteboardRef Reference to the global pasteboard.
40 *
41 * @returns IPRT status code.
42 */
43int initPasteboard (PasteboardRef *pPasteboardRef)
44{
45 int rc = VINF_SUCCESS;
46
47 if (PasteboardCreate (kPasteboardClipboard, pPasteboardRef))
48 rc = VERR_NOT_SUPPORTED;
49
50 return rc;
51}
52
53/**
54 * Release the reference to the global pasteboard.
55 *
56 * @param pPasteboardRef Reference to the global pasteboard.
57 */
58void destroyPasteboard (PasteboardRef *pPasteboardRef)
59{
60 CFRelease (*pPasteboardRef);
61 *pPasteboardRef = NULL;
62}
63
64/**
65 * Inspect the global pasteboard for new content. Check if there is some type
66 * that is supported by vbox and return it.
67 *
68 * @param pPasteboardRef Reference to the global pasteboard.
69 * @param pfFormats Pointer for the bit combination of the
70 * supported types.
71 * @param pbChanged True if something has changed after the
72 * last call.
73 *
74 * @returns IPRT status code. (Always VINF_SUCCESS atm.)
75 */
76int queryNewPasteboardFormats (PasteboardRef pPasteboard, uint32_t *pfFormats, bool *pfChanged)
77{
78 Log (("queryNewPasteboardFormats\n"));
79
80 OSStatus err = noErr;
81 *pfChanged = true;
82
83 PasteboardSyncFlags syncFlags;
84 /* Make sure all is in sync */
85 syncFlags = PasteboardSynchronize (pPasteboard);
86 /* If nothing changed return */
87 if (!(syncFlags & kPasteboardModified))
88 {
89 *pfChanged = false;
90 return VINF_SUCCESS;
91 }
92
93 /* Are some items in the pasteboard? */
94 ItemCount itemCount;
95 err = PasteboardGetItemCount (pPasteboard, &itemCount);
96 if (itemCount < 1)
97 return VINF_SUCCESS;
98
99 /* The id of the first element in the pasteboard */
100 int rc = VINF_SUCCESS;
101 PasteboardItemID itemID;
102 if (!(err = PasteboardGetItemIdentifier (pPasteboard, 1, &itemID)))
103 {
104 /* Retrieve all flavors in the pasteboard, maybe there
105 * is something we can use. */
106 CFArrayRef flavorTypeArray;
107 if (!(err = PasteboardCopyItemFlavors (pPasteboard, itemID, &flavorTypeArray)))
108 {
109 CFIndex flavorCount;
110 flavorCount = CFArrayGetCount (flavorTypeArray);
111 for (CFIndex flavorIndex = 0; flavorIndex < flavorCount; flavorIndex++)
112 {
113 CFStringRef flavorType;
114 flavorType = static_cast <CFStringRef> (CFArrayGetValueAtIndex (flavorTypeArray,
115 flavorIndex));
116 /* Currently only unicode supported */
117 if (UTTypeConformsTo (flavorType, CFSTR ("public.utf8-plain-text")) ||
118 UTTypeConformsTo (flavorType, CFSTR ("public.utf16-plain-text")))
119 {
120 Log (("Unicode flavor detected.\n"));
121 *pfFormats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
122 }
123 }
124 CFRelease (flavorTypeArray);
125 }
126 }
127
128 Log (("queryNewPasteboardFormats: rc = %02X\n", rc));
129 return rc;
130}
131
132/**
133 * Read content from the host clipboard and write it to the internal clipboard
134 * structure for further processing.
135 *
136 * @param pPasteboardRef Reference to the global pasteboard.
137 * @param fFormats The format type which should be read.
138 * @param pv The destination buffer.
139 * @param cb The size of the destination buffer.
140 * @param pcbActual The size which is needed to transfer the content.
141 *
142 * @returns IPRT status code.
143 */
144int readFromPasteboard (PasteboardRef pPasteboard, uint32_t fFormat, void *pv, uint32_t cb, uint32_t *pcbActual)
145{
146 Log (("readFromPasteboard: fFormat = %02X\n", fFormat));
147
148 OSStatus err = noErr;
149
150 /* Make sure all is in sync */
151 PasteboardSynchronize (pPasteboard);
152
153 /* Are some items in the pasteboard? */
154 ItemCount itemCount;
155 err = PasteboardGetItemCount (pPasteboard, &itemCount);
156 if (itemCount < 1)
157 return VINF_SUCCESS;
158
159 /* The id of the first element in the pasteboard */
160 int rc = VERR_NOT_SUPPORTED;
161 PasteboardItemID itemID;
162 if (!(err = PasteboardGetItemIdentifier (pPasteboard, 1, &itemID)))
163 {
164 /* The guest request unicode */
165 if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
166 {
167 CFDataRef outData;
168 PRTUTF16 pwszTmp = NULL;
169 /* Try utf-16 first */
170 if (!(err = PasteboardCopyItemFlavorData (pPasteboard, itemID, CFSTR ("public.utf16-plain-text"), &outData)))
171 {
172 Log (("Clipboard content is utf-16\n"));
173 rc = RTUtf16DupEx (&pwszTmp, (PRTUTF16)CFDataGetBytePtr (outData), 0);
174 }
175 /* Second try is utf-8 */
176 else
177 if (!(err = PasteboardCopyItemFlavorData (pPasteboard, itemID, CFSTR ("public.utf8-plain-text"), &outData)))
178 {
179 Log (("readFromPasteboard: clipboard content is utf-8\n"));
180 rc = RTStrToUtf16 ((const char*)CFDataGetBytePtr (outData), &pwszTmp);
181 }
182 if (pwszTmp)
183 {
184 /* Check how much longer will the converted text will be. */
185 size_t cwSrc = RTUtf16Len (pwszTmp);
186 size_t cwDest;
187 rc = vboxClipboardUtf16GetWinSize (pwszTmp, cwSrc, &cwDest);
188 if (RT_FAILURE (rc))
189 {
190 RTUtf16Free (pwszTmp);
191 Log (("readFromPasteboard: clipboard conversion failed. vboxClipboardUtf16GetWinSize returned %Rrc. Abandoning.\n", rc));
192 AssertRCReturn (rc, rc);
193 }
194 /* Set the actually needed data size */
195 *pcbActual = cwDest * 2;
196 /* Return success state */
197 rc = VINF_SUCCESS;
198 /* Do not copy data if the dst buffer is not big enough. */
199 if (*pcbActual <= cb)
200 {
201 rc = vboxClipboardUtf16LinToWin (pwszTmp, RTUtf16Len (pwszTmp), static_cast <PRTUTF16> (pv), cb / 2);
202 if (RT_FAILURE (rc))
203 {
204 RTUtf16Free (pwszTmp);
205 Log (("readFromPasteboard: clipboard conversion failed. vboxClipboardUtf16LinToWin() returned %Rrc. Abandoning.\n", rc));
206 AssertRCReturn (rc, rc);
207 }
208#ifdef SHOW_CLIPBOARD_CONTENT
209 Log (("readFromPasteboard: clipboard content: %ls\n", static_cast <PRTUTF16> (pv)));
210#endif
211 }
212 /* Free the temp string */
213 RTUtf16Free (pwszTmp);
214 }
215 }
216 }
217
218 Log (("readFromPasteboard: rc = %02X\n", rc));
219 return rc;
220}
221
222/**
223 * Write clipboard content to the host clipboard from the internal clipboard
224 * structure.
225 *
226 * @param pPasteboardRef Reference to the global pasteboard.
227 * @param pv The source buffer.
228 * @param cb The size of the source buffer.
229 * @param fFormats The format type which should be written.
230 *
231 * @returns IPRT status code.
232 */
233int writeToPasteboard (PasteboardRef pPasteboard, void *pv, uint32_t cb, uint32_t fFormat)
234{
235 Log (("writeToPasteboard: fFormat = %02X\n", fFormat));
236
237 /* Clear the pasteboard */
238 if (PasteboardClear (pPasteboard))
239 return VERR_NOT_SUPPORTED;
240
241 /* Make sure all is in sync */
242 PasteboardSynchronize (pPasteboard);
243
244 int rc = VERR_NOT_SUPPORTED;
245 /* Handle the unicode text */
246 if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
247 {
248 PRTUTF16 pwszSrcText = static_cast <PRTUTF16> (pv);
249 size_t cwSrc = cb / 2;
250 size_t cwDest = 0;
251 /* How long will the converted text be? */
252 rc = vboxClipboardUtf16GetLinSize (pwszSrcText, cwSrc, &cwDest);
253 if (RT_FAILURE (rc))
254 {
255 Log (("writeToPasteboard: clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Rrc. Abandoning.\n", rc));
256 AssertRCReturn (rc, rc);
257 }
258 /* Empty clipboard? Not critical */
259 if (cwDest == 0)
260 {
261 Log (("writeToPasteboard: received empty clipboard data from the guest, returning false.\n"));
262 return VINF_SUCCESS;
263 }
264 /* Allocate the necessary memory */
265 PRTUTF16 pwszDestText = static_cast <PRTUTF16> (RTMemAlloc (cwDest * 2));
266 if (pwszDestText == NULL)
267 {
268 Log (("writeToPasteboard: failed to allocate %d bytes\n", cwDest * 2));
269 return VERR_NO_MEMORY;
270 }
271 /* Convert the EOL */
272 rc = vboxClipboardUtf16WinToLin (pwszSrcText, cwSrc, pwszDestText, cwDest);
273 if (RT_FAILURE (rc))
274 {
275 Log (("writeToPasteboard: clipboard conversion failed. vboxClipboardUtf16WinToLin() returned %Rrc. Abandoning.\n", rc));
276 RTMemFree (pwszDestText);
277 AssertRCReturn (rc, rc);
278 }
279
280 CFDataRef textData = NULL;
281 /* Item id is 1. Nothing special here. */
282 PasteboardItemID itemId = (PasteboardItemID)1;
283 /* Create a CData object which we could pass to the pasteboard */
284 if ((textData = CFDataCreate (kCFAllocatorDefault,
285 reinterpret_cast<UInt8*> (pwszDestText), cwDest * 2)))
286 {
287 /* Put the Utf-16 version to the pasteboard */
288 PasteboardPutItemFlavor (pPasteboard, itemId,
289 CFSTR ("public.utf16-plain-text"),
290 textData, 0);
291 }
292 /* Create a Utf-8 version */
293 char *pszDestText;
294 rc = RTUtf16ToUtf8 (pwszDestText, &pszDestText);
295 if (RT_SUCCESS (rc))
296 {
297 /* Create a CData object which we could pass to the pasteboard */
298 if ((textData = CFDataCreate (kCFAllocatorDefault,
299 reinterpret_cast<UInt8*> (pszDestText), strlen(pszDestText))))
300 {
301 /* Put the Utf-8 version to the pasteboard */
302 PasteboardPutItemFlavor (pPasteboard, itemId,
303 CFSTR ("public.utf8-plain-text"),
304 textData, 0);
305 }
306 RTStrFree (pszDestText);
307 }
308
309 RTMemFree (pwszDestText);
310 rc = VINF_SUCCESS;
311 }
312 else
313 rc = VERR_NOT_IMPLEMENTED;
314
315 Log (("writeToPasteboard: rc = %02X\n", rc));
316 return rc;
317}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette