1 /////////////////////////////////////////////////////////////////////////////
8 // Copyright: (c) AUTHOR
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "textctrl.h"
17 #include <sys/types.h>
26 #include "wx/button.h"
28 #include "wx/textctrl.h"
29 #include "wx/notebook.h"
30 #include "wx/tabctrl.h"
31 #include "wx/settings.h"
32 #include "wx/filefn.h"
35 #if defined(__BORLANDC__) && !defined(__WIN32__)
37 #elif !defined(__MWERKS__) && !defined(__GNUWIN32) && !defined(__WXMAC_X__)
41 #include "wx/mac/uma.h"
43 #if !USE_SHARED_LIBRARY
44 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
46 BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
47 EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
48 EVT_CHAR(wxTextCtrl::OnChar)
49 EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
50 EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
51 EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
52 EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
53 EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
55 EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
56 EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
57 EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
58 EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
59 EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
64 wxTextCtrl::wxTextCtrl()
68 const short kVerticalMargin = 2 ;
69 const short kHorizontalMargin = 2 ;
71 bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
74 const wxSize& size, long style,
75 const wxValidator& validator,
78 // base initialization
79 if ( !CreateBase(parent, id, pos, size, style, validator, name) )
82 wxSize mySize = size ;
83 if ( UMAHasAppearance() )
85 m_macHorizontalBorder = 5 ; // additional pixels around the real control
86 m_macVerticalBorder = 5 ;
90 m_macHorizontalBorder = 0 ; // additional pixels around the real control
91 m_macVerticalBorder = 0 ;
100 if ( UMAHasAppearance() )
105 mySize.y += 2 * m_macVerticalBorder ;
108 MacPreControlCreate( parent , id , "" , pos , mySize ,style, validator , name , &bounds , title ) ;
110 if ( m_windowStyle & wxTE_MULTILINE )
112 wxASSERT_MSG( !(m_windowStyle & wxTE_PROCESS_ENTER),
113 wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") );
115 m_windowStyle |= wxTE_PROCESS_ENTER;
119 m_macControl = UMANewControl( parent->GetMacRootWindow() , &bounds , "\p" , true , 0 , 0 , 1,
120 ( style & wxTE_PASSWORD ) ? kControlEditTextPasswordProc : kControlEditTextProc , (long) this ) ;
121 MacPostControlCreate() ;
129 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
130 (*teH)->lineHeight = -1 ;
133 if( wxApp::s_macDefaultEncodingIsPC )
134 value = wxMacMakeMacStringFromPC( st ) ;
137 UMASetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ;
142 wxString wxTextCtrl::GetValue() const
145 UMAGetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 32767 , wxBuffer , &actualsize) ;
146 wxBuffer[actualsize] = 0 ;
147 if( wxApp::s_macDefaultEncodingIsPC )
148 return wxMacMakePCStringFromMac( wxBuffer ) ;
150 return wxString(wxBuffer);
153 void wxTextCtrl::GetSelection(long* from, long* to) const
155 ControlEditTextSelectionRec selection ;
159 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
161 *from = (**teH).selStart;
162 *to = (**teH).selEnd;
165 void wxTextCtrl::SetValue(const wxString& st)
169 if( wxApp::s_macDefaultEncodingIsPC )
170 value = wxMacMakeMacStringFromPC( st ) ;
173 UMASetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ;
174 WindowRef window = GetMacRootWindow() ;
177 wxWindow* win = wxFindWinFromMacWindow( window ) ;
180 wxMacDrawingHelper help( win ) ;
181 // the mac control manager always assumes to have the origin at 0,0
184 bool hasTabBehind = false ;
185 wxWindow* parent = GetParent() ;
188 if( parent->MacGetWindowData() )
190 UMASetThemeWindowBackground( win->MacGetWindowData()->m_macWindow , kThemeBrushDialogBackgroundActive , false ) ;
194 if( parent->IsKindOf( CLASSINFO( wxNotebook ) ) || parent->IsKindOf( CLASSINFO( wxTabCtrl ) ))
196 if ( ((wxControl*)parent)->GetMacControl() )
197 SetUpControlBackground( ((wxControl*)parent)->GetMacControl() , -1 , true ) ;
201 parent = parent->GetParent() ;
204 UMADrawControl( m_macControl ) ;
205 UMASetThemeWindowBackground( win->MacGetWindowData()->m_macWindow , win->MacGetWindowData()->m_macWindowBackgroundTheme , false ) ;
210 // Clipboard operations
211 void wxTextCtrl::Copy()
218 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
222 err = ClearCurrentScrap( );
231 void wxTextCtrl::Cut()
238 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
242 err = ClearCurrentScrap( );
248 // MacInvalidateControl() ;
252 void wxTextCtrl::Paste()
259 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
262 WindowRef window = GetMacRootWindow() ;
265 wxWindow* win = wxFindWinFromMacWindow( window ) ;
268 wxMacDrawingHelper help( win ) ;
269 // the mac control manager always assumes to have the origin at 0,0
272 bool hasTabBehind = false ;
273 wxWindow* parent = GetParent() ;
276 if( parent->MacGetWindowData() )
278 UMASetThemeWindowBackground( win->MacGetWindowData()->m_macWindow , kThemeBrushDialogBackgroundActive , false ) ;
282 if( parent->IsKindOf( CLASSINFO( wxNotebook ) ) || parent->IsKindOf( CLASSINFO( wxTabCtrl ) ))
284 if ( ((wxControl*)parent)->GetMacControl() )
285 SetUpControlBackground( ((wxControl*)parent)->GetMacControl() , -1 , true ) ;
289 parent = parent->GetParent() ;
292 UMADrawControl( m_macControl ) ;
293 UMASetThemeWindowBackground( win->MacGetWindowData()->m_macWindow , win->MacGetWindowData()->m_macWindowBackgroundTheme , false ) ;
299 bool wxTextCtrl::CanCopy() const
301 // Can copy if there's a selection
303 GetSelection(& from, & to);
307 bool wxTextCtrl::CanCut() const
309 // Can cut if there's a selection
311 GetSelection(& from, & to);
315 bool wxTextCtrl::CanPaste() const
322 OSStatus err = noErr;
325 err = GetCurrentScrap( &scrapRef );
326 if ( err != noTypeErr && err != memFullErr )
328 ScrapFlavorFlags flavorFlags;
331 if (( err = GetScrapFlavorFlags( scrapRef, 'TEXT', &flavorFlags )) == noErr)
333 if (( err = GetScrapFlavorSize( scrapRef, 'TEXT', &byteCount )) == noErr)
342 if ( GetScrap( NULL , 'TEXT' , &offset ) > 0 )
350 void wxTextCtrl::SetEditable(bool editable)
353 UMAActivateControl( m_macControl ) ;
355 UMADeactivateControl( m_macControl ) ;
358 void wxTextCtrl::SetInsertionPoint(long pos)
360 SetSelection( pos , pos ) ;
363 void wxTextCtrl::SetInsertionPointEnd()
365 long pos = GetLastPosition();
366 SetInsertionPoint(pos);
369 long wxTextCtrl::GetInsertionPoint() const
371 ControlEditTextSelectionRec selection ;
375 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
376 // UMAGetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection , &size ) ;
377 return (**teH).selStart ;
380 long wxTextCtrl::GetLastPosition() const
382 ControlEditTextSelectionRec selection ;
386 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
388 // UMAGetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection , &size ) ;
389 return (**teH).teLength ;
392 void wxTextCtrl::Replace(long from, long to, const wxString& value)
397 ControlEditTextSelectionRec selection ;
399 selection.selStart = from ;
400 selection.selEnd = to ;
401 UMASetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
402 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
403 TESetSelect( from , to , teH ) ;
405 TEInsert( value , value.Length() , teH ) ;
409 void wxTextCtrl::Remove(long from, long to)
414 ControlEditTextSelectionRec selection ;
416 selection.selStart = from ;
417 selection.selEnd = to ;
418 UMASetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
419 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
424 void wxTextCtrl::SetSelection(long from, long to)
426 ControlEditTextSelectionRec selection ;
430 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
432 selection.selStart = from ;
433 selection.selEnd = to ;
435 UMASetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
436 TESetSelect( selection.selStart , selection.selEnd , teH ) ;
439 bool wxTextCtrl::LoadFile(const wxString& file)
441 if ( wxTextCtrlBase::LoadFile(file) )
449 void wxTextCtrl::WriteText(const wxString& text)
454 memcpy( wxBuffer, text , text.Length() ) ;
455 wxBuffer[text.Length() ] = 0 ;
456 // wxMacConvertNewlines( wxBuffer , wxBuffer ) ;
458 UMAGetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
460 TEInsert( wxBuffer , strlen( wxBuffer) , teH ) ;
464 void wxTextCtrl::AppendText(const wxString& text)
466 SetInsertionPointEnd();
470 void wxTextCtrl::Clear()
472 UMASetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 0 , (char*) ((const char*)NULL) ) ;
476 bool wxTextCtrl::IsModified() const
481 bool wxTextCtrl::IsEditable() const
486 bool wxTextCtrl::AcceptsFocus() const
488 // we don't want focus if we can't be edited
489 return IsEditable() && wxControl::AcceptsFocus();
492 wxSize wxTextCtrl::DoGetBestSize() const
497 if ( UMAHasAppearance() )
501 hText += 2 * m_macHorizontalBorder ;
504 wxGetCharSize(GetHWND(), &cx, &cy, &GetFont());
506 int wText = DEFAULT_ITEM_WIDTH;
508 int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
510 return wxSize(wText, hText);
512 if ( m_windowStyle & wxTE_MULTILINE )
514 hText *= wxMin(GetNumberOfLines(), 5);
516 //else: for single line control everything is ok
517 return wxSize(wText, hText);
520 // ----------------------------------------------------------------------------
522 // ----------------------------------------------------------------------------
524 void wxTextCtrl::Undo()
531 void wxTextCtrl::Redo()
538 bool wxTextCtrl::CanUndo() const
543 bool wxTextCtrl::CanRedo() const
548 // Makes 'unmodified'
549 void wxTextCtrl::DiscardEdits()
554 int wxTextCtrl::GetNumberOfLines() const
560 long wxTextCtrl::XYToPosition(long x, long y) const
566 bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
571 void wxTextCtrl::ShowPosition(long pos)
576 int wxTextCtrl::GetLineLength(long lineNo) const
578 return GetValue().Length();
581 wxString wxTextCtrl::GetLineText(long lineNo) const
590 void wxTextCtrl::Command(wxCommandEvent & event)
592 SetValue (event.GetString());
593 ProcessCommand (event);
596 void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
598 // By default, load the first file into the text window.
599 if (event.GetNumberOfFiles() > 0)
601 LoadFile(event.GetFiles()[0]);
605 void wxTextCtrl::OnChar(wxKeyEvent& event)
607 switch ( event.KeyCode() )
610 if (m_windowStyle & wxPROCESS_ENTER)
612 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
613 event.SetEventObject( this );
614 if ( GetEventHandler()->ProcessEvent(event) )
617 if ( !(m_windowStyle & wxTE_MULTILINE) )
619 wxWindow *parent = GetParent();
620 wxPanel *panel = wxDynamicCast(parent, wxPanel);
621 while ( parent != NULL && panel == NULL )
623 parent = parent->GetParent() ;
624 panel = wxDynamicCast(parent, wxPanel);
626 if ( panel && panel->GetDefaultItem() )
628 wxButton *def = panel->GetDefaultItem() ;
629 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
630 event.SetEventObject(def);
636 //else: multiline controls need Enter for themselves
641 // always produce navigation event - even if we process TAB
642 // ourselves the fact that we got here means that the user code
643 // decided to skip processing of this TAB - probably to let it
644 // do its default job.
646 wxNavigationKeyEvent eventNav;
647 eventNav.SetDirection(!event.ShiftDown());
648 eventNav.SetWindowChange(event.ControlDown());
649 eventNav.SetEventObject(this);
651 if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav) )
659 EventRecord *ev = wxTheApp->MacGetCurrentEvent() ;
662 keychar = short(ev->message & charCodeMask);
663 keycode = short(ev->message & keyCodeMask) >> 8 ;
664 UMAHandleControlKey( m_macControl , keycode , keychar , ev->modifiers ) ;
665 if ( keychar >= 0x20 || event.KeyCode() == WXK_RETURN || event.KeyCode() == WXK_DELETE || event.KeyCode() == WXK_BACK)
667 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
668 event.SetString( GetValue() ) ;
669 event.SetEventObject( this );
670 GetEventHandler()->ProcessEvent(event);
675 // ----------------------------------------------------------------------------
676 // standard handlers for standard edit menu events
677 // ----------------------------------------------------------------------------
679 void wxTextCtrl::OnCut(wxCommandEvent& event)
684 void wxTextCtrl::OnCopy(wxCommandEvent& event)
689 void wxTextCtrl::OnPaste(wxCommandEvent& event)
694 void wxTextCtrl::OnUndo(wxCommandEvent& event)
699 void wxTextCtrl::OnRedo(wxCommandEvent& event)
704 void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
706 event.Enable( CanCut() );
709 void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
711 event.Enable( CanCopy() );
714 void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
716 event.Enable( CanPaste() );
719 void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
721 event.Enable( CanUndo() );
724 void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
726 event.Enable( CanRedo() );