Index: trunk/src/kernel/qapplication_pm.cpp
===================================================================
--- trunk/src/kernel/qapplication_pm.cpp	(revision 60)
+++ trunk/src/kernel/qapplication_pm.cpp	(revision 61)
@@ -43,8 +43,4 @@
 
 #include "qapplication.h"
-//@@TODO (dmik): need?
-//#if defined(QT_NON_COMMERCIAL)
-//#include "qnc_win.h"
-//#endif
 #include "private/qapplication_p.h"
 #include "qwidget.h"
@@ -606,20 +602,4 @@
 }
 
-//@@TODO (dmik): later (guess remove)
-//Q_EXPORT HINSTANCE qWinAppInst()		// get Windows app handle
-//{
-//    return appInst;
-//}
-//
-//Q_EXPORT HINSTANCE qWinAppPrevInst()		// get Windows prev app handle
-//{
-//    return appPrevInst;
-//}
-//
-//Q_EXPORT int qWinAppCmdShow()			// get main window show command
-//{
-//    return appCmdShow;
-//}
-
 Q_EXPORT HPS qt_display_ps()			// get display PS
 {
@@ -1054,9 +1034,4 @@
 //    }
 //    */
-
-//@@TODO (dmik): need?
-//#if defined(QT_NON_COMMERCIAL)
-//    QT_NC_WNDPROC
-//#endif
 
     if ( qt_pmEventFilter( &qmsg, rc ) )	// send through app filter
@@ -1392,8 +1367,4 @@
 	    bool window_state_change = FALSE;
             PSWP pswp = (PSWP) mp1;
-//@@TODO (dmik): need?
-//#if defined(QT_NON_COMMERCIAL)
-//		QT_NC_SYSCOMMAND
-//#endif
             if ( pswp->fl & SWP_MAXIMIZE ) {
 		window_state_change = TRUE;
@@ -1432,66 +1403,5 @@
         }
 
-//@@TODO (dmik): remove, we processed these in the message above.
-//@@TODO (dmik): what to do with QWhatsThis?..
-//	case WM_SYSCOMMAND: {
-//#ifndef Q_OS_TEMP
-//	    bool window_state_change = FALSE;
-//	    switch( wParam ) {
-//	    case SC_CONTEXTHELP:
-//#ifndef QT_NO_WHATSTHIS
-//		QWhatsThis::enterWhatsThisMode();
-//#endif
-//		QT_WA( {
-//		    DefWindowProc( hwnd, WM_NCPAINT, 1, 0 );
-//		} , {
-//		    DefWindowProcA( hwnd, WM_NCPAINT, 1, 0 );
-//		} );
-//		break;
-//#if defined(QT_NON_COMMERCIAL)
-//		QT_NC_SYSCOMMAND
-//#endif
-//	    case SC_MAXIMIZE:
-//		window_state_change = TRUE;
-//		widget->clearWState(Qt::WState_Minimized);
-//		widget->setWState(Qt::WState_Maximized);
-//		result = FALSE;
-//		break;
-//	    case SC_MINIMIZE:
-//		window_state_change = TRUE;
-//		widget->setWState(Qt::WState_Minimized);
-//		if ( widget->isVisible() ) {
-//		    QHideEvent e;
-//		    qt_sendSpontaneousEvent( widget, &e );
-//		    widget->hideChildren( TRUE );
-//		}
-//		result = FALSE;
-//		break;
-//	    case SC_RESTORE:
-//		window_state_change = TRUE;
-//		if (widget->isMinimized()) {
-//		    widget->clearWState(Qt::WState_Minimized);
-//		    widget->showChildren( TRUE );
-//		    QShowEvent e;
-//		    qt_sendSpontaneousEvent( widget, &e );
-//		} else {
-//		    widget->clearWState(Qt::WState_Maximized);
-//		}
-//		result = FALSE;
-//		break;
-//	    default:
-//		result = FALSE;
-//		break;
-//	    }
-//
-//	    if (window_state_change) {
-//		QEvent e(QEvent::WindowStateChange);
-//		qt_sendSpontaneousEvent(widget, &e);
-//	    }
-//#endif
-//
-//	    break;
-//	}
-
-//@@TODO (dmik): later
+/// @todo (dmik) later
 //	case WM_SETTINGCHANGE:
 //	    if ( !msg.wParam ) {
@@ -1552,15 +1462,17 @@
 
         case WM_ACTIVATE:
-//@@TODO (dmik): remove
-//qDebug("WM_ACTIVATE: [%s] %d", widget->name(), SHORT1FROMMP(mp1) );
+#if 0
+            qDebug( "WM_ACTIVATE: [%s] %d", widget->name(), SHORT1FROMMP(mp1) );
+#endif            
 	    qApp->pmFocus( widget, SHORT1FROMMP(mp1) );
 	    break;
 
         case WM_SETFOCUS:
-//@@TODO (dmik): remove
-//qDebug("WM_SETFOCUS: [%s] %s [%s]", widget->name(),
-//        SHORT1FROMMP(mp2) ? "<=" : "=>",
-//        QWidget::find( (HWND)mp1 ) ? QWidget::find( (HWND)mp1 )->name() : "{foreign}"
-//);
+#if 0            
+            qDebug( "WM_SETFOCUS: [%s] %s [%s]", widget->name(),
+                    SHORT1FROMMP(mp2) ? "<=" : "=>",
+                    QWidget::find( (HWND)mp1 ) ? QWidget::find( (HWND)mp1 )->name()
+                                               : "{foreign}" );
+#endif            
             result = FALSE;
             if ( !SHORT1FROMMP(mp2) ) {
@@ -1589,20 +1501,5 @@
             break;
 
-//@@TODO (dmik): remove, handled in OS/2 version of WM_SETFOCUS above
-//	case WM_ACTIVATE:
-//	    if ( QApplication::activePopupWidget() && LOWORD(wParam) == WA_INACTIVE &&
-//		QWidget::find((HWND)lParam) == 0 ) {
-//		// Another application was activated while our popups are open,
-//		// then close all popups.  In case some popup refuses to close,
-//		// we give up after 1024 attempts (to avoid an infinite loop).
-//		int maxiter = 1024;
-//		QWidget *popup;
-//		while ( (popup=QApplication::activePopupWidget()) && maxiter-- )
-//		    popup->close();
-//	    }
-//	    qApp->winFocus( widget, LOWORD(wParam) == WA_INACTIVE ? 0 : 1 );
-//	    break;
-
-//@@TODO (dmik): later
+/// @todo (dmik) remove?
 //#ifndef Q_OS_TEMP
 //	    case WM_MOUSEACTIVATE:
@@ -1623,5 +1520,5 @@
             result = FALSE;
             break;
-//@@TODO (dmik): remove later
+/// @todo (dmik) remove later
 //	    case WM_SHOWWINDOW:
 //#ifndef Q_OS_TEMP
@@ -1656,5 +1553,5 @@
 	    RETURN(0);				// always handled
 
-//@@TODO (dmik): it seems we don't need this
+/// @todo (dmik) it seems we don't need this
 //	case WM_DESTROY:			// destroy window
 //	    if ( hwnd == curWin ) {
@@ -3364,17 +3261,9 @@
 #endif
 
-    // convert region y coordinates from GPI to Qt (see qregion_pm.cpp)
-    POINTL ptl = { 0, -height() };
-    GpiOffsetRegion( hps, hrgn, &ptl );
-    // create a non-null region
-    QRegion rgn( FALSE );
-    // destructor will delete rgn
-    rgn.data->rgn = hrgn;
-
-    QPaintEvent e(
-        rgn,
-        QRect( rcl.xLeft, rcl.yBottom, rcl.xRight, rcl.yTop ),
-        erase
-    );
+    // create a region that will take ownership of hrgn
+    QRegion rgn( hrgn, height() );
+
+    QPaintEvent e( rgn, QRect( rcl.xLeft, rcl.yBottom, rcl.xRight, rcl.yTop ),
+                   erase );
     QApplication::sendSpontaneousEvent( this, (QEvent*) &e );
 
@@ -3455,7 +3344,4 @@
         }
         QPoint newCPos( swp.x, swp.y );
-//@@TODO (dmik): should it apply to OS/2?
-//	// Ignore silly Windows move event to wild pos after iconify.
-//	if ( !isMinimized() && newCPos != oldPos ) {
 	if ( newCPos != oldPos ) {
 	    cr.moveTopLeft( newCPos );
Index: trunk/src/kernel/qcolor_pm.cpp
===================================================================
--- trunk/src/kernel/qcolor_pm.cpp	(revision 60)
+++ trunk/src/kernel/qcolor_pm.cpp	(revision 61)
@@ -248,5 +248,5 @@
 
 /*! \internal */
-//@@TODO (dmik): this seems not to be used anywhere
+/// @todo (dmik) this seems not to be used anywhere, remove?
 //uint QColor::realizePal( QWidget *widget )
 //{
Index: trunk/src/kernel/qpaintdevice_pm.cpp
===================================================================
--- trunk/src/kernel/qpaintdevice_pm.cpp	(revision 60)
+++ trunk/src/kernel/qpaintdevice_pm.cpp	(revision 61)
@@ -536,10 +536,5 @@
     if ( td != QInternal::Pixmap ) {
 	if ( !dst_ps && td == QInternal::Widget ) {
-            QWidget *dst_w = (QWidget*)dst;
-	    if ( dst_w->testWFlags(Qt::WPaintUnclipped) ) {
-                dst_ps = WinGetClipPS( dst_w->winId(), 0, PSF_PARENTCLIP );
-            } else {
-                dst_ps = WinGetPS( dst_w->winId() );
-            }
+	    dst_ps = ((QWidget*)dst)->getTargetPS();
 	    dst_tmp = TRUE;
 	}
Index: trunk/src/kernel/qpainter_pm.cpp
===================================================================
--- trunk/src/kernel/qpainter_pm.cpp	(revision 60)
+++ trunk/src/kernel/qpainter_pm.cpp	(revision 61)
@@ -42,5 +42,5 @@
 #include "qpixmapcache.h"
 #include "qptrlist.h"
-//@@TODO (dmik): later
+/// @todo (dmik) later
 //#include "qprinter.h"
 #include <stdlib.h>
@@ -53,24 +53,9 @@
 #include "qfontengine_p.h"
 
-//@@TODO (dmik): does OS/2 have this bug?
-///*
-//  Workaround for win32 bug. When GM_ADVANCED graphicsmode is used with a non identity
-//  matrix, subsequent calls to Ellipse, Chord and Pie will be inclusive. Also after
-//  graphics mode is reset to GM_COMPATIBLE. This causes ellipses to grow in size
-//  after a call to drawText when the painter is transformated.
-//
-//  To work around this we register if a non identity transform is set in
-//  QPainter::nativeXForm() and reduce the size by one if native xform has been used.
-//
-//  Testcase for confirmation is checked in in:
-//  //depot/manualtests/platformbugs/win32/ellipseafteradvgrmode.cpp
-//*/
-
 // QRgb has the same RGB format (0xaarrggbb) as OS/2 uses (ignoring the
 // highest alpha byte) so we just mask alpha to get the valid OS/2 color.
 #define COLOR_VALUE(c) ((flags & RGBColor) ? (c.rgb() & RGB_MASK) : c.pixel())
 
-//@@TODO (dmik): Innotek GCC 3.2.2 beta 4 CSD1 lacks this function in
-//  its version of the toolkit header. This should be fixed soon.
+// Innotek GCC lacks some API functions in its version of OS/2 Toolkit headers
 #if defined(Q_CC_GNU) && !defined(USE_OS2_TOOLKIT_HEADERS)
 extern "C" LONG  APIENTRY GpiQueryNearestPaletteIndex(HPAL hpal, ULONG color);
@@ -100,22 +85,4 @@
     rc &= GpiSetAttrs( hps, PRIM_LINE, LBB_BACK_MIX_MODE, 0, (PBUNDLE) &lb );
     return rc;
-}
-
-// helper function to select clip regions to the hps
-void qt_GpiSetClipRegion( HPS hps, HRGN hrgn, int devh, HRGN *hrgnOldRet )
-{
-    if ( hrgn ) {
-        // convert region y coordinates from Qt to GPI (see qregion_pm.cpp)
-        if ( devh ) {
-            POINTL ptl = { 0, devh };
-            GpiOffsetRegion( hps, hrgn, &ptl );
-        }
-    }
-    HRGN hrgnOld;
-    GpiSetClipRegion( hps, hrgn, &hrgnOld );
-    if ( hrgnOldRet )
-        *hrgnOldRet = hrgnOld;
-    else
-        GpiDestroyRegion( hps, hrgnOld );
 }
 
@@ -183,5 +150,4 @@
     }
     if ( bg_pixmap ) {
-//@@TODO (dmik): don't realize why the windows code doesn't do it...
         // normalize pixmap offsets according to x and y
         // to ensure that the offsets are always relative to
@@ -224,7 +190,4 @@
 {
     d = 0;
-//@@TODO (dmik): later
-//    hasUsedNativeXForm = FALSE;
-//    usingNativeXForm = FALSE;
     flags = IsStartingUp;
     pdev = 0;
@@ -240,10 +203,6 @@
     wm_stack = 0;
     hps = 0;
-//@@TODO (dmik): remove?
-//    hpen = 0;
-//    hbrush = 0;
-//    hfont = 0;
     holdpal = 0;
-    holdrgn = 0;
+    holdrgn = HRGN_ERROR;
     hbrushbm = 0;
     pixmapBrush = nocolBrush = FALSE;
@@ -407,5 +366,5 @@
     }
 
-    //@@TODO (dmik): possibly pixmapBrush is not needed, hbrushbm and
+    /// @todo (dmik) possibly pixmapBrush is not needed, hbrushbm and
     //  CustomPattern can substitute it.
     pixmapBrush = nocolBrush = FALSE;
@@ -521,8 +480,8 @@
     hps = 0;
     holdpal = 0;
-    holdrgn = 0;
+    holdrgn = HRGN_ERROR;
     devh = 0;
 
-    QRegion *pRepaintRgn = 0;
+    QRegion *repaintRgn = 0;
 
     if ( testf(ExtDev) ) {			// external device
@@ -574,18 +533,11 @@
         devh = wh;                              // for final y coord. flipping
         if ( !w->isDesktop() )
-            pRepaintRgn =                       // clip rgn passed from repaint()
+            repaintRgn =                        // clip rgn passed from repaint()
                 (QRegion *) WinQueryWindowULong( w->winId(), QWL_QTCLIPRGN );
 	if ( w->testWState(Qt::WState_InPaintEvent) ) {
 	    hps = w->hps;			// during paint event
 	} else {
-            if ( w->isDesktop() ) {
-                hps = WinGetScreenPS( HWND_DESKTOP );
-            } else {
-                if ( unclipped || w->testWFlags( WPaintUnclipped ) ) {
-                    hps = WinGetClipPS( w->winId(), 0, PSF_PARENTCLIP );
-                } else {
-                    hps = WinGetPS( w->winId() );
-                }
-            }
+            hps = w->getTargetPS ( unclipped ? QWidget::Unclipped :
+                                               QWidget::ClipAll ); 
 	    w->hps = hps;
 	}
@@ -608,5 +560,5 @@
 	    cpen.setColor( color1 );
 	}
-//@@TODO (dmik): later
+/// @todo (dmik) later
 //    } else if ( dt == QInternal::Printer ) {	// device is a printer
 //	if ( pdev->handle() )
@@ -634,5 +586,5 @@
 	cpen = QPen( copyFrom->foregroundColor() );
 	bg_col = copyFrom->backgroundColor();
-        pRepaintRgn =
+        repaintRgn =
             (QRegion *) WinQueryWindowULong( copyFrom->winId(), QWL_QTCLIPRGN );
     }
@@ -658,18 +610,22 @@
     setBrushOrigin( 0, 0 );
     if ( hps ) {
-        HRGN hrgn = 0;
-        if ( pRepaintRgn ) {
-            // make a shallow copy (for the case if the QWL_QTCLIPRGN pointer
-            // will become invalid -- it should not ever happen though)
-            repaintRgn = *pRepaintRgn;
-            QRegion rgn = repaintRgn;
-            // clip region in OS/2 cannot be used for anything else, make a deep copy
-            rgn.detach();
-            hrgn = rgn.handle();
-            // prevent QRegion's destructor from destroying the region handle
-            // (qt_GpiSetClipRegion does the job)
-            rgn.data->rgn = 0;
+        holdrgn = GpiQueryClipRegion( hps );
+        if ( repaintRgn ) {
+            // ensure that def_crgn is not null after assignment in any case
+            def_crgn = repaintRgn->isNull() ? QRegion( FALSE ) : *repaintRgn; 
         }
-        qt_GpiSetClipRegion( hps, hrgn, devh, &holdrgn );
+        // clip region in GPI cannot be used for anything else, so detach it
+        def_crgn.detach();
+        if ( holdrgn ) {
+            // intersect the original clip region and the region from repaint()
+            if ( def_crgn.isNull() )
+                def_crgn = QRegion( 0, 0, ww, wh );
+            GpiSetClipRegion( hps, 0, NULL ); // deselect holdrgn
+            HRGN hrgn = def_crgn.handle( devh );
+            GpiCombineRegion( hps, hrgn, hrgn, holdrgn, CRGN_AND );  
+        }
+        cur_crgn = def_crgn;
+        if ( !cur_crgn.isNull() )
+            GpiSetClipRegion( hps, cur_crgn.handle( devh ), NULL );
     } else {
         holdrgn = HRGN_ERROR;
@@ -695,14 +651,14 @@
         GpiSetPatternSet( hps, LCID_DEFAULT );
         GpiDeleteSetId( hps, LCID_QTPixmapBrush );
-    }
-//@@TODO (dmik): remove or set the LCID_DEFAULT font here?
-//    if ( hfont ) {
-//	SelectObject( hdc, stock_sysfont );
-//	hfont = 0;
-//    }
-    if ( holdrgn != HRGN_ERROR )
-        qt_GpiSetClipRegion( hps, holdrgn, 0, NULL );
-    if ( holdpal )
+        hbrushbm = 0;
+    }
+    if ( holdrgn != HRGN_ERROR ) {
+        GpiSetClipRegion( hps, holdrgn, NULL );
+        holdrgn = HRGN_ERROR;
+    }
+    if ( holdpal ) {
 	GpiSelectPalette( hps, holdpal );
+        holdpal = 0;
+    }
     if ( !pdev )
 	return FALSE;
@@ -719,4 +675,8 @@
     }
 
+    if ( !def_crgn.isNull() )
+        def_crgn = QRegion();
+    cur_crgn = def_crgn;
+    
     if ( pfont ) {
 	delete pfont;
@@ -741,6 +701,4 @@
 void QPainter::flush()
 {
-//@@TODO (dmik): need something here?
-//    GdiFlush();
 }
 
@@ -945,14 +903,17 @@
     }
 
-    HRGN hrgn = 0;
-    QRegion rgn;
+    // the current clip region is stored in cur_crgn, so deselect the handle
+    // to let us operate on it. Note that the assignment op below will destroy
+    // the handle if it is no more referred, so there is no need to do it
+    // explicitly.
+    GpiSetClipRegion( hps, 0, NULL );
 
     if ( enable ) {
-        if ( !repaintRgn.isNull() )
-            rgn = crgn.intersect( repaintRgn );
+        if ( !def_crgn.isNull() )
+            cur_crgn = crgn.intersect( def_crgn );
         else
-            rgn = crgn;
+            cur_crgn = crgn.isNull() ? QRegion( FALSE ) : crgn;
 #ifndef QT_NO_PRINTER
-//@@TODO (dmik): later
+/// @todo (dmik) later
 //	if ( pdev->devType() == QInternal::Printer ) {
 //	    double xscale = ((float)pdev->metric( QPaintDeviceMetrics::PdmPhysicalDpiX )) /
@@ -971,17 +932,12 @@
 #endif
     } else {
-        if ( !repaintRgn.isNull() )
-            rgn = repaintRgn;
-    }
-
-    if ( !rgn.isNull() ) {
-        // clip region in OS/2 cannot be used for anything else, make a deep copy
-        rgn.detach();
-        hrgn = rgn.handle();
-        // prevent QRegion's destructor from destroying the region handle
-        // (qt_GpiSetClipRegion does the job)
-        rgn.data->rgn = 0;
-    }
-    qt_GpiSetClipRegion( hps, hrgn, devh, NULL );
+        cur_crgn = def_crgn;
+    }
+
+    // clip region in GPI cannot be used for anything else, so detach it
+    cur_crgn.detach();
+    
+    if ( !cur_crgn.isNull() )
+        GpiSetClipRegion( hps, cur_crgn.handle( devh ), NULL );
 }
 
@@ -1315,7 +1271,4 @@
         qt_end_geom_line( hps, &gh );
     }
-//@@TODO (dmik): does OS/2 PM have the same bug?
-//    if ( (cpen.width() == 0) && (cpen.style() == SolidLine) )
-//	SetPixelV( hdc, x, y, COLOR_VALUE(cpen.color()) );
 }
 
@@ -1824,7 +1777,4 @@
 #endif // QT_NO_BEZIER
 
-//@@TODO (dmik): remove?
-//extern uint qt_bitblt_foreground;		// in qpaintdevice_pm.cpp
-
 void QPainter::drawPixmap( int x, int y, const QPixmap &pixmap,
 			   int sx, int sy, int sw, int sh )
@@ -1887,7 +1837,4 @@
 
     if ( txop <= TxTranslate ) {		// use optimized bitBlt
-//@@TODO (dmik): remove?
-//	if ( pixmap.depth() == 1 )
-//	    qt_bitblt_foreground = COLOR_VALUE(cpen.color());
 	bitBlt( pdev, x, y, &pixmap, sx, sy, sw, sh, (RasterOp)rop );
 	return;
@@ -2004,6 +1951,4 @@
     */
     QBitmap *mask = (QBitmap *)pixmap.mask();
-//@@TODO (dmik): is OS/2 buggy too?
-//#if 0 // Windows is too buggy, so we just use our own code (which is faster).
     if ( !testf(ExtDev) && txop <= TxTranslate && mask == 0 ) {
 	if ( txop == TxTranslate )
@@ -2012,5 +1957,4 @@
 	return;
     }
-//#endif
     if ( sw*sh < 8192 && sw*sh < 16*w*h ) {
 	int tw = sw, th = sh;
@@ -2032,5 +1976,4 @@
 }
 
-//@@TODO (dmik): need this at all?
 #if 0
 //
@@ -2157,14 +2100,5 @@
 	int ypos = y + si->y - ascent;
 
-//@@TODO (dmik): remove
-//#ifndef Q_OS_TEMP
-//	if ( rop != CopyROP ) {
-//	    // Doesn't work for non-TrueType fonts, but we dealt with those
-//	    // with the bitmap above.
-//	    BeginPath(hdc);
-//	}
-//#endif
-
-//@@TODO (dmik): do we really need this? we already have painter->handle()
+/// @todo (dmik) do we really need this? we already have painter->handle()
 //  inside QFontEngine::draw(), and the font should have been selected into
 //  hps by updateFont()
@@ -2179,21 +2113,6 @@
 
 	fe->draw( this, xpos, ypos, engine, si, textFlags );
-//@@TODO (dmik): need?
+/// @todo (dmik) need?
 //        fe->hps = oldPs;
-
-//@@TODO (dmik): remove
-//	if ( rop != CopyROP ) {
-//#ifndef Q_OS_TEMP
-//	    EndPath(hdc);
-//#endif
-//	    uint pix = COLOR_VALUE(cpen.data->color);
-//	    HBRUSH tbrush = CreateSolidBrush( pix );
-//	    SelectObject( hdc, tbrush );
-//#ifndef Q_OS_TEMP
-//	    FillPath(hdc);
-//#endif
-//	    SelectObject( hdc, hbrush );
-//	    DeleteObject( tbrush );
-//	}
     }
 }
@@ -2223,5 +2142,5 @@
     y += si->y;
 
-//@@TODO (dmik): do we really need this? we already have painter->handle()
+/// @todo (dmik) do we really need this? we already have painter->handle()
 //  inside QFontEngine::draw(), and the font should have been selected into
 //  hps by updateFont()
@@ -2231,5 +2150,5 @@
 
     fe->draw( this, x,  y, engine, si, textFlags );
-//@@TODO (dmik): need?
+/// @todo (dmik) need?
 //    fe->hps = oldPs;
 }
Index: trunk/src/kernel/qregion_pm.cpp
===================================================================
--- trunk/src/kernel/qregion_pm.cpp	(revision 60)
+++ trunk/src/kernel/qregion_pm.cpp	(revision 61)
@@ -43,10 +43,34 @@
 #include "qt_os2.h"
 
-// We always create a GPI resuorce for a region with top and bottom corner
-// points made negative and swapped. This gives us no-cost top to bottom
-// flipping but requires to call GpiOffsetRegion() to offset the region up by
-// the height of the presentation space viewport before it is actually used on
-// that presentation space (usually for clipping) and, on the contrary, offset
-// the region got from GPI down before it is stored in QRegion.
+//  To compensate the difference between Qt (where y axis goes downwards) and
+//  GPI (where y axis goes upwards) coordinate spaces when dealing with regions
+//  we use the following technique: when a GPI resource is allocated for a Qt
+//  region, we simply change the sign of all y coordinates to quickly flip it
+//  top to bottom in a manner that doesn't depend on the target device height.
+//  All we have to do to apply the created GPI region to a particular GPI device
+//  is to align its y axis to the top of the device (i.e. offset the region
+//  up by the height of the device), and unalign it afterwards to bring it back
+//  to the coordinate space of other device-independent (unaligned) regions.
+//  To optimize this, we remember (in data->hgt) the last height value used to
+//  align the region, and align it again only if the target device height
+//  changes. Zero height indicates a device-independent target (such as other
+//  unaligned Qt region).
+//
+//  The handle() function, used for external access to the region, takes an
+//  argument that must be always set to the height of the target device to
+//  guarantee the correct coordinate space alignment.
+
+#if defined(Q_CC_GNU) && !defined(USE_OS2_TOOLKIT_HEADERS)
+
+// Innotek GCC lacks some API functions in its version of OS/2 Toolkit headers
+
+extern "C" HRGN APIENTRY GpiCreateEllipticRegion( HPS hps,
+                                                  PRECTL prclRect );
+
+extern "C" HRGN APIENTRY GpiCreatePolygonRegion( HPS hps,
+                                                 ULONG ulCount,
+                                                 PPOLYGON paplgn,
+                                                 ULONG flOptions );
+#endif
 
 QRegion::QRegion()
@@ -55,4 +79,5 @@
     Q_CHECK_PTR( data );
     data->rgn = 0;
+    data->hgt = 0;
     data->is_null = TRUE;
 }
@@ -63,11 +88,22 @@
     Q_CHECK_PTR( data );
     data->rgn = 0;
+    data->hgt = 0;
     data->is_null = is_null;
 }
 
-QRegion::QRegion( const QRect &r, RegionType t )
+QRegion::QRegion( HRGN hrgn, int target_height )
 {
     data = new QRegionData;
     Q_CHECK_PTR( data );
+    data->rgn = hrgn;
+    data->hgt = target_height;
+    data->is_null = FALSE;
+}
+
+QRegion::QRegion( const QRect &r, RegionType t )
+{
+    data = new QRegionData;
+    Q_CHECK_PTR( data );
+    data->hgt = 0;
     data->is_null = FALSE;
     if ( r.isEmpty() ) {
@@ -79,8 +115,19 @@
             data->rgn = GpiCreateRegion( hps, 1, &rcl );
 	} else if ( t == Ellipse ) {		// elliptic region
-//@@TODO (dmik): create elliptic regions using GpiCreateEllipticRegion() later.
-//  now simply create it as rectangular.
-            RECTL rcl = { r.left(), -(r.bottom()+1), r.right()+1, -r.top() };
-            data->rgn = GpiCreateRegion( hps, 1, &rcl );
+            // if the width or height of the ellipse is odd, GPI always
+            // converts it to a nearest even value, which is obviously stupid
+            // (see also QPainter::drawArcInternal()). So, we don't use
+            // GpiCreateEllipticRegion(), but create an array of points to
+            // call GpiCreatePolygonRegion() instead.
+            QPointArray a;
+            a.makeArc( r.x(), r.y(), r.width(), r.height(), 0, 360 * 16 );
+            for ( uint i = 0; i < a.size(); ++ i )
+                a[i].ry() = -(a[i].y() + 1);
+            // GpiCreatePolygonRegion() is bogus and always starts a poligon from
+            // the current position. Make the last point the current one and reduce
+            // the number of points by one.
+            GpiMove( hps, (PPOINTL) &a[ a.size() - 1 ] );
+            POLYGON poly = { a.size() - 1, (PPOINTL) a.data() };
+            data->rgn = GpiCreatePolygonRegion( hps, 1, &poly, POLYGON_ALTERNATE );
 	}
     }
@@ -91,4 +138,5 @@
     data = new QRegionData;
     Q_CHECK_PTR( data );
+    data->hgt = 0;
     data->is_null = FALSE;
     QRect r = a.boundingRect();
@@ -96,8 +144,18 @@
 	data->rgn = 0;
     } else {
-//@@TODO (dmik): create poligonal regions using GpiCreatePolygonRegion() later.
-//  now simply create as bounding rectangle.
-        RECTL rcl = { r.left(), -(r.bottom()+1), r.right()+1, -r.top() };
-        data->rgn = GpiCreateRegion( qt_display_ps(), 1, &rcl );
+        HPS hps = qt_display_ps();
+        POINTL *pts = new POINTL[ a.size() ]; 
+        for ( uint i = 0; i < a.size(); ++ i ) {
+            pts[i].x = a[i].x();
+            pts[i].y = - (a[i].y() + 1);
+        }
+        // GpiCreatePolygonRegion() is bogus and always starts a poligon from
+        // the current position. Make the last point the current one and reduce
+        // the number of points by one.
+        GpiMove( hps, &pts[ a.size() - 1 ] );
+        POLYGON poly = { a.size() - 1, pts };
+        ULONG opts = winding ? POLYGON_WINDING : POLYGON_ALTERNATE;
+        data->rgn = GpiCreatePolygonRegion( hps, 1, &poly, opts );
+        delete[] pts;
     }
 }
@@ -192,4 +250,5 @@
     data = new QRegionData;
     Q_CHECK_PTR( data );
+    data->hgt = 0;
     data->is_null = FALSE;
     if ( bm.isNull() )
@@ -225,8 +284,10 @@
 {
     QRegion r ( data->is_null );
+    r.data->hgt = 0;
     if ( !data->is_null && data->rgn ) {
         HPS hps = qt_display_ps();
         r.data->rgn = GpiCreateRegion( hps, 0, NULL );
         GpiCombineRegion( hps, r.data->rgn, data->rgn, NULL, CRGN_COPY );
+        r.data->hgt = data->hgt;
     }
     return r;
@@ -252,5 +313,5 @@
     LONG rc = PRGN_OUTSIDE;
     if ( data->rgn ) {
-        POINTL ptl = { p.x(), -(p.y()+1) };
+        POINTL ptl = { p.x(), data->hgt - (p.y() + 1) };
         rc = GpiPtInRegion( qt_display_ps(), data->rgn, &ptl );
     }
@@ -262,5 +323,6 @@
     LONG rc = PRGN_OUTSIDE;
     if ( data->rgn ) {
-        RECTL rcl = { r.left(), -(r.bottom()+1), r.right()+1, -r.top() };
+        RECTL rcl = { r.left(), data->hgt - (r.bottom() + 1),
+                      r.right() + 1, data->hgt - r.top() };
         rc = GpiRectInRegion( qt_display_ps(), data->rgn, &rcl );
     }
@@ -318,10 +380,20 @@
     HPS hps = qt_display_ps();
     result.data->rgn = GpiCreateRegion( hps, 0, NULL );
-    if ( data->rgn && r.data->rgn )
-	GpiCombineRegion( hps, result.data->rgn, data->rgn, r.data->rgn, both );
-    else if ( data->rgn && left != CRGN_NOP )
-	GpiCombineRegion( hps, result.data->rgn, data->rgn, NULL, left );
-    else if ( r.data->rgn && right != CRGN_NOP )
-	GpiCombineRegion( hps, result.data->rgn, r.data->rgn, NULL, right );
+    LONG rc = RGN_NULL; 
+    if ( data->rgn && r.data->rgn ) {
+        updateHandle( r.data->hgt ); // bring to the same coordinate space
+	rc = GpiCombineRegion( hps, result.data->rgn, data->rgn, r.data->rgn, both );
+        result.data->hgt = r.data->hgt;
+    } else if ( data->rgn && left != CRGN_NOP ) {
+	rc = GpiCombineRegion( hps, result.data->rgn, data->rgn, 0, left );
+        result.data->hgt = data->hgt;
+    } else if ( r.data->rgn && right != CRGN_NOP ) {
+	rc = GpiCombineRegion( hps, result.data->rgn, r.data->rgn, 0, right );
+        result.data->hgt = r.data->hgt;
+    }
+    if ( rc == RGN_NULL || rc == RGN_ERROR ) {
+        GpiDestroyRegion( hps, result.data->rgn );
+        result.data->rgn = result.data->hgt = 0;
+    }
     return result;
 }
@@ -354,8 +426,9 @@
     if ( data->rgn )
         rc = GpiQueryRegionBox( qt_display_ps(), data->rgn, &rcl );
-    if ( rc == RGN_NULL )
+    if ( rc == RGN_NULL || rc == RGN_ERROR )
 	return QRect(0,0,0,0);
     else
-        return QRect(rcl.xLeft, -rcl.yTop, rcl.xRight-rcl.xLeft, rcl.yTop-rcl.yBottom );
+        return QRect( rcl.xLeft, data->hgt - rcl.yTop,
+                      rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom );
 }
 
@@ -382,5 +455,6 @@
     PRECTL r = rcls;
     for ( int i=0; i<(int)a.size(); i++ ) {
-        a[i].setRect( r->xLeft, -r->yTop, r->xRight-r->xLeft, r->yTop-r->yBottom );
+        a[i].setRect( r->xLeft, data->hgt - r->yTop,
+                      r->xRight - r->xLeft, r->yTop - r->yBottom );
 	r++;
     }
@@ -407,12 +481,28 @@
     if ( (is_empty ^ r_is_empty ) )             // one is empty, not both
 	return FALSE;
-    return is_empty ?
-	TRUE :					// both empty
-        GpiEqualRegion( qt_display_ps(), data->rgn, r.data->rgn ) == EQRGN_EQUAL;
-}
-
-void QRegion::update() const
-{
-    // lazy initialization. this method should be called only from handle()
-    data->rgn = GpiCreateRegion( qt_display_ps(), 0, NULL );
-}
+    if ( is_empty )				// both empty
+        return TRUE;
+    updateHandle( r.data->hgt ); // bring to the same coordinate space
+    return
+	GpiEqualRegion( qt_display_ps(), data->rgn, r.data->rgn ) == EQRGN_EQUAL;
+}
+
+/*!
+ *  \internal
+ *  Updates the region handle so that it is suitable for selection to
+ *  a device with the given \a height.
+ */
+void QRegion::updateHandle( int target_height ) const
+{
+    QRegion *that = const_cast< QRegion *>( this ); // we're const here
+    if ( !data->rgn ) {
+        // a handle of a null region is requested, allocate an empty region
+        that->data->rgn = GpiCreateRegion( qt_display_ps(), 0, NULL );
+        that->data->hgt = target_height;
+    } else if ( data->hgt != target_height ) {
+        // align region y axis to the top of the device
+        POINTL ptl = { 0, target_height - data->hgt };
+        GpiOffsetRegion( qt_display_ps(), data->rgn, &ptl );
+        that->data->hgt = target_height;
+    }
+}
Index: trunk/src/kernel/qwidget_pm.cpp
===================================================================
--- trunk/src/kernel/qwidget_pm.cpp	(revision 60)
+++ trunk/src/kernel/qwidget_pm.cpp	(revision 61)
@@ -973,8 +973,9 @@
         WinValidateRect( winId(), &rcl, FALSE );
 
-	QRegion *pcrgn = 0;
+        Q_ASSERT( !WinQueryWindowULong( winId(), QWL_QTCLIPRGN ) );
+        QRegion reg;
         if ( r != rect() ) {
-            pcrgn = new QRegion( r );
-            WinSetWindowULong( winId(), QWL_QTCLIPRGN, (ULONG) pcrgn );
+            reg = QRegion( r );
+            WinSetWindowULong( winId(), QWL_QTCLIPRGN, (ULONG) &reg );
         }
 
@@ -984,8 +985,5 @@
 	QApplication::sendEvent( this, &e );
 
-        if ( pcrgn ) {
-            WinSetWindowULong( winId(), QWL_QTCLIPRGN, 0 );
-            delete pcrgn;
-        }
+        WinSetWindowULong( winId(), QWL_QTCLIPRGN, 0 );
     }
 }
@@ -1000,13 +998,8 @@
 #endif
         // convert region y coordinates from Qt to GPI (see qregion_pm.cpp)
-        POINTL ptl = { 0, height() };
-        GpiOffsetRegion( qt_display_ps(), reg.handle(), &ptl );
-        WinValidateRegion( winId(), reg.handle(), FALSE );
-        // convert region y coordinates back from GPI to Qt
-        ptl.y = -ptl.y;
-        GpiOffsetRegion( qt_display_ps(), reg.handle(), &ptl );
-
-	QRegion *pcrgn = new QRegion( reg );
-        WinSetWindowULong( winId(), QWL_QTCLIPRGN, (ULONG) pcrgn );
+        WinValidateRegion( winId(), reg.handle( height() ), FALSE );
+
+        Q_ASSERT( !WinQueryWindowULong( winId(), QWL_QTCLIPRGN ) );
+        WinSetWindowULong( winId(), QWL_QTCLIPRGN, (ULONG) &reg );
 
 	QPaintEvent e( reg, erase );
@@ -1016,5 +1009,4 @@
 
         WinSetWindowULong( winId(), QWL_QTCLIPRGN, 0 );
-        delete pcrgn;
     }
 }
@@ -1413,5 +1405,5 @@
     } else if ( !hps ) {
 	tmphps = TRUE;
-	lhps = WinGetPS( winId() );
+	lhps = getTargetPS();
     } else {
 	tmphps = FALSE;
@@ -1428,8 +1420,6 @@
     );
 
-    if ( tmphps ) {
+    if ( tmphps )
 	WinReleasePS( lhps );
-	hps = 0;
-    }
 }
 
@@ -1450,13 +1440,9 @@
     } else if ( !hps ) {
 	tmphps = TRUE;
-	lhps = WinGetPS( winId() );
+	lhps = getTargetPS();
     } else {
 	tmphps = FALSE;
 	lhps = hps;
     }
-
-    // convert region y coordinates from Qt to GPI (see qregion_pm.cpp)
-    POINTL ptl = { 0, height() };
-    GpiOffsetRegion( lhps, rgn.handle(), &ptl );
 
     HRGN oldRegion = GpiQueryClipRegion( lhps );
@@ -1465,7 +1451,8 @@
         GpiSetClipRegion( lhps, 0, NULL );
         newRegion = GpiCreateRegion( lhps, 0, NULL );
-        GpiCombineRegion( lhps, newRegion, oldRegion, rgn.handle(), CRGN_AND );
+        GpiCombineRegion( lhps, newRegion, oldRegion, rgn.handle( height() ),
+                          CRGN_AND );
     } else {
-	newRegion = rgn.handle();
+	newRegion = rgn.handle( height() );
     }
     GpiSetClipRegion( lhps, newRegion, &oldRegion );
@@ -1482,14 +1469,8 @@
     GpiSetClipRegion( lhps, oldRegion, NULL );
 
-    // convert region y coordinates back from GPI to Qt
-    ptl.y = -ptl.y;
-    GpiOffsetRegion( lhps, rgn.handle(), &ptl );
-
     if ( oldRegion )
 	GpiDestroyRegion( lhps, newRegion );
-    if ( tmphps ) {
+    if ( tmphps )
 	WinReleasePS( lhps );
-	hps = 0;
-    }
 }
 
@@ -1882,2 +1863,28 @@
 }
 
+/*!
+ *  \internal
+ *
+ *  Obtains a presentaiton space to draw on this widget, set up according
+ *  to widget flags. If \a m != Unclipped and WPaintUnclipped flag is not
+ *  set, a clip region is set on the returned PS according to \a m.
+ *
+ *  The returned handle must be freed using WinReleasePS() after usage.
+ */
+HPS QWidget::getTargetPS( ClipMode m /* = ClipAll */ )
+{
+    HPS widgetPS = 0;
+    
+    if ( isDesktop() ) {
+        widgetPS = WinGetScreenPS( HWND_DESKTOP );
+    } else {
+        if ( m == Unclipped || testWFlags( WPaintUnclipped ) ) {
+            widgetPS = WinGetClipPS( winId(), 0, PSF_PARENTCLIP );
+        } else {
+            widgetPS = WinGetPS( winId() );
+        }
+    }
+
+    return widgetPS;
+}
+
