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