DIB Engine: introduction of bitmaplist structure

From: Massimo Del Fedele <max@veneto.com>


---

 dlls/winedib.drv/Makefile.in          |    3 
 dlls/winedib.drv/bitblt.c             |   44 ++--
 dlls/winedib.drv/bitmap.c             |   54 +++---
 dlls/winedib.drv/bitmaplist.c         |  168 +++++++++++++++++
 dlls/winedib.drv/dc.c                 |   20 +-
 dlls/winedib.drv/dib.c                |  323 +++++++++++++--------------------
 dlls/winedib.drv/dibdrv.h             |   55 ++++--
 dlls/winedib.drv/dibdrv_main.c        |    6 +
 dlls/winedib.drv/dibdrvbitmap.c       |  211 ++++++++++++----------
 dlls/winedib.drv/font.c               |    4 
 dlls/winedib.drv/graphics.c           |    8 -
 dlls/winedib.drv/palette.c            |   56 ++++--
 dlls/winedib.drv/pen_brush.c          |   66 ++++---
 dlls/winedib.drv/primitives_bitblt.c  |   16 +-
 dlls/winedib.drv/primitives_color.c   |   20 +-
 dlls/winedib.drv/primitives_convert.c |    9 +
 dlls/winedib.drv/primitives_font.c    |   18 +-
 dlls/winedib.drv/text.c               |    6 -
 18 files changed, 639 insertions(+), 448 deletions(-)
 create mode 100644 dlls/winedib.drv/bitmaplist.c


diff --git a/dlls/winedib.drv/Makefile.in b/dlls/winedib.drv/Makefile.in
index 722785e..a29edf0 100644
--- a/dlls/winedib.drv/Makefile.in
+++ b/dlls/winedib.drv/Makefile.in
@@ -3,13 +3,14 @@ TOPOBJDIR = ../..
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 EXTRAINCL = @FREETYPEINCL@ @FONTCONFIGINCL@
-EXTRALIBS = @XLIB@
+EXTRALIBS = @X_LIBS@ @X_PRE_LIBS@ @XLIB@ @X_EXTRA_LIBS@
 MODULE    = winedib.drv
 IMPORTS   = user32 gdi32 advapi32 kernel32 ntdll
 
 C_SRCS = \
     bitblt.c \
     bitmap.c \
+    bitmaplist.c \
     clipping.c \
     convert.c \
     dc.c \
diff --git a/dlls/winedib.drv/bitblt.c b/dlls/winedib.drv/bitblt.c
index 97feefd..3a987bd 100644
--- a/dlls/winedib.drv/bitblt.c
+++ b/dlls/winedib.drv/bitblt.c
@@ -267,8 +267,12 @@ BOOL _DIBDRV_InternalAlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
     _DIBDRV_Position_ws2ds(physDevSrc, &xSrc, &ySrc);
     _DIBDRV_Sizes_ws2ds(physDevSrc, &widthSrc, &heightSrc);
     
-    /* from tests, it seems that negative coords on phys space are not allowed */
-    if(xDst < 0 || yDst < 0 || xSrc < 0 || ySrc < 0)
+    /* from tests, it seems that coords out of phys spaces are not allowed */
+    if(xDst < 0 || yDst < 0 || xSrc < 0 || ySrc < 0 ||
+       xDst + widthDst > physDevDst->physBitmap->width ||
+       yDst + heightDst > physDevDst->physBitmap->height ||
+       xSrc + widthSrc > physDevSrc->physBitmap->width ||
+       ySrc + heightSrc > physDevSrc->physBitmap->height)
     {
         SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
@@ -279,10 +283,10 @@ BOOL _DIBDRV_InternalAlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
     setPoint(&ps, xSrc, ySrc);
     setSize(&szDst, widthDst, heightDst);
     setSize(&szSrc, widthSrc, heightSrc);
-    setRect(&dstClip, 0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height);
+    setRect(&dstClip, 0, 0, physDevDst->physBitmap->width, physDevDst->physBitmap->height);
     if(physDevSrc)
     {
-        setRect(&srcClip, 0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height);
+        setRect(&srcClip, 0, 0, physDevSrc->physBitmap->width, physDevSrc->physBitmap->height);
         res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, &dstClip);
     }
     else
@@ -306,7 +310,7 @@ BOOL _DIBDRV_InternalAlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
         setSize(&szSrc, widthSrc, heightSrc);
         if(!StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip))
             continue;
-        if(physDevDst->physBitmap.funcs->AlphaBlend(physDevDst, pd.x, pd.y, szDst.cx, szDst.cy,
+        if(physDevDst->physBitmap->funcs->AlphaBlend(physDevDst, pd.x, pd.y, szDst.cx, szDst.cy,
                                                     physDevSrc, ps.x, ps.y, szSrc.cx, szSrc.cy, blendfn))
             res = TRUE;
     }
@@ -326,9 +330,9 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width
     SIZE szDst = {widthDst, heightDst};
 
     MAYBE(TRACE("physDevDst:%p(%s%s), xDst:%d, yDst:%d, widthDst:%d, heightDst:%d, physDevSrc:%p(%s%s), xSrc:%d, ySrc:%d, widthSrc:%d, heightSrc:%d\n",
-          physDevDst, physDevDst->hasDIB ? "DIB-" : "DDB", physDevDst->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevDst->physBitmap) : "",
+          physDevDst, physDevDst->hasDIB ? "DIB-" : "DDB", physDevDst->hasDIB ? _DIBDRVBITMAP_GetFormatName(physDevDst->physBitmap) : "",
           xDst, yDst, widthDst, heightDst,
-          physDevSrc, physDevSrc->hasDIB ? "DIB-" : "DDB", physDevSrc->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevSrc->physBitmap) : "",
+          physDevSrc, physDevSrc->hasDIB ? "DIB-" : "DDB", physDevSrc->hasDIB ? _DIBDRVBITMAP_GetFormatName(physDevSrc->physBitmap) : "",
           xSrc, ySrc, widthSrc, heightSrc));
 
     /* if sizes are null or negative, or source positions are negatives, returns false */
@@ -450,11 +454,11 @@ BOOL _DIBDRV_InternalBitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
     setPoint(&pd, xDst, yDst);
     setPoint(&ps, xSrc, ySrc);
     setSize(&sz, width, height);
-    setRect(&dstClip, 0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height);
+    setRect(&dstClip, 0, 0, physDevDst->physBitmap->width, physDevDst->physBitmap->height);
 
     if(physDevSrc)
     {
-        setRect(&srcClip, 0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height);
+        setRect(&srcClip, 0, 0, physDevSrc->physBitmap->width, physDevSrc->physBitmap->height);
         res = BitBlt_ClipAreas(&ps, &pd, &sz, &srcClip, &dstClip);
     }
     else
@@ -476,7 +480,7 @@ BOOL _DIBDRV_InternalBitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
         setSize(&sz, width, height);
         if(!BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip))
             continue;
-        if(!physDevDst->physBitmap.funcs->BitBlt(physDevDst, pd.x, pd.y, sz.cx, sz.cy, physDevSrc, ps.x, ps.y, rop))
+        if(!physDevDst->physBitmap->funcs->BitBlt(physDevDst, pd.x, pd.y, sz.cx, sz.cy, physDevSrc, ps.x, ps.y, rop))
             res = FALSE;
     }
     return res;
@@ -496,16 +500,16 @@ BOOL DIBDRV_BitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
     SIZE sz = {width, height};
 
     MAYBE(TRACE("physDevDst:%p(%s%s), xDst:%d, yDst:%d, width:%d, height:%d, physDevSrc:%p(%s%s), xSrc:%d, ySrc:%d, rop:%08x\n",
-          physDevDst, physDevDst->hasDIB ? "DIB-" : "DDB", physDevDst->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevDst->physBitmap) : "",
+          physDevDst, physDevDst->hasDIB ? "DIB-" : "DDB", physDevDst->hasDIB ? _DIBDRVBITMAP_GetFormatName(physDevDst->physBitmap) : "",
           xDst, yDst, width, height,
-          physDevSrc, physDevSrc ? (physDevSrc->hasDIB ? "DIB-" : "DDB"): "---", physDevSrc && physDevSrc->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevSrc->physBitmap) : "",
+          physDevSrc, physDevSrc ? (physDevSrc->hasDIB ? "DIB-" : "DDB"): "---", physDevSrc && physDevSrc->hasDIB ? _DIBDRVBITMAP_GetFormatName(physDevSrc->physBitmap) : "",
           xSrc, ySrc, rop));
 
     if(physDevDst->hasDIB)
     {
         /* DIB section selected in dest DC, use DIB Engine */
         /* clip blit area */
-        RECT dstClip = {0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height};
+        RECT dstClip = {0, 0, physDevDst->physBitmap->width, physDevDst->physBitmap->height};
         
         if(!physDevSrc || physDevSrc->hasDIB)
         {
@@ -609,7 +613,7 @@ BOOL DIBDRV_BitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
             /* clip blit area */
             if(physDevSrc)
             {
-                RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height};
+                RECT srcClip = {0, 0, physDevSrc->physBitmap->width, physDevSrc->physBitmap->height};
                 res = !BitBlt_ClipAreas(&ps, &pd, &sz, &srcClip, 0);
             }
             else
@@ -672,10 +676,10 @@ BOOL _DIBDRV_InternalStretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
     setPoint(&ps, xSrc, ySrc);
     setSize(&szDst, widthDst, heightDst);
     setSize(&szSrc, widthSrc, heightSrc);
-    setRect(&dstClip, 0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height);
+    setRect(&dstClip, 0, 0, physDevDst->physBitmap->width, physDevDst->physBitmap->height);
     if(physDevSrc)
     {
-        setRect(&srcClip, 0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height);
+        setRect(&srcClip, 0, 0, physDevSrc->physBitmap->width, physDevSrc->physBitmap->height);
         res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, &dstClip);
     }
     else
@@ -699,7 +703,7 @@ BOOL _DIBDRV_InternalStretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
         setSize(&szSrc, widthSrc, heightSrc);
         if(!StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip))
             continue;
-        if(physDevDst->physBitmap.funcs->StretchBlt(physDevDst, pd.x, pd.y, szDst.cx, szDst.cy,
+        if(physDevDst->physBitmap->funcs->StretchBlt(physDevDst, pd.x, pd.y, szDst.cx, szDst.cy,
                                                     physDevSrc, ps.x, ps.y, szSrc.cx, szSrc.cy, rop))
             res = TRUE;
     }
@@ -727,9 +731,9 @@ BOOL DIBDRV_StretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
         return DIBDRV_BitBlt(physDevDst, xDst, yDst, widthDst, heightDst, physDevSrc, xSrc, ySrc, rop);
 
     MAYBE(TRACE("physDevDst:%p(%s%s), xDst:%d, yDst:%d, widthDst:%d, heightDst:%d, physDevSrc:%p(%s%s), xSrc:%d, ySrc:%d, widthSrc:%d, heightSrc:%d, rop:%08x\n",
-          physDevDst, physDevDst->hasDIB ? "DIB-" : "DDB", physDevDst->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevDst->physBitmap) : "",
+          physDevDst, physDevDst->hasDIB ? "DIB-" : "DDB", physDevDst->hasDIB ? _DIBDRVBITMAP_GetFormatName(physDevDst->physBitmap) : "",
           xDst, yDst, widthDst, heightDst,
-          physDevSrc, physDevSrc->hasDIB ? "DIB-" : "DDB", physDevSrc->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevSrc->physBitmap) : "",
+          physDevSrc, physDevSrc->hasDIB ? "DIB-" : "DDB", physDevSrc->hasDIB ? _DIBDRVBITMAP_GetFormatName(physDevSrc->physBitmap) : "",
           xSrc, ySrc, widthSrc, heightSrc, rop));
 
     if(physDevDst->hasDIB)
@@ -833,7 +837,7 @@ BOOL DIBDRV_StretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
             /* clip blit area */
             if(physDevSrc)
             {
-                RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height};
+                RECT srcClip = {0, 0, physDevSrc->physBitmap->width, physDevSrc->physBitmap->height};
                 res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, 0);
             }
             else
diff --git a/dlls/winedib.drv/bitmap.c b/dlls/winedib.drv/bitmap.c
index f3d3b9c..1562137 100644
--- a/dlls/winedib.drv/bitmap.c
+++ b/dlls/winedib.drv/bitmap.c
@@ -34,13 +34,15 @@ HBITMAP DIBDRV_SelectBitmap( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap )
     DIBSECTION dibSection;
     HBITMAP res;
     
+    MAYBE(TRACE("physDev:%p, hbitmap:%p\n", physDev, hbitmap));
+
     /* try to get the DIBSECTION data from the bitmap */
-    if(GetObjectW(hbitmap, sizeof(DIBSECTION), &dibSection) == sizeof(BITMAP))
+    if(GetObjectW(hbitmap, sizeof(DIBSECTION), &dibSection) != sizeof(DIBSECTION))
     {
         /* not a DIB section, sets it on physDev and use X11 behaviour */
 
-        MAYBE(TRACE("physDev:%p, hbitmap:%p\n", physDev, hbitmap));
         physDev->hasDIB = FALSE;
+        physDev->physBitmap = NULL;
         res = _DIBDRV_GetDisplayDriver()->pSelectBitmap(physDev->X11PhysDev, hbitmap);
         if(res)
             physDev->hbitmap = hbitmap;
@@ -49,32 +51,23 @@ HBITMAP DIBDRV_SelectBitmap( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap )
     {
         /* it's a DIB section, sets it on physDev and use DIB Engine behaviour */
         
-        MAYBE(TRACE("physDev:%p, hbitmap:%p, physBitmap=%p\n", physDev, hbitmap, &physDev->physBitmap));
-
-        /* frees any previously physical bitmap */
-        _DIBDRVBITMAP_Free(&physDev->physBitmap);
-
-        /* WARNING : the color table can't be grabbed here, since it's still
-           not initialized. It'll be grabbed on RealizeDefaultPalette(),
-           which is presumably the first call made after palette initialization.
-           So, by now we just set up palette size and leave NULL the palette pointer */
-        if(_DIBDRVBITMAP_InitFromBMIH(&physDev->physBitmap, &dibSection.dsBmih, dibSection.dsBitfields, NULL, dibSection.dsBm.bmBits))
+        /* sets the physical bitmap */
+        if((physDev->physBitmap = _BITMAPLIST_Get(hbitmap)) != NULL)
         {
-            /* stores the active bitmap */
-            res = physDev->hbitmap;
-            physDev->hbitmap = hbitmap;
-            
-            /* remember there's a DIB selected in */
             physDev->hasDIB = TRUE;
+            physDev->hbitmap = hbitmap;
+            MAYBE(TRACE("physDev->physBitmap:%p(%s)\n", physDev->physBitmap, _DIBDRVBITMAP_GetFormatName(physDev->physBitmap)));
+            res = hbitmap;
         }
         else
         {
-            ERR("Failed to initialize physical bitmap\n");
+            ERR("Physical bitmap %p not found in internal list\n", hbitmap);
+            physDev->hbitmap = GetStockObject(DEFAULT_BITMAP);
+            physDev->hasDIB = FALSE;
             res = 0;
         }
     }
     return res;
-    
 }
 
 /****************************************************************************
@@ -96,7 +89,7 @@ BOOL DIBDRV_CreateBitmap( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, LPVOID bmBits
     else
     {
         /* it's a DIB section, use DIB Engine behaviour - should not happen, but.... */
-        ONCE(FIXME("CreateBitmap() called for a DIB section - shouldn't happen\n"));
+        ERR("CreateBitmap() called for a DIB section - shouldn't happen\n");
         res = TRUE;
     }
     return res;
@@ -108,12 +101,13 @@ BOOL DIBDRV_CreateBitmap( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, LPVOID bmBits
 BOOL DIBDRV_DeleteBitmap( HBITMAP hbitmap )
 {
     DIBSECTION dibSection;
+    DIBDRVBITMAP *bmp;
     BOOL res;
     
     MAYBE(TRACE("hbitmap:%p\n", hbitmap));
 
     /* try to get the DIBSECTION data from the bitmap */
-    if(GetObjectW(hbitmap, sizeof(DIBSECTION), &dibSection) == sizeof(BITMAP))
+    if(GetObjectW(hbitmap, sizeof(DIBSECTION), &dibSection) != sizeof(DIBSECTION))
     {
         /* not a DIB section, use X11 behaviour */
         res = _DIBDRV_GetDisplayDriver()->pDeleteBitmap(hbitmap);
@@ -121,8 +115,22 @@ BOOL DIBDRV_DeleteBitmap( HBITMAP hbitmap )
     else
     {
         /* it's a DIB section, use DIB Engine behaviour */
-        ONCE(FIXME("STUB\n"));
-        res = TRUE;
+        
+        /* do not try to delete stock objects */
+        if(hbitmap == GetStockObject(DEFAULT_BITMAP))
+            res = TRUE;
+        
+        /* locates and frees the physical bitmap */
+        else if((bmp = _BITMAPLIST_Remove(hbitmap)) != NULL)
+        {
+            _DIBDRVBITMAP_Free(bmp);
+            res = TRUE;
+        }
+        else
+        {
+            ERR("Physical bitmap %p not found in internal list\n", hbitmap);
+            res = FALSE;
+        }
     }
     return res;
 }
diff --git a/dlls/winedib.drv/bitmaplist.c b/dlls/winedib.drv/bitmaplist.c
new file mode 100644
index 0000000..455f36a
--- /dev/null
+++ b/dlls/winedib.drv/bitmaplist.c
@@ -0,0 +1,168 @@
+/*
+ * DIBDRV in-memory bitmap list
+ *
+ * Copyright 2009 Massimo Del Fedele
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/* this modules manages association between HBITMAP handles and DIBDRVBITMAP
+ * physical bitmap objects. Needed mostly to get palettes from DIBs without
+ * resorting to GetDIBColorTable() or GETDIBits(), which are DC dependent.
+ * It makes also much easier (and faster) many bitmap operations */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include "dibdrv.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
+
+static CRITICAL_SECTION BITMAPLIST_CritSection;
+static CRITICAL_SECTION_DEBUG critsect_debug =
+{
+    0, 0, &BITMAPLIST_CritSection,
+    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": BITMAPLIST_CritSection") }
+};
+static CRITICAL_SECTION BITMAPLIST_CritSection = { &critsect_debug, -1, 0, 0, 0, 0 };
+
+typedef struct _BITMAPLIST_NODE
+{
+    HBITMAP hbmp;
+    DIBDRVBITMAP *bmp;
+    UINT refCount;
+    struct _BITMAPLIST_NODE *prev, *next;
+    
+} BITMAPLIST_NODE;
+
+/* the list */
+static BITMAPLIST_NODE *DIBDRV_BITMAPLIST;
+
+/* initializes bitmap list -- to be called at process attach */
+void _BITMAPLIST_Init(void)
+{
+    DIBDRV_BITMAPLIST = NULL;
+}
+
+/* terminates bitmap list -- to be called at process detach */
+void _BITMAPLIST_Terminate(void)
+{
+    BITMAPLIST_NODE *curNode, *nextNode;
+
+    EnterCriticalSection(&BITMAPLIST_CritSection);
+
+    /* frees all stored bitmaps, if any left */
+    curNode = DIBDRV_BITMAPLIST;
+    while(curNode)
+    {
+        nextNode = curNode->next;
+        ERR("Unfreed DIB found, handle is %p\n", curNode->hbmp);
+        HeapFree(GetProcessHeap(), 0, curNode);
+        curNode = nextNode;
+    }
+    DIBDRV_BITMAPLIST = NULL;
+    LeaveCriticalSection(&BITMAPLIST_CritSection);
+    DeleteCriticalSection(&BITMAPLIST_CritSection);
+}
+
+/* scan list for a DIB -- returns node containing it */
+static BITMAPLIST_NODE *GetNode(HBITMAP hbmp)
+{
+    BITMAPLIST_NODE *node = DIBDRV_BITMAPLIST;
+    while(node)
+    {
+        if(node->hbmp == hbmp)
+            return node;
+        node = node->next;
+    }
+    return NULL;
+}
+
+/* adds a DIB to the list - it adds it on top, as
+   usually most recently created DIBs are used first */
+BOOL _BITMAPLIST_Add(HBITMAP hbmp, DIBDRVBITMAP *bmp)
+{
+    BITMAPLIST_NODE *existNode, *node;
+    
+    EnterCriticalSection(&BITMAPLIST_CritSection);
+
+    /* checks if already there */
+    node = NULL;
+    existNode = GetNode(hbmp);
+    if(!existNode)
+    {
+        node = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPLIST_NODE));
+        if(!node)
+            ERR("HeapAlloc failed\n");
+        else
+        {
+            node->next = DIBDRV_BITMAPLIST;
+            node->prev = NULL;
+            DIBDRV_BITMAPLIST = node;
+            if(node->next)
+                node->next->prev = node;
+            node->hbmp = hbmp;
+            node->bmp = bmp;
+        }
+    }
+    LeaveCriticalSection(&BITMAPLIST_CritSection);
+    return !existNode && node;
+}
+
+/* removes a DIB from the list */
+DIBDRVBITMAP *_BITMAPLIST_Remove(HBITMAP hbmp)
+{
+    BITMAPLIST_NODE *node;
+    DIBDRVBITMAP *bmp;
+    
+    /* checks if already there */
+    EnterCriticalSection(&BITMAPLIST_CritSection);
+    node = GetNode(hbmp);
+    if(node)
+    {
+        if(node->prev)
+            node->prev->next = node->next;
+        else
+            DIBDRV_BITMAPLIST = node->next;
+        if(node->next)
+            node->next->prev = node->prev;
+    }
+    LeaveCriticalSection(&BITMAPLIST_CritSection);
+    if(node)
+    {
+        bmp = node->bmp;
+        HeapFree(GetProcessHeap(), 0, node);
+    }
+    else
+        bmp = NULL;
+    return bmp;    
+}
+
+/* scans list for a DIB */
+DIBDRVBITMAP *_BITMAPLIST_Get(HBITMAP hbmp)
+{
+    BITMAPLIST_NODE *node;
+    DIBDRVBITMAP *bmp;
+
+    EnterCriticalSection(&BITMAPLIST_CritSection);
+    node = GetNode(hbmp);
+    if(!node)
+        bmp = NULL;
+    else
+        bmp = node->bmp;
+    LeaveCriticalSection(&BITMAPLIST_CritSection);
+    return bmp;
+}
diff --git a/dlls/winedib.drv/dc.c b/dlls/winedib.drv/dc.c
index f5324b0..d2dae5f 100644
--- a/dlls/winedib.drv/dc.c
+++ b/dlls/winedib.drv/dc.c
@@ -165,8 +165,8 @@ BOOL DIBDRV_CreateDC( HDC hdc, DIBDRVPHYSDEV **pdev, LPCWSTR driver, LPCWSTR dev
     /* no DIB selected into DC on creation */
     physDev->hasDIB = FALSE;
     
-    /* clear physical bitmap */
-    _DIBDRVBITMAP_Clear(&physDev->physBitmap);
+    /* initializes the physical bitmap */
+    physDev->physBitmap = NULL;
     
     /* clears pen and brush */
     physDev->rop2 = R2_COPYPEN;
@@ -200,8 +200,8 @@ BOOL DIBDRV_CreateDC( HDC hdc, DIBDRVPHYSDEV **pdev, LPCWSTR driver, LPCWSTR dev
     physDev->brushHLine = dummy4;
     
     physDev->isBrushBitmap = FALSE;
-    _DIBDRVBITMAP_Clear(&physDev->brushBitmap);
-    _DIBDRVBITMAP_Clear(&physDev->brushBmpCache);
+    physDev->brushBitmap = NULL;
+    physDev->brushBmpCache = NULL;
     
     /* text color */
     physDev->textColor = 0;
@@ -234,12 +234,14 @@ BOOL DIBDRV_DeleteDC( DIBDRVPHYSDEV *physDev )
     res = _DIBDRV_GetDisplayDriver()->pDeleteDC(physDev->X11PhysDev);
     physDev->X11PhysDev = NULL;
     
-    /* frees physical bitmap */
-    _DIBDRVBITMAP_Free(&physDev->physBitmap);
+    /* resets physical bitmap */
+    physDev->physBitmap = NULL;
     
-    /* frees brush bitmap */
-    _DIBDRVBITMAP_Free(&physDev->brushBitmap);
-    _DIBDRVBITMAP_Free(&physDev->brushBmpCache);
+    /* reset brush bitmap */
+    _DIBDRVBITMAP_Free(physDev->brushBitmap);
+    physDev->brushBitmap = NULL;
+    _DIBDRVBITMAP_Free(physDev->brushBmpCache);
+    physDev->brushBmpCache = NULL;
     
     /* free brush ands and xors */
     if(physDev->brushAnds)
diff --git a/dlls/winedib.drv/dib.c b/dlls/winedib.drv/dib.c
index 41fb158..ae6a5cf 100644
--- a/dlls/winedib.drv/dib.c
+++ b/dlls/winedib.drv/dib.c
@@ -68,15 +68,44 @@ static DWORD pal8[] =
 HBITMAP DIBDRV_CreateDIBSection( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap,
                                  const BITMAPINFO *bmi, UINT usage )
 {
-    HBITMAP res;
+    DIBDRVBITMAP *bmp;
+    DIBSECTION ds;
     
     MAYBE(TRACE("physDev:%p, hbitmap:%p, bmi:%p, usage:%d\n", physDev, hbitmap, bmi, usage));
 
     /* createDIBSection is only DIB-related, so we just use the engine */
-    ONCE(FIXME("STUB\n"));
-    res = hbitmap;
 
-    return res;
+    /* we need bitmap bits */
+    if(GetObjectW(hbitmap, sizeof(DIBSECTION), &ds) != sizeof(DIBSECTION))
+    {
+        ERR("Bitmap is not a DIB Section\n");
+        return NULL;
+    }
+
+    /* creates the physical bitmap */
+    if(!(bmp = _DIBDRVBITMAP_CreateFromBitmapinfo(bmi, ds.dsBm.bmBits)))
+    {
+        ERR("_DIBDRVBITMAP_CreateFromBitmapinfo failed\n");
+        return NULL;
+    }
+    
+    /* TEMPORARY -- if usage is DIB_PAL_COLOR, sets the palette
+       as ungrabbed, so next call to RealizeDefaultPalette will
+       do it */
+    if(usage == DIB_PAL_COLORS)
+    {
+        FIXME("Do color table grabbing here instead of RealizeDefaultPalette\n");
+        bmp->colorTableGrabbed = FALSE;
+    }
+    
+    /* adds it to the internal list */
+    if(!_BITMAPLIST_Add(hbitmap, bmp))
+    {
+        ERR("Couldn't add physical bitmap to list\n");
+        _DIBDRVBITMAP_Free(bmp);
+        return NULL;
+    }
+    return hbitmap;
 }
 
 /***********************************************************************
@@ -87,15 +116,12 @@ INT DIBDRV_GetDIBits( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, UINT startscan,
 {
     INT res;
     DIBSECTION ds;
-    DIBDRVBITMAP sBmp, dBmp;
+    DIBDRVBITMAP *sBmp, *dBmp;
     DWORD *buf;
     int iLine;
     int size;
-    BOOL justInfo, justInfoHeader;
     int requestedBpp;
-    RGBQUAD *colorTable;
-    int colorTableSize;
-    BITMAPINFO *sourceInfo;
+    RGBQUAD *colorTable = NULL;
 
     MAYBE(TRACE("physDev:%p, hbitmap:%p, startscan:%d, lines:%d, bits:%p, info:%p, coloruse:%d\n",
         physDev, hbitmap, startscan, lines, bits, info, coloruse));
@@ -118,118 +144,46 @@ INT DIBDRV_GetDIBits( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, UINT startscan,
             return 0;
         }
         
-        /* get requested BPP */
-        requestedBpp = info->bmiHeader.biBitCount;
-        
-        /* check wetrher we wants just the BITMAPINFO data */
-        justInfo = (bits == NULL);
-        
-        /* check wether we wants just to get BITMAPINFOHEADER data */
-        justInfoHeader = (requestedBpp == 0);
-        
-        if(!justInfo && justInfoHeader)
+        /* if we wants just the BITMAPINFOHEADER data, do it */
+        if(bits == NULL && info->bmiHeader.biBitCount == 0)
         {
-            ERR("Bad requested BPP\n");
-            return 0;
+            memcpy(&info->bmiHeader, &ds.dsBmih, size);
+            return abs(ds.dsBmih.biHeight);
         }
-
-        /* copy / set missing DIB info */
-        if(justInfo)
-        {
-            info->bmiHeader.biWidth = ds.dsBmih.biWidth;
-            info->bmiHeader.biHeight = ds.dsBmih.biHeight;
-        }
-        info->bmiHeader.biPlanes = 1;
-        if(justInfoHeader)
-            info->bmiHeader.biBitCount = ds.dsBmih.biBitCount;
-        if(size == sizeof(BITMAPINFOHEADER))
-        {
-            if(justInfoHeader)
-            {
-                info->bmiHeader.biCompression = ds.dsBmih.biCompression;
-                info->bmiHeader.biXPelsPerMeter = ds.dsBmih.biXPelsPerMeter;
-                info->bmiHeader.biYPelsPerMeter = ds.dsBmih.biYPelsPerMeter;
-                info->bmiHeader.biClrUsed = ds.dsBmih.biClrUsed;
-                info->bmiHeader.biClrImportant = ds.dsBmih.biClrImportant;
-            }
-            info->bmiHeader.biSizeImage = ds.dsBmih.biSizeImage;
-        }
-
-        /* width and height *must* match source's ones */
-        if(info->bmiHeader.biWidth != ds.dsBmih.biWidth ||
-           abs(info->bmiHeader.biHeight) != abs(ds.dsBmih.biHeight))
+        
+        /* source and dest sizes must match */
+        if(info->bmiHeader.biWidth != ds.dsBmih.biWidth || abs(info->bmiHeader.biHeight) != abs(ds.dsBmih.biHeight))
         {
-            ERR("Size of requested bitmap data don't match source's ones\n");
+            WARN("Source and dest DIBs sizes don't match\n");
             return 0;
         }
-
-        /* if we just wants the BITMAPINFOHEADER data, we're done */
-        if(justInfoHeader || (justInfo && ds.dsBmih.biBitCount > 8))
-            return abs(info->bmiHeader.biHeight);
-            
-        /* we now have to get source data -- we need it for palette, for example */
-        colorTableSize = 0;
-        if(ds.dsBmih.biBitCount <= 8)
-            colorTableSize = (1 << ds.dsBmih.biBitCount);
-        else if(ds.dsBmih.biCompression == BI_BITFIELDS)
-            colorTableSize = 3;
-        sourceInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER) + colorTableSize * sizeof(RGBQUAD));
-        if(!sourceInfo)
+        
+        /* get requested BPP and check it */
+        requestedBpp = info->bmiHeader.biBitCount;
+        if(requestedBpp !=  1 && requestedBpp !=  4 &&
+           requestedBpp !=  8 && requestedBpp != 16 &&
+           requestedBpp != 24 && requestedBpp != 32)
         {
-            ERR("HeapAlloc failed\n");
+            ERR("Unknown BitCount %d\n", requestedBpp);
             return 0;
         }
-        memcpy(sourceInfo, &ds.dsBmih, sizeof(BITMAPINFOHEADER));
-        if(ds.dsBmih.biBitCount <= 8)
-        {
-            /* grab palette - well, we should. No way to do it by now....
-               we should add a list HBITMAP <--> DIBDRVBITMAP and fiddle to many
-               , many parts of the engine. Not worth the effort by now.
-               So, we just synthesize the table */
-            switch(requestedBpp)
-            {
-                case 1:
-                    memcpy((BYTE *)sourceInfo + sizeof(BITMAPINFOHEADER), pal1, 2*sizeof(DWORD));
-                    break;
-                    
-                case 4:
-                    memcpy((BYTE *)sourceInfo + sizeof(BITMAPINFOHEADER), pal4, 16*sizeof(DWORD));
-                    break;
-                
-                case 8:
-                    memcpy((BYTE *)sourceInfo + sizeof(BITMAPINFOHEADER), pal8, 256*sizeof(DWORD));
-                    break;
-                    
-                default:
-                    ERR("Unknown requested bith depth %d\n", requestedBpp);
-                    _DIBDRVBITMAP_Free(&sBmp);
-                    return 0;
-            }
-        }
-        else if(ds.dsBmih.biCompression == BI_BITFIELDS)
-            memcpy((BYTE *)sourceInfo + sizeof(BITMAPINFOHEADER), ds.dsBitfields, 3 * sizeof(RGBQUAD));
-        _DIBDRVBITMAP_Clear(&sBmp);
-        if(!_DIBDRVBITMAP_InitFromBitmapinfo(&sBmp, sourceInfo))
+        
+        /* now we must get (if needed) the color table */
+        if(!(sBmp = _BITMAPLIST_Get(hbitmap)))
         {
-            ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n");
-            HeapFree(GetProcessHeap(), 0, sourceInfo);
+            ERR("Couldn't retrieve source DIB data\n");
             return 0;
         }
-        _DIBDRVBITMAP_Set_Bits(&sBmp, ds.dsBm.bmBits, FALSE);
-        HeapFree(GetProcessHeap(), 0, sourceInfo);
-                
-        /* now grab / synthesize the color table if needed */
         if(requestedBpp <= 8)
         {
             colorTable = (RGBQUAD *)((BYTE *)info + size);
-            if(requestedBpp == ds.dsBmih.biBitCount)
-            {
-                /* same source and dest format - copy color tables */
-                memcpy(colorTable, sBmp.colorTable, colorTableSize);
-            }
+            
+            /* if same color format, just grab the color table */
+            if(requestedBpp == sBmp->bitCount)
+                memcpy(colorTable, sBmp->colorTable, sBmp->colorTableSize);
+            /* otherwise synthesize a new color table */
             else
             {
-                /* different formats -- synthesize color table */
                 switch(requestedBpp)
                 {
                     case 1:
@@ -246,38 +200,33 @@ INT DIBDRV_GetDIBits( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, UINT startscan,
                         
                     default:
                         ERR("Unknown requested bith depth %d\n", requestedBpp);
-                        _DIBDRVBITMAP_Free(&sBmp);
                         return 0;
                 }
             }
         }
         
-        /* if we just wanted DIB info, job is done */
-        if(justInfo)
-        {
-            _DIBDRVBITMAP_Free(&sBmp);
-            return abs(info->bmiHeader.biHeight);
-        }
-        
-        /* Creates a DIBDRVBITMAP from dest dib */
-        _DIBDRVBITMAP_Clear(&dBmp);
-        if(!_DIBDRVBITMAP_InitFromBitmapinfo(&dBmp, info))
+        /* If we wanted just BITMAPINFO data, we're done */
+        if(!bits)
+            return abs(ds.dsBmih.biHeight);
+
+        /* now it's time to transfer image bits; for this we should create
+           a DIBDRVBITMAP from dest BITMAPINFO data */
+        /* FIXME -- HERE is the place to add support for 'startscan' stuffs */
+        if(!(dBmp = _DIBDRVBITMAP_CreateFromBMIH((BITMAPINFOHEADER *)info, ds.dsBitfields, colorTable, bits)))
         {
-            ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n");
-            _DIBDRVBITMAP_Free(&sBmp);
+            ERR("Couldn't create dest DIB\n");
             return 0;
         }
-        _DIBDRVBITMAP_Set_Bits(&dBmp, bits, FALSE);
         
         /* now we can do the bit conversion */
         buf = HeapAlloc(GetProcessHeap(), 0, ds.dsBmih.biWidth * sizeof(RGBQUAD));
         for(iLine = 0; iLine < lines; iLine++)
         {
-            sBmp.funcs->GetLine(&sBmp, iLine, 0, ds.dsBmih.biWidth, buf);
-            dBmp.funcs->PutLine(&dBmp, iLine, 0, ds.dsBmih.biWidth, buf);
+            sBmp->funcs->GetLine(sBmp, iLine, 0, ds.dsBmih.biWidth, buf);
+            dBmp->funcs->PutLine(dBmp, iLine, 0, ds.dsBmih.biWidth, buf);
         }
-        _DIBDRVBITMAP_Free(&sBmp);
-        _DIBDRVBITMAP_Free(&dBmp);
+        HeapFree(GetProcessHeap(), 0, buf);
+        _DIBDRVBITMAP_Free(dBmp);
         return lines;
     }
     else
@@ -293,13 +242,11 @@ INT DIBDRV_GetDIBits( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, UINT startscan,
 UINT DIBDRV_SetDIBColorTable( DIBDRVPHYSDEV *physDev, UINT start, UINT count,
                               const RGBQUAD *colors )
 {
-    DIBDRVBITMAP *dib = &physDev->physBitmap;
-#if 0
-    HBITMAP thisDIB;
-#endif
+    DIBDRVBITMAP *dib = physDev->physBitmap;
+    HBRUSH thisBrush;
+    HPEN thisPen;
 
     MAYBE(TRACE("physDev:%p, start:%d, count:%d, colors:%p\n", physDev, start, count, colors));
-
     /* SetDIBColorTable operates on a DIB, so we use the engine */
     
     /* if bpp > 8, some error occurred... */
@@ -334,13 +281,16 @@ UINT DIBDRV_SetDIBColorTable( DIBDRVPHYSDEV *physDev, UINT start, UINT count,
     }
     memcpy(dib->colorTable + start, colors, sizeof(RGBQUAD) * count);
     dib->colorTableGrabbed = TRUE;
-
-    /* hack to make GDI32 sense the DIB color table change
-       (fixes a couple of todos in bitmap test suite */
-#if 0
-    thisDIB = SelectObject(physDev->hdc, GetStockObject(OBJ_BITMAP));
-    SelectObject(physDev->hdc, thisDIB);
-#endif
+    
+    /* for monochrome bitmaps, we need the 'lightest' color */
+    _DIBDRVBITMAP_GetLightestColorIndex(dib);
+    
+    /* we should re-select both current pen and brush
+       in order to update colormap-dependent colors */
+    thisBrush = SelectObject(physDev->hdc, GetStockObject(NULL_BRUSH));    
+    thisPen = SelectObject(physDev->hdc, GetStockObject(NULL_PEN));
+    SelectObject(physDev->hdc, thisBrush);    
+    SelectObject(physDev->hdc, thisPen);    
 
     return TRUE;
 }
@@ -353,7 +303,7 @@ INT DIBDRV_SetDIBits( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, UINT startscan,
 {
     INT res;
     DIBSECTION ds;
-    DIBDRVBITMAP sBmp, dBmp;
+    DIBDRVBITMAP *sBmp, *dBmp;
     DWORD *buf;
     int iLine;
     
@@ -373,31 +323,29 @@ INT DIBDRV_SetDIBits( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, UINT startscan,
         }
         
         /* Creates a DIBDRVBITMAP from source dib */
-        _DIBDRVBITMAP_Clear(&sBmp);
-        if(!_DIBDRVBITMAP_InitFromBitmapinfo(&sBmp, info))
+        if(!(sBmp = _DIBDRVBITMAP_CreateFromBitmapinfo(info, (LPVOID)bits)))
         {
-            ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n");
+            ERR("_DIBDRVBITMAP_CreateFromBitmapinfo failed\n");
             return 0;
         }
-        _DIBDRVBITMAP_Set_Bits(&sBmp, (LPVOID)bits, FALSE);
         
-        /* same for destination dib */
-        if(!_DIBDRVBITMAP_InitFromHBITMAP(&dBmp, hbitmap, FALSE))
+        /* get destination physical bitmap */
+        if(!(dBmp = _BITMAPLIST_Get(hbitmap)))
         {
-            ERR("_DIBDRVBITMAP_InitFromHBITMAP failed\n");
-            _DIBDRVBITMAP_Free(&sBmp);
+            ERR("Couldn't retrieve dest physical bitmap\n");
+            _DIBDRVBITMAP_Free(sBmp);
             return 0;
         }
-        
+            
         /* now we can do the bit conversion */
         buf = HeapAlloc(GetProcessHeap(), 0, ds.dsBmih.biWidth * sizeof(RGBQUAD));
         for(iLine = 0; iLine < lines; iLine++)
         {
-            sBmp.funcs->GetLine(&sBmp, iLine, 0, ds.dsBmih.biWidth, buf);
-            dBmp.funcs->PutLine(&dBmp, iLine, 0, ds.dsBmih.biWidth, buf);
+            sBmp->funcs->GetLine(sBmp, iLine, 0, ds.dsBmih.biWidth, buf);
+            dBmp->funcs->PutLine(dBmp, iLine, 0, ds.dsBmih.biWidth, buf);
         }
-        _DIBDRVBITMAP_Free(&sBmp);
-        _DIBDRVBITMAP_Free(&dBmp);
+        HeapFree(GetProcessHeap(), 0, buf);
+        _DIBDRVBITMAP_Free(sBmp);
         return lines;
     }
     else
@@ -411,34 +359,35 @@ INT DIBDRV_SetDIBits( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, UINT startscan,
 /*************************************************************************
  *              DIBDRV_SetDIBitsToDevice
  */
-INT DIBDRV_SetDIBitsToDevice( DIBDRVPHYSDEV *physDev, INT xDest, INT yDest, DWORD cx,
+INT DIBDRV_SetDIBitsToDevice( DIBDRVPHYSDEV *physDev, INT xDst, INT yDst, DWORD cx,
                               DWORD cy, INT xSrc, INT ySrc,
                               UINT startscan, UINT lines, LPCVOID bits,
                               const BITMAPINFO *info, UINT coloruse )
 {
-    BITMAPINFO *bitmapInfo;
-    int bmInfoSize;
     int dibHeight, dibWidth;
-    DIBDRVBITMAP sBmp;
-    int sLine, dLine, iLine;
+    DIBDRVBITMAP *sBmp, *dBmp;
+    int iLine;
     void *buf;
     
-    MAYBE(TRACE("physDev:%p, xDest:%d, yDest:%d, cx:%x, cy:%x, xSrc:%d, ySrc:%d, startscan:%d, lines:%d, bits:%p, info:%p, coloruse:%d\n",
-        physDev, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, bits, info, coloruse));
+    MAYBE(TRACE("physDev:%p, xDst:%d, yDst:%d, cx:%x, cy:%x, xSrc:%d, ySrc:%d, startscan:%d, lines:%d, bits:%p, info:%p, coloruse:%d\n",
+        physDev, xDst, yDst, cx, cy, xSrc, ySrc, startscan, lines, bits, info, coloruse));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
         
         /* inverts y on source -- FIXME: check if right with some tests, it seems so */
-        ySrc = abs(info->bmiHeader.biHeight) - ySrc - cy;
+//        ySrc = abs(info->bmiHeader.biHeight) - ySrc - cy;
         
         dibHeight = info->bmiHeader.biHeight;
         dibWidth = info->bmiHeader.biWidth;
 
         /* sanity check and source clipping on physical sizes */
         if(startscan >= abs(dibHeight))
+        {
+            ERR("startscan out of range\n");
             return 0;
+        }
         if(startscan + lines > abs(dibHeight))
             lines = abs(dibHeight) - startscan;
 
@@ -446,75 +395,63 @@ INT DIBDRV_SetDIBitsToDevice( DIBDRVPHYSDEV *physDev, INT xDest, INT yDest, DWOR
         dibHeight += (dibHeight > 0 ? -startscan : startscan);
 
         if(xSrc >= dibWidth)
+        {
+            ERR("xSrc out of range\n");
             return 0;
+        }
         if(xSrc + cx > dibWidth)
             cx = dibWidth - xSrc;
         if(ySrc > abs(dibHeight))
+        {
+            ERR("ySrc out of range\n");
             return 0;
+        }
         if(ySrc + cy > abs(dibHeight))
             cy = abs(dibHeight) - ySrc;
             
         ySrc -= startscan;
         cy -= startscan;
         if(cy <= 0)
+        {
+            ERR("Null or negative vertical size\n");
             return 0;
+        }
         if(ySrc < 0)
         {
-            yDest += ySrc;
+            yDst += ySrc;
             cy += ySrc;
             ySrc = 0;
         }
         if(cy <= 0)
-            return 0;
-
-        /* grab a copy of BITMAPINFO */
-        bmInfoSize = sizeof(BITMAPINFOHEADER);
-        if(info->bmiHeader.biCompression == BI_BITFIELDS)
-            bmInfoSize += 3 * sizeof(RGBQUAD);
-        else if (info->bmiHeader.biBitCount <= 8)
-        {
-            if(info->bmiHeader.biClrUsed)
-                bmInfoSize += info->bmiHeader.biClrUsed * sizeof(RGBQUAD);
-            else
-                bmInfoSize += (1 << info->bmiHeader.biBitCount) * sizeof(RGBQUAD);
-        }
-        if(!(bitmapInfo = HeapAlloc(GetProcessHeap(), 0, bmInfoSize)))
         {
-            ERR("HeapAlloc failed\n");
+            ERR("Null or negative vertical size\n");
             return 0;
         }
-        memcpy(bitmapInfo, info, bmInfoSize);
-        bitmapInfo->bmiHeader.biHeight = dibHeight;
 
-        /* create a DIBDRVBITMAP from BITMAPINFO data */
-        _DIBDRVBITMAP_Clear(&sBmp);
-        if(!_DIBDRVBITMAP_InitFromBitmapinfo(&sBmp, bitmapInfo))
+        /* Creates a DIBDRVBITMAP from source dib */
+        if(!(sBmp = _DIBDRVBITMAP_CreateFromBitmapinfo(info, (LPVOID)bits)))
         {
-            ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n");
-            HeapFree(GetProcessHeap, 0, bitmapInfo);
+            ERR("_DIBDRVBITMAP_CreateFromBitmapinfo failed\n");
             return 0;
         }
-        HeapFree(GetProcessHeap(), 0, bitmapInfo);
-        _DIBDRVBITMAP_Set_Bits(&sBmp, (LPVOID)bits, FALSE);
         
-        /* transfer lines to dest bitmap */
-        if(!(buf = HeapAlloc(GetProcessHeap(), 0, cx * sizeof(RGBQUAD))))
-        {
-            ERR("HeapAlloc failed\n");
-            return 0;
-        }
-        for(sLine = ySrc, dLine = yDest, iLine = 0; iLine < cy; sLine++, dLine++, iLine++)
+        /* get destination physical bitmap */
+        dBmp = physDev->physBitmap;
+
+        /* now we can do the bit conversion */
+        buf = HeapAlloc(GetProcessHeap(), 0, cx * sizeof(RGBQUAD));
+        for(iLine = 0; iLine < cy; iLine++)
         {
-            sBmp.funcs->GetLine(&sBmp, sLine, xSrc, cx, buf); 
-            physDev->physBitmap.funcs->PutLine(&physDev->physBitmap, dLine, xDest, cx, buf);
+            sBmp->funcs->GetLine(sBmp, ySrc++, xSrc, cx, buf);
+            dBmp->funcs->PutLine(dBmp, yDst++, xDst, cx, buf);
         }
         HeapFree(GetProcessHeap(), 0, buf);
-
+        _DIBDRVBITMAP_Free(sBmp);
         return cy;
     }
     else
     {
-        return _DIBDRV_GetDisplayDriver()->pSetDIBitsToDevice(physDev->X11PhysDev, xDest, yDest, cx, cy, xSrc, ySrc,
+        return _DIBDRV_GetDisplayDriver()->pSetDIBitsToDevice(physDev->X11PhysDev, xDst, yDst, cx, cy, xSrc, ySrc,
                                                             startscan, lines, bits, info, coloruse);
     }
 }
diff --git a/dlls/winedib.drv/dibdrv.h b/dlls/winedib.drv/dibdrv.h
index 8243d4b..4266703 100644
--- a/dlls/winedib.drv/dibdrv.h
+++ b/dlls/winedib.drv/dibdrv.h
@@ -171,6 +171,9 @@ typedef struct _DIBDRVBITMAP
     RGBQUAD *colorTable;
     DWORD colorTableSize;
     
+    /* lightest color index, for monochrome bitmaps */
+    int lightColor;
+    
     /* flag indicating that color table has been grabbed */
     BOOL colorTableGrabbed;
 
@@ -203,7 +206,7 @@ typedef struct _DIBDRVPHYSDEV
     HBITMAP hbitmap;
     
     /* physical bitmap */
-    DIBDRVBITMAP physBitmap;
+    DIBDRVBITMAP *physBitmap;
 
     /* active ROP2 */
     INT rop2;
@@ -249,8 +252,8 @@ typedef struct _DIBDRVPHYSDEV
     
     /* brush bitmap, if needed, and its converted/resized cache copy */
     BOOL isBrushBitmap;
-    DIBDRVBITMAP brushBitmap;
-    DIBDRVBITMAP brushBmpCache;
+    DIBDRVBITMAP *brushBitmap;
+    DIBDRVBITMAP *brushBmpCache;
     
     /* text color */
     COLORREF textColor;
@@ -317,7 +320,10 @@ const char *_DIBDRVBITMAP_GetFormatName(DIBDRVBITMAP const *bmp);
 void _DIBDRVBITMAP_Set_Bits(DIBDRVBITMAP *dib, void *bits, BOOL owns);
 void *_DIBDRVBITMAP_Get_Bits(DIBDRVBITMAP *dib);
 
-/* initializes dib from a bitmap : 
+/* calculates and sets the lightest color for monochrome bitmaps */
+int _DIBDRVBITMAP_GetLightestColorIndex(DIBDRVBITMAP *dib);
+
+/* initialize or create dib from a bitmap : 
     dib           dib being initialized
     bi            source BITMAPINFOHEADER with required DIB format info
     bit_fields    color masks
@@ -326,8 +332,11 @@ void *_DIBDRVBITMAP_Get_Bits(DIBDRVBITMAP *dib);
     NOTE : DIBDRVBITMAP doesn't owns bits, but do own color table */
 BOOL _DIBDRVBITMAP_InitFromBMIH(DIBDRVBITMAP *dib, const BITMAPINFOHEADER *bi, const DWORD *bit_fields,
                                 const RGBQUAD *color_table, void *bits);
+DIBDRVBITMAP *_DIBDRVBITMAP_CreateFromBMIH(const BITMAPINFOHEADER *bi, const DWORD *bit_fields,
+                     const RGBQUAD *colorTable, void *bits);
 
-BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, const BITMAPINFO *bmi);
+BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, const BITMAPINFO *bmi, void *bits);
+DIBDRVBITMAP *_DIBDRVBITMAP_CreateFromBitmapinfo(const BITMAPINFO *bmi, void *bits);
 
 /* initializes a DIBRDVBITMAP copying it from a source one
    Parameters :
@@ -336,13 +345,6 @@ BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, const BITMAPINFO *bmi);
       copy      TRUE->copy source pixel array FALSE->link to source pixel array */
 BOOL _DIBDRVBITMAP_InitFromDibdrvbitmap(DIBDRVBITMAP *dib, const DIBDRVBITMAP *src, BOOL copy);
 
-/* initializes a DIBRDVBITMAP from a DIB HBITMAP
-   Parameters :
-      bmp           destination DIBDRVBITMAP
-      hbmp          source HBITMAP
-      copyPixels    TRUE->copy source pixel array FALSE->link to source pixel array */
-BOOL _DIBDRVBITMAP_InitFromHBITMAP(DIBDRVBITMAP *bmp, const HBITMAP hbmp, BOOL copyPixels);
-
 /* creates a DIBRDVBITMAP copying format info from a source one
    Parameters :
       dib            destination DIBDRVBITMAP
@@ -350,13 +352,16 @@ BOOL _DIBDRVBITMAP_InitFromHBITMAP(DIBDRVBITMAP *bmp, const HBITMAP hbmp, BOOL c
       widht, height  sizes of newly created bitmap  */
 BOOL _DIBDRVBITMAP_CreateFromDibdrvbitmap(DIBDRVBITMAP *dib, const DIBDRVBITMAP *src, int width, int height);
 
+/* allocates a new DIBDTVBITMAP */
+DIBDRVBITMAP *_DIBDRVBITMAP_New(void);
+
+/* Frees and de-allocates a DIBDRVBITMAP structure data */
+void _DIBDRVBITMAP_Free(DIBDRVBITMAP *bmp);
+
 /* Clears a DIBDRVBITMAP structure data
    WARNING : doesn't free anything */
 void _DIBDRVBITMAP_Clear(DIBDRVBITMAP *bmp);
 
-/* Frees a DIBDRVBITMAP structure data */
-void _DIBDRVBITMAP_Free(DIBDRVBITMAP *bmp);
-
 /* checks whether the format of 2 DIBs are identical
    it checks the pixel bit count and the color table size
    and content, if needed */
@@ -375,6 +380,26 @@ BOOL _DIBDRVBITMAP_CreateSolid(DIBDRVBITMAP *bmp, DIBDRVBITMAP *format, int widt
 BOOL _DIBDRVBITMAP_ExpandHoriz(DIBDRVBITMAP *dib, int baseWidth, int minWidth);
 
 /* *********************************************************************
+ * BITMAP LIST MANAGEMENT FUNCTIONS
+ * ********************************************************************/
+
+/* initializes bitmap list -- to be called at process attach */
+void _BITMAPLIST_Init(void);
+
+/* terminates bitmap list -- to be called at process detach */
+void _BITMAPLIST_Terminate(void);
+
+/* adds a DIB to the list - it adds it on top, as
+   usually most recently created DIBs are used first */
+BOOL _BITMAPLIST_Add(HBITMAP hbmp, DIBDRVBITMAP *bmp);
+
+/* removes a DIB from the list */
+DIBDRVBITMAP *_BITMAPLIST_Remove(HBITMAP hbmp);
+
+/* scans list for a DIB */
+DIBDRVBITMAP *_BITMAPLIST_Get(HBITMAP hbmp);
+
+/* *********************************************************************
  * DIB <--> DDB CONVERSION ROUTINES
  * ********************************************************************/
 
diff --git a/dlls/winedib.drv/dibdrv_main.c b/dlls/winedib.drv/dibdrv_main.c
index e436440..119a294 100644
--- a/dlls/winedib.drv/dibdrv_main.c
+++ b/dlls/winedib.drv/dibdrv_main.c
@@ -42,6 +42,9 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
         /* initializes freetype library */
         if(!_DIBDRV_FreeType_Init())
             ERR("Couldn't initialize freetype library.\n");
+            
+        /* initializes internal bitmap list */
+        _BITMAPLIST_Init();
 
         break;
     case DLL_THREAD_DETACH:
@@ -55,6 +58,9 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
         /* unloads display driver */
         _DIBDRV_FreeDisplayDriver();
 
+        /* terminates internal bitmap list */
+        _BITMAPLIST_Terminate();
+
         break;
     }
     return ret;
diff --git a/dlls/winedib.drv/dibdrvbitmap.c b/dlls/winedib.drv/dibdrvbitmap.c
index 8e6b653..eb7d1e2 100644
--- a/dlls/winedib.drv/dibdrvbitmap.c
+++ b/dlls/winedib.drv/dibdrvbitmap.c
@@ -142,6 +142,33 @@ void *_DIBDRVBITMAP_Get_Bits(DIBDRVBITMAP * dib)
     }
 }
 
+/* calculates and sets the lightest color for monochrome bitmaps */
+int _DIBDRVBITMAP_GetLightestColorIndex(DIBDRVBITMAP *dib)
+{
+    DWORD foreRed, foreGreen, foreBlue;
+    DWORD backRed, backGreen, backBlue;
+    RGBQUAD *fore, *back;
+    
+    /* zero for non-monochrome bitmaps */
+    if(dib->bitCount != 1)
+        return 0;
+    /* just in case color table hasn't been grabbed yet */
+    if(!dib->colorTableGrabbed)
+        return 1;
+    back = dib->colorTable;
+    fore = back + 1;
+    foreRed = fore->rgbRed; foreGreen = fore->rgbGreen; foreBlue = fore->rgbBlue;
+    backRed = back->rgbRed; backGreen = back->rgbGreen; backBlue = back->rgbBlue;
+    if(foreRed*foreRed + foreGreen*foreGreen + foreBlue*foreBlue >
+       backRed*backRed + backGreen*backGreen + backBlue*backBlue)
+    {
+        dib->lightColor = 1;
+        return 1;
+    }
+    dib->lightColor = 0;
+    return 0;
+}
+
 /* initializes dib from a bitmap : 
     dib           dib being initialized
     bi            source BITMAPINFOHEADER with required DIB format info
@@ -264,6 +291,9 @@ BOOL _DIBDRVBITMAP_InitFromBMIH(DIBDRVBITMAP *dib, const BITMAPINFOHEADER *bi, c
         memcpy(dib->colorTable, colorTable,
             dib->colorTableSize * sizeof(dib->colorTable[0]));
         dib->colorTableGrabbed = TRUE;
+
+        /* for monochrome bitmaps, we need the 'lightest' color */
+        _DIBDRVBITMAP_GetLightestColorIndex(dib);
     }
     else if(!dib->colorTableSize)
         /* no color table on more than 8 bits/pixel */
@@ -273,16 +303,64 @@ BOOL _DIBDRVBITMAP_InitFromBMIH(DIBDRVBITMAP *dib, const BITMAPINFOHEADER *bi, c
     return TRUE;
 }
 
-BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, const BITMAPINFO *bmi)
+DIBDRVBITMAP *_DIBDRVBITMAP_CreateFromBMIH(const BITMAPINFOHEADER *bi, const DWORD *bit_fields,
+                     const RGBQUAD *colorTable, void *bits)
+{
+    DIBDRVBITMAP *bmp = _DIBDRVBITMAP_New();
+    if(bmp && !_DIBDRVBITMAP_InitFromBMIH(bmp, bi, bit_fields, colorTable, bits))
+    {
+        _DIBDRVBITMAP_Free(bmp);
+        bmp = NULL;
+    }
+    return bmp;
+}
+
+/* gets a BITMAPINFOHEADER from a soure BITMAPINFO- or BITMAPCORE-header */
+static BITMAPINFOHEADER *GetBitmapInfoHeader(BITMAPINFO const *bmi)
+{
+    BITMAPINFOHEADER *res = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
+    
+    int size = bmi->bmiHeader.biSize;
+    if(size >= sizeof(BITMAPINFOHEADER))
+    {
+        memcpy(res, bmi, sizeof(BITMAPINFOHEADER));
+        res->biSize = sizeof(BITMAPINFOHEADER);
+    }
+    else if(size == sizeof(BITMAPCOREHEADER))
+    {
+        BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)bmi;
+        res->biSize = sizeof(BITMAPINFOHEADER);
+        res->biWidth = core->bcWidth;
+        res->biHeight = core->bcHeight;
+        res->biPlanes = core->bcPlanes;
+        res->biBitCount = core->bcBitCount;
+    }
+    else
+    {
+        HeapFree(GetProcessHeap(), 0, res);
+        ERR("Bad/unknown header size %d\n", size);
+        res = NULL;
+    }
+    return res;
+}
+
+BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, const BITMAPINFO *bmi, void *bits)
 {
     static const DWORD bit_fields_DIB32_RGB[3] = {0xff0000, 0x00ff00, 0x0000ff};
     static const DWORD bit_fields_DIB16_RGB[3] = {0x7c00, 0x03e0, 0x001f};
-    BITMAPINFOHEADER *bi = (BITMAPINFOHEADER *)bmi;
     const DWORD *masks = NULL;
     RGBQUAD *colorTable = NULL;
-    BYTE *ptr = (BYTE*)bmi + bi->biSize;
-    int num_colors = bi->biClrUsed;
+    BITMAPINFOHEADER *bi;
+    BYTE *ptr;
+    int num_colors;
     BOOL res;
+
+    /* gets info header */
+    if(!(bi = GetBitmapInfoHeader(bmi)))
+        return FALSE;
+        
+    ptr = (BYTE*)bmi + bmi->bmiHeader.biSize;
+    num_colors = bi->biClrUsed;
     
     MAYBE(TRACE("dib=%p, bmi=%p\n", dib, bmi));
 
@@ -302,11 +380,23 @@ BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, const BITMAPINFO *bmi)
         colorTable = (RGBQUAD*)ptr;
     ptr += num_colors * sizeof(*colorTable);
 
-    res = _DIBDRVBITMAP_InitFromBMIH(dib, bi, masks, colorTable, ptr);
+    res = _DIBDRVBITMAP_InitFromBMIH(dib, bi, masks, colorTable, bits ? bits : ptr);
+    HeapFree(GetProcessHeap(), 0, bi);
     MAYBE(TRACE("END\n"));
     return res;
 }
 
+DIBDRVBITMAP *_DIBDRVBITMAP_CreateFromBitmapinfo(const BITMAPINFO *bmi, void *bits)
+{
+    DIBDRVBITMAP *bmp = _DIBDRVBITMAP_New();
+    if(bmp && !_DIBDRVBITMAP_InitFromBitmapinfo(bmp, bmi, bits))
+    {
+        _DIBDRVBITMAP_Free(bmp);
+        bmp = NULL;
+    }
+    return bmp;
+}
+
 /* initializes a DIBRDVBITMAP copying it from a source one
    Parameters :
       dib       destination DIBDRVBITMAP
@@ -335,6 +425,8 @@ BOOL _DIBDRVBITMAP_InitFromDibdrvbitmap(DIBDRVBITMAP *dib, const DIBDRVBITMAP *s
 
     dib->funcs = src->funcs;
     
+    dib->lightColor = src->lightColor;
+    
     if(copy)
     {
         int size = dib->height*abs(dib->stride);
@@ -378,92 +470,6 @@ BOOL _DIBDRVBITMAP_InitFromDibdrvbitmap(DIBDRVBITMAP *dib, const DIBDRVBITMAP *s
     return TRUE;
 }
 
-/* initializes a DIBRDVBITMAP from a DIB HBITMAP
-   Parameters :
-      bmp           destination DIBDRVBITMAP
-      hbmp          source HBITMAP
-      copyPixels    TRUE->copy source pixel array FALSE->link to source pixel array */
-BOOL _DIBDRVBITMAP_InitFromHBITMAP(DIBDRVBITMAP *bmp, const HBITMAP hbmp, BOOL copyPixels)
-{
-    BITMAPINFO *destInfo;
-    DIBSECTION ds;
-    int size;
-    
-    MAYBE(TRACE("bmp=%p, hbmp=%p, copyPixels = %s\n", bmp, hbmp, copyPixels ? "TRUE" : "FALSE"));
-
-    /* be sure bitmap is empty */
-    _DIBDRVBITMAP_Clear(bmp);
-    
-    /* gets source bitmap data */
-    if(!(size = GetObjectW(hbmp, sizeof(DIBSECTION), &ds)))
-    {
-        ERR("Failed getting bitmap object\n");
-        return FALSE;
-    }
-    if(size != sizeof(DIBSECTION))
-    {
-        ERR("Bitmap is not a DIB section\n");
-        return FALSE;
-    }
-    
-    destInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
-    if(!destInfo)
-    {
-        ERR("HeapAlloc failed\n");
-        return FALSE;
-    }
-    
-    memcpy(destInfo, &ds.dsBmih, sizeof(BITMAPINFOHEADER));
-    if(ds.dsBmih.biCompression == BI_BITFIELDS)
-        memcpy((BITMAPINFOHEADER *)destInfo + 1, ds.dsBitfields, 3 * sizeof(RGBQUAD));
-    else if(ds.dsBmih.biBitCount <= 8)
-    {
-        FIXME("Can't grab color table here.... syslvel lock\n");
-        return FALSE;
-#if 0
-        HDC refDC = CreateCompatibleDC(0);
-        if(!refDC)
-        {
-            ERR("CreateCompatibleDC() failed\n");
-            return FALSE;
-        }
-        if(!GetDIBits(refDC, hbmp, 0, 1, NULL, destInfo, DIB_RGB_COLORS))
-        {
-            DeleteDC(refDC);
-            HeapFree(GetProcessHeap(), 0, destInfo);
-            ERR("GetDIBits failed\n");
-            return FALSE;
-        }
-        DeleteDC(refDC);
-#endif
-    }
-    if(!_DIBDRVBITMAP_InitFromBitmapinfo(bmp, destInfo))
-    {
-        HeapFree(GetProcessHeap(), 0, destInfo);
-        ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n");
-        return FALSE;
-    }
-    HeapFree(GetProcessHeap(), 0, destInfo);
-    if(copyPixels)
-    {
-        size = abs(bmp->stride) * bmp->height;
-        if(!(bmp->bits = HeapAlloc(GetProcessHeap(), 0, size)))
-        {
-            ERR("HeapAlloc failed\n");
-            _DIBDRVBITMAP_Free(bmp);
-            return FALSE;
-        }
-        memcpy(bmp->bits, ds.dsBm.bmBits, size);
-        bmp->ownsBits = TRUE;
-    }
-    else
-        bmp->bits = ds.dsBm.bmBits;
-    if(bmp->stride < 0)
-        bmp->bits    = (BYTE*)bmp->bits - (bmp->height - 1) * bmp->stride;
-    
-    return TRUE;
-}
-
 
 /* creates a DIBRDVBITMAP copying format info from a source one
    Parameters :
@@ -512,6 +518,8 @@ void _DIBDRVBITMAP_Clear(DIBDRVBITMAP *bmp)
 {
     MAYBE(TRACE("bmp=%p\n", bmp));
     
+    if(!bmp)
+        return;
     bmp->bits = NULL;
     bmp->ownsBits = FALSE;
     bmp->colorTable = NULL;
@@ -521,11 +529,23 @@ void _DIBDRVBITMAP_Clear(DIBDRVBITMAP *bmp)
     MAYBE(TRACE("END\n"));
 }
 
+/* allocates a new DIBDTVBITMAP */
+DIBDRVBITMAP *_DIBDRVBITMAP_New(void)
+{
+    DIBDRVBITMAP *bmp = HeapAlloc(GetProcessHeap(), 0, sizeof(DIBDRVBITMAP));
+    if(!bmp)
+        return NULL;
+    _DIBDRVBITMAP_Clear(bmp);
+    return bmp;
+}
+
 /* Frees a DIBDRVBITMAP structure data */
 void _DIBDRVBITMAP_Free(DIBDRVBITMAP *bmp)
 {
     MAYBE(TRACE("bmp=%p\n", bmp));
     
+    if(!bmp)
+        return;
     /* frees bits, if needed */
     if(bmp->bits && bmp->ownsBits)
     {
@@ -535,17 +555,12 @@ void _DIBDRVBITMAP_Free(DIBDRVBITMAP *bmp)
             bmp->bits = (BYTE *)bmp->bits + bmp->stride * (bmp->height -1);
         HeapFree(GetProcessHeap(), 0, bmp->bits);
     }
-    bmp->ownsBits = FALSE;
-    bmp->bits = NULL;
-    
     /* frees color table */
     if(bmp->colorTable)
         HeapFree(GetProcessHeap(), 0, bmp->colorTable);
-    bmp->colorTable = NULL;
-    bmp->colorTableSize = 0;
-    bmp->colorTableGrabbed = FALSE;
+
+    HeapFree(GetProcessHeap(), 0, bmp);
     
-    MAYBE(TRACE("END\n"));
 }
 
 
diff --git a/dlls/winedib.drv/font.c b/dlls/winedib.drv/font.c
index f7ea8dc..bcfbaba 100644
--- a/dlls/winedib.drv/font.c
+++ b/dlls/winedib.drv/font.c
@@ -93,7 +93,7 @@ COLORREF DIBDRV_SetTextColor( DIBDRVPHYSDEV *physDev, COLORREF color )
 
 #ifdef DIBDRV_ANTIALIASED_FONTS        
         /* fills the text color table used on antialiased font display */
-        if(physDev->physBitmap.funcs)
+        if(physDev->physBitmap->funcs)
         {
             BYTE r, g, b;
             INT i;
@@ -103,7 +103,7 @@ COLORREF DIBDRV_SetTextColor( DIBDRVPHYSDEV *physDev, COLORREF color )
             b = GetBValue(color);
             for(i = 0; i < 256; i++)
             {
-                physDev->textColorTable[i] = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, RGB(
+                physDev->textColorTable[i] = physDev->physBitmap->funcs->ColorToPixel(physDev->physBitmap, RGB(
                     MulDiv(r, i, 255),
                     MulDiv(g, i, 255),
                     MulDiv(b, i, 255)
diff --git a/dlls/winedib.drv/graphics.c b/dlls/winedib.drv/graphics.c
index 4aebe8e..1fd155d 100644
--- a/dlls/winedib.drv/graphics.c
+++ b/dlls/winedib.drv/graphics.c
@@ -517,7 +517,7 @@ COLORREF DIBDRV_GetPixel( DIBDRVPHYSDEV *physDev, int x, int y )
     if(physDev->hasDIB)
     {
         _DIBDRV_Position_ws2ds(physDev, &x, &y);
-        res = physDev->physBitmap.funcs->GetPixel(&physDev->physBitmap, x, y);
+        res = physDev->physBitmap->funcs->GetPixel(physDev->physBitmap, x, y);
     }
     else
     {
@@ -976,18 +976,18 @@ COLORREF DIBDRV_SetPixel( DIBDRVPHYSDEV *physDev, int x, int y, COLORREF color )
         color = _DIBDRV_MapColor(physDev, color);
         
         /* map to pixel color / palette index */
-        color = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, color);
+        color = physDev->physBitmap->funcs->ColorToPixel(physDev->physBitmap, color);
         
         _DIBDRV_Position_ws2ds(physDev, &x, &y);
 
         /* gets previous pixel */
-        res = physDev->physBitmap.funcs->GetPixel(&physDev->physBitmap, x, y);
+        res = physDev->physBitmap->funcs->GetPixel(physDev->physBitmap, x, y);
      
         /* calculates AND and XOR from color */
         _DIBDRV_CalcAndXorMasks(GetROP2(physDev->hdc), color, &and, &xor);
         
         /* sets the pixel */
-        physDev->physBitmap.funcs->SetPixel(&physDev->physBitmap, x, y, and, xor);
+        physDev->physBitmap->funcs->SetPixel(physDev->physBitmap, x, y, and, xor);
     }
     else
     {
diff --git a/dlls/winedib.drv/palette.c b/dlls/winedib.drv/palette.c
index 87016da..301cf1d 100644
--- a/dlls/winedib.drv/palette.c
+++ b/dlls/winedib.drv/palette.c
@@ -38,12 +38,12 @@ COLORREF _DIBDRV_MapColor(DIBDRVPHYSDEV *physDev, COLORREF color)
         case 0x10 : /* DIBINDEX */
             MAYBE(TRACE("DIBINDEX Color is %08x\n", color));
             index =  color & 0xffff;
-            if(index >= physDev->physBitmap.colorTableSize)
+            if(index >= physDev->physBitmap->colorTableSize)
             {
-                WARN("DIBINDEX color out of range\n");
+                WARN("DIBINDEX color %d out of range, color table size is %d\n", index, physDev->physBitmap->colorTableSize);
                 return 0;
             }
-            palColor = physDev->physBitmap.colorTable + index;
+            palColor = physDev->physBitmap->colorTable + index;
             MAYBE(TRACE("Returning color %08x\n", RGB(palColor->rgbRed, palColor->rgbGreen, palColor->rgbBlue)));
             return RGB(palColor->rgbRed, palColor->rgbGreen, palColor->rgbBlue);
             
@@ -64,24 +64,36 @@ COLORREF _DIBDRV_MapColor(DIBDRVPHYSDEV *physDev, COLORREF color)
             return RGB(paletteEntry.peRed, paletteEntry.peGreen, paletteEntry.peBlue);
         
         case 0x02: /* PALETTERGB */
-            return _DIBDRV_GetNearestColor(&physDev->physBitmap, color & 0xffffff);
+            return _DIBDRV_GetNearestColor(physDev->physBitmap, color & 0xffffff);
         
         default:
             /* RGB color -- we must process special case for monochrome bitmaps */
-            if(physDev->physBitmap.bitCount == 1)
+            if(physDev->physBitmap->bitCount == 1)
             {
-                RGBQUAD *back = physDev->physBitmap.colorTable;
+                RGBQUAD *back = physDev->physBitmap->colorTable;
                 RGBQUAD *fore = back+1;
-                if(fore->rgbRed * fore->rgbRed + fore->rgbGreen * fore->rgbGreen + fore->rgbBlue * fore->rgbBlue <
-                   back->rgbRed * back->rgbRed + back->rgbGreen * back->rgbGreen + back->rgbBlue * back->rgbBlue)
+                COLORREF lightColorref, darkColorref;
+                
+                /* lightest color is considered to be 'foreground' one, i.e. associated to white color */
+                if(physDev->physBitmap->lightColor == 1)
                 {
-                    fore = back;
-                    back = fore + 1;
+                    darkColorref = RGB(back->rgbRed, back->rgbGreen, back->rgbBlue);
+                    lightColorref = RGB(fore->rgbRed, fore->rgbGreen, fore->rgbBlue);
                 }
-                if ( ((color >> 16) & 0xff) + ((color >>  8) & 0xff) + (color & 0xff) > 255*3/2)
-                    return RGB(fore->rgbRed, fore->rgbGreen, fore->rgbBlue);
                 else
-                    return RGB(back->rgbRed, back->rgbGreen, back->rgbBlue);
+                {
+                    darkColorref = RGB(fore->rgbRed, fore->rgbGreen, fore->rgbBlue);
+                    lightColorref = RGB(back->rgbRed, back->rgbGreen, back->rgbBlue);
+                }
+                
+                /* tested on Windows XP -- if present in colortable, maps to corresponding color
+                   if not, if white maps to the lightest color, otherwise darkest one. */
+                if(color == lightColorref || color == darkColorref)
+                    return color;
+                else if (color == 0x00ffffff)
+                    return lightColorref;
+                else
+                    return darkColorref;
             }
             else
                 return color;
@@ -200,20 +212,24 @@ UINT DIBDRV_RealizeDefaultPalette( DIBDRVPHYSDEV *physDev )
         /* HACK - we can't get the dib color table during SelectBitmap since it hasn't
            been initialized yet.  This is called from DC_InitDC so it's a convenient place
            to grab the color table. */
-        MAYBE(TRACE("Color table size = %d, Color table = %p\n", physDev->physBitmap.colorTableSize, physDev->physBitmap.colorTable));
-        if(!physDev->physBitmap.colorTableGrabbed)
+        MAYBE(TRACE("Color table size = %d, Color table = %p\n", physDev->physBitmap->colorTableSize, physDev->physBitmap->colorTable));
+        if(!physDev->physBitmap->colorTableGrabbed)
         {
             MAYBE(TRACE("Grabbing palette\n"));
-            physDev->physBitmap.colorTable = HeapAlloc(GetProcessHeap(), 0, sizeof(physDev->physBitmap.colorTable[0]) * physDev->physBitmap.colorTableSize);
-            GetDIBColorTable(physDev->hdc, 0, physDev->physBitmap.colorTableSize, physDev->physBitmap.colorTable);
+            physDev->physBitmap->colorTable = HeapAlloc(GetProcessHeap(), 0, sizeof(physDev->physBitmap->colorTable[0]) * physDev->physBitmap->colorTableSize);
+            GetDIBColorTable(physDev->hdc, 0, physDev->physBitmap->colorTableSize, physDev->physBitmap->colorTable);
 #ifdef DIBDRV_ENABLE_MAYBE 
-           for(i = 0; i < physDev->physBitmap.colorTableSize; i++)
+           for(i = 0; i < physDev->physBitmap->colorTableSize; i++)
             {
-                q = physDev->physBitmap.colorTable + i;
+                q = physDev->physBitmap->colorTable + i;
                 TRACE("  %03d : R%03d G%03d B%03d\n", i, q->rgbRed, q->rgbGreen, q->rgbBlue);
             }
 #endif
-            physDev->physBitmap.colorTableGrabbed = TRUE;
+            physDev->physBitmap->colorTableGrabbed = TRUE;
+
+            /* for monochrome bitmaps, we need the 'lightest' color */
+            _DIBDRVBITMAP_GetLightestColorIndex(physDev->physBitmap);
+    
         }
         res = 0;
     }
diff --git a/dlls/winedib.drv/pen_brush.c b/dlls/winedib.drv/pen_brush.c
index c40bfaf..32d50fb 100644
--- a/dlls/winedib.drv/pen_brush.c
+++ b/dlls/winedib.drv/pen_brush.c
@@ -48,20 +48,20 @@ static inline void OrderEndPoints(int *s, int *e)
 static void SolidPenHLine(DIBDRVPHYSDEV *physDev, int x1, int x2, int y)
 {
     OrderEndPoints(&x1, &x2);
-    physDev->physBitmap.funcs->SolidHLine(&physDev->physBitmap, x1, x2, y, physDev->penAnd, physDev->penXor);
+    physDev->physBitmap->funcs->SolidHLine(physDev->physBitmap, x1, x2, y, physDev->penAnd, physDev->penXor);
 }
 
 static void SolidPenVLine(DIBDRVPHYSDEV *physDev, int x, int y1, int y2)
 {
     OrderEndPoints(&y1, &y2);
-    physDev->physBitmap.funcs->SolidVLine(&physDev->physBitmap, x, y1, y2, physDev->penAnd, physDev->penXor);
+    physDev->physBitmap->funcs->SolidVLine(physDev->physBitmap, x, y1, y2, physDev->penAnd, physDev->penXor);
 }
 
 static void WINAPI SolidPenLineCallback(int x, int y, LPARAM lparam)
 {
     DIBDRVPHYSDEV *physDev = (DIBDRVPHYSDEV *)lparam;
 
-    physDev->physBitmap.funcs->SetPixel(&physDev->physBitmap, x, y, physDev->penAnd, physDev->penXor);
+    physDev->physBitmap->funcs->SetPixel(physDev->physBitmap, x, y, physDev->penAnd, physDev->penXor);
     return;
 }
 
@@ -120,7 +120,7 @@ static void DashedPenHLine(DIBDRVPHYSDEV *physDev, int x1, int x2, int y)
             if(x + dashLen > x2)
                 dashLen = x2 - x;
 
-            physDev->physBitmap.funcs->SolidHLine(&physDev->physBitmap, x, x + dashLen, y, and, xor);
+            physDev->physBitmap->funcs->SolidHLine(physDev->physBitmap, x, x + dashLen, y, and, xor);
             x += dashLen;
 
             physDev->leftInDash -= dashLen;
@@ -137,7 +137,7 @@ static void DashedPenHLine(DIBDRVPHYSDEV *physDev, int x1, int x2, int y)
             if(x - (int)dashLen < x2)
                 dashLen = x - x2;
 
-            physDev->physBitmap.funcs->SolidHLine(&physDev->physBitmap, x - dashLen + 1, x + 1, y, and, xor);
+            physDev->physBitmap->funcs->SolidHLine(physDev->physBitmap, x - dashLen + 1, x + 1, y, and, xor);
             x -= dashLen;
 
             physDev->leftInDash -= dashLen;
@@ -162,7 +162,7 @@ static void DashedPenVLine(DIBDRVPHYSDEV *physDev, int x, int y1, int y2)
             if(y + dashLen > y2)
                 dashLen = y2 - y;
 
-            physDev->physBitmap.funcs->SolidVLine(&physDev->physBitmap, x, y, y + dashLen, and, xor);
+            physDev->physBitmap->funcs->SolidVLine(physDev->physBitmap, x, y, y + dashLen, and, xor);
             y += dashLen;
 
             physDev->leftInDash -= dashLen;
@@ -179,7 +179,7 @@ static void DashedPenVLine(DIBDRVPHYSDEV *physDev, int x, int y1, int y2)
             if(y - (int)dashLen < y2)
                 dashLen = y - y2;
 
-            physDev->physBitmap.funcs->SolidVLine(&physDev->physBitmap, x, y - dashLen + 1, y + 1, and, xor);
+            physDev->physBitmap->funcs->SolidVLine(physDev->physBitmap, x, y - dashLen + 1, y + 1, and, xor);
             y -= dashLen;
 
             physDev->leftInDash -= dashLen;
@@ -195,7 +195,7 @@ static void WINAPI DashedPenLineCallback(int x, int y, LPARAM lparam)
 
     GetDashColors(physDev, &and, &xor);
 
-    physDev->physBitmap.funcs->SetPixel(&physDev->physBitmap, x, y, and, xor);
+    physDev->physBitmap->funcs->SetPixel(physDev->physBitmap, x, y, and, xor);
 
     physDev->leftInDash--;
     NextDash(physDev);
@@ -222,8 +222,8 @@ void _DIBDRV_ResetDashOrigin(DIBDRVPHYSDEV *physDev)
    the background color is used -- tested on WinXP */
 static DWORD AdjustFgColor(DIBDRVPHYSDEV *physDev, COLORREF color)
 {
-    RGBQUAD *back = physDev->physBitmap.colorTable;
-    RGBQUAD *fore = physDev->physBitmap.colorTable+1;
+    RGBQUAD *back = physDev->physBitmap->colorTable;
+    RGBQUAD *fore = physDev->physBitmap->colorTable+1;
     
     if(
       fore->rgbRed   == GetRValue(color) &&
@@ -270,9 +270,9 @@ static DWORD AdjustFgColor(DIBDRVPHYSDEV *physDev, COLORREF color)
     rgb.rgbGreen = GetGValue(color);
     rgb.rgbBlue  = GetBValue(color);
 
-    for(i = 0; i < physDev->physBitmap.colorTableSize; i++)
+    for(i = 0; i < physDev->physBitmap->colorTableSize; i++)
     {
-        RGBQUAD *cur = physDev->physBitmap.colorTable + i;
+        RGBQUAD *cur = physDev->physBitmap->colorTable + i;
         if((rgb.rgbRed == cur->rgbRed) && (rgb.rgbGreen == cur->rgbGreen) && (rgb.rgbBlue == cur->rgbBlue))
             return i;
     }
@@ -298,7 +298,7 @@ static void FixupFgColors1(DIBDRVPHYSDEV *physDev)
 static void SolidBrushHLine(DIBDRVPHYSDEV *physDev, int x1, int x2, int y)
 {
     OrderEndPoints(&x1, &x2);
-    physDev->physBitmap.funcs->SolidHLine(&physDev->physBitmap, x1, x2, y, physDev->brushAnd, physDev->brushXor);
+    physDev->physBitmap->funcs->SolidHLine(physDev->physBitmap, x1, x2, y, physDev->brushAnd, physDev->brushXor);
 }
 
 
@@ -324,16 +324,16 @@ static void GenerateMasks(DIBDRVPHYSDEV *physDev, DIBDRVBITMAP *bmp, DWORD **and
 
 static void PatternBrushHLine(DIBDRVPHYSDEV *physDev, int x1, int x2, int y)
 {
-    DWORD *and, *xor, brushY = y % physDev->brushBitmap.height;
+    DWORD *and, *xor, brushY = y % physDev->brushBitmap->height;
 
     if(!physDev->brushAnds)
-        GenerateMasks(physDev, &physDev->brushBitmap, &physDev->brushAnds, &physDev->brushXors);
+        GenerateMasks(physDev, physDev->brushBitmap, &physDev->brushAnds, &physDev->brushXors);
 
     OrderEndPoints(&x1, &x2);
-    and = (DWORD *)((char *)physDev->brushAnds + brushY * physDev->brushBitmap.stride);
-    xor = (DWORD *)((char *)physDev->brushXors + brushY * physDev->brushBitmap.stride);
+    and = (DWORD *)((char *)physDev->brushAnds + brushY * physDev->brushBitmap->stride);
+    xor = (DWORD *)((char *)physDev->brushXors + brushY * physDev->brushBitmap->stride);
 
-    physDev->physBitmap.funcs->PatternHLine(&physDev->physBitmap, x1, x2, y, and, xor, physDev->brushBitmap.width, x1 % physDev->brushBitmap.width);
+    physDev->physBitmap->funcs->PatternHLine(physDev->physBitmap, x1, x2, y, and, xor, physDev->brushBitmap->width, x1 % physDev->brushBitmap->width);
 }
 
 /* null function for PS_NULL and BS_NULL pen and brush styles */
@@ -356,8 +356,10 @@ HPEN DIBDRV_SelectPen( DIBDRVPHYSDEV *physDev, HPEN hpen )
     {
         GetObjectW(hpen, sizeof(logpen), &logpen);
 
-        physDev->penColorref = _DIBDRV_MapColor(physDev, logpen.lopnColor);
-        physDev->penColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, physDev->penColorref);
+        physDev->penColorref = logpen.lopnColor;
+        physDev->penColor = physDev->physBitmap->funcs->ColorToPixel(
+          physDev->physBitmap,
+          _DIBDRV_MapColor(physDev, physDev->penColorref));
 
         _DIBDRV_CalcAndXorMasks(GetROP2(physDev->hdc), physDev->penColor, &physDev->penAnd, &physDev->penXor);
 
@@ -441,8 +443,10 @@ HBRUSH DIBDRV_SelectBrush( DIBDRVPHYSDEV *physDev, HBRUSH hbrush )
         GetObjectW(hbrush, sizeof(logbrush), &logbrush);
 
         /* frees any currently selected DIB brush and cache */
-        _DIBDRVBITMAP_Free(&physDev->brushBitmap);
-        _DIBDRVBITMAP_Free(&physDev->brushBmpCache);
+        _DIBDRVBITMAP_Free(physDev->brushBitmap);
+        physDev->brushBitmap = NULL;
+        _DIBDRVBITMAP_Free(physDev->brushBmpCache);
+        physDev->brushBmpCache = NULL;
         if(physDev->brushAnds)
         {
             HeapFree(GetProcessHeap(), 0, physDev->brushAnds);
@@ -459,13 +463,15 @@ HBRUSH DIBDRV_SelectBrush( DIBDRVPHYSDEV *physDev, HBRUSH hbrush )
                 goto solid;
                 
             case BS_SOLID:
-                physDev->brushColorref = _DIBDRV_MapColor(physDev, logbrush.lbColor);
+                physDev->brushColorref = logbrush.lbColor;
     solid:
                 MAYBE(TRACE("SOLID Pattern -- color is %x\n", physDev->brushColorref));
                 physDev->brushStyle = BS_SOLID;
                 physDev->brushHLine = SolidBrushHLine;
 
-                physDev->brushColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, physDev->brushColorref);
+                physDev->brushColor = physDev->physBitmap->funcs->ColorToPixel(
+                  physDev->physBitmap,
+                  _DIBDRV_MapColor(physDev, physDev->brushColorref));
 
                 _DIBDRV_CalcAndXorMasks(physDev->rop2, physDev->brushColor,
                                            &physDev->brushAnd, &physDev->brushXor);
@@ -485,7 +491,7 @@ HBRUSH DIBDRV_SelectBrush( DIBDRVPHYSDEV *physDev, HBRUSH hbrush )
                 FIXME("DIB Pattern\n");
                 
                 /* if no DIB selected in, fallback to null brush */
-                if(!physDev->physBitmap.bits)
+                if(!physDev->physBitmap->bits)
                 {
                     physDev->brushColorref = 0;
                     goto solid;
@@ -495,7 +501,7 @@ HBRUSH DIBDRV_SelectBrush( DIBDRVPHYSDEV *physDev, HBRUSH hbrush )
                 bmi = GlobalLock16(logbrush.lbHatch);
         
                 /* initializes a temporary DIB with brush's one */
-                if(!_DIBDRVBITMAP_InitFromBitmapinfo(&src, bmi))
+                if(!_DIBDRVBITMAP_InitFromBitmapinfo(&src, bmi, NULL))
                 {
                     ERR("Failed to initialize brush DIB\n");
                     res = 0;
@@ -503,7 +509,7 @@ HBRUSH DIBDRV_SelectBrush( DIBDRVPHYSDEV *physDev, HBRUSH hbrush )
                 }
                 
                 /* converts brush bitmap to match currently selected one's format */
-                if(!_DIBDRVBITMAP_Convert(&physDev->brushBitmap, &src, &physDev->physBitmap))
+                if(!_DIBDRVBITMAP_Convert(physDev->brushBitmap, &src, physDev->physBitmap))
                 {
                     ERR("Failed to convert brush DIB\n");
                     _DIBDRVBITMAP_Free(&src);
@@ -537,7 +543,9 @@ HBRUSH DIBDRV_SelectBrush( DIBDRVPHYSDEV *physDev, HBRUSH hbrush )
             {
                 MAYBE(TRACE("NULL Pattern\n"));
                 physDev->brushColorref = 0;
-                physDev->brushColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, 0);
+                physDev->brushColor = physDev->physBitmap->funcs->ColorToPixel(
+                  physDev->physBitmap,
+                  _DIBDRV_MapColor(physDev, 0));
                 physDev->brushHLine = NullBrushHLine;
                 break;
             }
@@ -644,7 +652,7 @@ COLORREF DIBDRV_SetBkColor( DIBDRVPHYSDEV *physDev, COLORREF color )
     if(physDev->hasDIB)
     {
         physDev->backgroundColor = _DIBDRV_MapColor(physDev, color);
-        physDev->backgroundColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, physDev->backgroundColor);
+        physDev->backgroundColor = physDev->physBitmap->funcs->ColorToPixel(physDev->physBitmap, physDev->backgroundColor);
 
         _DIBDRV_CalcAndXorMasks(physDev->rop2, physDev->backgroundColor, &physDev->backgroundAnd, &physDev->backgroundXor);
         
diff --git a/dlls/winedib.drv/primitives_bitblt.c b/dlls/winedib.drv/primitives_bitblt.c
index 27d573f..3505277 100644
--- a/dlls/winedib.drv/primitives_bitblt.c
+++ b/dlls/winedib.drv/primitives_bitblt.c
@@ -169,8 +169,8 @@ BOOL _DIBDRV_AlphaBlend_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
     BYTE constAlpha = blendFn.SourceConstantAlpha;
     
     /* source and dest bitmaps */
-    const DIBDRVBITMAP *srcBmp = &physDevSrc->physBitmap;
-    DIBDRVBITMAP *dstBmp = &physDevDst->physBitmap;
+    const DIBDRVBITMAP *srcBmp = physDevSrc->physBitmap;
+    DIBDRVBITMAP *dstBmp = physDevDst->physBitmap;
     
     /* source and destination line buffers */
     DWORD *sBuf = HeapAlloc(GetProcessHeap(), 0, abs(srcBmp->stride));
@@ -403,15 +403,15 @@ BOOL _DIBDRV_BitBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
     
     /* gets source, dest and pattern bitmaps, if available */
     if(usePat && physDevDst->isBrushBitmap)
-        patBmp = &physDevDst->brushBmpCache;
+        patBmp = physDevDst->brushBmpCache;
     else
         patBmp = NULL;
 
     if(useSrc)
-        srcBmp = &physDevSrc->physBitmap;
+        srcBmp = physDevSrc->physBitmap;
     else
         srcBmp = NULL;
-    dstBmp = &physDevDst->physBitmap;
+    dstBmp = physDevDst->physBitmap;
     
     /* gets pattern color, in case it's needed
        it's NOT the COLORREF value (colors are swapped
@@ -656,15 +656,15 @@ BOOL _DIBDRV_StretchBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
     
     /* gets source, dest and pattern bitmaps, if available */
     if(usePat && physDevDst->isBrushBitmap)
-        patBmp = &physDevDst->brushBmpCache;
+        patBmp = physDevDst->brushBmpCache;
     else
         patBmp = NULL;
 
     if(useSrc)
-        srcBmp = &physDevSrc->physBitmap;
+        srcBmp = physDevSrc->physBitmap;
     else
         srcBmp = NULL;
-    dstBmp = &physDevDst->physBitmap;
+    dstBmp = physDevDst->physBitmap;
     
     /* gets pattern color, in case it's needed
        it's NOT the COLORREF value (colors are swapped
diff --git a/dlls/winedib.drv/primitives_color.c b/dlls/winedib.drv/primitives_color.c
index 6c42b44..93baf43 100644
--- a/dlls/winedib.drv/primitives_color.c
+++ b/dlls/winedib.drv/primitives_color.c
@@ -142,32 +142,30 @@ DWORD _DIBDRV_GetNearestColorIndex(const DIBDRVBITMAP *dib, COLORREF color)
 
 DWORD _DIBDRV_ColorToPixelColortable(const DIBDRVBITMAP *dib, COLORREF color)
 {
-    DWORD r, g, b;
-
-    r = GetRValue(color);
-    g = GetGValue(color);
-    b = GetBValue(color);
-    
     /* just in case it's being called without color table
        properly initialized */
     if(!dib->colorTableGrabbed)
         return 0;
         
+    color &= 0xffffff;
+        
     /* for monochrome bitmaps, color is :
            foreground if matching foreground ctable
            else background if matching background ctable
-           else foreground ix 0xffffff
+           else foreground if 0xffffff
            else background */
     if(dib->colorTableSize == 2)
     {
         RGBQUAD *back = dib->colorTable;
         RGBQUAD *fore = dib->colorTable + 1;
-        if(r == fore->rgbRed && g == fore->rgbGreen && b == fore->rgbBlue)
+        COLORREF backColorref = RGB(back->rgbRed, back->rgbGreen, back->rgbBlue);
+        COLORREF foreColorref = RGB(fore->rgbRed, fore->rgbGreen, fore->rgbBlue);
+        if(color == foreColorref)
             return 1;
-        else if(r == back->rgbRed && g == back->rgbGreen && b == back->rgbBlue)
+        else if(color == backColorref)
             return 0;
-        if((color & 0xffffff) == 0xffffff)
-            return 1;
+        else if(color == 0xffffff)
+            return dib->lightColor;
         else
             return 0;
     }
diff --git a/dlls/winedib.drv/primitives_convert.c b/dlls/winedib.drv/primitives_convert.c
index 24a5e77..7c4da14 100644
--- a/dlls/winedib.drv/primitives_convert.c
+++ b/dlls/winedib.drv/primitives_convert.c
@@ -537,6 +537,9 @@ BOOL _DIBDRV_PutLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width,
     /* get foreground color */
     DWORD back = *(DWORD *)bmp->colorTable       & 0x00ffffff;
     DWORD fore = *((DWORD *)bmp->colorTable + 1) & 0x00ffffff;
+    
+    /* get 'light' color */
+    int lightColor = bmp->lightColor;
 
     /* put first partial byte, if any */
     startx &= 0x07;
@@ -553,7 +556,7 @@ BOOL _DIBDRV_PutLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width,
                 b |= mask;
             else if(c == back)
                 b &= !mask;
-            else if(c == 0x00ffffff)
+            else if((c == 0x00ffffff && lightColor) || (c == 0 && !lightColor))
                 b |= mask;
             else
                 b &= !mask;
@@ -570,7 +573,7 @@ BOOL _DIBDRV_PutLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width,
         for(i = 0 ; i < 8 ; i++)
         {
             c = *dwBuf++ & 0x00ffffff;
-            if(c == fore || (c == 0x00ffffff && c != back))
+            if(c == fore || (c == 0x00ffffff && c != back && lightColor) || (c == 0 && !lightColor))
                 b |= mask;
             mask >>= 1;
         }
@@ -589,7 +592,7 @@ BOOL _DIBDRV_PutLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width,
                 b |= mask;
             else if(c == back)
                 b &= !mask;
-            else if(c == 0x00ffffff)
+            else if((c == 0x00ffffff && lightColor) || (c == 0 && !lightColor))
                 b |= mask;
             else
                 b &= !mask;
diff --git a/dlls/winedib.drv/primitives_font.c b/dlls/winedib.drv/primitives_font.c
index e604a39..a2824a5 100644
--- a/dlls/winedib.drv/primitives_font.c
+++ b/dlls/winedib.drv/primitives_font.c
@@ -31,7 +31,7 @@ void _DIBDRV_freetype_blit_8888(DIBDRVPHYSDEV *physDev, int x, int y, RECT *clip
 {
     /* FIXME : MUST BE OPTIMIZED !!! */
     
-    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    DIBDRVBITMAP *dib = physDev->physBitmap;
     int bmpX, bmpY;
     BYTE *buf;
     int dibX, dibY;
@@ -84,7 +84,7 @@ void _DIBDRV_freetype_blit_32_RGB(DIBDRVPHYSDEV *physDev, int x, int y, RECT *cl
 {
     /* FIXME : MUST BE OPTIMIZED !!! */
     
-    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    DIBDRVBITMAP *dib = physDev->physBitmap;
     int bmpX, bmpY;
     BYTE *buf;
     int dibX, dibY;
@@ -137,7 +137,7 @@ void _DIBDRV_freetype_blit_32_BITFIELDS(DIBDRVPHYSDEV *physDev, int x, int y, RE
 {
     /* FIXME : MUST BE OPTIMIZED !!! */
     
-    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    DIBDRVBITMAP *dib = physDev->physBitmap;
     int bmpX, bmpY;
     BYTE *buf;
     int dibX, dibY;
@@ -189,7 +189,7 @@ void _DIBDRV_freetype_blit_24(DIBDRVPHYSDEV *physDev, int x, int y, RECT *clipRe
 {
     /* FIXME : MUST BE OPTIMIZED !!! */
     
-    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    DIBDRVBITMAP *dib = physDev->physBitmap;
     int bmpX, bmpY;
     BYTE *buf;
     int dibX, dibY;
@@ -241,7 +241,7 @@ void _DIBDRV_freetype_blit_16_RGB(DIBDRVPHYSDEV *physDev, int x, int y, RECT *cl
 {
     /* FIXME : MUST BE OPTIMIZED !!! */
     
-    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    DIBDRVBITMAP *dib = physDev->physBitmap;
     int bmpX, bmpY;
     BYTE *buf;
     int dibX, dibY;
@@ -293,7 +293,7 @@ void _DIBDRV_freetype_blit_16_BITFIELDS(DIBDRVPHYSDEV *physDev, int x, int y, RE
 {
     /* FIXME : MUST BE OPTIMIZED !!! */
     
-    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    DIBDRVBITMAP *dib = physDev->physBitmap;
     int bmpX, bmpY;
     BYTE *buf;
     int dibX, dibY;
@@ -345,7 +345,7 @@ void _DIBDRV_freetype_blit_8(DIBDRVPHYSDEV *physDev, int x, int y, RECT *clipRec
 {
     /* FIXME : MUST BE OPTIMIZED !!! */
     
-    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    DIBDRVBITMAP *dib = physDev->physBitmap;
     int bmpX, bmpY;
     BYTE *buf;
     int dibX, dibY;
@@ -375,7 +375,7 @@ void _DIBDRV_freetype_blit_4(DIBDRVPHYSDEV *physDev, int x, int y, RECT *clipRec
 {
     /* FIXME : MUST BE OPTIMIZED !!! */
     
-    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    DIBDRVBITMAP *dib = physDev->physBitmap;
     int bmpX, bmpY;
     BYTE *buf;
     int dibX, dibY;
@@ -405,7 +405,7 @@ void _DIBDRV_freetype_blit_1(DIBDRVPHYSDEV *physDev, int x, int y, RECT *clipRec
 {
     /* FIXME : MUST BE OPTIMIZED !!! */
     
-    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    DIBDRVBITMAP *dib = physDev->physBitmap;
     int bmpX, bmpY;
     BYTE *buf;
     int dibX, dibY;
diff --git a/dlls/winedib.drv/text.c b/dlls/winedib.drv/text.c
index 0ae3575..94c7992 100644
--- a/dlls/winedib.drv/text.c
+++ b/dlls/winedib.drv/text.c
@@ -120,7 +120,7 @@ BOOL DIBDRV_ExtTextOut( DIBDRVPHYSDEV *physDev, INT x, INT y, UINT flags,
                 {
                     /* paints the backgound */
                     for(iLine = tr.top; iLine < tr.bottom; iLine++)
-                        physDev->physBitmap.funcs->SolidHLine(&physDev->physBitmap,
+                        physDev->physBitmap->funcs->SolidHLine(physDev->physBitmap,
                             tr.left, tr.right-1, iLine, 0, backPixel);
                 }
             }
@@ -187,7 +187,7 @@ BOOL DIBDRV_ExtTextOut( DIBDRVPHYSDEV *physDev, INT x, INT y, UINT flags,
                     error = pFT_Glyph_To_Bitmap(
                         &glyph,
     #ifdef DIBDRV_ANTIALIASED_FONTS        
-                        physDev->physBitmap.bitCount > 8 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO,
+                        physDev->physBitmap->bitCount > 8 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO,
     #else
                         FT_RENDER_MODE_MONO,
     #endif
@@ -220,7 +220,7 @@ BOOL DIBDRV_ExtTextOut( DIBDRVPHYSDEV *physDev, INT x, INT y, UINT flags,
                 }
 
                 /* now, draw to our target surface */
-                physDev->physBitmap.funcs->FreetypeBlit(physDev, x+bitmapGlyph->left, y-bitmapGlyph->top, &clipRec, bitmap);
+                physDev->physBitmap->funcs->FreetypeBlit(physDev, x+bitmapGlyph->left, y-bitmapGlyph->top, &clipRec, bitmap);
                 
                 /* frees converted bitmap, if any */
                 if(bitmap != &bitmapGlyph->bitmap)