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