]> git.saurik.com Git - wxWidgets.git/blame - src/os2/listctrl.cpp
Minor corrections to wxFlexGridSizer ctor documentation.
[wxWidgets.git] / src / os2 / listctrl.cpp
CommitLineData
c4f4cf89
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/os2/listctrl.cpp
3// Purpose: wxListCtrl
4// Author: David Webster
5// Modified by:
6// Created: 01/21/03
7// RCS-ID: $Id$
8// Copyright: (c) David Webster
65571936 9// Licence: wxWindows licence
c4f4cf89
DW
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
c4f4cf89
DW
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#if wxUSE_LISTCTRL
28
29#ifndef WX_PRECOMP
30 #include "wx/app.h"
31 #include "wx/intl.h"
32 #include "wx/log.h"
33 #include "wx/settings.h"
ed4b0fdc 34 #include "wx/dcclient.h"
fec9cc08 35 #include "wx/textctrl.h"
c4f4cf89
DW
36#endif
37
c4f4cf89
DW
38#include "wx/imaglist.h"
39#include "wx/listctrl.h"
c4f4cf89
DW
40
41#include "wx/os2/private.h"
42
43//
44// FIELDOFFSET in DETAIL view as defined in the OS2TK45 simply doesn't work
45// We use this, which does!
46//
47#undef FIELDOFFSET
48#define FIELDOFFSET(type, field) ((ULONG)&(((type *)0)->field))
49
50// ----------------------------------------------------------------------------
51// private helper classes
52// ----------------------------------------------------------------------------
53
54/////////////////////////////////////////////////////////////////////////////
55// STRUCT SMYRECORD
56// Under OS/2 we have to use our own RECORDCORE based struct if we have
378ad957
DW
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
c4f4cf89
DW
59// byte value containing a pointer to our CListIntemInternalData class
60// instance.
378ad957
DW
61//
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.
77ffb593 67// the wxWidgets wxLC_REPORT view, relies on STATIC structure for its
378ad957
DW
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.
77ffb593 71// wxWidgets is dynamic in nature, however. We insert columns, one at a
378ad957
DW
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.
75//
76// For example to display the data "Col 4 of Item 6" in a report view, I'd
77// have to do:
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.
81//
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.
c4f4cf89
DW
85/////////////////////////////////////////////////////////////////////////////
86typedef struct _MYRECORD
87{
88 RECORDCORE m_vRecord;
89 unsigned long m_ulItemId;
378ad957
DW
90 unsigned long m_ulUserData; //actually a pointer value to real data (a CListItemInternalData class instance)
91 PSZ m_pzColumn1;
92 PSZ m_pzColumn2;
93 PSZ m_pzColumn3;
94 PSZ m_pzColumn4;
95 PSZ m_pzColumn5;
96 PSZ m_pzColumn6;
97 PSZ m_pzColumn7;
98 PSZ m_pzColumn8;
99 PSZ m_pzColumn9;
100 PSZ m_pzColumn10;
c4f4cf89
DW
101} MYRECORD, *PMYRECORD;
102
103/////////////////////////////////////////////////////////////////////////////
104// CLASS CListItemInternalData
105//
106// Problem:
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.
111//
112// Solution:
113// Under MSW the only way to associate data with a
43e8916f 114// List item independent of its position in the list is to store a pointer
c4f4cf89
DW
115// to it in its lParam attribute. However user programs are already using
116// this (via the SetItemData() GetItemData() calls).
117//
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.
120//
121// class CListItemInternalData
122// {
123// public:
124// GuiAdvCtrl_CListItemAttr* pAttr;
125// long lParam; // user data
126// };
127//
128// To conserve memory, a CListItemInternalData is only allocated for a
129// LV_ITEM if text attributes or user data(lparam) are being set.
130//
131// For OS/2, the lParam value points to whatever actual data we have
132/////////////////////////////////////////////////////////////////////////////
133class CListItemInternalData
134{
135public:
136
137 CListItemInternalData(): m_pAttr(NULL)
138 ,m_lParam(0)
139 {}
140
141 ~CListItemInternalData()
142 {
143 delete m_pAttr;
144 m_pAttr = NULL;
145 }
146
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
151
152/////////////////////////////////////////////////////////////////////////////
153// STRUCT SInternalDataSort
154//
155// Sort items.
156//
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.
161//
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.
165//
166// data is arbitrary data to be passed to the sort function.
167//
168// Internal structures for proxying the user compare function
169// so that we can pass it the *real* user data
170/////////////////////////////////////////////////////////////////////////////
171typedef struct internalDataSort
172{
173 wxListCtrlCompare m_fnUser;
174 long m_lData;
175} SInternalDataSort; // end of STRUCT SInternalDataSort
176
177// ----------------------------------------------------------------------------
178// private helper functions
179// ----------------------------------------------------------------------------
180
181/////////////////////////////////////////////////////////////////////////////
182//
183// FindOS2ListFieldByColNum
184//
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.
188//
189// PARAMETERS
190// hWnd -- window handle of container to search
191// lIndex -- index to set
192//
193// RETURN VALUE
194// pointer to the FIELDINFO struct at the index in the container record
195//
196/////////////////////////////////////////////////////////////////////////////
197PFIELDINFO FindOS2ListFieldByColNum (
198 HWND hWnd
199, long lIndex
200)
201{
202 PFIELDINFO pFieldInfo = NULL;
203 CNRINFO vCnrInfo;
204 ULONG i;
205
206 if (!::WinSendMsg( hWnd
207 ,CM_QUERYCNRINFO
208 ,MPFROMP(&vCnrInfo)
209 ,(MPARAM)(USHORT)sizeof(CNRINFO)
210 ))
211 return NULL;
212 for (i = 0; i < vCnrInfo.cFields; i++)
213 {
214 if (i == 0)
215 pFieldInfo = (PFIELDINFO)PVOIDFROMMR(::WinSendMsg( hWnd
216 ,CM_QUERYDETAILFIELDINFO
217 ,MPFROMP(pFieldInfo)
218 ,(MPARAM)CMA_FIRST
219 ));
220 else
221 pFieldInfo = (PFIELDINFO)PVOIDFROMMR(::WinSendMsg( hWnd
222 ,CM_QUERYDETAILFIELDINFO
223 ,MPFROMP(pFieldInfo)
224 ,(MPARAM)CMA_NEXT
225 ));
226 if (!pFieldInfo)
227 return NULL;
228 if (i == (ULONG)lIndex)
229 break;
230 }
231 if (!pFieldInfo)
232 return NULL;
233 return pFieldInfo;
234} // end of FindOS2ListFieldByColNum
235
236/////////////////////////////////////////////////////////////////////////////
237//
238// FindOS2ListRecordByID
239//
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.
243//
244// PARAMETERS
245// hWnd -- window handle of container to search
246// lItemId -- index to set
247//
248// RETURN VALUE
249// pointer to the internal RECORDCORE struct at the index in the container
250//
251/////////////////////////////////////////////////////////////////////////////
252PMYRECORD FindOS2ListRecordByID (
253 HWND hWnd
254, long lItemId
255)
256{
257 PMYRECORD pRecord = NULL;
258 CNRINFO vCnrInfo;
259 unsigned long i;
260
261 if (!::WinSendMsg( hWnd
262 ,CM_QUERYCNRINFO
263 ,MPFROMP(&vCnrInfo)
264 ,(MPARAM)(USHORT)sizeof(CNRINFO)
265 ))
266 return NULL;
267 for (i = 0; i < vCnrInfo.cRecords; i++)
268 {
269 if (i == 0)
270 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
271 ,CM_QUERYRECORD
272 ,MPFROMP(pRecord)
273 ,MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)
274 ));
275 else
276 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
277 ,CM_QUERYRECORD
278 ,MPFROMP(pRecord)
279 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
280 ));
281 if (!pRecord)
282 return NULL;
283 if (pRecord->m_ulItemId == (ULONG)lItemId)
284 break;
285 }
286 return pRecord;
287} // end of FindOS2ListRecordByID
288
289/////////////////////////////////////////////////////////////////////////////
290//
291// BumpRecordIds
292//
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.
296//
297// PARAMETERS
298// hWnd -- window handle of container to search
299// pRecord -- record after which we starting bumping id's
300//
301// RETURN VALUE
302// none
303//
304/////////////////////////////////////////////////////////////////////////////
305void BumpRecordIds (
306 HWND hWnd
307, PMYRECORD pRecord
308)
309{
310 while(pRecord)
311 {
312 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
313 ,CM_QUERYRECORD
314 ,MPFROMP(pRecord)
315 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
316 ));
317 if (pRecord)
318 pRecord->m_ulItemId++;
319 }
320} // end of BumpRecordIds
321
322/////////////////////////////////////////////////////////////////////////////
323//
324// GetInternalData
325//
326// Get the internal data given a handle and an id
327//
328// PARAMETERS
329// hWnd -- window handle to the control in which item is located
330// lItemId -- ID to get
331//
332// RETURN VALUE
333// pointer to the internal data
334//
335// Note:
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/////////////////////////////////////////////////////////////////////////////
340CListItemInternalData* GetInternalData (
341 HWND hWnd
342, long lItemId
343)
344{
345 PMYRECORD pRecord = FindOS2ListRecordByID( hWnd
346 ,lItemId
347 );
348 //
349 // Internal user data is stored AFTER the last field of the RECORDCORE
350 //
351 if (!pRecord)
352 return NULL;
353 return((CListItemInternalData *)(pRecord->m_ulUserData));
354} // end of GetInternalData
355
356/////////////////////////////////////////////////////////////////////////////
357//
358// GetInternalData
359//
360// Get the internal data given a pointer to a list control and an id
361//
362// PARAMETERS
363// pCtl -- pointer to control inwhich item is located
364// lItemId -- ID to get
365//
366// RETURN VALUE
367// pointer to the internal data
368//
369/////////////////////////////////////////////////////////////////////////////
370CListItemInternalData* GetInternalData (
371 wxListCtrl* pCtl
372, long lItemId
373)
374{
375 return(GetInternalData( (HWND)pCtl->GetHWND()
376 ,lItemId
377 ));
378} // end of GetInternalData
379
380/////////////////////////////////////////////////////////////////////////////
381//
382// DeleteInternalData
383//
384// Delete the internal data for a record
385//
386// PARAMETERS
387// pCtl -- pointer to the list control containing the record
388// lItemId -- the record index to delete the internal data from
389//
390// RETURN VALUE
391// pointer to the internal data attribute
392//
393/////////////////////////////////////////////////////////////////////////////
394void DeleteInternalData (
395 wxListCtrl* pCtl
396, long lItemId
397)
398{
399 CListItemInternalData* pData = GetInternalData( pCtl
400 ,lItemId
401 );
402 if (pData)
403 {
404 if (pData->m_pMyRecord)
405 pData->m_pMyRecord->m_ulUserData = 0;
406 delete pData;
407 }
408} // end of DeleteInternalData
409
410// #pragma page "GetInternalDataAttr"
411/////////////////////////////////////////////////////////////////////////////
412//
413// GetInternalDataAttr
414//
415// Get the internal data item attribute given a pointer to a list control
416// and an id
417//
418// PARAMETERS
419// pCtl -- pointer to control to set
420// lItemId -- ID to set
421//
422// RETURN VALUE
423// pointer to the internal data attribute
424//
425/////////////////////////////////////////////////////////////////////////////
426wxListItemAttr* GetInternalDataAttr (
427 wxListCtrl* pCtl
428, long lItemId
429)
430{
431 CListItemInternalData* pData = GetInternalData( pCtl
432 ,lItemId
433 );
434
435 if (pData)
436 return(pData->m_pAttr);
437 else
438 return NULL;
439} // end of GetInternalDataAttr
440
441/////////////////////////////////////////////////////////////////////////////
442//
443// InternalDataCompareFunc
444//
445// This is compare function we pass to PM. It wraps the real compare
446// function in SInternalDataSort
447//
448// PARAMETERS
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.
452//
453// RETURN VALUE
454// pointer to the internal data attribute
455//
456/////////////////////////////////////////////////////////////////////////////
457SHORT EXPENTRY InternalDataCompareFunc (
458 PMYRECORD p1
459, PMYRECORD p2
460, PVOID pStorage
461)
462{
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);
468
469 return(pInternalData->m_fnUser( lD1
470 ,lD2
471 ,pInternalData->m_lData
472 ));
473} // end of InternalDataCompareFunc
474
475/////////////////////////////////////////////////////////////////////////////
476//
477// ConvertFromOS2ListItem
478//
479// Convert from an internal PM List item to a Toolkit List item
480//
481// PARAMETERS
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
485//
486// RETURN VALUE
487// none
488//
489/////////////////////////////////////////////////////////////////////////////
fec9cc08
WS
490void ConvertFromOS2ListItem ( HWND hWndListCtrl,
491 wxListItem& rInfo,
492 PMYRECORD pRecord )
c4f4cf89 493{
fec9cc08
WS
494 CListItemInternalData* pInternaldata = (CListItemInternalData *)pRecord->m_ulUserData;
495 bool bNeedText = false;
c4f4cf89
DW
496
497 if (pInternaldata)
498 rInfo.SetData(pInternaldata->m_lParam);
499
500 rInfo.SetMask(0);
501 rInfo.SetState(0);
502 rInfo.SetStateMask(0);
503 rInfo.SetId((long)pRecord->m_ulItemId);
504 if (hWndListCtrl != 0)
505 {
506 pRecord = FindOS2ListRecordByID( hWndListCtrl
507 ,rInfo.GetId()
508 );
509 }
510
511 //
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
515 //
516 if (pRecord->m_vRecord.flRecordAttr & CRA_DROPONABLE)
517 {
518 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_DROPHILITED);
519 rInfo.SetState(rInfo.m_state | wxLIST_STATE_DROPHILITED);
520 }
521 if (pRecord->m_vRecord.flRecordAttr & CRA_SELECTED)
522 {
523 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_SELECTED);
524 rInfo.SetState(rInfo.m_state | wxLIST_STATE_SELECTED);
525 }
526 if (pRecord->m_vRecord.flRecordAttr & CRA_DISABLED)
527 {
528 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_DISABLED);
529 rInfo.SetState(rInfo.m_state | wxLIST_STATE_DISABLED);
530 }
531 if (pRecord->m_vRecord.flRecordAttr & CRA_FILTERED)
532 {
533 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_FILTERED);
534 rInfo.SetState(rInfo.m_state | wxLIST_STATE_FILTERED);
535 }
536 if (pRecord->m_vRecord.flRecordAttr & CRA_INUSE)
537 {
538 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_INUSE);
539 rInfo.SetState(rInfo.m_state | wxLIST_STATE_INUSE);
540 }
541 if (pRecord->m_vRecord.flRecordAttr & CRA_PICKED)
542 {
543 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_PICKED);
544 rInfo.SetState(rInfo.m_state | wxLIST_STATE_PICKED);
545 }
546 if (pRecord->m_vRecord.flRecordAttr & CRA_SOURCE)
547 {
548 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_SOURCE);
549 rInfo.SetState(rInfo.m_state | wxLIST_STATE_SOURCE);
550 }
551
552 if (pRecord->m_vRecord.pszText != (PSZ)NULL)
553 {
554 rInfo.SetMask(rInfo.GetMask() | wxLIST_MASK_TEXT);
555 rInfo.SetText(pRecord->m_vRecord.pszText);
556 }
557 if (pRecord->m_vRecord.pszIcon != (PSZ)NULL ||
558 pRecord->m_vRecord.pszName != (PSZ)NULL)
559 {
560 rInfo.SetMask(rInfo.GetMask() | wxLIST_MASK_IMAGE);
561 rInfo.SetImage(pRecord->m_vRecord.hptrIcon);
562 }
563 if (pRecord->m_ulUserData)
564 rInfo.SetMask(rInfo.GetMask() | wxLIST_MASK_DATA);
565} // end of ConvertFromOS2ListItem
566
567/////////////////////////////////////////////////////////////////////////////
568//
569// ConvertToOS2Flags
570//
571// Convert from an library states to OS states
572//
573// PARAMETERS
574// lState -- the state
575// pRecord -- the OS list control to use
576//
577// RETURN VALUE
578// none
579//
580/////////////////////////////////////////////////////////////////////////////
581void ConvertToOS2Flags (
582 long lState
583, PMYRECORD pRecord
584)
585{
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
601
602/////////////////////////////////////////////////////////////////////////////
603//
604// ConvertToOS2ListItem
605//
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.
609//
610// PARAMETERS
378ad957
DW
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
c4f4cf89
DW
615//
616// RETURN VALUE
617// none
618//
619/////////////////////////////////////////////////////////////////////////////
620void ConvertToOS2ListItem (
621 const wxListCtrl* pCtrl
622, const wxListItem& rInfo
623, PMYRECORD pRecord
378ad957 624, PFIELDINFO pFieldInfo
c4f4cf89
DW
625)
626{
627 pRecord->m_ulItemId = (ULONG)rInfo.GetId();
378ad957 628 pRecord->m_vRecord.cb = sizeof(RECORDCORE);
c4f4cf89
DW
629 if (rInfo.GetMask() & wxLIST_MASK_STATE)
630 {
631 ConvertToOS2Flags( rInfo.m_state
632 ,pRecord
633 );
634 }
635 if (pCtrl->GetWindowStyleFlag() & wxLC_ICON ||
636 pCtrl->GetWindowStyleFlag() & wxLC_SMALL_ICON)
637 {
638 pRecord->m_vRecord.pszIcon = (char*)rInfo.GetText().c_str();
639 }
640 if (pCtrl->GetWindowStyleFlag() & wxLC_LIST) // PM TEXT view
641 {
642 pRecord->m_vRecord.pszText = (char*)rInfo.GetText().c_str();
643 }
378ad957
DW
644 //
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.
647 //
648 if (pCtrl->GetWindowStyleFlag() & wxLC_REPORT)
649 {
650 if (pFieldInfo)
651 {
652 switch(rInfo.GetColumn())
653 {
654 case 0:
655 pRecord->m_pzColumn1 = (char*)rInfo.GetText().c_str();
656 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn1);
657 break;
658
659 case 1:
660 pRecord->m_pzColumn2 = (char*)rInfo.GetText().c_str();
661 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn2);
662 break;
663
664 case 2:
665 pRecord->m_pzColumn3 = (char*)rInfo.GetText().c_str();
666 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn3);
667 break;
668
669 case 3:
670 pRecord->m_pzColumn4 = (char*)rInfo.GetText().c_str();
671 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn4);
672 break;
673
674 case 4:
675 pRecord->m_pzColumn5 = (char*)rInfo.GetText().c_str();
676 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn5);
677 break;
678
679 case 5:
680 pRecord->m_pzColumn6 = (char*)rInfo.GetText().c_str();
681 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn6);
682 break;
683
684 case 6:
685 pRecord->m_pzColumn7 = (char*)rInfo.GetText().c_str();
686 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn7);
687 break;
688
689 case 7:
690 pRecord->m_pzColumn8 = (char*)rInfo.GetText().c_str();
691 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn8);
692 break;
693
694 case 8:
695 pRecord->m_pzColumn9 = (char*)rInfo.GetText().c_str();
696 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn9);
697 break;
698
699 case 9:
700 pRecord->m_pzColumn10 = (char*)rInfo.GetText().c_str();
701 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn10);
702 break;
703
704 default:
9a83f860 705 wxFAIL_MSG( wxT("wxOS2 does not support more than 10 columns in REPORT view") );
378ad957
DW
706 break;
707 }
708 }
709 }
c4f4cf89
DW
710 if (rInfo.GetMask() & wxLIST_MASK_IMAGE)
711 {
712 pRecord->m_vRecord.hptrIcon = (HPOINTER)rInfo.GetImage();
713 pRecord->m_vRecord.hptrMiniIcon = (HPOINTER)rInfo.m_miniImage;
714 }
715} // end of ConvertToOS2ListItem
716
717/////////////////////////////////////////////////////////////////////////////
718//
719// ConvertToOS2ListCol
720//
721// Convert from a library List column to an internal PM List column
722//
723// PARAMETERS
724// lCol -- the columnd to convert
725// rItem -- the item to convert
726// pField -- the OS list column to use
727//
728// RETURN VALUE
729// none
730//
731/////////////////////////////////////////////////////////////////////////////
732void ConvertToOS2ListCol (
733 long lCol
734, const wxListItem& rItem
735, PFIELDINFO pField
736)
737{
738 memset(pField, '\0', sizeof(FIELDINFO));
739 pField->cb = sizeof(FIELDINFO);
378ad957
DW
740
741 //
742 // Default some settings
743 //
744 pField->flData = CFA_HORZSEPARATOR | CFA_SEPARATOR;
745 pField->flTitle = CFA_CENTER;
746
c4f4cf89
DW
747 if (rItem.GetMask() & wxLIST_MASK_TEXT)
748 {
749 pField->flData |= CFA_STRING;
378ad957 750 pField->pTitleData = (PVOID)rItem.GetText().c_str(); // text is column title not data
c4f4cf89
DW
751 }
752 if (rItem.GetMask() & wxLIST_MASK_FORMAT)
753 {
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;
760 }
378ad957
DW
761 else
762 pField->flData |= CFA_CENTER; // Just ensure the default is centered
c4f4cf89
DW
763 if (rItem.GetMask() & wxLIST_MASK_WIDTH)
764 {
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
769 }
378ad957
DW
770
771 //
772 // Still need to set the actual data
773 //
774 pField->offStruct = 0;
c4f4cf89
DW
775} // end of ConvertToOS2ListCol
776
c4f4cf89
DW
777
778IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
779IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
780IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
781
782IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
783
784BEGIN_EVENT_TABLE(wxListCtrl, wxControl)
785 EVT_PAINT(wxListCtrl::OnPaint)
786END_EVENT_TABLE()
787
788// ============================================================================
789// implementation
790// ============================================================================
791
792// ----------------------------------------------------------------------------
793// wxListCtrl construction
794// ----------------------------------------------------------------------------
795
796void wxListCtrl::Init ()
797{
798 m_pImageListNormal = NULL;
799 m_pImageListSmall = NULL;
800 m_pImageListState = NULL;
fec9cc08
WS
801 m_bOwnsImageListNormal = false;
802 m_bOwnsImageListSmall = false;
803 m_bOwnsImageListState = false;
c4f4cf89
DW
804 m_lBaseStyle = 0L;
805 m_nColCount = 0;
806 m_pTextCtrl = NULL;
fec9cc08
WS
807 m_bAnyInternalData = false;
808 m_bHasAnyAttr = false;
c4f4cf89
DW
809} // end of wxListCtrl::Init
810
fec9cc08
WS
811bool wxListCtrl::Create ( wxWindow* pParent,
812 wxWindowID vId,
813 const wxPoint& rPos,
814 const wxSize& rSize,
815 long lStyle,
816 const wxValidator& rValidator,
817 const wxString& rsName )
c4f4cf89 818{
fec9cc08
WS
819 int nX = rPos.x;
820 int nY = rPos.y;
821 int nWidth = rSize.x;
822 int nHeight = rSize.y;
c4f4cf89
DW
823
824#if wxUSE_VALIDATORS
825 SetValidator(rValidator);
826#endif // wxUSE_VALIDATORS
827
828 SetName(rsName);
829 SetWindowStyleFlag(lStyle);
830 SetParent(pParent);
831 if (nWidth <= 0)
832 nWidth = 100;
833 if (nHeight <= 0)
834 nHeight = 30;
835 if (nX < 0)
836 nX = 0;
837 if (nY < 0)
838 nY = 0;
839
840 m_windowId = (vId == -1) ? NewControlId() : vId;
841
fec9cc08 842 long lSstyle = WS_VISIBLE | WS_TABSTOP;
c4f4cf89
DW
843
844 if (GetWindowStyleFlag() & wxCLIP_SIBLINGS)
845 lSstyle |= WS_CLIPSIBLINGS;
846 m_lBaseStyle = lSstyle;
847 if (!DoCreateControl( nX
848 ,nY
849 ,nWidth
850 ,nHeight
851 ))
fec9cc08 852 return false;
c4f4cf89
DW
853 if (pParent)
854 pParent->AddChild(this);
fec9cc08 855 return true;
c4f4cf89
DW
856} // end of wxListCtrl::Create
857
fec9cc08
WS
858bool wxListCtrl::DoCreateControl ( int nX, int nY,
859 int nWidth, int nHeight )
c4f4cf89 860{
fec9cc08
WS
861 DWORD lWstyle = m_lBaseStyle;
862 long lOldStyle = 0; // Dummy
c4f4cf89 863
fec9cc08 864 CNRINFO vCnrInfo;
c4f4cf89
DW
865
866 lWstyle |= ConvertToOS2Style( lOldStyle
867 ,GetWindowStyleFlag()
868 );
869
870 m_hWnd = (WXHWND)::WinCreateWindow( GetParent()->GetHWND()
871 ,WC_CONTAINER
872 ,NULL
873 ,m_lBaseStyle
874 ,0, 0, 0, 0
875 ,GetParent()->GetHWND()
876 ,HWND_BOTTOM
877 ,(ULONG)m_windowId
878 ,NULL
879 ,NULL
880 );
881 if (!m_hWnd)
882 {
fec9cc08 883 return false;
c4f4cf89
DW
884 }
885
886 //
887 // Now set the display attributes of the container
888 //
889 if (!::WinSendMsg( GetHWND()
890 ,CM_QUERYCNRINFO
891 ,MPFROMP(&vCnrInfo)
892 ,(MPARAM)(USHORT)sizeof(CNRINFO)
893 ))
fec9cc08 894 return false;
c4f4cf89 895 lWstyle = ConvertViewToOS2Style(GetWindowStyleFlag());
378ad957
DW
896 vCnrInfo.flWindowAttr |= lWstyle;
897 if (!::WinSendMsg( GetHWND()
898 ,CM_SETCNRINFO
899 ,MPFROMP(&vCnrInfo)
900 ,(MPARAM)CMA_FLWINDOWATTR
901 ))
fec9cc08 902 return false;
c4f4cf89
DW
903
904 //
905 // And now set needed arrangement flags
906 //
907 lWstyle = ConvertArrangeToOS2Style(GetWindowStyleFlag());
378ad957
DW
908 if (!::WinSendMsg( GetHWND()
909 ,CM_ARRANGE
910 ,(MPARAM)CMA_ARRANGEGRID
911 ,(MPARAM)lWstyle
912 ))
fec9cc08 913 return false;
c4f4cf89
DW
914 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
915 SetForegroundColour(GetParent()->GetForegroundColour());
916 SubclassWin(m_hWnd);
917 SetFont(*wxSMALL_FONT);
918 SetXComp(0);
919 SetYComp(0);
fec9cc08
WS
920 SetSize( nX, nY, nWidth, nHeight );
921 return true;
c4f4cf89
DW
922} // end of wxListCtrl::DoCreateControl
923
924void wxListCtrl::UpdateStyle ()
925{
926 if (GetHWND())
927 {
fec9cc08
WS
928 long lDummy;
929 DWORD dwStyleNew = ConvertToOS2Style( lDummy, GetWindowStyleFlag() );
c4f4cf89
DW
930
931 dwStyleNew |= m_lBaseStyle;
932
933 //
934 // Get the current window style.
935 //
fec9cc08 936 ULONG dwStyleOld = ::WinQueryWindowULong(GetHWND(), QWL_STYLE);
c4f4cf89
DW
937
938 //
939 // Only set the window style if the view bits have changed.
940 //
941 if (dwStyleOld != dwStyleNew)
942 {
943 ::WinSetWindowULong(GetHWND(), QWL_STYLE, dwStyleNew);
944 }
945 }
946} // end of wxListCtrl::UpdateStyle
947
948void wxListCtrl::FreeAllInternalData ()
949{
950 if (m_bAnyInternalData)
951 {
fec9cc08
WS
952 int n = GetItemCount();
953 int i = 0;
c4f4cf89
DW
954
955 for (i = 0; i < n; i++)
956 DeleteInternalData(this, (long)i);
fec9cc08 957 m_bAnyInternalData = false;
c4f4cf89
DW
958 }
959} // end of wxListCtrl::FreeAllInternalData
960
961wxListCtrl::~wxListCtrl ()
962{
963 FreeAllInternalData();
964 if (m_pTextCtrl )
965 {
966 m_pTextCtrl->SetHWND(0);
967 m_pTextCtrl->UnsubclassWin();
968 delete m_pTextCtrl;
969 m_pTextCtrl = NULL;
970 }
971
972 if (m_bOwnsImageListNormal)
973 delete m_pImageListNormal;
974 if (m_bOwnsImageListSmall)
975 delete m_pImageListSmall;
976 if (m_bOwnsImageListState)
977 delete m_pImageListState;
978} // end of wxListCtrl::~wxListCtrl
979
980// ----------------------------------------------------------------------------
981// set/get/change style
982// ----------------------------------------------------------------------------
983
984// Add or remove a single window style
985void wxListCtrl::SetSingleStyle (
986 long lStyle
987, bool bAdd
988)
989{
990 long lFlag = GetWindowStyleFlag();
991
992 //
993 // Get rid of conflicting styles
994 //
995 if (bAdd)
996 {
997 if (lStyle & wxLC_MASK_TYPE)
998 lFlag = lFlag & ~wxLC_MASK_TYPE;
999 if (lStyle & wxLC_MASK_ALIGN )
1000 lFlag = lFlag & ~wxLC_MASK_ALIGN;
1001 if (lStyle & wxLC_MASK_SORT )
1002 lFlag = lFlag & ~wxLC_MASK_SORT;
1003 }
1004 if (lFlag & lStyle)
1005 {
1006 if (!bAdd)
1007 lFlag -= lStyle;
1008 }
1009 else
1010 {
1011 if (bAdd)
1012 {
1013 lFlag |= lStyle;
1014 }
1015 }
1016 m_windowStyle = lFlag;
1017 UpdateStyle();
1018} // end of wxListCtrl::SetSingleStyle
1019
1020// Set the whole window style
1021void wxListCtrl::SetWindowStyleFlag (
1022 long lFlag
1023)
1024{
1025 m_windowStyle = lFlag;
1026 UpdateStyle();
1027} // end of wxListCtrl::SetWindowStyleFlag
1028
1029long wxListCtrl::ConvertToOS2Style (
1030 long& rOldStyle
1031, long lStyle
1032) const
1033{
1034 long lWstyle = 0L;
1035
1036 //
1037 // The only styles OS2 uses on creation are auto arrange, read only, and
1038 // and selection styles. This lib does not support OS/2 MINIRECORDCORE
1039 // or VERIFYPOINTER styles
1040 //
1041 if (lStyle & wxLC_AUTOARRANGE)
1042 lWstyle |= CCS_AUTOPOSITION;
1043 if (lStyle & wxLC_SINGLE_SEL)
1044 lWstyle |= CCS_SINGLESEL;
1045 else
1046 lWstyle |= CCS_EXTENDSEL;
1047 if (!(lStyle & wxLC_EDIT_LABELS))
1048 lWstyle |= CCS_READONLY;
1049 return lWstyle;
1050} // end of wxListCtrl::ConvertToOS2Style
1051
1052long wxListCtrl::ConvertArrangeToOS2Style (
1053 long lStyle
1054)
1055{
1056 long lWstyle = 0;
1057
1058 if (lStyle & wxLC_ALIGN_LEFT)
1059 {
1060 lWstyle |= CMA_LEFT;
1061 }
1062
1063 if (lStyle & wxLC_ALIGN_TOP)
1064 {
1065 lWstyle |= CMA_TOP;
1066 }
1067 return lWstyle;
1068} // end of wxListCtrl::ConvertArrangeToOS2Style
1069
1070long wxListCtrl::ConvertViewToOS2Style (
1071 long lStyle
1072)
1073{
1074 long lWstyle = CA_DRAWICON; // we will only use icons
1075
1076 if (lStyle & wxLC_ICON)
1077 {
1078 lWstyle |= CV_ICON;
1079 }
1080 if (lStyle & wxLC_SMALL_ICON)
1081 {
1082 lWstyle |= (CV_ICON | CV_MINI);
1083 }
1084 if (lStyle & wxLC_LIST)
1085 {
1086 lWstyle |= CV_TEXT;
1087 }
1088 if (lStyle & wxLC_REPORT)
1089 {
1090 lWstyle |= CV_DETAIL;
1091 }
1092 if (lStyle & wxLC_VIRTUAL)
1093 {
1094 lWstyle |= CA_OWNERDRAW;
1095 }
1096 if (lStyle & wxLC_AUTOARRANGE)
1097 {
1098 lWstyle |= CV_FLOW;
1099 }
1100 if (!(lStyle & wxLC_NO_HEADER))
1101 {
1102 lWstyle |= CA_DETAILSVIEWTITLES;
1103 }
1104 return lWstyle;
1105} // end of wxListCtrl::ConvertViewToOS2Style
1106
1107// ----------------------------------------------------------------------------
1108// accessors
1109// ----------------------------------------------------------------------------
1110
1111// Sets the foreground, i.e. text, colour
fec9cc08 1112bool wxListCtrl::SetForegroundColour (const wxColour& rCol)
c4f4cf89 1113{
fec9cc08 1114 ULONG ulColor = wxColourToRGB(rCol);
c4f4cf89
DW
1115
1116 if (!wxWindow::SetForegroundColour(rCol))
fec9cc08 1117 return false;
c4f4cf89
DW
1118
1119 ::WinSetPresParam( GetHWND()
1120 ,PP_FOREGROUNDCOLOR
1121 ,sizeof(ULONG)
1122 ,&ulColor
1123 );
fec9cc08 1124 return true;
c4f4cf89
DW
1125} // end of wxListCtrl::SetForegroundColour
1126
1127// Sets the background colour
fec9cc08 1128bool wxListCtrl::SetBackgroundColour ( const wxColour& rCol )
c4f4cf89
DW
1129{
1130 if (!wxWindow::SetBackgroundColour(rCol))
fec9cc08 1131 return false;
c4f4cf89
DW
1132
1133 //
1134 // We set the same colour for both the "empty" background and the items
1135 // background
1136 //
fec9cc08 1137 ULONG ulColor = wxColourToRGB(rCol);
c4f4cf89
DW
1138
1139 ::WinSetPresParam( GetHWND()
1140 ,PP_BACKGROUNDCOLOR
1141 ,sizeof(ULONG)
1142 ,&ulColor
1143 );
fec9cc08 1144 return true;
c4f4cf89
DW
1145} // end of wxListCtrl::SetBackgroundColour
1146
1147// Gets information about this column
fec9cc08 1148bool wxListCtrl::GetColumn ( int nCol, wxListItem& rItem ) const
c4f4cf89 1149{
fec9cc08 1150 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND(), nCol );
c4f4cf89
DW
1151
1152 if (!pFieldInfo)
fec9cc08 1153 return false;
c4f4cf89
DW
1154 rItem.SetWidth(pFieldInfo->cxWidth);
1155 if ((rItem.GetMask() & wxLIST_MASK_TEXT) &&
1156 (pFieldInfo->flData & CFA_STRING) &&
1157 (pFieldInfo->pUserData != NULL))
1158 {
1159 rItem.SetText((char*)pFieldInfo->pUserData);
1160 }
1161 if (rItem.GetMask() & wxLIST_MASK_FORMAT )
1162 {
1163 if (pFieldInfo->flData & CFA_LEFT)
1164 rItem.m_format = wxLIST_FORMAT_LEFT;
1165 else if (pFieldInfo->flData & CFA_RIGHT)
1166 rItem.m_format = wxLIST_FORMAT_RIGHT;
1167 else if (pFieldInfo->flData & CFA_CENTER)
1168 rItem.m_format = wxLIST_FORMAT_CENTRE;
1169 }
fec9cc08 1170 return true;
c4f4cf89
DW
1171} // end of wxListCtrl::GetColumn
1172
1173// Sets information about this column
fec9cc08 1174bool wxListCtrl::SetColumn ( int nCol, wxListItem& rItem )
c4f4cf89 1175{
fec9cc08
WS
1176 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum( GetHWND(), nCol );
1177 ConvertToOS2ListCol( nCol, rItem, pFieldInfo );
c4f4cf89
DW
1178 //
1179 // Since we changed the field pointed to, we invalidate to see the result
1180 //
1181 ::WinSendMsg(GetHWND(), CM_INVALIDATEDETAILFIELDINFO, NULL, NULL);
fec9cc08 1182 return true;
c4f4cf89
DW
1183} // end of wxListCtrl::SetColumn
1184
1185// Gets the column width
fec9cc08 1186int wxListCtrl::GetColumnWidth ( int nCol ) const
c4f4cf89 1187{
fec9cc08 1188 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND(), nCol );
c4f4cf89
DW
1189
1190 if (!pFieldInfo)
1191 return 0;
1192 return((int)pFieldInfo->cxWidth);
1193} // end of wxListCtrl::GetColumnWidth
1194
1195// Sets the column width
fec9cc08 1196bool wxListCtrl::SetColumnWidth ( int nCol, int nWidth )
c4f4cf89 1197{
fec9cc08
WS
1198 int nCol2 = nCol;
1199 int nWidth2 = nWidth;
c4f4cf89
DW
1200
1201 if (GetWindowStyleFlag() & wxLC_LIST)
1202 nCol2 = -1;
1203
fec9cc08 1204 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum( GetHWND(), nCol );
c4f4cf89
DW
1205 pFieldInfo->cxWidth = nWidth;
1206 ::WinSendMsg(GetHWND(), CM_INVALIDATEDETAILFIELDINFO, NULL, NULL);
fec9cc08 1207 return true;
c4f4cf89
DW
1208} // end of wxListCtrl::SetColumnWidth
1209
1210// Gets the number of items that can fit vertically in the
1211// visible area of the list control (list or report view)
1212// or the total number of items in the list control (icon
1213// or small icon view)
1214int wxListCtrl::GetCountPerPage () const
1215{
1216 QUERYRECORDRECT vQueryRect;
1217 CNRINFO vCnrInfo;
1218 RECTL vRectRecord;
1219 RECTL vRectControl;
1220 int nCount;
1221
1222 if (!::WinSendMsg( GetHWND()
1223 ,CM_QUERYCNRINFO
1224 ,MPFROMP(&vCnrInfo)
1225 ,(MPARAM)(USHORT)sizeof(CNRINFO)
1226 ))
1227 return 0;
1228 memset(&vQueryRect, '\0', sizeof(QUERYRECORDRECT));
1229 vQueryRect.cb = sizeof(QUERYRECORDRECT);
1230 if (vCnrInfo.flWindowAttr & CV_ICON)
1231 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
1232 else if (vCnrInfo.flWindowAttr & CV_NAME)
1233 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
1234 else if (vCnrInfo.flWindowAttr & CV_TEXT)
1235 vQueryRect.fsExtent = CMA_TEXT;
1236 else if (vCnrInfo.flWindowAttr & CV_DETAIL)
1237 vQueryRect.fsExtent = CMA_TEXT;
1238 if (!::WinSendMsg( GetHWND()
1239 ,CM_QUERYRECORDRECT
1240 ,MPFROMP(&vRectRecord)
1241 ,MPFROMP(&vQueryRect)
1242 ))
1243 return 0;
1244 if (!::WinSendMsg( GetHWND()
1245 ,CM_QUERYVIEWPORTRECT
1246 ,MPFROMP(&vRectControl)
1247 ,MPFROM2SHORT(CMA_WINDOW, (USHORT)FALSE)
1248 ))
1249 return 0;
1250 nCount = (int)((int)((vRectControl.xRight - vRectControl.xLeft) / (vRectRecord.xRight - vRectRecord.xLeft)) *
1251 (int)((vRectControl.yTop - vRectControl.yBottom) / (vRectRecord.yTop - vRectRecord.yBottom))
1252 );
1253 if (nCount > (int)vCnrInfo.cFields)
1254 nCount = (int)vCnrInfo.cFields;
1255 return nCount;
1256} // end of wxListCtrl::GetCountPerPage
1257
1258// Gets the edit control for editing labels.
1259wxTextCtrl* wxListCtrl::GetEditControl() const
1260{
1261 return m_pTextCtrl;
1262}
1263
1264// Gets information about the item
fec9cc08 1265bool wxListCtrl::GetItem ( wxListItem& rInfo ) const
c4f4cf89 1266{
fec9cc08 1267 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), rInfo.GetId() );
c4f4cf89
DW
1268
1269 //
1270 // Give NULL as hwnd as we already have everything we need
1271 //
fec9cc08
WS
1272 ConvertFromOS2ListItem( NULL, rInfo, pRecord );
1273 return true;
c4f4cf89
DW
1274} // end of wxListCtrl::GetItem
1275
1276// Sets information about the item
fec9cc08 1277bool wxListCtrl::SetItem ( wxListItem& rInfo )
c4f4cf89 1278{
fec9cc08
WS
1279 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND(), rInfo.GetColumn() );
1280 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), rInfo.GetId() );
c4f4cf89
DW
1281
1282 ConvertToOS2ListItem( this
1283 ,rInfo
1284 ,pRecord
378ad957 1285 ,pFieldInfo
c4f4cf89
DW
1286 );
1287
1288 //
1289 // Check if setting attributes or lParam
1290 //
1291 if (rInfo.HasAttributes() || (rInfo.GetMask() & wxLIST_MASK_DATA))
1292 {
1293 //
1294 // Get internal item data
1295 // perhaps a cache here ?
1296 //
1297 CListItemInternalData* pData = GetInternalData( this
1298 ,rInfo.GetId()
1299 );
1300
1301 if (!pData)
1302 {
1303 //
1304 // Need to set it
1305 //
fec9cc08 1306 m_bAnyInternalData = true;
c4f4cf89
DW
1307 pData = new CListItemInternalData();
1308 pRecord->m_ulUserData = (unsigned long)pData;
1309 };
1310
1311 //
1312 // User data
1313 //
1314 if (rInfo.GetMask() & wxLIST_MASK_DATA)
1315 pData->m_lParam = (WXLPARAM)rInfo.GetData();
1316
1317 // attributes
1318 if (rInfo.HasAttributes())
1319 {
1320 if (pData->m_pAttr)
1321 *pData->m_pAttr = *rInfo.GetAttributes();
1322 else
1323 pData->m_pAttr = new wxListItemAttr(*rInfo.GetAttributes());
1324 }
378ad957 1325 pData->m_pMyRecord = pRecord; // they point to each other
c4f4cf89
DW
1326 }
1327
1328 //
1329 // We need to update the item immediately to show the new image
1330 //
fec9cc08 1331 bool bUpdateNow = (rInfo.GetMask() & wxLIST_MASK_IMAGE) != 0;
c4f4cf89
DW
1332
1333 //
1334 // Check whether it has any custom attributes
1335 //
1336 if (rInfo.HasAttributes())
1337 {
fec9cc08 1338 m_bHasAnyAttr = true;
c4f4cf89
DW
1339
1340 //
1341 // If the colour has changed, we must redraw the item
1342 //
fec9cc08 1343 bUpdateNow = true;
c4f4cf89 1344 }
378ad957
DW
1345 if (::WinIsWindowVisible(GetHWND()))
1346 {
1347 ::WinSendMsg( GetHWND()
1348 ,CM_INVALIDATERECORD
1349 ,MPFROMP(pRecord)
1350 ,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
1351 );
1352 RefreshItem(pRecord->m_ulItemId);
1353 }
c4f4cf89 1354 ::WinSendMsg( GetHWND()
378ad957
DW
1355 ,CM_INVALIDATEDETAILFIELDINFO
1356 ,NULL
1357 ,NULL
c4f4cf89 1358 );
fec9cc08 1359 return true;
c4f4cf89
DW
1360} // end of wxListCtrl::SetItem
1361
1362long wxListCtrl::SetItem (
1363 long lIndex
1364, int nCol
1365, const wxString& rsLabel
1366, int nImageId
1367)
1368{
1369 wxListItem vInfo;
1370
1371 vInfo.m_text = rsLabel;
1372 vInfo.m_mask = wxLIST_MASK_TEXT;
1373 vInfo.m_itemId = lIndex;
1374 vInfo.m_col = nCol;
1375 if (nImageId > -1)
1376 {
1377 vInfo.m_image = nImageId;
1378 vInfo.m_mask |= wxLIST_MASK_IMAGE;
1379 }
1380 return SetItem(vInfo);
1381} // end of wxListCtrl::SetItem
1382
1383// Gets the item state
1384int wxListCtrl::GetItemState (
1385 long lItem
1386, long lStateMask
1387) const
1388{
1389 wxListItem vInfo;
1390
1391 vInfo.m_mask = wxLIST_MASK_STATE;
1392 vInfo.m_stateMask = lStateMask;
1393 vInfo.m_itemId = lItem;
1394
1395 if (!GetItem(vInfo))
1396 return 0;
1397 return vInfo.m_state;
1398} // end of wxListCtrl::GetItemState
1399
1400// Sets the item state
fec9cc08 1401bool wxListCtrl::SetItemState ( long lItem, long lState, long lStateMask )
c4f4cf89 1402{
fec9cc08 1403 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
c4f4cf89
DW
1404
1405 //
1406 // Don't use SetItem() here as it doesn't work with the virtual list
1407 // controls
1408 //
fec9cc08 1409 ConvertToOS2Flags( lState, pRecord );
c4f4cf89
DW
1410
1411 //
1412 // for the virtual list controls we need to refresh the previously focused
1413 // item manually when changing focus without changing selection
1414 // programmatically because otherwise it keeps its focus rectangle until
1415 // next repaint (yet another comctl32 bug)
1416 //
1417 long lFocusOld;
1418
1419 if (IsVirtual() &&
1420 (lStateMask & wxLIST_STATE_FOCUSED) &&
1421 (lState & wxLIST_STATE_FOCUSED) )
1422 {
1423 lFocusOld = GetNextItem( -1
1424 ,wxLIST_NEXT_ALL
1425 ,wxLIST_STATE_FOCUSED
1426 );
1427 }
1428 else
1429 {
1430 lFocusOld = -1;
1431 }
1432 ::WinSendMsg( GetHWND()
1433 ,CM_INVALIDATERECORD
1434 ,MPFROMP(pRecord)
1435 ,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
1436 );
1437
1438 if (lFocusOld != -1)
1439 {
1440 //
1441 // No need to refresh the item if it was previously selected, it would
1442 // only result in annoying flicker
1443 //
1444 if (!(GetItemState( lFocusOld
1445 ,wxLIST_STATE_SELECTED
1446 ) & wxLIST_STATE_SELECTED))
1447 {
1448 RefreshItem(lFocusOld);
1449 }
1450 }
fec9cc08 1451 return true;
c4f4cf89
DW
1452} // end of wxListCtrl::SetItemState
1453
1454// Sets the item image
1455bool wxListCtrl::SetItemImage (
1456 long lItem
1457, int nImage
1458, int WXUNUSED(nSelImage))
06db67bc
RD
1459{
1460 return SetItemColumnInfo(lItem, 0, nImage);
1461} // end of wxListCtrl::SetItemImage
1462
1463// Sets the item image
1464bool wxListCtrl::SetItemColumnImage (
1465 long lItem
1466, long lColumn
c06de7d4 1467, int nImage)
c4f4cf89
DW
1468{
1469 wxListItem vInfo;
1470
1471 vInfo.m_mask = wxLIST_MASK_IMAGE;
1472 vInfo.m_image = nImage;
1473 vInfo.m_itemId = lItem;
06db67bc 1474 vInfo.m_col = lColumn;
c4f4cf89 1475 return SetItem(vInfo);
06db67bc 1476} // end of wxListCtrl::SetItemColumnImage
c4f4cf89
DW
1477
1478// Gets the item text
1479wxString wxListCtrl::GetItemText (
1480 long lItem
1481) const
1482{
1483 wxListItem vInfo;
1484
1485 vInfo.m_mask = wxLIST_MASK_TEXT;
1486 vInfo.m_itemId = lItem;
1487
1488 if (!GetItem(vInfo))
1489 return wxEmptyString;
1490 return vInfo.m_text;
1491} // end of wxListCtrl::GetItemText
1492
1493// Sets the item text
1494void wxListCtrl::SetItemText (
1495 long lItem
1496, const wxString& rsStr
1497)
1498{
1499 wxListItem vInfo;
1500
1501 vInfo.m_mask = wxLIST_MASK_TEXT;
1502 vInfo.m_itemId = lItem;
1503 vInfo.m_text = rsStr;
1504 SetItem(vInfo);
1505} // end of wxListCtrl::SetItemText
1506
1507// Gets the item data
1508long wxListCtrl::GetItemData (
1509 long lItem
1510) const
1511{
1512 wxListItem vInfo;
1513
1514 vInfo.m_mask = wxLIST_MASK_DATA;
1515 vInfo.m_itemId = lItem;
1516 if (!GetItem(vInfo))
1517 return 0;
1518 return vInfo.m_data;
1519} // end of wxListCtrl::GetItemData
1520
1521// Sets the item data
9fcd0bf7 1522bool wxListCtrl::SetItemPtrData (
c4f4cf89 1523 long lItem
9fcd0bf7 1524, wxUIntPtr lData
c4f4cf89
DW
1525)
1526{
1527 wxListItem vInfo;
1528
1529 vInfo.m_mask = wxLIST_MASK_DATA;
1530 vInfo.m_itemId = lItem;
1531 vInfo.m_data = lData;
1532 return SetItem(vInfo);
9fcd0bf7 1533} // end of wxListCtrl::SetItemPtrData
c4f4cf89
DW
1534
1535// Gets the item rectangle
fec9cc08
WS
1536bool wxListCtrl::GetItemRect ( long lItem,
1537 wxRect& rRect,
1538 int nCode ) const
c4f4cf89 1539{
fec9cc08
WS
1540 bool bSuccess;
1541 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
1542 QUERYRECORDRECT vQueryRect;
1543 RECTL vRect;
1544 int nHeight;
c4f4cf89
DW
1545
1546 if (!pRecord)
fec9cc08 1547 return false;
c4f4cf89
DW
1548 vQueryRect.cb = sizeof(QUERYRECORDRECT);
1549 vQueryRect.pRecord = &pRecord->m_vRecord;
1550 vQueryRect.fRightSplitWindow = TRUE;
1551 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
1552 ::WinSendMsg( GetHWND()
1553 ,CM_QUERYRECORDRECT
1554 ,MPFROMP(&vRect)
1555 ,MPFROMP(&vQueryRect)
1556 );
1557 //
1558 // remember OS/2 is backwards
1559 //
fec9cc08 1560 GetClientSize( NULL, &nHeight );
c4f4cf89
DW
1561 rRect.x = vRect.xLeft;
1562 rRect.y = nHeight - vRect.yTop;
1563 rRect.width = vRect.xRight;
1564 rRect.height = nHeight - vRect.yBottom;
fec9cc08 1565 bSuccess = true;
c4f4cf89
DW
1566 return bSuccess;
1567} // end of wxListCtrl::GetItemRect
1568
1569// Gets the item position
fec9cc08 1570bool wxListCtrl::GetItemPosition ( long lItem, wxPoint& rPos ) const
c4f4cf89 1571{
fec9cc08
WS
1572 bool bSuccess;
1573 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND() , lItem );
1574 QUERYRECORDRECT vQueryRect;
1575 RECTL vRect;
1576 int nHeight;
c4f4cf89
DW
1577
1578 if (!pRecord)
fec9cc08 1579 return false;
c4f4cf89
DW
1580 vQueryRect.cb = sizeof(QUERYRECORDRECT);
1581 vQueryRect.pRecord = &pRecord->m_vRecord;
1582 vQueryRect.fRightSplitWindow = TRUE;
1583 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
1584 ::WinSendMsg( GetHWND()
1585 ,CM_QUERYRECORDRECT
1586 ,MPFROMP(&vRect)
1587 ,MPFROMP(&vQueryRect)
1588 );
1589 //
1590 // remember OS/2 is backwards
1591 //
fec9cc08 1592 GetClientSize( NULL, &nHeight );
c4f4cf89
DW
1593 rPos.x = vRect.xLeft;
1594 rPos.y = nHeight - vRect.yTop;
fec9cc08 1595 bSuccess = true;
c4f4cf89
DW
1596 return bSuccess;
1597} // end of wxListCtrl::GetItemPosition
1598
1599// Sets the item position.
fec9cc08 1600bool wxListCtrl::SetItemPosition ( long lItem, const wxPoint& rPos )
c4f4cf89
DW
1601{
1602 //
1603 // Items cannot be positioned in X/Y coord in OS/2
1604 //
fec9cc08 1605 return false;
c4f4cf89
DW
1606} // end of wxListCtrl::SetItemPosition
1607
1608// Gets the number of items in the list control
1609int wxListCtrl::GetItemCount () const
1610{
1611 CNRINFO vCnrInfo;
1612
1613 if (!::WinSendMsg( GetHWND()
1614 ,CM_QUERYCNRINFO
1615 ,MPFROMP(&vCnrInfo)
1616 ,(MPARAM)(USHORT)sizeof(CNRINFO)
1617 ))
1618 return -1;
1619 return vCnrInfo.cRecords;
1620} // end of wxListCtrl::GetItemCount
1621
1622// Retrieves the spacing between icons in pixels.
fec9cc08 1623// If bIsSmall is true, gets the spacing for the small icon
c4f4cf89 1624// view, otherwise the large icon view.
fec9cc08 1625int wxListCtrl::GetItemSpacing ( bool bIsSmall ) const
c4f4cf89
DW
1626{
1627 CNRINFO vCnrInfo;
1628
1629 if (!::WinSendMsg( GetHWND()
1630 ,CM_QUERYCNRINFO
1631 ,MPFROMP(&vCnrInfo)
1632 ,(MPARAM)(USHORT)sizeof(CNRINFO)
1633 ))
1634 return -1;
1635 return vCnrInfo.cyLineSpacing;
1636} // end of wxListCtrl::GetItemSpacing
1637
1638void wxListCtrl::SetItemTextColour (
1639 long lItem
1640, const wxColour& rCol
1641)
1642{
1643 wxListItem vInfo;
1644
1645 vInfo.m_itemId = lItem;
1646 vInfo.SetTextColour(rCol);
1647 SetItem(vInfo);
1648} // end of wxListCtrl::SetItemTextColour
1649
1650wxColour wxListCtrl::GetItemTextColour (
1651 long lItem
1652) const
1653{
1654 wxListItem vInfo;
1655
1656 vInfo.m_itemId = lItem;
1657 GetItem(vInfo);
1658 return vInfo.GetTextColour();
1659} // end of wxListCtrl::GetItemTextColour
1660
1661void wxListCtrl::SetItemBackgroundColour (
1662 long lItem
1663, const wxColour& rCol
1664)
1665{
1666 wxListItem vInfo;
1667
1668 vInfo.m_itemId = lItem;
1669 vInfo.SetBackgroundColour(rCol);
1670 SetItem(vInfo);
1671} // end of wxListCtrl::SetItemBackgroundColour
1672
1673wxColour wxListCtrl::GetItemBackgroundColour (
1674 long lItem
1675) const
1676{
1677 wxListItem vInfo;
1678
1679 vInfo.m_itemId = lItem;
1680 GetItem(vInfo);
1681 return vInfo.GetBackgroundColour();
1682} // end of wxListCtrl::GetItemBackgroundColour
1683
1684// Gets the number of selected items in the list control
1685int wxListCtrl::GetSelectedItemCount () const
1686{
1687 PMYRECORD pRecord = NULL;
1688 int nCount = 0;
1689 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1690 ,CM_QUERYRECORDEMPHASIS
1691 ,(MPARAM)CMA_FIRST
1692 ,(MPARAM)CRA_SELECTED
1693 ));
1694 if (pRecord)
1695 nCount++;
1696 else
1697 return 0;
1698 while (pRecord)
1699 {
1700 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1701 ,CM_QUERYRECORDEMPHASIS
1702 ,MPFROMP(pRecord)
1703 ,(MPARAM)CRA_SELECTED
1704 ));
1705 if (pRecord)
1706 nCount++;
1707 }
1708 return nCount;
1709} // end of wxListCtrl::GetSelectedItemCount
1710
1711// Gets the text colour of the listview
1712wxColour wxListCtrl::GetTextColour () const
1713{
1714 wxColour vCol;
1715 ULONG ulColor;
1716
1717 ::WinQueryPresParam( GetHWND()
1718 ,PP_FOREGROUNDCOLOR
1719 ,0
1720 ,NULL
1721 ,sizeof(ULONG)
1722 ,&ulColor
1723 ,QPF_PURERGBCOLOR
1724 );
1725 vCol.Set(ulColor);
1726 return vCol;
1727} // end of wxListCtrl::GetTextColour
1728
1729// Sets the text colour of the listview
1730void wxListCtrl::SetTextColour (
1731 const wxColour& rCol
1732)
1733{
1734 ULONG ulColor = wxColourToRGB(rCol);
1735
1736 ::WinSetPresParam( GetHWND()
1737 ,PP_FOREGROUNDCOLOR
1738 ,sizeof(ULONG)
1739 ,&ulColor
1740 );
1741} // end of wxListCtrl::SetTextColour
1742
1743// Gets the index of the topmost visible item when in
1744// list or report view
1745long wxListCtrl::GetTopItem () const
1746{
1747 PMYRECORD pRecord = NULL;
1748 QUERYRECFROMRECT vQueryRect;
1749 RECTL vRect;
1750
1751 ::WinSendMsg( GetHWND()
1752 ,CM_QUERYVIEWPORTRECT
1753 ,MPFROMP(&vRect)
1754 ,MPFROM2SHORT(CMA_WINDOW, TRUE)
1755 );
1756 vQueryRect.cb = sizeof(QUERYRECFROMRECT);
1757 vQueryRect.rect = vRect;
1758 vQueryRect.fsSearch = CMA_PARTIAL;
1759
1760 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
1761 ,CM_QUERYRECORDFROMRECT
1762 ,(MPARAM)CMA_FIRST
1763 ,MPFROMP(&vQueryRect)
1764 );
1765
1766 if (!pRecord)
1767 return -1L;
1768 return (long)pRecord->m_ulItemId;
1769} // end of wxListCtrl::GetTopItem
1770
1771// Searches for an item, starting from 'item'.
1772// 'geometry' is one of
1773// wxLIST_NEXT_ABOVE/ALL/BELOW/LEFT/RIGHT.
1774// 'state' is a state bit flag, one or more of
1775// wxLIST_STATE_DROPHILITED/FOCUSED/SELECTED/CUT.
1776// item can be -1 to find the first item that matches the
1777// specified flags.
1778// Returns the item or -1 if unsuccessful.
1779long wxListCtrl::GetNextItem (
1780 long lItem
1781, int WXUNUSED(nGeom)
1782, int WXUNUSED(nState)
1783) const
1784{
1785 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1786 ,lItem
1787 );
1788
1789 pRecord = (PMYRECORD)pRecord->m_vRecord.preccNextRecord;
1790 if (pRecord)
1791 return((long)pRecord->m_ulItemId);
1792 return -1L;
1793} // end of wxListCtrl::GetNextItem
1794
1795wxImageList* wxListCtrl::GetImageList (
1796 int nWhich
1797) const
1798{
1799 if (nWhich == wxIMAGE_LIST_NORMAL )
1800 {
1801 return m_pImageListNormal;
1802 }
1803 else if (nWhich == wxIMAGE_LIST_SMALL )
1804 {
1805 return m_pImageListSmall;
1806 }
1807 else if (nWhich == wxIMAGE_LIST_STATE )
1808 {
1809 return m_pImageListState;
1810 }
1811 return NULL;
1812} // end of wxListCtrl::GetImageList
1813
fec9cc08
WS
1814void wxListCtrl::SetImageList ( wxImageList* pImageList,
1815 int nWhich )
c4f4cf89
DW
1816{
1817 if (nWhich == wxIMAGE_LIST_NORMAL)
1818 {
1819 if (m_bOwnsImageListNormal)
1820 delete m_pImageListNormal;
1821 m_pImageListNormal = pImageList;
fec9cc08 1822 m_bOwnsImageListNormal = false;
c4f4cf89
DW
1823 }
1824 else if (nWhich == wxIMAGE_LIST_SMALL)
1825 {
1826 if (m_bOwnsImageListSmall)
1827 delete m_pImageListSmall;
1828 m_pImageListSmall = pImageList;
fec9cc08 1829 m_bOwnsImageListSmall = false;
c4f4cf89
DW
1830 }
1831 else if (nWhich == wxIMAGE_LIST_STATE)
1832 {
1833 if (m_bOwnsImageListState)
1834 delete m_pImageListState;
1835 m_pImageListState = pImageList;
fec9cc08 1836 m_bOwnsImageListState = false;
c4f4cf89
DW
1837 }
1838} // end of wxListCtrl::SetImageList
1839
fec9cc08 1840void wxListCtrl::AssignImageList ( wxImageList* pImageList, int nWhich )
c4f4cf89 1841{
fec9cc08
WS
1842 SetImageList( pImageList, nWhich );
1843
c4f4cf89 1844 if (nWhich == wxIMAGE_LIST_NORMAL )
fec9cc08 1845 m_bOwnsImageListNormal = true;
c4f4cf89 1846 else if (nWhich == wxIMAGE_LIST_SMALL )
fec9cc08 1847 m_bOwnsImageListSmall = true;
c4f4cf89 1848 else if (nWhich == wxIMAGE_LIST_STATE )
fec9cc08 1849 m_bOwnsImageListState = true;
c4f4cf89
DW
1850} // end of wxListCtrl::AssignImageList
1851
1852// ----------------------------------------------------------------------------
1853// Operations
1854// ----------------------------------------------------------------------------
1855
1856// Arranges the items
fec9cc08 1857bool wxListCtrl::Arrange ( int nFlag )
c4f4cf89 1858{
fec9cc08
WS
1859 ULONG ulType = 0L;
1860 ULONG ulFlags = 0L;
c4f4cf89
DW
1861
1862 if (nFlag == wxLIST_ALIGN_SNAP_TO_GRID)
1863 {
1864 ulType = CMA_ARRANGEGRID;
1865 if (nFlag == wxLIST_ALIGN_LEFT)
1866 ulFlags |= CMA_LEFT;
1867 else if (nFlag == wxLIST_ALIGN_TOP)
1868 ulFlags |= CMA_TOP;
1869 else if (nFlag == wxLIST_ALIGN_DEFAULT)
1870 ulFlags |= CMA_LEFT;
1871 }
1872 else
1873 ulType = CMA_ARRANGESTANDARD;
1874 ::WinSendMsg( GetHWND()
1875 ,CM_ARRANGE
1876 ,(MPARAM)ulType
1877 ,(MPARAM)ulFlags
1878 );
1879 //
1880 // We do not support CMA_ARRANGESELECTED
1881 //
fec9cc08 1882 return true;
c4f4cf89
DW
1883} // end of wxListCtrl::Arrange
1884
1885// Deletes an item
fec9cc08 1886bool wxListCtrl::DeleteItem ( long lItem )
c4f4cf89 1887{
fec9cc08 1888 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
c4f4cf89
DW
1889 if (LONGFROMMR(::WinSendMsg( GetHWND()
1890 ,CM_REMOVERECORD
1891 ,(MPARAM)pRecord
1892 ,MPFROM2SHORT(1, CMA_FREE)
1893 )) == -1L)
1894 {
fec9cc08 1895 return false;
c4f4cf89
DW
1896 }
1897
1898 //
1899 // The virtual list control doesn't refresh itself correctly, help it
1900 //
1901 if (IsVirtual())
1902 {
1903 //
1904 // We need to refresh all the lines below the one which was deleted
1905 //
1906 wxRect vRectItem;
1907
1908 if (lItem > 0 && GetItemCount())
1909 {
1910 GetItemRect( lItem - 1
1911 ,vRectItem
1912 );
1913 }
1914 else
1915 {
1916 vRectItem.y = vRectItem.height = 0;
1917 }
1918 wxRect vRectWin = GetRect();
1919
1920 vRectWin.height = vRectWin.GetBottom() - vRectItem.GetBottom();
1921 vRectWin.y = vRectItem.GetBottom();
1922 RefreshRect(vRectWin);
1923 }
fec9cc08 1924 return true;
c4f4cf89
DW
1925} // end of wxListCtrl::DeleteItem
1926
1927// Deletes all items
1928bool wxListCtrl::DeleteAllItems ()
1929{
1930 return((LONG)::WinSendMsg( GetHWND()
1931 ,CM_REMOVERECORD
1932 ,NULL
1933 ,MPFROM2SHORT(0, CMA_FREE)
1934 ) != -1L);
1935} // end of wxListCtrl::DeleteAllItems
1936
1937// Deletes all items
1938bool wxListCtrl::DeleteAllColumns ()
1939{
1940 while (m_nColCount > 0)
1941 {
1942 DeleteColumn(m_nColCount - 1);
1943 m_nColCount--;
1944 }
1945
1946 wxASSERT_MSG(m_nColCount == 0, wxT("no columns should be left"));
fec9cc08 1947 return true;
c4f4cf89
DW
1948} // end of wxListCtrl::DeleteAllColumns
1949
1950// Deletes a column
fec9cc08 1951bool wxListCtrl::DeleteColumn ( int nCol )
c4f4cf89 1952{
fec9cc08
WS
1953 bool bSuccess = false;
1954 PFIELDINFO pField = FindOS2ListFieldByColNum( GetHWND(), nCol );
c4f4cf89
DW
1955 bSuccess = ((LONG)::WinSendMsg( GetHWND()
1956 ,CM_REMOVEDETAILFIELDINFO
1957 ,MPFROMP(pField)
1958 ,MPFROM2SHORT((SHORT)1, CMA_FREE)
1959 ) == -1L);
1960 if (bSuccess && (m_nColCount > 0))
1961 m_nColCount--;
1962 return bSuccess;
1963} // end of wxListCtrl::DeleteColumn
1964
1965// Clears items, and columns if there are any.
1966void wxListCtrl::ClearAll ()
1967{
1968 DeleteAllItems();
1969 if (m_nColCount > 0)
1970 DeleteAllColumns();
1971} // end of wxListCtrl::ClearAll
1972
1973//
1974// OS/2 does not use a text control for its container labels. You merely
1975// "open" a record for editting.
1976//
1977wxTextCtrl* wxListCtrl::EditLabel (
1978 long lItem
1979, wxClassInfo* WXUNUSED(pTextControlClass)
1980)
1981{
1982 CNREDITDATA vEdit;
1983 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1984 ,lItem
1985 );
1986
1987 vEdit.cb = sizeof(CNREDITDATA);
1988 vEdit.hwndCnr = GetHWND();
1989 vEdit.pRecord = &pRecord->m_vRecord;
1990 vEdit.pFieldInfo = NULL;
1991 vEdit.ppszText = NULL;
1992 vEdit.cbText = 0;
1993 vEdit.id = 0;
1994
1995 ::WinSendMsg( GetHWND()
1996 ,CM_OPENEDIT
1997 ,MPFROMP(&vEdit)
1998 ,(MPARAM)0
1999 );
2000 return m_pTextCtrl;
2001} // end of wxListCtrl::EditLabel
2002
2003// End label editing, optionally cancelling the edit. Under OS/2 you close
2004// the record for editting
fec9cc08 2005bool wxListCtrl::EndEditLabel ( bool WXUNUSED(bCancel) )
c4f4cf89
DW
2006{
2007 ::WinSendMsg( GetHWND()
2008 ,CM_CLOSEEDIT
2009 ,(MPARAM)0
2010 ,(MPARAM)0
2011 );
fec9cc08 2012 return true;
c4f4cf89
DW
2013} // end of wxListCtrl::EndEditLabel
2014
2015// Ensures this item is visible
fec9cc08 2016bool wxListCtrl::EnsureVisible ( long lItem )
c4f4cf89 2017{
fec9cc08 2018 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
c4f4cf89
DW
2019 ::WinSendMsg( GetHWND()
2020 ,CM_INVALIDATERECORD
2021 ,MPFROMP(pRecord)
2022 ,MPFROM2SHORT((SHORT)1, CMA_NOREPOSITION)
2023 );
fec9cc08 2024 return true;
c4f4cf89
DW
2025} // end of wxListCtrl::EnsureVisible
2026
2027// Find an item whose label matches this string, starting from the item after 'start'
2028// or the beginning if 'start' is -1.
2029long wxListCtrl::FindItem (
2030 long lStart
2031, const wxString& rsStr
2032, bool bPartial
2033)
2034{
2035 CNRINFO vCnrInfo;
2036 SEARCHSTRING vSearch;
2037 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
2038 ,lStart
2039 );
2040 ULONG ulFlag;
2041
2042
2043 if (!::WinSendMsg( GetHWND()
2044 ,CM_QUERYCNRINFO
2045 ,MPFROMP(&vCnrInfo)
2046 ,(MPARAM)(USHORT)sizeof(CNRINFO)
2047 ))
2048 return -1L;
2049
2050 if (vCnrInfo.flWindowAttr & CV_ICON)
2051 ulFlag = CV_ICON;
2052 if (vCnrInfo.flWindowAttr & CV_NAME)
2053 ulFlag = CV_NAME;
2054 if (vCnrInfo.flWindowAttr & CV_TEXT)
2055 ulFlag = CV_TEXT;
2056 if (vCnrInfo.flWindowAttr & CV_DETAIL)
2057 ulFlag = CV_DETAIL;
2058 if (!bPartial)
2059 ulFlag |= CV_EXACTLENGTH;
2060
2061 vSearch.cb = sizeof(SEARCHSTRING);
2062 vSearch.pszSearch = (char*)rsStr.c_str();
2063 vSearch.fsPrefix = TRUE;
2064 vSearch.fsCaseSensitive = TRUE;
2065 vSearch.usView = ulFlag;
2066
2067 if (lStart == -1)
2068 {
2069 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2070 ,CM_SEARCHSTRING
2071 ,MPFROMP(&vSearch)
2072 ,(MPARAM)CMA_FIRST
2073 );
2074 }
2075 else
2076 {
2077 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2078 ,CM_SEARCHSTRING
2079 ,MPFROMP(&vSearch)
2080 ,MPFROMP(pRecord)
2081 );
2082 }
2083 if (!pRecord)
2084 return -1L;
2085 return pRecord->m_ulItemId;
2086} // end of wxListCtrl::FindItem
2087
2088// Find an item whose data matches this data, starting from the item after 'start'
2089// or the beginning if 'start' is -1.
2090long wxListCtrl::FindItem (
2091 long lStart
2092, long lData
2093)
2094{
2095 long lIdx = lStart + 1;
2096 long lCount = GetItemCount();
2097
2098 while (lIdx < lCount)
2099 {
2100 if (GetItemData(lIdx) == lData)
2101 return lIdx;
2102 lIdx++;
2103 };
2104 return -1;
2105} // end of wxListCtrl::FindItem
2106
2107// Find an item nearest this position in the specified direction, starting from
2108// the item after 'start' or the beginning if 'start' is -1.
2109long wxListCtrl::FindItem (
2110 long lStart
2111, const wxPoint& rPoint
2112, int nDirection
2113)
2114{
2115 RECTL vRect;
2116 QUERYRECORDRECT vQueryRect;
2117 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
2118 ,lStart
2119 );
2120 CNRINFO vCnrInfo;
2121 ULONG i;
2122 wxRect vLibRect;
2123
2124 if (!::WinSendMsg( GetHWND()
2125 ,CM_QUERYCNRINFO
2126 ,MPFROMP(&vCnrInfo)
2127 ,(MPARAM)(USHORT)sizeof(CNRINFO)
2128 ))
2129 return -1L;
2130
2131 vQueryRect.cb = sizeof(QUERYRECORDRECT);
2132 vQueryRect.pRecord = &pRecord->m_vRecord;
2133 vQueryRect.fRightSplitWindow = TRUE;
2134 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
2135
2136 ::WinSendMsg( GetHWND()
2137 ,CM_QUERYRECORDRECT
2138 ,MPFROMP(&vRect)
2139 ,MPFROMP(&vQueryRect)
2140 );
2141 vLibRect.SetLeft(vRect.xLeft);
2142 vLibRect.SetTop(vRect.yTop);
2143 vLibRect.SetRight(vRect.xRight);
2144 vLibRect.SetBottom(vRect.yBottom);
22a35096 2145 if (vLibRect.Contains(rPoint))
c4f4cf89
DW
2146 return pRecord->m_ulItemId;
2147
2148 for (i = lStart + 1; i < vCnrInfo.cRecords; i++)
2149 {
2150 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
2151 ,CM_QUERYRECORD
2152 ,MPFROMP(pRecord)
2153 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
2154 ));
2155 vQueryRect.pRecord = (PRECORDCORE)pRecord;
2156 ::WinSendMsg( GetHWND()
2157 ,CM_QUERYRECORDRECT
2158 ,MPFROMP(&vRect)
2159 ,MPFROMP(&vQueryRect)
2160 );
2161 vLibRect.SetLeft(vRect.xLeft);
2162 vLibRect.SetTop(vRect.yTop);
2163 vLibRect.SetRight(vRect.xRight);
2164 vLibRect.SetBottom(vRect.yBottom);
22a35096 2165 if (vLibRect.Contains(rPoint))
c4f4cf89
DW
2166 return pRecord->m_ulItemId;
2167 }
2168 return -1L;
2169} // end of wxListCtrl::FindItem
2170
2171// Determines which item (if any) is at the specified point,
2172// giving details in 'flags' (see wxLIST_HITTEST_... flags above)
2173long wxListCtrl::HitTest (
2174 const wxPoint& rPoint
2175, int& WXUNUSED(rFlags)
2176)
2177{
2178 PMYRECORD pRecord = NULL;
2179 QUERYRECFROMRECT vQueryRect;
2180 RECTL vRect;
2181 long lHeight;
2182
2183 //
2184 // Get height for OS/2 point conversion
2185 //
2186 ::WinSendMsg( GetHWND()
2187 ,CM_QUERYVIEWPORTRECT
2188 ,MPFROMP(&vRect)
2189 ,MPFROM2SHORT(CMA_WINDOW, TRUE)
2190 );
2191 lHeight = vRect.yTop - vRect.yBottom;
2192
2193 //
2194 // For now just try and get a record in the general vicinity and forget
2195 // the flag
2196 //
2197 vRect.xLeft = rPoint.x - 2;
2198 vRect.xRight = rPoint.x + 2;
2199 vRect.yTop = (lHeight - rPoint.y) + 2;
2200 vRect.yBottom = (lHeight - rPoint.y) - 2;
2201
2202 vQueryRect.cb = sizeof(QUERYRECFROMRECT);
2203 vQueryRect.rect = vRect;
2204 vQueryRect.fsSearch = CMA_PARTIAL;
2205
2206 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2207 ,CM_QUERYRECORDFROMRECT
2208 ,(MPARAM)CMA_FIRST
2209 ,MPFROMP(&vQueryRect)
2210 );
2211
2212 if (!pRecord)
2213 return -1L;
2214 return pRecord->m_ulItemId;
2215} // end of wxListCtrl::HitTest
2216
2217// Inserts an item, returning the index of the new item if successful,
2218// -1 otherwise.
2219long wxListCtrl::InsertItem (
2220 wxListItem& rInfo
2221)
2222{
9a83f860 2223 wxASSERT_MSG( !IsVirtual(), wxT("can't be used with virtual controls") );
c4f4cf89 2224
378ad957
DW
2225 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND()
2226 ,rInfo.GetColumn()
2227 );
2228 PMYRECORD pRecordAfter = NULL;
c4f4cf89
DW
2229 PMYRECORD pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2230 ,CM_ALLOCRECORD
2231 ,MPFROMLONG(sizeof(MYRECORD) - sizeof(RECORDCORE))
378ad957 2232 ,MPFROMSHORT(1)
c4f4cf89 2233 );
378ad957
DW
2234
2235 ConvertToOS2ListItem( this
2236 ,rInfo
2237 ,pRecord
2238 ,pFieldInfo
2239 );
2240
2241 if (rInfo.GetId() > 0)
2242 pRecordAfter = FindOS2ListRecordByID( GetHWND()
2243 ,rInfo.GetId() - 1
2244 );
2245
c4f4cf89
DW
2246 RECORDINSERT vInsert;
2247
2248 vInsert.cb = sizeof(RECORDINSERT);
c4f4cf89 2249 vInsert.pRecordParent = NULL;
378ad957
DW
2250 if (!pRecordAfter)
2251 vInsert.pRecordOrder = (PRECORDCORE)CMA_FIRST;
2252 else
2253 vInsert.pRecordOrder = (PRECORDCORE)pRecordAfter;
c4f4cf89
DW
2254 vInsert.zOrder = CMA_TOP;
2255 vInsert.cRecordsInsert = 1;
378ad957 2256 vInsert.fInvalidateRecord = TRUE;
c4f4cf89
DW
2257
2258 //
2259 // Check wether we need to allocate our internal data
2260 //
2261 bool bNeedInternalData = ((rInfo.GetMask() & wxLIST_MASK_DATA) ||
2262 rInfo.HasAttributes()
2263 );
2264 if (bNeedInternalData)
2265 {
fec9cc08 2266 m_bAnyInternalData = true;
c4f4cf89
DW
2267
2268 //
2269 // Internal stucture that manages data
2270 //
2271 CListItemInternalData* pData = new CListItemInternalData();
2272
2273 pRecord->m_ulUserData = (unsigned long)pData;
2274 if (rInfo.GetMask() & wxLIST_MASK_DATA)
2275 pData->m_lParam = (WXLPARAM)rInfo.GetData();
2276
2277 //
2278 // Check whether it has any custom attributes
2279 //
2280 if (rInfo.HasAttributes())
2281 {
2282 //
2283 // Take copy of attributes
2284 //
2285 pData->m_pAttr = new wxListItemAttr(*rInfo.GetAttributes());
2286 }
2287 }
378ad957
DW
2288 if (!::WinSendMsg( GetHWND()
2289 ,CM_INSERTRECORD
2290 ,MPFROMP(pRecord)
2291 ,MPFROMP(&vInsert)
2292 ))
2293 return -1;
c4f4cf89
DW
2294 //
2295 // OS/2 must mannually bump the index's of following records
2296 //
2297 BumpRecordIds( GetHWND()
2298 ,pRecord
2299 );
378ad957
DW
2300 ::WinSendMsg( GetHWND()
2301 ,CM_INVALIDATEDETAILFIELDINFO
2302 ,NULL
2303 ,NULL
2304 );
c4f4cf89
DW
2305 return pRecord->m_ulItemId;
2306} // end of wxListCtrl::InsertItem
2307
2308long wxListCtrl::InsertItem (
2309 long lIndex
2310, const wxString& rsLabel
2311)
2312{
2313 wxListItem vInfo;
2314
378ad957 2315 memset(&vInfo, '\0', sizeof(wxListItem));
c4f4cf89
DW
2316 vInfo.m_text = rsLabel;
2317 vInfo.m_mask = wxLIST_MASK_TEXT;
2318 vInfo.m_itemId = lIndex;
2319 return InsertItem(vInfo);
2320} // end of wxListCtrl::InsertItem
2321
2322// Inserts an image item
2323long wxListCtrl::InsertItem (
2324 long lIndex
2325, int nImageIndex
2326)
2327{
2328 wxListItem vInfo;
2329
2330 vInfo.m_image = nImageIndex;
2331 vInfo.m_mask = wxLIST_MASK_IMAGE;
2332 vInfo.m_itemId = lIndex;
2333 return InsertItem(vInfo);
2334} // end of wxListCtrl::InsertItem
2335
2336// Inserts an image/string item
2337long wxListCtrl::InsertItem (
2338 long lIndex
2339, const wxString& rsLabel
2340, int nImageIndex
2341)
2342{
2343 wxListItem vInfo;
2344
2345 vInfo.m_image = nImageIndex;
2346 vInfo.m_text = rsLabel;
2347 vInfo.m_mask = wxLIST_MASK_IMAGE | wxLIST_MASK_TEXT;
2348 vInfo.m_itemId = lIndex;
2349 return InsertItem(vInfo);
2350} // end of wxListCtrl::InsertItem
2351
2352// For details view mode (only), inserts a column.
2353long wxListCtrl::InsertColumn (
2354 long lCol
2355, wxListItem& rItem
2356)
2357{
2358 bool bSuccess;
2359 PFIELDINFO pField = (PFIELDINFO)::WinSendMsg( GetHWND()
2360 ,CM_ALLOCDETAILFIELDINFO
2361 ,MPFROMLONG(1)
2362 ,NULL
2363 );
2364 PFIELDINFO pFieldAfter = FindOS2ListFieldByColNum ( GetHWND()
2365 ,lCol - 1
2366 );
2367 FIELDINFOINSERT vInsert;
2368
378ad957
DW
2369 ConvertToOS2ListCol ( lCol
2370 ,rItem
2371 ,pField
2372 );
2373
c4f4cf89
DW
2374 vInsert.cb = sizeof(FIELDINFOINSERT);
2375 vInsert.pFieldInfoOrder = pFieldAfter;
2376 vInsert.fInvalidateFieldInfo = TRUE;
2377 vInsert.cFieldInfoInsert = 1;
2378
c4f4cf89
DW
2379 bSuccess = ::WinSendMsg( GetHWND()
2380 ,CM_INSERTDETAILFIELDINFO
2381 ,MPFROMP(pField)
2382 ,MPFROMP(&vInsert)
2383 ) != (MRESULT)0;
2384 return bSuccess;
2385} // end of wxListCtrl::InsertColumn
2386
2387long wxListCtrl::InsertColumn (
2388 long lCol
2389, const wxString& rsHeading
2390, int nFormat
2391, int nWidth
2392)
2393{
2394 wxListItem vItem;
2395
2396 vItem.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
2397 vItem.m_text = rsHeading;
2398 if (nWidth > -1)
2399 {
2400 vItem.m_mask |= wxLIST_MASK_WIDTH;
2401 vItem.m_width = nWidth;
2402 }
2403 vItem.m_format = nFormat;
2404
2405 return InsertColumn( lCol
2406 ,vItem
2407 );
2408} // end of wxListCtrl::InsertColumn
2409
2410// scroll the control by the given number of pixels (exception: in list view,
2411// dx is interpreted as number of columns)
fec9cc08 2412bool wxListCtrl::ScrollList ( int nDx, int nDy )
c4f4cf89
DW
2413{
2414 if (nDx > 0)
2415 ::WinSendMsg( GetHWND()
2416 ,CM_SCROLLWINDOW
2417 ,(MPARAM)CMA_HORIZONTAL
2418 ,(MPARAM)nDx
2419 );
2420 if (nDy > 0)
2421 ::WinSendMsg( GetHWND()
2422 ,CM_SCROLLWINDOW
2423 ,(MPARAM)CMA_VERTICAL
2424 ,(MPARAM)nDy
2425 );
fec9cc08 2426 return true;
c4f4cf89
DW
2427} // end of wxListCtrl::ScrollList
2428
fec9cc08 2429bool wxListCtrl::SortItems ( wxListCtrlCompare fn, long lData )
c4f4cf89 2430{
fec9cc08 2431 SInternalDataSort vInternalData;
c4f4cf89
DW
2432
2433 vInternalData.m_fnUser = fn;
2434 vInternalData.m_lData = lData;
2435
2436 // WPARAM cast is needed for mingw/cygwin
2437 if (!::WinSendMsg( GetHWND()
2438 ,CM_SORTRECORD
2439 ,(PFN)InternalDataCompareFunc
2440 ,(PVOID)&vInternalData
2441 ))
2442 {
9a83f860 2443 wxLogDebug(wxT("CM_SORTRECORD failed"));
fec9cc08 2444 return false;
c4f4cf89 2445 }
fec9cc08 2446 return true;
c4f4cf89
DW
2447} // end of wxListCtrl::SortItems
2448
2449// ----------------------------------------------------------------------------
2450// message processing
2451// ----------------------------------------------------------------------------
2452
fec9cc08 2453bool wxListCtrl::OS2Command ( WXUINT uCmd, WXWORD wId )
c4f4cf89
DW
2454{
2455 if (uCmd == CN_ENDEDIT)
2456 {
fec9cc08 2457 wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED, wId );
c4f4cf89
DW
2458
2459 vEvent.SetEventObject( this );
2460 ProcessCommand(vEvent);
fec9cc08 2461 return true;
c4f4cf89
DW
2462 }
2463 else if (uCmd == CN_KILLFOCUS)
2464 {
fec9cc08 2465 wxCommandEvent vEvent( wxEVT_KILL_FOCUS, wId );
c4f4cf89
DW
2466 vEvent.SetEventObject( this );
2467 ProcessCommand(vEvent);
fec9cc08 2468 return true;
c4f4cf89
DW
2469 }
2470 else
fec9cc08 2471 return false;
c4f4cf89
DW
2472} // end of wxListCtrl::OS2Command
2473
2474// Necessary for drawing hrules and vrules, if specified
fec9cc08 2475void wxListCtrl::OnPaint ( wxPaintEvent& rEvent )
c4f4cf89
DW
2476{
2477 wxPaintDC vDc(this);
2478 wxPen vPen(wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT)
2479 ,1
2480 ,wxSOLID
2481 );
2482 wxSize vClientSize = GetClientSize();
2483 wxRect vItemRect;
2484 int nItemCount = GetItemCount();
2485 int nCy = 0;
2486 int i;
2487 bool bDrawHRules = ((GetWindowStyle() & wxLC_HRULES) != 0);
2488 bool bDrawVRules = ((GetWindowStyle() & wxLC_VRULES) != 0);
2489
2490 wxControl::OnPaint(rEvent);
2491
2492 //
2493 // Reset the device origin since it may have been set
2494 //
2495 vDc.SetDeviceOrigin(0, 0);
2496 if (!bDrawHRules && !bDrawVRules)
2497 return;
2498 if ((GetWindowStyle() & wxLC_REPORT) == 0)
2499 return;
2500 vDc.SetPen(vPen);
2501 vDc.SetBrush(*wxTRANSPARENT_BRUSH);
2502
2503 if (bDrawHRules)
2504 {
2505 long lTop = GetTopItem();
2506
2507 for (i = lTop; i < lTop + GetCountPerPage() + 1; i++)
2508 {
2509 if (GetItemRect( i
2510 ,vItemRect
2511 ))
2512 {
2513 nCy = vItemRect.GetTop();
2514 if (i != 0) // Don't draw the first one
2515 {
2516 vDc.DrawLine( 0
2517 ,nCy
2518 ,vClientSize.x
2519 ,nCy
2520 );
2521 }
2522 // Draw last line
2523 if (i == nItemCount - 1)
2524 {
2525 nCy = vItemRect.GetBottom();
2526 vDc.DrawLine( 0
2527 ,nCy
2528 ,vClientSize.x
2529 ,nCy
2530 );
2531 }
2532 }
2533 }
2534 }
2535 i = nItemCount - 1;
2536 if (bDrawVRules && (i > -1))
2537 {
2538 wxRect vFirstItemRect;
2539
2540 GetItemRect( 0
2541 ,vFirstItemRect
2542 );
2543 if (GetItemRect( i
2544 ,vItemRect
2545 ))
2546 {
2547 int nCol;
2548 int nX = vItemRect.GetX();
2549
2550 for (nCol = 0; nCol < GetColumnCount(); nCol++)
2551 {
2552 int nColWidth = GetColumnWidth(nCol);
2553
2554 nX += nColWidth ;
2555 vDc.DrawLine( nX - 1
2556 ,vFirstItemRect.GetY() - 2
2557 ,nX - 1
2558 ,vItemRect.GetBottom()
2559 );
2560 }
2561 }
2562 }
2563} // end of wxListCtrl::OnPaint
2564
2565// ----------------------------------------------------------------------------
2566// virtual list controls
2567// ----------------------------------------------------------------------------
2568
2569wxString wxListCtrl::OnGetItemText (
2570 long WXUNUSED(lItem)
2571, long WXUNUSED(lCol)
2572) const
2573{
2574 // this is a pure virtual function, in fact - which is not really pure
2575 // because the controls which are not virtual don't need to implement it
9a83f860 2576 wxFAIL_MSG( wxT("not supposed to be called") );
c4f4cf89
DW
2577 return wxEmptyString;
2578} // end of wxListCtrl::OnGetItemText
2579
2580int wxListCtrl::OnGetItemImage (
2581 long WXUNUSED(lItem)
2582) const
2583{
2584 // same as above
9a83f860 2585 wxFAIL_MSG( wxT("not supposed to be called") );
c4f4cf89
DW
2586 return -1;
2587} // end of wxListCtrl::OnGetItemImage
2588
208458a7
RD
2589int wxListCtrl::OnGetItemColumnImage (
2590 long lItem,
2591 long lColumn
2592) const
2593{
2594 if (!lColumn)
2595 return OnGetItemImage(lItem);
2596
2597 return -1;
2598} // end of wxListCtrl::OnGetItemColumnImage
2599
c4f4cf89
DW
2600wxListItemAttr* wxListCtrl::OnGetItemAttr (
2601 long WXUNUSED_UNLESS_DEBUG(lItem)
2602) const
2603{
2604 wxASSERT_MSG( lItem >= 0 && lItem < GetItemCount(),
9a83f860 2605 wxT("invalid item index in OnGetItemAttr()") );
c4f4cf89
DW
2606
2607 //
2608 // No attributes by default
2609 //
2610 return NULL;
2611} // end of wxListCtrl::OnGetItemAttr
2612
2613void wxListCtrl::SetItemCount (
2614 long lCount
2615)
2616{
9a83f860 2617 wxASSERT_MSG( IsVirtual(), wxT("this is for virtual controls only") );
c4f4cf89
DW
2618
2619 //
2620 // Cannot explicitly set the record count in OS/2
2621 //
2622} // end of wxListCtrl::SetItemCount
2623
2624void wxListCtrl::RefreshItem (
2625 long lItem
2626)
2627{
2628 wxRect vRect;
2629
2630 GetItemRect( lItem
2631 ,vRect
2632 );
2633 RefreshRect(vRect);
2634} // end of wxListCtrl::RefreshItem
2635
fec9cc08 2636void wxListCtrl::RefreshItems ( long lItemFrom, long lItemTo )
c4f4cf89 2637{
fec9cc08
WS
2638 wxRect vRect1;
2639 wxRect vRect2;
c4f4cf89 2640
fec9cc08
WS
2641 GetItemRect( lItemFrom , vRect1 );
2642 GetItemRect( lItemTo , vRect2 );
c4f4cf89 2643
fec9cc08 2644 wxRect vRect = vRect1;
c4f4cf89
DW
2645
2646 vRect.height = vRect2.GetBottom() - vRect1.GetTop();
2647 RefreshRect(vRect);
2648} // end of wxListCtrl::RefreshItems
2649
fec9cc08
WS
2650MRESULT wxListCtrl::OS2WindowProc( WXUINT uMsg,
2651 WXWPARAM wParam,
2652 WXLPARAM lParam )
c4f4cf89 2653{
fec9cc08 2654 bool bProcessed = false;
c4f4cf89
DW
2655 MRESULT lRc;
2656 wxListEvent vEvent( wxEVT_NULL
2657 ,m_windowId
2658 );
2659 wxEventType vEventType = wxEVT_NULL;
2660 PCNRDRAGINIT pDragInit = NULL;
2661 PCNREDITDATA pEditData = NULL;
2662 PNOTIFYRECORDENTER pNotifyEnter = NULL;
2663
2664 vEvent.SetEventObject(this);
2665 switch (uMsg)
2666 {
2667 case WM_CONTROL:
2668 //
2669 // First off let's set some internal data
2670 //
2671 switch(SHORT2FROMMP(wParam))
2672 {
2673 case CN_INITDRAG:
2674 case CN_DRAGOVER:
2675 case CN_DRAGAFTER:
2676 {
2677 CListItemInternalData* pInternaldata = (CListItemInternalData *)lParam;
2678
2679 if (pInternaldata)
2680 {
2681 wxListItem* pItem = (wxListItem*)&vEvent.GetItem();
2682
2683 pItem->SetData((long)pInternaldata->m_lParam);
2684 }
2685 }
2686 break;
2687 }
2688 //
2689 // Now let's go through the codes we're interested in
2690 //
2691 switch(SHORT2FROMMP(wParam))
2692 {
2693 case CN_INITDRAG:
2694 pDragInit = (PCNRDRAGINIT)lParam;
2695 if (pDragInit)
2696 {
2697 PMYRECORD pRecord = (PMYRECORD)pDragInit->pRecord;
2698
2699 vEventType = wxEVT_COMMAND_LIST_BEGIN_RDRAG;
2700 vEvent.m_itemIndex = pRecord->m_ulItemId;
2701 vEvent.m_pointDrag.x = pDragInit->x;
2702 vEvent.m_pointDrag.y = pDragInit->y;
2703 }
2704 break;
2705
2706 case CN_BEGINEDIT:
2707 pEditData = (PCNREDITDATA)lParam;
2708 if (pEditData)
2709 {
2710 vEventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT;
2711 ConvertFromOS2ListItem( GetHWND()
2712 ,(wxListItem &)vEvent.GetItem()
2713 ,(PMYRECORD)pEditData->pRecord
2714 );
2715 vEvent.m_itemIndex = vEvent.GetItem().GetId();
2716 }
2717 break;
2718
2719 case CN_ENDEDIT:
2720 pEditData = (PCNREDITDATA)lParam;
2721 if (pEditData)
2722 {
2723 vEventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT;
2724 ConvertFromOS2ListItem( GetHWND()
2725 ,(wxListItem &)vEvent.GetItem()
2726 ,(PMYRECORD)pEditData->pRecord
2727 );
2728 if (pEditData->cbText == 0)
2729 return (MRESULT)FALSE;
2730 vEvent.m_itemIndex = vEvent.GetItem().GetId();
2731 }
2732 break;
2733
2734 case CN_ENTER:
2735 pNotifyEnter = (PNOTIFYRECORDENTER)lParam;
2736 if (pNotifyEnter)
2737 {
2738 wxListItem* pItem = (wxListItem*)&vEvent.GetItem();
2739 PMYRECORD pMyRecord = (PMYRECORD)pNotifyEnter->pRecord;
2740
2741 vEventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED;
2742 vEvent.m_itemIndex = pMyRecord->m_ulItemId;
2743 pItem->SetText(GetItemText(pMyRecord->m_ulItemId));
2744 pItem->SetData(GetItemData(pMyRecord->m_ulItemId));
2745 }
2746 break;
2747
2748 //
2749 // Add the CN_DROP messages for Direct Manipulation
2750 //
2751 }
2752 vEvent.SetEventType(vEventType);
937013e0 2753 bProcessed = HandleWindowEvent(vEvent);
c4f4cf89
DW
2754 break;
2755 }
2756 if (!bProcessed)
2757 lRc = wxControl::OS2WindowProc( uMsg
2758 ,wParam
2759 ,lParam
2760 );
2761 return lRc;
2762} // end of wxListCtrl::WindowProc
2763
2764#endif // wxUSE_LISTCTRL