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