barrier/platform/CMSWindowsClipboard.cpp

218 lines
3.8 KiB
C++

#include "CMSWindowsClipboard.h"
#include "CLog.h"
//
// CMSWindowsClipboard
//
CMSWindowsClipboard::CMSWindowsClipboard(
HWND window) :
m_window(window),
m_time(0)
{
// do nothing
}
CMSWindowsClipboard::~CMSWindowsClipboard()
{
// do nothing
}
bool
CMSWindowsClipboard::empty()
{
log((CLOG_DEBUG "empty clipboard"));
if (!EmptyClipboard()) {
log((CLOG_DEBUG "failed to grab clipboard"));
return false;
}
return true;
}
void
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;
default:
win32Data = NULL;
break;
}
// put the data on the clipboard
if (win32Data != NULL) {
SetClipboardData(win32Format, win32Data);
}
}
bool
CMSWindowsClipboard::open(
Time time) const
{
log((CLOG_DEBUG "open clipboard"));
if (!OpenClipboard(m_window)) {
log((CLOG_WARN "failed to open clipboard"));
return false;
}
m_time = time;
return true;
}
void
CMSWindowsClipboard::close() const
{
log((CLOG_DEBUG "close clipboard"));
CloseClipboard();
}
IClipboard::Time
CMSWindowsClipboard::getTime() const
{
return m_time;
}
bool
CMSWindowsClipboard::has(
EFormat format) const
{
const UINT win32Format = convertFormatToWin32(format);
return (win32Format != 0 && IsClipboardFormatAvailable(win32Format) != 0);
}
CString
CMSWindowsClipboard::get(
EFormat format) const
{
// get the win32 format. return empty data if unknown format.
const UINT win32Format = convertFormatToWin32(format);
if (win32Format == 0) {
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) {
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;
}