1/////////////////////////////////////////////////////////////////////////////
2// Name:        src/os2/combobox.cpp
3// Purpose:     wxComboBox class
4// Author:      David Webster
5// Modified by:
6// Created:     10/13/99
7// RCS-ID:      $Id: combobox.cpp 42872 2006-10-31 20:46:35Z SN $
8// Copyright:   (c) David Webster
9// Licence:     wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#if wxUSE_COMBOBOX
16
17#include "wx/combobox.h"
18
19#ifndef WX_PRECOMP
20    #include "wx/settings.h"
21#endif
22
23#include "wx/clipbrd.h"
24#include "wx/os2/private.h"
25
26#define OWNER_DRAWN_LISTBOX_EXTRA_SPACE    (1)
27
28MRESULT EXPENTRY wxComboEditWndProc( HWND   hWnd
29                                    ,UINT   uMessage
30                                    ,MPARAM wParam
31                                    ,MPARAM lParam
32                                   );
33//
34// The pointer to standard wnd proc
35//
36static WXFARPROC gfnWndprocEdit     = (WXFARPROC)NULL;
37
38IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl)
39
40bool wxComboBox::OS2Command( WXUINT uParam, WXWORD WXUNUSED(wId) )
41{
42    long lSel = GetSelection();
43    wxString sValue;
44
45    switch (uParam)
46    {
47        case CBN_LBSELECT:
48            if (lSel > -1)
49            {
50                wxCommandEvent vEvent( wxEVT_COMMAND_COMBOBOX_SELECTED, GetId() );
51
52                vEvent.SetInt(lSel);
53                vEvent.SetEventObject(this);
54                vEvent.SetString(GetStringSelection());
55
56                ProcessCommand(vEvent);
57            }
58            break;
59
60        case CBN_EFCHANGE:
61            {
62                wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED, GetId() );
63
64                if (lSel == -1L)
65                    sValue = GetValue();
66                else
67                    sValue = GetStringSelection();
68                vEvent.SetString(sValue);
69                vEvent.SetEventObject(this);
70                ProcessCommand(vEvent);
71            }
72            break;
73    }
74    //
75    // There is no return value for the CBN_ notifications, so always return
76    // false from here to pass the message to DefWindowProc()
77    //
78    return false;
79} // end of wxComboBox::OS2Command
80
81bool wxComboBox::Create(
82  wxWindow*                         pParent
83, wxWindowID                        vId
84, const wxString&                   rsValue
85, const wxPoint&                    rPos
86, const wxSize&                     rSize
87, const wxArrayString&              asChoices
88, long                              lStyle
89, const wxValidator&                rValidator
90, const wxString&                   rsName
91)
92{
93    wxCArrayString chs(asChoices);
94
95    return Create(pParent, vId, rsValue, rPos, rSize, chs.GetCount(),
96                  chs.GetStrings(), lStyle, rValidator, rsName);
97}
98
99bool wxComboBox::Create(
100  wxWindow*                         pParent
101, wxWindowID                        vId
102, const wxString&                   rsValue
103, const wxPoint&                    rPos
104, const wxSize&                     rSize
105, int                               n
106, const wxString                    asChoices[]
107, long                              lStyle
108, const wxValidator&                rValidator
109, const wxString&                   rsName
110)
111{
112    m_isShown = false;
113
114    if (!CreateControl( pParent
115                       ,vId
116                       ,rPos
117                       ,rSize
118                       ,lStyle
119                       ,rValidator
120                       ,rsName
121                      ))
122        return false;
123
124    //
125    // Get the right style
126    //
127    long                            lSstyle = 0L;
128
129    lSstyle = WS_TABSTOP   |
130              WS_VISIBLE;
131
132    // clipping siblings does not yet work
133    // if (lStyle & wxCLIP_SIBLINGS )
134    //     lSstyle |= WS_CLIPSIBLINGS;
135    if (lStyle & wxCB_READONLY)
136        lSstyle |= CBS_DROPDOWNLIST;
137    else if (lStyle & wxCB_SIMPLE)
138        lSstyle |= CBS_SIMPLE; // A list (shown always) and edit control
139    else
140        lSstyle |= CBS_DROPDOWN;
141
142
143    if (!OS2CreateControl( _T("COMBOBOX")
144                          ,lSstyle
145                         ))
146        return false;
147
148    //
149    // A choice/combobox normally has a white background (or other, depending
150    // on global settings) rather than inheriting the parent's background colour.
151    //
152    SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
153
154    for (int i = 0; i < n; i++)
155    {
156        Append(asChoices[i]);
157    }
158
159    SetSize( rPos.x
160            ,rPos.y
161            ,rSize.x
162            ,rSize.y
163           );
164
165    // Set height to use with sizers i.e. without the dropdown listbox
166    wxFont vFont = GetFont();
167    int nEditHeight;
168    wxGetCharSize( GetHWND(), NULL, &nEditHeight, &vFont );
169    nEditHeight = EDIT_HEIGHT_FROM_CHAR_HEIGHT(nEditHeight);
170    SetInitialSize(wxSize(-1,nEditHeight+4));   // +2x2 for the border
171
172    if (!rsValue.empty())
173    {
174        SetValue(rsValue);
175    }
176    gfnWndprocEdit = (WXFARPROC)::WinSubclassWindow( (HWND)GetHwnd()
177                                                    ,(PFNWP)wxComboEditWndProc
178                                                   );
179    ::WinSetWindowULong(GetHwnd(), QWL_USER, (ULONG)this);
180    Show(true);
181    return true;
182} // end of wxComboBox::Create
183
184wxString wxComboBox::GetValue() const
185{
186    return wxGetWindowText(GetHwnd());
187}
188
189void wxComboBox::SetValue(
190  const wxString&                   rsValue
191)
192{
193    if ( HasFlag(wxCB_READONLY) )
194        SetStringSelection(rsValue);
195    else
196        ::WinSetWindowText(GetHwnd(), (PSZ)rsValue.c_str());
197} // end of wxComboBox::SetValue
198
199//
200// Clipboard operations
201//
202void wxComboBox::Copy()
203{
204    HWND                            hWnd = GetHwnd();
205
206    ::WinSendMsg(hWnd, EM_COPY, (MPARAM)0, (MPARAM)0);
207} // end of wxComboBox::Copy
208
209void wxComboBox::Cut()
210{
211    HWND                            hWnd = GetHwnd();
212
213    ::WinSendMsg(hWnd, EM_CUT, (MPARAM)0, (MPARAM)0);
214} // end of wxComboBox::Cut
215
216void wxComboBox::Paste()
217{
218    HWND                            hWnd = GetHwnd();
219
220    ::WinSendMsg(hWnd, EM_PASTE, (MPARAM)0, (MPARAM)0);
221} // end of wxComboBox::Paste
222
223void wxComboBox::SetEditable(
224  bool                              bEditable
225)
226{
227    HWND                            hWnd = GetHwnd();
228
229    ::WinSendMsg(hWnd, EM_SETREADONLY, (MPARAM)!bEditable, (MPARAM)0L);
230} // end of wxComboBox::SetEditable
231
232void wxComboBox::SetInsertionPoint(
233  long                              lPos
234)
235{
236    HWND                            hWnd = GetHwnd();
237
238    ::WinSendMsg(hWnd, EM_SETFIRSTCHAR, MPFROMLONG(lPos), (MPARAM)0);
239} // end of wxComboBox::SetInsertionPoint
240
241void wxComboBox::SetInsertionPointEnd()
242{
243    wxTextPos                       lPos = GetLastPosition();
244
245    SetInsertionPoint(lPos);
246} // end of wxComboBox::SetInsertionPointEnd
247
248long wxComboBox::GetInsertionPoint() const
249{
250    long                            lPos = LONGFROMMR(::WinSendMsg( GetHwnd()
251                                                                   ,LM_QUERYSELECTION
252                                                                   ,(MPARAM)0
253                                                                   ,(MPARAM)0
254                                                                  ));
255   if (lPos == LIT_NONE)
256        return wxNOT_FOUND;
257   return lPos;
258} // end of wxComboBox::GetInsertionPoint
259
260wxTextPos wxComboBox::GetLastPosition() const
261{
262    long                            lLineLength = 0L;
263    WNDPARAMS                       vParams;
264
265    //
266    // Get number of characters in the last (only) line. We'll add this to the character
267    // index for the last line, 1st position.
268    //
269
270
271    vParams.fsStatus = WPM_CCHTEXT;
272    if (::WinSendMsg( GetHwnd()
273                     ,WM_QUERYWINDOWPARAMS
274                     ,&vParams
275                     ,0
276                    ))
277    {
278        lLineLength = (long)vParams.cchText;
279    }
280    else
281        lLineLength = 0L;
282    return lLineLength;
283} // end of wxComboBox::GetLastPosition
284
285void wxComboBox::Replace( long lFrom,
286                          long lTo,
287                          const wxString& rsValue )
288{
289#if wxUSE_CLIPBOARD
290    HWND                            hWnd = GetHwnd();
291
292    //
293    // Set selection and remove it
294    //
295    ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0);
296    ::WinSendMsg(hWnd, EM_CUT, (MPARAM)0, (MPARAM)0);
297
298    //
299    // Now replace with 'value', by pasting.
300    //
301    wxSetClipboardData( wxDF_TEXT
302                       ,(wxObject *)rsValue.c_str()
303                       ,0
304                       ,0
305                      );
306
307    //
308    // Paste into edit control
309    //
310    ::WinSendMsg(hWnd, EM_PASTE, (MPARAM)0, (MPARAM)0L);
311#else
312    wxUnusedVar(lFrom);
313    wxUnusedVar(lTo);
314    wxUnusedVar(rsValue);
315#endif
316} // end of wxComboBox::Replace
317
318void wxComboBox::Remove( long lFrom, long lTo)
319{
320#if wxUSE_CLIPBOARD
321    HWND                            hWnd = GetHwnd();
322
323    ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0);
324    ::WinSendMsg(hWnd, EM_CUT, (MPARAM)0, (MPARAM)0);
325#else
326    wxUnusedVar(lFrom);
327    wxUnusedVar(lTo);
328#endif
329} // end of wxComboBox::Remove
330
331void wxComboBox::SetSelection( long lFrom, long lTo )
332{
333    HWND hWnd = GetHwnd();
334    long lFromChar = 0;
335    long lToChar   = 0;
336
337    //
338    // If from and to are both -1, it means
339    // (in wxWidgets) that all text should be selected.
340    // This translates into Windows convention
341    //
342    if ((lFrom == -1L) && (lTo == -1L))
343    {
344        lFromChar = 0;
345        lToChar = -1;
346    }
347
348    ::WinSendMsg( hWnd
349                 ,EM_SETSEL
350                 ,MPFROM2SHORT((USHORT)lFromChar, (USHORT)lToChar)
351                 ,(MPARAM)0
352                );
353} // end of wxComboBox::SetSelection
354
355bool wxComboBox::ProcessEditMsg(
356  WXUINT                            uMsg
357, WXWPARAM                          wParam
358, WXLPARAM                          lParam)
359{
360    SHORT                           vFlag;
361    switch (uMsg)
362    {
363        case WM_CHAR:
364            vFlag = SHORT1FROMMP(wParam);
365            switch(vFlag)
366            {
367                case KC_CHAR:
368                    return (HandleChar( wParam
369                                       ,lParam
370                                       ,true /* isASCII */
371                                      ));
372
373                case KC_PREVDOWN:
374                    return (HandleKeyDown( wParam
375                                          ,lParam
376                                         ));
377
378                case KC_KEYUP:
379                    return (HandleKeyUp( wParam
380                                        ,lParam
381                                       ));
382            }
383            break;
384
385        case WM_SETFOCUS:
386            if (SHORT1FROMMP((MPARAM)lParam) == TRUE)
387                return(HandleSetFocus((WXHWND)(HWND)wParam));
388            else
389                return(HandleKillFocus((WXHWND)(HWND)wParam));
390    }
391    return false;
392} // end of wxComboBox::ProcessEditMsg
393
394MRESULT EXPENTRY wxComboEditWndProc(
395  HWND                              hWnd
396, UINT                              uMessage
397, MPARAM                            wParam
398, MPARAM                            lParam
399)
400{
401    switch (uMessage)
402    {
403        //
404        // Forward some messages to the combobox
405        //
406        case WM_SETFOCUS:
407        case WM_CHAR:
408            {
409                wxComboBox* pCombo = (wxComboBox *)::WinQueryWindowULong( hWnd
410                                                                         ,QWL_USER
411                                                                        );
412
413                if (pCombo->ProcessEditMsg( uMessage
414                                           ,wParam
415                                           ,lParam
416                                          ))
417                    return ((MRESULT)0);
418            }
419            break;
420
421        //
422        // TODO: Deal with tooltips here
423        //
424    }
425    return (gfnWndprocEdit(hWnd, (ULONG)uMessage, (MPARAM)wParam, (MPARAM)lParam));
426} // end of wxComboEditWndProc
427
428#endif
429 // wxUSE_COMBOBOX
430