]> git.saurik.com Git - wxWidgets.git/blame - src/common/statbar.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / statbar.cpp
CommitLineData
71e03035 1///////////////////////////////////////////////////////////////////////////////
3304646d 2// Name: src/common/statbar.cpp
71e03035
VZ
3// Purpose: wxStatusBarBase implementation
4// Author: Vadim Zeitlin
7b6fefbe 5// Modified by: Francesco Montorsi
71e03035
VZ
6// Created: 14.10.01
7// RCS-ID: $Id$
8// Copyright: (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
526954c5 9// Licence: wxWindows licence
71e03035
VZ
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
71e03035
VZ
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
53b6d7a2
PC
27#if wxUSE_STATUSBAR
28
3304646d
WS
29#include "wx/statusbr.h"
30
71e03035 31#ifndef WX_PRECOMP
e9a05074 32 #include "wx/frame.h"
71e03035
VZ
33#endif //WX_PRECOMP
34
23318a53 35const char wxStatusBarNameStr[] = "statusBar";
53b6d7a2 36
6cf68971
VZ
37// ============================================================================
38// wxStatusBarPane implementation
39// ============================================================================
40
41bool wxStatusBarPane::SetText(const wxString& text)
42{
43 if ( text == m_text )
44 return false;
45
46 /*
47 If we have a message to restore on the stack, we update it to
48 correspond to the current one so that a sequence of calls such as
49
50 1. SetStatusText("foo")
51 2. PushStatusText("bar")
52 3. SetStatusText("new foo")
53 4. PopStatusText()
54
55 doesn't overwrite the "new foo" which should be shown at the end with
56 the old value "foo". This would be unexpected and hard to avoid,
57 especially when PushStatusText() is used internally by wxWidgets
58 without knowledge of the user program, as it is for showing the menu
59 and toolbar help strings.
60
61 By updating the top of the stack we ensure that the next call to
62 PopStatusText() basically becomes a NOP without breaking the balance
63 between the calls to push and pop as we would have done if we really
64 called PopStatusText() here.
65 */
66 if ( !m_arrStack.empty() )
67 {
68 m_arrStack.back() = text;
69 }
70
71 m_text = text;
72
73 return true;
74}
75
76bool wxStatusBarPane::PushText(const wxString& text)
77{
78 // save the currently shown text
79 m_arrStack.push_back(m_text);
80
81 // and update the new one if necessary
82 if ( text == m_text )
83 return false;
84
85 m_text = text;
86
87 return true;
88}
89
90bool wxStatusBarPane::PopText()
91{
92 wxCHECK_MSG( !m_arrStack.empty(), false, "no status message to pop" );
93
94 const wxString text = m_arrStack.back();
95
96 m_arrStack.pop_back();
97
98 if ( text == m_text )
99 return false;
100
101 m_text = text;
102
103 return true;
104}
7b6fefbe 105
71e03035
VZ
106// ============================================================================
107// wxStatusBarBase implementation
108// ============================================================================
109
a93e536b 110IMPLEMENT_DYNAMIC_CLASS(wxStatusBar, wxWindow)
71e03035 111
0dc8fac2 112#include "wx/arrimpl.cpp" // This is a magic incantation which must be done!
b2d76621 113WX_DEFINE_EXPORTED_OBJARRAY(wxStatusBarPaneArray)
7b6fefbe
FM
114
115
71e03035
VZ
116// ----------------------------------------------------------------------------
117// ctor/dtor
118// ----------------------------------------------------------------------------
119
120wxStatusBarBase::wxStatusBarBase()
121{
7b6fefbe 122 m_bSameWidthForAllPanes = true;
71e03035
VZ
123}
124
125wxStatusBarBase::~wxStatusBarBase()
126{
2ab82214
VZ
127 // notify the frame that it doesn't have a status bar any longer to avoid
128 // dangling pointers
67f30682 129 wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
2ab82214 130 if ( frame && frame->GetStatusBar() == this )
2ab82214 131 frame->SetStatusBar(NULL);
c2919ab3
VZ
132}
133
71e03035
VZ
134// ----------------------------------------------------------------------------
135// field widths
136// ----------------------------------------------------------------------------
137
138void wxStatusBarBase::SetFieldsCount(int number, const int *widths)
139{
9a83f860 140 wxCHECK_RET( number > 0, wxT("invalid field number in SetFieldsCount") );
71e03035 141
7b6fefbe 142 if ( (size_t)number > m_panes.GetCount() )
71e03035 143 {
7b6fefbe 144 wxStatusBarPane newPane;
c2919ab3 145
7b6fefbe
FM
146 // add more entries with the default style and zero width
147 // (this will be set later)
148 for (size_t i = m_panes.GetCount(); i < (size_t)number; ++i)
149 m_panes.Add(newPane);
71e03035 150 }
7b6fefbe
FM
151 else if ( (size_t)number < m_panes.GetCount() )
152 {
153 // remove entries in excess
154 m_panes.RemoveAt(number, m_panes.GetCount()-number);
155 }
156
fd3ece57
FM
157 // SetStatusWidths will automatically refresh
158 SetStatusWidths(number, widths);
71e03035
VZ
159}
160
161void wxStatusBarBase::SetStatusWidths(int WXUNUSED_UNLESS_DEBUG(n),
fd3ece57 162 const int widths[])
71e03035 163{
9a83f860 164 wxASSERT_MSG( (size_t)n == m_panes.GetCount(), wxT("field number mismatch") );
71e03035 165
54e18afc 166 if (widths == NULL)
fd3ece57
FM
167 {
168 // special value meaning: override explicit pane widths and make them all
169 // of the same size
170 m_bSameWidthForAllPanes = true;
171 }
172 else
173 {
174 for ( size_t i = 0; i < m_panes.GetCount(); i++ )
6cf68971 175 m_panes[i].SetWidth(widths[i]);
fd3ece57
FM
176
177 m_bSameWidthForAllPanes = false;
178 }
71e03035
VZ
179
180 // update the display after the widths changed
181 Refresh();
182}
183
c2919ab3 184void wxStatusBarBase::SetStatusStyles(int WXUNUSED_UNLESS_DEBUG(n),
fd3ece57 185 const int styles[])
c2919ab3 186{
9a83f860 187 wxCHECK_RET( styles, wxT("NULL pointer in SetStatusStyles") );
c2919ab3 188
9a83f860 189 wxASSERT_MSG( (size_t)n == m_panes.GetCount(), wxT("field number mismatch") );
c2919ab3 190
7b6fefbe 191 for ( size_t i = 0; i < m_panes.GetCount(); i++ )
6cf68971 192 m_panes[i].SetStyle(styles[i]);
c2919ab3
VZ
193
194 // update the display after the widths changed
195 Refresh();
196}
197
71e03035
VZ
198wxArrayInt wxStatusBarBase::CalculateAbsWidths(wxCoord widthTotal) const
199{
200 wxArrayInt widths;
201
7b6fefbe 202 if ( m_bSameWidthForAllPanes )
71e03035 203 {
7b6fefbe
FM
204 // Default: all fields have the same width. This is not always
205 // possible to do exactly (if widthTotal is not divisible by
206 // m_panes.GetCount()) - if that happens, we distribute the extra
207 // pixels among all fields:
208 int widthToUse = widthTotal;
68ab959c 209
7b6fefbe
FM
210 for ( size_t i = m_panes.GetCount(); i > 0; i-- )
211 {
212 // divide the unassigned width evently between the
213 // not yet processed fields:
214 int w = widthToUse / i;
215 widths.Add(w);
216 widthToUse -= w;
71e03035
VZ
217 }
218 }
7b6fefbe 219 else // do not override explicit pane widths
71e03035
VZ
220 {
221 // calculate the total width of all the fixed width fields and the
222 // total number of var field widths counting with multiplicity
7b6fefbe 223 size_t nTotalWidth = 0,
fd3ece57
FM
224 nVarCount = 0,
225 i;
7b6fefbe
FM
226
227 for ( i = 0; i < m_panes.GetCount(); i++ )
71e03035 228 {
b31eaa5c
FM
229 if ( m_panes[i].GetWidth() >= 0 )
230 nTotalWidth += m_panes[i].GetWidth();
71e03035 231 else
b31eaa5c 232 nVarCount += -m_panes[i].GetWidth();
71e03035
VZ
233 }
234
235 // the amount of extra width we have per each var width field
1a83b9bd 236 int widthExtra = widthTotal - nTotalWidth;
71e03035
VZ
237
238 // do fill the array
7b6fefbe 239 for ( i = 0; i < m_panes.GetCount(); i++ )
71e03035 240 {
b31eaa5c
FM
241 if ( m_panes[i].GetWidth() >= 0 )
242 widths.Add(m_panes[i].GetWidth());
71e03035
VZ
243 else
244 {
b31eaa5c
FM
245 int nVarWidth = widthExtra > 0 ? (widthExtra * (-m_panes[i].GetWidth())) / nVarCount : 0;
246 nVarCount += m_panes[i].GetWidth();
1a83b9bd
VZ
247 widthExtra -= nVarWidth;
248 widths.Add(nVarWidth);
71e03035
VZ
249 }
250 }
251 }
252
253 return widths;
254}
255
1f361cdd 256// ----------------------------------------------------------------------------
6cf68971
VZ
257// setting/getting status text
258// ----------------------------------------------------------------------------
259
260void wxStatusBarBase::SetStatusText(const wxString& text, int number)
261{
262 wxCHECK_RET( (unsigned)number < m_panes.size(),
263 "invalid status bar field index" );
264
265 if ( m_panes[number].SetText(text) )
266 DoUpdateStatusText(number);
267}
268
269wxString wxStatusBarBase::GetStatusText(int number) const
270{
271 wxCHECK_MSG( (unsigned)number < m_panes.size(), wxString(),
272 "invalid status bar field index" );
273
274 return m_panes[number].GetText();
275}
276
277void wxStatusBarBase::SetEllipsizedFlag(int number, bool isEllipsized)
278{
279 wxCHECK_RET( (unsigned)number < m_panes.size(),
280 "invalid status bar field index" );
281
282 m_panes[number].SetIsEllipsized(isEllipsized);
283}
284
285// ----------------------------------------------------------------------------
286// pushing/popping status text
1f361cdd
MB
287// ----------------------------------------------------------------------------
288
289void wxStatusBarBase::PushStatusText(const wxString& text, int number)
290{
6cf68971
VZ
291 wxCHECK_RET( (unsigned)number < m_panes.size(),
292 "invalid status bar field index" );
293
294 if ( m_panes[number].PushText(text) )
295 DoUpdateStatusText(number);
1f361cdd
MB
296}
297
298void wxStatusBarBase::PopStatusText(int number)
299{
6cf68971
VZ
300 wxCHECK_RET( (unsigned)number < m_panes.size(),
301 "invalid status bar field index" );
302
303 if ( m_panes[number].PopText() )
304 DoUpdateStatusText(number);
1f361cdd
MB
305}
306
71e03035 307#endif // wxUSE_STATUSBAR