/* $Id: clipboard-helper.cpp 33540 2010-10-28 09:27:05Z vboxsync $ */ /** @file * Shared Clipboard: Some helper function for converting between the various eol. */ /* * Copyright (C) 2006-2008 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. */ #include #include #include /** @todo use const where appropriate; delinuxify the code (*Lin* -> *Host*); use AssertLogRel*. */ int vboxClipboardUtf16GetWinSize(PRTUTF16 pwszSrc, size_t cwSrc, size_t *pcwDest) { size_t cwDest, i; LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc)); AssertLogRelMsgReturn(pwszSrc != NULL, ("vboxClipboardUtf16GetWinSize: received a null Utf16 string, returning VERR_INVALID_PARAMETER\n"), VERR_INVALID_PARAMETER); if (cwSrc == 0) { *pcwDest = 0; LogFlowFunc(("empty source string, returning\n")); return VINF_SUCCESS; } /** @todo convert the remainder of the Assert stuff to AssertLogRel. */ /* We only take little endian Utf16 */ if (pwszSrc[0] == UTF16BEMARKER) { LogRel(("vboxClipboardUtf16GetWinSize: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n")); AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER); } cwDest = 0; /* Calculate the size of the destination text string. */ /* Is this Utf16 or Utf16-LE? */ for (i = (pwszSrc[0] == UTF16LEMARKER ? 1 : 0); i < cwSrc; ++i, ++cwDest) { /* Check for a single line feed */ if (pwszSrc[i] == LINEFEED) ++cwDest; #ifdef RT_OS_DARWIN /* Check for a single carriage return (MacOS) */ if (pwszSrc[i] == CARRIAGERETURN) ++cwDest; #endif if (pwszSrc[i] == 0) { /* Don't count this, as we do so below. */ break; } } /* Count the terminating null byte. */ ++cwDest; LogFlowFunc(("returning VINF_SUCCESS, %d 16bit words\n", cwDest)); *pcwDest = cwDest; return VINF_SUCCESS; } int vboxClipboardUtf16LinToWin(PRTUTF16 pwszSrc, size_t cwSrc, PRTUTF16 pu16Dest, size_t cwDest) { size_t i, j; LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc)); if (!VALID_PTR(pwszSrc) || !VALID_PTR(pu16Dest)) { LogRel(("vboxClipboardUtf16LinToWin: received an invalid pointer, pwszSrc=%p, pu16Dest=%p, returning VERR_INVALID_PARAMETER\n", pwszSrc, pu16Dest)); AssertReturn(VALID_PTR(pwszSrc) && VALID_PTR(pu16Dest), VERR_INVALID_PARAMETER); } if (cwSrc == 0) { if (cwDest == 0) { LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n")); return VERR_BUFFER_OVERFLOW; } pu16Dest[0] = 0; LogFlowFunc(("empty source string, returning\n")); return VINF_SUCCESS; } /* We only take little endian Utf16 */ if (pwszSrc[0] == UTF16BEMARKER) { LogRel(("vboxClipboardUtf16LinToWin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n")); AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER); } /* Don't copy the endian marker. */ for (i = (pwszSrc[0] == UTF16LEMARKER ? 1 : 0), j = 0; i < cwSrc; ++i, ++j) { /* Don't copy the null byte, as we add it below. */ if (pwszSrc[i] == 0) break; if (j == cwDest) { LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n")); return VERR_BUFFER_OVERFLOW; } if (pwszSrc[i] == LINEFEED) { pu16Dest[j] = CARRIAGERETURN; ++j; if (j == cwDest) { LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n")); return VERR_BUFFER_OVERFLOW; } } #ifdef RT_OS_DARWIN /* Check for a single carriage return (MacOS) */ else if (pwszSrc[i] == CARRIAGERETURN) { /* set cr */ pu16Dest[j] = CARRIAGERETURN; ++j; if (j == cwDest) { LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n")); return VERR_BUFFER_OVERFLOW; } /* add the lf */ pu16Dest[j] = LINEFEED; continue; } #endif pu16Dest[j] = pwszSrc[i]; } /* Add the trailing null. */ if (j == cwDest) { LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n")); return VERR_BUFFER_OVERFLOW; } pu16Dest[j] = 0; LogFlowFunc(("rc=VINF_SUCCESS, pu16Dest=%ls\n", pu16Dest)); return VINF_SUCCESS; } int vboxClipboardUtf16GetLinSize(PRTUTF16 pwszSrc, size_t cwSrc, size_t *pcwDest) { size_t cwDest; LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc)); if (!VALID_PTR(pwszSrc)) { LogRel(("vboxClipboardUtf16GetLinSize: received an invalid Utf16 string %p. Returning VERR_INVALID_PARAMETER.\n", pwszSrc)); AssertReturn(VALID_PTR(pwszSrc), VERR_INVALID_PARAMETER); } if (cwSrc == 0) { LogFlowFunc(("empty source string, returning VINF_SUCCESS\n")); *pcwDest = 0; return VINF_SUCCESS; } /* We only take little endian Utf16 */ if (pwszSrc[0] == UTF16BEMARKER) { LogRel(("vboxClipboardUtf16GetLinSize: received a big endian Utf16 string. Returning VERR_INVALID_PARAMETER.\n")); AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER); } /* Calculate the size of the destination text string. */ /* Is this Utf16 or Utf16-LE? */ if (pwszSrc[0] == UTF16LEMARKER) cwDest = 0; else cwDest = 1; for (size_t i = 0; i < cwSrc; ++i, ++cwDest) { if ( (i + 1 < cwSrc) && (pwszSrc[i] == CARRIAGERETURN) && (pwszSrc[i + 1] == LINEFEED)) { ++i; } if (pwszSrc[i] == 0) { break; } } /* Terminating zero */ ++cwDest; LogFlowFunc(("returning %d\n", cwDest)); *pcwDest = cwDest; return VINF_SUCCESS; } int vboxClipboardUtf16WinToLin(PRTUTF16 pwszSrc, size_t cwSrc, PRTUTF16 pu16Dest, size_t cwDest) { size_t cwDestPos; LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u, pu16Dest=%p, cwDest=%u\n", cwSrc, pwszSrc, cwSrc, pu16Dest, cwDest)); /* A buffer of size 0 may not be an error, but it is not a good idea either. */ Assert(cwDest > 0); if (!VALID_PTR(pwszSrc) || !VALID_PTR(pu16Dest)) { LogRel(("vboxClipboardUtf16WinToLin: received an invalid ptr, pwszSrc=%p, pu16Dest=%p, returning VERR_INVALID_PARAMETER\n", pwszSrc, pu16Dest)); AssertReturn(VALID_PTR(pwszSrc) && VALID_PTR(pu16Dest), VERR_INVALID_PARAMETER); } /* We only take little endian Utf16 */ if (pwszSrc[0] == UTF16BEMARKER) { LogRel(("vboxClipboardUtf16WinToLin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n")); AssertMsgFailedReturn(("received a big endian string\n"), VERR_INVALID_PARAMETER); } if (cwDest == 0) { LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n")); return VERR_BUFFER_OVERFLOW; } if (cwSrc == 0) { pu16Dest[0] = 0; LogFlowFunc(("received empty string. Returning VINF_SUCCESS\n")); return VINF_SUCCESS; } /* Prepend the Utf16 byte order marker if it is missing. */ if (pwszSrc[0] == UTF16LEMARKER) { cwDestPos = 0; } else { pu16Dest[0] = UTF16LEMARKER; cwDestPos = 1; } for (size_t i = 0; i < cwSrc; ++i, ++cwDestPos) { if (pwszSrc[i] == 0) { break; } if (cwDestPos == cwDest) { LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n")); return VERR_BUFFER_OVERFLOW; } if ( (i + 1 < cwSrc) && (pwszSrc[i] == CARRIAGERETURN) && (pwszSrc[i + 1] == LINEFEED)) { ++i; } pu16Dest[cwDestPos] = pwszSrc[i]; } /* Terminating zero */ if (cwDestPos == cwDest) { LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n")); return VERR_BUFFER_OVERFLOW; } pu16Dest[cwDestPos] = 0; LogFlowFunc(("set string %ls. Returning\n", pu16Dest + 1)); return VINF_SUCCESS; }