]> git.saurik.com Git - wxWidgets.git/blame - src/msw/textentry.cpp
Always link with expat in monolithic build.
[wxWidgets.git] / src / msw / textentry.cpp
CommitLineData
69a05ef6
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/msw/textentry.cpp
3// Purpose: wxTextEntry implementation for wxMSW
4// Author: Vadim Zeitlin
5// Created: 2007-09-26
6// RCS-ID: $Id$
7// Copyright: (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// for compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#ifndef WX_PRECOMP
96506d1d 27 #include "wx/arrstr.h"
c0ae6c3b 28 #include "wx/string.h"
69a05ef6
VZ
29#endif // WX_PRECOMP
30
96a4cdeb
VZ
31#if wxUSE_TEXTCTRL || wxUSE_COMBOBOX
32
69a05ef6 33#include "wx/textentry.h"
ea98f11c 34#include "wx/textcompleter.h"
59396417 35#include "wx/dynlib.h"
69a05ef6 36
b4f70f77
VS
37#include <initguid.h>
38
69a05ef6
VZ
39#include "wx/msw/private.h"
40
63f7d502
VZ
41#if wxUSE_UXTHEME
42 #include "wx/msw/uxtheme.h"
43#endif
44
69a05ef6
VZ
45#define GetEditHwnd() ((HWND)(GetEditHWND()))
46
0847dca6 47// ----------------------------------------------------------------------------
e71e4c93 48// Classes used by auto-completion implementation.
0847dca6
VZ
49// ----------------------------------------------------------------------------
50
fd873451
VZ
51// standard VC6 SDK (WINVER == 0x0400) does not know about IAutoComplete
52#if wxUSE_OLE && (WINVER >= 0x0500)
53 #define HAS_AUTOCOMPLETE
54#endif
55
56#ifdef HAS_AUTOCOMPLETE
0847dca6
VZ
57
58#include "wx/msw/ole/oleutils.h"
59#include <shldisp.h>
60
715e4f7e 61#if defined(__MINGW32__) || defined (__WATCOMC__) || defined(__CYGWIN__)
96506d1d
VZ
62 // needed for IID_IAutoComplete, IID_IAutoComplete2 and ACO_AUTOSUGGEST
63 #include <shlguid.h>
0f0c5856
VZ
64
65 #ifndef ACO_AUTOAPPEND
66 #define ACO_AUTOAPPEND 0x02
67 #endif
96506d1d
VZ
68#endif
69
70#ifndef ACO_UPDOWNKEYDROPSLIST
71 #define ACO_UPDOWNKEYDROPSLIST 0x20
72#endif
73
74#ifndef SHACF_FILESYS_ONLY
75 #define SHACF_FILESYS_ONLY 0x00000010
76#endif
77
03dede4d
VZ
78#ifndef SHACF_FILESYS_DIRS
79 #define SHACF_FILESYS_DIRS 0x00000020
80#endif
81
e71e4c93
VZ
82namespace
83{
84
78f250a4
VZ
85// Normally this interface and its IID are defined in shobjidl.h header file
86// included in the platform SDK but MinGW and Cygwin don't have it so redefine
87// the interface ourselves and, as long as we do it all, do it for all
88// compilers to ensure we have the same behaviour for all of them and to avoid
89// the need to check for concrete compilers and maybe even their versions.
90class IAutoCompleteDropDown : public IUnknown
91{
92public:
93 virtual HRESULT wxSTDCALL GetDropDownStatus(DWORD *, LPWSTR *) = 0;
94 virtual HRESULT wxSTDCALL ResetEnumerator() = 0;
95};
96
c6212697 97DEFINE_GUID(wxIID_IAutoCompleteDropDown,
78f250a4
VZ
98 0x3cd141f4, 0x3c6a, 0x11d2, 0xbc, 0xaa, 0x00, 0xc0, 0x4f, 0xd9, 0x29, 0xdb);
99
c6212697 100DEFINE_GUID(wxCLSID_AutoComplete,
78f250a4
VZ
101 0x00bb2763, 0x6a77, 0x11d0, 0xa5, 0x35, 0x00, 0xc0, 0x4f, 0xd7, 0xd0, 0x62);
102
e71e4c93
VZ
103// Small helper class which can be used to ensure thread safety even when
104// wxUSE_THREADS==0 (and hence wxCriticalSection does nothing).
105class CSLock
106{
107public:
108 CSLock(CRITICAL_SECTION& cs) : m_cs(&cs)
109 {
110 ::EnterCriticalSection(m_cs);
111 }
112
113 ~CSLock()
114 {
115 ::LeaveCriticalSection(m_cs);
116 }
117
118private:
119 CRITICAL_SECTION * const m_cs;
120
121 wxDECLARE_NO_COPY_CLASS(CSLock);
122};
123
124} // anonymity namespace
125
126// Implementation of string enumerator used by wxTextAutoCompleteData. This
85047589 127// class simply forwards to wxTextCompleter associated with it.
e71e4c93
VZ
128//
129// Notice that Next() method of this class is called by IAutoComplete
130// background thread and so we must care about thread safety here.
0847dca6
VZ
131class wxIEnumString : public IEnumString
132{
133public:
ea98f11c 134 wxIEnumString()
0847dca6 135 {
e71e4c93 136 Init();
0847dca6
VZ
137 }
138
85047589 139 void ChangeCompleter(wxTextCompleter *completer)
68e6eb7d 140 {
85047589
VZ
141 // Indicate to Next() that it should bail out as soon as possible.
142 {
143 CSLock lock(m_csRestart);
68e6eb7d 144
85047589
VZ
145 m_restart = TRUE;
146 }
e71e4c93 147
85047589
VZ
148 // Now try to enter this critical section to ensure that Next() doesn't
149 // use the old pointer any more before changing it (this is vital as
150 // the old pointer will be destroyed after we return).
151 CSLock lock(m_csCompleter);
152
153 m_completer = completer;
e71e4c93
VZ
154 }
155
85047589 156 void UpdatePrefix(const wxString& prefix)
e71e4c93 157 {
85047589 158 CSLock lock(m_csRestart);
e71e4c93 159
85047589
VZ
160 // We simply store the prefix here and will really update during the
161 // next call to our Next() method as we want to call Start() from the
162 // worker thread to prevent the main UI thread from blocking while the
163 // completions are generated.
e71e4c93 164 m_prefix = prefix;
85047589 165 m_restart = TRUE;
e71e4c93 166 }
0847dca6
VZ
167
168 virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt,
169 LPOLESTR *rgelt,
170 ULONG *pceltFetched)
171 {
172 if ( !rgelt || (!pceltFetched && celt > 1) )
173 return E_POINTER;
174
175 ULONG pceltFetchedDummy;
176 if ( !pceltFetched )
177 pceltFetched = &pceltFetchedDummy;
178
179 *pceltFetched = 0;
180
85047589 181 CSLock lock(m_csCompleter);
e71e4c93 182
85047589
VZ
183 if ( !RestartIfNeeded() )
184 return S_FALSE;
e71e4c93 185
85047589 186 while ( celt-- )
0847dca6 187 {
85047589
VZ
188 // Stop iterating if we need to update completions anyhow.
189 if ( m_restart )
0847dca6
VZ
190 return S_FALSE;
191
85047589
VZ
192 const wxString s = m_completer->GetNext();
193 if ( s.empty() )
194 return S_FALSE;
195
196 const wxWX2WCbuf wcbuf = s.wc_str();
0847dca6
VZ
197 const size_t size = (wcslen(wcbuf) + 1)*sizeof(wchar_t);
198 void *olestr = CoTaskMemAlloc(size);
199 if ( !olestr )
200 return E_OUTOFMEMORY;
201
202 memcpy(olestr, wcbuf, size);
203
5c33522f 204 *rgelt++ = static_cast<LPOLESTR>(olestr);
0847dca6
VZ
205
206 ++(*pceltFetched);
207 }
208
209 return S_OK;
210 }
211
212 virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt)
213 {
85047589
VZ
214 if ( !celt )
215 return E_INVALIDARG;
e71e4c93 216
85047589
VZ
217 CSLock lock(m_csCompleter);
218
219 if ( !RestartIfNeeded() )
0847dca6 220 return S_FALSE;
85047589
VZ
221
222 while ( celt-- )
223 {
224 if ( m_restart )
225 return S_FALSE;
226
227 if ( m_completer->GetNext().empty() )
228 return S_FALSE;
0847dca6
VZ
229 }
230
231 return S_OK;
232 }
233
234 virtual HRESULT STDMETHODCALLTYPE Reset()
235 {
85047589 236 CSLock lock(m_csRestart);
e71e4c93 237
85047589 238 m_restart = TRUE;
0847dca6
VZ
239
240 return S_OK;
241 }
242
243 virtual HRESULT STDMETHODCALLTYPE Clone(IEnumString **ppEnum)
244 {
245 if ( !ppEnum )
246 return E_POINTER;
247
85047589 248 CSLock lock(m_csCompleter);
0847dca6 249
85047589 250 wxIEnumString * const e = new wxIEnumString;
0847dca6 251 e->AddRef();
85047589
VZ
252
253 e->ChangeCompleter(m_completer);
254
0847dca6
VZ
255 *ppEnum = e;
256
257 return S_OK;
258 }
259
e71e4c93
VZ
260 DECLARE_IUNKNOWN_METHODS;
261
0847dca6 262private:
3eeefdf9
VZ
263 // dtor doesn't have to be virtual as we're only ever deleted from our own
264 // Release() and are not meant to be derived form anyhow, but making it
265 // virtual silences gcc warnings; making it private makes it impossible to
266 // (mistakenly) delete us directly instead of calling Release()
e71e4c93
VZ
267 virtual ~wxIEnumString()
268 {
85047589
VZ
269 ::DeleteCriticalSection(&m_csRestart);
270 ::DeleteCriticalSection(&m_csCompleter);
e71e4c93
VZ
271 }
272
273 // Common part of all ctors.
274 void Init()
275 {
85047589
VZ
276 ::InitializeCriticalSection(&m_csCompleter);
277 ::InitializeCriticalSection(&m_csRestart);
e71e4c93
VZ
278
279 m_completer = NULL;
85047589 280 m_restart = FALSE;
e71e4c93
VZ
281 }
282
85047589
VZ
283 // Restart completions generation if needed. Should be only called from
284 // inside m_csCompleter.
285 //
286 // If false is returned, it means that there are no completions and that
287 // wxTextCompleter::GetNext() shouldn't be called at all.
288 bool RestartIfNeeded()
e71e4c93 289 {
85047589
VZ
290 bool rc = true;
291 for ( ;; )
e71e4c93 292 {
85047589
VZ
293 wxString prefix;
294 LONG restart;
295 {
296 CSLock lock(m_csRestart);
3eeefdf9 297
85047589
VZ
298 prefix = m_prefix;
299 restart = m_restart;
e71e4c93 300
85047589
VZ
301 m_restart = FALSE;
302 } // Release m_csRestart before calling Start() to avoid blocking
303 // the main thread in UpdatePrefix() during its execution.
e71e4c93 304
85047589
VZ
305 if ( !restart )
306 break;
e71e4c93 307
85047589 308 rc = m_completer->Start(prefix);
e71e4c93 309 }
85047589
VZ
310
311 return rc;
e71e4c93
VZ
312 }
313
314
85047589
VZ
315 // Critical section protecting m_completer itself. It must be entered when
316 // using the pointer to ensure that we don't continue using a dangling one
317 // after it is destroyed.
318 CRITICAL_SECTION m_csCompleter;
e71e4c93 319
85047589
VZ
320 // The completer we delegate to for the completions generation. It is never
321 // NULL after the initial ChangeCompleter() call.
322 wxTextCompleter *m_completer;
0847dca6 323
e71e4c93 324
85047589
VZ
325 // Critical section m_prefix and m_restart. It should be only entered for
326 // short periods of time, i.e. we shouldn't call any wxTextCompleter
327 // methods from inside, to prevent the main thread from blocking on it in
328 // UpdatePrefix().
329 CRITICAL_SECTION m_csRestart;
330
331 // If m_restart is true, we need to call wxTextCompleter::Start() with the
332 // given prefix to restart generating the completions.
e71e4c93
VZ
333 wxString m_prefix;
334
85047589
VZ
335 // Notice that we use LONG and not bool here to ensure that reading this
336 // value is atomic (32 bit reads are atomic operations under all Windows
337 // versions but reading bool isn't necessarily).
338 LONG m_restart;
339
ea98f11c 340
85047589 341 wxDECLARE_NO_COPY_CLASS(wxIEnumString);
0847dca6
VZ
342};
343
344BEGIN_IID_TABLE(wxIEnumString)
345 ADD_IID(Unknown)
346 ADD_IID(EnumString)
347END_IID_TABLE;
348
349IMPLEMENT_IUNKNOWN_METHODS(wxIEnumString)
350
ea98f11c 351
85047589
VZ
352// This class gathers the all auto-complete-related stuff we use. It is
353// allocated on demand by wxTextEntry when AutoComplete() is called.
ea98f11c
VZ
354class wxTextAutoCompleteData wxBIND_OR_CONNECT_HACK_ONLY_BASE_CLASS
355{
356public:
357 // The constructor associates us with the given text entry.
358 wxTextAutoCompleteData(wxTextEntry *entry)
359 : m_entry(entry),
360 m_win(entry->GetEditableWindow())
361 {
362 m_autoComplete = NULL;
363 m_autoCompleteDropDown = NULL;
364 m_enumStrings = NULL;
85047589
VZ
365
366 m_fixedCompleter = NULL;
ea98f11c
VZ
367 m_customCompleter = NULL;
368
b9a46ea5 369 m_connectedCharEvent = false;
ea98f11c
VZ
370
371 // Create an object exposing IAutoComplete interface which we'll later
372 // use to get IAutoComplete2 as the latter can't be created directly,
373 // apparently.
374 HRESULT hr = CoCreateInstance
375 (
c6212697 376 wxCLSID_AutoComplete,
ea98f11c
VZ
377 NULL,
378 CLSCTX_INPROC_SERVER,
379 IID_IAutoComplete,
380 reinterpret_cast<void **>(&m_autoComplete)
381 );
382 if ( FAILED(hr) )
383 {
384 wxLogApiError(wxT("CoCreateInstance(CLSID_AutoComplete)"), hr);
385 return;
386 }
387
388 // Create a string enumerator and initialize the completer with it.
389 m_enumStrings = new wxIEnumString;
390 m_enumStrings->AddRef();
391 hr = m_autoComplete->Init(m_entry->GetEditHWND(), m_enumStrings,
392 NULL, NULL);
393 if ( FAILED(hr) )
394 {
395 wxLogApiError(wxT("IAutoComplete::Init"), hr);
396
397 m_enumStrings->Release();
398 m_enumStrings = NULL;
399
400 return;
401 }
402
403 // As explained in DoRefresh(), we need to call IAutoCompleteDropDown::
404 // ResetEnumerator() if we want to be able to change the completions on
405 // the fly. In principle we could live without it, i.e. return true
406 // from IsOk() even if this QueryInterface() fails, but it doesn't look
407 // like this is ever going to have in practice anyhow as the shell-
408 // provided IAutoComplete always implements IAutoCompleteDropDown too.
409 hr = m_autoComplete->QueryInterface
410 (
c6212697 411 wxIID_IAutoCompleteDropDown,
ea98f11c
VZ
412 reinterpret_cast<void **>(&m_autoCompleteDropDown)
413 );
414 if ( FAILED(hr) )
415 {
416 wxLogApiError(wxT("IAutoComplete::QI(IAutoCompleteDropDown)"), hr);
417 return;
418 }
419
420 // Finally set the completion options using IAutoComplete2.
421 IAutoComplete2 *pAutoComplete2 = NULL;
422 hr = m_autoComplete->QueryInterface
423 (
424 IID_IAutoComplete2,
425 reinterpret_cast<void **>(&pAutoComplete2)
426 );
427 if ( SUCCEEDED(hr) )
428 {
429 pAutoComplete2->SetOptions(ACO_AUTOSUGGEST |
b9a46ea5 430 ACO_AUTOAPPEND |
ea98f11c
VZ
431 ACO_UPDOWNKEYDROPSLIST);
432 pAutoComplete2->Release();
433 }
434 }
435
436 ~wxTextAutoCompleteData()
437 {
438 delete m_customCompleter;
85047589 439 delete m_fixedCompleter;
ea98f11c
VZ
440
441 if ( m_enumStrings )
442 m_enumStrings->Release();
443 if ( m_autoCompleteDropDown )
444 m_autoCompleteDropDown->Release();
445 if ( m_autoComplete )
446 m_autoComplete->Release();
447 }
448
449 // Must be called after creating this object to verify if initializing it
450 // succeeded.
451 bool IsOk() const
452 {
453 return m_autoComplete && m_autoCompleteDropDown && m_enumStrings;
454 }
455
456 void ChangeStrings(const wxArrayString& strings)
457 {
85047589
VZ
458 if ( !m_fixedCompleter )
459 m_fixedCompleter = new wxTextCompleterFixed;
460
461 m_fixedCompleter->SetCompletions(strings);
462
463 m_enumStrings->ChangeCompleter(m_fixedCompleter);
ea98f11c
VZ
464
465 DoRefresh();
466 }
467
468 // Takes ownership of the pointer if it is non-NULL.
469 bool ChangeCustomCompleter(wxTextCompleter *completer)
470 {
85047589
VZ
471 // Ensure that the old completer is not used any more before deleting
472 // it.
473 m_enumStrings->ChangeCompleter(completer);
474
ea98f11c
VZ
475 delete m_customCompleter;
476 m_customCompleter = completer;
477
478 if ( m_customCompleter )
479 {
480 // We postpone connecting to this event until we really need to do
481 // it (however we don't disconnect from it when we don't need it
482 // any more because we don't have wxUNBIND_OR_DISCONNECT_HACK...).
b9a46ea5 483 if ( !m_connectedCharEvent )
ea98f11c 484 {
b9a46ea5
VZ
485 m_connectedCharEvent = true;
486
487 // Use the special wxEVT_AFTER_CHAR and not the usual
488 // wxEVT_CHAR here because we need to have the updated value of
489 // the text control in this handler in order to provide
490 // completions for the correct prefix and unfortunately we
491 // don't have any way to let DefWindowProc() run from our
492 // wxEVT_CHAR handler (as we must also let the other handlers
493 // defined at wx level run first).
494 //
495 // Notice that we can't use wxEVT_COMMAND_TEXT_UPDATED here
496 // neither as, due to our use of ACO_AUTOAPPEND, we get
497 // EN_CHANGE notifications from the control every time
498 // IAutoComplete auto-appends something to it.
499 wxBIND_OR_CONNECT_HACK(m_win, wxEVT_AFTER_CHAR,
500 wxKeyEventHandler,
501 wxTextAutoCompleteData::OnAfterChar,
ea98f11c
VZ
502 this);
503 }
504
505 UpdateStringsFromCustomCompleter();
506 }
507
508 return true;
509 }
510
511 void DisableCompletion()
512 {
513 // We currently simply reset the list of possible strings as this seems
514 // to effectively disable auto-completion just fine. We could (and
515 // probably should) use IAutoComplete::Enable(FALSE) for this too but
516 // then we'd need to call Enable(TRUE) to turn it on back again later.
85047589 517 ChangeStrings(wxArrayString());
ea98f11c
VZ
518 }
519
520private:
85047589
VZ
521 // Must be called after changing the values to be returned by wxIEnumString
522 // to really make the changes stick.
ea98f11c
VZ
523 void DoRefresh()
524 {
525 m_enumStrings->Reset();
526
527 // This is completely and utterly not documented and in fact the
528 // current MSDN seems to try to discourage us from using it by saying
529 // that "there is no reason to use this method unless the drop-down
530 // list is currently visible" but actually we absolutely must call it
531 // to force the auto-completer (and not just its drop-down!) to refresh
532 // the list of completions which could have changed now. Without this
533 // call the new choices returned by GetCompletions() that hadn't been
534 // returned by it before are simply silently ignored.
535 m_autoCompleteDropDown->ResetEnumerator();
536 }
537
538 // Update the strings returned by our string enumerator to correspond to
539 // the currently valid choices according to the custom completer.
540 void UpdateStringsFromCustomCompleter()
541 {
b9a46ea5
VZ
542 // As we use ACO_AUTOAPPEND, the selected part of the text is usually
543 // the one appended by us so don't consider it as part of the
544 // user-entered prefix.
545 long from, to;
546 m_entry->GetSelection(&from, &to);
547
548 if ( to == from )
549 from = m_entry->GetLastPosition(); // Take all if no selection.
550
551 const wxString prefix = m_entry->GetRange(0, from);
552
85047589 553 m_enumStrings->UpdatePrefix(prefix);
ea98f11c
VZ
554
555 DoRefresh();
556 }
557
b9a46ea5 558 void OnAfterChar(wxKeyEvent& event)
ea98f11c 559 {
b9a46ea5
VZ
560 // Notice that we must not refresh the completions when the user
561 // presses Backspace as this would result in adding back the just
562 // erased character(s) because of ACO_AUTOAPPEND option we use.
563 if ( m_customCompleter && event.GetKeyCode() != WXK_BACK )
ea98f11c
VZ
564 UpdateStringsFromCustomCompleter();
565
566 event.Skip();
567 }
568
569
570 // The text entry we're associated with.
571 wxTextEntry * const m_entry;
572
573 // The window of this text entry.
574 wxWindow * const m_win;
575
576 // The auto-completer object itself.
577 IAutoComplete *m_autoComplete;
578
579 // Its IAutoCompleteDropDown interface needed for ResetEnumerator() call.
580 IAutoCompleteDropDown *m_autoCompleteDropDown;
581
582 // Enumerator for strings currently used for auto-completion.
583 wxIEnumString *m_enumStrings;
584
85047589
VZ
585 // Fixed string completer or NULL if none.
586 wxTextCompleterFixed *m_fixedCompleter;
587
ea98f11c
VZ
588 // Custom completer or NULL if none.
589 wxTextCompleter *m_customCompleter;
590
591 // Initially false, set to true after connecting OnTextChanged() handler.
b9a46ea5 592 bool m_connectedCharEvent;
ea98f11c
VZ
593
594
595 wxDECLARE_NO_COPY_CLASS(wxTextAutoCompleteData);
596};
597
fd873451 598#endif // HAS_AUTOCOMPLETE
0847dca6 599
69a05ef6
VZ
600// ============================================================================
601// wxTextEntry implementation
602// ============================================================================
603
ea98f11c
VZ
604// ----------------------------------------------------------------------------
605// initialization and destruction
606// ----------------------------------------------------------------------------
607
608wxTextEntry::wxTextEntry()
609{
610#ifdef HAS_AUTOCOMPLETE
611 m_autoCompleteData = NULL;
612#endif // HAS_AUTOCOMPLETE
613}
614
615wxTextEntry::~wxTextEntry()
616{
617#ifdef HAS_AUTOCOMPLETE
618 delete m_autoCompleteData;
619#endif // HAS_AUTOCOMPLETE
620}
621
0847dca6
VZ
622// ----------------------------------------------------------------------------
623// operations on text
624// ----------------------------------------------------------------------------
625
69a05ef6
VZ
626void wxTextEntry::WriteText(const wxString& text)
627{
628 ::SendMessage(GetEditHwnd(), EM_REPLACESEL, 0, (LPARAM)text.wx_str());
629}
630
135b23b2 631wxString wxTextEntry::DoGetValue() const
69a05ef6
VZ
632{
633 return wxGetWindowText(GetEditHWND());
634}
635
636void wxTextEntry::Remove(long from, long to)
637{
638 DoSetSelection(from, to, SetSel_NoScroll);
639 WriteText(wxString());
640}
641
0847dca6
VZ
642// ----------------------------------------------------------------------------
643// clipboard operations
644// ----------------------------------------------------------------------------
645
69a05ef6
VZ
646void wxTextEntry::Copy()
647{
648 ::SendMessage(GetEditHwnd(), WM_COPY, 0, 0);
649}
650
651void wxTextEntry::Cut()
652{
653 ::SendMessage(GetEditHwnd(), WM_CUT, 0, 0);
654}
655
656void wxTextEntry::Paste()
657{
658 ::SendMessage(GetEditHwnd(), WM_PASTE, 0, 0);
659}
660
0847dca6
VZ
661// ----------------------------------------------------------------------------
662// undo/redo
663// ----------------------------------------------------------------------------
664
69a05ef6
VZ
665void wxTextEntry::Undo()
666{
667 ::SendMessage(GetEditHwnd(), EM_UNDO, 0, 0);
668}
669
670void wxTextEntry::Redo()
671{
3cb6eaec 672 // same as Undo, since Undo undoes the undo
69a05ef6
VZ
673 Undo();
674 return;
675}
676
677bool wxTextEntry::CanUndo() const
678{
679 return ::SendMessage(GetEditHwnd(), EM_CANUNDO, 0, 0) != 0;
680}
681
682bool wxTextEntry::CanRedo() const
683{
684 // see comment in Redo()
685 return CanUndo();
686}
687
0847dca6
VZ
688// ----------------------------------------------------------------------------
689// insertion point and selection
690// ----------------------------------------------------------------------------
691
69a05ef6
VZ
692void wxTextEntry::SetInsertionPoint(long pos)
693{
2851cf25
VZ
694 // calling DoSetSelection(-1, -1) would select everything which is not what
695 // we want here
696 if ( pos == -1 )
697 pos = GetLastPosition();
698
69a05ef6
VZ
699 // be careful to call DoSetSelection() which is overridden in wxTextCtrl
700 // and not just SetSelection() here
701 DoSetSelection(pos, pos);
702}
703
704long wxTextEntry::GetInsertionPoint() const
705{
706 long from;
707 GetSelection(&from, NULL);
708 return from;
709}
710
711long wxTextEntry::GetLastPosition() const
712{
713 return ::SendMessage(GetEditHwnd(), EM_LINELENGTH, 0, 0);
714}
715
716void wxTextEntry::DoSetSelection(long from, long to, int WXUNUSED(flags))
717{
718 // if from and to are both -1, it means (in wxWidgets) that all text should
719 // be selected, translate this into Windows convention
720 if ( (from == -1) && (to == -1) )
721 {
722 from = 0;
723 }
724
725 ::SendMessage(GetEditHwnd(), EM_SETSEL, from, to);
726}
727
728void wxTextEntry::GetSelection(long *from, long *to) const
729{
730 DWORD dwStart, dwEnd;
731 ::SendMessage(GetEditHwnd(), EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
732
733 if ( from )
734 *from = dwStart;
735 if ( to )
736 *to = dwEnd;
737}
738
0847dca6
VZ
739// ----------------------------------------------------------------------------
740// auto-completion
741// ----------------------------------------------------------------------------
742
6502dc68 743#if wxUSE_OLE
6b30ffed
VZ
744
745#ifdef HAS_AUTOCOMPLETE
746
03dede4d 747bool wxTextEntry::DoAutoCompleteFileNames(int flags)
59396417
VZ
748{
749 typedef HRESULT (WINAPI *SHAutoComplete_t)(HWND, DWORD);
750 static SHAutoComplete_t s_pfnSHAutoComplete = (SHAutoComplete_t)-1;
751 static wxDynamicLibrary s_dllShlwapi;
752 if ( s_pfnSHAutoComplete == (SHAutoComplete_t)-1 )
753 {
9a83f860 754 if ( !s_dllShlwapi.Load(wxT("shlwapi.dll"), wxDL_VERBATIM | wxDL_QUIET) )
59396417
VZ
755 {
756 s_pfnSHAutoComplete = NULL;
757 }
758 else
759 {
760 wxDL_INIT_FUNC(s_pfn, SHAutoComplete, s_dllShlwapi);
761 }
762 }
763
764 if ( !s_pfnSHAutoComplete )
765 return false;
766
03dede4d
VZ
767 DWORD dwFlags = 0;
768 if ( flags & wxFILE )
769 dwFlags |= SHACF_FILESYS_ONLY;
770 else if ( flags & wxDIR )
771 dwFlags |= SHACF_FILESYS_DIRS;
772 else
773 {
774 wxFAIL_MSG(wxS("No flags for file name auto completion?"));
775 return false;
776 }
777
778 HRESULT hr = (*s_pfnSHAutoComplete)(GetEditHwnd(), dwFlags);
59396417
VZ
779 if ( FAILED(hr) )
780 {
9a83f860 781 wxLogApiError(wxT("SHAutoComplete()"), hr);
59396417
VZ
782
783 return false;
784 }
ea98f11c
VZ
785
786 // Disable the other kinds of completion now that we use the built-in file
787 // names completion.
788 if ( m_autoCompleteData )
789 m_autoCompleteData->DisableCompletion();
790
59396417
VZ
791 return true;
792}
793
ea98f11c 794wxTextAutoCompleteData *wxTextEntry::GetOrCreateCompleter()
0847dca6 795{
ea98f11c 796 if ( !m_autoCompleteData )
68e6eb7d 797 {
ea98f11c
VZ
798 wxTextAutoCompleteData * const ac = new wxTextAutoCompleteData(this);
799 if ( ac->IsOk() )
800 m_autoCompleteData = ac;
801 else
802 delete ac;
68e6eb7d
VZ
803 }
804
ea98f11c
VZ
805 return m_autoCompleteData;
806}
807
808bool wxTextEntry::DoAutoCompleteStrings(const wxArrayString& choices)
809{
810 wxTextAutoCompleteData * const ac = GetOrCreateCompleter();
811 if ( !ac )
0847dca6 812 return false;
0847dca6 813
ea98f11c
VZ
814 ac->ChangeStrings(choices);
815
816 return true;
817}
818
819bool wxTextEntry::DoAutoCompleteCustom(wxTextCompleter *completer)
820{
821 // First deal with the case when we just want to disable auto-completion.
822 if ( !completer )
0847dca6 823 {
ea98f11c
VZ
824 if ( m_autoCompleteData )
825 m_autoCompleteData->DisableCompletion();
826 //else: Nothing to do, we hadn't used auto-completion even before.
0847dca6 827 }
ea98f11c 828 else // Have a valid completer.
0847dca6 829 {
ea98f11c
VZ
830 wxTextAutoCompleteData * const ac = GetOrCreateCompleter();
831 if ( !ac )
832 {
833 // Delete the custom completer for consistency with the case when
834 // we succeed to avoid memory leaks in user code.
835 delete completer;
836 return false;
837 }
838
839 // This gives ownership of the custom completer to m_autoCompleteData.
840 if ( !ac->ChangeCustomCompleter(completer) )
841 return false;
0847dca6
VZ
842 }
843
0847dca6 844 return true;
6b30ffed
VZ
845}
846
fd873451 847#else // !HAS_AUTOCOMPLETE
867b485e 848
6b30ffed
VZ
849// We still need to define stubs as we declared these overrides in the header.
850
03dede4d 851bool wxTextEntry::DoAutoCompleteFileNames(int flags)
6b30ffed 852{
03dede4d 853 return wxTextEntryBase::DoAutoCompleteFileNames(flags);
6b30ffed
VZ
854}
855
856bool wxTextEntry::DoAutoCompleteStrings(const wxArrayString& choices)
857{
858 return wxTextEntryBase::DoAutoCompleteStrings(choices);
0847dca6 859}
6b30ffed 860
32bd17fc
VZ
861bool wxTextEntry::DoAutoCompleteCustom(wxTextCompleter *completer)
862{
8d43e8c6 863 return wxTextEntryBase::DoAutoCompleteCustom(completer);
32bd17fc
VZ
864}
865
6b30ffed
VZ
866#endif // HAS_AUTOCOMPLETE/!HAS_AUTOCOMPLETE
867
6502dc68 868#endif // wxUSE_OLE
0847dca6 869
0847dca6
VZ
870// ----------------------------------------------------------------------------
871// editable state
872// ----------------------------------------------------------------------------
873
69a05ef6
VZ
874bool wxTextEntry::IsEditable() const
875{
5ad3f0c8 876 return !(::GetWindowLong(GetEditHwnd(), GWL_STYLE) & ES_READONLY);
69a05ef6
VZ
877}
878
879void wxTextEntry::SetEditable(bool editable)
880{
881 ::SendMessage(GetEditHwnd(), EM_SETREADONLY, !editable, 0);
882}
883
0847dca6
VZ
884// ----------------------------------------------------------------------------
885// max length
886// ----------------------------------------------------------------------------
887
69a05ef6
VZ
888void wxTextEntry::SetMaxLength(unsigned long len)
889{
890 if ( len >= 0xffff )
891 {
892 // this will set it to a platform-dependent maximum (much more
893 // than 64Kb under NT)
894 len = 0;
895 }
896
897 ::SendMessage(GetEditHwnd(), EM_LIMITTEXT, len, 0);
898}
96a4cdeb 899
63f7d502
VZ
900// ----------------------------------------------------------------------------
901// hints
902// ----------------------------------------------------------------------------
903
904#if wxUSE_UXTHEME
905
906#ifndef EM_SETCUEBANNER
907 #define EM_SETCUEBANNER 0x1501
908 #define EM_GETCUEBANNER 0x1502
909#endif
910
911bool wxTextEntry::SetHint(const wxString& hint)
912{
913 if ( wxUxThemeEngine::GetIfActive() )
914 {
915 // notice that this message always works with Unicode strings
7591b0bb
VZ
916 //
917 // we always use TRUE for wParam to show the hint even when the window
918 // has focus, otherwise there would be no way to show the hint for the
919 // initially focused window
63f7d502 920 if ( ::SendMessage(GetEditHwnd(), EM_SETCUEBANNER,
7591b0bb 921 TRUE, (LPARAM)(const wchar_t *)hint.wc_str()) )
63f7d502
VZ
922 return true;
923 }
924
925 return wxTextEntryBase::SetHint(hint);
926}
927
928wxString wxTextEntry::GetHint() const
929{
930 if ( wxUxThemeEngine::GetIfActive() )
931 {
932 wchar_t buf[256];
933 if ( ::SendMessage(GetEditHwnd(), EM_GETCUEBANNER,
934 (WPARAM)buf, WXSIZEOF(buf)) )
d2f434e4 935 return wxString(buf);
63f7d502
VZ
936 }
937
938 return wxTextEntryBase::GetHint();
939}
940
941
942#endif // wxUSE_UXTHEME
943
0847e36e
JS
944// ----------------------------------------------------------------------------
945// margins support
946// ----------------------------------------------------------------------------
947
948bool wxTextEntry::DoSetMargins(const wxPoint& margins)
949{
950#if !defined(__WXWINCE__)
951 bool res = true;
952
953 if ( margins.x != -1 )
954 {
955 // left margin
956 ::SendMessage(GetEditHwnd(), EM_SETMARGINS,
957 EC_LEFTMARGIN, MAKELONG(margins.x, 0));
958 }
959
960 if ( margins.y != -1 )
961 {
962 res = false;
963 }
964
965 return res;
966#else
967 return false;
968#endif
969}
970
971wxPoint wxTextEntry::DoGetMargins() const
972{
973#if !defined(__WXWINCE__)
974 LRESULT lResult = ::SendMessage(GetEditHwnd(), EM_GETMARGINS,
975 0, 0);
976 int left = LOWORD(lResult);
977 int top = -1;
978 return wxPoint(left, top);
979#else
980 return wxPoint(-1, -1);
981#endif
982}
983
96a4cdeb 984#endif // wxUSE_TEXTCTRL || wxUSE_COMBOBOX