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