Added image/bmp and text/html support to X11.

This commit is contained in:
crs 2004-05-02 21:31:19 +00:00
parent 500362d5c0
commit 4b212ad704
10 changed files with 657 additions and 13 deletions

View File

@ -23,30 +23,44 @@
inline
static
UInt16
decode16(const UInt8* n)
decode16(const UInt8* n, bool byteSwapped)
{
union x16 {
UInt8 n8[2];
UInt16 n16;
} c;
c.n8[0] = n[0];
c.n8[1] = n[1];
if (byteSwapped) {
c.n8[0] = n[1];
c.n8[1] = n[0];
}
else {
c.n8[0] = n[0];
c.n8[1] = n[1];
}
return c.n16;
}
inline
static
UInt32
decode32(const UInt8* n)
decode32(const UInt8* n, bool byteSwapped)
{
union x32 {
UInt8 n8[4];
UInt32 n32;
} c;
c.n8[0] = n[0];
c.n8[1] = n[1];
c.n8[2] = n[2];
c.n8[3] = n[3];
if (byteSwapped) {
c.n8[0] = n[3];
c.n8[1] = n[2];
c.n8[2] = n[1];
c.n8[3] = n[0];
}
else {
c.n8[0] = n[0];
c.n8[1] = n[1];
c.n8[2] = n[2];
c.n8[3] = n[3];
}
return c.n32;
}
@ -366,9 +380,29 @@ CUnicode::doUCS2ToUTF8(const UInt8* data, UInt32 n, bool* errors)
CString dst;
dst.reserve(n);
// check if first character is 0xfffe or 0xfeff
bool byteSwapped = false;
if (n >= 1) {
switch (decode16(data, false)) {
case 0x0000feff:
data += 2;
--n;
break;
case 0x0000fffe:
byteSwapped = true;
data += 2;
--n;
break;
default:
break;
}
}
// convert each character
for (; n > 0; data += 2, --n) {
UInt32 c = decode16(data);
UInt32 c = decode16(data, byteSwapped);
toUTF8(dst, c, errors);
}
@ -382,9 +416,29 @@ CUnicode::doUCS4ToUTF8(const UInt8* data, UInt32 n, bool* errors)
CString dst;
dst.reserve(n);
// check if first character is 0xfffe or 0xfeff
bool byteSwapped = false;
if (n >= 1) {
switch (decode32(data, false)) {
case 0x0000feff:
data += 4;
--n;
break;
case 0x0000fffe:
byteSwapped = true;
data += 4;
--n;
break;
default:
break;
}
}
// convert each character
for (; n > 0; data += 4, --n) {
UInt32 c = decode32(data);
UInt32 c = decode32(data, byteSwapped);
toUTF8(dst, c, errors);
}
@ -398,9 +452,29 @@ CUnicode::doUTF16ToUTF8(const UInt8* data, UInt32 n, bool* errors)
CString dst;
dst.reserve(n);
// check if first character is 0xfffe or 0xfeff
bool byteSwapped = false;
if (n >= 1) {
switch (decode16(data, false)) {
case 0x0000feff:
data += 2;
--n;
break;
case 0x0000fffe:
byteSwapped = true;
data += 2;
--n;
break;
default:
break;
}
}
// convert each character
for (; n > 0; data += 2, --n) {
UInt32 c = decode16(data);
UInt32 c = decode16(data, byteSwapped);
if (c < 0x0000d800 || c > 0x0000dfff) {
toUTF8(dst, c, errors);
}
@ -410,7 +484,7 @@ CUnicode::doUTF16ToUTF8(const UInt8* data, UInt32 n, bool* errors)
toUTF8(dst, s_replacement, NULL);
}
else if (c >= 0x0000d800 && c <= 0x0000dbff) {
UInt32 c2 = decode16(data);
UInt32 c2 = decode16(data, byteSwapped);
data += 2;
--n;
if (c2 < 0x0000dc00 || c2 > 0x0000dfff) {
@ -440,9 +514,29 @@ CUnicode::doUTF32ToUTF8(const UInt8* data, UInt32 n, bool* errors)
CString dst;
dst.reserve(n);
// check if first character is 0xfffe or 0xfeff
bool byteSwapped = false;
if (n >= 1) {
switch (decode32(data, false)) {
case 0x0000feff:
data += 4;
--n;
break;
case 0x0000fffe:
byteSwapped = true;
data += 4;
--n;
break;
default:
break;
}
}
// convert each character
for (; n > 0; data += 4, --n) {
UInt32 c = decode32(data);
UInt32 c = decode32(data, byteSwapped);
if (c >= 0x00110000) {
setError(errors);
c = s_replacement;

View File

@ -16,6 +16,8 @@
#include "CXWindowsClipboardTextConverter.h"
#include "CXWindowsClipboardUCS2Converter.h"
#include "CXWindowsClipboardUTF8Converter.h"
#include "CXWindowsClipboardHTMLConverter.h"
#include "CXWindowsClipboardBMPConverter.h"
#include "CXWindowsUtil.h"
#include "CThread.h"
#include "CLog.h"
@ -68,6 +70,9 @@ CXWindowsClipboard::CXWindowsClipboard(Display* display,
}
// add converters, most desired first
m_converters.push_back(new CXWindowsClipboardHTMLConverter(m_display,
"text/html"));
m_converters.push_back(new CXWindowsClipboardBMPConverter(m_display));
m_converters.push_back(new CXWindowsClipboardUTF8Converter(m_display,
"text/plain;charset=UTF-8"));
m_converters.push_back(new CXWindowsClipboardUTF8Converter(m_display,

View File

@ -0,0 +1,197 @@
/*
* 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 "CXWindowsClipboardAnyBitmapConverter.h"
// BMP info header structure
struct CBMPInfoHeader {
public:
UInt32 biSize;
SInt32 biWidth;
SInt32 biHeight;
UInt16 biPlanes;
UInt16 biBitCount;
UInt32 biCompression;
UInt32 biSizeImage;
SInt32 biXPelsPerMeter;
SInt32 biYPelsPerMeter;
UInt32 biClrUsed;
UInt32 biClrImportant;
};
// BMP is little-endian
static inline
UInt16
toLE(UInt16 data)
{
union x16 {
UInt8 n8[2];
UInt16 n16;
} c;
c.n8[0] = static_cast<UInt8>(data & 0xffu);
c.n8[1] = static_cast<UInt8>((data >> 8) & 0xffu);
return c.n16;
}
static inline
SInt32
toLE(SInt32 data)
{
union x32 {
UInt8 n8[4];
SInt32 n32;
} c;
c.n8[0] = static_cast<UInt8>(data & 0xffu);
c.n8[1] = static_cast<UInt8>((data >> 8) & 0xffu);
c.n8[2] = static_cast<UInt8>((data >> 16) & 0xffu);
c.n8[3] = static_cast<UInt8>((data >> 24) & 0xffu);
return c.n32;
}
static inline
UInt32
toLE(UInt32 data)
{
union x32 {
UInt8 n8[4];
UInt32 n32;
} c;
c.n8[0] = static_cast<UInt8>(data & 0xffu);
c.n8[1] = static_cast<UInt8>((data >> 8) & 0xffu);
c.n8[2] = static_cast<UInt8>((data >> 16) & 0xffu);
c.n8[3] = static_cast<UInt8>((data >> 24) & 0xffu);
return c.n32;
}
static inline
UInt16
fromLEU16(const UInt8* data)
{
return static_cast<UInt16>(data[0]) |
(static_cast<UInt16>(data[1]) << 8);
}
static inline
SInt32
fromLES32(const UInt8* data)
{
return static_cast<SInt32>(static_cast<UInt32>(data[0]) |
(static_cast<UInt32>(data[1]) << 8) |
(static_cast<UInt32>(data[2]) << 16) |
(static_cast<UInt32>(data[3]) << 24));
}
static inline
UInt32
fromLEU32(const UInt8* data)
{
return static_cast<UInt32>(data[0]) |
(static_cast<UInt32>(data[1]) << 8) |
(static_cast<UInt32>(data[2]) << 16) |
(static_cast<UInt32>(data[3]) << 24);
}
//
// CXWindowsClipboardAnyBitmapConverter
//
CXWindowsClipboardAnyBitmapConverter::CXWindowsClipboardAnyBitmapConverter()
{
// do nothing
}
CXWindowsClipboardAnyBitmapConverter::~CXWindowsClipboardAnyBitmapConverter()
{
// do nothing
}
IClipboard::EFormat
CXWindowsClipboardAnyBitmapConverter::getFormat() const
{
return IClipboard::kBitmap;
}
int
CXWindowsClipboardAnyBitmapConverter::getDataSize() const
{
return 8;
}
CString
CXWindowsClipboardAnyBitmapConverter::fromIClipboard(const CString& bmp) const
{
// fill BMP info header with native-endian data
CBMPInfoHeader infoHeader;
const UInt8* rawBMPInfoHeader = reinterpret_cast<const UInt8*>(bmp.data());
infoHeader.biSize = fromLEU32(rawBMPInfoHeader + 0);
infoHeader.biWidth = fromLES32(rawBMPInfoHeader + 4);
infoHeader.biHeight = fromLES32(rawBMPInfoHeader + 8);
infoHeader.biPlanes = fromLEU16(rawBMPInfoHeader + 12);
infoHeader.biBitCount = fromLEU16(rawBMPInfoHeader + 14);
infoHeader.biCompression = fromLEU32(rawBMPInfoHeader + 16);
infoHeader.biSizeImage = fromLEU32(rawBMPInfoHeader + 20);
infoHeader.biXPelsPerMeter = fromLES32(rawBMPInfoHeader + 24);
infoHeader.biYPelsPerMeter = fromLES32(rawBMPInfoHeader + 28);
infoHeader.biClrUsed = fromLEU32(rawBMPInfoHeader + 32);
infoHeader.biClrImportant = fromLEU32(rawBMPInfoHeader + 36);
// check that format is acceptable
if (infoHeader.biSize != 40 ||
infoHeader.biWidth == 0 || infoHeader.biHeight == 0 ||
infoHeader.biPlanes != 0 || infoHeader.biCompression != 0 ||
(infoHeader.biBitCount != 24 && infoHeader.biBitCount != 32)) {
return CString();
}
// convert to image format
const UInt8* rawBMPPixels = rawBMPInfoHeader + 40;
if (infoHeader.biBitCount == 24) {
return doBGRFromIClipboard(rawBMPPixels,
infoHeader.biWidth, infoHeader.biHeight);
}
else {
return doBGRAFromIClipboard(rawBMPPixels,
infoHeader.biWidth, infoHeader.biHeight);
}
}
CString
CXWindowsClipboardAnyBitmapConverter::toIClipboard(const CString& image) const
{
// convert to raw BMP data
UInt32 w, h, depth;
CString rawBMP = doToIClipboard(image, w, h, depth);
if (rawBMP.empty() || w == 0 || h == 0 || (depth != 24 && depth != 32)) {
return CString();
}
// fill BMP info header with little-endian data
CBMPInfoHeader infoHeader;
infoHeader.biSize = toLE(40);
infoHeader.biWidth = toLE(w);
infoHeader.biHeight = toLE(h);
infoHeader.biPlanes = toLE(1);
infoHeader.biBitCount = toLE(depth);
infoHeader.biCompression = toLE(0); // BI_RGB
infoHeader.biSizeImage = image.size();
infoHeader.biXPelsPerMeter = toLE(2834); // 72 dpi
infoHeader.biYPelsPerMeter = toLE(2834); // 72 dpi
infoHeader.biClrUsed = toLE(0);
infoHeader.biClrImportant = toLE(0);
// construct image
return CString(reinterpret_cast<const char*>(&infoHeader),
sizeof(infoHeader)) + rawBMP;
}

View File

@ -0,0 +1,59 @@
/*
* 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.
*/
#ifndef CXWINDOWSCLIPBOARDANYBITMAPCONVERTER_H
#define CXWINDOWSCLIPBOARDANYBITMAPCONVERTER_H
#include "CXWindowsClipboard.h"
//! Convert to/from some text encoding
class CXWindowsClipboardAnyBitmapConverter :
public IXWindowsClipboardConverter {
public:
CXWindowsClipboardAnyBitmapConverter();
virtual ~CXWindowsClipboardAnyBitmapConverter();
// IXWindowsClipboardConverter overrides
virtual IClipboard::EFormat
getFormat() const;
virtual Atom getAtom() const = 0;
virtual int getDataSize() const;
virtual CString fromIClipboard(const CString&) const;
virtual CString toIClipboard(const CString&) const;
protected:
//! Convert from IClipboard format
/*!
Convert raw BGR pixel data to another image format.
*/
virtual CString doBGRFromIClipboard(const UInt8* bgrData,
UInt32 w, UInt32 h) const = 0;
//! Convert from IClipboard format
/*!
Convert raw BGRA pixel data to another image format.
*/
virtual CString doBGRAFromIClipboard(const UInt8* bgrData,
UInt32 w, UInt32 h) const = 0;
//! Convert to IClipboard format
/*!
Convert an image into raw BGR or BGRA image data and store the
width, height, and image depth (24 or 32).
*/
virtual CString doToIClipboard(const CString&,
UInt32& w, UInt32& h, UInt32& depth) const = 0;
};
#endif

View File

@ -0,0 +1,126 @@
/*
* 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 "CXWindowsClipboardBMPConverter.h"
// BMP file header structure
struct CBMPHeader {
public:
UInt16 type;
UInt32 size;
UInt16 reserved1;
UInt16 reserved2;
UInt32 offset;
};
// BMP is little-endian
static inline
UInt32
fromLEU32(const UInt8* data)
{
return static_cast<UInt32>(data[0]) |
(static_cast<UInt32>(data[1]) << 8) |
(static_cast<UInt32>(data[2]) << 16) |
(static_cast<UInt32>(data[3]) << 24);
}
static inline
UInt32
toLE(UInt32 data)
{
union x32 {
UInt8 n8[4];
UInt32 n32;
} c;
c.n8[0] = static_cast<UInt8>(data & 0xffu);
c.n8[1] = static_cast<UInt8>((data >> 8) & 0xffu);
c.n8[2] = static_cast<UInt8>((data >> 16) & 0xffu);
c.n8[3] = static_cast<UInt8>((data >> 24) & 0xffu);
return c.n32;
}
//
// CXWindowsClipboardBMPConverter
//
CXWindowsClipboardBMPConverter::CXWindowsClipboardBMPConverter(
Display* display) :
m_atom(XInternAtom(display, "image/bmp", False))
{
// do nothing
}
CXWindowsClipboardBMPConverter::~CXWindowsClipboardBMPConverter()
{
// do nothing
}
IClipboard::EFormat
CXWindowsClipboardBMPConverter::getFormat() const
{
return IClipboard::kBitmap;
}
Atom
CXWindowsClipboardBMPConverter::getAtom() const
{
return m_atom;
}
int
CXWindowsClipboardBMPConverter::getDataSize() const
{
return 8;
}
CString
CXWindowsClipboardBMPConverter::fromIClipboard(const CString& bmp) const
{
// create BMP image
CBMPHeader header;
char* type = reinterpret_cast<char*>(&header.type);
type[0] = 'B';
type[1] = 'M';
header.size = toLE(14 + bmp.size());
header.reserved1 = 0;
header.reserved2 = 0;
header.offset = toLE(14 + 40);
return CString(reinterpret_cast<const char*>(&header), 14) + bmp;
}
CString
CXWindowsClipboardBMPConverter::toIClipboard(const CString& bmp) const
{
// make sure data is big enough for a BMP file
if (bmp.size() <= 14 + 40) {
return CString();
}
// check BMP file header
const UInt8* rawBMPHeader = reinterpret_cast<const UInt8*>(bmp.data());
if (rawBMPHeader[0] != 'B' || rawBMPHeader[1] != 'M') {
return CString();
}
// get offset to image data
UInt32 offset = fromLEU32(rawBMPHeader + 10);
// construct BMP
if (offset == 14 + 40) {
return bmp.substr(14);
}
else {
return bmp.substr(14, 40) + bmp.substr(offset, bmp.size() - offset);
}
}

View File

@ -0,0 +1,39 @@
/*
* 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.
*/
#ifndef CXWINDOWSCLIPBOARDBMPCONVERTER_H
#define CXWINDOWSCLIPBOARDBMPCONVERTER_H
#include "CXWindowsClipboard.h"
//! Convert to/from some text encoding
class CXWindowsClipboardBMPConverter :
public IXWindowsClipboardConverter {
public:
CXWindowsClipboardBMPConverter(Display* display);
virtual ~CXWindowsClipboardBMPConverter();
// IXWindowsClipboardConverter overrides
virtual IClipboard::EFormat
getFormat() const;
virtual Atom getAtom() const;
virtual int getDataSize() const;
virtual CString fromIClipboard(const CString&) const;
virtual CString toIClipboard(const CString&) const;
private:
Atom m_atom;
};
#endif

View File

@ -0,0 +1,62 @@
/*
* 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 "CXWindowsClipboardHTMLConverter.h"
#include "CUnicode.h"
//
// CXWindowsClipboardHTMLConverter
//
CXWindowsClipboardHTMLConverter::CXWindowsClipboardHTMLConverter(
Display* display, const char* name) :
m_atom(XInternAtom(display, name, False))
{
// do nothing
}
CXWindowsClipboardHTMLConverter::~CXWindowsClipboardHTMLConverter()
{
// do nothing
}
IClipboard::EFormat
CXWindowsClipboardHTMLConverter::getFormat() const
{
return IClipboard::kHTML;
}
Atom
CXWindowsClipboardHTMLConverter::getAtom() const
{
return m_atom;
}
int
CXWindowsClipboardHTMLConverter::getDataSize() const
{
return 8;
}
CString
CXWindowsClipboardHTMLConverter::fromIClipboard(const CString& data) const
{
return CUnicode::UTF8ToUTF16(data);
}
CString
CXWindowsClipboardHTMLConverter::toIClipboard(const CString& data) const
{
return CUnicode::UTF16ToUTF8(data);
}

View File

@ -0,0 +1,41 @@
/*
* 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.
*/
#ifndef CXWINDOWSCLIPBOARDHTMLCONVERTER_H
#define CXWINDOWSCLIPBOARDHTMLCONVERTER_H
#include "CXWindowsClipboard.h"
//! Convert to/from HTML encoding
class CXWindowsClipboardHTMLConverter : public IXWindowsClipboardConverter {
public:
/*!
\c name is converted to an atom and that is reported by getAtom().
*/
CXWindowsClipboardHTMLConverter(Display* display, const char* name);
virtual ~CXWindowsClipboardHTMLConverter();
// IXWindowsClipboardConverter overrides
virtual IClipboard::EFormat
getFormat() const;
virtual Atom getAtom() const;
virtual int getDataSize() const;
virtual CString fromIClipboard(const CString&) const;
virtual CString toIClipboard(const CString&) const;
private:
Atom m_atom;
};
#endif

View File

@ -15,6 +15,9 @@ NULL =
XWINDOWS_SOURCE_FILES = \
CXWindowsClipboard.cpp \
CXWindowsClipboardAnyBitmapConverter.cpp\
CXWindowsClipboardBMPConverter.cpp \
CXWindowsClipboardHTMLConverter.cpp \
CXWindowsClipboardTextConverter.cpp \
CXWindowsClipboardUCS2Converter.cpp \
CXWindowsClipboardUTF8Converter.cpp \
@ -24,6 +27,9 @@ XWINDOWS_SOURCE_FILES = \
CXWindowsScreenSaver.cpp \
CXWindowsUtil.cpp \
CXWindowsClipboard.h \
CXWindowsClipboardAnyBitmapConverter.h \
CXWindowsClipboardBMPConverter.h \
CXWindowsClipboardHTMLConverter.h \
CXWindowsClipboardTextConverter.h \
CXWindowsClipboardUCS2Converter.h \
CXWindowsClipboardUTF8Converter.h \
@ -36,6 +42,8 @@ XWINDOWS_SOURCE_FILES = \
MSWINDOWS_SOURCE_FILES = \
CMSWindowsClipboard.cpp \
CMSWindowsClipboardAnyTextConverter.cpp \
CMSWindowsClipboardBitmapConverter.cpp \
CMSWindowsClipboardHTMLConverter.cpp \
CMSWindowsClipboardTextConverter.cpp \
CMSWindowsClipboardUTF16Converter.cpp \
CMSWindowsDesks.cpp \
@ -46,6 +54,8 @@ MSWINDOWS_SOURCE_FILES = \
CMSWindowsUtil.cpp \
CMSWindowsClipboard.h \
CMSWindowsClipboardAnyTextConverter.h \
CMSWindowsClipboardBitmapConverter.h \
CMSWindowsClipboardHTMLConverter.h \
CMSWindowsClipboardTextConverter.h \
CMSWindowsClipboardUTF16Converter.h \
CMSWindowsDesks.h \

View File

@ -40,6 +40,17 @@ public:
via add() and retrieved via get() must be in one of these formats.
Platform dependent clipboard subclasses can and should present any
suitable formats derivable from these formats.
\c kText is a text format encoded in UTF-8. Newlines are LF (not
CR or LF/CR).
\k kBitmap is an image format. The data is a BMP file without the
14 byte header (i.e. starting at the INFOHEADER) and with the image
data immediately following the 40 byte INFOHEADER.
\k kHTML is a text format encoded in UTF-8 and containing a valid
HTML fragment (but not necessarily a complete HTML document).
Newlines are LF.
*/
enum EFormat {
kText, //!< Text format, UTF-8, newline is LF