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