]> git.saurik.com Git - wxWidgets.git/blobdiff - src/x11/dcclient.cpp
Added helper functions for string -> XmString conversion.
[wxWidgets.git] / src / x11 / dcclient.cpp
index 1af88bb2721b7359c1c9742c19dbf48e63bd3a06..162a8c71535e92e0bfbf48391a975114be86153b 100644 (file)
 #include "wx/window.h"
 #include "wx/app.h"
 #include "wx/image.h"
+#include "wx/module.h"
+#include "wx/fontutil.h"
 
 #include "wx/x11/private.h"
 
 #include <math.h>
 
+#if wxUSE_UNICODE
+#include "glib.h"
+#include "pango/pangox.h"
+#include "pango/pangoxft.h"
+
+#include "pango_x.cpp"
+#endif
+
 //-----------------------------------------------------------------------------
 // local defines
 //-----------------------------------------------------------------------------
@@ -162,6 +172,11 @@ wxWindowDC::wxWindowDC()
     m_isMemDC = FALSE;
     m_isScreenDC = FALSE;
     m_owner = (wxWindow *)NULL;
+    
+#if wxUSE_UNICODE
+    m_context = (PangoContext *)NULL;
+    m_fontdesc = (PangoFontDescription *)NULL;
+#endif
 }
 
 wxWindowDC::wxWindowDC( wxWindow *window )
@@ -192,6 +207,11 @@ wxWindowDC::wxWindowDC( wxWindow *window )
 
     m_display = (WXDisplay *) wxGlobalDisplay();
     
+#if wxUSE_UNICODE
+    m_context = wxTheApp->GetPangoContext();
+    m_fontdesc = window->GetFont().GetNativeFontInfo()->description;
+#endif
+
     int screen = DefaultScreen( (Display*) m_display );
     m_cmap = (WXColormap) DefaultColormap( (Display*) m_display, screen );
 
@@ -255,6 +275,11 @@ void wxWindowDC::SetUpDC()
 
     XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillSolid );
 
+#if wxUSE_NANOX
+    // By default, draw transparently
+    GrSetGCUseBackground((GC) m_textGC, FALSE);
+#endif
+
     /* m_penGC */
     m_pen.GetColour().CalcPixel( m_cmap );
     XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
@@ -308,10 +333,13 @@ void wxWindowDC::DoGetSize( int* width, int* height ) const
     m_owner->GetSize(width, height);
 }
 
-void wxWindowDC::DoFloodFill( wxCoord WXUNUSED(x1), wxCoord WXUNUSED(y1),
-                           const wxColour& WXUNUSED(col), int WXUNUSED(style) )
+extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y, 
+                          const wxColour & col, int style);
+
+bool wxWindowDC::DoFloodFill(wxCoord x, wxCoord y,
+                             const wxColour& col, int style)
 {
-    wxFAIL_MSG("not implemented");
+    return wxDoFloodFill(this, x, y, col, style);
 }
 
 bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const
@@ -323,7 +351,7 @@ bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const
     memdc.SelectObject(bitmap);
     memdc.Blit(0, 0, 1, 1, (wxDC*) this, x1, y1);
     memdc.SelectObject(wxNullBitmap);
-    wxImage image(bitmap);
+    wxImage image(bitmap.ConvertToImage());
     col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0));
     return TRUE;
 }
@@ -335,8 +363,19 @@ void wxWindowDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
     if (m_pen.GetStyle() != wxTRANSPARENT)
     {
         if (m_window)
-            XDrawLine( (Display*) m_display, (Window) m_window, 
-                (GC) m_penGC, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) );
+        {
+            // This hack is for the iPaq: XDrawLine draws
+            // nothing, whereas XDrawLines works...
+            wxPoint points[2];
+            points[0].x = x1;
+            points[0].y = y1;
+            points[1].x = x2;
+            points[1].y = y2;
+            DrawLines( 2, points, 0, 0 );
+            
+            // XDrawLine( (Display*) m_display, (Window) m_window, 
+            //    (GC) m_penGC, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) );
+        }
 
         CalcBoundingBox(x1, y1);
         CalcBoundingBox(x2, y2);
@@ -833,8 +872,10 @@ void wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord hei
 
 void wxWindowDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y)
 {
+    DoDrawBitmap(icon, x, y, TRUE);
 }
 
+#if wxUSE_NANOX
 void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
                                wxCoord x, wxCoord y,
                                bool useMask )
@@ -873,14 +914,14 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
     wxBitmap use_bitmap;
     if ((w != ww) || (h != hh))
     {
-        wxImage image( bitmap );
+        wxImage image( bitmap.ConvertToImage() );
         image.Rescale( ww, hh );
 #if 0
         if (is_mono)
             use_bitmap = image.ConvertToMonoBitmap(255,255,255);
         else
 #endif
-            use_bitmap = image.ConvertToBitmap();
+            use_bitmap = image;
     }
     else
     {
@@ -889,8 +930,127 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
 
     /* apply mask if any */
     WXPixmap mask = NULL;
-    if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
+    if (use_bitmap.GetMask())
+        mask = use_bitmap.GetMask()->GetBitmap();
+
+    if (useMask && mask)
+    {
+        Pixmap pixmap = (Pixmap) use_bitmap.GetPixmap() ;
+        Pixmap maskPixmap = (Pixmap) use_bitmap.GetMask()->GetBitmap() ;
+        Pixmap bufPixmap = GrNewPixmap(w, h, 0);
+        GC gc = GrNewGC();
+        GrSetGCUseBackground(gc, FALSE);
+        GrSetGCMode(gc, GR_MODE_COPY);
+
+        // This code assumes that background and foreground
+        // colours are used in ROPs, like in MSW.
+        // Not sure if this is true.
+
+        // Copy destination to buffer.
+        // In DoBlit, we need this step because Blit has
+        // a ROP argument. Here, we don't need it.
+        // In DoBlit, we may be able to eliminate this step
+        // if we check if the rop = copy
+#if 0
+        GrCopyArea(bufPixmap, gc, 0, 0, w, h, (Window) m_window,
+                  0, 0, GR_MODE_COPY);
+#endif
+            
+        // Copy src to buffer using selected raster op (none selected
+        // in DrawBitmap, so just use Gxcopy)
+        GrCopyArea(bufPixmap, gc, 0, 0, w, h, pixmap,
+                   0, 0, GR_MODE_COPY);
+
+        // Set masked area in buffer to BLACK (pixel value 0)
+        GrSetGCBackground(gc, WHITE);
+        GrSetGCForeground(gc, BLACK);
+        GrCopyArea(bufPixmap, gc, 0, 0, w, h, maskPixmap,
+                    0, 0, GR_MODE_AND);
+                       
+        // set unmasked area in dest to BLACK
+        GrSetGCBackground(gc, BLACK);
+        GrSetGCForeground(gc, WHITE);
+        GrCopyArea((Window) m_window, gc, xx, yy, w, h, maskPixmap,
+                   0, 0, GR_MODE_AND);
+
+        // OR buffer to dest
+        GrCopyArea((Window) m_window, gc, xx, yy, w, h, bufPixmap,
+                   0, 0, GR_MODE_OR);
+
+        GrDestroyGC(gc);
+        GrDestroyWindow(bufPixmap);
+    }
+    else
+      XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
+            (GC) m_penGC, 0, 0, w, h, xx, yy );
+
+    /* remove mask again if any */
+    if (useMask && mask)
+    {
+        if (!m_currentClippingRegion.IsNull())
+                XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
+    }
+}
+
+#else
+
+// Normal X11
+void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
+                               wxCoord x, wxCoord y,
+                               bool useMask )
+{
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
+
+    wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
+    
+    bool is_mono = (bitmap.GetBitmap() != NULL);
+
+    // scale/translate size and position
+    int xx = XLOG2DEV(x);
+    int yy = YLOG2DEV(y);
+
+    int w = bitmap.GetWidth();
+    int h = bitmap.GetHeight();
+
+    CalcBoundingBox( x, y );
+    CalcBoundingBox( x + w, y + h );
+
+    if (!m_window) return;
+
+    int ww = XLOG2DEVREL(w);
+    int hh = YLOG2DEVREL(h);
+
+    // compare to current clipping region
+    if (!m_currentClippingRegion.IsNull())
+    {
+        wxRegion tmp( xx,yy,ww,hh );
+        tmp.Intersect( m_currentClippingRegion );
+        if (tmp.IsEmpty())
+            return;
+    }
+
+    // scale bitmap if required
+    wxBitmap use_bitmap;
+    if ((w != ww) || (h != hh))
+    {
+        wxImage image( bitmap.ConvertToImage() );
+        image.Rescale( ww, hh );
+#if 0
+        if (is_mono)
+            use_bitmap = image.ConvertToMonoBitmap(255,255,255);
+        else
+#endif
+            use_bitmap = image;
+    }
+    else
     {
+        use_bitmap = bitmap;
+    }
+
+    // apply mask if any
+    WXPixmap mask = NULL;
+    if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
+    
         if (useMask && mask)
         {
             WXPixmap new_mask = NULL;
@@ -935,10 +1095,9 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
             if (new_mask)
                XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
         }
-    }
 
-    /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
-       drawing a mono-bitmap (XBitmap) we use the current text GC */
+    // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
+    // drawing a mono-bitmap (XBitmap) we use the current text GC
     if (is_mono)
         XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window,
             (GC) m_textGC, 0, 0, w, h, xx, yy, 1 );
@@ -946,7 +1105,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
         XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
             (GC) m_penGC, 0, 0, w, h, xx, yy );
 
-    /* remove mask again if any */
+    // remove mask again if any
     if (useMask && mask)
     {
         if (is_mono)
@@ -965,9 +1124,11 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
         }
     }
 }
+#endif
+  // wxUSE_NANOX/!wxUSE_NANOX
 
 bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
-                         wxDC *source, wxCoord xsrc, wxCoord ysrc, int rop, bool useMask,
+                         wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func, bool useMask,
                          wxCoord xsrcMask, wxCoord ysrcMask )
 {
    /* this is the nth try to get this utterly useless function to
@@ -991,13 +1152,13 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he
     bool use_bitmap_method = FALSE;
     bool is_mono = FALSE;
 
-    /* TODO: use the mask origin when drawing transparently */
+    // TODO: use the mask origin when drawing transparently 
     if (xsrcMask == -1 && ysrcMask == -1)
     {
-        xsrcMask = xsrc; ysrcMask = ysrc;
+        xsrcMask = xsrc;
+        ysrcMask = ysrc;
     }
     
-#if 0
     if (srcDC->m_isMemDC)
     {
         if (!memDC->m_selected.Ok()) return FALSE;
@@ -1042,14 +1203,14 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he
     CalcBoundingBox( xdest, ydest );
     CalcBoundingBox( xdest + width, ydest + height );
 
-    /* scale/translate size and position */
+    // scale/translate size and position
     wxCoord xx = XLOG2DEV(xdest);
     wxCoord yy = YLOG2DEV(ydest);
 
     wxCoord ww = XLOG2DEVREL(width);
     wxCoord hh = YLOG2DEVREL(height);
 
-    /* compare to current clipping region */
+    // compare to current clipping region
     if (!m_currentClippingRegion.IsNull())
     {
         wxRegion tmp( xx,yy,ww,hh );
@@ -1063,38 +1224,41 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he
 
     if (use_bitmap_method)
     {
-        /* scale/translate bitmap size */
+        // scale/translate bitmap size
         wxCoord bm_width = memDC->m_selected.GetWidth();
         wxCoord bm_height = memDC->m_selected.GetHeight();
 
         wxCoord bm_ww = XLOG2DEVREL( bm_width );
         wxCoord bm_hh = YLOG2DEVREL( bm_height );
 
-        /* scale bitmap if required */
+        // scale bitmap if required
         wxBitmap use_bitmap;
 
         if ((bm_width != bm_ww) || (bm_height != bm_hh))
         {
-            wxImage image( memDC->m_selected );
+            wxImage image( memDC->m_selected.ConvertToImage() );
             image = image.Scale( bm_ww, bm_hh );
 
+#if 0
             if (is_mono)
                 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
             else
-                use_bitmap = image.ConvertToBitmap();
+#endif
+                use_bitmap = image;
         }
         else
         {
             use_bitmap = memDC->m_selected;
         }
 
-        /* apply mask if any */
-        GdkBitmap *mask = (GdkBitmap *) NULL;
+        // apply mask if any
+        WXPixmap mask = NULL;
         if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
 
         if (useMask && mask)
         {
-            GdkBitmap *new_mask = (GdkBitmap*) NULL;
+            WXPixmap new_mask = NULL;
+#if 0
             if (!m_currentClippingRegion.IsNull())
             {
                 GdkColor col;
@@ -1114,59 +1278,62 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he
                 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
                 gdk_gc_unref( gc );
             }
-
+#endif
             if (is_mono)
             {
                 if (new_mask)
-                    gdk_gc_set_clip_mask( m_textGC, new_mask );
+                    XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask );
                 else
-                    gdk_gc_set_clip_mask( m_textGC, mask );
-                gdk_gc_set_clip_origin( m_textGC, xx, yy );
+                    XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
+                XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
             }
             else
             {
                 if (new_mask)
-                    gdk_gc_set_clip_mask( m_penGC, new_mask );
+                    XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask );
                 else
-                    gdk_gc_set_clip_mask( m_penGC, mask );
-                gdk_gc_set_clip_origin( m_penGC, xx, yy );
+                    XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
+                XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
             }
+            
             if (new_mask)
-                gdk_bitmap_unref( new_mask );
+               XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
         }
 
-        /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
-           drawing a mono-bitmap (XBitmap) we use the current text GC */
+        // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
+        // drawing a mono-bitmap (XBitmap) we use the current text GC
 
         if (is_mono)
-            gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, xx, yy, ww, hh );
+            XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window,
+                (GC) m_textGC, xsrc, ysrc, width, height, xx, yy, 1 );
         else
-            gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, xx, yy, ww, hh );
+            XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
+                (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
 
-        /* remove mask again if any */
+        // remove mask again if any
         if (useMask && mask)
         {
             if (is_mono)
             {
-                gdk_gc_set_clip_mask( m_textGC, (GdkBitmap *) NULL );
-                gdk_gc_set_clip_origin( m_textGC, 0, 0 );
+                XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
+                XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
                 if (!m_currentClippingRegion.IsNull())
-                    gdk_gc_set_clip_region( m_textGC, m_currentClippingRegion.GetRegion() );
+                    XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
             }
             else
             {
-                gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL );
-                gdk_gc_set_clip_origin( m_penGC, 0, 0 );
+                XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
+                XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
                 if (!m_currentClippingRegion.IsNull())
-                    gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() );
+                    XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
             }
         }
     }
-    else /* use_bitmap_method */
+    else // use_bitmap_method
     {
         if ((width != ww) || (height != hh))
         {
-            /* draw source window into a bitmap as we cannot scale
+            /* Draw source window into a bitmap as we cannot scale
                a window in contrast to a bitmap. this would actually
                work with memory dcs as well, but we'd lose the mask
                information and waste one step in this process since
@@ -1181,42 +1348,38 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord he
 
             wxBitmap bitmap( width, height );
 
-            /* copy including child window contents */
-            gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS );
-            gdk_window_copy_area( bitmap.GetPixmap(), m_penGC, 0, 0,
-                                  srcDC->GetWindow(),
-                                  xsrc, ysrc, width, height );
-            gdk_gc_set_subwindow( m_penGC, GDK_CLIP_BY_CHILDREN );
+            // copy including child window contents
+            XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
+            XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) bitmap.GetPixmap(),
+                       (GC) m_penGC, xsrc, ysrc, width, height, 0, 0 );
+            XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
 
-            /* scale image */
-            wxImage image( bitmap );
+            // scale image
+            wxImage image( bitmap.ConvertToImage() );
             image = image.Scale( ww, hh );
 
-            /* convert to bitmap */
-            bitmap = image.ConvertToBitmap();
-
-            /* draw scaled bitmap */
-            gdk_draw_pixmap( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 );
+            // convert to bitmap
+            bitmap = image;
 
+            // draw scaled bitmap
+            XCopyArea( (Display*) m_display, (Window) bitmap.GetPixmap(), (Window) m_window, 
+                       (GC) m_penGC, 0, 0, width, height, xx, yy );
         }
         else
         {
-            /* No scaling and not a memory dc with a mask either */
-
-            /* copy including child window contents */
-            gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS );
-            gdk_window_copy_area( m_window, m_penGC, xx, yy,
-                                  srcDC->GetWindow(),
-                                  xsrc, ysrc, width, height );
-            gdk_gc_set_subwindow( m_penGC, GDK_CLIP_BY_CHILDREN );
+            // No scaling and not a memory dc with a mask either
+
+            // copy including child window contents
+            XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
+            XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) m_window, 
+                       (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
+            XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
         }
     }
 
     SetLogicalFunction( old_logical_func );
+    
     return TRUE;
-#endif
-
-    return FALSE;
 }
 
 void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
@@ -1225,24 +1388,60 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
 
     if (!m_window) return;
 
-    XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
-
-    wxCHECK_RET( xfont, wxT("invalid font") );
-
     x = XLOG2DEV(x);
     y = YLOG2DEV(y);
 
-#if 0
-    wxCoord width = gdk_string_width( font, text.mbc_str() );
-    wxCoord height = font->ascent + font->descent;
+#if wxUSE_UNICODE
+    PangoLayout *layout = pango_layout_new(m_context);
+    pango_layout_set_font_description(layout, m_fontdesc);
+    
+    const wxCharBuffer data = wxConvUTF8.cWC2MB( text );
+    pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
+    
+    // Measure layout.
+    int w,h;
+    pango_layout_get_pixel_size(layout, &w, &h);
+    wxCoord width = w;
+    wxCoord height = h;
+    
+    // Draw layout.
+    x11_draw_layout( (Drawable) m_window, (GC) m_textGC, x, y, layout, m_textForegroundColour );
+    
+    g_object_unref( G_OBJECT( layout ) );
+    
+    CalcBoundingBox (x + width, y + height);
+    CalcBoundingBox (x, y);
+#else
+    XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
 
-    if ( m_backgroundMode == wxSOLID )
+    wxCHECK_RET( xfont, wxT("invalid font") );
+    
+    // First draw a rectangle representing the text background, if a text
+    // background is specified
+    if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT))
     {
-        gdk_gc_set_foreground( m_textGC, m_textBackgroundColour.GetColor() );
-        gdk_draw_rectangle( m_window, m_textGC, TRUE, x, y, width, height );
-        gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() );
+        // Since X draws from the baseline of the text, must add the text height
+        int cx = 0;
+        int cy = 0;
+        int ascent = 0;
+        int slen;
+        int direction, descent;
+
+        slen = strlen(text);
+        XCharStruct overall_return;
+
+        (void)XTextExtents(xfont, (char*) text.c_str(), slen, &direction,
+                                 &ascent, &descent, &overall_return);
+
+        cx = overall_return.width;
+        cy = ascent + descent;
+        m_textBackgroundColour.CalcPixel(m_cmap);
+        XSetForeground ((Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel());
+        XFillRectangle( (Display*) m_display, (Window) m_window,
+                    (GC) m_textGC, x, y, cx, cy );
+        XSetForeground ((Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel());
+
     }
-#endif
 
     XSetFont( (Display*) m_display, (GC) m_textGC, xfont->fid );
 #if !wxUSE_NANOX
@@ -1267,6 +1466,7 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
     CalcBoundingBox (x + width, y + height);
     CalcBoundingBox (x, y);
 #endif
+#endif
 }
 
 void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
@@ -1280,6 +1480,39 @@ void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoor
 {
     wxCHECK_RET( Ok(), "invalid dc" );
 
+    if (string.IsEmpty())
+    {
+        if (width) (*width) = 0;
+        if (height) (*height) = 0;
+        return;
+    }
+    
+#if wxUSE_UNICODE
+    PangoLayout *layout = pango_layout_new( m_context );
+
+    if (font)
+        pango_layout_set_font_description( layout, font->GetNativeFontInfo()->description );
+    else
+        pango_layout_set_font_description(layout, m_fontdesc);
+        
+    const wxCharBuffer data = wxConvUTF8.cWC2MB( string );
+    pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
+    // Measure text.
+    int w,h;
+    pango_layout_get_pixel_size(layout, &w, &h);
+    
+    if (width) (*width) = (wxCoord) w; 
+    if (height) (*height) = (wxCoord) h;
+    if (descent)
+    {
+        // Do something about metrics here. TODO.
+        (*descent) = 0;
+    }
+    if (externalLeading) (*externalLeading) = 0;  // ??
+    
+    g_object_unref( G_OBJECT( layout ) );
+#else
     wxFont fontToUse = m_font;
     if (font) fontToUse = *font;
 
@@ -1303,12 +1536,30 @@ void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoor
         *descent = (wxCoord)(descent2 / m_scaleY );
     if (externalLeading)
         *externalLeading = 0; // ??
+#endif
 }
 
 wxCoord wxWindowDC::GetCharWidth() const
 {
     wxCHECK_MSG( Ok(), 0, "invalid dc" );
     
+#if wxUSE_UNICODE
+    PangoLayout *layout = pango_layout_new( m_context );
+    
+    if (!m_fontdesc)
+    {
+        char *crash = NULL;
+        *crash = 0;
+    }
+    
+    pango_layout_set_font_description(layout, m_fontdesc);
+    pango_layout_set_text(layout, "H", 1 );
+    int w,h;
+    pango_layout_get_pixel_size(layout, &w, &h);
+    g_object_unref( G_OBJECT( layout ) );
+    
+    return w;
+#else
     wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
 
     XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
@@ -1321,12 +1572,31 @@ wxCoord wxWindowDC::GetCharWidth() const
     XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
         
     return (wxCoord)(overall.width / m_scaleX);
+#endif
 }
 
 wxCoord wxWindowDC::GetCharHeight() const
 {
     wxCHECK_MSG( Ok(), 0, "invalid dc" );
     
+#if wxUSE_UNICODE
+    PangoLayout *layout = pango_layout_new( m_context );
+    
+    if (!m_fontdesc)
+    {
+        char *crash = NULL;
+        *crash = 0;
+    }
+    
+    pango_layout_set_font_description(layout, m_fontdesc);
+    
+    pango_layout_set_text(layout, "H", 1 );
+    int w,h;
+    pango_layout_get_pixel_size(layout, &w, &h);
+    g_object_unref( G_OBJECT( layout ) );
+    
+    return h;
+#else
     wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
 
     XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
@@ -1339,6 +1609,7 @@ wxCoord wxWindowDC::GetCharHeight() const
     XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
         
     return (wxCoord)((ascent+descent) / m_scaleY);
+#endif
 }
 
 void wxWindowDC::Clear()
@@ -1714,6 +1985,10 @@ void wxWindowDC::SetBackgroundMode( int mode )
 
     m_backgroundMode = mode;
 
+#if wxUSE_NANOX
+    GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE);
+#endif
+
     if (!m_window) return;
 
     // CMB 21/7/98: fill style of cross-hatch brushes is affected by
@@ -1882,64 +2157,63 @@ int wxWindowDC::GetDepth() const
     return -1;
 }
 
+//-----------------------------------------------------------------------------
+// wxClientDC
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
+
+wxClientDC::wxClientDC( wxWindow *window )
+          : wxWindowDC( window )
+{
+    wxCHECK_RET( window, _T("NULL window in wxClientDC::wxClientDC") );
+    
+    m_window = (WXWindow*) window->GetClientAreaWindow();
+    
+    // Adjust the client area when the wxWindow is not using 2 X11 windows.
+    if (m_window == (WXWindow*) window->GetMainWindow())
+    {
+        wxPoint ptOrigin = window->GetClientAreaOrigin();
+        SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
+        wxSize size = window->GetClientSize();
+        SetClippingRegion(wxPoint(0, 0), size);
+    }
+}
+
+void wxClientDC::DoGetSize(int *width, int *height) const
+{
+    wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
+
+    m_owner->GetClientSize( width, height );
+}
+
 // ----------------------------------------------------------------------------
 // wxPaintDC
 // ----------------------------------------------------------------------------
 
 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
 
-wxPaintDC::wxPaintDC(wxWindow* win)
-  : wxClientDC(win)
+wxPaintDC::wxPaintDC(wxWindow* window)
+  : wxClientDC(window)
 {
 #if USE_PAINT_REGION
-    if (!win->GetClipPaintRegion())
+    if (!window->GetClipPaintRegion())
         return;
 
-    m_paintClippingRegion = win->GetUpdateRegion();
+    m_paintClippingRegion = window->GetUpdateRegion();
     Region region = (Region) m_paintClippingRegion.GetX11Region();
     if (region)
     {
-        m_paintClippingRegion = win->GetUpdateRegion();
-        Region region2 = (Region) m_paintClippingRegion.GetX11Region();
-        if (region2)
-        {
             m_currentClippingRegion.Union( m_paintClippingRegion );
 
-            XSetRegion( (Display*) m_display, (GC) m_penGC, region2 );
-            XSetRegion( (Display*) m_display, (GC) m_brushGC, region2 );
-            XSetRegion( (Display*) m_display, (GC) m_textGC, region2 );
-            XSetRegion( (Display*) m_display, (GC) m_bgGC, region2 );
-        }
+            XSetRegion( (Display*) m_display, (GC) m_penGC, region );
+            XSetRegion( (Display*) m_display, (GC) m_brushGC, region );
+            XSetRegion( (Display*) m_display, (GC) m_textGC, region );
+            XSetRegion( (Display*) m_display, (GC) m_bgGC, region );
     }
 #endif // USE_PAINT_REGION
 }
 
-//-----------------------------------------------------------------------------
-// wxClientDC
-//-----------------------------------------------------------------------------
-
-IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
-
-wxClientDC::wxClientDC( wxWindow *win )
-          : wxWindowDC( win )
-{
-    wxCHECK_RET( win, _T("NULL window in wxClientDC::wxClientDC") );
-    
-#ifdef __WXUNIVERSAL__
-    wxPoint ptOrigin = win->GetClientAreaOrigin();
-    SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
-    wxSize size = win->GetClientSize();
-    SetClippingRegion(wxPoint(0, 0), size);
-#endif // __WXUNIVERSAL__
-}
-
-void wxClientDC::DoGetSize(int *width, int *height) const
-{
-    wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
-
-    m_owner->GetClientSize( width, height );
-}
-
 // ----------------------------------------------------------------------------
 // wxDCModule
 // ----------------------------------------------------------------------------