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