]> git.saurik.com Git - wxWidgets.git/blob - src/common/textcmn.cpp
No changes, just use wxRecursionGuard instead of manual boolean flag.
[wxWidgets.git] / src / common / textcmn.cpp
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 // Copyright: (c) wxWidgets team
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // for compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
17
18 #ifdef __BORLANDC__
19 #pragma hdrstop
20 #endif
21
22 #ifndef WX_PRECOMP
23 #include "wx/event.h"
24 #endif // WX_PRECOMP
25
26 #if wxUSE_TEXTCTRL
27
28 #include "wx/textctrl.h"
29
30 #ifndef WX_PRECOMP
31 #include "wx/intl.h"
32 #include "wx/log.h"
33 #endif // WX_PRECOMP
34
35 #include "wx/ffile.h"
36
37 extern WXDLLEXPORT_DATA(const char) wxTextCtrlNameStr[] = "text";
38
39 // ----------------------------------------------------------------------------
40 // macros
41 // ----------------------------------------------------------------------------
42
43 // we don't have any objects of type wxTextCtrlBase in the program, only
44 // wxTextCtrl, so this cast is safe
45 #define TEXTCTRL(ptr) ((wxTextCtrl *)(ptr))
46
47 // ============================================================================
48 // implementation
49 // ============================================================================
50
51 // ----------------------------------------------------------------------------
52 // XTI
53 // ----------------------------------------------------------------------------
54
55 wxDEFINE_FLAGS( wxTextCtrlStyle )
56 wxBEGIN_FLAGS( wxTextCtrlStyle )
57 // new style border flags, we put them first to
58 // use them for streaming out
59 wxFLAGS_MEMBER(wxBORDER_SIMPLE)
60 wxFLAGS_MEMBER(wxBORDER_SUNKEN)
61 wxFLAGS_MEMBER(wxBORDER_DOUBLE)
62 wxFLAGS_MEMBER(wxBORDER_RAISED)
63 wxFLAGS_MEMBER(wxBORDER_STATIC)
64 wxFLAGS_MEMBER(wxBORDER_NONE)
65
66 // old style border flags
67 wxFLAGS_MEMBER(wxSIMPLE_BORDER)
68 wxFLAGS_MEMBER(wxSUNKEN_BORDER)
69 wxFLAGS_MEMBER(wxDOUBLE_BORDER)
70 wxFLAGS_MEMBER(wxRAISED_BORDER)
71 wxFLAGS_MEMBER(wxSTATIC_BORDER)
72 wxFLAGS_MEMBER(wxBORDER)
73
74 // standard window styles
75 wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
76 wxFLAGS_MEMBER(wxCLIP_CHILDREN)
77 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
78 wxFLAGS_MEMBER(wxWANTS_CHARS)
79 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
80 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
81 wxFLAGS_MEMBER(wxVSCROLL)
82 wxFLAGS_MEMBER(wxHSCROLL)
83
84 wxFLAGS_MEMBER(wxTE_PROCESS_ENTER)
85 wxFLAGS_MEMBER(wxTE_PROCESS_TAB)
86 wxFLAGS_MEMBER(wxTE_MULTILINE)
87 wxFLAGS_MEMBER(wxTE_PASSWORD)
88 wxFLAGS_MEMBER(wxTE_READONLY)
89 wxFLAGS_MEMBER(wxHSCROLL)
90 wxFLAGS_MEMBER(wxTE_RICH)
91 wxFLAGS_MEMBER(wxTE_RICH2)
92 wxFLAGS_MEMBER(wxTE_AUTO_URL)
93 wxFLAGS_MEMBER(wxTE_NOHIDESEL)
94 wxFLAGS_MEMBER(wxTE_LEFT)
95 wxFLAGS_MEMBER(wxTE_CENTRE)
96 wxFLAGS_MEMBER(wxTE_RIGHT)
97 wxFLAGS_MEMBER(wxTE_DONTWRAP)
98 wxFLAGS_MEMBER(wxTE_CHARWRAP)
99 wxFLAGS_MEMBER(wxTE_WORDWRAP)
100 wxEND_FLAGS( wxTextCtrlStyle )
101
102 wxIMPLEMENT_DYNAMIC_CLASS_XTI(wxTextCtrl, wxControl, "wx/textctrl.h")
103
104 wxBEGIN_PROPERTIES_TABLE(wxTextCtrl)
105 wxEVENT_PROPERTY( TextUpdated, wxEVT_TEXT, wxCommandEvent )
106 wxEVENT_PROPERTY( TextEnter, wxEVT_TEXT_ENTER, wxCommandEvent )
107
108 wxPROPERTY( Font, wxFont, SetFont, GetFont , wxEMPTY_PARAMETER_VALUE, \
109 0 /*flags*/, wxT("Helpstring"), wxT("group") )
110 wxPROPERTY( Value, wxString, SetValue, GetValue, wxString(), \
111 0 /*flags*/, wxT("Helpstring"), wxT("group"))
112
113 wxPROPERTY_FLAGS( WindowStyle, wxTextCtrlStyle, long, SetWindowStyleFlag, \
114 GetWindowStyleFlag, wxEMPTY_PARAMETER_VALUE, 0 /*flags*/, \
115 wxT("Helpstring"), wxT("group")) // style
116 wxEND_PROPERTIES_TABLE()
117
118 wxEMPTY_HANDLERS_TABLE(wxTextCtrl)
119
120 wxCONSTRUCTOR_6( wxTextCtrl, wxWindow*, Parent, wxWindowID, Id, \
121 wxString, Value, wxPoint, Position, wxSize, Size, \
122 long, WindowStyle)
123
124
125 IMPLEMENT_DYNAMIC_CLASS(wxTextUrlEvent, wxCommandEvent)
126
127 wxDEFINE_EVENT( wxEVT_TEXT, wxCommandEvent );
128 wxDEFINE_EVENT( wxEVT_TEXT_ENTER, wxCommandEvent );
129 wxDEFINE_EVENT( wxEVT_TEXT_URL, wxTextUrlEvent );
130 wxDEFINE_EVENT( wxEVT_TEXT_MAXLEN, wxCommandEvent );
131
132 IMPLEMENT_ABSTRACT_CLASS(wxTextCtrlBase, wxControl)
133
134 // ============================================================================
135 // wxTextAttr implementation
136 // ============================================================================
137
138 wxTextAttr::wxTextAttr(const wxColour& colText,
139 const wxColour& colBack,
140 const wxFont& font,
141 wxTextAttrAlignment alignment): m_textAlignment(alignment), m_colText(colText), m_colBack(colBack)
142 {
143 Init();
144
145 if (m_colText.IsOk()) m_flags |= wxTEXT_ATTR_TEXT_COLOUR;
146 if (m_colBack.IsOk()) m_flags |= wxTEXT_ATTR_BACKGROUND_COLOUR;
147 if (alignment != wxTEXT_ALIGNMENT_DEFAULT)
148 m_flags |= wxTEXT_ATTR_ALIGNMENT;
149
150 GetFontAttributes(font);
151 }
152
153 // Initialisation
154 void wxTextAttr::Init()
155 {
156 m_textAlignment = wxTEXT_ALIGNMENT_DEFAULT;
157 m_flags = 0;
158 m_leftIndent = 0;
159 m_leftSubIndent = 0;
160 m_rightIndent = 0;
161
162 m_fontSize = 12;
163 m_fontStyle = wxFONTSTYLE_NORMAL;
164 m_fontWeight = wxFONTWEIGHT_NORMAL;
165 m_fontUnderlined = false;
166 m_fontStrikethrough = false;
167 m_fontEncoding = wxFONTENCODING_DEFAULT;
168 m_fontFamily = wxFONTFAMILY_DEFAULT;
169
170 m_paragraphSpacingAfter = 0;
171 m_paragraphSpacingBefore = 0;
172 m_lineSpacing = 0;
173 m_bulletStyle = wxTEXT_ATTR_BULLET_STYLE_NONE;
174 m_textEffects = wxTEXT_ATTR_EFFECT_NONE;
175 m_textEffectFlags = wxTEXT_ATTR_EFFECT_NONE;
176 m_outlineLevel = 0;
177 m_bulletNumber = 0;
178 }
179
180 // Copy
181 void wxTextAttr::Copy(const wxTextAttr& attr)
182 {
183 m_colText = attr.m_colText;
184 m_colBack = attr.m_colBack;
185 m_textAlignment = attr.m_textAlignment;
186 m_leftIndent = attr.m_leftIndent;
187 m_leftSubIndent = attr.m_leftSubIndent;
188 m_rightIndent = attr.m_rightIndent;
189 m_tabs = attr.m_tabs;
190 m_flags = attr.m_flags;
191
192 m_fontSize = attr.m_fontSize;
193 m_fontStyle = attr.m_fontStyle;
194 m_fontWeight = attr.m_fontWeight;
195 m_fontUnderlined = attr.m_fontUnderlined;
196 m_fontStrikethrough = attr.m_fontStrikethrough;
197 m_fontFaceName = attr.m_fontFaceName;
198 m_fontEncoding = attr.m_fontEncoding;
199 m_fontFamily = attr.m_fontFamily;
200 m_textEffects = attr.m_textEffects;
201 m_textEffectFlags = attr.m_textEffectFlags;
202
203 m_paragraphSpacingAfter = attr.m_paragraphSpacingAfter;
204 m_paragraphSpacingBefore = attr.m_paragraphSpacingBefore;
205 m_lineSpacing = attr.m_lineSpacing;
206 m_characterStyleName = attr.m_characterStyleName;
207 m_paragraphStyleName = attr.m_paragraphStyleName;
208 m_listStyleName = attr.m_listStyleName;
209 m_bulletStyle = attr.m_bulletStyle;
210 m_bulletNumber = attr.m_bulletNumber;
211 m_bulletText = attr.m_bulletText;
212 m_bulletFont = attr.m_bulletFont;
213 m_bulletName = attr.m_bulletName;
214 m_outlineLevel = attr.m_outlineLevel;
215
216 m_urlTarget = attr.m_urlTarget;
217 }
218
219 // operators
220 void wxTextAttr::operator= (const wxTextAttr& attr)
221 {
222 Copy(attr);
223 }
224
225 // Equality test
226 bool wxTextAttr::operator== (const wxTextAttr& attr) const
227 {
228 return GetFlags() == attr.GetFlags() &&
229
230 GetTextColour() == attr.GetTextColour() &&
231 GetBackgroundColour() == attr.GetBackgroundColour() &&
232
233 GetAlignment() == attr.GetAlignment() &&
234 GetLeftIndent() == attr.GetLeftIndent() &&
235 GetLeftSubIndent() == attr.GetLeftSubIndent() &&
236 GetRightIndent() == attr.GetRightIndent() &&
237 TabsEq(GetTabs(), attr.GetTabs()) &&
238
239 GetParagraphSpacingAfter() == attr.GetParagraphSpacingAfter() &&
240 GetParagraphSpacingBefore() == attr.GetParagraphSpacingBefore() &&
241 GetLineSpacing() == attr.GetLineSpacing() &&
242 GetCharacterStyleName() == attr.GetCharacterStyleName() &&
243 GetParagraphStyleName() == attr.GetParagraphStyleName() &&
244 GetListStyleName() == attr.GetListStyleName() &&
245
246 GetBulletStyle() == attr.GetBulletStyle() &&
247 GetBulletText() == attr.GetBulletText() &&
248 GetBulletNumber() == attr.GetBulletNumber() &&
249 GetBulletFont() == attr.GetBulletFont() &&
250 GetBulletName() == attr.GetBulletName() &&
251
252 GetTextEffects() == attr.GetTextEffects() &&
253 GetTextEffectFlags() == attr.GetTextEffectFlags() &&
254
255 GetOutlineLevel() == attr.GetOutlineLevel() &&
256
257 GetFontSize() == attr.GetFontSize() &&
258 GetFontStyle() == attr.GetFontStyle() &&
259 GetFontWeight() == attr.GetFontWeight() &&
260 GetFontUnderlined() == attr.GetFontUnderlined() &&
261 GetFontFaceName() == attr.GetFontFaceName() &&
262 GetFontEncoding() == attr.GetFontEncoding() &&
263 GetFontFamily() == attr.GetFontFamily() &&
264
265 GetURL() == attr.GetURL();
266 }
267
268 // Partial equality test. Only returns false if an attribute doesn't match.
269 bool wxTextAttr::EqPartial(const wxTextAttr& attr, bool weakTest) const
270 {
271 int flags = attr.GetFlags();
272
273 if (!weakTest &&
274 ((!HasTextColour() && attr.HasTextColour()) ||
275 (!HasBackgroundColour() && attr.HasBackgroundColour()) ||
276 (!HasFontFaceName() && attr.HasFontFaceName()) ||
277 (!HasFontSize() && attr.HasFontSize()) ||
278 (!HasFontWeight() && attr.HasFontWeight()) ||
279 (!HasFontItalic() && attr.HasFontItalic()) ||
280 (!HasFontUnderlined() && attr.HasFontUnderlined()) ||
281 (!HasFontStrikethrough() && attr.HasFontStrikethrough()) ||
282 (!HasFontEncoding() && attr.HasFontEncoding()) ||
283 (!HasFontFamily() && attr.HasFontFamily()) ||
284 (!HasURL() && attr.HasURL()) ||
285 (!HasAlignment() && attr.HasAlignment()) ||
286 (!HasLeftIndent() && attr.HasLeftIndent()) ||
287 (!HasParagraphSpacingAfter() && attr.HasParagraphSpacingAfter()) ||
288 (!HasParagraphSpacingBefore() && attr.HasParagraphSpacingBefore()) ||
289 (!HasLineSpacing() && attr.HasLineSpacing()) ||
290 (!HasCharacterStyleName() && attr.HasCharacterStyleName()) ||
291 (!HasParagraphStyleName() && attr.HasParagraphStyleName()) ||
292 (!HasListStyleName() && attr.HasListStyleName()) ||
293 (!HasBulletStyle() && attr.HasBulletStyle()) ||
294 (!HasBulletNumber() && attr.HasBulletNumber()) ||
295 (!HasBulletText() && attr.HasBulletText()) ||
296 (!HasBulletName() && attr.HasBulletName()) ||
297 (!HasTabs() && attr.HasTabs()) ||
298 (!HasTextEffects() && attr.HasTextEffects()) ||
299 (!HasOutlineLevel() && attr.HasOutlineLevel())))
300 {
301 return false;
302 }
303
304 if (HasTextColour() && attr.HasTextColour() && GetTextColour() != attr.GetTextColour())
305 return false;
306
307 if (HasBackgroundColour() && attr.HasBackgroundColour() && GetBackgroundColour() != attr.GetBackgroundColour())
308 return false;
309
310 if (HasFontFaceName() && attr.HasFontFaceName() && GetFontFaceName() != attr.GetFontFaceName())
311 return false;
312
313 // This checks whether the two objects have the same font size dimension (px versus pt)
314 if (HasFontSize() && attr.HasFontSize() && (flags & wxTEXT_ATTR_FONT) != (GetFlags() & wxTEXT_ATTR_FONT))
315 return false;
316
317 if (HasFontPointSize() && attr.HasFontPointSize() && GetFontSize() != attr.GetFontSize())
318 return false;
319
320 if (HasFontPixelSize() && attr.HasFontPixelSize() && GetFontSize() != attr.GetFontSize())
321 return false;
322
323 if (HasFontWeight() && attr.HasFontWeight() && GetFontWeight() != attr.GetFontWeight())
324 return false;
325
326 if (HasFontItalic() && attr.HasFontItalic() && GetFontStyle() != attr.GetFontStyle())
327 return false;
328
329 if (HasFontUnderlined() && attr.HasFontUnderlined() && GetFontUnderlined() != attr.GetFontUnderlined())
330 return false;
331
332 if (HasFontStrikethrough() && attr.HasFontStrikethrough() && GetFontStrikethrough() != attr.GetFontStrikethrough())
333 return false;
334
335 if (HasFontEncoding() && attr.HasFontEncoding() && GetFontEncoding() != attr.GetFontEncoding())
336 return false;
337
338 if (HasFontFamily() && attr.HasFontFamily() && GetFontFamily() != attr.GetFontFamily())
339 return false;
340
341 if (HasURL() && attr.HasURL() && GetURL() != attr.GetURL())
342 return false;
343
344 if (HasAlignment() && attr.HasAlignment() && GetAlignment() != attr.GetAlignment())
345 return false;
346
347 if (HasLeftIndent() && attr.HasLeftIndent() &&
348 ((GetLeftIndent() != attr.GetLeftIndent()) || (GetLeftSubIndent() != attr.GetLeftSubIndent())))
349 return false;
350
351 if (HasRightIndent() && attr.HasRightIndent() && (GetRightIndent() != attr.GetRightIndent()))
352 return false;
353
354 if (HasParagraphSpacingAfter() && attr.HasParagraphSpacingAfter() &&
355 (GetParagraphSpacingAfter() != attr.GetParagraphSpacingAfter()))
356 return false;
357
358 if (HasParagraphSpacingBefore() && attr.HasParagraphSpacingBefore() &&
359 (GetParagraphSpacingBefore() != attr.GetParagraphSpacingBefore()))
360 return false;
361
362 if (HasLineSpacing() && attr.HasLineSpacing() && (GetLineSpacing() != attr.GetLineSpacing()))
363 return false;
364
365 if (HasCharacterStyleName() && attr.HasCharacterStyleName() && (GetCharacterStyleName() != attr.GetCharacterStyleName()))
366 return false;
367
368 if (HasParagraphStyleName() && attr.HasParagraphStyleName() && (GetParagraphStyleName() != attr.GetParagraphStyleName()))
369 return false;
370
371 if (HasListStyleName() && attr.HasListStyleName() && (GetListStyleName() != attr.GetListStyleName()))
372 return false;
373
374 if (HasBulletStyle() && attr.HasBulletStyle() && (GetBulletStyle() != attr.GetBulletStyle()))
375 return false;
376
377 if (HasBulletNumber() && attr.HasBulletNumber() && (GetBulletNumber() != attr.GetBulletNumber()))
378 return false;
379
380 if (HasBulletText() && attr.HasBulletText() &&
381 (GetBulletText() != attr.GetBulletText()) &&
382 (GetBulletFont() != attr.GetBulletFont()))
383 return false;
384
385 if (HasBulletName() && attr.HasBulletName() && (GetBulletName() != attr.GetBulletName()))
386 return false;
387
388 if (HasTabs() && attr.HasTabs() && !TabsEq(GetTabs(), attr.GetTabs()))
389 return false;
390
391 if ((HasPageBreak() != attr.HasPageBreak()))
392 return false;
393
394 if (HasTextEffects() && attr.HasTextEffects())
395 {
396 if (!BitlistsEqPartial(GetTextEffects(), attr.GetTextEffects(), attr.GetTextEffectFlags()))
397 return false;
398 }
399
400 if (HasOutlineLevel() && attr.HasOutlineLevel() && (GetOutlineLevel() != attr.GetOutlineLevel()))
401 return false;
402
403 return true;
404 }
405
406 // Create font from font attributes.
407 wxFont wxTextAttr::GetFont() const
408 {
409 if ( !HasFont() )
410 return wxNullFont;
411
412 int fontSize = 10;
413 if (HasFontSize())
414 fontSize = GetFontSize();
415
416 wxFontStyle fontStyle = wxFONTSTYLE_NORMAL;
417 if (HasFontItalic())
418 fontStyle = GetFontStyle();
419
420 wxFontWeight fontWeight = wxFONTWEIGHT_NORMAL;
421 if (HasFontWeight())
422 fontWeight = GetFontWeight();
423
424 bool underlined = false;
425 if (HasFontUnderlined())
426 underlined = GetFontUnderlined();
427
428 bool strikethrough = false;
429 if (HasFontStrikethrough())
430 strikethrough = GetFontStrikethrough();
431
432 wxString fontFaceName;
433 if (HasFontFaceName())
434 fontFaceName = GetFontFaceName();
435
436 wxFontEncoding encoding = wxFONTENCODING_DEFAULT;
437 if (HasFontEncoding())
438 encoding = GetFontEncoding();
439
440 wxFontFamily fontFamily = wxFONTFAMILY_DEFAULT;
441 if (HasFontFamily())
442 fontFamily = GetFontFamily();
443
444 if (HasFontPixelSize())
445 {
446 wxFont font(wxSize(0, fontSize), fontFamily, fontStyle, fontWeight, underlined, fontFaceName, encoding);
447 if (strikethrough)
448 font.SetStrikethrough(true);
449 return font;
450 }
451 else
452 {
453 wxFont font(fontSize, fontFamily, fontStyle, fontWeight, underlined, fontFaceName, encoding);
454 if (strikethrough)
455 font.SetStrikethrough(true);
456 return font;
457 }
458 }
459
460 // Get attributes from font.
461 bool wxTextAttr::GetFontAttributes(const wxFont& font, int flags)
462 {
463 if (!font.IsOk())
464 return false;
465
466 // If we pass both pixel and point size attributes, this is an indication
467 // to choose the most appropriate units.
468 if ((flags & wxTEXT_ATTR_FONT) == wxTEXT_ATTR_FONT)
469 {
470 if (font.IsUsingSizeInPixels())
471 {
472 m_fontSize = font.GetPixelSize().y;
473 flags &= ~wxTEXT_ATTR_FONT_POINT_SIZE;
474 }
475 else
476 {
477 m_fontSize = font.GetPointSize();
478 flags &= ~wxTEXT_ATTR_FONT_PIXEL_SIZE;
479 }
480 }
481 else if (flags & wxTEXT_ATTR_FONT_POINT_SIZE)
482 {
483 m_fontSize = font.GetPointSize();
484 flags &= ~wxTEXT_ATTR_FONT_PIXEL_SIZE;
485 }
486 else if (flags & wxTEXT_ATTR_FONT_PIXEL_SIZE)
487 {
488 m_fontSize = font.GetPixelSize().y;
489 }
490
491 if (flags & wxTEXT_ATTR_FONT_ITALIC)
492 m_fontStyle = font.GetStyle();
493
494 if (flags & wxTEXT_ATTR_FONT_WEIGHT)
495 m_fontWeight = font.GetWeight();
496
497 if (flags & wxTEXT_ATTR_FONT_UNDERLINE)
498 m_fontUnderlined = font.GetUnderlined();
499
500 if (flags & wxTEXT_ATTR_FONT_STRIKETHROUGH)
501 m_fontStrikethrough = font.GetStrikethrough();
502
503 if (flags & wxTEXT_ATTR_FONT_FACE)
504 m_fontFaceName = font.GetFaceName();
505
506 if (flags & wxTEXT_ATTR_FONT_ENCODING)
507 m_fontEncoding = font.GetEncoding();
508
509 if (flags & wxTEXT_ATTR_FONT_FAMILY)
510 {
511 // wxFont might not know its family, avoid setting m_fontFamily to an
512 // invalid value and rather pretend that we don't have any font family
513 // information at all in this case
514 const wxFontFamily fontFamily = font.GetFamily();
515 if ( fontFamily == wxFONTFAMILY_UNKNOWN )
516 flags &= ~wxTEXT_ATTR_FONT_FAMILY;
517 else
518 m_fontFamily = fontFamily;
519 }
520
521 m_flags |= flags;
522
523 return true;
524 }
525
526 // Resets bits in destination so new attributes aren't merged with mutually exclusive ones
527 static bool wxResetIncompatibleBits(const int mask, const int srcFlags, int& destFlags, int& destBits)
528 {
529 if ((srcFlags & mask) && (destFlags & mask))
530 {
531 destBits &= ~mask;
532 destFlags &= ~mask;
533 }
534
535 return true;
536 }
537
538 bool wxTextAttr::Apply(const wxTextAttr& style, const wxTextAttr* compareWith)
539 {
540 wxTextAttr& destStyle = (*this);
541
542 if (style.HasFontWeight())
543 {
544 if (!(compareWith && compareWith->HasFontWeight() && compareWith->GetFontWeight() == style.GetFontWeight()))
545 destStyle.SetFontWeight(style.GetFontWeight());
546 }
547
548 if (style.HasFontPointSize())
549 {
550 if (!(compareWith && compareWith->HasFontPointSize() && compareWith->GetFontSize() == style.GetFontSize()))
551 destStyle.SetFontPointSize(style.GetFontSize());
552 }
553 else if (style.HasFontPixelSize())
554 {
555 if (!(compareWith && compareWith->HasFontPixelSize() && compareWith->GetFontSize() == style.GetFontSize()))
556 destStyle.SetFontPixelSize(style.GetFontSize());
557 }
558
559 if (style.HasFontItalic())
560 {
561 if (!(compareWith && compareWith->HasFontItalic() && compareWith->GetFontStyle() == style.GetFontStyle()))
562 destStyle.SetFontStyle(style.GetFontStyle());
563 }
564
565 if (style.HasFontUnderlined())
566 {
567 if (!(compareWith && compareWith->HasFontUnderlined() && compareWith->GetFontUnderlined() == style.GetFontUnderlined()))
568 destStyle.SetFontUnderlined(style.GetFontUnderlined());
569 }
570
571 if (style.HasFontStrikethrough())
572 {
573 if (!(compareWith && compareWith->HasFontStrikethrough() && compareWith->GetFontStrikethrough() == style.GetFontStrikethrough()))
574 destStyle.SetFontStrikethrough(style.GetFontStrikethrough());
575 }
576
577 if (style.HasFontFaceName())
578 {
579 if (!(compareWith && compareWith->HasFontFaceName() && compareWith->GetFontFaceName() == style.GetFontFaceName()))
580 destStyle.SetFontFaceName(style.GetFontFaceName());
581 }
582
583 if (style.HasFontEncoding())
584 {
585 if (!(compareWith && compareWith->HasFontEncoding() && compareWith->GetFontEncoding() == style.GetFontEncoding()))
586 destStyle.SetFontEncoding(style.GetFontEncoding());
587 }
588
589 if (style.HasFontFamily())
590 {
591 if (!(compareWith && compareWith->HasFontFamily() && compareWith->GetFontFamily() == style.GetFontFamily()))
592 destStyle.SetFontFamily(style.GetFontFamily());
593 }
594
595 if (style.GetTextColour().IsOk() && style.HasTextColour())
596 {
597 if (!(compareWith && compareWith->HasTextColour() && compareWith->GetTextColour() == style.GetTextColour()))
598 destStyle.SetTextColour(style.GetTextColour());
599 }
600
601 if (style.GetBackgroundColour().IsOk() && style.HasBackgroundColour())
602 {
603 if (!(compareWith && compareWith->HasBackgroundColour() && compareWith->GetBackgroundColour() == style.GetBackgroundColour()))
604 destStyle.SetBackgroundColour(style.GetBackgroundColour());
605 }
606
607 if (style.HasAlignment())
608 {
609 if (!(compareWith && compareWith->HasAlignment() && compareWith->GetAlignment() == style.GetAlignment()))
610 destStyle.SetAlignment(style.GetAlignment());
611 }
612
613 if (style.HasTabs())
614 {
615 if (!(compareWith && compareWith->HasTabs() && TabsEq(compareWith->GetTabs(), style.GetTabs())))
616 destStyle.SetTabs(style.GetTabs());
617 }
618
619 if (style.HasLeftIndent())
620 {
621 if (!(compareWith && compareWith->HasLeftIndent() && compareWith->GetLeftIndent() == style.GetLeftIndent()
622 && compareWith->GetLeftSubIndent() == style.GetLeftSubIndent()))
623 destStyle.SetLeftIndent(style.GetLeftIndent(), style.GetLeftSubIndent());
624 }
625
626 if (style.HasRightIndent())
627 {
628 if (!(compareWith && compareWith->HasRightIndent() && compareWith->GetRightIndent() == style.GetRightIndent()))
629 destStyle.SetRightIndent(style.GetRightIndent());
630 }
631
632 if (style.HasParagraphSpacingAfter())
633 {
634 if (!(compareWith && compareWith->HasParagraphSpacingAfter() && compareWith->GetParagraphSpacingAfter() == style.GetParagraphSpacingAfter()))
635 destStyle.SetParagraphSpacingAfter(style.GetParagraphSpacingAfter());
636 }
637
638 if (style.HasParagraphSpacingBefore())
639 {
640 if (!(compareWith && compareWith->HasParagraphSpacingBefore() && compareWith->GetParagraphSpacingBefore() == style.GetParagraphSpacingBefore()))
641 destStyle.SetParagraphSpacingBefore(style.GetParagraphSpacingBefore());
642 }
643
644 if (style.HasLineSpacing())
645 {
646 if (!(compareWith && compareWith->HasLineSpacing() && compareWith->GetLineSpacing() == style.GetLineSpacing()))
647 destStyle.SetLineSpacing(style.GetLineSpacing());
648 }
649
650 if (style.HasCharacterStyleName())
651 {
652 if (!(compareWith && compareWith->HasCharacterStyleName() && compareWith->GetCharacterStyleName() == style.GetCharacterStyleName()))
653 destStyle.SetCharacterStyleName(style.GetCharacterStyleName());
654 }
655
656 if (style.HasParagraphStyleName())
657 {
658 if (!(compareWith && compareWith->HasParagraphStyleName() && compareWith->GetParagraphStyleName() == style.GetParagraphStyleName()))
659 destStyle.SetParagraphStyleName(style.GetParagraphStyleName());
660 }
661
662 if (style.HasListStyleName())
663 {
664 if (!(compareWith && compareWith->HasListStyleName() && compareWith->GetListStyleName() == style.GetListStyleName()))
665 destStyle.SetListStyleName(style.GetListStyleName());
666 }
667
668 if (style.HasBulletStyle())
669 {
670 if (!(compareWith && compareWith->HasBulletStyle() && compareWith->GetBulletStyle() == style.GetBulletStyle()))
671 destStyle.SetBulletStyle(style.GetBulletStyle());
672 }
673
674 if (style.HasBulletText())
675 {
676 if (!(compareWith && compareWith->HasBulletText() && compareWith->GetBulletText() == style.GetBulletText()))
677 {
678 destStyle.SetBulletText(style.GetBulletText());
679 destStyle.SetBulletFont(style.GetBulletFont());
680 }
681 }
682
683 if (style.HasBulletNumber())
684 {
685 if (!(compareWith && compareWith->HasBulletNumber() && compareWith->GetBulletNumber() == style.GetBulletNumber()))
686 destStyle.SetBulletNumber(style.GetBulletNumber());
687 }
688
689 if (style.HasBulletName())
690 {
691 if (!(compareWith && compareWith->HasBulletName() && compareWith->GetBulletName() == style.GetBulletName()))
692 destStyle.SetBulletName(style.GetBulletName());
693 }
694
695 if (style.HasURL())
696 {
697 if (!(compareWith && compareWith->HasURL() && compareWith->GetURL() == style.GetURL()))
698 destStyle.SetURL(style.GetURL());
699 }
700
701 if (style.HasPageBreak())
702 {
703 if (!(compareWith && compareWith->HasPageBreak()))
704 destStyle.SetPageBreak();
705 }
706
707 if (style.HasTextEffects())
708 {
709 if (!(compareWith && compareWith->HasTextEffects() && compareWith->GetTextEffects() == style.GetTextEffects()))
710 {
711 int destBits = destStyle.GetTextEffects();
712 int destFlags = destStyle.GetTextEffectFlags();
713
714 int srcBits = style.GetTextEffects();
715 int srcFlags = style.GetTextEffectFlags();
716
717 // Reset incompatible bits in the destination
718 wxResetIncompatibleBits((wxTEXT_ATTR_EFFECT_SUPERSCRIPT|wxTEXT_ATTR_EFFECT_SUBSCRIPT), srcFlags, destFlags, destBits);
719 wxResetIncompatibleBits((wxTEXT_ATTR_EFFECT_CAPITALS|wxTEXT_ATTR_EFFECT_SMALL_CAPITALS), srcFlags, destFlags, destBits);
720 wxResetIncompatibleBits((wxTEXT_ATTR_EFFECT_STRIKETHROUGH|wxTEXT_ATTR_EFFECT_DOUBLE_STRIKETHROUGH), srcFlags, destFlags, destBits);
721
722 CombineBitlists(destBits, srcBits, destFlags, srcFlags);
723
724 destStyle.SetTextEffects(destBits);
725 destStyle.SetTextEffectFlags(destFlags);
726 }
727 }
728
729 if (style.HasOutlineLevel())
730 {
731 if (!(compareWith && compareWith->HasOutlineLevel() && compareWith->GetOutlineLevel() == style.GetOutlineLevel()))
732 destStyle.SetOutlineLevel(style.GetOutlineLevel());
733 }
734
735 return true;
736 }
737
738 /* static */
739 wxTextAttr wxTextAttr::Combine(const wxTextAttr& attr,
740 const wxTextAttr& attrDef,
741 const wxTextCtrlBase *text)
742 {
743 wxFont font;
744 if (attr.HasFont())
745 font = attr.GetFont();
746
747 if ( !font.IsOk() )
748 {
749 if (attrDef.HasFont())
750 font = attrDef.GetFont();
751
752 if ( text && !font.IsOk() )
753 font = text->GetFont();
754 }
755
756 wxColour colFg = attr.GetTextColour();
757 if ( !colFg.IsOk() )
758 {
759 colFg = attrDef.GetTextColour();
760
761 if ( text && !colFg.IsOk() )
762 colFg = text->GetForegroundColour();
763 }
764
765 wxColour colBg = attr.GetBackgroundColour();
766 if ( !colBg.IsOk() )
767 {
768 colBg = attrDef.GetBackgroundColour();
769
770 if ( text && !colBg.IsOk() )
771 colBg = text->GetBackgroundColour();
772 }
773
774 wxTextAttr newAttr(colFg, colBg, font);
775
776 if (attr.HasAlignment())
777 newAttr.SetAlignment(attr.GetAlignment());
778 else if (attrDef.HasAlignment())
779 newAttr.SetAlignment(attrDef.GetAlignment());
780
781 if (attr.HasTabs())
782 newAttr.SetTabs(attr.GetTabs());
783 else if (attrDef.HasTabs())
784 newAttr.SetTabs(attrDef.GetTabs());
785
786 if (attr.HasLeftIndent())
787 newAttr.SetLeftIndent(attr.GetLeftIndent(), attr.GetLeftSubIndent());
788 else if (attrDef.HasLeftIndent())
789 newAttr.SetLeftIndent(attrDef.GetLeftIndent(), attr.GetLeftSubIndent());
790
791 if (attr.HasRightIndent())
792 newAttr.SetRightIndent(attr.GetRightIndent());
793 else if (attrDef.HasRightIndent())
794 newAttr.SetRightIndent(attrDef.GetRightIndent());
795
796 return newAttr;
797 }
798
799 /// Compare tabs
800 bool wxTextAttr::TabsEq(const wxArrayInt& tabs1, const wxArrayInt& tabs2)
801 {
802 if (tabs1.GetCount() != tabs2.GetCount())
803 return false;
804
805 size_t i;
806 for (i = 0; i < tabs1.GetCount(); i++)
807 {
808 if (tabs1[i] != tabs2[i])
809 return false;
810 }
811 return true;
812 }
813
814 // Remove attributes
815 bool wxTextAttr::RemoveStyle(wxTextAttr& destStyle, const wxTextAttr& style)
816 {
817 int flags = style.GetFlags();
818 int destFlags = destStyle.GetFlags();
819
820 destStyle.SetFlags(destFlags & ~flags);
821
822 return true;
823 }
824
825 /// Combine two bitlists, specifying the bits of interest with separate flags.
826 bool wxTextAttr::CombineBitlists(int& valueA, int valueB, int& flagsA, int flagsB)
827 {
828 // We want to apply B's bits to A, taking into account each's flags which indicate which bits
829 // are to be taken into account. A zero in B's bits should reset that bit in A but only if B's flags
830 // indicate it.
831
832 // First, reset the 0 bits from B. We make a mask so we're only dealing with B's zero
833 // bits at this point, ignoring any 1 bits in B or 0 bits in B that are not relevant.
834 int valueA2 = ~(~valueB & flagsB) & valueA;
835
836 // Now combine the 1 bits.
837 int valueA3 = (valueB & flagsB) | valueA2;
838
839 valueA = valueA3;
840 flagsA = (flagsA | flagsB);
841
842 return true;
843 }
844
845 /// Compare two bitlists
846 bool wxTextAttr::BitlistsEqPartial(int valueA, int valueB, int flags)
847 {
848 int relevantBitsA = valueA & flags;
849 int relevantBitsB = valueB & flags;
850 return relevantBitsA == relevantBitsB;
851 }
852
853 /// Split into paragraph and character styles
854 bool wxTextAttr::SplitParaCharStyles(const wxTextAttr& style, wxTextAttr& parStyle, wxTextAttr& charStyle)
855 {
856 wxTextAttr defaultCharStyle1(style);
857 wxTextAttr defaultParaStyle1(style);
858 defaultCharStyle1.SetFlags(defaultCharStyle1.GetFlags()&wxTEXT_ATTR_CHARACTER);
859 defaultParaStyle1.SetFlags(defaultParaStyle1.GetFlags()&wxTEXT_ATTR_PARAGRAPH);
860
861 charStyle.Apply(defaultCharStyle1);
862 parStyle.Apply(defaultParaStyle1);
863
864 return true;
865 }
866
867 // apply styling to text range
868 bool wxTextCtrlBase::SetStyle(long WXUNUSED(start), long WXUNUSED(end),
869 const wxTextAttr& WXUNUSED(style))
870 {
871 // to be implemented in derived classes
872 return false;
873 }
874
875 // get the styling at the given position
876 bool wxTextCtrlBase::GetStyle(long WXUNUSED(position), wxTextAttr& WXUNUSED(style))
877 {
878 // to be implemented in derived classes
879 return false;
880 }
881
882 // change default text attributes
883 bool wxTextCtrlBase::SetDefaultStyle(const wxTextAttr& style)
884 {
885 // keep the old attributes if the new style doesn't specify them unless the
886 // new style is empty - then reset m_defaultStyle (as there is no other way
887 // to do it)
888 if ( style.IsDefault() )
889 m_defaultStyle = style;
890 else
891 m_defaultStyle = wxTextAttr::Combine(style, m_defaultStyle, this);
892
893 return true;
894 }
895
896 // ----------------------------------------------------------------------------
897 // file IO functions
898 // ----------------------------------------------------------------------------
899
900 bool wxTextAreaBase::DoLoadFile(const wxString& filename, int WXUNUSED(fileType))
901 {
902 #if wxUSE_FFILE
903 wxFFile file(filename);
904 if ( file.IsOpened() )
905 {
906 wxString text;
907 if ( file.ReadAll(&text) )
908 {
909 SetValue(text);
910
911 DiscardEdits();
912 m_filename = filename;
913
914 return true;
915 }
916 }
917 #else
918 (void)filename; // avoid compiler warning about unreferenced parameter
919 #endif // wxUSE_FFILE
920
921 wxLogError(_("File couldn't be loaded."));
922
923 return false;
924 }
925
926 bool wxTextAreaBase::DoSaveFile(const wxString& filename, int WXUNUSED(fileType))
927 {
928 #if wxUSE_FFILE
929 wxFFile file(filename, wxT("w"));
930 if ( file.IsOpened() && file.Write(GetValue(), *wxConvCurrent) )
931 {
932 // if it worked, save for future calls
933 m_filename = filename;
934
935 // it's not modified any longer
936 DiscardEdits();
937
938 return true;
939 }
940 #else
941 (void)filename; // avoid compiler warning about unreferenced parameter
942 #endif // wxUSE_FFILE
943
944 return false;
945 }
946
947 bool wxTextAreaBase::SaveFile(const wxString& filename, int fileType)
948 {
949 wxString filenameToUse = filename.empty() ? m_filename : filename;
950 if ( filenameToUse.empty() )
951 {
952 // what kind of message to give? is it an error or a program bug?
953 wxLogDebug(wxT("Can't save textctrl to file without filename."));
954
955 return false;
956 }
957
958 return DoSaveFile(filenameToUse, fileType);
959 }
960
961 // ----------------------------------------------------------------------------
962 // stream-like insertion operator
963 // ----------------------------------------------------------------------------
964
965 wxTextCtrl& wxTextCtrlBase::operator<<(const wxString& s)
966 {
967 AppendText(s);
968 return *TEXTCTRL(this);
969 }
970
971 wxTextCtrl& wxTextCtrlBase::operator<<(double d)
972 {
973 return *this << wxString::Format("%.2f", d);
974 }
975
976 wxTextCtrl& wxTextCtrlBase::operator<<(int i)
977 {
978 return *this << wxString::Format("%d", i);
979 }
980
981 wxTextCtrl& wxTextCtrlBase::operator<<(long l)
982 {
983 return *this << wxString::Format("%ld", l);
984 }
985
986 // ----------------------------------------------------------------------------
987 // streambuf methods implementation
988 // ----------------------------------------------------------------------------
989
990 #if wxHAS_TEXT_WINDOW_STREAM
991
992 int wxTextCtrlBase::overflow(int c)
993 {
994 AppendText((wxChar)c);
995
996 // return something different from EOF
997 return 0;
998 }
999
1000 #endif // wxHAS_TEXT_WINDOW_STREAM
1001
1002 // ----------------------------------------------------------------------------
1003 // emulating key presses
1004 // ----------------------------------------------------------------------------
1005
1006 bool wxTextCtrlBase::EmulateKeyPress(const wxKeyEvent& event)
1007 {
1008 bool handled = false;
1009 // we have a native implementation for Win32 and so don't need this one
1010 #ifndef __WIN32__
1011 wxChar ch = 0;
1012 int keycode = event.GetKeyCode();
1013
1014 long from, to;
1015 GetSelection(&from,&to);
1016 long insert = GetInsertionPoint();
1017 long last = GetLastPosition();
1018
1019 // catch arrow left and right
1020
1021 switch ( keycode )
1022 {
1023 case WXK_LEFT:
1024 if ( event.ShiftDown() )
1025 SetSelection( (from > 0 ? from - 1 : 0) , to );
1026 else
1027 {
1028 if ( from != to )
1029 insert = from;
1030 else if ( insert > 0 )
1031 insert -= 1;
1032 SetInsertionPoint( insert );
1033 }
1034 handled = true;
1035 break;
1036 case WXK_RIGHT:
1037 if ( event.ShiftDown() )
1038 SetSelection( from, (to < last ? to + 1 : last) );
1039 else
1040 {
1041 if ( from != to )
1042 insert = to;
1043 else if ( insert < last )
1044 insert += 1;
1045 SetInsertionPoint( insert );
1046 }
1047 handled = true;
1048 break;
1049 case WXK_NUMPAD0:
1050 case WXK_NUMPAD1:
1051 case WXK_NUMPAD2:
1052 case WXK_NUMPAD3:
1053 case WXK_NUMPAD4:
1054 case WXK_NUMPAD5:
1055 case WXK_NUMPAD6:
1056 case WXK_NUMPAD7:
1057 case WXK_NUMPAD8:
1058 case WXK_NUMPAD9:
1059 ch = (wxChar)(wxT('0') + keycode - WXK_NUMPAD0);
1060 break;
1061
1062 case WXK_MULTIPLY:
1063 case WXK_NUMPAD_MULTIPLY:
1064 ch = wxT('*');
1065 break;
1066
1067 case WXK_ADD:
1068 case WXK_NUMPAD_ADD:
1069 ch = wxT('+');
1070 break;
1071
1072 case WXK_SUBTRACT:
1073 case WXK_NUMPAD_SUBTRACT:
1074 ch = wxT('-');
1075 break;
1076
1077 case WXK_DECIMAL:
1078 case WXK_NUMPAD_DECIMAL:
1079 ch = wxT('.');
1080 break;
1081
1082 case WXK_DIVIDE:
1083 case WXK_NUMPAD_DIVIDE:
1084 ch = wxT('/');
1085 break;
1086
1087 case WXK_DELETE:
1088 case WXK_NUMPAD_DELETE:
1089 // delete the character at cursor
1090 {
1091 const long pos = GetInsertionPoint();
1092 if ( pos < GetLastPosition() )
1093 Remove(pos, pos + 1);
1094 handled = true;
1095 }
1096 break;
1097
1098 case WXK_BACK:
1099 // delete the character before the cursor
1100 {
1101 const long pos = GetInsertionPoint();
1102 if ( pos > 0 )
1103 Remove(pos - 1, pos);
1104 handled = true;
1105 }
1106 break;
1107
1108 default:
1109 #if wxUSE_UNICODE
1110 if ( event.GetUnicodeKey() )
1111 {
1112 ch = event.GetUnicodeKey();
1113 }
1114 else
1115 #endif
1116 if ( keycode < 256 && keycode >= 0 && wxIsprint(keycode) )
1117 {
1118 // FIXME this is not going to work for non letters...
1119 if ( !event.ShiftDown() )
1120 {
1121 keycode = wxTolower(keycode);
1122 }
1123
1124 ch = (wxChar)keycode;
1125 }
1126 else
1127 {
1128 ch = wxT('\0');
1129 }
1130 }
1131
1132 if ( ch )
1133 {
1134 WriteText(ch);
1135
1136 handled = true;
1137 }
1138 #else // __WIN32__
1139 wxUnusedVar(event);
1140 #endif // !__WIN32__/__WIN32__
1141
1142 return handled;
1143 }
1144
1145 // ----------------------------------------------------------------------------
1146 // Other miscellaneous stuff
1147 // ----------------------------------------------------------------------------
1148
1149 bool wxTextCtrlBase::SetHint(const wxString& hint)
1150 {
1151 wxCHECK_MSG( IsSingleLine(), false,
1152 wxS("Hints can only be set for single line text controls") );
1153
1154 return wxTextEntry::SetHint(hint);
1155 }
1156
1157 // do the window-specific processing after processing the update event
1158 void wxTextCtrlBase::DoUpdateWindowUI(wxUpdateUIEvent& event)
1159 {
1160 // call inherited, but skip the wxControl's version, and call directly the
1161 // wxWindow's one instead, because the only reason why we are overriding this
1162 // function is that we want to use SetValue() instead of wxControl::SetLabel()
1163 wxWindowBase::DoUpdateWindowUI(event);
1164
1165 // update text
1166 if ( event.GetSetText() )
1167 {
1168 if ( event.GetText() != GetValue() )
1169 SetValue(event.GetText());
1170 }
1171 }
1172
1173 // ----------------------------------------------------------------------------
1174 // hit testing
1175 // ----------------------------------------------------------------------------
1176
1177 wxTextCtrlHitTestResult
1178 wxTextAreaBase::HitTest(const wxPoint& pt, wxTextCoord *x, wxTextCoord *y) const
1179 {
1180 // implement in terms of the other overload as the native ports typically
1181 // can get the position and not (x, y) pair directly (although wxUniv
1182 // directly gets x and y -- and so overrides this method as well)
1183 long pos;
1184 wxTextCtrlHitTestResult rc = HitTest(pt, &pos);
1185
1186 if ( rc != wxTE_HT_UNKNOWN )
1187 {
1188 PositionToXY(pos, x, y);
1189 }
1190
1191 return rc;
1192 }
1193
1194 wxTextCtrlHitTestResult
1195 wxTextAreaBase::HitTest(const wxPoint& WXUNUSED(pt), long * WXUNUSED(pos)) const
1196 {
1197 // not implemented
1198 return wxTE_HT_UNKNOWN;
1199 }
1200
1201 wxPoint wxTextAreaBase::PositionToCoords(long pos) const
1202 {
1203 wxCHECK_MSG( IsValidPosition(pos), wxDefaultPosition,
1204 wxS("Position argument out of range.") );
1205
1206 return DoPositionToCoords(pos);
1207 }
1208
1209 wxPoint wxTextAreaBase::DoPositionToCoords(long WXUNUSED(pos)) const
1210 {
1211 return wxDefaultPosition;
1212 }
1213
1214 #else // !wxUSE_TEXTCTRL
1215
1216 // define this one even if !wxUSE_TEXTCTRL because it is also used by other
1217 // controls (wxComboBox and wxSpinCtrl)
1218
1219 wxDEFINE_EVENT( wxEVT_TEXT, wxCommandEvent );
1220
1221 #endif // wxUSE_TEXTCTRL/!wxUSE_TEXTCTRL