]> git.saurik.com Git - wxWidgets.git/blame - src/common/textcmn.cpp
src/X11/font.cpp needs smae change as other wxXXX versions
[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
9d112688
JS
57IMPLEMENT_ABSTRACT_CLASS(wxTextCtrlBase, wxControl)
58
4bc1afd5
VZ
59// ----------------------------------------------------------------------------
60// style functions - not implemented here
61// ----------------------------------------------------------------------------
62
e00a5d3c
JS
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;
89b67477 71 m_leftSubIndent = 0;
e00a5d3c
JS
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;
89b67477 85 m_leftSubIndent = 0;
e00a5d3c
JS
86 m_rightIndent = 0;
87}
88
eda40bfc
VZ
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
e00a5d3c 121 wxTextAttr newAttr(colFg, colBg, font);
cb719f2e 122
e00a5d3c
JS
123 if (attr.HasAlignment())
124 newAttr.SetAlignment(attr.GetAlignment());
125 else if (attrDef.HasAlignment())
126 newAttr.SetAlignment(attrDef.GetAlignment());
cb719f2e 127
e00a5d3c
JS
128 if (attr.HasTabs())
129 newAttr.SetTabs(attr.GetTabs());
130 else if (attrDef.HasTabs())
131 newAttr.SetTabs(attrDef.GetTabs());
cb719f2e 132
e00a5d3c 133 if (attr.HasLeftIndent())
89b67477 134 newAttr.SetLeftIndent(attr.GetLeftIndent(), attr.GetLeftSubIndent());
e00a5d3c 135 else if (attrDef.HasLeftIndent())
89b67477 136 newAttr.SetLeftIndent(attrDef.GetLeftIndent(), attr.GetLeftSubIndent());
cb719f2e 137
e00a5d3c
JS
138 if (attr.HasRightIndent())
139 newAttr.SetRightIndent(attr.GetRightIndent());
140 else if (attrDef.HasRightIndent())
cb719f2e
WS
141 newAttr.SetRightIndent(attrDef.GetRightIndent());
142
e00a5d3c 143 return newAttr;
eda40bfc
VZ
144}
145
e00a5d3c
JS
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;
89b67477 153 m_leftSubIndent = attr.m_leftSubIndent;
e00a5d3c
JS
154 m_rightIndent = attr.m_rightIndent;
155 m_tabs = attr.m_tabs;
156 m_flags = attr.m_flags;
157}
158
159
4bc1afd5
VZ
160// apply styling to text range
161bool wxTextCtrlBase::SetStyle(long WXUNUSED(start), long WXUNUSED(end),
162 const wxTextAttr& WXUNUSED(style))
163{
0ec1179b 164 // to be implemented in derived classes
cb719f2e 165 return false;
4bc1afd5
VZ
166}
167
e00a5d3c
JS
168// get the styling at the given position
169bool wxTextCtrlBase::GetStyle(long WXUNUSED(position), wxTextAttr& WXUNUSED(style))
170{
0ec1179b 171 // to be implemented in derived classes
cb719f2e 172 return false;
e00a5d3c
JS
173}
174
4bc1afd5 175// change default text attributes
eda40bfc 176bool wxTextCtrlBase::SetDefaultStyle(const wxTextAttr& style)
4bc1afd5 177{
c598f225
VZ
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);
eda40bfc 185
cb719f2e 186 return true;
4bc1afd5
VZ
187}
188
a1b82138
VZ
189// ----------------------------------------------------------------------------
190// file IO functions
191// ----------------------------------------------------------------------------
192
3306aec1 193bool wxTextCtrlBase::DoLoadFile(const wxString& filename, int WXUNUSED(fileType))
a1b82138 194{
1e6feb95 195#if wxUSE_FFILE
a1b82138
VZ
196 wxFFile file(filename);
197 if ( file.IsOpened() )
198 {
199 wxString text;
200 if ( file.ReadAll(&text) )
201 {
202 SetValue(text);
203
204 DiscardEdits();
205
206 m_filename = filename;
207
cb719f2e 208 return true;
a1b82138
VZ
209 }
210 }
211
212 wxLogError(_("File couldn't be loaded."));
1e6feb95 213#endif // wxUSE_FFILE
a1b82138 214
cb719f2e 215 return false;
a1b82138
VZ
216}
217
0ec1179b 218bool wxTextAreaBase::SaveFile(const wxString& filename, int fileType)
a1b82138 219{
7d8268a1 220 wxString filenameToUse = filename.empty() ? m_filename : filename;
64dcc269 221 if ( filenameToUse.empty() )
a1b82138
VZ
222 {
223 // what kind of message to give? is it an error or a program bug?
223d09f6 224 wxLogDebug(wxT("Can't save textctrl to file without filename."));
a1b82138 225
cb719f2e 226 return false;
a1b82138
VZ
227 }
228
3306aec1
JS
229 return DoSaveFile(filenameToUse, fileType);
230}
231
232bool wxTextCtrlBase::DoSaveFile(const wxString& filename, int WXUNUSED(fileType))
233{
1e6feb95 234#if wxUSE_FFILE
3306aec1 235 wxFFile file(filename, _T("w"));
a1b82138
VZ
236 if ( file.IsOpened() && file.Write(GetValue()) )
237 {
3306aec1
JS
238 // if it worked, save for future calls
239 m_filename = filename;
ee2ec18e 240
a1b82138
VZ
241 // it's not modified any longer
242 DiscardEdits();
243
cb719f2e 244 return true;
a1b82138 245 }
64dcc269 246#endif // wxUSE_FFILE
a1b82138
VZ
247
248 wxLogError(_("The text couldn't be saved."));
249
cb719f2e 250 return false;
a1b82138
VZ
251}
252
253// ----------------------------------------------------------------------------
254// stream-like insertion operator
255// ----------------------------------------------------------------------------
256
257wxTextCtrl& wxTextCtrlBase::operator<<(const wxString& s)
258{
259 AppendText(s);
260 return *TEXTCTRL(this);
261}
262
263wxTextCtrl& wxTextCtrlBase::operator<<(float f)
264{
265 wxString str;
223d09f6 266 str.Printf(wxT("%.2f"), f);
a1b82138
VZ
267 AppendText(str);
268 return *TEXTCTRL(this);
269}
270
271wxTextCtrl& wxTextCtrlBase::operator<<(double d)
272{
273 wxString str;
223d09f6 274 str.Printf(wxT("%.2f"), d);
a1b82138
VZ
275 AppendText(str);
276 return *TEXTCTRL(this);
277}
278
279wxTextCtrl& wxTextCtrlBase::operator<<(int i)
280{
281 wxString str;
223d09f6 282 str.Printf(wxT("%d"), i);
a1b82138
VZ
283 AppendText(str);
284 return *TEXTCTRL(this);
285}
286
287wxTextCtrl& wxTextCtrlBase::operator<<(long i)
288{
289 wxString str;
223d09f6 290 str.Printf(wxT("%ld"), i);
a1b82138
VZ
291 AppendText(str);
292 return *TEXTCTRL(this);
293}
294
a324a7bc 295wxTextCtrl& wxTextCtrlBase::operator<<(const wxChar c)
a1b82138
VZ
296{
297 return operator<<(wxString(c));
298}
299
300// ----------------------------------------------------------------------------
301// streambuf methods implementation
302// ----------------------------------------------------------------------------
303
15cdc341 304#if wxHAS_TEXT_WINDOW_STREAM
a1b82138 305
d73e6791 306int wxTextCtrlBase::overflow(int c)
a1b82138 307{
d73e6791 308 AppendText((wxChar)c);
a1b82138 309
d73e6791 310 // return something different from EOF
a1b82138
VZ
311 return 0;
312}
313
15cdc341 314#endif // wxHAS_TEXT_WINDOW_STREAM
a1b82138 315
94af7d45
VZ
316// ----------------------------------------------------------------------------
317// emulating key presses
318// ----------------------------------------------------------------------------
319
320bool wxTextCtrlBase::EmulateKeyPress(const wxKeyEvent& event)
321{
0ec1179b
VZ
322 // we have a native implementation for Win32 and so don't need this one
323#ifndef __WIN32__
02a48e3b 324 wxChar ch = 0;
94af7d45
VZ
325 int keycode = event.GetKeyCode();
326 switch ( keycode )
327 {
328 case WXK_NUMPAD0:
329 case WXK_NUMPAD1:
330 case WXK_NUMPAD2:
331 case WXK_NUMPAD3:
332 case WXK_NUMPAD4:
333 case WXK_NUMPAD5:
334 case WXK_NUMPAD6:
335 case WXK_NUMPAD7:
336 case WXK_NUMPAD8:
337 case WXK_NUMPAD9:
7a893a31 338 ch = (wxChar)(_T('0') + keycode - WXK_NUMPAD0);
94af7d45
VZ
339 break;
340
341 case WXK_MULTIPLY:
342 case WXK_NUMPAD_MULTIPLY:
343 ch = _T('*');
344 break;
345
346 case WXK_ADD:
347 case WXK_NUMPAD_ADD:
348 ch = _T('+');
349 break;
350
351 case WXK_SUBTRACT:
352 case WXK_NUMPAD_SUBTRACT:
353 ch = _T('-');
354 break;
355
356 case WXK_DECIMAL:
357 case WXK_NUMPAD_DECIMAL:
358 ch = _T('.');
359 break;
360
361 case WXK_DIVIDE:
362 case WXK_NUMPAD_DIVIDE:
363 ch = _T('/');
364 break;
365
cd916794
VZ
366 case WXK_DELETE:
367 case WXK_NUMPAD_DELETE:
368 // delete the character at cursor
369 {
7d8268a1
WS
370 const long pos = GetInsertionPoint();
371 if ( pos < GetLastPosition() )
cd916794
VZ
372 Remove(pos, pos + 1);
373 }
374 break;
375
376 case WXK_BACK:
377 // delete the character before the cursor
378 {
379 const long pos = GetInsertionPoint();
380 if ( pos > 0 )
381 Remove(pos - 1, pos);
382 }
383 break;
384
94af7d45 385 default:
c4d25c01
VS
386#if wxUSE_UNICODE
387 if ( event.GetUnicodeKey() )
388 {
389 ch = event.GetUnicodeKey();
390 }
391 else
392#endif
401eb3de 393 if ( keycode < 256 && keycode >= 0 && wxIsprint(keycode) )
94af7d45
VZ
394 {
395 // FIXME this is not going to work for non letters...
396 if ( !event.ShiftDown() )
397 {
401eb3de 398 keycode = wxTolower(keycode);
94af7d45
VZ
399 }
400
401 ch = (wxChar)keycode;
402 }
403 else
404 {
405 ch = _T('\0');
406 }
407 }
408
409 if ( ch )
410 {
411 WriteText(ch);
412
cb719f2e 413 return true;
94af7d45 414 }
c8fe7fda
VZ
415#else // __WIN32__
416 wxUnusedVar(event);
417#endif // !__WIN32__/__WIN32__
94af7d45 418
0ec1179b 419 return false;
18414479
VZ
420}
421
e39af974
JS
422// do the window-specific processing after processing the update event
423void wxTextCtrlBase::DoUpdateWindowUI(wxUpdateUIEvent& event)
424{
a3a4105d
VZ
425 // call inherited, but skip the wxControl's version, and call directly the
426 // wxWindow's one instead, because the only reason why we are overriding this
427 // function is that we want to use SetValue() instead of wxControl::SetLabel()
428 wxWindowBase::DoUpdateWindowUI(event);
cb719f2e 429
a3a4105d 430 // update text
e39af974
JS
431 if ( event.GetSetText() )
432 {
433 if ( event.GetText() != GetValue() )
434 SetValue(event.GetText());
cb719f2e 435 }
e39af974
JS
436}
437
efe66bbc
VZ
438// ----------------------------------------------------------------------------
439// hit testing
440// ----------------------------------------------------------------------------
441
692c9b86 442wxTextCtrlHitTestResult
0ec1179b 443wxTextAreaBase::HitTest(const wxPoint& pt, wxTextCoord *x, wxTextCoord *y) const
692c9b86
VZ
444{
445 // implement in terms of the other overload as the native ports typically
446 // can get the position and not (x, y) pair directly (although wxUniv
447 // directly gets x and y -- and so overrides this method as well)
448 long pos;
449 wxTextCtrlHitTestResult rc = HitTest(pt, &pos);
450
451 if ( rc != wxTE_HT_UNKNOWN )
452 {
453 PositionToXY(pos, x, y);
454 }
455
456 return rc;
457}
458
efe66bbc 459wxTextCtrlHitTestResult
0ec1179b 460wxTextAreaBase::HitTest(const wxPoint& WXUNUSED(pt), long * WXUNUSED(pos)) const
efe66bbc
VZ
461{
462 // not implemented
463 return wxTE_HT_UNKNOWN;
464}
e39af974 465
ee2ec18e
VZ
466// ----------------------------------------------------------------------------
467// events
468// ----------------------------------------------------------------------------
469
0ec1179b 470/* static */
fa2f57be 471bool wxTextCtrlBase::SendTextUpdatedEvent(wxWindow *win)
ee2ec18e 472{
0ec1179b 473 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, win->GetId());
ee2ec18e
VZ
474
475 // do not do this as it could be very inefficient if the text control
476 // contains a lot of text and we're not using ref-counted wxString
477 // implementation -- instead, event.GetString() will query the control for
478 // its current text if needed
0ec1179b 479 //event.SetString(win->GetValue());
ee2ec18e 480
0ec1179b 481 event.SetEventObject(win);
fa2f57be 482 return win->GetEventHandler()->ProcessEvent(event);
ee2ec18e
VZ
483}
484
ad0bae85
VZ
485#else // !wxUSE_TEXTCTRL
486
487// define this one even if !wxUSE_TEXTCTRL because it is also used by other
488// controls (wxComboBox and wxSpinCtrl)
ad0bae85
VZ
489
490DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_UPDATED)
491
492#endif // wxUSE_TEXTCTRL/!wxUSE_TEXTCTRL