Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
8865f4a4
Commit
8865f4a4
authored
Sep 06, 2016
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
user32: Synthesize text clipboard formats on the user32 side.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
b1e8ed3e
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
210 additions
and
44 deletions
+210
-44
clipboard.c
dlls/ole32/tests/clipboard.c
+7
-10
clipboard.c
dlls/user32/clipboard.c
+184
-13
clipboard.c
dlls/user32/tests/clipboard.c
+19
-21
No files found.
dlls/ole32/tests/clipboard.c
View file @
8865f4a4
...
...
@@ -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
);
...
...
dlls/user32/clipboard.c
View file @
8865f4a4
...
...
@@ -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
(
!
wF
ormat
)
if
(
!
f
ormat
)
{
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
,
hD
ata
,
flags
&
CB_OWNER
))
if
(
USER_Driver
->
pSetClipboardData
(
format
,
d
ata
,
flags
&
CB_OWNER
))
{
hResult
=
hD
ata
;
hResult
=
d
ata
;
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
hD
ata
=
0
;
HANDLE
d
ata
=
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
;
}
...
...
dlls/user32/tests/clipboard.c
View file @
8865f4a4
...
...
@@ -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
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment