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