Listview M9
Dimitrie O. Paun
dpaun at rogers.com
Tue Oct 8 20:36:38 CDT 2002
This one should not affect functionality; it's just cleanup.
Ranges will be useful as separate entities, they don't have
to be tied to selection ranges only.
ChangeLog
Separate range manipulation functions from selection ranges.
--- dlls/comctl32/listview.c.M8 Tue Oct 8 20:49:21 2002
+++ dlls/comctl32/listview.c Tue Oct 8 21:31:10 2002
@@ -1825,34 +1825,38 @@
}
#if 0
-static void LISTVIEW_PrintSelectionRanges(LISTVIEW_INFO *infoPtr)
+static void ranges_dump(HDPA ranges)
{
INT i;
ERR("Selections are:\n");
- for (i = 0; i < infoPtr->hdpaSelectionRanges->nItemCount; i++)
+ for (i = 0; i < ranges->nItemCount; i++)
{
- RANGE *selection = DPA_GetPtr(infoPtr->hdpaSelectionRanges, i);
+ RANGE *selection = DPA_GetPtr(ranges, i);
ERR(" [%d - %d]\n", selection->lower, selection->upper);
}
}
+static void LISTVIEW_PrintSelectionRanges(LISTVIEW_INFO *infoPtr)
+{
+ ranges_dump(infoPtr->hdpaSelectionRanges);
+}
#endif
/***
* DESCRIPTION:
- * A compare function for selection ranges
+ * A compare function for ranges
*
- *PARAMETER(S)
- * [I] range1 : pointer to selection range 1;
- * [I] range2 : pointer to selection range 2;
+ * PARAMETER(S)
+ * [I] range1 : pointer to range 1;
+ * [I] range2 : pointer to range 2;
* [I] flags : flags
*
- *RETURNS:
+ * RETURNS:
* >0 : if Item 1 > Item 2
* <0 : if Item 2 > Item 1
* 0 : if Item 1 == Item 2
*/
-static INT CALLBACK LISTVIEW_CompareSelectionRanges(LPVOID range1, LPVOID range2, LPARAM flags)
+static INT CALLBACK ranges_cmp(LPVOID range1, LPVOID range2, LPARAM flags)
{
if (((RANGE*)range1)->upper < ((RANGE*)range2)->lower)
return -1;
@@ -1861,66 +1865,88 @@
return 0;
}
-/***
- * Helper function for LISTVIEW_AddSelectionRange, and LISTVIEW_SetItem.
- */
-static BOOL add_selection_range(LISTVIEW_INFO *infoPtr, INT lower, INT upper, BOOL adj_sel_only)
+static inline BOOL ranges_contain(HDPA ranges, INT nItem)
{
- RANGE selection;
- LVITEMW lvItem;
- INT index, i;
+ RANGE srchrng = { nItem, nItem };
+
+ return DPA_Search(ranges, &srchrng, 0, ranges_cmp, 0, DPAS_SORTED) != -1;
+}
+
+static BOOL ranges_shift(HDPA ranges, INT nItem, INT delta)
+{
+ RANGE srchrng, *chkrng;
+ INT index;
+
+ srchrng.upper = nItem;
+ srchrng.lower = nItem;
+
+ index = DPA_Search(ranges, &srchrng, 0, ranges_cmp, 0, DPAS_SORTED | DPAS_INSERTAFTER);
+ if (index == -1) return TRUE;
+
+ for (;index < ranges->nItemCount; index++)
+ {
+ chkrng = DPA_GetPtr(ranges, index);
+ if (chkrng->lower >= nItem && chkrng->lower + delta >= 0)
+ chkrng->lower += delta;
+ if (chkrng->upper >= nItem && chkrng->upper + delta >= 0)
+ chkrng->upper += delta;
+ }
+ return TRUE;
+}
+
+static BOOL ranges_add(HDPA ranges, INT lower, INT upper)
+{
+ RANGE srchrgn;
+ INT index;
TRACE("range (%i - %i)\n", lower, upper);
- /* try find overlapping selections first */
- selection.lower = lower - 1;
- selection.upper = upper + 1;
- index = DPA_Search(infoPtr->hdpaSelectionRanges, &selection, 0,
- LISTVIEW_CompareSelectionRanges, 0, 0);
+ /* try find overlapping regions first */
+ srchrgn.lower = lower - 1;
+ srchrgn.upper = upper + 1;
+ index = DPA_Search(ranges, &srchrgn, 0, ranges_cmp, 0, 0);
if (index == -1)
{
- RANGE *newsel;
+ RANGE *newrgn;
- /* create the brand new selection to insert */
- newsel = (RANGE *)COMCTL32_Alloc(sizeof(RANGE));
- if(!newsel) return FALSE;
- newsel->lower = lower;
- newsel->upper = upper;
+ /* create the brand new range to insert */
+ newrgn = (RANGE *)COMCTL32_Alloc(sizeof(RANGE));
+ if(!newrgn) return FALSE;
+ newrgn->lower = lower;
+ newrgn->upper = upper;
/* figure out where to insert it */
- index = DPA_Search(infoPtr->hdpaSelectionRanges, newsel, 0,
- LISTVIEW_CompareSelectionRanges, 0, DPAS_INSERTAFTER);
+ index = DPA_Search(ranges, newrgn, 0, ranges_cmp, 0, DPAS_INSERTAFTER);
if (index == -1) index = 0;
/* and get it over with */
- DPA_InsertPtr(infoPtr->hdpaSelectionRanges, index, newsel);
+ DPA_InsertPtr(ranges, index, newrgn);
}
else
{
- RANGE *chksel, *mrgsel;
+ RANGE *chkrgn, *mrgrgn;
INT fromindex, mergeindex;
- chksel = DPA_GetPtr(infoPtr->hdpaSelectionRanges, index);
- if (!chksel) return FALSE;
+ chkrgn = DPA_GetPtr(ranges, index);
+ if (!chkrgn) return FALSE;
TRACE("Merge with index %i (%d - %d)\n",
- index, chksel->lower, chksel->upper);
+ index, chkrgn->lower, chkrgn->upper);
- chksel->lower = min(lower, chksel->lower);
- chksel->upper = max(upper, chksel->upper);
+ chkrgn->lower = min(lower, chkrgn->lower);
+ chkrgn->upper = max(upper, chkrgn->upper);
TRACE("New range %i (%d - %d)\n",
- index, chksel->lower, chksel->upper);
+ index, chkrgn->lower, chkrgn->upper);
- /* merge now common selection ranges */
+ /* merge now common anges */
fromindex = 0;
- selection.lower = chksel->lower - 1;
- selection.upper = chksel->upper + 1;
+ srchrgn.lower = chkrgn->lower - 1;
+ srchrgn.upper = chkrgn->upper + 1;
do
{
- mergeindex = DPA_Search(infoPtr->hdpaSelectionRanges, &selection, fromindex,
- LISTVIEW_CompareSelectionRanges, 0, 0);
+ mergeindex = DPA_Search(ranges, &srchrgn, fromindex, ranges_cmp, 0, 0);
if (mergeindex == -1) break;
if (mergeindex == index)
{
@@ -1930,111 +1956,124 @@
TRACE("Merge with index %i\n", mergeindex);
- mrgsel = DPA_GetPtr(infoPtr->hdpaSelectionRanges, mergeindex);
- if (!mrgsel) return FALSE;
+ mrgrgn = DPA_GetPtr(ranges, mergeindex);
+ if (!mrgrgn) return FALSE;
- chksel->lower = min(chksel->lower, mrgsel->lower);
- chksel->upper = max(chksel->upper, mrgsel->upper);
- COMCTL32_Free(mrgsel);
- DPA_DeletePtr(infoPtr->hdpaSelectionRanges, mergeindex);
+ chkrgn->lower = min(chkrgn->lower, mrgrgn->lower);
+ chkrgn->upper = max(chkrgn->upper, mrgrgn->upper);
+ COMCTL32_Free(mrgrgn);
+ DPA_DeletePtr(ranges, mergeindex);
if (mergeindex < index) index --;
} while(1);
}
- /*DPA_Sort(infoPtr->hdpaSelectionRanges, LISTVIEW_CompareSelectionRanges, 0);*/
-
- if (adj_sel_only) return TRUE;
-
- /* set the selection on items */
- lvItem.state = LVIS_SELECTED;
- lvItem.stateMask = LVIS_SELECTED;
- for(i = lower; i <= upper; i++)
- LISTVIEW_SetItemState(infoPtr, i, &lvItem);
-
return TRUE;
}
-
-/***
- * Helper function for LISTVIEW_RemoveSelectionRange, and LISTVIEW_SetItem.
- */
-static BOOL remove_selection_range(LISTVIEW_INFO *infoPtr, INT lower, INT upper, BOOL adj_sel_only)
+
+static BOOL ranges_del(HDPA ranges, INT lower, INT upper)
{
- RANGE remsel, tmpsel, *chksel;
+ RANGE remrgn, tmprgn, *chkrgn;
BOOL done = FALSE;
- LVITEMW lvItem;
- INT index, i;
+ INT index;
- lvItem.state = 0;
- lvItem.stateMask = LVIS_SELECTED;
-
- remsel.lower = lower;
- remsel.upper = upper;
+ remrgn.lower = lower;
+ remrgn.upper = upper;
- TRACE("range: (%d - %d)\n", remsel.lower, remsel.upper);
+ TRACE("range: (%d - %d)\n", remrgn.lower, remrgn.upper);
do
{
- index = DPA_Search(infoPtr->hdpaSelectionRanges, &remsel, 0,
- LISTVIEW_CompareSelectionRanges, 0, 0);
+ index = DPA_Search(ranges, &remrgn, 0, ranges_cmp, 0, 0);
if (index == -1) return TRUE;
- chksel = DPA_GetPtr(infoPtr->hdpaSelectionRanges, index);
- if (!chksel) return FALSE;
+ chkrgn = DPA_GetPtr(ranges, index);
+ if (!chkrgn) return FALSE;
TRACE("Matches range index %i (%d - %d)\n",
- index, chksel->lower, chksel->upper);
+ index, chkrgn->lower, chkrgn->upper);
/* case 1: Same range */
- if ( (chksel->upper == remsel.upper) &&
- (chksel->lower == remsel.lower) )
+ if ( (chkrgn->upper == remrgn.upper) &&
+ (chkrgn->lower == remrgn.lower) )
{
- DPA_DeletePtr(infoPtr->hdpaSelectionRanges, index);
+ DPA_DeletePtr(ranges, index);
done = TRUE;
}
/* case 2: engulf */
- else if ( (chksel->upper <= remsel.upper) &&
- (chksel->lower >= remsel.lower) )
+ else if ( (chkrgn->upper <= remrgn.upper) &&
+ (chkrgn->lower >= remrgn.lower) )
{
- DPA_DeletePtr(infoPtr->hdpaSelectionRanges, index);
+ DPA_DeletePtr(ranges, index);
}
/* case 3: overlap upper */
- else if ( (chksel->upper < remsel.upper) &&
- (chksel->lower < remsel.lower) )
+ else if ( (chkrgn->upper < remrgn.upper) &&
+ (chkrgn->lower < remrgn.lower) )
{
- chksel->upper = remsel.lower - 1;
+ chkrgn->upper = remrgn.lower - 1;
}
/* case 4: overlap lower */
- else if ( (chksel->upper > remsel.upper) &&
- (chksel->lower > remsel.lower) )
+ else if ( (chkrgn->upper > remrgn.upper) &&
+ (chkrgn->lower > remrgn.lower) )
{
- chksel->lower = remsel.upper + 1;
+ chkrgn->lower = remrgn.upper + 1;
}
/* case 5: fully internal */
else
{
- RANGE *newsel =
- (RANGE *)COMCTL32_Alloc(sizeof(RANGE));
- if (!newsel) return FALSE;
- tmpsel = *chksel;
- newsel->lower = chksel->lower;
- newsel->upper = remsel.lower - 1;
- chksel->lower = remsel.upper + 1;
- DPA_InsertPtr(infoPtr->hdpaSelectionRanges, index, newsel);
- /*DPA_Sort(infoPtr->hdpaSelectionRanges, LISTVIEW_CompareSelectionRanges, 0);*/
- chksel = &tmpsel;
+ RANGE *newrgn = (RANGE *)COMCTL32_Alloc(sizeof(RANGE));
+ if (!newrgn) return FALSE;
+ tmprgn = *chkrgn;
+ newrgn->lower = chkrgn->lower;
+ newrgn->upper = remrgn.lower - 1;
+ chkrgn->lower = remrgn.upper + 1;
+ DPA_InsertPtr(ranges, index, newrgn);
+ chkrgn = &tmprgn;
}
-
- if (adj_sel_only) continue;
-
- /* here, chksel holds the selection to delete */
- for (i = chksel->lower; i <= chksel->upper; i++)
- LISTVIEW_SetItemState(infoPtr, i, &lvItem);
}
while(!done);
return TRUE;
}
+/***
+ * Helper function for LISTVIEW_RemoveSelectionRange, and LISTVIEW_SetItem.
+ */
+static BOOL remove_selection_range(LISTVIEW_INFO *infoPtr, INT lower, INT upper, BOOL adj_sel_only)
+{
+ LVITEMW lvItem;
+ INT i;
+
+ if (!ranges_del(infoPtr->hdpaSelectionRanges, lower, upper)) return FALSE;
+ if (adj_sel_only) return TRUE;
+
+ /* reset the selection on items */
+ lvItem.state = 0;
+ lvItem.stateMask = LVIS_SELECTED;
+ for(i = lower; i <= upper; i++)
+ LISTVIEW_SetItemState(infoPtr, i, &lvItem);
+
+ return TRUE;
+}
+/***
+ * Helper function for LISTVIEW_AddSelectionRange, and LISTVIEW_SetItem.
+ */
+static BOOL add_selection_range(LISTVIEW_INFO *infoPtr, INT lower, INT upper, BOOL adj_sel_only)
+{
+ LVITEMW lvItem;
+ INT i;
+
+ if (!ranges_add(infoPtr->hdpaSelectionRanges, lower, upper)) return FALSE;
+ if (adj_sel_only) return TRUE;
+
+ /* set the selection on items */
+ lvItem.state = LVIS_SELECTED;
+ lvItem.stateMask = LVIS_SELECTED;
+ for(i = lower; i <= upper; i++)
+ LISTVIEW_SetItemState(infoPtr, i, &lvItem);
+
+ return TRUE;
+}
+
/**
* DESCRIPTION:
* Adds a selection range.
@@ -2178,29 +2217,9 @@
*/
static void LISTVIEW_ShiftIndices(LISTVIEW_INFO *infoPtr, INT nItem, INT direction)
{
- RANGE selection,*checkselection;
- INT index;
-
- TRACE("Shifting %iu, %i steps\n",nItem,direction);
+ TRACE("Shifting %iu, %i steps\n", nItem, direction);
- selection.upper = nItem;
- selection.lower = nItem;
-
- index = DPA_Search(infoPtr->hdpaSelectionRanges, &selection, 0,
- LISTVIEW_CompareSelectionRanges,
- 0,DPAS_SORTED|DPAS_INSERTAFTER);
-
- while ((index < infoPtr->hdpaSelectionRanges->nItemCount)&&(index != -1))
- {
- checkselection = DPA_GetPtr(infoPtr->hdpaSelectionRanges,index);
- if ((checkselection->lower >= nItem)&&
- ((int)(checkselection->lower + direction) >= 0))
- checkselection->lower += direction;
- if ((checkselection->upper >= nItem)&&
- ((int)(checkselection->upper + direction) >= 0))
- checkselection->upper += direction;
- index ++;
- }
+ ranges_shift(infoPtr->hdpaSelectionRanges, nItem, direction);
/* Note that the following will fail if direction != +1 and -1 */
if (infoPtr->nSelectionMark > nItem)
@@ -4750,18 +4769,6 @@
/* LISTVIEW_GetISearchString */
/***
- * Helper function for LISTVIEW_GetItemT *only*. Tests if an item is selected.
- * It is important that no other functions call this because of callbacks.
- */
-static inline BOOL is_item_selected(LISTVIEW_INFO *infoPtr, INT nItem)
-{
- RANGE selection = { nItem, nItem };
-
- return DPA_Search(infoPtr->hdpaSelectionRanges, &selection, 0,
- LISTVIEW_CompareSelectionRanges, 0, DPAS_SORTED) != -1;
-}
-
-/***
* DESCRIPTION:
* Retrieves item attributes.
*
@@ -4863,7 +4870,7 @@
if ( lpLVItem->stateMask & ~infoPtr->uCallbackMask & LVIS_SELECTED )
{
lpLVItem->state &= ~LVIS_SELECTED;
- if (is_item_selected(infoPtr, lpLVItem->iItem))
+ if (ranges_contain(infoPtr->hdpaSelectionRanges, lpLVItem->iItem))
lpLVItem->state |= LVIS_SELECTED;
}
@@ -4972,7 +4979,7 @@
if ( lpLVItem->stateMask & ~infoPtr->uCallbackMask & LVIS_SELECTED )
{
lpLVItem->state &= ~LVIS_SELECTED;
- if (is_item_selected(infoPtr, lpLVItem->iItem))
+ if (ranges_contain(infoPtr->hdpaSelectionRanges, lpLVItem->iItem))
lpLVItem->state |= LVIS_SELECTED;
}
}
More information about the wine-patches
mailing list