From d84e5a26be7d634ba274870351dd7da0021e47bf Mon Sep 17 00:00:00 2001 From: crs Date: Sun, 2 May 2004 08:04:48 +0000 Subject: [PATCH] Added win32 clipboard support for images and HTML. Still need X11 support. --- lib/platform/CMSWindowsClipboard.cpp | 4 + .../CMSWindowsClipboardBitmapConverter.cpp | 146 ++++++++++++++++++ .../CMSWindowsClipboardBitmapConverter.h | 35 +++++ .../CMSWindowsClipboardHTMLConverter.cpp | 107 +++++++++++++ .../CMSWindowsClipboardHTMLConverter.h | 44 ++++++ lib/platform/platform.dsp | 16 ++ lib/server/server.dsp | 8 + lib/synergy/IClipboard.h | 2 + 8 files changed, 362 insertions(+) create mode 100644 lib/platform/CMSWindowsClipboardBitmapConverter.cpp create mode 100644 lib/platform/CMSWindowsClipboardBitmapConverter.h create mode 100644 lib/platform/CMSWindowsClipboardHTMLConverter.cpp create mode 100644 lib/platform/CMSWindowsClipboardHTMLConverter.h diff --git a/lib/platform/CMSWindowsClipboard.cpp b/lib/platform/CMSWindowsClipboard.cpp index 5f4c7675..7df9db9f 100644 --- a/lib/platform/CMSWindowsClipboard.cpp +++ b/lib/platform/CMSWindowsClipboard.cpp @@ -15,6 +15,8 @@ #include "CMSWindowsClipboard.h" #include "CMSWindowsClipboardTextConverter.h" #include "CMSWindowsClipboardUTF16Converter.h" +#include "CMSWindowsClipboardBitmapConverter.h" +#include "CMSWindowsClipboardHTMLConverter.h" #include "CLog.h" #include "CArchMiscWindows.h" @@ -35,6 +37,8 @@ CMSWindowsClipboard::CMSWindowsClipboard(HWND window) : // let it do so to avoid text encoding issues. m_converters.push_back(new CMSWindowsClipboardTextConverter); } + m_converters.push_back(new CMSWindowsClipboardBitmapConverter); + m_converters.push_back(new CMSWindowsClipboardHTMLConverter); } CMSWindowsClipboard::~CMSWindowsClipboard() diff --git a/lib/platform/CMSWindowsClipboardBitmapConverter.cpp b/lib/platform/CMSWindowsClipboardBitmapConverter.cpp new file mode 100644 index 00000000..a17c66cf --- /dev/null +++ b/lib/platform/CMSWindowsClipboardBitmapConverter.cpp @@ -0,0 +1,146 @@ +/* + * 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 "CMSWindowsClipboardBitmapConverter.h" +#include "CLog.h" + +// +// CMSWindowsClipboardBitmapConverter +// + +CMSWindowsClipboardBitmapConverter::CMSWindowsClipboardBitmapConverter() +{ + // do nothing +} + +CMSWindowsClipboardBitmapConverter::~CMSWindowsClipboardBitmapConverter() +{ + // do nothing +} + +IClipboard::EFormat +CMSWindowsClipboardBitmapConverter::getFormat() const +{ + return IClipboard::kBitmap; +} + +UINT +CMSWindowsClipboardBitmapConverter::getWin32Format() const +{ + return CF_DIB; +} + +HANDLE +CMSWindowsClipboardBitmapConverter::fromIClipboard(const CString& data) const +{ + // copy to memory handle + HGLOBAL gData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, data.size()); + if (gData != NULL) { + // get a pointer to the allocated memory + char* dst = (char*)GlobalLock(gData); + if (dst != NULL) { + memcpy(dst, data.data(), data.size()); + GlobalUnlock(gData); + } + else { + GlobalFree(gData); + gData = NULL; + } + } + + return gData; +} + +CString +CMSWindowsClipboardBitmapConverter::toIClipboard(HANDLE data) const +{ + // get datator + const char* src = (const char*)GlobalLock(data); + if (src == NULL) { + return CString(); + } + UInt32 srcSize = (UInt32)GlobalSize(data); + + // check image type + const BITMAPINFO* bitmap = reinterpret_cast(src); + LOG((CLOG_INFO "bitmap: %dx%d %d", bitmap->bmiHeader.biWidth, bitmap->bmiHeader.biHeight, (int)bitmap->bmiHeader.biBitCount)); + if (bitmap->bmiHeader.biPlanes == 1 && + (bitmap->bmiHeader.biBitCount == 24 || + bitmap->bmiHeader.biBitCount == 32) && + bitmap->bmiHeader.biCompression == BI_RGB) { + // already in canonical form + CString image(src, srcSize); + GlobalUnlock(data); + return image; + } + + // create a destination DIB section + LOG((CLOG_INFO "convert image from: depth=%d comp=%d", bitmap->bmiHeader.biBitCount, bitmap->bmiHeader.biCompression)); + void* raw; + BITMAPINFOHEADER info; + LONG w = bitmap->bmiHeader.biWidth; + LONG h = bitmap->bmiHeader.biHeight; + info.biSize = sizeof(BITMAPINFOHEADER); + info.biWidth = w; + info.biHeight = h; + info.biPlanes = 1; + info.biBitCount = 32; + info.biCompression = BI_RGB; + info.biSizeImage = 0; + info.biXPelsPerMeter = 1000; + info.biYPelsPerMeter = 1000; + info.biClrUsed = 0; + info.biClrImportant = 0; + HDC dc = GetDC(NULL); + HBITMAP dst = CreateDIBSection(dc, (BITMAPINFO*)&info, + DIB_RGB_COLORS, &raw, NULL, 0); + + // find the start of the pixel data + const char* srcBits = (const char*)bitmap + bitmap->bmiHeader.biSize; + if (bitmap->bmiHeader.biBitCount >= 16) { + if (bitmap->bmiHeader.biCompression == BI_BITFIELDS && + (bitmap->bmiHeader.biBitCount == 16 || + bitmap->bmiHeader.biBitCount == 32)) { + srcBits += 3 * sizeof(DWORD); + } + } + else if (bitmap->bmiHeader.biClrUsed != 0) { + srcBits += bitmap->bmiHeader.biClrUsed * sizeof(RGBQUAD); + } + else { + srcBits += (1 << bitmap->bmiHeader.biBitCount) * sizeof(RGBQUAD); + } + + // copy source image to destination image + HDC dstDC = CreateCompatibleDC(dc); + HGDIOBJ oldBitmap = SelectObject(dstDC, dst); + SetDIBitsToDevice(dstDC, 0, 0, w, h, 0, 0, 0, h, + srcBits, bitmap, DIB_RGB_COLORS); + SelectObject(dstDC, oldBitmap); + DeleteDC(dstDC); + GdiFlush(); + + // extract data + CString image((const char*)&info, info.biSize); + image.append((const char*)raw, 4 * w * h); + + // clean up GDI + DeleteObject(dst); + ReleaseDC(NULL, dc); + + // release handle + GlobalUnlock(data); + + return image; +} diff --git a/lib/platform/CMSWindowsClipboardBitmapConverter.h b/lib/platform/CMSWindowsClipboardBitmapConverter.h new file mode 100644 index 00000000..6ddd7ce8 --- /dev/null +++ b/lib/platform/CMSWindowsClipboardBitmapConverter.h @@ -0,0 +1,35 @@ +/* + * 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 CMSWINDOWSCLIPBOARDBITMAPCONVERTER_H +#define CMSWINDOWSCLIPBOARDBITMAPCONVERTER_H + +#include "CMSWindowsClipboard.h" + +//! Convert to/from some text encoding +class CMSWindowsClipboardBitmapConverter : + public IMSWindowsClipboardConverter { +public: + CMSWindowsClipboardBitmapConverter(); + virtual ~CMSWindowsClipboardBitmapConverter(); + + // IMSWindowsClipboardConverter overrides + virtual IClipboard::EFormat + getFormat() const; + virtual UINT getWin32Format() const; + virtual HANDLE fromIClipboard(const CString&) const; + virtual CString toIClipboard(HANDLE) const; +}; + +#endif diff --git a/lib/platform/CMSWindowsClipboardHTMLConverter.cpp b/lib/platform/CMSWindowsClipboardHTMLConverter.cpp new file mode 100644 index 00000000..a64a0f78 --- /dev/null +++ b/lib/platform/CMSWindowsClipboardHTMLConverter.cpp @@ -0,0 +1,107 @@ +/* + * 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 "CMSWindowsClipboardHTMLConverter.h" +#include "CStringUtil.h" + +// +// CMSWindowsClipboardHTMLConverter +// + +CMSWindowsClipboardHTMLConverter::CMSWindowsClipboardHTMLConverter() +{ + m_format = RegisterClipboardFormat("HTML Format"); +} + +CMSWindowsClipboardHTMLConverter::~CMSWindowsClipboardHTMLConverter() +{ + // do nothing +} + +IClipboard::EFormat +CMSWindowsClipboardHTMLConverter::getFormat() const +{ + return IClipboard::kHTML; +} + +UINT +CMSWindowsClipboardHTMLConverter::getWin32Format() const +{ + return m_format; +} + +CString +CMSWindowsClipboardHTMLConverter::doFromIClipboard(const CString& data) const +{ + // prepare to CF_HTML format prefix and suffix + CString prefix("Version:0.9\nStartHTML:-1\nEndHTML:-1\n" + "StartFragment:XXXXXXXXXX\nEndFragment:YYYYYYYYYY\n" + ""); + CString suffix("\n"); + UInt32 start = prefix.size(); + UInt32 end = start + data.size(); + prefix.replace(prefix.find("XXXXXXXXXX"), 10, + CStringUtil::print("%010u", start)); + prefix.replace(prefix.find("YYYYYYYYYY"), 10, + CStringUtil::print("%010u", end)); + + // concatenate + prefix += data; + prefix += suffix; + return prefix; +} + +CString +CMSWindowsClipboardHTMLConverter::doToIClipboard(const CString& data) const +{ + // get fragment start/end args + CString startArg = findArg(data, "StartFragment"); + CString endArg = findArg(data, "EndFragment"); + if (startArg.empty() || endArg.empty()) { + return CString(); + } + + // convert args to integers + SInt32 start = (SInt32)atoi(startArg.c_str()); + SInt32 end = (SInt32)atoi(endArg.c_str()); + if (start <= 0 || end <= 0 || start >= end) { + return CString(); + } + + // extract the fragment + return data.substr(start, end - start); +} + +CString +CMSWindowsClipboardHTMLConverter::findArg( + const CString& data, const CString& name) const +{ + CString::size_type i = data.find(name); + if (i == CString::npos) { + return CString(); + } + i = data.find_first_of(":\r\n", i); + if (i == CString::npos || data[i] != ':') { + return CString(); + } + i = data.find_first_of("0123456789\r\n", i + 1); + if (i == CString::npos || data[i] == '\r' || data[i] == '\n') { + return CString(); + } + CString::size_type j = data.find_first_not_of("0123456789", i); + if (j == CString::npos) { + j = data.size(); + } + return data.substr(i, j - i); +} diff --git a/lib/platform/CMSWindowsClipboardHTMLConverter.h b/lib/platform/CMSWindowsClipboardHTMLConverter.h new file mode 100644 index 00000000..02cd8f88 --- /dev/null +++ b/lib/platform/CMSWindowsClipboardHTMLConverter.h @@ -0,0 +1,44 @@ +/* + * 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 CMSWINDOWSCLIPBOARDHTMLCONVERTER_H +#define CMSWINDOWSCLIPBOARDHTMLCONVERTER_H + +#include "CMSWindowsClipboardAnyTextConverter.h" + +//! Convert to/from HTML encoding +class CMSWindowsClipboardHTMLConverter : + public CMSWindowsClipboardAnyTextConverter { +public: + CMSWindowsClipboardHTMLConverter(); + virtual ~CMSWindowsClipboardHTMLConverter(); + + // IMSWindowsClipboardConverter overrides + virtual IClipboard::EFormat + getFormat() const; + virtual UINT getWin32Format() const; + +protected: + // CMSWindowsClipboardAnyTextConverter overrides + virtual CString doFromIClipboard(const CString&) const; + virtual CString doToIClipboard(const CString&) const; + +private: + CString findArg(const CString& data, const CString& name) const; + +private: + UINT m_format; +}; + +#endif diff --git a/lib/platform/platform.dsp b/lib/platform/platform.dsp index a5036971..ad302539 100644 --- a/lib/platform/platform.dsp +++ b/lib/platform/platform.dsp @@ -95,6 +95,14 @@ SOURCE=.\CMSWindowsClipboardAnyTextConverter.cpp # End Source File # Begin Source File +SOURCE=.\CMSWindowsClipboardBitmapConverter.cpp +# End Source File +# Begin Source File + +SOURCE=.\CMSWindowsClipboardHTMLConverter.cpp +# End Source File +# Begin Source File + SOURCE=.\CMSWindowsClipboardTextConverter.cpp # End Source File # Begin Source File @@ -139,6 +147,14 @@ SOURCE=.\CMSWindowsClipboardAnyTextConverter.h # End Source File # Begin Source File +SOURCE=.\CMSWindowsClipboardBitmapConverter.h +# End Source File +# Begin Source File + +SOURCE=.\CMSWindowsClipboardHTMLConverter.h +# End Source File +# Begin Source File + SOURCE=.\CMSWindowsClipboardTextConverter.h # End Source File # Begin Source File diff --git a/lib/server/server.dsp b/lib/server/server.dsp index 1aa729c5..91d0c683 100644 --- a/lib/server/server.dsp +++ b/lib/server/server.dsp @@ -103,6 +103,10 @@ SOURCE=.\CClientProxy1_1.cpp # End Source File # Begin Source File +SOURCE=.\CClientProxy1_2.cpp +# End Source File +# Begin Source File + SOURCE=.\CClientProxyUnknown.cpp # End Source File # Begin Source File @@ -139,6 +143,10 @@ SOURCE=.\CClientProxy1_1.h # End Source File # Begin Source File +SOURCE=.\CClientProxy1_2.h +# End Source File +# Begin Source File + SOURCE=.\CClientProxyUnknown.h # End Source File # Begin Source File diff --git a/lib/synergy/IClipboard.h b/lib/synergy/IClipboard.h index c0bfbeb4..1f75909e 100644 --- a/lib/synergy/IClipboard.h +++ b/lib/synergy/IClipboard.h @@ -43,6 +43,8 @@ public: */ enum EFormat { kText, //!< Text format, UTF-8, newline is LF + kBitmap, //!< Bitmap format, BMP 24/32bpp, BI_RGB/BI_BITFIELDS + kHTML, //!< HTML format, HTML fragment, UTF-8, newline is LF kNumFormats //!< The number of clipboard formats };