VirtualBox

source: vbox/trunk/src/VBox/GuestHost/SharedClipboard/clipboard-helper.cpp@ 41160

Last change on this file since 41160 was 41083, checked in by vboxsync, 13 years ago

GA: Bitmap clipboard support (darwin). Thanks to François Revol (mmu_man).

  • Property eol-style set to native
  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 10.6 KB
Line 
1/* $Id: clipboard-helper.cpp 41083 2012-04-27 12:14:34Z vboxsync $ */
2/** @file
3 * Shared Clipboard: Some helper function for converting between the various eol.
4 */
5
6/*
7 * Copyright (C) 2006-2008 Oracle Corporation
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#include <iprt/alloc.h>
19#include <iprt/assert.h>
20#include <VBox/log.h>
21#include <VBox/GuestHost/clipboard-helper.h>
22
23/** @todo use const where appropriate; delinuxify the code (*Lin* -> *Host*); use AssertLogRel*. */
24
25int vboxClipboardUtf16GetWinSize(PRTUTF16 pwszSrc, size_t cwSrc, size_t *pcwDest)
26{
27 size_t cwDest, i;
28
29 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc));
30 AssertLogRelMsgReturn(pwszSrc != NULL, ("vboxClipboardUtf16GetWinSize: received a null Utf16 string, returning VERR_INVALID_PARAMETER\n"), VERR_INVALID_PARAMETER);
31 if (cwSrc == 0)
32 {
33 *pcwDest = 0;
34 LogFlowFunc(("empty source string, returning\n"));
35 return VINF_SUCCESS;
36 }
37/** @todo convert the remainder of the Assert stuff to AssertLogRel. */
38 /* We only take little endian Utf16 */
39 if (pwszSrc[0] == UTF16BEMARKER)
40 {
41 LogRel(("vboxClipboardUtf16GetWinSize: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
42 AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
43 }
44 cwDest = 0;
45 /* Calculate the size of the destination text string. */
46 /* Is this Utf16 or Utf16-LE? */
47 for (i = (pwszSrc[0] == UTF16LEMARKER ? 1 : 0); i < cwSrc; ++i, ++cwDest)
48 {
49 /* Check for a single line feed */
50 if (pwszSrc[i] == LINEFEED)
51 ++cwDest;
52#ifdef RT_OS_DARWIN
53 /* Check for a single carriage return (MacOS) */
54 if (pwszSrc[i] == CARRIAGERETURN)
55 ++cwDest;
56#endif
57 if (pwszSrc[i] == 0)
58 {
59 /* Don't count this, as we do so below. */
60 break;
61 }
62 }
63 /* Count the terminating null byte. */
64 ++cwDest;
65 LogFlowFunc(("returning VINF_SUCCESS, %d 16bit words\n", cwDest));
66 *pcwDest = cwDest;
67 return VINF_SUCCESS;
68}
69
70int vboxClipboardUtf16LinToWin(PRTUTF16 pwszSrc, size_t cwSrc, PRTUTF16 pu16Dest,
71 size_t cwDest)
72{
73 size_t i, j;
74 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc));
75 if (!VALID_PTR(pwszSrc) || !VALID_PTR(pu16Dest))
76 {
77 LogRel(("vboxClipboardUtf16LinToWin: received an invalid pointer, pwszSrc=%p, pu16Dest=%p, returning VERR_INVALID_PARAMETER\n", pwszSrc, pu16Dest));
78 AssertReturn(VALID_PTR(pwszSrc) && VALID_PTR(pu16Dest), VERR_INVALID_PARAMETER);
79 }
80 if (cwSrc == 0)
81 {
82 if (cwDest == 0)
83 {
84 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
85 return VERR_BUFFER_OVERFLOW;
86 }
87 pu16Dest[0] = 0;
88 LogFlowFunc(("empty source string, returning\n"));
89 return VINF_SUCCESS;
90 }
91 /* We only take little endian Utf16 */
92 if (pwszSrc[0] == UTF16BEMARKER)
93 {
94 LogRel(("vboxClipboardUtf16LinToWin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
95 AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
96 }
97 /* Don't copy the endian marker. */
98 for (i = (pwszSrc[0] == UTF16LEMARKER ? 1 : 0), j = 0; i < cwSrc; ++i, ++j)
99 {
100 /* Don't copy the null byte, as we add it below. */
101 if (pwszSrc[i] == 0)
102 break;
103 if (j == cwDest)
104 {
105 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
106 return VERR_BUFFER_OVERFLOW;
107 }
108 if (pwszSrc[i] == LINEFEED)
109 {
110 pu16Dest[j] = CARRIAGERETURN;
111 ++j;
112 if (j == cwDest)
113 {
114 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
115 return VERR_BUFFER_OVERFLOW;
116 }
117 }
118#ifdef RT_OS_DARWIN
119 /* Check for a single carriage return (MacOS) */
120 else if (pwszSrc[i] == CARRIAGERETURN)
121 {
122 /* set cr */
123 pu16Dest[j] = CARRIAGERETURN;
124 ++j;
125 if (j == cwDest)
126 {
127 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
128 return VERR_BUFFER_OVERFLOW;
129 }
130 /* add the lf */
131 pu16Dest[j] = LINEFEED;
132 continue;
133 }
134#endif
135 pu16Dest[j] = pwszSrc[i];
136 }
137 /* Add the trailing null. */
138 if (j == cwDest)
139 {
140 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
141 return VERR_BUFFER_OVERFLOW;
142 }
143 pu16Dest[j] = 0;
144 LogFlowFunc(("rc=VINF_SUCCESS, pu16Dest=%ls\n", pu16Dest));
145 return VINF_SUCCESS;
146}
147
148int vboxClipboardUtf16GetLinSize(PRTUTF16 pwszSrc, size_t cwSrc, size_t *pcwDest)
149{
150 size_t cwDest;
151
152 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc));
153 if (!VALID_PTR(pwszSrc))
154 {
155 LogRel(("vboxClipboardUtf16GetLinSize: received an invalid Utf16 string %p. Returning VERR_INVALID_PARAMETER.\n", pwszSrc));
156 AssertReturn(VALID_PTR(pwszSrc), VERR_INVALID_PARAMETER);
157 }
158 if (cwSrc == 0)
159 {
160 LogFlowFunc(("empty source string, returning VINF_SUCCESS\n"));
161 *pcwDest = 0;
162 return VINF_SUCCESS;
163 }
164 /* We only take little endian Utf16 */
165 if (pwszSrc[0] == UTF16BEMARKER)
166 {
167 LogRel(("vboxClipboardUtf16GetLinSize: received a big endian Utf16 string. Returning VERR_INVALID_PARAMETER.\n"));
168 AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
169 }
170 /* Calculate the size of the destination text string. */
171 /* Is this Utf16 or Utf16-LE? */
172 if (pwszSrc[0] == UTF16LEMARKER)
173 cwDest = 0;
174 else
175 cwDest = 1;
176 for (size_t i = 0; i < cwSrc; ++i, ++cwDest)
177 {
178 if ( (i + 1 < cwSrc)
179 && (pwszSrc[i] == CARRIAGERETURN)
180 && (pwszSrc[i + 1] == LINEFEED))
181 {
182 ++i;
183 }
184 if (pwszSrc[i] == 0)
185 {
186 break;
187 }
188 }
189 /* Terminating zero */
190 ++cwDest;
191 LogFlowFunc(("returning %d\n", cwDest));
192 *pcwDest = cwDest;
193 return VINF_SUCCESS;
194}
195
196int vboxClipboardUtf16WinToLin(PRTUTF16 pwszSrc, size_t cwSrc, PRTUTF16 pu16Dest,
197 size_t cwDest)
198{
199 size_t cwDestPos;
200
201 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u, pu16Dest=%p, cwDest=%u\n",
202 cwSrc, pwszSrc, cwSrc, pu16Dest, cwDest));
203 /* A buffer of size 0 may not be an error, but it is not a good idea either. */
204 Assert(cwDest > 0);
205 if (!VALID_PTR(pwszSrc) || !VALID_PTR(pu16Dest))
206 {
207 LogRel(("vboxClipboardUtf16WinToLin: received an invalid ptr, pwszSrc=%p, pu16Dest=%p, returning VERR_INVALID_PARAMETER\n", pwszSrc, pu16Dest));
208 AssertReturn(VALID_PTR(pwszSrc) && VALID_PTR(pu16Dest), VERR_INVALID_PARAMETER);
209 }
210 /* We only take little endian Utf16 */
211 if (pwszSrc[0] == UTF16BEMARKER)
212 {
213 LogRel(("vboxClipboardUtf16WinToLin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
214 AssertMsgFailedReturn(("received a big endian string\n"), VERR_INVALID_PARAMETER);
215 }
216 if (cwDest == 0)
217 {
218 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
219 return VERR_BUFFER_OVERFLOW;
220 }
221 if (cwSrc == 0)
222 {
223 pu16Dest[0] = 0;
224 LogFlowFunc(("received empty string. Returning VINF_SUCCESS\n"));
225 return VINF_SUCCESS;
226 }
227 /* Prepend the Utf16 byte order marker if it is missing. */
228 if (pwszSrc[0] == UTF16LEMARKER)
229 {
230 cwDestPos = 0;
231 }
232 else
233 {
234 pu16Dest[0] = UTF16LEMARKER;
235 cwDestPos = 1;
236 }
237 for (size_t i = 0; i < cwSrc; ++i, ++cwDestPos)
238 {
239 if (pwszSrc[i] == 0)
240 {
241 break;
242 }
243 if (cwDestPos == cwDest)
244 {
245 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
246 return VERR_BUFFER_OVERFLOW;
247 }
248 if ( (i + 1 < cwSrc)
249 && (pwszSrc[i] == CARRIAGERETURN)
250 && (pwszSrc[i + 1] == LINEFEED))
251 {
252 ++i;
253 }
254 pu16Dest[cwDestPos] = pwszSrc[i];
255 }
256 /* Terminating zero */
257 if (cwDestPos == cwDest)
258 {
259 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
260 return VERR_BUFFER_OVERFLOW;
261 }
262 pu16Dest[cwDestPos] = 0;
263 LogFlowFunc(("set string %ls. Returning\n", pu16Dest + 1));
264 return VINF_SUCCESS;
265}
266
267int vboxClipboardDibToBmp(const void *pSrc, size_t cbSrc, void **ppDest, size_t *pcbDest)
268{
269 size_t cb = sizeof(BMFILEHEADER) + cbSrc;
270 PBMFILEHEADER pFileHeader;
271 void *dest;
272 size_t pixelOffset;
273
274 PBMINFOHEADER pBitmapInfoHeader = (PBMINFOHEADER)pSrc;
275 if (cbSrc < sizeof(BMINFOHEADER) ||
276 RT_LE2H_U32(pBitmapInfoHeader->u32Size) < sizeof(BMINFOHEADER) ||
277 /** @todo Support all the many versions of the DIB headers. */
278 RT_LE2H_U32(pBitmapInfoHeader->u32Size) != sizeof(BMINFOHEADER))
279 {
280 Log (("vboxClipboardDibToBmp: invalid or unsupported bitmap data.\n"));
281 return VERR_INVALID_PARAMETER;
282 }
283 pixelOffset = sizeof(BMFILEHEADER)
284 + RT_LE2H_U32(pBitmapInfoHeader->u32Size)
285 + RT_LE2H_U32(pBitmapInfoHeader->u32ClrUsed) * sizeof(uint32_t);
286 if (cbSrc < pixelOffset)
287 {
288 Log (("vboxClipboardDibToBmp: invalid bitmap data.\n"));
289 return VERR_INVALID_PARAMETER;
290 }
291
292 dest = RTMemAlloc(cb);
293 if (dest == NULL)
294 {
295 Log (("writeToPasteboard: cannot allocate memory for bitmap.\n"));
296 return VERR_NO_MEMORY;
297 }
298
299 pFileHeader = (PBMFILEHEADER)dest;
300 pFileHeader->u16Type = BITMAPHEADERMAGIC;
301 pFileHeader->u32Size = RT_H2LE_U32(cb);
302 pFileHeader->u16Reserved1 = pFileHeader->u16Reserved2 = 0;
303 pFileHeader->u32OffBits = RT_H2LE_U32(pixelOffset);
304 memcpy((uint8_t *)dest + sizeof(BMFILEHEADER), pSrc, cbSrc);
305 *ppDest = dest;
306 *pcbDest = cb;
307 return VINF_SUCCESS;
308}
309
310int vboxClipboardBmpGetDib(const void *pSrc, size_t cbSrc, const void **pDest, size_t *pcbDest)
311{
312 PBMFILEHEADER pFileHeader = (PBMFILEHEADER)pSrc;
313
314 if (pFileHeader == NULL || cbSrc < sizeof(BMFILEHEADER) ||
315 pFileHeader->u16Type != BITMAPHEADERMAGIC ||
316 RT_LE2H_U32(pFileHeader->u32Size) != cbSrc)
317 {
318 Log (("vboxClipboardBmpGetDib: invalid bitmap data.\n"));
319 return VERR_INVALID_PARAMETER;
320 }
321 *pDest = ((uint8_t *)pSrc) + sizeof(BMFILEHEADER);
322 *pcbDest = cbSrc - sizeof(BMFILEHEADER);
323 return VINF_SUCCESS;
324}
325
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