winemac: Add support for CF_DIB and CF_BITMAP clipboard formats.
This commit is contained in:
parent
a8d55288de
commit
6528619494
|
@ -68,6 +68,8 @@ typedef struct
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
static HANDLE import_clipboard_data(CFDataRef data);
|
static HANDLE import_clipboard_data(CFDataRef data);
|
||||||
|
static HANDLE import_bmp_to_bitmap(CFDataRef data);
|
||||||
|
static HANDLE import_bmp_to_dib(CFDataRef data);
|
||||||
static HANDLE import_oemtext_to_text(CFDataRef data);
|
static HANDLE import_oemtext_to_text(CFDataRef data);
|
||||||
static HANDLE import_oemtext_to_unicodetext(CFDataRef data);
|
static HANDLE import_oemtext_to_unicodetext(CFDataRef data);
|
||||||
static HANDLE import_text_to_oemtext(CFDataRef data);
|
static HANDLE import_text_to_oemtext(CFDataRef data);
|
||||||
|
@ -79,6 +81,8 @@ static HANDLE import_utf8_to_text(CFDataRef data);
|
||||||
static HANDLE import_utf8_to_unicodetext(CFDataRef data);
|
static HANDLE import_utf8_to_unicodetext(CFDataRef data);
|
||||||
|
|
||||||
static CFDataRef export_clipboard_data(HANDLE data);
|
static CFDataRef export_clipboard_data(HANDLE data);
|
||||||
|
static CFDataRef export_bitmap_to_bmp(HANDLE data);
|
||||||
|
static CFDataRef export_dib_to_bmp(HANDLE data);
|
||||||
static CFDataRef export_oemtext_to_utf8(HANDLE data);
|
static CFDataRef export_oemtext_to_utf8(HANDLE data);
|
||||||
static CFDataRef export_text_to_utf8(HANDLE data);
|
static CFDataRef export_text_to_utf8(HANDLE data);
|
||||||
static CFDataRef export_unicodetext_to_utf8(HANDLE data);
|
static CFDataRef export_unicodetext_to_utf8(HANDLE data);
|
||||||
|
@ -171,6 +175,12 @@ static const struct
|
||||||
{ CF_UNICODETEXT, CFSTR("public.utf8-plain-text"), import_utf8_to_unicodetext, export_unicodetext_to_utf8, TRUE },
|
{ CF_UNICODETEXT, CFSTR("public.utf8-plain-text"), import_utf8_to_unicodetext, export_unicodetext_to_utf8, TRUE },
|
||||||
{ CF_TEXT, CFSTR("public.utf8-plain-text"), import_utf8_to_text, export_text_to_utf8, TRUE },
|
{ CF_TEXT, CFSTR("public.utf8-plain-text"), import_utf8_to_text, export_text_to_utf8, TRUE },
|
||||||
{ CF_OEMTEXT, CFSTR("public.utf8-plain-text"), import_utf8_to_oemtext, export_oemtext_to_utf8, TRUE },
|
{ CF_OEMTEXT, CFSTR("public.utf8-plain-text"), import_utf8_to_oemtext, export_oemtext_to_utf8, TRUE },
|
||||||
|
|
||||||
|
{ CF_DIB, CFSTR("org.winehq.builtin.dib"), import_clipboard_data, export_clipboard_data, FALSE },
|
||||||
|
{ CF_DIB, CFSTR("com.microsoft.bmp"), import_bmp_to_dib, export_dib_to_bmp, TRUE },
|
||||||
|
|
||||||
|
{ CF_BITMAP, CFSTR("org.winehq.builtin.bitmap"), import_bmp_to_bitmap, export_bitmap_to_bmp, FALSE },
|
||||||
|
{ CF_BITMAP, CFSTR("com.microsoft.bmp"), import_bmp_to_bitmap, export_bitmap_to_bmp, TRUE },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const WCHAR wszRichTextFormat[] = {'R','i','c','h',' ','T','e','x','t',' ','F','o','r','m','a','t',0};
|
static const WCHAR wszRichTextFormat[] = {'R','i','c','h',' ','T','e','x','t',' ','F','o','r','m','a','t',0};
|
||||||
|
@ -452,6 +462,113 @@ static HANDLE convert_unicodetext_to_codepage(HANDLE unicode_handle, UINT cp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* bitmap_info_size
|
||||||
|
*
|
||||||
|
* Return the size of the bitmap info structure including color table.
|
||||||
|
*/
|
||||||
|
static int bitmap_info_size(const BITMAPINFO *info, WORD coloruse)
|
||||||
|
{
|
||||||
|
unsigned int colors, size, masks = 0;
|
||||||
|
|
||||||
|
if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
|
||||||
|
{
|
||||||
|
const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER*)info;
|
||||||
|
colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
|
||||||
|
return sizeof(BITMAPCOREHEADER) + colors *
|
||||||
|
((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
|
||||||
|
}
|
||||||
|
else /* assume BITMAPINFOHEADER */
|
||||||
|
{
|
||||||
|
colors = info->bmiHeader.biClrUsed;
|
||||||
|
if (!colors && (info->bmiHeader.biBitCount <= 8))
|
||||||
|
colors = 1 << info->bmiHeader.biBitCount;
|
||||||
|
if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
|
||||||
|
size = max(info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD));
|
||||||
|
return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* create_dib_from_bitmap
|
||||||
|
*
|
||||||
|
* Allocates a packed DIB and copies the bitmap data into it.
|
||||||
|
*/
|
||||||
|
static HGLOBAL create_dib_from_bitmap(HBITMAP hBmp)
|
||||||
|
{
|
||||||
|
BITMAP bmp;
|
||||||
|
HDC hdc;
|
||||||
|
HGLOBAL hPackedDIB;
|
||||||
|
LPBYTE pPackedDIB;
|
||||||
|
LPBITMAPINFOHEADER pbmiHeader;
|
||||||
|
unsigned int cDataSize, cPackedSize, OffsetBits;
|
||||||
|
int nLinesCopied;
|
||||||
|
|
||||||
|
if (!GetObjectW(hBmp, sizeof(bmp), &bmp)) return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A packed DIB contains a BITMAPINFO structure followed immediately by
|
||||||
|
* an optional color palette and the pixel data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Calculate the size of the packed DIB */
|
||||||
|
cDataSize = abs(bmp.bmHeight) * (((bmp.bmWidth * bmp.bmBitsPixel + 31) / 8) & ~3);
|
||||||
|
cPackedSize = sizeof(BITMAPINFOHEADER)
|
||||||
|
+ ((bmp.bmBitsPixel <= 8) ? (sizeof(RGBQUAD) * (1 << bmp.bmBitsPixel)) : 0)
|
||||||
|
+ cDataSize;
|
||||||
|
/* Get the offset to the bits */
|
||||||
|
OffsetBits = cPackedSize - cDataSize;
|
||||||
|
|
||||||
|
/* Allocate the packed DIB */
|
||||||
|
TRACE("\tAllocating packed DIB of size %d\n", cPackedSize);
|
||||||
|
hPackedDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cPackedSize);
|
||||||
|
if (!hPackedDIB)
|
||||||
|
{
|
||||||
|
WARN("Could not allocate packed DIB!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A packed DIB starts with a BITMAPINFOHEADER */
|
||||||
|
pPackedDIB = GlobalLock(hPackedDIB);
|
||||||
|
pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
|
||||||
|
|
||||||
|
/* Init the BITMAPINFOHEADER */
|
||||||
|
pbmiHeader->biSize = sizeof(BITMAPINFOHEADER);
|
||||||
|
pbmiHeader->biWidth = bmp.bmWidth;
|
||||||
|
pbmiHeader->biHeight = bmp.bmHeight;
|
||||||
|
pbmiHeader->biPlanes = 1;
|
||||||
|
pbmiHeader->biBitCount = bmp.bmBitsPixel;
|
||||||
|
pbmiHeader->biCompression = BI_RGB;
|
||||||
|
pbmiHeader->biSizeImage = 0;
|
||||||
|
pbmiHeader->biXPelsPerMeter = pbmiHeader->biYPelsPerMeter = 0;
|
||||||
|
pbmiHeader->biClrUsed = 0;
|
||||||
|
pbmiHeader->biClrImportant = 0;
|
||||||
|
|
||||||
|
/* Retrieve the DIB bits from the bitmap and fill in the
|
||||||
|
* DIB color table if present */
|
||||||
|
hdc = GetDC(0);
|
||||||
|
nLinesCopied = GetDIBits(hdc, /* Handle to device context */
|
||||||
|
hBmp, /* Handle to bitmap */
|
||||||
|
0, /* First scan line to set in dest bitmap */
|
||||||
|
bmp.bmHeight, /* Number of scan lines to copy */
|
||||||
|
pPackedDIB + OffsetBits, /* [out] Address of array for bitmap bits */
|
||||||
|
(LPBITMAPINFO) pbmiHeader, /* [out] Address of BITMAPINFO structure */
|
||||||
|
0); /* RGB or palette index */
|
||||||
|
GlobalUnlock(hPackedDIB);
|
||||||
|
ReleaseDC(0, hdc);
|
||||||
|
|
||||||
|
/* Cleanup if GetDIBits failed */
|
||||||
|
if (nLinesCopied != bmp.bmHeight)
|
||||||
|
{
|
||||||
|
TRACE("\tGetDIBits returned %d. Actual lines=%d\n", nLinesCopied, bmp.bmHeight);
|
||||||
|
GlobalFree(hPackedDIB);
|
||||||
|
hPackedDIB = 0;
|
||||||
|
}
|
||||||
|
return hPackedDIB;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* import_clipboard_data
|
* import_clipboard_data
|
||||||
*
|
*
|
||||||
|
@ -487,6 +604,72 @@ static HANDLE import_clipboard_data(CFDataRef data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* import_bmp_to_bitmap
|
||||||
|
*
|
||||||
|
* Import BMP data, converting to CF_BITMAP format.
|
||||||
|
*/
|
||||||
|
static HANDLE import_bmp_to_bitmap(CFDataRef data)
|
||||||
|
{
|
||||||
|
HANDLE ret = 0;
|
||||||
|
HANDLE dib = import_bmp_to_dib(data);
|
||||||
|
BITMAPINFO *bmi;
|
||||||
|
|
||||||
|
if (dib && (bmi = GlobalLock(dib)))
|
||||||
|
{
|
||||||
|
HDC hdc;
|
||||||
|
unsigned int offset;
|
||||||
|
|
||||||
|
hdc = GetDC(NULL);
|
||||||
|
|
||||||
|
offset = bitmap_info_size(bmi, DIB_RGB_COLORS);
|
||||||
|
|
||||||
|
ret = CreateDIBitmap(hdc, &bmi->bmiHeader, CBM_INIT, (LPBYTE)bmi + offset,
|
||||||
|
bmi, DIB_RGB_COLORS);
|
||||||
|
|
||||||
|
GlobalUnlock(dib);
|
||||||
|
ReleaseDC(NULL, hdc);
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalFree(dib);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* import_bmp_to_dib
|
||||||
|
*
|
||||||
|
* Import BMP data, converting to CF_DIB format. This just entails
|
||||||
|
* stripping the BMP file format header.
|
||||||
|
*/
|
||||||
|
static HANDLE import_bmp_to_dib(CFDataRef data)
|
||||||
|
{
|
||||||
|
HANDLE ret = 0;
|
||||||
|
BITMAPFILEHEADER *bfh = (BITMAPFILEHEADER*)CFDataGetBytePtr(data);
|
||||||
|
CFIndex len = CFDataGetLength(data);
|
||||||
|
|
||||||
|
if (len >= sizeof(*bfh) + sizeof(BITMAPCOREHEADER) &&
|
||||||
|
bfh->bfType == 0x4d42 /* "BM" */)
|
||||||
|
{
|
||||||
|
BITMAPINFO *bmi = (BITMAPINFO*)(bfh + 1);
|
||||||
|
BYTE* p;
|
||||||
|
|
||||||
|
len -= sizeof(*bfh);
|
||||||
|
ret = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len);
|
||||||
|
if (!ret || !(p = GlobalLock(ret)))
|
||||||
|
{
|
||||||
|
GlobalFree(ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(p, bmi, len);
|
||||||
|
GlobalUnlock(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* import_oemtext_to_text
|
* import_oemtext_to_text
|
||||||
*
|
*
|
||||||
|
@ -657,6 +840,27 @@ static CFDataRef export_clipboard_data(HANDLE data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* export_bitmap_to_bmp
|
||||||
|
*
|
||||||
|
* Export CF_BITMAP to BMP file format.
|
||||||
|
*/
|
||||||
|
static CFDataRef export_bitmap_to_bmp(HANDLE data)
|
||||||
|
{
|
||||||
|
CFDataRef ret = NULL;
|
||||||
|
HGLOBAL dib;
|
||||||
|
|
||||||
|
dib = create_dib_from_bitmap(data);
|
||||||
|
if (dib)
|
||||||
|
{
|
||||||
|
ret = export_dib_to_bmp(dib);
|
||||||
|
GlobalFree(dib);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* export_codepage_to_utf8
|
* export_codepage_to_utf8
|
||||||
*
|
*
|
||||||
|
@ -681,6 +885,44 @@ static CFDataRef export_codepage_to_utf8(HANDLE data, UINT cp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* export_dib_to_bmp
|
||||||
|
*
|
||||||
|
* Export CF_DIB to BMP file format. This just entails prepending a BMP
|
||||||
|
* file format header to the data.
|
||||||
|
*/
|
||||||
|
static CFDataRef export_dib_to_bmp(HANDLE data)
|
||||||
|
{
|
||||||
|
CFMutableDataRef ret = NULL;
|
||||||
|
BYTE *dibdata;
|
||||||
|
CFIndex len;
|
||||||
|
BITMAPFILEHEADER bfh;
|
||||||
|
|
||||||
|
dibdata = GlobalLock(data);
|
||||||
|
if (!dibdata)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
len = sizeof(bfh) + GlobalSize(data);
|
||||||
|
ret = CFDataCreateMutable(NULL, len);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
bfh.bfType = 0x4d42; /* "BM" */
|
||||||
|
bfh.bfSize = len;
|
||||||
|
bfh.bfReserved1 = 0;
|
||||||
|
bfh.bfReserved2 = 0;
|
||||||
|
bfh.bfOffBits = sizeof(bfh) + bitmap_info_size((BITMAPINFO*)dibdata, DIB_RGB_COLORS);
|
||||||
|
CFDataAppendBytes(ret, (UInt8*)&bfh, sizeof(bfh));
|
||||||
|
|
||||||
|
/* rest of bitmap is the same as the packed dib */
|
||||||
|
CFDataAppendBytes(ret, (UInt8*)dibdata, len - sizeof(bfh));
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalUnlock(data);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* export_oemtext_to_utf8
|
* export_oemtext_to_utf8
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue