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