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