Authors: Chris Morgan <cmorgan@wpi.edu>, James Abbatiello <abbeyj@wpi.edu>
Implemented LISTVIEW_SortItems() and LISTVIEW_CallBackCompare()

diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index 4232501..0a509fb 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -15,7 +15,6 @@
  *   LISTVIEW_Notify : most notifications from children (editbox and header)
  *
  * Data structure:
- *   LISTVIEW_SortItems : empty stub 
  *   LISTVIEW_SetItemCount : empty stub 
  * 
  * Unicode:
@@ -5068,12 +5067,44 @@
   return TRUE;
 }
 
+
+/***
+ * DESCRIPTION:
+ * Callback internally used by LISTVIEW_SortItems()
+ * 
+ * PARAMETER(S):
+ * [I] LPVOID : first LISTVIEW_ITEM to compare
+ * [I] LPVOID : second LISTVIEW_ITEM to compare
+ * [I] LPARAM : HWND of control
+ *
+ * RETURN:
+ *   if first comes before second : negative
+ *   if first comes after second : positive
+ *   if first and second are equivalent : zero
+ */
+static INT WINAPI LISTVIEW_CallBackCompare( 
+  LPVOID first, 
+  LPVOID second, 
+  LPARAM lParam)
+{
+  /* Forward the call to the client defined callback */
+  HWND hwnd = (HWND)lParam;
+  LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+
+  return (infoPtr->pfnCompare)(
+    ((LISTVIEW_ITEM *)first)->lParam,
+    ((LISTVIEW_ITEM *)second)->lParam,
+    infoPtr->lParamSort);
+}
+
 /***
  * DESCRIPTION:
  * Sorts the listview items.
  * 
  * PARAMETER(S):
  * [I] HWND : window handle
+ * [I] WPARAM : application-defined value
+ * [I] LPARAM : pointer to comparision callback
  *
  * RETURN:
  *   SUCCESS : TRUE
@@ -5081,9 +5112,47 @@
  */
 static LRESULT LISTVIEW_SortItems(HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
-  FIXME("empty stub!\n");
+    LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
+    HDPA hdpaSubItems;
+    LISTVIEW_ITEM *lpItem;
+    int nCount, i;
+    HDPA sortList;
+    
+    if (!infoPtr || !infoPtr->hdpaItems)
+	return FALSE;
+    
+    nCount = GETITEMCOUNT(infoPtr);
+    // if there are 0 or 1 items, there is no need to sort
+    if (nCount > 1)
+    {
+	sortList = DPA_Create(nCount);
 
-  return TRUE;
+	infoPtr->pfnCompare = (PFNLVCOMPARE)lParam;
+	infoPtr->lParamSort = (LPARAM)wParam;
+	
+	// append pointers one by one to sortList
+	for (i = 0; i < nCount; i++)
+	{
+	    if ((hdpaSubItems = (HDPA) DPA_GetPtr(infoPtr->hdpaItems, i)))
+		if ((lpItem = (LISTVIEW_ITEM *) DPA_GetPtr(hdpaSubItems, 0)))
+		    DPA_InsertPtr(sortList, nCount + 1, lpItem);
+	}
+
+	// sort the sortList
+	DPA_Sort(sortList, LISTVIEW_CallBackCompare, hwnd);
+
+	// copy the pointers back
+	for (i = 0; i < nCount; i++)
+	{
+	    if ((hdpaSubItems = (HDPA) DPA_GetPtr(infoPtr->hdpaItems, i)) &&
+		(lpItem = (LISTVIEW_ITEM *) DPA_GetPtr(sortList, i)))
+		DPA_SetPtr(hdpaSubItems, 0, lpItem);
+	}
+
+	DPA_Destroy(sortList);
+    }
+
+    return TRUE;
 }
 
 /***
diff --git a/include/listview.h b/include/listview.h
index 9681045..44bbe86 100644
--- a/include/listview.h
+++ b/include/listview.h
@@ -53,7 +53,9 @@
     BOOL bFocus;
     DWORD dwExStyle;    /* extended listview style */
     HDPA hdpaItems;
-
+    PFNLVCOMPARE pfnCompare;
+    LPARAM lParamSort;
+    
 } LISTVIEW_INFO;