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