1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/os2/listctrl.cpp 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  33     #include "wx/settings.h" 
  34     #include "wx/dcclient.h" 
  35     #include "wx/textctrl.h" 
  38 #include "wx/imaglist.h" 
  39 #include "wx/listctrl.h" 
  41 #include "wx/os2/private.h" 
  44 // FIELDOFFSET in DETAIL view as defined in the OS2TK45 simply doesn't work 
  45 // We use this, which does! 
  48 #define FIELDOFFSET(type, field)    ((ULONG)&(((type *)0)->field)) 
  50 // ---------------------------------------------------------------------------- 
  51 // private helper classes 
  52 // ---------------------------------------------------------------------------- 
  54 ///////////////////////////////////////////////////////////////////////////// 
  56 //   Under OS/2 we have to use our own RECORDCORE based struct if we have 
  57 //   user data to store in a PM Container Control (and wxListCtrl is a PM 
  58 //   Container in ICON, NAME, TEXT or DETAIL view). m_ulUserData is a four 
  59 //   byte value containing a pointer to our CListIntemInternalData class 
  62 //   And now for the big time OS/2 Kludge.  In traditional OS/2 PM 
  63 //   applications using containers, programmers determine BEFORE creation 
  64 //   how many records the view will have, initially, and how many columns 
  65 //   the detail view of the container will have, as the container represents 
  66 //   a known data block.  Thus the OS/2 PM CV_DETAIL view, i.e. 
  67 //   the wxWidgets wxLC_REPORT view, relies on STATIC structure for its 
  68 //   columnar data.  It gets the data to display by telling it the specific 
  69 //   offset of the field in the struct containing the displayable data.  That 
  70 //   data has be of OS/2 Types, PSZ (char string), CDATE or CTIME format. 
  71 //   wxWidgets is dynamic in nature, however.  We insert columns, one at a 
  72 //   time and do not know how many until the app is done inserting them. So 
  73 //   for OS/2 I have to set a max allowable since they are fixed.  We return 
  74 //   an error to the app if they include more than we can handle. 
  76 //   For example to display the data "Col 4 of Item 6" in a report view, I'd 
  78 //   pRecord->m_pzColumn4 = "Col 4 of Item 6"; 
  79 //   pField->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn4); 
  80 //   and then call the PM API to set it. 
  82 //   This really stinks but I can't use a pointer to another struct as the 
  83 //   FIELDOFFSET call could only tell OS/2 the four byte value offset of 
  84 //   pointer field and it would display giberish in the column. 
  85 ///////////////////////////////////////////////////////////////////////////// 
  86 typedef struct _MYRECORD
 
  89     unsigned long                   m_ulItemId
; 
  90     unsigned long                   m_ulUserData
; //actually a pointer value to real data (a CListItemInternalData class instance) 
 101 } MYRECORD
, *PMYRECORD
; 
 103 ///////////////////////////////////////////////////////////////////////////// 
 104 // CLASS CListItemInternalData 
 107 //  The MSW version had problems with SetTextColour() et al as the 
 108 //  CListItemAttr's were stored keyed on the item index. If a item was 
 109 //  inserted anywhere but the end of the list the the text attributes 
 110 //  (colour etc) for the following items were out of sync. 
 113 //  Under MSW the only way to associate data with a 
 114 //  List item independent of its position in the list is to store a pointer 
 115 //  to it in its lParam attribute. However user programs are already using 
 116 //  this (via the SetItemData() GetItemData() calls). 
 118 //  However what we can do is store a pointer to a structure which contains 
 119 //  the attributes we want *and* a lParam for the users data, e.g. 
 121 //  class CListItemInternalData 
 124 //       GuiAdvCtrl_CListItemAttr* pAttr; 
 125 //       long                      lParam; // user data 
 128 //  To conserve memory, a CListItemInternalData is only allocated for a 
 129 //  LV_ITEM if text attributes or user data(lparam) are being set. 
 131 //  For OS/2, the lParam value points to whatever actual data we have 
 132 ///////////////////////////////////////////////////////////////////////////// 
 133 class CListItemInternalData
 
 137     CListItemInternalData(): m_pAttr(NULL
) 
 141     ~CListItemInternalData() 
 147     wxListItemAttr
*                 m_pAttr
; 
 148     WXLPARAM                        m_lParam
; // user data 
 149     PMYRECORD                       m_pMyRecord
; // so we can set the m_ulUserData to 0 when this is deleted 
 150 }; // end of CLASS CListItemInternalData 
 152 ///////////////////////////////////////////////////////////////////////////// 
 153 // STRUCT SInternalDataSort 
 157 // fn is a function which takes 3 long arguments: item1, item2, data. 
 158 // item1 is the long data associated with a first item (NOT the index). 
 159 // item2 is the long data associated with a second item (NOT the index). 
 160 // data is the same value as passed to SortItems. 
 162 // The return value is a negative number if the first item should precede the 
 163 // second item, a positive number of the second item should precede the first, 
 164 // or zero if the two items are equivalent. 
 166 // data is arbitrary data to be passed to the sort function. 
 168 // Internal structures for proxying the user compare function 
 169 // so that we can pass it the *real* user data 
 170 ///////////////////////////////////////////////////////////////////////////// 
 171 typedef struct internalDataSort
 
 173     wxListCtrlCompare               m_fnUser
; 
 175 } SInternalDataSort
; // end of STRUCT SInternalDataSort 
 177 // ---------------------------------------------------------------------------- 
 178 // private helper functions 
 179 // ---------------------------------------------------------------------------- 
 181 ///////////////////////////////////////////////////////////////////////////// 
 183 // FindOS2ListFieldByColNum 
 185 //  There is no way, under OS/2 to get a field in a container by index, 
 186 //  directly, so you must get the first one, then cycle through the list 
 187 //  until you get to where you want to be. 
 190 //  hWnd   -- window handle of container to search 
 191 //  lIndex -- index to set 
 194 //  pointer to the FIELDINFO struct at the index in the container record 
 196 ///////////////////////////////////////////////////////////////////////////// 
 197 PFIELDINFO 
FindOS2ListFieldByColNum ( 
 202     PFIELDINFO                      pFieldInfo 
= NULL
; 
 206     if (!::WinSendMsg( hWnd
 
 209                       ,(MPARAM
)(USHORT
)sizeof(CNRINFO
) 
 212     for (i 
= 0; i 
< vCnrInfo
.cFields
; i
++) 
 215             pFieldInfo 
= (PFIELDINFO
)PVOIDFROMMR(::WinSendMsg( hWnd
 
 216                                                               ,CM_QUERYDETAILFIELDINFO
 
 221             pFieldInfo 
= (PFIELDINFO
)PVOIDFROMMR(::WinSendMsg( hWnd
 
 222                                                               ,CM_QUERYDETAILFIELDINFO
 
 228         if (i 
== (ULONG
)lIndex
) 
 234 } // end of FindOS2ListFieldByColNum 
 236 ///////////////////////////////////////////////////////////////////////////// 
 238 // FindOS2ListRecordByID 
 240 //  There is no way, under OS/2 to get a record in a container by index, 
 241 //  directly, so you must get the first one, then cycle through the list 
 242 //  until you get to where you want to be. 
 245 //  hWnd    -- window handle of container to search 
 246 //  lItemId -- index to set 
 249 //  pointer to the internal RECORDCORE struct at the index in the container 
 251 ///////////////////////////////////////////////////////////////////////////// 
 252 PMYRECORD 
FindOS2ListRecordByID ( 
 257     PMYRECORD                       pRecord 
= NULL
; 
 261     if (!::WinSendMsg( hWnd
 
 264                       ,(MPARAM
)(USHORT
)sizeof(CNRINFO
) 
 267     for (i 
= 0; i 
< vCnrInfo
.cRecords
; i
++) 
 270             pRecord 
= (PMYRECORD
)PVOIDFROMMR(::WinSendMsg( hWnd
 
 273                                                           ,MPFROM2SHORT(CMA_FIRST
, CMA_ITEMORDER
) 
 276             pRecord 
= (PMYRECORD
)PVOIDFROMMR(::WinSendMsg( hWnd
 
 279                                                           ,MPFROM2SHORT(CMA_NEXT
, CMA_ITEMORDER
) 
 283         if (pRecord
->m_ulItemId 
== (ULONG
)lItemId
) 
 287 } // end of FindOS2ListRecordByID 
 289 ///////////////////////////////////////////////////////////////////////////// 
 293 //  Since OS/2 does not keep native record id's but wx insists on inserting 
 294 //  and selecting via ID's, when we insert a record in the middle we need 
 295 //  to bump the id's of each record after the one we just inserted. 
 298 //  hWnd    -- window handle of container to search 
 299 //  pRecord -- record after which we starting bumping id's 
 304 ///////////////////////////////////////////////////////////////////////////// 
 312         pRecord 
= (PMYRECORD
)PVOIDFROMMR(::WinSendMsg( hWnd
 
 315                                                       ,MPFROM2SHORT(CMA_NEXT
, CMA_ITEMORDER
) 
 318             pRecord
->m_ulItemId
++; 
 320 } // end of BumpRecordIds 
 322 ///////////////////////////////////////////////////////////////////////////// 
 326 //  Get the internal data given a handle and an id 
 329 //  hWnd    -- window handle to the control in which item is located 
 330 //  lItemId -- ID to get 
 333 //  pointer to the internal data 
 336 //  Under OS/2 PM a container item cannot be obtained via a simple index or 
 337 //  id retrieval.  We have to walk the record list if we are looking for 
 338 //  a record at a specific index location 
 339 ///////////////////////////////////////////////////////////////////////////// 
 340 CListItemInternalData
* GetInternalData ( 
 345     PMYRECORD                       pRecord 
= FindOS2ListRecordByID( hWnd
 
 349     // Internal user data is stored AFTER the last field of the RECORDCORE 
 353     return((CListItemInternalData 
*)(pRecord
->m_ulUserData
)); 
 354 } // end of GetInternalData 
 356 ///////////////////////////////////////////////////////////////////////////// 
 360 //  Get the internal data given a pointer to a list control and an id 
 363 //  pCtl    -- pointer to control inwhich item is located 
 364 //  lItemId -- ID to get 
 367 //  pointer to the internal data 
 369 ///////////////////////////////////////////////////////////////////////////// 
 370 CListItemInternalData
* GetInternalData ( 
 375     return(GetInternalData( (HWND
)pCtl
->GetHWND() 
 378 } // end of GetInternalData 
 380 ///////////////////////////////////////////////////////////////////////////// 
 382 // DeleteInternalData 
 384 //  Delete the internal data for a record 
 387 //  pCtl    -- pointer to the list control containing the record 
 388 //  lItemId -- the record index to delete the internal data from 
 391 //  pointer to the internal data attribute 
 393 ///////////////////////////////////////////////////////////////////////////// 
 394 void DeleteInternalData ( 
 399     CListItemInternalData
*          pData 
= GetInternalData( pCtl
 
 404         if (pData
->m_pMyRecord
) 
 405             pData
->m_pMyRecord
->m_ulUserData 
= 0; 
 408 } // end of DeleteInternalData 
 410 // #pragma page   "GetInternalDataAttr" 
 411 ///////////////////////////////////////////////////////////////////////////// 
 413 // GetInternalDataAttr 
 415 //  Get the internal data item attribute given a pointer to a list control 
 419 //  pCtl    -- pointer to control to set 
 420 //  lItemId -- ID to set 
 423 //  pointer to the internal data attribute 
 425 ///////////////////////////////////////////////////////////////////////////// 
 426 wxListItemAttr
* GetInternalDataAttr ( 
 431     CListItemInternalData
*          pData 
= GetInternalData( pCtl
 
 436         return(pData
->m_pAttr
); 
 439 } // end of GetInternalDataAttr 
 441 ///////////////////////////////////////////////////////////////////////////// 
 443 // InternalDataCompareFunc 
 445 //  This is compare function we pass to PM.  It wraps the real compare 
 446 //  function in SInternalDataSort 
 449 //  p1       -- is the first record structure to compare 
 450 //  p2       -- is the second record structure to compare 
 451 //  lStorage -- is the same value as passed to SortItems. 
 454 //  pointer to the internal data attribute 
 456 ///////////////////////////////////////////////////////////////////////////// 
 457 SHORT EXPENTRY 
InternalDataCompareFunc ( 
 463     SInternalDataSort
*              pInternalData 
= (SInternalDataSort 
*)pStorage
; 
 464     CListItemInternalData
*          pData1 
= (CListItemInternalData 
*)p1
->m_ulUserData
; 
 465     CListItemInternalData
*          pData2 
= (CListItemInternalData 
*)p2
->m_ulUserData
; 
 466     long                            lD1 
= (pData1 
== NULL 
? 0 : (long)pData1
->m_lParam
); 
 467     long                            lD2 
= (pData2 
== NULL 
? 0 : (long)pData2
->m_lParam
); 
 469     return(pInternalData
->m_fnUser( lD1
 
 471                                    ,pInternalData
->m_lData
 
 473 } // end of InternalDataCompareFunc 
 475 ///////////////////////////////////////////////////////////////////////////// 
 477 // ConvertFromOS2ListItem 
 479 //  Convert from an internal PM List item to a Toolkit List item 
 482 //  hWndListCtrl -- the control's windows handle 
 483 //  rInfo        -- the library list control to convert to 
 484 //  pRecord      -- the OS list control to convert from 
 489 ///////////////////////////////////////////////////////////////////////////// 
 490 void ConvertFromOS2ListItem ( HWND hWndListCtrl
, 
 494     CListItemInternalData
* pInternaldata 
= (CListItemInternalData 
*)pRecord
->m_ulUserData
; 
 495     bool bNeedText 
= false; 
 498         rInfo
.SetData(pInternaldata
->m_lParam
); 
 502     rInfo
.SetStateMask(0); 
 503     rInfo
.SetId((long)pRecord
->m_ulItemId
); 
 504     if (hWndListCtrl 
!= 0) 
 506         pRecord 
= FindOS2ListRecordByID( hWndListCtrl
 
 512     // The wxListItem class is really set up to handle the WIN32 list item 
 513     // and OS/2 are not as complicated.  Just set both state members to the 
 514     // same thing under OS/2 
 516     if (pRecord
->m_vRecord
.flRecordAttr 
& CRA_DROPONABLE
) 
 518         rInfo
.SetStateMask(rInfo
.m_stateMask 
| wxLIST_STATE_DROPHILITED
); 
 519         rInfo
.SetState(rInfo
.m_state 
| wxLIST_STATE_DROPHILITED
); 
 521     if (pRecord
->m_vRecord
.flRecordAttr 
& CRA_SELECTED
) 
 523         rInfo
.SetStateMask(rInfo
.m_stateMask 
| wxLIST_STATE_SELECTED
); 
 524         rInfo
.SetState(rInfo
.m_state 
| wxLIST_STATE_SELECTED
); 
 526     if (pRecord
->m_vRecord
.flRecordAttr 
& CRA_DISABLED
) 
 528         rInfo
.SetStateMask(rInfo
.m_stateMask 
| wxLIST_STATE_DISABLED
); 
 529         rInfo
.SetState(rInfo
.m_state 
| wxLIST_STATE_DISABLED
); 
 531     if (pRecord
->m_vRecord
.flRecordAttr 
& CRA_FILTERED
) 
 533         rInfo
.SetStateMask(rInfo
.m_stateMask 
| wxLIST_STATE_FILTERED
); 
 534         rInfo
.SetState(rInfo
.m_state 
| wxLIST_STATE_FILTERED
); 
 536     if (pRecord
->m_vRecord
.flRecordAttr 
& CRA_INUSE
) 
 538         rInfo
.SetStateMask(rInfo
.m_stateMask 
| wxLIST_STATE_INUSE
); 
 539         rInfo
.SetState(rInfo
.m_state 
| wxLIST_STATE_INUSE
); 
 541     if (pRecord
->m_vRecord
.flRecordAttr 
& CRA_PICKED
) 
 543         rInfo
.SetStateMask(rInfo
.m_stateMask 
| wxLIST_STATE_PICKED
); 
 544         rInfo
.SetState(rInfo
.m_state 
| wxLIST_STATE_PICKED
); 
 546     if (pRecord
->m_vRecord
.flRecordAttr 
& CRA_SOURCE
) 
 548         rInfo
.SetStateMask(rInfo
.m_stateMask 
| wxLIST_STATE_SOURCE
); 
 549         rInfo
.SetState(rInfo
.m_state 
| wxLIST_STATE_SOURCE
); 
 552     if (pRecord
->m_vRecord
.pszText 
!= (PSZ
)NULL
) 
 554         rInfo
.SetMask(rInfo
.GetMask() | wxLIST_MASK_TEXT
); 
 555         rInfo
.SetText(pRecord
->m_vRecord
.pszText
); 
 557     if (pRecord
->m_vRecord
.pszIcon 
!= (PSZ
)NULL 
|| 
 558         pRecord
->m_vRecord
.pszName 
!= (PSZ
)NULL
) 
 560         rInfo
.SetMask(rInfo
.GetMask() | wxLIST_MASK_IMAGE
); 
 561         rInfo
.SetImage(pRecord
->m_vRecord
.hptrIcon
); 
 563     if (pRecord
->m_ulUserData
) 
 564         rInfo
.SetMask(rInfo
.GetMask() | wxLIST_MASK_DATA
); 
 565 } // end of ConvertFromOS2ListItem 
 567 ///////////////////////////////////////////////////////////////////////////// 
 571 //  Convert from an library states to OS states 
 574 //  lState       -- the state 
 575 //  pRecord      -- the OS list control to use 
 580 ///////////////////////////////////////////////////////////////////////////// 
 581 void ConvertToOS2Flags ( 
 586     if (lState 
& wxLIST_STATE_DROPHILITED
) 
 587         pRecord
->m_vRecord
.flRecordAttr 
|= CRA_DROPONABLE
; 
 588     if (lState 
& wxLIST_STATE_SELECTED
) 
 589         pRecord
->m_vRecord
.flRecordAttr 
|= CRA_SELECTED
; 
 590     if (lState 
& wxLIST_STATE_DISABLED
) 
 591         pRecord
->m_vRecord
.flRecordAttr 
|= CRA_DISABLED
; 
 592     if (lState 
& wxLIST_STATE_FILTERED
) 
 593         pRecord
->m_vRecord
.flRecordAttr 
|= CRA_FILTERED
; 
 594     if (lState 
& wxLIST_STATE_INUSE
) 
 595         pRecord
->m_vRecord
.flRecordAttr 
|= CRA_INUSE
; 
 596     if (lState 
& wxLIST_STATE_PICKED
) 
 597         pRecord
->m_vRecord
.flRecordAttr 
|= CRA_PICKED
; 
 598     if (lState 
& wxLIST_STATE_SOURCE
) 
 599         pRecord
->m_vRecord
.flRecordAttr 
|= CRA_SOURCE
; 
 600 } // end of ConvertToOS2Flags 
 602 ///////////////////////////////////////////////////////////////////////////// 
 604 // ConvertToOS2ListItem 
 606 //  Convert from a library List item to an internal OS2 List item. We set 
 607 //  only the fields we need to set.  Some of them are set by the API when 
 608 //  they are added to the container. 
 611 //  pCtrl      -- the control to use 
 612 //  rInfo      -- the item to convert 
 613 //  pRecord    -- the OS list control to use, should be zeroed out 
 614 //  pFieldinfo -- a field struct that may contain columnar data for detail view 
 619 ///////////////////////////////////////////////////////////////////////////// 
 620 void ConvertToOS2ListItem ( 
 621   const wxListCtrl
*                 pCtrl
 
 622 , const wxListItem
&                 rInfo
 
 624 , PFIELDINFO                        pFieldInfo
 
 627     pRecord
->m_ulItemId    
= (ULONG
)rInfo
.GetId(); 
 628     pRecord
->m_vRecord
.cb 
= sizeof(RECORDCORE
); 
 629     if (rInfo
.GetMask() & wxLIST_MASK_STATE
) 
 631         ConvertToOS2Flags( rInfo
.m_state
 
 635     if (pCtrl
->GetWindowStyleFlag() & wxLC_ICON 
|| 
 636         pCtrl
->GetWindowStyleFlag() & wxLC_SMALL_ICON
) 
 638         pRecord
->m_vRecord
.pszIcon 
= (char*)rInfo
.GetText().c_str(); 
 640     if (pCtrl
->GetWindowStyleFlag() & wxLC_LIST
) // PM TEXT view 
 642         pRecord
->m_vRecord
.pszText 
= (char*)rInfo
.GetText().c_str(); 
 645     // In the case of a report view the text will be the data in the lead column 
 646     // ???? Don't know why, but that is how it works in other ports. 
 648     if (pCtrl
->GetWindowStyleFlag() & wxLC_REPORT
) 
 652             switch(rInfo
.GetColumn()) 
 655                     pRecord
->m_pzColumn1 
= (char*)rInfo
.GetText().c_str(); 
 656                     pFieldInfo
->offStruct 
= FIELDOFFSET(MYRECORD
, m_pzColumn1
); 
 660                     pRecord
->m_pzColumn2 
= (char*)rInfo
.GetText().c_str(); 
 661                     pFieldInfo
->offStruct 
= FIELDOFFSET(MYRECORD
, m_pzColumn2
); 
 665                     pRecord
->m_pzColumn3 
= (char*)rInfo
.GetText().c_str(); 
 666                     pFieldInfo
->offStruct 
= FIELDOFFSET(MYRECORD
, m_pzColumn3
); 
 670                     pRecord
->m_pzColumn4 
= (char*)rInfo
.GetText().c_str(); 
 671                     pFieldInfo
->offStruct 
= FIELDOFFSET(MYRECORD
, m_pzColumn4
); 
 675                     pRecord
->m_pzColumn5 
= (char*)rInfo
.GetText().c_str(); 
 676                     pFieldInfo
->offStruct 
= FIELDOFFSET(MYRECORD
, m_pzColumn5
); 
 680                     pRecord
->m_pzColumn6 
= (char*)rInfo
.GetText().c_str(); 
 681                     pFieldInfo
->offStruct 
= FIELDOFFSET(MYRECORD
, m_pzColumn6
); 
 685                     pRecord
->m_pzColumn7 
= (char*)rInfo
.GetText().c_str(); 
 686                     pFieldInfo
->offStruct 
= FIELDOFFSET(MYRECORD
, m_pzColumn7
); 
 690                     pRecord
->m_pzColumn8 
= (char*)rInfo
.GetText().c_str(); 
 691                     pFieldInfo
->offStruct 
= FIELDOFFSET(MYRECORD
, m_pzColumn8
); 
 695                     pRecord
->m_pzColumn9 
= (char*)rInfo
.GetText().c_str(); 
 696                     pFieldInfo
->offStruct 
= FIELDOFFSET(MYRECORD
, m_pzColumn9
); 
 700                     pRecord
->m_pzColumn10 
= (char*)rInfo
.GetText().c_str(); 
 701                     pFieldInfo
->offStruct 
= FIELDOFFSET(MYRECORD
, m_pzColumn10
); 
 705                     wxFAIL_MSG( _T("wxOS2 does not support more than 10 columns in REPORT view") ); 
 710     if (rInfo
.GetMask() & wxLIST_MASK_IMAGE
) 
 712         pRecord
->m_vRecord
.hptrIcon      
= (HPOINTER
)rInfo
.GetImage(); 
 713         pRecord
->m_vRecord
.hptrMiniIcon  
= (HPOINTER
)rInfo
.m_miniImage
; 
 715 } // end of ConvertToOS2ListItem 
 717 ///////////////////////////////////////////////////////////////////////////// 
 719 // ConvertToOS2ListCol 
 721 //  Convert from a library List column to an internal PM List column 
 724 //  lCol   -- the columnd to convert 
 725 //  rItem  -- the item to convert 
 726 //  pField -- the OS list column to use 
 731 ///////////////////////////////////////////////////////////////////////////// 
 732 void ConvertToOS2ListCol ( 
 734 , const wxListItem
&                 rItem
 
 738     memset(pField
, '\0', sizeof(FIELDINFO
)); 
 739     pField
->cb 
= sizeof(FIELDINFO
); 
 742     // Default some settings 
 744     pField
->flData  
= CFA_HORZSEPARATOR 
| CFA_SEPARATOR
; 
 745     pField
->flTitle 
= CFA_CENTER
; 
 747     if (rItem
.GetMask() & wxLIST_MASK_TEXT
) 
 749         pField
->flData 
|= CFA_STRING
; 
 750         pField
->pTitleData 
= (PVOID
)rItem
.GetText().c_str(); // text is column title not data 
 752     if (rItem
.GetMask() & wxLIST_MASK_FORMAT
) 
 754         if (rItem
.m_format 
== wxLIST_FORMAT_LEFT
) 
 755             pField
->flData 
|= CFA_LEFT
; 
 756         else if (rItem
.m_format 
== wxLIST_FORMAT_RIGHT
) 
 757             pField
->flData 
|= CFA_RIGHT
; 
 758         else if (rItem
.m_format 
== wxLIST_FORMAT_CENTRE
) 
 759             pField
->flData 
|= CFA_CENTER
; 
 762         pField
->flData 
|= CFA_CENTER
;  // Just ensure the default is centered 
 763     if (rItem
.GetMask() & wxLIST_MASK_WIDTH
) 
 765         if (!(rItem
.GetWidth() == wxLIST_AUTOSIZE 
|| 
 766              rItem
.GetWidth() == wxLIST_AUTOSIZE_USEHEADER
)) 
 767             pField
->cxWidth 
= rItem
.GetWidth(); 
 768         // else: OS/2 automatically sets the width if created with the approppriate style 
 772     // Still need to set the actual data 
 774     pField
->offStruct 
= 0; 
 775 } // end of ConvertToOS2ListCol 
 777 // ---------------------------------------------------------------------------- 
 779 // ---------------------------------------------------------------------------- 
 781 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_DRAG
) 
 782 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_RDRAG
) 
 783 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
) 
 784 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT
) 
 785 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM
) 
 786 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
) 
 787 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO
) 
 788 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO
) 
 789 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED
) 
 790 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED
) 
 791 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN
) 
 792 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM
) 
 793 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK
) 
 794 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_RIGHT_CLICK
) 
 795 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG
) 
 796 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_DRAGGING
) 
 797 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_END_DRAG
) 
 798 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
) 
 799 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK
) 
 800 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED
) 
 801 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_FOCUSED
) 
 802 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT
) 
 804 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl
, wxControl
) 
 805 IMPLEMENT_DYNAMIC_CLASS(wxListView
, wxListCtrl
) 
 806 IMPLEMENT_DYNAMIC_CLASS(wxListItem
, wxObject
) 
 808 IMPLEMENT_DYNAMIC_CLASS(wxListEvent
, wxNotifyEvent
) 
 810 BEGIN_EVENT_TABLE(wxListCtrl
, wxControl
) 
 811     EVT_PAINT(wxListCtrl::OnPaint
) 
 814 // ============================================================================ 
 816 // ============================================================================ 
 818 // ---------------------------------------------------------------------------- 
 819 // wxListCtrl construction 
 820 // ---------------------------------------------------------------------------- 
 822 void wxListCtrl::Init () 
 824     m_pImageListNormal     
= NULL
; 
 825     m_pImageListSmall      
= NULL
; 
 826     m_pImageListState      
= NULL
; 
 827     m_bOwnsImageListNormal 
= false; 
 828     m_bOwnsImageListSmall  
= false; 
 829     m_bOwnsImageListState  
= false; 
 833     m_bAnyInternalData     
= false; 
 834     m_bHasAnyAttr          
= false; 
 835 } // end of wxListCtrl::Init 
 837 bool wxListCtrl::Create ( wxWindow
* pParent
, 
 842                           const wxValidator
& rValidator
, 
 843                           const wxString
& rsName 
) 
 847     int nWidth 
= rSize
.x
; 
 848     int nHeight 
= rSize
.y
; 
 851     SetValidator(rValidator
); 
 852 #endif // wxUSE_VALIDATORS 
 855     SetWindowStyleFlag(lStyle
); 
 866     m_windowId 
= (vId 
== -1) ? NewControlId() : vId
; 
 868     long lSstyle 
= WS_VISIBLE 
| WS_TABSTOP
; 
 870     if (GetWindowStyleFlag() & wxCLIP_SIBLINGS
) 
 871         lSstyle 
|= WS_CLIPSIBLINGS
; 
 872     m_lBaseStyle 
= lSstyle
; 
 873     if (!DoCreateControl( nX
 
 880         pParent
->AddChild(this); 
 882 } // end of wxListCtrl::Create 
 884 bool wxListCtrl::DoCreateControl ( int nX
, int nY
, 
 885                                    int nWidth
, int nHeight 
) 
 887     DWORD lWstyle 
= m_lBaseStyle
; 
 888     long lOldStyle 
= 0; // Dummy 
 892     lWstyle 
|= ConvertToOS2Style( lOldStyle
 
 893                                  ,GetWindowStyleFlag() 
 896     m_hWnd 
= (WXHWND
)::WinCreateWindow( GetParent()->GetHWND() 
 901                                        ,GetParent()->GetHWND() 
 913     // Now set the display attributes of the container 
 915     if (!::WinSendMsg( GetHWND() 
 918                       ,(MPARAM
)(USHORT
)sizeof(CNRINFO
) 
 921     lWstyle 
= ConvertViewToOS2Style(GetWindowStyleFlag()); 
 922     vCnrInfo
.flWindowAttr 
|= lWstyle
; 
 923     if (!::WinSendMsg( GetHWND() 
 926                       ,(MPARAM
)CMA_FLWINDOWATTR
 
 931     // And now set needed arrangement flags 
 933     lWstyle 
= ConvertArrangeToOS2Style(GetWindowStyleFlag()); 
 934     if (!::WinSendMsg( GetHWND() 
 936                       ,(MPARAM
)CMA_ARRANGEGRID
 
 940     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
)); 
 941     SetForegroundColour(GetParent()->GetForegroundColour()); 
 943     SetFont(*wxSMALL_FONT
); 
 946     SetSize( nX
, nY
, nWidth
, nHeight 
); 
 948 } // end of wxListCtrl::DoCreateControl 
 950 void wxListCtrl::UpdateStyle () 
 955         DWORD dwStyleNew 
= ConvertToOS2Style( lDummy
, GetWindowStyleFlag() ); 
 957         dwStyleNew 
|= m_lBaseStyle
; 
 960         // Get the current window style. 
 962         ULONG dwStyleOld 
= ::WinQueryWindowULong(GetHWND(), QWL_STYLE
); 
 965         // Only set the window style if the view bits have changed. 
 967         if (dwStyleOld 
!= dwStyleNew
) 
 969             ::WinSetWindowULong(GetHWND(), QWL_STYLE
, dwStyleNew
); 
 972 } // end of wxListCtrl::UpdateStyle 
 974 void wxListCtrl::FreeAllInternalData () 
 976     if (m_bAnyInternalData
) 
 978         int n 
= GetItemCount(); 
 981         for (i 
= 0; i 
< n
; i
++) 
 982             DeleteInternalData(this, (long)i
); 
 983         m_bAnyInternalData 
= false; 
 985 } // end of wxListCtrl::FreeAllInternalData 
 987 wxListCtrl::~wxListCtrl () 
 989     FreeAllInternalData(); 
 992         m_pTextCtrl
->SetHWND(0); 
 993         m_pTextCtrl
->UnsubclassWin(); 
 998     if (m_bOwnsImageListNormal
) 
 999         delete m_pImageListNormal
; 
1000     if (m_bOwnsImageListSmall
) 
1001         delete m_pImageListSmall
; 
1002     if (m_bOwnsImageListState
) 
1003         delete m_pImageListState
; 
1004 } // end of wxListCtrl::~wxListCtrl 
1006 // ---------------------------------------------------------------------------- 
1007 // set/get/change style 
1008 // ---------------------------------------------------------------------------- 
1010 // Add or remove a single window style 
1011 void wxListCtrl::SetSingleStyle ( 
1016     long                            lFlag 
= GetWindowStyleFlag(); 
1019     // Get rid of conflicting styles 
1023         if (lStyle 
& wxLC_MASK_TYPE
) 
1024             lFlag 
= lFlag 
& ~wxLC_MASK_TYPE
; 
1025         if (lStyle 
& wxLC_MASK_ALIGN 
) 
1026             lFlag 
= lFlag 
& ~wxLC_MASK_ALIGN
; 
1027         if (lStyle 
& wxLC_MASK_SORT 
) 
1028             lFlag 
= lFlag 
& ~wxLC_MASK_SORT
; 
1042     m_windowStyle 
= lFlag
; 
1044 } // end of wxListCtrl::SetSingleStyle 
1046 // Set the whole window style 
1047 void wxListCtrl::SetWindowStyleFlag ( 
1051     m_windowStyle 
= lFlag
; 
1053 } // end of wxListCtrl::SetWindowStyleFlag 
1055 long wxListCtrl::ConvertToOS2Style ( 
1063     // The only styles OS2 uses on creation are auto arrange, read only, and 
1064     // and selection styles.  This lib does not support OS/2 MINIRECORDCORE 
1065     // or VERIFYPOINTER styles 
1067     if (lStyle 
& wxLC_AUTOARRANGE
) 
1068         lWstyle 
|= CCS_AUTOPOSITION
; 
1069     if (lStyle 
& wxLC_SINGLE_SEL
) 
1070         lWstyle 
|= CCS_SINGLESEL
; 
1072         lWstyle 
|= CCS_EXTENDSEL
; 
1073     if (!(lStyle 
& wxLC_EDIT_LABELS
)) 
1074         lWstyle 
|= CCS_READONLY
; 
1076 } // end of wxListCtrl::ConvertToOS2Style 
1078 long wxListCtrl::ConvertArrangeToOS2Style ( 
1084     if (lStyle 
& wxLC_ALIGN_LEFT
) 
1086         lWstyle 
|= CMA_LEFT
; 
1089     if (lStyle 
& wxLC_ALIGN_TOP
) 
1094 } // end of wxListCtrl::ConvertArrangeToOS2Style 
1096 long wxListCtrl::ConvertViewToOS2Style ( 
1100     long                            lWstyle 
= CA_DRAWICON
; // we will only use icons 
1102     if (lStyle 
& wxLC_ICON
) 
1106     if (lStyle 
& wxLC_SMALL_ICON
) 
1108         lWstyle 
|= (CV_ICON 
| CV_MINI
); 
1110     if (lStyle 
& wxLC_LIST
) 
1114     if (lStyle 
& wxLC_REPORT
) 
1116         lWstyle 
|= CV_DETAIL
; 
1118     if (lStyle 
& wxLC_VIRTUAL
) 
1120         lWstyle 
|= CA_OWNERDRAW
; 
1122     if (lStyle 
& wxLC_AUTOARRANGE
) 
1126     if (!(lStyle 
& wxLC_NO_HEADER
)) 
1128         lWstyle 
|= CA_DETAILSVIEWTITLES
; 
1131 } // end of wxListCtrl::ConvertViewToOS2Style 
1133 // ---------------------------------------------------------------------------- 
1135 // ---------------------------------------------------------------------------- 
1137 // Sets the foreground, i.e. text, colour 
1138 bool wxListCtrl::SetForegroundColour (const wxColour
& rCol
) 
1140     ULONG ulColor 
= wxColourToRGB(rCol
); 
1142     if (!wxWindow::SetForegroundColour(rCol
)) 
1145     ::WinSetPresParam( GetHWND() 
1151 } // end of wxListCtrl::SetForegroundColour 
1153 // Sets the background colour 
1154 bool wxListCtrl::SetBackgroundColour ( const wxColour
& rCol 
) 
1156     if (!wxWindow::SetBackgroundColour(rCol
)) 
1160     // We set the same colour for both the "empty" background and the items 
1163     ULONG ulColor 
= wxColourToRGB(rCol
); 
1165     ::WinSetPresParam( GetHWND() 
1171 } // end of wxListCtrl::SetBackgroundColour 
1173 // Gets information about this column 
1174 bool wxListCtrl::GetColumn ( int nCol
, wxListItem
& rItem 
) const 
1176     PFIELDINFO pFieldInfo 
= FindOS2ListFieldByColNum ( GetHWND(), nCol 
); 
1180     rItem
.SetWidth(pFieldInfo
->cxWidth
); 
1181     if ((rItem
.GetMask() & wxLIST_MASK_TEXT
) && 
1182         (pFieldInfo
->flData 
& CFA_STRING
) && 
1183         (pFieldInfo
->pUserData 
!= NULL
)) 
1185         rItem
.SetText((char*)pFieldInfo
->pUserData
); 
1187     if (rItem
.GetMask() & wxLIST_MASK_FORMAT 
) 
1189         if (pFieldInfo
->flData 
& CFA_LEFT
) 
1190             rItem
.m_format 
= wxLIST_FORMAT_LEFT
; 
1191         else if (pFieldInfo
->flData 
& CFA_RIGHT
) 
1192             rItem
.m_format 
= wxLIST_FORMAT_RIGHT
; 
1193         else if (pFieldInfo
->flData 
& CFA_CENTER
) 
1194             rItem
.m_format 
= wxLIST_FORMAT_CENTRE
; 
1197 } // end of wxListCtrl::GetColumn 
1199 // Sets information about this column 
1200 bool wxListCtrl::SetColumn ( int nCol
, wxListItem
& rItem 
) 
1202     PFIELDINFO pFieldInfo 
= FindOS2ListFieldByColNum( GetHWND(), nCol 
); 
1203     ConvertToOS2ListCol( nCol
, rItem
, pFieldInfo 
); 
1205     // Since we changed the field pointed to, we invalidate to see the result 
1207     ::WinSendMsg(GetHWND(), CM_INVALIDATEDETAILFIELDINFO
, NULL
, NULL
); 
1209 } // end of wxListCtrl::SetColumn 
1211 // Gets the column width 
1212 int wxListCtrl::GetColumnWidth ( int nCol 
) const 
1214     PFIELDINFO pFieldInfo 
= FindOS2ListFieldByColNum ( GetHWND(), nCol 
); 
1218     return((int)pFieldInfo
->cxWidth
); 
1219 } // end of wxListCtrl::GetColumnWidth 
1221 // Sets the column width 
1222 bool wxListCtrl::SetColumnWidth ( int nCol
, int nWidth 
) 
1225     int nWidth2 
= nWidth
; 
1227     if (GetWindowStyleFlag() & wxLC_LIST
) 
1230     PFIELDINFO pFieldInfo 
= FindOS2ListFieldByColNum( GetHWND(), nCol 
); 
1231     pFieldInfo
->cxWidth 
= nWidth
; 
1232     ::WinSendMsg(GetHWND(), CM_INVALIDATEDETAILFIELDINFO
, NULL
, NULL
); 
1234 } // end of wxListCtrl::SetColumnWidth 
1236 // Gets the number of items that can fit vertically in the 
1237 // visible area of the list control (list or report view) 
1238 // or the total number of items in the list control (icon 
1239 // or small icon view) 
1240 int wxListCtrl::GetCountPerPage () const 
1242     QUERYRECORDRECT                 vQueryRect
; 
1248     if (!::WinSendMsg( GetHWND() 
1251                       ,(MPARAM
)(USHORT
)sizeof(CNRINFO
) 
1254     memset(&vQueryRect
, '\0', sizeof(QUERYRECORDRECT
)); 
1255     vQueryRect
.cb 
= sizeof(QUERYRECORDRECT
); 
1256     if (vCnrInfo
.flWindowAttr 
& CV_ICON
) 
1257         vQueryRect
.fsExtent 
= CMA_ICON 
| CMA_TEXT
; 
1258     else if (vCnrInfo
.flWindowAttr 
& CV_NAME
) 
1259         vQueryRect
.fsExtent 
= CMA_ICON 
| CMA_TEXT
; 
1260     else if (vCnrInfo
.flWindowAttr 
& CV_TEXT
) 
1261         vQueryRect
.fsExtent 
= CMA_TEXT
; 
1262     else if (vCnrInfo
.flWindowAttr 
& CV_DETAIL
) 
1263         vQueryRect
.fsExtent 
= CMA_TEXT
; 
1264     if (!::WinSendMsg( GetHWND() 
1266                       ,MPFROMP(&vRectRecord
) 
1267                       ,MPFROMP(&vQueryRect
) 
1270     if (!::WinSendMsg( GetHWND() 
1271                       ,CM_QUERYVIEWPORTRECT
 
1272                       ,MPFROMP(&vRectControl
) 
1273                       ,MPFROM2SHORT(CMA_WINDOW
, (USHORT
)FALSE
) 
1276     nCount 
= (int)((int)((vRectControl
.xRight 
- vRectControl
.xLeft
) / (vRectRecord
.xRight 
- vRectRecord
.xLeft
)) * 
1277                    (int)((vRectControl
.yTop 
- vRectControl
.yBottom
) / (vRectRecord
.yTop 
- vRectRecord
.yBottom
)) 
1279     if (nCount 
> (int)vCnrInfo
.cFields
) 
1280         nCount 
= (int)vCnrInfo
.cFields
; 
1282 } // end of wxListCtrl::GetCountPerPage 
1284 // Gets the edit control for editing labels. 
1285 wxTextCtrl
* wxListCtrl::GetEditControl() const 
1290 // Gets information about the item 
1291 bool wxListCtrl::GetItem ( wxListItem
& rInfo 
) const 
1293     PMYRECORD pRecord 
= FindOS2ListRecordByID( GetHWND(), rInfo
.GetId() ); 
1296     // Give NULL as hwnd as we already have everything we need 
1298     ConvertFromOS2ListItem( NULL
, rInfo
, pRecord 
); 
1300 } // end of wxListCtrl::GetItem 
1302 // Sets information about the item 
1303 bool wxListCtrl::SetItem ( wxListItem
& rInfo 
) 
1305     PFIELDINFO pFieldInfo 
= FindOS2ListFieldByColNum ( GetHWND(), rInfo
.GetColumn() ); 
1306     PMYRECORD pRecord 
= FindOS2ListRecordByID( GetHWND(), rInfo
.GetId() ); 
1308     ConvertToOS2ListItem( this 
1315     // Check if setting attributes or lParam 
1317     if (rInfo
.HasAttributes() || (rInfo
.GetMask()  & wxLIST_MASK_DATA
)) 
1320         // Get internal item data 
1321         // perhaps a cache here ? 
1323         CListItemInternalData
*      pData 
= GetInternalData( this 
1332             m_bAnyInternalData    
= true; 
1333             pData                 
= new CListItemInternalData(); 
1334             pRecord
->m_ulUserData 
= (unsigned long)pData
; 
1340         if (rInfo
.GetMask()  & wxLIST_MASK_DATA
) 
1341             pData
->m_lParam 
= (WXLPARAM
)rInfo
.GetData(); 
1344         if (rInfo
.HasAttributes()) 
1347                 *pData
->m_pAttr 
= *rInfo
.GetAttributes(); 
1349                 pData
->m_pAttr 
= new wxListItemAttr(*rInfo
.GetAttributes()); 
1351         pData
->m_pMyRecord 
= pRecord
;  // they point to each other 
1355     // We need to update the item immediately to show the new image 
1357     bool bUpdateNow 
= (rInfo
.GetMask() & wxLIST_MASK_IMAGE
) != 0; 
1360     // Check whether it has any custom attributes 
1362     if (rInfo
.HasAttributes()) 
1364         m_bHasAnyAttr 
= true; 
1367         // If the colour has changed, we must redraw the item 
1371     if (::WinIsWindowVisible(GetHWND())) 
1373         ::WinSendMsg( GetHWND() 
1374                      ,CM_INVALIDATERECORD
 
1376                      ,MPFROM2SHORT(1, CMA_ERASE 
| CMA_REPOSITION 
| CMA_TEXTCHANGED
) 
1378         RefreshItem(pRecord
->m_ulItemId
); 
1380     ::WinSendMsg( GetHWND() 
1381                  ,CM_INVALIDATEDETAILFIELDINFO
 
1386 } // end of wxListCtrl::SetItem 
1388 long wxListCtrl::SetItem ( 
1391 , const wxString
&                   rsLabel
 
1397     vInfo
.m_text   
= rsLabel
; 
1398     vInfo
.m_mask   
= wxLIST_MASK_TEXT
; 
1399     vInfo
.m_itemId 
= lIndex
; 
1403         vInfo
.m_image 
= nImageId
; 
1404         vInfo
.m_mask 
|= wxLIST_MASK_IMAGE
; 
1406     return SetItem(vInfo
); 
1407 } // end of wxListCtrl::SetItem 
1409 // Gets the item state 
1410 int wxListCtrl::GetItemState ( 
1417     vInfo
.m_mask      
= wxLIST_MASK_STATE
; 
1418     vInfo
.m_stateMask 
= lStateMask
; 
1419     vInfo
.m_itemId    
= lItem
; 
1421     if (!GetItem(vInfo
)) 
1423     return vInfo
.m_state
; 
1424 } // end of wxListCtrl::GetItemState 
1426 // Sets the item state 
1427 bool wxListCtrl::SetItemState ( long lItem
, long lState
, long lStateMask 
) 
1429     PMYRECORD pRecord 
= FindOS2ListRecordByID( GetHWND(), lItem 
); 
1432     // Don't use SetItem() here as it doesn't work with the virtual list 
1435     ConvertToOS2Flags( lState
, pRecord 
); 
1438     // for the virtual list controls we need to refresh the previously focused 
1439     // item manually when changing focus without changing selection 
1440     // programmatically because otherwise it keeps its focus rectangle until 
1441     // next repaint (yet another comctl32 bug) 
1446         (lStateMask 
& wxLIST_STATE_FOCUSED
) && 
1447          (lState 
& wxLIST_STATE_FOCUSED
) ) 
1449         lFocusOld 
= GetNextItem( -1 
1451                                 ,wxLIST_STATE_FOCUSED
 
1458     ::WinSendMsg( GetHWND() 
1459                  ,CM_INVALIDATERECORD
 
1461                  ,MPFROM2SHORT(1, CMA_ERASE 
| CMA_REPOSITION 
| CMA_TEXTCHANGED
) 
1464     if (lFocusOld 
!= -1) 
1467         // No need to refresh the item if it was previously selected, it would 
1468         // only result in annoying flicker 
1470         if (!(GetItemState( lFocusOld
 
1471                            ,wxLIST_STATE_SELECTED
 
1472                           ) & wxLIST_STATE_SELECTED
)) 
1474             RefreshItem(lFocusOld
); 
1478 } // end of wxListCtrl::SetItemState 
1480 // Sets the item image 
1481 bool wxListCtrl::SetItemImage ( 
1484 , int                               WXUNUSED(nSelImage
)) 
1486     return SetItemColumnInfo(lItem
, 0, nImage
); 
1487 } // end of wxListCtrl::SetItemImage 
1489 // Sets the item image 
1490 bool wxListCtrl::SetItemColumnImage ( 
1497     vInfo
.m_mask   
= wxLIST_MASK_IMAGE
; 
1498     vInfo
.m_image  
= nImage
; 
1499     vInfo
.m_itemId 
= lItem
; 
1500     vInfo
.m_col    
= lColumn
; 
1501     return SetItem(vInfo
); 
1502 } // end of wxListCtrl::SetItemColumnImage 
1504 // Gets the item text 
1505 wxString 
wxListCtrl::GetItemText ( 
1511     vInfo
.m_mask   
= wxLIST_MASK_TEXT
; 
1512     vInfo
.m_itemId 
= lItem
; 
1514     if (!GetItem(vInfo
)) 
1515         return wxEmptyString
; 
1516     return vInfo
.m_text
; 
1517 } // end of wxListCtrl::GetItemText 
1519 // Sets the item text 
1520 void wxListCtrl::SetItemText ( 
1522 , const wxString
&                   rsStr
 
1527     vInfo
.m_mask   
= wxLIST_MASK_TEXT
; 
1528     vInfo
.m_itemId 
= lItem
; 
1529     vInfo
.m_text   
= rsStr
; 
1531 } // end of wxListCtrl::SetItemText 
1533 // Gets the item data 
1534 long wxListCtrl::GetItemData ( 
1540     vInfo
.m_mask   
= wxLIST_MASK_DATA
; 
1541     vInfo
.m_itemId 
= lItem
; 
1542     if (!GetItem(vInfo
)) 
1544     return vInfo
.m_data
; 
1545 } // end of wxListCtrl::GetItemData 
1547 // Sets the item data 
1548 bool wxListCtrl::SetItemData ( 
1555     vInfo
.m_mask   
= wxLIST_MASK_DATA
; 
1556     vInfo
.m_itemId 
= lItem
; 
1557     vInfo
.m_data   
= lData
; 
1558     return SetItem(vInfo
); 
1559 } // end of wxListCtrl::SetItemData 
1561 // Gets the item rectangle 
1562 bool wxListCtrl::GetItemRect ( long lItem
, 
1567     PMYRECORD pRecord 
= FindOS2ListRecordByID( GetHWND(), lItem 
); 
1568     QUERYRECORDRECT vQueryRect
; 
1574     vQueryRect
.cb                
= sizeof(QUERYRECORDRECT
); 
1575     vQueryRect
.pRecord           
= &pRecord
->m_vRecord
; 
1576     vQueryRect
.fRightSplitWindow 
= TRUE
; 
1577     vQueryRect
.fsExtent          
= CMA_ICON 
| CMA_TEXT
; 
1578     ::WinSendMsg( GetHWND() 
1581                  ,MPFROMP(&vQueryRect
) 
1584     // remember OS/2 is backwards 
1586     GetClientSize( NULL
, &nHeight 
); 
1587     rRect
.x      
= vRect
.xLeft
; 
1588     rRect
.y      
= nHeight 
- vRect
.yTop
; 
1589     rRect
.width  
= vRect
.xRight
; 
1590     rRect
.height 
= nHeight 
- vRect
.yBottom
; 
1593 } // end of wxListCtrl::GetItemRect 
1595 // Gets the item position 
1596 bool wxListCtrl::GetItemPosition ( long lItem
, wxPoint
& rPos 
) const 
1599     PMYRECORD pRecord 
= FindOS2ListRecordByID( GetHWND() , lItem 
); 
1600     QUERYRECORDRECT vQueryRect
; 
1606     vQueryRect
.cb                
= sizeof(QUERYRECORDRECT
); 
1607     vQueryRect
.pRecord           
= &pRecord
->m_vRecord
; 
1608     vQueryRect
.fRightSplitWindow 
= TRUE
; 
1609     vQueryRect
.fsExtent          
= CMA_ICON 
| CMA_TEXT
; 
1610     ::WinSendMsg( GetHWND() 
1613                  ,MPFROMP(&vQueryRect
) 
1616     // remember OS/2 is backwards 
1618     GetClientSize( NULL
, &nHeight 
); 
1619     rPos
.x   
= vRect
.xLeft
; 
1620     rPos
.y   
= nHeight 
- vRect
.yTop
; 
1623 } // end of wxListCtrl::GetItemPosition 
1625 // Sets the item position. 
1626 bool wxListCtrl::SetItemPosition ( long lItem
, const wxPoint
& rPos 
) 
1629     // Items cannot be positioned in X/Y coord in OS/2 
1632 } // end of wxListCtrl::SetItemPosition 
1634 // Gets the number of items in the list control 
1635 int wxListCtrl::GetItemCount () const 
1639     if (!::WinSendMsg( GetHWND() 
1642                       ,(MPARAM
)(USHORT
)sizeof(CNRINFO
) 
1645     return vCnrInfo
.cRecords
; 
1646 } // end of wxListCtrl::GetItemCount 
1648 // Retrieves the spacing between icons in pixels. 
1649 // If bIsSmall is true, gets the spacing for the small icon 
1650 // view, otherwise the large icon view. 
1651 int wxListCtrl::GetItemSpacing ( bool bIsSmall 
) const 
1655     if (!::WinSendMsg( GetHWND() 
1658                       ,(MPARAM
)(USHORT
)sizeof(CNRINFO
) 
1661     return vCnrInfo
.cyLineSpacing
; 
1662 } // end of wxListCtrl::GetItemSpacing 
1664 void wxListCtrl::SetItemTextColour ( 
1666 , const wxColour
&                   rCol
 
1671     vInfo
.m_itemId 
= lItem
; 
1672     vInfo
.SetTextColour(rCol
); 
1674 } // end of wxListCtrl::SetItemTextColour 
1676 wxColour 
wxListCtrl::GetItemTextColour ( 
1682     vInfo
.m_itemId 
= lItem
; 
1684     return vInfo
.GetTextColour(); 
1685 } // end of wxListCtrl::GetItemTextColour 
1687 void wxListCtrl::SetItemBackgroundColour ( 
1689 , const wxColour
&                   rCol
 
1694     vInfo
.m_itemId 
= lItem
; 
1695     vInfo
.SetBackgroundColour(rCol
); 
1697 } // end of wxListCtrl::SetItemBackgroundColour 
1699 wxColour 
wxListCtrl::GetItemBackgroundColour ( 
1705     vInfo
.m_itemId 
= lItem
; 
1707     return vInfo
.GetBackgroundColour(); 
1708 } // end of wxListCtrl::GetItemBackgroundColour 
1710 // Gets the number of selected items in the list control 
1711 int wxListCtrl::GetSelectedItemCount () const 
1713     PMYRECORD                       pRecord 
= NULL
; 
1715     pRecord 
= (PMYRECORD
)PVOIDFROMMR(::WinSendMsg( GetHWND() 
1716                                                   ,CM_QUERYRECORDEMPHASIS
 
1718                                                   ,(MPARAM
)CRA_SELECTED
 
1726         pRecord 
= (PMYRECORD
)PVOIDFROMMR(::WinSendMsg( GetHWND() 
1727                                                       ,CM_QUERYRECORDEMPHASIS
 
1729                                                       ,(MPARAM
)CRA_SELECTED
 
1735 } // end of wxListCtrl::GetSelectedItemCount 
1737 // Gets the text colour of the listview 
1738 wxColour 
wxListCtrl::GetTextColour () const 
1743     ::WinQueryPresParam( GetHWND() 
1753 } // end of wxListCtrl::GetTextColour 
1755 // Sets the text colour of the listview 
1756 void wxListCtrl::SetTextColour ( 
1757   const wxColour
&                   rCol
 
1760     ULONG                           ulColor 
= wxColourToRGB(rCol
); 
1762     ::WinSetPresParam( GetHWND() 
1767 } // end of wxListCtrl::SetTextColour 
1769 // Gets the index of the topmost visible item when in 
1770 // list or report view 
1771 long wxListCtrl::GetTopItem () const 
1773     PMYRECORD                       pRecord 
= NULL
; 
1774     QUERYRECFROMRECT                vQueryRect
; 
1777     ::WinSendMsg( GetHWND() 
1778                  ,CM_QUERYVIEWPORTRECT
 
1780                  ,MPFROM2SHORT(CMA_WINDOW
, TRUE
) 
1782     vQueryRect
.cb        
= sizeof(QUERYRECFROMRECT
); 
1783     vQueryRect
.rect      
= vRect
; 
1784     vQueryRect
.fsSearch 
= CMA_PARTIAL
; 
1786     pRecord 
= (PMYRECORD
)::WinSendMsg( GetHWND() 
1787                                       ,CM_QUERYRECORDFROMRECT
 
1789                                       ,MPFROMP(&vQueryRect
) 
1794     return (long)pRecord
->m_ulItemId
; 
1795 } // end of wxListCtrl::GetTopItem 
1797 // Searches for an item, starting from 'item'. 
1798 // 'geometry' is one of 
1799 // wxLIST_NEXT_ABOVE/ALL/BELOW/LEFT/RIGHT. 
1800 // 'state' is a state bit flag, one or more of 
1801 // wxLIST_STATE_DROPHILITED/FOCUSED/SELECTED/CUT. 
1802 // item can be -1 to find the first item that matches the 
1804 // Returns the item or -1 if unsuccessful. 
1805 long wxListCtrl::GetNextItem ( 
1807 , int                               WXUNUSED(nGeom
) 
1808 , int                               WXUNUSED(nState
) 
1811     PMYRECORD                       pRecord 
= FindOS2ListRecordByID( GetHWND() 
1815     pRecord 
= (PMYRECORD
)pRecord
->m_vRecord
.preccNextRecord
; 
1817         return((long)pRecord
->m_ulItemId
); 
1819 } // end of wxListCtrl::GetNextItem 
1821 wxImageList
* wxListCtrl::GetImageList ( 
1825     if (nWhich 
== wxIMAGE_LIST_NORMAL 
) 
1827         return m_pImageListNormal
; 
1829     else if (nWhich 
== wxIMAGE_LIST_SMALL 
) 
1831         return m_pImageListSmall
; 
1833     else if (nWhich 
== wxIMAGE_LIST_STATE 
) 
1835         return m_pImageListState
; 
1838 } // end of wxListCtrl::GetImageList 
1840 void wxListCtrl::SetImageList ( wxImageList
* pImageList
, 
1843     if (nWhich 
== wxIMAGE_LIST_NORMAL
) 
1845         if (m_bOwnsImageListNormal
) 
1846             delete m_pImageListNormal
; 
1847         m_pImageListNormal     
= pImageList
; 
1848         m_bOwnsImageListNormal 
= false; 
1850     else if (nWhich 
== wxIMAGE_LIST_SMALL
) 
1852         if (m_bOwnsImageListSmall
) 
1853             delete m_pImageListSmall
; 
1854         m_pImageListSmall    
= pImageList
; 
1855         m_bOwnsImageListSmall 
= false; 
1857     else if (nWhich 
== wxIMAGE_LIST_STATE
) 
1859         if (m_bOwnsImageListState
) 
1860             delete m_pImageListState
; 
1861         m_pImageListState     
= pImageList
; 
1862         m_bOwnsImageListState 
= false; 
1864 } // end of wxListCtrl::SetImageList 
1866 void wxListCtrl::AssignImageList ( wxImageList
* pImageList
, int nWhich 
) 
1868     SetImageList( pImageList
, nWhich 
); 
1870     if (nWhich 
== wxIMAGE_LIST_NORMAL 
) 
1871         m_bOwnsImageListNormal 
= true; 
1872     else if (nWhich 
== wxIMAGE_LIST_SMALL 
) 
1873         m_bOwnsImageListSmall 
= true; 
1874     else if (nWhich 
== wxIMAGE_LIST_STATE 
) 
1875         m_bOwnsImageListState 
= true; 
1876 } // end of wxListCtrl::AssignImageList 
1878 // ---------------------------------------------------------------------------- 
1880 // ---------------------------------------------------------------------------- 
1882 // Arranges the items 
1883 bool wxListCtrl::Arrange ( int nFlag 
) 
1888     if (nFlag 
== wxLIST_ALIGN_SNAP_TO_GRID
) 
1890         ulType 
= CMA_ARRANGEGRID
; 
1891         if (nFlag 
== wxLIST_ALIGN_LEFT
) 
1892             ulFlags 
|= CMA_LEFT
; 
1893         else if (nFlag 
== wxLIST_ALIGN_TOP
) 
1895         else if (nFlag 
== wxLIST_ALIGN_DEFAULT
) 
1896             ulFlags 
|= CMA_LEFT
; 
1899         ulType 
= CMA_ARRANGESTANDARD
; 
1900     ::WinSendMsg( GetHWND() 
1906     // We do not support CMA_ARRANGESELECTED 
1909 } // end of wxListCtrl::Arrange 
1912 bool wxListCtrl::DeleteItem ( long lItem 
) 
1914     PMYRECORD pRecord 
= FindOS2ListRecordByID( GetHWND(), lItem 
); 
1915     if (LONGFROMMR(::WinSendMsg( GetHWND() 
1918                                 ,MPFROM2SHORT(1, CMA_FREE
) 
1925     // The virtual list control doesn't refresh itself correctly, help it 
1930         // We need to refresh all the lines below the one which was deleted 
1934         if (lItem 
> 0 && GetItemCount()) 
1936             GetItemRect( lItem 
- 1 
1942             vRectItem
.y 
= vRectItem
.height 
= 0; 
1944         wxRect                      vRectWin 
= GetRect(); 
1946         vRectWin
.height 
= vRectWin
.GetBottom() - vRectItem
.GetBottom(); 
1947         vRectWin
.y      
= vRectItem
.GetBottom(); 
1948         RefreshRect(vRectWin
); 
1951 } // end of wxListCtrl::DeleteItem 
1953 // Deletes all items 
1954 bool wxListCtrl::DeleteAllItems () 
1956     return((LONG
)::WinSendMsg( GetHWND() 
1959                               ,MPFROM2SHORT(0, CMA_FREE
) 
1961 } // end of wxListCtrl::DeleteAllItems 
1963 // Deletes all items 
1964 bool wxListCtrl::DeleteAllColumns () 
1966     while (m_nColCount 
> 0) 
1968         DeleteColumn(m_nColCount 
- 1); 
1972     wxASSERT_MSG(m_nColCount 
== 0, wxT("no columns should be left")); 
1974 } // end of wxListCtrl::DeleteAllColumns 
1977 bool wxListCtrl::DeleteColumn ( int nCol 
) 
1979     bool bSuccess 
= false; 
1980     PFIELDINFO pField 
= FindOS2ListFieldByColNum( GetHWND(), nCol 
); 
1981     bSuccess 
= ((LONG
)::WinSendMsg( GetHWND() 
1982                                    ,CM_REMOVEDETAILFIELDINFO
 
1984                                    ,MPFROM2SHORT((SHORT
)1, CMA_FREE
) 
1986     if (bSuccess 
&& (m_nColCount 
> 0)) 
1989 } // end of wxListCtrl::DeleteColumn 
1991 // Clears items, and columns if there are any. 
1992 void wxListCtrl::ClearAll () 
1995     if (m_nColCount 
> 0) 
1997 } // end of wxListCtrl::ClearAll 
2000 // OS/2 does not use a text control for its container labels.  You merely 
2001 // "open" a record for editting. 
2003 wxTextCtrl
* wxListCtrl::EditLabel ( 
2005 , wxClassInfo
*                      WXUNUSED(pTextControlClass
) 
2009     PMYRECORD                       pRecord 
= FindOS2ListRecordByID( GetHWND() 
2013     vEdit
.cb         
= sizeof(CNREDITDATA
); 
2014     vEdit
.hwndCnr    
= GetHWND(); 
2015     vEdit
.pRecord    
= &pRecord
->m_vRecord
; 
2016     vEdit
.pFieldInfo 
= NULL
; 
2017     vEdit
.ppszText   
= NULL
; 
2021     ::WinSendMsg( GetHWND() 
2027 } // end of wxListCtrl::EditLabel 
2029 // End label editing, optionally cancelling the edit.  Under OS/2 you close 
2030 // the record for editting 
2031 bool wxListCtrl::EndEditLabel ( bool WXUNUSED(bCancel
) ) 
2033     ::WinSendMsg( GetHWND() 
2039 } // end of wxListCtrl::EndEditLabel 
2041 // Ensures this item is visible 
2042 bool wxListCtrl::EnsureVisible ( long lItem 
) 
2044     PMYRECORD pRecord 
= FindOS2ListRecordByID( GetHWND(), lItem 
); 
2045     ::WinSendMsg( GetHWND() 
2046                  ,CM_INVALIDATERECORD
 
2048                  ,MPFROM2SHORT((SHORT
)1, CMA_NOREPOSITION
) 
2051 } // end of wxListCtrl::EnsureVisible 
2053 // Find an item whose label matches this string, starting from the item after 'start' 
2054 // or the beginning if 'start' is -1. 
2055 long wxListCtrl::FindItem ( 
2057 , const wxString
&                   rsStr
 
2062     SEARCHSTRING                    vSearch
; 
2063     PMYRECORD                       pRecord 
= FindOS2ListRecordByID( GetHWND() 
2069     if (!::WinSendMsg( GetHWND() 
2072                       ,(MPARAM
)(USHORT
)sizeof(CNRINFO
) 
2076     if (vCnrInfo
.flWindowAttr 
& CV_ICON
) 
2078     if (vCnrInfo
.flWindowAttr 
& CV_NAME
) 
2080     if (vCnrInfo
.flWindowAttr 
& CV_TEXT
) 
2082     if (vCnrInfo
.flWindowAttr 
& CV_DETAIL
) 
2085         ulFlag 
|= CV_EXACTLENGTH
; 
2087     vSearch
.cb              
= sizeof(SEARCHSTRING
); 
2088     vSearch
.pszSearch       
= (char*)rsStr
.c_str(); 
2089     vSearch
.fsPrefix        
= TRUE
; 
2090     vSearch
.fsCaseSensitive 
= TRUE
; 
2091     vSearch
.usView          
= ulFlag
; 
2095         pRecord 
= (PMYRECORD
)::WinSendMsg( GetHWND() 
2103         pRecord 
= (PMYRECORD
)::WinSendMsg( GetHWND() 
2111     return pRecord
->m_ulItemId
; 
2112 } // end of wxListCtrl::FindItem 
2114 // Find an item whose data matches this data, starting from the item after 'start' 
2115 // or the beginning if 'start' is -1. 
2116 long wxListCtrl::FindItem ( 
2121     long                            lIdx 
= lStart 
+ 1; 
2122     long                            lCount 
= GetItemCount(); 
2124     while (lIdx 
< lCount
) 
2126         if (GetItemData(lIdx
) == lData
) 
2131 } // end of wxListCtrl::FindItem 
2133 // Find an item nearest this position in the specified direction, starting from 
2134 // the item after 'start' or the beginning if 'start' is -1. 
2135 long wxListCtrl::FindItem ( 
2137 , const wxPoint
&                    rPoint
 
2142     QUERYRECORDRECT                 vQueryRect
; 
2143     PMYRECORD                       pRecord 
= FindOS2ListRecordByID( GetHWND() 
2150     if (!::WinSendMsg( GetHWND() 
2153                       ,(MPARAM
)(USHORT
)sizeof(CNRINFO
) 
2157     vQueryRect
.cb                
= sizeof(QUERYRECORDRECT
); 
2158     vQueryRect
.pRecord           
= &pRecord
->m_vRecord
; 
2159     vQueryRect
.fRightSplitWindow 
= TRUE
; 
2160     vQueryRect
.fsExtent          
= CMA_ICON 
| CMA_TEXT
; 
2162     ::WinSendMsg( GetHWND() 
2165                  ,MPFROMP(&vQueryRect
) 
2167     vLibRect
.SetLeft(vRect
.xLeft
); 
2168     vLibRect
.SetTop(vRect
.yTop
); 
2169     vLibRect
.SetRight(vRect
.xRight
); 
2170     vLibRect
.SetBottom(vRect
.yBottom
); 
2171     if (vLibRect
.Inside(rPoint
)) 
2172         return pRecord
->m_ulItemId
; 
2174     for (i 
= lStart 
+ 1; i 
< vCnrInfo
.cRecords
; i
++) 
2176         pRecord 
= (PMYRECORD
)PVOIDFROMMR(::WinSendMsg( GetHWND() 
2179                                                       ,MPFROM2SHORT(CMA_NEXT
, CMA_ITEMORDER
) 
2181         vQueryRect
.pRecord 
= (PRECORDCORE
)pRecord
; 
2182         ::WinSendMsg( GetHWND() 
2185                      ,MPFROMP(&vQueryRect
) 
2187         vLibRect
.SetLeft(vRect
.xLeft
); 
2188         vLibRect
.SetTop(vRect
.yTop
); 
2189         vLibRect
.SetRight(vRect
.xRight
); 
2190         vLibRect
.SetBottom(vRect
.yBottom
); 
2191         if (vLibRect
.Inside(rPoint
)) 
2192             return pRecord
->m_ulItemId
; 
2195 } // end of wxListCtrl::FindItem 
2197 // Determines which item (if any) is at the specified point, 
2198 // giving details in 'flags' (see wxLIST_HITTEST_... flags above) 
2199 long wxListCtrl::HitTest ( 
2200   const wxPoint
&                    rPoint
 
2201 , int&                              WXUNUSED(rFlags
) 
2204     PMYRECORD                       pRecord 
= NULL
; 
2205     QUERYRECFROMRECT                vQueryRect
; 
2210     // Get height for OS/2 point conversion 
2212     ::WinSendMsg( GetHWND() 
2213                  ,CM_QUERYVIEWPORTRECT
 
2215                  ,MPFROM2SHORT(CMA_WINDOW
, TRUE
) 
2217     lHeight 
= vRect
.yTop 
- vRect
.yBottom
; 
2220     // For now just try and get a record in the general vicinity and forget 
2223     vRect
.xLeft   
= rPoint
.x 
- 2; 
2224     vRect
.xRight  
= rPoint
.x 
+ 2; 
2225     vRect
.yTop    
= (lHeight 
- rPoint
.y
) + 2; 
2226     vRect
.yBottom 
= (lHeight 
- rPoint
.y
) - 2; 
2228     vQueryRect
.cb 
= sizeof(QUERYRECFROMRECT
); 
2229     vQueryRect
.rect 
= vRect
; 
2230     vQueryRect
.fsSearch 
= CMA_PARTIAL
; 
2232     pRecord 
= (PMYRECORD
)::WinSendMsg( GetHWND() 
2233                                       ,CM_QUERYRECORDFROMRECT
 
2235                                       ,MPFROMP(&vQueryRect
) 
2240     return pRecord
->m_ulItemId
; 
2241 } // end of wxListCtrl::HitTest 
2243 // Inserts an item, returning the index of the new item if successful, 
2245 long wxListCtrl::InsertItem ( 
2249     wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual controls") ); 
2251     PFIELDINFO                      pFieldInfo 
= FindOS2ListFieldByColNum ( GetHWND() 
2254     PMYRECORD                       pRecordAfter 
= NULL
; 
2255     PMYRECORD                       pRecord 
= (PMYRECORD
)::WinSendMsg( GetHWND() 
2257                                                                       ,MPFROMLONG(sizeof(MYRECORD
) - sizeof(RECORDCORE
)) 
2261     ConvertToOS2ListItem( this 
2267     if (rInfo
.GetId() > 0) 
2268         pRecordAfter 
= FindOS2ListRecordByID( GetHWND() 
2272     RECORDINSERT                    vInsert
; 
2274     vInsert
.cb                
= sizeof(RECORDINSERT
); 
2275     vInsert
.pRecordParent     
= NULL
; 
2277         vInsert
.pRecordOrder  
= (PRECORDCORE
)CMA_FIRST
; 
2279         vInsert
.pRecordOrder  
= (PRECORDCORE
)pRecordAfter
; 
2280     vInsert
.zOrder            
= CMA_TOP
; 
2281     vInsert
.cRecordsInsert    
= 1; 
2282     vInsert
.fInvalidateRecord 
= TRUE
; 
2285     // Check wether we need to allocate our internal data 
2287     bool                            bNeedInternalData 
= ((rInfo
.GetMask() & wxLIST_MASK_DATA
) || 
2288                                                           rInfo
.HasAttributes() 
2290     if (bNeedInternalData
) 
2292         m_bAnyInternalData 
= true; 
2295         // Internal stucture that manages data 
2297         CListItemInternalData
*      pData 
= new CListItemInternalData(); 
2299         pRecord
->m_ulUserData 
= (unsigned long)pData
; 
2300         if (rInfo
.GetMask() & wxLIST_MASK_DATA
) 
2301             pData
->m_lParam 
= (WXLPARAM
)rInfo
.GetData(); 
2304         // Check whether it has any custom attributes 
2306         if (rInfo
.HasAttributes()) 
2309             // Take copy of attributes 
2311             pData
->m_pAttr 
= new wxListItemAttr(*rInfo
.GetAttributes()); 
2314     if (!::WinSendMsg( GetHWND() 
2321     // OS/2 must mannually bump the index's of following records 
2323     BumpRecordIds( GetHWND() 
2326     ::WinSendMsg( GetHWND() 
2327                  ,CM_INVALIDATEDETAILFIELDINFO
 
2331     return pRecord
->m_ulItemId
; 
2332 } // end of wxListCtrl::InsertItem 
2334 long wxListCtrl::InsertItem ( 
2336 , const wxString
&                   rsLabel
 
2341     memset(&vInfo
, '\0', sizeof(wxListItem
)); 
2342     vInfo
.m_text   
= rsLabel
; 
2343     vInfo
.m_mask   
= wxLIST_MASK_TEXT
; 
2344     vInfo
.m_itemId 
= lIndex
; 
2345     return InsertItem(vInfo
); 
2346 } // end of wxListCtrl::InsertItem 
2348 // Inserts an image item 
2349 long wxListCtrl::InsertItem ( 
2356     vInfo
.m_image  
= nImageIndex
; 
2357     vInfo
.m_mask   
= wxLIST_MASK_IMAGE
; 
2358     vInfo
.m_itemId 
= lIndex
; 
2359     return InsertItem(vInfo
); 
2360 } // end of wxListCtrl::InsertItem 
2362 // Inserts an image/string item 
2363 long wxListCtrl::InsertItem ( 
2365 , const wxString
&                   rsLabel
 
2371     vInfo
.m_image  
= nImageIndex
; 
2372     vInfo
.m_text   
= rsLabel
; 
2373     vInfo
.m_mask   
= wxLIST_MASK_IMAGE 
| wxLIST_MASK_TEXT
; 
2374     vInfo
.m_itemId 
= lIndex
; 
2375     return InsertItem(vInfo
); 
2376 } // end of wxListCtrl::InsertItem 
2378 // For details view mode (only), inserts a column. 
2379 long wxListCtrl::InsertColumn ( 
2385     PFIELDINFO                      pField 
= (PFIELDINFO
)::WinSendMsg( GetHWND() 
2386                                                                       ,CM_ALLOCDETAILFIELDINFO
 
2390     PFIELDINFO                      pFieldAfter 
= FindOS2ListFieldByColNum ( GetHWND() 
2393     FIELDINFOINSERT                 vInsert
; 
2395     ConvertToOS2ListCol ( lCol
 
2400     vInsert
.cb                   
= sizeof(FIELDINFOINSERT
); 
2401     vInsert
.pFieldInfoOrder      
= pFieldAfter
; 
2402     vInsert
.fInvalidateFieldInfo 
= TRUE
; 
2403     vInsert
.cFieldInfoInsert     
= 1; 
2405     bSuccess 
= ::WinSendMsg( GetHWND() 
2406                             ,CM_INSERTDETAILFIELDINFO
 
2411 } // end of wxListCtrl::InsertColumn 
2413 long wxListCtrl::InsertColumn ( 
2415 , const wxString
&                   rsHeading
 
2422     vItem
.m_mask 
= wxLIST_MASK_TEXT 
| wxLIST_MASK_FORMAT
; 
2423     vItem
.m_text 
= rsHeading
; 
2426         vItem
.m_mask 
|= wxLIST_MASK_WIDTH
; 
2427         vItem
.m_width 
= nWidth
; 
2429     vItem
.m_format 
= nFormat
; 
2431     return InsertColumn( lCol
 
2434 } // end of wxListCtrl::InsertColumn 
2436 // scroll the control by the given number of pixels (exception: in list view, 
2437 // dx is interpreted as number of columns) 
2438 bool wxListCtrl::ScrollList ( int nDx
, int nDy 
) 
2441         ::WinSendMsg( GetHWND() 
2443                      ,(MPARAM
)CMA_HORIZONTAL
 
2447         ::WinSendMsg( GetHWND() 
2449                      ,(MPARAM
)CMA_VERTICAL
 
2453 } // end of wxListCtrl::ScrollList 
2455 bool wxListCtrl::SortItems ( wxListCtrlCompare fn
, long lData 
) 
2457     SInternalDataSort vInternalData
; 
2459     vInternalData
.m_fnUser 
= fn
; 
2460     vInternalData
.m_lData  
= lData
; 
2462     // WPARAM cast is needed for mingw/cygwin 
2463     if (!::WinSendMsg( GetHWND() 
2465                       ,(PFN
)InternalDataCompareFunc
 
2466                       ,(PVOID
)&vInternalData
 
2469         wxLogDebug(_T("CM_SORTRECORD failed")); 
2473 } // end of wxListCtrl::SortItems 
2475 // ---------------------------------------------------------------------------- 
2476 // message processing 
2477 // ---------------------------------------------------------------------------- 
2479 bool wxListCtrl::OS2Command ( WXUINT uCmd
, WXWORD wId 
) 
2481     if (uCmd 
== CN_ENDEDIT
) 
2483         wxCommandEvent 
vEvent( wxEVT_COMMAND_TEXT_UPDATED
, wId 
); 
2485         vEvent
.SetEventObject( this ); 
2486         ProcessCommand(vEvent
); 
2489     else if (uCmd 
== CN_KILLFOCUS
) 
2491         wxCommandEvent 
vEvent( wxEVT_KILL_FOCUS
, wId 
); 
2492         vEvent
.SetEventObject( this ); 
2493         ProcessCommand(vEvent
); 
2498 } // end of wxListCtrl::OS2Command 
2500 // Necessary for drawing hrules and vrules, if specified 
2501 void wxListCtrl::OnPaint ( wxPaintEvent
& rEvent 
) 
2503     wxPaintDC                       
vDc(this); 
2504     wxPen                           
vPen(wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT
) 
2508     wxSize                          vClientSize 
= GetClientSize(); 
2510     int                             nItemCount 
= GetItemCount(); 
2513     bool                            bDrawHRules 
= ((GetWindowStyle() & wxLC_HRULES
) != 0); 
2514     bool                            bDrawVRules 
= ((GetWindowStyle() & wxLC_VRULES
) != 0); 
2516     wxControl::OnPaint(rEvent
); 
2519     // Reset the device origin since it may have been set 
2521     vDc
.SetDeviceOrigin(0, 0); 
2522     if (!bDrawHRules 
&& !bDrawVRules
) 
2524     if ((GetWindowStyle() & wxLC_REPORT
) == 0) 
2527     vDc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
2531         long                        lTop 
= GetTopItem(); 
2533         for (i 
= lTop
; i 
< lTop 
+ GetCountPerPage() + 1; i
++) 
2539                 nCy 
= vItemRect
.GetTop(); 
2540                 if (i 
!= 0) // Don't draw the first one 
2549                 if (i 
== nItemCount 
- 1) 
2551                     nCy 
= vItemRect
.GetBottom(); 
2562     if (bDrawVRules 
&& (i 
> -1)) 
2564         wxRect                      vFirstItemRect
; 
2574             int                     nX 
= vItemRect
.GetX(); 
2576             for (nCol 
= 0; nCol 
< GetColumnCount(); nCol
++) 
2578                 int                 nColWidth 
= GetColumnWidth(nCol
); 
2581                 vDc
.DrawLine( nX 
- 1 
2582                              ,vFirstItemRect
.GetY() - 2 
2584                              ,vItemRect
.GetBottom() 
2589 } // end of wxListCtrl::OnPaint 
2591 // ---------------------------------------------------------------------------- 
2592 // virtual list controls 
2593 // ---------------------------------------------------------------------------- 
2595 wxString 
wxListCtrl::OnGetItemText ( 
2596   long                              WXUNUSED(lItem
) 
2597 , long                              WXUNUSED(lCol
) 
2600     // this is a pure virtual function, in fact - which is not really pure 
2601     // because the controls which are not virtual don't need to implement it 
2602     wxFAIL_MSG( _T("not supposed to be called") ); 
2603     return wxEmptyString
; 
2604 } // end of wxListCtrl::OnGetItemText 
2606 int wxListCtrl::OnGetItemImage ( 
2607   long                              WXUNUSED(lItem
) 
2611     wxFAIL_MSG( _T("not supposed to be called") ); 
2613 } // end of wxListCtrl::OnGetItemImage 
2615 int wxListCtrl::OnGetItemColumnImage ( 
2621         return OnGetItemImage(lItem
); 
2624 } // end of wxListCtrl::OnGetItemColumnImage 
2626 wxListItemAttr
* wxListCtrl::OnGetItemAttr ( 
2627   long                              WXUNUSED_UNLESS_DEBUG(lItem
) 
2630     wxASSERT_MSG( lItem 
>= 0 && lItem 
< GetItemCount(), 
2631                   _T("invalid item index in OnGetItemAttr()") ); 
2634     // No attributes by default 
2637 } // end of wxListCtrl::OnGetItemAttr 
2639 void wxListCtrl::SetItemCount ( 
2643     wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") ); 
2646     // Cannot explicitly set the record count in OS/2 
2648 } // end of wxListCtrl::SetItemCount 
2650 void wxListCtrl::RefreshItem ( 
2660 } // end of wxListCtrl::RefreshItem 
2662 void wxListCtrl::RefreshItems ( long lItemFrom
, long lItemTo 
) 
2667     GetItemRect( lItemFrom 
, vRect1 
); 
2668     GetItemRect( lItemTo 
, vRect2 
); 
2670     wxRect vRect 
= vRect1
; 
2672     vRect
.height 
= vRect2
.GetBottom() - vRect1
.GetTop(); 
2674 } // end of wxListCtrl::RefreshItems 
2676 MRESULT 
wxListCtrl::OS2WindowProc( WXUINT uMsg
, 
2680     bool                            bProcessed 
= false; 
2682     wxListEvent                     
vEvent( wxEVT_NULL
 
2685     wxEventType                     vEventType 
= wxEVT_NULL
; 
2686     PCNRDRAGINIT                    pDragInit 
= NULL
; 
2687     PCNREDITDATA                    pEditData 
= NULL
; 
2688     PNOTIFYRECORDENTER              pNotifyEnter 
= NULL
; 
2690     vEvent
.SetEventObject(this); 
2695             // First off let's set some internal data 
2697             switch(SHORT2FROMMP(wParam
)) 
2703                         CListItemInternalData
*  pInternaldata 
= (CListItemInternalData 
*)lParam
; 
2707                             wxListItem
*     pItem 
= (wxListItem
*)&vEvent
.GetItem(); 
2709                             pItem
->SetData((long)pInternaldata
->m_lParam
); 
2715             // Now let's go through the codes we're interested in 
2717             switch(SHORT2FROMMP(wParam
)) 
2720                     pDragInit 
= (PCNRDRAGINIT
)lParam
; 
2723                         PMYRECORD       pRecord 
= (PMYRECORD
)pDragInit
->pRecord
; 
2725                         vEventType 
= wxEVT_COMMAND_LIST_BEGIN_RDRAG
; 
2726                         vEvent
.m_itemIndex   
= pRecord
->m_ulItemId
; 
2727                         vEvent
.m_pointDrag
.x 
= pDragInit
->x
; 
2728                         vEvent
.m_pointDrag
.y 
= pDragInit
->y
; 
2733                     pEditData 
= (PCNREDITDATA
)lParam
; 
2736                         vEventType 
= wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
; 
2737                         ConvertFromOS2ListItem( GetHWND() 
2738                                                ,(wxListItem 
&)vEvent
.GetItem() 
2739                                                ,(PMYRECORD
)pEditData
->pRecord
 
2741                         vEvent
.m_itemIndex 
= vEvent
.GetItem().GetId(); 
2746                     pEditData 
= (PCNREDITDATA
)lParam
; 
2749                         vEventType 
= wxEVT_COMMAND_LIST_END_LABEL_EDIT
; 
2750                         ConvertFromOS2ListItem( GetHWND() 
2751                                                ,(wxListItem 
&)vEvent
.GetItem() 
2752                                                ,(PMYRECORD
)pEditData
->pRecord
 
2754                         if (pEditData
->cbText 
== 0) 
2755                             return (MRESULT
)FALSE
; 
2756                         vEvent
.m_itemIndex 
= vEvent
.GetItem().GetId(); 
2761                     pNotifyEnter 
= (PNOTIFYRECORDENTER
)lParam
; 
2764                         wxListItem
*     pItem 
= (wxListItem
*)&vEvent
.GetItem(); 
2765                         PMYRECORD       pMyRecord 
= (PMYRECORD
)pNotifyEnter
->pRecord
; 
2767                         vEventType             
= wxEVT_COMMAND_LIST_ITEM_ACTIVATED
; 
2768                         vEvent
.m_itemIndex 
= pMyRecord
->m_ulItemId
; 
2769                         pItem
->SetText(GetItemText(pMyRecord
->m_ulItemId
)); 
2770                         pItem
->SetData(GetItemData(pMyRecord
->m_ulItemId
)); 
2775                     // Add the CN_DROP messages for Direct Manipulation 
2778             vEvent
.SetEventType(vEventType
); 
2779             bProcessed 
= GetEventHandler()->ProcessEvent(vEvent
); 
2783         lRc 
= wxControl::OS2WindowProc( uMsg
 
2788 } // end of wxListCtrl::WindowProc 
2790 #endif // wxUSE_LISTCTRL