From 8ada1e8a7252b6cf8666f27c03bcee8a04f38e2c Mon Sep 17 00:00:00 2001 From: crs Date: Tue, 23 Jul 2002 15:26:40 +0000 Subject: [PATCH] unicode clipboard changes for win32 plus some bug fixes. --- base/CUnicode.cpp | 107 +++++----- base/CUnicode.h | 14 +- base/base.dsp | 8 + platform/CMSWindowsClipboard.cpp | 191 ++++++------------ platform/CMSWindowsClipboard.h | 31 +++ .../CMSWindowsClipboardAnyTextConverter.cpp | 131 ++++++++++++ .../CMSWindowsClipboardAnyTextConverter.h | 32 +++ platform/CMSWindowsClipboardTextConverter.cpp | 34 ++++ platform/CMSWindowsClipboardTextConverter.h | 21 ++ .../CMSWindowsClipboardUTF16Converter.cpp | 34 ++++ platform/CMSWindowsClipboardUTF16Converter.h | 21 ++ platform/platform.dsp | 24 +++ 12 files changed, 470 insertions(+), 178 deletions(-) create mode 100755 platform/CMSWindowsClipboardAnyTextConverter.cpp create mode 100755 platform/CMSWindowsClipboardAnyTextConverter.h create mode 100755 platform/CMSWindowsClipboardTextConverter.cpp create mode 100755 platform/CMSWindowsClipboardTextConverter.h create mode 100755 platform/CMSWindowsClipboardUTF16Converter.cpp create mode 100755 platform/CMSWindowsClipboardUTF16Converter.h diff --git a/base/CUnicode.cpp b/base/CUnicode.cpp index f36a82d7..183499cf 100644 --- a/base/CUnicode.cpp +++ b/base/CUnicode.cpp @@ -160,8 +160,8 @@ CUnicode::UTF8ToUTF16(const CString& src, bool* errors) } else { c -= 0x00010000; - UInt16 utf16h = static_cast(c >> 10) + 0xd800; - UInt16 utf16l = (static_cast(c) & 0x03ff) + 0xdc00; + UInt16 utf16h = static_cast((c >> 10) + 0xd800); + UInt16 utf16l = static_cast((c & 0x03ff) + 0xdc00); dst.append(reinterpret_cast(&utf16h), 2); dst.append(reinterpret_cast(&utf16l), 2); } @@ -206,14 +206,16 @@ CUnicode::UTF8ToText(const CString& src, bool* errors) resetError(errors); // convert to wide char - wchar_t* tmp = UTF8ToWideChar(src, errors); + UInt32 size; + wchar_t* tmp = UTF8ToWideChar(src, size, errors); // get length of multibyte string - size_t len = 0; char mbc[MB_LEN_MAX]; mbstate_t state; memset(&state, 0, sizeof(state)); - for (const wchar_t* scan = tmp; *scan != 0; ++scan) { + size_t len = 0; + UInt32 n = size; + for (const wchar_t* scan = tmp; n > 0; ++scan, --n) { size_t mblen = wcrtomb(mbc, *scan, &state); if (mblen == -1) { // unconvertable character @@ -237,7 +239,8 @@ CUnicode::UTF8ToText(const CString& src, bool* errors) // convert to multibyte char* dst = mbs; - for (const wchar_t* scan = tmp; *scan != 0; ++scan) { + n = size; + for (const wchar_t* scan = tmp; n > 0; ++scan, --n) { size_t mblen = wcrtomb(dst, *scan, &state); if (mblen == -1) { // unconvertable character @@ -312,7 +315,7 @@ CUnicode::textToUTF8(const CString& src, bool* errors) size_t len = 0; mbstate_t state; memset(&state, 0, sizeof(state)); - for (const char* scan = src.c_str(); n > 0 && *scan != 0; ) { + for (const char* scan = src.c_str(); n > 0; ) { size_t mblen = mbrtowc(NULL, scan, n, &state); switch (mblen) { case (size_t)-2: @@ -331,6 +334,12 @@ CUnicode::textToUTF8(const CString& src, bool* errors) n -= 1; break; + case 0: + len += 1; + scan += 1; + n -= 1; + break; + default: // normal character len += 1; @@ -342,12 +351,12 @@ CUnicode::textToUTF8(const CString& src, bool* errors) memset(&state, 0, sizeof(state)); // allocate wide character string - wchar_t* wcs = new wchar_t[len + 1]; + wchar_t* wcs = new wchar_t[len]; // convert multibyte to wide char n = src.size(); wchar_t* dst = wcs; - for (const char* scan = src.c_str(); n > 0 && *scan != 0; ++dst) { + for (const char* scan = src.c_str(); n > 0; ++dst) { size_t mblen = mbrtowc(dst, scan, n, &state); switch (mblen) { case (size_t)-2: @@ -359,9 +368,15 @@ CUnicode::textToUTF8(const CString& src, bool* errors) case (size_t)-1: // invalid character. count one unknown character and // start at the next byte. + *dst = (wchar_t)0xfffd; + scan += 1; + n -= 1; + break; + + case 0: + *dst = (wchar_t)0x0000; scan += 1; n -= 1; - *dst = (wchar_t)0xfffd; break; default: @@ -371,10 +386,9 @@ CUnicode::textToUTF8(const CString& src, bool* errors) break; } } - *dst = L'\0'; // convert to UTF8 - CString utf8 = wideCharToUTF8(wcs, errors); + CString utf8 = wideCharToUTF8(wcs, len, errors); // clean up delete[] wcs; @@ -383,17 +397,17 @@ CUnicode::textToUTF8(const CString& src, bool* errors) } wchar_t* -CUnicode::UTF8ToWideChar(const CString& src, bool* errors) +CUnicode::UTF8ToWideChar(const CString& src, UInt32& size, bool* errors) { // convert to platform's wide character encoding. // note -- this must include a wide nul character (independent of // the CString's nul character). #if WINDOWS_LIKE - CString tmp = UTF8ToUCS16(src); - UInt32 size = tmp.size() >> 1; + CString tmp = UTF8ToUTF16(src, errors); + size = tmp.size() >> 1; #elif UNIX_LIKE - CString tmp = UTF8ToUCS4(src); - UInt32 size = tmp.size() >> 2; + CString tmp = UTF8ToUCS4(src, errors); + size = tmp.size() >> 2; #endif // copy to a wchar_t array @@ -403,17 +417,15 @@ CUnicode::UTF8ToWideChar(const CString& src, bool* errors) } CString -CUnicode::wideCharToUTF8(const wchar_t* src, bool* errors) +CUnicode::wideCharToUTF8(const wchar_t* src, UInt32 size, bool* errors) { // convert from platform's wide character encoding. // note -- this must include a wide nul character (independent of // the CString's nul character). #if WINDOWS_LIKE - return doUCS16ToUTF8(reinterpret_cast(src), - wcslen(src), errors); + return doUTF16ToUTF8(reinterpret_cast(src), size, errors); #elif UNIX_LIKE - return doUCS4ToUTF8(reinterpret_cast(src), - wcslen(src), errors); + return doUCS4ToUTF8(reinterpret_cast(src), size, errors); #endif } @@ -546,12 +558,10 @@ CUnicode::fromUTF8(const UInt8*& data, UInt32& n) size = 1; } else if (data[0] < 0xc0) { - // 10xxxxxx -- in the middle of a multibyte character. skip - // until we find a start byte and return error. - do { - --n; - ++data; - } while (n > 0 && (data[0] & 0xc0) == 0x80); + // 10xxxxxx -- in the middle of a multibyte character. counts + // as one invalid character. + --n; + ++data; return s_invalid; } else if (data[0] < 0xe0) { @@ -632,6 +642,7 @@ CUnicode::fromUTF8(const UInt8*& data, UInt32& n) default: assert(0 && "invalid size"); + return s_invalid; } // check that all bytes after the first have the pattern 10xxxxxx. @@ -724,38 +735,38 @@ CUnicode::toUTF8(CString& dst, UInt32 c, bool* errors) dst.append(reinterpret_cast(data), 1); } else if (c < 0x00000800) { - data[0] = static_cast((c >> 6) & 0x0000001f) + 0xc0; - data[1] = static_cast(c & 0x0000003f) + 0x80; + data[0] = static_cast(((c >> 6) & 0x0000001f) + 0xc0); + data[1] = static_cast((c & 0x0000003f) + 0x80); dst.append(reinterpret_cast(data), 2); } else if (c < 0x00010000) { - data[0] = static_cast((c >> 12) & 0x0000000f) + 0xe0; - data[1] = static_cast((c >> 6) & 0x0000003f) + 0x80; - data[2] = static_cast(c & 0x0000003f) + 0x80; + data[0] = static_cast(((c >> 12) & 0x0000000f) + 0xe0); + data[1] = static_cast(((c >> 6) & 0x0000003f) + 0x80); + data[2] = static_cast((c & 0x0000003f) + 0x80); dst.append(reinterpret_cast(data), 3); } else if (c < 0x00200000) { - data[0] = static_cast((c >> 18) & 0x00000007) + 0xf0; - data[1] = static_cast((c >> 12) & 0x0000003f) + 0x80; - data[2] = static_cast((c >> 6) & 0x0000003f) + 0x80; - data[3] = static_cast(c & 0x0000003f) + 0x80; + data[0] = static_cast(((c >> 18) & 0x00000007) + 0xf0); + data[1] = static_cast(((c >> 12) & 0x0000003f) + 0x80); + data[2] = static_cast(((c >> 6) & 0x0000003f) + 0x80); + data[3] = static_cast((c & 0x0000003f) + 0x80); dst.append(reinterpret_cast(data), 4); } else if (c < 0x04000000) { - data[0] = static_cast((c >> 24) & 0x00000003) + 0xf8; - data[1] = static_cast((c >> 18) & 0x0000003f) + 0x80; - data[2] = static_cast((c >> 12) & 0x0000003f) + 0x80; - data[3] = static_cast((c >> 6) & 0x0000003f) + 0x80; - data[4] = static_cast(c & 0x0000003f) + 0x80; + data[0] = static_cast(((c >> 24) & 0x00000003) + 0xf8); + data[1] = static_cast(((c >> 18) & 0x0000003f) + 0x80); + data[2] = static_cast(((c >> 12) & 0x0000003f) + 0x80); + data[3] = static_cast(((c >> 6) & 0x0000003f) + 0x80); + data[4] = static_cast((c & 0x0000003f) + 0x80); dst.append(reinterpret_cast(data), 5); } else if (c < 0x80000000) { - data[0] = static_cast((c >> 30) & 0x00000001) + 0xfc; - data[1] = static_cast((c >> 24) & 0x0000003f) + 0x80; - data[2] = static_cast((c >> 18) & 0x0000003f) + 0x80; - data[3] = static_cast((c >> 12) & 0x0000003f) + 0x80; - data[4] = static_cast((c >> 6) & 0x0000003f) + 0x80; - data[5] = static_cast(c & 0x0000003f) + 0x80; + data[0] = static_cast(((c >> 30) & 0x00000001) + 0xfc); + data[1] = static_cast(((c >> 24) & 0x0000003f) + 0x80); + data[2] = static_cast(((c >> 18) & 0x0000003f) + 0x80); + data[3] = static_cast(((c >> 12) & 0x0000003f) + 0x80); + data[4] = static_cast(((c >> 6) & 0x0000003f) + 0x80); + data[5] = static_cast((c & 0x0000003f) + 0x80); dst.append(reinterpret_cast(data), 6); } else { diff --git a/base/CUnicode.h b/base/CUnicode.h index 2676e086..89d67235 100644 --- a/base/CUnicode.h +++ b/base/CUnicode.h @@ -15,7 +15,9 @@ public: // not NULL then it gets true if any characters could not be // encoded in the target encoding and false otherwise. note // that decoding errors do not set errors to error. UTF8ToText() - // converts to the current locale's (multibyte) encoding. + // converts to the current locale's (multibyte) encoding. all of + // these methods include the nul terminator in the returned + // string (independent of the CString's own nul terminator). static CString UTF8ToUCS2(const CString&, bool* errors = NULL); static CString UTF8ToUCS4(const CString&, bool* errors = NULL); static CString UTF8ToUTF16(const CString&, bool* errors = NULL); @@ -25,7 +27,9 @@ public: // convert from some encoding to UTF-8. if errors is not NULL // then it gets true if any characters could not be decoded and // false otherwise. textToUTF8() converts from the current - // locale's (multibyte) encoding. + // locale's (multibyte) encoding. all of these methods strip + // a terminating nul so the returned UTF-8 string uses the + // CString's own nul terminator for termination. static CString UCS2ToUTF8(const CString&, bool* errors = NULL); static CString UCS4ToUTF8(const CString&, bool* errors = NULL); static CString UTF16ToUTF8(const CString&, bool* errors = NULL); @@ -36,11 +40,13 @@ private: // convert UTF8 to nul terminated wchar_t string (using whatever // encoding is native to the platform). caller must delete[] // the returned string. - static wchar_t* UTF8ToWideChar(const CString&, bool* errors); + static wchar_t* UTF8ToWideChar(const CString&, + UInt32& size, bool* errors); // convert nul terminated wchar_t string (in platform's native // encoding) to UTF8. - static CString wideCharToUTF8(const wchar_t*, bool* errors); + static CString wideCharToUTF8(const wchar_t*, + UInt32 size, bool* errors); // internal conversion to UTF8 static CString doUCS2ToUTF8(const UInt8* src, UInt32 n, bool* errors); diff --git a/base/base.dsp b/base/base.dsp index b3495e9e..e55fdedc 100644 --- a/base/base.dsp +++ b/base/base.dsp @@ -103,6 +103,10 @@ SOURCE=.\CString.cpp # End Source File # Begin Source File +SOURCE=.\CUnicode.cpp +# End Source File +# Begin Source File + SOURCE=.\XBase.cpp # End Source File # End Group @@ -135,6 +139,10 @@ SOURCE=.\CString.h # End Source File # Begin Source File +SOURCE=.\CUnicode.h +# End Source File +# Begin Source File + SOURCE=.\IInterface.h # End Source File # Begin Source File diff --git a/platform/CMSWindowsClipboard.cpp b/platform/CMSWindowsClipboard.cpp index 8a1029cd..7cefd466 100644 --- a/platform/CMSWindowsClipboard.cpp +++ b/platform/CMSWindowsClipboard.cpp @@ -1,4 +1,6 @@ #include "CMSWindowsClipboard.h" +#include "CMSWindowsClipboardTextConverter.h" +#include "CMSWindowsClipboardUTF16Converter.h" #include "CLog.h" // @@ -9,12 +11,14 @@ CMSWindowsClipboard::CMSWindowsClipboard(HWND window) : m_window(window), m_time(0) { - // do nothing + // add converters, most desired first + m_converters.push_back(new CMSWindowsClipboardUTF16Converter); + m_converters.push_back(new CMSWindowsClipboardTextConverter); } CMSWindowsClipboard::~CMSWindowsClipboard() { - // do nothing + clearConverters(); } bool @@ -35,22 +39,23 @@ CMSWindowsClipboard::add(EFormat format, const CString& data) { log((CLOG_DEBUG "add %d bytes to clipboard format: %d", data.size(), format)); - // convert data to win32 required form - const UINT win32Format = convertFormatToWin32(format); - HANDLE win32Data; - switch (win32Format) { - case CF_TEXT: - win32Data = convertTextToWin32(data); - break; + // convert data to win32 form + for (ConverterList::const_iterator index = m_converters.begin(); + index != m_converters.end(); ++index) { + IMSWindowsClipboardConverter* converter = *index; - default: - win32Data = NULL; - break; - } - - // put the data on the clipboard - if (win32Data != NULL) { - SetClipboardData(win32Format, win32Data); + // skip converters for other formats + if (converter->getFormat() == format) { + HANDLE win32Data = converter->fromIClipboard(data); + if (win32Data != NULL) { + UINT win32Format = converter->getWin32Format(); + if (SetClipboardData(win32Format, win32Data) == NULL) { + // free converted data if we couldn't put it on + // the clipboard + GlobalFree(win32Data); + } + } + } } } @@ -85,124 +90,58 @@ CMSWindowsClipboard::getTime() const bool CMSWindowsClipboard::has(EFormat format) const { - const UINT win32Format = convertFormatToWin32(format); - return (win32Format != 0 && IsClipboardFormatAvailable(win32Format) != 0); + for (ConverterList::const_iterator index = m_converters.begin(); + index != m_converters.end(); ++index) { + IMSWindowsClipboardConverter* converter = *index; + if (converter->getFormat() == format) { + if (IsClipboardFormatAvailable(converter->getWin32Format())) { + return true; + } + } + } + return false; } CString CMSWindowsClipboard::get(EFormat format) const { - // get the win32 format. return empty data if unknown format. - const UINT win32Format = convertFormatToWin32(format); - if (win32Format == 0) { + // find the converter for the first clipboard format we can handle + IMSWindowsClipboardConverter* converter = NULL; + UINT win32Format = EnumClipboardFormats(0); + while (win32Format != 0) { + for (ConverterList::const_iterator index = m_converters.begin(); + index != m_converters.end(); ++index) { + converter = *index; + if (converter->getWin32Format() == win32Format && + converter->getFormat() == format) { + break; + } + converter = NULL; + } + win32Format = EnumClipboardFormats(win32Format); + } + + // if no converter then we don't recognize any formats + if (converter == NULL) { return CString(); } - // get a handle to the clipboard data and convert it - HANDLE win32Data = GetClipboardData(win32Format); - CString data; - if (win32Data != NULL) { - // convert the data - switch (win32Format) { - case CF_TEXT: - data = convertTextFromWin32(win32Data); - } - } - - return data; -} - -UINT -CMSWindowsClipboard::convertFormatToWin32(EFormat format) const -{ - switch (format) { - case kText: - return CF_TEXT; - - default: - return 0; - } -} - -HANDLE -CMSWindowsClipboard::convertTextToWin32(const CString& data) const -{ - // compute size of converted text - UInt32 dstSize = 1; - const UInt32 srcSize = data.size(); - const char* src = data.c_str(); - for (UInt32 index = 0; index < srcSize; ++index) { - if (src[index] == '\n') { - // add \r - ++dstSize; - } - ++dstSize; - } - - // allocate - HGLOBAL gData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, dstSize); - if (gData != NULL) { - // get a pointer to the allocated memory - char* dst = (char*)GlobalLock(gData); - if (dst != NULL) { - // convert text. we change LF to CRLF. - dstSize = 0; - for (UInt32 index = 0; index < srcSize; ++index) { - if (src[index] == '\n') { - // add \r - dst[dstSize++] = '\r'; - } - dst[dstSize++] = src[index]; - } - dst[dstSize] = '\0'; - - // done converting - GlobalUnlock(gData); - } - } - return gData; -} - -CString -CMSWindowsClipboard::convertTextFromWin32(HANDLE handle) const -{ - // get source data and it's size - const char* src = (const char*)GlobalLock(handle); - UInt32 srcSize = (SInt32)GlobalSize(handle); - if (src == NULL || srcSize <= 1) { + // get a handle to the clipboard data + HANDLE win32Data = GetClipboardData(converter->getWin32Format()); + if (win32Data == NULL) { return CString(); } - // ignore trailing NUL - --srcSize; - - // compute size of converted text - UInt32 dstSize = 0; - UInt32 index; - for (index = 0; index < srcSize; ++index) { - if (src[index] == '\r') { - // skip \r - if (index + 1 < srcSize && src[index + 1] == '\n') { - ++index; - } - } - ++dstSize; - } - - // allocate - CString data; - data.reserve(dstSize); - - // convert text. we change CRLF to LF. - for (index = 0; index < srcSize; ++index) { - if (src[index] == '\r') { - // skip \r - if (index + 1 < srcSize && src[index + 1] == '\n') { - ++index; - } - } - data += src[index]; - } - - return data; + // convert + return converter->toIClipboard(win32Data); +} + +void +CMSWindowsClipboard::clearConverters() +{ + for (ConverterList::iterator index = m_converters.begin(); + index != m_converters.end(); ++index) { + delete *index; + } + m_converters.clear(); } diff --git a/platform/CMSWindowsClipboard.h b/platform/CMSWindowsClipboard.h index 6179ee30..fa253c1e 100644 --- a/platform/CMSWindowsClipboard.h +++ b/platform/CMSWindowsClipboard.h @@ -2,9 +2,12 @@ #define CMSWINDOWSCLIPBOARD_H #include "IClipboard.h" +#include "stdvector.h" #define WIN32_LEAN_AND_MEAN #include +class IMSWindowsClipboardConverter; + class CMSWindowsClipboard : public IClipboard { public: CMSWindowsClipboard(HWND window); @@ -20,13 +23,41 @@ public: virtual CString get(EFormat) const; private: + void clearConverters(); + UINT convertFormatToWin32(EFormat) const; HANDLE convertTextToWin32(const CString& data) const; CString convertTextFromWin32(HANDLE) const; private: + typedef std::vector ConverterList; + HWND m_window; mutable Time m_time; + ConverterList m_converters; +}; + +class IMSWindowsClipboardConverter : public IInterface { +public: + // accessors + + // return the clipboard format this object converts from/to + virtual IClipboard::EFormat + getFormat() const = 0; + + // return the atom representing the win32 clipboard format that + // this object converts from/to + virtual UINT getWin32Format() const = 0; + + // convert from the IClipboard format to the win32 clipboard format. + // the input data must be in the IClipboard format returned by + // getFormat(). the return data will be in the win32 clipboard + // format returned by getWin32Format(), allocated by GlobalAlloc(). + virtual HANDLE fromIClipboard(const CString&) const = 0; + + // convert from the win32 clipboard format to the IClipboard format + // (i.e., the reverse of fromIClipboard()). + virtual CString toIClipboard(HANDLE data) const = 0; }; #endif diff --git a/platform/CMSWindowsClipboardAnyTextConverter.cpp b/platform/CMSWindowsClipboardAnyTextConverter.cpp new file mode 100755 index 00000000..66035da5 --- /dev/null +++ b/platform/CMSWindowsClipboardAnyTextConverter.cpp @@ -0,0 +1,131 @@ +#include "CMSWindowsClipboardAnyTextConverter.h" + +// +// CMSWindowsClipboardAnyTextConverter +// + +CMSWindowsClipboardAnyTextConverter::CMSWindowsClipboardAnyTextConverter() +{ + // do nothing +} + +CMSWindowsClipboardAnyTextConverter::~CMSWindowsClipboardAnyTextConverter() +{ + // do nothing +} + +IClipboard::EFormat +CMSWindowsClipboardAnyTextConverter::getFormat() const +{ + return IClipboard::kText; +} + +HANDLE +CMSWindowsClipboardAnyTextConverter::fromIClipboard(const CString& data) const +{ + // convert linefeeds and then convert to desired encoding + CString text = doFromIClipboard(convertLinefeedToWin32(data)); + UInt32 size = text.size(); + + // copy to memory handle + HGLOBAL gData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, size); + if (gData != NULL) { + // get a pointer to the allocated memory + char* dst = (char*)GlobalLock(gData); + if (dst != NULL) { + memcpy(dst, text.data(), size); + GlobalUnlock(gData); + } + else { + GlobalFree(gData); + gData = NULL; + } + } + + return gData; +} + +CString +CMSWindowsClipboardAnyTextConverter::toIClipboard(HANDLE data) const +{ + // get datator + const char* src = (const char*)GlobalLock(data); + UInt32 srcSize = (UInt32)GlobalSize(data); + if (src == NULL || srcSize <= 1) { + return CString(); + } + + // convert text + CString text = doToIClipboard(CString(src, srcSize)); + + // release handle + GlobalUnlock(data); + + // convert newlines + return convertLinefeedToUnix(text); +} + +CString +CMSWindowsClipboardAnyTextConverter::convertLinefeedToWin32( + const CString& src) const +{ + // note -- we assume src is a valid UTF-8 string + + // count newlines in string + UInt32 numNewlines = 0; + UInt32 n = src.size(); + for (const char* scan = src.c_str(); n > 0; ++scan, --n) { + if (*scan == '\n') { + ++numNewlines; + } + } + if (numNewlines == 0) { + return src; + } + + // allocate new string + CString dst; + dst.reserve(src.size() + numNewlines); + + // copy string, converting newlines + n = src.size(); + for (const char* scan = src.c_str(); n > 0; ++scan, --n) { + if (scan[0] == '\n') { + dst += '\r'; + } + dst += scan[0]; + } + + return dst; +} + +CString +CMSWindowsClipboardAnyTextConverter::convertLinefeedToUnix( + const CString& src) const +{ + // count newlines in string + UInt32 numNewlines = 0; + UInt32 n = src.size(); + for (const char* scan = src.c_str(); n > 0; ++scan, --n) { + if (scan[0] == '\r' && scan[1] == '\n') { + ++numNewlines; + } + } + if (numNewlines == 0) { + return src; + } + + // allocate new string + CString dst; + dst.reserve(src.size()); + + // copy string, converting newlines + n = src.size(); + for (const char* scan = src.c_str(); n > 0; ++scan, --n) { + if (scan[0] != '\r' || scan[1] != '\n') { + dst += scan[0]; + } + } + + return dst; +} diff --git a/platform/CMSWindowsClipboardAnyTextConverter.h b/platform/CMSWindowsClipboardAnyTextConverter.h new file mode 100755 index 00000000..497702f0 --- /dev/null +++ b/platform/CMSWindowsClipboardAnyTextConverter.h @@ -0,0 +1,32 @@ +#ifndef CMSWINDOWSCLIPBOARDANYTEXTCONVERTER_H +#define CMSWINDOWSCLIPBOARDANYTEXTCONVERTER_H + +#include "CMSWindowsClipboard.h" + +class CMSWindowsClipboardAnyTextConverter : + public IMSWindowsClipboardConverter { +public: + CMSWindowsClipboardAnyTextConverter(); + virtual ~CMSWindowsClipboardAnyTextConverter(); + + // IMSWindowsClipboardConverter overrides + virtual IClipboard::EFormat + getFormat() const; + virtual UINT getWin32Format() const = 0; + virtual HANDLE fromIClipboard(const CString&) const; + virtual CString toIClipboard(HANDLE) const; + +protected: + // do UTF-8 conversion only. memory handle allocation and + // linefeed conversion is done by this class. doFromIClipboard() + // must include the nul terminator in the returned string (not + // including the CString's nul terminator). + virtual CString doFromIClipboard(const CString&) const = 0; + virtual CString doToIClipboard(const CString&) const = 0; + +private: + CString convertLinefeedToWin32(const CString&) const; + CString convertLinefeedToUnix(const CString&) const; +}; + +#endif diff --git a/platform/CMSWindowsClipboardTextConverter.cpp b/platform/CMSWindowsClipboardTextConverter.cpp new file mode 100755 index 00000000..195d88a1 --- /dev/null +++ b/platform/CMSWindowsClipboardTextConverter.cpp @@ -0,0 +1,34 @@ +#include "CMSWindowsClipboardTextConverter.h" +#include "CUnicode.h" + +// +// CMSWindowsClipboardTextConverter +// + +CMSWindowsClipboardTextConverter::CMSWindowsClipboardTextConverter() +{ + // do nothing +} + +CMSWindowsClipboardTextConverter::~CMSWindowsClipboardTextConverter() +{ + // do nothing +} + +UINT +CMSWindowsClipboardTextConverter::getWin32Format() const +{ + return CF_TEXT; +} + +CString +CMSWindowsClipboardTextConverter::doFromIClipboard(const CString& data) const +{ + return CUnicode::UTF8ToText(data); +} + +CString +CMSWindowsClipboardTextConverter::doToIClipboard(const CString& data) const +{ + return CUnicode::textToUTF8(data); +} diff --git a/platform/CMSWindowsClipboardTextConverter.h b/platform/CMSWindowsClipboardTextConverter.h new file mode 100755 index 00000000..7edab3e5 --- /dev/null +++ b/platform/CMSWindowsClipboardTextConverter.h @@ -0,0 +1,21 @@ +#ifndef CMSWINDOWSCLIPBOARDTEXTCONVERTER_H +#define CMSWINDOWSCLIPBOARDTEXTCONVERTER_H + +#include "CMSWindowsClipboardAnyTextConverter.h" + +class CMSWindowsClipboardTextConverter : + public CMSWindowsClipboardAnyTextConverter { +public: + CMSWindowsClipboardTextConverter(); + virtual ~CMSWindowsClipboardTextConverter(); + + // IMSWindowsClipboardConverter overrides + virtual UINT getWin32Format() const; + +protected: + // CMSWindowsClipboardAnyTextConverter overrides + virtual CString doFromIClipboard(const CString&) const; + virtual CString doToIClipboard(const CString&) const; +}; + +#endif diff --git a/platform/CMSWindowsClipboardUTF16Converter.cpp b/platform/CMSWindowsClipboardUTF16Converter.cpp new file mode 100755 index 00000000..3c9da906 --- /dev/null +++ b/platform/CMSWindowsClipboardUTF16Converter.cpp @@ -0,0 +1,34 @@ +#include "CMSWindowsClipboardUTF16Converter.h" +#include "CUnicode.h" + +// +// CMSWindowsClipboardUTF16Converter +// + +CMSWindowsClipboardUTF16Converter::CMSWindowsClipboardUTF16Converter() +{ + // do nothing +} + +CMSWindowsClipboardUTF16Converter::~CMSWindowsClipboardUTF16Converter() +{ + // do nothing +} + +UINT +CMSWindowsClipboardUTF16Converter::getWin32Format() const +{ + return CF_UNICODETEXT; +} + +CString +CMSWindowsClipboardUTF16Converter::doFromIClipboard(const CString& data) const +{ + return CUnicode::UTF8ToUTF16(data); +} + +CString +CMSWindowsClipboardUTF16Converter::doToIClipboard(const CString& data) const +{ + return CUnicode::UTF16ToUTF8(data); +} diff --git a/platform/CMSWindowsClipboardUTF16Converter.h b/platform/CMSWindowsClipboardUTF16Converter.h new file mode 100755 index 00000000..6ccaa3f8 --- /dev/null +++ b/platform/CMSWindowsClipboardUTF16Converter.h @@ -0,0 +1,21 @@ +#ifndef CMSWINDOWSCLIPBOARDUTF16CONVERTER_H +#define CMSWINDOWSCLIPBOARDUTF16CONVERTER_H + +#include "CMSWindowsClipboardAnyTextConverter.h" + +class CMSWindowsClipboardUTF16Converter : + public CMSWindowsClipboardAnyTextConverter { +public: + CMSWindowsClipboardUTF16Converter(); + virtual ~CMSWindowsClipboardUTF16Converter(); + + // IMSWindowsClipboardConverter overrides + virtual UINT getWin32Format() const; + +protected: + // CMSWindowsClipboardAnyTextConverter overrides + virtual CString doFromIClipboard(const CString&) const; + virtual CString doToIClipboard(const CString&) const; +}; + +#endif diff --git a/platform/platform.dsp b/platform/platform.dsp index ad92fece..080d4de2 100644 --- a/platform/platform.dsp +++ b/platform/platform.dsp @@ -91,6 +91,18 @@ SOURCE=.\CMSWindowsClipboard.cpp # End Source File # Begin Source File +SOURCE=.\CMSWindowsClipboardAnyTextConverter.cpp +# End Source File +# Begin Source File + +SOURCE=.\CMSWindowsClipboardTextConverter.cpp +# End Source File +# Begin Source File + +SOURCE=.\CMSWindowsClipboardUTF16Converter.cpp +# End Source File +# Begin Source File + SOURCE=.\CMSWindowsScreen.cpp # End Source File # Begin Source File @@ -111,6 +123,18 @@ SOURCE=.\CMSWindowsClipboard.h # End Source File # Begin Source File +SOURCE=.\CMSWindowsClipboardAnyTextConverter.h +# End Source File +# Begin Source File + +SOURCE=.\CMSWindowsClipboardTextConverter.h +# End Source File +# Begin Source File + +SOURCE=.\CMSWindowsClipboardUTF16Converter.h +# End Source File +# Begin Source File + SOURCE=.\CMSWindowsScreen.h # End Source File # Begin Source File