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