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