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