221 lines
4.6 KiB
C++
221 lines
4.6 KiB
C++
|
/*
|
||
|
* synergy -- mouse and keyboard sharing utility
|
||
|
* Copyright (C) 2004 Chris Schoeneman
|
||
|
*
|
||
|
* This package is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU General Public License
|
||
|
* found in the file COPYING that should have accompanied this file.
|
||
|
*
|
||
|
* This package is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*/
|
||
|
|
||
|
#include "COSXClipboard.h"
|
||
|
#include "COSXClipboardUTF16Converter.h"
|
||
|
#include "COSXClipboardTextConverter.h"
|
||
|
#include "CLog.h"
|
||
|
#include "XArch.h"
|
||
|
|
||
|
//
|
||
|
// COSXClipboard
|
||
|
//
|
||
|
|
||
|
COSXClipboard::COSXClipboard() :
|
||
|
m_time(0),
|
||
|
m_scrap(NULL)
|
||
|
{
|
||
|
m_converters.push_back(new COSXClipboardUTF16Converter);
|
||
|
m_converters.push_back(new COSXClipboardTextConverter);
|
||
|
}
|
||
|
|
||
|
COSXClipboard::~COSXClipboard()
|
||
|
{
|
||
|
clearConverters();
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
COSXClipboard::empty()
|
||
|
{
|
||
|
LOG((CLOG_DEBUG "empty clipboard"));
|
||
|
assert(m_scrap != NULL);
|
||
|
|
||
|
OSStatus err = ClearScrap(&m_scrap);
|
||
|
if (err != noErr) {
|
||
|
LOG((CLOG_DEBUG "failed to grab clipboard"));
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// we own the clipboard
|
||
|
err = PutScrapFlavor(
|
||
|
m_scrap,
|
||
|
getOwnershipFlavor(),
|
||
|
kScrapFlavorMaskNone,
|
||
|
0,
|
||
|
0);
|
||
|
if (err != noErr) {
|
||
|
LOG((CLOG_DEBUG "failed to grab clipboard"));
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
COSXClipboard::add(EFormat format, const CString & data)
|
||
|
{
|
||
|
LOG((CLOG_DEBUG "add %d bytes to clipboard format: %d", data.size(), format));
|
||
|
|
||
|
for (ConverterList::const_iterator index = m_converters.begin();
|
||
|
index != m_converters.end(); ++index) {
|
||
|
|
||
|
IOSXClipboardConverter* converter = *index;
|
||
|
|
||
|
// skip converters for other formats
|
||
|
if (converter->getFormat() == format) {
|
||
|
CString osXData = converter->fromIClipboard(data);
|
||
|
ScrapFlavorType flavorType = converter->getOSXFormat();
|
||
|
|
||
|
PutScrapFlavor(
|
||
|
m_scrap,
|
||
|
flavorType,
|
||
|
kScrapFlavorMaskNone,
|
||
|
osXData.size(),
|
||
|
osXData.data());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
COSXClipboard::open(Time time) const
|
||
|
{
|
||
|
LOG((CLOG_DEBUG "open clipboard"));
|
||
|
m_time = time;
|
||
|
OSStatus err = GetCurrentScrap(&m_scrap);
|
||
|
return (err == noErr);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
COSXClipboard::close() const
|
||
|
{
|
||
|
LOG((CLOG_DEBUG "close clipboard"));
|
||
|
m_scrap = NULL;
|
||
|
}
|
||
|
|
||
|
IClipboard::Time
|
||
|
COSXClipboard::getTime() const
|
||
|
{
|
||
|
return m_time;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
COSXClipboard::has(EFormat format) const
|
||
|
{
|
||
|
assert(m_scrap != NULL);
|
||
|
|
||
|
for (ConverterList::const_iterator index = m_converters.begin();
|
||
|
index != m_converters.end(); ++index) {
|
||
|
IOSXClipboardConverter* converter = *index;
|
||
|
if (converter->getFormat() == format) {
|
||
|
ScrapFlavorFlags flags;
|
||
|
ScrapFlavorType type = converter->getOSXFormat();
|
||
|
|
||
|
if (GetScrapFlavorFlags(m_scrap, type, &flags) == noErr) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
CString
|
||
|
COSXClipboard::get(EFormat format) const
|
||
|
{
|
||
|
CString result;
|
||
|
|
||
|
// find the converter for the first clipboard format we can handle
|
||
|
IOSXClipboardConverter* converter = NULL;
|
||
|
for (ConverterList::const_iterator index = m_converters.begin();
|
||
|
index != m_converters.end(); ++index) {
|
||
|
converter = *index;
|
||
|
|
||
|
ScrapFlavorFlags flags;
|
||
|
ScrapFlavorType type = converter->getOSXFormat();
|
||
|
|
||
|
if (converter->getFormat() == format &&
|
||
|
GetScrapFlavorFlags(m_scrap, type, &flags) == noErr) {
|
||
|
break;
|
||
|
}
|
||
|
converter = NULL;
|
||
|
}
|
||
|
|
||
|
// if no converter then we don't recognize any formats
|
||
|
if (converter == NULL) {
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
// get the clipboard data.
|
||
|
char* buffer = NULL;
|
||
|
try {
|
||
|
Size flavorSize;
|
||
|
OSStatus err = GetScrapFlavorSize(m_scrap,
|
||
|
converter->getOSXFormat(), &flavorSize);
|
||
|
if (err != noErr) {
|
||
|
throw err;
|
||
|
}
|
||
|
|
||
|
buffer = new char[flavorSize];
|
||
|
if (buffer == NULL) {
|
||
|
throw memFullErr;
|
||
|
}
|
||
|
|
||
|
err = GetScrapFlavorData(m_scrap,
|
||
|
converter->getOSXFormat(), &flavorSize, buffer);
|
||
|
if (err != noErr) {
|
||
|
throw err;
|
||
|
}
|
||
|
|
||
|
result = CString(buffer, flavorSize);
|
||
|
}
|
||
|
catch (OSStatus err) {
|
||
|
LOG((CLOG_DEBUG "exception thrown in COSXClipboard::get MacError (%d)", err));
|
||
|
}
|
||
|
catch (...) {
|
||
|
LOG((CLOG_DEBUG "unknown exception in COSXClipboard::get"));
|
||
|
RETHROW_XTHREAD
|
||
|
}
|
||
|
delete[] buffer;
|
||
|
|
||
|
return converter->toIClipboard(result);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
COSXClipboard::clearConverters()
|
||
|
{
|
||
|
for (ConverterList::iterator index = m_converters.begin();
|
||
|
index != m_converters.end(); ++index) {
|
||
|
delete *index;
|
||
|
}
|
||
|
m_converters.clear();
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
COSXClipboard::isOwnedBySynergy()
|
||
|
{
|
||
|
ScrapFlavorFlags flags;
|
||
|
ScrapRef scrap;
|
||
|
OSStatus err = GetCurrentScrap(&scrap);
|
||
|
if (err == noErr) {
|
||
|
err = GetScrapFlavorFlags(scrap, getOwnershipFlavor() , &flags);
|
||
|
}
|
||
|
return (err == noErr);
|
||
|
}
|
||
|
|
||
|
ScrapFlavorType
|
||
|
COSXClipboard::getOwnershipFlavor()
|
||
|
{
|
||
|
return 'Syne';
|
||
|
}
|