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