winemac: Simplify format_for_type() and callers since there's at most one format for a given Mac pasteboard type.

Signed-off-by: Ken Thomases <ken@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Ken Thomases 2016-10-23 13:03:29 -05:00 committed by Alexandre Julliard
parent 9cedf37205
commit 33b9494ecf
1 changed files with 84 additions and 134 deletions

View File

@ -310,44 +310,39 @@ static WINE_CLIPFORMAT* register_format(UINT id, CFStringRef type)
/************************************************************************** /**************************************************************************
* format_for_type * format_for_type
*/ */
static WINE_CLIPFORMAT* format_for_type(WINE_CLIPFORMAT *current, CFStringRef type) static WINE_CLIPFORMAT* format_for_type(CFStringRef type)
{ {
struct list *ptr = current ? &current->entry : &format_list; WINE_CLIPFORMAT *format;
WINE_CLIPFORMAT *format = NULL;
TRACE("current %p/%s type %s\n", current, debugstr_format(current ? current->format_id : 0), debugstr_cf(type)); TRACE("type %s\n", debugstr_cf(type));
while ((ptr = list_next(&format_list, ptr))) LIST_FOR_EACH_ENTRY(format, &format_list, WINE_CLIPFORMAT, entry)
{ {
format = LIST_ENTRY(ptr, WINE_CLIPFORMAT, entry);
if (CFEqual(format->type, type)) if (CFEqual(format->type, type))
goto done; goto done;
} }
format = NULL; format = NULL;
if (!current) if (CFStringHasPrefix(type, CFSTR("org.winehq.builtin.")))
{ {
if (CFStringHasPrefix(type, CFSTR("org.winehq.builtin."))) ERR("Shouldn't happen. Built-in type %s should have matched something in format list.\n",
{ debugstr_cf(type));
ERR("Shouldn't happen. Built-in type %s should have matched something in format list.\n", }
debugstr_cf(type)); else if (CFStringHasPrefix(type, registered_name_type_prefix))
} {
else if (CFStringHasPrefix(type, registered_name_type_prefix)) LPWSTR name;
{ int len = CFStringGetLength(type) - CFStringGetLength(registered_name_type_prefix);
LPWSTR name;
int len = CFStringGetLength(type) - CFStringGetLength(registered_name_type_prefix);
name = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); name = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
CFStringGetCharacters(type, CFRangeMake(CFStringGetLength(registered_name_type_prefix), len), CFStringGetCharacters(type, CFRangeMake(CFStringGetLength(registered_name_type_prefix), len),
(UniChar*)name); (UniChar*)name);
name[len] = 0; name[len] = 0;
format = register_format(RegisterClipboardFormatW(name), type); format = register_format(RegisterClipboardFormatW(name), type);
if (!format) if (!format)
ERR("Failed to register format for type %s name %s\n", debugstr_cf(type), debugstr_w(name)); ERR("Failed to register format for type %s name %s\n", debugstr_cf(type), debugstr_w(name));
HeapFree(GetProcessHeap(), 0, name); HeapFree(GetProcessHeap(), 0, name);
}
} }
done: done:
@ -1261,10 +1256,9 @@ HANDLE macdrv_get_pasteboard_data(CFTypeRef pasteboard, UINT desired_format)
type = CFArrayGetValueAtIndex(types, i); type = CFArrayGetValueAtIndex(types, i);
format = NULL; if ((format = format_for_type(type)))
while ((!best_format || best_format->synthesized) && (format = format_for_type(format, type)))
{ {
TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format ? format->format_id : 0)); TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
if (format->format_id == desired_format) if (format->format_id == desired_format)
{ {
@ -1320,18 +1314,20 @@ BOOL macdrv_pasteboard_has_format(CFTypeRef pasteboard, UINT desired_format)
count = CFArrayGetCount(types); count = CFArrayGetCount(types);
TRACE("got %d types\n", count); TRACE("got %d types\n", count);
for (i = 0; !found && i < count; i++) for (i = 0; i < count; i++)
{ {
CFStringRef type = CFArrayGetValueAtIndex(types, i); CFStringRef type = CFArrayGetValueAtIndex(types, i);
WINE_CLIPFORMAT* format; WINE_CLIPFORMAT* format = format_for_type(type);
format = NULL; if (format)
while (!found && (format = format_for_type(format, type)))
{ {
TRACE("for type %s got format %s\n", debugstr_cf(type), debugstr_format(format->format_id)); TRACE("for type %s got format %s\n", debugstr_cf(type), debugstr_format(format->format_id));
if (format->format_id == desired_format) if (format->format_id == desired_format)
{
found = TRUE; found = TRUE;
break;
}
} }
} }
@ -1381,62 +1377,34 @@ CFArrayRef macdrv_copy_pasteboard_formats(CFTypeRef pasteboard)
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
CFStringRef type = CFArrayGetValueAtIndex(types, i); CFStringRef type = CFArrayGetValueAtIndex(types, i);
BOOL found = FALSE;
format = NULL; format = format_for_type(type);
while ((format = format_for_type(format, type))) if (!format)
{ {
/* Suppose type is "public.utf8-plain-text". format->format_id will be each of TRACE("ignoring type %s\n", debugstr_cf(type));
CF_TEXT, CF_OEMTEXT, and CF_UNICODETEXT in turn. We want to look up the natural continue;
type for each of those IDs (e.g. CF_TEXT -> "org.winehq.builtin.text") and then see
if that type is present in the pasteboard. If it is, then we don't want to add the
format to the list yet because it would be out of order.
For example, if a Mac app put "public.utf8-plain-text" and "public.tiff" on the
pasteboard, then we want the Win32 clipboard formats to be CF_TEXT, CF_OEMTEXT, and
CF_UNICODETEXT, and CF_TIFF, in that order. All of the text formats belong before
CF_TIFF because the Mac app expressed that text was "better" than the TIFF. In
this case, as soon as we encounter "public.utf8-plain-text" we should add all of
the associated text format IDs.
But if a Wine process put "org.winehq.builtin.unicodetext",
"public.utf8-plain-text", "public.utf16-plain-text", and "public.tiff", then we
want the clipboard formats to be CF_UNICODETEXT, CF_TIFF, CF_TEXT, and CF_OEMTEXT,
in that order. The Windows program presumably added CF_UNICODETEXT and CF_TIFF.
We're synthesizing CF_TEXT and CF_OEMTEXT from CF_UNICODETEXT but we want them to
come after the non-synthesized CF_TIFF. In this case, we don't want to add the
text formats upon encountering "public.utf8-plain-text",
We tell the two cases apart by seeing that one of the natural types for the text
formats (i.e. "org.winehq.builtin.unicodetext") is present on the pasteboard.
"found" indicates that. */
if (!format->synthesized)
{
TRACE("for type %s got primary format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
CFArrayAppendValue(formats, (void*)format->format_id);
found = TRUE;
}
else if (!found && format->natural_format &&
CFArrayContainsValue(types, CFRangeMake(0, count), format->natural_format->type))
{
TRACE("for type %s deferring synthesized formats because type %s is also present\n",
debugstr_cf(type), debugstr_cf(format->natural_format->type));
found = TRUE;
}
} }
if (!found) if (!format->synthesized)
{ {
while ((format = format_for_type(format, type))) TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
{ CFArrayAppendValue(formats, (void*)format->format_id);
/* Don't override a real value with a synthesized value. */ }
if (!CFArrayContainsValue(formats, CFRangeMake(0, CFArrayGetCount(formats)), (void*)format->format_id)) else if (format->natural_format &&
{ CFArrayContainsValue(types, CFRangeMake(0, count), format->natural_format->type))
TRACE("for type %s got synthesized format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id)); {
CFArrayAppendValue(formats, (void*)format->format_id); TRACE("for type %s deferring synthesized formats because type %s is also present\n",
} debugstr_cf(type), debugstr_cf(format->natural_format->type));
} }
else if (CFArrayContainsValue(formats, CFRangeMake(0, CFArrayGetCount(formats)), (void*)format->format_id))
{
TRACE("for type %s got duplicate synthesized format %p/%s; skipping\n", debugstr_cf(type), format,
debugstr_format(format->format_id));
}
else
{
TRACE("for type %s got synthesized format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
CFArrayAppendValue(formats, (void*)format->format_id);
} }
} }
@ -1445,19 +1413,15 @@ CFArrayRef macdrv_copy_pasteboard_formats(CFTypeRef pasteboard)
{ {
CFStringRef type = CFArrayGetValueAtIndex(types, i); CFStringRef type = CFArrayGetValueAtIndex(types, i);
format = NULL; format = format_for_type(type);
while ((format = format_for_type(format, type))) if (!format) continue;
{ if (!format->synthesized) continue;
if (format->synthesized)
{ /* Don't duplicate a real value with a synthesized value. */
/* Don't override a real value with a synthesized value. */ if (CFArrayContainsValue(formats, CFRangeMake(0, CFArrayGetCount(formats)), (void*)format->format_id)) continue;
if (!CFArrayContainsValue(formats, CFRangeMake(0, CFArrayGetCount(formats)), (void*)format->format_id))
{ TRACE("for type %s got synthesized format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
TRACE("for type %s got synthesized format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id)); CFArrayAppendValue(formats, (void*)format->format_id);
CFArrayAppendValue(formats, (void*)format->format_id);
}
}
}
} }
CFRelease(types); CFRelease(types);
@ -1528,53 +1492,39 @@ BOOL query_pasteboard_data(HWND hwnd, CFStringRef type)
CLIPBOARDINFO cbinfo; CLIPBOARDINFO cbinfo;
WINE_CLIPFORMAT* format; WINE_CLIPFORMAT* format;
CFArrayRef types = NULL; CFArrayRef types = NULL;
CFRange range;
TRACE("hwnd %p type %s\n", hwnd, debugstr_cf(type)); TRACE("hwnd %p type %s\n", hwnd, debugstr_cf(type));
if (get_clipboard_info(&cbinfo)) if (get_clipboard_info(&cbinfo))
hwnd = cbinfo.hwnd_owner; hwnd = cbinfo.hwnd_owner;
format = NULL; format = format_for_type(type);
while ((format = format_for_type(format, type))) if (!format) goto done;
TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id));
if (!format->synthesized)
{ {
TRACE("for type %s got format %p/%s\n", debugstr_cf(type), format, debugstr_format(format->format_id)); TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(format->format_id), hwnd);
SendMessageW(hwnd, WM_RENDERFORMAT, format->format_id, 0);
ret = TRUE;
goto done;
}
if (!format->synthesized) types = macdrv_copy_pasteboard_types(NULL);
{ if (!types)
TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(format->format_id), hwnd); {
SendMessageW(hwnd, WM_RENDERFORMAT, format->format_id, 0); WARN("Failed to copy pasteboard types\n");
ret = TRUE; goto done;
goto done; }
}
if (!types) if (format->natural_format &&
{ CFArrayContainsValue(types, CFRangeMake(0, CFArrayGetCount(types)), format->natural_format->type))
types = macdrv_copy_pasteboard_types(NULL); {
if (!types) TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(format->format_id), hwnd);
{ SendMessageW(hwnd, WM_RENDERFORMAT, format->format_id, 0);
WARN("Failed to copy pasteboard types\n"); ret = TRUE;
break; goto done;
}
range = CFRangeMake(0, CFArrayGetCount(types));
}
/* The type maps to a synthesized format. Now look up what type that format maps to natively
(not synthesized). For example, if type is "public.utf8-plain-text", then this format may
have an ID of CF_TEXT. From CF_TEXT, we want to find "org.winehq.builtin.text" to see if
that type is present in the pasteboard. If it is, then the app must have promised it and
we can ask it to render it. (If it had put it on the clipboard immediately, then the
pasteboard would also have data for "public.utf8-plain-text" and we wouldn't be here.) If
"org.winehq.builtin.text" is not on the pasteboard, then one of the other text formats is
presumably responsible for the promise that we're trying to satisfy, so we keep looking. */
if (format->natural_format && CFArrayContainsValue(types, range, format->natural_format->type))
{
TRACE("Sending WM_RENDERFORMAT message for format %s to hwnd %p\n", debugstr_format(format->format_id), hwnd);
SendMessageW(hwnd, WM_RENDERFORMAT, format->format_id, 0);
ret = TRUE;
goto done;
}
} }
done: done: