1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/common/textcmn.cpp 
   3 // Purpose:     implementation of platform-independent functions of wxTextCtrl 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) wxWidgets team 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // for compilers that support precompilation, includes "wx.h". 
  17 #include "wx/wxprec.h" 
  29 #include "wx/textctrl.h" 
  38 // ---------------------------------------------------------------------------- 
  40 // ---------------------------------------------------------------------------- 
  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)) 
  46 // ============================================================================ 
  48 // ============================================================================ 
  50 IMPLEMENT_DYNAMIC_CLASS(wxTextUrlEvent
, wxCommandEvent
) 
  52 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_UPDATED
) 
  53 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_ENTER
) 
  54 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_URL
) 
  55 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_MAXLEN
) 
  57 // ---------------------------------------------------------------------------- 
  58 // style functions - not implemented here 
  59 // ---------------------------------------------------------------------------- 
  61 wxTextAttr::wxTextAttr(const wxColour
& colText
, 
  62                const wxColour
& colBack
, 
  64                wxTextAttrAlignment alignment
) 
  65     : m_colText(colText
), m_colBack(colBack
), m_font(font
), m_textAlignment(alignment
) 
  71     if (m_colText
.Ok()) m_flags 
|= wxTEXT_ATTR_TEXT_COLOUR
; 
  72     if (m_colBack
.Ok()) m_flags 
|= wxTEXT_ATTR_BACKGROUND_COLOUR
; 
  73     if (m_font
.Ok()) m_flags 
|= wxTEXT_ATTR_FONT
; 
  74     if (alignment 
!= wxTEXT_ALIGNMENT_DEFAULT
) 
  75         m_flags 
|= wxTEXT_ATTR_ALIGNMENT
; 
  78 void wxTextAttr::Init() 
  80     m_textAlignment 
= wxTEXT_ALIGNMENT_DEFAULT
; 
  88 wxTextAttr 
wxTextAttr::Combine(const wxTextAttr
& attr
, 
  89                                const wxTextAttr
& attrDef
, 
  90                                const wxTextCtrlBase 
*text
) 
  92     wxFont font 
= attr
.GetFont(); 
  95         font 
= attrDef
.GetFont(); 
  97         if ( text 
&& !font
.Ok() ) 
  98             font 
= text
->GetFont(); 
 101     wxColour colFg 
= attr
.GetTextColour(); 
 104         colFg 
= attrDef
.GetTextColour(); 
 106         if ( text 
&& !colFg
.Ok() ) 
 107             colFg 
= text
->GetForegroundColour(); 
 110     wxColour colBg 
= attr
.GetBackgroundColour(); 
 113         colBg 
= attrDef
.GetBackgroundColour(); 
 115         if ( text 
&& !colBg
.Ok() ) 
 116             colBg 
= text
->GetBackgroundColour(); 
 119     wxTextAttr 
newAttr(colFg
, colBg
, font
); 
 121     if (attr
.HasAlignment()) 
 122         newAttr
.SetAlignment(attr
.GetAlignment()); 
 123     else if (attrDef
.HasAlignment()) 
 124         newAttr
.SetAlignment(attrDef
.GetAlignment()); 
 127         newAttr
.SetTabs(attr
.GetTabs()); 
 128     else if (attrDef
.HasTabs()) 
 129         newAttr
.SetTabs(attrDef
.GetTabs()); 
 131     if (attr
.HasLeftIndent()) 
 132         newAttr
.SetLeftIndent(attr
.GetLeftIndent(), attr
.GetLeftSubIndent()); 
 133     else if (attrDef
.HasLeftIndent()) 
 134         newAttr
.SetLeftIndent(attrDef
.GetLeftIndent(), attr
.GetLeftSubIndent()); 
 136     if (attr
.HasRightIndent()) 
 137         newAttr
.SetRightIndent(attr
.GetRightIndent()); 
 138     else if (attrDef
.HasRightIndent()) 
 139         newAttr
.SetRightIndent(attrDef
.GetRightIndent()); 
 144 void wxTextAttr::operator= (const wxTextAttr
& attr
) 
 146     m_font 
= attr
.m_font
; 
 147     m_colText 
= attr
.m_colText
; 
 148     m_colBack 
= attr
.m_colBack
; 
 149     m_textAlignment 
= attr
.m_textAlignment
; 
 150     m_leftIndent 
= attr
.m_leftIndent
; 
 151     m_leftSubIndent 
= attr
.m_leftSubIndent
; 
 152     m_rightIndent 
= attr
.m_rightIndent
; 
 153     m_tabs 
= attr
.m_tabs
; 
 154     m_flags 
= attr
.m_flags
; 
 158 // apply styling to text range 
 159 bool wxTextCtrlBase::SetStyle(long WXUNUSED(start
), long WXUNUSED(end
), 
 160                               const wxTextAttr
& WXUNUSED(style
)) 
 162     // to be implemented in derived TextCtrl classes 
 166 // get the styling at the given position 
 167 bool wxTextCtrlBase::GetStyle(long WXUNUSED(position
), wxTextAttr
& WXUNUSED(style
)) 
 169     // to be implemented in derived TextCtrl classes 
 173 // change default text attributes 
 174 bool wxTextCtrlBase::SetDefaultStyle(const wxTextAttr
& style
) 
 176     // keep the old attributes if the new style doesn't specify them unless the 
 177     // new style is empty - then reset m_defaultStyle (as there is no other way 
 179     if ( style
.IsDefault() ) 
 180         m_defaultStyle 
= style
; 
 182         m_defaultStyle 
= wxTextAttr::Combine(style
, m_defaultStyle
, this); 
 187 // get default text attributes 
 188 const wxTextAttr
& wxTextCtrlBase::GetDefaultStyle() const 
 190     return m_defaultStyle
; 
 193 // ---------------------------------------------------------------------------- 
 195 // ---------------------------------------------------------------------------- 
 197 bool wxTextCtrlBase::LoadFile(const wxString
& filename
) 
 200     wxFFile 
file(filename
); 
 201     if ( file
.IsOpened() ) 
 204         if ( file
.ReadAll(&text
) ) 
 210             m_filename 
= filename
; 
 216     wxLogError(_("File couldn't be loaded.")); 
 217 #endif // wxUSE_FFILE 
 222 bool wxTextCtrlBase::SaveFile(const wxString
& filename
) 
 224     wxString filenameToUse 
= filename
.empty() ? m_filename 
: filename
; 
 225     if ( filenameToUse
.empty() ) 
 227         // what kind of message to give? is it an error or a program bug? 
 228         wxLogDebug(wxT("Can't save textctrl to file without filename.")); 
 234     wxFFile 
file(filenameToUse
, _T("w")); 
 235     if ( file
.IsOpened() && file
.Write(GetValue()) ) 
 237         // it's not modified any longer 
 240         // if it worked, save for future calls 
 241         m_filename 
= filenameToUse
; 
 245 #endif // wxUSE_FFILE 
 247     wxLogError(_("The text couldn't be saved.")); 
 252 // ---------------------------------------------------------------------------- 
 253 // stream-like insertion operator 
 254 // ---------------------------------------------------------------------------- 
 256 wxTextCtrl
& wxTextCtrlBase::operator<<(const wxString
& s
) 
 259     return *TEXTCTRL(this); 
 262 wxTextCtrl
& wxTextCtrlBase::operator<<(float f
) 
 265     str
.Printf(wxT("%.2f"), f
); 
 267     return *TEXTCTRL(this); 
 270 wxTextCtrl
& wxTextCtrlBase::operator<<(double d
) 
 273     str
.Printf(wxT("%.2f"), d
); 
 275     return *TEXTCTRL(this); 
 278 wxTextCtrl
& wxTextCtrlBase::operator<<(int i
) 
 281     str
.Printf(wxT("%d"), i
); 
 283     return *TEXTCTRL(this); 
 286 wxTextCtrl
& wxTextCtrlBase::operator<<(long i
) 
 289     str
.Printf(wxT("%ld"), i
); 
 291     return *TEXTCTRL(this); 
 294 wxTextCtrl
& wxTextCtrlBase::operator<<(const wxChar c
) 
 296     return operator<<(wxString(c
)); 
 299 // ---------------------------------------------------------------------------- 
 300 // streambuf methods implementation 
 301 // ---------------------------------------------------------------------------- 
 303 #if wxHAS_TEXT_WINDOW_STREAM 
 305 int wxTextCtrlBase::overflow(int c
) 
 307     AppendText((wxChar
)c
); 
 309     // return something different from EOF 
 313 #endif // wxHAS_TEXT_WINDOW_STREAM 
 315 // ---------------------------------------------------------------------------- 
 317 // ---------------------------------------------------------------------------- 
 319 bool wxTextCtrlBase::CanCopy() const 
 321     // can copy if there's a selection 
 323     GetSelection(&from
, &to
); 
 327 bool wxTextCtrlBase::CanCut() const 
 329     // can cut if there's a selection and if we're not read only 
 330     return CanCopy() && IsEditable(); 
 333 bool wxTextCtrlBase::CanPaste() const 
 335     // can paste if we are not read only 
 339 // ---------------------------------------------------------------------------- 
 340 // emulating key presses 
 341 // ---------------------------------------------------------------------------- 
 344 // the generic version is unused in wxMSW 
 345 bool wxTextCtrlBase::EmulateKeyPress(const wxKeyEvent
& WXUNUSED(event
)) 
 350 bool wxTextCtrlBase::EmulateKeyPress(const wxKeyEvent
& event
) 
 353     int keycode 
= event
.GetKeyCode(); 
 366             ch 
= (wxChar
)(_T('0') + keycode 
- WXK_NUMPAD0
); 
 370         case WXK_NUMPAD_MULTIPLY
: 
 380         case WXK_NUMPAD_SUBTRACT
: 
 385         case WXK_NUMPAD_DECIMAL
: 
 390         case WXK_NUMPAD_DIVIDE
: 
 395         case WXK_NUMPAD_DELETE
: 
 396             // delete the character at cursor 
 398                 const long pos 
= GetInsertionPoint(); 
 399                 if ( pos 
< GetLastPosition() ) 
 400                     Remove(pos
, pos 
+ 1); 
 405             // delete the character before the cursor 
 407                 const long pos 
= GetInsertionPoint(); 
 409                     Remove(pos 
- 1, pos
); 
 415             if ( event
.GetUnicodeKey() ) 
 417                 ch 
= event
.GetUnicodeKey(); 
 421             if ( keycode 
< 256 && keycode 
>= 0 && wxIsprint(keycode
) ) 
 423                 // FIXME this is not going to work for non letters... 
 424                 if ( !event
.ShiftDown() ) 
 426                     keycode 
= wxTolower(keycode
); 
 429                 ch 
= (wxChar
)keycode
; 
 448 // ---------------------------------------------------------------------------- 
 449 // selection and ranges 
 450 // ---------------------------------------------------------------------------- 
 452 void wxTextCtrlBase::SelectAll() 
 454     SetSelection(0, GetLastPosition()); 
 457 wxString 
wxTextCtrlBase::GetStringSelection() const 
 460     GetSelection(&from
, &to
); 
 462     return GetRange(from
, to
); 
 465 wxString 
wxTextCtrlBase::GetRange(long from
, long to
) const 
 470         sel 
= GetValue().Mid(from
, to 
- from
); 
 476 // do the window-specific processing after processing the update event 
 477 void wxTextCtrlBase::DoUpdateWindowUI(wxUpdateUIEvent
& event
) 
 479     // call inherited, but skip the wxControl's version, and call directly the 
 480     // wxWindow's one instead, because the only reason why we are overriding this 
 481     // function is that we want to use SetValue() instead of wxControl::SetLabel() 
 482     wxWindowBase::DoUpdateWindowUI(event
); 
 485     if ( event
.GetSetText() ) 
 487         if ( event
.GetText() != GetValue() ) 
 488             SetValue(event
.GetText()); 
 492 // ---------------------------------------------------------------------------- 
 494 // ---------------------------------------------------------------------------- 
 496 wxTextCtrlHitTestResult
 
 497 wxTextCtrlBase::HitTest(const wxPoint
& pt
, wxTextCoord 
*x
, wxTextCoord 
*y
) const 
 499     // implement in terms of the other overload as the native ports typically 
 500     // can get the position and not (x, y) pair directly (although wxUniv 
 501     // directly gets x and y -- and so overrides this method as well) 
 503     wxTextCtrlHitTestResult rc 
= HitTest(pt
, &pos
); 
 505     if ( rc 
!= wxTE_HT_UNKNOWN 
) 
 507         PositionToXY(pos
, x
, y
); 
 513 wxTextCtrlHitTestResult
 
 514 wxTextCtrlBase::HitTest(const wxPoint
& WXUNUSED(pt
), 
 515                         long * WXUNUSED(pos
)) const 
 518     return wxTE_HT_UNKNOWN
; 
 521 #else // !wxUSE_TEXTCTRL 
 523 // define this one even if !wxUSE_TEXTCTRL because it is also used by other 
 524 // controls (wxComboBox and wxSpinCtrl) 
 526 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TEXT_UPDATED
) 
 528 #endif // wxUSE_TEXTCTRL/!wxUSE_TEXTCTRL