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:
parent
9cedf37205
commit
33b9494ecf
|
@ -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 ? ¤t->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:
|
||||||
|
|
Loading…
Reference in New Issue