]> git.saurik.com Git - wxWidgets.git/blame - src/os2/listctrl.cpp
added wxUSE_PRINTF_POS_PARAMS which can be used to force the use of built-in printf...
[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:
705 wxFAIL_MSG( _T("wxOS2 does not support more than 10 columns in REPORT view") );
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
777// ----------------------------------------------------------------------------
778// events
779// ----------------------------------------------------------------------------
780
781DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_DRAG)
782DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_RDRAG)
783DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT)
784DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT)
785DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM)
786DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS)
787DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO)
788DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO)
789DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED)
790DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED)
791DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN)
792DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM)
793DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK)
794DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_RIGHT_CLICK)
795DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG)
796DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_DRAGGING)
797DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_END_DRAG)
798DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK)
799DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK)
800DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED)
801DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_FOCUSED)
802DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT)
803
804IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
805IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
806IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
807
808IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
809
810BEGIN_EVENT_TABLE(wxListCtrl, wxControl)
811 EVT_PAINT(wxListCtrl::OnPaint)
812END_EVENT_TABLE()
813
814// ============================================================================
815// implementation
816// ============================================================================
817
818// ----------------------------------------------------------------------------
819// wxListCtrl construction
820// ----------------------------------------------------------------------------
821
822void wxListCtrl::Init ()
823{
824 m_pImageListNormal = NULL;
825 m_pImageListSmall = NULL;
826 m_pImageListState = NULL;
fec9cc08
WS
827 m_bOwnsImageListNormal = false;
828 m_bOwnsImageListSmall = false;
829 m_bOwnsImageListState = false;
c4f4cf89
DW
830 m_lBaseStyle = 0L;
831 m_nColCount = 0;
832 m_pTextCtrl = NULL;
fec9cc08
WS
833 m_bAnyInternalData = false;
834 m_bHasAnyAttr = false;
c4f4cf89
DW
835} // end of wxListCtrl::Init
836
fec9cc08
WS
837bool wxListCtrl::Create ( wxWindow* pParent,
838 wxWindowID vId,
839 const wxPoint& rPos,
840 const wxSize& rSize,
841 long lStyle,
842 const wxValidator& rValidator,
843 const wxString& rsName )
c4f4cf89 844{
fec9cc08
WS
845 int nX = rPos.x;
846 int nY = rPos.y;
847 int nWidth = rSize.x;
848 int nHeight = rSize.y;
c4f4cf89
DW
849
850#if wxUSE_VALIDATORS
851 SetValidator(rValidator);
852#endif // wxUSE_VALIDATORS
853
854 SetName(rsName);
855 SetWindowStyleFlag(lStyle);
856 SetParent(pParent);
857 if (nWidth <= 0)
858 nWidth = 100;
859 if (nHeight <= 0)
860 nHeight = 30;
861 if (nX < 0)
862 nX = 0;
863 if (nY < 0)
864 nY = 0;
865
866 m_windowId = (vId == -1) ? NewControlId() : vId;
867
fec9cc08 868 long lSstyle = WS_VISIBLE | WS_TABSTOP;
c4f4cf89
DW
869
870 if (GetWindowStyleFlag() & wxCLIP_SIBLINGS)
871 lSstyle |= WS_CLIPSIBLINGS;
872 m_lBaseStyle = lSstyle;
873 if (!DoCreateControl( nX
874 ,nY
875 ,nWidth
876 ,nHeight
877 ))
fec9cc08 878 return false;
c4f4cf89
DW
879 if (pParent)
880 pParent->AddChild(this);
fec9cc08 881 return true;
c4f4cf89
DW
882} // end of wxListCtrl::Create
883
fec9cc08
WS
884bool wxListCtrl::DoCreateControl ( int nX, int nY,
885 int nWidth, int nHeight )
c4f4cf89 886{
fec9cc08
WS
887 DWORD lWstyle = m_lBaseStyle;
888 long lOldStyle = 0; // Dummy
c4f4cf89 889
fec9cc08 890 CNRINFO vCnrInfo;
c4f4cf89
DW
891
892 lWstyle |= ConvertToOS2Style( lOldStyle
893 ,GetWindowStyleFlag()
894 );
895
896 m_hWnd = (WXHWND)::WinCreateWindow( GetParent()->GetHWND()
897 ,WC_CONTAINER
898 ,NULL
899 ,m_lBaseStyle
900 ,0, 0, 0, 0
901 ,GetParent()->GetHWND()
902 ,HWND_BOTTOM
903 ,(ULONG)m_windowId
904 ,NULL
905 ,NULL
906 );
907 if (!m_hWnd)
908 {
fec9cc08 909 return false;
c4f4cf89
DW
910 }
911
912 //
913 // Now set the display attributes of the container
914 //
915 if (!::WinSendMsg( GetHWND()
916 ,CM_QUERYCNRINFO
917 ,MPFROMP(&vCnrInfo)
918 ,(MPARAM)(USHORT)sizeof(CNRINFO)
919 ))
fec9cc08 920 return false;
c4f4cf89 921 lWstyle = ConvertViewToOS2Style(GetWindowStyleFlag());
378ad957
DW
922 vCnrInfo.flWindowAttr |= lWstyle;
923 if (!::WinSendMsg( GetHWND()
924 ,CM_SETCNRINFO
925 ,MPFROMP(&vCnrInfo)
926 ,(MPARAM)CMA_FLWINDOWATTR
927 ))
fec9cc08 928 return false;
c4f4cf89
DW
929
930 //
931 // And now set needed arrangement flags
932 //
933 lWstyle = ConvertArrangeToOS2Style(GetWindowStyleFlag());
378ad957
DW
934 if (!::WinSendMsg( GetHWND()
935 ,CM_ARRANGE
936 ,(MPARAM)CMA_ARRANGEGRID
937 ,(MPARAM)lWstyle
938 ))
fec9cc08 939 return false;
c4f4cf89
DW
940 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
941 SetForegroundColour(GetParent()->GetForegroundColour());
942 SubclassWin(m_hWnd);
943 SetFont(*wxSMALL_FONT);
944 SetXComp(0);
945 SetYComp(0);
fec9cc08
WS
946 SetSize( nX, nY, nWidth, nHeight );
947 return true;
c4f4cf89
DW
948} // end of wxListCtrl::DoCreateControl
949
950void wxListCtrl::UpdateStyle ()
951{
952 if (GetHWND())
953 {
fec9cc08
WS
954 long lDummy;
955 DWORD dwStyleNew = ConvertToOS2Style( lDummy, GetWindowStyleFlag() );
c4f4cf89
DW
956
957 dwStyleNew |= m_lBaseStyle;
958
959 //
960 // Get the current window style.
961 //
fec9cc08 962 ULONG dwStyleOld = ::WinQueryWindowULong(GetHWND(), QWL_STYLE);
c4f4cf89
DW
963
964 //
965 // Only set the window style if the view bits have changed.
966 //
967 if (dwStyleOld != dwStyleNew)
968 {
969 ::WinSetWindowULong(GetHWND(), QWL_STYLE, dwStyleNew);
970 }
971 }
972} // end of wxListCtrl::UpdateStyle
973
974void wxListCtrl::FreeAllInternalData ()
975{
976 if (m_bAnyInternalData)
977 {
fec9cc08
WS
978 int n = GetItemCount();
979 int i = 0;
c4f4cf89
DW
980
981 for (i = 0; i < n; i++)
982 DeleteInternalData(this, (long)i);
fec9cc08 983 m_bAnyInternalData = false;
c4f4cf89
DW
984 }
985} // end of wxListCtrl::FreeAllInternalData
986
987wxListCtrl::~wxListCtrl ()
988{
989 FreeAllInternalData();
990 if (m_pTextCtrl )
991 {
992 m_pTextCtrl->SetHWND(0);
993 m_pTextCtrl->UnsubclassWin();
994 delete m_pTextCtrl;
995 m_pTextCtrl = NULL;
996 }
997
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
1005
1006// ----------------------------------------------------------------------------
1007// set/get/change style
1008// ----------------------------------------------------------------------------
1009
1010// Add or remove a single window style
1011void wxListCtrl::SetSingleStyle (
1012 long lStyle
1013, bool bAdd
1014)
1015{
1016 long lFlag = GetWindowStyleFlag();
1017
1018 //
1019 // Get rid of conflicting styles
1020 //
1021 if (bAdd)
1022 {
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;
1029 }
1030 if (lFlag & lStyle)
1031 {
1032 if (!bAdd)
1033 lFlag -= lStyle;
1034 }
1035 else
1036 {
1037 if (bAdd)
1038 {
1039 lFlag |= lStyle;
1040 }
1041 }
1042 m_windowStyle = lFlag;
1043 UpdateStyle();
1044} // end of wxListCtrl::SetSingleStyle
1045
1046// Set the whole window style
1047void wxListCtrl::SetWindowStyleFlag (
1048 long lFlag
1049)
1050{
1051 m_windowStyle = lFlag;
1052 UpdateStyle();
1053} // end of wxListCtrl::SetWindowStyleFlag
1054
1055long wxListCtrl::ConvertToOS2Style (
1056 long& rOldStyle
1057, long lStyle
1058) const
1059{
1060 long lWstyle = 0L;
1061
1062 //
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
1066 //
1067 if (lStyle & wxLC_AUTOARRANGE)
1068 lWstyle |= CCS_AUTOPOSITION;
1069 if (lStyle & wxLC_SINGLE_SEL)
1070 lWstyle |= CCS_SINGLESEL;
1071 else
1072 lWstyle |= CCS_EXTENDSEL;
1073 if (!(lStyle & wxLC_EDIT_LABELS))
1074 lWstyle |= CCS_READONLY;
1075 return lWstyle;
1076} // end of wxListCtrl::ConvertToOS2Style
1077
1078long wxListCtrl::ConvertArrangeToOS2Style (
1079 long lStyle
1080)
1081{
1082 long lWstyle = 0;
1083
1084 if (lStyle & wxLC_ALIGN_LEFT)
1085 {
1086 lWstyle |= CMA_LEFT;
1087 }
1088
1089 if (lStyle & wxLC_ALIGN_TOP)
1090 {
1091 lWstyle |= CMA_TOP;
1092 }
1093 return lWstyle;
1094} // end of wxListCtrl::ConvertArrangeToOS2Style
1095
1096long wxListCtrl::ConvertViewToOS2Style (
1097 long lStyle
1098)
1099{
1100 long lWstyle = CA_DRAWICON; // we will only use icons
1101
1102 if (lStyle & wxLC_ICON)
1103 {
1104 lWstyle |= CV_ICON;
1105 }
1106 if (lStyle & wxLC_SMALL_ICON)
1107 {
1108 lWstyle |= (CV_ICON | CV_MINI);
1109 }
1110 if (lStyle & wxLC_LIST)
1111 {
1112 lWstyle |= CV_TEXT;
1113 }
1114 if (lStyle & wxLC_REPORT)
1115 {
1116 lWstyle |= CV_DETAIL;
1117 }
1118 if (lStyle & wxLC_VIRTUAL)
1119 {
1120 lWstyle |= CA_OWNERDRAW;
1121 }
1122 if (lStyle & wxLC_AUTOARRANGE)
1123 {
1124 lWstyle |= CV_FLOW;
1125 }
1126 if (!(lStyle & wxLC_NO_HEADER))
1127 {
1128 lWstyle |= CA_DETAILSVIEWTITLES;
1129 }
1130 return lWstyle;
1131} // end of wxListCtrl::ConvertViewToOS2Style
1132
1133// ----------------------------------------------------------------------------
1134// accessors
1135// ----------------------------------------------------------------------------
1136
1137// Sets the foreground, i.e. text, colour
fec9cc08 1138bool wxListCtrl::SetForegroundColour (const wxColour& rCol)
c4f4cf89 1139{
fec9cc08 1140 ULONG ulColor = wxColourToRGB(rCol);
c4f4cf89
DW
1141
1142 if (!wxWindow::SetForegroundColour(rCol))
fec9cc08 1143 return false;
c4f4cf89
DW
1144
1145 ::WinSetPresParam( GetHWND()
1146 ,PP_FOREGROUNDCOLOR
1147 ,sizeof(ULONG)
1148 ,&ulColor
1149 );
fec9cc08 1150 return true;
c4f4cf89
DW
1151} // end of wxListCtrl::SetForegroundColour
1152
1153// Sets the background colour
fec9cc08 1154bool wxListCtrl::SetBackgroundColour ( const wxColour& rCol )
c4f4cf89
DW
1155{
1156 if (!wxWindow::SetBackgroundColour(rCol))
fec9cc08 1157 return false;
c4f4cf89
DW
1158
1159 //
1160 // We set the same colour for both the "empty" background and the items
1161 // background
1162 //
fec9cc08 1163 ULONG ulColor = wxColourToRGB(rCol);
c4f4cf89
DW
1164
1165 ::WinSetPresParam( GetHWND()
1166 ,PP_BACKGROUNDCOLOR
1167 ,sizeof(ULONG)
1168 ,&ulColor
1169 );
fec9cc08 1170 return true;
c4f4cf89
DW
1171} // end of wxListCtrl::SetBackgroundColour
1172
1173// Gets information about this column
fec9cc08 1174bool wxListCtrl::GetColumn ( int nCol, wxListItem& rItem ) const
c4f4cf89 1175{
fec9cc08 1176 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND(), nCol );
c4f4cf89
DW
1177
1178 if (!pFieldInfo)
fec9cc08 1179 return false;
c4f4cf89
DW
1180 rItem.SetWidth(pFieldInfo->cxWidth);
1181 if ((rItem.GetMask() & wxLIST_MASK_TEXT) &&
1182 (pFieldInfo->flData & CFA_STRING) &&
1183 (pFieldInfo->pUserData != NULL))
1184 {
1185 rItem.SetText((char*)pFieldInfo->pUserData);
1186 }
1187 if (rItem.GetMask() & wxLIST_MASK_FORMAT )
1188 {
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;
1195 }
fec9cc08 1196 return true;
c4f4cf89
DW
1197} // end of wxListCtrl::GetColumn
1198
1199// Sets information about this column
fec9cc08 1200bool wxListCtrl::SetColumn ( int nCol, wxListItem& rItem )
c4f4cf89 1201{
fec9cc08
WS
1202 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum( GetHWND(), nCol );
1203 ConvertToOS2ListCol( nCol, rItem, pFieldInfo );
c4f4cf89
DW
1204 //
1205 // Since we changed the field pointed to, we invalidate to see the result
1206 //
1207 ::WinSendMsg(GetHWND(), CM_INVALIDATEDETAILFIELDINFO, NULL, NULL);
fec9cc08 1208 return true;
c4f4cf89
DW
1209} // end of wxListCtrl::SetColumn
1210
1211// Gets the column width
fec9cc08 1212int wxListCtrl::GetColumnWidth ( int nCol ) const
c4f4cf89 1213{
fec9cc08 1214 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND(), nCol );
c4f4cf89
DW
1215
1216 if (!pFieldInfo)
1217 return 0;
1218 return((int)pFieldInfo->cxWidth);
1219} // end of wxListCtrl::GetColumnWidth
1220
1221// Sets the column width
fec9cc08 1222bool wxListCtrl::SetColumnWidth ( int nCol, int nWidth )
c4f4cf89 1223{
fec9cc08
WS
1224 int nCol2 = nCol;
1225 int nWidth2 = nWidth;
c4f4cf89
DW
1226
1227 if (GetWindowStyleFlag() & wxLC_LIST)
1228 nCol2 = -1;
1229
fec9cc08 1230 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum( GetHWND(), nCol );
c4f4cf89
DW
1231 pFieldInfo->cxWidth = nWidth;
1232 ::WinSendMsg(GetHWND(), CM_INVALIDATEDETAILFIELDINFO, NULL, NULL);
fec9cc08 1233 return true;
c4f4cf89
DW
1234} // end of wxListCtrl::SetColumnWidth
1235
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)
1240int wxListCtrl::GetCountPerPage () const
1241{
1242 QUERYRECORDRECT vQueryRect;
1243 CNRINFO vCnrInfo;
1244 RECTL vRectRecord;
1245 RECTL vRectControl;
1246 int nCount;
1247
1248 if (!::WinSendMsg( GetHWND()
1249 ,CM_QUERYCNRINFO
1250 ,MPFROMP(&vCnrInfo)
1251 ,(MPARAM)(USHORT)sizeof(CNRINFO)
1252 ))
1253 return 0;
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()
1265 ,CM_QUERYRECORDRECT
1266 ,MPFROMP(&vRectRecord)
1267 ,MPFROMP(&vQueryRect)
1268 ))
1269 return 0;
1270 if (!::WinSendMsg( GetHWND()
1271 ,CM_QUERYVIEWPORTRECT
1272 ,MPFROMP(&vRectControl)
1273 ,MPFROM2SHORT(CMA_WINDOW, (USHORT)FALSE)
1274 ))
1275 return 0;
1276 nCount = (int)((int)((vRectControl.xRight - vRectControl.xLeft) / (vRectRecord.xRight - vRectRecord.xLeft)) *
1277 (int)((vRectControl.yTop - vRectControl.yBottom) / (vRectRecord.yTop - vRectRecord.yBottom))
1278 );
1279 if (nCount > (int)vCnrInfo.cFields)
1280 nCount = (int)vCnrInfo.cFields;
1281 return nCount;
1282} // end of wxListCtrl::GetCountPerPage
1283
1284// Gets the edit control for editing labels.
1285wxTextCtrl* wxListCtrl::GetEditControl() const
1286{
1287 return m_pTextCtrl;
1288}
1289
1290// Gets information about the item
fec9cc08 1291bool wxListCtrl::GetItem ( wxListItem& rInfo ) const
c4f4cf89 1292{
fec9cc08 1293 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), rInfo.GetId() );
c4f4cf89
DW
1294
1295 //
1296 // Give NULL as hwnd as we already have everything we need
1297 //
fec9cc08
WS
1298 ConvertFromOS2ListItem( NULL, rInfo, pRecord );
1299 return true;
c4f4cf89
DW
1300} // end of wxListCtrl::GetItem
1301
1302// Sets information about the item
fec9cc08 1303bool wxListCtrl::SetItem ( wxListItem& rInfo )
c4f4cf89 1304{
fec9cc08
WS
1305 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND(), rInfo.GetColumn() );
1306 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), rInfo.GetId() );
c4f4cf89
DW
1307
1308 ConvertToOS2ListItem( this
1309 ,rInfo
1310 ,pRecord
378ad957 1311 ,pFieldInfo
c4f4cf89
DW
1312 );
1313
1314 //
1315 // Check if setting attributes or lParam
1316 //
1317 if (rInfo.HasAttributes() || (rInfo.GetMask() & wxLIST_MASK_DATA))
1318 {
1319 //
1320 // Get internal item data
1321 // perhaps a cache here ?
1322 //
1323 CListItemInternalData* pData = GetInternalData( this
1324 ,rInfo.GetId()
1325 );
1326
1327 if (!pData)
1328 {
1329 //
1330 // Need to set it
1331 //
fec9cc08 1332 m_bAnyInternalData = true;
c4f4cf89
DW
1333 pData = new CListItemInternalData();
1334 pRecord->m_ulUserData = (unsigned long)pData;
1335 };
1336
1337 //
1338 // User data
1339 //
1340 if (rInfo.GetMask() & wxLIST_MASK_DATA)
1341 pData->m_lParam = (WXLPARAM)rInfo.GetData();
1342
1343 // attributes
1344 if (rInfo.HasAttributes())
1345 {
1346 if (pData->m_pAttr)
1347 *pData->m_pAttr = *rInfo.GetAttributes();
1348 else
1349 pData->m_pAttr = new wxListItemAttr(*rInfo.GetAttributes());
1350 }
378ad957 1351 pData->m_pMyRecord = pRecord; // they point to each other
c4f4cf89
DW
1352 }
1353
1354 //
1355 // We need to update the item immediately to show the new image
1356 //
fec9cc08 1357 bool bUpdateNow = (rInfo.GetMask() & wxLIST_MASK_IMAGE) != 0;
c4f4cf89
DW
1358
1359 //
1360 // Check whether it has any custom attributes
1361 //
1362 if (rInfo.HasAttributes())
1363 {
fec9cc08 1364 m_bHasAnyAttr = true;
c4f4cf89
DW
1365
1366 //
1367 // If the colour has changed, we must redraw the item
1368 //
fec9cc08 1369 bUpdateNow = true;
c4f4cf89 1370 }
378ad957
DW
1371 if (::WinIsWindowVisible(GetHWND()))
1372 {
1373 ::WinSendMsg( GetHWND()
1374 ,CM_INVALIDATERECORD
1375 ,MPFROMP(pRecord)
1376 ,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
1377 );
1378 RefreshItem(pRecord->m_ulItemId);
1379 }
c4f4cf89 1380 ::WinSendMsg( GetHWND()
378ad957
DW
1381 ,CM_INVALIDATEDETAILFIELDINFO
1382 ,NULL
1383 ,NULL
c4f4cf89 1384 );
fec9cc08 1385 return true;
c4f4cf89
DW
1386} // end of wxListCtrl::SetItem
1387
1388long wxListCtrl::SetItem (
1389 long lIndex
1390, int nCol
1391, const wxString& rsLabel
1392, int nImageId
1393)
1394{
1395 wxListItem vInfo;
1396
1397 vInfo.m_text = rsLabel;
1398 vInfo.m_mask = wxLIST_MASK_TEXT;
1399 vInfo.m_itemId = lIndex;
1400 vInfo.m_col = nCol;
1401 if (nImageId > -1)
1402 {
1403 vInfo.m_image = nImageId;
1404 vInfo.m_mask |= wxLIST_MASK_IMAGE;
1405 }
1406 return SetItem(vInfo);
1407} // end of wxListCtrl::SetItem
1408
1409// Gets the item state
1410int wxListCtrl::GetItemState (
1411 long lItem
1412, long lStateMask
1413) const
1414{
1415 wxListItem vInfo;
1416
1417 vInfo.m_mask = wxLIST_MASK_STATE;
1418 vInfo.m_stateMask = lStateMask;
1419 vInfo.m_itemId = lItem;
1420
1421 if (!GetItem(vInfo))
1422 return 0;
1423 return vInfo.m_state;
1424} // end of wxListCtrl::GetItemState
1425
1426// Sets the item state
fec9cc08 1427bool wxListCtrl::SetItemState ( long lItem, long lState, long lStateMask )
c4f4cf89 1428{
fec9cc08 1429 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
c4f4cf89
DW
1430
1431 //
1432 // Don't use SetItem() here as it doesn't work with the virtual list
1433 // controls
1434 //
fec9cc08 1435 ConvertToOS2Flags( lState, pRecord );
c4f4cf89
DW
1436
1437 //
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)
1442 //
1443 long lFocusOld;
1444
1445 if (IsVirtual() &&
1446 (lStateMask & wxLIST_STATE_FOCUSED) &&
1447 (lState & wxLIST_STATE_FOCUSED) )
1448 {
1449 lFocusOld = GetNextItem( -1
1450 ,wxLIST_NEXT_ALL
1451 ,wxLIST_STATE_FOCUSED
1452 );
1453 }
1454 else
1455 {
1456 lFocusOld = -1;
1457 }
1458 ::WinSendMsg( GetHWND()
1459 ,CM_INVALIDATERECORD
1460 ,MPFROMP(pRecord)
1461 ,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
1462 );
1463
1464 if (lFocusOld != -1)
1465 {
1466 //
1467 // No need to refresh the item if it was previously selected, it would
1468 // only result in annoying flicker
1469 //
1470 if (!(GetItemState( lFocusOld
1471 ,wxLIST_STATE_SELECTED
1472 ) & wxLIST_STATE_SELECTED))
1473 {
1474 RefreshItem(lFocusOld);
1475 }
1476 }
fec9cc08 1477 return true;
c4f4cf89
DW
1478} // end of wxListCtrl::SetItemState
1479
1480// Sets the item image
1481bool wxListCtrl::SetItemImage (
1482 long lItem
1483, int nImage
1484, int WXUNUSED(nSelImage))
06db67bc
RD
1485{
1486 return SetItemColumnInfo(lItem, 0, nImage);
1487} // end of wxListCtrl::SetItemImage
1488
1489// Sets the item image
1490bool wxListCtrl::SetItemColumnImage (
1491 long lItem
1492, long lColumn
1493, int nImage
c4f4cf89
DW
1494{
1495 wxListItem vInfo;
1496
1497 vInfo.m_mask = wxLIST_MASK_IMAGE;
1498 vInfo.m_image = nImage;
1499 vInfo.m_itemId = lItem;
06db67bc 1500 vInfo.m_col = lColumn;
c4f4cf89 1501 return SetItem(vInfo);
06db67bc 1502} // end of wxListCtrl::SetItemColumnImage
c4f4cf89
DW
1503
1504// Gets the item text
1505wxString wxListCtrl::GetItemText (
1506 long lItem
1507) const
1508{
1509 wxListItem vInfo;
1510
1511 vInfo.m_mask = wxLIST_MASK_TEXT;
1512 vInfo.m_itemId = lItem;
1513
1514 if (!GetItem(vInfo))
1515 return wxEmptyString;
1516 return vInfo.m_text;
1517} // end of wxListCtrl::GetItemText
1518
1519// Sets the item text
1520void wxListCtrl::SetItemText (
1521 long lItem
1522, const wxString& rsStr
1523)
1524{
1525 wxListItem vInfo;
1526
1527 vInfo.m_mask = wxLIST_MASK_TEXT;
1528 vInfo.m_itemId = lItem;
1529 vInfo.m_text = rsStr;
1530 SetItem(vInfo);
1531} // end of wxListCtrl::SetItemText
1532
1533// Gets the item data
1534long wxListCtrl::GetItemData (
1535 long lItem
1536) const
1537{
1538 wxListItem vInfo;
1539
1540 vInfo.m_mask = wxLIST_MASK_DATA;
1541 vInfo.m_itemId = lItem;
1542 if (!GetItem(vInfo))
1543 return 0;
1544 return vInfo.m_data;
1545} // end of wxListCtrl::GetItemData
1546
1547// Sets the item data
1548bool wxListCtrl::SetItemData (
1549 long lItem
1550, long lData
1551)
1552{
1553 wxListItem vInfo;
1554
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
1560
1561// Gets the item rectangle
fec9cc08
WS
1562bool wxListCtrl::GetItemRect ( long lItem,
1563 wxRect& rRect,
1564 int nCode ) const
c4f4cf89 1565{
fec9cc08
WS
1566 bool bSuccess;
1567 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
1568 QUERYRECORDRECT vQueryRect;
1569 RECTL vRect;
1570 int nHeight;
c4f4cf89
DW
1571
1572 if (!pRecord)
fec9cc08 1573 return false;
c4f4cf89
DW
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()
1579 ,CM_QUERYRECORDRECT
1580 ,MPFROMP(&vRect)
1581 ,MPFROMP(&vQueryRect)
1582 );
1583 //
1584 // remember OS/2 is backwards
1585 //
fec9cc08 1586 GetClientSize( NULL, &nHeight );
c4f4cf89
DW
1587 rRect.x = vRect.xLeft;
1588 rRect.y = nHeight - vRect.yTop;
1589 rRect.width = vRect.xRight;
1590 rRect.height = nHeight - vRect.yBottom;
fec9cc08 1591 bSuccess = true;
c4f4cf89
DW
1592 return bSuccess;
1593} // end of wxListCtrl::GetItemRect
1594
1595// Gets the item position
fec9cc08 1596bool wxListCtrl::GetItemPosition ( long lItem, wxPoint& rPos ) const
c4f4cf89 1597{
fec9cc08
WS
1598 bool bSuccess;
1599 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND() , lItem );
1600 QUERYRECORDRECT vQueryRect;
1601 RECTL vRect;
1602 int nHeight;
c4f4cf89
DW
1603
1604 if (!pRecord)
fec9cc08 1605 return false;
c4f4cf89
DW
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()
1611 ,CM_QUERYRECORDRECT
1612 ,MPFROMP(&vRect)
1613 ,MPFROMP(&vQueryRect)
1614 );
1615 //
1616 // remember OS/2 is backwards
1617 //
fec9cc08 1618 GetClientSize( NULL, &nHeight );
c4f4cf89
DW
1619 rPos.x = vRect.xLeft;
1620 rPos.y = nHeight - vRect.yTop;
fec9cc08 1621 bSuccess = true;
c4f4cf89
DW
1622 return bSuccess;
1623} // end of wxListCtrl::GetItemPosition
1624
1625// Sets the item position.
fec9cc08 1626bool wxListCtrl::SetItemPosition ( long lItem, const wxPoint& rPos )
c4f4cf89
DW
1627{
1628 //
1629 // Items cannot be positioned in X/Y coord in OS/2
1630 //
fec9cc08 1631 return false;
c4f4cf89
DW
1632} // end of wxListCtrl::SetItemPosition
1633
1634// Gets the number of items in the list control
1635int wxListCtrl::GetItemCount () const
1636{
1637 CNRINFO vCnrInfo;
1638
1639 if (!::WinSendMsg( GetHWND()
1640 ,CM_QUERYCNRINFO
1641 ,MPFROMP(&vCnrInfo)
1642 ,(MPARAM)(USHORT)sizeof(CNRINFO)
1643 ))
1644 return -1;
1645 return vCnrInfo.cRecords;
1646} // end of wxListCtrl::GetItemCount
1647
1648// Retrieves the spacing between icons in pixels.
fec9cc08 1649// If bIsSmall is true, gets the spacing for the small icon
c4f4cf89 1650// view, otherwise the large icon view.
fec9cc08 1651int wxListCtrl::GetItemSpacing ( bool bIsSmall ) const
c4f4cf89
DW
1652{
1653 CNRINFO vCnrInfo;
1654
1655 if (!::WinSendMsg( GetHWND()
1656 ,CM_QUERYCNRINFO
1657 ,MPFROMP(&vCnrInfo)
1658 ,(MPARAM)(USHORT)sizeof(CNRINFO)
1659 ))
1660 return -1;
1661 return vCnrInfo.cyLineSpacing;
1662} // end of wxListCtrl::GetItemSpacing
1663
1664void wxListCtrl::SetItemTextColour (
1665 long lItem
1666, const wxColour& rCol
1667)
1668{
1669 wxListItem vInfo;
1670
1671 vInfo.m_itemId = lItem;
1672 vInfo.SetTextColour(rCol);
1673 SetItem(vInfo);
1674} // end of wxListCtrl::SetItemTextColour
1675
1676wxColour wxListCtrl::GetItemTextColour (
1677 long lItem
1678) const
1679{
1680 wxListItem vInfo;
1681
1682 vInfo.m_itemId = lItem;
1683 GetItem(vInfo);
1684 return vInfo.GetTextColour();
1685} // end of wxListCtrl::GetItemTextColour
1686
1687void wxListCtrl::SetItemBackgroundColour (
1688 long lItem
1689, const wxColour& rCol
1690)
1691{
1692 wxListItem vInfo;
1693
1694 vInfo.m_itemId = lItem;
1695 vInfo.SetBackgroundColour(rCol);
1696 SetItem(vInfo);
1697} // end of wxListCtrl::SetItemBackgroundColour
1698
1699wxColour wxListCtrl::GetItemBackgroundColour (
1700 long lItem
1701) const
1702{
1703 wxListItem vInfo;
1704
1705 vInfo.m_itemId = lItem;
1706 GetItem(vInfo);
1707 return vInfo.GetBackgroundColour();
1708} // end of wxListCtrl::GetItemBackgroundColour
1709
1710// Gets the number of selected items in the list control
1711int wxListCtrl::GetSelectedItemCount () const
1712{
1713 PMYRECORD pRecord = NULL;
1714 int nCount = 0;
1715 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1716 ,CM_QUERYRECORDEMPHASIS
1717 ,(MPARAM)CMA_FIRST
1718 ,(MPARAM)CRA_SELECTED
1719 ));
1720 if (pRecord)
1721 nCount++;
1722 else
1723 return 0;
1724 while (pRecord)
1725 {
1726 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1727 ,CM_QUERYRECORDEMPHASIS
1728 ,MPFROMP(pRecord)
1729 ,(MPARAM)CRA_SELECTED
1730 ));
1731 if (pRecord)
1732 nCount++;
1733 }
1734 return nCount;
1735} // end of wxListCtrl::GetSelectedItemCount
1736
1737// Gets the text colour of the listview
1738wxColour wxListCtrl::GetTextColour () const
1739{
1740 wxColour vCol;
1741 ULONG ulColor;
1742
1743 ::WinQueryPresParam( GetHWND()
1744 ,PP_FOREGROUNDCOLOR
1745 ,0
1746 ,NULL
1747 ,sizeof(ULONG)
1748 ,&ulColor
1749 ,QPF_PURERGBCOLOR
1750 );
1751 vCol.Set(ulColor);
1752 return vCol;
1753} // end of wxListCtrl::GetTextColour
1754
1755// Sets the text colour of the listview
1756void wxListCtrl::SetTextColour (
1757 const wxColour& rCol
1758)
1759{
1760 ULONG ulColor = wxColourToRGB(rCol);
1761
1762 ::WinSetPresParam( GetHWND()
1763 ,PP_FOREGROUNDCOLOR
1764 ,sizeof(ULONG)
1765 ,&ulColor
1766 );
1767} // end of wxListCtrl::SetTextColour
1768
1769// Gets the index of the topmost visible item when in
1770// list or report view
1771long wxListCtrl::GetTopItem () const
1772{
1773 PMYRECORD pRecord = NULL;
1774 QUERYRECFROMRECT vQueryRect;
1775 RECTL vRect;
1776
1777 ::WinSendMsg( GetHWND()
1778 ,CM_QUERYVIEWPORTRECT
1779 ,MPFROMP(&vRect)
1780 ,MPFROM2SHORT(CMA_WINDOW, TRUE)
1781 );
1782 vQueryRect.cb = sizeof(QUERYRECFROMRECT);
1783 vQueryRect.rect = vRect;
1784 vQueryRect.fsSearch = CMA_PARTIAL;
1785
1786 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
1787 ,CM_QUERYRECORDFROMRECT
1788 ,(MPARAM)CMA_FIRST
1789 ,MPFROMP(&vQueryRect)
1790 );
1791
1792 if (!pRecord)
1793 return -1L;
1794 return (long)pRecord->m_ulItemId;
1795} // end of wxListCtrl::GetTopItem
1796
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
1803// specified flags.
1804// Returns the item or -1 if unsuccessful.
1805long wxListCtrl::GetNextItem (
1806 long lItem
1807, int WXUNUSED(nGeom)
1808, int WXUNUSED(nState)
1809) const
1810{
1811 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1812 ,lItem
1813 );
1814
1815 pRecord = (PMYRECORD)pRecord->m_vRecord.preccNextRecord;
1816 if (pRecord)
1817 return((long)pRecord->m_ulItemId);
1818 return -1L;
1819} // end of wxListCtrl::GetNextItem
1820
1821wxImageList* wxListCtrl::GetImageList (
1822 int nWhich
1823) const
1824{
1825 if (nWhich == wxIMAGE_LIST_NORMAL )
1826 {
1827 return m_pImageListNormal;
1828 }
1829 else if (nWhich == wxIMAGE_LIST_SMALL )
1830 {
1831 return m_pImageListSmall;
1832 }
1833 else if (nWhich == wxIMAGE_LIST_STATE )
1834 {
1835 return m_pImageListState;
1836 }
1837 return NULL;
1838} // end of wxListCtrl::GetImageList
1839
fec9cc08
WS
1840void wxListCtrl::SetImageList ( wxImageList* pImageList,
1841 int nWhich )
c4f4cf89
DW
1842{
1843 if (nWhich == wxIMAGE_LIST_NORMAL)
1844 {
1845 if (m_bOwnsImageListNormal)
1846 delete m_pImageListNormal;
1847 m_pImageListNormal = pImageList;
fec9cc08 1848 m_bOwnsImageListNormal = false;
c4f4cf89
DW
1849 }
1850 else if (nWhich == wxIMAGE_LIST_SMALL)
1851 {
1852 if (m_bOwnsImageListSmall)
1853 delete m_pImageListSmall;
1854 m_pImageListSmall = pImageList;
fec9cc08 1855 m_bOwnsImageListSmall = false;
c4f4cf89
DW
1856 }
1857 else if (nWhich == wxIMAGE_LIST_STATE)
1858 {
1859 if (m_bOwnsImageListState)
1860 delete m_pImageListState;
1861 m_pImageListState = pImageList;
fec9cc08 1862 m_bOwnsImageListState = false;
c4f4cf89
DW
1863 }
1864} // end of wxListCtrl::SetImageList
1865
fec9cc08 1866void wxListCtrl::AssignImageList ( wxImageList* pImageList, int nWhich )
c4f4cf89 1867{
fec9cc08
WS
1868 SetImageList( pImageList, nWhich );
1869
c4f4cf89 1870 if (nWhich == wxIMAGE_LIST_NORMAL )
fec9cc08 1871 m_bOwnsImageListNormal = true;
c4f4cf89 1872 else if (nWhich == wxIMAGE_LIST_SMALL )
fec9cc08 1873 m_bOwnsImageListSmall = true;
c4f4cf89 1874 else if (nWhich == wxIMAGE_LIST_STATE )
fec9cc08 1875 m_bOwnsImageListState = true;
c4f4cf89
DW
1876} // end of wxListCtrl::AssignImageList
1877
1878// ----------------------------------------------------------------------------
1879// Operations
1880// ----------------------------------------------------------------------------
1881
1882// Arranges the items
fec9cc08 1883bool wxListCtrl::Arrange ( int nFlag )
c4f4cf89 1884{
fec9cc08
WS
1885 ULONG ulType = 0L;
1886 ULONG ulFlags = 0L;
c4f4cf89
DW
1887
1888 if (nFlag == wxLIST_ALIGN_SNAP_TO_GRID)
1889 {
1890 ulType = CMA_ARRANGEGRID;
1891 if (nFlag == wxLIST_ALIGN_LEFT)
1892 ulFlags |= CMA_LEFT;
1893 else if (nFlag == wxLIST_ALIGN_TOP)
1894 ulFlags |= CMA_TOP;
1895 else if (nFlag == wxLIST_ALIGN_DEFAULT)
1896 ulFlags |= CMA_LEFT;
1897 }
1898 else
1899 ulType = CMA_ARRANGESTANDARD;
1900 ::WinSendMsg( GetHWND()
1901 ,CM_ARRANGE
1902 ,(MPARAM)ulType
1903 ,(MPARAM)ulFlags
1904 );
1905 //
1906 // We do not support CMA_ARRANGESELECTED
1907 //
fec9cc08 1908 return true;
c4f4cf89
DW
1909} // end of wxListCtrl::Arrange
1910
1911// Deletes an item
fec9cc08 1912bool wxListCtrl::DeleteItem ( long lItem )
c4f4cf89 1913{
fec9cc08 1914 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
c4f4cf89
DW
1915 if (LONGFROMMR(::WinSendMsg( GetHWND()
1916 ,CM_REMOVERECORD
1917 ,(MPARAM)pRecord
1918 ,MPFROM2SHORT(1, CMA_FREE)
1919 )) == -1L)
1920 {
fec9cc08 1921 return false;
c4f4cf89
DW
1922 }
1923
1924 //
1925 // The virtual list control doesn't refresh itself correctly, help it
1926 //
1927 if (IsVirtual())
1928 {
1929 //
1930 // We need to refresh all the lines below the one which was deleted
1931 //
1932 wxRect vRectItem;
1933
1934 if (lItem > 0 && GetItemCount())
1935 {
1936 GetItemRect( lItem - 1
1937 ,vRectItem
1938 );
1939 }
1940 else
1941 {
1942 vRectItem.y = vRectItem.height = 0;
1943 }
1944 wxRect vRectWin = GetRect();
1945
1946 vRectWin.height = vRectWin.GetBottom() - vRectItem.GetBottom();
1947 vRectWin.y = vRectItem.GetBottom();
1948 RefreshRect(vRectWin);
1949 }
fec9cc08 1950 return true;
c4f4cf89
DW
1951} // end of wxListCtrl::DeleteItem
1952
1953// Deletes all items
1954bool wxListCtrl::DeleteAllItems ()
1955{
1956 return((LONG)::WinSendMsg( GetHWND()
1957 ,CM_REMOVERECORD
1958 ,NULL
1959 ,MPFROM2SHORT(0, CMA_FREE)
1960 ) != -1L);
1961} // end of wxListCtrl::DeleteAllItems
1962
1963// Deletes all items
1964bool wxListCtrl::DeleteAllColumns ()
1965{
1966 while (m_nColCount > 0)
1967 {
1968 DeleteColumn(m_nColCount - 1);
1969 m_nColCount--;
1970 }
1971
1972 wxASSERT_MSG(m_nColCount == 0, wxT("no columns should be left"));
fec9cc08 1973 return true;
c4f4cf89
DW
1974} // end of wxListCtrl::DeleteAllColumns
1975
1976// Deletes a column
fec9cc08 1977bool wxListCtrl::DeleteColumn ( int nCol )
c4f4cf89 1978{
fec9cc08
WS
1979 bool bSuccess = false;
1980 PFIELDINFO pField = FindOS2ListFieldByColNum( GetHWND(), nCol );
c4f4cf89
DW
1981 bSuccess = ((LONG)::WinSendMsg( GetHWND()
1982 ,CM_REMOVEDETAILFIELDINFO
1983 ,MPFROMP(pField)
1984 ,MPFROM2SHORT((SHORT)1, CMA_FREE)
1985 ) == -1L);
1986 if (bSuccess && (m_nColCount > 0))
1987 m_nColCount--;
1988 return bSuccess;
1989} // end of wxListCtrl::DeleteColumn
1990
1991// Clears items, and columns if there are any.
1992void wxListCtrl::ClearAll ()
1993{
1994 DeleteAllItems();
1995 if (m_nColCount > 0)
1996 DeleteAllColumns();
1997} // end of wxListCtrl::ClearAll
1998
1999//
2000// OS/2 does not use a text control for its container labels. You merely
2001// "open" a record for editting.
2002//
2003wxTextCtrl* wxListCtrl::EditLabel (
2004 long lItem
2005, wxClassInfo* WXUNUSED(pTextControlClass)
2006)
2007{
2008 CNREDITDATA vEdit;
2009 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
2010 ,lItem
2011 );
2012
2013 vEdit.cb = sizeof(CNREDITDATA);
2014 vEdit.hwndCnr = GetHWND();
2015 vEdit.pRecord = &pRecord->m_vRecord;
2016 vEdit.pFieldInfo = NULL;
2017 vEdit.ppszText = NULL;
2018 vEdit.cbText = 0;
2019 vEdit.id = 0;
2020
2021 ::WinSendMsg( GetHWND()
2022 ,CM_OPENEDIT
2023 ,MPFROMP(&vEdit)
2024 ,(MPARAM)0
2025 );
2026 return m_pTextCtrl;
2027} // end of wxListCtrl::EditLabel
2028
2029// End label editing, optionally cancelling the edit. Under OS/2 you close
2030// the record for editting
fec9cc08 2031bool wxListCtrl::EndEditLabel ( bool WXUNUSED(bCancel) )
c4f4cf89
DW
2032{
2033 ::WinSendMsg( GetHWND()
2034 ,CM_CLOSEEDIT
2035 ,(MPARAM)0
2036 ,(MPARAM)0
2037 );
fec9cc08 2038 return true;
c4f4cf89
DW
2039} // end of wxListCtrl::EndEditLabel
2040
2041// Ensures this item is visible
fec9cc08 2042bool wxListCtrl::EnsureVisible ( long lItem )
c4f4cf89 2043{
fec9cc08 2044 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
c4f4cf89
DW
2045 ::WinSendMsg( GetHWND()
2046 ,CM_INVALIDATERECORD
2047 ,MPFROMP(pRecord)
2048 ,MPFROM2SHORT((SHORT)1, CMA_NOREPOSITION)
2049 );
fec9cc08 2050 return true;
c4f4cf89
DW
2051} // end of wxListCtrl::EnsureVisible
2052
2053// Find an item whose label matches this string, starting from the item after 'start'
2054// or the beginning if 'start' is -1.
2055long wxListCtrl::FindItem (
2056 long lStart
2057, const wxString& rsStr
2058, bool bPartial
2059)
2060{
2061 CNRINFO vCnrInfo;
2062 SEARCHSTRING vSearch;
2063 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
2064 ,lStart
2065 );
2066 ULONG ulFlag;
2067
2068
2069 if (!::WinSendMsg( GetHWND()
2070 ,CM_QUERYCNRINFO
2071 ,MPFROMP(&vCnrInfo)
2072 ,(MPARAM)(USHORT)sizeof(CNRINFO)
2073 ))
2074 return -1L;
2075
2076 if (vCnrInfo.flWindowAttr & CV_ICON)
2077 ulFlag = CV_ICON;
2078 if (vCnrInfo.flWindowAttr & CV_NAME)
2079 ulFlag = CV_NAME;
2080 if (vCnrInfo.flWindowAttr & CV_TEXT)
2081 ulFlag = CV_TEXT;
2082 if (vCnrInfo.flWindowAttr & CV_DETAIL)
2083 ulFlag = CV_DETAIL;
2084 if (!bPartial)
2085 ulFlag |= CV_EXACTLENGTH;
2086
2087 vSearch.cb = sizeof(SEARCHSTRING);
2088 vSearch.pszSearch = (char*)rsStr.c_str();
2089 vSearch.fsPrefix = TRUE;
2090 vSearch.fsCaseSensitive = TRUE;
2091 vSearch.usView = ulFlag;
2092
2093 if (lStart == -1)
2094 {
2095 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2096 ,CM_SEARCHSTRING
2097 ,MPFROMP(&vSearch)
2098 ,(MPARAM)CMA_FIRST
2099 );
2100 }
2101 else
2102 {
2103 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2104 ,CM_SEARCHSTRING
2105 ,MPFROMP(&vSearch)
2106 ,MPFROMP(pRecord)
2107 );
2108 }
2109 if (!pRecord)
2110 return -1L;
2111 return pRecord->m_ulItemId;
2112} // end of wxListCtrl::FindItem
2113
2114// Find an item whose data matches this data, starting from the item after 'start'
2115// or the beginning if 'start' is -1.
2116long wxListCtrl::FindItem (
2117 long lStart
2118, long lData
2119)
2120{
2121 long lIdx = lStart + 1;
2122 long lCount = GetItemCount();
2123
2124 while (lIdx < lCount)
2125 {
2126 if (GetItemData(lIdx) == lData)
2127 return lIdx;
2128 lIdx++;
2129 };
2130 return -1;
2131} // end of wxListCtrl::FindItem
2132
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.
2135long wxListCtrl::FindItem (
2136 long lStart
2137, const wxPoint& rPoint
2138, int nDirection
2139)
2140{
2141 RECTL vRect;
2142 QUERYRECORDRECT vQueryRect;
2143 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
2144 ,lStart
2145 );
2146 CNRINFO vCnrInfo;
2147 ULONG i;
2148 wxRect vLibRect;
2149
2150 if (!::WinSendMsg( GetHWND()
2151 ,CM_QUERYCNRINFO
2152 ,MPFROMP(&vCnrInfo)
2153 ,(MPARAM)(USHORT)sizeof(CNRINFO)
2154 ))
2155 return -1L;
2156
2157 vQueryRect.cb = sizeof(QUERYRECORDRECT);
2158 vQueryRect.pRecord = &pRecord->m_vRecord;
2159 vQueryRect.fRightSplitWindow = TRUE;
2160 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
2161
2162 ::WinSendMsg( GetHWND()
2163 ,CM_QUERYRECORDRECT
2164 ,MPFROMP(&vRect)
2165 ,MPFROMP(&vQueryRect)
2166 );
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;
2173
2174 for (i = lStart + 1; i < vCnrInfo.cRecords; i++)
2175 {
2176 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
2177 ,CM_QUERYRECORD
2178 ,MPFROMP(pRecord)
2179 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
2180 ));
2181 vQueryRect.pRecord = (PRECORDCORE)pRecord;
2182 ::WinSendMsg( GetHWND()
2183 ,CM_QUERYRECORDRECT
2184 ,MPFROMP(&vRect)
2185 ,MPFROMP(&vQueryRect)
2186 );
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;
2193 }
2194 return -1L;
2195} // end of wxListCtrl::FindItem
2196
2197// Determines which item (if any) is at the specified point,
2198// giving details in 'flags' (see wxLIST_HITTEST_... flags above)
2199long wxListCtrl::HitTest (
2200 const wxPoint& rPoint
2201, int& WXUNUSED(rFlags)
2202)
2203{
2204 PMYRECORD pRecord = NULL;
2205 QUERYRECFROMRECT vQueryRect;
2206 RECTL vRect;
2207 long lHeight;
2208
2209 //
2210 // Get height for OS/2 point conversion
2211 //
2212 ::WinSendMsg( GetHWND()
2213 ,CM_QUERYVIEWPORTRECT
2214 ,MPFROMP(&vRect)
2215 ,MPFROM2SHORT(CMA_WINDOW, TRUE)
2216 );
2217 lHeight = vRect.yTop - vRect.yBottom;
2218
2219 //
2220 // For now just try and get a record in the general vicinity and forget
2221 // the flag
2222 //
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;
2227
2228 vQueryRect.cb = sizeof(QUERYRECFROMRECT);
2229 vQueryRect.rect = vRect;
2230 vQueryRect.fsSearch = CMA_PARTIAL;
2231
2232 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2233 ,CM_QUERYRECORDFROMRECT
2234 ,(MPARAM)CMA_FIRST
2235 ,MPFROMP(&vQueryRect)
2236 );
2237
2238 if (!pRecord)
2239 return -1L;
2240 return pRecord->m_ulItemId;
2241} // end of wxListCtrl::HitTest
2242
2243// Inserts an item, returning the index of the new item if successful,
2244// -1 otherwise.
2245long wxListCtrl::InsertItem (
2246 wxListItem& rInfo
2247)
2248{
2249 wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual controls") );
2250
378ad957
DW
2251 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND()
2252 ,rInfo.GetColumn()
2253 );
2254 PMYRECORD pRecordAfter = NULL;
c4f4cf89
DW
2255 PMYRECORD pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2256 ,CM_ALLOCRECORD
2257 ,MPFROMLONG(sizeof(MYRECORD) - sizeof(RECORDCORE))
378ad957 2258 ,MPFROMSHORT(1)
c4f4cf89 2259 );
378ad957
DW
2260
2261 ConvertToOS2ListItem( this
2262 ,rInfo
2263 ,pRecord
2264 ,pFieldInfo
2265 );
2266
2267 if (rInfo.GetId() > 0)
2268 pRecordAfter = FindOS2ListRecordByID( GetHWND()
2269 ,rInfo.GetId() - 1
2270 );
2271
c4f4cf89
DW
2272 RECORDINSERT vInsert;
2273
2274 vInsert.cb = sizeof(RECORDINSERT);
c4f4cf89 2275 vInsert.pRecordParent = NULL;
378ad957
DW
2276 if (!pRecordAfter)
2277 vInsert.pRecordOrder = (PRECORDCORE)CMA_FIRST;
2278 else
2279 vInsert.pRecordOrder = (PRECORDCORE)pRecordAfter;
c4f4cf89
DW
2280 vInsert.zOrder = CMA_TOP;
2281 vInsert.cRecordsInsert = 1;
378ad957 2282 vInsert.fInvalidateRecord = TRUE;
c4f4cf89
DW
2283
2284 //
2285 // Check wether we need to allocate our internal data
2286 //
2287 bool bNeedInternalData = ((rInfo.GetMask() & wxLIST_MASK_DATA) ||
2288 rInfo.HasAttributes()
2289 );
2290 if (bNeedInternalData)
2291 {
fec9cc08 2292 m_bAnyInternalData = true;
c4f4cf89
DW
2293
2294 //
2295 // Internal stucture that manages data
2296 //
2297 CListItemInternalData* pData = new CListItemInternalData();
2298
2299 pRecord->m_ulUserData = (unsigned long)pData;
2300 if (rInfo.GetMask() & wxLIST_MASK_DATA)
2301 pData->m_lParam = (WXLPARAM)rInfo.GetData();
2302
2303 //
2304 // Check whether it has any custom attributes
2305 //
2306 if (rInfo.HasAttributes())
2307 {
2308 //
2309 // Take copy of attributes
2310 //
2311 pData->m_pAttr = new wxListItemAttr(*rInfo.GetAttributes());
2312 }
2313 }
378ad957
DW
2314 if (!::WinSendMsg( GetHWND()
2315 ,CM_INSERTRECORD
2316 ,MPFROMP(pRecord)
2317 ,MPFROMP(&vInsert)
2318 ))
2319 return -1;
c4f4cf89
DW
2320 //
2321 // OS/2 must mannually bump the index's of following records
2322 //
2323 BumpRecordIds( GetHWND()
2324 ,pRecord
2325 );
378ad957
DW
2326 ::WinSendMsg( GetHWND()
2327 ,CM_INVALIDATEDETAILFIELDINFO
2328 ,NULL
2329 ,NULL
2330 );
c4f4cf89
DW
2331 return pRecord->m_ulItemId;
2332} // end of wxListCtrl::InsertItem
2333
2334long wxListCtrl::InsertItem (
2335 long lIndex
2336, const wxString& rsLabel
2337)
2338{
2339 wxListItem vInfo;
2340
378ad957 2341 memset(&vInfo, '\0', sizeof(wxListItem));
c4f4cf89
DW
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
2347
2348// Inserts an image item
2349long wxListCtrl::InsertItem (
2350 long lIndex
2351, int nImageIndex
2352)
2353{
2354 wxListItem vInfo;
2355
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
2361
2362// Inserts an image/string item
2363long wxListCtrl::InsertItem (
2364 long lIndex
2365, const wxString& rsLabel
2366, int nImageIndex
2367)
2368{
2369 wxListItem vInfo;
2370
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
2377
2378// For details view mode (only), inserts a column.
2379long wxListCtrl::InsertColumn (
2380 long lCol
2381, wxListItem& rItem
2382)
2383{
2384 bool bSuccess;
2385 PFIELDINFO pField = (PFIELDINFO)::WinSendMsg( GetHWND()
2386 ,CM_ALLOCDETAILFIELDINFO
2387 ,MPFROMLONG(1)
2388 ,NULL
2389 );
2390 PFIELDINFO pFieldAfter = FindOS2ListFieldByColNum ( GetHWND()
2391 ,lCol - 1
2392 );
2393 FIELDINFOINSERT vInsert;
2394
378ad957
DW
2395 ConvertToOS2ListCol ( lCol
2396 ,rItem
2397 ,pField
2398 );
2399
c4f4cf89
DW
2400 vInsert.cb = sizeof(FIELDINFOINSERT);
2401 vInsert.pFieldInfoOrder = pFieldAfter;
2402 vInsert.fInvalidateFieldInfo = TRUE;
2403 vInsert.cFieldInfoInsert = 1;
2404
c4f4cf89
DW
2405 bSuccess = ::WinSendMsg( GetHWND()
2406 ,CM_INSERTDETAILFIELDINFO
2407 ,MPFROMP(pField)
2408 ,MPFROMP(&vInsert)
2409 ) != (MRESULT)0;
2410 return bSuccess;
2411} // end of wxListCtrl::InsertColumn
2412
2413long wxListCtrl::InsertColumn (
2414 long lCol
2415, const wxString& rsHeading
2416, int nFormat
2417, int nWidth
2418)
2419{
2420 wxListItem vItem;
2421
2422 vItem.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
2423 vItem.m_text = rsHeading;
2424 if (nWidth > -1)
2425 {
2426 vItem.m_mask |= wxLIST_MASK_WIDTH;
2427 vItem.m_width = nWidth;
2428 }
2429 vItem.m_format = nFormat;
2430
2431 return InsertColumn( lCol
2432 ,vItem
2433 );
2434} // end of wxListCtrl::InsertColumn
2435
2436// scroll the control by the given number of pixels (exception: in list view,
2437// dx is interpreted as number of columns)
fec9cc08 2438bool wxListCtrl::ScrollList ( int nDx, int nDy )
c4f4cf89
DW
2439{
2440 if (nDx > 0)
2441 ::WinSendMsg( GetHWND()
2442 ,CM_SCROLLWINDOW
2443 ,(MPARAM)CMA_HORIZONTAL
2444 ,(MPARAM)nDx
2445 );
2446 if (nDy > 0)
2447 ::WinSendMsg( GetHWND()
2448 ,CM_SCROLLWINDOW
2449 ,(MPARAM)CMA_VERTICAL
2450 ,(MPARAM)nDy
2451 );
fec9cc08 2452 return true;
c4f4cf89
DW
2453} // end of wxListCtrl::ScrollList
2454
fec9cc08 2455bool wxListCtrl::SortItems ( wxListCtrlCompare fn, long lData )
c4f4cf89 2456{
fec9cc08 2457 SInternalDataSort vInternalData;
c4f4cf89
DW
2458
2459 vInternalData.m_fnUser = fn;
2460 vInternalData.m_lData = lData;
2461
2462 // WPARAM cast is needed for mingw/cygwin
2463 if (!::WinSendMsg( GetHWND()
2464 ,CM_SORTRECORD
2465 ,(PFN)InternalDataCompareFunc
2466 ,(PVOID)&vInternalData
2467 ))
2468 {
2469 wxLogDebug(_T("CM_SORTRECORD failed"));
fec9cc08 2470 return false;
c4f4cf89 2471 }
fec9cc08 2472 return true;
c4f4cf89
DW
2473} // end of wxListCtrl::SortItems
2474
2475// ----------------------------------------------------------------------------
2476// message processing
2477// ----------------------------------------------------------------------------
2478
fec9cc08 2479bool wxListCtrl::OS2Command ( WXUINT uCmd, WXWORD wId )
c4f4cf89
DW
2480{
2481 if (uCmd == CN_ENDEDIT)
2482 {
fec9cc08 2483 wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED, wId );
c4f4cf89
DW
2484
2485 vEvent.SetEventObject( this );
2486 ProcessCommand(vEvent);
fec9cc08 2487 return true;
c4f4cf89
DW
2488 }
2489 else if (uCmd == CN_KILLFOCUS)
2490 {
fec9cc08 2491 wxCommandEvent vEvent( wxEVT_KILL_FOCUS, wId );
c4f4cf89
DW
2492 vEvent.SetEventObject( this );
2493 ProcessCommand(vEvent);
fec9cc08 2494 return true;
c4f4cf89
DW
2495 }
2496 else
fec9cc08 2497 return false;
c4f4cf89
DW
2498} // end of wxListCtrl::OS2Command
2499
2500// Necessary for drawing hrules and vrules, if specified
fec9cc08 2501void wxListCtrl::OnPaint ( wxPaintEvent& rEvent )
c4f4cf89
DW
2502{
2503 wxPaintDC vDc(this);
2504 wxPen vPen(wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT)
2505 ,1
2506 ,wxSOLID
2507 );
2508 wxSize vClientSize = GetClientSize();
2509 wxRect vItemRect;
2510 int nItemCount = GetItemCount();
2511 int nCy = 0;
2512 int i;
2513 bool bDrawHRules = ((GetWindowStyle() & wxLC_HRULES) != 0);
2514 bool bDrawVRules = ((GetWindowStyle() & wxLC_VRULES) != 0);
2515
2516 wxControl::OnPaint(rEvent);
2517
2518 //
2519 // Reset the device origin since it may have been set
2520 //
2521 vDc.SetDeviceOrigin(0, 0);
2522 if (!bDrawHRules && !bDrawVRules)
2523 return;
2524 if ((GetWindowStyle() & wxLC_REPORT) == 0)
2525 return;
2526 vDc.SetPen(vPen);
2527 vDc.SetBrush(*wxTRANSPARENT_BRUSH);
2528
2529 if (bDrawHRules)
2530 {
2531 long lTop = GetTopItem();
2532
2533 for (i = lTop; i < lTop + GetCountPerPage() + 1; i++)
2534 {
2535 if (GetItemRect( i
2536 ,vItemRect
2537 ))
2538 {
2539 nCy = vItemRect.GetTop();
2540 if (i != 0) // Don't draw the first one
2541 {
2542 vDc.DrawLine( 0
2543 ,nCy
2544 ,vClientSize.x
2545 ,nCy
2546 );
2547 }
2548 // Draw last line
2549 if (i == nItemCount - 1)
2550 {
2551 nCy = vItemRect.GetBottom();
2552 vDc.DrawLine( 0
2553 ,nCy
2554 ,vClientSize.x
2555 ,nCy
2556 );
2557 }
2558 }
2559 }
2560 }
2561 i = nItemCount - 1;
2562 if (bDrawVRules && (i > -1))
2563 {
2564 wxRect vFirstItemRect;
2565
2566 GetItemRect( 0
2567 ,vFirstItemRect
2568 );
2569 if (GetItemRect( i
2570 ,vItemRect
2571 ))
2572 {
2573 int nCol;
2574 int nX = vItemRect.GetX();
2575
2576 for (nCol = 0; nCol < GetColumnCount(); nCol++)
2577 {
2578 int nColWidth = GetColumnWidth(nCol);
2579
2580 nX += nColWidth ;
2581 vDc.DrawLine( nX - 1
2582 ,vFirstItemRect.GetY() - 2
2583 ,nX - 1
2584 ,vItemRect.GetBottom()
2585 );
2586 }
2587 }
2588 }
2589} // end of wxListCtrl::OnPaint
2590
2591// ----------------------------------------------------------------------------
2592// virtual list controls
2593// ----------------------------------------------------------------------------
2594
2595wxString wxListCtrl::OnGetItemText (
2596 long WXUNUSED(lItem)
2597, long WXUNUSED(lCol)
2598) const
2599{
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
2605
2606int wxListCtrl::OnGetItemImage (
2607 long WXUNUSED(lItem)
2608) const
2609{
2610 // same as above
2611 wxFAIL_MSG( _T("not supposed to be called") );
2612 return -1;
2613} // end of wxListCtrl::OnGetItemImage
2614
208458a7
RD
2615int wxListCtrl::OnGetItemColumnImage (
2616 long lItem,
2617 long lColumn
2618) const
2619{
2620 if (!lColumn)
2621 return OnGetItemImage(lItem);
2622
2623 return -1;
2624} // end of wxListCtrl::OnGetItemColumnImage
2625
c4f4cf89
DW
2626wxListItemAttr* wxListCtrl::OnGetItemAttr (
2627 long WXUNUSED_UNLESS_DEBUG(lItem)
2628) const
2629{
2630 wxASSERT_MSG( lItem >= 0 && lItem < GetItemCount(),
2631 _T("invalid item index in OnGetItemAttr()") );
2632
2633 //
2634 // No attributes by default
2635 //
2636 return NULL;
2637} // end of wxListCtrl::OnGetItemAttr
2638
2639void wxListCtrl::SetItemCount (
2640 long lCount
2641)
2642{
2643 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
2644
2645 //
2646 // Cannot explicitly set the record count in OS/2
2647 //
2648} // end of wxListCtrl::SetItemCount
2649
2650void wxListCtrl::RefreshItem (
2651 long lItem
2652)
2653{
2654 wxRect vRect;
2655
2656 GetItemRect( lItem
2657 ,vRect
2658 );
2659 RefreshRect(vRect);
2660} // end of wxListCtrl::RefreshItem
2661
fec9cc08 2662void wxListCtrl::RefreshItems ( long lItemFrom, long lItemTo )
c4f4cf89 2663{
fec9cc08
WS
2664 wxRect vRect1;
2665 wxRect vRect2;
c4f4cf89 2666
fec9cc08
WS
2667 GetItemRect( lItemFrom , vRect1 );
2668 GetItemRect( lItemTo , vRect2 );
c4f4cf89 2669
fec9cc08 2670 wxRect vRect = vRect1;
c4f4cf89
DW
2671
2672 vRect.height = vRect2.GetBottom() - vRect1.GetTop();
2673 RefreshRect(vRect);
2674} // end of wxListCtrl::RefreshItems
2675
fec9cc08
WS
2676MRESULT wxListCtrl::OS2WindowProc( WXUINT uMsg,
2677 WXWPARAM wParam,
2678 WXLPARAM lParam )
c4f4cf89 2679{
fec9cc08 2680 bool bProcessed = false;
c4f4cf89
DW
2681 MRESULT lRc;
2682 wxListEvent vEvent( wxEVT_NULL
2683 ,m_windowId
2684 );
2685 wxEventType vEventType = wxEVT_NULL;
2686 PCNRDRAGINIT pDragInit = NULL;
2687 PCNREDITDATA pEditData = NULL;
2688 PNOTIFYRECORDENTER pNotifyEnter = NULL;
2689
2690 vEvent.SetEventObject(this);
2691 switch (uMsg)
2692 {
2693 case WM_CONTROL:
2694 //
2695 // First off let's set some internal data
2696 //
2697 switch(SHORT2FROMMP(wParam))
2698 {
2699 case CN_INITDRAG:
2700 case CN_DRAGOVER:
2701 case CN_DRAGAFTER:
2702 {
2703 CListItemInternalData* pInternaldata = (CListItemInternalData *)lParam;
2704
2705 if (pInternaldata)
2706 {
2707 wxListItem* pItem = (wxListItem*)&vEvent.GetItem();
2708
2709 pItem->SetData((long)pInternaldata->m_lParam);
2710 }
2711 }
2712 break;
2713 }
2714 //
2715 // Now let's go through the codes we're interested in
2716 //
2717 switch(SHORT2FROMMP(wParam))
2718 {
2719 case CN_INITDRAG:
2720 pDragInit = (PCNRDRAGINIT)lParam;
2721 if (pDragInit)
2722 {
2723 PMYRECORD pRecord = (PMYRECORD)pDragInit->pRecord;
2724
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;
2729 }
2730 break;
2731
2732 case CN_BEGINEDIT:
2733 pEditData = (PCNREDITDATA)lParam;
2734 if (pEditData)
2735 {
2736 vEventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT;
2737 ConvertFromOS2ListItem( GetHWND()
2738 ,(wxListItem &)vEvent.GetItem()
2739 ,(PMYRECORD)pEditData->pRecord
2740 );
2741 vEvent.m_itemIndex = vEvent.GetItem().GetId();
2742 }
2743 break;
2744
2745 case CN_ENDEDIT:
2746 pEditData = (PCNREDITDATA)lParam;
2747 if (pEditData)
2748 {
2749 vEventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT;
2750 ConvertFromOS2ListItem( GetHWND()
2751 ,(wxListItem &)vEvent.GetItem()
2752 ,(PMYRECORD)pEditData->pRecord
2753 );
2754 if (pEditData->cbText == 0)
2755 return (MRESULT)FALSE;
2756 vEvent.m_itemIndex = vEvent.GetItem().GetId();
2757 }
2758 break;
2759
2760 case CN_ENTER:
2761 pNotifyEnter = (PNOTIFYRECORDENTER)lParam;
2762 if (pNotifyEnter)
2763 {
2764 wxListItem* pItem = (wxListItem*)&vEvent.GetItem();
2765 PMYRECORD pMyRecord = (PMYRECORD)pNotifyEnter->pRecord;
2766
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));
2771 }
2772 break;
2773
2774 //
2775 // Add the CN_DROP messages for Direct Manipulation
2776 //
2777 }
2778 vEvent.SetEventType(vEventType);
2779 bProcessed = GetEventHandler()->ProcessEvent(vEvent);
2780 break;
2781 }
2782 if (!bProcessed)
2783 lRc = wxControl::OS2WindowProc( uMsg
2784 ,wParam
2785 ,lParam
2786 );
2787 return lRc;
2788} // end of wxListCtrl::WindowProc
2789
2790#endif // wxUSE_LISTCTRL