+#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
+             );
+}
+
+void wxPMDCImpl::DoDrawRotatedText(
+  const wxString&                   rsText
+, wxCoord                           vX
+, wxCoord                           vY
+, double                            dAngle
+)
+{
+    if (dAngle == 0.0)
+    {
+        DoDrawText( rsText
+                   ,vX
+                   ,vY
+                  );
+    }
+
+   // TODO:
+   /*
+    if ( angle == 0.0 )
+    {
+        DoDrawText(text, x, y);
+    }
+    else
+    {
+        LOGFONT lf;
+        wxFillLogFont(&lf, &m_font);
+
+        // GDI wants the angle in tenth of degree
+        long angle10 = (long)(angle * 10);
+        lf.lfEscapement = angle10;
+        lf. lfOrientation = angle10;
+
+        HFONT hfont = ::CreateFontIndirect(&lf);
+        if ( !hfont )
+        {
+            wxLogLastError("CreateFont");
+        }
+        else
+        {
+            HFONT hfontOld = ::SelectObject(GetHdc(), hfont);
+
+            DrawAnyText(text, x, y);
+
+            (void)::SelectObject(GetHdc(), hfontOld);
+        }
+
+        // call the bounding box by adding all four vertices of the rectangle
+        // containing the text to it (simpler and probably not slower than
+        // determining which of them is really topmost/leftmost/...)
+        wxCoord w, h;
+        GetTextExtent(text, &w, &h);
+
+        double rad = DegToRad(angle);
+
+        // "upper left" and "upper right"
+        CalcBoundingBox(x, y);
+        CalcBoundingBox(x + w*cos(rad), y - h*sin(rad));
+        CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
+
+        // "bottom left" and "bottom right"
+        x += (wxCoord)(h*sin(rad));
+        y += (wxCoord)(h*cos(rad));
+        CalcBoundingBox(x, y);
+        CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
+    }
+*/
+}
+
+// ---------------------------------------------------------------------------
+// set GDI objects
+// ---------------------------------------------------------------------------
+
+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
+)
+{
+    if (m_hOldFont)
+    {
+        m_hOldFont = 0;
+    }
+    m_palette = rPalette;
+    if (!rPalette.Ok())
+    {
+        if (m_hOldFont)
+        {
+            m_hOldFont = 0;
+        }
+    }
+    HPALETTE                    hOldPal = ::GpiSelectPalette((HDC) m_hPS, (HPALETTE) m_palette.GetHPALETTE());
+    if (!m_hOldPalette)
+        m_hOldPalette = (WXHPALETTE)hOldPal;
+} // end of wxPMDCImpl::SetPalette
+
+void wxPMDCImpl::SetFont(
+  const wxFont&                     rFont
+)
+{
+    //
+    // Set the old object temporarily, in case the assignment deletes an object
+    // that's not yet selected out.
+    //
+    if (m_hOldFont)
+    {
+        m_hOldFont = 0;
+    }
+    m_font = rFont;
+    if (!rFont.Ok())
+    {
+        m_hOldFont = 0;
+    }
+
+    m_font.SetPS(m_hPS); // this will realize the font
+
+    if (m_font.Ok())
+    {
+        HFONT                       hFont = m_font.GetResourceHandle();
+        if (hFont == (HFONT) NULL)
+        {
+            wxLogDebug(wxT("::SelectObject failed in wxPMDCImpl::SetFont."));
+        }
+        if (!m_hOldFont)
+            m_hOldFont = (WXHFONT) hFont;
+    }
+} // end of wxPMDCImpl::SetFont
+
+void wxPMDCImpl::SetPen(
+  const wxPen&                      rPen
+)
+{
+    if (m_pen == rPen)
+        return;
+    m_pen = rPen;
+    if (!m_pen.Ok())
+        return;
+
+    if (m_hOldPen)
+        m_hOldPen = 0L;
+    m_pen = rPen;
+
+    if (!m_pen.Ok())
+    {
+        if (m_hOldPen)
+        {
+            m_pen.SetPS((HPS)m_hOldPen);
+        }
+        m_hOldPen = 0L;
+    }
+
+    if (m_pen.Ok())
+    {
+        if (m_pen.GetResourceHandle())
+        {
+            m_pen.SetPS(m_hPS);
+            if (!m_hOldPen)
+                m_hOldPen = m_pen.GetPS();
+        }
+        ::GpiSetColor(m_hPS, m_pen.GetColour().GetPixel());
+    }
+}
+
+void wxPMDCImpl::SetBrush(
+  const wxBrush&                    rBrush
+)
+{
+    if (m_hOldBrush)
+        m_hOldBrush = 0L;
+    m_brush = rBrush;
+    if (!m_brush.Ok())
+    if (m_brush == rBrush)
+        return;
+    if (!m_brush.Ok())
+        if (m_hOldBrush)
+            m_hOldBrush = 0L;
+
+    if (!m_brush.Ok())
+    {
+        if (m_hOldBrush)
+        {
+            m_brush.SetPS((HPS)m_hOldBrush);
+        }
+        m_hOldBrush = 0L;
+    }
+
+    if (m_brush.Ok())
+    {
+        if (m_brush.GetResourceHandle())
+        {
+            m_brush.SetPS(m_hPS);
+            if (!m_hOldBrush)
+                m_hOldBrush = (WXHWND)m_brush.GetPS();
+        }
+    }
+} // end of wxPMDCImpl::SetBrush
+
+void wxPMDCImpl::SetBackground(const wxBrush& rBrush)
+{
+    m_backgroundBrush = rBrush;
+
+    if (m_backgroundBrush.Ok())
+    {
+        (void)::GpiSetBackColor((HPS)m_hPS, m_backgroundBrush.GetColour().GetPixel());
+    }
+} // end of wxPMDCImpl::SetBackground
+
+void wxPMDCImpl::SetBackgroundMode(int nMode)
+{
+    m_backgroundMode = nMode;
+} // end of wxPMDCImpl::SetBackgroundMode
+
+void wxPMDCImpl::SetLogicalFunction(int nFunction)
+{
+    m_logicalFunction = nFunction;
+    SetRop((WXHDC)m_hDC);
+} // wxPMDCImpl::SetLogicalFunction
+
+void wxPMDCImpl::SetRop(WXHDC hDC)
+{
+    if (!hDC || m_logicalFunction < 0)
+        return;
+
+    LONG lCRop;
+    switch (m_logicalFunction)
+    {
+        case wxXOR:
+            lCRop = FM_XOR;
+            break;
+
+        case wxINVERT:
+            lCRop = FM_INVERT;
+            break;
+
+        case wxOR_REVERSE:
+            lCRop = FM_MERGESRCNOT;
+            break;
+
+        case wxAND_REVERSE:
+            lCRop = FM_NOTMASKSRC;
+            break;
+
+        case wxCLEAR:
+            lCRop = FM_ONE;
+            break;
+
+        case wxSET:
+            lCRop = FM_ZERO;
+            break;
+
+        case wxSRC_INVERT:
+            lCRop = FM_MERGENOTSRC;
+            break;
+
+        case wxOR_INVERT:
+            lCRop = FM_MERGESRCNOT;
+            break;
+
+        case wxAND:
+            lCRop = FM_AND;
+            break;
+
+        case wxOR:
+            lCRop = FM_OR;
+            break;
+
+        case wxAND_INVERT:
+            lCRop = FM_SUBTRACT;
+            break;
+
+        case wxEQUIV:
+        case wxNAND:
+        case wxCOPY:
+        default:
+            lCRop = FM_OVERPAINT;
+            break;
+    }
+    ::GpiSetMix((HPS)hDC, lCRop);
+} // end of wxPMDCImpl::SetRop
+
+bool wxPMDCImpl::StartDoc( const wxString& WXUNUSED(rsMessage) )
+{
+    // We might be previewing, so return true to let it continue.
+    return true;
+} // end of wxPMDCImpl::StartDoc
+
+void wxPMDCImpl::EndDoc()
+{
+} // end of wxPMDCImpl::EndDoc
+
+void wxPMDCImpl::StartPage()
+{
+} // end of wxPMDCImpl::StartPage
+
+void wxPMDCImpl::EndPage()
+{
+} // end of wxPMDCImpl::EndPage
+
+// ---------------------------------------------------------------------------
+// text metrics
+// ---------------------------------------------------------------------------
+
+wxCoord wxPMDCImpl::GetCharHeight() const
+{
+    FONTMETRICS                     vFM; // metrics structure
+
+    ::GpiQueryFontMetrics( m_hPS
+                          ,sizeof(FONTMETRICS)
+                          ,&vFM
+                         );
+    return YDEV2LOGREL(vFM.lXHeight);
+}
+
+wxCoord wxPMDCImpl::GetCharWidth() const
+{
+    FONTMETRICS                     vFM; // metrics structure
+
+    ::GpiQueryFontMetrics( m_hPS
+                          ,sizeof(FONTMETRICS)
+                          ,&vFM
+                         );
+    return XDEV2LOGREL(vFM.lAveCharWidth);
+}
+
+void wxPMDCImpl::DoGetTextExtent(
+  const wxString&                   rsString
+, wxCoord*                          pvX
+, wxCoord*                          pvY
+, wxCoord*                          pvDescent
+, wxCoord*                          pvExternalLeading
+, const wxFont*                     pTheFont
+) const
+{
+    POINTL                          avPoint[TXTBOX_COUNT];
+    POINTL                          vPtMin;
+    POINTL                          vPtMax;
+    int                             i;
+    int                             l;
+    FONTMETRICS                     vFM; // metrics structure
+    BOOL                            bRc;
+    ERRORID                         vErrorCode; // last error id code
+    wxFont*                         pFontToUse = (wxFont*)pTheFont;
+
+    wxChar                          zMsg[128]; // DEBUG
+    wxString                        sError;
+
+    if (!pFontToUse)
+        pFontToUse = (wxFont*)&m_font;
+    l = rsString.length();
+
+    //
+    // In world coordinates.
+    //
+    if (!m_hPS)
+    {
+       (void)wxMessageBox( _T("wxWidgets core library")
+                           ,"Using uninitialized DC for measuring text!\n"
+                           ,wxICON_INFORMATION
+                           );
+    }
+       
+    bRc = ::GpiQueryTextBox( m_hPS
+                            ,l
+                            ,rsString.char_str()
+                            ,TXTBOX_COUNT // return maximum information
+                            ,avPoint      // array of coordinates points
+                           );
+    if(!bRc)
+    {
+       vErrorCode = ::WinGetLastError(wxGetInstance());
+       sError = wxPMErrorToStr(vErrorCode);
+       // DEBUG
+       wxSprintf(zMsg, _T("GpiQueryTextBox for %s: failed with Error: %lx - %s"), rsString.c_str(), vErrorCode, sError.c_str());
+       (void)wxMessageBox( _T("wxWidgets core library")
+                          ,zMsg
+                          ,wxICON_INFORMATION
+                         );
+    }
+
+    vPtMin.x = avPoint[0].x;
+    vPtMax.x = avPoint[0].x;
+    vPtMin.y = avPoint[0].y;
+    vPtMax.y = avPoint[0].y;
+    for (i = 1; i < 4; i++)
+    {
+        if(vPtMin.x > avPoint[i].x) vPtMin.x = avPoint[i].x;
+        if(vPtMin.y > avPoint[i].y) vPtMin.y = avPoint[i].y;
+        if(vPtMax.x < avPoint[i].x) vPtMax.x = avPoint[i].x;
+        if(vPtMax.y < avPoint[i].y) vPtMax.y = avPoint[i].y;
+    }
+    ::GpiQueryFontMetrics( m_hPS
+                          ,sizeof(FONTMETRICS)
+                          ,&vFM
+                         );
+
+    if (pvX)
+        *pvX = (wxCoord)(vPtMax.x - vPtMin.x + 1);
+    if (pvY)
+        *pvY = (wxCoord)(vPtMax.y - vPtMin.y + 1);
+    if (pvDescent)
+        *pvDescent = vFM.lMaxDescender;
+    if (pvExternalLeading)
+        *pvExternalLeading = vFM.lExternalLeading;
+}
+
+void wxPMDCImpl::SetMapMode(
+  int                               nMode
+)
+{
+    int                             nPixelWidth = 0;
+    int                             nPixelHeight = 0;
+    int                             nMmWidth = 1;
+    int                             nMmHeight = 1;
+    LONG                            lArray[CAPS_VERTICAL_RESOLUTION+1];
+
+    m_mappingMode = nMode;
+
+    if(::DevQueryCaps( m_hDC
+                      ,CAPS_FAMILY                  // id of first item
+                      ,CAPS_VERTICAL_RESOLUTION+1   // number of items wanted
+                      ,lArray
+                     ))
+    {
+        LONG                        lHorzRes;
+        LONG                        lVertRes;
+
+        nPixelWidth    = lArray[CAPS_WIDTH];
+        nPixelHeight   = lArray[CAPS_HEIGHT];
+        lHorzRes  = lArray[CAPS_HORIZONTAL_RESOLUTION]; // returns pel/meter
+        lVertRes  = lArray[CAPS_VERTICAL_RESOLUTION];   // returns pel/meter
+        nMmWidth  = (lHorzRes/1000) * nPixelWidth;
+        nMmHeight = (lVertRes/1000) * nPixelHeight;
+    }
+    if ((nPixelWidth == 0) || (nPixelHeight == 0) || (nMmWidth == 0) || (nMmHeight == 0))
+    {
+        return;
+    }
+
+    double dMm2pixelsX = nPixelWidth/(double)nMmWidth;
+    double dMm2pixelsY = nPixelHeight/(double)nMmHeight;
+
+    switch (nMode)
+    {
+        case wxMM_TWIPS:
+            m_logicalScaleX = (twips2mm * dMm2pixelsX);
+            m_logicalScaleY = (twips2mm * dMm2pixelsY);
+            break;
+
+        case wxMM_POINTS:
+            m_logicalScaleX = (pt2mm * dMm2pixelsX);
+            m_logicalScaleY = (pt2mm * dMm2pixelsY);
+            break;
+
+        case wxMM_METRIC:
+            m_logicalScaleX = dMm2pixelsX;
+            m_logicalScaleY = dMm2pixelsY;
+            break;
+
+        case wxMM_LOMETRIC:
+            m_logicalScaleX = (dMm2pixelsX/10.0);
+            m_logicalScaleY = (dMm2pixelsY/10.0);
+            break;
+
+        case wxMM_TEXT:
+        default:
+            m_logicalScaleX = 1.0;
+            m_logicalScaleY = 1.0;
+            break;
+    }
+
+    SIZEL                           vSize;
+    ULONG                           ulOptions;
+
+    ulOptions = ::GpiQueryPS(m_hPS, &vSize);
+    if (!ulOptions & PU_ARBITRARY)
+    {
+        ulOptions = PU_ARBITRARY | GPIF_DEFAULT;
+        ::GpiSetPS(m_hPS, &vSize, ulOptions);
+    }
+    ComputeScaleAndOrigin();