Index: /trunk/include/qpixmap.h
===================================================================
--- /trunk/include/qpixmap.h	(revision 58)
+++ /trunk/include/qpixmap.h	(revision 59)
@@ -217,5 +217,5 @@
         HBITMAP hbm;
         HBITMAP maskedHbm;  // pixmap precomposed for masking
-//@@TODO (dmik): need this?        
+        bool hasRealAlpha;
 	uchar *realAlphaBits;
 #elif defined(Q_WS_X11)
@@ -254,8 +254,11 @@
 				   int sw, int sh, bool useDstAlpha );
 #elif defined(Q_WS_PM)
-    void prepareForMasking( bool prepare );
+    void prepareForMasking( bool prepare, bool force = FALSE );
     HPOINTER createIcon( bool pointer, int hotX, int hotY, bool mini );
     void attachHandle( HBITMAP hbm );
     HBITMAP detachHandle();
+    void unfoldAlphaChannel();
+    void convertToAlpha();
+    static int trueColorDepth();
     friend class QPMMimeImage;
 #endif
Index: /trunk/src/kernel/qpaintdevice_pm.cpp
===================================================================
--- /trunk/src/kernel/qpaintdevice_pm.cpp	(revision 58)
+++ /trunk/src/kernel/qpaintdevice_pm.cpp	(revision 59)
@@ -125,19 +125,14 @@
 
 // draws the pixmap with a mask using the black source method
-void drawMaskedPixmap(
-    HPS dst_ps, int dst_depth, HPS src_ps, int src_w, int src_h, HPS mask_ps,
-    int dx, int dy, int sx, int sy, int w, int h, Qt::RasterOp rop
-) {
-    // all rectangles for different operations combined together
-    POINTL ptls[] = {
-        { dx, dy }, { dx + w, dy + h },         // 0: src/buf => dst
-        { sx, sy }, { sx + w, sy + h },         // 2: src <=> buf
-        { sx, sy }, { sx + w, sy + h },         // 4: dst => buf
-        { dx, dy }
-    };
+static void drawMaskedPixmap(
+    HPS dst_ps, int dst_depth, bool grab_dest, HPS src_ps, HPS mask_ps,
+    int dx, int dy, int sx, int sy, int w, int h, Qt::RasterOp rop )
+{
     IMAGEBUNDLE oldIb;
 
     if ( !mask_ps ) {
         // self-masked pixmap
+        POINTL ptls[] = { { dx, dy }, { dx + w, dy + h },
+                          { sx, sy } };
         IMAGEBUNDLE newIb;
         GpiQueryAttrs( dst_ps, PRIM_IMAGE, IBB_BACK_MIX_MODE, (PBUNDLE) &oldIb );
@@ -148,122 +143,254 @@
     } else {
         bool simple = (rop == Qt::CopyROP) || (rop == Qt::XorROP);
-        // helper hps for dblbuf
-        HPS hpsBuf = qt_alloc_mem_ps( src_w, simple ? src_h : src_h * 2, dst_ps );
-        // helper bitmap for dblbuf
-        BITMAPINFOHEADER2 bmh;
-        memset( &bmh, 0, sizeof(BITMAPINFOHEADER2) );
-        bmh.cbFix = sizeof(BITMAPINFOHEADER2);
-        bmh.cx = src_w;
-        bmh.cy = simple ? src_h : src_h * 2;
-        bmh.cPlanes = 1;
-        bmh.cBitCount = dst_depth;
-        HBITMAP hbmBuf = GpiCreateBitmap( hpsBuf, &bmh, 0, NULL, NULL );
-        GpiSetBitmap( hpsBuf, hbmBuf );
-
+        // origial helper buffer handles 
+        HPS hpsBuf = 0;
+        HBITMAP hbmBuf = 0;
+        // two pointers to the helper buffer 
+        HPS hpsBuf1 = dst_ps;
+        HPS hpsBuf2 = 0;
+        // first helper buffer's coordinates 
+        int buf1_x = dx, buf1_y = dy;
+        // second helper buffer's coordinates 
+        int buf2_x = -1, buf2_y = -1;
+        
+        if ( grab_dest || !simple ) {
+            // create the helper buffer (we need two buffers if grab_dest and
+            // not simple -- double the height in this case)
+            BITMAPINFOHEADER2 bmh;
+            memset( &bmh, 0, sizeof(BITMAPINFOHEADER2) );
+            bmh.cbFix = sizeof(BITMAPINFOHEADER2);
+            bmh.cx = w;
+            bmh.cy = grab_dest && !simple ? h * 2 : h;
+            bmh.cPlanes = 1;
+            bmh.cBitCount = dst_depth;
+            hpsBuf = qt_alloc_mem_ps( bmh.cx, bmh.cy, dst_ps );
+            hbmBuf = GpiCreateBitmap( hpsBuf, &bmh, 0, NULL, NULL );
+            GpiSetBitmap( hpsBuf, hbmBuf );
+            // setup buffer handles and coordinates
+            if ( grab_dest && !simple ) {
+                hpsBuf1 = hpsBuf2 = hpsBuf;
+                buf1_x = buf1_y = 0;
+                buf2_x = 0;
+                buf2_y = h;
+            } else if ( grab_dest ) {
+                hpsBuf1 = hpsBuf;
+                buf1_x = buf1_y = 0;
+            } else { // i.e. !grab_dest && !simple
+                hpsBuf2 = hpsBuf;
+                buf2_x = buf2_y = 0;
+            }
+        }
+
+        // save current destination colors
+        ULONG oldColor = GpiQueryColor( dst_ps );
+        ULONG oldBackColor = GpiQueryBackColor( dst_ps );
+        
         // query the destination color for 1-bpp bitmaps
         GpiQueryAttrs( dst_ps, PRIM_IMAGE, IBB_COLOR, (PBUNDLE) &oldIb );
-        // setup colors for the masking
-        GpiSetColor( hpsBuf, CLR_TRUE );
-        GpiSetBackColor( hpsBuf, CLR_FALSE );
-
-        // grab the destination
-        GpiBitBlt( hpsBuf, dst_ps, 3, &ptls[4], ROP_SRCCOPY, BBO_IGNORE );
+        // setup colors for masking
+        GpiSetColor( hpsBuf1, CLR_TRUE );
+        GpiSetBackColor( hpsBuf1, CLR_FALSE );
+        if ( hpsBuf2 != hpsBuf1 ) {
+            GpiSetColor( hpsBuf2, CLR_TRUE );
+            GpiSetBackColor( hpsBuf2, CLR_FALSE );
+        }
+
+        if ( grab_dest ) {
+            // grab the destination
+            POINTL ptls[] = { { buf1_x, buf1_y }, { buf1_x + w, buf1_y + h },
+                              { dx, dy } };
+            GpiBitBlt( hpsBuf1, dst_ps, 3, ptls, ROP_SRCCOPY, BBO_IGNORE );
+        }
+        
+        // compose a masked pixmap with a given rop into the second buffer
+        if ( !simple ) {
+            // grab the destination to the 2nd buffer
+            POINTL ptDB2[] = { { buf2_x, buf2_y }, { buf2_x + w, buf2_y + h },
+                               { dx, dy } };
+            GpiBitBlt( hpsBuf2, dst_ps, 3, ptDB2, ROP_SRCCOPY, BBO_IGNORE );
+            // bitblt pixmap using rop
+            POINTL ptSB2[] = { { buf2_x, buf2_y }, { buf2_x + w, buf2_y + h },
+                               { sx, sy } };
+            GpiSetColor( hpsBuf2, oldIb.lColor );
+            GpiBitBlt( hpsBuf2, src_ps, 3, ptSB2, qt_ropCodes_2ROP[rop], BBO_IGNORE );
+            // make transparent pixels black
+            GpiSetColor( hpsBuf2, CLR_TRUE );
+            GpiBitBlt( hpsBuf2, mask_ps, 3, ptSB2, ROP_SRCAND, BBO_IGNORE );
+        }
+
         // draw the mask: make non-transparent pixels (corresponding to
         // ones in the mask) black. skip this step when rop = XorROP
         // to get the XOR effect.
-        if ( rop != Qt::XorROP )
-            GpiBitBlt( hpsBuf, mask_ps, 3, &ptls[2], 0x22, BBO_IGNORE );
-
-        // compose a masked pixmap with a given rop into the second buffer
+        if ( rop != Qt::XorROP ) {
+            POINTL ptls[] = { { buf1_x, buf1_y }, { buf1_x + w, buf1_y + h },
+                              { sx, sy } };
+            GpiBitBlt( hpsBuf1, mask_ps, 3, ptls, 0x22, BBO_IGNORE );
+        }
+        
         if ( !simple ) {
-            // grab the destination to the 2nd buffer
-            ptls[4].y += h; ptls[5].y += h;
-            GpiBitBlt( hpsBuf, dst_ps, 3, &ptls[4], ROP_SRCCOPY, BBO_IGNORE );
-            ptls[4].y -= h; ptls[5].y -= h;
-            // bitblt pixmap using rop
-            ptls[2].y += h; ptls[3].y += h;
-            GpiSetColor( hpsBuf, oldIb.lColor );
-            GpiBitBlt( hpsBuf, src_ps, 3, &ptls[2], qt_ropCodes_2ROP[rop], BBO_IGNORE );
-            // make transparent pixels black
-            GpiSetColor( hpsBuf, CLR_TRUE );
-            GpiBitBlt( hpsBuf, mask_ps, 3, &ptls[2], ROP_SRCAND, BBO_IGNORE );
-            // draw masked pixmap from the 2nd buffer to the 1rd
-            ptls[2].y -= h; ptls[3].y -= h;
-            ptls[4].y += h; ptls[5].y += h;
-            GpiBitBlt( hpsBuf, hpsBuf, 3, &ptls[2], ROP_SRCPAINT, BBO_IGNORE );
+            // draw masked pixmap from the 2nd buffer to the 1st
+            POINTL ptB2B1[] = { { buf1_x, buf1_y }, { buf1_x + w, buf1_y + h },
+                                { buf2_x, buf2_y } };
+            GpiBitBlt( hpsBuf1, hpsBuf2, 3, ptB2B1, ROP_SRCPAINT, BBO_IGNORE );
         } else {
             // draw masked pixmap; transparent pixels are zeroed there
             // by prepareForMasking( TRUE )
-            GpiSetColor( hpsBuf, oldIb.lColor );
-            GpiBitBlt( hpsBuf, src_ps, 3, &ptls[2], ROP_SRCINVERT, BBO_IGNORE );
+            POINTL ptls[] = { { buf1_x, buf1_y }, { buf1_x + w, buf1_y + h },
+                              { sx, sy } };
+            GpiSetColor( hpsBuf1, oldIb.lColor );
+            GpiBitBlt( hpsBuf1, src_ps, 3, ptls, ROP_SRCINVERT, BBO_IGNORE );
         }
 
         // flush the buffer
-        GpiBitBlt( dst_ps, hpsBuf, 3, &ptls[0], ROP_SRCCOPY, BBO_IGNORE );
+        if ( hpsBuf1 != dst_ps ) {
+            POINTL ptls[] = { { dx, dy }, { dx + w, dy + h },
+                              { buf1_x, buf1_y } };
+            GpiBitBlt( dst_ps, hpsBuf1, 3, ptls, ROP_SRCCOPY, BBO_IGNORE );
+        }
+        
         // free resources
+        if ( hpsBuf ) {
+            GpiSetBitmap( hpsBuf, 0 );
+            GpiDeleteBitmap( hbmBuf );
+            qt_free_mem_ps( hpsBuf );
+        }
+        
+        // restore current destination colors
+        GpiSetColor( dst_ps, oldColor );
+        GpiSetBackColor( dst_ps, oldBackColor );
+    }
+}
+
+// draws the pixmap with a mask using the black source method
+static void drawAlphaPixmap (
+    HPS dst_ps, int dst_w, HPS src_ps, int src_w, uchar *alpha,
+    int dx, int dy, int sx, int sy, int w, int h, int depth )
+{
+    Q_ASSERT( depth == 32 || depth == 24 );
+
+    bool grab_dest = false;
+    int dst_x = dx;
+    
+    if ( dst_w == 0 ) {
+        grab_dest = true;
+        dst_w = w;
+        dst_x = 0;
+    }
+    
+    int dst_bpl = ((depth * dst_w + 31) / 32) * 4;
+    int src_bpl = ((depth * src_w + 31) / 32) * 4;
+    
+    uchar *dst = new uchar [dst_bpl * h];
+    uchar *src = new uchar [src_bpl * h];
+    
+    BITMAPINFOHEADER2 bmh;
+    memset( &bmh, 0, sizeof(BITMAPINFOHEADER2) );
+    bmh.cbFix = sizeof(BITMAPINFOHEADER2);
+    bmh.cPlanes = 1;
+    bmh.cBitCount = depth;
+    if ( grab_dest ) {
+        bmh.cx = w;
+        bmh.cy = h;
+        
+        // helper hps for dblbuf
+        HPS hpsBuf = qt_alloc_mem_ps( w, h, dst_ps );
+        // helper bitmap for dblbuf
+        HBITMAP hbmBuf = GpiCreateBitmap( hpsBuf, &bmh, 0, NULL, NULL );
+        GpiSetBitmap( hpsBuf, hbmBuf );
+        
+        // grab the destination and get bits
+        POINTL ptls[] = { { 0, 0 }, { w, h }, { dx, dy } };
+        GpiBitBlt ( hpsBuf, dst_ps, 3, ptls, ROP_SRCCOPY, BBO_IGNORE );
+        GpiQueryBitmapBits( hpsBuf, 0, h, (PBYTE) dst, (PBITMAPINFO2) &bmh );
+    
+        // free dblbuf
         GpiSetBitmap( hpsBuf, 0 );
         GpiDeleteBitmap( hbmBuf );
         qt_free_mem_ps( hpsBuf );
-    }
-}
-
-//@@TODO (dmik): later
-//
-//#ifndef Q_OS_TEMP
-//// For alpha blending, we must load the AlphaBlend() function at run time.
-//#if !defined(AC_SRC_ALPHA)
-//#define AC_SRC_ALPHA 0x01
-//#endif
-//typedef BOOL (WINAPI *ALPHABLEND)( HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION );
-//static HINSTANCE msimg32Lib = 0;
-//static ALPHABLEND alphaBlend = 0;
-//static bool loadAlphaBlendFailed = FALSE;
-//static void cleanup_msimg32Lib()
-//{
-//    if ( msimg32Lib != 0 ) {
-//	FreeLibrary( msimg32Lib );
-//	msimg32Lib = 0;
-//	alphaBlend = 0;
-//	loadAlphaBlendFailed = FALSE;
-//    }
-//}
-//#endif
-//
-///*
-//   Try to do an AlphaBlend(). If it fails for some reasons, use BitBlt()
-//   instead. The arguments are like in the BitBlt() call.
-//*/
-//void qt_AlphaBlend( HDC dst_dc, int dx, int dy, int sw, int sh, HDC src_dc, int sx, int sy, DWORD rop )
-//{
-//#ifndef Q_OS_TEMP
-//    BLENDFUNCTION blend = {
-//	AC_SRC_OVER,
-//	0,
-//	255,
-//	AC_SRC_ALPHA
-//    };
-//    if ( alphaBlend ) {
-//	alphaBlend( dst_dc, dx, dy, sw, sh, src_dc, sx, sy, sw, sh, blend );
-//    } else {
-//	if ( !loadAlphaBlendFailed ) {
-//	    // try to load msimg32.dll and get the function
-//	    // AlphaBlend()
-//	    loadAlphaBlendFailed = TRUE;
-//	    msimg32Lib = LoadLibraryA( "msimg32" );
-//	    if ( msimg32Lib != 0 ) {
-//		qAddPostRoutine( cleanup_msimg32Lib );
-//		alphaBlend = (ALPHABLEND) GetProcAddress( msimg32Lib, "AlphaBlend" );
-//		loadAlphaBlendFailed = ( alphaBlend == 0 );
-//	    }
-//	}
-//	if ( loadAlphaBlendFailed )
-//	    BitBlt( dst_dc, dx, dy, sw, sh, src_dc, sx, sy, rop );
-//	else
-//	    alphaBlend( dst_dc, dx, dy, sw, sh, src_dc, sx, sy, sw, sh, blend );
-//    }
-//#else
-//    BitBlt( dst_dc, dx, dy, sw, sh, src_dc, sx, sy, rop );
-//#endif
-//}
+    } else {
+        // get bits of the destination
+        GpiQueryBitmapBits( dst_ps, dy, h, (PBYTE) dst, (PBITMAPINFO2) &bmh );
+    }
+    
+    // get bits of the source pixmap
+    GpiQueryBitmapBits( src_ps, sy, h, (PBYTE) src, (PBITMAPINFO2) &bmh );
+    
+    uchar px_sz = depth / 8;
+    uchar *dst_ptr = dst + px_sz * dst_x;
+    uchar *src_ptr = src + px_sz * sx;
+    uchar *a_ptr = alpha ? alpha + sx : 0; 
+    int dst_inc = dst_bpl - px_sz * w;
+    int src_inc = src_bpl - px_sz * w;
+    int px_skip = px_sz - 3;
+    
+    // use two separate code paths to increase the speed slightly by
+    // eliminating one comparison op (a_ptr != 0) inside the most nested loop 
+    if ( a_ptr ) {
+        for ( int y = 0; y < h; y++ ) {
+            for ( int x = 0; x < w; x++ ) {
+                uchar a = *(a_ptr++);
+                if ( a == 0 ) {
+                    dst_ptr += px_sz;
+                    src_ptr += px_sz;
+                    continue;
+                } else if ( a == 255 ) {
+                    *(dst_ptr++) = *(src_ptr++);
+                    *(dst_ptr++) = *(src_ptr++);
+                    *(dst_ptr++) = *(src_ptr++);
+                } else {
+                    *dst_ptr += (*(src_ptr++) - *dst_ptr) * a / 255;
+                    dst_ptr ++;
+                    *dst_ptr += (*(src_ptr++) - *dst_ptr) * a / 255;
+                    dst_ptr ++;
+                    *dst_ptr += (*(src_ptr++) - *dst_ptr) * a / 255;
+                    dst_ptr ++;
+                }
+                dst_ptr += px_skip;
+                src_ptr += px_skip;
+            }
+            dst_ptr += dst_inc;
+            src_ptr += src_inc;
+        }
+    } else {
+        for ( int y = 0; y < h; y++ ) {
+            for ( int x = 0; x < w; x++ ) {
+                uchar a = src_ptr [3];
+                if ( a == 0 ) {
+                    dst_ptr += px_sz;
+                    src_ptr += px_sz;
+                    continue;
+                } else if ( a == 255 ) {
+                    *(dst_ptr++) = *(src_ptr++);
+                    *(dst_ptr++) = *(src_ptr++);
+                    *(dst_ptr++) = *(src_ptr++);
+                } else {
+                    *dst_ptr += (*(src_ptr++) - *dst_ptr) * a / 255;
+                    dst_ptr ++;
+                    *dst_ptr += (*(src_ptr++) - *dst_ptr) * a / 255;
+                    dst_ptr ++;
+                    *dst_ptr += (*(src_ptr++) - *dst_ptr) * a / 255;
+                    dst_ptr ++;
+                }
+                dst_ptr += px_skip;
+                src_ptr += px_skip;
+            }
+            dst_ptr += dst_inc;
+            src_ptr += src_inc;
+        }
+    }
+    
+    // flush the dst buffer
+    {
+        bmh.cx = dst_w;
+        bmh.cy = h;
+        POINTL ptls[] = { { dx, dy }, { dx + w - 1, dy + h - 1 },
+                          { dst_x, 0 }, { dst_x + w, h } };
+        GpiDrawBits( dst_ps, (PVOID) dst, (PBITMAPINFO2) &bmh, 4, ptls,
+                     ROP_SRCCOPY, BBO_IGNORE );
+    }
+
+    delete[] src;
+    delete[] dst;
+}
 
 void bitBlt( QPaintDevice *dst, int dx, int dy,
@@ -271,5 +398,5 @@
 	     Qt::RasterOp rop, bool ignoreMask  )
 {
-    if ( !src || !dst ) {
+    if ( !src || !dst || sw == 0 || sh == 0 ) {
 #if defined(QT_CHECK_NULL)
 	Q_ASSERT( src != 0 );
@@ -288,17 +415,34 @@
     int td = dst->devType();			// to device type
 
-    if ( sw <= 0 ) {				// special width
-	if ( sw < 0 )
-	    sw = src->metric(QPaintDeviceMetrics::PdmWidth) - sx;
-	else
-	    return;
-    }
-    if ( sh <= 0 ) {				// special height
-	if ( sh < 0 )
-	    sh = src->metric(QPaintDeviceMetrics::PdmHeight) - sy;
-	else
-	    return;
-    }
-
+    int src_w = src->metric(QPaintDeviceMetrics::PdmWidth);
+    int src_h = src->metric(QPaintDeviceMetrics::PdmHeight);
+    int dst_w = dst->metric(QPaintDeviceMetrics::PdmWidth);
+    int dst_h = dst->metric(QPaintDeviceMetrics::PdmHeight);
+    
+    if ( sw < 0 )				// special width
+        sw = src_w - sx;
+    if ( sh < 0 )				// special height
+        sh = src_h - sy;
+
+    // ensure coordinates are within borders, clip if necessary
+    if ( sx < 0 || sy < 0 || sx + sw > src_w || sy + sh > src_h ||
+         dx < 0 || dy < 0 || dx + sw > dst_w || dy + sh > dst_h )
+    {
+        int tx = dx - sx;
+        int ty = dy - sy;
+        QRect dr( 0, 0, dst_w, dst_h );  // dst rect
+        QRect sr( tx, ty, src_w, src_h ); // src rect in dst coords
+        QRect bltr( dx, dy, sw, sh ); // blit rect in dst coords
+        bltr &= (dr & sr);
+        if (bltr.isEmpty())
+            return;
+        dx = bltr.x();
+        dy = bltr.y();
+        sx = dx - tx;
+        sy = dy - ty;
+        sw = bltr.width();
+        sh = bltr.height();
+    }
+    
     if ( dst->paintingActive() && dst->isExtDev() ) {
 	QPixmap *pm;				// output to picture/printer
@@ -423,82 +567,66 @@
     };
 
-    if ( src_pm && src_pm->data->realAlphaBits ) {
-        qWarning( "::bitBlt() for pixmaps with alpha is not yet implemented on OS/2" );
-//@@TODO (dmik): later
-//	if ( td == QInternal::Pixmap && ((QPixmap *)dst)->data->realAlphaBits )
-//	    QPixmap::bitBltAlphaPixmap( ((QPixmap *)dst), dx, dy, src_pm, sx, sy, sw, sh, TRUE );
-//	else
-//	    qt_AlphaBlend( dst_dc, dx, dy, sw, sh, src_dc, sx, sy, ropCodes[rop] );
+    if ( td == QInternal::Pixmap ) {
+        // Ensure the auxiliary masked bitmap created for masking is destroyed
+        // (to cause it to be recreated when the destination is blitted next
+        // time). Also ensure the alpha channel of the destination pixmap is
+        // unfolded -- any GPI call will clear the high byte that may be storing
+        // the alpha bits, so the pixmap will appear as fully transparent.
+        QPixmap *dst_pm = (QPixmap *) dst;
+        if ( dst_pm->data->mask )
+            dst_pm->prepareForMasking( FALSE, TRUE );
+        if ( dst_pm->data->hasRealAlpha )
+            dst_pm->unfoldAlphaChannel();
+    }
+
+    if ( src_pm && src_pm->data->hasRealAlpha && !ignoreMask ) {
+        int dst_w = 0; // implies grab_dest = true
+        if ( td == QInternal::Pixmap )
+            dst_w = ((QPixmap *) dst)->data->w; // implies grab_dest = false
+        drawAlphaPixmap( dst_ps, dst_w, src_ps, src_pm->data->w,
+                         src_pm->data->realAlphaBits,
+                         dx, fdy, sx, fsy, sw, sh, QPixmap::trueColorDepth() );
     } else if ( mask ) {
-	if ( /*src_pm &&*/ td==QInternal::Pixmap && ((QPixmap *)dst)->data->realAlphaBits ) {
-            qWarning( "::bitBlt() for pixmaps with alpha is not yet implemented on OS/2" );
-//@@TODO (dmik): later
-//	    src_pm->convertToAlphaPixmap();
-//	    QPixmap::bitBltAlphaPixmap( (QPixmap *)dst, dx, dy, src_pm, sx, sy, sw, sh, TRUE );
-	} else {
 #if 0
-//@@TODO (dmik): unfortunately, this nice method of setting the mask as a
-//  pattern and using the corresponding ROPs to do masking in one step
-//  will not apways work on many video drivers (including SDD/SNAP) since
-//  they can spontaneously simplify the bitmap set as a pattern (for example,
-//  take only first 8 pixels of the mask width), which will produce wrong
-//  results.
-            const ULONG AllAreaAttrs =
-                ABB_COLOR | ABB_BACK_COLOR |
-                ABB_MIX_MODE | ABB_BACK_MIX_MODE |
-                ABB_SET | ABB_SYMBOL | ABB_REF_POINT;
-            AREABUNDLE oldAb;
-            GpiQueryAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, (PBUNDLE) &oldAb );
-            AREABUNDLE newAb = {
-                CLR_TRUE, CLR_FALSE, FM_OVERPAINT, BM_OVERPAINT,
-                LCID_QTMaskBitmap, 0, ptls [0]
-            };
-            GpiSetBitmap( mask->hps, 0 );
-            GpiSetBitmapId( dst_ps, mask->hbm(), LCID_QTMaskBitmap );
-            GpiSetAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, 0, (PBUNDLE) &newAb );
-            // we use the same rop codes for masked bitblt after setting the
-            // low half of the rop byte to 0xA, which means destination bits
-            // should be preserved where the corresponding bits in the mask
-            // are zeroes.
-            GpiBitBlt( dst_ps, src_ps, 3, ptls, (qt_ropCodes_2ROP[rop] & 0xF0) | 0x0A, BBO_IGNORE );
-            GpiSetAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, 0, (PBUNDLE) &oldAb );
-            GpiDeleteSetId( dst_ps, LCID_QTMaskBitmap );
-            GpiSetBitmap( mask->hps, mask->hbm() );
+        //  Unfortunately, this nice method of setting the mask as a pattern
+        //  and using the corresponding ROPs to do masking in one step will
+        //  not apways work on many video drivers (including SDD/SNAP) since
+        //  they can spontaneously simplify the bitmap set as a pattern (for
+        //  example, take only first 8 pixels of the mask width), which will
+        //  produce wrong results.
+        const ULONG AllAreaAttrs =
+            ABB_COLOR | ABB_BACK_COLOR |
+            ABB_MIX_MODE | ABB_BACK_MIX_MODE |
+            ABB_SET | ABB_SYMBOL | ABB_REF_POINT;
+        AREABUNDLE oldAb;
+        GpiQueryAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, (PBUNDLE) &oldAb );
+        AREABUNDLE newAb = {
+            CLR_TRUE, CLR_FALSE, FM_OVERPAINT, BM_OVERPAINT,
+            LCID_QTMaskBitmap, 0, ptls [0]
+        };
+        GpiSetBitmap( mask->hps, 0 );
+        GpiSetBitmapId( dst_ps, mask->hbm(), LCID_QTMaskBitmap );
+        GpiSetAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, 0, (PBUNDLE) &newAb );
+        // we use the same rop codes for masked bitblt after setting the
+        // low half of the rop byte to 0xA, which means destination bits
+        // should be preserved where the corresponding bits in the mask
+        // are zeroes.
+        GpiBitBlt( dst_ps, src_ps, 3, ptls, (qt_ropCodes_2ROP[rop] & 0xF0) | 0x0A, BBO_IGNORE );
+        GpiSetAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, 0, (PBUNDLE) &oldAb );
+        GpiDeleteSetId( dst_ps, LCID_QTMaskBitmap );
+        GpiSetBitmap( mask->hps, mask->hbm() );
 #else
-            src_pm->prepareForMasking( TRUE );
-            drawMaskedPixmap(
-                dst_ps, dst->metric( QPaintDeviceMetrics::PdmDepth ),
-                src_ps, src_pm->data->w, src_pm->data->h,
-                src_pm->data->selfmask ? 0 : mask->hps,
-                dx, fdy, sx, fsy, sw, sh, rop
-            );
-            src_pm->prepareForMasking( FALSE );
-#endif
-	}
+        bool grab_dest = td != QInternal::Pixmap;
+        src_pm->prepareForMasking( TRUE );
+        drawMaskedPixmap(
+            dst_ps, dst->metric( QPaintDeviceMetrics::PdmDepth ), grab_dest,
+            src_ps, src_pm->data->selfmask ? 0 : mask->hps,
+            dx, fdy, sx, fsy, sw, sh, rop );
+        src_pm->prepareForMasking( FALSE );
+#endif
     } else {
-	if ( td==QInternal::Pixmap && ((QPixmap *)dst)->isQBitmap() ) {
-            GpiBitBlt( dst_ps, src_ps, 3, ptls, qt_ropCodes_2ROP[rop], BBO_IGNORE );
-	} else if ( src_pm && td==QInternal::Pixmap && ((QPixmap *)dst)->data->realAlphaBits ) {
-            qWarning( "::bitBlt() for pixmaps with alpha is not yet implemented on OS/2" );
-//@@TODO (dmik): later
-//	    QPixmap *dst_pm = (QPixmap *)dst;
-//	    if ( rop == Qt::CopyROP ) {
-//		src_pm->convertToAlphaPixmap();
-//		QPixmap::bitBltAlphaPixmap( dst_pm, dx, dy, src_pm, sx, sy, sw, sh, TRUE );
-//	    } else {
-//		src_pm->convertToAlphaPixmap();
-//		if ( dst_pm->mask() ) {
-//		    int width = QMIN( dst_pm->mask()->width()-dx, sw );
-//		    int height = QMIN( dst_pm->mask()->height()-dy, sh );
-//		    MaskBlt( dst_dc, dx, dy, width, height, src_pm->hdc, sx, sy, dst_pm->mask()->hbm(),
-//			    dx, dy, MAKEROP4(0x00aa0000,ropCodes[rop]) );
-//		} else {
-//		    BitBlt( dst_dc, dx, dy, sw, sh, src_pm->hdc, sx, sy, ropCodes[rop] );
-//		}
-//	    }
-	} else {
-            GpiBitBlt( dst_ps, src_ps, 3, ptls, qt_ropCodes_2ROP[rop], BBO_IGNORE );
-	}
-    }
+        GpiBitBlt( dst_ps, src_ps, 3, ptls, qt_ropCodes_2ROP[rop], BBO_IGNORE );
+    }
+
     if ( src_tmp )
 	WinReleasePS( src_ps );
Index: /trunk/src/kernel/qpainter_pm.cpp
===================================================================
--- /trunk/src/kernel/qpainter_pm.cpp	(revision 58)
+++ /trunk/src/kernel/qpainter_pm.cpp	(revision 59)
@@ -505,6 +505,17 @@
     if ( (pdev->devFlags & QInternal::CompatibilityMode) != 0 )
 	setf(Qt2Compat);
-    else if ( dt == QInternal::Pixmap )		// device is a pixmap
-	((QPixmap*)pdev)->detach();		// will modify it
+    else if ( dt == QInternal::Pixmap )	{       // device is a pixmap
+        QPixmap *pm = (QPixmap*) pdev;          // will modify it 
+	pm->detach();		                
+        // Ensure the auxiliary masked bitmap created for masking is destroyed
+        // (to cause it to be recreated when the pixmap is blitted next time).
+        // Also ensure the alpha channel of the pixmap is unfolded -- any GPI
+        // call will clear the high byte that may be storing the alpha bits,
+        // so the pixmap will appear as fully transparent.
+        if ( pm->data->mask )
+            pm->prepareForMasking( FALSE, TRUE );
+        if ( pm->data->hasRealAlpha )
+            pm->unfoldAlphaChannel();
+    }
 
     hps = 0;
@@ -802,38 +813,4 @@
 }
 
-/*
-  This function adjusts the raster operations for painting into a QBitmap on
-  Windows.
-
-//@@TODO (dmik): think of it. should it be the same on OS/2? see also
-//  qcolor_pm.cpp, qpixmap.cpp (qt_xForm_helper()), qpaintdevice_pm.cpp (bitBlt())
-
-  For bitmaps und Windows, color0 is 0xffffff and color1 is 0x000000 -- so we
-  have to use adjusted ROPs in this case to get the same effect as on Unix.
-*/
-//@@TODO (dmik): possibly remove
-//Qt::RasterOp qt_map_rop_for_bitmaps( Qt::RasterOp r )
-//{
-//    static const Qt::RasterOp ropCodes[] = {
-//	Qt::CopyROP,	// CopyROP
-//	Qt::AndROP,		// OrROP
-//	Qt::NotXorROP,	// XorROP
-//	Qt::NotOrROP,	// NotAndROP
-//	Qt::NotCopyROP,	// NotCopyROP
-//	Qt::NotAndROP,	// NotOrROP
-//	Qt::XorROP,	// NotXorROP
-//	Qt::OrROP,	// AndROP
-//	Qt::NotROP,	// NotROP
-//	Qt::SetROP,	// ClearROP
-//	Qt::ClearROP,	// SetROP
-//	Qt::NopROP,	// NopROP
-//	Qt::OrNotROP,	// AndNotROP
-//	Qt::AndNotROP,	// OrNotROP
-//	Qt::NorROP,	// NandROP
-//	Qt::NandROP	// NorROP
-//    };
-//    return ropCodes[r];
-//}
-
 void QPainter::setRasterOp( RasterOp r )
 {
@@ -861,10 +838,4 @@
    if ( bg_mode != TransparentMode )
        qt_GpiSetBackMix( hps, qt_ropCodes[r], cpen.style() == NoPen );
-
-//@@TODO (dmik): remove? see above todo (qt_map_rop_for_bitmaps())
-//    if ( pdev->devType()==QInternal::Pixmap && ((QPixmap*)pdev)->isQBitmap() )
-//	SetROP2( hdc, ropCodes[ qt_map_rop_for_bitmaps(r) ] );
-//    else
-//	SetROP2( hdc, ropCodes[r] );
 }
 
Index: /trunk/src/kernel/qpixmap.cpp
===================================================================
--- /trunk/src/kernel/qpixmap.cpp	(revision 58)
+++ /trunk/src/kernel/qpixmap.cpp	(revision 59)
@@ -746,4 +746,14 @@
 #endif
 	}
+#if defined (Q_WS_PM)
+        if ( data->hasRealAlpha ) {
+	    detach();
+            data->hasRealAlpha = FALSE;
+            if ( data->realAlphaBits ) {
+                delete[] data->realAlphaBits;
+                data->realAlphaBits = 0;
+            }
+        }
+#endif
 	return;
     }
@@ -766,4 +776,11 @@
 
 #if defined (Q_WS_PM)
+    if ( data->hasRealAlpha ) {
+        data->hasRealAlpha = FALSE;
+        if ( data->realAlphaBits ) {
+            delete[] data->realAlphaBits;
+            data->realAlphaBits = 0;
+        }
+    }
     if ( data->maskedHbm ) {
         GpiDeleteBitmap( data->maskedHbm );
Index: /trunk/src/kernel/qpixmap_pm.cpp
===================================================================
--- /trunk/src/kernel/qpixmap_pm.cpp	(revision 58)
+++ /trunk/src/kernel/qpixmap_pm.cpp	(revision 59)
@@ -95,21 +95,4 @@
 }
 
-//@@TODO (dmik): later
-//void QPixmap::initAlphaPixmap( uchar *bytes, int length, BITMAPINFO *bmi )
-//{
-//    if ( data->mcp )
-//	freeCell( TRUE );
-//    if ( !hdc )
-//	hdc = alloc_mem_dc( 0, &data->old_hbm );
-//
-//    HBITMAP hBitmap = CreateDIBSection( hdc, bmi, DIB_RGB_COLORS, (void**)&data->realAlphaBits, NULL, 0 );
-//    if ( bytes )
-//	memcpy( data->realAlphaBits, bytes, length );
-//
-//    DeleteObject( SelectObject( hdc, data->old_hbm ) );
-//    data->old_hbm = (HBITMAP)SelectObject( hdc, hBitmap );
-//    DATA_HBM = hBitmap;
-//}
-
 
 void QPixmap::init( int w, int h, int d, bool bitmap, Optimization optim )
@@ -123,5 +106,5 @@
 
     static int serial = 0;
-    int dd = defaultDepth();
+    const int dd = defaultDepth();
 
     if ( optim == DefaultOptim )		// use default optimization
@@ -162,8 +145,8 @@
     bmh.cy = h;
     bmh.cPlanes = 1;
-    if ( data->d == dd )			// compatible bitmap
+    if ( data->d == 1 )                         // monocrome bitmap
+        bmh.cBitCount = 1;
+    else                                        // compatible bitmap
         bmh.cBitCount = dd;
-    else					// monocrome bitmap
-        bmh.cBitCount = 1;
     data->hbm = GpiCreateBitmap( hps, &bmh, 0, NULL, NULL );
 
@@ -188,4 +171,8 @@
         if ( hps )
             GpiSetBitmap( hps, 0 );
+        if ( data->hasRealAlpha && data->realAlphaBits ) {
+            delete[] data->realAlphaBits;
+            data->realAlphaBits = 0;
+        }
 	if ( data->mask ) {
 	    delete data->mask;
@@ -221,5 +208,5 @@
     data->d = 1;
 
-    int bitsbpl = (w+7)/8;			// original # bytes per line
+    int bitsbpl = (w + 7) / 8;			// original # bytes per line
 
     int bpl = ((w + 31) / 32) * 4;              // bytes per scanline,
@@ -288,7 +275,7 @@
     static int dd = 0;
     if ( dd == 0 ) {
-        LONG formats [2];
+        LONG formats[ 2 ];
         GpiQueryDeviceBitmapFormats( qt_display_ps(), 2, formats );
-        dd = formats [0] * formats [1];
+        dd = formats[ 0 ] * formats[ 1 ];
     }
     return dd;
@@ -382,5 +369,5 @@
     int	w = width();
     int	h = height();
-    const QBitmap *m = data->realAlphaBits ? 0 : mask();
+    const QBitmap *m = data->hasRealAlpha ? 0 : mask();
     int	d = depth();
     int	ncols = 2;
@@ -392,45 +379,14 @@
 	d = 32;					//   > 8  ==> 32
 	ncols = 0;
+#if defined QT_CHECK_RANGE
+    if ( trueColorDepth() != 32 )
+        qWarning( "QPixmap::convertToImage(): video driver doesn't seem to "
+                  "support the 32-bpp color depth!" );
+        // don't return since we still hope the driver can at least convert
+        // from/to 32-bpp bitmaps
+#endif            
     }
 
     QImage image( w, h, d, ncols, QImage::BigEndian );
-    if ( data->realAlphaBits ) {
-        qWarning( "QPixmap::convertToImage() for pixmaps with alpha is not yet implemented on OS/2" );
-//@@TODO (dmik): later
-//#ifndef Q_OS_TEMP
-//	GdiFlush();
-//#endif
-//	memcpy( image.bits(), data->realAlphaBits, image.numBytes() );
-//	image.setAlphaBuffer( TRUE );
-//
-//	// Windows has premultiplied alpha, so revert it
-//	uchar *p = image.bits();
-//	uchar *end = p + image.numBytes();
-//	uchar alphaByte;
-//	while ( p < end ) {
-//	    alphaByte = *(p+3);
-//	    if ( alphaByte == 0 ) {
-//		*p = 255;
-//		++p;
-//		*p = 255;
-//		++p;
-//		*p = 255;
-//		++p;
-//		++p;
-//	    } else if ( alphaByte == 255 ) {
-//		p += 4;
-//	    } else {
-//		uchar alphaByte2 = alphaByte / 2;
-//		*p = ( (int)(*p) * 255 + alphaByte2 ) / alphaByte;
-//		++p;
-//		*p = ( (int)(*p) * 255 + alphaByte2 ) / alphaByte;
-//		++p;
-//		*p = ( (int)(*p) * 255 + alphaByte2 ) / alphaByte;
-//		++p;
-//		++p;
-//	    }
-//	}
-//	return image;
-    }
 
     // allocate header + ncols palette entries
@@ -447,4 +403,23 @@
     GpiQueryBitmapBits( hps, 0, h, (PBYTE) image.bits(), (PBITMAPINFO2) bmi_data );
 
+    if ( data->hasRealAlpha ) {
+        if ( data->realAlphaBits ) {
+            // incorporate the alpha channel to image data
+            // (see comments in convertFromImage() for details)
+            uchar *src = data->realAlphaBits;
+            int y = 0;
+            while ( y < image.height() ) {
+                uchar *dst = image.scanLine( y++ );
+                uchar *end = dst + image.bytesPerLine();
+                dst += 3;
+                while ( dst < end ) {
+                    *dst = *(src++);
+                    dst += 4;
+                }
+            }
+        }
+	image.setAlphaBuffer( TRUE );
+    }    
+    
     // flip the image top to bottom
     {
@@ -550,5 +525,4 @@
 }
 
-
 bool QPixmap::convertFromImage( const QImage &img, int conversion_flags )
 {
@@ -582,10 +556,15 @@
 	} else if ( d == 1 ) {
 	    if ( image.numColors() == 2 ) {
-//@@TODO (dmik): the code below is necessary to prevent converting
-//  1-bpp images with alpha channel to 8-bpp images. it is currently
-//  commented out only for compatibility with Qt/Win32; Qt/OS2 is ready
-//  to handle such images properly.
-//		QRgb c0 = image.color(0) | ~RGB_MASK;	// Auto: convert to best
-//		QRgb c1 = image.color(1) | ~RGB_MASK;
+                // Note: 1-bpp images other than true black-white cannot be
+                // correctly stored as GPI bitmaps (it doesn't store the palette
+                // for them), so the code below ensures they will be converted
+                // to 8-bpp images first. However, black-white images with alpha
+                // channel will be also converted, though they can be stored
+                // as bitmaps. The correct code to prevent setting conv8 to TRUE
+                // for black-white bitmaps both with and w/o alpha should be:
+                //      QRgb c0 = image.color(0) | ~RGB_MASK;
+                //      QRgb c1 = image.color(1) | ~RGB_MASK;
+                // but it is left as is solely for compatibility with Qt/Win32
+                // (otherwise we would get visually different pixmaps).
 		QRgb c0 = image.color(0);	// Auto: convert to best
 		QRgb c1 = image.color(1);
@@ -607,10 +586,5 @@
 
     bool hasRealAlpha = FALSE;
-    if ( img.hasAlphaBuffer()
-//@@TODO (dmik): remove later.
-//        &&
-//	    ( QApplication::winVersion() != Qt::WV_95 &&
-//	      QApplication::winVersion() != Qt::WV_NT )
-    ) {
+    if ( img.hasAlphaBuffer() ) {
         if (image.depth() == 8) {
 	    const QRgb * const rgb = img.colorTable();
@@ -623,7 +597,6 @@
 	    }
 	    if (hasRealAlpha) {
-//@@TODO (dmik): also need to convert? guess yes.
-//		image = image.convertDepth(32, conversion_flags);
-//		d = image.depth();
+		image = image.convertDepth(32, conversion_flags);
+		d = image.depth();
 	    }
 	} else if (image.depth() == 32) {
@@ -645,38 +618,31 @@
     }
 
-//@@TODO (dmik): temporary code. will be removed when alpha support is done.
-    if ( hasRealAlpha ) {
-        qWarning( "QPixmap::convertFromImage() for images with alpha is not yet implemented on OS/2" );
-        hasRealAlpha = FALSE;
-    }
-
     int w = image.width();
     int h = image.height();
 
-    if ( width() == w && height() == h && ( (d == 1 && depth() == 1) ||
-					    (d != 1 && depth() != 1) ) ) {
-	if ( data->realAlphaBits && !hasRealAlpha ) {
-//@@TODO (dmik): later
-//	    // pixmap uses a DIB section, but image has no alpha channel, so we
-//	    // can't reuse the old pixmap
-//	    QPixmap pm(w, h, d == 1 ? 1 : -1, data->bitmap, data->optim);
-//	    *this = pm;
-	} else {
-	    // same size etc., use the existing pixmap
-	    detach();
-	    if ( data->mask ) {			// get rid of the mask
-		delete data->mask;
-		data->mask = 0;
-                if ( data->maskedHbm ) {
-                    GpiDeleteBitmap( data->maskedHbm );
-                    data->maskedHbm = 0;
-                }
-	    }
-	}
+    if ( width() == w && height() == h &&
+         ( (d == 1 && depth() == 1) ||
+           (d != 1 && depth() != 1 && hasRealAlpha == hasAlphaChannel()) ) ) {
+        // same size etc., use the existing pixmap
+        detach();
+        if ( data->mask ) {			// get rid of the mask
+            delete data->mask;
+            data->mask = 0;
+            if ( data->maskedHbm )
+                prepareForMasking( FALSE, TRUE );
+        }
     } else {
 	// different size or depth, make a new pixmap
-	QPixmap pm(w, h, d == 1 ? 1 : -1, data->bitmap, data->optim);
+	QPixmap pm( w, h, d == 1 ? 1 : -1, data->bitmap, data->optim );
 	*this = pm;
     }
+
+#if defined QT_CHECK_RANGE      
+    if ( d == 32 && trueColorDepth() != 32 )
+        qWarning( "QPixmap::convertFromImage(): video driver doesn't seem to "
+                  "support the 32-bpp color depth!" );
+        // don't return since we still hope the driver can at least convert
+        // from/to 32-bpp bitmaps
+#endif            
 
     int	  ncols	   = image.numColors();
@@ -707,5 +673,5 @@
             r->bBlue = qBlue( c );
             r->bGreen = qGreen( c );
-            r->bRed = qRed( c);
+            r->bRed = qRed( c );
             r->fcOptions = 0;
             if ( doAlloc ) {
@@ -716,60 +682,54 @@
     }
 
-//@@TODO (dmik): later
-//#ifndef Q_OS_TEMP
-//    if ( hasRealAlpha ) {
-//	initAlphaPixmap( image.bits(), image.numBytes(), bmi );
-//
-//	// Windows expects premultiplied alpha
-//	uchar *p = image.bits();
-//	uchar *b = data->realAlphaBits;
-//	uchar *end = p + image.numBytes();
-//	uchar alphaByte;
-//	while ( p < end ) {
-//	    alphaByte = *(p+3);
-//	    if ( alphaByte == 0 ) {
-//		*(b++) = 0;
-//		*(b++) = 0;
-//		*(b++) = 0;
-//		b++;
-//		p += 4;
-//	    } else if ( alphaByte == 255 ) {
-//		b += 4;
-//		p += 4;
-//	    } else {
-//		*(b++) = ( (*(p++)) * (int)alphaByte + 127 ) / 255;
-//		*(b++) = ( (*(p++)) * (int)alphaByte + 127 ) / 255;
-//		*(b++) = ( (*(p++)) * (int)alphaByte + 127 ) / 255;
-//		b++;
-//		p++;
-//	    }
-//	}
-//    }
-//#else
-    data->realAlphaBits = 0;
-//#endif
-
-    if ( data->realAlphaBits == 0 ) {
-        // flip the image top to bottom
-        image.detach();
-        int bpl = image.bytesPerLine();
-        uchar *line = new uchar[bpl];
-        uchar *top = image.scanLine( 0 );
-        uchar *bottom = image.scanLine( h - 1 );
-        while( top < bottom ) {
-            memcpy( line, top, bpl );
-            memcpy( top, bottom, bpl );
-            memcpy( bottom, line, bpl );
-            top += bpl;
-            bottom -= bpl;
-        }
-        delete [] line;
-        GpiSetBitmapBits( hps, 0, h, (PBYTE) image.bits(), (PBITMAPINFO2) bmi_data );
-    }
+    data->hasRealAlpha = hasRealAlpha;
+
+    // If we have real alpha bits and the default video driver depth is 32-bpp,
+    // we store the alpha channel in the unused high byte of the 32-bit pixel
+    // value to save memory and slightly optimize the performance (QImage already
+    // contains the alpha channel there, so nothing has to be done when setting
+    // bitmap bits). Otherwise we create a separate array to store the alpha
+    // channel from QImage. 
+    
+    if ( hasRealAlpha && depth() != 32 ) {
+        if ( data->realAlphaBits == 0 ) {
+            // alpha bits buffer doesn't exist yet, create it
+            data->realAlphaBits = new uchar [w * h];
+        }
+        // store alpha bits flipping scan lines top to bottom
+        uchar *dst = data->realAlphaBits + w * (h - 1);
+        int y = 0;
+        while ( y < image.height() ) {
+            uchar *src = image.scanLine( y++ );
+            uchar *end = src + image.bytesPerLine();
+            src += 3;
+            while ( src < end ) {
+                *(dst++) = *src;
+                src += 4;
+            }
+            // go to the previous row
+            dst -= w * 2;
+        }
+    } 
+
+    // flip the image top to bottom
+    image.detach();
+    int bpl = image.bytesPerLine();
+    uchar *line = new uchar[bpl];
+    uchar *top = image.scanLine( 0 );
+    uchar *bottom = image.scanLine( h - 1 );
+    while( top < bottom ) {
+        memcpy( line, top, bpl );
+        memcpy( top, bottom, bpl );
+        memcpy( bottom, line, bpl );
+        top += bpl;
+        bottom -= bpl;
+    }
+    delete [] line;
+    GpiSetBitmapBits( hps, 0, h, (PBYTE) image.bits(), (PBITMAPINFO2) bmi_data );
 
     if ( img.hasAlphaBuffer() ) {
 	QBitmap m;
 	m = img.createAlphaMask( conversion_flags );
-	setMask( m );
+        data->mask = new QBitmap( m ); 
     }
 
@@ -834,5 +794,5 @@
 	h = QABS( h );
 	w = QABS( w );
-	if ( data->realAlphaBits == 0 ) {
+	if ( !data->hasRealAlpha ) {
 	    QPixmap pm( w, h, depth(), optimization() );
             POINTL ptls[] = {
@@ -869,5 +829,5 @@
     }
 
-    if ( data->realAlphaBits ) {
+    if ( data->hasRealAlpha ) {
 	bpp = 32;
     } else {
@@ -877,6 +837,6 @@
     }
 
-    sbpl = ((ws*bpp+31)/32)*4;
-    sptr = new uchar[hs*sbpl];
+    sbpl = ((ws * bpp + 31) / 32) * 4;
+    sptr = new uchar[ hs * sbpl ];
     int ncols;
     if ( bpp <= 8 ) {
@@ -886,4 +846,12 @@
     }
 
+#if defined QT_CHECK_RANGE      
+    if ( bpp == 32 && trueColorDepth() != 32 )
+        qWarning( "QPixmap::xForm(): video driver doesn't seem to "
+                  "support the 32-bpp color depth!" );
+        // don't return since we still hope the driver can at least convert
+        // from/to 32-bpp bitmaps
+#endif            
+    
     // allocate header + ncols palette entries
     int bmi_data_len = sizeof(BITMAPINFOHEADER2) + 4 * ncols;
@@ -905,20 +873,24 @@
     }
 
-    int result;
-    if ( data->realAlphaBits ) {
-	memcpy( sptr, data->realAlphaBits, sbpl*hs );
-	result = 1;
-    } else {
-        result = GpiQueryBitmapBits( hps, 0, hs, (PBYTE) sptr, (PBITMAPINFO2) bmi_data );
-    }
-
-    if ( !result ) {				// error, return null pixmap
-	delete [] sptr;
-        delete [] bmi_data;
-	return QPixmap( 0, 0, 0, data->bitmap, NormalOptim );
-    }
-
-    dbpl   = ((w*bpp+31)/32)*4;
-    dbytes = dbpl*h;
+    GpiQueryBitmapBits( hps, 0, hs, (PBYTE) sptr, (PBITMAPINFO2) bmi_data );
+    
+    if ( data->hasRealAlpha && data->realAlphaBits ) {
+        // incorporate the alpha channel to image data
+        // (see comments in convertFromImage() for details)
+        int bpx = bpp / 8;
+        int inc = sbpl - bpx * ws;
+        uchar *src = data->realAlphaBits;
+        uchar *dst = sptr + 3; // move to the alpha byte 
+        for ( int y = 0; y < hs; ++ y ) {
+            for ( int x = 0; x < ws; ++ x ) {
+                *dst = *(src++); 
+                dst += bpx;
+            }
+            dst += inc;
+        }
+    }
+    
+    dbpl   = ((w * bpp + 31) / 32) * 4;
+    dbytes = dbpl * h;
 
     dptr = new uchar[ dbytes ];			// create buffer for bits
@@ -928,5 +900,5 @@
     else if ( bpp == 8 )
 	memset( dptr, white.pixel(), dbytes );
-    else if ( data->realAlphaBits )
+    else if ( data->hasRealAlpha )
 	memset( dptr, 0x00, dbytes );
     else
@@ -935,8 +907,8 @@
     int	  xbpl, p_inc;
     if ( depth1 ) {
-	xbpl  = (w+7)/8;
+	xbpl  = (w + 7) / 8;
 	p_inc = dbpl - xbpl;
     } else {
-	xbpl  = (w*bpp)/8;
+	xbpl  = (w * bpp) / 8;
 	p_inc = dbpl - xbpl;
     }
@@ -963,13 +935,6 @@
     bmh.cx = w;
     bmh.cy = h;
-    if ( data->realAlphaBits ) {
-        qWarning( "QPixmap::xForm() for pixmaps with alpha is not yet implemented on OS/2" );
-/// @todo (dmik) later
-//	pm.initAlphaPixmap( dptr, dbytes, bmi );
-    } else {
-        GpiSetBitmapBits( pm.hps, 0, h, (PBYTE) dptr, (PBITMAPINFO2) bmi_data );
-    }
-    delete [] bmi_data;
-    delete [] dptr;
+    GpiSetBitmapBits( pm.hps, 0, h, (PBYTE) dptr, (PBITMAPINFO2) bmi_data );
+    
     if ( data->mask ) {
 	QBitmap bm = data->selfmask ? *((QBitmap*)(&pm)) :
@@ -977,4 +942,27 @@
 	pm.setMask( bm );
     }
+    
+    if ( data->hasRealAlpha ) {
+        pm.data->hasRealAlpha = TRUE; 
+        if ( pm.depth() != 32 ) {
+            // we are not able to store the alpha channel in the bitmap bits,
+            // store it separately
+            pm.data->realAlphaBits = new uchar[ w * h ];
+            int bpx = bpp / 8;
+            uchar *dst = pm.data->realAlphaBits;
+            uchar *src = dptr + 3; // move to the alpha byte
+            for ( int y = 0; y < h; ++ y ) {
+                for ( int x = 0; x < w; ++ x ) {
+                    *(dst++) = *src;
+                    src += bpx;
+                }
+                src += p_inc;
+            }
+        }
+    }
+    
+    delete [] bmi_data;
+    delete [] dptr;
+    
     return pm;
 }
@@ -988,149 +976,23 @@
 bool QPixmap::hasAlpha() const
 {
-    return data->realAlphaBits || data->mask;
+    return data->hasRealAlpha || data->mask;
 }
 
 bool QPixmap::hasAlphaChannel() const
 {
-    return data->realAlphaBits != 0;
-}
-
-//@@TODO (dmik): later
-//void QPixmap::convertToAlphaPixmap( bool initAlpha )
-//{
-//    char bmi_data[sizeof(BITMAPINFO)];
-//    memset( bmi_data, 0, sizeof(BITMAPINFO) );
-//    BITMAPINFO	     *bmi = (BITMAPINFO*)bmi_data;
-//    BITMAPINFOHEADER *bmh = (BITMAPINFOHEADER*)bmi;
-//    bmh->biSize		  = sizeof(BITMAPINFOHEADER);
-//    bmh->biWidth	  = width();
-//    bmh->biHeight	  = -height();			// top-down bitmap
-//    bmh->biPlanes	  = 1;
-//    bmh->biBitCount	  = 32;
-//    bmh->biCompression	  = BI_RGB;
-//    bmh->biSizeImage	  = width() * height() * 4;
-//    bmh->biClrUsed	  = 0;
-//    bmh->biClrImportant	  = 0;
-//
-//    QPixmap pm( width(), height(), -1 );
-//    pm.initAlphaPixmap( 0, 0, bmi );
-//
-//#ifndef Q_OS_TEMP
-//    GetDIBits( qt_display_dc(), DATA_HBM, 0, height(), pm.data->realAlphaBits, bmi, DIB_RGB_COLORS );
-//    if ( initAlpha ) {
-//	// In bitBlt(), if the destination has an alpha channel and the source
-//	// doesn't have one, we bitBlt() the source with the destination's
-//	// alpha channel. In that case, there is no need to initialize the
-//	// alpha values.
-//	uchar *p = pm.data->realAlphaBits;
-//	uchar *pe = p + bmh->biSizeImage;
-//	if ( mask() ) {
-//	    QImage msk = mask()->convertToImage();
-//	    int i = 0;
-//	    int w = width();
-//	    int backgroundIndex = msk.color(0) == Qt::color0.rgb() ? 0 : 1;
-//	    while ( p < pe ) {
-//		if ( msk.pixelIndex( i%w, i/w ) == backgroundIndex ) {
-//		    *(p++) = 0x00;
-//		    *(p++) = 0x00;
-//		    *(p++) = 0x00;
-//		    *(p++) = 0x00;
-//		} else {
-//		    p += 3;
-//		    *(p++) = 0xff;
-//		}
-//		++i;
-//	    }
-//	} else {
-//	    p += 3;
-//	    while ( p < pe ) {
-//		*p = 0xff;
-//		p += 4;
-//	    }
-//	}
-//    }
-//#else
-//    memcpy( pm.data->ppvBits, data->ppvBits, bmh->biSizeImage );
-//#endif
-//    if ( mask() )
-//	pm.setMask( *mask() );
-//
-//    *this = pm;
-//}
-//
-//void QPixmap::bitBltAlphaPixmap( QPixmap *dst, int dx, int dy,
-//			         const QPixmap *src, int sx, int sy,
-//			         int sw, int sh, bool useDstAlpha )
-//{
-//    if ( sw < 0 )
-//	sw = src->width() - sx;
-//    else
-//	sw = QMIN( src->width()-sx, sw );
-//    sw = QMIN( dst->width()-dx, sw );
-//
-//    if ( sh < 0 )
-//	sh = src->height() - sy ;
-//    else
-//	sh = QMIN( src->height()-sy, sh );
-//    sh = QMIN( dst->height()-dy, sh );
-//
-//    if ( sw <= 0 || sh <= 0 )
-//	return;
-//
-//#ifndef Q_OS_TEMP
-//    GdiFlush();
-//#endif
-//    uchar *sBits = src->data->realAlphaBits + ( sy * src->width() + sx ) * 4;
-//    uchar *dBits = dst->data->realAlphaBits + ( dy * dst->width() + dx ) * 4;
-//    int sw4 = sw * 4;
-//    int src4 = src->width() * 4;
-//    int dst4 = dst->width() * 4;
-//    if ( useDstAlpha ) {
-//	// Copy the source pixels premultiplied with the destination's alpha
-//	// channel. The alpha channel remains the destination's alpha channel.
-//	uchar *sCur;
-//	uchar *dCur;
-//	uchar alphaByte;
-//	for ( int i=0; i<sh; i++ ) {
-//	    sCur = sBits;
-//	    dCur = dBits;
-//	    for ( int j=0; j<sw; j++ ) {
-//		alphaByte = *(dCur+3);
-//		if ( alphaByte == 0 || (*(sCur+3)) == 0 ) {
-//		    dCur += 4;
-//		    sCur += 4;
-//		} else if ( alphaByte == 255 ) {
-//		    *(dCur++) = *(sCur++);
-//		    *(dCur++) = *(sCur++);
-//		    *(dCur++) = *(sCur++);
-//		    dCur++;
-//		    sCur++;
-//		} else {
-//		    *(dCur++) = ( (*(sCur++)) * (int)alphaByte + 127 ) / 255;
-//		    *(dCur++) = ( (*(sCur++)) * (int)alphaByte + 127 ) / 255;
-//		    *(dCur++) = ( (*(sCur++)) * (int)alphaByte + 127 ) / 255;
-//		    dCur++;
-//		    sCur++;
-//		}
-//	    }
-//	    sBits += src4;
-//	    dBits += dst4;
-//	}
-//    } else {
-//	// Copy the source into the destination. Use the source's alpha
-//	// channel.
-//	for ( int i=0; i<sh; i++ ) {
-//	    memcpy( dBits, sBits, sw4 );
-//	    sBits += src4;
-//	    dBits += dst4;
-//	}
-//    }
-//}
-
-// Prepares for painting the masked pixmap: precomposes and selects the
-// masked pixmap (with transparent pixels made black) into this pixmap's hps.
-// If prepare = FALSE, it does the cleanup. Currently used in ::bitBlt()
-// and in QPixmap::createIcon().
-void QPixmap::prepareForMasking( bool prepare )
+    return data->hasRealAlpha;
+}
+
+/**
+ *  \internal
+ *  If \a prepare is TRUE, prepares for painting a pixmap with mask: precomposes
+ *  and selects a masked bitmap (with transparent pixels made black) into this
+ *  pixmap's hps. If \a prepare is FALSE, it does the cleanup. If \a force is
+ *  TRUE on cleanup, the masked bitmap is destroyed regardless of the
+ *  optimization type.
+ * 
+ *  Currently used in ::bitBlt() and in QPixmap::createIcon().
+ */
+void QPixmap::prepareForMasking( bool prepare, bool force /* = FALSE */ )
 {
     if ( !data->mask || data->selfmask )
@@ -1175,9 +1037,7 @@
         GpiSetBitmap( hps, data->hbm );
         // delete the precomposed masked pixmap when memory optimization
-        // is in force or when no precomosing was done
-        if (
-            data->maskedHbm &&
-            (data->optim != NormalOptim && data->optim != BestOptim)
-        ) {
+        // is in force (or force is TRUE)
+        if ( data->maskedHbm && (force || (data->optim != NormalOptim &&
+                                           data->optim != BestOptim)) ) {
             GpiDeleteBitmap( data->maskedHbm );
             data->maskedHbm = 0;
@@ -1295,4 +1155,135 @@
 }
 
+void QPixmap::unfoldAlphaChannel()
+{
+    // do nothing if there is no alpha channel or if it is already unfolded
+    // (i.e. stored in a separate array)
+    if ( !data->hasRealAlpha || data->realAlphaBits )
+        return;
+
+    Q_ASSERT( data->d == 32 );
+    if ( !data->d == 32 )
+        return;
+    
+    data->realAlphaBits = new uchar[ data->w * data->h ];
+    
+    // no space for palette, since the depth is 32-bpp
+    BITMAPINFOHEADER2 bmh;
+    memset( &bmh, 0, sizeof(BITMAPINFOHEADER2) );
+    bmh.cbFix = sizeof(BITMAPINFOHEADER2);
+    bmh.cx = data->w;
+    bmh.cy = data->h;
+    bmh.cPlanes = 1;
+    bmh.cBitCount = data->d;
+    
+    int bpl = ((data->d * data->w + 31) / 32) * 4;
+    uchar *bits = new uchar [bpl * data->h];
+    
+    GpiQueryBitmapBits( hps, 0, data->h, (PBYTE) bits, (PBITMAPINFO2) &bmh );
+
+    int bpx = data->d / 8;
+    int inc = bpl - bpx * data->w;
+    uchar *src = bits + 3; // move to the alpha byte
+    uchar *dst = data->realAlphaBits;
+    for ( int y = 0; y < data->h; ++ y ) {
+        for ( int x = 0; x < data->w; ++ x ) {
+            *(dst++) = *src;
+            src += bpx;
+        }
+        src += inc;
+    }
+    
+    delete[] bits;
+}
+
+/**
+ *  \internal
+ *  Converts the pixmap (actually, the pixmap's mask, if any) to the alpha
+ *  channel. Implies #unfoldAlphaChannel().
+ */
+void QPixmap::convertToAlpha()
+{
+    if ( isNull() || data->hasRealAlpha )
+        return;
+    
+    if ( data->mask ) {
+        // allocate header + 2 palette entries
+        char *bmi_data = new char[ sizeof(BITMAPINFOHEADER2) + 8 ];
+        memset( bmi_data, 0, sizeof(BITMAPINFOHEADER2) );
+        BITMAPINFOHEADER2 &bmh = *(PBITMAPINFOHEADER2) bmi_data;
+        bmh.cbFix = sizeof(BITMAPINFOHEADER2);
+        bmh.cx = data->w;
+        bmh.cy = data->h;
+        bmh.cPlanes = 1;
+        bmh.cBitCount = 1;
+        bmh.cclrUsed = 2;
+        
+        int bpl = ((data->w + 31) / 32) * 4;
+        uchar *bits = new uchar [bpl * data->h];
+        
+        GpiQueryBitmapBits( data->mask->hps, 0, data->h, (PBYTE) bits,
+                            (PBITMAPINFO2) bmi_data );
+
+        data->realAlphaBits = new uchar[ data->w * data->h ];
+
+        int inc = bpl - data->w / 8;
+        uchar *src = bits;
+        uchar *dst = data->realAlphaBits;
+        uchar m = 0x80;
+        for ( int y = 0; y < data->h; ++ y ) {
+            for ( int x = 0; x < data->w; ++ x ) {
+                *(dst ++) = (*src) & m ? 0xFF : 0x00; 
+                m >>= 1;
+                if ( !m ) {
+                    m = 0x80;
+                    ++ src;
+                }
+            }
+            src += inc;
+        }
+        
+        data->hasRealAlpha = TRUE;
+        
+        delete[] bits;
+        delete[] bmi_data;
+    } else {
+        data->realAlphaBits = new uchar[ data->w * data->h ];
+        memset( data->realAlphaBits, 0xFF, data->w * data->h );
+        data->hasRealAlpha = TRUE;
+    }
+}
+
+/**
+ *  \internal
+ *  This depth is used when querying and setting bitmap bits for pixmaps
+ *  with alpha channel, either 24 or 32 (depending on the video driver caps).
+ *  \note This depth is not used to create bitmaps (#defaultDepth() is always
+ *  in charge for that purpose). 
+ */
+//static
+int QPixmap::trueColorDepth()
+{
+    static int tcd = 0;
+    if ( tcd == 0 ) {
+        HDC display_dc = GpiQueryDevice( qt_display_ps() );
+        LONG formatCnt = 0;
+        DevQueryCaps( display_dc, CAPS_BITMAP_FORMATS, 1, &formatCnt );
+        LONG *formats = new LONG[ formatCnt * 2 ];
+        GpiQueryDeviceBitmapFormats( qt_display_ps(), formatCnt * 2, formats );
+        for( int i = 0; i < formatCnt * 2; i += 2 ) {
+            if ( formats[ i ] == 1 && formats[ i + 1 ] == 32 ) {
+                tcd = 32;
+                break;
+            }
+        }
+        delete[] formats;
+        // if the 32-bpp format is not supported, we assume the 24-bpp
+        // format that must be supported by all video drivers
+        if ( tcd == 0 )
+            tcd = 24;
+    }
+    return tcd;
+}
+
 /*!
     \internal
@@ -1306,7 +1297,12 @@
     \param mini pixmap for a mini-sized pointer/icon
     
+    \return PM handle of the created pointer or 0 in case of any error
+    
     \note Due to a bug in WinCreatePointerIndirect, you can specify either
     \a normal pixmap or \a mini pixmap, but not both (if both are specified,
-    \a normal will be used). This may be fixed later. 
+    \a normal will be used). PM will use scaling to draw a pointer of the
+    other size when necessary. This bug may be fixed later.
+    
+    \warning This function is not portable.    
 */
 // static
@@ -1316,8 +1312,7 @@
     // Due to a bug in WinCreatePointerIndirect (it always ignores
     // hbmMiniPointer and hbmMiniColor fields), we can specify either a normal
-    // icon (and get a mini icon autocreated by PM) or a mini icon (with a
-    // normal icon autocreated by PM), but not both. This methods still accepts
-    // pixmaps for both icon sizes (assuming that we will find a workaround one
-    // day) but uses only one of them.
+    // icon, but not both. This methods still accepts pixmaps for both icon
+    // sizes (assuming that we will find a workaround one day) but uses only
+    // one of them.
     
     if ( normal && !normal->isNull() ) {
@@ -1347,16 +1342,41 @@
 	return;
     }
-
+    
+    if ( sw < 0 )
+        sw = src->width() - sx;
+    if ( sh < 0 )
+        sh = src->height() - sy;
+    
+    // ensure coordinates are within borders, clip if necessary
+    if ( sx < 0 || sy < 0 || sx + sw > src->width() || sy + sh > src->height() ||
+         dx < 0 || dy < 0 || dx + sw > dst->width() || dy + sh > dst->height() )
+    {
+        int tx = dx - sx;
+        int ty = dy - sy;
+        QRect dr( 0, 0, dst->width(), dst->height() ); // dst rect
+        QRect sr( tx, ty, src->width(), src->height() ); // src rect in dst coords
+        QRect bltr( dx, dy, sw, sh ); // blit rect in dst coords
+        bltr &= (dr & sr);
+        if (bltr.isEmpty())
+            return;
+        dx = bltr.x();
+        dy = bltr.y();
+        sx = dx - tx;
+        sy = dy - ty;
+        sw = bltr.width();
+        sh = bltr.height();
+    }
+    
+    dst->detach();
+        
     // copy mask data
     if ( src->data->mask ) {
-	if ( ! dst->data->mask ) {
+	if ( !dst->data->mask ) {
 	    dst->data->mask = new QBitmap( dst->width(), dst->height() );
-
 	    // new masks are fully opaque by default
 	    dst->data->mask->fill( Qt::color1 );
 	} else if ( dst->data->maskedHbm ) {
             // reset the precomposed masked pixmap
-            GpiDeleteBitmap( dst->data->maskedHbm );
-            dst->data->maskedHbm = 0;
+            dst->prepareForMasking( FALSE, TRUE );
         }
 
@@ -1364,14 +1384,26 @@
 		src->data->mask, sx, sy, sw, sh, Qt::CopyROP, TRUE );
     }
-
-    if ( src->data->realAlphaBits ) {
-        qWarning( "::copyBlt() for pixmaps with alpha is not yet implemented on OS/2" );
-//@@TODO (dmik): later
-//	if ( !dst->data->realAlphaBits )
-//	    dst->convertToAlphaPixmap();
-//	QPixmap::bitBltAlphaPixmap( dst, dx, dy, src, sx, sy, sw, sh, FALSE );
-    } else {
-	// copy pixel data
-	bitBlt( dst, dx, dy, src, sx, sy, sw, sh, Qt::CopyROP, TRUE );
-    }
-}
+    
+    // copy alpha bits
+    if ( src->data->hasRealAlpha ||
+         (src->data->mask && dst->data->hasRealAlpha) ) {
+        if ( src->data->hasRealAlpha )
+            const_cast <QPixmap *> (src)->unfoldAlphaChannel();
+        else
+            const_cast <QPixmap *> (src)->convertToAlpha();
+        if ( dst->data->hasRealAlpha )
+            dst->unfoldAlphaChannel();
+        else
+            dst->convertToAlpha();
+        uchar *srca = src->data->realAlphaBits + src->width() * sy + sx;
+        uchar *dsta = dst->data->realAlphaBits + dst->width() * dy + dx;
+        for ( int y = 0; y < sh; ++ y ) {
+            memcpy( dsta, srca, sw );
+            srca += src->width();
+            dsta += dst->width();
+        }
+    }
+    
+    // copy pixel data
+    bitBlt( dst, dx, dy, src, sx, sy, sw, sh, Qt::CopyROP, TRUE );
+}
