From 59d3027c0cc10bd2cf729d4e23fc93f314076959 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 16 Apr 2000 23:58:50 +0000 Subject: [PATCH] 1. wxTextCtrl::SetValue() moves the cursor to the end of text (as in GTK) 2. bug in wxThread::Delete() when the thread hadn't been staretd fixed 3. setting font for radiobox now works immediately (you had to invalidate the window manually, e.g. by covering it with another one, before) 4. added and documented wxConstCast() and wxStaticCast() 5. attempts to make wxFontEnumeraotr::EnumEncodings() work under MSW git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_2_BRANCH@7185 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/function.tex | 27 +++++++- include/wx/msw/private.h | 1 + include/wx/object.h | 15 +++++ src/common/fontmap.cpp | 3 + src/msw/fontenum.cpp | 49 ++++++++++++++- src/msw/fontutil.cpp | 123 ++++++++++++++++++++----------------- src/msw/radiobox.cpp | 9 +-- src/msw/textctrl.cpp | 4 ++ src/msw/thread.cpp | 79 ++++++++++++++++-------- 9 files changed, 220 insertions(+), 90 deletions(-) diff --git a/docs/latex/wx/function.tex b/docs/latex/wx/function.tex index 6a4e64f058..351af3fd18 100644 --- a/docs/latex/wx/function.tex +++ b/docs/latex/wx/function.tex @@ -2162,6 +2162,18 @@ avoid using {\tt \#ifdef}s when creating bitmaps. +\membersection{wxConstCast}\label{wxconstcast} + +\func{}{wxConstCast}{ptr, classname} + +This macro expands into {\tt const\_cast(ptr)} if the compiler +supports {\it const\_cast} or into an old, C-style cast, otherwise. + +\wxheading{See also} + +\helpref{wxDynamicCast}{wxdynamiccast}\\ +\helpref{wxStatiicCast}{wxstaticcast} + \membersection{WXDEBUG\_NEW}\label{debugnew} \func{}{WXDEBUG\_NEW}{arg} @@ -2207,7 +2219,9 @@ Example: \wxheading{See also} -\helpref{RTTI overview}{runtimeclassoverview} +\helpref{RTTI overview}{runtimeclassoverview}\\ +\helpref{wxConstCast}{wxconstcast}\\ +\helpref{wxStatiicCast}{wxstaticcast} \membersection{wxICON}\label{wxiconmacro} @@ -2456,6 +2470,17 @@ is no connection between names used in resources, and the global bitmap data. Another name for \helpref{wxResourceRegisterBitmapData}{registerbitmapdata}. +\membersection{wxStaticCast}\label{wxstaticcast} + +\func{}{wxStaticCast}{ptr, classname} + +This macro checks that the cast is valid in debug mode (an assert failure will +result if {\tt wxDynamicCast(ptr, classname) == NULL}) and then returns the +result of executing an equivalent of {\tt static\_cast(ptr)}. + +\helpref{wxDynamicCast}{wxdynamiccast}\\ +\helpref{wxConstCast}{wxconstcast} + \section{Log functions}\label{logfunctions} These functions provide a variety of logging functions: see \helpref{Log classes overview}{wxlogoverview} for diff --git a/include/wx/msw/private.h b/include/wx/msw/private.h index f8d268066d..6c5f404608 100644 --- a/include/wx/msw/private.h +++ b/include/wx/msw/private.h @@ -321,6 +321,7 @@ WXDLLEXPORT wxWindow* wxFindWinFromHandle(WXHWND hWnd); WXDLLEXPORT void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont *the_font); WXDLLEXPORT void wxFillLogFont(LOGFONT *logFont, const wxFont *font); WXDLLEXPORT wxFont wxCreateFontFromLogFont(const LOGFONT *logFont); +WXDLLEXPORT wxFontEncoding wxGetFontEncFromCharSet(int charset); WXDLLEXPORT void wxSliderEvent(WXHWND control, WXWORD wParam, WXWORD pos); WXDLLEXPORT void wxScrollBarEvent(WXHWND hbar, WXWORD wParam, WXWORD pos); diff --git a/include/wx/object.h b/include/wx/object.h index a6f7968ffe..3ce6e27bc3 100644 --- a/include/wx/object.h +++ b/include/wx/object.h @@ -170,6 +170,21 @@ wxObject* WXDLLEXPORT_CTORFN wxConstructorFor##name(void) \ ? (className *)(obj) \ : (className *)0) +#define wxConstCast(obj, className) ((className *)(obj)) + +#ifdef __WXDEBUG__ + inline void wxCheckCast(void *ptr) + { + wxASSERT_MSG( ptr, _T("wxStaticCast() used incorrectly") ); + } + + #define wxStaticCast(obj, className) \ + (wxCheckCast(wxDynamicCast(obj, className)), ((className *)(obj))) + +#else // !Debug + #define wxStaticCast(obj, className) ((className *)(obj)) +#endif // Debug/!Debug + // Unfortunately Borland seems to need this include. #ifdef __BORLANDC__ #if wxUSE_IOSTREAMH diff --git a/src/common/fontmap.cpp b/src/common/fontmap.cpp index 3a40d704a6..89dca5c3f6 100644 --- a/src/common/fontmap.cpp +++ b/src/common/fontmap.cpp @@ -88,6 +88,7 @@ static wxFontEncoding gs_encodings[] = wxFONTENCODING_CP1255, wxFONTENCODING_CP1256, wxFONTENCODING_CP1257, + wxFONTENCODING_CP437, }; // the descriptions for them @@ -117,6 +118,7 @@ static const wxChar* gs_encodingDescs[] = wxTRANSLATE( "Windows Hebrew (CP 1255)" ), wxTRANSLATE( "Windows Arabic (CP 1256)" ), wxTRANSLATE( "Windows Baltic (CP 1257)" ), + wxTRANSLATE( "Windows/DOS OEM (CP 437)" ), }; // and the internal names @@ -146,6 +148,7 @@ static const wxChar* gs_encodingNames[] = wxT( "windows1255" ), wxT( "windows1256" ), wxT( "windows1257" ), + wxT( "windows437" ), }; // ---------------------------------------------------------------------------- diff --git a/src/msw/fontenum.cpp b/src/msw/fontenum.cpp index f91b00c91f..3c2610ba21 100644 --- a/src/msw/fontenum.cpp +++ b/src/msw/fontenum.cpp @@ -41,15 +41,21 @@ // private classes // ---------------------------------------------------------------------------- +// the helper class which calls ::EnumFontFamilies() and whose OnFont() is +// called from the callback passed to this function and, in its turn, calls the +// appropariate wxFontEnumerator method class wxFontEnumeratorHelper { public: wxFontEnumeratorHelper(wxFontEnumerator *fontEnum); // control what exactly are we enumerating + // we enumerate fonts with given enocding bool SetEncoding(wxFontEncoding encoding); - void SetFixedOnly(bool fixedOnly) - { m_fixedOnly = fixedOnly; } + // we enumerate fixed-width fonts + void SetFixedOnly(bool fixedOnly) { m_fixedOnly = fixedOnly; } + // we enumerate the encodings available in this family + void SetFamily(const wxString& family); // call to start enumeration void DoEnumerate(); @@ -67,8 +73,17 @@ private: // if not empty, enum only the fonts with this facename wxString m_facename; + // if not empty, enum only the fonts in this family + wxString m_family; + // if TRUE, enum only fixed fonts bool m_fixedOnly; + + // if TRUE, we enumerate the encodings, not fonts + bool m_enumEncodings; + + // the list of charsets we already found while enumerating charsets + wxArrayInt m_charsets; }; // ---------------------------------------------------------------------------- @@ -91,6 +106,13 @@ wxFontEnumeratorHelper::wxFontEnumeratorHelper(wxFontEnumerator *fontEnum) m_fontEnum = fontEnum; m_charset = -1; m_fixedOnly = FALSE; + m_enumEncodings = FALSE; +} + +void wxFontEnumeratorHelper::SetFamily(const wxString& family) +{ + m_enumEncodings = TRUE; + m_family = family; } bool wxFontEnumeratorHelper::SetEncoding(wxFontEncoding encoding) @@ -147,6 +169,25 @@ void wxFontEnumeratorHelper::DoEnumerate() bool wxFontEnumeratorHelper::OnFont(const LPLOGFONT lf, const LPTEXTMETRIC tm) const { + if ( m_enumEncodings ) + { + // is this a new charset? + int cs = lf->lfCharSet; + if ( m_charsets.Index(cs) == wxNOT_FOUND ) + { + wxConstCast(this, wxFontEnumeratorHelper)->m_charsets.Add(cs); + + wxFontEncoding enc = wxGetFontEncFromCharSet(cs); + return m_fontEnum->OnFontEncoding(m_family, + wxFontMapper::GetEncodingName(enc)); + } + else + { + // continue enumeration + return TRUE; + } + } + if ( m_fixedOnly ) { // check that it's a fixed pitch font (there is *no* error here, the @@ -191,7 +232,9 @@ bool wxFontEnumerator::EnumerateFacenames(wxFontEncoding encoding, bool wxFontEnumerator::EnumerateEncodings(const wxString& family) { - wxFAIL_MSG(wxT("TODO")); + wxFontEnumeratorHelper fe(this); + fe.SetFamily(family); + fe.DoEnumerate(); return TRUE; } diff --git a/src/msw/fontutil.cpp b/src/msw/fontutil.cpp index d1ccf3f844..a5b4de99d7 100644 --- a/src/msw/fontutil.cpp +++ b/src/msw/fontutil.cpp @@ -94,7 +94,7 @@ bool wxNativeEncodingInfo::FromString(const wxString& s) wxString wxNativeEncodingInfo::ToString() const { wxString s; - + s << (long)encoding << _T(';') << facename; if ( charset != ANSI_CHARSET ) { @@ -173,7 +173,7 @@ bool wxGetNativeFontEncoding(wxFontEncoding encoding, } info->encoding = encoding; - + return TRUE; } @@ -198,6 +198,69 @@ bool wxTestFontEncoding(const wxNativeEncodingInfo& info) return TRUE; } +// ---------------------------------------------------------------------------- +// wxFontEncoding <-> CHARSET_XXX +// ---------------------------------------------------------------------------- + +wxFontEncoding wxGetFontEncFromCharSet(int cs) +{ + wxFontEncoding fontEncoding; + + switch ( cs ) + { + default: + // JACS: Silently using ANSI_CHARSET + // apparently works for Chinese Windows. Assume it works + // for all/most other languages. + //wxFAIL_MSG(wxT("unsupported charset")); + // fall through + + case ANSI_CHARSET: + fontEncoding = wxFONTENCODING_CP1252; + break; + +#ifdef __WIN32__ + case EASTEUROPE_CHARSET: + fontEncoding = wxFONTENCODING_CP1250; + break; + + case BALTIC_CHARSET: + fontEncoding = wxFONTENCODING_CP1257; + break; + + case RUSSIAN_CHARSET: + fontEncoding = wxFONTENCODING_CP1251; + break; + + case ARABIC_CHARSET: + fontEncoding = wxFONTENCODING_CP1256; + break; + + case GREEK_CHARSET: + fontEncoding = wxFONTENCODING_CP1253; + break; + + case HEBREW_CHARSET: + fontEncoding = wxFONTENCODING_CP1255; + break; + + case TURKISH_CHARSET: + fontEncoding = wxFONTENCODING_CP1254; + break; + + case THAI_CHARSET: + fontEncoding = wxFONTENCODING_CP437; + break; +#endif // Win32 + + case OEM_CHARSET: + fontEncoding = wxFONTENCODING_CP437; + break; + } + + return fontEncoding; +} + // ---------------------------------------------------------------------------- // wxFont <-> LOGFONT conversion // ---------------------------------------------------------------------------- @@ -410,62 +473,8 @@ wxFont wxCreateFontFromLogFont(const LOGFONT *logFont) #endif int fontPoints = (int) (((72.0*((double)height))/(double) ppInch) + 0.5); - wxFontEncoding fontEncoding; - switch ( logFont->lfCharSet ) - { - default: - // JACS: Silently using ANSI_CHARSET - // apparently works for Chinese Windows. Assume it works - // for all/most other languages. - //wxFAIL_MSG(wxT("unsupported charset")); - // fall through - - case ANSI_CHARSET: - fontEncoding = wxFONTENCODING_CP1252; - break; - -#ifdef __WIN32__ - case EASTEUROPE_CHARSET: - fontEncoding = wxFONTENCODING_CP1250; - break; - - case BALTIC_CHARSET: - fontEncoding = wxFONTENCODING_CP1257; - break; - - case RUSSIAN_CHARSET: - fontEncoding = wxFONTENCODING_CP1251; - break; - - case ARABIC_CHARSET: - fontEncoding = wxFONTENCODING_CP1256; - break; - - case GREEK_CHARSET: - fontEncoding = wxFONTENCODING_CP1253; - break; - - case HEBREW_CHARSET: - fontEncoding = wxFONTENCODING_CP1255; - break; - - case TURKISH_CHARSET: - fontEncoding = wxFONTENCODING_CP1254; - break; - - case THAI_CHARSET: - fontEncoding = wxFONTENCODING_CP437; - break; -#endif - - case OEM_CHARSET: - fontEncoding = wxFONTENCODING_CP437; - break; - } - return wxFont(fontPoints, fontFamily, fontStyle, fontWeight, fontUnderline, fontFace, - fontEncoding); + wxGetFontEncFromCharSet(logFont->lfCharSet)); } - diff --git a/src/msw/radiobox.cpp b/src/msw/radiobox.cpp index 29ba27348e..8197f63b70 100644 --- a/src/msw/radiobox.cpp +++ b/src/msw/radiobox.cpp @@ -716,11 +716,12 @@ bool wxRadioBox::SetFont(const wxFont& font) WXHFONT hfont = wxFont(font).GetResourceHandle(); for ( int n = 0; n < m_noItems; n++ ) { - ::SendMessage((HWND)m_radioButtons[n], WM_SETFONT, (WPARAM)hfont, 0L); - } + HWND hwndBtn = (HWND)m_radioButtons[n]; + ::SendMessage(hwndBtn, WM_SETFONT, (WPARAM)hfont, 0L); - // this is needed because otherwise the buttons are not redrawn correctly - Refresh(); + // otherwise the buttons are not redrawn correctly + ::InvalidateRect(hwndBtn, NULL, FALSE /* don't erase bg */); + } return TRUE; } diff --git a/src/msw/textctrl.cpp b/src/msw/textctrl.cpp index b763b0a7a7..8d1c44c0cc 100644 --- a/src/msw/textctrl.cpp +++ b/src/msw/textctrl.cpp @@ -422,6 +422,10 @@ void wxTextCtrl::SetValue(const wxString& value) SetWindowText(GetHwnd(), valueDos.c_str()); + // for compatibility with the GTK and because it is more logical, we + // move the cursor to the end of the text after SetValue() + SetInsertionPointEnd(); + AdjustSpaceLimit(); } } diff --git a/src/msw/thread.cpp b/src/msw/thread.cpp index 75dfff574d..e701abb39b 100644 --- a/src/msw/thread.cpp +++ b/src/msw/thread.cpp @@ -390,31 +390,38 @@ private: DWORD wxThreadInternal::WinThreadStart(wxThread *thread) { - // first of all, check whether we hadn't been cancelled already + DWORD rc; + bool wasCancelled; + + // first of all, check whether we hadn't been cancelled already and don't + // start the user code at all then if ( thread->m_internal->GetState() == STATE_EXITED ) { - return (DWORD)-1; + rc = (DWORD)-1; + wasCancelled = TRUE; } - - // store the thread object in the TLS - if ( !::TlsSetValue(gs_tlsThisThread, thread) ) + else // do run thread { - wxLogSysError(_("Can not start thread: error writing TLS.")); + // store the thread object in the TLS + if ( !::TlsSetValue(gs_tlsThisThread, thread) ) + { + wxLogSysError(_("Can not start thread: error writing TLS.")); - return (DWORD)-1; + return (DWORD)-1; + } + + rc = (DWORD)thread->Entry(); + + // enter m_critsect before changing the thread state + thread->m_critsect.Enter(); + wasCancelled = thread->m_internal->GetState() == STATE_CANCELED; + thread->m_internal->SetState(STATE_EXITED); + thread->m_critsect.Leave(); } - DWORD rc = (DWORD)thread->Entry(); - - // enter m_critsect before changing the thread state - thread->m_critsect.Enter(); - bool wasCancelled = thread->m_internal->GetState() == STATE_CANCELED; - thread->m_internal->SetState(STATE_EXITED); - thread->m_critsect.Leave(); - thread->OnExit(); - // if the thread was cancelled (from Delete()), then it the handle is still + // if the thread was cancelled (from Delete()), then its handle is still // needed there if ( thread->IsDetached() && !wasCancelled ) { @@ -522,7 +529,13 @@ bool wxThreadInternal::Resume() return FALSE; } - m_state = STATE_RUNNING; + // don't change the state from STATE_EXITED because it's special and means + // we are going to terminate without running any user code - if we did it, + // the codei n Delete() wouldn't work + if ( m_state != STATE_EXITED ) + { + m_state = STATE_RUNNING; + } return TRUE; } @@ -753,29 +766,44 @@ wxThreadError wxThread::Delete(ExitCode *pRc) // Delete() is always safe to call, so consider all possible states - // has the thread started to run? - bool shouldResume = FALSE; + // we might need to resume the thread, but we might also not need to cancel + // it if it doesn't run yet + bool shouldResume = FALSE, + shouldCancel = TRUE, + isRunning = FALSE; + // check if the thread already started to run { wxCriticalSectionLocker lock(m_critsect); if ( m_internal->GetState() == STATE_NEW ) { - // WinThreadStart() will see it and terminate immediately + // WinThreadStart() will see it and terminate immediately, no need + // to cancel the thread - but we still need to resume it to let it + // run m_internal->SetState(STATE_EXITED); - shouldResume = TRUE; + Resume(); // it knows about STATE_EXITED special case + + shouldCancel = FALSE; + isRunning = TRUE; + + // shouldResume is correctly set to FALSE here + } + else + { + shouldResume = IsPaused(); } } - // is the thread paused? - if ( shouldResume || IsPaused() ) + // resume the thread if it is paused + if ( shouldResume ) Resume(); HANDLE hThread = m_internal->GetHandle(); // does is still run? - if ( IsRunning() ) + if ( isRunning || IsRunning() ) { if ( IsMain() ) { @@ -788,6 +816,7 @@ wxThreadError wxThread::Delete(ExitCode *pRc) } // ask the thread to terminate + if ( shouldCancel ) { wxCriticalSectionLocker lock(m_critsect); @@ -880,7 +909,7 @@ wxThreadError wxThread::Delete(ExitCode *pRc) { // if the thread exits normally, this is done in WinThreadStart, but in // this case it would have been too early because - // MsgWaitForMultipleObject() would fail if the therad handle was + // MsgWaitForMultipleObject() would fail if the thread handle was // closed while we were waiting on it, so we must do it here delete this; }