superposition of text styles in wxTextCtrl now works as expected (and as documented)
[wxWidgets.git] / src / common / textcmn.cpp
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
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 #ifdef __GNUG__
17 #pragma implementation "textctrlbase.h"
18 #endif
19
20 // for compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #if wxUSE_TEXTCTRL
28
29 #ifndef WX_PRECOMP
30 #include "wx/intl.h"
31 #include "wx/log.h"
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
49 IMPLEMENT_DYNAMIC_CLASS(wxTextUrlEvent, wxCommandEvent)
50
51 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_UPDATED)
52 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_ENTER)
53 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_URL)
54 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_MAXLEN)
55
56 // ----------------------------------------------------------------------------
57 // ctor
58 // ----------------------------------------------------------------------------
59
60 wxTextCtrlBase::wxTextCtrlBase()
61 {
62 }
63
64 wxTextCtrlBase::~wxTextCtrlBase()
65 {
66 }
67
68 // ----------------------------------------------------------------------------
69 // style functions - not implemented here
70 // ----------------------------------------------------------------------------
71
72 /* static */
73 wxTextAttr wxTextAttr::Combine(const wxTextAttr& attr,
74 const wxTextAttr& attrDef,
75 const wxTextCtrlBase *text)
76 {
77 wxFont font = attr.GetFont();
78 if ( !font.Ok() )
79 {
80 font = attrDef.GetFont();
81
82 if ( text && !font.Ok() )
83 font = text->GetFont();
84 }
85
86 wxColour colFg = attr.GetTextColour();
87 if ( !colFg.Ok() )
88 {
89 colFg = attrDef.GetTextColour();
90
91 if ( text && !colFg.Ok() )
92 colFg = text->GetForegroundColour();
93 }
94
95 wxColour colBg = attr.GetBackgroundColour();
96 if ( !colBg.Ok() )
97 {
98 colBg = attrDef.GetBackgroundColour();
99
100 if ( text && !colBg.Ok() )
101 colBg = text->GetBackgroundColour();
102 }
103
104 return wxTextAttr(colFg, colBg, font);
105 }
106
107 // apply styling to text range
108 bool wxTextCtrlBase::SetStyle(long WXUNUSED(start), long WXUNUSED(end),
109 const wxTextAttr& WXUNUSED(style))
110 {
111 // to be implemented in derived TextCtrl classes
112 return FALSE;
113 }
114
115 // change default text attributes
116 bool wxTextCtrlBase::SetDefaultStyle(const wxTextAttr& style)
117 {
118 // keep the old attributes if the new style doesn't specify them
119 m_defaultStyle = wxTextAttr::Combine(style, m_defaultStyle, this);
120
121 return TRUE;
122 }
123
124 // get default text attributes
125 const wxTextAttr& wxTextCtrlBase::GetDefaultStyle() const
126 {
127 return m_defaultStyle;
128 }
129
130 // ----------------------------------------------------------------------------
131 // file IO functions
132 // ----------------------------------------------------------------------------
133
134 bool wxTextCtrlBase::LoadFile(const wxString& filename)
135 {
136 #if wxUSE_FFILE
137 wxFFile file(filename);
138 if ( file.IsOpened() )
139 {
140 wxString text;
141 if ( file.ReadAll(&text) )
142 {
143 SetValue(text);
144
145 DiscardEdits();
146
147 m_filename = filename;
148
149 return TRUE;
150 }
151 }
152
153 wxLogError(_("File couldn't be loaded."));
154 #endif // wxUSE_FFILE
155
156 return FALSE;
157 }
158
159 bool wxTextCtrlBase::SaveFile(const wxString& filename)
160 {
161 wxString filenameToUse = filename.IsEmpty() ? m_filename : filename;
162 if ( !filenameToUse )
163 {
164 // what kind of message to give? is it an error or a program bug?
165 wxLogDebug(wxT("Can't save textctrl to file without filename."));
166
167 return FALSE;
168 }
169
170 #if wxUSE_FFILE
171 wxFFile file(filename, "w");
172 if ( file.IsOpened() && file.Write(GetValue()) )
173 {
174 // it's not modified any longer
175 DiscardEdits();
176
177 m_filename = filename;
178
179 return TRUE;
180 }
181
182 wxLogError(_("The text couldn't be saved."));
183 #endif // wxUSE_FFILE
184
185 return FALSE;
186 }
187
188 // ----------------------------------------------------------------------------
189 // stream-like insertion operator
190 // ----------------------------------------------------------------------------
191
192 wxTextCtrl& wxTextCtrlBase::operator<<(const wxString& s)
193 {
194 AppendText(s);
195 return *TEXTCTRL(this);
196 }
197
198 wxTextCtrl& wxTextCtrlBase::operator<<(float f)
199 {
200 wxString str;
201 str.Printf(wxT("%.2f"), f);
202 AppendText(str);
203 return *TEXTCTRL(this);
204 }
205
206 wxTextCtrl& wxTextCtrlBase::operator<<(double d)
207 {
208 wxString str;
209 str.Printf(wxT("%.2f"), d);
210 AppendText(str);
211 return *TEXTCTRL(this);
212 }
213
214 wxTextCtrl& wxTextCtrlBase::operator<<(int i)
215 {
216 wxString str;
217 str.Printf(wxT("%d"), i);
218 AppendText(str);
219 return *TEXTCTRL(this);
220 }
221
222 wxTextCtrl& wxTextCtrlBase::operator<<(long i)
223 {
224 wxString str;
225 str.Printf(wxT("%ld"), i);
226 AppendText(str);
227 return *TEXTCTRL(this);
228 }
229
230 wxTextCtrl& wxTextCtrlBase::operator<<(const wxChar c)
231 {
232 return operator<<(wxString(c));
233 }
234
235 // ----------------------------------------------------------------------------
236 // streambuf methods implementation
237 // ----------------------------------------------------------------------------
238
239 #ifndef NO_TEXT_WINDOW_STREAM
240
241 int wxTextCtrlBase::overflow(int c)
242 {
243 AppendText((wxChar)c);
244
245 // return something different from EOF
246 return 0;
247 }
248
249 #endif // NO_TEXT_WINDOW_STREAM
250
251 // ----------------------------------------------------------------------------
252 // clipboard stuff
253 // ----------------------------------------------------------------------------
254
255 bool wxTextCtrlBase::CanCopy() const
256 {
257 // can copy if there's a selection
258 long from, to;
259 GetSelection(&from, &to);
260 return from != to;
261 }
262
263 bool wxTextCtrlBase::CanCut() const
264 {
265 // can cut if there's a selection and if we're not read only
266 return CanCopy() && IsEditable();
267 }
268
269 bool wxTextCtrlBase::CanPaste() const
270 {
271 // can paste if we are not read only
272 return IsEditable();
273 }
274
275 // ----------------------------------------------------------------------------
276 // misc
277 // ----------------------------------------------------------------------------
278
279 void wxTextCtrlBase::SelectAll()
280 {
281 SetSelection(0, GetLastPosition());
282 }
283
284 wxString wxTextCtrlBase::GetStringSelection() const
285 {
286 long from, to;
287 GetSelection(&from, &to);
288
289 wxString sel;
290 if ( from < to )
291 {
292 sel = GetValue().Mid(from, to - from);
293 }
294
295 return sel;
296 }
297
298 #else // !wxUSE_TEXTCTRL
299
300 // define this one even if !wxUSE_TEXTCTRL because it is also used by other
301 // controls (wxComboBox and wxSpinCtrl)
302 #include "wx/event.h"
303
304 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_UPDATED)
305
306 #endif // wxUSE_TEXTCTRL/!wxUSE_TEXTCTRL
307