Changed the listview control to add the report view and fix some bugs
for the list view.

diff --git a/dlls/comctl32/header.c b/dlls/comctl32/header.c
index 280e61b..f7dc5bf 100644
--- a/dlls/comctl32/header.c
+++ b/dlls/comctl32/header.c
@@ -730,19 +730,26 @@
 
         infoPtr->uNumItem++;
         infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem);
-        /* pre insert copy */
-        if (nItem > 0) {
-            memcpy (&infoPtr->items[0], &oldItems[0],
-                    nItem * sizeof(HEADER_ITEM));
+        if (nItem == 0) {
+            memcpy (&infoPtr->items[1], &oldItems[0],
+                    (infoPtr->uNumItem-1) * sizeof(HEADER_ITEM));
         }
+        else
+        {
+              /* pre insert copy */
+            if (nItem > 0) {
+                 memcpy (&infoPtr->items[0], &oldItems[0],
+                         nItem * sizeof(HEADER_ITEM));
+            }
 
-        /* post insert copy */
-        if (nItem < infoPtr->uNumItem - 1) {
-            memcpy (&infoPtr->items[nItem+1], &oldItems[nItem],
-                    (infoPtr->uNumItem - nItem) * sizeof(HEADER_ITEM));
+            /* post insert copy */
+            if (nItem < infoPtr->uNumItem - 1) {
+                memcpy (&infoPtr->items[nItem+1], &oldItems[nItem],
+                        (infoPtr->uNumItem - nItem) * sizeof(HEADER_ITEM));
+            }
         }
-
-	COMCTL32_Free (oldItems);
+    
+        COMCTL32_Free (oldItems);
     }
 
     lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index 157af47..208f927 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -5,139 +5,1310 @@
  * Copyright 1999 Luc Tourangeau
  *
  * NOTES
- * Listview control implementation. The behavior conforms to version 4.70 
- * and earlier of the listview contol.
+ * Listview control implementation. 
  *
  * TODO:
- *   Most messages and notifications
- *   Report, small icon and icon display modes 
+ *   LISTVIEW_GetMaxItemWidth : large icon view
+ *   LISTVIEW_Notify : notification from children 
+ *   LISTVIEW_KeyDown : key press messages
+ *   LISTVIEW_HScroll : small icon and icon
+ *   LISTVIEW_VScroll : small icon and icon
+ *   LISTVIEW_SortItems : empty stub 
+ *   LISTVIEW_SetItemPosition : small icon and icon
+ *   LISTVIEW_SetItemCount : empty stub 
+ *   LISTVIEW_SetItem32W : no unicode yet!
+ *   LISTVIEW_SetColumn32A : DOUBLE CHECK 
+ *   LISTVIEW_Scroll : scrolling in pixels 
+ *   LISTVIEW_RedrawItems : define bounding rect 
+ *   LISTVIEW_InsertItem32W : no unicode yet!
+ *   LISTVIEW_InsertColumn32W : no unicode yet!
+ *   LISTVIEW_GetViewRect : small icon and icon 
+ *   LISTVIEW_GetOrigin : small icon and icon
+ *   LISTVIEW_GetNumberOfWorkAreas : small icon and icon
+ *   LISTVIEW_GetNextItem : all
+ *   LISTVIEW_SetScroll : scrolling in pixels 
+ *   LISTVIEW_GetItemRect : all 
+ *   LISTVIEW_GetHotCursor : all 
+ *   LISTVIEW_GetHotItem : all 
+ *   LISTVIEW_GetHoverTime : all
+ *   LISTVIEW_GetISearchString : all 
+ *   LISTVIEW_GetBkImage : all
+ *   LISTVIEW_FindItem : all 
+ *   LISTVIEW_EnsureVisible : some 
+ *   LISTVIEW_EditLabel : REPORT (need to implement a timer)
+ *   LISTVIEW_GetItemPosition : small icon and icon
+ *   LISTVIEW_GetItemRect : some
+ *   LISTVIEW_Arrange : small icon and icon
+ *   LISTVIEW_ApproximateViewRect : report, small icon and icon
+ *   LISTVIEW_RefreshIcon : large icon draw function
  */
 
-#include <string.h>
+#include "windows.h"
 #include "commctrl.h"
 #include "listview.h"
 #include "win.h"
 #include "debug.h"
 #include "winuser.h"
+#include "string.h"
 
-/* prototypes */
-static INT LISTVIEW_GetItemCountPerColumn(HWND hwnd);
-static INT LISTVIEW_GetItemCountPerRow(HWND hwnd);
-static INT LISTVIEW_GetFirstVisibleItem(HWND hwnd);
-static VOID LISTVIEW_SetVisible(HWND hwnd, INT nItem);
+/* constants */
+#define DISP_TEXT_SIZE 128
+#define WIDTH_PADDING 12
+#define HEIGHT_PADDING 2
+#define MIN_COLUMN_WIDTH 96
+
+/* macro section */
+#define GETITEMCOUNT(infoPtr) ((infoPtr)->hdpaItems->nItemCount)
+#define ListView_LVNotify(hwnd,lCtrlId,plvnm) \
+    (BOOL)SendMessageA((hwnd),WM_NOTIFY,(WPARAM)(INT)lCtrlId,(LPARAM)(LPNMLISTVIEW)(plvnm))
+#define ListView_Notify(hwnd,lCtrlId,pnmh) \
+    (BOOL)SendMessageA((hwnd),WM_NOTIFY,(WPARAM)(INT)lCtrlId,(LPARAM)(LPNMHDR)(pnmh))
+
+/* forward declarations */
+static VOID LISTVIEW_SetSize(HWND hwnd, LONG lStyle, LONG lWidth, 
+                             LONG lHeight);
+static VOID LISTVIEW_SetViewInfo(HWND hwnd);
+static VOID LISTVIEW_SetScroll(HWND hwnd);
+static VOID LISTVIEW_AddGroupSelection(HWND hwnd, INT nItem);
+static VOID LISTVIEW_AddSelection(HWND hwnd, INT nItem);
+static BOOL LISTVIEW_ToggleSelection(HWND hwnd, INT nItem);
+static VOID LISTVIEW_SetGroupSelection(HWND hwnd, INT nItem);
+static VOID LISTVIEW_SetSelection(HWND hwnd, INT nItem);
+static VOID LISTVIEW_RemoveSelections(HWND hwnd, INT nFirst, INT nLast);
+static VOID LISTVIEW_SetItemFocus(HWND hwnd, INT nItem);
+static BOOL LISTVIEW_RemoveSubItem(HDPA hdpaSubItems, INT nSubItem);
+static BOOL LISTVIEW_RemoveColumn(HDPA hdpaItems, INT nColumn);
+static BOOL LISTVIEW_InitItem(HWND hwnd, LISTVIEW_ITEM *lpItem, 
+                              LPLVITEMA lpLVItem);
+static BOOL LISTVIEW_InitSubItem(HWND hwnd, LISTVIEW_SUBITEM *lpSubItem,
+                                 LPLVITEMA lpLVItem);
+static BOOL LISTVIEW_AddSubItem(HWND hwnd, LPLVITEMA lpLVItem);
+static BOOL LISTVIEW_SetItem(HWND hwnd, LPLVITEMA lpLVItem);
+static BOOL LISTVIEW_SetSubItem(HWND hwnd, LPLVITEMA lpLVItem);
+static INT LISTVIEW_FindInsertPosition(HDPA hdpaSubItems, INT nSubItem);
+static LISTVIEW_SUBITEM* LISTVIEW_GetSubItem(HDPA hdpaSubItems, INT nSubItem);
 
 
 /***
  * DESCRIPTION:
- * Scrolls the specified item into the visible area.
+ * Prints a message for unsupported window styles.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : item index
+ * [I] LONG : window style
  *
  * RETURN:
  * None
  */
-static VOID LISTVIEW_SetVisible(HWND hwnd, INT nItem)
+static VOID LISTVIEW_UnsupportedStyles(LONG lStyle)
+{
+  if ((LVS_TYPEMASK & lStyle) == LVS_ALIGNLEFT)
+  {
+    FIXME(listview, "  LVS_ALIGNLEFT\n");
+  } 
+     
+  if ((LVS_TYPEMASK & lStyle) ==  LVS_ALIGNTOP)
+  {
+    FIXME(listview, "  LVS_ALIGNTOP\n");
+  }
+
+  if ((LVS_TYPEMASK & lStyle) == LVS_AUTOARRANGE)
+  {
+    FIXME(listview, "  LVS_AUTOARRANGE\n");
+  }
+
+  if ((LVS_TYPEMASK & lStyle) == LVS_EDITLABELS)
+  {
+    FIXME(listview, "  LVS_EDITLABELS\n");
+  }
+
+  if ((LVS_TYPEMASK & lStyle) == LVS_ICON)
+  {
+    FIXME(listview, "  LVS_ICON\n");
+  }
+
+  if ((LVS_TYPEMASK & lStyle) == LVS_NOCOLUMNHEADER)
+  {
+    FIXME(listview, "  LVS_SORTDESCENDING\n");
+  }
+
+  if ((LVS_TYPEMASK & lStyle) == LVS_NOLABELWRAP)
+  {
+    FIXME(listview, "  LVS_NOLABELWRAP\n");
+  }
+
+  if ((LVS_TYPEMASK & lStyle) == LVS_NOSCROLL)
+  {
+    FIXME(listview, "  LVS_NOSCROLL\n");
+  }
+
+  if ((LVS_TYPEMASK & lStyle) == LVS_NOSORTHEADER)
+  {
+    FIXME(listview, "  LVS_NOSORTHEADER\n");
+  }
+
+  if ((LVS_TYPEMASK & lStyle) == LVS_OWNERDRAWFIXED)
+  {
+    FIXME(listview, "  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");
+  }
+
+  if ((LVS_TYPEMASK & lStyle) == LVS_SMALLICON)
+  {
+    FIXME(listview, "  LVS_SMALLICON\n");
+  }
+
+  if ((LVS_TYPEMASK & lStyle) == LVS_SORTDESCENDING)
+  {
+    FIXME(listview, "  LVS_SORTDESCENDING\n");
+  }
+
+  if ((LVS_TYPEMASK & lStyle) == LVS_SORTDESCENDING)
+  {
+    FIXME(listview, "  LVS_SORTDESCENDING\n");
+  }
+}
+
+/***
+ * DESCRIPTION:
+ * Retrieves display information.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [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 display information.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] LISTVIEW_SUBITEM* : listview control subitem
+ * [O] INT : image index
+ * [O] UINT : state value
+ * [O] CHAR** : string
+ * [I] INT : size of string
+ *
+ * RETURN:
+ * None
+ */
+static VOID LISTVIEW_GetSubItemDispInfo(HWND hwnd, INT nItem, LPARAM lParam,
+                                        LISTVIEW_SUBITEM *lpSubItem, 
+                                        INT nColumn, 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 = nColumn;
+    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:
+ * Calculates a new column width.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ *
+ * RETURN:
+ * Returns item width.
+ */
+static INT LISTVIEW_GetMaxItemWidth(HWND hwnd)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  LISTVIEW_ITEM *lpItem;
+  HDPA hdpaSubItems;
+  INT nStringWidth;
+  INT nMaxItemWidth = 0;
+  INT i;
+  
+  if ((LVS_TYPEMASK & lStyle) == LVS_ICON)
+  {
+    /* TO DO */
+  }
+  else
+  {
+    for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
+    { 
+      hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, i);
+      if (hdpaSubItems != NULL)
+      {
+        lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
+        if (lpItem != NULL)
+        {
+          CHAR szDispText[DISP_TEXT_SIZE];
+          LPSTR pszDispText;
+          pszDispText = szDispText;
+          LISTVIEW_GetItemDispInfo(hwnd, i, lpItem, NULL, NULL, &pszDispText, 
+                                   DISP_TEXT_SIZE);
+          nStringWidth = ListView_GetStringWidthA(hwnd, pszDispText);
+          nMaxItemWidth = max(nMaxItemWidth, nStringWidth);
+        }
+      }
+    }
+    
+    /* add arbitrary padding for separating columns */
+    nMaxItemWidth += WIDTH_PADDING;
+
+    if (infoPtr->himlSmall != NULL)
+    {
+      nMaxItemWidth += infoPtr->iconSize.cx;
+    }
+
+    if (infoPtr->himlState != NULL)
+    {
+      nMaxItemWidth += infoPtr->iconSize.cx;
+    }
+  }
+
+  nMaxItemWidth = max(MIN_COLUMN_WIDTH, nMaxItemWidth);
+
+  return nMaxItemWidth;
+}
+
+/***
+ * DESCRIPTION:
+ * Sets diplay information (needed for drawing and calculations).
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * 
+ * RETURN:
+ * None
+ */
+static VOID LISTVIEW_SetViewInfo(HWND hwnd)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  INT nHeight;
+  INT nWidth;
+  HDC hdc;
+  HFONT hOldFont;
+  TEXTMETRICA tm; 
+
+  /* get text height */
+  hdc = GetDC(hwnd);
+  hOldFont = SelectObject(hdc, infoPtr->hFont);
+  GetTextMetricsA(hdc, &tm);
+
+  nHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
+  nWidth = infoPtr->rcList.right - infoPtr->rcList.left;
+
+  switch (LVS_TYPEMASK & lStyle)
+  {
+  case LVS_LIST:
+    infoPtr->nColumnWidth = LISTVIEW_GetMaxItemWidth(hwnd);
+    infoPtr->nItemHeight = (max(tm.tmHeight, infoPtr->iconSize.cy) + 
+                            HEIGHT_PADDING);
+    
+    infoPtr->nCountPerColumn = nHeight / infoPtr->nItemHeight;
+    if (infoPtr->nCountPerColumn == 0)
+    {
+      infoPtr->nCountPerColumn = 1;
+    }
+    
+    infoPtr->nCountPerRow = nWidth / infoPtr->nColumnWidth;
+    if (infoPtr->nCountPerRow == 0)
+    {
+      infoPtr->nCountPerRow = 1;
+    }
+    break;
+
+  case LVS_REPORT:
+    infoPtr->nItemHeight = (max(tm.tmHeight, infoPtr->iconSize.cy) + 
+                            HEIGHT_PADDING);
+    infoPtr->nCountPerRow = 1;
+    infoPtr->nCountPerColumn = nHeight / infoPtr->nItemHeight;
+    if (infoPtr->nCountPerColumn == 0)
+    {
+      infoPtr->nCountPerColumn = 1;
+    }
+    break;
+
+  }
+
+  SelectObject(hdc, hOldFont);
+  ReleaseDC(hwnd, hdc);
+}
+
+/***
+ * DESCRIPTION:
+ * Adds a block of selections.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] INT : item index 
+ *
+ * RETURN:
+ * None
+ */
+static VOID LISTVIEW_AddGroupSelection(HWND hwnd, INT nItem)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  INT nFirst = min(infoPtr->nSelectionMark, nItem);
+  INT nLast = max(infoPtr->nSelectionMark, nItem);
+  LVITEMA lvItem;
+  INT i;
+
+  lvItem.state = LVIS_SELECTED;
+  lvItem.stateMask= LVIS_SELECTED;
+  
+  for (i = nFirst; i <= nLast; i++)
+  {
+    ListView_SetItemState(hwnd, i, &lvItem);
+  }
+  
+  LISTVIEW_SetItemFocus(hwnd, nItem);
+  infoPtr->nSelectionMark = nItem;
+}
+
+/***
+ * DESCRIPTION:
+ * Adds a single selection.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] INT : item index 
+ *
+ * RETURN:
+ * None
+ */
+static VOID LISTVIEW_AddSelection(HWND hwnd, INT nItem)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  LVITEMA lvItem;
+
+  lvItem.state = LVIS_SELECTED;
+  lvItem.stateMask= LVIS_SELECTED;
+
+  ListView_SetItemState(hwnd, nItem, &lvItem);
+
+  LISTVIEW_SetItemFocus(hwnd, nItem);
+  infoPtr->nSelectionMark = nItem;
+}
+
+/***
+ * DESCRIPTION:
+ * Selects or unselects an item.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] INT : item index 
+ *
+ * RETURN:
+ *   SELECT: TRUE 
+ *   UNSELECT : FALSE
+ */
+static BOOL LISTVIEW_ToggleSelection(HWND hwnd, INT nItem)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  BOOL bResult;
+  LVITEMA lvItem;
+
+  lvItem.stateMask= LVIS_SELECTED;
+
+  if (ListView_GetItemState(hwnd, nItem, LVIS_SELECTED) & LVIS_SELECTED)
+  {
+    lvItem.state = 0;
+    ListView_SetItemState(hwnd, nItem, &lvItem);
+    bResult = FALSE;
+  }
+  else
+  {
+    lvItem.state = LVIS_SELECTED;
+    ListView_SetItemState(hwnd, nItem, &lvItem);
+    bResult = TRUE;
+  }
+
+  LISTVIEW_SetItemFocus(hwnd, nItem);
+  infoPtr->nSelectionMark = nItem;
+
+  return bResult;
+}
+
+/***
+ * DESCRIPTION:
+ * Reinitilizes the listview items.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] INT : item index 
+ *
+ * RETURN:
+ * None 
+ */
+static VOID LISTVIEW_SetGroupSelection(HWND hwnd, INT nItem)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  INT nFirst = min(infoPtr->nSelectionMark, nItem);
+  INT nLast = max(infoPtr->nSelectionMark, nItem);
+  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);
+  }
+
+  LISTVIEW_SetItemFocus(hwnd, nItem);
+}
+
+/***
+ * DESCRIPTION:
+ * Manages the item focus.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] INT : item index 
+ *
+ * RETURN:
+ * None
+ */
+static VOID LISTVIEW_SetItemFocus(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:
+ * Reinitilizes the listview items.
+ * 
+ * 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)
+  {
+    LISTVIEW_RemoveSelections(hwnd, 0, nItem - 1);
+  }
+
+  if (nItem < GETITEMCOUNT(infoPtr))
+  {
+    LISTVIEW_RemoveSelections(hwnd, nItem + 1, GETITEMCOUNT(infoPtr));
+  }
+
+  lvItem.state = 0;
+  lvItem.stateMask = LVIS_FOCUSED;
+  ListView_SetItemState(hwnd, infoPtr->nFocusedItem, &lvItem); 
+  
+  lvItem.state =  LVIS_SELECTED | LVIS_FOCUSED;
+  lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
+  ListView_SetItemState(hwnd, nItem, &lvItem);
+
+  infoPtr->nFocusedItem = nItem;
+  infoPtr->nSelectionMark = nItem;
+}
+
+/***
+ * DESCRIPTION:
+ * Reinitilizes the listview items.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] INT : item index 
+ *
+ * RETURN:
+ * None
+ */
+static VOID LISTVIEW_KeySelection(HWND hwnd, INT nItem)
+{
+  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:
+ * Removes all selection states.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] INT : item index 
+ *
+ * RETURN:
+ *   SUCCCESS : TRUE
+ *   FAILURE : FALSE
+ */
+static VOID LISTVIEW_RemoveSelections(HWND hwnd, INT nFirst, INT nLast)
+{
+  LVITEMA lvItem;
+  INT i;
+
+  lvItem.state = 0;
+  lvItem.stateMask = LVIS_SELECTED;
+
+  for (i = nFirst; i <= nLast; i++)
+  {
+    ListView_SetItemState(hwnd, i, &lvItem);
+  }
+}
+
+/***
+ * DESCRIPTION:
+ * Removes a column.
+ * 
+ * PARAMETER(S):
+ * [IO] HDPA : dynamic pointer array handle
+ * [I] INT : column index (subitem index)
+ *
+ * RETURN:
+ *   SUCCCESS : TRUE
+ *   FAILURE : FALSE
+ */
+static BOOL LISTVIEW_RemoveColumn(HDPA hdpaItems, INT nSubItem)
+{
+  BOOL bResult = TRUE;
+  HDPA hdpaSubItems;
+  INT i;
+
+  for (i = 0; i < hdpaItems->nItemCount; i++)
+  {
+    hdpaSubItems = (HDPA)DPA_GetPtr(hdpaItems, i);
+    if (hdpaSubItems != NULL)
+    {
+      if (LISTVIEW_RemoveSubItem(hdpaSubItems, nSubItem) == FALSE)
+      {
+        bResult = FALSE;
+      }
+    }
+  }
+    
+  return bResult;
+}
+
+/***
+ * DESCRIPTION:
+ * Removes a subitem at a given position.
+ * 
+ * PARAMETER(S):
+ * [IO] HDPA : dynamic pointer array handle
+ * [I] INT : subitem index
+ *
+ * RETURN:
+ *   SUCCCESS : TRUE
+ *   FAILURE : FALSE
+ */
+static BOOL LISTVIEW_RemoveSubItem(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)
+      {
+        /* free string */
+        if ((lpSubItem->pszText != NULL) && 
+            (lpSubItem->pszText != LPSTR_TEXTCALLBACKA))
+        {
+          COMCTL32_Free(lpSubItem->pszText);
+        }
+      
+        /* free item */
+        COMCTL32_Free(lpSubItem);
+
+        /* free dpa memory */
+        if (DPA_DeletePtr(hdpaSubItems, i) == NULL)
+        {
+          return FALSE;
+        }
+      }
+      else if (lpSubItem->iSubItem > nSubItem)
+      {
+        return TRUE;
+      }
+    }
+  }    
+  
+  return TRUE;
+}
+
+/***
+ * DESCRIPTION:
+ * Compares the item information.
+ * 
+ * PARAMETER(S):
+ * [I] LISTVIEW_ITEM *: destination item 
+ * [I] LPLVITEM : source item 
+ *
+ * RETURN:
+ *   SUCCCESS : TRUE (EQUAL)
+ *   FAILURE : FALSE (NOT EQUAL)
+ */
+static UINT LISTVIEW_GetItemChanges(LISTVIEW_ITEM *lpItem, LPLVITEMA lpLVItem)
+{
+  UINT uChanged = 0;
+
+  if ((lpItem != NULL) && (lpLVItem != NULL))
+  {
+    if (lpLVItem->mask & LVIF_STATE)
+    {
+      if ((lpItem->state & lpLVItem->stateMask) != 
+          (lpLVItem->state & lpLVItem->stateMask))
+      {
+        uChanged |= LVIF_STATE; 
+      }
+    }
+    
+    if (lpLVItem->mask & LVIF_IMAGE)
+    {
+      if (lpItem->iImage != lpLVItem->iImage)
+      {
+        uChanged |= LVIF_IMAGE; 
+      }
+    }
+  
+    if (lpLVItem->mask & LVIF_PARAM)
+    {
+      if (lpItem->lParam != lpLVItem->lParam)
+      {
+        uChanged |= LVIF_PARAM; 
+      }
+    }
+    
+    if (lpLVItem->mask & LVIF_INDENT)
+    {
+      if (lpItem->iIndent != lpLVItem->iIndent)
+      {
+        uChanged |= LVIF_INDENT; 
+      }
+    }
+
+    if (lpLVItem->mask & LVIF_TEXT) 
+    {
+      if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA) 
+      {
+        if (lpItem->pszText != LPSTR_TEXTCALLBACKA)
+        {
+          uChanged |= LVIF_TEXT; 
+        }
+      }
+      else
+      {
+        if (lpItem->pszText == LPSTR_TEXTCALLBACKA)
+        {
+          uChanged |= LVIF_TEXT; 
+        }
+      }
+    }
+  }
+
+  return uChanged;
+}
+
+/***
+ * DESCRIPTION:
+ * Initializes item attributes.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [O] LISTVIEW_ITEM *: destination item 
+ * [I] LPLVITEM : source item 
+ *
+ * RETURN:
+ *   SUCCCESS : TRUE
+ *   FAILURE : FALSE
+ */
+static BOOL LISTVIEW_InitItem(HWND hwnd, LISTVIEW_ITEM *lpItem, 
+                                LPLVITEMA lpLVItem)
 {
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-  INT nItemCountPerRow;
-  INT nItemCountPerColumn;
-  INT nLastItem;
-  INT nFirstItem;
-  INT nHScrollPos;
-  INT nVScrollPos;
+  BOOL bResult = FALSE;
 
-  /* retrieve the index of the first visible fully item */
-  nFirstItem = LISTVIEW_GetFirstVisibleItem(hwnd);
-
-  /* nunber of fully visible items per row */
-  nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
-
-  /* nunber of fully visible items per column */
-  nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
-
-  if ((nItemCountPerRow > 0) && (nItemCountPerColumn > 0))
+  if ((lpItem != NULL) && (lpLVItem != NULL))
   {
-    if (lStyle & LVS_LIST)
+    bResult = TRUE;
+    
+    if (lpLVItem->mask & LVIF_STATE)
     {
-      if (lStyle & WS_HSCROLL)
-      {
-        /* last visible item index */
-        nLastItem = nItemCountPerColumn * nItemCountPerRow + nFirstItem - 1;
-        if (nItem > nLastItem)
-        {
-          /* calculate new scroll position based on item index */
-          if (((nItem - nLastItem) % nItemCountPerColumn) == 0)
-            nHScrollPos = (nItem - nLastItem) / nItemCountPerColumn;
-          else
-            nHScrollPos = (nItem - nLastItem) / nItemCountPerColumn + 1;
-          SendMessageA(hwnd, LVM_SCROLL, (WPARAM)nHScrollPos, (LPARAM)0);
-        }
-        else if (nItem < nFirstItem)
-        {
-          /* calculate new scroll position based on item index */
-          if (((nItem - nFirstItem) % nItemCountPerColumn) == 0)
-            nHScrollPos = (nItem - nFirstItem) / nItemCountPerColumn;
-          else
-            nHScrollPos = (nItem - nFirstItem) / nItemCountPerColumn - 1;
-          SendMessageA(hwnd, LVM_SCROLL, (WPARAM)nHScrollPos, (LPARAM)0);
-        }
-      }
+      lpItem->state &= ~lpLVItem->stateMask;
+      lpItem->state |= (lpLVItem->state & lpLVItem->stateMask);
     }
-    else if (lStyle & LVS_REPORT)
+    
+    if (lpLVItem->mask & LVIF_IMAGE)
     {
-      if (lStyle & WS_VSCROLL)
-      {
-        if (nFirstItem > 0)
-        {
-          nLastItem = nItemCountPerColumn + nFirstItem;
-        }
-        else
-{
-          nLastItem = nItemCountPerColumn + nFirstItem - 1;
-        }
-
-        if (nItem > nLastItem)
-        {
-          /* calculate new scroll position based on item index */
-          nVScrollPos = nItem - nLastItem;
-          SendMessageA(hwnd, LVM_SCROLL, (WPARAM)0, (LPARAM)nVScrollPos);
-        }
-        else if (nItem < nFirstItem)
-        {
-          /* calculate new scroll position based on item index */
-          nVScrollPos = nItem - nFirstItem;
-          SendMessageA(hwnd, LVM_SCROLL, (WPARAM)0, (LPARAM)nVScrollPos);
-        }
-      }
+      lpItem->iImage = lpLVItem->iImage;
     }
-    else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON))
+  
+    if (lpLVItem->mask & LVIF_PARAM)
     {
-      if (lStyle & WS_VSCROLL)
-      {
-        /* last visible item index */
-        nLastItem = nItemCountPerColumn * nItemCountPerRow + nFirstItem - 1;
-        if (nItem > nLastItem)
-        {
-          /* calculate new scroll position based on item index */
-          nVScrollPos = (nItem - nLastItem) / nItemCountPerRow + 1;
-          SendMessageA(hwnd, LVM_SCROLL, (WPARAM)0, (LPARAM)nVScrollPos);
-        }
-        else if (nItem < nFirstItem)
-        {
-          /* calculate new scroll position based on item index */
-          nHScrollPos = (nItem - nFirstItem) / nItemCountPerRow - 1;
-          SendMessageA(hwnd, LVM_SCROLL, (WPARAM)0, (LPARAM)nHScrollPos);
-        }
-      }
+      lpItem->lParam = lpLVItem->lParam;
+    }
+    
+    if (lpLVItem->mask & LVIF_INDENT)
+    {
+      lpItem->iIndent = lpLVItem->iIndent;
     }
 
-    /* refresh display */
-    InvalidateRect(hwnd, NULL, FALSE);
-    UpdateWindow(hwnd);
+    if (lpLVItem->mask & LVIF_TEXT) 
+    {
+      if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA) 
+      {
+        if ((lStyle & LVS_SORTASCENDING) || (lStyle & LVS_SORTDESCENDING))
+        {
+          return FALSE;
+        }
 
+        if ((lpItem->pszText != NULL) && 
+            (lpItem->pszText != LPSTR_TEXTCALLBACKA))
+        {
+          COMCTL32_Free(lpItem->pszText);
+        }
+    
+        lpItem->pszText = LPSTR_TEXTCALLBACKA;
+      }
+      else 
+      {
+        if (lpItem->pszText == LPSTR_TEXTCALLBACKA)
+        {
+          lpItem->pszText = NULL;
+        }
+        
+        bResult = Str_SetPtrA(&lpItem->pszText, lpLVItem->pszText);
+      }
+    }
+  }
+
+  return bResult;
 }
+
+/***
+ * DESCRIPTION:
+ * Initializes subitem attributes.
+ *
+ * NOTE: the documentation specifies that the operation fails if the user
+ * tries to set the indent of a subitem.
+ *
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [O] LISTVIEW_SUBITEM *: destination subitem
+ * [I] LPLVITEM : source subitem
+ *
+ * RETURN:
+ *   SUCCCESS : TRUE
+ *   FAILURE : FALSE
+ */
+static BOOL LISTVIEW_InitSubItem(HWND hwnd, LISTVIEW_SUBITEM *lpSubItem, 
+                                   LPLVITEMA lpLVItem)
+{
+  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  BOOL bResult = FALSE;
+  
+  if ((lpSubItem != NULL) && (lpLVItem != NULL))
+  {
+    if (!(lpLVItem->mask & LVIF_INDENT))
+    {
+      bResult = TRUE;
+      ZeroMemory(lpSubItem, sizeof(LISTVIEW_SUBITEM));
+
+      lpSubItem->iSubItem = lpLVItem->iSubItem;
+
+      if (lpLVItem->mask & LVIF_IMAGE)
+      {
+        lpSubItem->iImage = lpLVItem->iImage;
+      }
+      
+      if (lpLVItem->mask & LVIF_TEXT) 
+      {
+        if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA) 
+        {
+          if ((lStyle & LVS_SORTASCENDING) || (lStyle & LVS_SORTDESCENDING))
+          {
+            return FALSE;
+          } 
+
+          if ((lpSubItem->pszText != NULL) && 
+              (lpSubItem->pszText != LPSTR_TEXTCALLBACKA))
+          {
+            COMCTL32_Free(lpSubItem->pszText);
+          }
+    
+          lpSubItem->pszText = LPSTR_TEXTCALLBACKA;
+        }
+        else 
+        {
+          if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA)
+          {
+            lpSubItem->pszText = NULL;
+          }
+        
+          bResult = Str_SetPtrA(&lpSubItem->pszText, lpLVItem->pszText);
+        }
+      }
+    }
+  }
+
+  return bResult;
+}
+
+/***
+ * DESCRIPTION:
+ * Adds a subitem at a given position (column index).
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] LPLVITEM : new subitem atttributes 
+ *
+ * RETURN:
+ *   SUCCESS : TRUE
+ *   FAILURE : FALSE
+ */
+static BOOL LISTVIEW_AddSubItem(HWND hwnd, LPLVITEMA lpLVItem)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  BOOL bResult = FALSE;
+  HDPA hdpaSubItems;
+  LISTVIEW_SUBITEM *lpSubItem = NULL;
+  INT nPosition, nItem;
+
+  if (lpLVItem != NULL)
+  {
+    hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
+    if (hdpaSubItems != NULL)
+    {
+      lpSubItem = (LISTVIEW_SUBITEM *)COMCTL32_Alloc(sizeof(LISTVIEW_SUBITEM));
+      if (lpSubItem != NULL)
+      {
+        if (LISTVIEW_InitSubItem(hwnd, lpSubItem, lpLVItem) == TRUE)
+        {
+          nPosition = LISTVIEW_FindInsertPosition(hdpaSubItems, 
+                                                  lpSubItem->iSubItem);
+          nItem = DPA_InsertPtr(hdpaSubItems, nPosition, lpSubItem);
+          if (nItem != -1)
+          {
+            bResult = TRUE;
+          }            
+        }
+      }
+    }
+  }
+  
+  /* cleanup if unsuccessful */   
+  if ((bResult == FALSE) && (lpSubItem != NULL))
+  {
+    COMCTL32_Free(lpSubItem);
+  }
+  
+  return bResult;
+}
+
+/***
+ * DESCRIPTION:
+ * Finds the dpa insert position (array index).
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] INT : subitem index
+ *
+ * RETURN:
+ *   SUCCESS : TRUE
+ *   FAILURE : FALSE
+ */
+static INT LISTVIEW_FindInsertPosition(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 i;
+      }
+    } 
+  }
+
+  return hdpaSubItems->nItemCount;
+}
+
+/***
+ * DESCRIPTION:
+ * Retrieves a listview subitem at a given position (column index).
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] INT : subitem index
+ *
+ * RETURN:
+ *   SUCCESS : TRUE
+ *   FAILURE : FALSE
+ */
+static LISTVIEW_SUBITEM* LISTVIEW_GetSubItem(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;
+      }
+      else if (lpSubItem->iSubItem > nSubItem)
+      {
+        return NULL;
+      }  
+    }
+  }
+  
+  return NULL;
+}
+
+/***
+ * DESCRIPTION:
+ * Sets item attributes.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] LPLVITEM : new item atttributes 
+ *
+ * RETURN:
+ *   SUCCESS : TRUE
+ *   FAILURE : FALSE
+ */
+static BOOL LISTVIEW_SetItem(HWND hwnd, LPLVITEMA lpLVItem)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  BOOL bResult = FALSE;
+  HDPA hdpaSubItems;
+  LISTVIEW_ITEM *lpItem;
+  NMLISTVIEW nmlv;
+  UINT uChanged;
+  LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
+
+  if (lpLVItem != NULL)
+  {
+    if (lpLVItem->iSubItem == 0)
+    {
+      hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
+      if (hdpaSubItems != NULL)
+      {
+        lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, lpLVItem->iSubItem);
+        if (lpItem != NULL)
+        {
+          ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
+          nmlv.hdr.hwndFrom = hwnd;
+          nmlv.hdr.idFrom = lCtrlId;
+          nmlv.hdr.code = LVN_ITEMCHANGING;
+          nmlv.lParam = lpItem->lParam;
+          uChanged = LISTVIEW_GetItemChanges(lpItem, lpLVItem);
+          if (uChanged != 0)
+          {
+            if (uChanged & LVIF_STATE)
+            {
+              nmlv.uNewState = lpLVItem->state & lpLVItem->stateMask;
+              nmlv.uOldState = lpItem->state & lpLVItem->stateMask;
+            }
+
+            nmlv.uChanged = uChanged;
+            nmlv.iItem = lpLVItem->iItem;
+            nmlv.lParam = lpItem->lParam;
+            /* send LVN_ITEMCHANGING notification */
+            ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
+
+            /* copy information */
+            bResult = LISTVIEW_InitItem(hwnd, lpItem, lpLVItem);
+
+            /* send LVN_ITEMCHANGED notification */
+            nmlv.hdr.code = LVN_ITEMCHANGED;
+            ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
+          }
+          else
+          {
+            bResult = TRUE;
+          }
+
+          InvalidateRect(hwnd, NULL, FALSE);
+        }
+      }
+    }
+  }
+
+  return bResult;
+}
+
+/***
+ * DESCRIPTION:
+ * Sets subitem attributes.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] LPLVITEM : new subitem atttributes 
+ *
+ * RETURN:
+ *   SUCCESS : TRUE
+ *   FAILURE : FALSE
+ */
+static BOOL LISTVIEW_SetSubItem(HWND hwnd, LPLVITEMA lpLVItem)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  BOOL bResult = FALSE;
+  HDPA hdpaSubItems;
+  LISTVIEW_SUBITEM *lpSubItem;
+
+  if (lpLVItem != NULL)
+  {
+    if (lpLVItem->iSubItem > 0)
+    {
+      hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
+      if (hdpaSubItems != NULL)
+      {
+        /* set subitem only if column is present */
+        if (Header_GetItemCount(infoPtr->hwndHeader) > lpLVItem->iSubItem)
+        {
+          lpSubItem = LISTVIEW_GetSubItem(hdpaSubItems, lpLVItem->iSubItem);
+          if (lpSubItem != NULL)
+          {
+            bResult = LISTVIEW_InitSubItem(hwnd, lpSubItem, lpLVItem);
+          }
+          else
+          {
+            bResult = LISTVIEW_AddSubItem(hwnd, lpLVItem);
+          }
+          
+          InvalidateRect(hwnd, NULL, FALSE);
+        } 
+      }
+    }
+  }
+
+  return bResult;
 }
 
 /***
@@ -145,55 +1316,32 @@
  * Retrieves the index of the item at coordinate (0, 0) of the client area.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  *
  * RETURN:
  * item index
  */
-static INT LISTVIEW_GetFirstVisibleItem(HWND hwnd)
+static INT LISTVIEW_GetTopIndex(HWND hwnd)
 {
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *) GetWindowLongA(hwnd, 0);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-  INT nItemCountPerRow;
-  INT nItemCountPerColumn;
-  INT nMinRange;
-  INT nMaxRange;
-  INT nHScrollPos;
-/*  INT32 nVScrollPos; */
   INT nItem = 0;
 
-  /* get number of items per column */
-  nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
-
-  /* get number of fully visble items per row */ 
-  nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
-
-  if ((nItemCountPerRow > 0) && (nItemCountPerColumn > 0))
+  switch (LVS_TYPEMASK & lStyle)
   {
-    if (lStyle & LVS_LIST)
+  case LVS_LIST:
+    if (lStyle & WS_HSCROLL)
     {
-      if (lStyle & WS_HSCROLL)
-      {
-        GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
-        nHScrollPos = GetScrollPos(hwnd, SB_HORZ);
-        if (nMinRange < nHScrollPos)
-        {
-          nItem = ((nHScrollPos - nMinRange) * nItemCountPerColumn * 
-                   nItemCountPerRow);
-        }
-      }
+      nItem = GetScrollPos(hwnd, SB_HORZ) * infoPtr->nCountPerColumn;
     }
-    else if (lStyle & LVS_REPORT)
+    break;
+
+  case LVS_REPORT:
+    if (lStyle & WS_VSCROLL)
     {
-      /* TO DO */
+      nItem = GetScrollPos(hwnd, SB_VERT);
     }
-    else if (lStyle & LVS_SMALLICON)
-    {
-      /* TO DO */
-    }
-    else if (lStyle & LVS_ICON)
-    {
-      /* TO DO */
-    }
+    break;
   }
 
   return nItem;
@@ -201,525 +1349,313 @@
 
 /***
  * DESCRIPTION:
- * Retrieves the number of items per row. In other words, the number 
- * visible display columns.
+ * Sets scrollbar(s). 
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  *
  * RETURN:
- * Number of items per row.
+ *   TRUE if scrollbars were added, modified or removed.
  */
-static INT LISTVIEW_GetItemCountPerRow(HWND hwnd)
+static VOID LISTVIEW_SetVScroll(HWND hwnd)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-  INT nItemCountPerRow = 0;
+  INT nScrollPos;
+  INT nMaxRange;
 
-  if (infoPtr->nWidth > 0)
+  switch (LVS_TYPEMASK & lStyle)
   {
-    if (lStyle & LVS_LIST)
-    {
-      if (infoPtr->nColumnWidth > 0)
-      {
-        nItemCountPerRow = infoPtr->nWidth / infoPtr->nColumnWidth;
-        if (nItemCountPerRow == 0)
-          nItemCountPerRow = 1;
-      }
-    }
-    else if (lStyle & LVS_REPORT)
-    {
-      /* TO DO */
-    }
-    else if (lStyle & LVS_SMALLICON)
-    {
-      /* TO DO */
-    }
-    else if (lStyle & LVS_ICON)
-    {
-      /* TO DO */
-    }
+  case LVS_REPORT:
+    nMaxRange = GETITEMCOUNT(infoPtr) - infoPtr->nCountPerColumn;
+    SetScrollRange(hwnd, SB_VERT, 0, nMaxRange, FALSE);
+    nScrollPos = ListView_GetTopIndex(hwnd);
+    SetScrollPos(hwnd, SB_VERT, nScrollPos, TRUE);
+    break;
+    
+  default:
+    /* TO DO */
   }
-
-  return nItemCountPerRow; 
 }
 
-/***
- * DESCRIPTION:
- * Retrieves the number of items that can be displayed vertically in   
- * the listview.
- * 
- * PARAMETER(S):
- * [I] HWND32 : window handle
- *
- * RETURN:
- * Number of items per column.
- */
-static INT LISTVIEW_GetItemCountPerColumn(HWND hwnd)
+static VOID LISTVIEW_SetHScroll(HWND hwnd)
 {
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+/*   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); */
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-  INT nItemCountPerColumn = 0;
-  
-  if (infoPtr->nHeight > 0)
+/*   INT nScrollPos; */
+/*   INT nMaxRange; */
+
+  switch (LVS_TYPEMASK & lStyle)
   {
-    if (lStyle & LVS_LIST)
-    {
-      if (infoPtr->nItemHeight > 0)
-        nItemCountPerColumn = infoPtr->nHeight / infoPtr->nItemHeight;
-    }
-    else if (lStyle & LVS_REPORT)
-    {
-      /* TO DO */
-    }
-    else if (lStyle & LVS_SMALLICON)
-    {
-      /* TO DO */
-    }
-    else if (lStyle & LVS_ICON)
-    {
-      /* TO DO */
-    }
+  case LVS_REPORT:
+    /* TO DO */
+    break;
+
+  default:
+    /* TO DO */
   }
-
-  return nItemCountPerColumn;
 }
 
-/***
- * DESCRIPTION:
- * Retrieves the number of columns needed to display  
- * all the items in listview.
- * 
- * PARAMETER(S):
- * [I] HWND32 : window handle
- *
- * RETURN:
- * Number of columns.
- */
-static INT LISTVIEW_GetColumnCount(HWND hwnd)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle  = GetWindowLongA(hwnd, GWL_STYLE);
-  INT nColumnCount = 0;
-  INT nItemCountPerColumn;
-
-  nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
-
- if ((infoPtr->nItemCount > 0) && (nItemCountPerColumn > 0))
- {
-   if (lStyle & LVS_LIST)
-   {
-     if ((infoPtr->nItemCount % nItemCountPerColumn) == 0)
-     {
-       nColumnCount = infoPtr->nItemCount / nItemCountPerColumn ;
-     }
-     else
-     {
-       nColumnCount = infoPtr->nItemCount / nItemCountPerColumn + 1;
-     }
-   }
-   else if (lStyle & LVS_REPORT)
-   {
-     /* TO DO */
-   }
-   else if (lStyle & LVS_SMALLICON)
-   {
-     /* TO DO */
-   }
-   else if (lStyle & LVS_ICON)
-   {
-     /* TO DO */
-   }
- }
-
-  return nColumnCount;
-}
-
-/***
- * DESCRIPTION:
- * Sets the scrolling parameters.
- * 
- * PARAMETER(S):
- * [I] HWND32 : window handle
- *
- * RETURN:
- * None
- */
 static VOID LISTVIEW_SetScroll(HWND hwnd)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-  INT nColumnCount;
-  INT nItemCountPerRow;
-  INT nItemCountPerColumn;
-  INT nMinRange, nMaxRange;
-  INT nHScrollPos;
-/*   INT32 nVScrollPos; */
+  INT nHiddenItemCount;
+  INT nScrollPos;
+  INT nMaxRange;
+  INT nCountPerPage;
+  RECT rc;
+  BOOL bHScroll = FALSE;
+  BOOL bVScroll = FALSE;
+  INT nHeaderWidth = 0;
+  INT nItemCount;
+  INT i;
 
-  nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
-  nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
-
-  if ((nItemCountPerColumn > 0) && (nItemCountPerRow > 0))
+  switch (LVS_TYPEMASK & lStyle)
   {
-    if (lStyle & LVS_LIST)
+  case LVS_LIST:
+    nCountPerPage = infoPtr->nCountPerRow * infoPtr->nCountPerColumn;
+    if (nCountPerPage < GETITEMCOUNT(infoPtr))
     {
-      /* get number of columns needed to display all the listview items */
-      nColumnCount = LISTVIEW_GetColumnCount(hwnd);      
-      if (nColumnCount > 0) 
+      /* add scrollbar if not already present */
+      if (!(lStyle & WS_HSCROLL))
       {
-        if (nColumnCount > nItemCountPerRow)
-        {
-          /* add scrollbar if not already present */
-          if (!(lStyle & WS_HSCROLL))
-          {
-            /* display scrollbar */
-            ShowScrollBar(hwnd, SB_HORZ, TRUE);
-        
-            /* set scrollbar range and position */
-            nMaxRange = nColumnCount - nItemCountPerRow;
-            SetScrollRange(hwnd, SB_HORZ, 0, nMaxRange, FALSE);
-            SetScrollPos(hwnd, SB_HORZ, 0, TRUE);
-          }
-          else
-          {
-            nHScrollPos = GetScrollPos(hwnd, SB_HORZ);
-            GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
-            if (nMaxRange != nColumnCount - nItemCountPerRow)
-            {
-              nMaxRange = nColumnCount - nItemCountPerRow;
-              SetScrollRange(hwnd, SB_HORZ, nMinRange, nMaxRange, FALSE);
+        ShowScrollBar(hwnd, SB_HORZ, TRUE);
+      }
 
-              if (nHScrollPos > nMaxRange)
-                nHScrollPos = nMaxRange;
+      /* calculate new scrollbar range */
+      nHiddenItemCount = GETITEMCOUNT(infoPtr) - nCountPerPage;
+      if ((nHiddenItemCount % infoPtr->nCountPerColumn) == 0)
+      {
+        nMaxRange = nHiddenItemCount / infoPtr->nCountPerColumn;
+      }
+      else
+      {
+        nMaxRange = nHiddenItemCount / infoPtr->nCountPerColumn + 1;
+      }
         
-              SetScrollPos(hwnd, SB_HORZ, nHScrollPos, TRUE);
-            }
-          }
-          
-          /* refresh the client area */
-          InvalidateRect(hwnd,NULL, TRUE);
-          UpdateWindow(hwnd);
-        }
-        else
-        {
-          /* remove scrollbar if present */
-          if (lStyle & WS_HSCROLL)
-          {
-            /* hide scrollbar */
-            ShowScrollBar(hwnd, SB_HORZ, FALSE);
-
-            /* refresh the client area */
-            InvalidateRect(hwnd,NULL, TRUE);
-            UpdateWindow(hwnd);
-          }
-        }
+      SetScrollRange(hwnd, SB_HORZ, 0, nMaxRange, FALSE);
+      nScrollPos = ListView_GetTopIndex(hwnd) / infoPtr->nCountPerColumn;
+      SetScrollPos(hwnd, SB_HORZ, nScrollPos, TRUE);
+    }
+    else
+    {
+      /* remove scrollbar if present */
+      if (lStyle & WS_HSCROLL)
+      {
+        /* hide scrollbar */
+        ShowScrollBar(hwnd, SB_HORZ, FALSE);
       }
     }
-    else if (lStyle & LVS_REPORT) 
+    break;
+    
+  case LVS_REPORT:
+    nItemCount = Header_GetItemCount(infoPtr->hwndHeader);
+    for (i = 0; i < nItemCount; i++)
     {
-      HDLAYOUT hl;
-      WINDOWPOS wp;
-      RECT rc;
-        
-      rc.top = 0;
-      rc.left = 0;
-      rc.right = infoPtr->nWidth;
-      rc.bottom = infoPtr->nHeight;
+      if (Header_GetItemRect(infoPtr->hwndHeader, i, &rc) != 0)
+      {
+        nHeaderWidth += (rc.right - rc.left);
+      }
+    }
 
-      hl.prc = &rc;
-      hl.pwpos = &wp;
-      SendMessageA(infoPtr->hwndHeader, HDM_LAYOUT, 0, (LPARAM)&hl);
-      
-      SetWindowPos(infoPtr->hwndHeader, hwnd,
-                     wp.x, wp.y, wp.cx, wp.cy, wp.flags);
-      
-/*       infoPtr->rcList.top += wp.cy; */
-    }
-    else if (lStyle & LVS_SMALLICON) 
+    if (nHeaderWidth > (infoPtr->rcList.right - infoPtr->rcList.left))
     {
-      /* TO DO */
+      bHScroll = TRUE;
+      
+      /* add horizontal scrollbar if not present */
+      if (!(lStyle & WS_HSCROLL))
+      {
+        /* display scrollbar */
+        ShowScrollBar(hwnd, SB_HORZ, TRUE);
+      }
     }
-    else if (lStyle & LVS_ICON) 
+    else
     {
-      /* TO DO */
+      /* remove scrollbar if present */
+      if (lStyle & WS_HSCROLL)
+      {
+        /* hide scrollbar */
+        ShowScrollBar(hwnd, SB_HORZ, FALSE);
+      }
+    }
+  
+    if (infoPtr->nCountPerColumn < GETITEMCOUNT(infoPtr))
+    {
+      bVScroll = TRUE;
+
+      /* add scrollbar if not already present */
+      if (!(lStyle & WS_VSCROLL))
+      {
+        /* display scrollbar */
+        ShowScrollBar(hwnd, SB_VERT, TRUE);
+      }
+    }
+    else
+    {
+      /* remove scrollbar if present */
+      if (lStyle & WS_VSCROLL)
+      {
+        /* hide scrollbar */
+        ShowScrollBar(hwnd, SB_VERT, FALSE);
+      }
+    }
+    break;
+
+  default:
+    /* TO DO */
+  }
+
+  /* set range and position */
+  GetClientRect(hwnd, &rc);
+  if ((bHScroll == TRUE) || (bVScroll == TRUE))
+  {
+    LISTVIEW_SetSize(hwnd, lStyle, rc.right, rc.bottom);
+    LISTVIEW_SetViewInfo(hwnd);
+    if (bHScroll == TRUE)
+    {
+      LISTVIEW_SetHScroll(hwnd);
+    }
+
+    if (bVScroll == TRUE)
+    {
+      LISTVIEW_SetVScroll(hwnd);
     }
   }
 }
 
 /***
  * DESCRIPTION:
- * Modifies the state (selected and focused) of the listview items.
+ * Draws a subitem.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : focused item index
- * [I] BOOL32 : flag for determining weither the control keys are used or not
- * [I] BOOL32 : flag for determining the input type (mouse or keyboard)
+ * [I] HDC : device context handle
+ * [I] LISTVIEW_INFO * : listview information
+ * [I] LISTVIEW_SUBITEM * : subitem
+ * [I] RECT * : clipping rectangle
  *
  * RETURN:
  * None
  */
-static VOID LISTVIEW_SetItemStates(HWND hwnd, INT nFocusedItem, 
-                                   BOOL bVirtualKeys, BOOL bMouseInput)
+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);
-  WORD wShift = HIWORD(GetKeyState(VK_SHIFT));
-  WORD wCtrl = HIWORD(GetKeyState(VK_CONTROL));
-  INT i;
-  LVITEMA lvItem;
+  CHAR szDispText[DISP_TEXT_SIZE];
+  LPSTR pszDispText = NULL;
 
-  /* initialize memory */
-  ZeroMemory(&lvItem, sizeof(LVITEMA));
-    
-  if (wShift && (bVirtualKeys == TRUE))
+  /* set item colors */
+  SetBkColor(hdc, infoPtr->clrTextBk);
+  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, lprc->left + 10, lprc->top, ETO_OPAQUE|ETO_CLIPPED, 
+              lprc, pszDispText, lstrlenA(pszDispText), NULL);
+}
+
+/***
+ * DESCRIPTION:
+ * Draws an item.
+ * 
+ * PARAMETER(S):
+ * [I] HDC : device context handle
+ * [I] LISTVIEW_INFO * : listview information
+ * [I] LISTVIEW_ITEM * : item
+ * [I] RECT * : clipping rectangle
+ *
+ * RETURN:
+ * None
+ */
+static VOID LISTVIEW_DrawItem(HWND hwnd, HDC hdc, LISTVIEW_ITEM *lpItem, 
+                              INT nItem, RECT *lprc)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); 
+  BOOL bSelected;
+  INT nLabelWidth;
+  INT nImage;
+  CHAR szDispText[DISP_TEXT_SIZE];
+  LPSTR pszDispText = NULL;
+  UINT uState;
+
+  pszDispText = szDispText;
+  LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, &nImage, &uState, &pszDispText,
+                           DISP_TEXT_SIZE);
+  if (uState & LVIS_SELECTED)
   {
-    /* reset the selected and focused states of all the items */
-    lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
-    lvItem.state = 0;
-    SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&lvItem);
+    bSelected = TRUE;
 
-    if (infoPtr->nSelectionMark > nFocusedItem)
-    {
-      for (i = infoPtr->nSelectionMark; i > nFocusedItem; i--)
-      {
-        /* select items */
-        lvItem.stateMask = LVIS_SELECTED;
-        lvItem.state = LVIS_SELECTED;
-        SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)i, (LPARAM)&lvItem);
-      }
-    }
-    else
-    {
-      for (i = infoPtr->nSelectionMark; i < nFocusedItem; i++)
-      {
-        /* select items */
-        lvItem.stateMask = LVIS_SELECTED;
-        lvItem.state = LVIS_SELECTED;
-        SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)i, (LPARAM)&lvItem);
-      }
-    }
-
-    /* select anf focus item */
-    lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
-    lvItem.state = LVIS_SELECTED | LVIS_FOCUSED;
-    SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)i, (LPARAM)&lvItem);
+    /* set item colors */ 
+    SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
+    SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
+    
+    /* set raster mode */
+    SetROP2(hdc, R2_XORPEN);
   }
   else
   {
-    if (wCtrl && (bVirtualKeys == TRUE))
-    {
-      /* make sure the focus is lost */
-      lvItem.stateMask = LVIS_FOCUSED;
-      lvItem.state = 0;
-      SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&lvItem);
+    bSelected = FALSE;
 
-      if (bMouseInput == TRUE)
-      {
-        if (SendMessageA(hwnd, LVM_GETITEMSTATE, (WPARAM)nFocusedItem, 
-                           (LPARAM)LVIS_SELECTED) & LVIS_SELECTED)
-        {
-          /* focus and unselect (toggle selection) */
-          lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
-          lvItem.state = LVIS_FOCUSED;
-          SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)nFocusedItem, 
-                         (LPARAM)&lvItem);
-        }
-        else
-        {
-          /* select and focus */
-          lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
-          lvItem.state = LVIS_SELECTED | LVIS_FOCUSED;
-          SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)nFocusedItem, 
-                         (LPARAM)&lvItem);
-        }
-        
-        /* set the group selection start position */
-        infoPtr->nSelectionMark = nFocusedItem;
-      }
-      else
-      {
-        /* focus */
-        lvItem.stateMask = LVIS_FOCUSED;
-        lvItem.state = LVIS_FOCUSED;
-        SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)nFocusedItem, 
-                       (LPARAM)&lvItem);
-      }
+    /* 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 == TRUE)
+    {
+      ImageList_Draw(infoPtr->himlState, uState >> 12, hdc, lprc->left, 
+                     lprc->top, ILD_SELECTED);
     }
     else
     {
-      /* clear selection and focus for all the items */
-      lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
-      lvItem.state = 0;
-      SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&lvItem);
-
-      /* set select and focus for this particular item */
-      lvItem.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
-      lvItem.state = LVIS_FOCUSED | LVIS_SELECTED;
-      SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)nFocusedItem, 
-                     (LPARAM)&lvItem);
-
-      /* set the new group selection start position */
-      infoPtr->nSelectionMark = nFocusedItem;
+      ImageList_Draw(infoPtr->himlState, uState >> 12, hdc, lprc->left, 
+                     lprc->top, ILD_NORMAL);
     }
+    
+    lprc->left += infoPtr->iconSize.cx; 
   }
-}
-
-/***
- * DESCRIPTION:
- * Draws listview items when in list display maode.
- * 
- * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] HDC32 : device context handle 
- *
- * RETURN:
- * None
- */
-static VOID LISTVIEW_RefreshList(HWND hwnd, HDC hdc)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-    LISTVIEW_ITEM *lpItem;
-  HFONT hOldFont;
-  HPEN hPen, hOldPen;
-  INT nItemCountPerColumn;
-  INT nItemCountPerRow;
-  INT nSmallIconWidth;
-  SIZE labelSize;
-  INT nDrawPosX = 0;
-  INT nDrawPosY = 0;
-  BOOL bSelected;
-  RECT rcBoundingBox;
-  COLORREF clrHighlight;
-  COLORREF clrHighlightText;
-  INT i;
-  INT nColumn = 0;
-  INT nRow;
-  INT j;
-
-  /* get number of items per column */
-  nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
-
-  /* get number of items per row */
-  nItemCountPerRow = LISTVIEW_GetItemCountPerColumn(hwnd);
   
-  if ((nItemCountPerColumn > 0) && (nItemCountPerRow > 0))
+  /* small icons */
+  if (infoPtr->himlSmall != NULL)
   {
-     /* select font */
-    hOldFont = SelectObject(hdc, infoPtr->hFont);
-
-    /* inititialize system dependent information */
-    clrHighlight = GetSysColor(COLOR_HIGHLIGHT);
-    clrHighlightText = GetSysColor(COLOR_HIGHLIGHTTEXT);
-    nSmallIconWidth = GetSystemMetrics(SM_CXSMICON);  
-
-    /* select transparent brush (for drawing the focus box) */
-    SelectObject(hdc, GetStockObject(NULL_BRUSH)); 
-
-    /* select the doted pen (for drawing the focus box) */
-    hPen = CreatePen(PS_DOT, 1, 0);
-    hOldPen = SelectObject(hdc, hPen);
-
-    /* get starting index */
-    i = LISTVIEW_GetFirstVisibleItem(hwnd);
-    
-    /* DRAW ITEMS */
-    for (j = 0; i < infoPtr->nItemCount; i++, j++)
+    if (bSelected == TRUE)
     {
-      /* set draw position for current item */
-      nRow = j % nItemCountPerColumn;
-      nColumn = j / nItemCountPerColumn;
-      if (nRow == 0)
-        nDrawPosY = 0;
-      else
-        nDrawPosY += infoPtr->nItemHeight;
-
-      nDrawPosX = nColumn * infoPtr->nColumnWidth;
-    
-      /* get item */
-      lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, i);
-      if (lpItem != NULL)
-      {
-        if (lpItem->state & LVIS_SELECTED)
-        {
-          bSelected = TRUE;
-        
-          /* set item colors */ 
-          SetBkColor(hdc, clrHighlight);
-          SetTextColor(hdc, clrHighlightText);
-
-          /* 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);
-        }
-
-        /* state images */
-        if (infoPtr->himlState != NULL)
-        {
-          /* right shift 12 bits to obtain index in image list */
-          if (bSelected == TRUE)
-            ImageList_Draw(infoPtr->himlState, lpItem->state >> 12, hdc, 
-                           nDrawPosX, nDrawPosY, ILD_SELECTED);
-          else
-            ImageList_Draw(infoPtr->himlState, lpItem->state >> 12, hdc, 
-                           nDrawPosX, nDrawPosY, ILD_NORMAL);
-        
-          nDrawPosX += nSmallIconWidth; 
-        }
-
-        /* small icons */
-        if (infoPtr->himlSmall != NULL)
-        {
-          if (bSelected == TRUE)
-            ImageList_Draw(infoPtr->himlSmall, lpItem->iImage, hdc, nDrawPosX, 
-                           nDrawPosY, ILD_SELECTED);
-          else
-            ImageList_Draw(infoPtr->himlSmall, lpItem->iImage, hdc, nDrawPosX, 
-                           nDrawPosY, ILD_NORMAL);
-        
-          nDrawPosX += nSmallIconWidth; 
-        }
-
-        /* get string size (in pixels) */
-        GetTextExtentPoint32A(hdc, lpItem->pszText, 
-                              lstrlenA(lpItem->pszText), &labelSize);
-
-        /* define a bounding box */
-        rcBoundingBox.left = nDrawPosX;
-        rcBoundingBox.top = nDrawPosY;
-
-        /* 2 pixels for padding purposes */
-        rcBoundingBox.right = nDrawPosX + labelSize.cx + 2;
-
-        /* padding already included in infoPtr->nItemHeight */
-        rcBoundingBox.bottom = nDrawPosY + infoPtr->nItemHeight;
-      
-        /* draw text */  
-        ExtTextOutA(hdc, nDrawPosX + 1, nDrawPosY+ 1, 
-                      ETO_OPAQUE|ETO_CLIPPED, &rcBoundingBox, 
-                      lpItem->pszText, lstrlenA(lpItem->pszText), NULL);
-      
-        if (lpItem->state & LVIS_FOCUSED)
-          Rectangle(hdc, rcBoundingBox.left, rcBoundingBox.top, 
-                      rcBoundingBox.right, rcBoundingBox.bottom); 
-      }
+      ImageList_Draw(infoPtr->himlSmall, nImage, hdc, lprc->left, 
+                     lprc->top, ILD_SELECTED);
     }
+    else
+    {
+      ImageList_Draw(infoPtr->himlSmall, nImage, hdc, lprc->left, 
+                     lprc->top, ILD_NORMAL);
+    }
+    
+    lprc->left += infoPtr->iconSize.cx; 
+  }
 
-    /* unselect objects */
-    SelectObject(hdc, hOldFont);
-    SelectObject(hdc, hOldPen);
+  nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText);
+  if (lprc->left + nLabelWidth < lprc->right)
+  {
+    lprc->right = lprc->left + nLabelWidth;
+  }
 
-    /* delete pen */
-    DeleteObject(hPen);
+  /* draw text */  
+  ExtTextOutA(hdc, lprc->left + 1, lprc->top + 1, ETO_OPAQUE|ETO_CLIPPED, 
+              lprc, pszDispText, lstrlenA(pszDispText), NULL);
+        
+  if (lpItem->state & LVIS_FOCUSED)
+  {
+    Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom); 
   }
 }
 
@@ -728,15 +1664,152 @@
  * Draws listview items when in report display mode.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] HDC32 : device context handle 
+ * [I] HWND : window handle
+ * [I] HDC : device context handle 
  *
  * RETURN:
  * None
  */
 static VOID LISTVIEW_RefreshReport(HWND hwnd, HDC hdc)
 {
-  /* TO DO */
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd,0);
+  INT nDrawPosY = infoPtr->rcList.top;
+  LISTVIEW_ITEM *lpItem;
+  LISTVIEW_SUBITEM *lpSubItem = NULL;
+  INT nColumnCount;
+  HDPA hdpaSubItems;
+  RECT rc;
+  INT  j, k;
+  INT nItem;
+  INT nLast;
+  BOOL bNeedSubItem = TRUE;
+
+  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)
+      {
+        Header_GetItemRect(infoPtr->hwndHeader, 0, &rc);
+        rc.top = nDrawPosY;
+        rc.bottom = rc.top + infoPtr->nItemHeight;
+        
+        /* draw state icon + icon + text */
+        LISTVIEW_DrawItem(hwnd, hdc, lpItem, nItem, &rc);
+      }
+
+      nColumnCount = Header_GetItemCount(infoPtr->hwndHeader);
+      for (k = 1, j = 1; j < nColumnCount; j++)
+      {
+        Header_GetItemRect(infoPtr->hwndHeader, j, &rc);
+        rc.top = nDrawPosY;
+        rc.bottom = rc.top + infoPtr->nItemHeight;
+
+        if (k < hdpaSubItems->nItemCount)
+        {
+          if (bNeedSubItem == TRUE)
+          {
+            lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, k);
+            k++;
+          }
+
+          if (lpSubItem != NULL)
+          {
+            if (lpSubItem->iSubItem == j)
+            {
+              LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, lpSubItem,
+                                   j, &rc);
+              bNeedSubItem = TRUE;
+            }
+            else
+            {
+              LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j, 
+                                   &rc);
+              bNeedSubItem = FALSE;
+            }
+          }
+          else
+          {
+            LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j, 
+                                 &rc);
+            bNeedSubItem = TRUE;
+          }
+        }
+        else
+        {
+          LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j, &rc);
+        }
+      }
+    }
+
+    nDrawPosY += infoPtr->nItemHeight;
+    nItem++;
+  }
+}
+
+/***
+ * 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);
+  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->nColumnWidth == 0)
+    {
+      nColumnCount = infoPtr->rcList.right / infoPtr->nColumnWidth;
+    }
+    else
+    {
+      nColumnCount = infoPtr->rcList.right / infoPtr->nColumnWidth + 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->nColumnWidth;
+            rc.bottom = rc.top + infoPtr->nItemHeight;
+            rc.right = rc.left + infoPtr->nColumnWidth;
+
+            /* draw state icon + icon + text */
+            LISTVIEW_DrawItem(hwnd, hdc,  lpItem, nItem, &rc);
+          }
+        }
+ 
+        nItem++;
+        j++;
+      }
+    }
+  }
 }
 
 /***
@@ -744,15 +1817,46 @@
  * Draws listview items when in small icon display mode.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] HDC32 : device context handle 
+ * [I] HWND : window handle
+ * [I] HDC : device context handle 
  *
  * RETURN:
  * None
  */
 static VOID LISTVIEW_RefreshSmallIcon(HWND hwnd, HDC hdc)
 {
-  /* TO DO */
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  LISTVIEW_ITEM *lpItem;
+  HDPA hdpaSubItems;
+  RECT rc;
+  INT i, j;
+  INT nItem = ListView_GetTopIndex(hwnd);
+
+  for (i = 0; i < infoPtr->nCountPerColumn; i++)
+  {
+    j = 0;
+    while ((nItem < GETITEMCOUNT(infoPtr)) && (j < infoPtr->nCountPerRow))
+    {
+      hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
+      if (hdpaSubItems != NULL)
+      {
+        lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
+        if (lpItem != NULL)
+        {
+          rc.top = i * infoPtr->nItemHeight;
+          rc.left = j * infoPtr->nColumnWidth;
+          rc.bottom = rc.top + infoPtr->nItemHeight;
+          rc.right = rc.left + infoPtr->nColumnWidth;
+
+          /* draw state icon + icon + text */
+          LISTVIEW_DrawItem(hwnd, hdc,  lpItem, nItem, &rc);
+        }
+      }
+ 
+      nItem++;
+      j++;
+    }
+  }
 }
 
 /***
@@ -760,8 +1864,8 @@
  * Draws listview items when in icon display mode.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] HDC32 : device context handle 
+ * [I] HWND : window handle
+ * [I] HDC : device context handle 
  *
  * RETURN:
  * None
@@ -776,32 +1880,50 @@
  * Draws listview items.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] HDC32 : device context handle 
+ * [I] HWND : window handle
+ * [I] HDC : device context handle 
  *
  * RETURN:
- * None
+ * NoneX
  */
 static VOID LISTVIEW_Refresh(HWND hwnd, HDC hdc)
 {
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-  
-  if (lStyle & LVS_LIST)
+  HFONT hOldFont;
+  HPEN hPen, hOldPen;
+
+  /* select font */
+  hOldFont = SelectObject(hdc, infoPtr->hFont);
+
+  /* select the doted pen (for drawing the focus box) */
+  hPen = CreatePen(PS_DOT, 1, 0);
+  hOldPen = SelectObject(hdc, hPen);
+
+  /* select transparent brush (for drawing the focus box) */
+  SelectObject(hdc, GetStockObject(NULL_BRUSH)); 
+
+  switch (LVS_TYPEMASK & lStyle)
   {
-    LISTVIEW_RefreshList(hwnd, hdc);
-  }
-  else if (lStyle & LVS_REPORT)
-  {
+  case LVS_LIST:
+    LISTVIEW_RefreshList(hwnd, hdc); 
+    break;
+  case LVS_REPORT:
     LISTVIEW_RefreshReport(hwnd, hdc);
-  }
-  else if (lStyle & LVS_SMALLICON)
-  {
+    break;
+  case LVS_SMALLICON:
     LISTVIEW_RefreshSmallIcon(hwnd, hdc);
-  }
-  else if (lStyle & LVS_ICON)
-  {
+    break;
+  case LVS_ICON:
     LISTVIEW_RefreshIcon(hwnd, hdc);
   }
+
+  /* unselect objects */
+  SelectObject(hdc, hOldFont);
+  SelectObject(hdc, hOldPen);
+  
+  /* delete pen */
+  DeleteObject(hPen);
 }
 
 
@@ -810,10 +1932,10 @@
  * Calculates the approximate width and height of a given number of items.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : number of items
- * [I] INT32 : width
- * [I] INT32 : height
+ * [I] HWND : window handle
+ * [I] INT : number of items
+ * [I] INT : width
+ * [I] INT : height
  *
  * RETURN:
  * Returns a DWORD. The width in the low word and the height in high word.
@@ -828,14 +1950,14 @@
   DWORD dwViewRect = 0;
 
   if (nItemCount == -1)
-    nItemCount = infoPtr->nItemCount;
+    nItemCount = GETITEMCOUNT(infoPtr);
 
   if (lStyle & LVS_LIST)
   {
     if (wHeight == 0xFFFF)
     {
       /* use current height */
-      wHeight = infoPtr->nHeight;
+      wHeight = infoPtr->rcList.bottom;
     }
 
     if (wHeight < infoPtr->nItemHeight)
@@ -858,6 +1980,7 @@
       }
     }
 
+    /* Microsoft padding magic */
     wHeight = nItemCountPerColumn * infoPtr->nItemHeight + 2;
     wWidth = nColumnCount * infoPtr->nColumnWidth + 2;
 
@@ -884,8 +2007,8 @@
  * Arranges listview items in icon display mode.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : alignment code
+ * [I] HWND : window handle
+ * [I] INT : alignment code
  *
  * RETURN:
  *   SUCCESS : TRUE
@@ -893,11 +2016,11 @@
  */
 static LRESULT LISTVIEW_Arrange(HWND hwnd, INT nAlignCode)
 {
-  /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0); */
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
   BOOL bResult = FALSE;
 
-  if (lStyle & LVS_ICON)
+  if (((LVS_TYPEMASK & lStyle) == LVS_ICON) || 
+      ((LVS_TYPEMASK & lStyle) == LVS_SMALLICON))
   {
     switch (nAlignCode)
     {
@@ -922,10 +2045,10 @@
 
 /***
  * DESCRIPTION:
- * Removes all listview items.
+ * Removes all listview items and subitems.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  *
  * RETURN:
  *   SUCCESS : TRUE
@@ -936,58 +2059,88 @@
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
   LISTVIEW_ITEM *lpItem;
+  LISTVIEW_SUBITEM *lpSubItem;
   NMLISTVIEW nmlv;
-  BOOL bNotify;
+  BOOL bSuppress;
+  BOOL bResult = FALSE;
   INT i;
-  BOOL bResult = TRUE;
+  INT j;
+  HDPA hdpaSubItems;
 
-  if (infoPtr->nItemCount > 0)
+  if (GETITEMCOUNT(infoPtr) > 0)
   {
+    /* initialize memory */
+    ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
+    
     /* send LVN_DELETEALLITEMS notification */
-    ZeroMemory (&nmlv, sizeof (NMLISTVIEW));
     nmlv.hdr.hwndFrom = hwnd;
     nmlv.hdr.idFrom = lCtrlId;
-    nmlv.hdr.code     = LVN_DELETEALLITEMS;
-    nmlv.iItem        = -1;
-    bNotify = !(BOOL)SendMessageA(GetParent(hwnd), WM_NOTIFY, 
-                                      (WPARAM)lCtrlId, (LPARAM)&nmlv);
+    nmlv.hdr.code = LVN_DELETEALLITEMS;
+    nmlv.iItem = -1;
 
-    nmlv.hdr.code     = LVN_DELETEITEM;
+    /* verify if subsequent LVN_DELETEITEM notifications should be 
+       suppressed */
+    bSuppress = ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
 
-    for (i = 0; i < infoPtr->nItemCount; i++) 
+    for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
     {
-      if (bNotify == TRUE)
+      hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, i);
+      if (hdpaSubItems != NULL)
       {
-        /* send LVN_DELETEITEM notification */
-        nmlv.iItem = i;
-        SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, 
-                       (LPARAM)&nmlv);
-	}
+        for (j = 1; j < hdpaSubItems->nItemCount; j++)
+        {
+          lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, j);
+          if (lpSubItem != NULL)
+          {
+            /* free subitem string */
+            if ((lpSubItem->pszText != NULL) && 
+                (lpSubItem->pszText != LPSTR_TEXTCALLBACKA))
+            {
+              COMCTL32_Free(lpSubItem->pszText);
+            }
+            
+            /* free subitem */
+            COMCTL32_Free(lpSubItem);
+          }    
+        }
+    
+        lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
+        if (lpItem != NULL)
+        {
+          if (bSuppress == FALSE)
+          {
+            /* send LVN_DELETEITEM notification */
+            nmlv.hdr.code = LVN_DELETEITEM;
+            nmlv.iItem = i;
+            nmlv.lParam = lpItem->lParam;
+            ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
+          }
 
-      /* get item */
-      lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, i);
-      if (lpItem != NULL) 
-      {
-        /* free item string */
-        if ((lpItem->pszText != NULL) && 
-            (lpItem->pszText != LPSTR_TEXTCALLBACKA))
-		COMCTL32_Free (lpItem->pszText);
-
-        /* free item */
-	    COMCTL32_Free (lpItem);
-	}
+          /* free item string */
+          if ((lpItem->pszText != NULL) && 
+              (lpItem->pszText != LPSTR_TEXTCALLBACKA))
+          {
+            COMCTL32_Free(lpItem->pszText);
+          }
+          
+          /* free item */
+          COMCTL32_Free(lpItem);
+        }
+        
+        DPA_Destroy(hdpaSubItems);
+      }
     }
 
-    /* ???? needs follow up */ 
-    DPA_DeleteAllPtrs (infoPtr->hdpaItems);
- 
-    /* reset item counter */
-    infoPtr->nItemCount = 0;
-
-    /* reset scrollbar */
+    /* reinitialize listview memory */
+    bResult = DPA_DeleteAllPtrs(infoPtr->hdpaItems);
+    
+    /* reset scroll parameters */
     LISTVIEW_SetScroll(hwnd);
-}
 
+    /* invalidate client area (optimization needed) */
+    InvalidateRect(hwnd, NULL, FALSE);
+  }
+  
   return bResult;
 }
 
@@ -996,8 +2149,8 @@
  * Removes a column from the listview control.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : column index
+ * [I] HWND : window handle
+ * [I] INT : column index
  *
  * RETURN:
  *   SUCCESS : TRUE
@@ -1005,17 +2158,21 @@
  */
 static LRESULT LISTVIEW_DeleteColumn(HWND hwnd, INT nColumn)
 {
-/*   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0); */
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  BOOL bResult = FALSE;
+  
+  if (Header_DeleteItem(infoPtr->hwndHeader, nColumn) == TRUE)
+  {
+    bResult = LISTVIEW_RemoveColumn(infoPtr->hdpaItems, nColumn);
+  }
 
-    /* FIXME ??? */
-/* if (infoPtr->nItemCount > 0) */
-/* return FALSE; */
-/* if (!SendMessage32A(infoPtr->hwndHeader, HDM_DELETEITEM, wParam, 0)) */
-/* return FALSE; */
-/* infoPtr->nColumnCount--; */
-/* FIXME (listview, "semi stub!\n"); */
+  /* reset scroll parameters */
+  LISTVIEW_SetScroll(hwnd);
 
-    return TRUE;
+  /* refresh client area */
+  InvalidateRect(hwnd, NULL, FALSE);
+
+  return bResult;
 }
 
 /***
@@ -1023,8 +2180,8 @@
  * Removes an item from the listview control.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : item index  
+ * [I] HWND : window handle
+ * [I] INT : item index  
  *
  * RETURN:
  *   SUCCESS : TRUE
@@ -1034,56 +2191,174 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
-    LISTVIEW_ITEM *lpItem;
-    NMLISTVIEW nmlv;
+  NMLISTVIEW nmlv;
   BOOL bResult = FALSE;
+  HDPA hdpaSubItems;
+  LISTVIEW_ITEM *lpItem;
+  LISTVIEW_SUBITEM *lpSubItem;
+  INT i;
 
-  if ((nItem >= 0) && (nItem < infoPtr->nItemCount))
+  if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
   {
-    /* send LVN_DELETEITEM notification */
-    ZeroMemory (&nmlv, sizeof (NMLISTVIEW));
-    nmlv.hdr.hwndFrom = hwnd;
-    nmlv.hdr.idFrom = lCtrlId;
-    nmlv.hdr.code     = LVN_DELETEITEM;
-    nmlv.iItem        = nItem;
-    SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, 
-                   (LPARAM)&nmlv);
+    /* initialize memory */
+    ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
 
-    /* remove item */
-    lpItem = (LISTVIEW_ITEM*)DPA_DeletePtr (infoPtr->hdpaItems, nItem);
-    if (lpItem != NULL)
+    hdpaSubItems = (HDPA)DPA_DeletePtr(infoPtr->hdpaItems, nItem);
+    if (hdpaSubItems != NULL)
     {
-      /* free item string */
-      if ((lpItem->pszText != NULL) && 
-          (lpItem->pszText != LPSTR_TEXTCALLBACKA))
-	COMCTL32_Free (lpItem->pszText);
+      for (i = 1; i < hdpaSubItems->nItemCount; i++)
+      {
+        lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i);
+        if (lpSubItem != NULL)
+        {
+          /* free item string */
+          if ((lpSubItem->pszText != NULL) && 
+              (lpSubItem->pszText != LPSTR_TEXTCALLBACKA))
+          {
+            COMCTL32_Free(lpSubItem->pszText);
+          }
+          
+          /* free item */
+          COMCTL32_Free(lpSubItem);
+        }    
+      }
+    
+      lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
+      if (lpItem != NULL)
+      {
+        /* send LVN_DELETEITEM notification */
+        nmlv.hdr.hwndFrom = hwnd;
+        nmlv.hdr.idFrom = lCtrlId;
+        nmlv.hdr.code = LVN_DELETEITEM;
+        nmlv.iItem = nItem;
+        nmlv.lParam = lpItem->lParam;
+        SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, 
+                     (LPARAM)&nmlv);
 
-      /* free item */
-    COMCTL32_Free (lpItem);
+        /* free item string */
+        if ((lpItem->pszText != NULL) && 
+            (lpItem->pszText != LPSTR_TEXTCALLBACKA))
+        {
+          COMCTL32_Free(lpItem->pszText);
+        }
+        
+        /* free item */
+        COMCTL32_Free(lpItem);
+      }
+      
+      bResult = DPA_Destroy(hdpaSubItems);
     }
 
-    /* decrement item counter */
-    infoPtr->nItemCount--;
-
-    /* reset some of the draw data */
-    LISTVIEW_SetScroll(hwnd);
-   
-    bResult = TRUE;
-}
-
+    /* refresh client area */
+    InvalidateRect(hwnd, NULL, FALSE);
+  }
+  
   return bResult;
 }
 
 /* << LISTVIEW_EditLabel >> */
-/* << LISTVIEW_EnsureVisible >> */
 
 /***
  * DESCRIPTION:
+ * Ensures the specified item is visible, scrolling into view if necessary.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] INT : item index
+ * [I] BOOL : partially or entirely visible
+ *
+ * RETURN:
+ *   SUCCESS : TRUE
+ *   FAILURE : FALSE
+ */
+static BOOL LISTVIEW_EnsureVisible(HWND hwnd, INT nItem, BOOL bPartial)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  INT nLast;
+  INT nFirst;
+  INT nScrollPos;
+  BOOL bResult = TRUE;
+
+  switch (LVS_TYPEMASK & lStyle)
+  {
+  case LVS_LIST:
+    if (lStyle & WS_HSCROLL)
+    {
+      nFirst = ListView_GetTopIndex(hwnd);
+
+      /* calculate last fully visible item index */
+      nLast = infoPtr->nCountPerColumn * infoPtr->nCountPerRow + nFirst - 1;
+
+      if (nItem > nLast)
+      {
+        /* calculate new scroll position based on item index */
+        if (((nItem - nLast) % infoPtr->nCountPerColumn) == 0)
+        {
+          nScrollPos = (nItem - nLast) / infoPtr->nCountPerColumn;
+        }
+        else
+        {
+          nScrollPos = (nItem - nLast) / infoPtr->nCountPerColumn + 1;
+        }
+
+        bResult = ListView_Scroll(hwnd, nScrollPos, 0);
+      }
+      else if (nItem < nFirst)
+      {
+        /* calculate new scroll position based on item index */
+        if (((nItem - nFirst) % infoPtr->nCountPerColumn) == 0)
+        {
+          nScrollPos = (nItem - nFirst) / infoPtr->nCountPerColumn;
+        }
+        else
+        {
+          nScrollPos = (nItem - nFirst) / infoPtr->nCountPerColumn -1;
+        }
+
+        bResult = ListView_Scroll(hwnd, nScrollPos, 0);
+      }
+    }
+    break;
+
+  case LVS_REPORT:
+    if (lStyle & WS_VSCROLL)
+    {
+      nFirst = ListView_GetTopIndex(hwnd);
+
+      /* calculate last fully visible item index */
+      nLast = infoPtr->nCountPerColumn + nFirst - 1;
+      if (nItem > nLast)
+      {
+        nScrollPos = nItem - nLast;
+        bResult = ListView_Scroll(hwnd, 0, nScrollPos);
+      }
+      else if (nItem < nFirst)
+      {
+        nScrollPos = nItem - nFirst;
+        bResult = ListView_Scroll(hwnd, 0, nScrollPos);
+      }
+    }
+    break;
+
+  case LVS_SMALLICON:
+    /* TO DO */
+    break;
+
+  case LVS_ICON:
+    /* TO DO */
+    break;
+  }
+
+  return bResult;
+}
+/***
+ * DESCRIPTION:
  * Searches for an item with specific characteristics.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : base item index
+ * [I] HWND : window handle
+ * [I] INT : base item index
  * [I] LPLVFINDINFO : item information to look for
  * 
  * RETURN:
@@ -1093,11 +2368,11 @@
 static LRESULT LISTVIEW_FindItem(HWND hwnd, INT nStart, 
                                  LPLVFINDINFO lpFindInfo)
 {
-/*   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0); */
+/*   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); */
 /*   LISTVIEW_ITEM *lpItem; */
-/*   INT32 nItem; */
-/*   INT32 nEnd = infoPtr->nItemCount; */
-/*   BOOL32 bWrap = FALSE; */
+/*   INT nItem; */
+/*   INT nEnd = GETITEMCOUNT(infoPtr); */
+/*   BOOL bWrap = FALSE; */
 /*   if (nStart == -1) */
 /*     nStart = 0; */
 /*   else */
@@ -1163,7 +2438,7 @@
  * Retrieves the background color of the listview control.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  *
  * RETURN:
  * COLORREF associated with the background.
@@ -1172,7 +2447,7 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
 
-    return infoPtr->clrBk;
+  return infoPtr->clrBk;
 }
 
 /***
@@ -1180,103 +2455,146 @@
  * Retrieves the background image of the listview control.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [O] LPLVMKBIMAGE : background image information
+ * [I] HWND : window handle
+ * [O] LPLVMKBIMAGE : background image attributes
  *
  * RETURN:
  *   SUCCESS : TRUE
- *   FAILURE : FALSE
+ *   FAILURE : FALSE`
  */
-/* static LRESULT LISTVIEW_GetBkImage(HWND32 hwnd, LPLVBKIMAGE lpBkImage) */
-/* { */
-/*   return FALSE; */
-/* } */
+/*  static LRESULT LISTVIEW_GetBkImage(HWND hwnd, LPLVBKIMAGE lpBkImage)  */
+/*  {  */
+/*    return FALSE;  */
+/*  }  */
 
-/* << LISTVIEW_GetCallbackMask >> */
+/***
+ * DESCRIPTION:
+ * Retrieves the callback mask.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ *
+ * RETURN:
+ *  Value of mask
+ */
+static UINT LISTVIEW_GetCallbackMask(HWND hwnd)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+
+  return infoPtr->uCallbackMask;
+}
 
 /***
  * DESCRIPTION:
  * Retrieves column attributes.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 :  column index
- * [IO] LPLVCOLUMN32A : column information
+ * [I] HWND : window handle
+ * [I] INT :  column index
+ * [IO] LPLVCOLUMNA : column information
  *
  * RETURN:
  *   SUCCESS : TRUE
  *   FAILURE : FALSE
  */
-static LRESULT LISTVIEW_GetColumnA(HWND hwnd, INT nIndex, 
+static LRESULT LISTVIEW_GetColumnA(HWND hwnd, INT nItem, 
                                      LPLVCOLUMNA lpColumn)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-    HDITEMA hdi;
+  HDITEMA hdi;
+  BOOL bResult = FALSE;
 
-  if (lpColumn == NULL)
-	return FALSE;
-
-    ZeroMemory (&hdi, sizeof(HDITEMA));
-
-  if (lpColumn->mask & LVCF_FMT)
-	hdi.mask |= HDI_FORMAT;
-
-  if (lpColumn->mask & LVCF_WIDTH)
-        hdi.mask |= HDI_WIDTH;
-
-  if (lpColumn->mask & LVCF_TEXT)
-        hdi.mask |= (HDI_TEXT | HDI_FORMAT);
-
-  if (lpColumn->mask & LVCF_IMAGE)
-        hdi.mask |= HDI_IMAGE;
-
-  if (lpColumn->mask & LVCF_ORDER)
-        hdi.mask |= HDI_ORDER;
-
-    if (!SendMessageA (infoPtr->hwndHeader, HDM_GETITEMA,
-                       (WPARAM)nIndex, (LPARAM)&hdi))
-	return FALSE;
-
-  if (lpColumn->mask & LVCF_FMT) 
+  if (lpColumn != NULL)
   {
-    lpColumn->fmt = 0;
-
-	if (hdi.fmt & HDF_LEFT)
-      lpColumn->fmt |= LVCFMT_LEFT;
-	else if (hdi.fmt & HDF_RIGHT)
-      lpColumn->fmt |= LVCFMT_RIGHT;
-	else if (hdi.fmt & HDF_CENTER)
-      lpColumn->fmt |= LVCFMT_CENTER;
-
-	if (hdi.fmt & HDF_IMAGE)
-      lpColumn->fmt |= LVCFMT_COL_HAS_IMAGES;
+    /* initialize memory */
+    ZeroMemory(&hdi, sizeof(HDITEMA));
+    
+    if (lpColumn->mask & LVCF_FMT)
+    {
+      hdi.mask |= HDI_FORMAT;
     }
 
-  if (lpColumn->mask & LVCF_WIDTH)
-    lpColumn->cx = hdi.cxy;
+    if (lpColumn->mask & LVCF_WIDTH)
+    {
+      hdi.mask |= HDI_WIDTH;
+    }
 
-  if ((lpColumn->mask & LVCF_TEXT) && (lpColumn->pszText) && (hdi.pszText))
-    lstrcpynA (lpColumn->pszText, hdi.pszText, lpColumn->cchTextMax);
+    if (lpColumn->mask & LVCF_TEXT)
+    {
+      hdi.mask |= (HDI_TEXT | HDI_FORMAT);
+    }
 
-  if (lpColumn->mask & LVCF_IMAGE)
-    lpColumn->iImage = hdi.iImage;
+    if (lpColumn->mask & LVCF_IMAGE)
+    {
+      hdi.mask |= HDI_IMAGE;
+    }
 
-  if (lpColumn->mask & LVCF_ORDER)
-    lpColumn->iOrder = hdi.iOrder;
+    if (lpColumn->mask & LVCF_ORDER)
+    {
+      hdi.mask |= HDI_ORDER;
+    }
 
-    return TRUE;
+    bResult = Header_GetItemA(infoPtr->hwndHeader, nItem, &hdi);
+    if (bResult == TRUE)
+    {
+      if (lpColumn->mask & LVCF_FMT) 
+      {
+        lpColumn->fmt = 0;
+
+        if (hdi.fmt & HDF_LEFT)
+        {
+          lpColumn->fmt |= LVCFMT_LEFT;
+        }
+        else if (hdi.fmt & HDF_RIGHT)
+        {
+          lpColumn->fmt |= LVCFMT_RIGHT;
+        }
+        else if (hdi.fmt & HDF_CENTER)
+        {
+          lpColumn->fmt |= LVCFMT_CENTER;
+        }
+
+        if (hdi.fmt & HDF_IMAGE)
+        {
+          lpColumn->fmt |= LVCFMT_COL_HAS_IMAGES;
+        }
+      }
+
+      if (lpColumn->mask & LVCF_WIDTH)
+      {
+        lpColumn->cx = hdi.cxy;
+      }
+      
+      if ((lpColumn->mask & LVCF_TEXT) && (lpColumn->pszText) && (hdi.pszText))
+      {
+        lstrcpynA (lpColumn->pszText, hdi.pszText, lpColumn->cchTextMax);
+      }
+
+      if (lpColumn->mask & LVCF_IMAGE)
+      {
+        lpColumn->iImage = hdi.iImage;
+      }
+
+      if (lpColumn->mask & LVCF_ORDER)
+      {
+        lpColumn->iOrder = hdi.iOrder;
+      }
+    }
+  }
+
+  return bResult;
 }
 
-/* << LISTVIEW_GetColumn32W >> */
+/* << LISTVIEW_GetColumnW >> */
 /* << LISTVIEW_GetColumnOrderArray >> */
 
 /***
  * DESCRIPTION:
- * Retrieves the column width when list or report display mode.
+ * Retrieves the column width.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] int32 : column index
+ * [I] HWND : window handle
+ * [I] int : column index
  *
  * RETURN:
  *   SUCCESS : column width
@@ -1286,23 +2604,21 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-    HDITEMA hdi;
+  HDITEMA hdi;
   INT nColumnWidth = 0;
 
-  if ((lStyle & LVS_LIST) || (lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON))
+  if ((LVS_TYPEMASK & lStyle) ==  LVS_LIST)
   {
     nColumnWidth = infoPtr->nColumnWidth;
   }
-  else if (lStyle & LVS_REPORT)
+  else if ((LVS_TYPEMASK & lStyle) ==  LVS_REPORT)
   {
-    /* verify validity of index */
-    if ((nColumn >= 0) && (nColumn < infoPtr->nColumnCount))
-    {
-      /* get column width from header */
+    /* get column width from header */
+    ZeroMemory(&hdi, sizeof(HDITEMA));
     hdi.mask = HDI_WIDTH;
-    if (SendMessageA (infoPtr->hwndHeader, HDM_GETITEMA,
-                         (WPARAM)nColumn, (LPARAM)&hdi))
-        nColumnWidth = hdi.cxy;
+    if (Header_GetItemA(infoPtr->hwndHeader, nColumn, &hdi) == TRUE)
+    {
+      nColumnWidth = hdi.cxy;
     }
   }
 
@@ -1316,7 +2632,7 @@
  * retrieves the total number of visible items.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  *
  * RETURN:
  * Number of fully visible items.
@@ -1326,23 +2642,22 @@
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
   INT nItemCount = 0;
-  INT nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
-  INT nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
 
-  if (lStyle & LVS_LIST)
+  switch (LVS_TYPEMASK & lStyle)
   {
-    if ((nItemCountPerRow > 0) && (nItemCountPerColumn > 0))
+  case LVS_LIST:
+    if (infoPtr->rcList.right / infoPtr->nColumnWidth)
     {
-      nItemCount = nItemCountPerRow * nItemCountPerColumn;
+      nItemCount = infoPtr->nCountPerRow * infoPtr->nCountPerColumn;
     }
-  }
-  else if (lStyle & LVS_REPORT)
-  {
-    nItemCount = nItemCountPerColumn;
-  }
-  else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON))
-  {
-    nItemCount = infoPtr->nItemCount;
+    break;
+  
+  case LVS_REPORT:
+    nItemCount = infoPtr->nCountPerColumn;
+    break;
+
+  default:
+    nItemCount = GETITEMCOUNT(infoPtr);
   }
 
   return nItemCount;
@@ -1356,7 +2671,7 @@
  * Retrieves a header handle.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  *
  * RETURN:
  * Header handle.
@@ -1365,7 +2680,7 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
 
-    return infoPtr->hwndHeader;
+  return infoPtr->hwndHeader;
 }
 
 /* << LISTVIEW_GetHotCursor >> */
@@ -1377,8 +2692,8 @@
  * Retrieves an image list handle.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : image list identifier 
+ * [I] HWND : window handle
+ * [I] INT : image list identifier 
  * 
  * RETURN:
  *   SUCCESS : image list handle
@@ -1391,18 +2706,20 @@
 
   switch (nImageList) 
   {
-	case LVSIL_NORMAL:
+  case LVSIL_NORMAL:
     himl = infoPtr->himlNormal;
-	case LVSIL_SMALL:
+    break;
+  case LVSIL_SMALL:
     himl = infoPtr->himlSmall;
-	case LVSIL_STATE:
+    break;
+  case LVSIL_STATE:
     himl = infoPtr->himlState;
-    }
+    break;
+  }
 
   return (LRESULT)himl;
 }
 
-
 /* << LISTVIEW_GetISearchString >> */
 
 /***
@@ -1410,55 +2727,97 @@
  * Retrieves item attributes.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [IO] LPLVITEM32A : item info
+ * [I] HWND : window handle
+ * [IO] LPLVITEMA : item info
  * 
  * RETURN:
  *   SUCCESS : TRUE 
  *   FAILURE : FALSE
  */
-static LRESULT LISTVIEW_GetItemA(HWND hwnd, LPLVITEMA lpItem)
+static LRESULT LISTVIEW_GetItemA(HWND hwnd, LPLVITEMA lpLVItem)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LISTVIEW_ITEM *lpListItem;
+  LISTVIEW_ITEM *lpItem;
+  LISTVIEW_SUBITEM *lpSubItem;
+  HDPA hdpaSubItems;
   BOOL bResult = FALSE;
 
-  if (lpItem != NULL)
+  if (lpLVItem != NULL)
   {
-    if ((lpItem->iItem >= 0) && (lpItem->iItem < infoPtr->nItemCount))
+    if ((lpLVItem->iItem >= 0) && (lpLVItem->iItem < GETITEMCOUNT(infoPtr)))
     {
-      /* get item */
-      lpListItem = DPA_GetPtr(infoPtr->hdpaItems, lpItem->iItem);
-      if (lpListItem != NULL)
+      hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
+      if (hdpaSubItems != NULL)
       {
-        /* not tested for subitem > 0 */
-        lpListItem += lpItem->iSubItem;
-        if (lpListItem != NULL) 
+        if (lpLVItem->iSubItem == 0)
         {
-          /* retrieve valid data */
-    if (lpItem->mask & LVIF_STATE)
-            lpItem->state = lpListItem->state & lpItem->stateMask;
-
-          if (lpItem->mask & LVIF_TEXT) 
+          lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
+          if (lpItem != NULL)
           {
-            if (lpListItem->pszText == LPSTR_TEXTCALLBACKA)
-	    lpItem->pszText = LPSTR_TEXTCALLBACKA;
-	else
-              Str_GetPtrA(lpListItem->pszText, lpItem->pszText, 
-			   lpItem->cchTextMax);
-    }
+            bResult = TRUE;
 
-    if (lpItem->mask & LVIF_IMAGE)
-            lpItem->iImage = lpListItem->iImage;
+            /* retrieve valid data */
+            if (lpLVItem->mask & LVIF_STATE)
+            {
+              lpLVItem->state = lpItem->state & lpLVItem->stateMask;
+            }
 
-    if (lpItem->mask & LVIF_PARAM)
-            lpItem->lParam = lpListItem->lParam;
+            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 (lpItem->mask & LVIF_INDENT)
-            lpItem->iIndent = lpListItem->iIndent;
+            if (lpLVItem->mask & LVIF_IMAGE)
+            {
+              lpLVItem->iImage = lpItem->iImage;
+            }
+          
+            if (lpLVItem->mask & LVIF_PARAM)
+            {
+              lpLVItem->lParam = lpItem->lParam;
+            }
+      
+            if (lpLVItem->mask & LVIF_INDENT)
+            {
+              lpLVItem->iIndent = lpItem->iIndent;
+            }
+          }
+        }
+        else
+        {
+          lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, 
+                                                     lpLVItem->iSubItem);
+          if (lpSubItem != NULL)
+          {
+            bResult = TRUE;
 
-          bResult = TRUE;
-}
+            if (lpLVItem->mask & LVIF_TEXT) 
+            {
+              if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA)
+              {
+                lpLVItem->pszText = LPSTR_TEXTCALLBACKA;
+              }
+              else
+              {
+                bResult = Str_GetPtrA(lpSubItem->pszText, lpLVItem->pszText, 
+                                        lpLVItem->cchTextMax);
+              }
+            }
+
+            if (lpLVItem->mask & LVIF_IMAGE)
+            {
+              lpLVItem->iImage = lpSubItem->iImage;
+            }
+          }
+        }
       }
     }
   }
@@ -1466,7 +2825,7 @@
   return bResult;
 }
 
-/* << LISTVIEW_GetItem32W >> */
+/* << LISTVIEW_GetItemW >> */
 /* << LISTVIEW_GetHotCursor >> */
 /* << LISTVIEW_GetHotItem >> */
 /* << LISTVIEW_GetHoverTime >> */
@@ -1476,16 +2835,16 @@
  * Retrieves the number of items in the listview control.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * 
  * RETURN:
  * Number of items.
  */
 static LRESULT LISTVIEW_GetItemCount(HWND hwnd)
 {
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
 
-    return infoPtr->nItemCount;
+  return GETITEMCOUNT(infoPtr);
 }
 
 /***
@@ -1493,73 +2852,87 @@
  * Retrieves the position (upper-left) of the listview control item.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : item index
- * [O] LPPOINT32 : coordinate information
+ * [I] HWND : window handle
+ * [I] INT : item index
+ * [O] LPPOINT : coordinate information
  *
  * RETURN:
  *   SUCCESS : TRUE
  *   FAILURE : FALSE
  */
 static LRESULT LISTVIEW_GetItemPosition(HWND hwnd, INT nItem, 
-                                        LPPOINT lpPt)
+                                        LPPOINT lppt)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
   INT nColumn;
   INT nRow;
   BOOL bResult = FALSE;
-  INT nItemCountPerColumn;
-  INT nItemCountPerRow;
-  INT nFirstItem;
-  INT nLastItem;
+  INT nFirst;
+  INT nLast;
 
-  if ((nItem >= 0) && (nItem < infoPtr->nItemCount) && (lpPt != NULL))
+  if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)) && (lppt != NULL))
   {
-    if (lStyle & LVS_LIST)
-{
-      nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
-      nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
+    switch (LVS_TYPEMASK & lStyle)
+    {
+    case LVS_LIST:
+      nFirst = ListView_GetTopIndex(hwnd);
+      nLast = infoPtr->nCountPerColumn * infoPtr->nCountPerRow + nFirst - 1;
 
-      if ((nItemCountPerColumn > 0) && (nItemCountPerRow > 0))
+      if ((nItem >= nFirst) || (nItem <= nLast))
       {
-        nFirstItem = LISTVIEW_GetFirstVisibleItem(hwnd); 
-        nLastItem = nFirstItem + nItemCountPerRow * nItemCountPerRow - 1;
+        nItem -= nFirst; 
+       
+        /* get column */
+        nColumn = nItem / infoPtr->nCountPerColumn;
 
-        if ((nItem >= nFirstItem) || (nItem <= nLastItem))
-        {
-          nItem -= nFirstItem; 
+        /* get row */
+        nRow = nItem % infoPtr->nCountPerColumn;
+          
+        /* X coordinate of the column */
+        lppt->x = nColumn * infoPtr->nColumnWidth + infoPtr->rcList.left;
 
-          /* get column */
-          nColumn = nItem / nItemCountPerColumn;
-
-          /* get row */
-          nRow = nItem % nItemCountPerColumn;
-
-          /* X coordinate of the column */
-          lpPt->x = nColumn * infoPtr->nColumnWidth;
-
-          /* Y coordinate of the item */
-          lpPt->y = nRow * infoPtr->nItemHeight;
-
-          bResult = TRUE;
-        }
+        /* Y coordinate of the item */
+        lppt->y = nRow * infoPtr->nItemHeight + infoPtr->rcList.top;
+          
+        bResult = TRUE;
       }
-      else if (lStyle & LVS_REPORT)
+      break;
+
+    case LVS_REPORT:
+      nFirst = ListView_GetTopIndex(hwnd);
+      nLast = infoPtr->nCountPerColumn * infoPtr->nCountPerRow + nFirst - 1;
+
+      /* get column */
+      nColumn = nItem / infoPtr->nCountPerColumn;
+      
+      /* get row */
+      nRow = nItem % infoPtr->nCountPerColumn;
+
+      if ((nItem >= nFirst) || (nItem <= nLast))
       {
-        /* TO DO */
-      }
-      else if (lStyle & LVS_SMALLICON)
-      {
-        /* TO DO */
-      }
-      else if (lStyle & LVS_ICON)
-{
-        /* TO DO */
-      }
+        nItem -= nFirst; 
+   
+        /* get column */
+        nColumn = nItem / infoPtr->nCountPerColumn;
+
+        /* get row */
+        nRow = nItem % infoPtr->nCountPerColumn;
+
+        /* X coordinate of the column */
+        lppt->x = infoPtr->rcList.left;
+
+        /* Y coordinate of the item */
+        lppt->y = nRow * infoPtr->nItemHeight + infoPtr->rcList.top;
+          
+        bResult = TRUE;
+      }        
+
+    default:
+      /* TO DO */
     }
   }
-
+    
   return bResult;
 }
 
@@ -1568,64 +2941,96 @@
  * Retrieves the bounding rectangle for a listview control item.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : item index
- * [IO] LPRECT32 : bounding rectangle coordinates
+ * [I] HWND : window handle
+ * [I] INT : item index
+ * [IO] LPRECT : bounding rectangle coordinates
  * 
  * RETURN:
  *   SUCCESS : TRUE
  *   FAILURE : FALSE
  */
-static LRESULT LISTVIEW_GetItemRect(HWND hwnd, INT nItem, LPRECT lpRect)
+static LRESULT LISTVIEW_GetItemRect(HWND hwnd, INT nItem, LPRECT lprc)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
   LISTVIEW_ITEM *lpItem;
-  POINT pt;
-  INT nLabelWidth;
+  HDPA hdpaSubItems;
+  INT nLabelWidth = 0;
+  INT nStateWidth = 0;
+  INT nIconWidth = 0;
   BOOL bResult = FALSE;
-  INT nSmallIconWidth;
+  CHAR szDispText[DISP_TEXT_SIZE];
+  LPSTR pszDispText;
+  POINT pt;
 
-  nSmallIconWidth = GetSystemMetrics(SM_CXSMICON);
+  /*init pointer */
+  pszDispText = szDispText;
 
-  if ((nItem < 0) || (nItem >= infoPtr->nItemCount) || (lpRect == NULL))
-    return FALSE;
+  if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)) && (lprc != NULL))
+  {
+    hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
+    if (hdpaSubItems != NULL)
+    {
+      lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
+      if (lpItem != NULL)
+      {
+        if ((LVS_TYPEMASK & lStyle) == LVS_ICON)
+        {
 
-  /* get item */
-  lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem);
-  if (lpItem == NULL) 
-    return FALSE;
+        }
+        else
+        {
+          if (ListView_GetItemPosition(hwnd, nItem, &pt) == TRUE)
+          {
+            /* get width of label in pixels */
+            LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, NULL, NULL, 
+                                     &pszDispText, DISP_TEXT_SIZE);
+            nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText); 
+          }
 
-  if (!SendMessageA(hwnd, LVM_GETITEMPOSITION, (WPARAM)nItem, (LPARAM)&pt))
-    return FALSE;
+          if (infoPtr->himlState != NULL)
+          {
+            nStateWidth = infoPtr->iconSize.cx;
+          }
 
-  nLabelWidth = SendMessageA(hwnd, LVM_GETSTRINGWIDTHA, (WPARAM)0, 
-                               (LPARAM)lpItem->pszText);
-  switch(lpRect->left) 
-  { 
-  case LVIR_BOUNDS: 
-    lpRect->left = pt.x;
-    lpRect->top = pt.y;
-    lpRect->right = lpRect->left + nSmallIconWidth + nLabelWidth;
-    lpRect->bottom = lpRect->top + infoPtr->nItemHeight;
-    bResult = TRUE;
-    break;
-  case LVIR_ICON:
-    lpRect->left = pt.x;
-    lpRect->top = pt.y;
-    lpRect->right = lpRect->left + nSmallIconWidth;
-    lpRect->bottom = lpRect->top + infoPtr->nItemHeight;
-    bResult = TRUE;
-    break;
-  case LVIR_LABEL: 
-    lpRect->left = pt.x + nSmallIconWidth;
-    lpRect->top = pt.y;
-    lpRect->right = lpRect->left + nLabelWidth;
-    lpRect->bottom = infoPtr->nItemHeight;
-    bResult = TRUE;
-    break;
-  case LVIR_SELECTBOUNDS:
-    /* TO DO */
-    break;
+          if (infoPtr->himlSmall == NULL)
+          {
+            nIconWidth = infoPtr->iconSize.cx;
+          }
+
+          switch(lprc->left)  
+          {  
+          case LVIR_BOUNDS:  
+            lprc->left = pt.x;
+            lprc->top = pt.y;
+            lprc->right = lprc->left + nStateWidth + nIconWidth + nLabelWidth;
+            lprc->bottom = lprc->top + infoPtr->nItemHeight;
+            bResult = TRUE;
+            break;
+          case LVIR_ICON:
+            lprc->left = pt.x + nStateWidth;
+            lprc->top = pt.y;
+            lprc->right = lprc->left + nIconWidth;
+            lprc->bottom = lprc->top + infoPtr->nItemHeight;
+            bResult = TRUE;
+            break;
+          case LVIR_LABEL: 
+            lprc->left = pt.x + nIconWidth + nStateWidth;
+            lprc->top = pt.y;
+            lprc->right = lprc->left + nLabelWidth;
+            lprc->bottom = infoPtr->nItemHeight;
+            bResult = TRUE;
+            break;
+          case LVIR_SELECTBOUNDS:
+            lprc->left = pt.x + nStateWidth;
+            lprc->top = pt.y;
+            lprc->right = lprc->left + nIconWidth + nLabelWidth;
+            lprc->bottom = lprc->top + infoPtr->nItemHeight;
+            bResult = TRUE;
+          }
+        }
+      }
+    }
   }
         
   return bResult;
@@ -1636,34 +3041,28 @@
  * Retrieves the spacing between listview control items.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] BOOL32 : small icon (TRUE) or large icon (FALSE)
+ * [I] HWND : window handle
+ * [I] BOOL : flag for small or large icon 
  *
  * RETURN:
  * Horizontal + vertical spacing
  */
 static LRESULT LISTVIEW_GetItemSpacing(HWND hwnd, BOOL bSmall)
 {
-  INT nSmallIconHSpacing;
-  INT nSmallIconVSpacing;
-  INT nIconHSpacing;
-  INT nIconVSpacing;
-  LONG lResult = 0;
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  LONG lResult;
 
   if (bSmall == TRUE)
   {
-    /* ??? */
-    nSmallIconHSpacing = 0;
-    nSmallIconVSpacing = 0;
-    lResult = MAKELONG(nSmallIconHSpacing, nSmallIconVSpacing);
-    }
-    else
-  {
-    nIconHSpacing = GetSystemMetrics(SM_CXICONSPACING);
-    nIconVSpacing = GetSystemMetrics(SM_CYICONSPACING);
-    lResult = MAKELONG(nIconHSpacing, nIconVSpacing);
+    lResult = MAKELONG(infoPtr->largeIconSpacing.cx, 
+                       infoPtr->largeIconSpacing.cy);
   }
-  
+  else
+  {
+    lResult = MAKELONG(infoPtr->smallIconSpacing.cx, 
+                       infoPtr->smallIconSpacing.cy);
+  }
+
   return lResult;
 }
 
@@ -1672,9 +3071,9 @@
  * Retrieves the state of a listview control item.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : item index
- * [I] UINT32 : state mask
+ * [I] HWND : window handle
+ * [I] INT : item index
+ * [I] UINT : state mask
  * 
  * RETURN:
  * State specified by the mask.
@@ -1682,17 +3081,22 @@
 static LRESULT LISTVIEW_GetItemState(HWND hwnd, INT nItem, UINT uMask)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LISTVIEW_ITEM *lpItem;
-  INT nState = 0;
+  LVITEMA lvItem;
+  UINT uState = 0;
 
-  if ((nItem >= 0) && (nItem < infoPtr->nItemCount))
+  if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
   {
-    lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem);
-    if (lpItem != NULL) 
-      nState =   lpItem->state & uMask;
+    ZeroMemory(&lvItem, sizeof(LVITEMA));
+    lvItem.iItem = nItem;
+    lvItem.stateMask = uMask;
+    lvItem.mask = LVIF_STATE;
+    if (ListView_GetItemA(hwnd, &lvItem) == TRUE)
+    {
+      uState = lvItem.state;
+    }
   }
 
-  return nState;
+  return uState;
 }
 
 /***
@@ -1700,34 +3104,73 @@
  * Retrieves the text of a listview control item or subitem. 
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : item index
- * [IO] LPLVITEM32A : item information
+ * [I] HWND : window handle
+ * [I] INT : item index
+ * [IO] LPLVITEMA : item information
  * 
  * RETURN:
  * None
  */
-static VOID LISTVIEW_GetItemTextA(HWND hwnd, INT nItem, 
-                                    LPLVITEMA lpItem)
+static LRESULT LISTVIEW_GetItemTextA(HWND hwnd, INT nItem, 
+                                       LPLVITEMA lpLVItem)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LISTVIEW_ITEM *lpListItem;
+  LISTVIEW_ITEM *lpItem;
+  LISTVIEW_SUBITEM *lpSubItem;
+  HDPA hdpaSubItems;
+  INT nLength = 0;
+  
+  if (lpLVItem != NULL)
+  {
+    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);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
 
-  if ((nItem < 0) || (nItem >= infoPtr->nItemCount) || (lpItem == NULL))
-    return;
-
-  lpListItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem);
-  if (lpListItem == NULL)
-    return;
-
-  lpListItem += lpItem->iSubItem;
-  if (lpListItem == NULL)
-    return;
-
-  if (lpListItem->pszText == LPSTR_TEXTCALLBACKA) 
-    lpItem->pszText = LPSTR_TEXTCALLBACKA;
-    else
-    Str_GetPtrA(lpListItem->pszText, lpItem->pszText, lpItem->cchTextMax);
+  return nLength;
 }
 
 /***
@@ -1735,28 +3178,35 @@
  * Searches for an item based on properties + relationships.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : item index
- * [I] UINT32 : relationship flag
+ * [I] HWND : window handle
+ * [I] INT : item index
+ * [I] UINT : relationship flag
  * 
  * RETURN:
  *   SUCCESS : item index
  *   FAILURE : -1
  */
-static LRESULT LISTVIEW_GetNextItem (HWND hwnd, INT nItem, UINT uFlags)
+static LRESULT LISTVIEW_GetNextItem(HWND hwnd, INT nItem, UINT uFlags)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   INT nResult = -1;
 
-  /* start at begin */
   if (nItem == -1)
+  {
+    /* start at begin */
     nItem = 0;
+  }
+  else
+  {
+    /* exclude specified item */
+    nItem++;
+  }
 
-  if ((nItem >= 0) && (nItem < infoPtr->nItemCount))
+  if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
   {
     /* TO DO */
-}
-
+  }  
+  
   return nResult;
 }
 
@@ -1767,8 +3217,8 @@
  * Retrieves the current origin when in icon or small icon display mode.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [O] LPPOINT32 : coordinate information
+ * [I] HWND : window handle
+ * [O] LPPOINT : coordinate information
  * 
  * RETURN:
  *   SUCCESS : TRUE
@@ -1779,13 +3229,17 @@
   LONG lStyle = GetWindowLongA(hwnd, GWL_ID);
   BOOL bResult = FALSE;
 
-  if (lStyle & LVS_SMALLICON) 
+  if ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON) 
   {
     /* TO DO */
+    lpOrigin->x = 0;
+    lpOrigin->y = 0;
   }
-  else if (lStyle & LVS_ICON)
+  else if ((lStyle & LVS_TYPEMASK) == LVS_ICON) 
   {
     /* TO DO */
+    lpOrigin->x = 0;
+    lpOrigin->y = 0;
   }
 
   return bResult;
@@ -1796,7 +3250,7 @@
  * Retrieves the number of items that are marked as selected.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * 
  * RETURN:
  * Number of items selected.
@@ -1804,17 +3258,14 @@
 static LRESULT LISTVIEW_GetSelectedCount(HWND hwnd)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LISTVIEW_ITEM *lpItem;
   INT nSelectedCount = 0;
   INT i;
 
-  for (i = 0; i < infoPtr->nItemCount; i++)
+  for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
   {
-    lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, i);
-    if (lpItem != NULL)
+    if (ListView_GetItemState(hwnd, i, LVIS_SELECTED) & LVIS_SELECTED)
     {
-      if (lpItem->state & LVIS_SELECTED)
-        nSelectedCount++;
+      nSelectedCount++;
     }
   }
 
@@ -1826,7 +3277,7 @@
  * Retrieves item index that marks the start of a multiple selection.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * 
  * RETURN:
  * Index number or -1 if there is no selection mark.
@@ -1834,12 +3285,8 @@
 static LRESULT LISTVIEW_GetSelectionMark(HWND hwnd)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  INT nResult = -1;
 
-  if (SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, (WPARAM)0, (LPARAM)0) != 0)
-    nResult = infoPtr->nSelectionMark;
-
-  return nResult;
+  return infoPtr->nSelectionMark;
 }
 
 /***
@@ -1847,7 +3294,7 @@
  * Retrieves the width of a string.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * 
  * RETURN:
  *   SUCCESS : string width (in pixels)
@@ -1856,23 +3303,23 @@
 static LRESULT LISTVIEW_GetStringWidthA(HWND hwnd, LPCSTR lpsz)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-    HFONT hFont, hOldFont;
-    HDC hdc;
+  HFONT hFont, hOldFont;
+  HDC hdc;
   SIZE textSize;
-  INT nResult = 0;
 
+  /* initialize */ 
+  ZeroMemory(&textSize, sizeof(SIZE));
   if (lpsz != NULL)
   {
-    hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
+    hFont = infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont;
     hdc = GetDC(hwnd);
-    hOldFont = SelectObject (hdc, hFont);
-    GetTextExtentPoint32A(hdc, lpsz, lstrlenA(lpsz), &textSize);
-    SelectObject (hdc, hOldFont);
+    hOldFont = SelectObject(hdc, hFont);
+    GetTextExtentPointA(hdc, lpsz, lstrlenA(lpsz), &textSize);
+    SelectObject(hdc, hOldFont);
     ReleaseDC(hwnd, hdc);
-    nResult = textSize.cx;
   }
 
-  return nResult;
+  return textSize.cx;
 }
 
 /***
@@ -1880,7 +3327,7 @@
  * Retrieves the text backgound color.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * 
  * RETURN:
  * COLORREF associated with the the background.
@@ -1897,7 +3344,7 @@
  * Retrieves the text color.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * 
  * RETURN:
  * COLORREF associated with the text.
@@ -1914,22 +3361,23 @@
  * Retrieves the bounding rectangle of all the items.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [O] LPRECT32 : bounding rectangle
+ * [I] HWND : window handle
+ * [O] LPRECT : bounding rectangle
  *
  * RETURN:
  *   SUCCESS : TRUE
  *   FAILURE : FALSE
  */
-static LRESULT LISTVIEW_GetViewRect(HWND hwnd, LPRECT lpBoundingRect)
+static LRESULT LISTVIEW_GetViewRect(HWND hwnd, LPRECT lprc)
 {
-  /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0); */
+  /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); */
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
   BOOL bResult = FALSE;
 
-  if (lpBoundingRect != NULL)
+  if (lprc != NULL)
   {
-    if ((lStyle & LVS_ICON) || (lStyle & LVS_SMALLICON))
+    if (((lStyle & LVS_TYPEMASK) == LVS_ICON) || 
+        ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON))
     {
       /* TO DO */
     }
@@ -1940,92 +3388,95 @@
 
 /***
  * DESCRIPTION:
- * Determines item index when in small icon view.
+ * Determines which section of the item was selected (if any).
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
+ * [I] INT : item index
  * [IO] LPLVHITTESTINFO : hit test information
  *
  * RETURN:
  *   SUCCESS : item index
  *   FAILURE : -1
  */
-static LRESULT HitTestSmallIconView(HWND hwnd, LPLVHITTESTINFO lpHitTestInfo)
+static INT LISTVIEW_HitTestItem(HWND hwnd, INT nItem, 
+                                  LPLVHITTESTINFO lpHitTestInfo)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  HDPA hdpaSubItems;
   LISTVIEW_ITEM *lpItem;
-  INT nColumn;
-  INT nRow;
-  INT nItem = 0;
-  INT nLabelWidth;
   INT nOffset;
+  INT nLabelWidth;
   INT nPosX = 0;
-  INT nSmallIconWidth;
-  INT nItemCountPerRow;
+  CHAR szDispText[DISP_TEXT_SIZE];
+  LPSTR pszDispText;
 
-  /* get column */
-  nColumn = lpHitTestInfo->pt.x / infoPtr->nColumnWidth;
+  /*init pointer */
+  pszDispText = szDispText;
 
-  /* get row */
-  nRow = lpHitTestInfo->pt.y / infoPtr->nItemHeight;
-  
-  /* calculate offset from start of column (in pixels) */
-  nOffset = lpHitTestInfo->pt.x % infoPtr->nColumnWidth;
-
-  /* get recommended width of a small icon */
-  nSmallIconWidth = GetSystemMetrics(SM_CXSMICON);
-
-  /* calculate index */
-  nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
-  nItem = nRow * nItemCountPerRow + LISTVIEW_GetFirstVisibleItem(hwnd) + nColumn;
+  if ((LVS_TYPEMASK & lStyle) == LVS_LIST)
+  {
+    /* calculate offset from start of item (in pixels) */
+    nOffset = lpHitTestInfo->pt.x % infoPtr->nColumnWidth;
+  }
+  else
+  {
+    nOffset = lpHitTestInfo->pt.x;
+  }
 
   /* verify existance of item */
-  if (nItem < infoPtr->nItemCount)
+  if (nItem < GETITEMCOUNT(infoPtr))
   {
     /* get item */
-    lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem);
-    if (lpItem != NULL)
+    hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
+    if (hdpaSubItems != NULL)
     {
-      if (infoPtr->himlState != NULL)
+      lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
+      if (lpItem != NULL)
       {
-        nPosX += nSmallIconWidth;
-        if (nOffset <= nPosX)
+        if (infoPtr->himlState != NULL)
         {
-          lpHitTestInfo->flags = LVHT_ONITEMSTATEICON | LVHT_ONITEM;
+          nPosX += infoPtr->iconSize.cx;
+          if (nOffset <= nPosX)
+          {
+            lpHitTestInfo->flags = LVHT_ONITEMSTATEICON | LVHT_ONITEM;
+            lpHitTestInfo->iItem = nItem;
+            lpHitTestInfo->iSubItem = 0;
+            return nItem;
+          }
+        }
+
+        if (infoPtr->himlSmall != NULL)
+        {
+          nPosX += infoPtr->iconSize.cx;
+          if (nOffset <= nPosX)
+          {
+            lpHitTestInfo->flags = LVHT_ONITEMICON | LVHT_ONITEM;
+            lpHitTestInfo->iItem = nItem;
+            lpHitTestInfo->iSubItem = 0;
+            return nItem;
+          }
+        }
+
+        /* get width of label in pixels */
+        LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, NULL, NULL, 
+                                 &pszDispText, DISP_TEXT_SIZE);
+        nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText); 
+        nLabelWidth += nPosX;
+
+        if (nOffset <= nLabelWidth)
+        {
+          lpHitTestInfo->flags = LVHT_ONITEMLABEL | LVHT_ONITEM;
           lpHitTestInfo->iItem = nItem;
           lpHitTestInfo->iSubItem = 0;
           return nItem;
         }
       }
-
-      if (infoPtr->himlSmall != NULL)
-      {
-        nPosX += nSmallIconWidth;
-        if (nOffset <= nPosX)
-        {
-          lpHitTestInfo->flags = LVHT_ONITEMICON | LVHT_ONITEM;
-          lpHitTestInfo->iItem = nItem;
-          lpHitTestInfo->iSubItem = 0;
-          return nItem;
-}
-      }
-
-      /* get width of label in pixels */
-      nLabelWidth = SendMessageA(hwnd, LVM_GETSTRINGWIDTHA, (WPARAM)0, 
-                                   (LPARAM)lpItem->pszText); 
-      nLabelWidth += nPosX;
-
-      if (nOffset <= nLabelWidth)
-{
-        lpHitTestInfo->flags = LVHT_ONITEMLABEL | LVHT_ONITEM;
-        lpHitTestInfo->iItem = nItem;
-        lpHitTestInfo->iSubItem = 0;
-          return nItem;
-      }
     }
   }
 
-  /* hit is not on an item */
+  /* hit is not on item */
   lpHitTestInfo->flags = LVHT_NOWHERE; 
      
   return -1;
@@ -2033,104 +3484,10 @@
 
 /***
  * DESCRIPTION:
- * Determines item index when in list display mode.
- * 
- * PARAMETER(S):
- * [I] HWND32 : window handle
- * [IO] LPLVHITTESTINFO : hit test information
- *
- * RETURN:
- *   SUCCESS : item index
- *   FAILURE : -1
- */
-static LRESULT HitTestListView(HWND hwnd, LPLVHITTESTINFO lpHitTestInfo)
-{
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LISTVIEW_ITEM *lpItem;
-  INT nColumn;
-  INT nRow;
-  INT nItem = 0;
-  INT nLabelWidth;
-  INT nOffset;
-  INT nPosX = 0;
-  INT nSmallIconWidth;
-  INT nItemCountPerColumn;
-
-  /* get column */
-  nColumn = lpHitTestInfo->pt.x / infoPtr->nColumnWidth;
-
-  /* get row */ 
-  nRow = lpHitTestInfo->pt.y / infoPtr->nItemHeight;
-  
-  /* calculate offset from start of column (in pixels) */
-  nOffset = lpHitTestInfo->pt.x % infoPtr->nColumnWidth;
-
-  /* get recommended width of a small icon */
-  nSmallIconWidth = GetSystemMetrics(SM_CXSMICON);
-
-  /* calculate index */
-  nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
-  nItem = (nColumn * nItemCountPerColumn + LISTVIEW_GetFirstVisibleItem(hwnd) 
-           + nRow);
-
-  /* verify existance of item */
-  if (nItem < infoPtr->nItemCount)
-  {
-    /* get item */
-    lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem);
-    if (lpItem != NULL)
-    {
-      if (infoPtr->himlState != NULL)
-      {
-        nPosX += nSmallIconWidth;
-        if (nOffset <= nPosX)
-        {
-          lpHitTestInfo->flags = LVHT_ONITEMSTATEICON | LVHT_ONITEM;
-          lpHitTestInfo->iItem = nItem;
-          lpHitTestInfo->iSubItem = 0;
-          return nItem;
-        }
-      }
-
-      if (infoPtr->himlSmall != NULL)
-      {
-        nPosX += nSmallIconWidth;
-        if (nOffset <= nPosX)
-{
-          lpHitTestInfo->flags = LVHT_ONITEMICON | LVHT_ONITEM;
-          lpHitTestInfo->iItem = nItem;
-          lpHitTestInfo->iSubItem = 0;
-          return nItem;
-        }
-      }
-
-      /* get width of label in pixels */
-      nLabelWidth = SendMessageA(hwnd, LVM_GETSTRINGWIDTHA, (WPARAM)0, 
-                                   (LPARAM)lpItem->pszText); 
-      nLabelWidth += nPosX;
-
-      if (nOffset <= nLabelWidth)
-      {
-        lpHitTestInfo->flags = LVHT_ONITEMLABEL | LVHT_ONITEM;
-        lpHitTestInfo->iItem = nItem;
-        lpHitTestInfo->iSubItem = 0;
-          return nItem;
-      }
-    }
-  }
-
-  /* hit is not on an item */
-  lpHitTestInfo->flags = LVHT_NOWHERE; 
-     
-    return -1;
-}
-
-/***
- * DESCRIPTION:
  * Determines wich listview item is located at the specified position.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * [IO} LPLVHITTESTINFO : hit test information
  *
  * RETURN:
@@ -2139,24 +3496,68 @@
  */
 static LRESULT LISTVIEW_HitTest(HWND hwnd, LPLVHITTESTINFO lpHitTestInfo)
 {
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  INT nColumn;
+  INT nRow;
+  INT nTopIndex;
+  INT nItem = -1;
 
-  if (lStyle & LVS_LIST)
-    return HitTestListView(hwnd, lpHitTestInfo);
-  else if (lStyle & LVS_REPORT)
+  lpHitTestInfo->flags = 0;
+  if (infoPtr->rcList.left > lpHitTestInfo->pt.x)
   {
-    /* TO DO */
+    lpHitTestInfo->flags = LVHT_TOLEFT;
   }
-  else if (lStyle & LVS_SMALLICON)
+  else if (infoPtr->rcList.right < lpHitTestInfo->pt.x) 
   {
-    return HitTestSmallIconView(hwnd, lpHitTestInfo);
+    lpHitTestInfo->flags = LVHT_TORIGHT;
   }
-  else if (lStyle & LVS_ICON)
+  
+  if (infoPtr->rcList.top > lpHitTestInfo->pt.y)
   {
-    /* TO DO */
+    lpHitTestInfo->flags |= LVHT_ABOVE;
+  } 
+  else if (infoPtr->rcList.bottom < lpHitTestInfo->pt.y) 
+  {
+    lpHitTestInfo->flags |= LVHT_BELOW;
   }
 
-  return -1;
+  if (lpHitTestInfo->flags == 0)
+  {
+    switch (LVS_TYPEMASK & lStyle)
+    {
+    case LVS_LIST:
+      /* get current column */
+      nColumn = lpHitTestInfo->pt.x / infoPtr->nColumnWidth;
+
+      /* get current row */ 
+      nRow = lpHitTestInfo->pt.y / infoPtr->nItemHeight;
+    
+      /* get the index of the first visible item */
+      nTopIndex = ListView_GetTopIndex(hwnd);
+
+      nItem = nColumn * infoPtr->nCountPerColumn + nTopIndex + nRow;
+      nItem = LISTVIEW_HitTestItem(hwnd, nItem, lpHitTestInfo);
+      break;
+
+    case LVS_REPORT:
+      /* get current row */ 
+      nRow = ((lpHitTestInfo->pt.y - infoPtr->rcList.top) / 
+              infoPtr->nItemHeight);
+
+      /* get the index of the first visible item */
+      nTopIndex = ListView_GetTopIndex(hwnd);
+    
+      nItem = nTopIndex + nRow;
+      nItem = LISTVIEW_HitTestItem(hwnd, nItem, lpHitTestInfo);
+      break;
+
+    default:
+/*       nItem = LISTVIEW_HitTestItem(hwnd, nItem, lpHitTestInfo); */
+    }
+  }
+
+  return nItem;
 }
 
 /***
@@ -2164,223 +3565,202 @@
  * Inserts a new column.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : column index
- * [I] LPLVCOLUMN32A : column information
+ * [I] HWND : window handle
+ * [I] INT : column index
+ * [I] LPLVCOLUMNA : column information
  *
  * RETURN:
  *   SUCCESS : new column index
  *   FAILURE : -1
  */
-static LRESULT LISTVIEW_InsertColumnA(HWND hwnd, INT nIndex, 
+static LRESULT LISTVIEW_InsertColumnA(HWND hwnd, INT nColumn, 
                                         LPLVCOLUMNA lpColumn)
 {
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
-    HDITEMA hdi;
-    INT nResult;
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  HDITEMA hdi;
+  INT nNewColumn = -1;
 
-  if ((lpColumn == NULL) || (infoPtr->nItemCount > 0))
-	return -1;
-
-  FIXME (listview, "(%d %p): semi stub!\n", nIndex, lpColumn);
-
-  /* initialize memory */
-    ZeroMemory (&hdi, sizeof(HDITEMA));
-
-  if (lpColumn->mask & LVCF_FMT) 
+  if (lpColumn != NULL) 
   {
-	if (nIndex == 0)
-	    hdi.fmt |= HDF_LEFT;
-    else if (lpColumn->fmt & LVCFMT_LEFT)
-	    hdi.fmt |= HDF_LEFT;
-    else if (lpColumn->fmt & LVCFMT_RIGHT)
-	    hdi.fmt |= HDF_RIGHT;
-    else if (lpColumn->fmt & LVCFMT_CENTER)
-	    hdi.fmt |= HDF_CENTER;
-    if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES)
-	    hdi.fmt |= HDF_IMAGE;
-	    
-	hdi.mask |= HDI_FORMAT;
+    /* initialize memory */
+    ZeroMemory(&hdi, sizeof(HDITEMA));
+
+    if (lpColumn->mask & LVCF_FMT) 
+    {
+      /* format member is valid */
+      hdi.mask |= HDI_FORMAT;
+
+      /* set text alignment (leftmost column must be left-aligned) */
+      if (nColumn == 0)
+      {
+        hdi.fmt |= HDF_LEFT;
+      }
+      else
+      {
+        if (lpColumn->fmt & LVCFMT_LEFT)
+        {
+          hdi.fmt |= HDF_LEFT;
+        }
+        else if (lpColumn->fmt & LVCFMT_RIGHT)
+        {
+          hdi.fmt |= HDF_RIGHT;
+        }
+        else if (lpColumn->fmt & LVCFMT_CENTER)
+        {
+          hdi.fmt |= HDF_CENTER;
+        }
+      }
+ 
+      if (lpColumn->fmt & LVCFMT_BITMAP_ON_RIGHT)
+      {
+        hdi.fmt |= HDF_BITMAP_ON_RIGHT;
+        /* ??? */
+      }
+
+      if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES)
+      {
+        /* ??? */
+      }
+      
+      if (lpColumn->fmt & LVCFMT_IMAGE)
+      {
+        hdi.fmt |= HDF_IMAGE;
+        hdi.iImage = I_IMAGECALLBACK;
+      }
     }
 
-  if (lpColumn->mask & LVCF_WIDTH) 
-  {
-        hdi.mask |= HDI_WIDTH;
-    hdi.cxy = lpColumn->cx;
+    if (lpColumn->mask & LVCF_WIDTH) 
+    {
+      hdi.mask |= HDI_WIDTH;
+      hdi.cxy = lpColumn->cx;
     }
-    
-  if (lpColumn->mask & LVCF_TEXT) 
-  {
-        hdi.mask |= (HDI_TEXT | HDI_FORMAT);
-    hdi.pszText = lpColumn->pszText;
-	hdi.fmt |= HDF_STRING;
+  
+    if (lpColumn->mask & LVCF_TEXT) 
+    {
+      hdi.mask |= HDI_TEXT | HDI_FORMAT;
+      hdi.pszText = lpColumn->pszText;
+      hdi.cchTextMax = lstrlenA(lpColumn->pszText);
+      hdi.fmt |= HDF_STRING;
+    }
+  
+    if (lpColumn->mask & LVCF_IMAGE) 
+    {
+      hdi.mask |= HDI_IMAGE;
+      hdi.iImage = lpColumn->iImage;
     }
 
-  if (lpColumn->mask & LVCF_IMAGE) 
-  {
-        hdi.mask |= HDI_IMAGE;
-    hdi.iImage = lpColumn->iImage;
+    if (lpColumn->mask & LVCF_ORDER) 
+    {
+      hdi.mask |= HDI_ORDER;
+      hdi.iOrder = lpColumn->iOrder;
     }
 
-  if (lpColumn->mask & LVCF_ORDER) 
-  {
-        hdi.mask |= HDI_ORDER;
-    hdi.iOrder = lpColumn->iOrder;
-    }
+    /* insert item in header control */
+    nNewColumn = SendMessageA(infoPtr->hwndHeader, HDM_INSERTITEMA,
+                             (WPARAM)nColumn, (LPARAM)&hdi);
 
-    nResult = SendMessageA (infoPtr->hwndHeader, HDM_INSERTITEMA,
-                           (WPARAM)nIndex, (LPARAM)&hdi);
-    if (nResult == -1)
-	return -1;
+    LISTVIEW_SetScroll(hwnd);
+    InvalidateRect(hwnd, NULL, FALSE);
+  }
 
-  /* increment column counter */
-    infoPtr->nColumnCount++;
-
-    return nResult;
+  return nNewColumn;
 }
 
-/* << LISTVIEW_InsertColumn32W >> */
+/* << LISTVIEW_InsertColumnW >> */
 
 /***
  * DESCRIPTION:
  * Inserts a new item in the listview control.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] LPLVITEM32A : item information
+ * [I] HWND : window handle
+ * [I] LPLVITEMA : item information
  *
  * RETURN:
  *   SUCCESS : new item index
  *   FAILURE : -1
  */
-static LRESULT LISTVIEW_InsertItemA(HWND hwnd, LPLVITEMA lpItem)
+static LRESULT LISTVIEW_InsertItemA(HWND hwnd, LPLVITEMA lpLVItem)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
   LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
-    LISTVIEW_ITEM *lpListItem;
-  INT nItem;
-    NMLISTVIEW nmlv;
-  LVITEMA lvItem;
-  INT nColumnWidth = 0;
-  INT nSmallIconWidth;
+  NMLISTVIEW nmlv;
+  INT nItem = -1;
+  HDPA hdpaSubItems;
+  LISTVIEW_ITEM *lpItem = NULL;
 
-  if (lpItem == NULL)
-	return -1;
-
-  if (lpItem->iSubItem != 0)
-	return -1;
-
-  /* allocate memory */
-  lpListItem = (LISTVIEW_ITEM *)COMCTL32_Alloc(sizeof(LISTVIEW_ITEM));
-  if (lpListItem == NULL)
-	return -1;
-
-  nSmallIconWidth = GetSystemMetrics(SM_CXSMICON);
-
-  /* initialize listview control item */
-  ZeroMemory(lpListItem, sizeof(LISTVIEW_ITEM));
-
-  /* copy only valid data */
-  if (lpItem->mask & LVIF_TEXT) 
+  if (lpLVItem != NULL)
   {
-	if (lpItem->pszText == LPSTR_TEXTCALLBACKA)
+    /* make sure it's not a subitem; cannot insert a subitem */
+    if (lpLVItem->iSubItem == 0)
     {
-      if ((lStyle & LVS_SORTASCENDING) || (lStyle & LVS_SORTDESCENDING))
-        return -1;
+      lpItem = (LISTVIEW_ITEM *)COMCTL32_Alloc(sizeof(LISTVIEW_ITEM));
+      if (lpItem != NULL)
+      {
+        ZeroMemory(lpItem, sizeof(LISTVIEW_ITEM));
+        if (LISTVIEW_InitItem(hwnd, lpItem, lpLVItem) == TRUE)
+        {
+          /* insert item in listview control data structure */
+          hdpaSubItems = DPA_Create(8);
+          if (hdpaSubItems != NULL)
+          {
+            nItem = DPA_InsertPtr(hdpaSubItems, 0, lpItem);
+            if (nItem != -1)
+            {
+              nItem = DPA_InsertPtr(infoPtr->hdpaItems, lpLVItem->iItem, 
+                                    hdpaSubItems);
+              if (nItem != -1)
+              {
+                /* manage item focus */
+                if (lpLVItem->mask & LVIF_STATE)
+                {
+                  if (lpLVItem->stateMask & LVIS_FOCUSED)
+                  {
+                    LISTVIEW_SetItemFocus(hwnd, nItem);
+                  }           
+                }
 
-      lpListItem->pszText = LPSTR_TEXTCALLBACKA;
-    }
-	else
-    {
-      nColumnWidth = SendMessageA(hwnd, LVM_GETSTRINGWIDTHA, 
-                                    (WPARAM)0, (LPARAM)lpItem->pszText);
+                /* send LVN_INSERTITEM notification */
+                ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
+                nmlv.hdr.hwndFrom = hwnd;
+                nmlv.hdr.idFrom = lCtrlId;
+                nmlv.hdr.code = LVN_INSERTITEM;
+                nmlv.iItem = nItem;
+                nmlv.lParam = lpItem->lParam;;
+                ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
 
-      /* add padding for separating columns */
-      nColumnWidth += 10;
-
-      /* calculate column width; make sure it's at least 96 pixels */
-      if (nColumnWidth < 96)
-        nColumnWidth = 96;
-        
-      Str_SetPtrA(&lpListItem->pszText, lpItem->pszText);
+                /* set scrolling parameters */
+                LISTVIEW_SetScroll(hwnd);
+                
+                /* refresh client area */
+                InvalidateRect(hwnd, NULL, FALSE);
+              }
+            }
+          }
+        }
+      }
     }
   }
 
-  if (lpItem->mask & LVIF_STATE)
+  /* free memory if unsuccessful */
+  if ((nItem == -1) && (lpItem != NULL))
   {
-    if (lpItem->stateMask & LVIS_FOCUSED)
-    {
-      /* clear LVIS_FOCUSED states */
-      ZeroMemory(&lvItem, sizeof(LVITEMA));
-      lvItem.stateMask = LVIS_FOCUSED;
-      lvItem.state = 0;
-      SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&lvItem);
-
-      /* set focused item index */
-      infoPtr->nFocusedItem = lpItem->iItem;
-    }
-
-    lpListItem->state = lpItem->state & lpItem->stateMask;
+    COMCTL32_Free(lpItem);
   }
 
-    if (lpItem->mask & LVIF_IMAGE)
-    lpListItem->iImage = lpItem->iImage;
-
-    if (lpItem->mask & LVIF_PARAM)
-    lpListItem->lParam = lpItem->lParam;
-
-    if (lpItem->mask & LVIF_INDENT)
-    lpListItem->iIndent = lpItem->iIndent;
-
-  /* insert item in listview control data structure */
-  nItem = DPA_InsertPtr(infoPtr->hdpaItems, lpItem->iItem, lpListItem);
-  if (nItem == -1)
-    return -1;
-
-  /* increment item counter */
-    infoPtr->nItemCount++;
-
-  /* calculate column width */
-  if (infoPtr->himlSmall != NULL)
-    nColumnWidth += nSmallIconWidth;
-
-  /* calculate column width */
-  if (infoPtr->himlState != NULL)
-    nColumnWidth += nSmallIconWidth;
-
-  /* set column width */
-   if (nColumnWidth > infoPtr->nColumnWidth)
-     infoPtr->nColumnWidth = nColumnWidth;
-
-  /* set drawing data */
-  LISTVIEW_SetScroll(hwnd);
-
-  /* send LVN_INSERTITEM notification */
-    ZeroMemory (&nmlv, sizeof (NMLISTVIEW));
-  nmlv.hdr.hwndFrom = hwnd;
-  nmlv.hdr.idFrom = lCtrlId;
-    nmlv.hdr.code     = LVN_INSERTITEM;
-  nmlv.iItem = nItem;
-  SendMessageA(GetParent (hwnd), WM_NOTIFY, (WPARAM)lCtrlId, 
-                 (LPARAM)&nmlv);
-
-  InvalidateRect(hwnd, NULL, FALSE);
-  UpdateWindow(hwnd);
-
   return nItem;
 }
 
-/* << LISTVIEW_InsertItem32W >> */
+/* << LISTVIEW_InsertItemW >> */
 
 /***
  * DESCRIPTION:
  * Redraws a range of items.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : first item
- * [I] INT32 : last item
+ * [I] HWND : window handle
+ * [I] INT : first item
+ * [I] INT : last item
  *
  * RETURN:
  *   SUCCESS : TRUE
@@ -2389,19 +3769,22 @@
 static LRESULT LISTVIEW_RedrawItems(HWND hwnd, INT nFirst, INT nLast)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); 
+  BOOL bResult = FALSE;
+  RECT rc;
 
-  if (nFirst > nLast)
-    return FALSE;
+  if (nFirst <= nLast)
+  {
+    if ((nFirst >= 0) && (nFirst < GETITEMCOUNT(infoPtr)))
+    {
+      if ((nLast >= 0) && (nLast < GETITEMCOUNT(infoPtr)))
+      {
+        /* bResult = */
+        InvalidateRect(hwnd, &rc, FALSE);
+      }
+    }
+  }
 
-  if ((nFirst < 0) || (nFirst >= infoPtr->nItemCount))
-    return FALSE;
-
-  if ((nLast < 0) || (nLast >= infoPtr->nItemCount))
-    return FALSE;
-
-  /* TO DO */
-
-  return TRUE;
+  return bResult;
 }
 
 /***
@@ -2409,9 +3792,9 @@
  * Scrolls the content of a listview.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : amount of horizontal scrolling
- * [I] INT32 : amount of vertical scrolling
+ * [I] HWND : window handle
+ * [I] INT : amount of horizontal scrolling
+ * [I] INT : amount of vertical scrolling
  *
  * RETURN:
  *   SUCCESS : TRUE
@@ -2420,39 +3803,57 @@
 static LRESULT LISTVIEW_Scroll(HWND hwnd, INT nHScroll, INT nVScroll)
 {
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  INT nScrollPos = 0;
   BOOL bResult = FALSE;
-  INT nHScrollPos;
   INT nMinRange;
   INT nMaxRange;
 
-  if (lStyle & LVS_LIST)
+  if (lStyle & WS_HSCROLL)
   {
-    nHScrollPos = GetScrollPos(hwnd, SB_HORZ);
+    nScrollPos = GetScrollPos(hwnd, SB_HORZ);
     GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
+    nScrollPos += nHScroll;
 
-    if ((nMinRange <= nHScrollPos + nHScroll) && 
-        (nHScrollPos + nHScroll <= nMaxRange))
+    if ((LVS_TYPEMASK & lStyle) == LVS_LIST)
     {
-      bResult = TRUE;
-      nHScrollPos += nHScroll;
-      SetScrollPos(hwnd, SB_HORZ, nHScrollPos, TRUE);
-
-      /* refresh client area */
-      InvalidateRect(hwnd, NULL, TRUE);
-      UpdateWindow(hwnd);
+      nScrollPos = GetScrollPos(hwnd, SB_HORZ);
+      GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
+      nScrollPos += nHScroll;
+      if ((nMinRange <= nScrollPos) && (nScrollPos <= nMaxRange))
+      {
+        bResult = TRUE;
+        SetScrollPos(hwnd, SB_HORZ, nScrollPos, TRUE);
+      }
     }
-  }  
-  else if (lStyle & LVS_REPORT)
-  {
-    /* TO DO */
-}
-  else if (lStyle & LVS_SMALLICON)
-  {
-    /* TO DO */
+    else
+    {
+      /* TO DO */
+    }
   }
-  else if (lStyle & LVS_ICON)
+  
+  if (lStyle & WS_VSCROLL)
   {
-    /* TO DO */
+    if ((LVS_TYPEMASK & lStyle) == LVS_REPORT)
+    {
+      nScrollPos = GetScrollPos(hwnd, SB_VERT);
+      GetScrollRange(hwnd, SB_VERT, &nMinRange, &nMaxRange);
+      nScrollPos += nVScroll;
+      if ((nMinRange <= nScrollPos) && (nScrollPos <= nMaxRange))
+      {
+        bResult = TRUE;
+        SetScrollPos(hwnd, SB_VERT, nScrollPos, TRUE);
+      }
+    }
+    else
+    {
+      /* TO DO */
+    }
+  }
+
+  if (bResult == TRUE)
+  {
+    /* refresh client area */
+    InvalidateRect(hwnd, NULL, TRUE);
   }
 
   return bResult; 
@@ -2463,19 +3864,41 @@
  * Sets the background color.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * [I] COLORREF : background color
  *
  * RETURN:
  *   SUCCESS : TRUE
  *   FAILURE : FALSE
-*/
+ */
 static LRESULT LISTVIEW_SetBkColor(HWND hwnd, COLORREF clrBk)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
 
   infoPtr->clrBk = clrBk;
   InvalidateRect(hwnd, NULL, TRUE);
+  
+  return TRUE;
+}
+
+/***
+ * DESCRIPTION:
+ * Sets the callback mask. This mask will be used when the parent
+ * window stores the state information (some or all).
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] UINT : state mask
+ *
+ * RETURN:
+ *   SUCCESS : TRUE
+ *   FAILURE : FALSE
+ */
+static BOOL LISTVIEW_SetCallbackMask(HWND hwnd, UINT uMask)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+
+  infoPtr->uCallbackMask = uMask;
 
   return TRUE;
 }
@@ -2485,70 +3908,101 @@
  * Sets column attributes.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : column index
- * [I] LPLVCOLUMN32A : column information
+ * [I] HWND : window handle
+ * [I] INT : column index
+ * [I] LPLVCOLUMNA : column attributes
  *
  * RETURN:
  *   SUCCESS : TRUE
  *   FAILURE : FALSE
  */
-static LRESULT LISTVIEW_SetColumnA(HWND hwnd, INT nIndex, 
+static LRESULT LISTVIEW_SetColumnA(HWND hwnd, INT nColumn, 
                                      LPLVCOLUMNA lpColumn)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-    HDITEMA hdi;
+  HDITEMA hdi;
+  BOOL bResult = FALSE;
 
-  if (lpColumn == NULL)
-	return -1;
-
-  /* initialize memory */
-    ZeroMemory (&hdi, sizeof(HDITEMA));
-
-  if (lpColumn->mask & LVCF_FMT) 
+  if ((lpColumn != NULL) && (nColumn >= 0) && 
+      (nColumn < Header_GetItemCount(infoPtr->hwndHeader)))
   {
-	if (nIndex == 0)
-	    hdi.fmt |= HDF_LEFT;
-    else if (lpColumn->fmt & LVCFMT_LEFT)
-	    hdi.fmt |= HDF_LEFT;
-    else if (lpColumn->fmt & LVCFMT_RIGHT)
-	    hdi.fmt |= HDF_RIGHT;
-    else if (lpColumn->fmt & LVCFMT_CENTER)
-	    hdi.fmt |= HDF_CENTER;
+    /* initialize memory */
+    ZeroMemory(&hdi, sizeof(HDITEMA));
 
-    if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES)
-	    hdi.fmt |= HDF_IMAGE;
-	    
-	hdi.mask |= HDI_FORMAT;
+    if (lpColumn->mask & LVCF_FMT) 
+    {
+      /* format member is valid */
+      hdi.mask |= HDI_FORMAT;
+
+      /* set text alignment (leftmost column must be left-aligned) */
+      if (nColumn == 0)
+      {
+        hdi.fmt |= HDF_LEFT;
+      }
+      else
+      {
+        if (lpColumn->fmt & LVCFMT_LEFT)
+        {
+          hdi.fmt |= HDF_LEFT;
+        }
+        else if (lpColumn->fmt & LVCFMT_RIGHT)
+        {
+          hdi.fmt |= HDF_RIGHT;
+        }
+        else if (lpColumn->fmt & LVCFMT_CENTER)
+        {
+          hdi.fmt |= HDF_CENTER;
+        }
+      }
+      
+      if (lpColumn->fmt & LVCFMT_BITMAP_ON_RIGHT)
+      {
+        hdi.fmt |= HDF_BITMAP_ON_RIGHT;
+      }
+
+      if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES)
+      {
+        hdi.fmt |= HDF_IMAGE;
+      }
+      
+      if (lpColumn->fmt & LVCFMT_IMAGE)
+      {
+        hdi.fmt |= HDF_IMAGE;
+        hdi.iImage = I_IMAGECALLBACK;
+      }
     }
 
-  if (lpColumn->mask & LVCF_WIDTH) 
-  {
-        hdi.mask |= HDI_WIDTH;
-    hdi.cxy = lpColumn->cx;
+    if (lpColumn->mask & LVCF_WIDTH) 
+    {
+      hdi.mask |= HDI_WIDTH;
+      hdi.cxy = lpColumn->cx;
     }
     
-  if (lpColumn->mask & LVCF_TEXT) 
-  {
-        hdi.mask |= (HDI_TEXT | HDI_FORMAT);
-    hdi.pszText = lpColumn->pszText;
-	hdi.fmt |= HDF_STRING;
+    if (lpColumn->mask & LVCF_TEXT) 
+    {
+      hdi.mask |= HDI_TEXT | HDI_FORMAT;
+      hdi.pszText = lpColumn->pszText;
+      hdi.cchTextMax = lstrlenA(lpColumn->pszText);
+      hdi.fmt |= HDF_STRING;
+    }
+  
+    if (lpColumn->mask & LVCF_IMAGE) 
+    {
+      hdi.mask |= HDI_IMAGE;
+      hdi.iImage = lpColumn->iImage;
     }
 
-  if (lpColumn->mask & LVCF_IMAGE) 
-  {
-        hdi.mask |= HDI_IMAGE;
-    hdi.iImage = lpColumn->iImage;
+    if (lpColumn->mask & LVCF_ORDER) 
+    {
+      hdi.mask |= HDI_ORDER;
+      hdi.iOrder = lpColumn->iOrder;
     }
 
-  if (lpColumn->mask & LVCF_ORDER) 
-  {
-        hdi.mask |= HDI_ORDER;
-    hdi.iOrder = lpColumn->iOrder;
-    }
-
-    return (LRESULT)SendMessageA (infoPtr->hwndHeader, HDM_SETITEMA,
-                                  (WPARAM)nIndex, (LPARAM)&hdi);
+    /* set header item attributes */
+    bResult = Header_SetItemA(infoPtr->hwndHeader, nColumn, &hdi);
+  }
+  
+  return bResult;
 }
 
 /***
@@ -2556,36 +4010,38 @@
  * Sets image list.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : image list type  
+ * [I] HWND : window handle
+ * [I] INT : image list type  
  * [I] HIMAGELIST : image list handle
  *
  * RETURN:
  *   SUCCESS : old image list
  *   FAILURE : NULL
-*/
+ */
 static LRESULT LISTVIEW_SetImageList(HWND hwnd, INT nType, HIMAGELIST himl)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-    HIMAGELIST himlTemp = 0;
+  HIMAGELIST himlTemp = 0;
 
   switch (nType) 
   {
-	case LVSIL_NORMAL:
-	    himlTemp = infoPtr->himlNormal;
+  case LVSIL_NORMAL:
+    himlTemp = infoPtr->himlNormal;
     infoPtr->himlNormal = himl;
-	    return (LRESULT)himlTemp;
-	case LVSIL_SMALL:
-	    himlTemp = infoPtr->himlSmall;
-    infoPtr->himlSmall = himl;
-	    return (LRESULT)himlTemp;
-	case LVSIL_STATE:
-	    himlTemp = infoPtr->himlState;
-    infoPtr->himlState = himl;
-	    return (LRESULT)himlTemp;
-    }
+    return (LRESULT)himlTemp;
 
-    return (LRESULT)NULL;
+  case LVSIL_SMALL:
+    himlTemp = infoPtr->himlSmall;
+    infoPtr->himlSmall = himl;
+    return (LRESULT)himlTemp;
+
+  case LVSIL_STATE:
+    himlTemp = infoPtr->himlState;
+    infoPtr->himlState = himl;
+    return (LRESULT)himlTemp;
+  }
+
+  return (LRESULT)NULL;
 }
 
 
@@ -2594,120 +4050,64 @@
  * Sets item attributes.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] LPLVITEM32 : item information 
+ * [I] HWND : window handle
+ * [I] LPLVITEM : item information 
  *
  * RETURN:
  *   SUCCESS : TRUE
  *   FAILURE : FALSE
  */
-static LRESULT LISTVIEW_SetItemA(HWND hwnd, LPLVITEMA lpItem)
+static LRESULT LISTVIEW_SetItemA(HWND hwnd, LPLVITEMA lpLVItem)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
-  LISTVIEW_ITEM *lpListItem;
-    NMLISTVIEW nmlv;
+  BOOL bResult = FALSE;
 
-  if (lpItem == NULL)
-	return FALSE;
-
-    if ((lpItem->iItem < 0) || (lpItem->iItem >= infoPtr->nItemCount))
-	return FALSE;
-
-    /* send LVN_ITEMCHANGING notification */
-    ZeroMemory (&nmlv, sizeof (NMLISTVIEW));
-  nmlv.hdr.hwndFrom = hwnd;
-  nmlv.hdr.idFrom = lCtrlId;
-    nmlv.hdr.code     = LVN_ITEMCHANGING;
-    nmlv.iItem        = lpItem->iItem;
-    nmlv.iSubItem     = lpItem->iSubItem;
-    nmlv.uChanged     = lpItem->mask;
-  if (SendMessageA(GetParent(hwnd), WM_NOTIFY,  (WPARAM)lCtrlId, 
-                     (LPARAM)&nmlv) == FALSE) 
-	return FALSE;
-
-  /* get item */
-  lpListItem = DPA_GetPtr(infoPtr->hdpaItems, lpItem->iItem);
-  if (lpListItem == NULL)
-    return FALSE;
-
-  /* copy valid data */
-  if (lpItem->iSubItem > 0)
+  if (lpLVItem != NULL)
   {
-    /* verify existance of sub-item */
-    lpListItem += lpItem->iSubItem;
-    if (lpListItem == NULL)
-	return FALSE;
-
-    /* exit if indent attribute is valid */
-    if (lpItem->mask & LVIF_INDENT)
-	return FALSE;
-
-    if (lpItem->mask & LVIF_IMAGE)
+    if ((lpLVItem->iItem >= 0) && (lpLVItem->iItem < GETITEMCOUNT(infoPtr)))
     {
-      /* set sub-item attribute */
-    }
-
-	}
-  else
-  {
-    if (lpItem->mask & LVIF_STATE)
-    {
-      lpListItem->state &= ~lpItem->stateMask;
-      lpListItem->state |= (lpItem->state & lpItem->stateMask);
-    }
-
-    if (lpItem->mask & LVIF_IMAGE)
-      lpListItem->iImage = lpItem->iImage;
-
-    if (lpItem->mask & LVIF_PARAM)
-      lpListItem->lParam = lpItem->lParam;
-
-    if (lpItem->mask & LVIF_INDENT)
-      lpListItem->iIndent = lpItem->iIndent;
-  }
-  
-  if (lpItem->mask & LVIF_TEXT) 
-  {
-    if (lpItem->pszText == LPSTR_TEXTCALLBACKA) 
-    {
-      if ((lpListItem->pszText != NULL) &&
-          (lpListItem->pszText != LPSTR_TEXTCALLBACKA))
-        COMCTL32_Free (lpListItem->pszText);
-
-      lpListItem->pszText = LPSTR_TEXTCALLBACKA;
-    }
-    else 
-    {
-      if (lpListItem->pszText == LPSTR_TEXTCALLBACKA)
-        lpListItem->pszText = NULL;
-      
-      if (Str_SetPtrA(&lpListItem->pszText, lpItem->pszText) == FALSE)
-        return FALSE;
+      if (lpLVItem->iSubItem == 0)
+      {
+        bResult = LISTVIEW_SetItem(hwnd, lpLVItem);
+      }
+      else
+      {
+        bResult = LISTVIEW_SetSubItem(hwnd, lpLVItem);
+      }
     }
   }
 
-    /* send LVN_ITEMCHANGED notification */
-    nmlv.hdr.code = LVN_ITEMCHANGED;
-  SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, 
-                 (LPARAM)&nmlv);
 
-    return TRUE;
+  return bResult;
 }
 
-/* << LISTVIEW_SetItem32W >> */
+/* << LISTVIEW_SetItemW >> */
 
-/* LISTVIEW_SetItemCount*/
+/***
+ * DESCRIPTION:
+ * Preallocates memory.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] INT : item count (prjected number of items)
+ *
+ * RETURN:
+ * None
+ */
+static VOID LISTVIEW_SetItemCount(HWND hwnd, INT nItemCount)
+{
+  /* TO DO */
+}
 
 /***
  * DESCRIPTION:
  * Sets item position.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : item index
- * [I] INT32 : x coordinate
- * [I] INT32 : y coordinate
+ * [I] HWND : window handle
+ * [I] INT : item index
+ * [I] INT : x coordinate
+ * [I] INT : y coordinate
  *
  * RETURN:
  *   SUCCESS : TRUE
@@ -2718,27 +4118,18 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  BOOL bResult = FALSE;
 
-  if ((nItem < 0) || (nItem >= infoPtr->nItemCount))
-	return FALSE;
-
-  if ((lStyle & LVS_ICON) && (lStyle & LVS_SMALLICON))
+  if ((nItem >= 0) || (nItem < GETITEMCOUNT(infoPtr)))
   {
-    /* get item */
-
-    /* set position of item */
-
-    /* refresh */
-    if (lStyle & LVS_AUTOARRANGE)
+    if (((lStyle & LVS_TYPEMASK) == LVS_ICON) || 
+        ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON))
     {
-      InvalidateRect(hwnd, NULL, FALSE);
-      UpdateWindow(hwnd);
+      /* TO DO */
     }
+  }
 
-    return TRUE;
-}
-
-  return FALSE;
+  return bResult;
 }
 
 /***
@@ -2746,48 +4137,84 @@
  * Sets the state of one or many items.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I]INT32 : item index
- * [I] LPLVITEM32 : item information 
+ * [I] HWND : window handle
+ * [I]INT : item index
+ * [I] LPLVITEM : item or subitem info
  *
  * RETURN:
  *   SUCCESS : TRUE
  *   FAILURE : FALSE
-*/
+ */
 static LRESULT LISTVIEW_SetItemState(HWND hwnd, INT nItem, 
-                                     LPLVITEMA lpItem)
+                                     LPLVITEMA lpLVItem)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LISTVIEW_ITEM *lpListItem;
+  BOOL bResult = FALSE;
+  LVITEMA lvItem;
   INT i;
 
   if (nItem == -1)
   {
-    /* apply to all the items */
-    for (i = 0; i< infoPtr->nItemCount; i++)
+    bResult = TRUE;
+    ZeroMemory(&lvItem, sizeof(LVITEMA));
+    lvItem.mask = LVIF_STATE;
+    lvItem.state = lpLVItem->state;
+    lvItem.stateMask = lpLVItem->stateMask;
+    
+    /* apply to all items */
+    for (i = 0; i< GETITEMCOUNT(infoPtr); i++)
     {
-      lpListItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, i);
-      if (lpListItem == NULL)
-	return FALSE;
-
-      lpListItem->state &= ~lpItem->stateMask;
-      lpListItem->state |= (lpItem->state & lpItem->stateMask);
-	}
-	}
-  else if ((nItem >= 0) && (nItem < infoPtr->nItemCount))
-  {
-    lpListItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem);
-    if (lpListItem == NULL)
-      return FALSE;
-
-    /* set state */
-    lpListItem->state &= ~lpItem->stateMask;
-    lpListItem->state |= (lpItem->state & lpItem->stateMask);
+      lvItem.iItem = i;
+      if (ListView_SetItemA(hwnd, &lvItem) == FALSE)
+      {
+        bResult = FALSE;
+      }
     }
+  }
   else
-    return FALSE;
+  {
+    ZeroMemory(&lvItem, sizeof(LVITEMA));
+    lvItem.mask = LVIF_STATE;
+    lvItem.state = lpLVItem->state;
+    lvItem.stateMask = lpLVItem->stateMask;
+    lvItem.iItem = nItem;
+    bResult = ListView_SetItemA(hwnd, &lvItem);
+  }
 
-    return TRUE;
+  return bResult;
+}
+
+/***
+ * DESCRIPTION:
+ * Sets the text of an item or subitem.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] INT : item index
+ * [I] LPLVITEMA : item or subitem info
+ *
+ * RETURN:
+ *   SUCCESS : TRUE
+ *   FAILURE : FALSE
+ */
+static BOOL LISTVIEW_SetItemTextA(HWND hwnd, INT nItem, 
+                                      LPLVITEMA lpLVItem)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  BOOL bResult = FALSE;
+  LVITEMA lvItem;
+
+  if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
+  {
+    ZeroMemory(&lvItem, sizeof(LVITEMA));
+    lvItem.mask = LVIF_TEXT;
+    lvItem.pszText = lpLVItem->pszText;
+    lvItem.iItem = nItem;
+    lvItem.iSubItem = lpLVItem->iSubItem;
+    bResult = ListView_SetItemA(hwnd, &lvItem);
+  }
+  
+  return bResult;
 }
 
 /***
@@ -2795,20 +4222,20 @@
  * Sets the text background color.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * [I] COLORREF : text background color
  *
  * RETURN:
  *   SUCCESS : TRUE
  *   FAILURE : FALSE
-*/
+ */
 static LRESULT LISTVIEW_SetTextBkColor(HWND hwnd, COLORREF clrTextBk)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
 
   infoPtr->clrTextBk = clrTextBk;
 
-    return TRUE;
+  return TRUE;
 }
 
 /***
@@ -2816,7 +4243,7 @@
  * Sets the text background color.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * [I] COLORREF : text color 
  *
  * RETURN:
@@ -2829,61 +4256,63 @@
 
   infoPtr->clrText = clrText;
 
-    return TRUE;
+  return TRUE;
 }
 
 /***
  * DESCRIPTION:
- * ??
+ * Sort items.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  *
  * RETURN:
  *   SUCCESS : TRUE
  *   FAILURE : FALSE
-*/
+ */
 static LRESULT LISTVIEW_SortItems(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
-/*  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLong32A(hwnd, 0); */
+  FIXME (listview, "empty stub!\n");
 
-    FIXME (listview, "empty stub!\n");
-
-    return TRUE;
+  return TRUE;
 }
 
 /***
  * DESCRIPTION:
- * Updates an items.
+ * Updates an items or rearranges the listview control.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : item index
+ * [I] HWND : window handle
+ * [I] INT : item index
  *
  * RETURN:
  *   SUCCESS : TRUE
  *   FAILURE : FALSE
-*/
+ */
 static LRESULT LISTVIEW_Update(HWND hwnd, INT nItem)
 {
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-  RECT rcItemRect;
   BOOL bResult = FALSE;
+  RECT rc;
 
-  if ((nItem >= 0) || (nItem < infoPtr->nItemCount))
+  if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
   {
-    /* get item bounding rectangle */
-    rcItemRect.left = LVIR_BOUNDS;
-    SendMessageA(hwnd, LVM_GETITEMRECT, (WPARAM)nItem, 
-                   (LPARAM)&rcItemRect);
-
-    InvalidateRect(hwnd, &rcItemRect, FALSE);
+    bResult = TRUE;
 
     /* rearrange with default alignment style */
-    if ((lStyle & LVS_AUTOARRANGE) && 
-        ((lStyle & LVS_ICON) || (lStyle & LVS_SMALLICON)))
-      SendMessageA(hwnd, LVM_ARRANGE, (WPARAM)LVA_DEFAULT, (LPARAM)0);
+    if ((lStyle & LVS_AUTOARRANGE) && (((lStyle & LVS_TYPEMASK) == LVS_ICON) ||
+        ((lStyle & LVS_TYPEMASK)  == LVS_SMALLICON)))
+    {
+      ListView_Arrange(hwnd, 0);
+    }
+    else
+    {
+      /* get item bounding rectangle */
+      rc.left = LVIR_BOUNDS;
+      ListView_GetItemRect(hwnd, nItem, &rc);
+      InvalidateRect(hwnd, &rc, FALSE);
+    }
   }
 
   return bResult;
@@ -2894,7 +4323,7 @@
  * Creates a listview control.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  *
  * RETURN:
  * Zero
@@ -2902,80 +4331,120 @@
 static LRESULT LISTVIEW_Create(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); 
+  LPCREATESTRUCTA lpcs = (LPCREATESTRUCTA)lParam;
   LOGFONTA logFont;
-  HFONT hOldFont;
-  HDC hdc;
-  TEXTMETRICA tm;
-  INT nSmallIconHeight;
+  HDLAYOUT hl;
+  WINDOWPOS wp;
+
+  /* determine the type of structures to use */
+  infoPtr->notifyFormat = SendMessageA(GetParent(hwnd), WM_NOTIFYFORMAT, 
+                                       (WPARAM)hwnd, (LPARAM)NF_QUERY);
+  if (infoPtr->notifyFormat != NFR_ANSI)
+  {
+    FIXME (listview, "ANSI notify format is NOT used\n");
+  }
 
   /* initialize color information  */
   infoPtr->clrBk = GetSysColor(COLOR_WINDOW);
   infoPtr->clrText = GetSysColor(COLOR_WINDOWTEXT);
   infoPtr->clrTextBk = GetSysColor(COLOR_WINDOW); 
 
-    /* get default font (icon title) */
-    SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
-    infoPtr->hDefaultFont = CreateFontIndirectA (&logFont);
-    infoPtr->hFont = infoPtr->hDefaultFont;
+  /* set default values */
+  infoPtr->uCallbackMask = 0;
+  infoPtr->nFocusedItem = -1;
+  infoPtr->nSelectionMark = -1;
+  infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON);
+  infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON);
+  ZeroMemory(&infoPtr->rcList, sizeof(RECT));
 
-  /* initialize column width */
-  infoPtr->nColumnWidth = 96;
+  /* get default font (icon title) */
+  SystemParametersInfoA(SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
+  infoPtr->hDefaultFont = CreateFontIndirectA(&logFont);
+  infoPtr->hFont = infoPtr->hDefaultFont;
+  
+  /* create header */
+  infoPtr->hwndHeader =	CreateWindowA(WC_HEADERA, (LPCSTR)NULL, 
+                                        WS_CHILD | HDS_HORZ | HDS_BUTTONS , 
+                                        0, 0, 0, 0, hwnd, (HMENU)0, 
+                                        lpcs->hInstance, NULL);
 
-  /* get text height */
-  hdc = GetDC(hwnd);
-  hOldFont = SelectObject(hdc, infoPtr->hFont);
-  GetTextMetricsA(hdc, &tm);
+  /* set header font */
+  SendMessageA(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)infoPtr->hFont, 
+               (LPARAM)TRUE);
 
-  /* initialize item height with padding */
-  if (!(lStyle & LVS_ICON)) 
+  switch (lpcs->style & LVS_TYPEMASK)
   {
-    nSmallIconHeight = GetSystemMetrics(SM_CYSMICON);
-    infoPtr->nItemHeight = max(tm.tmHeight, nSmallIconHeight) + 2;
+  case LVS_REPORT:
+    /* reset header */
+    hl.prc = &infoPtr->rcList;
+    hl.pwpos = &wp;
+    Header_Layout(infoPtr->hwndHeader, &hl);
+    SetWindowPos(infoPtr->hwndHeader, hwnd, wp.x, wp.y, wp.cx, wp.cy, 
+                   wp.flags);
+
+    /* set new top coord */
+    infoPtr->rcList.top = wp.cy;
+
+    /* display header */
+    ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL);
+    break;
+
+  case LVS_LIST:
+    break;
+
+  default:
+    /*  temporary (until there is support) */
+    SetWindowLongA(hwnd, GWL_STYLE, 
+                     (lpcs->style & ~LVS_TYPEMASK) | LVS_LIST);
   }
 
-  SelectObject(hdc, hOldFont);
-  ReleaseDC(hwnd, hdc);
-
- /* create header */
-  infoPtr->hwndHeader =	CreateWindowA(WC_HEADERA, "", lStyle, 0, 0, 0, 0, 
-                                        hwnd, (HMENU)0, 
-                                        GetWindowLongA(hwnd, GWL_HINSTANCE),
-                                        NULL);
-    /* set header font */
-  SendMessageA(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)infoPtr->hFont, 
-                 (LPARAM)TRUE);
+  /* TEMPORARY */
+  LISTVIEW_UnsupportedStyles(lpcs->style);
 
   /* allocate memory */
-    infoPtr->hdpaItems = DPA_Create (10);
+  infoPtr->hdpaItems = DPA_Create(10);
 
-    return 0;
+  /* set view dependent information */
+  LISTVIEW_SetViewInfo(hwnd);
+
+  return 0;
 }
 
 
-static LRESULT
-LISTVIEW_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
+/***
+ * DESCRIPTION:
+ * Destroys the window
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * 
+ * RETURN:
+ * Zero
+ */
+static LRESULT LISTVIEW_Destroy(HWND hwnd)
 {
-    LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
 
-    /* delete all items */
-    LISTVIEW_DeleteAllItems(hwnd);
+  /* delete all items */
+  LISTVIEW_DeleteAllItems(hwnd);
 
-    /* destroy dpa */
-    DPA_Destroy (infoPtr->hdpaItems);
+  /* destroy dpa */
+  DPA_Destroy(infoPtr->hdpaItems);
 
-    /* destroy header */
-    if (infoPtr->hwndHeader)
-	DestroyWindow (infoPtr->hwndHeader);
+  /* destroy header */
+  if (infoPtr->hwndHeader)
+  {
+    DestroyWindow(infoPtr->hwndHeader);
+  }
 
-    /* destroy font */
-    infoPtr->hFont = (HFONT)0;
-    if (infoPtr->hDefaultFont)
-	DeleteObject (infoPtr->hDefaultFont);
+  /* destroy font */
+  infoPtr->hFont = (HFONT)0;
+  if (infoPtr->hDefaultFont)
+  {
+    DeleteObject(infoPtr->hDefaultFont);
+  }
 
-    infoPtr->nColumnWidth = 96;
-
-    return 0;
+  return 0;
 }
 
 /***
@@ -2983,26 +4452,28 @@
  * Erases the background of the listview control
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- *
+ * [I] HWND : window handle
+ * [I] WPARAM : device context handle
+ * [I] LPARAM : not used
+ * 
  * RETURN:
  *   SUCCESS : TRUE
  *   FAILURE : FALSE
  */
-static LRESULT LISTVIEW_EraseBackground(HWND hwnd, WPARAM wParam, LPARAM lParam)
+static LRESULT LISTVIEW_EraseBackground(HWND hwnd, WPARAM wParam, 
+                                        LPARAM lParam)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   BOOL bResult;
 
   if (infoPtr->clrBk == CLR_NONE) 
+  {
     bResult = SendMessageA(GetParent(hwnd), WM_ERASEBKGND, wParam, lParam);
+  }
   else 
   {
     HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk);
-    RECT   clientRect;
-
-    GetClientRect(hwnd, &clientRect);
-    FillRect((HDC)wParam, &clientRect, hBrush);
+    FillRect((HDC)wParam, &infoPtr->rcList, hBrush);
     DeleteObject(hBrush);
     bResult = TRUE;
   }
@@ -3015,7 +4486,7 @@
  * Gets the listview control font.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  *
  * RETURN:
  * Font handle.
@@ -3032,55 +4503,210 @@
  * Performs horizontal scrolling.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : scroll code
- * [I] INT32 : scroll position
- * [I] HWND32 : scrollbar control window handle
+ * [I] HWND : window handle
+ * [I] INT : scroll code
+ * [I] INT : scroll position
+ * [I] HWND : scrollbar control window handle
+ *
+ * RETURN:
+ * Zero
+ */
+static LRESULT LISTVIEW_VScroll(HWND hwnd, INT nScrollCode, 
+                                INT nScroll, HWND hScrollWnd)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
+  INT nScrollPos, nOldScrollPos;
+  INT nMinRange;
+  INT nMaxRange;
+
+  GetScrollRange(hwnd, SB_VERT, &nMinRange, &nMaxRange);
+  nOldScrollPos = nScrollPos = GetScrollPos(hwnd, SB_VERT);
+
+  switch (LVS_TYPEMASK & lStyle)
+  {
+  case LVS_REPORT:
+    switch (nScrollCode)
+    {
+    case SB_LINEUP:
+      if (nScrollPos > nMinRange)
+      {
+        nScrollPos--;
+      }
+      break;
+    case SB_LINEDOWN:
+      if (nScrollPos < nMaxRange)
+      {
+        nScrollPos++;
+      }
+      break;
+    case SB_PAGEUP:
+      if (nScrollPos > nMinRange + infoPtr->nCountPerColumn)
+      {
+        nScrollPos -= infoPtr->nCountPerColumn;
+      }
+      else
+      {
+        nScrollPos = nMinRange;
+      }
+      break;
+    case SB_PAGEDOWN:
+      if (nScrollPos < nMaxRange - infoPtr->nCountPerColumn)
+      {
+        nScrollPos += infoPtr->nCountPerColumn;
+      }
+      else
+      {
+        nScrollPos = nMaxRange;
+      }
+      break;
+    case SB_THUMBPOSITION:
+      nScrollPos = nScroll;
+      break;
+    }
+    break;
+
+    default:
+      /* TO DO */
+  }
+
+  /* set new scroll position */
+  if (nScrollPos != nOldScrollPos)
+  {
+    SetScrollPos(hwnd, SB_VERT, nScrollPos, TRUE);
+    
+    /* refresh client area */
+    InvalidateRect(hwnd, NULL, TRUE);
+  }
+
+  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 nScrollPos, HWND hScrollWnd)
+                                INT nScroll, HWND hScrollWnd)
 {
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-  INT nHScrollPos;
+  INT nScrollPos, nOldScrollPos;
   INT nMinRange;
   INT nMaxRange;
 
   GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
-  nHScrollPos = GetScrollPos(hwnd, SB_HORZ);
+  nOldScrollPos = nScrollPos = GetScrollPos(hwnd, SB_HORZ);
 
-  if (lStyle & LVS_LIST)
+  switch (LVS_TYPEMASK & lStyle)
   {
+  case LVS_LIST:
+
+    /* list display mode horizontal scrolling */
     switch (nScrollCode)
     {
     case SB_LINELEFT:
-      if (nHScrollPos > nMinRange)
-        nHScrollPos--;
+      if (nScrollPos > nMinRange)
+      {
+        nScrollPos--;
+      }
       break;
     case SB_LINERIGHT:
-      if (nHScrollPos < nMaxRange)
-        nHScrollPos++;
+      if (nScrollPos < nMaxRange)
+      {
+        nScrollPos++;
+      }
       break;
     case SB_PAGELEFT:
-      if (nHScrollPos > nMinRange)
-        nHScrollPos--;
+      if (nScrollPos > nMinRange)
+      {
+        nScrollPos = max(nMinRange, nScrollPos - infoPtr->nCountPerRow);
+      }
+      else
+      {
+        nScrollPos = nMinRange;
+      }
       break;
     case SB_PAGERIGHT:
-      if (nHScrollPos < nMaxRange)
-        nHScrollPos++;
+      if (nScrollPos < nMaxRange - 1)
+      {
+        nScrollPos = min(nMaxRange, nScrollPos + infoPtr->nCountPerRow);
+      }
+      else
+      {
+        nScrollPos = nMaxRange;
+      }
       break;
     case SB_THUMBPOSITION:
-      nHScrollPos = nScrollPos;
-    break;
+      nScrollPos = nScroll;
+      break;
     }
+    break;
 
-    SetScrollPos(hwnd, SB_HORZ, nHScrollPos, TRUE);
+  case LVS_REPORT:
+
+    /* report/details display mode horizontal scrolling */
+    switch (nScrollCode)
+    {
+    case SB_LINELEFT:
+      if (nScrollPos > nMinRange)
+      {
+        nScrollPos--;
+      }
+      break;
+    case SB_LINERIGHT:
+      if (nScrollPos < nMaxRange)
+      {
+        nScrollPos++;
+      }
+      break;
+    case SB_PAGELEFT:
+      if (nScrollPos > nMinRange)
+      {
+        nScrollPos = max(nMinRange, nScrollPos - infoPtr->rcList.right);
+      }
+      else
+      {
+        nScrollPos = nMinRange;
+      }
+      break;
+    case SB_PAGERIGHT:
+      if (nScrollPos < nMaxRange)
+      {
+        nScrollPos = min(nMaxRange, nScrollPos + infoPtr->rcList.right);
+      }
+      else
+      {
+        nScrollPos = nMaxRange;
+      }
+      break;
+    case SB_THUMBPOSITION:
+      nScrollPos = nScroll;
+      break;
+    }
+    break;
+
+    default:
+      /* TO DO */
+  }
+
+  /* set new scroll position */
+  if (nScrollPos != nOldScrollPos)
+  {
+    SetScrollPos(hwnd, SB_HORZ, nScrollPos, TRUE);
 
     /* refresh client area */
     InvalidateRect(hwnd, NULL, TRUE);
-    UpdateWindow(hwnd);
   }
 
   return 0;
@@ -3088,11 +4714,11 @@
 
 /***
  * DESCRIPTION:
- * ?????
+ * ??? 
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : virtual key 
+ * [I] HWND : window handle
+ * [I] INT : virtual key 
  * [I] LONG : key data
  *
  * RETURN:
@@ -3102,173 +4728,125 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
   LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-  LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
+  INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
   HWND hwndParent = GetParent(hwnd);
-  INT nItemCountPerColumn;
-  INT nItemCountPerRow;
+  NMLVKEYDOWN nmKeyDown; 
   NMHDR nmh;
-  INT nColumn;
-/*   NMLVKEYDOWN nmKeyDown; */
 
   /* send LVN_KEYDOWN notification */
-/*   nmh.hwndFrom = hwnd; */
-/*   nmh.idFrom = lCtrlId; */
-/*   nmh.code = LVN_KEYDOWN; */
-/*   nmKeyDown.hdr = nmh; */
-/*   nmKeyDown..wVKey = nVirtualKey; */
-/*   nmKeyCode.flags = 0; */
-/*   SendMessage32A(hwndParent, WM_NOTIFY, (WPARAM32)lCtrlId, (LPARAM)&nmKeyDown); */
+  ZeroMemory(&nmKeyDown, sizeof(NMLVKEYDOWN));
+  nmKeyDown.hdr.hwndFrom = hwnd;  
+  nmKeyDown.hdr.idFrom = nCtrlId;  
+  nmKeyDown.hdr.code = LVN_KEYDOWN;  
+  nmKeyDown.wVKey = nVirtualKey; 
+  nmKeyDown.flags = 0; 
+  SendMessageA(hwndParent, WM_NOTIFY, (WPARAM)nCtrlId, (LPARAM)&nmKeyDown); 
+  
+  /* initialize */
+  nmh.hwndFrom = hwnd;
+  nmh.idFrom = nCtrlId;
 
   switch (nVirtualKey)
   {
   case VK_RETURN:
-    if ((infoPtr->nItemCount > 0) && (infoPtr->nFocusedItem != -1))
+    if ((GETITEMCOUNT(infoPtr) > 0) && (infoPtr->nFocusedItem != -1))
     {
       /* send NM_RETURN notification */
       nmh.code = NM_RETURN;
-      SendMessageA(hwndParent, WM_NOTIFY, (WPARAM)lCtrlId, (LPARAM)&nmh);
+      ListView_Notify(hwndParent, nCtrlId, &nmh);
 
       /* send LVN_ITEMACTIVATE notification */
       nmh.code = LVN_ITEMACTIVATE;
-      SendMessageA(hwndParent, WM_NOTIFY, (WPARAM)lCtrlId, (LPARAM)&nmh);
+      ListView_Notify(hwndParent, nCtrlId, &nmh);
     }
     break;
 
   case VK_HOME:
-    if (infoPtr->nItemCount > 0)
+    if (GETITEMCOUNT(infoPtr) > 0)
     {
-      /* set item state(s) */
-      infoPtr->nFocusedItem = 0;
-      LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
-
-      /* make item visible */
-      LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
+      LISTVIEW_KeySelection(hwnd, 0); 
     }
     break;
 
   case VK_END:
-    if (infoPtr->nItemCount > 0)
-{
-      /* set item state(s) */
-      infoPtr->nFocusedItem = infoPtr->nItemCount - 1;
-      LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
-
-      /* make item visible */
-      LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
+    if (GETITEMCOUNT(infoPtr) > 0)
+    {
+      LISTVIEW_KeySelection(hwnd, GETITEMCOUNT(infoPtr) - 1);
     }
-
     break;
 
   case VK_LEFT:
-    if (lStyle & LVS_LIST)
+    switch (LVS_TYPEMASK & lStyle)
     {
-      nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
-      if (infoPtr->nFocusedItem >= nItemCountPerColumn) 
+    case LVS_LIST:
+      if (infoPtr->nFocusedItem >= infoPtr->nCountPerColumn) 
       {
-         /* set item state(s) */
-        infoPtr->nFocusedItem -= nItemCountPerColumn;
-        LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
+        LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - infoPtr->nCountPerColumn);
+      }
+      break;
+    case LVS_REPORT:
+      break;
 
-        /* make item visible */
-        LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
+    default:
+      if (infoPtr->nFocusedItem % infoPtr->nCountPerRow != 0)
+      {
+        LISTVIEW_SetSelection(hwnd, infoPtr->nFocusedItem - 1); 
       }
     }
-    else if (lStyle & LVS_REPORT)
-    {
-      /* TO DO ; does not affect the focused item, it only scrolls */
-    }
-    else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON))
-    {
-      nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
-      nColumn = infoPtr->nFocusedItem % nItemCountPerRow;
-      if (nColumn != 0)
-      {
-        infoPtr->nFocusedItem -= 1; 
-        LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
+    break;
 
-        /* refresh display */
-        InvalidateRect(hwnd, NULL, FALSE);
-        UpdateWindow(hwnd);
+  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 (infoPtr->nFocusedItem >= infoPtr->nCountPerRow)
+      {
+        LISTVIEW_SetSelection(hwnd, infoPtr->nFocusedItem - 
+                              infoPtr->nCountPerRow);
       }
     }
     break;
     
-  case VK_UP:
-    if ((lStyle & LVS_LIST) || (lStyle & LVS_REPORT))
+  case VK_RIGHT:
+    switch (LVS_TYPEMASK & lStyle)
     {
-      if (infoPtr->nFocusedItem > 0)
+    case LVS_LIST:
+      if (infoPtr->nFocusedItem < 
+          (GETITEMCOUNT(infoPtr) - infoPtr->nCountPerColumn))
       {
-        infoPtr->nFocusedItem -= 1;
-        LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
+        LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + 
+                              infoPtr->nCountPerColumn);
+      }
+    case LVS_REPORT:
+      break;
 
-        LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
-}
-    }
-    else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON))
-    {
-      nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
-      if (infoPtr->nFocusedItem >= nItemCountPerRow)
+    default:
+      if (infoPtr->nCountPerRow > 0)
       {
-        infoPtr->nFocusedItem -= nItemCountPerRow;
-        LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
-
-        LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
       }
     }
     break;
 
-  case VK_RIGHT:
-    if (lStyle & LVS_LIST)
-{
-      nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
-      if (infoPtr->nFocusedItem < infoPtr->nItemCount - nItemCountPerColumn)
-      {
-        infoPtr->nFocusedItem += nItemCountPerColumn;
-        LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
-
-        LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
-    }
-    }
-    else if (lStyle & LVS_REPORT)
-    {
-    }
-    else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON))
-    {
-      nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
-      nColumn = infoPtr->nFocusedItem % nItemCountPerRow;
-      if (nColumn != nItemCountPerRow - 1)
-      {
-        infoPtr->nFocusedItem += 1; 
-        LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
-
-        /* refresh display */
-        InvalidateRect(hwnd, NULL, FALSE);
-        UpdateWindow(hwnd);
-}
-
-    }
-    break;
-
   case VK_DOWN:
-    if ((lStyle & LVS_LIST) || (lStyle & LVS_REPORT))
-{
-      if (infoPtr->nFocusedItem < infoPtr->nItemCount - 1)
-      {
-        infoPtr->nFocusedItem += 1;
-        LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
-
-        LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
-}
-    }
-    else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON))
+    switch (LVS_TYPEMASK & lStyle)
     {
-      nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
-      if (infoPtr->nFocusedItem < infoPtr->nItemCount - nItemCountPerRow)
+    case LVS_LIST:
+    case LVS_REPORT:
+      if (infoPtr->nFocusedItem < GETITEMCOUNT(infoPtr) - 1)
       {
-        infoPtr->nFocusedItem += nItemCountPerRow;
-        LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
-
-        LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
+        LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + 1);
+      }
+    default:
+      if (infoPtr->nCountPerRow > 0)
+      {
       }
     }
     break;
@@ -3280,6 +4858,9 @@
     break;
   }
 
+  /* refresh client area */
+  InvalidateRect(hwnd, NULL, TRUE);
+
   return 0;
 }
 
@@ -3288,7 +4869,7 @@
  * Kills the focus.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  *
  * RETURN:
  * Zero
@@ -3296,19 +4877,19 @@
 static LRESULT LISTVIEW_KillFocus(HWND hwnd)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
-  LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
-    NMHDR nmh;
+  INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
+  NMHDR nmh;
 
+  /* send NM_KILLFOCUS notification */
   nmh.hwndFrom = hwnd;
-  nmh.idFrom = lCtrlId;
-    nmh.code = NM_KILLFOCUS;
-  SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, 
-                 (LPARAM)&nmh);
+  nmh.idFrom = nCtrlId;
+  nmh.code = NM_KILLFOCUS;
+  ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
 
   /* set window focus flag */
-    infoPtr->bFocus = FALSE;
+  infoPtr->bFocus = FALSE;
 
-    return 0;
+  return 0;
 }
 
 /***
@@ -3316,7 +4897,7 @@
  * Left mouse button double click.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * [I] WORD : key flag
  * [I] WORD : x coordinate
  * [I] WORD : y coordinate
@@ -3327,20 +4908,18 @@
 static LRESULT LISTVIEW_LButtonDblClk(HWND hwnd, WORD wKey, WORD wPosX, 
                                       WORD wPosY)
 {
-  LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
+  LONG nCtrlId = GetWindowLongA(hwnd, GWL_ID);
   NMHDR nmh;
 
   /* send NM_DBLCLK notification */
   nmh.hwndFrom = hwnd;
-  nmh.idFrom = lCtrlId;
+  nmh.idFrom = nCtrlId;
   nmh.code = NM_DBLCLK;
-  SendMessageA(GetParent (hwnd), WM_NOTIFY, (WPARAM)lCtrlId, 
-                 (LPARAM)&nmh);
+  ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
 
   /* send LVN_ITEMACTIVATE notification */
   nmh.code = LVN_ITEMACTIVATE;
-  SendMessageA(GetParent (hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
-                 (LPARAM)&nmh);
+  ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
 
   return 0;
 }
@@ -3350,7 +4929,7 @@
  * Left mouse button down.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * [I] WORD : key flag
  * [I] WORD : x coordinate
  * [I] WORD : y coordinate
@@ -3362,21 +4941,22 @@
                                     WORD wPosY)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
+  INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
   LVHITTESTINFO hitTestInfo;
-  LVITEMA lvItem;
   NMHDR nmh;
   INT nItem;
+  static BOOL bGroupSelect = TRUE;
 
   /* send NM_RELEASEDCAPTURE notification */ 
   nmh.hwndFrom = hwnd;
-  nmh.idFrom = lCtrlId;
+  nmh.idFrom = nCtrlId;
   nmh.code = NM_RELEASEDCAPTURE;
-  SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, 
-                 (LPARAM)&nmh);
-
+  ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
+ 
   if (infoPtr->bFocus == FALSE)
+  {
     SetFocus(hwnd);
+  }
 
   /* set left button down flag */
   infoPtr->bLButtonDown = TRUE;
@@ -3386,39 +4966,41 @@
   hitTestInfo.pt.y = wPosY;
   
   /* perform hit test */
-  nItem = SendMessageA(hwnd, LVM_HITTEST, (WPARAM)0, (LPARAM)&hitTestInfo);
-    if ((nItem >= 0) && (nItem < infoPtr->nItemCount))
+  nItem = ListView_HitTest(hwnd, &hitTestInfo);
+  if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
   {
-    /* perform state changes (selection and focus) */
-    infoPtr->nFocusedItem = nItem;
-    LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, TRUE);
-
-    /* scroll intem into view if doing a multiple selection */
-
-    if ((wKey & MK_CONTROL) || (wKey & MK_SHIFT))
-{
-      LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
+    if ((wKey & MK_CONTROL) && (wKey & MK_SHIFT))
+    {
+      if (bGroupSelect == TRUE)
+      {
+        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
     {
-      /* refresh display */
-      InvalidateRect(hwnd, NULL, FALSE);
-      UpdateWindow(hwnd);
+      LISTVIEW_SetSelection(hwnd, nItem);
     }
   }
   else
   {
-    /* clear selection(s) */
-    ZeroMemory(&lvItem, sizeof(LVITEMA));
-    lvItem.stateMask = LVIS_SELECTED;
-    lvItem.state = 0;
-    SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&lvItem);
-
-    /* repaint everything */
-    InvalidateRect(hwnd, NULL, FALSE);
-    UpdateWindow(hwnd);
+    /* remove all selections */
+    LISTVIEW_RemoveSelections(hwnd, 0, GETITEMCOUNT(infoPtr));
   }
 
+  InvalidateRect(hwnd, NULL, TRUE);
+
   return 0;
 }
 
@@ -3427,7 +5009,7 @@
  * Left mouse button up.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * [I] WORD : key flag
  * [I] WORD : x coordinate
  * [I] WORD : y coordinate
@@ -3439,23 +5021,22 @@
                                   WORD wPosY)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
+  INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
   NMHDR nmh;
 
   if (infoPtr->bLButtonDown == TRUE) 
   {
     /* send NM_CLICK notification */
     nmh.hwndFrom = hwnd;
-    nmh.idFrom = lCtrlId;
+    nmh.idFrom = nCtrlId;
     nmh.code = NM_CLICK;
-    SendMessageA(GetParent (hwnd), WM_NOTIFY, (WPARAM)lCtrlId, 
-                     (LPARAM)&nmh);
+    ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
+
+    /* set left button flag */
+    infoPtr->bLButtonDown = FALSE;
   }
 
-  /* set left button flag */
-  infoPtr->bLButtonDown = FALSE;
-
-    return 0;
+  return 0;
 }
 
 /***
@@ -3463,8 +5044,8 @@
  * Creates the listview control (called before WM_CREATE).
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] WPARAM32 : unhandled 
+ * [I] HWND : window handle
+ * [I] WPARAM : unhandled 
  * [I] LPARAM : widow creation info
  * 
  * RETURN:
@@ -3472,22 +5053,22 @@
  */
 static LRESULT LISTVIEW_NCCreate(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
-    LISTVIEW_INFO *infoPtr;
+  LISTVIEW_INFO *infoPtr;
 
-    /* allocate memory for info structure */
-    infoPtr = (LISTVIEW_INFO *)COMCTL32_Alloc (sizeof(LISTVIEW_INFO));
+  /* allocate memory for info structure */
+  infoPtr = (LISTVIEW_INFO *)COMCTL32_Alloc(sizeof(LISTVIEW_INFO));
   SetWindowLongA(hwnd, 0, (LONG)infoPtr);
   if (infoPtr == NULL) 
   {
-	ERR (listview, "could not allocate info memory!\n");
-	return 0;
-    }
+    ERR(listview, "could not allocate info memory!\n");
+    return 0;
+  }
 
   if ((LISTVIEW_INFO *)GetWindowLongA(hwnd, 0) != infoPtr) 
   {
-	ERR (listview, "pointer assignment error!\n");
-	return 0;
-    }
+    ERR(listview, "pointer assignment error!\n");
+    return 0;
+  }
 
   return DefWindowProcA(hwnd, WM_NCCREATE, wParam, lParam);
 }
@@ -3497,7 +5078,7 @@
  * Destroys the listview control (called after WM_DESTROY).
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * 
  * RETURN:
  * Zero
@@ -3506,10 +5087,10 @@
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
 
-    /* free list view info data */
-    COMCTL32_Free (infoPtr);
+  /* free listview info */
+  COMCTL32_Free(infoPtr);
 
-    return 0;
+  return 0;
 }
 
 /***
@@ -3517,8 +5098,8 @@
  * Handles notification from children.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] INT32 : control identifier
+ * [I] HWND : window handle
+ * [I] INT : control identifier
  * [I] LPNMHDR : notification information
  * 
  * RETURN:
@@ -3527,19 +5108,35 @@
 static LRESULT LISTVIEW_Notify(HWND hwnd, INT nCtrlId, LPNMHDR lpnmh)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-
+  
   if (lpnmh->hwndFrom == infoPtr->hwndHeader) 
   {
     /* handle notification from header control */
-	FIXME (listview, "WM_NOTIFY from header!\n");
+    if (lpnmh->code == HDN_ENDTRACKA)
+    {
+      InvalidateRect(hwnd, NULL, TRUE);
     }
-  else 
-  {
-    /* handle notification from unknown source */
-	FIXME (listview, "WM_NOTIFY from unknown source!\n");
-    }
+  }
 
-    return 0;
+  return 0;
+}
+
+static LRESULT LISTVIEW_NotifyFormat(HWND hwndFrom, HWND hwnd, INT nCommand)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  
+  if (nCommand == NF_REQUERY)
+  {
+    /* determine the type of structures to use */
+    infoPtr->notifyFormat = SendMessageA(hwndFrom, WM_NOTIFYFORMAT, 
+                                         (WPARAM)hwnd, (LPARAM)NF_QUERY);
+    if (infoPtr->notifyFormat == NFR_UNICODE)
+    {
+      FIXME (listview, "NO support for unicode structures");
+    }
+  }
+
+  return 0;
 }
 
 /***
@@ -3547,34 +5144,36 @@
  * Draws the listview control.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] HDC32 : device context handle
+ * [I] HWND : window handle
+ * [I] HDC : device context handle
  *
  * RETURN:
  * Zero
  */
 static LRESULT LISTVIEW_Paint(HWND hwnd, HDC hdc)
 {
-    PAINTSTRUCT ps;
+  PAINTSTRUCT ps;
 
   if (hdc == 0)
   {
     hdc = BeginPaint(hwnd, &ps);
     LISTVIEW_Refresh(hwnd, hdc);
     EndPaint(hwnd, &ps);
-}
+  }
   else
+  {
     LISTVIEW_Refresh(hwnd, hdc);
+  }
 
   return 0;
 }
 
 /***
  * DESCRIPTION:
- * Right mouse button double clisk.
+ * Right mouse button double click.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * [I] WORD : key flag
  * [I] WORD : x coordinate
  * [I] WORD : y coordinate
@@ -3585,22 +5184,20 @@
 static LRESULT LISTVIEW_RButtonDblClk(HWND hwnd, WORD wKey, WORD wPosX, 
                                       WORD wPosY)
 {
-  LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
+  INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
   NMHDR nmh;
 
   /* send NM_RELEASEDCAPTURE notification */ 
   nmh.hwndFrom = hwnd;
-  nmh.idFrom = lCtrlId;
+  nmh.idFrom = nCtrlId;
   nmh.code = NM_RELEASEDCAPTURE;
-  SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, 
-                 (LPARAM)&nmh);
+  ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
 
   /* send NM_RDBLCLK notification */
   nmh.code = NM_RDBLCLK;
-  SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, 
-                 (LPARAM)&nmh);
+  ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
 
-    return 0;
+  return 0;
 }
 
 /***
@@ -3608,7 +5205,7 @@
  * Right mouse button input.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * [I] WORD : key flag
  * [I] WORD : x coordinate
  * [I] WORD : y coordinate
@@ -3620,27 +5217,24 @@
                                     WORD wPosY)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
+  INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
   LVHITTESTINFO hitTestInfo;
   NMHDR nmh;
-  LVITEMA lvItem;
   INT nItem;
 
-  /* The syslistview32 control sends a NM_RELEASEDCAPTURE notification.
-     I do not know why, but I decided to send it as well for compatibility 
-     purposes. */
-  ZeroMemory(&nmh, sizeof(NMHDR));
+  /* send NM_RELEASEDCAPTURE notification */
   nmh.hwndFrom = hwnd;
-  nmh.idFrom = lCtrlId;
+  nmh.idFrom = nCtrlId;
   nmh.code = NM_RELEASEDCAPTURE;
-  SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, 
-                 (LPARAM)&nmh);
+  ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
  
-  /* make sure listview control has focus */
+  /* make sure the listview control window has the focus */
   if (infoPtr->bFocus == FALSE)
+  {
     SetFocus(hwnd);
+  }
 
-  /* set left button down flag */
+  /* set right button down flag */
   infoPtr->bRButtonDown = TRUE;
 
   /* set hit coordinates */
@@ -3648,27 +5242,20 @@
   hitTestInfo.pt.y = wPosY;
 
   /* perform hit test */
-  nItem = SendMessageA(hwnd, LVM_HITTEST, (WPARAM)0, (LPARAM)&hitTestInfo);
-  if ((nItem >= 0) && (nItem < infoPtr->nItemCount))
+  nItem = ListView_HitTest(hwnd, &hitTestInfo);
+  if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
   {
-    /* perform state changes (selection and focus) */
-    infoPtr->nFocusedItem = nItem;
-    LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, FALSE, TRUE);
+    if (!((wKey & MK_SHIFT) || (wKey & MK_CONTROL)))
+    {
+      LISTVIEW_SetSelection(hwnd, nItem);
+    }
   }
   else
   {
-    /* clear selection(s) */
-    ZeroMemory(&lvItem, sizeof(LVITEMA));
-    lvItem.stateMask = LVIS_SELECTED;
-    lvItem.state = 0;
-    SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&lvItem);
+    LISTVIEW_RemoveSelections(hwnd, 0, GETITEMCOUNT(infoPtr));
   }
 
-  /* repaint everything */
-  InvalidateRect(hwnd, NULL, FALSE);
-  UpdateWindow(hwnd);
-
-    return 0;
+  return 0;
 }
 
 /***
@@ -3676,7 +5263,7 @@
  * Right mouse button up.
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * [I] WORD : key flag
  * [I] WORD : x coordinate
  * [I] WORD : y coordinate
@@ -3688,24 +5275,23 @@
                                   WORD wPosY)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
-    NMHDR nmh;
+  INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
+  NMHDR nmh;
 
   if (infoPtr->bRButtonDown == TRUE) 
   {
-    /* initialize notification information */
+    /* send NM_RClICK notification */
     ZeroMemory(&nmh, sizeof(NMHDR));
     nmh.hwndFrom = hwnd;
-    nmh.idFrom = lCtrlId;
+    nmh.idFrom = nCtrlId;
     nmh.code = NM_RCLICK;
-    SendMessageA(GetParent (hwnd), WM_NOTIFY, (WPARAM)lCtrlId, 
-                   (LPARAM)&nmh);
+    ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
+
+    /* set button flag */
+    infoPtr->bRButtonDown = FALSE;
   }
-
-  /* set button flag */
-  infoPtr->bRButtonDown = FALSE;
-
-    return 0;
+  
+  return 0;
 }
 
 /***
@@ -3713,8 +5299,8 @@
  * Sets the focus.  
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] HWND32 : window handle of previously focused window
+ * [I] HWND : window handle
+ * [I] HWND : window handle of previously focused window
  *
  * RETURN:
  * Zero
@@ -3722,15 +5308,14 @@
 static LRESULT LISTVIEW_SetFocus(HWND hwnd, HWND hwndLoseFocus)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
+  INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
   NMHDR nmh;
-    
+
   /* send NM_SETFOCUS notification */
   nmh.hwndFrom = hwnd;
-  nmh.idFrom = lCtrlId;
+  nmh.idFrom = nCtrlId;
   nmh.code = NM_SETFOCUS;
-  SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, 
-                 (LPARAM)&nmh);
+  ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
 
   /* set window focus flag */
   infoPtr->bFocus = TRUE;
@@ -3743,8 +5328,8 @@
  * Sets the font.  
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
- * [I] HFONT32 : font handle
+ * [I] HWND : window handle
+ * [I] HFONT : font handle
  * [I] WORD : redraw flag
  *
  * RETURN:
@@ -3762,20 +5347,22 @@
   else
   {
     infoPtr->hFont = hFont;
-    }
+  }
 
-  if (lStyle & LVS_REPORT)
+  if ((LVS_TYPEMASK & lStyle ) == LVS_REPORT)
   {
-    /* set font of header */
+    /* set header font */
     SendMessageA(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)hFont, 
                    MAKELPARAM(fRedraw, 0));
-}
+  }
 
   /* invalidate listview control client area */
   InvalidateRect(hwnd, NULL, FALSE);
-
+  
   if (fRedraw == TRUE)
+  {
     UpdateWindow(hwnd);
+  }
 
   return 0;
 }
@@ -3785,7 +5372,7 @@
  * Resizes the listview control.  
  * 
  * PARAMETER(S):
- * [I] HWND32 : window handle
+ * [I] HWND : window handle
  * [I] WORD : new width
  * [I] WORD : new height
  *
@@ -3794,31 +5381,156 @@
  */
 static LRESULT LISTVIEW_Size(HWND hwnd, WORD wWidth, WORD wHeight)
 {
-  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
-  LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
-  INT nHScrollHeight;
-
-  if (lStyle & LVS_LIST)
-  {
-    if (!(lStyle & WS_HSCROLL))
-    {
-      nHScrollHeight = GetSystemMetrics(SM_CYHSCROLL);
-      if (wHeight > nHScrollHeight)
-        wHeight -= nHScrollHeight;
-    }
-
-    infoPtr->nHeight = (INT)wHeight;
-    infoPtr->nWidth = (INT)wWidth;
-  }
-
-  /* set scrollbar(s) if needed */
+  LISTVIEW_SetSize(hwnd, GetWindowLongA(hwnd, GWL_STYLE), wWidth, wHeight);
+  LISTVIEW_SetViewInfo(hwnd);
   LISTVIEW_SetScroll(hwnd);
 
-  /* refresh client area */
+  /* invalidate + erase background */
   InvalidateRect(hwnd, NULL, TRUE);
-  UpdateWindow(hwnd);
 
-    return 0;
+  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;
+  INT lTop = 0;
+  RECT rc;
+
+  switch (lStyle & LVS_TYPEMASK)
+  {
+  case LVS_LIST:
+    if ((lStyle & LVS_TYPEMASK) == LVS_LIST)
+    {
+      if (!(lStyle & WS_HSCROLL))
+      {
+        INT nHScrollHeight;
+      
+        nHScrollHeight = GetSystemMetrics(SM_CYHSCROLL);
+        if (lHeight > nHScrollHeight)
+        { 
+          lHeight -= nHScrollHeight;
+        }
+      }
+    }
+    break;
+
+  case LVS_REPORT:
+    rc.left = 0;
+    rc.top = 0;
+    rc.right = lWidth;
+    rc.bottom = lHeight;
+    hl.prc = &rc;
+    hl.pwpos = &wp;
+    Header_Layout(infoPtr->hwndHeader, &hl);
+    lTop = wp.cy;
+    break;
+  }
+    
+  infoPtr->rcList.top = lTop;
+  infoPtr->rcList.left = 0;
+  infoPtr->rcList.bottom = lHeight;
+  infoPtr->rcList.right = lWidth;
+}
+
+/***
+ * DESCRIPTION:
+ * Notification sent when the window style is modified.
+ * 
+ * PARAMETER(S):
+ * [I] HWND : window handle
+ * [I] WPARAM : window style type (normal or extended)
+ * [I] LPSTYLESTRUCT : window style information
+ *
+ * RETURN:
+ * Zero
+ */
+static INT LISTVIEW_StyleChanged(HWND hwnd, WPARAM wStyleType, 
+                                 LPSTYLESTRUCT lpss)
+{
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+  HDLAYOUT hl;
+  WINDOWPOS wp;
+  HDC hdc;
+  RECT rc;
+  HBRUSH hBrush;
+
+  if (wStyleType == GWL_STYLE)
+  {
+    /* remove vertical scrollbar */
+    if (lpss->styleOld & WS_VSCROLL)
+    {
+      ShowScrollBar(hwnd, SB_VERT, FALSE);
+    }
+
+    /* remove horizontal scrollbar */
+    if (lpss->styleOld & WS_HSCROLL)
+    {
+      ShowScrollBar(hwnd, SB_HORZ, FALSE);
+    }
+
+    if ((LVS_TYPEMASK & lpss->styleOld) == LVS_REPORT)
+    {
+      /* hide header */
+      ShowWindow(infoPtr->hwndHeader, SW_HIDE);
+    }
+
+    /* erase everything */
+    GetClientRect(hwnd, &rc);
+    hdc = GetDC(hwnd);
+    hBrush = CreateSolidBrush(infoPtr->clrBk);
+    FillRect(hdc, &rc, hBrush);
+    DeleteObject(hBrush);
+    ReleaseDC(hwnd, hdc);
+
+    if ((lpss->styleNew & LVS_TYPEMASK) == LVS_REPORT)
+    {
+      hl.prc = &rc;
+      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);
+    }
+    else if (((lpss->styleNew & LVS_TYPEMASK) == LVS_ICON) ||
+             ((lpss->styleNew & LVS_TYPEMASK) == LVS_SMALLICON))
+    {
+      /* for NOW (it's only temporary) */
+      SetWindowLongA(hwnd, GWL_STYLE, (lpss->styleNew&~LVS_TYPEMASK)|LVS_LIST);
+    }
+
+    /* TEMPORARY */
+    LISTVIEW_UnsupportedStyles(lpss->styleNew);
+
+    /* set new size */
+    LISTVIEW_SetSize(hwnd, lpss->styleNew, rc.right, rc.bottom);
+
+    /* recalculate attributes */
+    LISTVIEW_SetViewInfo(hwnd);
+
+    /* set scrollbars, if needed */
+    LISTVIEW_SetScroll(hwnd);
+    
+    /* invalidate + erase background */
+    InvalidateRect(hwnd, NULL, TRUE);
+  }
+
+  return 0;
 }
 
 /***
@@ -3826,9 +5538,9 @@
  * Window procedure of the listview control.
  * 
  * PARAMETER(S):
- * [I] HWND32 :
- * [I] UINT32 :
- * [I] WPARAM32 :
+ * [I] HWND :
+ * [I] UINT :
+ * [I] WPARAM :
  * [I] LPARAM : 
  *
  * RETURN:
@@ -3837,44 +5549,48 @@
 LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
                                    LPARAM lParam)
 {
-    switch (uMsg)
-    {
+  switch (uMsg)
+  {
   case LVM_APPROXIMATEVIEWRECT: 
     return LISTVIEW_ApproximateViewRect(hwnd, (INT)wParam, 
                                         LOWORD(lParam), HIWORD(lParam));
   case LVM_ARRANGE: 
     return LISTVIEW_Arrange(hwnd, (INT)wParam);
 
-/*	case LVM_CREATEDRAGIMAGE: */
+/* case LVM_CREATEDRAGIMAGE: */
 
-	case LVM_DELETEALLITEMS:
+  case LVM_DELETEALLITEMS:
     return LISTVIEW_DeleteAllItems(hwnd);
 
-	case LVM_DELETECOLUMN:
+  case LVM_DELETECOLUMN:
     return LISTVIEW_DeleteColumn(hwnd, (INT)wParam);
 
-	case LVM_DELETEITEM:
+  case LVM_DELETEITEM:
     return LISTVIEW_DeleteItem(hwnd, (INT)wParam);
 
 /*	case LVM_EDITLABEL: */
-/*	case LVM_ENSUREVISIBLE: */
+
+  case LVM_ENSUREVISIBLE:
+    return LISTVIEW_EnsureVisible(hwnd, (INT)wParam, (BOOL)lParam);
 
   case LVM_FINDITEMA:
     return LISTVIEW_FindItem(hwnd, (INT)wParam, (LPLVFINDINFO)lParam);
 
-	case LVM_GETBKCOLOR:
+  case LVM_GETBKCOLOR:
     return LISTVIEW_GetBkColor(hwnd);
 
 /*	case LVM_GETBKIMAGE: */
-/*	case LVM_GETCALLBACKMASK: */
 
-	case LVM_GETCOLUMNA:
+  case LVM_GETCALLBACKMASK:
+    return LISTVIEW_GetCallbackMask(hwnd);
+
+  case LVM_GETCOLUMNA:
     return LISTVIEW_GetColumnA(hwnd, (INT)wParam, (LPLVCOLUMNA)lParam);
 
-/*	case LVM_GETCOLUMN32W: */
+/*	case LVM_GETCOLUMNW: */
 /*	case LVM_GETCOLUMNORDERARRAY: */
 
-	case LVM_GETCOLUMNWIDTH:
+  case LVM_GETCOLUMNWIDTH:
     return LISTVIEW_GetColumnWidth(hwnd, (INT)wParam);
 
   case LVM_GETCOUNTPERPAGE:
@@ -3883,27 +5599,27 @@
 /*	case LVM_GETEDITCONTROL: */
 /*	case LVM_GETEXTENDEDLISTVIEWSTYLE: */
 
-	case LVM_GETHEADER:
+  case LVM_GETHEADER:
     return LISTVIEW_GetHeader(hwnd);
 
 /*	case LVM_GETHOTCURSOR: */
 /*	case LVM_GETHOTITEM: */
 /*	case LVM_GETHOVERTIME: */
 
-	case LVM_GETIMAGELIST:
+  case LVM_GETIMAGELIST:
     return LISTVIEW_GetImageList(hwnd, (INT)wParam);
 
 /*	case LVM_GETISEARCHSTRING: */
 
-	case LVM_GETITEMA:
+  case LVM_GETITEMA:
     return LISTVIEW_GetItemA(hwnd, (LPLVITEMA)lParam);
 
-/*	case LVM_GETITEM32W: */
+/*	case LVM_GETITEMW: */
 
-	case LVM_GETITEMCOUNT:
+  case LVM_GETITEMCOUNT:
     return LISTVIEW_GetItemCount(hwnd);
 
-	case LVM_GETITEMPOSITION:
+  case LVM_GETITEMPOSITION:
     return LISTVIEW_GetItemPosition(hwnd, (INT)wParam, (LPPOINT)lParam);
 
   case LVM_GETITEMRECT: 
@@ -3915,39 +5631,42 @@
   case LVM_GETITEMSTATE: 
     return LISTVIEW_GetItemState(hwnd, (INT)wParam, (UINT)lParam);
     
-	case LVM_GETITEMTEXTA:
+  case LVM_GETITEMTEXTA:
     LISTVIEW_GetItemTextA(hwnd, (INT)wParam, (LPLVITEMA)lParam);
     break;
 
-/*	case LVM_GETITEMTEXT32W: */
+/*	case LVM_GETITEMTEXTW: */
 
-	case LVM_GETNEXTITEM:
+  case LVM_GETNEXTITEM:
     return LISTVIEW_GetNextItem(hwnd, (INT)wParam, LOWORD(lParam));
 
 /*	case LVM_GETNUMBEROFWORKAREAS: */
   case LVM_GETORIGIN:
     return LISTVIEW_GetOrigin(hwnd, (LPPOINT)lParam);
 
-	case LVM_GETSELECTEDCOUNT:
+  case LVM_GETSELECTEDCOUNT:
     return LISTVIEW_GetSelectedCount(hwnd);
 
   case LVM_GETSELECTIONMARK: 
     return LISTVIEW_GetSelectionMark(hwnd);
 
-	case LVM_GETSTRINGWIDTHA:
+  case LVM_GETSTRINGWIDTHA:
     return LISTVIEW_GetStringWidthA (hwnd, (LPCSTR)lParam);
 
-/*	case LVM_GETSTRINGWIDTH32W: */
+/*	case LVM_GETSTRINGWIDTHW: */
 /*	case LVM_GETSUBITEMRECT: */
 
-	case LVM_GETTEXTBKCOLOR:
+  case LVM_GETTEXTBKCOLOR:
     return LISTVIEW_GetTextBkColor(hwnd);
 
-	case LVM_GETTEXTCOLOR:
+  case LVM_GETTEXTCOLOR:
     return LISTVIEW_GetTextColor(hwnd);
 
 /*	case LVM_GETTOOLTIPS: */
-/*	case LVM_GETTOPINDEX: */
+
+  case LVM_GETTOPINDEX:
+    return LISTVIEW_GetTopIndex(hwnd);
+
 /*	case LVM_GETUNICODEFORMAT: */
 
   case LVM_GETVIEWRECT:
@@ -3955,36 +5674,38 @@
 
 /*	case LVM_GETWORKAREAS: */
 
-	case LVM_HITTEST:
+  case LVM_HITTEST:
     return LISTVIEW_HitTest(hwnd, (LPLVHITTESTINFO)lParam);
 
-	case LVM_INSERTCOLUMNA:
+  case LVM_INSERTCOLUMNA:
     return LISTVIEW_InsertColumnA(hwnd, (INT)wParam, 
                                     (LPLVCOLUMNA)lParam);
 
-/*	case LVM_INSERTCOLUMN32W: */
+/*	case LVM_INSERTCOLUMNW: */
 
-	case LVM_INSERTITEMA:
+  case LVM_INSERTITEMA:
     return LISTVIEW_InsertItemA(hwnd, (LPLVITEMA)lParam);
 
-/*	case LVM_INSERTITEM32W: */
+/*	case LVM_INSERTITEMW: */
 
-	case LVM_REDRAWITEMS:
+  case LVM_REDRAWITEMS:
     return LISTVIEW_RedrawItems(hwnd, (INT)wParam, (INT)lParam);
 
   case LVM_SCROLL: 
     return LISTVIEW_Scroll(hwnd, (INT)wParam, (INT)lParam);
 
-	case LVM_SETBKCOLOR:
+  case LVM_SETBKCOLOR:
     return LISTVIEW_SetBkColor(hwnd, (COLORREF)lParam);
 
 /*	case LVM_SETBKIMAGE: */
-/*	case LVM_SETCALLBACKMASK: */
 
-	case LVM_SETCOLUMNA:
+  case LVM_SETCALLBACKMASK:
+    return LISTVIEW_SetCallbackMask(hwnd, (UINT)wParam);
+
+  case LVM_SETCOLUMNA:
     return LISTVIEW_SetColumnA(hwnd, (INT)wParam, (LPLVCOLUMNA)lParam);
 
-/*	case LVM_SETCOLUMN32W: */
+/*	case LVM_SETCOLUMNW: */
 /*	case LVM_SETCOLUMNORDERARRAY: */
 /*	case LVM_SETCOLUMNWIDTH: */
 /*	case LVM_SETEXTENDEDLISTVIEWSTYLE: */
@@ -3993,39 +5714,43 @@
 /*	case LVM_SETHOVERTIME: */
 /*	case LVM_SETICONSPACING: */
 	
-	case LVM_SETIMAGELIST:
+  case LVM_SETIMAGELIST:
     return LISTVIEW_SetImageList(hwnd, (INT)wParam, (HIMAGELIST)lParam);
 
-	case LVM_SETITEMA:
+  case LVM_SETITEMA:
     return LISTVIEW_SetItemA(hwnd, (LPLVITEMA)lParam);
 
-/*	case LVM_SETITEM32W: */
-/*	case LVM_SETITEMCOUNT: */
+/*	case LVM_SETITEMW: */
 
-	case LVM_SETITEMPOSITION16:
-    return LISTVIEW_SetItemPosition(hwnd, (INT)wParam, 
-                                    (INT)LOWORD(lParam), 
-                                    (INT) HIWORD(lParam));
+  case LVM_SETITEMCOUNT: 
+    LISTVIEW_SetItemCount(hwnd, (INT)wParam);
+    break;
+    
+  case LVM_SETITEMPOSITION:
+    return LISTVIEW_SetItemPosition(hwnd, (INT)wParam, (INT)LOWORD(lParam),
+                                    (INT)HIWORD(lParam));
 
-/*	case LVM_SETITEMPOSITION32: */
+/*	case LVM_SETITEMPOSITION: */
 
   case LVM_SETITEMSTATE: 
     return LISTVIEW_SetItemState(hwnd, (INT)wParam, (LPLVITEMA)lParam);
 
-/*	case LVM_SETITEMTEXT: */
+  case LVM_SETITEMTEXTA:
+    return LISTVIEW_SetItemTextA(hwnd, (INT)wParam, (LPLVITEMA)lParam);
+
 /*	case LVM_SETSELECTIONMARK: */
 
-	case LVM_SETTEXTBKCOLOR:
+  case LVM_SETTEXTBKCOLOR:
     return LISTVIEW_SetTextBkColor(hwnd, (COLORREF)lParam);
 
-	case LVM_SETTEXTCOLOR:
+  case LVM_SETTEXTCOLOR:
     return LISTVIEW_SetTextColor(hwnd, (COLORREF)lParam);
 
 /*	case LVM_SETTOOLTIPS: */
 /*	case LVM_SETUNICODEFORMAT: */
 /*	case LVM_SETWORKAREAS: */
 
-	case LVM_SORTITEMS:
+  case LVM_SORTITEMS:
     return LISTVIEW_SortItems(hwnd, wParam, lParam);
 
 /*	case LVM_SUBITEMHITTEST: */
@@ -4036,19 +5761,19 @@
 /*	case WM_CHAR: */
 /*	case WM_COMMAND: */
 
-	case WM_CREATE:
+  case WM_CREATE:
     return LISTVIEW_Create(hwnd, wParam, lParam);
+    
+  case WM_DESTROY:
+    return LISTVIEW_Destroy(hwnd);
+    
+  case WM_ERASEBKGND:
+    return LISTVIEW_EraseBackground(hwnd, wParam, lParam);
 
-	case WM_DESTROY:
-    return LISTVIEW_Destroy(hwnd, wParam, lParam);
+  case WM_GETDLGCODE:
+    return DLGC_WANTTAB | DLGC_WANTARROWS;
 
-	case WM_ERASEBKGND:
-    return LISTVIEW_EraseBackground (hwnd, wParam, lParam);
-
-	case WM_GETDLGCODE:
-	    return DLGC_WANTTAB | DLGC_WANTARROWS;
-
-	case WM_GETFONT:
+  case WM_GETFONT:
     return LISTVIEW_GetFont(hwnd);
 
   case WM_HSCROLL:
@@ -4058,40 +5783,43 @@
   case WM_KEYDOWN:
     return LISTVIEW_KeyDown(hwnd, (INT)wParam, (LONG)lParam);
 
-	case WM_KILLFOCUS:
+  case WM_KILLFOCUS:
     return LISTVIEW_KillFocus(hwnd);
 
-	case WM_LBUTTONDBLCLK:
+  case WM_LBUTTONDBLCLK:
     return LISTVIEW_LButtonDblClk(hwnd, (WORD)wParam, LOWORD(lParam), 
                                 HIWORD(lParam));
-
-	case WM_LBUTTONDOWN:
+    
+  case WM_LBUTTONDOWN:
     return LISTVIEW_LButtonDown(hwnd, (WORD)wParam, LOWORD(lParam), 
                                 HIWORD(lParam));
   case WM_LBUTTONUP:
     return LISTVIEW_LButtonUp(hwnd, (WORD)wParam, LOWORD(lParam), 
                               HIWORD(lParam));
-
+    
 /*	case WM_MOUSEMOVE: */
 /*	    return LISTVIEW_MouseMove (hwnd, wParam, lParam); */
 
-	case WM_NCCREATE:
+  case WM_NCCREATE:
     return LISTVIEW_NCCreate(hwnd, wParam, lParam);
 
-	case WM_NCDESTROY:
+  case WM_NCDESTROY:
     return LISTVIEW_NCDestroy(hwnd);
 
-	case WM_NOTIFY:
+  case WM_NOTIFY:
     return LISTVIEW_Notify(hwnd, (INT)wParam, (LPNMHDR)lParam);
 
-	case WM_PAINT:
+  case WM_NOTIFYFORMAT:
+    return LISTVIEW_NotifyFormat(hwnd, (HWND)wParam, (INT)lParam);
+
+  case WM_PAINT: 
     return LISTVIEW_Paint(hwnd, (HDC)wParam); 
 
-	case WM_RBUTTONDBLCLK:
+  case WM_RBUTTONDBLCLK:
     return LISTVIEW_RButtonDblClk(hwnd, (WORD)wParam, LOWORD(lParam), 
                                   HIWORD(lParam));
 
-	case WM_RBUTTONDOWN:
+  case WM_RBUTTONDOWN:
     return LISTVIEW_RButtonDown(hwnd, (WORD)wParam, LOWORD(lParam), 
                                 HIWORD(lParam));
 
@@ -4099,32 +5827,41 @@
     return LISTVIEW_RButtonUp(hwnd, (WORD)wParam, LOWORD(lParam), 
                               HIWORD(lParam));
 
-	case WM_SETFOCUS:
+  case WM_SETFOCUS:
     return LISTVIEW_SetFocus(hwnd, (HWND)wParam);
 
-	case WM_SETFONT:
+  case WM_SETFONT:
     return LISTVIEW_SetFont(hwnd, (HFONT)wParam, (WORD)lParam);
 
 /*	case WM_SETREDRAW: */
 
-	case WM_SIZE:
+  case WM_SIZE:
     return LISTVIEW_Size(hwnd, LOWORD(lParam), HIWORD(lParam));
 
+  case WM_STYLECHANGED:
+    return LISTVIEW_StyleChanged(hwnd, wParam, (LPSTYLESTRUCT)lParam);
+
 /*	case WM_TIMER: */
-/*	case WM_VSCROLL: */
+
+  case WM_VSCROLL:
+    return LISTVIEW_VScroll(hwnd, (INT)LOWORD(wParam), 
+                            (INT)HIWORD(wParam), (HWND)lParam);
+
 /*	case WM_WINDOWPOSCHANGED: */
 /*	case WM_WININICHANGE: */
 
-	default:
-	    if (uMsg >= WM_USER)
-		ERR (listview, "unknown msg %04x wp=%08x lp=%08lx\n",
-		     uMsg, wParam, lParam);
-
-    /* call default window procedure */
-	    return DefWindowProcA (hwnd, uMsg, wParam, lParam);
+  default:
+    if (uMsg >= WM_USER)
+    {
+      ERR(listview, "unknown msg %04x wp=%08x lp=%08lx\n",
+          uMsg, wParam, lParam);
     }
 
-    return 0;
+    /* call default window procedure */
+    return DefWindowProcA(hwnd, uMsg, wParam, lParam);
+  }
+
+  return 0;
 }
 
 /***
@@ -4139,20 +5876,20 @@
  */
 VOID LISTVIEW_Register(VOID)
 {
-    WNDCLASSA wndClass;
+  WNDCLASSA wndClass;
 
   if (!GlobalFindAtomA(WC_LISTVIEWA)) 
   {
-    ZeroMemory (&wndClass, sizeof(WNDCLASSA));
-    wndClass.style         = CS_GLOBALCLASS | CS_DBLCLKS;
-    wndClass.lpfnWndProc   = (WNDPROC)LISTVIEW_WindowProc;
-    wndClass.cbClsExtra    = 0;
-    wndClass.cbWndExtra    = sizeof(LISTVIEW_INFO *);
-    wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
+    ZeroMemory(&wndClass, sizeof(WNDCLASSA));
+    wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
+    wndClass.lpfnWndProc = (WNDPROC)LISTVIEW_WindowProc;
+    wndClass.cbClsExtra = 0;
+    wndClass.cbWndExtra = sizeof(LISTVIEW_INFO *);
+    wndClass.hCursor = LoadCursorA(0, IDC_ARROWA);
     wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
     wndClass.lpszClassName = WC_LISTVIEWA;
     RegisterClassA (&wndClass);
-}
+  }
 }
 
 /***
@@ -4167,7 +5904,7 @@
  */
 VOID LISTVIEW_Unregister(VOID)
 {
-    if (GlobalFindAtomA (WC_LISTVIEWA))
-	UnregisterClassA (WC_LISTVIEWA, (HINSTANCE)NULL);
+  if (GlobalFindAtomA(WC_LISTVIEWA))
+    UnregisterClassA(WC_LISTVIEWA, (HINSTANCE)NULL);
 }
 
diff --git a/include/commctrl.h b/include/commctrl.h
index 91d2fde..de957de 100644
--- a/include/commctrl.h
+++ b/include/commctrl.h
@@ -2170,6 +2170,7 @@
 #define LVIF_STATE              0x0008
 #define LVIF_INDENT             0x0010
 #define LVIF_NORECOMPUTE        0x0800
+#define LVIF_DI_SETITEM         0x1000
 
 #define LVIR_BOUNDS             0x0000
 #define LVIR_LABEL              0x0002
@@ -2497,6 +2498,30 @@
 
 typedef INT (CALLBACK *PFNLVCOMPARE)(LPARAM, LPARAM, LPARAM);
 
+#define ListView_Arrange(hwnd,code) \
+    (INT)SendMessageA((hwnd),LVM_ARRANGE,(WPARAM)(INT)(code),0L)
+#define ListView_GetItemPosition(hwnd,i,ppt) \
+    (INT)SendMessageA((hwnd),LVM_GETITEMPOSITION,(WPARAM)(INT)(i),(LPARAM)(LPPOINT)(ppt))
+#define ListView_GetItemRect(hwnd,i,prc) \
+    (INT)SendMessageA((hwnd),LVM_GETITEMRECT,(WPARAM)(INT)(i),(LPARAM)(LPRECT)(prc))
+#define ListView_SetItemA(hwnd,pitem) \
+    (INT)SendMessageA((hwnd),LVM_SETITEMA,0,(LPARAM)(const LVITEMA *)(pitem))
+#define ListView_SetItemState(hwnd,i,pitem) \
+    (BOOL)SendMessageA((hwnd),LVM_SETITEMSTATE,(WPARAM)(UINT)(i),(LPARAM)(LPLVITEMA)(pitem))
+#define ListView_GetItemState(hwnd,i,mask) \
+    (BOOL)SendMessageA((hwnd),LVM_GETITEMSTATE,(WPARAM)(UINT)(i),(LPARAM)(UINT)(mask))
+#define ListView_GetCountPerPage(hwnd) \
+    (BOOL)SendMessageW((hwnd),LVM_GETCOUNTPERPAGE,0,0L)
+#define ListView_GetImageList(hwnd,iImageList) \
+    (HIMAGELIST)SendMessageA((hwnd),LVM_GETIMAGELIST,(WPARAM)(INT)(iImageList),0L)
+#define ListView_GetStringWidthA(hwnd,pstr) \
+    (INT)SendMessageA((hwnd),LVM_GETSTRINGWIDTHA,0,(LPARAM)(LPCSTR)(pstr))
+#define ListView_GetTopIndex(hwnd) \
+    (BOOL)SendMessageA((hwnd),LVM_GETTOPINDEX,0,0L)
+#define ListView_Scroll(hwnd,dx,dy) \
+    (BOOL)SendMessageA((hwnd),LVM_SCROLL,(WPARAM)(INT)(dx),(LPARAM)(INT)(dy))
+#define ListView_EnsureVisible(hwnd,i,fPartialOk) \
+    (BOOL)SendMessageA((hwnd),LVM_ENSUREVISIBLE,(WPARAM)(INT)i,(LPARAM)(BOOL)fPartialOk)
 #define ListView_SetBkColor(hwnd,clrBk) \
     (BOOL)SendMessageA((hwnd),LVM_SETBKCOLOR,0,(LPARAM)(COLORREF)(clrBk))
 #define ListView_GetImageList(hwnd,iImageList) \
@@ -2511,7 +2536,7 @@
     (BOOL)SendMessageW((hwnd),LVM_GETITEMW,0,(LPARAM)(LVITEMW *)(pitem))
 #define ListView_GetItem WINELIB_NAME_AW(ListView_GetItem)
 #define ListView_HitTest(hwnd,pinfo) \
-    (INT)SendMessageA((hwnd),LVMHITTEST,0,(LPARAM)(LPLVHITTESTINFO)(pinfo))
+    (INT)SendMessageA((hwnd),LVM_HITTEST,0,(LPARAM)(LPLVHITTESTINFO)(pinfo))
 #define ListView_InsertItemA(hwnd,pitem) \
     (INT)SendMessageA((hwnd),LVM_INSERTITEMA,0,(LPARAM)(const LVITEMA *)(pitem))
 #define ListView_InsertItemW(hwnd,pitem) \
diff --git a/include/listview.h b/include/listview.h
index 55ab3b5..28db989 100644
--- a/include/listview.h
+++ b/include/listview.h
@@ -7,6 +7,13 @@
 #ifndef __WINE_LISTVIEW_H
 #define __WINE_LISTVIEW_H
 
+typedef struct tagLISTVIEW_SUBITEM
+{
+    LPSTR pszText;
+    INT iImage;
+    INT iSubItem;
+
+} LISTVIEW_SUBITEM;
 
 typedef struct tagLISTVIEW_ITEM
 {
@@ -27,19 +34,23 @@
     HIMAGELIST himlNormal;
     HIMAGELIST himlSmall;
     HIMAGELIST himlState;
-  BOOL bLButtonDown;
-  BOOL bRButtonDown;
-    INT      nColumnCount;
-  INT nFocusedItem;
-  INT nItemCount;
-  INT nItemHeight;
-  INT nColumnWidth;
-  INT nSelectionMark;
+    BOOL bLButtonDown;
+    BOOL bRButtonDown;
+    INT nCountPerColumn;
+    INT nCountPerRow;
+    INT nFocusedItem;
+    INT nItemHeight;
+    INT nColumnWidth;
+    INT nSelectionMark;
+    SHORT notifyFormat;
+    RECT rcList;
+    SIZE iconSize;
+    SIZE smallIconSpacing;
+    SIZE largeIconSpacing;
+    UINT uCallbackMask;
     HWND     hwndHeader;
     HFONT    hDefaultFont;
     HFONT    hFont;
-  INT nWidth;
-  INT nHeight;
     BOOL     bFocus;
     DWORD      dwExStyle;    /* extended listview style */
     HDPA       hdpaItems;