+/////////////////////////////////////////////////////////////////////////////
+//
+// BumpRecordIds
+//
+//  Since OS/2 does not keep native record id's but wx insists on inserting
+//  and selecting via ID's, when we insert a record in the middle we need
+//  to bump the id's of each record after the one we just inserted.
+//
+// PARAMETERS
+//  hWnd    -- window handle of container to search
+//  pRecord -- record after which we starting bumping id's
+//
+// RETURN VALUE
+//  none
+//
+/////////////////////////////////////////////////////////////////////////////
+void BumpRecordIds (
+  HWND                              hWnd
+, PMYRECORD                         pRecord
+)
+{
+    while(pRecord)
+    {
+        pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
+                                                      ,CM_QUERYRECORD
+                                                      ,MPFROMP(pRecord)
+                                                      ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
+                                                     ));
+        if (pRecord)
+            pRecord->m_ulItemId++;
+    }
+} // end of BumpRecordIds
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// GetInternalData
+//
+//  Get the internal data given a handle and an id
+//
+// PARAMETERS
+//  hWnd    -- window handle to the control in which item is located
+//  lItemId -- ID to get
+//
+// RETURN VALUE
+//  pointer to the internal data
+//
+// Note:
+//  Under OS/2 PM a container item cannot be obtained via a simple index or
+//  id retrieval.  We have to walk the record list if we are looking for
+//  a record at a specific index location
+/////////////////////////////////////////////////////////////////////////////
+CListItemInternalData* GetInternalData (
+  HWND                              hWnd
+, long                              lItemId
+)
+{
+    PMYRECORD                       pRecord = FindOS2ListRecordByID( hWnd
+                                                                    ,lItemId
+                                                                   );
+    //
+    // Internal user data is stored AFTER the last field of the RECORDCORE
+    //
+    if (!pRecord)
+        return NULL;
+    return((CListItemInternalData *)(pRecord->m_ulUserData));
+} // end of GetInternalData
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// GetInternalData
+//
+//  Get the internal data given a pointer to a list control and an id
+//
+// PARAMETERS
+//  pCtl    -- pointer to control inwhich item is located
+//  lItemId -- ID to get
+//
+// RETURN VALUE
+//  pointer to the internal data
+//
+/////////////////////////////////////////////////////////////////////////////
+CListItemInternalData* GetInternalData (
+  wxListCtrl*                       pCtl
+, long                              lItemId
+)
+{
+    return(GetInternalData( (HWND)pCtl->GetHWND()
+                           ,lItemId
+                          ));
+} // end of GetInternalData
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DeleteInternalData
+//
+//  Delete the internal data for a record
+//
+// PARAMETERS
+//  pCtl    -- pointer to the list control containing the record
+//  lItemId -- the record index to delete the internal data from
+//
+// RETURN VALUE
+//  pointer to the internal data attribute
+//
+/////////////////////////////////////////////////////////////////////////////
+void DeleteInternalData (
+  wxListCtrl*                       pCtl
+, long                              lItemId
+)
+{
+    CListItemInternalData*          pData = GetInternalData( pCtl
+                                                            ,lItemId
+                                                           );
+    if (pData)
+    {
+        if (pData->m_pMyRecord)
+            pData->m_pMyRecord->m_ulUserData = 0;
+        delete pData;
+    }
+} // end of DeleteInternalData
+
+// #pragma page   "GetInternalDataAttr"
+/////////////////////////////////////////////////////////////////////////////
+//
+// GetInternalDataAttr
+//
+//  Get the internal data item attribute given a pointer to a list control
+//  and an id
+//
+// PARAMETERS
+//  pCtl    -- pointer to control to set
+//  lItemId -- ID to set
+//
+// RETURN VALUE
+//  pointer to the internal data attribute
+//
+/////////////////////////////////////////////////////////////////////////////
+wxListItemAttr* GetInternalDataAttr (
+  wxListCtrl*                       pCtl
+, long                              lItemId
+)
+{
+    CListItemInternalData*          pData = GetInternalData( pCtl
+                                                            ,lItemId
+                                                           );
+
+    if (pData)
+        return(pData->m_pAttr);
+    else
+        return NULL;
+} // end of GetInternalDataAttr
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// InternalDataCompareFunc
+//
+//  This is compare function we pass to PM.  It wraps the real compare
+//  function in SInternalDataSort
+//
+// PARAMETERS
+//  p1       -- is the first record structure to compare
+//  p2       -- is the second record structure to compare
+//  lStorage -- is the same value as passed to SortItems.
+//
+// RETURN VALUE
+//  pointer to the internal data attribute
+//
+/////////////////////////////////////////////////////////////////////////////
+SHORT EXPENTRY InternalDataCompareFunc (
+  PMYRECORD                         p1
+, PMYRECORD                         p2
+, PVOID                             pStorage
+)
+{
+    SInternalDataSort*              pInternalData = (SInternalDataSort *)pStorage;
+    CListItemInternalData*          pData1 = (CListItemInternalData *)p1->m_ulUserData;
+    CListItemInternalData*          pData2 = (CListItemInternalData *)p2->m_ulUserData;
+    long                            lD1 = (pData1 == NULL ? 0 : (long)pData1->m_lParam);
+    long                            lD2 = (pData2 == NULL ? 0 : (long)pData2->m_lParam);
+
+    return(pInternalData->m_fnUser( lD1
+                                   ,lD2
+                                   ,pInternalData->m_lData
+                                  ));
+} // end of InternalDataCompareFunc
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// ConvertFromOS2ListItem
+//
+//  Convert from an internal PM List item to a Toolkit List item
+//
+// PARAMETERS
+//  hWndListCtrl -- the control's windows handle
+//  rInfo        -- the library list control to convert to
+//  pRecord      -- the OS list control to convert from
+//
+// RETURN VALUE
+//  none
+//
+/////////////////////////////////////////////////////////////////////////////
+void ConvertFromOS2ListItem ( HWND hWndListCtrl,
+                              wxListItem& rInfo,
+                              PMYRECORD pRecord )
+{
+    CListItemInternalData* pInternaldata = (CListItemInternalData *)pRecord->m_ulUserData;
+    bool bNeedText = false;
+
+    if (pInternaldata)
+        rInfo.SetData(pInternaldata->m_lParam);
+
+    rInfo.SetMask(0);
+    rInfo.SetState(0);
+    rInfo.SetStateMask(0);
+    rInfo.SetId((long)pRecord->m_ulItemId);
+    if (hWndListCtrl != 0)
+    {
+        pRecord = FindOS2ListRecordByID( hWndListCtrl
+                                        ,rInfo.GetId()
+                                       );
+    }
+
+    //
+    // The wxListItem class is really set up to handle the WIN32 list item
+    // and OS/2 are not as complicated.  Just set both state members to the
+    // same thing under OS/2
+    //
+    if (pRecord->m_vRecord.flRecordAttr & CRA_DROPONABLE)
+    {
+        rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_DROPHILITED);
+        rInfo.SetState(rInfo.m_state | wxLIST_STATE_DROPHILITED);
+    }
+    if (pRecord->m_vRecord.flRecordAttr & CRA_SELECTED)
+    {
+        rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_SELECTED);
+        rInfo.SetState(rInfo.m_state | wxLIST_STATE_SELECTED);
+    }
+    if (pRecord->m_vRecord.flRecordAttr & CRA_DISABLED)
+    {
+        rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_DISABLED);
+        rInfo.SetState(rInfo.m_state | wxLIST_STATE_DISABLED);
+    }
+    if (pRecord->m_vRecord.flRecordAttr & CRA_FILTERED)
+    {
+        rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_FILTERED);
+        rInfo.SetState(rInfo.m_state | wxLIST_STATE_FILTERED);
+    }
+    if (pRecord->m_vRecord.flRecordAttr & CRA_INUSE)
+    {
+        rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_INUSE);
+        rInfo.SetState(rInfo.m_state | wxLIST_STATE_INUSE);
+    }
+    if (pRecord->m_vRecord.flRecordAttr & CRA_PICKED)
+    {
+        rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_PICKED);
+        rInfo.SetState(rInfo.m_state | wxLIST_STATE_PICKED);
+    }
+    if (pRecord->m_vRecord.flRecordAttr & CRA_SOURCE)
+    {
+        rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_SOURCE);
+        rInfo.SetState(rInfo.m_state | wxLIST_STATE_SOURCE);
+    }
+
+    if (pRecord->m_vRecord.pszText != (PSZ)NULL)
+    {
+        rInfo.SetMask(rInfo.GetMask() | wxLIST_MASK_TEXT);
+        rInfo.SetText(pRecord->m_vRecord.pszText);
+    }
+    if (pRecord->m_vRecord.pszIcon != (PSZ)NULL ||
+        pRecord->m_vRecord.pszName != (PSZ)NULL)
+    {
+        rInfo.SetMask(rInfo.GetMask() | wxLIST_MASK_IMAGE);
+        rInfo.SetImage(pRecord->m_vRecord.hptrIcon);
+    }
+    if (pRecord->m_ulUserData)
+        rInfo.SetMask(rInfo.GetMask() | wxLIST_MASK_DATA);
+} // end of ConvertFromOS2ListItem
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// ConvertToOS2Flags
+//
+//  Convert from an library states to OS states
+//
+// PARAMETERS
+//  lState       -- the state
+//  pRecord      -- the OS list control to use
+//
+// RETURN VALUE
+//  none
+//
+/////////////////////////////////////////////////////////////////////////////
+void ConvertToOS2Flags (
+  long                              lState
+, PMYRECORD                         pRecord
+)
+{
+    if (lState & wxLIST_STATE_DROPHILITED)
+        pRecord->m_vRecord.flRecordAttr |= CRA_DROPONABLE;
+    if (lState & wxLIST_STATE_SELECTED)
+        pRecord->m_vRecord.flRecordAttr |= CRA_SELECTED;
+    if (lState & wxLIST_STATE_DISABLED)
+        pRecord->m_vRecord.flRecordAttr |= CRA_DISABLED;
+    if (lState & wxLIST_STATE_FILTERED)
+        pRecord->m_vRecord.flRecordAttr |= CRA_FILTERED;
+    if (lState & wxLIST_STATE_INUSE)
+        pRecord->m_vRecord.flRecordAttr |= CRA_INUSE;
+    if (lState & wxLIST_STATE_PICKED)
+        pRecord->m_vRecord.flRecordAttr |= CRA_PICKED;
+    if (lState & wxLIST_STATE_SOURCE)
+        pRecord->m_vRecord.flRecordAttr |= CRA_SOURCE;
+} // end of ConvertToOS2Flags
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// ConvertToOS2ListItem
+//
+//  Convert from a library List item to an internal OS2 List item. We set
+//  only the fields we need to set.  Some of them are set by the API when
+//  they are added to the container.
+//
+// PARAMETERS
+//  pCtrl      -- the control to use
+//  rInfo      -- the item to convert
+//  pRecord    -- the OS list control to use, should be zeroed out
+//  pFieldinfo -- a field struct that may contain columnar data for detail view
+//
+// RETURN VALUE
+//  none
+//
+/////////////////////////////////////////////////////////////////////////////
+void ConvertToOS2ListItem (
+  const wxListCtrl*                 pCtrl
+, const wxListItem&                 rInfo
+, PMYRECORD                         pRecord
+, PFIELDINFO                        pFieldInfo
+)
+{
+    pRecord->m_ulItemId    = (ULONG)rInfo.GetId();
+    pRecord->m_vRecord.cb = sizeof(RECORDCORE);
+    if (rInfo.GetMask() & wxLIST_MASK_STATE)
+    {
+        ConvertToOS2Flags( rInfo.m_state
+                          ,pRecord
+                         );
+    }
+    if (pCtrl->GetWindowStyleFlag() & wxLC_ICON ||
+        pCtrl->GetWindowStyleFlag() & wxLC_SMALL_ICON)
+    {
+        pRecord->m_vRecord.pszIcon = (char*)rInfo.GetText().c_str();
+    }
+    if (pCtrl->GetWindowStyleFlag() & wxLC_LIST) // PM TEXT view
+    {
+        pRecord->m_vRecord.pszText = (char*)rInfo.GetText().c_str();
+    }
+    //
+    // In the case of a report view the text will be the data in the lead column
+    // ???? Don't know why, but that is how it works in other ports.
+    //
+    if (pCtrl->GetWindowStyleFlag() & wxLC_REPORT)
+    {
+        if (pFieldInfo)
+        {
+            switch(rInfo.GetColumn())
+            {
+                case 0:
+                    pRecord->m_pzColumn1 = (char*)rInfo.GetText().c_str();
+                    pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn1);
+                    break;
+
+                case 1:
+                    pRecord->m_pzColumn2 = (char*)rInfo.GetText().c_str();
+                    pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn2);
+                    break;
+
+                case 2:
+                    pRecord->m_pzColumn3 = (char*)rInfo.GetText().c_str();
+                    pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn3);
+                    break;
+
+                case 3:
+                    pRecord->m_pzColumn4 = (char*)rInfo.GetText().c_str();
+                    pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn4);
+                    break;
+
+                case 4:
+                    pRecord->m_pzColumn5 = (char*)rInfo.GetText().c_str();
+                    pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn5);
+                    break;
+
+                case 5:
+                    pRecord->m_pzColumn6 = (char*)rInfo.GetText().c_str();
+                    pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn6);
+                    break;
+
+                case 6:
+                    pRecord->m_pzColumn7 = (char*)rInfo.GetText().c_str();
+                    pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn7);
+                    break;
+
+                case 7:
+                    pRecord->m_pzColumn8 = (char*)rInfo.GetText().c_str();
+                    pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn8);
+                    break;
+
+                case 8:
+                    pRecord->m_pzColumn9 = (char*)rInfo.GetText().c_str();
+                    pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn9);
+                    break;
+
+                case 9:
+                    pRecord->m_pzColumn10 = (char*)rInfo.GetText().c_str();
+                    pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn10);
+                    break;
+
+                default:
+                    wxFAIL_MSG( wxT("wxOS2 does not support more than 10 columns in REPORT view") );
+                    break;
+            }