]> git.saurik.com Git - wxWidgets.git/blame - src/common/textcmn.cpp
Fixed some potential buffer overruns
[wxWidgets.git] / src / common / textcmn.cpp
CommitLineData
a1b82138
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: common/textcmn.cpp
3// Purpose: implementation of platform-independent functions of wxTextCtrl
4// Author: Julian Smart
5// Modified by:
6// Created: 13.07.99
7// RCS-ID: $Id$
77ffb593 8// Copyright: (c) wxWidgets team
65571936 9// Licence: wxWindows licence
a1b82138
VZ
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
1e6feb95 15
14f355c2 16#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
bf3e0fbd
KB
17 #pragma implementation "textctrlbase.h"
18#endif
1e6feb95 19
a1b82138
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
1e6feb95
VZ
27#if wxUSE_TEXTCTRL
28
a1b82138 29#ifndef WX_PRECOMP
0efe5ba7
VZ
30 #include "wx/intl.h"
31 #include "wx/log.h"
a1b82138
VZ
32 #include "wx/textctrl.h"
33#endif // WX_PRECOMP
34
35#include "wx/ffile.h"
36
37// ----------------------------------------------------------------------------
38// macros
39// ----------------------------------------------------------------------------
40
41// we don't have any objects of type wxTextCtrlBase in the program, only
42// wxTextCtrl, so this cast is safe
43#define TEXTCTRL(ptr) ((wxTextCtrl *)(ptr))
44
45// ============================================================================
46// implementation
47// ============================================================================
48
c57e3339
VZ
49IMPLEMENT_DYNAMIC_CLASS(wxTextUrlEvent, wxCommandEvent)
50
51DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_UPDATED)
52DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_ENTER)
53DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_URL)
d7eee191 54DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_MAXLEN)
c57e3339 55
4bc1afd5
VZ
56// ----------------------------------------------------------------------------
57// style functions - not implemented here
58// ----------------------------------------------------------------------------
59
e00a5d3c
JS
60wxTextAttr::wxTextAttr(const wxColour& colText,
61 const wxColour& colBack,
62 const wxFont& font,
63 wxTextAttrAlignment alignment)
64 : m_colText(colText), m_colBack(colBack), m_font(font), m_textAlignment(alignment)
65{
66 m_flags = 0;
67 m_leftIndent = 0;
89b67477 68 m_leftSubIndent = 0;
e00a5d3c
JS
69 m_rightIndent = 0;
70 if (m_colText.Ok()) m_flags |= wxTEXT_ATTR_TEXT_COLOUR;
71 if (m_colBack.Ok()) m_flags |= wxTEXT_ATTR_BACKGROUND_COLOUR;
72 if (m_font.Ok()) m_flags |= wxTEXT_ATTR_FONT;
73 if (alignment != wxTEXT_ALIGNMENT_DEFAULT)
74 m_flags |= wxTEXT_ATTR_ALIGNMENT;
75}
76
77void wxTextAttr::Init()
78{
79 m_textAlignment = wxTEXT_ALIGNMENT_DEFAULT;
80 m_flags = 0;
81 m_leftIndent = 0;
89b67477 82 m_leftSubIndent = 0;
e00a5d3c
JS
83 m_rightIndent = 0;
84}
85
eda40bfc
VZ
86/* static */
87wxTextAttr wxTextAttr::Combine(const wxTextAttr& attr,
88 const wxTextAttr& attrDef,
89 const wxTextCtrlBase *text)
90{
91 wxFont font = attr.GetFont();
92 if ( !font.Ok() )
93 {
94 font = attrDef.GetFont();
95
96 if ( text && !font.Ok() )
97 font = text->GetFont();
98 }
99
100 wxColour colFg = attr.GetTextColour();
101 if ( !colFg.Ok() )
102 {
103 colFg = attrDef.GetTextColour();
104
105 if ( text && !colFg.Ok() )
106 colFg = text->GetForegroundColour();
107 }
108
109 wxColour colBg = attr.GetBackgroundColour();
110 if ( !colBg.Ok() )
111 {
112 colBg = attrDef.GetBackgroundColour();
113
114 if ( text && !colBg.Ok() )
115 colBg = text->GetBackgroundColour();
116 }
117
e00a5d3c 118 wxTextAttr newAttr(colFg, colBg, font);
cb719f2e 119
e00a5d3c
JS
120 if (attr.HasAlignment())
121 newAttr.SetAlignment(attr.GetAlignment());
122 else if (attrDef.HasAlignment())
123 newAttr.SetAlignment(attrDef.GetAlignment());
cb719f2e 124
e00a5d3c
JS
125 if (attr.HasTabs())
126 newAttr.SetTabs(attr.GetTabs());
127 else if (attrDef.HasTabs())
128 newAttr.SetTabs(attrDef.GetTabs());
cb719f2e 129
e00a5d3c 130 if (attr.HasLeftIndent())
89b67477 131 newAttr.SetLeftIndent(attr.GetLeftIndent(), attr.GetLeftSubIndent());
e00a5d3c 132 else if (attrDef.HasLeftIndent())
89b67477 133 newAttr.SetLeftIndent(attrDef.GetLeftIndent(), attr.GetLeftSubIndent());
cb719f2e 134
e00a5d3c
JS
135 if (attr.HasRightIndent())
136 newAttr.SetRightIndent(attr.GetRightIndent());
137 else if (attrDef.HasRightIndent())
cb719f2e
WS
138 newAttr.SetRightIndent(attrDef.GetRightIndent());
139
e00a5d3c 140 return newAttr;
eda40bfc
VZ
141}
142
e00a5d3c
JS
143void wxTextAttr::operator= (const wxTextAttr& attr)
144{
145 m_font = attr.m_font;
146 m_colText = attr.m_colText;
147 m_colBack = attr.m_colBack;
148 m_textAlignment = attr.m_textAlignment;
149 m_leftIndent = attr.m_leftIndent;
89b67477 150 m_leftSubIndent = attr.m_leftSubIndent;
e00a5d3c
JS
151 m_rightIndent = attr.m_rightIndent;
152 m_tabs = attr.m_tabs;
153 m_flags = attr.m_flags;
154}
155
156
4bc1afd5
VZ
157// apply styling to text range
158bool wxTextCtrlBase::SetStyle(long WXUNUSED(start), long WXUNUSED(end),
159 const wxTextAttr& WXUNUSED(style))
160{
161 // to be implemented in derived TextCtrl classes
cb719f2e 162 return false;
4bc1afd5
VZ
163}
164
e00a5d3c
JS
165// get the styling at the given position
166bool wxTextCtrlBase::GetStyle(long WXUNUSED(position), wxTextAttr& WXUNUSED(style))
167{
168 // to be implemented in derived TextCtrl classes
cb719f2e 169 return false;
e00a5d3c
JS
170}
171
4bc1afd5 172// change default text attributes
eda40bfc 173bool wxTextCtrlBase::SetDefaultStyle(const wxTextAttr& style)
4bc1afd5 174{
c598f225
VZ
175 // keep the old attributes if the new style doesn't specify them unless the
176 // new style is empty - then reset m_defaultStyle (as there is no other way
177 // to do it)
178 if ( style.IsDefault() )
179 m_defaultStyle = style;
180 else
181 m_defaultStyle = wxTextAttr::Combine(style, m_defaultStyle, this);
eda40bfc 182
cb719f2e 183 return true;
4bc1afd5
VZ
184}
185
186// get default text attributes
187const wxTextAttr& wxTextCtrlBase::GetDefaultStyle() const
188{
189 return m_defaultStyle;
190}
191
a1b82138
VZ
192// ----------------------------------------------------------------------------
193// file IO functions
194// ----------------------------------------------------------------------------
195
196bool wxTextCtrlBase::LoadFile(const wxString& filename)
197{
1e6feb95 198#if wxUSE_FFILE
a1b82138
VZ
199 wxFFile file(filename);
200 if ( file.IsOpened() )
201 {
202 wxString text;
203 if ( file.ReadAll(&text) )
204 {
205 SetValue(text);
206
207 DiscardEdits();
208
209 m_filename = filename;
210
cb719f2e 211 return true;
a1b82138
VZ
212 }
213 }
214
215 wxLogError(_("File couldn't be loaded."));
1e6feb95 216#endif // wxUSE_FFILE
a1b82138 217
cb719f2e 218 return false;
a1b82138
VZ
219}
220
221bool wxTextCtrlBase::SaveFile(const wxString& filename)
222{
223 wxString filenameToUse = filename.IsEmpty() ? m_filename : filename;
64dcc269 224 if ( filenameToUse.empty() )
a1b82138
VZ
225 {
226 // what kind of message to give? is it an error or a program bug?
223d09f6 227 wxLogDebug(wxT("Can't save textctrl to file without filename."));
a1b82138 228
cb719f2e 229 return false;
a1b82138
VZ
230 }
231
1e6feb95 232#if wxUSE_FFILE
64dcc269 233 wxFFile file(filenameToUse, _T("w"));
a1b82138
VZ
234 if ( file.IsOpened() && file.Write(GetValue()) )
235 {
236 // it's not modified any longer
237 DiscardEdits();
238
64dcc269
VZ
239 // if it worked, save for future calls
240 m_filename = filenameToUse;
a1b82138 241
cb719f2e 242 return true;
a1b82138 243 }
64dcc269 244#endif // wxUSE_FFILE
a1b82138
VZ
245
246 wxLogError(_("The text couldn't be saved."));
247
cb719f2e 248 return false;
a1b82138
VZ
249}
250
251// ----------------------------------------------------------------------------
252// stream-like insertion operator
253// ----------------------------------------------------------------------------
254
255wxTextCtrl& wxTextCtrlBase::operator<<(const wxString& s)
256{
257 AppendText(s);
258 return *TEXTCTRL(this);
259}
260
261wxTextCtrl& wxTextCtrlBase::operator<<(float f)
262{
263 wxString str;
223d09f6 264 str.Printf(wxT("%.2f"), f);
a1b82138
VZ
265 AppendText(str);
266 return *TEXTCTRL(this);
267}
268
269wxTextCtrl& wxTextCtrlBase::operator<<(double d)
270{
271 wxString str;
223d09f6 272 str.Printf(wxT("%.2f"), d);
a1b82138
VZ
273 AppendText(str);
274 return *TEXTCTRL(this);
275}
276
277wxTextCtrl& wxTextCtrlBase::operator<<(int i)
278{
279 wxString str;
223d09f6 280 str.Printf(wxT("%d"), i);
a1b82138
VZ
281 AppendText(str);
282 return *TEXTCTRL(this);
283}
284
285wxTextCtrl& wxTextCtrlBase::operator<<(long i)
286{
287 wxString str;
223d09f6 288 str.Printf(wxT("%ld"), i);
a1b82138
VZ
289 AppendText(str);
290 return *TEXTCTRL(this);
291}
292
a324a7bc 293wxTextCtrl& wxTextCtrlBase::operator<<(const wxChar c)
a1b82138
VZ
294{
295 return operator<<(wxString(c));
296}
297
298// ----------------------------------------------------------------------------
299// streambuf methods implementation
300// ----------------------------------------------------------------------------
301
302#ifndef NO_TEXT_WINDOW_STREAM
303
d73e6791 304int wxTextCtrlBase::overflow(int c)
a1b82138 305{
d73e6791 306 AppendText((wxChar)c);
a1b82138 307
d73e6791 308 // return something different from EOF
a1b82138
VZ
309 return 0;
310}
311
a1b82138
VZ
312#endif // NO_TEXT_WINDOW_STREAM
313
1e6feb95
VZ
314// ----------------------------------------------------------------------------
315// clipboard stuff
316// ----------------------------------------------------------------------------
317
318bool wxTextCtrlBase::CanCopy() const
319{
320 // can copy if there's a selection
321 long from, to;
322 GetSelection(&from, &to);
323 return from != to;
324}
325
326bool wxTextCtrlBase::CanCut() const
327{
328 // can cut if there's a selection and if we're not read only
329 return CanCopy() && IsEditable();
330}
331
332bool wxTextCtrlBase::CanPaste() const
333{
334 // can paste if we are not read only
335 return IsEditable();
336}
337
94af7d45
VZ
338// ----------------------------------------------------------------------------
339// emulating key presses
340// ----------------------------------------------------------------------------
341
b37023dc
VS
342#ifdef __WIN32__
343// the generic version is unused in wxMSW
344bool wxTextCtrlBase::EmulateKeyPress(const wxKeyEvent& WXUNUSED(event))
345{
cb719f2e 346 return false;
b37023dc
VS
347}
348#else // !__WIN32__
94af7d45
VZ
349bool wxTextCtrlBase::EmulateKeyPress(const wxKeyEvent& event)
350{
02a48e3b 351 wxChar ch = 0;
94af7d45
VZ
352 int keycode = event.GetKeyCode();
353 switch ( keycode )
354 {
355 case WXK_NUMPAD0:
356 case WXK_NUMPAD1:
357 case WXK_NUMPAD2:
358 case WXK_NUMPAD3:
359 case WXK_NUMPAD4:
360 case WXK_NUMPAD5:
361 case WXK_NUMPAD6:
362 case WXK_NUMPAD7:
363 case WXK_NUMPAD8:
364 case WXK_NUMPAD9:
365 ch = _T('0') + keycode - WXK_NUMPAD0;
366 break;
367
368 case WXK_MULTIPLY:
369 case WXK_NUMPAD_MULTIPLY:
370 ch = _T('*');
371 break;
372
373 case WXK_ADD:
374 case WXK_NUMPAD_ADD:
375 ch = _T('+');
376 break;
377
378 case WXK_SUBTRACT:
379 case WXK_NUMPAD_SUBTRACT:
380 ch = _T('-');
381 break;
382
383 case WXK_DECIMAL:
384 case WXK_NUMPAD_DECIMAL:
385 ch = _T('.');
386 break;
387
388 case WXK_DIVIDE:
389 case WXK_NUMPAD_DIVIDE:
390 ch = _T('/');
391 break;
392
cd916794
VZ
393 case WXK_DELETE:
394 case WXK_NUMPAD_DELETE:
395 // delete the character at cursor
396 {
397 const long pos = GetInsertionPoint(),
398 last = GetLastPosition();
399 if ( pos < last )
400 Remove(pos, pos + 1);
401 }
402 break;
403
404 case WXK_BACK:
405 // delete the character before the cursor
406 {
407 const long pos = GetInsertionPoint();
408 if ( pos > 0 )
409 Remove(pos - 1, pos);
410 }
411 break;
412
94af7d45 413 default:
c4d25c01
VS
414#if wxUSE_UNICODE
415 if ( event.GetUnicodeKey() )
416 {
417 ch = event.GetUnicodeKey();
418 }
419 else
420#endif
401eb3de 421 if ( keycode < 256 && keycode >= 0 && wxIsprint(keycode) )
94af7d45
VZ
422 {
423 // FIXME this is not going to work for non letters...
424 if ( !event.ShiftDown() )
425 {
401eb3de 426 keycode = wxTolower(keycode);
94af7d45
VZ
427 }
428
429 ch = (wxChar)keycode;
430 }
431 else
432 {
433 ch = _T('\0');
434 }
435 }
436
437 if ( ch )
438 {
439 WriteText(ch);
440
cb719f2e 441 return true;
94af7d45 442 }
94af7d45 443
cb719f2e 444 return false;
94af7d45 445}
b37023dc 446#endif // !__WIN32__
94af7d45 447
1e6feb95 448// ----------------------------------------------------------------------------
a5aa8086 449// selection and ranges
1e6feb95
VZ
450// ----------------------------------------------------------------------------
451
452void wxTextCtrlBase::SelectAll()
453{
454 SetSelection(0, GetLastPosition());
455}
456
eef97940 457wxString wxTextCtrlBase::GetStringSelection() const
18414479
VZ
458{
459 long from, to;
460 GetSelection(&from, &to);
461
a5aa8086
VZ
462 return GetRange(from, to);
463}
464
465wxString wxTextCtrlBase::GetRange(long from, long to) const
466{
18414479
VZ
467 wxString sel;
468 if ( from < to )
469 {
470 sel = GetValue().Mid(from, to - from);
471 }
472
473 return sel;
474}
475
e39af974
JS
476// do the window-specific processing after processing the update event
477void wxTextCtrlBase::DoUpdateWindowUI(wxUpdateUIEvent& event)
478{
479 if ( event.GetSetEnabled() )
480 Enable(event.GetEnabled());
cb719f2e 481
e39af974
JS
482 if ( event.GetSetText() )
483 {
484 if ( event.GetText() != GetValue() )
485 SetValue(event.GetText());
cb719f2e 486 }
e39af974
JS
487}
488
efe66bbc
VZ
489// ----------------------------------------------------------------------------
490// hit testing
491// ----------------------------------------------------------------------------
492
692c9b86
VZ
493wxTextCtrlHitTestResult
494wxTextCtrlBase::HitTest(const wxPoint& pt, wxTextCoord *x, wxTextCoord *y) const
495{
496 // implement in terms of the other overload as the native ports typically
497 // can get the position and not (x, y) pair directly (although wxUniv
498 // directly gets x and y -- and so overrides this method as well)
499 long pos;
500 wxTextCtrlHitTestResult rc = HitTest(pt, &pos);
501
502 if ( rc != wxTE_HT_UNKNOWN )
503 {
504 PositionToXY(pos, x, y);
505 }
506
507 return rc;
508}
509
efe66bbc
VZ
510wxTextCtrlHitTestResult
511wxTextCtrlBase::HitTest(const wxPoint& WXUNUSED(pt),
692c9b86 512 long * WXUNUSED(pos)) const
efe66bbc
VZ
513{
514 // not implemented
515 return wxTE_HT_UNKNOWN;
516}
e39af974 517
ad0bae85
VZ
518#else // !wxUSE_TEXTCTRL
519
520// define this one even if !wxUSE_TEXTCTRL because it is also used by other
521// controls (wxComboBox and wxSpinCtrl)
522#include "wx/event.h"
523
524DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_UPDATED)
525
526#endif // wxUSE_TEXTCTRL/!wxUSE_TEXTCTRL
1e6feb95 527