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