+     POINTL                         vPtlPos;
+     POINTL                         vPtlArc[2]; // Structure for current position
+     double                         dRadius;
+     double                         dAngl1;
+     double                         dAngl2;
+     double                         dAnglmid;
+     wxCoord                        vXm;
+     wxCoord                        vYm;
+     ARCPARAMS                      vArcp; // Structure for arc parameters
+
+    if((vX1 == vXc && vY1 == vXc) || (vX2 == vXc && vY2 == vXc))
+        return; // Draw point ??
+    dRadius = 0.5 * ( hypot( (double)(vY1 - vYc)
+                            ,(double)(vX1 - vXc)
+                           ) +
+                      hypot( (double)(vY2 - vYc)
+                            ,(double)(vX2 - vXc)
+                           )
+                     );
+
+    dAngl1 = atan2( (double)(vY1 - vYc)
+                   ,(double)(vX1 - vXc)
+                  );
+    dAngl2 = atan2( (double)(vY2 - vYc)
+                   ,(double)(vX2 - vXc)
+                  );
+    if(dAngl2 < dAngl1)
+        dAngl2 += M_PI * 2;
+
+    //
+    // GpiPointArc can't draw full arc
+    //
+     if(dAngl2 == dAngl1 || (vX1 == vX2 && vY1 == vY2) )
+     {
+        //
+        // Medium point
+        //
+        dAnglmid = (dAngl1 + dAngl2)/2. + M_PI;
+        vXm      = (wxCoord)(vXc + dRadius * cos(dAnglmid));
+        vYm      = (wxCoord)(vYc + dRadius * sin(dAnglmid));
+        DoDrawArc( vX1, vY1
+                  ,vXm, vYm
+                  ,vXc, vYc
+                 );
+        DoDrawArc( vXm, vYm
+                  ,vX2, vY2
+                  ,vXc, vYc
+                 );
+        return;
+    }
+
+    //
+    // Medium point
+    //
+    dAnglmid = (dAngl1 + dAngl2)/2.;
+    vXm      = (wxCoord)(vXc + dRadius * cos(dAnglmid));
+    vYm      = (wxCoord)(vYc + dRadius * sin(dAnglmid));
+
+    //
+    // Ellipse main axis (r,q), (p,s) with center at (0,0) */
+    //
+    vArcp.lR = 0;
+    vArcp.lQ = 1;
+    vArcp.lP = 1;
+    vArcp.lS = 0;
+    ::GpiSetArcParams(m_hPS, &vArcp); // Sets parameters to default
+
+    vPtlPos.x = vX1; // Loads x-coordinate
+    vPtlPos.y = vY1; // Loads y-coordinate
+    ::GpiMove(m_hPS, &vPtlPos); // Sets current position
+    vPtlArc[0].x = vXm;
+    vPtlArc[0].y = vYm;
+    vPtlArc[1].x = vX2;
+    vPtlArc[1].y = vY2;
+    ::GpiPointArc(m_hPS, vPtlArc); // Draws the arc
+    CalcBoundingBox( (wxCoord)(vXc - dRadius)
+                    ,(wxCoord)(vYc - dRadius)
+                   );
+    CalcBoundingBox( (wxCoord)(vXc + dRadius)
+                    ,(wxCoord)(vYc + dRadius)
+                   );
+} // end of wxPMDCImpl::DoDrawArc
+
+void wxPMDCImpl::DoDrawCheckMark(
+  wxCoord                           vX1
+, wxCoord                           vY1
+, wxCoord                           vWidth
+, wxCoord                           vHeight
+)
+{
+    POINTL                          vPoint[2];
+
+    vY1 = OS2Y(vY1,vHeight);
+
+    vPoint[0].x = vX1;
+    vPoint[0].y = vY1;
+    vPoint[1].x = vX1 + vWidth;
+    vPoint[1].y = vY1 + vHeight;
+
+    ::GpiMove(m_hPS, &vPoint[0]);
+    ::GpiBox( m_hPS       // handle to a presentation space
+             ,DRO_OUTLINE // draw the box outline ? or ?
+             ,&vPoint[1]  // address of the corner
+             ,0L          // horizontal corner radius
+             ,0L          // vertical corner radius
+            );
+    if(vWidth > 4 && vHeight > 4)
+    {
+        int                         nTmp;
+
+        vPoint[0].x += 2; vPoint[0].y += 2;
+        vPoint[1].x -= 2; vPoint[1].y -= 2;
+        ::GpiMove(m_hPS, &vPoint[0]);
+        ::GpiLine(m_hPS, &vPoint[1]);
+        nTmp = vPoint[0].x;
+        vPoint[0].x = vPoint[1].x;
+        vPoint[1].x = nTmp;
+        ::GpiMove(m_hPS, &vPoint[0]);
+        ::GpiLine(m_hPS, &vPoint[1]);
+    }
+    CalcBoundingBox( vX1
+                    ,vY1
+                   );
+
+    wxCoord                         vX2 = vX1 + vWidth;
+    wxCoord                         vY2 = vY1 + vHeight;
+
+    CalcBoundingBox( vX2
+                    ,vY2
+                   );
+} // end of wxPMDCImpl::DoDrawCheckMark
+
+void wxPMDCImpl::DoDrawPoint(
+  wxCoord                           vX
+, wxCoord                           vY
+)
+{
+    POINTL                          vPoint;
+    COLORREF                        vColor = 0x00ffffff;
+
+    if (m_pen.Ok())
+    {
+        vColor = m_pen.GetColour().GetPixel();
+    }
+    ::GpiSetColor(m_hPS, vColor);
+    vPoint.x = vX;
+    vPoint.y = OS2Y(vY,0);
+    ::GpiSetPel(m_hPS, &vPoint);
+    CalcBoundingBox( vX
+                    ,vY
+                   );
+} // end of wxPMDCImpl::DoDrawPoint
+
+void wxPMDCImpl::DoDrawPolygon( int n,
+                          wxPoint vPoints[],
+                          wxCoord vXoffset,
+                          wxCoord vYoffset,
+                          int 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 = 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();
+    if(m_brush.GetStyle() == wxTRANSPARENT)
+        nIsTRANSPARENT = 1;
+
+    vPlgn.ulPoints = n;
+    vPlgn.aPointl = (POINTL*) calloc( n + 1
+                                     ,sizeof(POINTL)
+                                    ); // well, new will call malloc
+
+    for(i = 0; i < n; i++)
+    {
+        vPlgn.aPointl[i].x = vPoints[i].x+vXoffset;
+        vPlgn.aPointl[i].y = OS2Y(vPoints[i].y+vYoffset,0);
+    }
+    flOptions = POLYGON_BOUNDARY;
+    if(nFillStyle == wxWINDING_RULE)
+        flOptions |= POLYGON_WINDING;
+    else
+        flOptions |= POLYGON_ALTERNATE;
+
+    ::GpiSetColor(m_hPS, lBorderColor);
+    ::GpiMove(m_hPS, &vPlgn.aPointl[0]);
+    lHits = ::GpiPolygons(m_hPS, ulCount, &vPlgn, flOptions, flModel);
+    free(vPlgn.aPointl);
+} // end of wxPMDCImpl::DoDrawPolygon
+
+void wxPMDCImpl::DoDrawLines(
+  int                               n
+, wxPoint                           vPoints[]
+, wxCoord                           vXoffset
+, wxCoord                           vYoffset
+)
+{
+    POINTL                          vPoint;
+
+    if (vXoffset != 0L || vXoffset != 0L)
+    {
+        int                             i;
+
+        vPoint.x = vPoints[0].x + vXoffset;
+        vPoint.y = OS2Y(vPoints[0].y + vYoffset,0);
+        ::GpiMove(m_hPS, &vPoint);
+
+        LONG                            lBorderColor = m_pen.GetColour().GetPixel();
+
+        ::GpiSetColor(m_hPS, lBorderColor);
+        for(i = 1; i < n; i++)
+        {
+            vPoint.x = vPoints[i].x + vXoffset;
+            vPoint.y = OS2Y(vPoints[i].y + vYoffset,0);
+            ::GpiLine(m_hPS, &vPoint);
+        }
+    }
+    else
+    {
+        int                         i;
+
+        CalcBoundingBox( vPoints[0].x
+                        ,vPoints[0].y
+                       );
+        vPoint.x = vPoints[0].x;
+        vPoint.y = OS2Y(vPoints[0].y,0);
+        ::GpiMove(m_hPS, &vPoint);
+
+        for (i = 0; i < n; i++)
+        {
+            CalcBoundingBox( vPoints[i].x
+                            ,vPoints[i].y
+                           );
+            vPoint.x = vPoints[i].x;
+            vPoint.y = OS2Y(vPoints[i].y,0);
+            ::GpiLine(m_hPS, &vPoint);
+        }
+    }
+} // end of wxPMDCImpl::DoDrawLines
+
+void wxPMDCImpl::DoDrawRectangle(
+  wxCoord                           vX
+, wxCoord                           vY
+, wxCoord                           vWidth
+, wxCoord                           vHeight
+)
+{
+    POINTL                          vPoint[2];
+    LONG                            lControl;
+    LONG                            lColor;
+    LONG                            lBorderColor;
+    int                             nIsTRANSPARENT = 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))
+        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 - 1;
+    vPoint[1].y = vY + vHeight - 1;
+    ::GpiMove(m_hPS, &vPoint[0]);
+    lColor       = m_brush.GetColour().GetPixel();
+    lBorderColor = m_pen.GetColour().GetPixel();
+    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, lBorderColor);
+        ::GpiBox( m_hPS       // handle to a presentation space
+                 ,lControl   // draw the box outline ? or ?
+                 ,&vPoint[1]  // address of the corner
+                 ,0L          // horizontal corner radius
+                 ,0L          // vertical corner radius
+                );
+    }
+    else
+    {
+        lControl = DRO_OUTLINE;
+        ::GpiSetColor( m_hPS
+                      ,lBorderColor
+                     );
+        ::GpiBox( m_hPS
+                 ,lControl
+                 ,&vPoint[1]
+                 ,0L
+                 ,0L
+                );
+        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]
+                 ,0L
+                 ,0L
+                );
+    }
+    CalcBoundingBox(vX, vY);
+    CalcBoundingBox(vX2, vY2);
+} // end of wxPMDCImpl::DoDrawRectangle
+
+void wxPMDCImpl::DoDrawRoundedRectangle(
+  wxCoord                           vX
+, wxCoord                           vY
+, wxCoord                           vWidth
+, wxCoord                           vHeight
+, double                            dRadius
+)
+{
+    POINTL                          vPoint[2];
+    LONG                            lControl;
+    LONG                            lColor;
+    LONG                            lBorderColor;
+    int                             nIsTRANSPARENT = 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))
+        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 - 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;
+        ::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 wxPMDCImpl::DoDrawRoundedRectangle
+
+// Draw Ellipse within box (x,y) - (x+width, y+height)
+void wxPMDCImpl::DoDrawEllipse(
+  wxCoord                           vX
+, wxCoord                           vY
+, wxCoord                           vWidth
+, wxCoord                           vHeight
+)
+{
+    POINTL                          vPtlPos; // Structure for current position
+    FIXED                           vFxMult; // Multiplier for ellipse
+    ARCPARAMS                       vArcp;   // Structure for arc parameters
+
+    vY = OS2Y(vY,vHeight);
+
+    vArcp.lR = 0;
+    vArcp.lQ = vHeight/2;
+    vArcp.lP = vWidth/2;
+    vArcp.lS = 0;
+    ::GpiSetArcParams( m_hPS
+                      ,&vArcp
+                     ); // Sets parameters to default
+    vPtlPos.x = vX + vWidth/2;  // Loads x-coordinate
+    vPtlPos.y = vY + vHeight/2; // Loads y-coordinate
+    ::GpiMove( m_hPS
+              ,&vPtlPos
+             ); // Sets current position
+    vFxMult = MAKEFIXED(1, 0);             /* Sets multiplier            */
+
+    //
+    // DRO_FILL, DRO_OTLINEFILL - where to get
+    //
+    ::GpiFullArc( m_hPS
+                 ,DRO_OUTLINE
+                 ,vFxMult
+                ); // Draws full arc with center at current position
+
+    wxCoord                         vX2 = (vX + vWidth);
+    wxCoord                         vY2 = (vY + vHeight);
+
+    CalcBoundingBox(vX, vY);
+    CalcBoundingBox(vX2, vY2);
+} // end of wxPMDCImpl::DoDrawEllipse
+
+void wxPMDCImpl::DoDrawEllipticArc(
+  wxCoord                           vX
+, wxCoord                           vY
+, wxCoord                           vWidth
+, wxCoord                           vHeight
+, double                            dSa
+, double                            dEa
+)
+{
+    POINTL                          vPtlPos; // Structure for current position
+    FIXED                           vFxMult; // Multiplier for ellipse
+    ARCPARAMS                       vArcp;   // Structure for arc parameters
+    FIXED                           vFSa;
+    FIXED                           vFSweepa; // Start angle, sweep angle
+    double                          dIntPart;
+    double                          dFractPart;
+
+    vY = OS2Y(vY,vHeight);
+
+    dFractPart = modf(dSa,&dIntPart);
+    vFSa = MAKEFIXED((int)dIntPart, (int)(dFractPart * 0xffff) );
+    dFractPart = modf(dEa - dSa, &dIntPart);
+    vFSweepa = MAKEFIXED((int)dIntPart, (int)(dFractPart * 0xffff) );
+
+    //
+    // Ellipse main axis (r,q), (p,s) with center at (0,0)
+    //
+    vArcp.lR = 0;
+    vArcp.lQ = vHeight/2;
+    vArcp.lP = vWidth/2;
+    vArcp.lS = 0;
+    ::GpiSetArcParams(m_hPS, &vArcp); // Sets parameters to default
+    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
+
+    //
+    // May be not to the center ?
+    //
+    vPtlPos.x = vX + vWidth/2 ; // Loads x-coordinate
+    vPtlPos.y = vY + vHeight/2; // Loads y-coordinate
+    vFxMult = MAKEFIXED(1, 0);  // Sets multiplier
+
+    //
+    // DRO_FILL, DRO_OTLINEFILL - where to get
+    //
+    ::GpiPartialArc( m_hPS
+                    ,&vPtlPos
+                    ,vFxMult
+                    ,vFSa
+                    ,vFSweepa
+                   );
+    wxCoord                         vX2 = (vX + vWidth);
+    wxCoord                         vY2 = (vY + vHeight);
+
+    CalcBoundingBox(vX, vY);
+    CalcBoundingBox(vX2, vY2);
+} // end of wxPMDCImpl::DoDrawEllipticArc
+
+void wxPMDCImpl::DoDrawIcon(
+  const wxIcon&                     rIcon
+, wxCoord                           vX
+, wxCoord                           vY
+)
+{
+    //
+    // 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);
+
+        DoDrawBitmap(vBitmap, vX, vY, false);
+    }
+    CalcBoundingBox(vX, vY);
+    CalcBoundingBox(vX + rIcon.GetWidth(), vY + rIcon.GetHeight());
+} // end of wxPMDCImpl::DoDrawIcon
+
+void wxPMDCImpl::DoDrawBitmap(
+  const wxBitmap&                   rBmp
+, wxCoord                           vX
+, wxCoord                           vY
+, bool                              bUseMask
+)
+{
+#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();
+
+            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;
+
+                //
+                // 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
+)
+{
+    wxCoord                         vWidth;
+    wxCoord                         vHeight;
+
+    DrawAnyText( rsText
+                ,vX
+                ,vY
+               );
+
+    CalcBoundingBox(vX, vY);
+    GetOwner()->GetTextExtent(rsText, &vWidth, &vHeight);
+    CalcBoundingBox((vX + vWidth), (vY + vHeight));
+} // end of wxPMDCImpl::DoDrawText
+
+void wxPMDCImpl::DrawAnyText( const wxString& rsText,
+                        wxCoord vX,
+                        wxCoord vY )
+{
+    int                             nOldBackground = 0;
+    POINTL                          vPtlStart;
+    LONG                            lHits;
+    wxCoord                         vTextX = 0;
+    wxCoord                         vTextY = 0;
+
+    //
+    // prepare for drawing the text
+    //
+
+    //
+    // Set text color attributes
+    //
+    if (m_textForegroundColour.Ok())
+    {
+        SetTextColor( m_hPS
+                     ,(int)m_textForegroundColour.GetPixel()
+                    );
+    }
+
+    if (m_textBackgroundColour.Ok())
+    {
+        nOldBackground = SetTextBkColor( m_hPS
+                                        ,(int)m_textBackgroundColour.GetPixel()
+                                       );
+    }
+    SetBkMode( m_hPS
+              ,m_backgroundMode
+             );
+    GetOwner()->GetTextExtent( rsText
+                              ,&vTextX
+                              ,&vTextY
+                             );
+    vPtlStart.x = vX;
+    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;
+    }
+
+    ::GpiMove(m_hPS, &vPtlStart);
+    lHits = ::GpiCharString( m_hPS
+                            ,rsText.length()
+                            ,rsText.char_str()
+                           );
+    if (lHits != GPI_OK)
+    {
+        wxLogLastError(wxT("TextOut"));
+    }
+
+    //
+    // Restore the old parameters (text foreground colour may be left because
+    // it never is set to anything else, but background should remain
+    // transparent even if we just drew an opaque string)
+    //
+    if (m_textBackgroundColour.Ok())
+            SetTextBkColor( m_hPS
+                           ,nOldBackground
+                          );
+    SetBkMode( m_hPS
+              ,wxTRANSPARENT
+             );