Don't reset m_fp if wxFFile::Open() fails.
[wxWidgets.git] / src / msw / textmeasure.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/textmeasure.cpp
3 // Purpose: wxTextMeasure implementation for wxMSW
4 // Author: Manuel Martin
5 // Created: 2012-10-05
6 // Copyright: (c) 1997-2012 wxWidgets team
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 #include "wx/msw/private.h"
26
27 #ifndef WX_PRECOMP
28 #include "wx/window.h"
29 #include "wx/font.h"
30 #endif //WX_PRECOMP
31
32 #include "wx/private/textmeasure.h"
33
34 #include "wx/msw/dc.h"
35
36 // ============================================================================
37 // wxTextMeasure implementation
38 // ============================================================================
39
40 void wxTextMeasure::Init()
41 {
42 m_hdc = NULL;
43 m_hfontOld = NULL;
44
45 if ( m_dc )
46 {
47 wxClassInfo* const ci = m_dc->GetImpl()->GetClassInfo();
48
49 if ( ci->IsKindOf(wxCLASSINFO(wxMSWDCImpl)))
50 {
51 m_useDCImpl = false;
52 }
53 }
54 }
55
56 void wxTextMeasure::BeginMeasuring()
57 {
58 if ( m_dc )
59 {
60 m_hdc = m_dc->GetHDC();
61
62 // Non-native wxDC subclasses should override their DoGetTextExtent()
63 // and other methods.
64 wxASSERT_MSG( m_hdc, wxS("Must not be used with non-native wxDCs") );
65 }
66 else if ( m_win )
67 {
68 m_hdc = ::GetDC(GetHwndOf(m_win));
69 }
70
71 // We need to set the font if it's explicitly specified, of course, but
72 // also if we're associated with a window because the window HDC created
73 // above has the default font selected into it and not the font of the
74 // window.
75 if ( m_font || m_win )
76 m_hfontOld = (HFONT)::SelectObject(m_hdc, GetHfontOf(GetFont()));
77 }
78
79 void wxTextMeasure::EndMeasuring()
80 {
81 if ( m_hfontOld )
82 {
83 ::SelectObject(m_hdc, m_hfontOld);
84 m_hfontOld = NULL;
85 }
86
87 if ( m_win )
88 ::ReleaseDC(GetHwndOf(m_win), m_hdc);
89 //else: our HDC belongs to m_dc, don't touch it
90
91 m_hdc = NULL;
92 }
93
94 // Notice we don't check here the font. It is supposed to be OK before the call.
95 void wxTextMeasure::DoGetTextExtent(const wxString& string,
96 wxCoord *width,
97 wxCoord *height,
98 wxCoord *descent,
99 wxCoord *externalLeading)
100 {
101 SIZE sizeRect;
102 const size_t len = string.length();
103 if ( !::GetTextExtentPoint32(m_hdc, string.t_str(), len, &sizeRect) )
104 {
105 wxLogLastError(wxT("GetTextExtentPoint32()"));
106 }
107
108 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
109 // the result computed by GetTextExtentPoint32() may be too small as it
110 // accounts for under/overhang of the first/last character while we want
111 // just the bounding rect for this string so adjust the width as needed
112 // (using API not available in 2002 SDKs of WinCE)
113 if ( len > 0 )
114 {
115 ABC widthABC;
116 const wxChar chFirst = *string.begin();
117 if ( ::GetCharABCWidths(m_hdc, chFirst, chFirst, &widthABC) )
118 {
119 if ( widthABC.abcA < 0 )
120 sizeRect.cx -= widthABC.abcA;
121
122 if ( len > 1 )
123 {
124 const wxChar chLast = *string.rbegin();
125 ::GetCharABCWidths(m_hdc, chLast, chLast, &widthABC);
126 }
127 //else: we already have the width of the last character
128
129 if ( widthABC.abcC < 0 )
130 sizeRect.cx -= widthABC.abcC;
131 }
132 //else: GetCharABCWidths() failed, not a TrueType font?
133 }
134 #endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
135
136 *width = sizeRect.cx;
137 *height = sizeRect.cy;
138
139 if ( descent || externalLeading )
140 {
141 TEXTMETRIC tm;
142 ::GetTextMetrics(m_hdc, &tm);
143 if ( descent )
144 *descent = tm.tmDescent;
145 if ( externalLeading )
146 *externalLeading = tm.tmExternalLeading;
147 }
148 }
149
150 bool wxTextMeasure::DoGetPartialTextExtents(const wxString& text,
151 wxArrayInt& widths,
152 double scaleX)
153 {
154 if ( !m_hdc )
155 return wxTextMeasureBase::DoGetPartialTextExtents(text, widths, scaleX);
156
157 static int maxLenText = -1;
158 static int maxWidth = -1;
159
160 if (maxLenText == -1)
161 {
162 // Win9x and WinNT+ have different limits
163 int version = wxGetOsVersion();
164 maxLenText = version == wxOS_WINDOWS_NT ? 65535 : 8192;
165 maxWidth = version == wxOS_WINDOWS_NT ? INT_MAX : 32767;
166 }
167
168 int len = text.length();
169 if ( len > maxLenText )
170 len = maxLenText;
171
172 int fit = 0;
173 SIZE sz = {0,0};
174 if ( !::GetTextExtentExPoint(m_hdc,
175 text.t_str(), // string to check
176 len,
177 maxWidth,
178 &fit, // [out] count of chars
179 // that will fit
180 &widths[0], // array to fill
181 &sz) )
182 {
183 wxLogLastError(wxT("GetTextExtentExPoint"));
184
185 return false;
186 }
187
188 return true;
189 }