mirror of
https://github.com/debauchee/barrier.git
synced 2026-11-02 13:35:14 +08:00
unicode clipboard changes for win32 plus some bug fixes.
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
#define CMSWINDOWSCLIPBOARD_H
|
||||
|
||||
#include "IClipboard.h"
|
||||
#include "stdvector.h"
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
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<IMSWindowsClipboardConverter*> 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
|
||||
|
||||
131
platform/CMSWindowsClipboardAnyTextConverter.cpp
Executable file
131
platform/CMSWindowsClipboardAnyTextConverter.cpp
Executable 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;
|
||||
}
|
||||
32
platform/CMSWindowsClipboardAnyTextConverter.h
Executable file
32
platform/CMSWindowsClipboardAnyTextConverter.h
Executable 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
|
||||
34
platform/CMSWindowsClipboardTextConverter.cpp
Executable file
34
platform/CMSWindowsClipboardTextConverter.cpp
Executable 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);
|
||||
}
|
||||
21
platform/CMSWindowsClipboardTextConverter.h
Executable file
21
platform/CMSWindowsClipboardTextConverter.h
Executable 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
|
||||
34
platform/CMSWindowsClipboardUTF16Converter.cpp
Executable file
34
platform/CMSWindowsClipboardUTF16Converter.cpp
Executable 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);
|
||||
}
|
||||
21
platform/CMSWindowsClipboardUTF16Converter.h
Executable file
21
platform/CMSWindowsClipboardUTF16Converter.h
Executable 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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user