]> git.saurik.com Git - wxWidgets.git/blobdiff - src/os2/dc.cpp
Add wxGrid::RefreshAttr() method to force attribute refresh.
[wxWidgets.git] / src / os2 / dc.cpp
index 883aa74a06c3e235b654f25fccc660e2f04f49ad..228e231c5f0068a3ab8705383288e05cc8858fe6 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        dc.cpp
+// Name:        src/os2/dc.cpp
 // Purpose:     wxDC class
 // Author:      David Webster
 // Modified by:
     #include "wx/log.h"
     #include "wx/icon.h"
     #include "wx/msgdlg.h"
+    #include "wx/dcprint.h"
+    #include "wx/statusbr.h"
+    #include "wx/module.h"
 #endif
 
-#include "wx/dcprint.h"
-
 #include <string.h>
-#include <math.h>
 
+#include "wx/os2/dc.h"
+#include "wx/os2/dcclient.h"
 #include "wx/os2/private.h"
 
-    IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
+IMPLEMENT_ABSTRACT_CLASS(wxPMDCImpl, wxDCImpl)
 
 //
-// wxWindows uses the Microsoft convention that the origin is the UPPER left.
+// wxWidgets uses the Microsoft convention that the origin is the UPPER left.
 // Native OS/2 however in the GPI and PM define the origin as the LOWER left.
-// In order to map OS/2 GPI/PM y coordinates to wxWindows coordinates we must
+// In order to map OS/2 GPI/PM y coordinates to wxWidgets coordinates we must
 // perform the following transformation:
 //
 // Parent object height:     POBJHEIGHT
 // Desried origin:           WXORIGINY
 // Object to place's height: OBJHEIGHT
 //
-// To get the OS2 position from the wxWindows one:
+// To get the OS2 position from the wxWidgets one:
 //
 // OS2Y = POBJHEIGHT - (WXORIGINY + OBJHEIGHT)
 //
 // For OS/2 wxDC's we will always determine m_vRclPaint as the size of the
 // OS/2 Presentation Space associated with the device context.  y is the
-// desired application's y coordinate of the origin in wxWindows space.
+// desired application's y coordinate of the origin in wxWidgets space.
 // objy is the height of the object we are going to draw.
 //
 #define OS2Y(y, objy) ((m_vRclPaint.yTop - m_vRclPaint.yBottom) - (y + objy))
@@ -64,11 +66,6 @@ static const int VIEWPORT_EXTENT = 1000;
 static const int MM_POINTS = 9;
 static const int MM_METRIC = 10;
 
-// usually this is defined in math.h
-#ifndef M_PI
-    static const double M_PI = 3.14159265358979323846;
-#endif // M_PI
-
 // ---------------------------------------------------------------------------
 // private functions
 // ---------------------------------------------------------------------------
@@ -149,29 +146,204 @@ int SetBkMode(
 // implementation
 // ===========================================================================
 
+#if wxUSE_DC_CACHEING
+
+/*
+ * This implementation is a bit ugly and uses the old-fashioned wxList class, so I will
+ * improve it in due course, either using arrays, or simply storing pointers to one
+ * entry for the bitmap, and two for the DCs. -- JACS
+ */
+
 // ---------------------------------------------------------------------------
-// wxDC
+// wxDCCacheEntry
 // ---------------------------------------------------------------------------
 
-wxDC::wxDC(void)
+wxList wxPMDCImpl::m_svBitmapCache;
+wxList wxPMDCImpl::m_svDCCache;
+
+wxDCCacheEntry::wxDCCacheEntry(
+  WXHBITMAP                         hBitmap
+, int                               nWidth
+, int                               nHeight
+, int                               nDepth
+)
 {
-    m_pCanvas      = NULL;
+    m_hBitmap = hBitmap;
+    m_hPS     = NULLHANDLE;
+    m_nWidth  = nWidth;
+    m_nHeight = nHeight;
+    m_nDepth  = nDepth;
+} // end of wxDCCacheEntry::wxDCCacheEntry
 
-    m_hOldBitmap   = 0;
-    m_hOldPen      = 0;
-    m_hOldBrush    = 0;
-    m_hOldFont     = 0;
-    m_hOldPalette  = 0;
+wxDCCacheEntry::wxDCCacheEntry(
+  HPS                               hPS
+, int                               nDepth
+)
+{
+    m_hBitmap = NULLHANDLE;
+    m_hPS     = hPS;
+    m_nWidth  = 0;
+    m_nHeight = 0;
+    m_nDepth  = nDepth;
+} // end of wxDCCacheEntry::wxDCCacheEntry
 
-    m_bOwnsDC      = FALSE;
-    m_hDC          = 0;
-    m_hOldPS       = NULL;
-    m_hPS          = NULL;
-    m_bIsPaintTime = FALSE; // True at Paint Time
-    m_brush.GetColour().Set("WHITE");
-} // end of wxDC::wxDC
+wxDCCacheEntry::~wxDCCacheEntry()
+{
+    if (m_hBitmap)
+        ::GpiDeleteBitmap(m_hBitmap);
+    if (m_hPS)
+        ::GpiDestroyPS(m_hPS);
+} // end of wxDCCacheEntry::~wxDCCacheEntry
 
-wxDC::~wxDC(void)
+wxDCCacheEntry* wxPMDCImpl::FindBitmapInCache(
+  HPS                               hPS
+, int                               nWidth
+, int                               nHeight
+)
+{
+    int                             nDepth = 24; // we'll fix this later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL);
+    wxNode*                         pNode = m_svBitmapCache.First();
+    BITMAPINFOHEADER2               vBmpHdr;
+
+    while(pNode)
+    {
+        wxDCCacheEntry*             pEntry = (wxDCCacheEntry*)pNode->Data();
+
+        if (pEntry->m_nDepth == nDepth)
+        {
+            memset(&vBmpHdr, 0, sizeof(BITMAPINFOHEADER2));
+
+            if (pEntry->m_nWidth < nWidth || pEntry->m_nHeight < nHeight)
+            {
+                ::GpiDeleteBitmap((HBITMAP)pEntry->m_hBitmap);
+                vBmpHdr.cbFix     = sizeof(BITMAPINFOHEADER2);
+                vBmpHdr.cx        = nWidth;
+                vBmpHdr.cy        = nHeight;
+                vBmpHdr.cPlanes   = 1;
+                vBmpHdr.cBitCount = (USHORT)nDepth;
+
+                pEntry->m_hBitmap = (WXHBITMAP) ::GpiCreateBitmap( hPS
+                                                                  ,&vBmpHdr
+                                                                  ,0L, NULL, NULL
+                                                                 );
+                if (!pEntry->m_hBitmap)
+                {
+                    wxLogLastError(wxT("CreateCompatibleBitmap"));
+                }
+                pEntry->m_nWidth  = nWidth;
+                pEntry->m_nHeight = nHeight;
+                return pEntry;
+            }
+            return pEntry;
+        }
+        pNode = pNode->Next();
+    }
+    memset(&vBmpHdr, 0, sizeof(BITMAPINFOHEADER2));
+    vBmpHdr.cbFix     = sizeof(BITMAPINFOHEADER2);
+    vBmpHdr.cx        = nWidth;
+    vBmpHdr.cy        = nHeight;
+    vBmpHdr.cPlanes   = 1;
+    vBmpHdr.cBitCount = (USHORT)nDepth;
+
+    WXHBITMAP                       hBitmap = (WXHBITMAP) ::GpiCreateBitmap( hPS
+                                                                            ,&vBmpHdr
+                                                                            ,0L, NULL, NULL
+                                                                           );
+    if (!hBitmap)
+    {
+        wxLogLastError(wxT("CreateCompatibleBitmap"));
+    }
+    wxDCCacheEntry*                 pEntry = new wxDCCacheEntry( hBitmap
+                                                                ,nWidth
+                                                                ,nHeight
+                                                                ,nDepth
+                                                               );
+    AddToBitmapCache(pEntry);
+    return pEntry;
+} // end of FindBitmapInCache
+
+wxDCCacheEntry* wxPMDCImpl::FindDCInCache(
+  wxDCCacheEntry*                   pNotThis
+, HPS                               hPS
+)
+{
+    int                             nDepth = 24; // we'll fix this up later ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL);
+    wxNode*                         pNode = m_svDCCache.First();
+
+    while(pNode)
+    {
+        wxDCCacheEntry*             pEntry = (wxDCCacheEntry*)pNode->Data();
+
+        //
+        // Don't return the same one as we already have
+        //
+        if (!pNotThis || (pNotThis != pEntry))
+        {
+            if (pEntry->m_nDepth == nDepth)
+            {
+                return pEntry;
+            }
+        }
+        pNode = pNode->Next();
+    }
+    wxDCCacheEntry*                 pEntry = new wxDCCacheEntry( hPS
+                                                                ,nDepth
+                                                               );
+    AddToDCCache(pEntry);
+    return pEntry;
+} // end of wxPMDCImpl::FindDCInCache
+
+void wxPMDCImpl::AddToBitmapCache(
+  wxDCCacheEntry*                   pEntry
+)
+{
+    m_svBitmapCache.Append(pEntry);
+} // end of wxPMDCImpl::AddToBitmapCache
+
+void wxPMDCImpl::AddToDCCache(
+  wxDCCacheEntry*                   pEntry
+)
+{
+    m_svDCCache.Append(pEntry);
+} // end of wxPMDCImpl::AddToDCCache
+
+void wxPMDCImpl::ClearCache()
+{
+    m_svBitmapCache.DeleteContents(true);
+    m_svBitmapCache.Clear();
+    m_svBitmapCache.DeleteContents(false);
+    m_svDCCache.DeleteContents(true);
+    m_svDCCache.Clear();
+    m_svDCCache.DeleteContents(false);
+} // end of wxPMDCImpl::ClearCache
+
+// Clean up cache at app exit
+class wxDCModule : public wxModule
+{
+public:
+    virtual bool OnInit() { return true; }
+    virtual void OnExit() { wxPMDCImpl::ClearCache(); }
+
+private:
+    DECLARE_DYNAMIC_CLASS(wxDCModule)
+}; // end of CLASS wxDCModule
+
+IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
+
+#endif // ndef for wxUSE_DC_CACHEING
+
+// ---------------------------------------------------------------------------
+// wxDC
+// ---------------------------------------------------------------------------
+
+wxPMDCImpl::wxPMDCImpl( wxDC *owner, WXHDC hDC ) :
+    wxDCImpl( owner )
+{
+    Init();
+    m_hDC          = hDC;
+} // end of wxPMDCImpl::wxPMDCImpl
+
+wxPMDCImpl::~wxPMDCImpl(void)
 {
     if ( m_hDC != 0 )
     {
@@ -200,12 +372,12 @@ wxDC::~wxDC(void)
             }
         }
     }
-} // end of wxDC::~wxDC
+} // end of wxPMDCImpl::~wxDC
 
 // This will select current objects out of the DC,
 // which is what you have to do before deleting the
 // DC.
-void wxDC::SelectOldObjects(
+void wxPMDCImpl::SelectOldObjects(
   WXHDC                             hPS
 )
 {
@@ -235,7 +407,7 @@ void wxDC::SelectOldObjects(
     m_font            = wxNullFont;
     m_backgroundBrush = wxNullBrush;
     m_vSelectedBitmap = wxNullBitmap;
-} // end of wxDC::SelectOldObjects
+} // end of wxPMDCImpl::SelectOldObjects
 
 // ---------------------------------------------------------------------------
 // clipping
@@ -253,7 +425,7 @@ void wxDC::SelectOldObjects(
     m_clipY2 = (wxCoord) YDEV2LOG(rect.yBottom); \
 }
 
-void wxDC::DoSetClippingRegion(
+void wxPMDCImpl::DoSetClippingRegion(
   wxCoord                           vX
 , wxCoord                           vY
 , wxCoord                           vWidth
@@ -263,31 +435,31 @@ void wxDC::DoSetClippingRegion(
     RECTL                           vRect;
 
     vY = OS2Y(vY,vHeight);
-    m_clipping    = TRUE;
+    m_clipping    = true;
     vRect.xLeft   = vX;
     vRect.yTop    = vY + vHeight;
     vRect.xRight  = vX + vWidth;
     vRect.yBottom = vY;
     ::GpiIntersectClipRectangle(m_hPS, &vRect);
     DO_SET_CLIPPING_BOX()
-} // end of wxDC::DoSetClippingRegion
+} // end of wxPMDCImpl::DoSetClippingRegion
 
-void wxDC::DoSetClippingRegionAsRegion(
+void wxPMDCImpl::DoSetDeviceClippingRegion(
   const wxRegion&                   rRegion
 )
 {
      wxCHECK_RET(rRegion.GetHRGN(), wxT("invalid clipping region"));
      HRGN                           hRgnOld;
 
-     m_clipping = TRUE;
+     m_clipping = true;
      ::GpiSetClipRegion( m_hPS
                         ,(HRGN)rRegion.GetHRGN()
                         ,&hRgnOld
                        );
     DO_SET_CLIPPING_BOX()
-} // end of wxDC::DoSetClippingRegionAsRegion
+} // end of wxPMDCImpl::DoSetDeviceClippingRegion
 
-void wxDC::DestroyClippingRegion(void)
+void wxPMDCImpl::DestroyClippingRegion(void)
 {
     if (m_clipping && m_hPS)
     {
@@ -307,61 +479,75 @@ void wxDC::DestroyClippingRegion(void)
 
          ::GpiSetClipRegion(m_hPS, hRgn, &hRgnOld);
      }
-      m_clipping = FALSE;
-} // end of wxDC::DestroyClippingRegion
+    ResetClipping();
+} // end of wxPMDCImpl::DestroyClippingRegion
 
 // ---------------------------------------------------------------------------
 // query capabilities
 // ---------------------------------------------------------------------------
 
-bool wxDC::CanDrawBitmap() const
+bool wxPMDCImpl::CanDrawBitmap() const
 {
-    return TRUE;
+    return true;
 }
 
-bool wxDC::CanGetTextExtent() const
+bool wxPMDCImpl::CanGetTextExtent() const
 {
     LONG                            lTechnology = 0L;
 
     ::DevQueryCaps(GetHDC(), CAPS_TECHNOLOGY, 1L, &lTechnology);
     return (lTechnology == CAPS_TECH_RASTER_DISPLAY) || (lTechnology == CAPS_TECH_RASTER_PRINTER);
-} // end of wxDC::CanGetTextExtent
+} // end of wxPMDCImpl::CanGetTextExtent
 
-int wxDC::GetDepth() const
+int wxPMDCImpl::GetDepth() const
 {
-    LONG                            lArray[CAPS_COLOR_BITCOUNT];
-    int                             nBitsPerPixel;
+    LONG                            lCapsColorBitcount;
+    int                             nBitsPerPixel = 0;
 
     if(::DevQueryCaps( GetHDC()
-                      ,CAPS_FAMILY
                       ,CAPS_COLOR_BITCOUNT
-                      ,lArray
+                      ,1L
+                      ,&lCapsColorBitcount
                      ))
     {
-        nBitsPerPixel = (int)lArray[CAPS_COLOR_BITCOUNT];
+        nBitsPerPixel = (int)lCapsColorBitcount;
     }
     return nBitsPerPixel;
-} // end of wxDC::GetDepth
+} // end of wxPMDCImpl::GetDepth
 
 // ---------------------------------------------------------------------------
 // drawing
 // ---------------------------------------------------------------------------
 
-void wxDC::Clear()
+void wxPMDCImpl::Clear()
 {
+    //
+    // If this is a canvas DC then just fill with the background color
+    // Otherwise purge the whole thing
+    //
+    if (m_pCanvas)
+    {
+        RECTL                       vRect;
+
+        ::GpiQueryClipBox(m_hPS, &vRect);
+        ::WinFillRect(m_hPS, &vRect, ::GpiQueryBackColor(m_hPS));
+    }
+    else
     ::GpiErase(m_hPS);
-} // end of wxDC::Clear
+} // end of wxPMDCImpl::Clear
 
-void wxDC::DoFloodFill(
+bool wxPMDCImpl::DoFloodFill(
   wxCoord                           vX
 , wxCoord                           vY
 , const wxColour&                   rCol
-, int                               nStyle
+, wxFloodFillStyle                  nStyle
 )
 {
     POINTL                          vPtlPos;
     LONG                            lColor;
     LONG                            lOptions;
+    LONG                            lHits;
+    bool                            bSuccess = false;
 
     vPtlPos.x = vX;             // Loads x-coordinate
     vPtlPos.y = OS2Y(vY,0);     // Loads y-coordinate
@@ -371,10 +557,13 @@ void wxDC::DoFloodFill(
     if(wxFLOOD_SURFACE == nStyle)
         lOptions = FF_SURFACE;
 
-    ::GpiFloodFill(m_hPS, lOptions, lColor);
-} // end of wxDC::DoFloodFill
+    if ((lHits = ::GpiFloodFill(m_hPS, lOptions, lColor)) != GPI_ERROR)
+        bSuccess = true;
+
+    return bSuccess;
+} // end of wxPMDCImpl::DoFloodFill
 
-bool wxDC::DoGetPixel(
+bool wxPMDCImpl::DoGetPixel(
   wxCoord                           vX
 , wxCoord                           vY
 , wxColour*                         pCol
@@ -385,17 +574,7 @@ bool wxDC::DoGetPixel(
 
     vPoint.x = vX;
     vPoint.y = OS2Y(vY,0);
-    lColor = ::GpiSetPel(m_hPS, &vPoint);
-
-    //
-    // Get the color of the pen
-    //
-    LONG                            lPencolor = 0x00ffffff;
-
-    if (m_pen.Ok())
-    {
-        lPencolor = m_pen.GetColour().GetPixel();
-    }
+    lColor = ::GpiQueryPel(m_hPS, &vPoint);
 
     //
     // return the color of the pixel
@@ -405,10 +584,10 @@ bool wxDC::DoGetPixel(
                   ,GetGValue(lColor)
                   ,GetBValue(lColor)
                  );
-    return(lColor == lPencolor);
-} // end of wxDC::DoGetPixel
+    return true;
+} // end of wxPMDCImpl::DoGetPixel
 
-void wxDC::DoCrossHair(
+void wxPMDCImpl::DoCrossHair(
   wxCoord                           vX
 , wxCoord                           vY
 )
@@ -440,9 +619,9 @@ void wxDC::DoCrossHair(
     ::GpiLine(m_hPS, &vPoint[3]);
     CalcBoundingBox(vX1, vY1);
     CalcBoundingBox(vX2, vY2);
-} // end of wxDC::DoCrossHair
+} // end of wxPMDCImpl::DoCrossHair
 
-void wxDC::DoDrawLine(
+void wxPMDCImpl::DoDrawLine(
   wxCoord                           vX1
 , wxCoord                           vY1
 , wxCoord                           vX2
@@ -450,19 +629,43 @@ void wxDC::DoDrawLine(
 )
 {
     POINTL                          vPoint[2];
+    COLORREF                        vColor = 0x00ffffff;
 
-    vY1 = OS2Y(vY1,0);
-    vY2 = OS2Y(vY2,0);
-
+    //
+    // Might be a memory DC with no Paint rect.
+    //
+    if (!(m_vRclPaint.yTop == 0 &&
+          m_vRclPaint.yBottom == 0 &&
+          m_vRclPaint.xRight == 0 &&
+          m_vRclPaint.xLeft == 0))
+    {
+        vY1 = OS2Y(vY1,0);
+        vY2 = OS2Y(vY2,0);
+    }
+    else
+    {
+        if (m_vSelectedBitmap.Ok())
+        {
+            m_vRclPaint.yTop = m_vSelectedBitmap.GetHeight();
+            m_vRclPaint.xRight = m_vSelectedBitmap.GetWidth();
+            vY1 = OS2Y(vY1,0);
+            vY2 = OS2Y(vY2,0);
+        }
+    }
     vPoint[0].x = vX1;
     vPoint[0].y = vY1;
     vPoint[1].x = vX2;
     vPoint[1].y = vY2;
+    if (m_pen.Ok())
+    {
+        vColor = m_pen.GetColour().GetPixel();
+    }
+    ::GpiSetColor(m_hPS, vColor);
     ::GpiMove(m_hPS, &vPoint[0]);
     ::GpiLine(m_hPS, &vPoint[1]);
     CalcBoundingBox(vX1, vY1);
     CalcBoundingBox(vX2, vY2);
-} // end of wxDC::DoDrawLine
+} // end of wxPMDCImpl::DoDrawLine
 
 //////////////////////////////////////////////////////////////////////////////
 // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1)
@@ -470,7 +673,7 @@ void wxDC::DoDrawLine(
 // current brush for filling the shape. The arc is drawn in an anticlockwise
 // direction from the start point to the end point.
 //////////////////////////////////////////////////////////////////////////////
-void wxDC::DoDrawArc(
+void wxPMDCImpl::DoDrawArc(
   wxCoord                           vX1
 , wxCoord                           vY1
 , wxCoord                           vX2
@@ -481,8 +684,6 @@ void wxDC::DoDrawArc(
 {
      POINTL                         vPtlPos;
      POINTL                         vPtlArc[2]; // Structure for current position
-     int                            nDx;
-     int                            nDy;
      double                         dRadius;
      double                         dAngl1;
      double                         dAngl2;
@@ -519,8 +720,8 @@ void wxDC::DoDrawArc(
         // Medium point
         //
         dAnglmid = (dAngl1 + dAngl2)/2. + M_PI;
-        vXm      = vXc + dRadius * cos(dAnglmid);
-        vYm      = vYc + dRadius * sin(dAnglmid);
+        vXm      = (wxCoord)(vXc + dRadius * cos(dAnglmid));
+        vYm      = (wxCoord)(vYc + dRadius * sin(dAnglmid));
         DoDrawArc( vX1, vY1
                   ,vXm, vYm
                   ,vXc, vYc
@@ -536,8 +737,8 @@ void wxDC::DoDrawArc(
     // Medium point
     //
     dAnglmid = (dAngl1 + dAngl2)/2.;
-    vXm      = vXc + dRadius * cos(dAnglmid);
-    vYm      = vYc + dRadius * sin(dAnglmid);
+    vXm      = (wxCoord)(vXc + dRadius * cos(dAnglmid));
+    vYm      = (wxCoord)(vYc + dRadius * sin(dAnglmid));
 
     //
     // Ellipse main axis (r,q), (p,s) with center at (0,0) */
@@ -556,15 +757,15 @@ void wxDC::DoDrawArc(
     vPtlArc[1].x = vX2;
     vPtlArc[1].y = vY2;
     ::GpiPointArc(m_hPS, vPtlArc); // Draws the arc
-    CalcBoundingBox( (vXc - dRadius)
-                    ,(vYc - dRadius)
+    CalcBoundingBox( (wxCoord)(vXc - dRadius)
+                    ,(wxCoord)(vYc - dRadius)
                    );
-    CalcBoundingBox( (vXc + dRadius)
-                    ,(vYc + dRadius)
+    CalcBoundingBox( (wxCoord)(vXc + dRadius)
+                    ,(wxCoord)(vYc + dRadius)
                    );
-} // end of wxDC::DoDrawArc
+} // end of wxPMDCImpl::DoDrawArc
 
-void wxDC::DoDrawCheckMark(
+void wxPMDCImpl::DoDrawCheckMark(
   wxCoord                           vX1
 , wxCoord                           vY1
 , wxCoord                           vWidth
@@ -611,9 +812,9 @@ void wxDC::DoDrawCheckMark(
     CalcBoundingBox( vX2
                     ,vY2
                    );
-} // end of wxDC::DoDrawCheckMark
+} // end of wxPMDCImpl::DoDrawCheckMark
 
-void wxDC::DoDrawPoint(
+void wxPMDCImpl::DoDrawPoint(
   wxCoord                           vX
 , wxCoord                           vY
 )
@@ -632,49 +833,46 @@ void wxDC::DoDrawPoint(
     CalcBoundingBox( vX
                     ,vY
                    );
-} // end of wxDC::DoDrawPoint
+} // end of wxPMDCImpl::DoDrawPoint
 
-void wxDC::DoDrawPolygon(
-  int                               n
-, wxPoint                           vPoints[]
-, wxCoord                           vXoffset
-, wxCoord                           vYoffset
-, int                               nFillStyle
-)
+void wxPMDCImpl::DoDrawPolygon( int n,
+                          wxPoint vPoints[],
+                          wxCoord vXoffset,
+                          wxCoord vYoffset,
+                          wxPolygonFillMode nFillStyle )
 {
-    ULONG                           ulCount = 1;    // Number of polygons.
-    POLYGON                         vPlgn;          // polygon.
-    ULONG                           flOptions = 0L; // Drawing options.
-
-//////////////////////////////////////////////////////////////////////////////
-// This contains fields of option bits... to draw boundary lines as well as
-// the area interior.
-//
-// Drawing boundary lines:
-//   POLYGON_NOBOUNDARY              Does not draw boundary lines.
-//   POLYGON_BOUNDARY                Draws boundary lines (the default).
-//
-// Construction of the area interior:
-//   POLYGON_ALTERNATE               Constructs interior in alternate mode
-//                                   (the default).
-//   POLYGON_WINDING                 Constructs interior in winding mode.
-//////////////////////////////////////////////////////////////////////////////
-
-    ULONG                           flModel = 0L; // Drawing model.
-
-//////////////////////////////////////////////////////////////////////////////
-// Drawing model.
-//   POLYGON_INCL  Fill is inclusive of bottom right (the default).
-//   POLYGON_EXCL  Fill is exclusive of bottom right.
-//       This is provided to aid migration from other graphics models.
-//////////////////////////////////////////////////////////////////////////////
+    ULONG     ulCount = 1;    // Number of polygons.
+    POLYGON   vPlgn;          // polygon.
+    ULONG     flOptions = 0L; // Drawing options.
 
-    LONG                            lHits = 0L; // Correlation/error indicator.
-    POINTL                          vPoint;
-    int                             i;
-    int                             nIsTRANSPARENT = 0;
-    LONG                            lBorderColor = 0L;
-    LONG                            lColor = 0L;
+    //////////////////////////////////////////////////////////////////////////////
+    // This contains fields of option bits... to draw boundary lines as well as
+    // the area interior.
+    //
+    // Drawing boundary lines:
+    //   POLYGON_NOBOUNDARY              Does not draw boundary lines.
+    //   POLYGON_BOUNDARY                Draws boundary lines (the default).
+    //
+    // Construction of the area interior:
+    //   POLYGON_ALTERNATE               Constructs interior in alternate mode
+    //                                   (the default).
+    //   POLYGON_WINDING                 Constructs interior in winding mode.
+    //////////////////////////////////////////////////////////////////////////////
+
+    ULONG     flModel = POLYGON_INCL; // Drawing model.
+
+    //////////////////////////////////////////////////////////////////////////////
+    // Drawing model.
+    //   POLYGON_INCL  Fill is inclusive of bottom right (the default).
+    //   POLYGON_EXCL  Fill is exclusive of bottom right.
+    //       This is provided to aid migration from other graphics models.
+    //////////////////////////////////////////////////////////////////////////////
+
+    LONG      lHits = 0L; // Correlation/error indicator.
+    int       i;
+    int       nIsTRANSPARENT = 0;
+    LONG      lBorderColor = 0L;
+    LONG      lColor = 0L;
 
     lBorderColor = m_pen.GetColour().GetPixel();
     lColor       = m_brush.GetColour().GetPixel();
@@ -688,25 +886,22 @@ void wxDC::DoDrawPolygon(
 
     for(i = 0; i < n; i++)
     {
-        vPlgn.aPointl[i].x = vPoints[i].x;         // +xoffset;
-        vPlgn.aPointl[i].y = OS2Y(vPoints[i].y,0); // +yoffset;
+        vPlgn.aPointl[i].x = vPoints[i].x+vXoffset;
+        vPlgn.aPointl[i].y = OS2Y(vPoints[i].y+vYoffset,0);
     }
-    flModel = POLYGON_BOUNDARY;
+    flOptions = POLYGON_BOUNDARY;
     if(nFillStyle == wxWINDING_RULE)
-        flModel |= POLYGON_WINDING;
+        flOptions |= POLYGON_WINDING;
     else
-        flModel |= POLYGON_ALTERNATE;
-
-    vPoint.x = vXoffset;
-    vPoint.y = OS2Y(vYoffset,0);
+        flOptions |= POLYGON_ALTERNATE;
 
     ::GpiSetColor(m_hPS, lBorderColor);
-    ::GpiMove(m_hPS, &vPoint);
+    ::GpiMove(m_hPS, &vPlgn.aPointl[0]);
     lHits = ::GpiPolygons(m_hPS, ulCount, &vPlgn, flOptions, flModel);
     free(vPlgn.aPointl);
-} // end of wxDC::DoDrawPolygon
+} // end of wxPMDCImpl::DoDrawPolygon
 
-void wxDC::DoDrawLines(
+void wxPMDCImpl::DoDrawLines(
   int                               n
 , wxPoint                           vPoints[]
 , wxCoord                           vXoffset
@@ -737,8 +932,8 @@ void wxDC::DoDrawLines(
     {
         int                         i;
 
-        CalcBoundingBox( vPoints[i].x
-                        ,vPoints[i].y
+        CalcBoundingBox( vPoints[0].x
+                        ,vPoints[0].y
                        );
         vPoint.x = vPoints[0].x;
         vPoint.y = OS2Y(vPoints[0].y,0);
@@ -754,9 +949,9 @@ void wxDC::DoDrawLines(
             ::GpiLine(m_hPS, &vPoint);
         }
     }
-} // end of wxDC::DoDrawLines
+} // end of wxPMDCImpl::DoDrawLines
 
-void wxDC::DoDrawRectangle(
+void wxPMDCImpl::DoDrawRectangle(
   wxCoord                           vX
 , wxCoord                           vY
 , wxCoord                           vWidth
@@ -769,15 +964,31 @@ void wxDC::DoDrawRectangle(
     LONG                            lBorderColor;
     int                             nIsTRANSPARENT = 0;
 
-    vY = OS2Y(vY,vHeight);
+    //
+    // Might be a memory DC with no Paint rect.
+    //
+    if (!(m_vRclPaint.yTop == 0 &&
+          m_vRclPaint.yBottom == 0 &&
+          m_vRclPaint.xRight == 0 &&
+          m_vRclPaint.xLeft == 0))
+        vY = OS2Y(vY,vHeight);
+    else
+    {
+        if (m_vSelectedBitmap.Ok())
+        {
+            m_vRclPaint.yTop = m_vSelectedBitmap.GetHeight();
+            m_vRclPaint.xRight = m_vSelectedBitmap.GetWidth();
+            vY = OS2Y(vY,vHeight);
+        }
+    }
 
     wxCoord                         vX2 = vX + vWidth;
     wxCoord                         vY2 = vY + vHeight;
 
     vPoint[0].x = vX;
     vPoint[0].y = vY;
-    vPoint[1].x = vX + vWidth;
-    vPoint[1].y = vY + vHeight;
+    vPoint[1].x = vX + vWidth - 1;
+    vPoint[1].y = vY + vHeight - 1;
     ::GpiMove(m_hPS, &vPoint[0]);
     lColor       = m_brush.GetColour().GetPixel();
     lBorderColor = m_pen.GetColour().GetPixel();
@@ -789,7 +1000,7 @@ void wxDC::DoDrawRectangle(
         if(m_brush.GetStyle() == wxTRANSPARENT)
             lControl = DRO_OUTLINE;
 
-        ::GpiSetColor(m_hPS, lColor);
+        ::GpiSetColor(m_hPS, lBorderColor);
         ::GpiBox( m_hPS       // handle to a presentation space
                  ,lControl   // draw the box outline ? or ?
                  ,&vPoint[1]  // address of the corner
@@ -816,7 +1027,7 @@ void wxDC::DoDrawRectangle(
         vPoint[0].x = vX + 1;
         vPoint[0].y = vY + 1;
         vPoint[1].x = vX + vWidth - 2;
-        vPoint[1].y = vY + vHeight + 2;
+        vPoint[1].y = vY + vHeight - 2;
         ::GpiMove(m_hPS, &vPoint[0]);
         ::GpiBox( m_hPS
                  ,lControl
@@ -827,9 +1038,9 @@ void wxDC::DoDrawRectangle(
     }
     CalcBoundingBox(vX, vY);
     CalcBoundingBox(vX2, vY2);
-} // end of wxDC::DoDrawRectangle
+} // end of wxPMDCImpl::DoDrawRectangle
 
-void wxDC::DoDrawRoundedRectangle(
+void wxPMDCImpl::DoDrawRoundedRectangle(
   wxCoord                           vX
 , wxCoord                           vY
 , wxCoord                           vWidth
@@ -839,33 +1050,91 @@ void wxDC::DoDrawRoundedRectangle(
 {
     POINTL                          vPoint[2];
     LONG                            lControl;
+    LONG                            lColor;
+    LONG                            lBorderColor;
+    int                             nIsTRANSPARENT = 0;
 
-    vY = OS2Y(vY,vHeight);
+    //
+    // Might be a memory DC with no Paint rect.
+    //
+    if (!(m_vRclPaint.yTop == 0 &&
+          m_vRclPaint.yBottom == 0 &&
+          m_vRclPaint.xRight == 0 &&
+          m_vRclPaint.xLeft == 0))
+        vY = OS2Y(vY,vHeight);
+    else
+    {
+        if (m_vSelectedBitmap.Ok())
+        {
+            m_vRclPaint.yTop = m_vSelectedBitmap.GetHeight();
+            m_vRclPaint.xRight = m_vSelectedBitmap.GetWidth();
+            vY = OS2Y(vY,vHeight);
+        }
+    }
 
     wxCoord                         vX2 = (vX + vWidth);
     wxCoord                         vY2 = (vY + vHeight);
 
     vPoint[0].x = vX;
-    vPoint[0].y = YLOG2DEV(vY) - vHeight;
-    vPoint[1].x = vX + vWidth;
-    vPoint[1].y = vY;
+    vPoint[0].y = vY;
+    vPoint[1].x = vX + vWidth - 1;
+    vPoint[1].y = vY + vHeight - 1;
     ::GpiMove(m_hPS, &vPoint[0]);
 
+    lColor       = m_brush.GetColour().GetPixel();
+    lBorderColor = m_pen.GetColour().GetPixel();
     lControl = DRO_OUTLINEFILL; //DRO_FILL;
     if (m_brush.GetStyle() == wxTRANSPARENT)
+        nIsTRANSPARENT = 1;
+    if(lColor == lBorderColor || nIsTRANSPARENT)
+    {
+        lControl = DRO_OUTLINEFILL; //DRO_FILL;
+        if(m_brush.GetStyle() == wxTRANSPARENT)
+            lControl = DRO_OUTLINE;
+
+        ::GpiSetColor(m_hPS, lColor);
+        ::GpiBox( m_hPS         // handle to a presentation space
+                 ,lControl      // draw the box outline ? or ?
+                 ,&vPoint[1]    // address of the corner
+                 ,(LONG)dRadius // horizontal corner radius
+                 ,(LONG)dRadius // vertical corner radius
+                );
+    }
+    else
+    {
         lControl = DRO_OUTLINE;
-    ::GpiBox( m_hPS         // handle to a presentation space
-             ,DRO_OUTLINE   // draw the box outline ? or ?
-             ,&vPoint[1]    // address of the corner
-             ,(LONG)dRadius // horizontal corner radius
-             ,(LONG)dRadius // vertical corner radius
-            );
+        ::GpiSetColor( m_hPS
+                      ,lBorderColor
+                     );
+        ::GpiBox( m_hPS
+                 ,lControl
+                 ,&vPoint[1]
+                 ,(LONG)dRadius
+                 ,(LONG)dRadius
+                );
+        lControl = DRO_FILL;
+        ::GpiSetColor( m_hPS
+                      ,lColor
+                     );
+        vPoint[0].x = vX + 1;
+        vPoint[0].y = vY + 1;
+        vPoint[1].x = vX + vWidth - 2;
+        vPoint[1].y = vY + vHeight - 2;
+        ::GpiMove(m_hPS, &vPoint[0]);
+        ::GpiBox( m_hPS
+                 ,lControl
+                 ,&vPoint[1]
+                 ,(LONG)dRadius
+                 ,(LONG)dRadius
+                );
+    }
+
     CalcBoundingBox(vX, vY);
     CalcBoundingBox(vX2, vY2);
-} // end of wxDC::DoDrawRoundedRectangle
+} // end of wxPMDCImpl::DoDrawRoundedRectangle
 
 // Draw Ellipse within box (x,y) - (x+width, y+height)
-void wxDC::DoDrawEllipse(
+void wxPMDCImpl::DoDrawEllipse(
   wxCoord                           vX
 , wxCoord                           vY
 , wxCoord                           vWidth
@@ -905,9 +1174,9 @@ void wxDC::DoDrawEllipse(
 
     CalcBoundingBox(vX, vY);
     CalcBoundingBox(vX2, vY2);
-} // end of wxDC::DoDrawEllipse
+} // end of wxPMDCImpl::DoDrawEllipse
 
-void wxDC::DoDrawEllipticArc(
+void wxPMDCImpl::DoDrawEllipticArc(
   wxCoord                           vX
 , wxCoord                           vY
 , wxCoord                           vWidth
@@ -923,7 +1192,6 @@ void wxDC::DoDrawEllipticArc(
     FIXED                           vFSweepa; // Start angle, sweep angle
     double                          dIntPart;
     double                          dFractPart;
-    double                          dRadius;
 
     vY = OS2Y(vY,vHeight);
 
@@ -940,8 +1208,8 @@ void wxDC::DoDrawEllipticArc(
     vArcp.lP = vWidth/2;
     vArcp.lS = 0;
     ::GpiSetArcParams(m_hPS, &vArcp); // Sets parameters to default
-    vPtlPos.x = vX + vWidth/2  * (1. + cos(DegToRad(dSa))); // Loads x-coordinate
-    vPtlPos.y = vY + vHeight/2 * (1. + sin(DegToRad(dSa))); // Loads y-coordinate
+    vPtlPos.x = (wxCoord)(vX + vWidth/2  * (1. + cos(DegToRad(dSa)))); // Loads x-coordinate
+    vPtlPos.y = (wxCoord)(vY + vHeight/2 * (1. + sin(DegToRad(dSa)))); // Loads y-coordinate
     ::GpiMove(m_hPS, &vPtlPos); // Sets current position
 
     //
@@ -965,47 +1233,439 @@ void wxDC::DoDrawEllipticArc(
 
     CalcBoundingBox(vX, vY);
     CalcBoundingBox(vX2, vY2);
-} // end of wxDC::DoDrawEllipticArc
+} // end of wxPMDCImpl::DoDrawEllipticArc
 
-void wxDC::DoDrawIcon(
+void wxPMDCImpl::DoDrawIcon(
   const wxIcon&                     rIcon
 , wxCoord                           vX
 , wxCoord                           vY
 )
 {
-    vY = OS2Y(vY,rIcon.GetHeight());
-    wxCHECK_RET( rIcon.Ok(), wxT("invalid icon in DrawIcon") );
+    //
+    // Need to copy back into a bitmap.  ::WinDrawPointer uses device coords
+    // and I don't feel like figuring those out for scrollable windows so
+    // just convert to a bitmap then let the DoDrawBitmap routine display it
+    //
+    if (rIcon.IsXpm())
+    {
+        DoDrawBitmap(rIcon.GetXpmSrc(), vX, vY, true);
+    }
+    else
+    {
+        wxBitmap                        vBitmap(rIcon);
 
-    ::WinDrawPointer( GetHPS()
-                     ,vX
-                     ,vY
-                     ,(HPOINTER)GetHiconOf(rIcon)
-                     ,DP_NORMAL
-                    );
+        DoDrawBitmap(vBitmap, vX, vY, false);
+    }
     CalcBoundingBox(vX, vY);
     CalcBoundingBox(vX + rIcon.GetWidth(), vY + rIcon.GetHeight());
-} // end of wxDC::DoDrawIcon
+} // end of wxPMDCImpl::DoDrawIcon
 
-void wxDC::DoDrawBitmap(
+void wxPMDCImpl::DoDrawBitmap(
   const wxBitmap&                   rBmp
 , wxCoord                           vX
 , wxCoord                           vY
 , bool                              bUseMask
 )
 {
-    POINTL                          vPoint = {vX, vY};
+#if wxUSE_PRINTING_ARCHITECTURE
+    if (!IsKindOf(CLASSINFO(wxPrinterDC)))
+#endif
+    {
+        HBITMAP                         hBitmap =  (HBITMAP)rBmp.GetHBITMAP();
+        HBITMAP                         hBitmapOld = NULLHANDLE;
+        POINTL                          vPoint[4];
+
+        vY = OS2Y(vY,rBmp.GetHeight());
+
+        vPoint[0].x = vX;
+        vPoint[0].y = vY + rBmp.GetHeight();
+        vPoint[1].x = vX + rBmp.GetWidth();
+        vPoint[1].y = vY;
+        vPoint[2].x = 0;
+        vPoint[2].y = 0;
+        vPoint[3].x = rBmp.GetWidth();
+        vPoint[3].y = rBmp.GetHeight();
+        if (bUseMask)
+        {
+            wxMask*                     pMask = rBmp.GetMask();
 
-    ::WinDrawBitmap( GetHPS()
-                    ,(HBITMAP)GetHbitmapOf(rBmp)
-                    ,NULL
-                    ,&vPoint
-                    ,0L
-                    ,0L
-                    ,DBM_NORMAL
-                   );
-} // end of wxDC::DoDrawBitmap
+            if (pMask)
+            {
+                //
+                // Need to imitate ::MaskBlt in windows.
+                // 1) Extract the bits from from the bitmap.
+                // 2) Extract the bits from the mask
+                // 3) Using the mask bits do the following:
+                //   A) If the mask byte is 00 leave the bitmap byte alone
+                //   B) If the mask byte is FF copy the screen color into
+                //      bitmap byte
+                // 4) Create a new bitmap and set its bits to the above result
+                // 5) Blit this to the screen PS
+                //
+                HBITMAP                 hMask = (HBITMAP)pMask->GetMaskBitmap();
+                HBITMAP                 hOldMask   = NULLHANDLE;
+                HBITMAP                 hOldBitmap = NULLHANDLE;
+                HBITMAP                 hNewBitmap = NULLHANDLE;
+                unsigned char*          pucBits;     // buffer that will contain the bitmap data
+                unsigned char*          pucBitsMask; // buffer that will contain the mask data
+                unsigned char*          pucData;     // pointer to use to traverse bitmap data
+                unsigned char*          pucDataMask; // pointer to use to traverse mask data
+                LONG                    lHits;
+                ERRORID                 vError;
+                wxString                sError;
 
-void wxDC::DoDrawText(
+                //
+                // The usual Memory context creation stuff
+                //
+                DEVOPENSTRUC                    vDop  = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
+                SIZEL                           vSize = {0, 0};
+                HDC                             hDC   = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
+                HPS                             hPS   = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC);
+
+                //
+                // The usual bitmap header stuff
+                //
+                BITMAPINFOHEADER2               vHeader;
+                BITMAPINFO2                     vInfo;
+
+                memset(&vHeader, '\0', 16);
+                vHeader.cbFix           = 16;
+
+                memset(&vInfo, '\0', 16);
+                vInfo.cbFix           = 16;
+                vInfo.cx              = (ULONG)rBmp.GetWidth();
+                vInfo.cy              = (ULONG)rBmp.GetHeight();
+                vInfo.cPlanes         = 1;
+                vInfo.cBitCount       = 24; // Set to desired count going in
+
+                //
+                // Create the buffers for data....all wxBitmaps are 24 bit internally
+                //
+                int                     nBytesPerLine = rBmp.GetWidth() * 3;
+                int                     nSizeDWORD    = sizeof(DWORD);
+                int                     nLineBoundary = nBytesPerLine % nSizeDWORD;
+                int                     nPadding = 0;
+                int                     i;
+                int                     j;
+                LONG                    lScans = 0L;
+                LONG                    lColor = 0L;
+
+                //
+                // Need to get a background color for mask blitting
+                //
+                if (IsKindOf(CLASSINFO(wxWindowDCImpl)))
+                {
+                    wxWindowDCImpl*  pWindowDC = wxDynamicCast(this, wxWindowDCImpl);
+
+                    lColor = pWindowDC->m_pCanvas->GetBackgroundColour().GetPixel();
+                }
+                else if (GetBrush().Ok())
+                    lColor = GetBrush().GetColour().GetPixel();
+                else
+                    lColor = m_textBackgroundColour.GetPixel();
+
+                //
+                // Bitmap must be in a double-word aligned address so we may
+                // have some padding to worry about
+                //
+                if (nLineBoundary > 0)
+                {
+                    nPadding     = nSizeDWORD - nLineBoundary;
+                    nBytesPerLine += nPadding;
+                }
+                pucBits = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight());
+                pucBitsMask = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight());
+                memset(pucBits, '\0', (nBytesPerLine * rBmp.GetHeight()));
+                memset(pucBitsMask, '\0', (nBytesPerLine * rBmp.GetHeight()));
+
+                //
+                // Extract the bitmap and mask data
+                //
+                if ((hOldBitmap = ::GpiSetBitmap(hPS, hBitmap)) == HBM_ERROR)
+                {
+                    vError = ::WinGetLastError(vHabmain);
+                    sError = wxPMErrorToStr(vError);
+                }
+                ::GpiQueryBitmapInfoHeader(hBitmap, &vHeader);
+                vInfo.cBitCount = 24;
+                if ((lScans = ::GpiQueryBitmapBits( hPS
+                                                   ,0L
+                                                   ,(LONG)rBmp.GetHeight()
+                                                   ,(PBYTE)pucBits
+                                                   ,&vInfo
+                                                  )) == GPI_ALTERROR)
+                {
+                    vError = ::WinGetLastError(vHabmain);
+                    sError = wxPMErrorToStr(vError);
+                }
+                if ((hOldMask = ::GpiSetBitmap(hPS, hMask)) == HBM_ERROR)
+                {
+                    vError = ::WinGetLastError(vHabmain);
+                    sError = wxPMErrorToStr(vError);
+                }
+                ::GpiQueryBitmapInfoHeader(hMask, &vHeader);
+                vInfo.cBitCount = 24;
+                if ((lScans = ::GpiQueryBitmapBits( hPS
+                                                   ,0L
+                                                   ,(LONG)rBmp.GetHeight()
+                                                   ,(PBYTE)pucBitsMask
+                                                   ,&vInfo
+                                                  )) == GPI_ALTERROR)
+                {
+                    vError = ::WinGetLastError(vHabmain);
+                    sError = wxPMErrorToStr(vError);
+                }
+                if (( hMask = ::GpiSetBitmap(hPS, hOldMask)) == HBM_ERROR)
+                {
+                    vError = ::WinGetLastError(vHabmain);
+                    sError = wxPMErrorToStr(vError);
+                }
+
+                //
+                // Now set the bytes(bits) according to the mask values
+                // 3 bytes per pel...must handle one at a time
+                //
+                pucData     = pucBits;
+                pucDataMask = pucBitsMask;
+
+                //
+                // 16 bit kludge really only kinda works.  The mask gets applied
+                // where needed but the original bitmap bits are dorked sometimes
+                //
+                bool                    bpp16 = (wxDisplayDepth() == 16);
+
+                for (i = 0; i < rBmp.GetHeight(); i++)
+                {
+                    for (j = 0; j < rBmp.GetWidth(); j++)
+                    {
+                        // Byte 1
+                        if (bpp16 && *pucDataMask == 0xF8) // 16 bit display gobblygook
+                            pucData++;
+                        else if (*pucDataMask == 0xFF) // leave bitmap byte alone
+                            pucData++;
+                        else
+                        {
+                            *pucData = ((unsigned char)(lColor >> 16));
+                            pucData++;
+                        }
+                        // Byte 2
+                        if (bpp16 && *(pucDataMask + 1) == 0xFC) // 16 bit display gobblygook
+                            pucData++;
+                        else if (*(pucDataMask + 1) == 0xFF) // leave bitmap byte alone
+                            pucData++;
+                        else
+                        {
+                            *pucData = ((unsigned char)(lColor >> 8));
+                            pucData++;
+                        }
+
+                        // Byte 3
+                        if (bpp16 && *(pucDataMask + 2) == 0xF8) // 16 bit display gobblygook
+                            pucData++;
+                        else if (*(pucDataMask + 2) == 0xFF) // leave bitmap byte alone
+                            pucData++;
+                        else
+                        {
+                            *pucData = ((unsigned char)lColor);
+                            pucData++;
+                        }
+                        pucDataMask += 3;
+                    }
+                    for (j = 0; j < nPadding; j++)
+                    {
+                        pucData++;
+                        pucDataMask++;
+                    }
+                }
+                //
+                // Create a new bitmap
+                //
+                vHeader.cx              = (ULONG)rBmp.GetWidth();
+                vHeader.cy              = (ULONG)rBmp.GetHeight();
+                vHeader.cPlanes         = 1L;
+                vHeader.cBitCount       = 24;
+                if ((hNewBitmap = ::GpiCreateBitmap( hPS
+                                                    ,&vHeader
+                                                    ,CBM_INIT
+                                                    ,(PBYTE)pucBits
+                                                    ,&vInfo
+                                                   )) == GPI_ERROR)
+                {
+                    vError = ::WinGetLastError(vHabmain);
+                    sError = wxPMErrorToStr(vError);
+                }
+
+                //
+                // Now blit it to the screen PS
+                //
+                if ((lHits = ::GpiWCBitBlt( (HPS)GetHPS()
+                                           ,hNewBitmap
+                                           ,4
+                                           ,vPoint
+                                           ,ROP_SRCCOPY
+                                           ,BBO_IGNORE
+                                          )) == GPI_ERROR)
+                {
+                    vError = ::WinGetLastError(vHabmain);
+                    sError = wxPMErrorToStr(vError);
+                }
+
+                //
+                // Clean up
+                //
+                free(pucBits);
+                free(pucBitsMask);
+                ::GpiSetBitmap(hPS, NULLHANDLE);
+                ::GpiDeleteBitmap(hNewBitmap);
+                ::GpiDestroyPS(hPS);
+                ::DevCloseDC(hDC);
+            }
+        }
+        else
+        {
+            ULONG                       lOldForeGround = ::GpiQueryColor((HPS)GetHPS());
+            ULONG                       lOldBackGround = ::GpiQueryBackColor((HPS)GetHPS());
+
+            if (m_textForegroundColour.Ok())
+            {
+                ::GpiSetColor( (HPS)GetHPS()
+                               ,m_textForegroundColour.GetPixel()
+                              );
+            }
+            if (m_textBackgroundColour.Ok())
+            {
+                ::GpiSetBackColor( (HPS)GetHPS()
+                                  ,m_textBackgroundColour.GetPixel()
+                                 );
+            }
+            //
+            // Need to alter bits in a mono bitmap to match the new
+            // background-foreground if it is different.
+            //
+            if (rBmp.IsMono() &&
+               ((m_textForegroundColour.GetPixel() != lOldForeGround) ||
+                (m_textBackgroundColour.GetPixel() != lOldBackGround)))
+            {
+                DEVOPENSTRUC        vDop  = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
+                SIZEL               vSize = {0, 0};
+                HDC                 hDC   = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
+                HPS                 hPS   = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC);
+
+                int                 nBytesPerLine = rBmp.GetWidth() * 3;
+                int                 i, j;
+                LONG                lForeGround = m_textForegroundColour.GetPixel();
+                LONG                lBackGround = m_textBackgroundColour.GetPixel();
+                LONG                lScans;
+                HBITMAP             hOldBitmap = NULLHANDLE;
+                BITMAPINFO2         vInfo;
+                ERRORID             vError;
+                wxString            sError;
+
+
+                memset(&vInfo, '\0', 16);
+                vInfo.cbFix           = 16;
+                vInfo.cx              = (ULONG)rBmp.GetWidth();
+                vInfo.cy              = (ULONG)rBmp.GetHeight();
+                vInfo.cPlanes         = 1;
+                vInfo.cBitCount       = 24;
+
+                unsigned char*          pucBits;     // buffer that will contain the bitmap data
+                unsigned char*          pucData;     // pointer to use to traverse bitmap data
+
+                pucBits = new unsigned char[nBytesPerLine * rBmp.GetHeight()];
+                memset(pucBits, '\0', (nBytesPerLine * rBmp.GetHeight()));
+
+                if ((hOldBitmap = ::GpiSetBitmap(hPS, hBitmap)) == HBM_ERROR)
+                {
+                    vError = ::WinGetLastError(vHabmain);
+                    sError = wxPMErrorToStr(vError);
+                    return;
+                }
+                if ((lScans = ::GpiQueryBitmapBits( hPS
+                                                   ,0L
+                                                   ,(LONG)rBmp.GetHeight()
+                                                   ,(PBYTE)pucBits
+                                                   ,&vInfo
+                                                  )) == GPI_ALTERROR)
+                {
+                    vError = ::WinGetLastError(vHabmain);
+                    sError = wxPMErrorToStr(vError);
+                    return;
+                }
+                unsigned char           cOldRedFore   = (unsigned char)(lOldForeGround >> 16);
+                unsigned char           cOldGreenFore = (unsigned char)(lOldForeGround >> 8);
+                unsigned char           cOldBlueFore  = (unsigned char)lOldForeGround;
+
+                unsigned char           cRedFore   = (unsigned char)(lForeGround >> 16);
+                unsigned char           cGreenFore = (unsigned char)(lForeGround >> 8);
+                unsigned char           cBlueFore  = (unsigned char)lForeGround;
+
+                unsigned char           cRedBack   = (unsigned char)(lBackGround >> 16);
+                unsigned char           cGreenBack = (unsigned char)(lBackGround >> 8);
+                unsigned char           cBlueBack  = (unsigned char)lBackGround;
+
+                pucData = pucBits;
+                for (i = 0; i < rBmp.GetHeight(); i++)
+                {
+                    for (j = 0; j < rBmp.GetWidth(); j++)
+                    {
+                        unsigned char    cBmpRed   = *pucData;
+                        unsigned char    cBmpGreen = *(pucData + 1);
+                        unsigned char    cBmpBlue  = *(pucData + 2);
+
+                        if ((cBmpRed == cOldRedFore) &&
+                            (cBmpGreen == cOldGreenFore) &&
+                            (cBmpBlue == cOldBlueFore))
+                        {
+                            *pucData = cBlueFore;
+                            pucData++;
+                            *pucData = cGreenFore;
+                            pucData++;
+                            *pucData = cRedFore;
+                            pucData++;
+                        }
+                        else
+                        {
+                            *pucData = cBlueBack;
+                            pucData++;
+                            *pucData = cGreenBack;
+                            pucData++;
+                            *pucData = cRedBack;
+                            pucData++;
+                        }
+                    }
+                }
+                if ((lScans = ::GpiSetBitmapBits( hPS
+                                                 ,0L
+                                                 ,(LONG)rBmp.GetHeight()
+                                                 ,(PBYTE)pucBits
+                                                 ,&vInfo
+                                                )) == GPI_ALTERROR)
+                {
+                    vError = ::WinGetLastError(vHabmain);
+                    sError = wxPMErrorToStr(vError);
+                    return;
+                }
+                delete [] pucBits;
+                ::GpiSetBitmap(hPS, NULLHANDLE);
+                ::GpiDestroyPS(hPS);
+                ::DevCloseDC(hDC);
+            }
+            ::GpiWCBitBlt( (HPS)GetHPS()
+                          ,hBitmap
+                          ,4
+                          ,vPoint
+                          ,ROP_SRCCOPY
+                          ,BBO_IGNORE
+                         );
+            ::GpiSetBitmap((HPS)GetHPS(), hBitmapOld);
+            ::GpiSetColor((HPS)GetHPS(), lOldForeGround);
+            ::GpiSetBackColor((HPS)GetHPS(), lOldBackGround);
+        }
+    }
+} // end of wxPMDCImpl::DoDrawBitmap
+
+void wxPMDCImpl::DoDrawText(
   const wxString&                   rsText
 , wxCoord                           vX
 , wxCoord                           vY
@@ -1020,15 +1680,13 @@ void wxDC::DoDrawText(
                );
 
     CalcBoundingBox(vX, vY);
-    GetTextExtent(rsText, &vWidth, &vHeight);
+    GetOwner()->GetTextExtent(rsText, &vWidth, &vHeight);
     CalcBoundingBox((vX + vWidth), (vY + vHeight));
-} // end of wxDC::DoDrawText
+} // end of wxPMDCImpl::DoDrawText
 
-void wxDC::DrawAnyText(
-  const wxString&                   rsText
-, wxCoord                           vX
-, wxCoord                           vY
-)
+void wxPMDCImpl::DrawAnyText( const wxString& rsText,
+                        wxCoord vX,
+                        wxCoord vY )
 {
     int                             nOldBackground = 0;
     POINTL                          vPtlStart;
@@ -1059,18 +1717,35 @@ void wxDC::DrawAnyText(
     SetBkMode( m_hPS
               ,m_backgroundMode
              );
-    GetTextExtent( rsText
-                  ,&vTextX
-                  ,&vTextY
-                 );
+    GetOwner()->GetTextExtent( rsText
+                              ,&vTextX
+                              ,&vTextY
+                             );
     vPtlStart.x = vX;
-    vPtlStart.y = OS2Y(vY,vTextY);
+    if (!(m_vRclPaint.yTop == 0 &&
+          m_vRclPaint.yBottom == 0 &&
+          m_vRclPaint.xRight == 0 &&
+          m_vRclPaint.xLeft == 0))
+    {
+        vPtlStart.y = OS2Y(vY,vTextY);
+    }
+    else
+    {
+        if (m_vSelectedBitmap.Ok())
+        {
+            m_vRclPaint.yTop = m_vSelectedBitmap.GetHeight();
+            m_vRclPaint.xRight = m_vSelectedBitmap.GetWidth();
+            vPtlStart.y = OS2Y(vY,vTextY);
+        }
+        else
+            vPtlStart.y = vY;
+    }
 
-    lHits = ::GpiCharStringAt( m_hPS
-                              ,&vPtlStart
-                              ,rsText.length()
-                              ,(PCH)rsText.c_str()
-                             );
+    ::GpiMove(m_hPS, &vPtlStart);
+    lHits = ::GpiCharString( m_hPS
+                            ,rsText.length()
+                            ,rsText.char_str()
+                           );
     if (lHits != GPI_OK)
     {
         wxLogLastError(wxT("TextOut"));
@@ -1090,7 +1765,7 @@ void wxDC::DrawAnyText(
              );
 }
 
-void wxDC::DoDrawRotatedText(
+void wxPMDCImpl::DoDrawRotatedText(
   const wxString&                   rsText
 , wxCoord                           vX
 , wxCoord                           vY
@@ -1161,7 +1836,51 @@ void wxDC::DoDrawRotatedText(
 // set GDI objects
 // ---------------------------------------------------------------------------
 
-void wxDC::SetPalette(
+void wxPMDCImpl::DoSelectPalette( bool WXUNUSED(bRealize) )
+{
+    //
+    // Set the old object temporarily, in case the assignment deletes an object
+    // that's not yet selected out.
+    //
+    if (m_hOldPalette)
+    {
+        m_hOldPalette = 0;
+    }
+
+    if (m_palette.Ok())
+    {
+        HPALETTE                    hOldPal;
+
+        hOldPal = ::GpiSelectPalette((HDC) m_hPS, (HPALETTE) m_palette.GetHPALETTE());
+        if (!m_hOldPalette)
+            m_hOldPalette = (WXHPALETTE)hOldPal;
+    }
+} // end of wxPMDCImpl::DoSelectPalette
+
+void wxPMDCImpl::InitializePalette()
+{
+    if (wxDisplayDepth() <= 8 )
+    {
+        //
+        // Look for any window or parent that has a custom palette. If any has
+        // one then we need to use it in drawing operations
+        //
+        wxWindow*                   pWin = m_pCanvas->GetAncestorWithCustomPalette();
+
+        m_hasCustomPalette = pWin && pWin->HasCustomPalette();
+        if (m_hasCustomPalette)
+        {
+            m_palette = pWin->GetPalette();
+
+            //
+            // turn on PM translation for this palette
+            //
+            DoSelectPalette();
+        }
+    }
+} // end of wxPMDCImpl::InitializePalette
+
+void wxPMDCImpl::SetPalette(
   const wxPalette&                  rPalette
 )
 {
@@ -1180,9 +1899,9 @@ void wxDC::SetPalette(
     HPALETTE                    hOldPal = ::GpiSelectPalette((HDC) m_hPS, (HPALETTE) m_palette.GetHPALETTE());
     if (!m_hOldPalette)
         m_hOldPalette = (WXHPALETTE)hOldPal;
-} // end of wxDC::SetPalette
+} // end of wxPMDCImpl::SetPalette
 
-void wxDC::SetFont(
+void wxPMDCImpl::SetFont(
   const wxFont&                     rFont
 )
 {
@@ -1207,19 +1926,17 @@ void wxDC::SetFont(
         HFONT                       hFont = m_font.GetResourceHandle();
         if (hFont == (HFONT) NULL)
         {
-            wxLogDebug(wxT("::SelectObject failed in wxDC::SetFont."));
+            wxLogDebug(wxT("::SelectObject failed in wxPMDCImpl::SetFont."));
         }
         if (!m_hOldFont)
             m_hOldFont = (WXHFONT) hFont;
     }
-} // end of wxDC::SetFont
+} // end of wxPMDCImpl::SetFont
 
-void wxDC::SetPen(
+void wxPMDCImpl::SetPen(
   const wxPen&                      rPen
 )
 {
-    wxCHECK_RET( Ok(), wxT("invalid window dc") );
-
     if (m_pen == rPen)
         return;
     m_pen = rPen;
@@ -1247,15 +1964,14 @@ void wxDC::SetPen(
             if (!m_hOldPen)
                 m_hOldPen = m_pen.GetPS();
         }
+        ::GpiSetColor(m_hPS, m_pen.GetColour().GetPixel());
     }
 }
 
-void wxDC::SetBrush(
+void wxPMDCImpl::SetBrush(
   const wxBrush&                    rBrush
 )
 {
-    wxCHECK_RET( Ok(), wxT("invalid window dc") );
-
     if (m_hOldBrush)
         m_hOldBrush = 0L;
     m_brush = rBrush;
@@ -1284,75 +2000,35 @@ void wxDC::SetBrush(
                 m_hOldBrush = (WXHWND)m_brush.GetPS();
         }
     }
-} // end of wxDC::SetBrush
+} // end of wxPMDCImpl::SetBrush
 
-void wxDC::SetBackground(
-  const wxBrush&                    rBrush
-)
+void wxPMDCImpl::SetBackground(const wxBrush& rBrush)
 {
     m_backgroundBrush = rBrush;
-    if (!m_backgroundBrush.Ok())
-        return;
-    if (m_pCanvas)
-    {
-        bool                        bCustomColours = TRUE;
 
-        //
-        // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to
-        // change background colours from the control-panel specified colours.
-        //
-        if (m_pCanvas->IsKindOf(CLASSINFO(wxWindow)) &&
-            ((m_pCanvas->GetWindowStyleFlag() & wxUSER_COLOURS) != wxUSER_COLOURS))
-            bCustomColours = FALSE;
-        if (bCustomColours)
-        {
-            if (m_backgroundBrush.GetStyle()==wxTRANSPARENT)
-            {
-                m_pCanvas->SetTransparent(TRUE);
-            }
-            else
-            {
-                //
-                // Setting the background brush of a DC
-                // doesn't affect the window background colour. However,
-                // I'm leaving in the transparency setting because it's needed by
-                // various controls (e.g. wxStaticText) to determine whether to draw
-                // transparently or not. TODO: maybe this should be a new function
-                // wxWindow::SetTransparency(). Should that apply to the child itself, or the
-                // parent?
-                // m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour());
-                //
-                m_pCanvas->SetTransparent(FALSE);
-            }
-        }
+    if (m_backgroundBrush.Ok())
+    {
+        (void)::GpiSetBackColor((HPS)m_hPS, m_backgroundBrush.GetColour().GetPixel());
     }
-    COLORREF                        vNewColor = m_backgroundBrush.GetColour().GetPixel();
-    (void)::GpiSetBackColor((HPS)m_hPS, (LONG)vNewColor);
-} // end of wxDC::SetBackground
+} // end of wxPMDCImpl::SetBackground
 
-void wxDC::SetBackgroundMode(
-  int                               nMode
-)
+void wxPMDCImpl::SetBackgroundMode(int nMode)
 {
     m_backgroundMode = nMode;
-} // end of wxDC::SetBackgroundMode
+} // end of wxPMDCImpl::SetBackgroundMode
 
-void wxDC::SetLogicalFunction(
-  int                               nFunction
-)
+void wxPMDCImpl::SetLogicalFunction(wxRasterOperationMode nFunction)
 {
     m_logicalFunction = nFunction;
     SetRop((WXHDC)m_hDC);
-} // wxDC::SetLogicalFunction
+} // wxPMDCImpl::SetLogicalFunction
 
-void wxDC::SetRop(
-  WXHDC                             hDC
-)
+void wxPMDCImpl::SetRop(WXHDC hDC)
 {
     if (!hDC || m_logicalFunction < 0)
         return;
 
-    LONG                            lCRop;
+    LONG lCRop;
     switch (m_logicalFunction)
     {
         case wxXOR:
@@ -1407,33 +2083,31 @@ void wxDC::SetRop(
             break;
     }
     ::GpiSetMix((HPS)hDC, lCRop);
-} // end of wxDC::SetRop
+} // end of wxPMDCImpl::SetRop
 
-bool wxDC::StartDoc(
-  const wxString&                   rsMessage
-)
+bool wxPMDCImpl::StartDoc( const wxString& WXUNUSED(rsMessage) )
 {
-    // We might be previewing, so return TRUE to let it continue.
-    return TRUE;
-} // end of wxDC::StartDoc
+    // We might be previewing, so return true to let it continue.
+    return true;
+} // end of wxPMDCImpl::StartDoc
 
-void wxDC::EndDoc()
+void wxPMDCImpl::EndDoc()
 {
-} // end of wxDC::EndDoc
+} // end of wxPMDCImpl::EndDoc
 
-void wxDC::StartPage()
+void wxPMDCImpl::StartPage()
 {
-} // end of wxDC::StartPage
+} // end of wxPMDCImpl::StartPage
 
-void wxDC::EndPage()
+void wxPMDCImpl::EndPage()
 {
-} // end of wxDC::EndPage
+} // end of wxPMDCImpl::EndPage
 
 // ---------------------------------------------------------------------------
 // text metrics
 // ---------------------------------------------------------------------------
 
-wxCoord wxDC::GetCharHeight() const
+wxCoord wxPMDCImpl::GetCharHeight() const
 {
     FONTMETRICS                     vFM; // metrics structure
 
@@ -1444,7 +2118,7 @@ wxCoord wxDC::GetCharHeight() const
     return YDEV2LOGREL(vFM.lXHeight);
 }
 
-wxCoord wxDC::GetCharWidth() const
+wxCoord wxPMDCImpl::GetCharWidth() const
 {
     FONTMETRICS                     vFM; // metrics structure
 
@@ -1455,13 +2129,13 @@ wxCoord wxDC::GetCharWidth() const
     return XDEV2LOGREL(vFM.lAveCharWidth);
 }
 
-void wxDC::DoGetTextExtent(
+void wxPMDCImpl::DoGetTextExtent(
   const wxString&                   rsString
 , wxCoord*                          pvX
 , wxCoord*                          pvY
 , wxCoord*                          pvDescent
 , wxCoord*                          pvExternalLeading
-, wxFont*                           pTheFont
+, const wxFont*                     pTheFont
 ) const
 {
     POINTL                          avPoint[TXTBOX_COUNT];
@@ -1471,24 +2145,30 @@ void wxDC::DoGetTextExtent(
     int                             l;
     FONTMETRICS                     vFM; // metrics structure
     BOOL                            bRc;
-    char*                           pStr;
     ERRORID                         vErrorCode; // last error id code
     wxFont*                         pFontToUse = (wxFont*)pTheFont;
 
-    char                            zMsg[128]; // DEBUG
+    wxChar                          zMsg[128]; // DEBUG
     wxString                        sError;
 
     if (!pFontToUse)
         pFontToUse = (wxFont*)&m_font;
     l = rsString.length();
-    pStr = (PCH) rsString.c_str();
 
     //
     // In world coordinates.
     //
+    if (!m_hPS)
+    {
+    (void)wxMessageBox( wxT("wxWidgets core library")
+                ,"Using uninitialized DC for measuring text!\n"
+                ,wxICON_INFORMATION
+                );
+    }
+
     bRc = ::GpiQueryTextBox( m_hPS
                             ,l
-                            ,pStr
+                            ,rsString.char_str()
                             ,TXTBOX_COUNT // return maximum information
                             ,avPoint      // array of coordinates points
                            );
@@ -1497,8 +2177,8 @@ void wxDC::DoGetTextExtent(
        vErrorCode = ::WinGetLastError(wxGetInstance());
        sError = wxPMErrorToStr(vErrorCode);
        // DEBUG
-       sprintf(zMsg, "GpiQueryTextBox for %s: failed with Error: %x - %s", pStr, vErrorCode, sError.c_str());
-       (void)wxMessageBox( "wxWindows Menu sample"
+       wxSprintf(zMsg, wxT("GpiQueryTextBox for %s: failed with Error: %lx - %s"), rsString.c_str(), vErrorCode, sError.c_str());
+       (void)wxMessageBox( wxT("wxWidgets core library")
                           ,zMsg
                           ,wxICON_INFORMATION
                          );
@@ -1530,21 +2210,21 @@ void wxDC::DoGetTextExtent(
         *pvExternalLeading = vFM.lExternalLeading;
 }
 
-void wxDC::SetMapMode(
-  int                               nMode
+void wxPMDCImpl::SetMapMode(
+  wxMappingMode                     nMode
 )
 {
     int                             nPixelWidth = 0;
     int                             nPixelHeight = 0;
     int                             nMmWidth = 1;
     int                             nMmHeight = 1;
-    LONG                            lArray[CAPS_VERTICAL_RESOLUTION];
+    LONG                            lArray[CAPS_VERTICAL_RESOLUTION+1];
 
     m_mappingMode = nMode;
 
     if(::DevQueryCaps( m_hDC
-                      ,CAPS_FAMILY
-                      ,CAPS_VERTICAL_RESOLUTION
+                      ,CAPS_FAMILY                  // id of first item
+                      ,CAPS_VERTICAL_RESOLUTION+1   // number of items wanted
                       ,lArray
                      ))
     {
@@ -1556,15 +2236,15 @@ void wxDC::SetMapMode(
         lHorzRes  = lArray[CAPS_HORIZONTAL_RESOLUTION]; // returns pel/meter
         lVertRes  = lArray[CAPS_VERTICAL_RESOLUTION];   // returns pel/meter
         nMmWidth  = (lHorzRes/1000) * nPixelWidth;
-        nMmWidth = (lVertRes/1000) * nPixelHeight;
+        nMmHeight = (lVertRes/1000) * nPixelHeight;
     }
     if ((nPixelWidth == 0) || (nPixelHeight == 0) || (nMmWidth == 0) || (nMmHeight == 0))
     {
         return;
     }
 
-    double                          dMm2pixelsX = nPixelWidth/nMmWidth;
-    double                          dMm2pixelsY = nPixelHeight/nMmHeight;
+    double dMm2pixelsX = nPixelWidth/(double)nMmWidth;
+    double dMm2pixelsY = nPixelHeight/(double)nMmHeight;
 
     switch (nMode)
     {
@@ -1594,6 +2274,7 @@ void wxDC::SetMapMode(
             m_logicalScaleY = 1.0;
             break;
     }
+
     SIZEL                           vSize;
     ULONG                           ulOptions;
 
@@ -1603,45 +2284,29 @@ void wxDC::SetMapMode(
         ulOptions = PU_ARBITRARY | GPIF_DEFAULT;
         ::GpiSetPS(m_hPS, &vSize, ulOptions);
     }
-    m_nWindowExtX = (int)MS_XDEV2LOGREL(VIEWPORT_EXTENT);
-    m_nWindowExtY = (int)MS_YDEV2LOGREL(VIEWPORT_EXTENT);
-    // ????
-}; // end of wxDC::SetMapMode
+    ComputeScaleAndOrigin();
 
-void wxDC::SetUserScale(
-  double                            dX
-, double                            dY
-)
+}; // end of wxPMDCImpl::SetMapMode
+
+void wxPMDCImpl::SetUserScale( double dX,
+                         double dY )
 {
     m_userScaleX = dX;
     m_userScaleY = dY;
 
     SetMapMode(m_mappingMode);
-} // end of wxDC::SetUserScale
+} // end of wxPMDCImpl::SetUserScale
 
-void wxDC::SetAxisOrientation(
-  bool                              bXLeftRight
-, bool                              bYBottomUp
-)
+void wxPMDCImpl::SetAxisOrientation( bool bXLeftRight,
+                               bool bYBottomUp )
 {
     m_signX = bXLeftRight ? 1 : -1;
     m_signY = bYBottomUp ? -1 : 1;
 
     SetMapMode(m_mappingMode);
-} // end of wxDC::SetAxisOrientation
-
-void wxDC::SetSystemScale(
-  double                            dX
-, double                            dY
-)
-{
-    m_scaleX = dX;
-    m_scaleY = dY;
+} // end of wxPMDCImpl::SetAxisOrientation
 
-    SetMapMode(m_mappingMode);
-} // end of wxDC::SetSystemScale
-
-void wxDC::SetLogicalOrigin(
+void wxPMDCImpl::SetLogicalOrigin(
   wxCoord                           vX
 , wxCoord                           vY
 )
@@ -1658,9 +2323,9 @@ void wxDC::SetLogicalOrigin(
     ::GpiSetPageViewport( m_hPS
                          ,&vRect
                         );
-}; // end of wxDC::SetLogicalOrigin
+}; // end of wxPMDCImpl::SetLogicalOrigin
 
-void wxDC::SetDeviceOrigin(
+void wxPMDCImpl::SetDeviceOrigin(
   wxCoord                           vX
 , wxCoord                           vY
 )
@@ -1679,81 +2344,46 @@ void wxDC::SetDeviceOrigin(
     ::GpiSetPageViewport( m_hPS
                          ,&vRect
                         );
-}; // end of wxDC::SetDeviceOrigin
-
-// ---------------------------------------------------------------------------
-// coordinates transformations
-// ---------------------------------------------------------------------------
-
-wxCoord wxDCBase::DeviceToLogicalX(wxCoord x) const
-{
-    return (wxCoord) (((x) - m_deviceOriginX)/(m_logicalScaleX*m_userScaleX*m_signX*m_scaleX) - m_logicalOriginX);
-}
-
-wxCoord wxDCBase::DeviceToLogicalXRel(wxCoord x) const
-{
-    return (wxCoord) ((x)/(m_logicalScaleX*m_userScaleX*m_signX*m_scaleX));
-}
-
-wxCoord wxDCBase::DeviceToLogicalY(wxCoord y) const
-{
-    return (wxCoord) (((y) - m_deviceOriginY)/(m_logicalScaleY*m_userScaleY*m_signY*m_scaleY) - m_logicalOriginY);
-}
-
-wxCoord wxDCBase::DeviceToLogicalYRel(wxCoord y) const
-{
-    return (wxCoord) ((y)/(m_logicalScaleY*m_userScaleY*m_signY*m_scaleY));
-}
-
-wxCoord wxDCBase::LogicalToDeviceX(wxCoord x) const
-{
-    return (wxCoord) ((x - m_logicalOriginX)*m_logicalScaleX*m_userScaleX*m_signX*m_scaleX + m_deviceOriginX);
-}
-
-wxCoord wxDCBase::LogicalToDeviceXRel(wxCoord x) const
-{
-    return (wxCoord) (x*m_logicalScaleX*m_userScaleX*m_signX*m_scaleX);
-}
-
-wxCoord wxDCBase::LogicalToDeviceY(wxCoord y) const
-{
-    return (wxCoord) ((y - m_logicalOriginY)*m_logicalScaleY*m_userScaleY*m_signY*m_scaleY + m_deviceOriginY);
-}
-
-wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const
-{
-    return (wxCoord) (y*m_logicalScaleY*m_userScaleY*m_signY*m_scaleY);
-}
+}; // end of wxPMDCImpl::SetDeviceOrigin
 
 // ---------------------------------------------------------------------------
 // bit blit
 // ---------------------------------------------------------------------------
 
-bool wxDC::DoBlit(
-  wxCoord                           vXdest
-, wxCoord                           vYdest
-, wxCoord                           vWidth
-, wxCoord                           vHeight
-, wxDC*                             pSource
-, wxCoord                           vXsrc
-, wxCoord                           vYsrc
-, int                               nRop
-, bool                              bUseMask
-)
+bool wxPMDCImpl::DoBlit( wxCoord vXdest,
+                   wxCoord vYdest,
+                   wxCoord vWidth,
+                   wxCoord vHeight,
+                   wxDC*   pSource,
+                   wxCoord vXsrc,
+                   wxCoord vYsrc,
+                   wxRasterOperationMode     nRop,
+                   bool    bUseMask,
+                   wxCoord WXUNUSED(vXsrcMask),
+                   wxCoord WXUNUSED(vYsrcMask) )
 {
     wxMask*                         pMask = NULL;
     CHARBUNDLE                      vCbnd;
     COLORREF                        vOldTextColor;
     COLORREF                        vOldBackground = ::GpiQueryBackColor(m_hPS);
 
+    wxDCImpl *impl = pSource->GetImpl();
+    wxPMDCImpl *pm_impl = wxDynamicCast( impl, wxPMDCImpl );
+    if (!pm_impl)
+    {
+        // TODO: Do we want to be able to blit
+        //       from other DCs too?
+        return false;
+    }
+
     if (bUseMask)
     {
-        const wxBitmap&             rBmp = pSource->m_vSelectedBitmap;
+        const wxBitmap&             rBmp = pm_impl->GetSelectedBitmap();
 
         pMask = rBmp.GetMask();
         if (!(rBmp.Ok() && pMask && pMask->GetMaskBitmap()))
         {
-            bUseMask = FALSE;
+            bUseMask = false;
         }
     }
 
@@ -1801,7 +2431,7 @@ bool wxDC::DoBlit(
         case wxNOR:          lRop = ROP_NOTSRCCOPY;       break;
         default:
            wxFAIL_MSG( wxT("unsupported logical function") );
-           return FALSE;
+           return false;
     }
 
     bool                            bSuccess;
@@ -1821,14 +2451,10 @@ bool wxDC::DoBlit(
         HPS                             hPSBuffer;
         DEVOPENSTRUC                    vDOP = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
         BITMAPINFOHEADER2               vBmpHdr;
+        HBITMAP                         hBufBitmap;
         SIZEL                           vSize = {0, 0};
         LONG                            rc;
 
-        hDCMask = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDOP, NULLHANDLE);
-        hDCBuffer = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDOP, NULLHANDLE);
-        hPSMask = ::GpiCreatePS(vHabmain, hDCMask, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
-        hPSBuffer = ::GpiCreatePS(vHabmain, hDCBuffer, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
-
         memset(&vBmpHdr, 0, sizeof(BITMAPINFOHEADER2));
         vBmpHdr.cbFix     = sizeof(BITMAPINFOHEADER2);
         vBmpHdr.cx        = vWidth;
@@ -1836,26 +2462,56 @@ bool wxDC::DoBlit(
         vBmpHdr.cPlanes   = 1;
         vBmpHdr.cBitCount = 24;
 
-        HBITMAP                         hBufBitmap = ::GpiCreateBitmap(GetHPS(), &vBmpHdr, 0L, NULL, NULL);
-        POINTL                          aPoint1[4] = { 0, 0
-                                                      ,vWidth, vHeight
-                                                      ,vXdest, vYdest
-                                                      ,vXdest + vWidth, vYdest + vHeight
+#if wxUSE_DC_CACHEING
+        {
+            //
+            // create a temp buffer bitmap and DCs to access it and the mask
+            //
+            wxDCCacheEntry*         pDCCacheEntry1    = FindDCInCache( NULL
+                                                                      ,pm_impl->GetHPS()
+                                                                     );
+            wxDCCacheEntry*         pDCCacheEntry2    = FindDCInCache( pDCCacheEntry1
+                                                                      ,GetHPS()
+                                                                     );
+            wxDCCacheEntry*         pBitmapCacheEntry = FindBitmapInCache( GetHPS()
+                                                                          ,vWidth
+                                                                          ,vHeight
+                                                                         );
+
+            hPSMask = pDCCacheEntry1->m_hPS;
+            hDCBuffer = (HDC)pDCCacheEntry2->m_hPS;
+            hBufBitmap = (HBITMAP)pBitmapCacheEntry->m_hBitmap;
+            wxUnusedVar(hDCMask);
+        }
+#else
+        {
+            hDCMask = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDOP, NULLHANDLE);
+            hDCBuffer = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDOP, NULLHANDLE);
+            hPSMask = ::GpiCreatePS(vHabmain, hDCMask, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
+            hPSBuffer = ::GpiCreatePS(vHabmain, hDCBuffer, &vSize, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
+            hBufBitmap = ::GpiCreateBitmap(GetHPS(), &vBmpHdr, 0L, NULL, NULL);
+        }
+#endif
+
+        POINTL                          aPoint1[4] = { {0, 0}
+                              ,{vWidth, vHeight}
+                              ,{vXdest, vYdest}
+                              ,{vXdest + vWidth, vYdest + vHeight}
                                                      };
-        POINTL                          aPoint2[4] = { 0, 0
-                                                      ,vWidth, vHeight
-                                                      ,vXsrc, vYsrc
-                                                      ,vXsrc + vWidth, vYsrc + vHeight
+        POINTL                          aPoint2[4] = { {0, 0}
+                              ,{vWidth, vHeight}
+                              ,{vXsrc, vYsrc}
+                              ,{vXsrc + vWidth, vYsrc + vHeight}
                                                      };
-        POINTL                          aPoint3[4] = { vXdest, vYdest
-                                                      ,vXdest + vWidth, vYdest + vHeight
-                                                      ,vXsrc, vYsrc
-                                                      ,vXsrc + vWidth, vYsrc + vHeight
+        POINTL                          aPoint3[4] = { {vXdest, vYdest}
+                              ,{vXdest + vWidth, vYdest + vHeight}
+                              ,{vXsrc, vYsrc}
+                              ,{vXsrc + vWidth, vYsrc + vHeight}
                                                      };
-        POINTL                          aPoint4[4] = { vXdest, vYdest
-                                                      ,vXdest + vWidth, vYdest + vHeight
-                                                      ,0, 0
-                                                      ,vWidth, vHeight
+        POINTL                          aPoint4[4] = { {vXdest, vYdest}
+                              ,{vXdest + vWidth, vYdest + vHeight}
+                              ,{0, 0}
+                              ,{vWidth, vHeight}
                                                      };
         ::GpiSetBitmap(hPSMask, (HBITMAP) pMask->GetMaskBitmap());
         ::GpiSetBitmap(hPSBuffer, (HBITMAP) hBufBitmap);
@@ -1946,7 +2602,7 @@ bool wxDC::DoBlit(
                         );
         if (rc == GPI_ERROR)
         {
-            bSuccess = FALSE;
+            bSuccess = false;
             wxLogLastError(wxT("BitBlt"));
         }
 
@@ -1955,23 +2611,25 @@ bool wxDC::DoBlit(
         //
         ::GpiSetBitmap(hPSMask, NULLHANDLE);
         ::GpiSetBitmap(hPSBuffer, NULLHANDLE);
+#if !wxUSE_DC_CACHEING
         ::GpiDestroyPS(hPSMask);
         ::GpiDestroyPS(hPSBuffer);
         ::DevCloseDC(hDCMask);
         ::DevCloseDC(hDCBuffer);
         ::GpiDeleteBitmap(hBufBitmap);
-        bSuccess = TRUE;
+#endif
+        bSuccess = true;
     }
     else // no mask, just BitBlt() it
     {
-        POINTL                          aPoint[4] = { vXdest, vYdest
-                                                     ,vXdest + vWidth, vYdest + vHeight
-                                                     ,vXsrc, vYsrc
-                                                     ,vXsrc + vWidth, vYsrc + vHeight
+      POINTL                          aPoint[4] = { {vXdest, vYdest}
+                           ,{vXdest + vWidth, vYdest + vHeight}
+                           ,{vXsrc, vYsrc}
+                           ,{vXsrc + vWidth, vYsrc + vHeight}
                                                     };
 
         bSuccess = (::GpiBitBlt( m_hPS
-                                ,pSource->GetHPS()
+                                ,pm_impl->GetHPS()
                                 ,4L
                                 ,aPoint
                                 ,lRop
@@ -1993,60 +2651,62 @@ bool wxDC::DoBlit(
     return bSuccess;
 }
 
-void wxDC::DoGetSize(
-  int*                              pnWidth
-, int*                              pnHeight
-) const
+void wxPMDCImpl::DoGetSize( int* pnWidth,
+                            int* pnHeight ) const
 {
-    LONG                            lArray[CAPS_HEIGHT];
+    LONG lArray[CAPS_HEIGHT+1];
 
     if(::DevQueryCaps( m_hDC
                       ,CAPS_FAMILY
-                      ,CAPS_HEIGHT
+                      ,CAPS_HEIGHT+1
                       ,lArray
                      ))
     {
-        *pnWidth  = lArray[CAPS_WIDTH];
-        *pnHeight = lArray[CAPS_HEIGHT];
+        if (pnWidth)
+            *pnWidth  = lArray[CAPS_WIDTH];
+        if (pnHeight)
+            *pnHeight = lArray[CAPS_HEIGHT];
     }
-}; // end of wxDC::DoGetSize(
+}; // end of wxPMDCImpl::DoGetSize(
 
-void wxDC::DoGetSizeMM(
-  int*                              pnWidth
-, int*                              pnHeight
-) const
+void wxPMDCImpl::DoGetSizeMM( int* pnWidth,
+                        int* pnHeight ) const
 {
-    LONG                            lArray[CAPS_VERTICAL_RESOLUTION];
+    LONG                            lArray[CAPS_VERTICAL_RESOLUTION+1];
 
     if(::DevQueryCaps( m_hDC
                       ,CAPS_FAMILY
-                      ,CAPS_VERTICAL_RESOLUTION
+                      ,CAPS_VERTICAL_RESOLUTION+1
                       ,lArray
                      ))
     {
-        int                         nWidth;
-        int                         nHeight;
-        int                         nHorzRes;
-        int                         nVertRes;
+        if(pnWidth)
+        {
+            int nWidth   = lArray[CAPS_WIDTH];
+            int nHorzRes = lArray[CAPS_HORIZONTAL_RESOLUTION]; // returns pel/meter
+            // use fp to avoid returning 0 if nHorzRes < 1000
+            *pnWidth  = (int)((nHorzRes/1000.0) * nWidth);
+        }
 
-        nWidth    = lArray[CAPS_WIDTH];
-        nHeight   = lArray[CAPS_HEIGHT];
-        nHorzRes  = lArray[CAPS_HORIZONTAL_RESOLUTION]; // returns pel/meter
-        nVertRes  = lArray[CAPS_VERTICAL_RESOLUTION];   // returns pel/meter
-        nWidth  = (nHorzRes/1000) * nWidth;
-        nHeight = (nVertRes/1000) * nHeight;
+        if(pnHeight)
+        {
+            int nHeight  = lArray[CAPS_HEIGHT];
+            int nVertRes = lArray[CAPS_VERTICAL_RESOLUTION];   // returns pel/meter
+            // use fp to avoid returning 0 if nVertRes < 1000
+            *pnHeight = (int)((nVertRes/1000.0) * nHeight);
+        }
     }
-}; // end of wxDC::DoGetSizeMM
+}; // end of wxPMDCImpl::DoGetSizeMM
 
-wxSize wxDC::GetPPI() const
+wxSize wxPMDCImpl::GetPPI() const
 {
-    LONG                            lArray[CAPS_VERTICAL_RESOLUTION];
-    int                             nWidth;
-    int                             nHeight;
+    LONG                            lArray[CAPS_VERTICAL_RESOLUTION+1];
+    int                             nWidth = 0;
+    int                             nHeight = 0;
 
     if(::DevQueryCaps( m_hDC
                       ,CAPS_FAMILY
-                      ,CAPS_VERTICAL_RESOLUTION
+                      ,CAPS_VERTICAL_RESOLUTION+1
                       ,lArray
                      ))
     {
@@ -2059,33 +2719,15 @@ wxSize wxDC::GetPPI() const
         nPelHeight = lArray[CAPS_HEIGHT];
         nHorzRes   = lArray[CAPS_HORIZONTAL_RESOLUTION]; // returns pel/meter
         nVertRes   = lArray[CAPS_VERTICAL_RESOLUTION];   // returns pel/meter
-        nWidth   = (nHorzRes/39.3) * nPelWidth;
-        nHeight  = (nVertRes/39.3) * nPelHeight;
+        nWidth   = (int)((nHorzRes/39.3) * nPelWidth);
+        nHeight  = (int)((nVertRes/39.3) * nPelHeight);
     }
-    return (wxSize(nWidth,nHeight));
-} // end of wxDC::GetPPI
+    wxSize ppisize(nWidth, nHeight);
+    return ppisize;
+} // end of wxPMDCImpl::GetPPI
 
-void wxDC::SetLogicalScale(
-  double                            dX
-, double                            dY
-)
+void wxPMDCImpl::SetLogicalScale( double dX, double dY )
 {
     m_logicalScaleX = dX;
     m_logicalScaleY = dY;
-}; // end of wxDC::SetLogicalScale
-
-#if WXWIN_COMPATIBILITY
-void wxDC::DoGetTextExtent(const wxString& string, float *x, float *y,
-                         float *descent, float *externalLeading,
-                         wxFont *theFont, bool use16bit) const
-{
-    wxCoord x1, y1, descent1, externalLeading1;
-    GetTextExtent(string, & x1, & y1, & descent1, & externalLeading1, theFont, use16bit);
-    *x = x1; *y = y1;
-    if (descent)
-        *descent = descent1;
-    if (externalLeading)
-        *externalLeading = externalLeading1;
-}
-#endif
-
+}; // end of wxPMDCImpl::SetLogicalScale