From 0e4659403fe6ece1c8be2f5140ca98cf970785b1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 17 Oct 2014 18:23:07 -0400 Subject: [PATCH] libwinpr-clipboard: add basic clipboard synthesizers --- winpr/include/winpr/clipboard.h | 4 +- winpr/libwinpr/clipboard/CMakeLists.txt | 4 +- winpr/libwinpr/clipboard/clipboard.c | 30 +- winpr/libwinpr/clipboard/clipboard.h | 5 +- winpr/libwinpr/clipboard/synthetic.c | 500 +++++++++++++++++++++ .../libwinpr/clipboard/test/TestClipboardFormats.c | 32 +- 6 files changed, 514 insertions(+), 61 deletions(-) create mode 100644 winpr/libwinpr/clipboard/synthetic.c diff --git a/winpr/include/winpr/clipboard.h b/winpr/include/winpr/clipboard.h index 57cb37f..8ff60e6 100644 --- a/winpr/include/winpr/clipboard.h +++ b/winpr/include/winpr/clipboard.h @@ -25,7 +25,7 @@ typedef struct _wClipboard wClipboard; -typedef void* (*CLIPBOARD_SYNTHESIZE_FN)(void* context, UINT32 formatId, const void* data, UINT32* pSize); +typedef void* (*CLIPBOARD_SYNTHESIZE_FN)(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize); #ifdef __cplusplus extern "C" { @@ -43,7 +43,7 @@ WINPR_API UINT32 ClipboardGetRegisteredFormatIds(wClipboard* clipboard, UINT32** WINPR_API UINT32 ClipboardRegisterFormat(wClipboard* clipboard, const char* name); WINPR_API BOOL ClipboardRegisterSynthesizer(wClipboard* clipboard, UINT32 formatId, - UINT32 syntheticId, CLIPBOARD_SYNTHESIZE_FN pfnSynthesize, void* context); + UINT32 syntheticId, CLIPBOARD_SYNTHESIZE_FN pfnSynthesize); WINPR_API UINT32 ClipboardGetFormatId(wClipboard* clipboard, const char* name); WINPR_API const char* ClipboardGetFormatName(wClipboard* clipboard, UINT32 formatId); diff --git a/winpr/libwinpr/clipboard/CMakeLists.txt b/winpr/libwinpr/clipboard/CMakeLists.txt index 1b22e53..a5be7cb 100644 --- a/winpr/libwinpr/clipboard/CMakeLists.txt +++ b/winpr/libwinpr/clipboard/CMakeLists.txt @@ -16,7 +16,9 @@ # limitations under the License. winpr_module_add( - clipboard.c) + synthetic.c + clipboard.c + clipboard.h) if(BUILD_TESTING) add_subdirectory(test) diff --git a/winpr/libwinpr/clipboard/clipboard.c b/winpr/libwinpr/clipboard/clipboard.c index f160777..13e1655 100644 --- a/winpr/libwinpr/clipboard/clipboard.c +++ b/winpr/libwinpr/clipboard/clipboard.c @@ -36,29 +36,6 @@ * http://www.w3.org/TR/clipboard-apis/ */ -/** - * Synthesized Clipboard Formats - * - * Clipboard Format Conversion Format - * - * CF_BITMAP CF_DIB - * CF_BITMAP CF_DIBV5 - * CF_DIB CF_BITMAP - * CF_DIB CF_PALETTE - * CF_DIB CF_DIBV5 - * CF_DIBV5 CF_BITMAP - * CF_DIBV5 CF_DIB - * CF_DIBV5 CF_PALETTE - * CF_ENHMETAFILE CF_METAFILEPICT - * CF_METAFILEPICT CF_ENHMETAFILE - * CF_OEMTEXT CF_TEXT - * CF_OEMTEXT CF_UNICODETEXT - * CF_TEXT CF_OEMTEXT - * CF_TEXT CF_UNICODETEXT - * CF_UNICODETEXT CF_OEMTEXT - * CF_UNICODETEXT CF_TEXT - */ - const char* CF_STANDARD_STRINGS[CF_MAX] = { "CF_RAW", /* 0 */ @@ -246,7 +223,7 @@ UINT32 ClipboardRegisterFormat(wClipboard* clipboard, const char* name) } BOOL ClipboardRegisterSynthesizer(wClipboard* clipboard, UINT32 formatId, - UINT32 syntheticId, CLIPBOARD_SYNTHESIZE_FN pfnSynthesize, void* context) + UINT32 syntheticId, CLIPBOARD_SYNTHESIZE_FN pfnSynthesize) { UINT32 index; wClipboardFormat* format; @@ -279,7 +256,6 @@ BOOL ClipboardRegisterSynthesizer(wClipboard* clipboard, UINT32 formatId, synthesizer->syntheticId = syntheticId; synthesizer->pfnSynthesize = pfnSynthesize; - synthesizer->context = context; return TRUE; } @@ -357,6 +333,8 @@ BOOL ClipboardInitFormats(wClipboard* clipboard) return FALSE; } + ClipboardInitSynthesizers(clipboard); + return TRUE; } @@ -425,7 +403,7 @@ void* ClipboardGetData(wClipboard* clipboard, UINT32 formatId, UINT32* pSize) DstSize = SrcSize; - pDstData = synthesizer->pfnSynthesize(synthesizer->context, formatId, pSrcData, &DstSize); + pDstData = synthesizer->pfnSynthesize(clipboard, format->formatId, pSrcData, &DstSize); } return pDstData; diff --git a/winpr/libwinpr/clipboard/clipboard.h b/winpr/libwinpr/clipboard/clipboard.h index 63d7c80..76d6526 100644 --- a/winpr/libwinpr/clipboard/clipboard.h +++ b/winpr/libwinpr/clipboard/clipboard.h @@ -22,6 +22,8 @@ #include +#include + typedef struct _wClipboardFormat wClipboardFormat; typedef struct _wClipboardSynthesizer wClipboardSynthesizer; @@ -36,7 +38,6 @@ struct _wClipboardFormat struct _wClipboardSynthesizer { - void* context; UINT32 syntheticId; CLIPBOARD_SYNTHESIZE_FN pfnSynthesize; }; @@ -62,4 +63,6 @@ struct _wClipboard CRITICAL_SECTION lock; }; +BOOL ClipboardInitSynthesizers(wClipboard* clipboard); + #endif /* WINPR_CLIPBOARD_PRIVATE_H */ diff --git a/winpr/libwinpr/clipboard/synthetic.c b/winpr/libwinpr/clipboard/synthetic.c new file mode 100644 index 0000000..ac7d339 --- /dev/null +++ b/winpr/libwinpr/clipboard/synthetic.c @@ -0,0 +1,500 @@ +/** + * WinPR: Windows Portable Runtime + * Clipboard Functions + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "clipboard.h" + +/** + * Standard Clipboard Formats: + * http://msdn.microsoft.com/en-us/library/windows/desktop/ff729168/ + */ + +/** + * Synthesized Clipboard Formats + * + * Clipboard Format Conversion Format + * + * CF_BITMAP CF_DIB + * CF_BITMAP CF_DIBV5 + * CF_DIB CF_BITMAP + * CF_DIB CF_PALETTE + * CF_DIB CF_DIBV5 + * CF_DIBV5 CF_BITMAP + * CF_DIBV5 CF_DIB + * CF_DIBV5 CF_PALETTE + * CF_ENHMETAFILE CF_METAFILEPICT + * CF_METAFILEPICT CF_ENHMETAFILE + * CF_OEMTEXT CF_TEXT + * CF_OEMTEXT CF_UNICODETEXT + * CF_TEXT CF_OEMTEXT + * CF_TEXT CF_UNICODETEXT + * CF_UNICODETEXT CF_OEMTEXT + * CF_UNICODETEXT CF_TEXT + */ + +/** + * "CF_TEXT": + * + * Null-terminated ANSI text with CR/LF line endings. + */ + +static void* clipboard_synthesize_cf_text(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +{ + int size; + char* pDstData = NULL; + + if (formatId == CF_UNICODETEXT) + { + char* str = NULL; + + size = (int) *pSize; + size = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) data, + size / 2, (CHAR**) &str, 0, NULL, NULL); + + if (!str) + return NULL; + + pDstData = ConvertLineEndingToCRLF((const char*) str, &size); + free(str); + + *pSize = size; + + return pDstData; + } + else if ((formatId == CF_TEXT) || (formatId == CF_OEMTEXT) || + (formatId == ClipboardGetFormatId(clipboard, "UTF8_STRING")) || + (formatId == ClipboardGetFormatId(clipboard, "text/plain")) || + (formatId == ClipboardGetFormatId(clipboard, "TEXT")) || + (formatId == ClipboardGetFormatId(clipboard, "STRING"))) + { + size = (int) *pSize; + pDstData = ConvertLineEndingToCRLF((const char*) data, &size); + + if (!pDstData) + return NULL; + + *pSize = size; + + return pDstData; + } + + return NULL; +} + +/** + * "CF_OEMTEXT": + * + * Null-terminated OEM text with CR/LF line endings. + */ + +static void* clipboard_synthesize_cf_oemtext(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +{ + return clipboard_synthesize_cf_text(clipboard, formatId, data, pSize); +} + +/** + * "CF_LOCALE": + * + * System locale identifier associated with CF_TEXT + */ + +static void* clipboard_synthesize_cf_locale(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +{ + UINT32* pDstData = NULL; + + pDstData = (UINT32*) malloc(sizeof(UINT32)); + *pDstData = 0x0409; /* English - United States */ + + return (void*) pDstData; +} + +/** + * "CF_UNICODETEXT": + * + * Null-terminated UTF-16 text with CR/LF line endings. + */ + +static void* clipboard_synthesize_cf_unicodetext(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +{ + int size; + int status; + char* crlfStr = NULL; + WCHAR* pDstData = NULL; + + if ((formatId == CF_TEXT) || (formatId == CF_OEMTEXT) || + (formatId == ClipboardGetFormatId(clipboard, "UTF8_STRING")) || + (formatId == ClipboardGetFormatId(clipboard, "text/plain")) || + (formatId == ClipboardGetFormatId(clipboard, "TEXT")) || + (formatId == ClipboardGetFormatId(clipboard, "STRING"))) + { + size = (int) *pSize; + crlfStr = ConvertLineEndingToCRLF((char*) data, &size); + + if (!crlfStr) + return NULL; + + status = ConvertToUnicode(CP_UTF8, 0, crlfStr, size, &pDstData, 0); + free(crlfStr); + + if (status <= 0) + return NULL; + + *pSize = ((status + 1) * 2); + } + + return (void*) pDstData; +} + +/** + * "UTF8_STRING": + * + * Null-terminated UTF-8 string with LF line endings. + */ + +static void* clipboard_synthesize_utf8_string(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +{ + int size; + char* pDstData = NULL; + + if (formatId == CF_UNICODETEXT) + { + size = (int) *pSize; + size = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) data, + size / 2, (CHAR**) &pDstData, 0, NULL, NULL); + + if (!pDstData) + return NULL; + + size = ConvertLineEndingToLF(pDstData, size); + + *pSize = size; + + return pDstData; + } + else if ((formatId == CF_TEXT) || (formatId == CF_OEMTEXT) || + (formatId == ClipboardGetFormatId(clipboard, "text/plain")) || + (formatId == ClipboardGetFormatId(clipboard, "TEXT")) || + (formatId == ClipboardGetFormatId(clipboard, "STRING"))) + { + size = (int) *pSize; + pDstData = (char*) malloc(size); + + if (!pDstData) + return NULL; + + CopyMemory(pDstData, data, size); + + size = ConvertLineEndingToLF((char*) pDstData, size); + + *pSize = size; + + return pDstData; + } + + return NULL; +} + +/** + * "CF_DIB": + * + * BITMAPINFO structure followed by the bitmap bits. + */ + +static void* clipboard_synthesize_cf_dib(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +{ + /* TODO */ + + return NULL; +} + +/** + * "CF_DIBV5": + * + * BITMAPV5HEADER structure followed by the bitmap color space information and the bitmap bits. + */ + +static void* clipboard_synthesize_cf_dibv5(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +{ + /* TODO */ + + return NULL; +} + +/** + * "image/bmp": + * + * Bitmap file format. + */ + +static void* clipboard_synthesize_image_bmp(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +{ + /* TODO */ + + return NULL; +} + +/** + * "HTML Format": + * + * HTML clipboard format: msdn.microsoft.com/en-us/library/windows/desktop/ms649015/ + */ + +static void* clipboard_synthesize_html_format(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +{ + /* TODO */ + + return NULL; +} + +/** + * "text/html": + * + * HTML text format. + */ + +static void* clipboard_synthesize_text_html(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) +{ + /* TODO */ + + return NULL; +} + +BOOL ClipboardInitSynthesizers(wClipboard* clipboard) +{ + UINT32 formatId; + UINT32 altFormatId; + + /** + * CF_TEXT + */ + + ClipboardRegisterSynthesizer(clipboard, CF_TEXT, CF_OEMTEXT, + clipboard_synthesize_cf_oemtext); + + ClipboardRegisterSynthesizer(clipboard, CF_TEXT, CF_UNICODETEXT, + clipboard_synthesize_cf_unicodetext); + + ClipboardRegisterSynthesizer(clipboard, CF_TEXT, CF_LOCALE, + clipboard_synthesize_cf_locale); + + altFormatId = ClipboardRegisterFormat(clipboard, "UTF8_STRING"); + + ClipboardRegisterSynthesizer(clipboard, CF_TEXT, altFormatId, + clipboard_synthesize_utf8_string); + + /** + * CF_OEMTEXT + */ + + ClipboardRegisterSynthesizer(clipboard, CF_OEMTEXT, CF_TEXT, + clipboard_synthesize_cf_text); + + ClipboardRegisterSynthesizer(clipboard, CF_OEMTEXT, CF_UNICODETEXT, + clipboard_synthesize_cf_unicodetext); + + ClipboardRegisterSynthesizer(clipboard, CF_OEMTEXT, CF_LOCALE, + clipboard_synthesize_cf_locale); + + altFormatId = ClipboardRegisterFormat(clipboard, "UTF8_STRING"); + + ClipboardRegisterSynthesizer(clipboard, CF_OEMTEXT, altFormatId, + clipboard_synthesize_utf8_string); + + /** + * CF_UNICODETEXT + */ + + ClipboardRegisterSynthesizer(clipboard, CF_UNICODETEXT, CF_TEXT, + clipboard_synthesize_cf_text); + + ClipboardRegisterSynthesizer(clipboard, CF_UNICODETEXT, CF_OEMTEXT, + clipboard_synthesize_cf_oemtext); + + ClipboardRegisterSynthesizer(clipboard, CF_UNICODETEXT, CF_LOCALE, + clipboard_synthesize_cf_locale); + + altFormatId = ClipboardRegisterFormat(clipboard, "UTF8_STRING"); + + ClipboardRegisterSynthesizer(clipboard, CF_UNICODETEXT, altFormatId, + clipboard_synthesize_utf8_string); + + /** + * UTF8_STRING + */ + + formatId = ClipboardRegisterFormat(clipboard, "UTF8_STRING"); + + if (formatId) + { + ClipboardRegisterSynthesizer(clipboard, formatId, CF_TEXT, + clipboard_synthesize_cf_text); + + ClipboardRegisterSynthesizer(clipboard, formatId, CF_OEMTEXT, + clipboard_synthesize_cf_oemtext); + + ClipboardRegisterSynthesizer(clipboard, formatId, CF_UNICODETEXT, + clipboard_synthesize_cf_unicodetext); + + ClipboardRegisterSynthesizer(clipboard, formatId, CF_LOCALE, + clipboard_synthesize_cf_locale); + } + + /** + * text/plain + */ + + formatId = ClipboardRegisterFormat(clipboard, "text/plain"); + + if (formatId) + { + ClipboardRegisterSynthesizer(clipboard, formatId, CF_TEXT, + clipboard_synthesize_cf_text); + + ClipboardRegisterSynthesizer(clipboard, formatId, CF_OEMTEXT, + clipboard_synthesize_cf_oemtext); + + ClipboardRegisterSynthesizer(clipboard, formatId, CF_UNICODETEXT, + clipboard_synthesize_cf_unicodetext); + + ClipboardRegisterSynthesizer(clipboard, formatId, CF_LOCALE, + clipboard_synthesize_cf_locale); + } + + /** + * TEXT + */ + + formatId = ClipboardRegisterFormat(clipboard, "TEXT"); + + if (formatId) + { + ClipboardRegisterSynthesizer(clipboard, formatId, CF_TEXT, + clipboard_synthesize_cf_text); + + ClipboardRegisterSynthesizer(clipboard, formatId, CF_OEMTEXT, + clipboard_synthesize_cf_oemtext); + + ClipboardRegisterSynthesizer(clipboard, formatId, CF_UNICODETEXT, + clipboard_synthesize_cf_unicodetext); + + ClipboardRegisterSynthesizer(clipboard, formatId, CF_LOCALE, + clipboard_synthesize_cf_locale); + } + + /** + * STRING + */ + + formatId = ClipboardRegisterFormat(clipboard, "STRING"); + + if (formatId) + { + ClipboardRegisterSynthesizer(clipboard, formatId, CF_TEXT, + clipboard_synthesize_cf_text); + + ClipboardRegisterSynthesizer(clipboard, formatId, CF_OEMTEXT, + clipboard_synthesize_cf_oemtext); + + ClipboardRegisterSynthesizer(clipboard, formatId, CF_UNICODETEXT, + clipboard_synthesize_cf_unicodetext); + + ClipboardRegisterSynthesizer(clipboard, formatId, CF_LOCALE, + clipboard_synthesize_cf_locale); + } + + /** + * CF_DIB + */ + + if (formatId) + { + ClipboardRegisterSynthesizer(clipboard, CF_DIB, CF_DIBV5, + clipboard_synthesize_cf_dibv5); + + altFormatId = ClipboardRegisterFormat(clipboard, "image/bmp"); + + ClipboardRegisterSynthesizer(clipboard, CF_DIB, altFormatId, + clipboard_synthesize_image_bmp); + } + + /** + * CF_DIBV5 + */ + + if (formatId) + { + ClipboardRegisterSynthesizer(clipboard, CF_DIBV5, CF_DIB, + clipboard_synthesize_cf_dib); + + altFormatId = ClipboardRegisterFormat(clipboard, "image/bmp"); + + ClipboardRegisterSynthesizer(clipboard, CF_DIBV5, altFormatId, + clipboard_synthesize_image_bmp); + } + + /** + * image/bmp + */ + + formatId = ClipboardRegisterFormat(clipboard, "image/bmp"); + + if (formatId) + { + ClipboardRegisterSynthesizer(clipboard, formatId, CF_DIB, + clipboard_synthesize_cf_dib); + + ClipboardRegisterSynthesizer(clipboard, formatId, CF_DIBV5, + clipboard_synthesize_cf_dibv5); + } + + /** + * HTML Format + */ + + formatId = ClipboardRegisterFormat(clipboard, "HTML Format"); + + if (formatId) + { + altFormatId = ClipboardRegisterFormat(clipboard, "text/html"); + + ClipboardRegisterSynthesizer(clipboard, formatId, altFormatId, + clipboard_synthesize_text_html); + } + + /** + * text/html + */ + + formatId = ClipboardRegisterFormat(clipboard, "text/html"); + + if (formatId) + { + altFormatId = ClipboardRegisterFormat(clipboard, "HTML Format"); + + ClipboardRegisterSynthesizer(clipboard, formatId, altFormatId, + clipboard_synthesize_html_format); + } + + return TRUE; +} diff --git a/winpr/libwinpr/clipboard/test/TestClipboardFormats.c b/winpr/libwinpr/clipboard/test/TestClipboardFormats.c index 12e8272..2242bcd 100644 --- a/winpr/libwinpr/clipboard/test/TestClipboardFormats.c +++ b/winpr/libwinpr/clipboard/test/TestClipboardFormats.c @@ -3,30 +3,6 @@ #include #include -void* synthesize_utf8_string_to_cf_unicodetext(void* context, UINT32 formatId, const void* data, UINT32* pSize) -{ - int size; - int status; - char* crlfStr = NULL; - WCHAR* pDstData = NULL; - - size = (int) *pSize; - crlfStr = ConvertLineEndingToCRLF((char*) data, &size); - - if (!crlfStr) - return NULL; - - status = ConvertToUnicode(CP_UTF8, 0, crlfStr, size, &pDstData, 0); - free(crlfStr); - - if (status <= 0) - return NULL; - - *pSize = ((status + 1) * 2); - - return (void*) pDstData; -} - int TestClipboardFormats(int argc, char* argv[]) { UINT32 index; @@ -42,7 +18,7 @@ int TestClipboardFormats(int argc, char* argv[]) formatId = ClipboardRegisterFormat(clipboard, "text/html"); formatId = ClipboardRegisterFormat(clipboard, "image/bmp"); formatId = ClipboardRegisterFormat(clipboard, "image/png"); - utf8StringFormatId = ClipboardRegisterFormat(clipboard, "UFT8_STRING"); + utf8StringFormatId = ClipboardRegisterFormat(clipboard, "UTF8_STRING"); pFormatIds = NULL; count = ClipboardGetRegisteredFormatIds(clipboard, &pFormatIds); @@ -82,16 +58,10 @@ int TestClipboardFormats(int argc, char* argv[]) if (1) { - BOOL bSuccess; UINT32 DstSize; char* pSrcData; WCHAR* pDstData; - bSuccess = ClipboardRegisterSynthesizer(clipboard, utf8StringFormatId, - CF_UNICODETEXT, synthesize_utf8_string_to_cf_unicodetext, NULL); - - fprintf(stderr, "ClipboardRegisterSynthesizer: %d\n", bSuccess); - DstSize = 0; pDstData = (WCHAR*) ClipboardGetData(clipboard, CF_UNICODETEXT, &DstSize); -- 2.7.4