VirtualBox

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

Last change on this file since 7165 was 7162, checked in by vboxsync, 17 years ago

r=bird: some missing docs, fixed incorrect cleanup order and made cleanup a little bit faster (user sem, not sleep).

  • Property eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 10.0 KB
Line 
1/* $Id: darwin-pasteboard.cpp 7162 2008-02-27 02:28:43Z vboxsync $ */
2/** @file
3 * Shared Clipboard: Mac OS X host implementation.
4 */
5
6/*
7 * Copyright (C) 2008 innotek GmbH
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
18/// @todo: same as defined in VBoxClipboardSvc.h
19/// @todo r-bird: why don't you include it?
20#define VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT 0x01
21#define VBOX_SHARED_CLIPBOARD_FMT_BITMAP 0x02
22#define VBOX_SHARED_CLIPBOARD_FMT_HTML 0x04
23
24#include <Carbon/Carbon.h>
25
26#include <iprt/mem.h>
27#include <iprt/assert.h>
28#include "iprt/err.h"
29
30#define LOG_GROUP LOG_GROUP_HGCM
31#include "VBox/log.h"
32#include "clipboard-helper.h"
33
34//#define SHOW_CLIPBOARD_CONTENT
35
36/** @todo r=bird: document these functions */
37
38int initPasteboard (PasteboardRef *pPasteboardRef)
39{
40 int rc = VINF_SUCCESS;
41
42 if (PasteboardCreate (kPasteboardClipboard, pPasteboardRef))
43 rc = VERR_NOT_SUPPORTED;
44
45 return rc;
46}
47
48void destroyPasteboard (PasteboardRef *pPasteboardRef)
49{
50 CFRelease (*pPasteboardRef);
51 *pPasteboardRef = NULL;
52}
53
54int queryPasteboardFormats (PasteboardRef pPasteboard, uint32_t *pfFormats)
55{
56 Log (("queryPasteboardFormats\n"));
57
58 OSStatus err = noErr;
59
60 PasteboardSyncFlags syncFlags;
61 /* Make sure all is in sync */
62 syncFlags = PasteboardSynchronize (pPasteboard);
63 /* If nothing changed return */
64 if (!(syncFlags & kPasteboardModified))
65 return VINF_SUCCESS;
66
67 /* Are some items in the pasteboard? */
68 ItemCount itemCount;
69 err = PasteboardGetItemCount (pPasteboard, &itemCount);
70 if (itemCount < 1)
71 return VINF_SUCCESS;
72
73 /* The id of the first element in the pastboard */
74 int rc = VERR_NOT_SUPPORTED;
75 PasteboardItemID itemID;
76 if (!(err = PasteboardGetItemIdentifier (pPasteboard, 1, &itemID)))
77 {
78 /* Retrieve all flavors in the pasteboard, maybe there
79 * is something we can use. */
80 CFArrayRef flavorTypeArray;
81 if (!(err = PasteboardCopyItemFlavors (pPasteboard, itemID, &flavorTypeArray)))
82 {
83 CFIndex flavorCount;
84 flavorCount = CFArrayGetCount (flavorTypeArray);
85 for (CFIndex flavorIndex = 0; flavorIndex < flavorCount; flavorIndex++)
86 {
87 CFStringRef flavorType;
88 flavorType = static_cast <CFStringRef> (CFArrayGetValueAtIndex (flavorTypeArray,
89 flavorIndex));
90 /* Currently only unicode supported */
91 if (UTTypeConformsTo (flavorType, CFSTR ("public.utf8-plain-text")) ||
92 UTTypeConformsTo (flavorType, CFSTR ("public.utf16-plain-text")))
93 {
94 Log (("Unicode flavor detected.\n"));
95 *pfFormats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
96 }
97 }
98 rc = VINF_SUCCESS;
99 CFRelease (flavorTypeArray);
100 }
101 }
102
103 Log (("queryPasteboardFormats: rc = %02X\n", rc));
104 return rc;
105}
106
107int readFromPasteboard (PasteboardRef pPasteboard, uint32_t fFormat, void *pv, uint32_t cb, uint32_t *pcbActual)
108{
109 Log (("readFromPastboard: fFormat = %02X\n", fFormat));
110
111 OSStatus err = noErr;
112
113 /* Make sure all is in sync */
114 PasteboardSynchronize (pPasteboard);
115
116 /* Are some items in the pasteboard? */
117 ItemCount itemCount;
118 err = PasteboardGetItemCount (pPasteboard, &itemCount);
119 if (itemCount < 1)
120 return VINF_SUCCESS;
121
122 /* The id of the first element in the pastboard */
123 int rc = VERR_NOT_SUPPORTED;
124 PasteboardItemID itemID;
125 if (!(err = PasteboardGetItemIdentifier (pPasteboard, 1, &itemID)))
126 {
127 /* The guest request unicode */
128 if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
129 {
130 CFDataRef outData;
131 PRTUTF16 pwszTmp = NULL;
132 /* Utf-16 is currently broken on more than one line.
133 * Has to be investigated. */
134#if 0
135 /* Try utf-16 first */
136 if (!(err = PasteboardCopyItemFlavorData (pPasteboard, itemID, CFSTR ("public.utf16-plain-text"), &outData)))
137 {
138 Log (("Clipboard content is utf-16\n"));
139 rc = RTUtf16DupEx (&pwszTmp, (PRTUTF16)CFDataGetBytePtr (outData), 0);
140 }
141 /* Second try is utf-8 */
142 else
143#endif
144 if (!(err = PasteboardCopyItemFlavorData (pPasteboard, itemID, CFSTR ("public.utf8-plain-text"), &outData)))
145 {
146 Log (("readFromPastboard: clipboard content is utf-8\n"));
147 rc = RTStrToUtf16 ((const char*)CFDataGetBytePtr (outData), &pwszTmp);
148 }
149 if (pwszTmp)
150 {
151 /* Check how much longer will the converted text will be. */
152 size_t cwSrc = RTUtf16Len (pwszTmp);
153 size_t cwDest;
154 rc = vboxClipboardUtf16GetWinSize (pwszTmp, cwSrc, &cwDest);
155 if (RT_FAILURE (rc))
156 {
157 RTUtf16Free (pwszTmp);
158 Log (("readFromPastboard: clipboard conversion failed. vboxClipboardUtf16GetWinSize returned %Vrc. Abandoning.\n", rc));
159 AssertRCReturn (rc, rc);
160 }
161 /* Set the actually needed data size */
162 *pcbActual = cwDest * 2;
163 /* Return success state */
164 rc = VINF_SUCCESS;
165 /* Do not copy data if the dst buffer is not big enough. */
166 if (*pcbActual <= cb)
167 {
168 rc = vboxClipboardUtf16LinToWin (pwszTmp, RTUtf16Len (pwszTmp), static_cast <PRTUTF16> (pv), cb / 2);
169 if (RT_FAILURE (rc))
170 {
171 RTUtf16Free (pwszTmp);
172 Log (("readFromPastboard: clipboard conversion failed. vboxClipboardUtf16LinToWin() returned %Vrc. Abandoning.\n", rc));
173 AssertRCReturn (rc, rc);
174 }
175#ifdef SHOW_CLIPBOARD_CONTENT
176 Log (("readFromPastboard: clipboard content: %ls\n", static_cast <PRTUTF16> (pv)));
177#endif
178 }
179 /* Free the temp string */
180 RTUtf16Free (pwszTmp);
181 }
182 }
183 }
184
185 Log (("readFromPastboard: rc = %02X\n", rc));
186 return rc;
187}
188
189int writeToPasteboard (PasteboardRef pPasteboard, void *pv, uint32_t cb, uint32_t fFormat)
190{
191 Log (("writeToPasteboard: fFormat = %02X\n", fFormat));
192
193 /* Clear the pastboard */
194 if (PasteboardClear (pPasteboard))
195 return VERR_NOT_SUPPORTED;
196
197 /* Make sure all is in sync */
198 PasteboardSynchronize (pPasteboard);
199
200 int rc = VERR_NOT_SUPPORTED;
201 /* Handle the unicode text */
202 if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
203 {
204 PRTUTF16 pwszSrcText = static_cast <PRTUTF16> (pv);
205 size_t cwSrc = cb / 2;
206 size_t cwDest = 0;
207 /* How long will the converted text be? */
208 rc = vboxClipboardUtf16GetLinSize (pwszSrcText, cwSrc, &cwDest);
209 if (RT_FAILURE (rc))
210 {
211 Log (("writeToPasteboard: clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Vrc. Abandoning.\n", rc));
212 AssertRCReturn (rc, rc);
213 }
214 /* Empty clipboard? Not critical */
215 if (cwDest == 0)
216 {
217 Log (("writeToPasteboard: received empty clipboard data from the guest, returning false.\n"));
218 return VINF_SUCCESS;
219 }
220 /* Allocate the necessary memory */
221 PRTUTF16 pwszDestText = static_cast <PRTUTF16> (RTMemAlloc (cwDest * 2));
222 if (pwszDestText == NULL)
223 {
224 Log (("writeToPasteboard: failed to allocate %d bytes\n", cwDest * 2));
225 return VERR_NO_MEMORY;
226 }
227 /* Convert the EOL */
228 rc = vboxClipboardUtf16WinToLin (pwszSrcText, cwSrc, pwszDestText, cwDest);
229 if (RT_FAILURE (rc))
230 {
231 Log (("writeToPasteboard: clipboard conversion failed. vboxClipboardUtf16WinToLin() returned %Vrc. Abandoning.\n", rc));
232 RTMemFree (pwszDestText);
233 AssertRCReturn (rc, rc);
234 }
235
236 CFDataRef textData = NULL;
237 /* Item id is 1. Nothing special here. */
238 PasteboardItemID itemId = (PasteboardItemID)1;
239 /* Create a CData object which we could pass to the pasteboard */
240 if ((textData = CFDataCreate (kCFAllocatorDefault,
241 reinterpret_cast<UInt8*> (pwszDestText), cwDest * 2)))
242 {
243 /* Put the Utf-16 version to the pasteboard */
244 PasteboardPutItemFlavor (pPasteboard, itemId,
245 CFSTR ("public.utf16-plain-text"),
246 textData, 0);
247 }
248 /* Create a Utf-8 version */
249 char *pszDestText;
250 rc = RTUtf16ToUtf8 (pwszDestText, &pszDestText);
251 if (RT_SUCCESS (rc))
252 {
253 /* Create a CData object which we could pass to the pasteboard */
254 if ((textData = CFDataCreate (kCFAllocatorDefault,
255 reinterpret_cast<UInt8*> (pszDestText), RTUtf16CalcUtf8Len (pwszDestText)))) /** @todo r=bird: why not strlen(pszDestText)? */
256 {
257 /* Put the Utf-8 version to the pasteboard */
258 PasteboardPutItemFlavor (pPasteboard, itemId,
259 CFSTR ("public.utf8-plain-text"),
260 textData, 0);
261 }
262 RTStrFree (pszDestText);
263 }
264
265 RTMemFree (pwszDestText);
266 rc = VINF_SUCCESS;
267 }
268 else
269 rc = VERR_NOT_IMPLEMENTED;
270
271 Log (("writeToPasteboard: rc = %02X\n", rc));
272 return rc;
273}
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