From: Damjan Jovanovic Subject: [v4 PATCH] winex11.drv: import X11's "text/html" as "HTML Format" (try 4) Message-Id: Date: Thu, 17 Nov 2016 01:28:38 +0200 Initial support for importing "text/html" into Windows's "HTML Format", which fixes pasting rich text into a large number of apps and closes #7372. Currently OpenOffice (SVN trunk), Excel and Firefox work, but apps needing full HTML documents instead of only HTML fragments will only be able to paste from apps that provide those. Try 2 makes character arrays static const where possible. Try 3 uses GMEM_FIXED for GlobalAlloc(). Try 4 also allows pasting when the source isn't Firefox. Signed-off-by: Damjan Jovanovic --- dlls/winex11.drv/clipboard.c | 71 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c index f56fd4f..d8215af 100644 --- a/dlls/winex11.drv/clipboard.c +++ b/dlls/winex11.drv/clipboard.c @@ -116,6 +116,7 @@ static HANDLE import_string( Atom type, const void *data, size_t size ); static HANDLE import_utf8_string( Atom type, const void *data, size_t size ); static HANDLE import_compound_text( Atom type, const void *data, size_t size ); static HANDLE import_text( Atom type, const void *data, size_t size ); +static HANDLE import_text_html( Atom type, const void *data, size_t size ); static HANDLE import_text_uri_list( Atom type, const void *data, size_t size ); static HANDLE import_targets( Atom type, const void *data, size_t size ); @@ -174,7 +175,7 @@ static const struct { JFIFW, 0, XATOM_image_jpeg, import_data, export_data }, { PNGW, 0, XATOM_image_png, import_data, export_data }, { HTMLFormatW, 0, XATOM_HTML_Format, import_data, export_data }, - { HTMLFormatW, 0, XATOM_text_html, import_data, export_text_html }, + { HTMLFormatW, 0, XATOM_text_html, import_text_html, export_text_html }, { 0, 0, XATOM_TARGETS, import_targets, export_targets }, { 0, 0, XATOM_MULTIPLE, NULL, export_multiple }, { 0, 0, XATOM_TIMESTAMP, NULL, export_timestamp }, @@ -834,6 +835,74 @@ static HANDLE import_enhmetafile( Atom type, const void *data, size_t size ) } +static char *standardize_text_html( const char *data, size_t size ) +{ + char *textHtml = NULL; + + /* Firefox uses UTF-16LE with byte order mark. Convert to UTF-8 without the BOM. */ + if (size >= 2 && ((BYTE*)data)[0] == 0xff && ((BYTE*)data)[1] == 0xfe) + { + INT textHtmlSize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)&data[2], (size-2)/2, NULL, 0, NULL, NULL); + textHtml = HeapAlloc(GetProcessHeap(), 0, textHtmlSize); + if (textHtml) + WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)&data[2], (size-2)/2, textHtml, textHtmlSize, NULL, NULL); + else + ERR("out of memory\n"); + } + else + { + textHtml = HeapAlloc(GetProcessHeap(), 0, size); + if (textHtml) + memcpy(textHtml, data, size); + else + ERR("out of memory\n"); + } + return textHtml; +} + + +/************************************************************************** + * import_text_html + */ +static HANDLE import_text_html( Atom type, const void *data, size_t size ) +{ + static const char startFragment[] = ""; + static const char endFragment[] = ""; + char *textHtml = NULL; + char description[256]; + static const char descriptionFormat[] = + "Version:0.9\n" + "StartHTML:-1\n" + "EndHTML:-1\n" + "StartFragment:%010u\n" + "EndFragment:%010u\n"; + char *clipData = NULL; + int clipDataSize; + + textHtml = standardize_text_html(data, size); + if (textHtml == NULL) + goto end; + + snprintf(description, sizeof(description), descriptionFormat, 0, 0); + snprintf(description, sizeof(description), descriptionFormat, + strlen(description) + strlen(startFragment), + strlen(description) + strlen(startFragment) + strlen(textHtml)); + clipDataSize = strlen(description) + strlen(startFragment) + strlen(textHtml) + strlen(endFragment) + 1; + clipData = GlobalAlloc(GMEM_FIXED, clipDataSize); + if (clipData) + { + snprintf(clipData, clipDataSize, "%s%s%s%s", description, startFragment, textHtml, endFragment); + TRACE("incoming \"HTML Format\" with these contents:\n%s\n", clipData); + } + else + ERR("out of memory\n"); + +end: + HeapFree(GetProcessHeap(), 0, textHtml); + return clipData; +} + + /************************************************************************** * import_text_uri_list *