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