Commit 8865f4a4 authored by Alexandre Julliard's avatar Alexandre Julliard

user32: Synthesize text clipboard formats on the user32 side.

parent b1e8ed3e
......@@ -1336,17 +1336,14 @@ static void test_nonole_clipboard(void)
hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
ok(hr == S_OK, "got %08x\n", hr); /* User32 adds some synthesised formats */
todo_wine ok(fmt.cfFormat == CF_LOCALE, "cf %04x\n", fmt.cfFormat);
if(fmt.cfFormat == CF_LOCALE)
{
ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
ok(fmt.cfFormat == CF_LOCALE, "cf %04x\n", fmt.cfFormat);
ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
ok(fmt.dwAspect == DVASPECT_CONTENT, "aspect %x\n", fmt.dwAspect);
ok(fmt.lindex == -1, "lindex %d\n", fmt.lindex);
todo_wine ok(fmt.tymed == (TYMED_ISTREAM | TYMED_HGLOBAL), "tymed %x\n", fmt.tymed);
hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
ok(hr == S_OK, "got %08x\n", hr);
}
hr = IEnumFORMATETC_Next(enum_fmt, 1, &fmt, NULL);
ok(hr == S_OK, "got %08x\n", hr);
ok(fmt.cfFormat == CF_OEMTEXT, "cf %04x\n", fmt.cfFormat);
ok(fmt.ptd == NULL, "ptd %p\n", fmt.ptd);
......
......@@ -32,6 +32,7 @@
#include "config.h"
#include "wine/port.h"
#include <assert.h>
#include <stdarg.h>
#include <stdlib.h>
#include <sys/types.h>
......@@ -61,6 +62,162 @@ WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
static BOOL bCBHasChanged = FALSE;
/* formats that can be synthesized are: CF_TEXT, CF_OEMTEXT, CF_UNICODETEXT,
CF_BITMAP, CF_DIB, CF_DIBV5, CF_ENHMETAFILE, CF_METAFILEPICT */
static UINT synthesized_formats[CF_MAX];
/* add a synthesized format to the list */
static void add_synthesized_format( UINT format, UINT from )
{
assert( format < CF_MAX );
SetClipboardData( format, 0 );
synthesized_formats[format] = from;
}
/* store the current locale in the CF_LOCALE format */
static void set_clipboard_locale(void)
{
HANDLE data = GlobalAlloc( GMEM_FIXED, sizeof(LCID) );
if (!data) return;
*(LCID *)data = GetUserDefaultLCID();
SetClipboardData( CF_LOCALE, data );
TRACE( "added CF_LOCALE\n" );
}
/* get the clipboard locale stored in the CF_LOCALE format */
static LCID get_clipboard_locale(void)
{
HANDLE data;
LCID lcid = GetUserDefaultLCID();
if ((data = GetClipboardData( CF_LOCALE )))
{
LCID *ptr = GlobalLock( data );
if (ptr && GlobalSize( data ) >= sizeof(*ptr)) lcid = *ptr;
GlobalUnlock( data );
}
return lcid;
}
/* get the codepage to use for text conversions in the specified format (CF_TEXT or CF_OEMTEXT) */
static UINT get_format_codepage( LCID lcid, UINT format )
{
LCTYPE type = (format == CF_TEXT) ? LOCALE_IDEFAULTANSICODEPAGE : LOCALE_IDEFAULTCODEPAGE;
UINT ret;
if (!GetLocaleInfoW( lcid, type | LOCALE_RETURN_NUMBER, (LPWSTR)&ret, sizeof(ret)/sizeof(WCHAR) ))
ret = (format == CF_TEXT) ? CP_ACP : CP_OEMCP;
return ret;
}
/* add synthesized text formats based on what is already in the clipboard */
static void add_synthesized_text(void)
{
BOOL has_text = IsClipboardFormatAvailable( CF_TEXT );
BOOL has_oemtext = IsClipboardFormatAvailable( CF_OEMTEXT );
BOOL has_unicode = IsClipboardFormatAvailable( CF_UNICODETEXT );
if (!has_text && !has_oemtext && !has_unicode) return; /* no text, nothing to do */
if (!IsClipboardFormatAvailable( CF_LOCALE )) set_clipboard_locale();
if (has_unicode)
{
if (!has_text) add_synthesized_format( CF_TEXT, CF_UNICODETEXT );
if (!has_oemtext) add_synthesized_format( CF_OEMTEXT, CF_UNICODETEXT );
}
else if (has_text)
{
if (!has_oemtext) add_synthesized_format( CF_OEMTEXT, CF_TEXT );
if (!has_unicode) add_synthesized_format( CF_UNICODETEXT, CF_TEXT );
}
else
{
if (!has_text) add_synthesized_format( CF_TEXT, CF_OEMTEXT );
if (!has_unicode) add_synthesized_format( CF_UNICODETEXT, CF_OEMTEXT );
}
}
/* render synthesized ANSI text based on the contents of the 'from' format */
static HANDLE render_synthesized_textA( HANDLE data, UINT format, UINT from )
{
void *src;
WCHAR *srcW = NULL;
HANDLE ret = 0;
LCID lcid = get_clipboard_locale();
UINT codepage = get_format_codepage( lcid, format );
UINT len, size = GlobalSize( data );
if (!(src = GlobalLock( data ))) return 0;
if (from != CF_UNICODETEXT) /* first convert incoming format to Unicode */
{
UINT from_codepage = get_format_codepage( lcid, from );
len = MultiByteToWideChar( from_codepage, 0, src, size, NULL, 0 );
if (!(srcW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) goto done;
MultiByteToWideChar( from_codepage, 0, src, size, srcW, len );
src = srcW;
size = len * sizeof(WCHAR);
}
len = WideCharToMultiByte( codepage, 0, src, size / sizeof(WCHAR), NULL, 0, NULL, NULL );
if ((ret = GlobalAlloc( GMEM_FIXED, len )))
WideCharToMultiByte( codepage, 0, src, size / sizeof(WCHAR), ret, len, NULL, NULL );
done:
HeapFree( GetProcessHeap(), 0, srcW );
GlobalUnlock( data );
return ret;
}
/* render synthesized Unicode text based on the contents of the 'from' format */
static HANDLE render_synthesized_textW( HANDLE data, UINT from )
{
char *src;
HANDLE ret;
UINT len, size = GlobalSize( data );
UINT codepage = get_format_codepage( get_clipboard_locale(), from );
if (!(src = GlobalLock( data ))) return 0;
len = MultiByteToWideChar( codepage, 0, src, size, NULL, 0 );
if ((ret = GlobalAlloc( GMEM_FIXED, len * sizeof(WCHAR) )))
MultiByteToWideChar( codepage, 0, src, size, ret, len );
GlobalUnlock( data );
return ret;
}
/* render a synthesized format */
static HANDLE render_synthesized_format( UINT format, UINT from )
{
HANDLE data = GetClipboardData( from );
if (!data) return 0;
TRACE( "rendering %04x from %04x\n", format, from );
switch (format)
{
case CF_TEXT:
case CF_OEMTEXT:
data = render_synthesized_textA( data, format, from );
break;
case CF_UNICODETEXT:
data = render_synthesized_textW( data, from );
break;
default:
assert( 0 );
}
if (data)
{
TRACE( "adding %04x %p\n", format, data );
SetClipboardData( format, data );
}
return data;
}
/**************************************************************************
* get_clipboard_flags
*/
......@@ -154,7 +311,11 @@ BOOL WINAPI OpenClipboard( HWND hwnd )
req->window = wine_server_user_handle( hwnd );
if ((ret = !wine_server_call_err( req )))
{
if (!reply->owner) bCBHasChanged = FALSE;
if (!reply->owner)
{
bCBHasChanged = FALSE;
memset( synthesized_formats, 0, sizeof(synthesized_formats) );
}
}
}
SERVER_END_REQ;
......@@ -173,6 +334,12 @@ BOOL WINAPI CloseClipboard(void)
TRACE("() Changed=%d\n", bCBHasChanged);
if (bCBHasChanged)
{
memset( synthesized_formats, 0, sizeof(synthesized_formats) );
add_synthesized_text();
}
SERVER_START_REQ( close_clipboard )
{
req->changed = bCBHasChanged;
......@@ -219,6 +386,7 @@ BOOL WINAPI EmptyClipboard(void)
{
USER_Driver->pEmptyClipboard();
bCBHasChanged = TRUE;
memset( synthesized_formats, 0, sizeof(synthesized_formats) );
}
return ret;
}
......@@ -337,14 +505,14 @@ BOOL WINAPI ChangeClipboardChain( HWND hwnd, HWND next )
/**************************************************************************
* SetClipboardData (USER32.@)
*/
HANDLE WINAPI SetClipboardData(UINT wFormat, HANDLE hData)
HANDLE WINAPI SetClipboardData( UINT format, HANDLE data )
{
HANDLE hResult = 0;
UINT flags;
TRACE("(%04X, %p) !\n", wFormat, hData);
TRACE( "%04x %p\n", format, data );
if (!wFormat)
if (!format)
{
SetLastError( ERROR_CLIPBOARD_NOT_OPEN );
return 0;
......@@ -357,10 +525,11 @@ HANDLE WINAPI SetClipboardData(UINT wFormat, HANDLE hData)
return 0;
}
if (USER_Driver->pSetClipboardData(wFormat, hData, flags & CB_OWNER))
if (USER_Driver->pSetClipboardData( format, data, flags & CB_OWNER))
{
hResult = hData;
hResult = data;
bCBHasChanged = TRUE;
if (format < CF_MAX) synthesized_formats[format] = 0;
}
return hResult;
......@@ -439,11 +608,11 @@ BOOL WINAPI GetUpdatedClipboardFormats( UINT *formats, UINT size, UINT *out_size
/**************************************************************************
* GetClipboardData (USER32.@)
*/
HANDLE WINAPI GetClipboardData(UINT wFormat)
HANDLE WINAPI GetClipboardData( UINT format )
{
HANDLE hData = 0;
HANDLE data = 0;
TRACE("%04x\n", wFormat);
TRACE( "%04x\n", format );
if (!(get_clipboard_flags() & CB_OPEN))
{
......@@ -451,11 +620,13 @@ HANDLE WINAPI GetClipboardData(UINT wFormat)
SetLastError(ERROR_CLIPBOARD_NOT_OPEN);
return 0;
}
if (format < CF_MAX && synthesized_formats[format])
data = render_synthesized_format( format, synthesized_formats[format] );
else
data = USER_Driver->pGetClipboardData( format );
hData = USER_Driver->pGetClipboardData( wFormat );
TRACE("returning %p\n", hData);
return hData;
TRACE( "returning %p\n", data );
return data;
}
......
......@@ -588,9 +588,9 @@ static void test_synthesized(void)
UINT todo;
} tests[] =
{
/* 0 */ { CF_TEXT, { CF_TEXT, CF_LOCALE, CF_OEMTEXT, CF_UNICODETEXT }, 1 << 1 },
{ CF_OEMTEXT, { CF_OEMTEXT, CF_LOCALE, CF_TEXT, CF_UNICODETEXT }, 1 << 1 },
{ CF_UNICODETEXT, { CF_UNICODETEXT, CF_LOCALE, CF_TEXT, CF_OEMTEXT }, 1 << 1 },
/* 0 */ { CF_TEXT, { CF_TEXT, CF_LOCALE, CF_OEMTEXT, CF_UNICODETEXT }},
{ CF_OEMTEXT, { CF_OEMTEXT, CF_LOCALE, CF_TEXT, CF_UNICODETEXT }},
{ CF_UNICODETEXT, { CF_UNICODETEXT, CF_LOCALE, CF_TEXT, CF_OEMTEXT }},
{ CF_ENHMETAFILE, { CF_ENHMETAFILE, CF_METAFILEPICT }},
{ CF_METAFILEPICT, { CF_METAFILEPICT, CF_ENHMETAFILE }},
/* 5 */ { CF_BITMAP, { CF_BITMAP, CF_DIB, CF_DIBV5 }, 1 << 2 },
......@@ -623,11 +623,11 @@ static void test_synthesized(void)
ok(r, "gle %d\n", GetLastError());
count = CountClipboardFormats();
todo_wine ok( count == 6, "count %u\n", count );
ok( count == 6, "count %u\n", count );
r = IsClipboardFormatAvailable( CF_TEXT );
ok( r, "CF_TEXT not available err %d\n", GetLastError());
r = IsClipboardFormatAvailable( CF_LOCALE );
todo_wine ok( r, "CF_LOCALE not available err %d\n", GetLastError());
ok( r, "CF_LOCALE not available err %d\n", GetLastError());
r = IsClipboardFormatAvailable( CF_OEMTEXT );
ok( r, "CF_OEMTEXT not available err %d\n", GetLastError());
r = IsClipboardFormatAvailable( CF_UNICODETEXT );
......@@ -650,13 +650,11 @@ static void test_synthesized(void)
ok(data != NULL, "couldn't get data, cf %08x\n", cf);
cf = EnumClipboardFormats(cf);
todo_wine ok(cf == CF_LOCALE, "cf %08x\n", cf);
if(cf == CF_LOCALE)
{
data = GetClipboardData(cf);
ok(data != NULL, "couldn't get data, cf %08x\n", cf);
cf = EnumClipboardFormats(cf);
}
ok(cf == CF_LOCALE, "cf %08x\n", cf);
data = GetClipboardData(cf);
ok(data != NULL, "couldn't get data, cf %08x\n", cf);
cf = EnumClipboardFormats(cf);
ok(cf == CF_OEMTEXT, "cf %08x\n", cf);
data = GetClipboardData(cf);
ok(data != NULL, "couldn't get data, cf %08x\n", cf);
......@@ -690,8 +688,8 @@ static void test_synthesized(void)
cf = EnumClipboardFormats(cf);
ok( cf == CF_OEMTEXT, "cf %08x\n", cf );
cf = EnumClipboardFormats(cf);
todo_wine ok( cf == CF_LOCALE, "cf %08x\n", cf );
if (cf == CF_LOCALE) cf = EnumClipboardFormats( cf );
ok( cf == CF_LOCALE, "cf %08x\n", cf );
cf = EnumClipboardFormats( cf );
ok( cf == 0, "cf %08x\n", cf );
r = EmptyClipboard();
......@@ -1696,7 +1694,7 @@ static void test_handles( HWND hwnd )
data = GetClipboardData( CF_UNICODETEXT );
ok( is_fixed( data ), "expected fixed mem %p\n", data );
data = GetClipboardData( CF_LOCALE );
todo_wine ok( is_fixed( data ), "expected fixed mem %p\n", data );
ok( is_fixed( data ), "expected fixed mem %p\n", data );
data = GetClipboardData( CF_BITMAP );
ok( data == bitmap, "expected bitmap %p\n", data );
data = GetClipboardData( CF_PALETTE );
......@@ -1964,11 +1962,11 @@ static void test_GetUpdatedClipboardFormats(void)
memset( formats, 0xcc, sizeof(formats) );
r = pGetUpdatedClipboardFormats( formats, 256, &count );
ok( r, "gle %d\n", GetLastError() );
todo_wine ok( count == 4, "wrong count %u\n", count );
ok( count == 4, "wrong count %u\n", count );
ok( formats[0] == CF_UNICODETEXT, "wrong format %u\n", formats[0] );
ok( formats[1] == CF_TEXT, "wrong format %u\n", formats[1] );
todo_wine ok( formats[2] == CF_LOCALE, "wrong format %u\n", formats[2] );
todo_wine ok( formats[3] == CF_OEMTEXT, "wrong format %u\n", formats[3] );
ok( formats[2] == CF_LOCALE, "wrong format %u\n", formats[2] );
ok( formats[3] == CF_OEMTEXT, "wrong format %u\n", formats[3] );
ok( formats[4] == 0xcccccccc, "wrong format %u\n", formats[4] );
count = 0xdeadbeef;
......@@ -1976,20 +1974,20 @@ static void test_GetUpdatedClipboardFormats(void)
r = pGetUpdatedClipboardFormats( formats, 2, &count );
ok( !r, "gle %d\n", GetLastError() );
ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "wrong error %u\n", GetLastError() );
todo_wine ok( count == 4, "wrong count %u\n", count );
ok( count == 4, "wrong count %u\n", count );
ok( formats[0] == 0xcccccccc, "wrong format %u\n", formats[0] );
count = 0xdeadbeef;
r = pGetUpdatedClipboardFormats( NULL, 256, &count );
ok( !r, "gle %d\n", GetLastError() );
ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
todo_wine ok( count == 4, "wrong count %u\n", count );
ok( count == 4, "wrong count %u\n", count );
count = 0xdeadbeef;
r = pGetUpdatedClipboardFormats( NULL, 256, &count );
ok( !r, "gle %d\n", GetLastError() );
ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
todo_wine ok( count == 4, "wrong count %u\n", count );
ok( count == 4, "wrong count %u\n", count );
}
START_TEST(clipboard)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment