1a7e9c4d8SPedro Giffuni /*************************************************************************
2a7e9c4d8SPedro Giffuni 
3a7e9c4d8SPedro Giffuni    Copyright 2011 Yuri Dario <mc6530@mclink.it>
4a7e9c4d8SPedro Giffuni 
5a7e9c4d8SPedro Giffuni    Licensed under the Apache License, Version 2.0 (the "License");
6a7e9c4d8SPedro Giffuni    you may not use this file except in compliance with the License.
7a7e9c4d8SPedro Giffuni    You may obtain a copy of the License at
8a7e9c4d8SPedro Giffuni 
9a7e9c4d8SPedro Giffuni        http://www.apache.org/licenses/LICENSE-2.0
10a7e9c4d8SPedro Giffuni 
11a7e9c4d8SPedro Giffuni    Unless required by applicable law or agreed to in writing, software
12a7e9c4d8SPedro Giffuni    distributed under the License is distributed on an "AS IS" BASIS,
13a7e9c4d8SPedro Giffuni    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14a7e9c4d8SPedro Giffuni    See the License for the specific language governing permissions and
15a7e9c4d8SPedro Giffuni    limitations under the License.
16a7e9c4d8SPedro Giffuni 
17a7e9c4d8SPedro Giffuni  ************************************************************************/
18a7e9c4d8SPedro Giffuni 
19a7e9c4d8SPedro Giffuni #define INCL_WIN
20a7e9c4d8SPedro Giffuni #include <svpm.h>
21*e18b2dafSYuri Dario #include <string.h>
22a7e9c4d8SPedro Giffuni 
23a7e9c4d8SPedro Giffuni #ifndef _OS2CLIPBOARD_HXX_
24a7e9c4d8SPedro Giffuni #include "Os2Clipboard.hxx"
25a7e9c4d8SPedro Giffuni #endif
26a7e9c4d8SPedro Giffuni 
27a7e9c4d8SPedro Giffuni // same typedefs from win32 sdk
28a7e9c4d8SPedro Giffuni typedef unsigned short WORD;
29a7e9c4d8SPedro Giffuni typedef unsigned long DWORD;
30a7e9c4d8SPedro Giffuni 
31a7e9c4d8SPedro Giffuni #pragma pack(push, 1)
32a7e9c4d8SPedro Giffuni 
33a7e9c4d8SPedro Giffuni typedef struct {
34a7e9c4d8SPedro Giffuni   PM_BYTE rgbBlue;
35a7e9c4d8SPedro Giffuni   PM_BYTE rgbGreen;
36a7e9c4d8SPedro Giffuni   PM_BYTE rgbRed;
37a7e9c4d8SPedro Giffuni   PM_BYTE rgbReserved;
38a7e9c4d8SPedro Giffuni } RGBQUAD, *LPRGBQUAD;
39a7e9c4d8SPedro Giffuni 
40a7e9c4d8SPedro Giffuni typedef struct
41a7e9c4d8SPedro Giffuni {
42a7e9c4d8SPedro Giffuni     WORD    bfType;
43a7e9c4d8SPedro Giffuni     DWORD   bfSize;
44a7e9c4d8SPedro Giffuni     WORD    bfReserved1;
45a7e9c4d8SPedro Giffuni     WORD    bfReserved2;
46a7e9c4d8SPedro Giffuni     DWORD   bfOffBits;
47a7e9c4d8SPedro Giffuni } W32_BITMAPFILEHEADER, *PW32_BITMAPFILEHEADER;
48a7e9c4d8SPedro Giffuni 
49a7e9c4d8SPedro Giffuni typedef struct
50a7e9c4d8SPedro Giffuni {
51a7e9c4d8SPedro Giffuni     DWORD 	biSize;
52a7e9c4d8SPedro Giffuni     LONG  	biWidth;
53a7e9c4d8SPedro Giffuni     LONG  	biHeight;
54a7e9c4d8SPedro Giffuni     WORD 	biPlanes;
55a7e9c4d8SPedro Giffuni     WORD 	biBitCount;
56a7e9c4d8SPedro Giffuni     DWORD 	biCompression;
57a7e9c4d8SPedro Giffuni     DWORD 	biSizeImage;
58a7e9c4d8SPedro Giffuni     LONG  	biXPelsPerMeter;
59a7e9c4d8SPedro Giffuni     LONG  	biYPelsPerMeter;
60a7e9c4d8SPedro Giffuni     DWORD 	biClrUsed;
61a7e9c4d8SPedro Giffuni     DWORD 	biClrImportant;
62a7e9c4d8SPedro Giffuni } W32_BITMAPINFOHEADER, *PW32_BITMAPINFOHEADER;
63a7e9c4d8SPedro Giffuni 
64a7e9c4d8SPedro Giffuni #pragma pack(pop)
65a7e9c4d8SPedro Giffuni 
66a7e9c4d8SPedro Giffuni // store screen bitcount
67a7e9c4d8SPedro Giffuni LONG	lBitCountScreen;
68a7e9c4d8SPedro Giffuni 
69a7e9c4d8SPedro Giffuni /*
70a7e9c4d8SPedro Giffuni  * Convert an OOo bitmap to an OS/2 bitmap handle
71a7e9c4d8SPedro Giffuni  *
72a7e9c4d8SPedro Giffuni  * An OOo bitmap is a BITMAPFILEHEADER structure followed by a Windows DIB
73a7e9c4d8SPedro Giffuni  *
74a7e9c4d8SPedro Giffuni  * OS/2 InfoHeader is a superset of Win32 InhoHeader, so we can just copy
75a7e9c4d8SPedro Giffuni  * the win32 memory over the os2 memory and fix the cbFix field.
76a7e9c4d8SPedro Giffuni  * colortable and bitmap data share the same format.
77a7e9c4d8SPedro Giffuni  *
78a7e9c4d8SPedro Giffuni */
OOoBmpToOS2Handle(Any & aAnyB)79a7e9c4d8SPedro Giffuni HBITMAP	OOoBmpToOS2Handle( Any &aAnyB)
80a7e9c4d8SPedro Giffuni {
81a7e9c4d8SPedro Giffuni 	// copy bitmap to clipboard
82a7e9c4d8SPedro Giffuni 	Sequence<sal_Int8> ByteStream;
83a7e9c4d8SPedro Giffuni 	aAnyB >>= ByteStream;
84a7e9c4d8SPedro Giffuni 
85a7e9c4d8SPedro Giffuni 	// get w32 file header data
86a7e9c4d8SPedro Giffuni 	PW32_BITMAPFILEHEADER pbfh = (PW32_BITMAPFILEHEADER)ByteStream.getArray();
87a7e9c4d8SPedro Giffuni 	// get w32 info header
88a7e9c4d8SPedro Giffuni 	PW32_BITMAPINFOHEADER pbih = (PW32_BITMAPINFOHEADER) (pbfh+1);
89a7e9c4d8SPedro Giffuni 
90a7e9c4d8SPedro Giffuni 	// create os2 infoheader2 (same fields of w32)
91a7e9c4d8SPedro Giffuni 	BITMAPINFOHEADER2 bih2;
92a7e9c4d8SPedro Giffuni 	memset( &bih2, 0, sizeof( bih2));
93a7e9c4d8SPedro Giffuni 	memcpy( &bih2, pbih, pbih->biSize);
94a7e9c4d8SPedro Giffuni 	bih2.cbFix = sizeof(bih2);
95a7e9c4d8SPedro Giffuni 
96a7e9c4d8SPedro Giffuni 	// Determine size of color table
97a7e9c4d8SPedro Giffuni 	int iNumColors, numbits=bih2.cPlanes * bih2.cBitCount;
98a7e9c4d8SPedro Giffuni 	if (numbits != 24)
99a7e9c4d8SPedro Giffuni 		iNumColors = bih2.cclrUsed ? bih2.cclrUsed : 2<<numbits;
100a7e9c4d8SPedro Giffuni 	else
101a7e9c4d8SPedro Giffuni 		iNumColors = bih2.cclrUsed;
102a7e9c4d8SPedro Giffuni 	int iColorTableSize = iNumColors*sizeof(RGB2);
103a7e9c4d8SPedro Giffuni 
104a7e9c4d8SPedro Giffuni 	// allocate bitmap info2 (header2+colortable)
105a7e9c4d8SPedro Giffuni 	PBITMAPINFO2 pbi2=(PBITMAPINFO2) malloc( sizeof(BITMAPINFOHEADER2)+iColorTableSize);
106a7e9c4d8SPedro Giffuni 	// setup header fields
107a7e9c4d8SPedro Giffuni 	memcpy( pbi2, &bih2, sizeof(BITMAPINFOHEADER2));
108a7e9c4d8SPedro Giffuni 	// copy color palette (follows pbih)
109a7e9c4d8SPedro Giffuni 	memcpy( &pbi2->argbColor[0], (pbih+1), iColorTableSize);
110a7e9c4d8SPedro Giffuni 
111a7e9c4d8SPedro Giffuni 	// get bitmap data
112a7e9c4d8SPedro Giffuni 	PBYTE pbPelData = (PBYTE)ByteStream.getArray() + pbfh->bfOffBits;
113a7e9c4d8SPedro Giffuni 	HPS hps = WinGetPS(HWND_DESKTOP);
114a7e9c4d8SPedro Giffuni 	HBITMAP hbm = GpiCreateBitmap( hps, &bih2, CBM_INIT, pbPelData, pbi2);
115a7e9c4d8SPedro Giffuni 	debug_printf( "OOoBmpToOS2Handle hbm %x\n", hbm);
116a7e9c4d8SPedro Giffuni 	WinReleasePS(hps);
117a7e9c4d8SPedro Giffuni 
118a7e9c4d8SPedro Giffuni 	// return handle
119a7e9c4d8SPedro Giffuni 	return hbm;
120a7e9c4d8SPedro Giffuni }
121a7e9c4d8SPedro Giffuni 
122a7e9c4d8SPedro Giffuni /*
123a7e9c4d8SPedro Giffuni  * Convert an OS/2 bitmap handle to OOo bitmap
124a7e9c4d8SPedro Giffuni  *
125a7e9c4d8SPedro Giffuni  * First we need to copy the bitmap to a PS, then we can get bitmap data.
126a7e9c4d8SPedro Giffuni  *
127a7e9c4d8SPedro Giffuni */
OS2HandleToOOoBmp(HBITMAP hbm,Sequence<sal_Int8> * OOoDIBStream)128a7e9c4d8SPedro Giffuni int	OS2HandleToOOoBmp( HBITMAP hbm, Sequence< sal_Int8 >* OOoDIBStream)
129a7e9c4d8SPedro Giffuni {
130a7e9c4d8SPedro Giffuni 	HAB 	hab = WinQueryAnchorBlock(HWND_DESKTOP);
131a7e9c4d8SPedro Giffuni 	HDC 	hdc;
132a7e9c4d8SPedro Giffuni 	SIZEL 	sizl;
133a7e9c4d8SPedro Giffuni 	HPS 	hps;
134a7e9c4d8SPedro Giffuni 	PM_BYTE*	pbBuffer;
135a7e9c4d8SPedro Giffuni 	ULONG	cbBuffer;
136a7e9c4d8SPedro Giffuni 
137a7e9c4d8SPedro Giffuni 	struct {
138a7e9c4d8SPedro Giffuni 		BITMAPINFOHEADER2 bmp2;
139a7e9c4d8SPedro Giffuni 		RGB2 argb2Color[0x100];
140a7e9c4d8SPedro Giffuni 	} bm;
141a7e9c4d8SPedro Giffuni 
142a7e9c4d8SPedro Giffuni 	if (!lBitCountScreen) {
143a7e9c4d8SPedro Giffuni 		HPS hps = WinGetPS(HWND_DESKTOP);
144a7e9c4d8SPedro Giffuni 		HDC hdc = GpiQueryDevice(hps);
145a7e9c4d8SPedro Giffuni 		DevQueryCaps(hdc, CAPS_COLOR_BITCOUNT, 1L, &lBitCountScreen);
146a7e9c4d8SPedro Giffuni 		WinReleasePS(hps);
147a7e9c4d8SPedro Giffuni 	}
148a7e9c4d8SPedro Giffuni 
149a7e9c4d8SPedro Giffuni 	// STEP 1: get OS/2 bitmap data and header
150a7e9c4d8SPedro Giffuni 	// get bitmap header
151a7e9c4d8SPedro Giffuni 	memset(&(bm.bmp2), 0, sizeof(bm.bmp2));
152a7e9c4d8SPedro Giffuni 	bm.bmp2.cbFix = 16;
153a7e9c4d8SPedro Giffuni 	GpiQueryBitmapInfoHeader(hbm, &bm.bmp2);
154a7e9c4d8SPedro Giffuni 
155a7e9c4d8SPedro Giffuni 	/* Data only actually stored in clipboard quality */
156a7e9c4d8SPedro Giffuni 	if ( lBitCountScreen < bm.bmp2.cBitCount )
157a7e9c4d8SPedro Giffuni 		bm.bmp2.cBitCount = lBitCountScreen;
158a7e9c4d8SPedro Giffuni 
159a7e9c4d8SPedro Giffuni 	if ( bm.bmp2.cBitCount == 16 )
160a7e9c4d8SPedro Giffuni 		bm.bmp2.cBitCount = 24;
161a7e9c4d8SPedro Giffuni 
162a7e9c4d8SPedro Giffuni 	if ( bm.bmp2.cPlanes != 1 ) {
163a7e9c4d8SPedro Giffuni 		return 0;
164a7e9c4d8SPedro Giffuni 	}
165a7e9c4d8SPedro Giffuni 
166a7e9c4d8SPedro Giffuni 	if ( (hdc = DevOpenDC(hab, OD_MEMORY, "*", 0L, (PDEVOPENDATA) NULL, (HDC) NULL)) == (HDC) NULL ) {
167a7e9c4d8SPedro Giffuni 		return 0;
168a7e9c4d8SPedro Giffuni 	}
169a7e9c4d8SPedro Giffuni 
170a7e9c4d8SPedro Giffuni 	sizl.cx = bm.bmp2.cx;
171a7e9c4d8SPedro Giffuni 	sizl.cy = bm.bmp2.cy;
172a7e9c4d8SPedro Giffuni 	if ( (hps = GpiCreatePS(hab, hdc, &sizl, PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC)) == (HPS) NULL ) {
173a7e9c4d8SPedro Giffuni 		DevCloseDC(hdc);
174a7e9c4d8SPedro Giffuni 		return 0;
175a7e9c4d8SPedro Giffuni 	}
176a7e9c4d8SPedro Giffuni 	// copy bitmap to hps
177a7e9c4d8SPedro Giffuni 	GpiSetBitmap(hps, hbm);
178a7e9c4d8SPedro Giffuni 
179a7e9c4d8SPedro Giffuni 	// buffer lengths
180a7e9c4d8SPedro Giffuni 	cbBuffer = (((bm.bmp2.cBitCount * bm.bmp2.cx) + 31) / 32) * 4 * bm.bmp2.cy * bm.bmp2.cPlanes;
181a7e9c4d8SPedro Giffuni 	pbBuffer = (PM_BYTE*) malloc( cbBuffer);
182a7e9c4d8SPedro Giffuni 	// now get bitmap data
183a7e9c4d8SPedro Giffuni 	GpiQueryBitmapBits(hps, 0L, (LONG) bm.bmp2.cy, pbBuffer, (BITMAPINFO2*)&bm);
184a7e9c4d8SPedro Giffuni 	// free OS/2 resources
185a7e9c4d8SPedro Giffuni 	GpiSetBitmap(hps, (HBITMAP) NULL);
186a7e9c4d8SPedro Giffuni 	GpiDestroyPS(hps);
187a7e9c4d8SPedro Giffuni 	DevCloseDC(hdc);
188a7e9c4d8SPedro Giffuni 
189a7e9c4d8SPedro Giffuni 	// STEP 2: now convert to Win32 DIB
190a7e9c4d8SPedro Giffuni 	// Determine size of color table
191a7e9c4d8SPedro Giffuni 	int iNumColors, numbits=bm.bmp2.cPlanes * bm.bmp2.cBitCount;
192a7e9c4d8SPedro Giffuni 	if (numbits != 24)
193a7e9c4d8SPedro Giffuni 		iNumColors = bm.bmp2.cclrUsed ? bm.bmp2.cclrUsed : 2<<numbits;
194a7e9c4d8SPedro Giffuni 	else
195a7e9c4d8SPedro Giffuni 		iNumColors = bm.bmp2.cclrUsed;
196a7e9c4d8SPedro Giffuni 	int iColorTableSize = iNumColors*sizeof(RGBQUAD);
197a7e9c4d8SPedro Giffuni 
198a7e9c4d8SPedro Giffuni 	// reallocate data stream object size
199a7e9c4d8SPedro Giffuni 	OOoDIBStream->realloc( sizeof( W32_BITMAPFILEHEADER )
200a7e9c4d8SPedro Giffuni 				+ sizeof( W32_BITMAPINFOHEADER) + iColorTableSize + cbBuffer);
201a7e9c4d8SPedro Giffuni 
202a7e9c4d8SPedro Giffuni 	// fill w32 file header data
203a7e9c4d8SPedro Giffuni 	PW32_BITMAPFILEHEADER pbfh = (PW32_BITMAPFILEHEADER) OOoDIBStream->getArray();
204a7e9c4d8SPedro Giffuni 	memset( pbfh, 0, sizeof( W32_BITMAPFILEHEADER));
205a7e9c4d8SPedro Giffuni 	pbfh->bfType = 'MB';
206a7e9c4d8SPedro Giffuni 	pbfh->bfSize = sizeof( W32_BITMAPFILEHEADER )
207a7e9c4d8SPedro Giffuni 				+ sizeof( W32_BITMAPINFOHEADER) + iColorTableSize + cbBuffer;
208a7e9c4d8SPedro Giffuni 	pbfh->bfOffBits = sizeof( W32_BITMAPFILEHEADER) + sizeof( W32_BITMAPINFOHEADER) + iColorTableSize;
209a7e9c4d8SPedro Giffuni 
210a7e9c4d8SPedro Giffuni 	// fill w32 info header
211a7e9c4d8SPedro Giffuni 	PW32_BITMAPINFOHEADER pbih = (PW32_BITMAPINFOHEADER) (pbfh+1);
212a7e9c4d8SPedro Giffuni 	// copy header fields (only win32 ones) and fix size
213a7e9c4d8SPedro Giffuni 	memcpy( pbih, &bm.bmp2, sizeof(W32_BITMAPINFOHEADER));
214a7e9c4d8SPedro Giffuni 	pbih->biSize = sizeof(W32_BITMAPINFOHEADER);
215a7e9c4d8SPedro Giffuni 
216a7e9c4d8SPedro Giffuni 	// fill color palette (follows pbih)
217a7e9c4d8SPedro Giffuni 	memcpy( (pbih+1), &bm.argb2Color[0], iColorTableSize);
218a7e9c4d8SPedro Giffuni 
219a7e9c4d8SPedro Giffuni 	// fill bitmap data
220a7e9c4d8SPedro Giffuni 	memcpy( (char*) pbfh + pbfh->bfOffBits, pbBuffer, cbBuffer);
221a7e9c4d8SPedro Giffuni 
222a7e9c4d8SPedro Giffuni 	// done
223a7e9c4d8SPedro Giffuni 	free( pbBuffer);
224a7e9c4d8SPedro Giffuni 	return 1;
225a7e9c4d8SPedro Giffuni }
226a7e9c4d8SPedro Giffuni 
227a7e9c4d8SPedro Giffuni #ifdef TESTBMP
228a7e9c4d8SPedro Giffuni 
229a7e9c4d8SPedro Giffuni #include <io.h>
230a7e9c4d8SPedro Giffuni #include <fcntl.h>
231a7e9c4d8SPedro Giffuni #include <stdio.h>
232a7e9c4d8SPedro Giffuni 
main(void)233a7e9c4d8SPedro Giffuni int main( void)
234a7e9c4d8SPedro Giffuni {
235a7e9c4d8SPedro Giffuni 	HAB hAB = WinQueryAnchorBlock( HWND_DESKTOP );
236a7e9c4d8SPedro Giffuni 
237a7e9c4d8SPedro Giffuni 	// query clipboard data to get mimetype
238a7e9c4d8SPedro Giffuni 	if( WinOpenClipbrd( hAB ) )
239a7e9c4d8SPedro Giffuni 	{
240a7e9c4d8SPedro Giffuni 		ULONG handle = WinQueryClipbrdData( hAB, CF_BITMAP);
241a7e9c4d8SPedro Giffuni 		if (handle) {
242a7e9c4d8SPedro Giffuni 			Sequence< sal_Int8 > winDIBStream;
243a7e9c4d8SPedro Giffuni 			// convert to oustring and return it
244a7e9c4d8SPedro Giffuni 			if (OS2HandleToOOoBmp( handle, &winDIBStream) == 1) {
245a7e9c4d8SPedro Giffuni 				printf( "Conversion ok.\n");
246a7e9c4d8SPedro Giffuni 				int fd = open( "test.bmp", O_BINARY | O_CREAT | O_TRUNC | O_RDWR);
247a7e9c4d8SPedro Giffuni 				printf( "writing to fd %d\n", fd);
248a7e9c4d8SPedro Giffuni 				write( fd, winDIBStream.getArray(), winDIBStream.getLength());
249a7e9c4d8SPedro Giffuni 				close( fd);
250a7e9c4d8SPedro Giffuni 			} else
251a7e9c4d8SPedro Giffuni 				printf( "failed conversion.\n");
252a7e9c4d8SPedro Giffuni 
253a7e9c4d8SPedro Giffuni 		}
254a7e9c4d8SPedro Giffuni 		WinCloseClipbrd( hAB);
255a7e9c4d8SPedro Giffuni 	}
256a7e9c4d8SPedro Giffuni 	return 0;
257a7e9c4d8SPedro Giffuni }
258a7e9c4d8SPedro Giffuni 
259a7e9c4d8SPedro Giffuni #endif //TESTBMP
260a7e9c4d8SPedro Giffuni 
261