Index: trunk/src/comctl32/comctl32.c
===================================================================
--- trunk/src/comctl32/comctl32.c	(revision 163)
+++ trunk/src/comctl32/comctl32.c	(revision 164)
@@ -1,3 +1,3 @@
-/* $Id: comctl32.c,v 1.5 1999-06-10 16:21:58 achimha Exp $ */
+/* $Id: comctl32.c,v 1.6 1999-06-23 19:45:00 achimha Exp $ */
 /*
  * Win32 common controls implementation
@@ -313,7 +313,7 @@
     UINT border = BDR_SUNKENOUTER;
 
-    if (style == SBT_POPOUT)
+    if (style & SBT_POPOUT)
       border = BDR_RAISEDOUTER;
-    else if (style == SBT_NOBORDERS)
+    else if (style & SBT_NOBORDERS)
       border = 0;
 
Index: trunk/src/comctl32/comctl32undoc.c
===================================================================
--- trunk/src/comctl32/comctl32undoc.c	(revision 163)
+++ trunk/src/comctl32/comctl32undoc.c	(revision 164)
@@ -1,3 +1,3 @@
-/* $Id: comctl32undoc.c,v 1.6 1999-06-10 16:21:58 achimha Exp $ */
+/* $Id: comctl32undoc.c,v 1.7 1999-06-23 19:45:00 achimha Exp $ */
 /*
  * Undocumented functions from COMCTL32.DLL
@@ -618,5 +618,5 @@
     LPVOID pDest, lpTemp;
     
-//    TRACE (commctrl, "(%p %d %p)\n", hdsa, nIndex, pSrc);
+//    TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
 
     if ((!hdsa) || nIndex < 0)
@@ -627,5 +627,5 @@
 	if (hdsa->nMaxCount > nIndex) {
 	    /* within the allocated space, set a new boundary */
-	    hdsa->nItemCount = nIndex;
+	    hdsa->nItemCount = nIndex + 1;
 	}
 	else {
@@ -640,4 +640,5 @@
 
 	    hdsa->nMaxCount = nNewItems;
+	    hdsa->nItemCount = nIndex + 1;
 	    hdsa->pData = lpTemp;
 	}    
@@ -646,5 +647,5 @@
     /* put the new entry in */
     pDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
-//    TRACE (commctrl, "-- move dest=%p src=%p size=%d\n",
+//    TRACE("-- move dest=%p src=%p size=%d\n",
 //	   pDest, pSrc, hdsa->nItemSize);
     memmove (pDest, pSrc, hdsa->nItemSize);
@@ -674,5 +675,5 @@
     LPDWORD p;
     
-//    TRACE(commctrl, "(%p %d %p)\n", hdsa, nIndex, pSrc);
+//    TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
 
     if ((!hdsa) || nIndex < 0)
@@ -682,7 +683,7 @@
 	p = *(DWORD**)((char *) pSrc + i);
 //	if (IsBadStringPtrA ((char*)p, 256))
-//	    TRACE (commctrl, "-- %d=%p\n", i, (DWORD*)p);
+//	    TRACE("-- %d=%p\n", i, (DWORD*)p);
 //	else
-//	    TRACE (commctrl, "-- %d=%p [%s]\n", i, p, debugstr_a((char*)p));
+//	    TRACE("-- %d=%p [%s]\n", i, p, debugstr_a((char*)p));
     }
    
@@ -709,5 +710,5 @@
 	lpDest = (char *) lpTemp + hdsa->nItemSize;
 	nSize = (hdsa->nItemCount - nIndex) * hdsa->nItemSize;
-//	TRACE (commctrl, "-- move dest=%p src=%p size=%d\n",
+//	TRACE("-- move dest=%p src=%p size=%d\n",
 //	       lpDest, lpTemp, nSize);
 	memmove (lpDest, lpTemp, nSize);
@@ -717,5 +718,5 @@
     hdsa->nItemCount++;
     lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
-//    TRACE (commctrl, "-- move dest=%p src=%p size=%d\n",
+//    TRACE("-- move dest=%p src=%p size=%d\n",
 //	   lpDest, pSrc, hdsa->nItemSize);
     memmove (lpDest, pSrc, hdsa->nItemSize);
Index: trunk/src/comctl32/debugtools.h
===================================================================
--- trunk/src/comctl32/debugtools.h	(revision 164)
+++ trunk/src/comctl32/debugtools.h	(revision 164)
@@ -0,0 +1,21 @@
+/* $Id: debugtools.h,v 1.1 1999-06-23 19:45:00 achimha Exp $ */
+
+/*
+ * These are the WINE debug functions which used to be vararg macros (argh!!!)
+ *
+ * Copyright 1999 Achim Hasenmueller
+ *
+ */
+
+void TRACE(char *test, ...)
+{
+}
+void ERR(char *test, ...)
+{
+}
+void WARN(char *test, ...)
+{
+}
+void FIXME(char *test, ...)
+{
+}
Index: trunk/src/comctl32/imagelist.c
===================================================================
--- trunk/src/comctl32/imagelist.c	(revision 163)
+++ trunk/src/comctl32/imagelist.c	(revision 164)
@@ -1,3 +1,3 @@
-/* $Id: imagelist.c,v 1.3 1999-06-10 16:21:59 achimha Exp $ */
+/* $Id: imagelist.c,v 1.4 1999-06-23 19:45:00 achimha Exp $ */
 /*
  *  ImageList implementation
@@ -1207,20 +1207,14 @@
     HICON  hIcon;
     HDC    hdcSrc, hdcDst;
-    INT    nWidth, nHeight;
 
     if ((himl == NULL) || (i < 0) || (i >= himl->cCurImage))
 	return 0;
 
-    nWidth = GetSystemMetrics (SM_CXICON);
-    nHeight = GetSystemMetrics (SM_CYICON);
-
     hdcSrc = CreateCompatibleDC(0);
     hdcDst = CreateCompatibleDC(0);
 
     ii.fIcon = TRUE;
-    ii.xHotspot = nWidth / 2;
-    ii.yHotspot = nHeight / 2;
-    ii.hbmMask  = CreateCompatibleBitmap (hdcDst, nWidth, nHeight);
-    ii.hbmColor = CreateCompatibleBitmap (hdcDst, nWidth, nHeight);
+    ii.hbmMask  = CreateCompatibleBitmap (hdcDst, himl->cx, himl->cy);
+    ii.hbmColor = CreateCompatibleBitmap (hdcDst, himl->cx, himl->cy);
 
 
@@ -1229,14 +1223,14 @@
     if (himl->hbmMask) {
 	SelectObject (hdcSrc, himl->hbmMask);
-	BitBlt (hdcDst, 0, 0, nWidth, nHeight,
+	BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
 		  hdcSrc, i * himl->cx, 0, SRCCOPY);
     }
     else
-	PatBlt (hdcDst, 0, 0, nWidth, nHeight, BLACKNESS);
+	PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS);
 
     /* draw image*/
     SelectObject (hdcDst, ii.hbmColor);
     SelectObject (hdcSrc, himl->hbmImage);
-    BitBlt (hdcDst, 0, 0, nWidth, nHeight,
+    BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
 	      hdcSrc, i * himl->cx, 0, SRCCOPY);
 
Index: trunk/src/comctl32/listview.c
===================================================================
--- trunk/src/comctl32/listview.c	(revision 163)
+++ trunk/src/comctl32/listview.c	(revision 164)
@@ -1,3 +1,2 @@
-/* $Id: listview.c,v 1.3 1999-06-10 16:22:00 achimha Exp $ */
 /*
  * Listview control
@@ -11,10 +10,6 @@
  *
  * TODO:
- *
- *   1. Multiple selections in icon or small icon display modes DO NOT
- *      behave like the Microsoft control.
- *   2. No horizontal scrolling when header is larger than the client area.
- *   3. Implement LVM_FINDITEM for key selections.
- *   4. Drawing optimizations.
+ *   1. No horizontal scrolling when header is larger than the client area.
+ *   2. Drawing optimizations.
  *
  * Notifications:
@@ -22,5 +17,4 @@
  *
  * Data structure:
- *   LISTVIEW_SortItems : empty stub 
  *   LISTVIEW_SetItemCount : empty stub 
  * 
@@ -41,8 +35,6 @@
  *   LISTVIEW_GetColumnOrderArray : not implemented
  *   LISTVIEW_Arrange : empty stub
- *   LISTVIEW_FindItem : empty stub 
  *   LISTVIEW_ApproximateViewRect : incomplete
  *   LISTVIEW_Scroll : not implemented 
- *   LISTVIEW_KeyDown : page up and page down  + redo small icon and icon 
  *   LISTVIEW_RedrawItems : empty stub
  *   LISTVIEW_Update : not completed
@@ -53,4 +45,5 @@
 #include "commctrl.h"
 #include "listview.h"
+#include "debugtools.h"
 
 /*
@@ -86,6 +79,4 @@
  * macros
  */
-
-/* retrieve the number of items in the listview */
 #define GETITEMCOUNT(infoPtr) ((infoPtr)->hdpaItems->nItemCount)
 #define ListView_LVNotify(hwnd,lCtrlId,plvnm) \
@@ -93,9 +84,13 @@
 #define ListView_Notify(hwnd,lCtrlId,pnmh) \
     (BOOL)SendMessageA((hwnd),WM_NOTIFY,(WPARAM)(INT)lCtrlId,(LPARAM)(LPNMHDR)(pnmh))
+/* retrieve the number of items in the listview */
+#define GETITEMCOUNT(infoPtr) ((infoPtr)->hdpaItems->nItemCount)
 
 /* 
  * forward declarations 
  */
-
+static INT LISTVIEW_HitTestItem(HWND, LPLVHITTESTINFO);
+static INT LISTVIEW_GetCountPerRow(HWND);
+static INT LISTVIEW_GetCountPerColumn(HWND);
 static VOID LISTVIEW_AlignLeft(HWND);
 static VOID LISTVIEW_AlignTop(HWND);
@@ -104,33 +99,26 @@
 static BOOL LISTVIEW_AddSubItem(HWND, LPLVITEMA);
 static INT LISTVIEW_FindInsertPosition(HDPA, INT);
-static VOID LISTVIEW_GetItemDispInfo(HWND, INT, LISTVIEW_ITEM *lpItem, INT *, 
-                                     UINT *, CHAR **, INT);
-static INT LISTVIEW_GetItemHeight(HWND, LONG);
+static INT LISTVIEW_GetItemHeight(HWND);
 static BOOL LISTVIEW_GetItemPosition(HWND, INT, LPPOINT);
 static LRESULT LISTVIEW_GetItemRect(HWND, INT, LPRECT);
-static INT LISTVIEW_GetItemWidth(HWND, LONG);
+static INT LISTVIEW_GetItemWidth(HWND);
 static INT LISTVIEW_GetLabelWidth(HWND, INT);
 static LRESULT LISTVIEW_GetOrigin(HWND, LPPOINT);
 static LISTVIEW_SUBITEM* LISTVIEW_GetSubItem(HDPA, INT);
-static VOID LISTVIEW_GetSubItemDispInfo(HWND hwnd, INT, LPARAM,
-                                        LISTVIEW_SUBITEM *, INT, INT *, 
-                                        CHAR **, INT);
 static LRESULT LISTVIEW_GetViewRect(HWND, LPRECT);
 static BOOL LISTVIEW_InitItem(HWND, LISTVIEW_ITEM *, LPLVITEMA);
 static BOOL LISTVIEW_InitSubItem(HWND, LISTVIEW_SUBITEM *, LPLVITEMA);
-static LRESULT LISTVIEW_MouseSelection(HWND, INT, INT);
+static LRESULT LISTVIEW_MouseSelection(HWND, POINT);
 static BOOL LISTVIEW_RemoveColumn(HDPA, INT);
 static VOID LISTVIEW_RemoveSelections(HWND, INT, INT);
 static BOOL LISTVIEW_RemoveSubItem(HDPA, INT);
-static BOOL LISTVIEW_ScrollView(HWND, INT, INT);
 static VOID LISTVIEW_SetGroupSelection(HWND, INT);
 static BOOL LISTVIEW_SetItem(HWND, LPLVITEMA);
-static VOID LISTVIEW_SetItemFocus(HWND, INT);
+static BOOL LISTVIEW_SetItemFocus(HWND, INT);
 static BOOL LISTVIEW_SetItemPosition(HWND, INT, INT, INT);
-static VOID LISTVIEW_SetScroll(HWND, LONG);
+static VOID LISTVIEW_UpdateScroll(HWND);
 static VOID LISTVIEW_SetSelection(HWND, INT);
-static VOID LISTVIEW_SetSize(HWND, LONG, LONG, LONG);
+static VOID LISTVIEW_UpdateSize(HWND);
 static BOOL LISTVIEW_SetSubItem(HWND, LPLVITEMA);
-static VOID LISTVIEW_SetViewInfo(HWND, LONG);
 static LRESULT LISTVIEW_SetViewRect(HWND, LPRECT);
 static BOOL LISTVIEW_ToggleSelection(HWND, INT);
@@ -139,83 +127,172 @@
 /***
  * DESCRIPTION:
- * Scrolls the content of the listview.
- * 
- * PARAMETER(S):
- * [I] HWND : window handle
- * [I] INT : number of horizontal scroll positions 
- *           (relative to the current scroll postioon)
- * [I] INT : number of vertical scroll positions
- *           (relative to the current scroll postioon)
- *
- * RETURN:
- *   SUCCESS : TRUE
- *   FAILURE : FALSE
- */
-static BOOL LISTVIEW_ScrollView(HWND hwnd, INT nHScroll, INT nVScroll)
+ * Update the scrollbars. This functions should be called whenever 
+ * the content, size or view changes.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ *
+ * RETURN:
+ * None
+ */
+static VOID LISTVIEW_UpdateScroll(HWND hwnd)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); 
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView =  lStyle & LVS_TYPEMASK;
+  INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
   INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
-  INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
-  INT nHScrollPos = 0;
-  INT nVScrollPos = 0;
-  INT nHScrollInc = 0;
-  INT nVScrollInc = 0;
-  BOOL bResult = FALSE;
-
-  if (((lStyle & WS_HSCROLL) != 0) && (nHScroll != 0))
-  {
-    switch (LVS_TYPEMASK & lStyle)
-    {
-    case LVS_LIST:
-      nHScrollInc = nHScroll * infoPtr->nItemWidth;
-      break;
-
-    case LVS_REPORT:
-      /* TO DO : not implemented at this point. I experiences some 
-         problems when performing child window scrolling. */
-      break;
-
-    case LVS_SMALLICON:
-    case LVS_ICON:
-      nHScrollInc = nHScroll * max(nListWidth, nListWidth / 10);
-      break;
-    }
-    
-    nHScrollPos = GetScrollPos(hwnd, SB_HORZ) + nHScroll;
-  }
-
-  if (((lStyle & WS_VSCROLL) != 0) & (nVScroll != 0))
-  {
-    switch (LVS_TYPEMASK & lStyle)
-    {
-    case LVS_REPORT:
-      nVScrollInc = nVScroll * infoPtr->nItemHeight;
-      nVScrollPos = GetScrollPos(hwnd, SB_VERT) + nVScroll;
-      break;
+  SCROLLINFO scrollInfo;
+
+  ZeroMemory(&scrollInfo, sizeof(SCROLLINFO));
+  scrollInfo.cbSize = sizeof(SCROLLINFO);
+
+  if (uView == LVS_LIST)
+  {
+    INT nCountPerColumn = LISTVIEW_GetCountPerColumn(hwnd);
+    INT nCountPerPage = LISTVIEW_GetCountPerRow(hwnd) * nCountPerColumn;
+    if (nCountPerPage < GETITEMCOUNT(infoPtr))
+    {
+      /* calculate new scrollbar range */
+      INT nHiddenItemCount = GETITEMCOUNT(infoPtr) - nCountPerPage;
+      if (nHiddenItemCount % nCountPerColumn == 0)
+      {
+        scrollInfo.nMax = nHiddenItemCount / nCountPerColumn;
+      }
+      else
+      {
+        scrollInfo.nMax = nHiddenItemCount / nCountPerColumn + 1;
+      }
       
-    case LVS_SMALLICON:
-    case LVS_ICON:
-      nVScrollInc = nVScroll * max(nListHeight, nListHeight / 10);
-      nVScrollPos = GetScrollPos(hwnd, SB_VERT) + nVScroll;
-      break;
-    }
-  }
-
-  /* perform scroll operation & set new scroll position */
-  if ((nHScrollInc != 0) || (nVScrollInc != 0))
-  {
-    RECT rc;
-    HDC hdc = GetDC(hwnd);
-    ScrollDC(hdc, -nHScrollInc, -nVScrollInc, &infoPtr->rcList, NULL, 
-             (HRGN) NULL, &rc);
-    InvalidateRect(hwnd, &rc, TRUE);
-    SetScrollPos(hwnd, SB_HORZ, nHScrollPos, TRUE);
-    SetScrollPos(hwnd, SB_VERT, nVScrollPos, TRUE);
-    ReleaseDC(hwnd, hdc);
-    bResult = TRUE;
-  }
-
-  return bResult; 
+      scrollInfo.nPos = ListView_GetTopIndex(hwnd) / nCountPerColumn;
+      /*scrollInfo.nPage = LISTVIEW_GetCountPerRow(hwnd);*/
+      scrollInfo.fMask = SIF_RANGE | SIF_POS /*| SIF_PAGE*/;
+      SetScrollInfo(hwnd, SB_HORZ, &scrollInfo, TRUE);
+    }
+    else
+    {
+      /* hide scrollbar */
+      if (lStyle & WS_HSCROLL)
+      {
+	ShowScrollBar(hwnd, SB_HORZ, FALSE);
+      }
+    }
+  }
+  else if (uView == LVS_REPORT)
+  {
+    /* update vertical scrollbar */
+    scrollInfo.nMin = 0;
+    scrollInfo.nMax = GETITEMCOUNT(infoPtr) - LISTVIEW_GetCountPerColumn(hwnd);
+    scrollInfo.nPos = ListView_GetTopIndex(hwnd);
+    /*scrollInfo.nPage = nCountPerColumn;*/
+    scrollInfo.fMask = SIF_RANGE | SIF_POS /*| SIF_PAGE*/;
+    SetScrollInfo(hwnd, SB_VERT, &scrollInfo, TRUE);
+
+    /* update horizontal scrollbar */
+/*     if (infoPtr->nItemWidth > nListWidth) */
+/*     { */
+/*       scrollInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE; */
+/*       SetScrollInfo(hwnd, SB_HORZ, &scrollInfo, TRUE); */
+/*     } */
+
+    /* horizontal scrolling has not been implemented yet! I experienced some 
+       problems when performing child window scrolling. */
+  }
+  else
+  {
+    RECT rcView;
+
+    if (LISTVIEW_GetViewRect(hwnd, &rcView) != FALSE)
+    {
+      INT nViewWidth = rcView.right - rcView.left;
+      INT nViewHeight = rcView.bottom - rcView.top;
+
+      if (nViewWidth > nListWidth)
+      {
+        INT nHiddenWidth;
+        INT nScrollPosWidth = nListWidth / 10;
+
+        if (nScrollPosWidth == 0)
+        {
+          nScrollPosWidth = 1;
+          nHiddenWidth = nViewWidth - nListWidth;
+        }
+        else
+        {
+          nHiddenWidth = nViewWidth - nScrollPosWidth * 10;
+        }
+
+        scrollInfo.fMask = SIF_POS;
+        if (GetScrollInfo(hwnd, SB_HORZ, &scrollInfo) == FALSE)
+        {
+          scrollInfo.nPos = 0;
+        }
+  
+        if (nHiddenWidth % nScrollPosWidth == 0)
+        {
+          scrollInfo.nMax = nHiddenWidth / nScrollPosWidth; 
+        }
+        else
+        {
+          scrollInfo.nMax = nHiddenWidth / nScrollPosWidth + 1; 
+        }
+          
+        scrollInfo.nMin = 0;
+        /*scrollInfo.nPage = 10;*/
+        scrollInfo.fMask = SIF_RANGE | SIF_POS /*| SIF_PAGE*/;
+        SetScrollInfo(hwnd, SB_HORZ, &scrollInfo, TRUE);
+      }
+      else
+      {
+        if (lStyle & WS_HSCROLL)
+        {
+          ShowScrollBar(hwnd, SB_HORZ, FALSE);
+        }
+      }
+
+      if (nViewHeight > nListHeight)
+      {
+        INT nHiddenHeight;
+        INT nScrollPosHeight = nListHeight / 10;
+
+        if (nScrollPosHeight == 0)
+        {
+          nScrollPosHeight = 1;
+          nHiddenHeight = nViewHeight - nListHeight;
+        }
+        else
+        {
+          nHiddenHeight = nViewHeight - nScrollPosHeight * 10;
+        }
+
+        scrollInfo.fMask = SIF_POS;
+        if (GetScrollInfo(hwnd, SB_VERT, &scrollInfo) == FALSE)
+        {
+          scrollInfo.nPos = 0;
+        }
+
+        if (nHiddenHeight % nScrollPosHeight == 0)
+        {
+          scrollInfo.nMax = nHiddenHeight / nScrollPosHeight; 
+        }
+        else
+        {
+          scrollInfo.nMax = nHiddenHeight / nScrollPosHeight + 1; 
+        }
+
+        scrollInfo.nMin = 0;
+        /*scrollInfo.nPage = 10;*/
+        scrollInfo.fMask = SIF_RANGE | SIF_POS /*| SIF_PAGE*/;
+        SetScrollInfo(hwnd, SB_VERT, &scrollInfo, TRUE);
+      }
+      else
+      {
+        if (lStyle & WS_VSCROLL)
+        {
+          ShowScrollBar(hwnd, SB_VERT, FALSE);
+        }
+      }
+    }
+  }
 }
 
@@ -235,55 +312,40 @@
   if ((LVS_TYPEMASK & lStyle) == LVS_EDITLABELS)
   {
-//    FIXME( listview, "  LVS_EDITLABELS\n");
-  }
-
-  if ((LVS_TYPEMASK & lStyle) == LVS_NOCOLUMNHEADER)
-  {
-//    FIXME( listview, "  LVS_SORTDESCENDING\n");
+    FIXME("  LVS_EDITLABELS\n");
   }
 
   if ((LVS_TYPEMASK & lStyle) == LVS_NOLABELWRAP)
   {
-//    FIXME( listview, "  LVS_NOLABELWRAP\n");
+    FIXME("  LVS_NOLABELWRAP\n");
   }
 
   if ((LVS_TYPEMASK & lStyle) == LVS_NOSCROLL)
   {
-//    FIXME( listview, "  LVS_NOSCROLL\n");
+    FIXME("  LVS_NOSCROLL\n");
   }
 
   if ((LVS_TYPEMASK & lStyle) == LVS_NOSORTHEADER)
   {
-//    FIXME( listview, "  LVS_NOSORTHEADER\n");
+    FIXME("  LVS_NOSORTHEADER\n");
   }
 
   if ((LVS_TYPEMASK & lStyle) == LVS_OWNERDRAWFIXED)
   {
-//    FIXME( listview, "  LVS_OWNERDRAWFIXED\n");
+    FIXME("  LVS_OWNERDRAWFIXED\n");
   }
 
   if ((LVS_TYPEMASK & lStyle) == LVS_SHAREIMAGELISTS)
   {
-//    FIXME( listview, "  LVS_SHAREIMAGELISTS\n");
-  }
-
-  if ((LVS_TYPEMASK & lStyle) == LVS_SHOWSELALWAYS)
-  {
-//    FIXME( listview, "  LVS_SHOWSELALWAYS\n");
-  }
-
-  if ((LVS_TYPEMASK & lStyle) == LVS_SINGLESEL)
-  {
-//    FIXME( listview, "  LVS_SINGLESEL\n");
+    FIXME("  LVS_SHAREIMAGELISTS\n");
   }
 
   if ((LVS_TYPEMASK & lStyle) == LVS_SORTASCENDING)
   {
-//    FIXME( listview, "  LVS_SORTASCENDING\n");
+    FIXME("  LVS_SORTASCENDING\n");
   }
 
   if ((LVS_TYPEMASK & lStyle) == LVS_SORTDESCENDING)
   {
-//    FIXME( listview, "  LVS_SORTDESCENDING\n");
+    FIXME("  LVS_SORTDESCENDING\n");
   }
 }
@@ -302,5 +364,5 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
   INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
   POINT ptItem;
@@ -308,10 +370,9 @@
   INT i;
   
-  switch (LVS_TYPEMASK & lStyle)
-  {
-  case LVS_SMALLICON:
-  case LVS_ICON:
+  if ((uView == LVS_SMALLICON) || (uView == LVS_ICON))
+  {
     ZeroMemory(&ptItem, sizeof(POINT));
     ZeroMemory(&rcView, sizeof(RECT));
+    
     if (nListWidth > infoPtr->nItemWidth)
     {
@@ -324,8 +385,10 @@
         }
         
-        LISTVIEW_SetItemPosition(hwnd, i, ptItem.x, ptItem.y);
+        ListView_SetItemPosition(hwnd, i, ptItem.x, ptItem.y);
         ptItem.x += infoPtr->nItemWidth;
         rcView.right = max(rcView.right, ptItem.x);
       }
+
+      rcView.bottom = ptItem.y + infoPtr->nItemHeight;
     }
     else
@@ -333,12 +396,12 @@
       for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
       {
-        LISTVIEW_SetItemPosition(hwnd, i, ptItem.x, ptItem.y);
-        ptItem.x += infoPtr->nItemWidth;
-      }
-      rcView.right = ptItem.x;
-      rcView.bottom = infoPtr->nItemHeight;
-    }
-
-    rcView.bottom = ptItem.y + infoPtr->nItemHeight;
+        ListView_SetItemPosition(hwnd, i, ptItem.x, ptItem.y);
+        ptItem.y += infoPtr->nItemHeight;
+      }
+
+      rcView.right = infoPtr->nItemWidth;
+      rcView.bottom = ptItem.y;
+    }
+
     LISTVIEW_SetViewRect(hwnd, &rcView);
   }
@@ -358,5 +421,5 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
   INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
   POINT ptItem;
@@ -364,10 +427,9 @@
   INT i;
   
-  switch (LVS_TYPEMASK & lStyle)
-  {
-  case LVS_SMALLICON:
-  case LVS_ICON:
+  if ((uView == LVS_SMALLICON) || (uView == LVS_ICON))
+  {
     ZeroMemory(&ptItem, sizeof(POINT));
     ZeroMemory(&rcView, sizeof(RECT));
+
     if (nListHeight > infoPtr->nItemHeight)
     {
@@ -380,8 +442,10 @@
         }
 
-        LISTVIEW_SetItemPosition(hwnd, i, ptItem.x, ptItem.y);
+        ListView_SetItemPosition(hwnd, i, ptItem.x, ptItem.y);
         ptItem.y += infoPtr->nItemHeight;
         rcView.bottom = max(rcView.bottom, ptItem.y);
       }
+
+      rcView.right = ptItem.x + infoPtr->nItemWidth;
     }
     else
@@ -389,216 +453,117 @@
       for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
       {
-        LISTVIEW_SetItemPosition(hwnd, i, ptItem.x, ptItem.y);
-        ptItem.y += infoPtr->nItemHeight;
-      }
-      rcView.bottom = ptItem.y;
-      rcView.right = infoPtr->nItemWidth;
-    }
-
-    rcView.right = ptItem.x + infoPtr->nItemWidth;
+        ListView_SetItemPosition(hwnd, i, ptItem.x, ptItem.y);
+        ptItem.x += infoPtr->nItemWidth;
+      }
+
+      rcView.bottom = infoPtr->nItemHeight;
+      rcView.right = ptItem.x;
+    }
+
     LISTVIEW_SetViewRect(hwnd, &rcView);
-    break;
- }
-}
-
-/***
- * DESCRIPTION:
- * Retrieves display information.
- * 
- * PARAMETER(S):
- * [I] HWND : window handle
- * [I] INT : item index
- * [I] LISTVIEW_ITEM* : listview control item
- * [O] INT : image index
- * [O] UINT : state value
- * [O] CHAR** : string
- * [I] INT : size of string
- *
- * RETURN:
- * None
- */
-static VOID LISTVIEW_GetItemDispInfo(HWND hwnd, INT nItem, 
-                                     LISTVIEW_ITEM *lpItem, INT *pnDispImage, 
-                                     UINT *puState, CHAR **ppszDispText, 
-                                     INT nDispTextSize)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
-  NMLVDISPINFOA dispInfo;
-  ZeroMemory(&dispInfo, sizeof(NMLVDISPINFOA));
- 
-  if ((pnDispImage != NULL) && (lpItem->iImage == I_IMAGECALLBACK))
-  {
-    dispInfo.item.mask |= LVIF_IMAGE;
-  }
-
-  if ((ppszDispText != NULL) && (lpItem->pszText == LPSTR_TEXTCALLBACKA))
-  {
-    ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize);
-    dispInfo.item.mask |= LVIF_TEXT;
-    dispInfo.item.pszText = *ppszDispText;
-    dispInfo.item.cchTextMax = nDispTextSize;
-  }
-
-  if ((puState != NULL) && (infoPtr->uCallbackMask != 0))
-  {
-    dispInfo.item.mask |= LVIF_STATE;
-    dispInfo.item.stateMask = infoPtr->uCallbackMask; 
-  }
-
-  if (dispInfo.item.mask != 0)
-  {
-    dispInfo.hdr.hwndFrom = hwnd;
-    dispInfo.hdr.idFrom = lCtrlId;
-    dispInfo.hdr.code = LVN_GETDISPINFOA;
-    dispInfo.item.iItem = nItem;
-    dispInfo.item.iSubItem = 0;
-    dispInfo.item.lParam = lpItem->lParam;
-    ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo);
-  }
-
-  if (pnDispImage != NULL)
-  {
-    if (dispInfo.item.mask & LVIF_IMAGE)
-    {
-      *pnDispImage = dispInfo.item.iImage;
-    }
-    else
-    {
-      *pnDispImage = lpItem->iImage;
-    }
-  }
-
-  if (ppszDispText != NULL)
-  {
-    if (dispInfo.item.mask & LVIF_TEXT)
-    {
-      if (dispInfo.item.mask & LVIF_DI_SETITEM)
-      {
-        Str_SetPtrA(&lpItem->pszText, dispInfo.item.pszText);
-      }
-      *ppszDispText = dispInfo.item.pszText;
-    }
-    else
-    {
-      *ppszDispText = lpItem->pszText;
-    }
-  }
-
-  if (puState != NULL)
-  {
-    if (dispInfo.item.mask & LVIF_STATE)
-    {
-      *puState = lpItem->state;
-      *puState &= ~dispInfo.item.stateMask;
-      *puState |= (dispInfo.item.state & dispInfo.item.stateMask);
-    }
-    else
-    {
-      *puState = lpItem->state;
-    }
-  }
-}
-
-/***
- * DESCRIPTION:
- * Retrieves subitem display information.
- * 
- * PARAMETER(S):
- * [I] HWND : window handle
- * [I] INT : item index
- * [I] LONG : LPARAM of item
- * [I] LISTVIEW_SUBITEM* : listview control subitem
- * [I] INT : subitem position/order 
- * [O] INT : image index
- * [O] UINT : state value
- * [O] CHAR** : display string
- * [I] INT : size of string
- *
- * RETURN:
- * None
- */
-static VOID LISTVIEW_GetSubItemDispInfo(HWND hwnd, INT nItem, LPARAM lParam,
-                                        LISTVIEW_SUBITEM *lpSubItem, 
-                                        INT nSubItemPos, INT *pnDispImage, 
-                                        CHAR **ppszDispText, INT nDispTextSize)
-{
-  LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
-  NMLVDISPINFOA dispInfo;
-  ZeroMemory(&dispInfo, sizeof(NMLVDISPINFOA));
-
-  if (lpSubItem == NULL)
-  {
-    ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize);
-    dispInfo.item.mask |= LVIF_TEXT;
-    dispInfo.item.pszText = *ppszDispText;
-    dispInfo.item.cchTextMax = nDispTextSize;
-    dispInfo.hdr.hwndFrom = hwnd;
-    dispInfo.hdr.idFrom = lCtrlId;
-    dispInfo.hdr.code = LVN_GETDISPINFOA;
-    dispInfo.item.iItem = nItem;
-    dispInfo.item.iSubItem = nSubItemPos;
-    dispInfo.item.lParam = lParam;
-    ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo);
-    if (dispInfo.item.mask & LVIF_DI_SETITEM)
-    {
-      Str_SetPtrA(&lpSubItem->pszText, dispInfo.item.pszText);
-    }
-    *ppszDispText = dispInfo.item.pszText;
-  }
-  else
-  {
-    if ((pnDispImage != NULL) && (lpSubItem->iImage == I_IMAGECALLBACK))
-    {
-      dispInfo.item.mask |= LVIF_IMAGE;
-    }
-
-    if ((ppszDispText != NULL) && (lpSubItem->pszText == LPSTR_TEXTCALLBACKA))
-    {
-      ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize);
-      dispInfo.item.mask |= LVIF_TEXT;
-      dispInfo.item.pszText = *ppszDispText;
-      dispInfo.item.cchTextMax = nDispTextSize;
-    }
-
-    if (dispInfo.item.mask != 0)
-    {
-      dispInfo.hdr.hwndFrom = hwnd;
-      dispInfo.hdr.idFrom = lCtrlId;
-      dispInfo.hdr.code = LVN_GETDISPINFOA;
-      dispInfo.item.iItem = nItem;
-      dispInfo.item.iSubItem = lpSubItem->iSubItem;
-      dispInfo.item.lParam = lParam;
-      ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo);
-    }
-
-    if (pnDispImage != NULL)
-    {
-      if (dispInfo.item.mask & LVIF_IMAGE)
-      {
-        *pnDispImage = dispInfo.item.iImage;
-      }
-      else
-      {
-        *pnDispImage = lpSubItem->iImage;
-      }
-    }
-
-    if (ppszDispText != NULL)
-    {
-      if (dispInfo.item.mask & LVIF_TEXT)
-      {
-        if (dispInfo.item.mask & LVIF_DI_SETITEM)
-        {
-          Str_SetPtrA(&lpSubItem->pszText, dispInfo.item.pszText);
-        }
-        *ppszDispText = dispInfo.item.pszText;
-      }
-      else
-      {
-        *ppszDispText = lpSubItem->pszText;
-      }
-    }
-  }
+  }
+}
+
+/***
+ * DESCRIPTION:
+ * Set the bounding rectangle of all the items.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] LPRECT : bounding rectangle
+ *
+ * RETURN:
+ *   SUCCESS : TRUE
+ *   FAILURE : FALSE
+ */
+static LRESULT LISTVIEW_SetViewRect(HWND hwnd, LPRECT lprcView)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
+  BOOL bResult = FALSE;
+
+//  TRACE("(hwnd=%x, left=%d, top=%d, right=%d, bottom=%d)\n", hwnd, 
+//        lprcView->left, lprcView->top, lprcView->right, lprcView->bottom);
+  
+  if (lprcView != NULL)
+  {
+    bResult = TRUE;
+    infoPtr->rcView.left = lprcView->left;
+    infoPtr->rcView.top = lprcView->top;
+    infoPtr->rcView.right = lprcView->right;
+    infoPtr->rcView.bottom = lprcView->bottom;
+  }
+
+  return bResult;
+}
+
+/***
+ * DESCRIPTION:
+ * Retrieves the bounding rectangle of all the items.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [O] LPRECT : bounding rectangle
+ *
+ * RETURN:
+ *   SUCCESS : TRUE
+ *   FAILURE : FALSE
+ */
+static LRESULT LISTVIEW_GetViewRect(HWND hwnd, LPRECT lprcView)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
+  BOOL bResult = FALSE;
+  POINT ptOrigin;
+
+//  TRACE("(hwnd=%x, lprcView=%p)\n", hwnd, lprcView);
+
+  if (lprcView != NULL)
+  {
+    bResult = LISTVIEW_GetOrigin(hwnd, &ptOrigin);
+    if (bResult != FALSE)
+    {
+      lprcView->left = infoPtr->rcView.left + ptOrigin.x;
+      lprcView->top = infoPtr->rcView.top + ptOrigin.y;
+      lprcView->right = infoPtr->rcView.right + ptOrigin.x;
+      lprcView->bottom = infoPtr->rcView.bottom + ptOrigin.y;
+    }
+
+//    TRACE("(left=%d, top=%d, right=%d, bottom=%d)\n", 
+//          lprcView->left, lprcView->top, lprcView->right, lprcView->bottom);
+  }
+
+  return bResult;
+}
+
+/***
+ * DESCRIPTION:
+ * Retrieves the subitem pointer associated with the subitem index.
+ * 
+ * PARAMETER(S):
+ * [I] HDPA : DPA handle for a specific item
+ * [I] INT : index of subitem
+ *
+ * RETURN:
+ *   SUCCESS : subitem pointer
+ *   FAILURE : NULL
+ */
+static LISTVIEW_SUBITEM* LISTVIEW_GetSubItemPtr(HDPA hdpaSubItems, 
+                                                INT nSubItem)
+{
+  LISTVIEW_SUBITEM *lpSubItem;
+  INT i;
+
+  for (i = 1; i < hdpaSubItems->nItemCount; i++)
+  {
+    lpSubItem = (LISTVIEW_SUBITEM *) DPA_GetPtr(hdpaSubItems, i);
+    if (lpSubItem != NULL)
+    {
+      if (lpSubItem->iSubItem == nSubItem)
+      {
+        return lpSubItem;
+      }
+    }
+  }
+
+  return NULL;
 }
 
@@ -614,7 +579,8 @@
  * Returns item width.
  */
-static INT LISTVIEW_GetItemWidth(HWND hwnd, LONG lStyle)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+static INT LISTVIEW_GetItemWidth(HWND hwnd)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
   INT nHeaderItemCount;
   RECT rcHeaderItem;
@@ -623,13 +589,12 @@
   INT i;
 
-//  TRACE(listview, "(hwnd=%x,lStyle=%lx)\n", hwnd, lStyle);
-
-  switch (LVS_TYPEMASK & lStyle)
-  {
-  case LVS_ICON:
+//  TRACE("(hwnd=%x)\n", hwnd);
+
+  if (uView == LVS_ICON)
+  {
     nItemWidth = infoPtr->iconSpacing.cx;
-    break;
-
-  case LVS_REPORT:
+  }
+  else if (uView == LVS_REPORT)
+  {
     /* calculate width of header */
     nHeaderItemCount = Header_GetItemCount(infoPtr->hwndHeader);
@@ -641,8 +606,7 @@
       }
     }
-    break;
-
-  case LVS_SMALLICON:
-  case LVS_LIST:
+  }
+  else
+  {
     for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
     { 
@@ -650,5 +614,5 @@
       nItemWidth = max(nItemWidth, nLabelWidth);
     }
-
+    
     /* default label size */
     if (GETITEMCOUNT(infoPtr) == 0)
@@ -678,8 +642,6 @@
       }
     }
-    break;
-
-  }
-
+  }
+  
   return nItemWidth;
 }
@@ -694,66 +656,28 @@
  *
  * RETURN:
- * Returns item width.
- */
-static INT LISTVIEW_GetItemHeight(HWND hwnd, LONG lStyle)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+ * Returns item height.
+ */
+static INT LISTVIEW_GetItemHeight(HWND hwnd)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
   INT nItemHeight = 0;
-  TEXTMETRICA tm; 
-  HFONT hOldFont;
-  HDC hdc;
-
-  switch (LVS_TYPEMASK & lStyle)
-  {
-  case LVS_ICON:
+
+  if (uView == LVS_ICON)
+  {
     nItemHeight = infoPtr->iconSpacing.cy;
-    break;
-
-  case LVS_SMALLICON:
-  case LVS_REPORT:
-  case LVS_LIST:
-    hdc = GetDC(hwnd);
-    hOldFont = SelectObject(hdc, infoPtr->hFont);
+  }
+  else 
+  {
+    TEXTMETRICA tm; 
+    HDC hdc = GetDC(hwnd);
+    HFONT hOldFont = SelectObject(hdc, infoPtr->hFont);
     GetTextMetricsA(hdc, &tm);
     nItemHeight = max(tm.tmHeight, infoPtr->iconSize.cy) + HEIGHT_PADDING;
     SelectObject(hdc, hOldFont);
     ReleaseDC(hwnd, hdc);
-    break;
   }
 
   return nItemHeight;
-}
-
-/***
- * DESCRIPTION:
- * Sets diplay information (needed for drawing operations).
- * 
- * PARAMETER(S):
- * [I] HWND : window handle
- * 
- * RETURN:
- * None
- */
-static VOID LISTVIEW_SetViewInfo(HWND hwnd, LONG lStyle)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
-  INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
-
-  switch (LVS_TYPEMASK & lStyle)
-  {
-  case LVS_REPORT:
-    /* get number of fully visible items per column */
-    infoPtr->nCountPerColumn = max(1, nListHeight / infoPtr->nItemHeight);
-    break;
-
-  case LVS_LIST:
-    /* get number of fully visible items per column */
-    infoPtr->nCountPerColumn = max(1, nListHeight / infoPtr->nItemHeight);
-    
-    /* get number of fully visible items per row */
-    infoPtr->nCountPerRow = max(1, nListWidth / infoPtr->nItemWidth);
-    break;
-  }
 }
 
@@ -855,4 +779,40 @@
 /***
  * DESCRIPTION:
+ * Selects items based on view coorddiantes. 
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] RECT : selection rectangle  
+ *
+ * RETURN:
+ * None
+ */
+static VOID LISTVIEW_SetSelectionRect(HWND hwnd, RECT rcSelRect)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  LVITEMA lvItem;
+  POINT ptItem;
+  INT i;
+
+  lvItem.stateMask = LVIS_SELECTED;
+
+  for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
+  {
+    LISTVIEW_GetItemPosition(hwnd, i, &ptItem);
+    if (PtInRect(&rcSelRect, ptItem) != FALSE)
+    {
+      lvItem.state = LVIS_SELECTED;
+    }
+    else
+    {
+      lvItem.state = 0;
+    }
+
+    ListView_SetItemState(hwnd, i, &lvItem);
+  }
+}
+
+/***
+ * DESCRIPTION:
  * Sets a single group selection.
  * 
@@ -867,25 +827,40 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  INT nFirst = min(infoPtr->nSelectionMark, nItem);
-  INT nLast = max(infoPtr->nSelectionMark, nItem);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
   LVITEMA lvItem;
-  INT i;
-
-  if (nFirst > 0)
-  {
-    LISTVIEW_RemoveSelections(hwnd, 0, nFirst - 1);
-  }
-
-  if (nLast < GETITEMCOUNT(infoPtr))
-  {
-    LISTVIEW_RemoveSelections(hwnd, nLast + 1, GETITEMCOUNT(infoPtr));
-  }
-
-  lvItem.state = LVIS_SELECTED;
-  lvItem.stateMask = LVIS_SELECTED;
-
-  for (i = nFirst; i <= nLast; i++)
-  {
-    ListView_SetItemState(hwnd, i, &lvItem);
+
+  if ((uView == LVS_LIST) || (uView == LVS_REPORT))
+  {
+    INT i;
+    INT nFirst = min(infoPtr->nSelectionMark, nItem);
+    INT nLast = max(infoPtr->nSelectionMark, nItem);
+    lvItem.stateMask = LVIS_SELECTED;
+   
+    for (i = 0; i <= GETITEMCOUNT(infoPtr); i++)
+    {
+      if ((i < nFirst) || (i > nLast))
+      {
+        lvItem.state = 0;
+      }
+      else
+      {
+        lvItem.state = LVIS_SELECTED;
+      }
+
+      ListView_SetItemState(hwnd, i, &lvItem);
+    }
+  }
+  else
+  {
+    POINT ptItem;
+    POINT ptSelMark;
+    RECT rcSel;
+    LISTVIEW_GetItemPosition(hwnd, nItem, &ptItem);
+    LISTVIEW_GetItemPosition(hwnd, infoPtr->nSelectionMark, &ptSelMark);
+    rcSel.left = min(ptSelMark.x, ptItem.x);
+    rcSel.top = min(ptSelMark.y, ptItem.y);
+    rcSel.right = max(ptSelMark.x, ptItem.x) + infoPtr->nItemWidth;
+    rcSel.bottom = max(ptSelMark.y, ptItem.y) + infoPtr->nItemHeight;
+    LISTVIEW_SetSelectionRect(hwnd, rcSel);
   }
 
@@ -902,41 +877,47 @@
  *
  * RETURN:
+ *   TRUE : focused item changed
+ *   FALSE : focused item has NOT changed
+ */
+static BOOL LISTVIEW_SetItemFocus(HWND hwnd, INT nItem)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  BOOL bResult = FALSE;
+  LVITEMA lvItem;
+
+  if (infoPtr->nFocusedItem != nItem)
+  {
+    bResult = TRUE;
+    ZeroMemory(&lvItem, sizeof(LVITEMA));
+    lvItem.stateMask = LVIS_FOCUSED;
+    ListView_SetItemState(hwnd, infoPtr->nFocusedItem, &lvItem); 
+
+    lvItem.state =  LVIS_FOCUSED;
+    lvItem.stateMask = LVIS_FOCUSED;
+    ListView_SetItemState(hwnd, nItem, &lvItem);
+
+    infoPtr->nFocusedItem = nItem;
+    ListView_EnsureVisible(hwnd, nItem, FALSE);
+  }
+  
+  return bResult; 
+}
+
+/***
+ * DESCRIPTION:
+ * Sets a single selection.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] INT : item index 
+ *
+ * RETURN:
  * None
  */
-static VOID LISTVIEW_SetItemFocus(HWND hwnd, INT nItem)
+static VOID LISTVIEW_SetSelection(HWND hwnd, INT nItem)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LVITEMA lvItem;
 
-  lvItem.state = 0;
-  lvItem.stateMask = LVIS_FOCUSED;
-  ListView_SetItemState(hwnd, infoPtr->nFocusedItem, &lvItem); 
-  
-  lvItem.state =  LVIS_FOCUSED;
-  lvItem.stateMask = LVIS_FOCUSED;
-  ListView_SetItemState(hwnd, nItem, &lvItem);
-
-  infoPtr->nFocusedItem = nItem;
-
-  /* if multiple selection is allowed */
-  ListView_EnsureVisible(hwnd, nItem, FALSE);
-}
-
-/***
- * DESCRIPTION:
- * Sets a single selection.
- * 
- * PARAMETER(S):
- * [I] HWND : window handle
- * [I] INT : item index 
- *
- * RETURN:
- * None
- */
-static VOID LISTVIEW_SetSelection(HWND hwnd, INT nItem)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LVITEMA lvItem;
-
   if (nItem > 0)
   {
@@ -949,5 +930,5 @@
   }
 
-  lvItem.state = 0;
+  ZeroMemory(&lvItem, sizeof(LVITEMA));
   lvItem.stateMask = LVIS_FOCUSED;
   ListView_SetItemState(hwnd, infoPtr->nFocusedItem, &lvItem); 
@@ -970,36 +951,53 @@
  *
  * RETURN:
- * None
- */
-static VOID LISTVIEW_KeySelection(HWND hwnd, INT nItem)
-{
+ *   SUCCESS : TRUE (needs to be repainted)
+ *   FAILURE : FALSE (nothing has changed)
+ */
+static BOOL LISTVIEW_KeySelection(HWND hwnd, INT nItem)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
   WORD wShift = HIWORD(GetKeyState(VK_SHIFT));
   WORD wCtrl = HIWORD(GetKeyState(VK_CONTROL));
-
-  if (wShift)
-  {
-    LISTVIEW_SetGroupSelection(hwnd, nItem); 
-  }
-  else if (wCtrl)
-  {
-    LISTVIEW_SetItemFocus(hwnd, nItem);
-  }
-  else
-  {
-    LISTVIEW_SetSelection(hwnd, nItem); 
-
-    /* if multiple selection is allowed */
-    ListView_EnsureVisible(hwnd, nItem, FALSE);
-  }
-}
-
-/***
- * DESCRIPTION:
- * Determines the selected item.
- * 
- * PARAMETER(S):
- * [I] HWND : window handle
- * [I] INT : x ccordinate
- * [I] INT : y coordinate
+  BOOL bResult = FALSE;
+
+  if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
+  {
+    if (lStyle & LVS_SINGLESEL)
+    {
+      bResult = TRUE;
+      LISTVIEW_SetSelection(hwnd, nItem); 
+      ListView_EnsureVisible(hwnd, nItem, FALSE);
+    }
+    else
+    {
+      if (wShift)
+      {
+        bResult = TRUE;
+        LISTVIEW_SetGroupSelection(hwnd, nItem); 
+      }
+      else if (wCtrl)
+      {
+        bResult = LISTVIEW_SetItemFocus(hwnd, nItem);
+      }
+      else
+      {
+        bResult = TRUE;
+        LISTVIEW_SetSelection(hwnd, nItem); 
+        ListView_EnsureVisible(hwnd, nItem, FALSE);
+      }
+    }
+  }
+
+  return bResult;
+}
+  
+/***
+ * DESCRIPTION:
+ * Selects an item based on coordinates.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] POINT : mouse click ccordinates
  *
  * RETURN:
@@ -1007,5 +1005,5 @@
  *   FAILURE : -1
  */
-static LRESULT LISTVIEW_MouseSelection(HWND hwnd, INT nPosX, INT nPosY)
+static LRESULT LISTVIEW_MouseSelection(HWND hwnd, POINT pt)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
@@ -1018,6 +1016,5 @@
     if (LISTVIEW_GetItemRect(hwnd, i, &rcItem) == TRUE)
     {
-      if ((rcItem.left <= nPosX) && (nPosX <= rcItem.right) && 
-          (rcItem.top <= nPosY) && (nPosY <= rcItem.bottom))
+      if (PtInRect(&rcItem, pt) != FALSE)
       {
         return i;
@@ -1118,5 +1115,5 @@
           COMCTL32_Free(lpSubItem->pszText);
         }
-      
+        
         /* free item */
         COMCTL32_Free(lpSubItem);
@@ -1164,5 +1161,5 @@
       }
     }
-    
+
     if (lpLVItem->mask & LVIF_IMAGE)
     {
@@ -1314,5 +1311,5 @@
  * Initializes subitem attributes.
  *
- * NOTE: the documentation specifies that the operation fails if the user
+ * NOTE: The documentation specifies that the operation fails if the user
  * tries to set the indent of a subitem.
  *
@@ -1543,5 +1540,5 @@
               nmlv.uOldState = lpItem->state & lpLVItem->stateMask;
             }
-
+            
             nmlv.uChanged = uChanged;
             nmlv.iItem = lpLVItem->iItem;
@@ -1631,245 +1628,35 @@
 static INT LISTVIEW_GetTopIndex(HWND hwnd)
 {
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *) GetWindowLongA(hwnd, 0);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView = lStyle & LVS_TYPEMASK;
   INT nItem = 0;
-
-  switch (LVS_TYPEMASK & lStyle)
-  {
-  case LVS_LIST:
+  SCROLLINFO scrollInfo;
+
+  ZeroMemory(&scrollInfo, sizeof(SCROLLINFO));
+  scrollInfo.cbSize = sizeof(SCROLLINFO);
+  scrollInfo.fMask = SIF_POS;
+  
+  if (uView == LVS_LIST)
+  {
     if (lStyle & WS_HSCROLL)
     {
-      nItem = GetScrollPos(hwnd, SB_HORZ) * infoPtr->nCountPerColumn;
-    }
-    break;
-
-  case LVS_REPORT:
+      if (GetScrollInfo(hwnd, SB_HORZ, &scrollInfo) != FALSE)
+      {
+        nItem = scrollInfo.nPos * LISTVIEW_GetCountPerColumn(hwnd);
+      }
+    }
+  }
+  else if (uView == LVS_REPORT)
+  {
     if (lStyle & WS_VSCROLL)
     {
-      nItem = GetScrollPos(hwnd, SB_VERT);
-    }
-    break;
-  }
-
+      if (GetScrollInfo(hwnd, SB_VERT, &scrollInfo) != FALSE)
+      {
+        nItem = scrollInfo.nPos;
+      }
+    }
+  }
+  
   return nItem;
-}
-
-/***
- * DESCRIPTION:
- * Evaluates if scrollbars are needed & sets the scroll range/position.
- * 
- * PARAMETER(S):
- * [I] HWND : window handle
- * [I] LONG : window style
- *
- * RETURN:
- * None
- */
-static VOID LISTVIEW_SetScroll(HWND hwnd, LONG lStyle)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
-  INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
-  INT nHScrollHeight = GetSystemMetrics(SM_CYHSCROLL);
-  INT nVScrollWidth = GetSystemMetrics(SM_CXVSCROLL);
-  INT nHiddenWidth;
-  INT nHiddenHeight;
-  INT nHiddenItemCount;
-  INT nScrollPos;
-  INT nMaxRange;
-  INT nCountPerPage;
-  INT nPixPerScrollPos;
-  RECT rcView;
-
-//  TRACE(listview, "(hwnd=%x,lStyle=%lx)\n", hwnd, lStyle);
-
-  switch (LVS_TYPEMASK & lStyle)
-  {
-  case LVS_LIST:
-    nCountPerPage = infoPtr->nCountPerRow * infoPtr->nCountPerColumn;
-    if (nCountPerPage < GETITEMCOUNT(infoPtr))
-    {
-      /* display horizontal scrollbar */
-      if ((lStyle &  WS_HSCROLL) == 0)
-      {
-	ShowScrollBar(hwnd, SB_HORZ, TRUE);
-      }
-
-      /* calculate new scrollbar range */
-      nHiddenItemCount = GETITEMCOUNT(infoPtr) - nCountPerPage;
-      if ((nHiddenItemCount % infoPtr->nCountPerColumn) == 0)
-      {
-        nMaxRange = nHiddenItemCount / infoPtr->nCountPerColumn;
-      }
-     else
-      {
-        nMaxRange = nHiddenItemCount / infoPtr->nCountPerColumn + 1;
-      }
-        
-      SetScrollRange(hwnd, SB_HORZ, 0, nMaxRange, FALSE);
-      nScrollPos = ListView_GetTopIndex(hwnd) / infoPtr->nCountPerColumn;
-      SetScrollPos(hwnd, SB_HORZ, nScrollPos, TRUE);
-    }
-    else
-    {
-      /* hide scrollbar */
-      if ((lStyle & WS_HSCROLL) != 0)
-      {
-	ShowScrollBar(hwnd, SB_HORZ, FALSE);
-      }
-    }
-    break;
-    
-  case LVS_REPORT:
-/*
- * This section was commented out because I experienced some problems
- * with the scrolling of the header control. The idea was to add a 
- * horizontal scrollbar when the width of the client area was smaller
- * than the width of the header control.
- */
-
-/*     if (infoPtr->nItemWidth > nListWidth) */
-/*     { */
-/*       if ((lStyle &  WS_HSCROLL) == 0) */
-/*       { */
-/*         ShowScrollBar(hwnd, SB_HORZ, TRUE); */
-/*         LISTVIEW_SetSize(hwnd, lStyle, -1, -1); */
-/*         LISTVIEW_SetViewInfo(hwnd, lStyle); */
-/*       } */
-      
-/*       nListWidth = infoPtr->rcList.right - infoPtr->rcList.left; */
-/*       nHiddenWidth = infoPtr->nItemWidth - nListWidth; */
-/*       nPixPerScrollPos = max(1, nListWidth / 10); */
-      
-/*       if ((nHiddenWidth % nPixPerScrollPos) == 0) */
-/*       { */
-/*         nMaxRange = nHiddenWidth / nPixPerScrollPos;  */
-/*       } */
-/*       else */
-/*       { */
-/*         nMaxRange = nHiddenWidth / nPixPerScrollPos + 1;  */
-/*       } */
-
-/*       SetScrollRange(hwnd, SB_HORZ, 0, nMaxRange, FALSE); */
-/*       SetScrollPos(hwnd, SB_HORZ, 0, TRUE); */
-/*     } */
-/*     else */
-/*     { */
-/*       if ((lStyle &  WS_HSCROLL) != 0) */
-/*       { */
-/*         ShowScrollBar(hwnd, SB_HORZ, FASLE); */
-/*         LISTVIEW_SetSize(hwnd, lStyle, -1, -1);  */
-/*         LISTVIEW_SetViewInfo(hwnd, lStyle);  */
-/*       } */
-/*     } */
-  
-    if (infoPtr->nCountPerColumn < GETITEMCOUNT(infoPtr))
-    {
-      if ((lStyle &  WS_VSCROLL) == 0)
-      {
-        if (nListWidth > nVScrollWidth)
-        {
-          ShowScrollBar(hwnd, SB_VERT, TRUE);
-          nListWidth -= nVScrollWidth;
-        }
-      }
-        
-      /* vertical range & position */
-      nMaxRange = GETITEMCOUNT(infoPtr) - infoPtr->nCountPerColumn;
-      SetScrollRange(hwnd, SB_VERT, 0, nMaxRange, FALSE);
-      SetScrollPos(hwnd, SB_VERT, ListView_GetTopIndex(hwnd), TRUE);
-    }
-    else
-    {
-      if ((lStyle &  WS_VSCROLL) != 0)
-      {
-        ShowScrollBar(hwnd, SB_VERT, FALSE);
-        nListWidth += nVScrollWidth;
-      }
-    }
-    break;
-
-  case LVS_ICON:
-  case LVS_SMALLICON:
-    if (LISTVIEW_GetViewRect(hwnd, &rcView) != FALSE)
-    {
-      if (rcView.right - rcView.left > nListWidth)
-      {
-        if ((lStyle & WS_HSCROLL) == 0)
-        {
-          if (nListHeight > nHScrollHeight)
-          {
-            ShowScrollBar(hwnd, SB_HORZ, TRUE);
-            nListHeight -= nHScrollHeight;
-          }
-        }
- 
-        /* calculate size of hidden items */
-        nHiddenWidth = rcView.right - rcView.left - nListWidth;
-        nPixPerScrollPos = max(1, nListWidth / 10);
-
-        /* vertical range & position */
-        if ((nHiddenWidth % nPixPerScrollPos) == 0)
-        {
-          nMaxRange = nHiddenWidth / nPixPerScrollPos; 
-        }
-        else
-        {
-          nMaxRange = nHiddenWidth / nPixPerScrollPos + 1; 
-        }
-
-        /* set range and position */
-        SetScrollRange(hwnd, SB_HORZ, 0, nMaxRange, FALSE);
-        SetScrollPos(hwnd, SB_HORZ, 0, TRUE);
-      }
-      else
-      {
-        if ((lStyle &  WS_HSCROLL) != 0)
-        {
-          ShowScrollBar(hwnd, SB_HORZ, FALSE);
-          nListHeight += nHScrollHeight;
-        }
-      }
-
-      if (rcView.bottom - rcView.top > nListHeight)
-      {
-        if ((lStyle &  WS_VSCROLL) == 0)
-        {
-          if (nListWidth > nVScrollWidth)
-          {
-            ShowScrollBar(hwnd, SB_VERT, TRUE);
-            nListWidth -= nVScrollWidth;
-          }
-        }
-        
-        /* calculate size of hidden items */
-        nHiddenHeight = rcView.bottom - rcView.top - nListHeight;
-        nPixPerScrollPos = max(1, nListHeight / 10);
-        
-        /* set vertical range & position */
-        if ((nHiddenHeight % nPixPerScrollPos) == 0)
-        {
-          nMaxRange = nHiddenHeight / nPixPerScrollPos; 
-        }
-        else
-        {
-          nMaxRange = nHiddenHeight / nPixPerScrollPos + 1; 
-        }
-          
-        /* set range and position */
-        SetScrollRange(hwnd, SB_VERT, 0, nMaxRange, FALSE);
-        SetScrollPos(hwnd, SB_VERT, 0, TRUE);
-      }
-      else
-      {
-        if ((lStyle &  WS_VSCROLL) != 0)
-        {
-          ShowScrollBar(hwnd, SB_VERT, FALSE);
-          nListWidth += nVScrollWidth;
-        }
-      }
-    }
-    break;
-  }
 }
 
@@ -1882,7 +1669,5 @@
  * [I] HDC : device context handle
  * [I] INT : item index
- * [I] LPARAM : item lparam 
- * [I] LISTVIEW_SUBITEM * : item
- * [I] INT : column index (header index)
+ * [I] INT : subitem index
  * [I] RECT * : clipping rectangle
  *
@@ -1890,11 +1675,22 @@
  * None
  */
-static VOID LISTVIEW_DrawSubItem(HWND hwnd, HDC hdc, INT nItem, LPARAM lParam,
-                                 LISTVIEW_SUBITEM *lpSubItem, INT nColumn, 
-                                 RECT *lprc)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+static VOID LISTVIEW_DrawSubItem(HWND hwnd, HDC hdc, INT nItem, INT nSubItem, 
+                                 RECT rcItem)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); 
   CHAR szDispText[DISP_TEXT_SIZE];
-  LPSTR pszDispText = NULL;
+  LVITEMA lvItem;
+
+  TRACE("(hwnd=%x, hdc=%x, nItem=%d, nSubItem=%d\n", hwnd, hdc, 
+        nItem, nSubItem);
+
+  /* get information needed for drawing the item */
+  ZeroMemory(&lvItem, sizeof(LVITEMA));
+  lvItem.mask = LVIF_TEXT;
+  lvItem.iItem = nItem;
+  lvItem.iSubItem = nSubItem;
+  lvItem.cchTextMax = DISP_TEXT_SIZE;
+  lvItem.pszText = szDispText;
+  ListView_GetItemA(hwnd, &lvItem);
 
   /* set item colors */
@@ -1902,17 +1698,127 @@
   SetTextColor(hdc, infoPtr->clrText);
   
-  pszDispText = szDispText;
-  LISTVIEW_GetSubItemDispInfo(hwnd, nItem, lParam, lpSubItem, nColumn, NULL, 
-                              &pszDispText, DISP_TEXT_SIZE);
-
-  /* draw text : using arbitrary offset of 10 pixels */  
+  ExtTextOutA(hdc, rcItem.left, rcItem.top, ETO_OPAQUE | ETO_CLIPPED, 
+              &rcItem, lvItem.pszText, lstrlenA(lvItem.pszText), NULL);
+}
+
+
+/***
+ * DESCRIPTION:
+ * Draws an item.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] HDC : device context handle
+ * [I] INT : item index
+ * [I] RECT * : clipping rectangle
+ *
+ * RETURN:
+ * None
+ */
+static VOID LISTVIEW_DrawItem(HWND hwnd, HDC hdc, INT nItem, RECT rcItem)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); 
+  CHAR szDispText[DISP_TEXT_SIZE];
+  INT nLabelWidth;
+  LVITEMA lvItem;
+  INT nMixMode;
+  DWORD dwBkColor;
+  DWORD dwTextColor;
+
+  TRACE("(hwnd=%x, hdc=%x, nItem=%d\n", hwnd, hdc, nItem);
+
+  /* get information needed for drawing the item */
+  ZeroMemory(&lvItem, sizeof(LVITEMA));
+  lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_INDENT;
+  lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED | LVIS_STATEIMAGEMASK;
+  lvItem.iItem = nItem;
+  lvItem.iSubItem = 0;
+  lvItem.cchTextMax = DISP_TEXT_SIZE;
+  lvItem.pszText = szDispText;
+  ListView_GetItemA(hwnd, &lvItem);
+
+  /* state icons */
+  if (infoPtr->himlState != NULL)
+  {
+     UINT uStateImage = (lvItem.state & LVIS_STATEIMAGEMASK) >> 12; 
+     if (uStateImage != 0)
+     {
+       ImageList_Draw(infoPtr->himlState, uStateImage - 1, hdc, rcItem.left, 
+                      rcItem.top, ILD_NORMAL);
+     }
+ 
+     rcItem.left += infoPtr->iconSize.cx; 
+  }
   
-  ExtTextOutA(hdc, lprc->left, lprc->top, ETO_OPAQUE|ETO_CLIPPED, 
-              lprc, pszDispText, lstrlenA(pszDispText), NULL);
-}
-
-/***
- * DESCRIPTION:
- * Draws an item.
+  /* small icons */
+  if (infoPtr->himlSmall != NULL)
+  {
+    if (lvItem.state & LVIS_SELECTED)
+    {
+      ImageList_SetBkColor(infoPtr->himlSmall, CLR_NONE);
+      ImageList_Draw(infoPtr->himlSmall, lvItem.iImage, hdc, rcItem.left, 
+                     rcItem.top, ILD_SELECTED);
+    }
+    else
+    {
+      ImageList_SetBkColor(infoPtr->himlSmall, CLR_NONE);
+      ImageList_Draw(infoPtr->himlSmall, lvItem.iImage, hdc, rcItem.left, 
+                     rcItem.top, ILD_NORMAL);
+    }
+    
+    rcItem.left += infoPtr->iconSize.cx; 
+  }
+
+  if ((lvItem.state & LVIS_SELECTED) && (infoPtr->bFocus != FALSE))
+  {
+    /* set item colors */ 
+    dwBkColor = SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
+    dwTextColor = SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
+    /* set raster mode */
+    nMixMode = SetROP2(hdc, R2_XORPEN);
+  }
+  else if ((GetWindowLongA(hwnd, GWL_STYLE) & LVS_SHOWSELALWAYS) && 
+           (lvItem.state & LVIS_SELECTED) && (infoPtr->bFocus == FALSE))
+  {
+    dwBkColor = SetBkColor(hdc, GetSysColor(COLOR_3DFACE));
+    dwTextColor = SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT));
+    /* set raster mode */
+    nMixMode = SetROP2(hdc, R2_COPYPEN);
+  }
+  else
+  {
+    /* set item colors */
+    dwBkColor = SetBkColor(hdc, infoPtr->clrTextBk);
+    dwTextColor = SetTextColor(hdc, infoPtr->clrText);
+    /* set raster mode */
+    nMixMode = SetROP2(hdc, R2_COPYPEN);
+  }
+  
+  nLabelWidth = ListView_GetStringWidthA(hwnd, lvItem.pszText);
+  if (rcItem.left + nLabelWidth < rcItem.right)
+  {
+    rcItem.right = rcItem.left + nLabelWidth;
+  }
+  
+  /* draw label */  
+  ExtTextOutA(hdc, rcItem.left, rcItem.top, ETO_OPAQUE | ETO_CLIPPED, 
+              &rcItem, lvItem.pszText, lstrlenA(lvItem.pszText), NULL);
+  
+  if ((lvItem.state & LVIS_FOCUSED) && (infoPtr->bFocus == TRUE))
+  {
+    Rectangle(hdc, rcItem.left, rcItem.top, rcItem.right, rcItem.bottom); 
+  }
+
+  if (nMixMode != 0)
+  {
+    SetROP2(hdc, R2_COPYPEN);
+    SetBkColor(hdc, infoPtr->clrTextBk);
+    SetTextColor(hdc, infoPtr->clrText);
+  }
+}
+
+/***
+ * DESCRIPTION:
+ * Draws an item when in large icon display mode.
  * 
  * PARAMETER(S):
@@ -1926,29 +1832,32 @@
  * None
  */
-static VOID LISTVIEW_DrawItem(HWND hwnd, HDC hdc, LISTVIEW_ITEM *lpItem, 
-                              INT nItem, RECT rc)
+static VOID LISTVIEW_DrawLargeItem(HWND hwnd, HDC hdc, INT nItem, RECT rcItem)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); 
   CHAR szDispText[DISP_TEXT_SIZE];
-  LPSTR pszDispText = NULL;
-  BOOL bSelected;
+  INT nDrawPosX = rcItem.left;
   INT nLabelWidth;
-  INT nImage;
-  UINT uState;
-
-//  TRACE(listview, "(hwnd=%x,hdc=%x,lpItem=%p,nItem=%d,rc.left=%d,rctop=%d,rc.right=%d,rc.bottom=%d)\n", hwnd, hdc, lpItem, nItem, rc.left, rc.top, rc.right, rc.bottom);
-
-  pszDispText = szDispText;
-  LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, &nImage, &uState, &pszDispText,
-                           DISP_TEXT_SIZE);
- 
- if (uState & LVIS_SELECTED)
-  {
-    bSelected = TRUE;
-
+  TEXTMETRICA tm;
+  LVITEMA lvItem;
+
+  TRACE("(hwnd=%x, hdc=%x, nItem=%d, left=%d, top=%d, right=%d, \
+bottom=%d)\n", hwnd, hdc, nItem, rcItem.left, rcItem.top, rcItem.right, 
+        rcItem.bottom);
+
+  /* get information needed for drawing the item */
+  ZeroMemory(&lvItem, sizeof(LVITEMA));
+  lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
+  lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
+  lvItem.iItem = nItem;
+  lvItem.iSubItem = 0;
+  lvItem.cchTextMax = DISP_TEXT_SIZE;
+  lvItem.pszText = szDispText;
+  ListView_GetItemA(hwnd, &lvItem);
+
+  if (lvItem.state & LVIS_SELECTED)
+  {
     /* set item colors */ 
     SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
     SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
-    
     /* set raster mode */
     SetROP2(hdc, R2_XORPEN);
@@ -1956,159 +1865,50 @@
   else
   {
-    bSelected = FALSE;
-    
     /* set item colors */
     SetBkColor(hdc, infoPtr->clrTextBk);
     SetTextColor(hdc, infoPtr->clrText);
-    
     /* set raster mode */
     SetROP2(hdc, R2_COPYPEN);
   }
 
-  /* state icons */
-  if (infoPtr->himlState != NULL)
-  {
-    /* right shift 12 bits to obtain index in image list */
-    if (bSelected != FALSE)
-    {
-      ImageList_Draw(infoPtr->himlState, uState >> 12, hdc, rc.left, 
-                     rc.top, ILD_SELECTED);
+  if (infoPtr->himlNormal != NULL)
+  {
+    rcItem.top += ICON_TOP_PADDING;
+    nDrawPosX += (infoPtr->iconSpacing.cx - infoPtr->iconSize.cx) / 2;
+    if (lvItem.state & LVIS_SELECTED)
+    {
+      ImageList_Draw(infoPtr->himlNormal, lvItem.iImage, hdc, nDrawPosX, 
+                     rcItem.top, ILD_SELECTED);
     }
     else
     {
-      ImageList_Draw(infoPtr->himlState, uState >> 12, hdc, rc.left, 
-                     rc.top, ILD_NORMAL);
-    }
-    
-    rc.left += infoPtr->iconSize.cx; 
-  }
-  
-  /* small icons */
-  if (infoPtr->himlSmall != NULL)
-  {
-    if (bSelected != FALSE)
-    {
-      ImageList_Draw(infoPtr->himlSmall, nImage, hdc, rc.left, 
-                     rc.top, ILD_SELECTED);
-    }
-    else
-    {
-      ImageList_Draw(infoPtr->himlSmall, nImage, hdc, rc.left, 
-                     rc.top, ILD_NORMAL);
-    }
-    
-    rc.left += infoPtr->iconSize.cx; 
-  }
-  
-  nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText);
-  if (rc.left + nLabelWidth < rc.right)
-  {
-    rc.right = rc.left + nLabelWidth;
-  } 
-
-  /* draw label */  
-  ExtTextOutA(hdc, rc.left, rc.top, ETO_OPAQUE|ETO_CLIPPED, 
-              &rc, pszDispText, lstrlenA(pszDispText), NULL);
-  
-  if (lpItem->state & LVIS_FOCUSED)
-  {
-    Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom); 
-  }
-}
-
-/***
- * DESCRIPTION:
- * Draws an item when in large icon display mode.
- * 
- * PARAMETER(S):
- * [I] HWND : window handle
- * [I] HDC : device context handle
- * [I] LISTVIEW_ITEM * : item
- * [I] INT : item index
- * [I] RECT * : clipping rectangle
- *
- * RETURN:
- * None
- */
-static VOID LISTVIEW_DrawLargeItem(HWND hwnd, HDC hdc, LISTVIEW_ITEM *lpItem, 
-                                   INT nItem, RECT rc)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); 
-  CHAR szDispText[DISP_TEXT_SIZE];
-  LPSTR pszDispText = NULL;
-  BOOL bSelected;
-  INT nLabelWidth;
-  INT nImage;
-  UINT uState;
-  INT nDrawPosX = 0;
-  TEXTMETRICA tm;
-
-//  TRACE(listview, "(hwnd=%x,hdc=%x,lpItem=%p,nItem=%d,rc.left=%d,rctop=%d,rc.right=%d,rc.bottom=%d)\n", hwnd, hdc, lpItem, nItem, rc.left, rc.top, rc.right, rc.bottom);
-
-  pszDispText = szDispText;
-  LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, &nImage, &uState, &pszDispText,
-                           DISP_TEXT_SIZE);
-  if (uState & LVIS_SELECTED)
-  {
-    bSelected = TRUE;
-
-    /* set item colors */ 
-    SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
-    SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
-    
-    /* set raster mode */
-    SetROP2(hdc, R2_XORPEN);
-  }
-  else
-  {
-    bSelected = FALSE;
-
-    /* set item colors */
-    SetBkColor(hdc, infoPtr->clrTextBk);
-    SetTextColor(hdc, infoPtr->clrText);
-    
-    /* set raster mode */
-    SetROP2(hdc, R2_COPYPEN);
-  }
-
-  if (infoPtr->himlNormal != NULL)
-  {
-    rc.top += ICON_TOP_PADDING;
-    nDrawPosX = rc.left + (infoPtr->iconSpacing.cx - infoPtr->iconSize.cx) / 2;
-    if (bSelected != FALSE)
-    {
-      ImageList_Draw(infoPtr->himlNormal, nImage, hdc, nDrawPosX, rc.top, 
-                     ILD_SELECTED);
-    }
-    else
-    {
-      ImageList_Draw(infoPtr->himlNormal, nImage, hdc, nDrawPosX, rc.top, 
-                     ILD_NORMAL);
-    }
-  }
-
-  rc.top += infoPtr->iconSize.cy + ICON_BOTTOM_PADDING; 
-  nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText);
+      ImageList_Draw(infoPtr->himlNormal, lvItem.iImage, hdc, nDrawPosX, 
+                     rcItem.top, ILD_NORMAL);
+    }
+  }
+
+  rcItem.top += infoPtr->iconSize.cy + ICON_BOTTOM_PADDING; 
+  nLabelWidth = ListView_GetStringWidthA(hwnd, lvItem.pszText);
   nDrawPosX = infoPtr->iconSpacing.cx - nLabelWidth;
   if (nDrawPosX > 1)
   {
-    rc.left += nDrawPosX / 2;
-    rc.right = rc.left + nLabelWidth;
+    rcItem.left += nDrawPosX / 2;
+    rcItem.right = rcItem.left + nLabelWidth;
   }
   else
   {
-    rc.left += 1;
-    rc.right = rc.left + infoPtr->iconSpacing.cx - 1;
+    rcItem.left += 1;
+    rcItem.right = rcItem.left + infoPtr->iconSpacing.cx - 1;
   }
 
   /* draw label */  
   GetTextMetricsA(hdc, &tm);
-  rc.bottom = rc.top + tm.tmHeight + HEIGHT_PADDING; 
-  ExtTextOutA(hdc, rc.left, rc.top, ETO_OPAQUE|ETO_CLIPPED, 
-              &rc, pszDispText, lstrlenA(pszDispText), NULL);
+  rcItem.bottom = rcItem.top + tm.tmHeight + HEIGHT_PADDING; 
+  ExtTextOutA(hdc, rcItem.left, rcItem.top, ETO_OPAQUE | ETO_CLIPPED, 
+              &rcItem, lvItem.pszText, lstrlenA(lvItem.pszText), NULL);
         
-  if (lpItem->state & LVIS_FOCUSED)
-  {
-    Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom); 
+  if (lvItem.state & LVIS_FOCUSED)
+  {
+    Rectangle(hdc, rcItem.left, rcItem.top, rcItem.right, rcItem.bottom); 
   }
 }
@@ -2129,89 +1929,234 @@
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd,0);
   INT nDrawPosY = infoPtr->rcList.top;
-  LISTVIEW_ITEM *lpItem;
-  LISTVIEW_SUBITEM *lpSubItem = NULL;
-  BOOL bNeedSubItem = TRUE;
   INT nColumnCount;
-  HDPA hdpaSubItems;
   RECT rcItem;
-  INT  j, k;
+  INT  j;
   INT nItem;
   INT nLast;
 
   nItem = ListView_GetTopIndex(hwnd);
-  nLast = nItem + infoPtr->nCountPerColumn;
-  while (nItem <= nLast)
-  {
-    hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
-    if (hdpaSubItems != NULL)
-    {
-      lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
-      if (lpItem != NULL)
-      {
-        /* the width of the header items will determine the size of the 
-           listview items */
-        Header_GetItemRect(infoPtr->hwndHeader, 0, &rcItem);
-        rcItem.left += REPORT_MARGINX;
-        rcItem.right = max(rcItem.left, rcItem.right - REPORT_MARGINX);
-        rcItem.top = nDrawPosY;
-        rcItem.bottom = rcItem.top + infoPtr->nItemHeight;
-        LISTVIEW_DrawItem(hwnd, hdc, lpItem, nItem, rcItem);
-      }
-
-      nColumnCount = Header_GetItemCount(infoPtr->hwndHeader);
-      for (k = 1, j = 1; j < nColumnCount; j++)
-      {
-        Header_GetItemRect(infoPtr->hwndHeader, j, &rcItem);
-        rcItem.left += REPORT_MARGINX;
-        rcItem.right = max(rcItem.left, rcItem.right - REPORT_MARGINX);
-        rcItem.top = nDrawPosY;
-        rcItem.bottom = rcItem.top + infoPtr->nItemHeight;
-
-        if (k < hdpaSubItems->nItemCount)
-        {
-          if (bNeedSubItem != FALSE)
+
+  /* add 1 for displaying a partial item at the bottom */
+  nLast = nItem + LISTVIEW_GetCountPerColumn(hwnd) + 1;
+  nLast = min(nLast, GETITEMCOUNT(infoPtr));
+  for (; nItem < nLast; nItem++)
+  {
+    nColumnCount = Header_GetItemCount(infoPtr->hwndHeader);
+    for (j = 0; j < nColumnCount; j++)
+    {
+      Header_GetItemRect(infoPtr->hwndHeader, j, &rcItem);
+      rcItem.left += REPORT_MARGINX;
+      rcItem.right = max(rcItem.left, rcItem.right - REPORT_MARGINX);
+      rcItem.top = nDrawPosY;
+      rcItem.bottom = rcItem.top + infoPtr->nItemHeight;
+      if (j == 0)
+      {
+        LISTVIEW_DrawItem(hwnd, hdc, nItem, rcItem); 
+      }
+      else 
+      {
+        LISTVIEW_DrawSubItem(hwnd, hdc, nItem, j, rcItem);
+      }
+    }
+    
+    nDrawPosY += infoPtr->nItemHeight;
+  }
+}
+
+/***
+ * DESCRIPTION:
+ * Retrieves the number of items that can fit vertically in the client area.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ *
+ * RETURN:
+ * Number of items per row.
+ */
+static INT LISTVIEW_GetCountPerRow(HWND hwnd)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd,0);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
+  INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
+  INT nCountPerRow = 1;
+
+  if (nListWidth > 0)
+  {
+    if (uView == LVS_REPORT)
+    {
+      nCountPerRow = 1;
+    }
+    else
+    {
+      nCountPerRow =  nListWidth / infoPtr->nItemWidth;
+      if (nCountPerRow == 0)
+      {
+        nCountPerRow = 1;
+      }
+    }
+  }
+
+  return nCountPerRow;
+}
+
+/***
+ * DESCRIPTION:
+ * Retrieves the number of items that can fit horizontally in the client 
+ * area.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ *
+ * RETURN:
+ * Number of items per column.
+ */
+static INT LISTVIEW_GetCountPerColumn(HWND hwnd)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd,0);
+  INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
+  INT nCountPerColumn = 1;
+
+  if (nListHeight > 0)
+  {
+    nCountPerColumn =  nListHeight / infoPtr->nItemHeight;
+    if (nCountPerColumn == 0)
+    {
+      nCountPerColumn = 1;
+    }
+  }
+
+  return nCountPerColumn;
+}
+
+/***
+ * DESCRIPTION:
+ * Retrieves the number of columns needed to display all the items when in 
+ * list display mode.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ *
+ * RETURN:
+ * Number of columns.
+ */
+static INT LISTVIEW_GetColumnCount(hwnd)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  INT nColumnCount = 0;
+
+  if ((lStyle & LVS_TYPEMASK) == LVS_LIST)
+  {
+    if (infoPtr->rcList.right % infoPtr->nItemWidth == 0)
+    {
+      nColumnCount = infoPtr->rcList.right / infoPtr->nItemWidth;
+    }
+    else
+    {
+      nColumnCount = infoPtr->rcList.right / infoPtr->nItemWidth + 1;
+    }
+  }
+
+  return nColumnCount;
+}  
+  
+
+/***
+ * DESCRIPTION:
+ * Draws listview items when in list display mode.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] HDC : device context handle 
+ *
+ * RETURN:
+ * None
+ */
+static VOID LISTVIEW_RefreshList(HWND hwnd, HDC hdc)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  RECT rcItem;
+  INT i, j;
+  INT nItem;
+  INT nColumnCount;
+  INT nCountPerColumn;
+  
+  /* get number of fully visible columns */
+  nColumnCount = LISTVIEW_GetColumnCount(hwnd);
+  nCountPerColumn = LISTVIEW_GetCountPerColumn(hwnd);
+  nItem = ListView_GetTopIndex(hwnd);
+
+  for (i = 0; i < nColumnCount; i++)
+  {
+    for (j = 0; j < nCountPerColumn; j++, nItem++)
+    {
+      if (nItem >= GETITEMCOUNT(infoPtr))
+        return;
+
+      rcItem.top = j * infoPtr->nItemHeight;
+      rcItem.left = i * infoPtr->nItemWidth;
+      rcItem.bottom = rcItem.top + infoPtr->nItemHeight;
+      rcItem.right = rcItem.left + infoPtr->nItemWidth;
+      LISTVIEW_DrawItem(hwnd, hdc, nItem, rcItem);
+    }
+  }
+}
+
+/***
+ * DESCRIPTION:
+ * Draws listview items when in icon or small icon display mode.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] HDC : device context handle 
+ *
+ * RETURN:
+ * None
+ */
+static VOID LISTVIEW_RefreshIcon(HWND hwnd, HDC hdc, BOOL bSmall)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  POINT ptPosition;
+  POINT ptOrigin;
+  RECT rcItem;
+  INT i;
+
+  LISTVIEW_GetOrigin(hwnd, &ptOrigin);
+  for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
+  {
+    LISTVIEW_GetItemPosition(hwnd, i, &ptPosition);
+    ptPosition.x += ptOrigin.x;
+    ptPosition.y += ptOrigin.y;
+      
+    if (ptPosition.y + infoPtr->nItemHeight > infoPtr->rcList.top)
+    {
+      if (ptPosition.x + infoPtr->nItemWidth > infoPtr->rcList.left)
+      {
+        if (ptPosition.y < infoPtr->rcList.bottom)
+        {
+          if (ptPosition.x < infoPtr->rcList.right)
           {
-            lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, k);
-            k++;
-          }
-
-          if (lpSubItem != NULL)
-          {
-            if (lpSubItem->iSubItem == j)
+            rcItem.top = ptPosition.y;
+            rcItem.left = ptPosition.x;
+            rcItem.bottom = rcItem.top + infoPtr->nItemHeight;
+            rcItem.right = rcItem.left + infoPtr->nItemWidth;
+            if (bSmall == FALSE)
             {
-              LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, lpSubItem,
-                                   j, &rcItem);
-              bNeedSubItem = TRUE;
+              LISTVIEW_DrawLargeItem(hwnd, hdc, i, rcItem);
             }
             else
             {
-              LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j, 
-                                   &rcItem);
-              bNeedSubItem = FALSE;
+              LISTVIEW_DrawItem(hwnd, hdc, i, rcItem);
             }
           }
-          else
-          {
-            LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j, 
-                                 &rcItem);
-            bNeedSubItem = TRUE;
-          }
-        }
-        else
-        {
-          LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j, 
-                               &rcItem);
-        }
-      }
-    }
-
-    nDrawPosY += infoPtr->nItemHeight;
-    nItem++;
-  }
-}
-
-/***
- * DESCRIPTION:
- * Draws listview items when in list display mode.
+        }
+      }
+    }
+  }
+}
+
+/***
+ * DESCRIPTION:
+ * Draws listview items.
  * 
  * PARAMETER(S):
@@ -2220,128 +2165,4 @@
  *
  * RETURN:
- * None
- */
-static VOID LISTVIEW_RefreshList(HWND hwnd, HDC hdc)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LISTVIEW_ITEM *lpItem;
-  HDPA hdpaSubItems;
-  RECT rc;
-  INT i, j;
-  INT nColumnCount;
-  INT nItem = ListView_GetTopIndex(hwnd);
-
-  if (infoPtr->rcList.right > 0)
-  {
-    /* get number of display columns */
-    if (infoPtr->rcList.right % infoPtr->nItemWidth == 0)
-    {
-      nColumnCount = infoPtr->rcList.right / infoPtr->nItemWidth;
-    }
-    else
-    {
-      nColumnCount = infoPtr->rcList.right / infoPtr->nItemWidth + 1;
-    }
-
-    for (i = 0; i < nColumnCount; i++)
-    {
-      j = 0;
-      while ((nItem < GETITEMCOUNT(infoPtr)) && 
-             (j<infoPtr->nCountPerColumn))
-      {
-        hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
-        if (hdpaSubItems != NULL)
-        {
-          lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
-          if (lpItem != NULL)
-          {
-            rc.top = j * infoPtr->nItemHeight;
-            rc.left = i * infoPtr->nItemWidth;
-            rc.bottom = rc.top + infoPtr->nItemHeight;
-            rc.right = rc.left + infoPtr->nItemWidth;
-            LISTVIEW_DrawItem(hwnd, hdc,  lpItem, nItem, rc);
-          }
-        }
- 
-        nItem++;
-        j++;
-      }
-    }
-  }
-}
-
-/***
- * DESCRIPTION:
- * Draws listview items when in icon or small icon display mode.
- * 
- * PARAMETER(S):
- * [I] HWND : window handle
- * [I] HDC : device context handle 
- *
- * RETURN:
- * None
- */
-static VOID LISTVIEW_RefreshIcon(HWND hwnd, HDC hdc, BOOL bSmall)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LISTVIEW_ITEM *lpItem;
-  HDPA hdpaSubItems;
-  POINT ptPosition;
-  POINT ptOrigin;
-  RECT rc;
-  INT i;
-
-  LISTVIEW_GetOrigin(hwnd, &ptOrigin);
-
-  for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
-  {
-    LISTVIEW_GetItemPosition(hwnd, i, &ptPosition);
-    ptPosition.x += ptOrigin.x;
-    ptPosition.y += ptOrigin.y;
-
-    if (ptPosition.y + infoPtr->nItemHeight > infoPtr->rcList.top)
-    {
-      if (ptPosition.x + infoPtr->nItemWidth > infoPtr->rcList.left)
-      {
-        if (ptPosition.y < infoPtr->rcList.bottom)
-        {
-          if (ptPosition.x < infoPtr->rcList.right)
-          {
-            hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, i);
-            if (hdpaSubItems != NULL)
-            {
-              lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
-              if (lpItem != NULL)
-              {
-                rc.top = ptPosition.y;
-                rc.left = ptPosition.x;
-                rc.bottom = rc.top + infoPtr->nItemHeight;
-                rc.right = rc.left + infoPtr->nItemWidth;
-                if (bSmall == FALSE)
-                {
-                  LISTVIEW_DrawLargeItem(hwnd, hdc, lpItem, i, rc);
-                }
-                else
-                {
-                  LISTVIEW_DrawItem(hwnd, hdc, lpItem, i, rc);
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-}
-
-/***
- * DESCRIPTION:
- * Draws listview items.
- * 
- * PARAMETER(S):
- * [I] HWND : window handle
- * [I] HDC : device context handle 
- *
- * RETURN:
  * NoneX
  */
@@ -2349,5 +2170,5 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
   HFONT hOldFont;
   HPEN hPen, hOldPen;
@@ -2363,16 +2184,18 @@
   SelectObject(hdc, GetStockObject(NULL_BRUSH)); 
 
-  switch (LVS_TYPEMASK & lStyle)
-  {
-  case LVS_LIST:
+  if (uView == LVS_LIST)
+  {
     LISTVIEW_RefreshList(hwnd, hdc); 
-    break;
-  case LVS_REPORT:
+  }
+  else if (uView == LVS_REPORT)
+  {
     LISTVIEW_RefreshReport(hwnd, hdc);
-    break;
-  case LVS_SMALLICON:
+  }
+  else if (uView == LVS_SMALLICON)
+  {
     LISTVIEW_RefreshIcon(hwnd, hdc, TRUE);
-    break;
-  case LVS_ICON:
+  }
+  else if (uView == LVS_ICON)
+  {
     LISTVIEW_RefreshIcon(hwnd, hdc, FALSE);
   }
@@ -2404,5 +2227,5 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
   INT nItemCountPerColumn = 1;
   INT nColumnCount = 0;
@@ -2410,12 +2233,14 @@
 
   if (nItemCount == -1)
+  {
     nItemCount = GETITEMCOUNT(infoPtr);
-
-  if (lStyle & LVS_LIST)
+  }
+
+  if (uView == LVS_LIST)
   {
     if (wHeight == 0xFFFF)
     {
       /* use current height */
-      wHeight = infoPtr->rcList.bottom;
+      wHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
     }
 
@@ -2431,10 +2256,16 @@
         nItemCountPerColumn = wHeight / infoPtr->nItemHeight;
         if (nItemCountPerColumn == 0)
+        {
           nItemCountPerColumn = 1;
-
+        }
+        
         if (nItemCount % nItemCountPerColumn != 0)
+        {
           nColumnCount = nItemCount / nItemCountPerColumn;
+        }
         else
+        {
           nColumnCount = nItemCount / nItemCountPerColumn + 1;
+        }
       }
     }
@@ -2446,13 +2277,13 @@
     dwViewRect = MAKELONG(wWidth, wHeight);
   }
-  else if (lStyle & LVS_REPORT)
+  else if (uView == LVS_REPORT)
   {
     /* TO DO */
-    }
-  else if (lStyle & LVS_SMALLICON)
+  }
+  else if (uView == LVS_SMALLICON)
   {
     /* TO DO */
   }
-  else if (lStyle & LVS_ICON)
+  else if (uView == LVS_ICON)
   {
     /* TO DO */
@@ -2476,9 +2307,8 @@
 static LRESULT LISTVIEW_Arrange(HWND hwnd, INT nAlignCode)
 {
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK; 
   BOOL bResult = FALSE;
 
-  if (((LVS_TYPEMASK & lStyle) == LVS_ICON) || 
-      ((LVS_TYPEMASK & lStyle) == LVS_SMALLICON))
+  if ((uView == LVS_ICON) || (uView == LVS_SMALLICON))
   {
     switch (nAlignCode)
@@ -2520,4 +2350,5 @@
   LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView = lStyle & LVS_TYPEMASK;
   LISTVIEW_ITEM *lpItem;
   LISTVIEW_SUBITEM *lpSubItem;
@@ -2529,5 +2360,5 @@
   HDPA hdpaSubItems;
 
-//  TRACE(listview, "(hwnd=%x,)\n", hwnd);
+  TRACE("(hwnd=%x,)\n", hwnd);
 
   if (GETITEMCOUNT(infoPtr) > 0)
@@ -2599,8 +2430,6 @@
     
     /* align items (set position of each item) */
-    switch (lStyle & LVS_TYPEMASK)
-    {
-    case LVS_ICON:
-    case LVS_SMALLICON:
+    if ((uView == LVS_ICON) || (uView == LVS_SMALLICON))
+    {
       if (lStyle & LVS_ALIGNLEFT)
       {
@@ -2611,8 +2440,7 @@
         LISTVIEW_AlignTop(hwnd);
       }
-      break;
     }
     
-    LISTVIEW_SetScroll(hwnd, lStyle);
+    LISTVIEW_UpdateScroll(hwnd);
 
     /* invalidate client area (optimization needed) */
@@ -2638,5 +2466,5 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
   BOOL bResult = FALSE;
   
@@ -2646,12 +2474,12 @@
 
     /* reset scroll parameters */
-    if ((lStyle & LVS_TYPEMASK) == LVS_REPORT)
-    {
-      LISTVIEW_SetViewInfo(hwnd, lStyle);
-      LISTVIEW_SetScroll(hwnd, lStyle);
-    }
-
-    /* refresh client area */
-    InvalidateRect(hwnd, NULL, FALSE);
+    if (uView == LVS_REPORT)
+    {
+      /* update scrollbar(s) */
+      LISTVIEW_UpdateScroll(hwnd);
+
+      /* refresh client area */
+      InvalidateRect(hwnd, NULL, FALSE);
+    }
   }
 
@@ -2675,4 +2503,5 @@
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView = lStyle & LVS_TYPEMASK;
   LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
   NMLISTVIEW nmlv;
@@ -2683,5 +2512,5 @@
   INT i;
 
-//  TRACE(listview, "(hwnd=%x,nItem=%d)\n", hwnd, nItem);
+  TRACE("(hwnd=%x,nItem=%d)\n", hwnd, nItem);
 
   if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
@@ -2737,8 +2566,6 @@
 
     /* align items (set position of each item) */
-    switch(lStyle & LVS_TYPEMASK)
-    {
-    case LVS_ICON:
-    case LVS_SMALLICON:
+    if ((uView == LVS_SMALLICON) || (uView == LVS_ICON))
+    {
       if (lStyle & LVS_ALIGNLEFT)
       {
@@ -2749,8 +2576,7 @@
         LISTVIEW_AlignTop(hwnd);
       }
-      break;
-    }
-
-    LISTVIEW_SetScroll(hwnd, lStyle);
+    }
+
+    LISTVIEW_UpdateScroll(hwnd);
 
     /* refresh client area */
@@ -2779,13 +2605,15 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
   INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
   INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
-  INT nHScrollPos = 0;
-  INT nVScrollPos = 0;
   INT nScrollPosHeight = 0;
   INT nScrollPosWidth = 0;
+  SCROLLINFO scrollInfo;
   RECT rcItem;
-  BOOL bResult = FALSE;
+
+  ZeroMemory(&scrollInfo, sizeof(SCROLLINFO));
+  scrollInfo.cbSize = sizeof(SCROLLINFO);
+  scrollInfo.fMask = SIF_POS;
 
   /* ALWAYS bPartial == FALSE, FOR NOW! */
@@ -2796,52 +2624,56 @@
     if (rcItem.left < infoPtr->rcList.left)
     {
-      /* scroll left */
-      switch (LVS_TYPEMASK & lStyle)
-      {
-      case LVS_LIST:
-        rcItem.left += infoPtr->rcList.left;
-        nScrollPosWidth = infoPtr->nItemWidth;
-        break;
-
-      case LVS_SMALLICON:
-      case LVS_ICON:
-        nScrollPosWidth = max(1, nListWidth / 10);
-        rcItem.left += infoPtr->rcList.left;
-        break;
-      }
-
-      if (rcItem.left % nScrollPosWidth == 0)
-      {
-        nHScrollPos = rcItem.left / nScrollPosWidth;
-      }
-      else
-      {
-        nHScrollPos = rcItem.left / nScrollPosWidth - 1;
+      if (GetScrollInfo(hwnd, SB_HORZ, &scrollInfo) != FALSE)
+      {
+        /* scroll left */
+        if (uView == LVS_LIST)
+        {
+          nScrollPosWidth = infoPtr->nItemWidth;
+          rcItem.left += infoPtr->rcList.left;
+        }
+        else if ((uView == LVS_SMALLICON) || (uView == LVS_ICON))
+        {
+          nScrollPosWidth = max(1, nListWidth / 10);
+          rcItem.left += infoPtr->rcList.left;
+        }
+        
+        if (rcItem.left % nScrollPosWidth == 0)
+        {
+          scrollInfo.nPos += rcItem.left / nScrollPosWidth;
+        }
+        else
+        {
+          scrollInfo.nPos += rcItem.left / nScrollPosWidth - 1;
+        }
+        
+        SetScrollInfo(hwnd, SB_HORZ, &scrollInfo, TRUE);
       }
     }
     else if (rcItem.right > infoPtr->rcList.right)
     {
-      /* scroll right */
-      switch (LVS_TYPEMASK & lStyle)
-      {
-      case LVS_LIST:
-        rcItem.right -= infoPtr->rcList.right;
-        nScrollPosWidth = infoPtr->nItemWidth;
-        break;
-
-      case LVS_SMALLICON:
-      case LVS_ICON:
-        nScrollPosWidth = max(1, nListWidth / 10);
-        rcItem.right -= infoPtr->rcList.right;
-        break;
-      }
-
-      if (rcItem.right % nScrollPosWidth == 0)
-      {
-        nHScrollPos = rcItem.right / nScrollPosWidth;
-      }
-      else
-      {
-        nHScrollPos = rcItem.right / nScrollPosWidth + 1;
+      if (GetScrollInfo(hwnd, SB_HORZ, &scrollInfo) != FALSE)
+      {
+        /* scroll right */
+        if (uView == LVS_LIST)
+        {
+          rcItem.right -= infoPtr->rcList.right;
+          nScrollPosWidth = infoPtr->nItemWidth;
+        }
+        else if ((uView == LVS_SMALLICON) || (uView == LVS_ICON))
+        {
+          rcItem.right -= infoPtr->rcList.right;
+          nScrollPosWidth = max(1, nListWidth / 10);
+        }
+
+        if (rcItem.right % nScrollPosWidth == 0)
+        {
+          scrollInfo.nPos += rcItem.right / nScrollPosWidth;
+        }
+        else
+        {
+          scrollInfo.nPos += rcItem.right / nScrollPosWidth + 1;
+        }
+
+        SetScrollInfo(hwnd, SB_HORZ, &scrollInfo, TRUE);
       }
     }
@@ -2850,58 +2682,122 @@
     {
       /* scroll up */
-      switch (LVS_TYPEMASK & lStyle)
-      {
-      case LVS_REPORT:
-        rcItem.top -= infoPtr->rcList.top; 
-        nScrollPosHeight = infoPtr->nItemHeight;
-        break;
-
-      case LVS_SMALLICON:
-      case LVS_ICON:
-        nScrollPosHeight = max(1, nListHeight / 10);
-        rcItem.top += infoPtr->rcList.top;
-        break;
-      }
-
-      if (rcItem.top % nScrollPosHeight == 0)
-      {
-        nVScrollPos = rcItem.top / nScrollPosHeight;
+      if (GetScrollInfo(hwnd, SB_VERT, &scrollInfo) != FALSE)
+      {
+        if (uView == LVS_REPORT)
+        {
+          rcItem.top -= infoPtr->rcList.top; 
+          nScrollPosHeight = infoPtr->nItemHeight;
+        }
+        else if ((uView == LVS_ICON) || (uView == LVS_SMALLICON))
+        {
+          nScrollPosHeight = max(1, nListHeight / 10);
+          rcItem.top += infoPtr->rcList.top;
+        }
+
+        if (rcItem.top % nScrollPosHeight == 0)
+        {
+          scrollInfo.nPos += rcItem.top / nScrollPosHeight;
+        }
+        else
+        {
+          scrollInfo.nPos += rcItem.top / nScrollPosHeight - 1;
+        }
+        
+        SetScrollInfo(hwnd, SB_VERT, &scrollInfo, TRUE);
+      }
+    }
+    else if (rcItem.bottom > infoPtr->rcList.bottom)
+    {
+      /* scroll down */
+      if (GetScrollInfo(hwnd, SB_VERT, &scrollInfo) != FALSE)
+      {
+        if (uView == LVS_REPORT)
+        {
+          rcItem.bottom -= infoPtr->rcList.bottom;
+          nScrollPosHeight = infoPtr->nItemHeight;
+        }
+        else if ((uView == LVS_ICON) || (uView == LVS_SMALLICON))
+        {
+          nScrollPosHeight = max(1, nListHeight / 10);
+          rcItem.bottom -= infoPtr->rcList.bottom;
+        }
+
+        if (rcItem.bottom % nScrollPosHeight == 0)
+        {
+          scrollInfo.nPos += rcItem.bottom / nScrollPosHeight;
+        }
+        else
+        {
+          scrollInfo.nPos += rcItem.bottom / nScrollPosHeight + 1;
+        }
+        
+        SetScrollInfo(hwnd, SB_VERT, &scrollInfo, TRUE);
+      }
+    }
+  }
+  
+  return TRUE;
+}
+
+/***
+ * DESCRIPTION:
+ * Retrieves the nearest item, given a position and a direction.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] POINT : start position
+ * [I] UINT : direction
+ *
+ * RETURN:
+ * Item index if successdful, -1 otherwise.
+ */
+static INT LISTVIEW_GetNearestItem(HWND hwnd, POINT pt, UINT vkDirection)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  LVHITTESTINFO lvHitTestInfo;
+  INT nItem = -1;
+  RECT rcView;
+
+  if (LISTVIEW_GetViewRect(hwnd, &rcView) != FALSE)
+  {
+    ZeroMemory(&lvHitTestInfo, sizeof(LVHITTESTINFO));
+    LISTVIEW_GetOrigin(hwnd, &lvHitTestInfo.pt);
+    lvHitTestInfo.pt.x += pt.x;
+    lvHitTestInfo.pt.y += pt.y;
+    
+    do
+    { 
+      if (vkDirection == VK_DOWN)
+      {
+        lvHitTestInfo.pt.y += infoPtr->nItemHeight;
+      }      
+      else if (vkDirection == VK_UP)
+      {
+        lvHitTestInfo.pt.y -= infoPtr->nItemHeight;
+      }
+      else if (vkDirection == VK_LEFT)
+      {
+        lvHitTestInfo.pt.x -= infoPtr->nItemWidth;
+      }
+      else if (vkDirection == VK_RIGHT)
+      {
+        lvHitTestInfo.pt.x += infoPtr->nItemWidth;
+      }
+
+      if (PtInRect(&rcView, lvHitTestInfo.pt) == FALSE)
+      {
+        return -1;
       }
       else
       {
-        nVScrollPos = rcItem.top / nScrollPosHeight - 1;
-      }
-    }
-    else if (rcItem.bottom > infoPtr->rcList.bottom)
-    {
-      switch (LVS_TYPEMASK & lStyle)
-      {
-      case LVS_REPORT:
-        rcItem.bottom -= infoPtr->rcList.bottom;
-        nScrollPosHeight = infoPtr->nItemHeight;
-        break;
-
-      case LVS_SMALLICON:
-      case LVS_ICON:
-        nScrollPosHeight = max(1, nListHeight / 10);
-        rcItem.bottom -= infoPtr->rcList.bottom;
-        break;
-      }
-
-      if (rcItem.bottom % nScrollPosHeight == 0)
-      {
-        nVScrollPos = rcItem.bottom / nScrollPosHeight;
-      }
-      else
-      {
-        nVScrollPos = rcItem.bottom / nScrollPosHeight + 1;
-      }
-    }
-
-    bResult = LISTVIEW_ScrollView(hwnd, nHScrollPos, nVScrollPos);
-  }
-  
-  return bResult;
-}
+        nItem = LISTVIEW_HitTestItem(hwnd, &lvHitTestInfo);
+      }
+
+    }
+    while (nItem == -1);
+  }
+
+  return nItem;
+}  
 
 /***
@@ -2921,7 +2817,110 @@
                                  LPLVFINDINFO lpFindInfo)
 {
-//  FIXME (listview, "empty stub!\n");
-
-  return -1; 
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  POINT ptItem;
+  CHAR szDispText[DISP_TEXT_SIZE];
+  LVITEMA lvItem;
+  BOOL bWrap = FALSE;
+  INT nItem = nStart;
+  INT nLast = GETITEMCOUNT(infoPtr);
+
+  if ((nItem >= -1) && (lpFindInfo != NULL))
+  {
+    ZeroMemory(&lvItem, sizeof(LVITEMA));
+
+    if (lpFindInfo->flags & LVFI_PARAM)
+    {
+      lvItem.mask |= LVIF_PARAM;
+    }
+    
+    if (lpFindInfo->flags & LVFI_STRING)
+    {
+      lvItem.mask |= LVIF_TEXT;
+      lvItem.pszText = szDispText;
+      lvItem.cchTextMax = DISP_TEXT_SIZE;
+    }
+
+    if (lpFindInfo->flags & LVFI_PARTIAL)
+    {
+      lvItem.mask |= LVIF_TEXT;
+      lvItem.pszText = szDispText;
+      lvItem.cchTextMax = DISP_TEXT_SIZE;
+    }
+
+    if (lpFindInfo->flags & LVFI_WRAP)
+    {
+      bWrap = TRUE;
+    }
+
+    if (lpFindInfo->flags & LVFI_NEARESTXY)
+    {
+      ptItem.x = lpFindInfo->pt.x;
+      ptItem.y = lpFindInfo->pt.y;
+    }
+
+    while (1)
+    {
+      while (nItem < nLast)
+      {
+        if (lpFindInfo->flags & LVFI_NEARESTXY)
+        {
+          nItem = LISTVIEW_GetNearestItem(hwnd, ptItem, 
+                                          lpFindInfo->vkDirection);
+          if (nItem != -1)
+          {
+            /* get position of the new item index */
+            if (ListView_GetItemPosition(hwnd, nItem, &ptItem) == FALSE)
+              return -1;
+          }
+          else
+            return -1;
+        }
+        else
+        {
+          nItem++;
+        }
+        
+        lvItem.iItem = nItem;
+        lvItem.iSubItem = 0;
+        if (ListView_GetItemA(hwnd, &lvItem) != FALSE)
+        {
+          if (lvItem.mask & LVIF_TEXT)
+          {
+            if (lpFindInfo->flags & LVFI_PARTIAL)
+            {
+              if (strstr(lvItem.pszText, lpFindInfo->psz) == NULL)
+                continue;
+            }
+            else
+            {
+              if (strcmp(lvItem.pszText, lpFindInfo->psz) != 0)
+                continue;
+            }
+          }
+          
+          if (lvItem.mask & LVIF_PARAM)
+          {
+            if (lpFindInfo->lParam != lvItem.lParam)
+              continue;
+          }
+          
+          return nItem;
+        }
+      }
+
+      if (bWrap != FALSE)
+      {
+        nItem = -1;
+        nLast = nStart + 1;
+        bWrap = FALSE;
+      }
+      else
+      {
+        return -1;
+      }       
+    }
+  }
+
+ return -1; 
 }
 
@@ -2991,6 +2990,5 @@
  *   FAILURE : FALSE
  */
-static LRESULT LISTVIEW_GetColumnA(HWND hwnd, INT nItem, 
-                                     LPLVCOLUMNA lpColumn)
+static LRESULT LISTVIEW_GetColumnA(HWND hwnd, INT nItem, LPLVCOLUMNA lpColumn)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
@@ -3097,15 +3095,14 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
+  INT nColumnWidth = 0;
   HDITEMA hdi;
-  INT nColumnWidth = 0;
-
-  switch (LVS_TYPEMASK & lStyle)
-  {
-  case LVS_LIST:
+
+  if (uView == LVS_LIST)
+  {
     nColumnWidth = infoPtr->nItemWidth;
-    break;
-
-  case LVS_REPORT:
+  }
+  else if (uView == LVS_REPORT)
+  {
     /* get column width from header */
     ZeroMemory(&hdi, sizeof(HDITEMA));
@@ -3115,5 +3112,4 @@
       nColumnWidth = hdi.cxy;
     }
-    break;
   }
 
@@ -3136,24 +3132,22 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
   INT nItemCount = 0;
 
-  switch (LVS_TYPEMASK & lStyle)
-  {
-  case LVS_LIST:
-    if (infoPtr->rcList.right / infoPtr->nItemWidth)
-    {
-      nItemCount = infoPtr->nCountPerRow * infoPtr->nCountPerColumn;
-    }
-    break;
-  
-  case LVS_REPORT:
-    nItemCount = infoPtr->nCountPerColumn;
-    break;
-    
-  case LVS_SMALLICON:
-  case LVS_ICON:
+  if (uView == LVS_LIST)
+  {
+    if (infoPtr->rcList.right > infoPtr->nItemWidth)
+    {
+      nItemCount = LISTVIEW_GetCountPerRow(hwnd) * 
+                   LISTVIEW_GetCountPerColumn(hwnd);
+    }
+  }
+  else if (uView == LVS_REPORT)
+  {
+    nItemCount = LISTVIEW_GetCountPerColumn(hwnd);
+  }
+  else
+  {
     nItemCount = GETITEMCOUNT(infoPtr);
-    break;
   }
 
@@ -3235,10 +3229,12 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
+  BOOL bResult = FALSE;
+  NMLVDISPINFOA dispInfo;
+  LISTVIEW_SUBITEM *lpSubItem;
   LISTVIEW_ITEM *lpItem;
-  LISTVIEW_SUBITEM *lpSubItem;
   HDPA hdpaSubItems;
-  BOOL bResult = FALSE;
-
-//  TRACE(listview, "(hwnd=%x,lpLVItem=%p)\n", hwnd, lpLVItem);
+
+  TRACE("(hwnd=%x, lpLVItem=%p)\n", hwnd, lpLVItem);
 
   if (lpLVItem != NULL)
@@ -3246,43 +3242,85 @@
     if ((lpLVItem->iItem >= 0) && (lpLVItem->iItem < GETITEMCOUNT(infoPtr)))
     {
+      ZeroMemory(&dispInfo, sizeof(NMLVDISPINFOA));
       hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
       if (hdpaSubItems != NULL)
       {
-        if (lpLVItem->iSubItem == 0)
-        {
-          lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
-          if (lpItem != NULL)
+        lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
+        if (lpItem != NULL)
+        {
+          bResult = TRUE;
+          if (lpLVItem->iSubItem == 0)
           {
-            bResult = TRUE;
-
-            /* retrieve valid data */
-            if (lpLVItem->mask & LVIF_STATE)
+            if ((lpItem->iImage == I_IMAGECALLBACK) &&
+                (lpLVItem->mask & LVIF_IMAGE))
+            {
+              dispInfo.item.mask |= LVIF_IMAGE;
+            }
+            
+            if ((lpItem->pszText == LPSTR_TEXTCALLBACKA) && 
+                (lpLVItem->mask & LVIF_TEXT))
+            {
+              dispInfo.item.mask |= LVIF_TEXT;
+              ZeroMemory(lpLVItem->pszText, sizeof(CHAR)*lpLVItem->cchTextMax);
+              dispInfo.item.pszText = lpLVItem->pszText;
+              dispInfo.item.cchTextMax = lpLVItem->cchTextMax;
+            }
+            
+            if ((infoPtr->uCallbackMask != 0) && (lpLVItem->mask & LVIF_STATE))
+            {        
+              dispInfo.item.mask |= LVIF_STATE;
+              dispInfo.item.stateMask = infoPtr->uCallbackMask; 
+            }
+            
+            if (dispInfo.item.mask != 0)
+            {
+              dispInfo.hdr.hwndFrom = hwnd;
+              dispInfo.hdr.idFrom = lCtrlId;
+              dispInfo.hdr.code = LVN_GETDISPINFOA;
+              dispInfo.item.iItem = lpLVItem->iItem;
+              dispInfo.item.iSubItem = 0;
+              dispInfo.item.lParam = lpItem->lParam;
+              ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo);
+            }
+            
+            if (dispInfo.item.mask & LVIF_IMAGE)
+            {
+              lpLVItem->iImage = dispInfo.item.iImage;
+            }
+            else if (lpLVItem->mask & LVIF_IMAGE)
+            {
+              lpLVItem->iImage = lpItem->iImage;
+            }
+            
+            if (dispInfo.item.mask & LVIF_TEXT)
+            {
+              if (dispInfo.item.mask & LVIF_DI_SETITEM)
+              {
+                Str_SetPtrA(&lpItem->pszText, dispInfo.item.pszText);
+              }
+              lpLVItem->pszText = dispInfo.item.pszText;
+            }
+            else if (lpLVItem->mask & LVIF_TEXT)
+            {
+              lpLVItem->pszText = lpItem->pszText;
+            }
+            
+            if (dispInfo.item.mask & LVIF_STATE)
+            {
+              lpLVItem->state = lpItem->state;
+              lpLVItem->state &= ~dispInfo.item.stateMask;
+              lpLVItem->state |= (dispInfo.item.state & 
+                                  dispInfo.item.stateMask);
+            }
+            else if (lpLVItem->mask & LVIF_STATE)
             {
               lpLVItem->state = lpItem->state & lpLVItem->stateMask;
             }
 
-            if (lpLVItem->mask & LVIF_TEXT) 
-            {
-              if (lpItem->pszText == LPSTR_TEXTCALLBACKA)
-              {
-                lpLVItem->pszText = LPSTR_TEXTCALLBACKA;
-              }
-              else
-              {
-                bResult = Str_GetPtrA(lpItem->pszText, lpLVItem->pszText, 
-                                        lpLVItem->cchTextMax);
-              }
-            }
-
-            if (lpLVItem->mask & LVIF_IMAGE)
-            {
-              lpLVItem->iImage = lpItem->iImage;
-            }
-          
             if (lpLVItem->mask & LVIF_PARAM)
             {
               lpLVItem->lParam = lpItem->lParam;
             }
-      
+            
             if (lpLVItem->mask & LVIF_INDENT)
             {
@@ -3290,29 +3328,74 @@
             }
           }
-        }
-        else
-        {
-          lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, 
-                                                     lpLVItem->iSubItem);
-          if (lpSubItem != NULL)
+          else
           {
-            bResult = TRUE;
-
-            if (lpLVItem->mask & LVIF_TEXT) 
+            lpSubItem = LISTVIEW_GetSubItemPtr(hdpaSubItems, 
+                                               lpLVItem->iSubItem);
+            if (lpSubItem != NULL)
             {
-              if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA)
+              if ((lpSubItem->iImage == I_IMAGECALLBACK) &&
+                  (lpLVItem->mask & LVIF_IMAGE))
               {
-                lpLVItem->pszText = LPSTR_TEXTCALLBACKA;
+                dispInfo.item.mask |= LVIF_IMAGE;
               }
-              else
+              
+              if ((lpSubItem->pszText == LPSTR_TEXTCALLBACKA) && 
+                  (lpLVItem->mask & LVIF_TEXT))
               {
-                bResult = Str_GetPtrA(lpSubItem->pszText, lpLVItem->pszText, 
-                                        lpLVItem->cchTextMax);
+                dispInfo.item.mask |= LVIF_TEXT;
+                ZeroMemory(lpLVItem->pszText, 
+                           sizeof(CHAR)*lpLVItem->cchTextMax);
+                dispInfo.item.pszText = lpLVItem->pszText;
+                dispInfo.item.cchTextMax = lpLVItem->cchTextMax;
               }
             }
-
-            if (lpLVItem->mask & LVIF_IMAGE)
+            else
             {
-              lpLVItem->iImage = lpSubItem->iImage;
+              if (lpLVItem->mask & LVIF_IMAGE)
+              {
+                dispInfo.item.mask |= LVIF_IMAGE;
+              }
+          
+              if (lpLVItem->mask & LVIF_TEXT)
+              {
+                dispInfo.item.mask |= LVIF_TEXT;
+                ZeroMemory(lpLVItem->pszText, 
+                           sizeof(CHAR)*lpLVItem->cchTextMax);
+                dispInfo.item.pszText = lpLVItem->pszText;
+                dispInfo.item.cchTextMax = lpLVItem->cchTextMax;
+              }
+            }
+
+            if (dispInfo.item.mask != 0)
+            {
+              dispInfo.hdr.hwndFrom = hwnd;
+              dispInfo.hdr.idFrom = lCtrlId;
+              dispInfo.hdr.code = LVN_GETDISPINFOA;
+              dispInfo.item.iItem = lpLVItem->iItem;
+              dispInfo.item.iSubItem = lpLVItem->iSubItem;
+              dispInfo.item.lParam = lpItem->lParam;
+              ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo);
+            }
+
+            if (dispInfo.item.mask & LVIF_IMAGE)
+            {
+              lpLVItem->iImage = dispInfo.item.iImage;
+            }
+            else if (lpLVItem->mask & LVIF_IMAGE)
+            {
+              lpLVItem->iImage = lpItem->iImage;
+            }
+
+            if (dispInfo.item.mask & LVIF_TEXT)
+            {
+              if (dispInfo.item.mask & LVIF_DI_SETITEM)
+              {
+                Str_SetPtrA(&lpItem->pszText, dispInfo.item.pszText);
+              }
+              lpLVItem->pszText = dispInfo.item.pszText;
+            }
+            else if (lpLVItem->mask & LVIF_TEXT)
+            {
+              lpLVItem->pszText = lpItem->pszText;
             }
           }
@@ -3364,56 +3447,51 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
   BOOL bResult = FALSE;
   HDPA hdpaSubItems;
   LISTVIEW_ITEM *lpItem;
+  INT nCountPerColumn;
   INT nRow;
 
-//  TRACE(listview, "(hwnd=%x,nItem=%d,lpptPosition=%p)\n", hwnd, nItem, 
-//        lpptPosition);
+  TRACE("(hwnd=%x,nItem=%d,lpptPosition=%p)\n", hwnd, nItem, 
+        lpptPosition);
 
   if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)) && 
       (lpptPosition != NULL))
   {
-    switch (LVS_TYPEMASK & lStyle)
-    {
-    case LVS_LIST:
+    if (uView == LVS_LIST)
+    {
       bResult = TRUE;
       nItem = nItem - ListView_GetTopIndex(hwnd);
+      nCountPerColumn = LISTVIEW_GetCountPerColumn(hwnd);
       if (nItem < 0)
       {
-        nRow = nItem % infoPtr->nCountPerColumn;
+        nRow = nItem % nCountPerColumn;
         if (nRow == 0)
         {
-          lpptPosition->x = (nItem / infoPtr->nCountPerColumn * 
-                             infoPtr->nItemWidth);
+          lpptPosition->x = nItem / nCountPerColumn * infoPtr->nItemWidth;
           lpptPosition->y = 0;
         }
         else
         {
-          lpptPosition->x = ((nItem / infoPtr->nCountPerColumn - 1) * 
-                             infoPtr->nItemWidth);
-          lpptPosition->y = ((nRow + infoPtr->nCountPerColumn) * 
-                             infoPtr->nItemHeight);  
+          lpptPosition->x = (nItem / nCountPerColumn -1) * infoPtr->nItemWidth;
+          lpptPosition->y = (nRow + nCountPerColumn) * infoPtr->nItemHeight;  
         }
       }
       else
       {
-        lpptPosition->x = (nItem / infoPtr->nCountPerColumn * 
-                           infoPtr->nItemWidth);
-        lpptPosition->y = (nItem % infoPtr->nCountPerColumn * 
-                           infoPtr->nItemHeight);
-      }
-      break;
-
-    case LVS_REPORT:
+        lpptPosition->x = nItem / nCountPerColumn * infoPtr->nItemWidth;
+        lpptPosition->y = nItem % nCountPerColumn * infoPtr->nItemHeight;
+      }
+    }
+    else if (uView == LVS_REPORT)
+    {
       bResult = TRUE;
       lpptPosition->x = REPORT_MARGINX;
       lpptPosition->y = ((nItem - ListView_GetTopIndex(hwnd)) * 
                          infoPtr->nItemHeight) + infoPtr->rcList.top;
-      break;
-
-    case LVS_SMALLICON:
-    case LVS_ICON:
+    }
+    else
+    {
       hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
       if (hdpaSubItems != NULL)
@@ -3427,5 +3505,4 @@
         }
       }
-      break;
     }
   }
@@ -3450,5 +3527,5 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
   BOOL bResult = FALSE;
   POINT ptOrigin;
@@ -3460,6 +3537,6 @@
   TEXTMETRICA tm;
 
-//  TRACE(listview, "(hwnd=%x,nItem=%d,lprc=%p)\n", hwnd, nItem, lprc);
-
+  TRACE("(hwnd=%x, nItem=%d, lprc=%p)\n", hwnd, nItem, lprc);
+  
   if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)) && (lprc != NULL))
   {
@@ -3469,7 +3546,6 @@
       {  
       case LVIR_ICON: 
-        switch (LVS_TYPEMASK & lStyle)
-        {
-        case LVS_ICON:
+        if (uView == LVS_ICON)
+        {
           if (infoPtr->himlNormal != NULL)
           {
@@ -3484,7 +3560,7 @@
             }
           }
-          break;
-
-        case LVS_SMALLICON:
+        }
+        else if (uView == LVS_SMALLICON)
+        {
           if (LISTVIEW_GetOrigin(hwnd, &ptOrigin) != FALSE)
           {
@@ -3495,21 +3571,14 @@
 
             if (infoPtr->himlState != NULL)
-            {
               lprc->left += infoPtr->iconSize.cx;
-            }
               
             if (infoPtr->himlSmall != NULL)
-            {
               lprc->right = lprc->left + infoPtr->iconSize.cx;
-            }
             else
-            {
               lprc->right = lprc->left;
-            }
           }
-          break;
-
-        case LVS_REPORT:
-        case LVS_LIST:
+        }
+        else 
+        {
           bResult = TRUE;
           lprc->left = ptItem.x;
@@ -3530,12 +3599,10 @@
             lprc->right = lprc->left;
           }
-          break;
         }
         break;
 
       case LVIR_LABEL: 
-        switch (LVS_TYPEMASK & lStyle)
-        {
-        case LVS_ICON:
+        if (uView == LVS_ICON)
+        {
           if (infoPtr->himlNormal != NULL)
           {
@@ -3566,7 +3633,7 @@
             }              
           }
-          break;
-
-        case LVS_SMALLICON:
+        }
+        else if (uView == LVS_SMALLICON)
+        {
           if (LISTVIEW_GetOrigin(hwnd, &ptOrigin) != FALSE)
           {
@@ -3596,8 +3663,7 @@
             }
           }
-          break;
-
-        case LVS_REPORT:
-        case LVS_LIST:
+        }
+        else
+        {
           bResult = TRUE;
           lprc->left = ptItem.x; 
@@ -3616,12 +3682,10 @@
 
           lprc->right = lprc->left + LISTVIEW_GetLabelWidth(hwnd, nItem);
-          break;
         }
         break;
 
       case LVIR_BOUNDS:
-        switch (LVS_TYPEMASK & lStyle)
-        {
-        case LVS_ICON:
+        if (uView == LVS_ICON)
+        {
           if (infoPtr->himlNormal != NULL)
           {
@@ -3635,31 +3699,23 @@
             }
           } 
-          break;
-
-        case LVS_SMALLICON:
+        }
+        else if (uView == LVS_SMALLICON)
+        {
           if (LISTVIEW_GetOrigin(hwnd, &ptOrigin) != FALSE)
           {
             bResult = TRUE;
-            lprc->left = ptItem.x +ptOrigin.x; 
+            lprc->left = ptItem.x + ptOrigin.x; 
             lprc->right = lprc->left;
             lprc->top = ptItem.y + ptOrigin.y;
             lprc->bottom = lprc->top + infoPtr->nItemHeight;
-            
             if (infoPtr->himlState != NULL)
-            {
               lprc->right += infoPtr->iconSize.cx;
-            }
-            
             if (infoPtr->himlSmall != NULL)
-            {
               lprc->right += infoPtr->iconSize.cx;
-            }
-            
             lprc->right += LISTVIEW_GetLabelWidth(hwnd, nItem);
           }
-          break;
-
-        case LVS_REPORT:
-        case LVS_LIST:
+        }
+        else
+        {
           bResult = TRUE;
           lprc->left = ptItem.x; 
@@ -3679,12 +3735,10 @@
 
           lprc->right += LISTVIEW_GetLabelWidth(hwnd, nItem);
-          break;
         }
         break;
         
       case LVIR_SELECTBOUNDS:
-        switch (LVS_TYPEMASK & lStyle)
-        {
-        case LVS_ICON:
+        if (uView == LVS_ICON)
+        {
           if (infoPtr->himlNormal != NULL)
           {
@@ -3698,7 +3752,7 @@
             }
           } 
-          break;
-
-        case LVS_SMALLICON:
+        }
+        else if (uView == LVS_SMALLICON)
+        {
           if (LISTVIEW_GetOrigin(hwnd, &ptOrigin) != FALSE)
           {
@@ -3722,8 +3776,7 @@
             lprc->right += LISTVIEW_GetLabelWidth(hwnd, nItem);
           }
-          break;
-
-        case LVS_REPORT:
-        case LVS_LIST:
+        }
+        else
+        {
           bResult = TRUE;
           lprc->left = ptItem.x; 
@@ -3744,5 +3797,4 @@
 
           lprc->right += LISTVIEW_GetLabelWidth(hwnd, nItem);
-          break;
         }
         break;
@@ -3765,29 +3817,22 @@
  *   FAILURE : zero
  */
-
 static INT LISTVIEW_GetLabelWidth(HWND hwnd, INT nItem)
 {
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LISTVIEW_ITEM *lpItem;
-  HDPA hdpaSubItems;
+  CHAR szDispText[DISP_TEXT_SIZE];
   INT nLabelWidth = 0;
-
-//  TRACE(listview, "(hwnd=%x,nItem=%d)\n", hwnd, nItem);
-
-  hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
-  if (hdpaSubItems != NULL)
-  {
-    lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
-    if (lpItem != NULL)
-    {
-      CHAR szDispText[DISP_TEXT_SIZE];
-      LPSTR pszDispText = NULL;
-      pszDispText = szDispText;
-      LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, NULL, NULL, &pszDispText,
-                               DISP_TEXT_SIZE);
-      nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText);
-    }
-  }
-
+  LVITEMA lvItem;
+
+  TRACE("(hwnd=%x, nItem=%d)\n", hwnd, nItem);
+
+  ZeroMemory(&lvItem, sizeof(LVITEMA));
+  lvItem.mask = LVIF_TEXT;
+  lvItem.iItem = nItem;
+  lvItem.cchTextMax = DISP_TEXT_SIZE;
+  lvItem.pszText = szDispText;
+  if (ListView_GetItemA(hwnd, &lvItem) != FALSE)
+  {
+    nLabelWidth = ListView_GetStringWidthA(hwnd, lvItem.pszText); 
+  }
+    
   return nLabelWidth;
 }
@@ -3865,12 +3910,10 @@
  * 
  * RETURN:
- * None
+ *   SUCCESS : string length
+ *   FAILURE : 0
  */
 static LRESULT LISTVIEW_GetItemTextA(HWND hwnd, INT nItem, LPLVITEMA lpLVItem)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LISTVIEW_ITEM *lpItem;
-  LISTVIEW_SUBITEM *lpSubItem;
-  HDPA hdpaSubItems;
   INT nLength = 0;
   
@@ -3879,46 +3922,9 @@
     if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
     {
-      hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
-      if (hdpaSubItems != NULL)
-      {
-        if (lpLVItem->iSubItem == 0)
-        {
-          lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
-          if (lpItem != NULL)
-          {
-            if (lpLVItem->mask & LVIF_TEXT) 
-            {
-              if (lpItem->pszText == LPSTR_TEXTCALLBACKA)
-              {
-                lpLVItem->pszText = LPSTR_TEXTCALLBACKA;
-              }
-              else
-              {
-                nLength = Str_GetPtrA(lpItem->pszText, lpLVItem->pszText, 
-                                      lpLVItem->cchTextMax);
-              }
-            }
-          }
-        }
-        else
-        {
-          lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, 
-                                                     lpLVItem->iSubItem);
-          if (lpSubItem != NULL)
-          {
-            if (lpLVItem->mask & LVIF_TEXT) 
-            {
-              if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA)
-              {
-                lpLVItem->pszText = LPSTR_TEXTCALLBACKA;
-              }
-              else
-              {
-                nLength = Str_GetPtrA(lpSubItem->pszText, lpLVItem->pszText, 
-                                      lpLVItem->cchTextMax);
-              }
-            }
-          }
-        }
+      lpLVItem->mask = LVIF_TEXT;
+      lpLVItem->iItem = nItem;
+      if (ListView_GetItemA(hwnd, lpLVItem) != FALSE)
+      {
+        nLength = lstrlenA(lpLVItem->pszText);
       }
     }
@@ -3934,6 +3940,6 @@
  * PARAMETER(S):
  * [I] HWND : window handle
- * [I] INT : starting search item index
- * [I] UINT : relationship flag
+ * [I] INT : item index
+ * [I] INT : relationship flag
  * 
  * RETURN:
@@ -3941,100 +3947,136 @@
  *   FAILURE : -1
  */
-static LRESULT LISTVIEW_GetNextItem(HWND hwnd, INT iStart, UINT uFlags)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-  LISTVIEW_ITEM *lpItem;
-  UINT style_mask = LVS_TYPEMASK & lStyle;
+static LRESULT LISTVIEW_GetNextItem(HWND hwnd, INT nItem, UINT uFlags)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
   UINT uMask = 0;
-  INT nItems = GETITEMCOUNT(infoPtr);
-  INT iIndex = iStart;
-  INT eIndex = nItems - 1;
-  INT sIndex = 0;
-  INT delta = 1;
+  LVFINDINFO lvFindInfo;
+  INT nCountPerColumn;
+  INT i;
   
-  INT nCountPerColumn = max((infoPtr->rcList.bottom - infoPtr->rcList.top) /
-			    infoPtr->nItemHeight, 1);
-  INT nCountPerRow = max((infoPtr->rcList.right - infoPtr->rcList.left) /
-			 infoPtr->nItemWidth, 1);
-
-  if(uFlags & LVNI_ABOVE) /* moving upwards from iStart */
-  {
-    if(style_mask == LVS_LIST || style_mask == LVS_REPORT)
-      delta = -1;
+  if ((nItem >= -1) && (nItem < GETITEMCOUNT(infoPtr)))
+  { 
+    ZeroMemory(&lvFindInfo, sizeof(LVFINDINFO));
+
+    if (uFlags & LVNI_CUT)
+      uMask |= LVIS_CUT;
+    
+    if (uFlags & LVNI_DROPHILITED)
+      uMask |= LVIS_DROPHILITED;
+          
+    if (uFlags & LVNI_FOCUSED)
+      uMask |= LVIS_FOCUSED;
+
+    if (uFlags & LVNI_SELECTED)
+      uMask |= LVIS_SELECTED;
+
+    if (uFlags & LVNI_ABOVE)
+    {
+      if ((uView == LVS_LIST) || (uView == LVS_REPORT))
+      {
+        while (nItem >= 0)
+        {
+          nItem--;
+          if ((ListView_GetItemState(hwnd, nItem, uMask) & uMask) == uMask)
+            return nItem;
+        }
+      }
+      else
+      {
+        lvFindInfo.flags = LVFI_NEARESTXY;
+        lvFindInfo.vkDirection = VK_UP;
+        ListView_GetItemPosition(hwnd, nItem, &lvFindInfo.pt);
+        while ((nItem = LISTVIEW_FindItem(hwnd, nItem, &lvFindInfo)) != -1)
+        {
+          if ((ListView_GetItemState(hwnd, nItem, uMask) & uMask) == uMask)
+            return nItem;
+        }
+      }
+    }
+    else if (uFlags & LVNI_BELOW)
+    {
+      if ((uView == LVS_LIST) || (uView == LVS_REPORT))
+      {
+        while (nItem < GETITEMCOUNT(infoPtr))
+        {
+          nItem++;
+          if ((ListView_GetItemState(hwnd, nItem, uMask) & uMask) == uMask)
+            return nItem;
+        }
+      }
+      else
+      {
+        lvFindInfo.flags = LVFI_NEARESTXY;
+        lvFindInfo.vkDirection = VK_DOWN;
+        ListView_GetItemPosition(hwnd, nItem, &lvFindInfo.pt);
+        while ((nItem = LISTVIEW_FindItem(hwnd, nItem, &lvFindInfo)) != -1)
+        {
+          if ((ListView_GetItemState(hwnd, nItem, uMask) & uMask) == uMask)
+            return nItem;
+        }
+      }
+    }
+    else if (uFlags & LVNI_TOLEFT)
+    {
+      if (uView == LVS_LIST)
+      {
+        nCountPerColumn = LISTVIEW_GetCountPerColumn(hwnd);
+        while (nItem - nCountPerColumn >= 0)
+        {
+          nItem -= nCountPerColumn;
+          if ((ListView_GetItemState(hwnd, nItem, uMask) & uMask) == uMask)
+            return nItem;
+        }
+      }
+      else if ((uView == LVS_SMALLICON) || (uView == LVS_ICON))
+      {
+        lvFindInfo.flags = LVFI_NEARESTXY;
+        lvFindInfo.vkDirection = VK_LEFT;
+        ListView_GetItemPosition(hwnd, nItem, &lvFindInfo.pt);
+        while ((nItem = LISTVIEW_FindItem(hwnd, nItem, &lvFindInfo)) != -1)
+        {
+          if ((ListView_GetItemState(hwnd, nItem, uMask) & uMask) == uMask)
+            return nItem;
+        }
+      }
+    }
+    else if (uFlags & LVNI_TORIGHT)
+    {
+      if (uView == LVS_LIST)
+      {
+        nCountPerColumn = LISTVIEW_GetCountPerColumn(hwnd);
+        while (nItem + nCountPerColumn < GETITEMCOUNT(infoPtr))
+        {
+          nItem += nCountPerColumn;
+          if ((ListView_GetItemState(hwnd, nItem, uMask) & uMask) == uMask)
+            return nItem;
+        }
+      }
+      else if ((uView == LVS_SMALLICON) || (uView == LVS_ICON))
+      {
+        lvFindInfo.flags = LVFI_NEARESTXY;
+        lvFindInfo.vkDirection = VK_RIGHT;
+        ListView_GetItemPosition(hwnd, nItem, &lvFindInfo.pt);
+        while ((nItem = LISTVIEW_FindItem(hwnd, nItem, &lvFindInfo)) != -1)
+        {
+          if ((ListView_GetItemState(hwnd, nItem, uMask) & uMask) == uMask)
+            return nItem;
+        }
+      }
+    }
     else
     {
-      if(lStyle & LVS_ALIGNLEFT)
-      {
-        sIndex = iStart - (iStart % nCountPerColumn);
-	delta = -1;
-      }
-      else
-        delta = -nCountPerRow;
-    }
-  }
-  else if(uFlags & LVNI_BELOW) /* moving downwards from iStart */
-  { 
-    if(style_mask == LVS_SMALLICON || style_mask == LVS_ICON)
-    {
-      if (lStyle & LVS_ALIGNLEFT)
-        eIndex = iStart + (nCountPerColumn - (iStart % nCountPerColumn) - 1);
-      else
-	delta = nCountPerRow;
-    }    
-  } 
-  else if(uFlags & LVNI_TOLEFT) /* moving to the left of iStart */
-  {
-    if(style_mask == LVS_LIST)
-      delta = -infoPtr->nCountPerColumn;
-    else if(style_mask == LVS_SMALLICON || style_mask == LVS_ICON)
-    {
-      if(style_mask & LVS_ALIGNLEFT)
-        delta = -nCountPerColumn;
-      else
-      {
-        sIndex = iStart - (iStart % nCountPerRow);
-        delta = -1;
-      }
-    }    
-    else if(style_mask == LVS_REPORT)
-      return -1; 
-  }  
-  else if(uFlags & LVNI_TORIGHT) /* moving to the right of iStart */
-  {
-    if(style_mask == LVS_LIST)
-      delta = infoPtr->nCountPerColumn;
-    else if(style_mask == LVS_ICON || style_mask == LVS_SMALLICON)
-    {
-      if(lStyle & LVS_ALIGNLEFT)
-	delta = nCountPerColumn;
-      else
-	eIndex = iStart + (nCountPerRow - (iStart % nCountPerRow) - 1);
-    }
-    else if(style_mask == LVS_REPORT)
-      return -1;
-  }
-  
-  /* perform come bounds checking before entering the main loop */
-  if(sIndex < 0) sIndex = 0;
-  if(eIndex > (nItems - 1)) eIndex = (nItems - 1);
-
-  /* build uMask, the mask we are searching for */
-  if(uFlags & LVNI_CUT) uMask|=LVIS_CUT;
-  if(uFlags & LVNI_DROPHILITED) uMask|=LVIS_DROPHILITED;
-  if(uFlags & LVNI_FOCUSED) uMask|=LVIS_FOCUSED;
-  if(uFlags & LVNI_SELECTED) uMask|=LVIS_SELECTED;  
-
-  while(TRUE) /* searching loop */
-  {
-    iIndex+=delta;    
-
-    if((iIndex < sIndex) || (iIndex > eIndex))
-      break;
-
-    /* see if flags match */
-    if(!uMask || (LISTVIEW_GetItemState(hwnd, iIndex, uMask) == uMask))
-      return iIndex;
-  }
+      nItem++;
+
+      /* search by index */
+      for (i = nItem; i < GETITEMCOUNT(infoPtr); i++)
+      {
+        if ((ListView_GetItemState(hwnd, i, uMask) & uMask) == uMask)
+          return i;
+      }
+    }
+  }
+
   return -1;
 }
@@ -4058,36 +4100,39 @@
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView = lStyle & LVS_TYPEMASK;
   INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
   INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
   BOOL bResult = FALSE;
-
-//  TRACE(listview, "(hwnd=%x,lpptOrigin=%p)\n", hwnd, lpptOrigin);
-
-  switch (LVS_TYPEMASK & lStyle)
-  {
-  case LVS_ICON:
-  case LVS_SMALLICON:
-    if ((lStyle & WS_HSCROLL) != 0)
-    {
-      lpptOrigin->x = -GetScrollPos(hwnd, SB_HORZ) * nListWidth / 10;
-    }
-    else
-    {
-      lpptOrigin->x = 0;
-    }
-
-    if ((lStyle & WS_VSCROLL) != 0)
-    {
-      lpptOrigin->y = -GetScrollPos(hwnd, SB_VERT) * nListHeight / 10;
-    }
-    else
-    {
-      lpptOrigin->y = 0;
-    }
   
+  TRACE("(hwnd=%x, lpptOrigin=%p)\n", hwnd, lpptOrigin);
+
+  if ((uView == LVS_SMALLICON) || (uView == LVS_ICON))
+  {
+    SCROLLINFO scrollInfo;
+    ZeroMemory(lpptOrigin, sizeof(POINT));
+    ZeroMemory(&scrollInfo, sizeof(SCROLLINFO));
+    scrollInfo.cbSize = sizeof(SCROLLINFO);
+
+    if (lStyle & WS_HSCROLL)
+    {
+      scrollInfo.fMask = SIF_POS;
+      if (GetScrollInfo(hwnd, SB_HORZ, &scrollInfo) != FALSE) 
+      {
+        lpptOrigin->x = -scrollInfo.nPos * max(nListWidth / 10, 1);
+      }
+    }
+
+    if (lStyle & WS_VSCROLL)
+    {
+      scrollInfo.fMask = SIF_POS;
+      if (GetScrollInfo(hwnd, SB_VERT, &scrollInfo) != FALSE)
+      {
+        lpptOrigin->y = -scrollInfo.nPos * max(nListHeight / 10, 1);
+      }
+    }
+      
     bResult = TRUE;
-    break;
-  }
-
+  }
+  
   return bResult;
 }
@@ -4116,5 +4161,5 @@
     }
   }
-
+  
   return nSelectedCount;
 }
@@ -4205,80 +4250,4 @@
 /***
  * DESCRIPTION:
- * Set the bounding rectangle of all the items.
- * 
- * PARAMETER(S):
- * [I] HWND : window handle
- * [I] LPRECT : bounding rectangle
- *
- * RETURN:
- *   SUCCESS : TRUE
- *   FAILURE : FALSE
- */
-static LRESULT LISTVIEW_SetViewRect(HWND hwnd, LPRECT lprcView)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-  BOOL bResult = FALSE;
-
-//  TRACE(listview, "(hwnd=%x,lprcView->left=%d,lprcView->top=%d,lprcView->right=%d,lprcView->bottom=%d)\n", hwnd, lprcView->left, lprcView->top, lprcView->right, lprcView->bottom);
-
-  if (lprcView != NULL)
-  {
-    switch (lStyle & LVS_TYPEMASK)
-    {
-    case LVS_ICON:
-    case LVS_SMALLICON:
-      bResult = TRUE;
-      infoPtr->rcView.left = lprcView->left;
-      infoPtr->rcView.top = lprcView->top;
-      infoPtr->rcView.right = lprcView->right;
-      infoPtr->rcView.bottom = lprcView->bottom;
-      break;
-    }
-  }
-
-  return bResult;
-}
-
-/***
- * DESCRIPTION:
- * Retrieves the bounding rectangle of all the items.
- * 
- * PARAMETER(S):
- * [I] HWND : window handle
- * [O] LPRECT : bounding rectangle
- *
- * RETURN:
- *   SUCCESS : TRUE
- *   FAILURE : FALSE
- */
-static LRESULT LISTVIEW_GetViewRect(HWND hwnd, LPRECT lprcView)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
-  BOOL bResult = FALSE;
-  POINT ptOrigin;
-
-//  TRACE(listview, "(hwnd=%x,lprcView=%p)\n", hwnd, lprcView);
-
-  if (lprcView != NULL)
-  {
-    bResult = LISTVIEW_GetOrigin(hwnd, &ptOrigin);
-    if (bResult != FALSE)
-    {
-      lprcView->left = infoPtr->rcView.left + ptOrigin.x;
-      lprcView->top = infoPtr->rcView.top + ptOrigin.y;
-      lprcView->right = infoPtr->rcView.right + ptOrigin.x;
-      lprcView->bottom = infoPtr->rcView.bottom + ptOrigin.y;
-    }
-
-//    TRACE(listview, "(lprcView->left=%d,lprcView->top=%d,lprcView->right=%d,lprcView->bottom=%d)\n", lprcView->left, lprcView->top, lprcView->right, lprcView->bottom);
-
-  }
-
-  return bResult;
-}
-
-/***
- * DESCRIPTION:
  * Determines which section of the item was selected (if any).
  * 
@@ -4296,4 +4265,7 @@
   RECT rcItem;
   INT i;
+  
+  TRACE("(hwnd=%x, x=%ld, y=%ld)\n", hwnd, lpHitTestInfo->pt.x,
+        lpHitTestInfo->pt.y);
 
   for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
@@ -4302,38 +4274,35 @@
     if (LISTVIEW_GetItemRect(hwnd, i, &rcItem) != FALSE)
     {
-      rcItem.left = LVIR_ICON;
-      if (LISTVIEW_GetItemRect(hwnd, i, &rcItem) != FALSE)
-      {
-        if ((lpHitTestInfo->pt.x >= rcItem.left) && 
-            (lpHitTestInfo->pt.x <= rcItem.right) && 
-            (lpHitTestInfo->pt.y >= rcItem.top) &&
-            (lpHitTestInfo->pt.y <= rcItem.bottom))
-        {
-          lpHitTestInfo->flags = LVHT_ONITEMICON | LVHT_ONITEM;
-          lpHitTestInfo->iItem = i;
-          lpHitTestInfo->iSubItem = 0;
-          return i;
-        }
-      }
+      if (PtInRect(&rcItem, lpHitTestInfo->pt) != FALSE)
+      {
+        rcItem.left = LVIR_ICON;
+        if (LISTVIEW_GetItemRect(hwnd, i, &rcItem) != FALSE)
+        {
+          if (PtInRect(&rcItem, lpHitTestInfo->pt) != FALSE)
+          {
+            lpHitTestInfo->flags = LVHT_ONITEMICON;
+            lpHitTestInfo->iItem = i;
+            lpHitTestInfo->iSubItem = 0;
+            return i;
+          }
+        }
       
-      rcItem.left = LVIR_LABEL;
-      if (LISTVIEW_GetItemRect(hwnd, i, &rcItem) != FALSE)
-      {
-        if ((lpHitTestInfo->pt.x >= rcItem.left) && 
-            (lpHitTestInfo->pt.x <= rcItem.right) &&
-            (lpHitTestInfo->pt.y >= rcItem.top) &&
-            (lpHitTestInfo->pt.y <= rcItem.bottom))
-        {
-          lpHitTestInfo->flags = LVHT_ONITEMLABEL | LVHT_ONITEM;
-          lpHitTestInfo->iItem = i;
-          lpHitTestInfo->iSubItem = 0;
-          return i;
-        }
-      }
-
-      lpHitTestInfo->flags = LVHT_ONITEMSTATEICON | LVHT_ONITEM;
-      lpHitTestInfo->iItem = i;
-      lpHitTestInfo->iSubItem = 0;
-      return i;
+        rcItem.left = LVIR_LABEL;
+        if (LISTVIEW_GetItemRect(hwnd, i, &rcItem) != FALSE)
+        {
+          if (PtInRect(&rcItem, lpHitTestInfo->pt) != FALSE)
+          {
+            lpHitTestInfo->flags = LVHT_ONITEMLABEL;
+            lpHitTestInfo->iItem = i;
+            lpHitTestInfo->iSubItem = 0;
+            return i;
+          }
+        }
+        
+        lpHitTestInfo->flags = LVHT_ONITEMSTATEICON;
+        lpHitTestInfo->iItem = i;
+        lpHitTestInfo->iSubItem = 0;
+        return i;
+      }
     }
   }
@@ -4346,5 +4315,5 @@
 /***
  * DESCRIPTION:
- * Determines wich listview item is located at the specified position.
+ * Determines which listview item is located at the specified position.
  * 
  * PARAMETER(S):
@@ -4362,4 +4331,5 @@
 
   lpHitTestInfo->flags = 0;
+
   if (infoPtr->rcList.left > lpHitTestInfo->pt.x)
   {
@@ -4370,9 +4340,8 @@
     lpHitTestInfo->flags = LVHT_TORIGHT;
   }
-  
   if (infoPtr->rcList.top > lpHitTestInfo->pt.y)
   {
     lpHitTestInfo->flags |= LVHT_ABOVE;
-  } 
+  }
   else if (infoPtr->rcList.bottom < lpHitTestInfo->pt.y) 
   {
@@ -4405,9 +4374,9 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
   HDITEMA hdi;
   INT nNewColumn = -1;
 
-//  TRACE(listview,"(hwnd=%x,nColumn=%d,lpColumn=%p)\n",hwnd, nColumn, lpColumn);
+  TRACE("(hwnd=%x, nColumn=%d, lpColumn=%p)\n",hwnd, nColumn, 
+        lpColumn);
 
   if (lpColumn != NULL) 
@@ -4490,5 +4459,5 @@
                              (WPARAM)nColumn, (LPARAM)&hdi);
 
-    LISTVIEW_SetScroll(hwnd, lStyle);
+    LISTVIEW_UpdateScroll(hwnd);
     InvalidateRect(hwnd, NULL, FALSE);
   }
@@ -4515,4 +4484,5 @@
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView = lStyle & LVS_TYPEMASK;
   LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
   NMLISTVIEW nmlv;
@@ -4521,5 +4491,5 @@
   LISTVIEW_ITEM *lpItem = NULL;
 
-//  TRACE(listview, "(hwnd=%x,lpLVItem=%p)\n", hwnd, lpLVItem);
+  TRACE("(hwnd=%x,lpLVItem=%p)\n", hwnd, lpLVItem);
 
   if (lpLVItem != NULL)
@@ -4564,8 +4534,6 @@
                 
                 /* align items (set position of each item) */
-                switch (lStyle & LVS_TYPEMASK)
+                if ((uView == LVS_SMALLICON) || (uView == LVS_ICON))
                 {
-                case LVS_ICON:
-                case LVS_SMALLICON:
                   if (lStyle & LVS_ALIGNLEFT)
                   {
@@ -4576,8 +4544,7 @@
                     LISTVIEW_AlignTop(hwnd);
                   }
-                  break;
                 }
-
-                LISTVIEW_SetScroll(hwnd, lStyle);
+                
+                LISTVIEW_UpdateScroll(hwnd);
                 /* refresh client area */
                 InvalidateRect(hwnd, NULL, FALSE);
@@ -4803,19 +4770,17 @@
     LONG lStyle;
 
-    /* set column width only if in report mode */
+    // set column width only if in report mode
     lStyle = GetWindowLongA(hwnd, GWL_STYLE);
     if ((lStyle & LVS_TYPEMASK) != LVS_REPORT)
 	return (FALSE);
 
-    /* make sure we can get the listview info */
+    // make sure we can get the listview info
     if (!(infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0)))
 	return (FALSE);  
-    if (!infoPtr->hwndHeader) /* make sure we have a header */
+    if (!infoPtr->hwndHeader) // make sure we have a header
 	return (FALSE);	
 	
-    /*
-     * FIXME: currently ignoring LVSCW_AUTOSIZE (-1) and
-     * LVSCV_AUTOSIZE_USEHEADER (-2)
-     */
+    // FIXME: currently ignoring LVSCW_AUTOSIZE (-1) and
+    // LVSCV_AUTOSIZE_USEHEADER (-2)
     if (cx < 0) 
 	return (FALSE);
@@ -4824,10 +4789,10 @@
     hdi.cxy = cx;
 
-    /* call header to update the column change */
+    // call header to update the column change
     lret = Header_SetItemA(infoPtr->hwndHeader, (WPARAM)iCol, (LPARAM)&hdi);
 
-    infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd, LVS_REPORT);
-
-    InvalidateRect(hwnd, NULL, TRUE); /* force redraw of the listview */
+    infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd);
+
+    InvalidateRect(hwnd, NULL, TRUE); // force redraw of the listview
 
     return lret;
@@ -4867,4 +4832,5 @@
     himlTemp = infoPtr->himlState;
     infoPtr->himlState = himl;
+    ImageList_SetBkColor(infoPtr->himlState, CLR_NONE);
     return (LRESULT)himlTemp;
   }
@@ -4925,5 +4891,5 @@
 static VOID LISTVIEW_SetItemCount(HWND hwnd, INT nItemCount)
 {
-//  FIXME (listview, "empty stub!\n");
+  FIXME("empty stub!\n");
 }
 
@@ -4946,17 +4912,15 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
   LISTVIEW_ITEM *lpItem;
   HDPA hdpaSubItems;
   BOOL bResult = FALSE;
 
-//  TRACE(listview, "(hwnd=%x,nItem=%d,X=%d,Y=%d)\n", hwnd, nItem, nPosX, nPosY);
+  TRACE("(hwnd=%x,nItem=%d,X=%d,Y=%d)\n", hwnd, nItem, nPosX, nPosY);
 
   if ((nItem >= 0) || (nItem < GETITEMCOUNT(infoPtr)))
   {
-    switch (lStyle & LVS_TYPEMASK)
-    {
-    case LVS_ICON:
-    case LVS_SMALLICON:
+    if ((uView == LVS_ICON) || (uView == LVS_SMALLICON))
+    {
       hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
       if (hdpaSubItems != NULL)
@@ -4970,5 +4934,4 @@
         }
       }
-      break;
     }
   }
@@ -5003,5 +4966,5 @@
     lvItem.mask = LVIF_STATE;
     lvItem.state = lpLVItem->state;
-    lvItem.stateMask = lpLVItem->stateMask;
+    lvItem.stateMask = lpLVItem->stateMask ;
     
     /* apply to all items */
@@ -5104,4 +5067,34 @@
 }
 
+
+/***
+ * DESCRIPTION:
+ * Callback internally used by LISTVIEW_SortItems()
+ * 
+ * PARAMETER(S):
+ * [I] LPVOID : first LISTVIEW_ITEM to compare
+ * [I] LPVOID : second LISTVIEW_ITEM to compare
+ * [I] LPARAM : HWND of control
+ *
+ * RETURN:
+ *   if first comes before second : negative
+ *   if first comes after second : positive
+ *   if first and second are equivalent : zero
+ */
+static INT WINAPI LISTVIEW_CallBackCompare( 
+  LPVOID first, 
+  LPVOID second, 
+  LPARAM lParam)
+{
+  /* Forward the call to the client defined callback */
+  HWND hwnd = (HWND)lParam;
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+
+  return (infoPtr->pfnCompare)(
+    ((LISTVIEW_ITEM *)first)->lParam,
+    ((LISTVIEW_ITEM *)second)->lParam,
+    infoPtr->lParamSort);
+}
+
 /***
  * DESCRIPTION:
@@ -5110,4 +5103,6 @@
  * PARAMETER(S):
  * [I] HWND : window handle
+ * [I] WPARAM : application-defined value
+ * [I] LPARAM : pointer to comparision callback
  *
  * RETURN:
@@ -5117,7 +5112,45 @@
 static LRESULT LISTVIEW_SortItems(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
-//  FIXME (listview, "empty stub!\n");
-
-  return TRUE;
+    LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+    HDPA hdpaSubItems;
+    LISTVIEW_ITEM *lpItem;
+    int nCount, i;
+    HDPA sortList;
+    
+    if (!infoPtr || !infoPtr->hdpaItems)
+	return FALSE;
+    
+    nCount = GETITEMCOUNT(infoPtr);
+    // if there are 0 or 1 items, there is no need to sort
+    if (nCount > 1)
+    {
+	sortList = DPA_Create(nCount);
+
+	infoPtr->pfnCompare = (PFNLVCOMPARE)lParam;
+	infoPtr->lParamSort = (LPARAM)wParam;
+	
+	// append pointers one by one to sortList
+	for (i = 0; i < nCount; i++)
+	{
+	    if ((hdpaSubItems = (HDPA) DPA_GetPtr(infoPtr->hdpaItems, i)))
+		if ((lpItem = (LISTVIEW_ITEM *) DPA_GetPtr(hdpaSubItems, 0)))
+		    DPA_InsertPtr(sortList, nCount + 1, lpItem);
+	}
+
+	// sort the sortList
+	DPA_Sort(sortList, LISTVIEW_CallBackCompare, hwnd);
+
+	// copy the pointers back
+	for (i = 0; i < nCount; i++)
+	{
+	    if ((hdpaSubItems = (HDPA) DPA_GetPtr(infoPtr->hdpaItems, i)) &&
+		(lpItem = (LISTVIEW_ITEM *) DPA_GetPtr(sortList, i)))
+		DPA_SetPtr(hdpaSubItems, 0, lpItem);
+	}
+
+	DPA_Destroy(sortList);
+    }
+
+    return TRUE;
 }
 
@@ -5156,5 +5189,5 @@
       rc.left = LVIR_BOUNDS;
       ListView_GetItemRect(hwnd, nItem, &rc);
-      InvalidateRect(hwnd, &rc, FALSE);
+      InvalidateRect(hwnd, &rc, TRUE);
     }
   }
@@ -5177,4 +5210,5 @@
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LPCREATESTRUCTA lpcs = (LPCREATESTRUCTA)lParam;
+  UINT uView = lpcs->style & LVS_TYPEMASK;
   LOGFONTA logFont;
 
@@ -5187,5 +5221,5 @@
   if (infoPtr->notifyFormat != NFR_ANSI)
   {
-//    FIXME (listview, "ANSI notify format is NOT used\n");
+    FIXME("ANSI notify format is NOT used\n");
   }
   
@@ -5217,20 +5251,24 @@
   SendMessageA(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)infoPtr->hFont, 
                (LPARAM)TRUE);
-
   
-  switch (lpcs->style & LVS_TYPEMASK)
-  {
-  case LVS_ICON:
+  if (uView == LVS_ICON)
+  {
     infoPtr->iconSize.cx = GetSystemMetrics(SM_CXICON);
     infoPtr->iconSize.cy = GetSystemMetrics(SM_CYICON);
-    break;
-
-  case LVS_REPORT:
-    ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL);
-  case LVS_SMALLICON:
-  case LVS_LIST:
+  }
+  else if (uView == LVS_REPORT)
+  {
+    if (!(LVS_NOCOLUMNHEADER & lpcs->style))
+    {
+      ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL);
+    }
+
     infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON);
     infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON);
-    break;
+  }
+  else
+  {
+    infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON);
+    infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON);
   }
 
@@ -5242,6 +5280,6 @@
 
   /* initialize size of items */
-  infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd, lpcs->style);
-  infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd, lpcs->style);
+  infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd);
+  infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd);
 
   return 0;
@@ -5308,5 +5346,6 @@
  * [I] HWND : window handle
  * [I] INT : scroll code
- * [I] INT : scroll position
+ * [I] SHORT : current scroll position if scroll code is SB_THIMBPOSITION 
+ *             or SB_THUMBTRACK.
  * [I] HWND : scrollbar control window handle
  *
@@ -5314,213 +5353,204 @@
  * Zero
  */
-static LRESULT LISTVIEW_VScroll(HWND hwnd, INT nScrollCode, INT nScroll, 
+static LRESULT LISTVIEW_VScroll(HWND hwnd, INT nScrollCode, SHORT nCurrentPos,
                                 HWND hScrollWnd)
 {
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-  INT nScrollPosInc = 0;
-  INT nScrollPos;
-  INT nMinRange;
-  INT nMaxRange;
-
-  GetScrollRange(hwnd, SB_VERT, &nMinRange, &nMaxRange);
-  nScrollPos = GetScrollPos(hwnd, SB_VERT);
-
-  switch (nScrollCode)
-  {
-  case SB_LINEUP:
-    if (nScrollPos > nMinRange)
-    {
-      nScrollPosInc = -1;
-    }
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
+  SCROLLINFO scrollInfo;
+
+  ZeroMemory(&scrollInfo, sizeof(SCROLLINFO));
+  scrollInfo.cbSize = sizeof(SCROLLINFO);
+  scrollInfo.fMask = /*SIF_PAGE |*/ SIF_POS | SIF_RANGE;
+ 
+  if (GetScrollInfo(hwnd, SB_VERT, &scrollInfo) != FALSE)
+  {
+    INT nOldScrollPos = scrollInfo.nPos;
+    switch (nScrollCode)
+    {
+    case SB_LINEUP:
+      if (scrollInfo.nPos > scrollInfo.nMin)
+      {
+        scrollInfo.nPos--;
+      }
     break;
     
-  case SB_LINEDOWN:
-    if (nScrollPos < nMaxRange)
-    {
-      nScrollPosInc = 1;
-    }
-    break;
-
-  case SB_PAGEUP:
-    switch (LVS_TYPEMASK & lStyle)
-    {
-    case LVS_REPORT:
-      if (nScrollPos > nMinRange + infoPtr->nCountPerColumn)
-      {
-        nScrollPosInc = -infoPtr->nCountPerColumn;
-      } 
-      else
-      {
-        nScrollPosInc = nMinRange - nScrollPos;
-      }
-      break;
-
-    case LVS_SMALLICON:
-    case LVS_ICON:
-      if (nScrollPos > nMinRange + 10)
-      {
-        nScrollPosInc = -10;
-      }
-      else
-      {
-        nScrollPosInc = nMinRange - nScrollPos;
-      }
-      break;
-    }
-    break;
-
-   case SB_PAGEDOWN:
-     switch (LVS_TYPEMASK & lStyle)
-     {
-     case LVS_REPORT:
-       if (nScrollPos < nMaxRange - infoPtr->nCountPerColumn)
-       {
-         nScrollPosInc = infoPtr->nCountPerColumn;
-       }
-       else
-       {
-         nScrollPosInc = nMaxRange - nScrollPos;
-       }
-       break;
-
-     case LVS_SMALLICON:
-     case LVS_ICON:
-       if (nScrollPos < nMaxRange - 10)
-       {
-         nScrollPosInc = 10;
-       }
-       else
-       {
-         nScrollPosInc = nMaxRange - nScrollPos;
-       }
-       break;
-     }
-     break;
-
-   case SB_THUMBPOSITION:
-     nScrollPosInc = nScroll - nScrollPos; 
-    break;
-  }
-
-  if (nScrollPosInc != 0)
-  {
-    LISTVIEW_ScrollView(hwnd, 0, nScrollPosInc);
-  }
-
-  return 0;
-}
-
-
-/***
- * DESCRIPTION:
- * Performs horizontal scrolling.
- * 
- * PARAMETER(S):
- * [I] HWND : window handle
- * [I] INT : scroll code
- * [I] INT : scroll position
- * [I] HWND : scrollbar control window handle
- *
- * RETURN:
- * Zero
- */
-static LRESULT LISTVIEW_HScroll(HWND hwnd, INT nScrollCode, 
-                                INT nScroll, HWND hScrollWnd)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-  INT nScrollPosInc = 0;
-  INT nScrollPos;
-  INT nMinRange;
-  INT nMaxRange;
-
-  GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
-  nScrollPos = GetScrollPos(hwnd, SB_HORZ);
-
-  switch (nScrollCode)
-  {
-  case SB_LINELEFT:
-    if (nScrollPos > nMinRange)
-    {
-      nScrollPosInc = -1;
-    }
-    break;
-
-  case SB_LINERIGHT:
-    if (nScrollPos < nMaxRange)
-    {
-      nScrollPosInc = 1;
-    }
-    break;
-
-  case SB_PAGELEFT:
-    switch (LVS_TYPEMASK & lStyle)
-    {
-    case LVS_LIST:
-      if (nScrollPos > nMinRange + infoPtr->nCountPerRow)
-      {
-        nScrollPosInc = -infoPtr->nCountPerRow;
-      }
-      else
-      {
-        nScrollPosInc = nMinRange - nScrollPos;
-      }
-      break;
-
-    case LVS_REPORT:
-    case LVS_SMALLICON:
-    case LVS_ICON:
-      if (nScrollPos > nMinRange + 10)
-      {
-        nScrollPosInc = -10;
-      }
-      else
-      {
-        nScrollPosInc = nMinRange - nScrollPos;
-      }
-      break;
-    }
-    break;
-
-  case SB_PAGERIGHT:
-    switch (LVS_TYPEMASK & lStyle)
-    {
-    case LVS_LIST:
-      if (nScrollPos < nMaxRange - infoPtr->nCountPerRow)
-      {
-        nScrollPosInc = infoPtr->nCountPerRow;
-      }
-      else
-      {
-        nScrollPosInc = nMaxRange - nScrollPos;
+    case SB_LINEDOWN:
+      if (scrollInfo.nPos < scrollInfo.nMax)
+      {
+        scrollInfo.nPos++;
       }
       break;
       
-    case LVS_REPORT:
-    case LVS_SMALLICON:
-    case LVS_ICON:
-      if (nScrollPos < nMaxRange - 10)
-      {
-        nScrollPosInc = 10;
-      }
-      else
-      {
-        nScrollPosInc = nMaxRange - nScrollPos;
+    case SB_PAGEUP:
+      if (scrollInfo.nPos > scrollInfo.nMin)
+      {
+        INT nPage = 0;
+
+        if (uView == LVS_REPORT)
+        {
+          nPage = LISTVIEW_GetCountPerColumn(hwnd);
+        }
+        else if ((uView == LVS_ICON) || (uView == LVS_SMALLICON))
+        {
+          nPage = 10;
+        }
+
+        if (scrollInfo.nPos >= nPage)
+        {
+          scrollInfo.nPos -= nPage;
+        }
+        else
+        {
+          scrollInfo.nPos = scrollInfo.nMin;
+        }
       }
       break;
-    }
-    break;
-
-  case SB_THUMBPOSITION:
-    nScrollPosInc = nScroll - nScrollPos;
-    break;
-  }
-
-  if (nScrollPosInc != 0)
-  {
-    LISTVIEW_ScrollView(hwnd, nScrollPosInc, 0);
-  }
-
+      
+    case SB_PAGEDOWN:
+      if (scrollInfo.nPos < scrollInfo.nMax)
+      {
+        INT nPage = 0;
+
+        if (uView == LVS_REPORT)
+        {
+          nPage = LISTVIEW_GetCountPerColumn(hwnd);
+        }
+        else if ((uView == LVS_ICON) || (uView == LVS_SMALLICON))
+        {
+          nPage = 10;
+        }
+        
+        if (scrollInfo.nPos <= scrollInfo.nMax - nPage)
+        {
+          scrollInfo.nPos += nPage;
+        }
+        else
+        {
+          scrollInfo.nPos = scrollInfo.nMax;
+        }
+      }
+      break;
+
+    case SB_THUMBPOSITION:
+      break;
+    }
+
+    if (nOldScrollPos != scrollInfo.nPos)
+    {
+      scrollInfo.fMask = SIF_POS;
+      SetScrollInfo(hwnd, SB_VERT, &scrollInfo, TRUE);
+      InvalidateRect(hwnd, NULL, TRUE);
+    }
+  }
+    
+  return 0;
+}
+
+/***
+ * DESCRIPTION:
+ * Performs horizontal scrolling.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] INT : scroll code
+ * [I] SHORT : current scroll position if scroll code is SB_THIMBPOSITION 
+ *             or SB_THUMBTRACK.
+ * [I] HWND : scrollbar control window handle
+ *
+ * RETURN:
+ * Zero
+ */
+static LRESULT LISTVIEW_HScroll(HWND hwnd, INT nScrollCode, SHORT nCurrentPos,
+                                HWND hScrollWnd)
+{
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
+  SCROLLINFO scrollInfo;
+
+  ZeroMemory(&scrollInfo, sizeof(SCROLLINFO));
+  scrollInfo.cbSize = sizeof(SCROLLINFO);
+  scrollInfo.fMask = /*SIF_PAGE |*/ SIF_POS | SIF_RANGE;
+ 
+  if (GetScrollInfo(hwnd, SB_HORZ, &scrollInfo) != FALSE)
+  {
+    INT nOldScrollPos = scrollInfo.nPos;
+
+    switch (nScrollCode)
+    {
+    case SB_LINELEFT:
+      if (scrollInfo.nPos > scrollInfo.nMin)
+      {
+        scrollInfo.nPos--;
+      }
+      break;
+    
+    case SB_LINERIGHT:
+      if (scrollInfo.nPos < scrollInfo.nMax)
+      {
+        scrollInfo.nPos++;
+      }
+      break;
+      
+    case SB_PAGELEFT:
+      if (scrollInfo.nPos > scrollInfo.nMin)
+      {
+        INT nPage = 0;
+
+        if (uView == LVS_LIST)
+        {
+          nPage = LISTVIEW_GetCountPerRow(hwnd);
+        }
+        else if ((uView == LVS_ICON) || (uView == LVS_SMALLICON))
+        {
+          nPage = 10;
+        }
+        
+        if (scrollInfo.nPos >= nPage)
+        {
+          scrollInfo.nPos -= nPage;
+        }
+        else
+        {
+          scrollInfo.nPos = scrollInfo.nMin;
+        }
+      }
+      break;
+      
+    case SB_PAGERIGHT:
+      if (scrollInfo.nPos < scrollInfo.nMax)
+      {
+        INT nPage = 0;
+
+        if (uView == LVS_LIST)
+        {
+          nPage = LISTVIEW_GetCountPerRow(hwnd);
+        }
+        else if ((uView == LVS_ICON) || (uView == LVS_SMALLICON))
+        {
+          nPage = 10;
+        }
+        
+        if (scrollInfo.nPos <= scrollInfo.nMax - nPage)
+        {
+          scrollInfo.nPos += nPage;
+        }
+        else
+        {
+          scrollInfo.nPos = scrollInfo.nMax;
+        }
+      }
+      break;
+
+    case SB_THUMBPOSITION:
+      break;
+    }
+
+    if (nOldScrollPos != scrollInfo.nPos)
+    {
+      scrollInfo.fMask = SIF_POS;
+      SetScrollInfo(hwnd, SB_HORZ, &scrollInfo, TRUE);
+      InvalidateRect(hwnd, NULL, TRUE);
+    }
+  }
+    
   return 0;
 }
@@ -5541,12 +5571,10 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
   INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
-  INT nCountPerColumn;
-  INT nCountPerRow;
   HWND hwndParent = GetParent(hwnd);
   NMLVKEYDOWN nmKeyDown; 
   NMHDR nmh;
-  INT oldFocusedItem = infoPtr->nFocusedItem;
+  INT nItem = -1;
+  BOOL bRedraw = FALSE;
 
   /* send LVN_KEYDOWN notification */
@@ -5581,5 +5609,5 @@
     if (GETITEMCOUNT(infoPtr) > 0)
     {
-      LISTVIEW_KeySelection(hwnd, 0); 
+      nItem = 0;
     }
     break;
@@ -5588,156 +5616,43 @@
     if (GETITEMCOUNT(infoPtr) > 0)
     {
-      LISTVIEW_KeySelection(hwnd, GETITEMCOUNT(infoPtr) - 1);
+      nItem = GETITEMCOUNT(infoPtr) - 1;
     }
     break;
 
   case VK_LEFT:
-    switch (LVS_TYPEMASK & lStyle)
-    {
-    case LVS_LIST:
-      if (infoPtr->nFocusedItem >= infoPtr->nCountPerColumn) 
-      {
-        LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - 
-                              infoPtr->nCountPerColumn);
-      }
-      break;
-
-    case LVS_SMALLICON:
-    case LVS_ICON:
-      if (lStyle & LVS_ALIGNLEFT)
-      {
-        nCountPerColumn = max((infoPtr->rcList.bottom - infoPtr->rcList.top) /
-                              infoPtr->nItemHeight, 1);
-        if (infoPtr->nFocusedItem >= nCountPerColumn) 
-        {
-          LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - nCountPerColumn);
-        }
-      }
-      else
-      {
-        nCountPerRow = max((infoPtr->rcList.right - infoPtr->rcList.left) /
-                           infoPtr->nItemWidth, 1);
-        if (infoPtr->nFocusedItem % nCountPerRow != 0)
-        {
-          LISTVIEW_SetSelection(hwnd, infoPtr->nFocusedItem - 1); 
-        }
-      }
-      break;
-    }
+    nItem = LISTVIEW_GetNextItem(hwnd, infoPtr->nFocusedItem, LVNI_TOLEFT);
     break;
-  
+
   case VK_UP:
-    switch (LVS_TYPEMASK & lStyle)
-    {
-    case LVS_LIST:
-    case LVS_REPORT:
-      if (infoPtr->nFocusedItem > 0)
-      {
-        LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - 1);
-      }
-      break;
-
-    default:
-      if (lStyle & LVS_ALIGNLEFT)
-      {
-        nCountPerColumn = max((infoPtr->rcList.bottom - infoPtr->rcList.top) /
-                              infoPtr->nItemHeight, 1);
-        if (infoPtr->nFocusedItem % nCountPerColumn != 0)
-        {
-          LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - 1);
-        }
-      }
-      else
-      {
-        nCountPerRow = max((infoPtr->rcList.right - infoPtr->rcList.left) /
-                           infoPtr->nItemWidth, 1);
-        if (infoPtr->nFocusedItem >= nCountPerRow)
-        {
-          LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - nCountPerRow);
-        }
-      }
-    }
+    nItem = LISTVIEW_GetNextItem(hwnd, infoPtr->nFocusedItem, LVNI_ABOVE);
     break;
     
   case VK_RIGHT:
-    switch (LVS_TYPEMASK & lStyle)
-    {
-    case LVS_LIST:
-      if (infoPtr->nFocusedItem < GETITEMCOUNT(infoPtr) - 
-          infoPtr->nCountPerColumn)
-      {
-        LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem +
-                              infoPtr->nCountPerColumn);
-      }
-      break;
-
-    case LVS_ICON:
-    case LVS_SMALLICON:
-      if (lStyle & LVS_ALIGNLEFT)
-      {
-        nCountPerColumn = max((infoPtr->rcList.bottom - infoPtr->rcList.top) /
-                              infoPtr->nItemHeight, 1);
-        if (infoPtr->nFocusedItem < GETITEMCOUNT(infoPtr) - nCountPerColumn)
-        {
-          LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + nCountPerColumn);
-        }
-      }
-      else
-      {
-        nCountPerRow = max((infoPtr->rcList.right - infoPtr->rcList.left) /
-                           infoPtr->nItemWidth, 1);
-        if ((infoPtr->nFocusedItem % nCountPerRow != nCountPerRow - 1) && 
-            (infoPtr->nFocusedItem < GETITEMCOUNT(infoPtr) - 1))
-        {
-          LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + 1);
-        }
-      }
-    }
+    nItem = LISTVIEW_GetNextItem(hwnd, infoPtr->nFocusedItem, LVNI_TORIGHT);
     break;
 
   case VK_DOWN:
-    switch (LVS_TYPEMASK & lStyle)
-    {
-    case LVS_LIST:
-    case LVS_REPORT:
-      if (infoPtr->nFocusedItem < GETITEMCOUNT(infoPtr) - 1)
-      {
-        LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + 1);
-      }
-      break;
-
-    case LVS_SMALLICON:
-    case LVS_ICON:
-      if (lStyle & LVS_ALIGNLEFT)
-      {
-        nCountPerColumn = max((infoPtr->rcList.bottom - infoPtr->rcList.top) /
-                              infoPtr->nItemHeight, 1);
-        if (infoPtr->nFocusedItem % nCountPerColumn != nCountPerColumn - 1)
-        {
-          LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + 1);
-        }
-      }
-      else
-      {
-        nCountPerRow = max((infoPtr->rcList.right - infoPtr->rcList.left) /
-                           infoPtr->nItemWidth, 1);
-        if (infoPtr->nFocusedItem < GETITEMCOUNT(infoPtr) - nCountPerRow)
-        {
-          LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + nCountPerRow);
-        }
-      }
-    }
+    nItem = LISTVIEW_GetNextItem(hwnd, infoPtr->nFocusedItem, LVNI_BELOW);
     break;
 
   case VK_PRIOR:
+    /* TO DO */
     break;
 
   case VK_NEXT:
+    /* TO DO */
     break;
   }
 
-  /* refresh client area if necessary*/
-  if(oldFocusedItem != infoPtr->nFocusedItem)
-    InvalidateRect(hwnd, NULL, TRUE);
+  if ((nItem != -1) && (nItem != infoPtr->nFocusedItem))
+  {
+    bRedraw = LISTVIEW_KeySelection(hwnd, nItem);
+    if (bRedraw != FALSE)
+    {
+      /* refresh client area */
+      InvalidateRect(hwnd, NULL, TRUE);
+      UpdateWindow(hwnd);
+    }
+  }
 
   return 0;
@@ -5769,4 +5684,7 @@
   infoPtr->bFocus = FALSE;
 
+  /* NEED drawing optimization ; redraw the selected items */
+  InvalidateRect(hwnd, NULL, FALSE);
+
   return 0;
 }
@@ -5791,5 +5709,5 @@
   NMHDR nmh;
 
-//  TRACE(listview, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd, wKey, wPosX, wPosY);
+  TRACE("(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd, wKey, wPosX, wPosY);
 
   /* send NM_DBLCLK notification */
@@ -5823,10 +5741,13 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
   INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
   static BOOL bGroupSelect = TRUE;
+  POINT ptPosition;
   NMHDR nmh;
   INT nItem;
 
-//  TRACE(listview, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd, wKey, wPosX, wPosY);
+  TRACE("(hwnd=%x, key=%hu, X=%hu, Y=%hu)\n", hwnd, wKey, wPosX, 
+        wPosY);
 
   /* send NM_RELEASEDCAPTURE notification */ 
@@ -5843,30 +5764,39 @@
   /* set left button down flag */
   infoPtr->bLButtonDown = TRUE;
-
-  nItem = LISTVIEW_MouseSelection(hwnd, wPosX, wPosY);
+  
+  ptPosition.x = wPosX;
+  ptPosition.y = wPosY;
+  nItem = LISTVIEW_MouseSelection(hwnd, ptPosition);
   if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
   {
-    if ((wKey & MK_CONTROL) && (wKey & MK_SHIFT))
-    {
-      if (bGroupSelect != FALSE)
-      {
-        LISTVIEW_AddGroupSelection(hwnd, nItem);
+    if (lStyle & LVS_SINGLESEL)
+    {
+      LISTVIEW_SetSelection(hwnd, nItem);
+    }
+    else
+    {
+      if ((wKey & MK_CONTROL) && (wKey & MK_SHIFT))
+      {
+        if (bGroupSelect != FALSE)
+        {
+          LISTVIEW_AddGroupSelection(hwnd, nItem);
+        }
+        else
+        {
+          LISTVIEW_AddSelection(hwnd, nItem);
+        }
+      }
+      else if (wKey & MK_CONTROL)
+      {
+        bGroupSelect = LISTVIEW_ToggleSelection(hwnd, nItem);
+      }
+      else  if (wKey & MK_SHIFT)
+      {
+        LISTVIEW_SetGroupSelection(hwnd, nItem);
       }
       else
       {
-        LISTVIEW_AddSelection(hwnd, nItem);
-      }
-    }
-    else if (wKey & MK_CONTROL)
-    {
-      bGroupSelect = LISTVIEW_ToggleSelection(hwnd, nItem);
-    }
-    else  if (wKey & MK_SHIFT)
-    {
-      LISTVIEW_SetGroupSelection(hwnd, nItem);
-    }
-    else
-    {
-      LISTVIEW_SetSelection(hwnd, nItem);
+        LISTVIEW_SetSelection(hwnd, nItem);
+      }
     }
   }
@@ -5900,5 +5830,5 @@
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
 
-//  TRACE(listview, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd, wKey, wPosX, wPosY);
+  TRACE("(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd, wKey, wPosX, wPosY);
 
   if (infoPtr->bLButtonDown != FALSE) 
@@ -5936,5 +5866,5 @@
   LISTVIEW_INFO *infoPtr;
 
-//  TRACE(listview, "(hwnd=%x,wParam=%x,lParam=%lx)\n", hwnd, wParam, lParam);
+  TRACE("(hwnd=%x,wParam=%x,lParam=%lx)\n", hwnd, wParam, lParam);
 
   /* allocate memory for info structure */
@@ -5943,5 +5873,5 @@
   if (infoPtr == NULL) 
   {
-//    ERR(listview, "could not allocate info memory!\n");
+    ERR("could not allocate info memory!\n");
     return 0;
   }
@@ -5949,5 +5879,5 @@
   if ((LISTVIEW_INFO *)GetWindowLongA(hwnd, 0) != infoPtr) 
   {
-//    ERR(listview, "pointer assignment error!\n");
+    ERR("pointer assignment error!\n");
     return 0;
   }
@@ -5970,5 +5900,5 @@
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
 
-//  TRACE(listview, "(hwnd=%x)\n", hwnd);
+  TRACE("(hwnd=%x)\n", hwnd);
 
   /* delete all items */
@@ -6012,5 +5942,5 @@
     if (lpnmh->code == HDN_ENDTRACKA)
     {
-      infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd, LVS_REPORT);
+      infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd);
       InvalidateRect(hwnd, NULL, TRUE);
     }
@@ -6043,5 +5973,5 @@
     if (infoPtr->notifyFormat == NFR_UNICODE)
     {
-//      FIXME (listview, "NO support for unicode structures");
+      FIXME("NO support for unicode structures");
     }
   }
@@ -6065,5 +5995,5 @@
   PAINTSTRUCT ps;
 
-//   TRACE(listview, "(hwnd=%x,hdc=%x)\n", hwnd, hdc);
+   TRACE("(hwnd=%x,hdc=%x)\n", hwnd, hdc);
 
   if (hdc == 0)
@@ -6100,5 +6030,5 @@
   NMHDR nmh;
 
-//  TRACE(listview, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd, wKey, wPosX, wPosY);
+  TRACE("(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd, wKey, wPosX, wPosY);
 
   /* send NM_RELEASEDCAPTURE notification */ 
@@ -6133,8 +6063,9 @@
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
+  POINT ptPosition;
   NMHDR nmh;
   INT nItem;
 
-//  TRACE(listview, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd, wKey, wPosX, wPosY);
+  TRACE("(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd, wKey, wPosX, wPosY);
 
   /* send NM_RELEASEDCAPTURE notification */
@@ -6154,5 +6085,7 @@
 
   /* determine the index of the selected item */
-  nItem = LISTVIEW_MouseSelection(hwnd, wPosX, wPosY);
+  ptPosition.x = wPosX;
+  ptPosition.y = wPosY;
+  nItem = LISTVIEW_MouseSelection(hwnd, ptPosition);
   if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
   {
@@ -6166,5 +6099,5 @@
     LISTVIEW_RemoveSelections(hwnd, 0, GETITEMCOUNT(infoPtr));
   }
-
+  
   return 0;
 }
@@ -6190,5 +6123,5 @@
   NMHDR nmh;
 
-//  TRACE(listview, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd, wKey, wPosX, wPosY);
+  TRACE("(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd, wKey, wPosX, wPosY);
 
   if (infoPtr->bRButtonDown != FALSE) 
@@ -6252,7 +6185,7 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-
-//  TRACE(listview, "(hwnd=%x,hfont=%x,redraw=%hu)\n", hwnd, hFont, fRedraw);
+  UINT uView = GetWindowLongA(hwnd, GWL_STYLE) & LVS_TYPEMASK;
+
+  TRACE("(hwnd=%x,hfont=%x,redraw=%hu)\n", hwnd, hFont, fRedraw);
 
   if (hFont == 0)
@@ -6265,5 +6198,5 @@
   }
 
-  if ((LVS_TYPEMASK & lStyle ) == LVS_REPORT)
+  if (uView == LVS_REPORT)
   {
     /* set header font */
@@ -6298,87 +6231,59 @@
 static LRESULT LISTVIEW_Size(HWND hwnd, int Width, int Height)
 {
+  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); 
+  UINT uView = lStyle & LVS_TYPEMASK;
+
+  TRACE("(hwnd=%x, width=%d, height=%d)\n",hwnd, Width, Height);
+
+  LISTVIEW_UpdateSize(hwnd);
+
+  if ((uView == LVS_SMALLICON) || (uView == LVS_ICON))
+  {
+    if (lStyle & LVS_ALIGNLEFT)
+    {
+      LISTVIEW_AlignLeft(hwnd);
+    }
+    else
+    {
+      LISTVIEW_AlignTop(hwnd);
+    }
+  }
+
+  LISTVIEW_UpdateScroll(hwnd);
+  
+  /* invalidate client area + erase background */
+  InvalidateRect(hwnd, NULL, TRUE);
+
+  return 0;
+}
+
+/***
+ * DESCRIPTION:
+ * Sets the size information.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ *
+ * RETURN:
+ * Zero
+ */
+static VOID LISTVIEW_UpdateSize(HWND hwnd)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-
-//  TRACE(listview, "(hwnd=%x,width=%d,height=%d)\n",hwnd, Width, Height);
-
-  LISTVIEW_SetSize(hwnd, lStyle, -1, -1);
-  switch (lStyle & LVS_TYPEMASK)
-  {
-  case LVS_LIST:
-  case LVS_REPORT:
-    LISTVIEW_SetViewInfo(hwnd, lStyle);
-    break;
-    
-  case LVS_ICON:
-  case LVS_SMALLICON:
-    if (lStyle & LVS_ALIGNLEFT)
-    {
-      LISTVIEW_AlignLeft(hwnd);
-    }
-    else
-    {
-      LISTVIEW_AlignTop(hwnd);
-    }
-    break;
-  }
-
-  LISTVIEW_SetScroll(hwnd, lStyle);
-
-  /* invalidate + erase background */
-  InvalidateRect(hwnd, NULL, TRUE);
-
-  return 0;
-}
-
-/***
- * DESCRIPTION:
- * Sets the size information for a given style. 
- * 
- * PARAMETER(S):
- * [I] HWND : window handle
- * [I] LONG : window style
- * [I] WORD : new width 
- * [I] WORD : new height
- *
- * RETURN:
- * Zero
- */
-static VOID LISTVIEW_SetSize(HWND hwnd, LONG lStyle, LONG lWidth, LONG lHeight)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  HDLAYOUT hl;
-  WINDOWPOS wp;
+  UINT uView = lStyle & LVS_TYPEMASK;
   RECT rcList;
   
   GetClientRect(hwnd, &rcList);
-  if (lWidth == -1)
-  {
-    infoPtr->rcList.left = max(rcList.left, 0);
-    infoPtr->rcList.right = max(rcList.right, 0);
-  }
-  else
-  {
-    infoPtr->rcList.left = max(rcList.left, 0);
-    infoPtr->rcList.right = infoPtr->rcList.left + max(lWidth, 0);
-  }
-
-  if (lHeight == -1)
-  {
-    infoPtr->rcList.top = max(rcList.top, 0);
-    infoPtr->rcList.bottom = max(rcList.bottom, 0);
-  }
-  else
-  {
-    infoPtr->rcList.top = max(rcList.top, 0);
-    infoPtr->rcList.bottom = infoPtr->rcList.top + max(lHeight, 0);
-  }
-    
-  switch (lStyle & LVS_TYPEMASK)
-  {
-  case LVS_LIST:
+  infoPtr->rcList.left = 0;
+  infoPtr->rcList.right = max(rcList.right - rcList.left, 1);
+  infoPtr->rcList.top = 0;
+  infoPtr->rcList.bottom = max(rcList.bottom - rcList.top, 1);
+     
+  if (uView == LVS_LIST)
+  {
     if ((lStyle & WS_HSCROLL) == 0)
     {
-      INT nHScrollHeight;
-      nHScrollHeight = GetSystemMetrics(SM_CYHSCROLL);
+      INT nHScrollHeight = GetSystemMetrics(SM_CYHSCROLL);
       if (infoPtr->rcList.bottom > nHScrollHeight)
       { 
@@ -6386,12 +6291,17 @@
       }
     }
-    break;
-
-  case LVS_REPORT:
+  }
+  else if (uView == LVS_REPORT)
+  {
+    HDLAYOUT hl;
+    WINDOWPOS wp;
+
     hl.prc = &rcList;
     hl.pwpos = &wp;
     Header_Layout(infoPtr->hwndHeader, &hl);
-    infoPtr->rcList.top = max(wp.cy, 0);
-    break;
+    if (!(LVS_NOCOLUMNHEADER & lStyle))
+    {
+      infoPtr->rcList.top = max(wp.cy, 0);
+    }
   }
 }
@@ -6413,37 +6323,34 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  UINT uNewView = lpss->styleNew & LVS_TYPEMASK;
+  UINT uOldView = lpss->styleOld & LVS_TYPEMASK;
   RECT rcList = infoPtr->rcList;
-  HDLAYOUT hl;
-  WINDOWPOS wp;
-
-//  TRACE(listview, "(hwnd=%x,styletype=%x,stylestruct=%p)\n", 
-//        hwnd, wStyleType, lpss);
+
+  TRACE("(hwnd=%x, styletype=%x, stylestruct=%p)\n", 
+        hwnd, wStyleType, lpss);
 
   if (wStyleType == GWL_STYLE)
   {
+    if (uOldView == LVS_REPORT)
+    {
+      ShowWindow(infoPtr->hwndHeader, SW_HIDE);
+    }
+ 
     if ((lpss->styleOld & WS_HSCROLL) != 0)
     {
-      ShowScrollBar(hwnd, SB_HORZ, FALSE);
-    }
-
+       ShowScrollBar(hwnd, SB_HORZ, FALSE);
+    }
+ 
     if ((lpss->styleOld & WS_VSCROLL) != 0)
     {
-      ShowScrollBar(hwnd, SB_VERT, FALSE);
-    }
-
-    if ((LVS_TYPEMASK & lpss->styleOld) == LVS_REPORT)
-    {
-      /* remove header */
-      ShowWindow(infoPtr->hwndHeader, SW_HIDE);
-    }
-
-    switch (lpss->styleNew & LVS_TYPEMASK)
-    {
-    case LVS_ICON:
+       ShowScrollBar(hwnd, SB_VERT, FALSE);
+    }
+ 
+    if (uNewView == LVS_ICON)
+    {
       infoPtr->iconSize.cx = GetSystemMetrics(SM_CXICON);
       infoPtr->iconSize.cy = GetSystemMetrics(SM_CYICON);
-      LISTVIEW_SetSize(hwnd, lpss->styleNew, -1, -1);
-      infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd, lpss->styleNew);
-      infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd, lpss->styleNew);
+      infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd);
+      infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd);
       if (lpss->styleNew & LVS_ALIGNLEFT)
       {
@@ -6454,36 +6361,37 @@
         LISTVIEW_AlignTop(hwnd);
       }
-      break;
-
-    case LVS_REPORT:
+    }
+    else if (uNewView == LVS_REPORT)
+    {
+      HDLAYOUT hl;
+      WINDOWPOS wp;
+
       hl.prc = &rcList;
       hl.pwpos = &wp;
       Header_Layout(infoPtr->hwndHeader, &hl);
-      SetWindowPos(infoPtr->hwndHeader, hwnd, wp.x, wp.y, wp.cx, 
-                   wp.cy, wp.flags);
-      ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL);
+      SetWindowPos(infoPtr->hwndHeader, hwnd, wp.x, wp.y, wp.cx, wp.cy, 
+                   wp.flags);
+      if (!(LVS_NOCOLUMNHEADER & lpss->styleNew))
+      {
+        ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL);
+      }
       infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON);
       infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON);
-      infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd, lpss->styleNew);
-      infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd, lpss->styleNew);
-      LISTVIEW_SetSize(hwnd, lpss->styleNew, -1, -1);
-      LISTVIEW_SetViewInfo(hwnd, lpss->styleNew);
-      break;
-
-    case LVS_LIST:
+      infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd);
+      infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd);
+    }
+    else if (uNewView == LVS_LIST)
+    {
       infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON);
       infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON);
-      infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd, lpss->styleNew);
-      infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd, lpss->styleNew);
-      LISTVIEW_SetSize(hwnd, lpss->styleNew, -1, -1);
-      LISTVIEW_SetViewInfo(hwnd, lpss->styleNew);
-      break;
-
-    case LVS_SMALLICON:
+      infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd);
+      infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd);
+    }
+    else
+    {
       infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON);
       infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON);
-      LISTVIEW_SetSize(hwnd, lpss->styleNew, -1, -1);
-      infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd, lpss->styleNew);
-      infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd, lpss->styleNew);
+      infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd);
+      infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd);
       if (lpss->styleNew & LVS_ALIGNLEFT)
       {
@@ -6494,14 +6402,17 @@
         LISTVIEW_AlignTop(hwnd);
       }
-      break;
-    }
-
-    LISTVIEW_SetScroll(hwnd, lpss->styleNew);
+    }
+
+    /* update the size of the client area */
+    LISTVIEW_UpdateSize(hwnd);
+
+    /* add scrollbars if needed */
+    LISTVIEW_UpdateScroll(hwnd);
     
-    /* print unsupported styles */
+    /* invalidate client area + erase background */
+    InvalidateRect(hwnd, NULL, TRUE);
+
+    /* print the list of unsupported window styles */
     LISTVIEW_UnsupportedStyles(lpss->styleNew);
-
-    /* invalidate client area */
-    InvalidateRect(hwnd, NULL, TRUE);
   }
 
@@ -6512,13 +6423,5 @@
  * DESCRIPTION:
  * Window procedure of the listview control.
- * 
- * PARAMETER(S):
- * [I] HWND :
- * [I] UINT :
- * [I] WPARAM :
- * [I] LPARAM : 
- *
- * RETURN:
- * 
+ *
  */
 LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
@@ -6830,6 +6733,6 @@
     if (uMsg >= WM_USER)
     {
-//      ERR(listview, "unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, 
-//          lParam);
+      ERR("unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, 
+          lParam);
     }
 
Index: trunk/src/comctl32/status.c
===================================================================
--- trunk/src/comctl32/status.c	(revision 163)
+++ trunk/src/comctl32/status.c	(revision 164)
@@ -1,3 +1,3 @@
-/* $Id: status.c,v 1.4 1999-06-16 20:25:43 cbratschi Exp $ */
+/* $Id: status.c,v 1.5 1999-06-23 19:45:01 achimha Exp $ */
 /*
  * Interface code to StatusWindow widget/control
@@ -80,7 +80,7 @@
     UINT border = BDR_SUNKENOUTER;
 
-    if (part->style==SBT_POPOUT)
+    if (part->style & SBT_POPOUT)
       border = BDR_RAISEDOUTER;
-    else if (part->style==SBT_NOBORDERS)
+    else if (part->style & SBT_NOBORDERS)
       border = 0;
 
@@ -136,5 +136,5 @@
     hOldFont = SelectObject (hdc, self->hFont ? self->hFont : self->hDefaultFont);
 
-    if (part->style == SBT_OWNERDRAW) {
+    if (part->style & SBT_OWNERDRAW) {
         DRAWITEMSTRUCT dis;
 
@@ -192,5 +192,5 @@
     else {
         for (i = 0; i < infoPtr->numParts; i++) {
-            if (infoPtr->parts[i].style == SBT_OWNERDRAW) {
+	    if (infoPtr->parts[i].style & SBT_OWNERDRAW) {
                 DRAWITEMSTRUCT dis;
 
@@ -365,5 +365,5 @@
         part = &self->parts[nPart];
 
-    if (part->style == SBT_OWNERDRAW)
+    if (part->style & SBT_OWNERDRAW)
         result = (LRESULT)part->text;
     else {
@@ -391,5 +391,5 @@
         part = &infoPtr->parts[nPart];
 
-    if (part->style == SBT_OWNERDRAW)
+    if (part->style & SBT_OWNERDRAW)
         result = (LRESULT)part->text;
     else {
@@ -571,5 +571,5 @@
     if (oldNumParts > self->numParts) {
         for (i = self->numParts ; i < oldNumParts; i++) {
-            if (self->parts[i].text && (self->parts[i].style != SBT_OWNERDRAW))
+	    if (self->parts[i].text && !(self->parts[i].style & SBT_OWNERDRAW))
                 COMCTL32_Free (self->parts[i].text);
         }
@@ -635,8 +635,8 @@
     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
     STATUSWINDOWPART *part;
-    int part_num;
-    int style;
+    int	part_num;
+    int	style;
     LPSTR text;
-    int len;
+    int	len;
     HDC hdc;
 
@@ -646,22 +646,24 @@
 
     if ((self->simple) || (self->parts==NULL) || (part_num==255))
-        part = &self->part0;
+	part = &self->part0;
     else
-        part = &self->parts[part_num];
+	part = &self->parts[part_num];
     if (!part) return FALSE;
+
+    if (!(part->style & SBT_OWNERDRAW) && part->text)
+	COMCTL32_Free (part->text);
+    part->text = 0;
+
+    if (style & SBT_OWNERDRAW) {
+	part->text = (LPWSTR)text;
+    }
+    else {
+	/* duplicate string */
+	if (text && (len = lstrlenA(text))) {
+	    part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
+	    lstrcpyAtoW (part->text, text);
+	}
+    }
     part->style = style;
-    if (style == SBT_OWNERDRAW) {
-        part->text = (LPWSTR)text;
-    }
-    else {
-        /* duplicate string */
-        if (part->text)
-            COMCTL32_Free (part->text);
-        part->text = 0;
-        if (text && (len = lstrlenA(text))) {
-            part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
-            lstrcpyAtoW (part->text, text);
-        }
-    }
 
     hdc = GetDC (hwnd);
@@ -687,22 +689,24 @@
 
     if ((self->simple) || (self->parts==NULL) || (part_num==255))
-        part = &self->part0;
+	part = &self->part0;
     else
-        part = &self->parts[part_num];
+	part = &self->parts[part_num];
     if (!part) return FALSE;
+
+    if (!(part->style & SBT_OWNERDRAW) && part->text)
+	COMCTL32_Free (part->text);
+    part->text = 0;
+
+    if (style & SBT_OWNERDRAW) {
+	part->text = text;
+    }
+    else {
+	/* duplicate string */
+	if (text && (len = lstrlenW(text))) {
+	    part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
+	    lstrcpyW(part->text, text);
+	}
+    }
     part->style = style;
-    if (style == SBT_OWNERDRAW) {
-        part->text = text;
-    }
-    else {
-        /* duplicate string */
-        if (part->text)
-            COMCTL32_Free (part->text);
-        part->text = 0;
-        if (text && (len = lstrlenW(text))) {
-            part->text = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
-            lstrcpyW(part->text, text);
-        }
-    }
 
     hdc = GetDC (hwnd);
@@ -892,21 +896,21 @@
 {
     STATUSWINDOWINFO *self = STATUSBAR_GetInfoPtr (hwnd);
-    int i;
+    int	i;
 
     for (i = 0; i < self->numParts; i++) {
-        if (self->parts[i].text && (self->parts[i].style != SBT_OWNERDRAW))
-            COMCTL32_Free (self->parts[i].text);
-    }
-    if (self->part0.text && (self->part0.style != SBT_OWNERDRAW))
-        COMCTL32_Free (self->part0.text);
+	if (self->parts[i].text && !(self->parts[i].style & SBT_OWNERDRAW))
+	    COMCTL32_Free (self->parts[i].text);
+    }
+    if (self->part0.text && !(self->part0.style & SBT_OWNERDRAW))
+	COMCTL32_Free (self->part0.text);
     COMCTL32_Free (self->parts);
 
     /* delete default font */
     if (self->hDefaultFont)
-        DeleteObject (self->hDefaultFont);
+	DeleteObject (self->hDefaultFont);
 
     /* delete tool tip control */
     if (self->hwndToolTip)
-        DestroyWindow (self->hwndToolTip);
+	DestroyWindow (self->hwndToolTip);
 
     COMCTL32_Free (self);
Index: trunk/src/comctl32/tab.c
===================================================================
--- trunk/src/comctl32/tab.c	(revision 163)
+++ trunk/src/comctl32/tab.c	(revision 164)
@@ -1,3 +1,3 @@
-/* $Id: tab.c,v 1.4 1999-06-10 16:22:02 achimha Exp $ */
+/* $Id: tab.c,v 1.5 1999-06-23 19:45:01 achimha Exp $ */
 /*
  * Tab control
@@ -775,5 +775,5 @@
   if (isVisible)
   {
-    HBRUSH hbr       = CreateSolidBrush (GetSysColor(COLOR_BACKGROUND));    
+    HBRUSH hbr       = CreateSolidBrush (GetSysColor(COLOR_BTNFACE));    
     HPEN   hwPen     = GetSysColorPen (COLOR_3DHILIGHT);
     HPEN   hbPen     = GetSysColorPen (COLOR_BTNSHADOW);
@@ -848,5 +848,5 @@
        * Background color. 
        */
-      hbr = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));    
+      hbr = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));    
 
       /*
@@ -1087,5 +1087,5 @@
   RECT clientRect;
 
-  HBRUSH brush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
+  HBRUSH brush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
 
   hdc = givenDC ? givenDC : GetDC(hwnd);
Index: trunk/src/comctl32/treeview.c
===================================================================
--- trunk/src/comctl32/treeview.c	(revision 163)
+++ trunk/src/comctl32/treeview.c	(revision 164)
@@ -1,3 +1,3 @@
-/* $Id: treeview.c,v 1.4 1999-06-16 20:25:44 cbratschi Exp $ */
+/* $Id: treeview.c,v 1.5 1999-06-23 19:45:02 achimha Exp $ */
 /* Treeview control
  *
@@ -1148,7 +1148,7 @@
    }
 
-   if (tvItem->mask & TVIF_PARAM) {
-        tvItem->lParam=wineItem->lParam;
-   }
+   // undocumented: windows ignores TVIF_PARAM and
+   // always sets lParam
+   tvItem->lParam=wineItem->lParam;
 
    if (tvItem->mask & TVIF_SELECTEDIMAGE) {
@@ -1507,5 +1507,5 @@
                     infoPtr->uNumPtrsAlloced/2 * sizeof(TREEVIEW_ITEM));
     memcpy (&infoPtr->freeList[0], &oldfreeList[0],
-                    infoPtr->uNumPtrsAlloced>>6 * sizeof(INT));
+                    (infoPtr->uNumPtrsAlloced>>6) * sizeof(INT));
 
     COMCTL32_Free (oldItems);
