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