unicode clipboard changes for win32 plus some bug fixes.

This commit is contained in:
crs 2002-07-23 15:26:40 +00:00
parent b1163aa593
commit 8ada1e8a72
12 changed files with 470 additions and 178 deletions

View File

@ -160,8 +160,8 @@ CUnicode::UTF8ToUTF16(const CString& src, bool* errors)
} }
else { else {
c -= 0x00010000; c -= 0x00010000;
UInt16 utf16h = static_cast<UInt16>(c >> 10) + 0xd800; UInt16 utf16h = static_cast<UInt16>((c >> 10) + 0xd800);
UInt16 utf16l = (static_cast<UInt16>(c) & 0x03ff) + 0xdc00; UInt16 utf16l = static_cast<UInt16>((c & 0x03ff) + 0xdc00);
dst.append(reinterpret_cast<const char*>(&utf16h), 2); dst.append(reinterpret_cast<const char*>(&utf16h), 2);
dst.append(reinterpret_cast<const char*>(&utf16l), 2); dst.append(reinterpret_cast<const char*>(&utf16l), 2);
} }
@ -206,14 +206,16 @@ CUnicode::UTF8ToText(const CString& src, bool* errors)
resetError(errors); resetError(errors);
// convert to wide char // convert to wide char
wchar_t* tmp = UTF8ToWideChar(src, errors); UInt32 size;
wchar_t* tmp = UTF8ToWideChar(src, size, errors);
// get length of multibyte string // get length of multibyte string
size_t len = 0;
char mbc[MB_LEN_MAX]; char mbc[MB_LEN_MAX];
mbstate_t state; mbstate_t state;
memset(&state, 0, sizeof(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); size_t mblen = wcrtomb(mbc, *scan, &state);
if (mblen == -1) { if (mblen == -1) {
// unconvertable character // unconvertable character
@ -237,7 +239,8 @@ CUnicode::UTF8ToText(const CString& src, bool* errors)
// convert to multibyte // convert to multibyte
char* dst = mbs; 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); size_t mblen = wcrtomb(dst, *scan, &state);
if (mblen == -1) { if (mblen == -1) {
// unconvertable character // unconvertable character
@ -312,7 +315,7 @@ CUnicode::textToUTF8(const CString& src, bool* errors)
size_t len = 0; size_t len = 0;
mbstate_t state; mbstate_t state;
memset(&state, 0, sizeof(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); size_t mblen = mbrtowc(NULL, scan, n, &state);
switch (mblen) { switch (mblen) {
case (size_t)-2: case (size_t)-2:
@ -331,6 +334,12 @@ CUnicode::textToUTF8(const CString& src, bool* errors)
n -= 1; n -= 1;
break; break;
case 0:
len += 1;
scan += 1;
n -= 1;
break;
default: default:
// normal character // normal character
len += 1; len += 1;
@ -342,12 +351,12 @@ CUnicode::textToUTF8(const CString& src, bool* errors)
memset(&state, 0, sizeof(state)); memset(&state, 0, sizeof(state));
// allocate wide character string // allocate wide character string
wchar_t* wcs = new wchar_t[len + 1]; wchar_t* wcs = new wchar_t[len];
// convert multibyte to wide char // convert multibyte to wide char
n = src.size(); n = src.size();
wchar_t* dst = wcs; 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); size_t mblen = mbrtowc(dst, scan, n, &state);
switch (mblen) { switch (mblen) {
case (size_t)-2: case (size_t)-2:
@ -359,9 +368,15 @@ CUnicode::textToUTF8(const CString& src, bool* errors)
case (size_t)-1: case (size_t)-1:
// invalid character. count one unknown character and // invalid character. count one unknown character and
// start at the next byte. // start at the next byte.
*dst = (wchar_t)0xfffd;
scan += 1;
n -= 1;
break;
case 0:
*dst = (wchar_t)0x0000;
scan += 1; scan += 1;
n -= 1; n -= 1;
*dst = (wchar_t)0xfffd;
break; break;
default: default:
@ -371,10 +386,9 @@ CUnicode::textToUTF8(const CString& src, bool* errors)
break; break;
} }
} }
*dst = L'\0';
// convert to UTF8 // convert to UTF8
CString utf8 = wideCharToUTF8(wcs, errors); CString utf8 = wideCharToUTF8(wcs, len, errors);
// clean up // clean up
delete[] wcs; delete[] wcs;
@ -383,17 +397,17 @@ CUnicode::textToUTF8(const CString& src, bool* errors)
} }
wchar_t* 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. // convert to platform's wide character encoding.
// note -- this must include a wide nul character (independent of // note -- this must include a wide nul character (independent of
// the CString's nul character). // the CString's nul character).
#if WINDOWS_LIKE #if WINDOWS_LIKE
CString tmp = UTF8ToUCS16(src); CString tmp = UTF8ToUTF16(src, errors);
UInt32 size = tmp.size() >> 1; size = tmp.size() >> 1;
#elif UNIX_LIKE #elif UNIX_LIKE
CString tmp = UTF8ToUCS4(src); CString tmp = UTF8ToUCS4(src, errors);
UInt32 size = tmp.size() >> 2; size = tmp.size() >> 2;
#endif #endif
// copy to a wchar_t array // copy to a wchar_t array
@ -403,17 +417,15 @@ CUnicode::UTF8ToWideChar(const CString& src, bool* errors)
} }
CString 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. // convert from platform's wide character encoding.
// note -- this must include a wide nul character (independent of // note -- this must include a wide nul character (independent of
// the CString's nul character). // the CString's nul character).
#if WINDOWS_LIKE #if WINDOWS_LIKE
return doUCS16ToUTF8(reinterpret_cast<const UInt8*>(src), return doUTF16ToUTF8(reinterpret_cast<const UInt8*>(src), size, errors);
wcslen(src), errors);
#elif UNIX_LIKE #elif UNIX_LIKE
return doUCS4ToUTF8(reinterpret_cast<const UInt8*>(src), return doUCS4ToUTF8(reinterpret_cast<const UInt8*>(src), size, errors);
wcslen(src), errors);
#endif #endif
} }
@ -546,12 +558,10 @@ CUnicode::fromUTF8(const UInt8*& data, UInt32& n)
size = 1; size = 1;
} }
else if (data[0] < 0xc0) { else if (data[0] < 0xc0) {
// 10xxxxxx -- in the middle of a multibyte character. skip // 10xxxxxx -- in the middle of a multibyte character. counts
// until we find a start byte and return error. // as one invalid character.
do { --n;
--n; ++data;
++data;
} while (n > 0 && (data[0] & 0xc0) == 0x80);
return s_invalid; return s_invalid;
} }
else if (data[0] < 0xe0) { else if (data[0] < 0xe0) {
@ -632,6 +642,7 @@ CUnicode::fromUTF8(const UInt8*& data, UInt32& n)
default: default:
assert(0 && "invalid size"); assert(0 && "invalid size");
return s_invalid;
} }
// check that all bytes after the first have the pattern 10xxxxxx. // 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<char*>(data), 1); dst.append(reinterpret_cast<char*>(data), 1);
} }
else if (c < 0x00000800) { else if (c < 0x00000800) {
data[0] = static_cast<UInt8>((c >> 6) & 0x0000001f) + 0xc0; data[0] = static_cast<UInt8>(((c >> 6) & 0x0000001f) + 0xc0);
data[1] = static_cast<UInt8>(c & 0x0000003f) + 0x80; data[1] = static_cast<UInt8>((c & 0x0000003f) + 0x80);
dst.append(reinterpret_cast<char*>(data), 2); dst.append(reinterpret_cast<char*>(data), 2);
} }
else if (c < 0x00010000) { else if (c < 0x00010000) {
data[0] = static_cast<UInt8>((c >> 12) & 0x0000000f) + 0xe0; data[0] = static_cast<UInt8>(((c >> 12) & 0x0000000f) + 0xe0);
data[1] = static_cast<UInt8>((c >> 6) & 0x0000003f) + 0x80; data[1] = static_cast<UInt8>(((c >> 6) & 0x0000003f) + 0x80);
data[2] = static_cast<UInt8>(c & 0x0000003f) + 0x80; data[2] = static_cast<UInt8>((c & 0x0000003f) + 0x80);
dst.append(reinterpret_cast<char*>(data), 3); dst.append(reinterpret_cast<char*>(data), 3);
} }
else if (c < 0x00200000) { else if (c < 0x00200000) {
data[0] = static_cast<UInt8>((c >> 18) & 0x00000007) + 0xf0; data[0] = static_cast<UInt8>(((c >> 18) & 0x00000007) + 0xf0);
data[1] = static_cast<UInt8>((c >> 12) & 0x0000003f) + 0x80; data[1] = static_cast<UInt8>(((c >> 12) & 0x0000003f) + 0x80);
data[2] = static_cast<UInt8>((c >> 6) & 0x0000003f) + 0x80; data[2] = static_cast<UInt8>(((c >> 6) & 0x0000003f) + 0x80);
data[3] = static_cast<UInt8>(c & 0x0000003f) + 0x80; data[3] = static_cast<UInt8>((c & 0x0000003f) + 0x80);
dst.append(reinterpret_cast<char*>(data), 4); dst.append(reinterpret_cast<char*>(data), 4);
} }
else if (c < 0x04000000) { else if (c < 0x04000000) {
data[0] = static_cast<UInt8>((c >> 24) & 0x00000003) + 0xf8; data[0] = static_cast<UInt8>(((c >> 24) & 0x00000003) + 0xf8);
data[1] = static_cast<UInt8>((c >> 18) & 0x0000003f) + 0x80; data[1] = static_cast<UInt8>(((c >> 18) & 0x0000003f) + 0x80);
data[2] = static_cast<UInt8>((c >> 12) & 0x0000003f) + 0x80; data[2] = static_cast<UInt8>(((c >> 12) & 0x0000003f) + 0x80);
data[3] = static_cast<UInt8>((c >> 6) & 0x0000003f) + 0x80; data[3] = static_cast<UInt8>(((c >> 6) & 0x0000003f) + 0x80);
data[4] = static_cast<UInt8>(c & 0x0000003f) + 0x80; data[4] = static_cast<UInt8>((c & 0x0000003f) + 0x80);
dst.append(reinterpret_cast<char*>(data), 5); dst.append(reinterpret_cast<char*>(data), 5);
} }
else if (c < 0x80000000) { else if (c < 0x80000000) {
data[0] = static_cast<UInt8>((c >> 30) & 0x00000001) + 0xfc; data[0] = static_cast<UInt8>(((c >> 30) & 0x00000001) + 0xfc);
data[1] = static_cast<UInt8>((c >> 24) & 0x0000003f) + 0x80; data[1] = static_cast<UInt8>(((c >> 24) & 0x0000003f) + 0x80);
data[2] = static_cast<UInt8>((c >> 18) & 0x0000003f) + 0x80; data[2] = static_cast<UInt8>(((c >> 18) & 0x0000003f) + 0x80);
data[3] = static_cast<UInt8>((c >> 12) & 0x0000003f) + 0x80; data[3] = static_cast<UInt8>(((c >> 12) & 0x0000003f) + 0x80);
data[4] = static_cast<UInt8>((c >> 6) & 0x0000003f) + 0x80; data[4] = static_cast<UInt8>(((c >> 6) & 0x0000003f) + 0x80);
data[5] = static_cast<UInt8>(c & 0x0000003f) + 0x80; data[5] = static_cast<UInt8>((c & 0x0000003f) + 0x80);
dst.append(reinterpret_cast<char*>(data), 6); dst.append(reinterpret_cast<char*>(data), 6);
} }
else { else {

View File

@ -15,7 +15,9 @@ public:
// not NULL then it gets true if any characters could not be // not NULL then it gets true if any characters could not be
// encoded in the target encoding and false otherwise. note // encoded in the target encoding and false otherwise. note
// that decoding errors do not set errors to error. UTF8ToText() // 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 UTF8ToUCS2(const CString&, bool* errors = NULL);
static CString UTF8ToUCS4(const CString&, bool* errors = NULL); static CString UTF8ToUCS4(const CString&, bool* errors = NULL);
static CString UTF8ToUTF16(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 // convert from some encoding to UTF-8. if errors is not NULL
// then it gets true if any characters could not be decoded and // then it gets true if any characters could not be decoded and
// false otherwise. textToUTF8() converts from the current // 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 UCS2ToUTF8(const CString&, bool* errors = NULL);
static CString UCS4ToUTF8(const CString&, bool* errors = NULL); static CString UCS4ToUTF8(const CString&, bool* errors = NULL);
static CString UTF16ToUTF8(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 // convert UTF8 to nul terminated wchar_t string (using whatever
// encoding is native to the platform). caller must delete[] // encoding is native to the platform). caller must delete[]
// the returned string. // 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 // convert nul terminated wchar_t string (in platform's native
// encoding) to UTF8. // 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 // internal conversion to UTF8
static CString doUCS2ToUTF8(const UInt8* src, UInt32 n, bool* errors); static CString doUCS2ToUTF8(const UInt8* src, UInt32 n, bool* errors);

View File

@ -103,6 +103,10 @@ SOURCE=.\CString.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\CUnicode.cpp
# End Source File
# Begin Source File
SOURCE=.\XBase.cpp SOURCE=.\XBase.cpp
# End Source File # End Source File
# End Group # End Group
@ -135,6 +139,10 @@ SOURCE=.\CString.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\CUnicode.h
# End Source File
# Begin Source File
SOURCE=.\IInterface.h SOURCE=.\IInterface.h
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@ -1,4 +1,6 @@
#include "CMSWindowsClipboard.h" #include "CMSWindowsClipboard.h"
#include "CMSWindowsClipboardTextConverter.h"
#include "CMSWindowsClipboardUTF16Converter.h"
#include "CLog.h" #include "CLog.h"
// //
@ -9,12 +11,14 @@ CMSWindowsClipboard::CMSWindowsClipboard(HWND window) :
m_window(window), m_window(window),
m_time(0) m_time(0)
{ {
// do nothing // add converters, most desired first
m_converters.push_back(new CMSWindowsClipboardUTF16Converter);
m_converters.push_back(new CMSWindowsClipboardTextConverter);
} }
CMSWindowsClipboard::~CMSWindowsClipboard() CMSWindowsClipboard::~CMSWindowsClipboard()
{ {
// do nothing clearConverters();
} }
bool 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)); log((CLOG_DEBUG "add %d bytes to clipboard format: %d", data.size(), format));
// convert data to win32 required form // convert data to win32 form
const UINT win32Format = convertFormatToWin32(format); for (ConverterList::const_iterator index = m_converters.begin();
HANDLE win32Data; index != m_converters.end(); ++index) {
switch (win32Format) { IMSWindowsClipboardConverter* converter = *index;
case CF_TEXT:
win32Data = convertTextToWin32(data);
break;
default: // skip converters for other formats
win32Data = NULL; if (converter->getFormat() == format) {
break; HANDLE win32Data = converter->fromIClipboard(data);
} if (win32Data != NULL) {
UINT win32Format = converter->getWin32Format();
// put the data on the clipboard if (SetClipboardData(win32Format, win32Data) == NULL) {
if (win32Data != NULL) { // free converted data if we couldn't put it on
SetClipboardData(win32Format, win32Data); // the clipboard
GlobalFree(win32Data);
}
}
}
} }
} }
@ -85,124 +90,58 @@ CMSWindowsClipboard::getTime() const
bool bool
CMSWindowsClipboard::has(EFormat format) const CMSWindowsClipboard::has(EFormat format) const
{ {
const UINT win32Format = convertFormatToWin32(format); for (ConverterList::const_iterator index = m_converters.begin();
return (win32Format != 0 && IsClipboardFormatAvailable(win32Format) != 0); index != m_converters.end(); ++index) {
IMSWindowsClipboardConverter* converter = *index;
if (converter->getFormat() == format) {
if (IsClipboardFormatAvailable(converter->getWin32Format())) {
return true;
}
}
}
return false;
} }
CString CString
CMSWindowsClipboard::get(EFormat format) const CMSWindowsClipboard::get(EFormat format) const
{ {
// get the win32 format. return empty data if unknown format. // find the converter for the first clipboard format we can handle
const UINT win32Format = convertFormatToWin32(format); IMSWindowsClipboardConverter* converter = NULL;
if (win32Format == 0) { 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(); return CString();
} }
// get a handle to the clipboard data and convert it // get a handle to the clipboard data
HANDLE win32Data = GetClipboardData(win32Format); HANDLE win32Data = GetClipboardData(converter->getWin32Format());
CString data; if (win32Data == NULL) {
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) {
return CString(); return CString();
} }
// ignore trailing NUL // convert
--srcSize; return converter->toIClipboard(win32Data);
}
// compute size of converted text
UInt32 dstSize = 0; void
UInt32 index; CMSWindowsClipboard::clearConverters()
for (index = 0; index < srcSize; ++index) { {
if (src[index] == '\r') { for (ConverterList::iterator index = m_converters.begin();
// skip \r index != m_converters.end(); ++index) {
if (index + 1 < srcSize && src[index + 1] == '\n') { delete *index;
++index; }
} m_converters.clear();
}
++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;
} }

View File

@ -2,9 +2,12 @@
#define CMSWINDOWSCLIPBOARD_H #define CMSWINDOWSCLIPBOARD_H
#include "IClipboard.h" #include "IClipboard.h"
#include "stdvector.h"
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
class IMSWindowsClipboardConverter;
class CMSWindowsClipboard : public IClipboard { class CMSWindowsClipboard : public IClipboard {
public: public:
CMSWindowsClipboard(HWND window); CMSWindowsClipboard(HWND window);
@ -20,13 +23,41 @@ public:
virtual CString get(EFormat) const; virtual CString get(EFormat) const;
private: private:
void clearConverters();
UINT convertFormatToWin32(EFormat) const; UINT convertFormatToWin32(EFormat) const;
HANDLE convertTextToWin32(const CString& data) const; HANDLE convertTextToWin32(const CString& data) const;
CString convertTextFromWin32(HANDLE) const; CString convertTextFromWin32(HANDLE) const;
private: private:
typedef std::vector<IMSWindowsClipboardConverter*> ConverterList;
HWND m_window; HWND m_window;
mutable Time m_time; 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 #endif

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -91,6 +91,18 @@ SOURCE=.\CMSWindowsClipboard.cpp
# End Source File # End Source File
# Begin 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 SOURCE=.\CMSWindowsScreen.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
@ -111,6 +123,18 @@ SOURCE=.\CMSWindowsClipboard.h
# End Source File # End Source File
# Begin 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 SOURCE=.\CMSWindowsScreen.h
# End Source File # End Source File
# Begin Source File # Begin Source File