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