Diff of /ooDialog/trunk/ooDialog/oodListView.cpp [r8475] .. [r8476] Maximize Restore

  Switch to side-by-side view

--- a/ooDialog/trunk/ooDialog/oodListView.cpp
+++ b/ooDialog/trunk/ooDialog/oodListView.cpp
@@ -763,7 +763,7 @@
 
 
 /**
- * Returns a new LvSubItem object for the sprecified subitem in the list-view.
+ * Returns a new LvSubItem object for the specified subitem in the list-view.
  *
  * @param c
  * @param hList
@@ -1457,36 +1457,6 @@
     return -1;
 }
 
-/** ListView::BkColor=
- *  ListView::TextColor=
- *  ListView::TextBkColor=
- *
- *
- *  @remarks.  This method is hopelessly outdated.  It should take a COLORREF so
- *             that the user has access to all available colors rather than be
- *             limited to 18 colors out of a 256 color display.
- */
-RexxMethod3(RexxObjectPtr, lv_setColor, uint32_t, color, NAME, method, CSELF, pCSelf)
-{
-    HWND hList = getDChCtrl(pCSelf);
-
-    COLORREF ref = PALETTEINDEX(color);
-
-    if ( *method == 'B' )
-    {
-        ListView_SetBkColor(hList, ref);
-    }
-    else if ( method[4] == 'C' )
-    {
-        ListView_SetTextColor(hList, ref);
-    }
-    else
-    {
-        ListView_SetTextBkColor(hList, ref);
-    }
-    return NULLOBJECT;
-}
-
 /** ListView::check()
  ** ListView::uncheck()
  *
@@ -2132,617 +2102,6 @@
     return rxNewPoint(context, p.x, p.y);
 }
 
-/** ListView::getSubitem()
- *
- *  Returns a LvSubItem object for the item and subitem indexes specified.
- *
- *  @remarks  The ListView_GetItem macro will not fail, even if the subitem
- *            index is greater than any existing subitem.  Text is the empty
- *            string.  Plus, there is no reason that the user could not have
- *            added subitems, but the list-view is not in report view.  So, we
- *            don't check subitemIndex with getColumnCount()
- */
-RexxMethod3(RexxObjectPtr, lv_getSubitem, uint32_t, itemIndex, uint32_t, subitemIndex, CSELF, pCSelf)
-{
-    RexxObjectPtr result = TheNilObj;
-    HWND          hList  = getDChCtrl(pCSelf);
-
-    if ( subitemIndex == 0 )
-    {
-        goto done_out;
-    }
-
-    // If we have a LvFullRow object assigned to the user data, we use the Rexx
-    // subitem in the full row, if it exists.  maybeGetFullRow() will update the
-    // item index, which will ensure things are correct.
-
-    pCLvFullRow pclvfr = maybeGetFullRow(hList, itemIndex);
-    if ( pclvfr != NULL )
-    {
-        if ( subitemIndex <= pclvfr->subItemCount )
-        {
-            result = pclvfr->rxSubItems[subitemIndex];
-            goto done_out;
-        }
-    }
-
-    result = newLvSubitem(context, hList, itemIndex, subitemIndex);
-
-done_out:
-    return result;
-}
-
-/** ListView::hasCheckBoxes()
- */
-RexxMethod1(RexxObjectPtr, lv_hasCheckBoxes, CSELF, pCSelf)
-{
-    return (hasCheckBoxes(getDChCtrl(pCSelf)) ? TheTrueObj : TheFalseObj);
-}
-
-/** ListView::hitTestInfo()
- *
- *  Determine the location of a point relative to the list-view control.
- *
- *  @param  pt  [required]  The position, x and y co-ordinates of the point to
- *              test. This can be specified in two forms.
- *
- *      Form 1:  arg 1 is a .Point object.
- *      Form 2:  arg 1 is the x co-ordinate and arg2 is the y co-ordinate.
- *
- *  @param  info  [optional in/out]  A directory object in which all hit info is
- *                returned.  If the directory is supplied, on return the
- *                directory will have these indexes:
- *
- *                info    Keywords concerning the location of the point.
- *
- *                infoEx  Extended keywords concerning the location of the
- *                        point.  Vista and later.
- *
- *                item    Same value as the return.  The item index if the point
- *                        hits an item, otherwise -1.  (Because list-views are 0
- *                        based indexes in ooDialog.)
- *
- *                subItem The subitem index if the point hits a subitem.
- *
- *                group   Vista and later.  Group index of the item hit (read
- *                        only). Valid only for owner data. If the point is
- *                        within an item that is displayed in multiple groups
- *                        then group will specify the group index of the item.
- *
- *  @return  The index of the item hit, or -1 if the point does not hit an item.
- *
- *  @note    Sometimes the returned index of the hit spot is all that is needed.
- *           In these cases, there is no need to supply the optional directory
- *           object.  However, other times the complete hit test information may
- *           be desired.
- *
- *           Any x, y coordinates will work.  I.e. -6000, -7000 will work. The
- *           item will be -1 and location will be "ABOVE TOLEFT"
- */
-RexxMethod2(int32_t, lv_hitTestInfo, ARGLIST, args, CSELF, pCSelf)
-{
-    int32_t result = -1;
-
-    pCDialogControl pcdc = validateDCCSelf(context, pCSelf);
-    if ( pcdc == NULL )
-    {
-        goto done_out;
-    }
-    HWND hwnd = pcdc->hCtrl;
-
-    size_t sizeArray;
-    size_t argsUsed;
-    POINT  point;
-    if ( ! getPointFromArglist(context, args, &point, 1, 3, &sizeArray, &argsUsed) )
-    {
-        goto done_out;
-    }
-
-    bool haveDirectory = (sizeArray > argsUsed) ? true : false;
-    RexxDirectoryObject info;
-
-    // Check arg count against expected.
-    if ( sizeArray > (haveDirectory ? argsUsed + 1 : argsUsed) )
-    {
-        tooManyArgsException(context->threadContext, (haveDirectory ? argsUsed + 1 : argsUsed));
-        goto done_out;
-    }
-
-    if ( haveDirectory )
-    {
-        RexxObjectPtr _info = context->ArrayAt(args, argsUsed + 1);
-        if ( _info == NULLOBJECT || ! context->IsDirectory(_info) )
-        {
-            wrongClassException(context->threadContext, argsUsed + 1, "Directory");
-            goto done_out;
-        }
-
-        info = (RexxDirectoryObject)_info;
-    }
-
-    LVHITTESTINFO hti;
-    hti.pt = point;
-
-    char buf[128];
-    *buf = '\0';
-
-    if ( _isAtLeastVista() )
-    {
-        result = ListView_HitTestEx(hwnd, &hti);
-
-        if ( haveDirectory )
-        {
-            context->DirectoryPut(info, context->Int32(hti.iGroup), "GROUP");
-
-            if ( hti.flags & LVHT_EX_FOOTER          ) strcat(buf, "Footer ");
-            if ( hti.flags & LVHT_EX_GROUP           ) strcat(buf, "Group ");
-            if ( hti.flags & LVHT_EX_GROUP_BACKGROUND) strcat(buf, "GroupBackground ");
-            if ( hti.flags & LVHT_EX_GROUP_COLLAPSE  ) strcat(buf, "GroupCollapse ");
-            if ( hti.flags & LVHT_EX_GROUP_FOOTER    ) strcat(buf, "GroupFooter ");
-            if ( hti.flags & LVHT_EX_GROUP_HEADER    ) strcat(buf, "GroupHeader ");
-            if ( hti.flags & LVHT_EX_GROUP_STATEICON ) strcat(buf, "GroupStateIcon ");
-            if ( hti.flags & LVHT_EX_GROUP_SUBSETLINK) strcat(buf, "GroupSubsetLink ");
-            if ( hti.flags & LVHT_EX_ONCONTENTS      ) strcat(buf, "OnContents ");
-
-            if ( *buf != '\0' )
-            {
-                *(buf + strlen(buf) - 1) = '\0';
-            }
-            context->DirectoryPut(info, context->String(buf), "INFOEX");
-        }
-    }
-    else
-    {
-        result = ListView_HitTest(hwnd, &hti);
-    }
-
-    if ( haveDirectory )
-    {
-        context->DirectoryPut(info, context->Int32(hti.iItem), "ITEM");
-        context->DirectoryPut(info, context->Int32(hti.iSubItem), "SUBITEM");
-
-        *buf = '\0';
-
-        if ( hti.flags & LVHT_ABOVE          ) strcat(buf, "Above ");
-        if ( hti.flags & LVHT_BELOW          ) strcat(buf, "Below ");
-        if ( hti.flags & LVHT_TORIGHT        ) strcat(buf, "ToRight ");
-        if ( hti.flags & LVHT_TOLEFT         ) strcat(buf, "ToLeft ");
-        if ( hti.flags & LVHT_NOWHERE        ) strcat(buf, "NoWhere ");
-        if ( hti.flags & LVHT_ONITEMICON     ) strcat(buf, "OnIcon ");
-        if ( hti.flags & LVHT_ONITEMLABEL    ) strcat(buf, "OnLabel ");
-        if ( hti.flags & LVHT_ONITEMSTATEICON) strcat(buf, "OnStateIcon ");
-        if ( hti.flags & LVHT_ONITEM         ) strcat(buf, "OnItem ");
-
-        if ( *buf != '\0' )
-        {
-            *(buf + strlen(buf) - 1) = '\0';
-        }
-        context->DirectoryPut(info, context->String(buf), "INFO");
-    }
-
-done_out:
-    return result;
-}
-
-/** ListView::insert()
- *
- * Inserts a new list view item or a new subitem into in an existing list view
- * item.
- *
- * Note that as a byproduct of the way the underlying Windows API works, this
- * method would also modify an existing subitem.
- *
- * @param itemIndex
- * @param subitemIndex
- * @param text
- * @param imageIndex
- *
- * @return  -1 on error, othewise the inserted item index.
- *
- * @note  If a subitem is being inserted, the returned index will be the index
- *        of the item the subitem is inserted into.
- *
- */
-RexxMethod5(int32_t, lv_insert, OPTIONAL_uint32_t, _itemIndex, OPTIONAL_uint32_t, subitemIndex, CSTRING, text,
-            OPTIONAL_int32_t, imageIndex, CSELF, pCSelf)
-{
-    HWND hList = getDChCtrl(pCSelf);
-    int32_t newItem = -1;
-    int32_t itemIndex = _itemIndex;
-    LVITEM lvi = {0};
-
-    if ( argumentOmitted(1) )
-    {
-        itemIndex = getDCinsertIndex(pCSelf);
-        if ( subitemIndex > 0 )
-        {
-            itemIndex--;
-            if ( itemIndex > (ListView_GetItemCount(hList) - 1) )
-            {
-                userDefinedMsgException(context->threadContext, 2, "A subitem can not be inserted prior to inserting the item");
-                goto done_out;
-            }
-        }
-    }
-
-    imageIndex = (argumentOmitted(4) ? -1 : imageIndex);
-
-    lvi.mask = LVIF_TEXT;
-    lvi.iItem = itemIndex;
-    lvi.iSubItem = subitemIndex;
-    lvi.pszText = (LPSTR)text;
-
-    if ( imageIndex > -1 )
-    {
-        lvi.iImage = imageIndex;
-        lvi.mask |= LVIF_IMAGE;
-    }
-
-    if ( subitemIndex == 0 )
-    {
-        newItem = ListView_InsertItem(hList, &lvi);
-        ((pCDialogControl)pCSelf)->lastItem = newItem;
-    }
-    else
-    {
-        if ( ListView_SetItem(hList, &lvi) )
-        {
-            newItem = itemIndex;
-        }
-    }
-
-done_out:
-    return newItem;
-}
-
-/** ListView::insertColumnPx()
- *
- *
- *  @param column
- *  @param text
- *  @param width   The width of the column in pixels
- *
- *
- *  @note  Even though the width argument in insertColumn() was documented as
- *         being in pixels, the code actually converted it to dialog units.
- *         This method is provided to really use pixels.
- *
- *  @remarks  Not sure why there is a restriction on the length of the column
- *            label, or why the passed text is copied to a buffer.  The
- *            ListView_InsertColumn() API does not impose a limit on the length,
- *            and just asks for a pointer to a string.  Both the length
- *            restriction and the copy are probably not needed.
- */
-RexxMethod5(int, lv_insertColumnPx, OPTIONAL_uint16_t, column, CSTRING, text, uint16_t, width,
-            OPTIONAL_CSTRING, fmt, CSELF, pCSelf)
-{
-    HWND hwnd = getDChCtrl(pCSelf);
-
-    LVCOLUMN lvi = {0};
-    int retVal = 0;
-    char szText[256];
-
-    lvi.mask = LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT | LVCF_WIDTH;
-
-    // If omitted, column is 0, which is also the default.
-    lvi.iSubItem = column;
-
-    lvi.cchTextMax = (int)strlen(text);
-    if ( lvi.cchTextMax > (sizeof(szText) - 1) )
-    {
-        userDefinedMsgException(context->threadContext, 2, "the column title must be less than 256 characters");
-        return 0;
-    }
-    strcpy(szText, text);
-    lvi.pszText = szText;
-    lvi.cx = width;
-
-    lvi.fmt = LVCFMT_LEFT;
-    if ( argumentExists(4) )
-    {
-        char f = toupper(*fmt);
-        if ( f == 'C' )
-        {
-            lvi.fmt = LVCFMT_CENTER;
-        }
-        else if ( f == 'R' )
-        {
-            lvi.fmt = LVCFMT_RIGHT;
-        }
-    }
-
-    retVal = ListView_InsertColumn(hwnd, lvi.iSubItem, &lvi);
-    if ( retVal != -1 && lvi.fmt != LVCFMT_LEFT && lvi.iSubItem == 0 )
-    {
-        /* According to the MSDN docs: "If a column is added to a
-         * list-view control with index 0 (the leftmost column) and with
-         * LVCFMT_RIGHT or LVCFMT_CENTER specified, the text is not
-         * right-aligned or centered." This is the suggested work around.
-         */
-        lvi.iSubItem = 1;
-        ListView_InsertColumn(hwnd, lvi.iSubItem, &lvi);
-        ListView_DeleteColumn(hwnd, 0);
-    }
-    return retVal;
-}
-
-/** ListView::insertFullRow()
- *
- *  Inserts an item into the list view at the position specified using a
- *  LvFullRow object.
- *
- */
-RexxMethod2(int32_t, lv_insertFullRow, RexxObjectPtr, row, CSELF, pCSelf)
-{
-    return fullRowOperation(context, row, lvfrInsert, pCSelf);
-}
-
-/** ListView::isChecked()
- *
- *
- */
-RexxMethod2(RexxObjectPtr, lv_isChecked, int32_t, index, CSELF, pCSelf)
-{
-    HWND hList = getDChCtrl(pCSelf);
-
-    if ( hasCheckBoxes(hList) )
-    {
-        if ( index >= 0 && index <= ListView_GetItemCount(hList) - 1 )
-        {
-            if ( ListView_GetCheckState(hList, index) != 0 )
-            {
-                return TheTrueObj;
-            }
-        }
-    }
-    return TheFalseObj;
-}
-
-/** ListView::itemState()
- *
- *
- */
-RexxMethod2(RexxStringObject, lv_itemState, uint32_t, index, CSELF, pCSelf)
-{
-    HWND hList = getDChCtrl(pCSelf);
-
-    uint32_t state = ListView_GetItemState(hList, index, LVIS_CUT | LVIS_DROPHILITED | LVIS_FOCUSED | LVIS_SELECTED);
-
-    char buf[64];
-    *buf = '\0';
-
-    if ( state & LVIS_CUT )         strcat(buf, "CUT ");
-    if ( state & LVIS_DROPHILITED ) strcat(buf, "DROP ");
-    if ( state & LVIS_FOCUSED )     strcat(buf, "FOCUSED ");
-    if ( state & LVIS_SELECTED )    strcat(buf, "SELECTED ");
-
-    if ( *buf != '\0' )
-    {
-        *(buf + strlen(buf) - 1) = '\0';
-    }
-    return context->String(buf);
-}
-
-/** ListView::itemText()
- *
- *
- */
-RexxMethod3(RexxStringObject, lv_itemText, uint32_t, index, OPTIONAL_uint32_t, subitem, CSELF, pCSelf)
-{
-    char buf[256];
-    ListView_GetItemText(getDChCtrl(pCSelf), index, subitem, buf, sizeof(buf));
-    return context->String(buf);
-}
-
-/** ListView::setColumnWidthPX()
- *
- *
- */
-RexxMethod3(RexxObjectPtr, lv_setColumnWidthPx, uint32_t, index, OPTIONAL_RexxObjectPtr, _width, CSELF, pCSelf)
-{
-    HWND hList = getDChCtrl(pCSelf);
-
-    int width = getColumnWidthArg(context, _width, 2);
-    if ( width == OOD_BAD_WIDTH_EXCEPTION )
-    {
-        return TheOneObj;
-    }
-
-    if ( width == LVSCW_AUTOSIZE || width == LVSCW_AUTOSIZE_USEHEADER )
-    {
-        if ( !isInReportView(hList) )
-        {
-            userDefinedMsgException(context->threadContext, 2, "can not be AUTO or AUTOHEADER if not in report view");
-            return TheOneObj;
-        }
-    }
-
-    return (ListView_SetColumnWidth(hList, index, width) ? TheZeroObj : TheOneObj);
-}
-
-/** ListView::modify()
- *
- *
- *  @remarks  If the user has a LvFullRox object as the user data, we update the
- *            values in that object after a successful modify().
- */
-RexxMethod5(RexxObjectPtr, lv_modify, OPTIONAL_uint32_t, itemIndex, OPTIONAL_uint32_t, subitemIndex, CSTRING, text,
-            OPTIONAL_int32_t, imageIndex, CSELF, pCSelf)
-{
-    RexxObjectPtr result = TheOneObj;  // Error result.
-
-    HWND hList = getDChCtrl(pCSelf);
-
-    if ( argumentOmitted(1) )
-    {
-        itemIndex = getDCinsertIndex(pCSelf);
-        if ( subitemIndex > 0 )
-        {
-            itemIndex--;
-        }
-    }
-    itemIndex  = (argumentOmitted(1) ? getSelected(hList) : itemIndex);
-    imageIndex = (argumentOmitted(4) ? -1 : imageIndex);
-
-    if ( itemIndex < 0 )
-    {
-        itemIndex = 0;
-    }
-
-    LVITEM lvi = {0};
-    lvi.mask = LVIF_TEXT;
-    lvi.iItem = itemIndex;
-    lvi.iSubItem = subitemIndex;
-    lvi.pszText = (LPSTR)text;
-
-    if ( imageIndex > -1 )
-    {
-        lvi.iImage = imageIndex;
-        lvi.mask |= LVIF_IMAGE;
-    }
-
-    if ( ListView_SetItem(hList, &lvi) )
-    {
-        result = TheZeroObj;
-
-        pCLvFullRow pclvfr = maybeGetFullRow(hList, itemIndex);
-        if ( pclvfr != NULL )
-        {
-            resetFullRowText(context, pclvfr, subitemIndex, text);
-
-            if ( imageIndex > -1 && subitemIndex <= pclvfr->subItemCount )
-            {
-                pclvfr->subItems[subitemIndex]->iImage = imageIndex;
-            }
-        }
-    }
-
-    return result;
-}
-
-/** ListView::modifyColumnPX()
- *
- *
- * @remarks  LVSCW_AUTOSIZE_USEHEADER and LVSCW_AUTOSIZE are *only* accepted by
- *           ListView_SetColumnWidth()
- */
-RexxMethod5(RexxObjectPtr, lv_modifyColumnPx, uint32_t, index, OPTIONAL_CSTRING, label, OPTIONAL_uint16_t, _width,
-            OPTIONAL_CSTRING, align, CSELF, pCSelf)
-{
-    HWND hList = getDChCtrl(pCSelf);
-    LVCOLUMN lvi = {0};
-
-    if ( argumentExists(2) && *label != '\0' )
-    {
-        lvi.pszText = (LPSTR)label;
-        lvi.cchTextMax = (int)strlen(label);
-        lvi.mask |= LVCF_TEXT;
-    }
-    if ( argumentExists(3) )
-    {
-        lvi.cx = _width;
-        lvi.mask |= LVCF_WIDTH;
-    }
-    if ( argumentExists(4) && *align != '\0' )
-    {
-        if ( StrCmpI(align, "CENTER")     == 0 ) lvi.fmt = LVCFMT_CENTER;
-        else if ( StrCmpI(align, "RIGHT") == 0 ) lvi.fmt = LVCFMT_RIGHT;
-        else if ( StrCmpI(align, "LEFT")  == 0 ) lvi.fmt = LVCFMT_LEFT;
-        else
-        {
-            wrongArgValueException(context->threadContext, 4, "LEFT, RIGHT, or CENTER", align);
-            goto err_out;
-        }
-        lvi.mask |= LVCF_FMT;
-    }
-
-    return (ListView_SetColumn(hList, index, &lvi) ? TheZeroObj : TheOneObj);
-
-err_out:
-    return TheNegativeOneObj;
-}
-
-/** ListView::modifyItem()
- *
- *  Modifies a list-view item using a LvItem object.
- *
- *  @remarks  There are 3 scenarios we have to manage here.
- *
- *            1.) There is no current lParam user data set.  In this case the
- *            lvItem is just used as is to do a set item.  If a lParam user data
- *            value is set, we need to protect it.
- *
- *            2.) There is a current lParam user data set, but it is not a full
- *            row object.  In this case, if lvItem contains a lParam user data
- *            value, we need to replace the current value with the new value.
- *
- *            3.) There is a current lParam user data set and it is a full row
- *            object.  In this case, if lvItem contains a lParma user data value
- *            we need to update the current value with the new value.  If not,
- *            we need to merge the new lvItem into the full row item.
- */
-RexxMethod2(logical_t, lv_modifyItem, RexxObjectPtr, lvItem, CSELF, pCSelf)
-{
-    pCDialogControl pcdc = validateDCCSelf(context, pCSelf);
-
-    if ( pcdc == NULL )
-    {
-        goto err_out;
-    }
-
-    if ( ! context->IsOfType(lvItem, "LVITEM") )
-    {
-        wrongClassException(context->threadContext, 1, "LvItem");
-        goto err_out;
-    }
-
-    HWND     hList = pcdc->hCtrl;
-    LPLVITEM lvi   = (LPLVITEM)context->ObjectToCSelf(lvItem);
-
-    RexxObjectPtr oldUserData      = getCurrentLviUserData(hList, lvi->iItem);
-    pCLvFullRow   pclvfr           = maybeGetFullRow(hList, lvi->iItem);
-    bool          lParamIsModified = (lvi->mask & LVIF_PARAM) ? true : false;
-
-    if ( ListView_SetItem(hList, lvi) == 0 )
-    {
-        goto err_out;
-    }
-
-    printf("New lv item mask=0x%08x state=0x%08x stateMask=0x%08x\n", lvi->mask, lvi->state, lvi->stateMask);
-
-    if ( lParamIsModified )
-    {
-        protectLviUserData(context, pcdc, lvi);
-    }
-
-    if ( oldUserData != TheNilObj )
-    {
-        if ( pclvfr == NULL )
-        {
-            if ( lParamIsModified )
-            {
-                unProtectControlUserData(context, pcdc, oldUserData);
-            }
-        }
-        else
-        {
-            if ( lParamIsModified )
-            {
-                unProtectControlUserData(context, pcdc, oldUserData);
-            }
-            else
-            {
-                mergeLviState(context, pclvfr, pclvfr->subItems[0], lvi);
-            }
-        }
-    }
-
-    return TRUE;
-
-err_out:
-    return FALSE;
-}
-
 /** ListView::next()
  *  ListView::nextSelected()
  *  ListView::nextLeft()
@@ -2800,6 +2159,675 @@
     return ListView_GetNextItem(getDChCtrl(pCSelf), startItem, flag);
 }
 
+/** ListView::selected()
+ *  ListView::focused()
+ *  ListView::dropHighlighted()
+ *
+ *
+ */
+RexxMethod2(int32_t, lv_getNextItemWithState, NAME, method, CSELF, pCSelf)
+{
+    uint32_t flag;
+
+    if ( *method == 'S' )
+    {
+        flag = LVNI_SELECTED;
+    }
+    else if ( *method == 'F' )
+    {
+        flag = LVNI_FOCUSED;
+    }
+    else
+    {
+        flag = LVNI_DROPHILITED;
+    }
+    return ListView_GetNextItem(getDChCtrl(pCSelf), -1, flag);
+}
+
+/** ListView::getSubitem()
+ *
+ *  Returns a LvSubItem object for the item and subitem indexes specified.
+ *
+ *  @remarks  The ListView_GetItem macro will not fail, even if the subitem
+ *            index is greater than any existing subitem.  Text is the empty
+ *            string.  Plus, there is no reason that the user could not have
+ *            added subitems, but the list-view is not in report view.  So, we
+ *            don't check subitemIndex with getColumnCount()
+ */
+RexxMethod3(RexxObjectPtr, lv_getSubitem, uint32_t, itemIndex, uint32_t, subitemIndex, CSELF, pCSelf)
+{
+    RexxObjectPtr result = TheNilObj;
+    HWND          hList  = getDChCtrl(pCSelf);
+
+    if ( subitemIndex == 0 )
+    {
+        goto done_out;
+    }
+
+    // If we have a LvFullRow object assigned to the user data, we use the Rexx
+    // subitem in the full row, if it exists.  maybeGetFullRow() will update the
+    // item index, which will ensure things are correct.
+
+    pCLvFullRow pclvfr = maybeGetFullRow(hList, itemIndex);
+    if ( pclvfr != NULL )
+    {
+        if ( subitemIndex <= pclvfr->subItemCount )
+        {
+            result = pclvfr->rxSubItems[subitemIndex];
+            goto done_out;
+        }
+    }
+
+    result = newLvSubitem(context, hList, itemIndex, subitemIndex);
+
+done_out:
+    return result;
+}
+
+/** ListView::hasCheckBoxes()
+ */
+RexxMethod1(RexxObjectPtr, lv_hasCheckBoxes, CSELF, pCSelf)
+{
+    return (hasCheckBoxes(getDChCtrl(pCSelf)) ? TheTrueObj : TheFalseObj);
+}
+
+/** ListView::hitTestInfo()
+ *
+ *  Determine the location of a point relative to the list-view control.
+ *
+ *  @param  pt  [required]  The position, x and y co-ordinates of the point to
+ *              test. This can be specified in two forms.
+ *
+ *      Form 1:  arg 1 is a .Point object.
+ *      Form 2:  arg 1 is the x co-ordinate and arg2 is the y co-ordinate.
+ *
+ *  @param  info  [optional in/out]  A directory object in which all hit info is
+ *                returned.  If the directory is supplied, on return the
+ *                directory will have these indexes:
+ *
+ *                info    Keywords concerning the location of the point.
+ *
+ *                infoEx  Extended keywords concerning the location of the
+ *                        point.  Vista and later.
+ *
+ *                item    Same value as the return.  The item index if the point
+ *                        hits an item, otherwise -1.  (Because list-views are 0
+ *                        based indexes in ooDialog.)
+ *
+ *                subItem The subitem index if the point hits a subitem.
+ *
+ *                group   Vista and later.  Group index of the item hit (read
+ *                        only). Valid only for owner data. If the point is
+ *                        within an item that is displayed in multiple groups
+ *                        then group will specify the group index of the item.
+ *
+ *  @return  The index of the item hit, or -1 if the point does not hit an item.
+ *
+ *  @note    Sometimes the returned index of the hit spot is all that is needed.
+ *           In these cases, there is no need to supply the optional directory
+ *           object.  However, other times the complete hit test information may
+ *           be desired.
+ *
+ *           Any x, y coordinates will work.  I.e. -6000, -7000 will work. The
+ *           item will be -1 and location will be "ABOVE TOLEFT"
+ */
+RexxMethod2(int32_t, lv_hitTestInfo, ARGLIST, args, CSELF, pCSelf)
+{
+    int32_t result = -1;
+
+    pCDialogControl pcdc = validateDCCSelf(context, pCSelf);
+    if ( pcdc == NULL )
+    {
+        goto done_out;
+    }
+    HWND hwnd = pcdc->hCtrl;
+
+    size_t sizeArray;
+    size_t argsUsed;
+    POINT  point;
+    if ( ! getPointFromArglist(context, args, &point, 1, 3, &sizeArray, &argsUsed) )
+    {
+        goto done_out;
+    }
+
+    bool haveDirectory = (sizeArray > argsUsed) ? true : false;
+    RexxDirectoryObject info;
+
+    // Check arg count against expected.
+    if ( sizeArray > (haveDirectory ? argsUsed + 1 : argsUsed) )
+    {
+        tooManyArgsException(context->threadContext, (haveDirectory ? argsUsed + 1 : argsUsed));
+        goto done_out;
+    }
+
+    if ( haveDirectory )
+    {
+        RexxObjectPtr _info = context->ArrayAt(args, argsUsed + 1);
+        if ( _info == NULLOBJECT || ! context->IsDirectory(_info) )
+        {
+            wrongClassException(context->threadContext, argsUsed + 1, "Directory");
+            goto done_out;
+        }
+
+        info = (RexxDirectoryObject)_info;
+    }
+
+    LVHITTESTINFO hti;
+    hti.pt = point;
+
+    char buf[128];
+    *buf = '\0';
+
+    if ( _isAtLeastVista() )
+    {
+        result = ListView_HitTestEx(hwnd, &hti);
+
+        if ( haveDirectory )
+        {
+            context->DirectoryPut(info, context->Int32(hti.iGroup), "GROUP");
+
+            if ( hti.flags & LVHT_EX_FOOTER          ) strcat(buf, "Footer ");
+            if ( hti.flags & LVHT_EX_GROUP           ) strcat(buf, "Group ");
+            if ( hti.flags & LVHT_EX_GROUP_BACKGROUND) strcat(buf, "GroupBackground ");
+            if ( hti.flags & LVHT_EX_GROUP_COLLAPSE  ) strcat(buf, "GroupCollapse ");
+            if ( hti.flags & LVHT_EX_GROUP_FOOTER    ) strcat(buf, "GroupFooter ");
+            if ( hti.flags & LVHT_EX_GROUP_HEADER    ) strcat(buf, "GroupHeader ");
+            if ( hti.flags & LVHT_EX_GROUP_STATEICON ) strcat(buf, "GroupStateIcon ");
+            if ( hti.flags & LVHT_EX_GROUP_SUBSETLINK) strcat(buf, "GroupSubsetLink ");
+            if ( hti.flags & LVHT_EX_ONCONTENTS      ) strcat(buf, "OnContents ");
+
+            if ( *buf != '\0' )
+            {
+                *(buf + strlen(buf) - 1) = '\0';
+            }
+            context->DirectoryPut(info, context->String(buf), "INFOEX");
+        }
+    }
+    else
+    {
+        result = ListView_HitTest(hwnd, &hti);
+    }
+
+    if ( haveDirectory )
+    {
+        context->DirectoryPut(info, context->Int32(hti.iItem), "ITEM");
+        context->DirectoryPut(info, context->Int32(hti.iSubItem), "SUBITEM");
+
+        *buf = '\0';
+
+        if ( hti.flags & LVHT_ABOVE          ) strcat(buf, "Above ");
+        if ( hti.flags & LVHT_BELOW          ) strcat(buf, "Below ");
+        if ( hti.flags & LVHT_TORIGHT        ) strcat(buf, "ToRight ");
+        if ( hti.flags & LVHT_TOLEFT         ) strcat(buf, "ToLeft ");
+        if ( hti.flags & LVHT_NOWHERE        ) strcat(buf, "NoWhere ");
+        if ( hti.flags & LVHT_ONITEMICON     ) strcat(buf, "OnIcon ");
+        if ( hti.flags & LVHT_ONITEMLABEL    ) strcat(buf, "OnLabel ");
+        if ( hti.flags & LVHT_ONITEMSTATEICON) strcat(buf, "OnStateIcon ");
+        if ( hti.flags & LVHT_ONITEM         ) strcat(buf, "OnItem ");
+
+        if ( *buf != '\0' )
+        {
+            *(buf + strlen(buf) - 1) = '\0';
+        }
+        context->DirectoryPut(info, context->String(buf), "INFO");
+    }
+
+done_out:
+    return result;
+}
+
+/** ListView::insert()
+ *
+ * Inserts a new list view item or a new subitem into in an existing list view
+ * item.
+ *
+ * Note that as a byproduct of the way the underlying Windows API works, this
+ * method would also modify an existing subitem.
+ *
+ * @param itemIndex
+ * @param subitemIndex
+ * @param text
+ * @param imageIndex
+ *
+ * @return  -1 on error, othewise the inserted item index.
+ *
+ * @note  If a subitem is being inserted, the returned index will be the index
+ *        of the item the subitem is inserted into.
+ *
+ */
+RexxMethod5(int32_t, lv_insert, OPTIONAL_uint32_t, _itemIndex, OPTIONAL_uint32_t, subitemIndex, CSTRING, text,
+            OPTIONAL_int32_t, imageIndex, CSELF, pCSelf)
+{
+    HWND hList = getDChCtrl(pCSelf);
+    int32_t newItem = -1;
+    int32_t itemIndex = _itemIndex;
+    LVITEM lvi = {0};
+
+    if ( argumentOmitted(1) )
+    {
+        itemIndex = getDCinsertIndex(pCSelf);
+        if ( subitemIndex > 0 )
+        {
+            itemIndex--;
+            if ( itemIndex > (ListView_GetItemCount(hList) - 1) )
+            {
+                userDefinedMsgException(context->threadContext, 2, "A subitem can not be inserted prior to inserting the item");
+                goto done_out;
+            }
+        }
+    }
+
+    imageIndex = (argumentOmitted(4) ? -1 : imageIndex);
+
+    lvi.mask = LVIF_TEXT;
+    lvi.iItem = itemIndex;
+    lvi.iSubItem = subitemIndex;
+    lvi.pszText = (LPSTR)text;
+
+    if ( imageIndex > -1 )
+    {
+        lvi.iImage = imageIndex;
+        lvi.mask |= LVIF_IMAGE;
+    }
+
+    if ( subitemIndex == 0 )
+    {
+        newItem = ListView_InsertItem(hList, &lvi);
+        ((pCDialogControl)pCSelf)->lastItem = newItem;
+    }
+    else
+    {
+        if ( ListView_SetItem(hList, &lvi) )
+        {
+            newItem = itemIndex;
+        }
+    }
+
+done_out:
+    return newItem;
+}
+
+/** ListView::insertColumnPx()
+ *
+ *
+ *  @param column
+ *  @param text
+ *  @param width   The width of the column in pixels
+ *
+ *
+ *  @note  Even though the width argument in insertColumn() was documented as
+ *         being in pixels, the code actually converted it to dialog units.
+ *         This method is provided to really use pixels.
+ *
+ *  @remarks  Not sure why there is a restriction on the length of the column
+ *            label, or why the passed text is copied to a buffer.  The
+ *            ListView_InsertColumn() API does not impose a limit on the length,
+ *            and just asks for a pointer to a string.  Both the length
+ *            restriction and the copy are probably not needed.
+ */
+RexxMethod5(int, lv_insertColumnPx, OPTIONAL_uint16_t, column, CSTRING, text, uint16_t, width,
+            OPTIONAL_CSTRING, fmt, CSELF, pCSelf)
+{
+    HWND hwnd = getDChCtrl(pCSelf);
+
+    LVCOLUMN lvi = {0};
+    int retVal = 0;
+    char szText[256];
+
+    lvi.mask = LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT | LVCF_WIDTH;
+
+    // If omitted, column is 0, which is also the default.
+    lvi.iSubItem = column;
+
+    lvi.cchTextMax = (int)strlen(text);
+    if ( lvi.cchTextMax > (sizeof(szText) - 1) )
+    {
+        userDefinedMsgException(context->threadContext, 2, "the column title must be less than 256 characters");
+        return 0;
+    }
+    strcpy(szText, text);
+    lvi.pszText = szText;
+    lvi.cx = width;
+
+    lvi.fmt = LVCFMT_LEFT;
+    if ( argumentExists(4) )
+    {
+        char f = toupper(*fmt);
+        if ( f == 'C' )
+        {
+            lvi.fmt = LVCFMT_CENTER;
+        }
+        else if ( f == 'R' )
+        {
+            lvi.fmt = LVCFMT_RIGHT;
+        }
+    }
+
+    retVal = ListView_InsertColumn(hwnd, lvi.iSubItem, &lvi);
+    if ( retVal != -1 && lvi.fmt != LVCFMT_LEFT && lvi.iSubItem == 0 )
+    {
+        /* According to the MSDN docs: "If a column is added to a
+         * list-view control with index 0 (the leftmost column) and with
+         * LVCFMT_RIGHT or LVCFMT_CENTER specified, the text is not
+         * right-aligned or centered." This is the suggested work around.
+         */
+        lvi.iSubItem = 1;
+        ListView_InsertColumn(hwnd, lvi.iSubItem, &lvi);
+        ListView_DeleteColumn(hwnd, 0);
+    }
+    return retVal;
+}
+
+/** ListView::insertFullRow()
+ *
+ *  Inserts an item into the list view at the position specified using a
+ *  LvFullRow object.
+ *
+ */
+RexxMethod2(int32_t, lv_insertFullRow, RexxObjectPtr, row, CSELF, pCSelf)
+{
+    return fullRowOperation(context, row, lvfrInsert, pCSelf);
+}
+
+/** ListView::isChecked()
+ *
+ *
+ */
+RexxMethod2(RexxObjectPtr, lv_isChecked, int32_t, index, CSELF, pCSelf)
+{
+    HWND hList = getDChCtrl(pCSelf);
+
+    if ( hasCheckBoxes(hList) )
+    {
+        if ( index >= 0 && index <= ListView_GetItemCount(hList) - 1 )
+        {
+            if ( ListView_GetCheckState(hList, index) != 0 )
+            {
+                return TheTrueObj;
+            }
+        }
+    }
+    return TheFalseObj;
+}
+
+/** ListView::itemState()
+ *
+ *
+ */
+RexxMethod2(RexxStringObject, lv_itemState, uint32_t, index, CSELF, pCSelf)
+{
+    HWND hList = getDChCtrl(pCSelf);
+
+    uint32_t state = ListView_GetItemState(hList, index, LVIS_CUT | LVIS_DROPHILITED | LVIS_FOCUSED | LVIS_SELECTED);
+
+    char buf[64];
+    *buf = '\0';
+
+    if ( state & LVIS_CUT )         strcat(buf, "CUT ");
+    if ( state & LVIS_DROPHILITED ) strcat(buf, "DROP ");
+    if ( state & LVIS_FOCUSED )     strcat(buf, "FOCUSED ");
+    if ( state & LVIS_SELECTED )    strcat(buf, "SELECTED ");
+
+    if ( *buf != '\0' )
+    {
+        *(buf + strlen(buf) - 1) = '\0';
+    }
+    return context->String(buf);
+}
+
+/** ListView::itemText()
+ *
+ *
+ */
+RexxMethod3(RexxStringObject, lv_itemText, uint32_t, index, OPTIONAL_uint32_t, subitem, CSELF, pCSelf)
+{
+    char buf[256];
+    ListView_GetItemText(getDChCtrl(pCSelf), index, subitem, buf, sizeof(buf));
+    return context->String(buf);
+}
+
+/** ListView::setColumnWidthPX()
+ *
+ *
+ */
+RexxMethod3(RexxObjectPtr, lv_setColumnWidthPx, uint32_t, index, OPTIONAL_RexxObjectPtr, _width, CSELF, pCSelf)
+{
+    HWND hList = getDChCtrl(pCSelf);
+
+    int width = getColumnWidthArg(context, _width, 2);
+    if ( width == OOD_BAD_WIDTH_EXCEPTION )
+    {
+        return TheOneObj;
+    }
+
+    if ( width == LVSCW_AUTOSIZE || width == LVSCW_AUTOSIZE_USEHEADER )
+    {
+        if ( !isInReportView(hList) )
+        {
+            userDefinedMsgException(context->threadContext, 2, "can not be AUTO or AUTOHEADER if not in report view");
+            return TheOneObj;
+        }
+    }
+
+    return (ListView_SetColumnWidth(hList, index, width) ? TheZeroObj : TheOneObj);
+}
+
+/** ListView::modify()
+ *
+ *
+ *  @remarks  If the user has a LvFullRox object as the user data, we update the
+ *            values in that object after a successful modify().
+ */
+RexxMethod5(RexxObjectPtr, lv_modify, OPTIONAL_uint32_t, itemIndex, OPTIONAL_uint32_t, subitemIndex, CSTRING, text,
+            OPTIONAL_int32_t, imageIndex, CSELF, pCSelf)
+{
+    RexxObjectPtr result = TheOneObj;  // Error result.
+
+    HWND hList = getDChCtrl(pCSelf);
+
+    if ( argumentOmitted(1) )
+    {
+        itemIndex = getDCinsertIndex(pCSelf);
+        if ( subitemIndex > 0 )
+        {
+            itemIndex--;
+        }
+    }
+    itemIndex  = (argumentOmitted(1) ? getSelected(hList) : itemIndex);
+    imageIndex = (argumentOmitted(4) ? -1 : imageIndex);
+
+    if ( itemIndex < 0 )
+    {
+        itemIndex = 0;
+    }
+
+    LVITEM lvi = {0};
+    lvi.mask = LVIF_TEXT;
+    lvi.iItem = itemIndex;
+    lvi.iSubItem = subitemIndex;
+    lvi.pszText = (LPSTR)text;
+
+    if ( imageIndex > -1 )
+    {
+        lvi.iImage = imageIndex;
+        lvi.mask |= LVIF_IMAGE;
+    }
+
+    if ( ListView_SetItem(hList, &lvi) )
+    {
+        result = TheZeroObj;
+
+        pCLvFullRow pclvfr = maybeGetFullRow(hList, itemIndex);
+        if ( pclvfr != NULL )
+        {
+            resetFullRowText(context, pclvfr, subitemIndex, text);
+
+            if ( imageIndex > -1 && subitemIndex <= pclvfr->subItemCount )
+            {
+                pclvfr->subItems[subitemIndex]->iImage = imageIndex;
+            }
+        }
+    }
+
+    return result;
+}
+
+/** ListView::modifyColumnPX()
+ *
+ *
+ * @remarks  LVSCW_AUTOSIZE_USEHEADER and LVSCW_AUTOSIZE are *only* accepted by
+ *           ListView_SetColumnWidth()
+ */
+RexxMethod5(RexxObjectPtr, lv_modifyColumnPx, uint32_t, index, OPTIONAL_CSTRING, label, OPTIONAL_uint16_t, _width,
+            OPTIONAL_CSTRING, align, CSELF, pCSelf)
+{
+    HWND hList = getDChCtrl(pCSelf);
+    LVCOLUMN lvi = {0};
+
+    if ( argumentExists(2) && *label != '\0' )
+    {
+        lvi.pszText = (LPSTR)label;
+        lvi.cchTextMax = (int)strlen(label);
+        lvi.mask |= LVCF_TEXT;
+    }
+    if ( argumentExists(3) )
+    {
+        lvi.cx = _width;
+        lvi.mask |= LVCF_WIDTH;
+    }
+    if ( argumentExists(4) && *align != '\0' )
+    {
+        if ( StrCmpI(align, "CENTER")     == 0 ) lvi.fmt = LVCFMT_CENTER;
+        else if ( StrCmpI(align, "RIGHT") == 0 ) lvi.fmt = LVCFMT_RIGHT;
+        else if ( StrCmpI(align, "LEFT")  == 0 ) lvi.fmt = LVCFMT_LEFT;
+        else
+        {
+            wrongArgValueException(context->threadContext, 4, "LEFT, RIGHT, or CENTER", align);
+            goto err_out;
+        }
+        lvi.mask |= LVCF_FMT;
+    }
+
+    return (ListView_SetColumn(hList, index, &lvi) ? TheZeroObj : TheOneObj);
+
+err_out:
+    return TheNegativeOneObj;
+}
+
+/** ListView::modifyItem()
+ *
+ *  Modifies a list-view item using a LvItem object.
+ *
+ *  @remarks  There are 3 scenarios we have to manage here.
+ *
+ *            1.) There is no current lParam user data set.  In this case the
+ *            lvItem is just used as is to do a set item.  If a lParam user data
+ *            value is set, we need to protect it.
+ *
+ *            2.) There is a current lParam user data set, but it is not a full
+ *            row object.  In this case, if lvItem contains a lParam user data
+ *            value, we need to replace the current value with the new value.
+ *
+ *            3.) There is a current lParam user data set and it is a full row
+ *            object.  In this case, if lvItem contains a lParma user data value
+ *            we need to update the current value with the new value.  If not,
+ *            we need to merge the new lvItem into the full row item.
+ */
+RexxMethod2(logical_t, lv_modifyItem, RexxObjectPtr, lvItem, CSELF, pCSelf)
+{
+    pCDialogControl pcdc = validateDCCSelf(context, pCSelf);
+
+    if ( pcdc == NULL )
+    {
+        goto err_out;
+    }
+
+    if ( ! context->IsOfType(lvItem, "LVITEM") )
+    {
+        wrongClassException(context->threadContext, 1, "LvItem");
+        goto err_out;
+    }
+
+    HWND     hList = pcdc->hCtrl;
+    LPLVITEM lvi   = (LPLVITEM)context->ObjectToCSelf(lvItem);
+
+    RexxObjectPtr oldUserData      = getCurrentLviUserData(hList, lvi->iItem);
+    pCLvFullRow   pclvfr           = maybeGetFullRow(hList, lvi->iItem);
+    bool          lParamIsModified = (lvi->mask & LVIF_PARAM) ? true : false;
+
+    if ( ListView_SetItem(hList, lvi) == 0 )
+    {
+        goto err_out;
+    }
+
+    printf("New lv item mask=0x%08x state=0x%08x stateMask=0x%08x\n", lvi->mask, lvi->state, lvi->stateMask);
+
+    if ( lParamIsModified )
+    {
+        protectLviUserData(context, pcdc, lvi);
+    }
+
+    if ( oldUserData != TheNilObj )
+    {
+        if ( pclvfr == NULL )
+        {
+            if ( lParamIsModified )
+            {
+                unProtectControlUserData(context, pcdc, oldUserData);
+            }
+        }
+        else
+        {
+            if ( lParamIsModified )
+            {
+                unProtectControlUserData(context, pcdc, oldUserData);
+            }
+            else
+            {
+                mergeLviState(context, pclvfr, pclvfr->subItems[0], lvi);
+            }
+        }
+    }
+
+    return TRUE;
+
+err_out:
+    return FALSE;
+}
+
+/** ListView::removeItemData()
+ *
+ * @remarks  Note that if the lParam user data is a LvFullRow object, there is
+ *           no updating of that object that needs to be done, it is simply
+ *           removed from the list-view.
+ */
+RexxMethod2(RexxObjectPtr, lv_removeItemData, uint32_t, index, CSELF, pCSelf)
+{
+    pCDialogControl pcdc = validateDCCSelf(context, pCSelf);
+    if ( pcdc == NULL )
+    {
+        return TheNilObj;
+    }
+
+    RexxObjectPtr result = getCurrentLviUserData(pcdc->hCtrl, index);
+    if ( result != TheNilObj )
+    {
+        LVITEM lvi = {LVIF_PARAM, index};
+
+        if ( ListView_SetItem(pcdc->hCtrl, &lvi) )
+        {
+            unProtectControlUserData(context, pcdc, result);
+        }
+        else
+        {
+            // Not removed, set result back to the .nil ojbect.
+            result = TheNilObj;
+        }
+    }
+
+    return result;
+}
+
 /** ListView::replaceExtendedStyle()
  *
  *
@@ -2829,39 +2857,6 @@
     return changeStyle(context, (pCDialogControl)pCSelf, removeStyle, additionalStyle, true);
 }
 
-/** ListView::removeItemData()
- *
- * @remarks  Note that if the lParam user data is a LvFullRow object, there is
- *           no updating of that object that needs to be done, it is simply
- *           removed from the list-view.
- */
-RexxMethod2(RexxObjectPtr, lv_removeItemData, uint32_t, index, CSELF, pCSelf)
-{
-    pCDialogControl pcdc = validateDCCSelf(context, pCSelf);
-    if ( pcdc == NULL )
-    {
-        return TheNilObj;
-    }
-
-    RexxObjectPtr result = getCurrentLviUserData(pcdc->hCtrl, index);
-    if ( result != TheNilObj )
-    {
-        LVITEM lvi = {LVIF_PARAM, index};
-
-        if ( ListView_SetItem(pcdc->hCtrl, &lvi) )
-        {
-            unProtectControlUserData(context, pcdc, result);
-        }
-        else
-        {
-            // Not removed, set result back to the .nil ojbect.
-            result = TheNilObj;
-        }
-    }
-
-    return result;
-}
-
 /** ListView::select()
  *  ListView::deselect()
  *  ListView::focus()
@@ -2891,31 +2886,6 @@
     return TheZeroObj;
 }
 
-/** ListView::selected()
- *  ListView::focused()
- *  ListView::dropHighlighted()
- *
- *
- */
-RexxMethod2(int32_t, lv_getNextItemWithState, NAME, method, CSELF, pCSelf)
-{
-    uint32_t flag;
-
-    if ( *method == 'S' )
-    {
-        flag = LVNI_SELECTED;
-    }
-    else if ( *method == 'F' )
-    {
-        flag = LVNI_FOCUSED;
-    }
-    else
-    {
-        flag = LVNI_DROPHILITED;
-    }
-    return ListView_GetNextItem(getDChCtrl(pCSelf), -1, flag);
-}
-
 /** ListView::prependFullRow()
  *
  *  Adds an item to the list view at the beginning of the list using a LvFullRow
@@ -2925,6 +2895,36 @@
 RexxMethod2(int32_t, lv_prependFullRow, RexxObjectPtr, row, CSELF, pCSelf)
 {
     return fullRowOperation(context, row, lvfrInsert, pCSelf);
+}
+
+/** ListView::BkColor=
+ *  ListView::TextColor=
+ *  ListView::TextBkColor=
+ *
+ *
+ *  @remarks.  This method is hopelessly outdated.  It should take a COLORREF so
+ *             that the user has access to all available colors rather than be
+ *             limited to 18 colors out of a 256 color display.
+ */
+RexxMethod3(RexxObjectPtr, lv_setColor, uint32_t, color, NAME, method, CSELF, pCSelf)
+{
+    HWND hList = getDChCtrl(pCSelf);
+
+    COLORREF ref = PALETTEINDEX(color);
+
+    if ( *method == 'B' )
+    {
+        ListView_SetBkColor(hList, ref);
+    }
+    else if ( method[4] == 'C' )
+    {
+        ListView_SetTextColor(hList, ref);
+    }
+    else
+    {
+        ListView_SetTextBkColor(hList, ref);
+    }
+    return NULLOBJECT;
 }
 
 /** ListView::setColumnOrder()