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