]> git.saurik.com Git - wxWidgets.git/blame - src/osx/textctrl_osx.cpp
hook the docview-specific customization of event handling logic at TryValidator(...
[wxWidgets.git] / src / osx / textctrl_osx.cpp
CommitLineData
524c47aa
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/osx/textctrl_osx.cpp
3// Purpose: wxTextCtrl
4// Author: Stefan Csomor
5// Modified by: Ryan Norton (MLTE GetLineLength and GetLineText)
6// Created: 1998-01-01
7// RCS-ID: $Id: textctrl.cpp 54820 2008-07-29 20:04:11Z SC $
8// Copyright: (c) Stefan Csomor
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#include "wx/wxprec.h"
13
14#if wxUSE_TEXTCTRL
15
16#include "wx/textctrl.h"
17
18#ifndef WX_PRECOMP
19 #include "wx/intl.h"
20 #include "wx/app.h"
21 #include "wx/utils.h"
22 #include "wx/dc.h"
23 #include "wx/button.h"
24 #include "wx/menu.h"
25 #include "wx/settings.h"
26 #include "wx/msgdlg.h"
27 #include "wx/toplevel.h"
28#endif
29
30#ifdef __DARWIN__
31 #include <sys/types.h>
32 #include <sys/stat.h>
33#else
34 #include <stat.h>
35#endif
36
37#if wxUSE_STD_IOSTREAM
38 #if wxUSE_IOSTREAMH
39 #include <fstream.h>
40 #else
41 #include <fstream>
42 #endif
43#endif
44
45#include "wx/filefn.h"
46#include "wx/sysopt.h"
47#include "wx/thread.h"
48
49#include "wx/osx/private.h"
524c47aa
SC
50
51IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxTextCtrlBase)
52
53BEGIN_EVENT_TABLE(wxTextCtrl, wxTextCtrlBase)
54 EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
55 EVT_CHAR(wxTextCtrl::OnChar)
56 EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
57 EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
58 EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
59 EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
60 EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
61 EVT_MENU(wxID_CLEAR, wxTextCtrl::OnDelete)
62 EVT_MENU(wxID_SELECTALL, wxTextCtrl::OnSelectAll)
63
64 EVT_CONTEXT_MENU(wxTextCtrl::OnContextMenu)
65
66 EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
67 EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
68 EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
69 EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
70 EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
71 EVT_UPDATE_UI(wxID_CLEAR, wxTextCtrl::OnUpdateDelete)
72 EVT_UPDATE_UI(wxID_SELECTALL, wxTextCtrl::OnUpdateSelectAll)
73END_EVENT_TABLE()
74
75
76void wxTextCtrl::Init()
77{
78 m_editable = true ;
79 m_dirty = false;
80
81 m_maxLength = 0;
82 m_privateContextMenu = NULL;
83 m_triggerOnSetValue = true ;
84}
85
86wxTextCtrl::~wxTextCtrl()
87{
88#if wxUSE_MENUS
89 delete m_privateContextMenu;
90#endif
91}
92
93bool wxTextCtrl::Create( wxWindow *parent,
94 wxWindowID id,
95 const wxString& str,
96 const wxPoint& pos,
97 const wxSize& size,
98 long style,
99 const wxValidator& validator,
100 const wxString& name )
101{
102 m_macIsUserPane = false ;
103 m_editable = true ;
104
105 if ( ! (style & wxNO_BORDER) )
106 style = (style & ~wxBORDER_MASK) | wxSUNKEN_BORDER ;
107
108 if ( !wxTextCtrlBase::Create( parent, id, pos, size, style & ~(wxHSCROLL | wxVSCROLL), validator, name ) )
109 return false;
110
111 if ( m_windowStyle & wxTE_MULTILINE )
112 {
113 // always turn on this style for multi-line controls
114 m_windowStyle |= wxTE_PROCESS_ENTER;
115 style |= wxTE_PROCESS_ENTER ;
116 }
117
524c47aa 118
1e181c7a 119 m_peer = wxWidgetImpl::CreateTextControl( this, GetParent(), GetId(), str, pos, size, style, GetExtraStyle() );
524c47aa
SC
120
121 MacPostControlCreate(pos, size) ;
122
123 // only now the embedding is correct and we can do a positioning update
124
125 MacSuperChangedPosition() ;
126
127 if ( m_windowStyle & wxTE_READONLY)
128 SetEditable( false ) ;
129
130 SetCursor( wxCursor( wxCURSOR_IBEAM ) ) ;
131
132 return true;
133}
134
1e181c7a 135wxTextWidgetImpl* wxTextCtrl::GetTextPeer() const
524c47aa 136{
1e181c7a 137 return dynamic_cast<wxTextWidgetImpl*> (m_peer);
524c47aa
SC
138}
139
140void wxTextCtrl::MacSuperChangedPosition()
141{
142 wxWindow::MacSuperChangedPosition() ;
143#if wxOSX_USE_CARBON
144 GetPeer()->SuperChangedPosition() ;
145#endif
146}
147
148void wxTextCtrl::MacVisibilityChanged()
149{
150#if wxOSX_USE_CARBON
151 GetPeer()->VisibilityChanged( GetPeer()->IsVisible() );
152#endif
153}
154
155void wxTextCtrl::MacCheckSpelling(bool check)
156{
1e181c7a 157 GetTextPeer()->CheckSpelling(check);
524c47aa
SC
158}
159
160wxString wxTextCtrl::GetValue() const
161{
1e181c7a 162 return GetTextPeer()->GetStringValue() ;
524c47aa
SC
163}
164
165void wxTextCtrl::GetSelection(long* from, long* to) const
166{
1e181c7a 167 GetTextPeer()->GetSelection( from , to ) ;
524c47aa
SC
168}
169
170void wxTextCtrl::DoSetValue(const wxString& str, int flags)
171{
172 // optimize redraws
173 if ( GetValue() == str )
174 return;
175
1e181c7a 176 GetTextPeer()->SetStringValue( str ) ;
524c47aa
SC
177
178 if ( (flags & SetValue_SendEvent) && m_triggerOnSetValue )
179 {
180 SendTextUpdatedEvent();
181 }
182}
183
184void wxTextCtrl::SetMaxLength(unsigned long len)
185{
186 m_maxLength = len ;
187}
188
189bool wxTextCtrl::SetFont( const wxFont& font )
190{
191 if ( !wxTextCtrlBase::SetFont( font ) )
192 return false ;
193
1e181c7a 194 GetPeer()->SetFont( font , GetForegroundColour() , GetWindowStyle(), false /* dont ignore black */ ) ;
524c47aa
SC
195
196 return true ;
197}
198
199bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
200{
1e181c7a 201 GetTextPeer()->SetStyle( start , end , style ) ;
524c47aa
SC
202
203 return true ;
204}
205
206bool wxTextCtrl::SetDefaultStyle(const wxTextAttr& style)
207{
208 wxTextCtrlBase::SetDefaultStyle( style ) ;
209 SetStyle( -1 /*current selection*/ , -1 /*current selection*/ , GetDefaultStyle() ) ;
210
211 return true ;
212}
213
214// Clipboard operations
215
216void wxTextCtrl::Copy()
217{
218 if (CanCopy())
1e181c7a 219 GetTextPeer()->Copy() ;
524c47aa
SC
220}
221
222void wxTextCtrl::Cut()
223{
224 if (CanCut())
225 {
1e181c7a 226 GetTextPeer()->Cut() ;
524c47aa
SC
227
228 wxCommandEvent event( wxEVT_COMMAND_TEXT_UPDATED, m_windowId );
229 event.SetEventObject( this );
230 HandleWindowEvent( event );
231 }
232}
233
234void wxTextCtrl::Paste()
235{
236 if (CanPaste())
237 {
1e181c7a 238 GetTextPeer()->Paste() ;
524c47aa
SC
239
240 // TODO: eventually we should add setting the default style again
241
242 wxCommandEvent event( wxEVT_COMMAND_TEXT_UPDATED, m_windowId );
243 event.SetEventObject( this );
244 HandleWindowEvent( event );
245 }
246}
247
248bool wxTextCtrl::CanCopy() const
249{
250 // Can copy if there's a selection
251 long from, to;
252 GetSelection( &from, &to );
253
254 return (from != to);
255}
256
257bool wxTextCtrl::CanCut() const
258{
259 if ( !IsEditable() )
260 return false;
261
262 // Can cut if there's a selection
263 long from, to;
264 GetSelection( &from, &to );
265
266 return (from != to);
267}
268
269bool wxTextCtrl::CanPaste() const
270{
271 if (!IsEditable())
272 return false;
273
1e181c7a 274 return GetTextPeer()->CanPaste() ;
524c47aa
SC
275}
276
277void wxTextCtrl::SetEditable(bool editable)
278{
279 if ( editable != m_editable )
280 {
281 m_editable = editable ;
1e181c7a 282 GetTextPeer()->SetEditable( editable ) ;
524c47aa
SC
283 }
284}
285
286void wxTextCtrl::SetInsertionPoint(long pos)
287{
288 SetSelection( pos , pos ) ;
289}
290
291void wxTextCtrl::SetInsertionPointEnd()
292{
0b6a49c2 293 long pos = GetLastPosition();
524c47aa
SC
294 SetInsertionPoint( pos );
295}
296
297long wxTextCtrl::GetInsertionPoint() const
298{
299 long begin, end ;
300 GetSelection( &begin , &end ) ;
301
302 return begin ;
303}
304
305wxTextPos wxTextCtrl::GetLastPosition() const
306{
1e181c7a 307 return GetTextPeer()->GetLastPosition() ;
524c47aa
SC
308}
309
310void wxTextCtrl::Replace(long from, long to, const wxString& str)
311{
1e181c7a 312 GetTextPeer()->Replace( from , to , str ) ;
524c47aa
SC
313}
314
315void wxTextCtrl::Remove(long from, long to)
316{
1e181c7a 317 GetTextPeer()->Remove( from , to ) ;
524c47aa
SC
318}
319
320void wxTextCtrl::SetSelection(long from, long to)
321{
1e181c7a 322 GetTextPeer()->SetSelection( from , to ) ;
524c47aa
SC
323}
324
325void wxTextCtrl::WriteText(const wxString& str)
326{
1e181c7a 327 GetTextPeer()->WriteText( str ) ;
524c47aa
SC
328}
329
330void wxTextCtrl::AppendText(const wxString& text)
331{
332 SetInsertionPointEnd();
333 WriteText( text );
334}
335
336void wxTextCtrl::Clear()
337{
1e181c7a 338 GetTextPeer()->Clear() ;
524c47aa
SC
339}
340
341bool wxTextCtrl::IsModified() const
342{
343 return m_dirty;
344}
345
346bool wxTextCtrl::IsEditable() const
347{
348 return IsEnabled() && m_editable ;
349}
350
351bool wxTextCtrl::AcceptsFocus() const
352{
353 // we don't want focus if we can't be edited
354 return /*IsEditable() && */ wxControl::AcceptsFocus();
355}
356
357wxSize wxTextCtrl::DoGetBestSize() const
358{
359 int wText, hText;
360
361 // these are the numbers from the HIG:
362 // we reduce them by the borders first
363 wText = 100 ;
364
365 switch ( m_windowVariant )
366 {
367 case wxWINDOW_VARIANT_NORMAL :
368 hText = 22 - 6 ;
369 break ;
370
371 case wxWINDOW_VARIANT_SMALL :
372 hText = 19 - 6 ;
373 break ;
374
375 case wxWINDOW_VARIANT_MINI :
376 hText = 15 - 6 ;
377 break ;
378
379 default :
380 hText = 22 - 6;
381 break ;
382 }
383
384 // as the above numbers have some free space around the text
385 // we get 5 lines like this anyway
386 if ( m_windowStyle & wxTE_MULTILINE )
387 hText *= 5 ;
388
389 if ( !HasFlag(wxNO_BORDER) )
390 hText += 6 ;
391
392 return wxSize(wText, hText);
393}
394
395// ----------------------------------------------------------------------------
396// Undo/redo
397// ----------------------------------------------------------------------------
398
399void wxTextCtrl::Undo()
400{
401 if (CanUndo())
1e181c7a 402 GetTextPeer()->Undo() ;
524c47aa
SC
403}
404
405void wxTextCtrl::Redo()
406{
407 if (CanRedo())
1e181c7a 408 GetTextPeer()->Redo() ;
524c47aa
SC
409}
410
411bool wxTextCtrl::CanUndo() const
412{
413 if ( !IsEditable() )
414 return false ;
415
1e181c7a 416 return GetTextPeer()->CanUndo() ;
524c47aa
SC
417}
418
419bool wxTextCtrl::CanRedo() const
420{
421 if ( !IsEditable() )
422 return false ;
423
1e181c7a 424 return GetTextPeer()->CanRedo() ;
524c47aa
SC
425}
426
427void wxTextCtrl::MarkDirty()
428{
429 m_dirty = true;
430}
431
432void wxTextCtrl::DiscardEdits()
433{
434 m_dirty = false;
435}
436
437int wxTextCtrl::GetNumberOfLines() const
438{
1e181c7a 439 return GetTextPeer()->GetNumberOfLines() ;
524c47aa
SC
440}
441
442long wxTextCtrl::XYToPosition(long x, long y) const
443{
1e181c7a 444 return GetTextPeer()->XYToPosition( x , y ) ;
524c47aa
SC
445}
446
447bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
448{
1e181c7a 449 return GetTextPeer()->PositionToXY( pos , x , y ) ;
524c47aa
SC
450}
451
452void wxTextCtrl::ShowPosition(long pos)
453{
1e181c7a 454 return GetTextPeer()->ShowPosition(pos) ;
524c47aa
SC
455}
456
457int wxTextCtrl::GetLineLength(long lineNo) const
458{
1e181c7a 459 return GetTextPeer()->GetLineLength(lineNo) ;
524c47aa
SC
460}
461
462wxString wxTextCtrl::GetLineText(long lineNo) const
463{
1e181c7a 464 return GetTextPeer()->GetLineText(lineNo) ;
524c47aa
SC
465}
466
467void wxTextCtrl::Command(wxCommandEvent & event)
468{
469 SetValue(event.GetString());
470 ProcessCommand(event);
471}
472
473void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
474{
475 // By default, load the first file into the text window.
476 if (event.GetNumberOfFiles() > 0)
477 LoadFile( event.GetFiles()[0] );
478}
479
480void wxTextCtrl::OnChar(wxKeyEvent& event)
481{
482 int key = event.GetKeyCode() ;
483 bool eat_key = false ;
484 long from, to;
485
486 if ( key == 'a' && event.MetaDown() )
487 {
488 SelectAll() ;
489
490 return ;
491 }
492
493 if ( key == 'c' && event.MetaDown() )
494 {
495 if ( CanCopy() )
496 Copy() ;
497
498 return ;
499 }
500
501 if ( !IsEditable() && key != WXK_LEFT && key != WXK_RIGHT && key != WXK_DOWN && key != WXK_UP && key != WXK_TAB &&
502 !( key == WXK_RETURN && ( (m_windowStyle & wxTE_PROCESS_ENTER) || (m_windowStyle & wxTE_MULTILINE) ) )
503// && key != WXK_PAGEUP && key != WXK_PAGEDOWN && key != WXK_HOME && key != WXK_END
504 )
505 {
506 // eat it
507 return ;
508 }
509
510 // Check if we have reached the max # of chars (if it is set), but still
511 // allow navigation and deletion
512 GetSelection( &from, &to );
513 if ( !IsMultiLine() && m_maxLength && GetValue().length() >= m_maxLength &&
514 key != WXK_LEFT && key != WXK_RIGHT && key != WXK_TAB && key != WXK_UP && key != WXK_DOWN &&
515 key != WXK_BACK && key != WXK_DELETE && !( key == WXK_RETURN && (m_windowStyle & wxTE_PROCESS_ENTER) ) &&
516 from == to )
517 {
518 // eat it, we don't want to add more than allowed # of characters
519
520 // TODO: generate EVT_TEXT_MAXLEN()
521 return;
522 }
523
524 // assume that any key not processed yet is going to modify the control
525 m_dirty = true;
526
527 if ( key == 'v' && event.MetaDown() )
528 {
529 if ( CanPaste() )
530 Paste() ;
531
532 return ;
533 }
534
535 if ( key == 'x' && event.MetaDown() )
536 {
537 if ( CanCut() )
538 Cut() ;
539
540 return ;
541 }
542
543 switch ( key )
544 {
545 case WXK_RETURN:
546 if (m_windowStyle & wxTE_PROCESS_ENTER)
547 {
548 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
549 event.SetEventObject( this );
550 event.SetString( GetValue() );
551 if ( HandleWindowEvent(event) )
552 return;
553 }
554
555 if ( !(m_windowStyle & wxTE_MULTILINE) )
556 {
557 wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow);
558 if ( tlw && tlw->GetDefaultItem() )
559 {
560 wxButton *def = wxDynamicCast(tlw->GetDefaultItem(), wxButton);
561 if ( def && def->IsEnabled() )
562 {
563 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
564 event.SetEventObject(def);
565 def->Command(event);
566
567 return ;
568 }
569 }
570
571 // this will make wxWidgets eat the ENTER key so that
572 // we actually prevent line wrapping in a single line text control
573 eat_key = true;
574 }
575 break;
576
577 case WXK_TAB:
578 if ( !(m_windowStyle & wxTE_PROCESS_TAB))
579 {
580 int flags = 0;
581 if (!event.ShiftDown())
582 flags |= wxNavigationKeyEvent::IsForward ;
583 if (event.ControlDown())
584 flags |= wxNavigationKeyEvent::WinChange ;
585 Navigate(flags);
586
587 return;
588 }
589 else
590 {
591 // This is necessary (don't know why);
592 // otherwise the tab will not be inserted.
593 WriteText(wxT("\t"));
594 eat_key = true;
595 }
596 break;
597
598 default:
599 break;
600 }
601
602 if (!eat_key)
603 {
604 // perform keystroke handling
605 event.Skip(true) ;
606 }
607
608 if ( ( key >= 0x20 && key < WXK_START ) ||
609 ( key >= WXK_NUMPAD0 && key <= WXK_DIVIDE ) ||
610 key == WXK_RETURN ||
611 key == WXK_DELETE ||
612 key == WXK_BACK)
613 {
614 wxCommandEvent event1(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
615 event1.SetEventObject( this );
616 wxPostEvent( GetEventHandler(), event1 );
617 }
618}
619
620// ----------------------------------------------------------------------------
621// standard handlers for standard edit menu events
622// ----------------------------------------------------------------------------
623
624void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
625{
626 Cut();
627}
628
629void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event))
630{
631 Copy();
632}
633
634void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event))
635{
636 Paste();
637}
638
639void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event))
640{
641 Undo();
642}
643
644void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event))
645{
646 Redo();
647}
648
649void wxTextCtrl::OnDelete(wxCommandEvent& WXUNUSED(event))
650{
651 long from, to;
652
653 GetSelection( &from, &to );
654 if (from != -1 && to != -1)
655 Remove( from, to );
656}
657
658void wxTextCtrl::OnSelectAll(wxCommandEvent& WXUNUSED(event))
659{
660 SetSelection(-1, -1);
661}
662
663void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
664{
665 event.Enable( CanCut() );
666}
667
668void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
669{
670 event.Enable( CanCopy() );
671}
672
673void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
674{
675 event.Enable( CanPaste() );
676}
677
678void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
679{
680 event.Enable( CanUndo() );
681}
682
683void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
684{
685 event.Enable( CanRedo() );
686}
687
688void wxTextCtrl::OnUpdateDelete(wxUpdateUIEvent& event)
689{
690 long from, to;
691
692 GetSelection( &from, &to );
693 event.Enable( from != -1 && to != -1 && from != to && IsEditable() ) ;
694}
695
696void wxTextCtrl::OnUpdateSelectAll(wxUpdateUIEvent& event)
697{
698 event.Enable(GetLastPosition() > 0);
699}
700
701// CS: Context Menus only work with MLTE implementations or non-multiline HIViews at the moment
702
703void wxTextCtrl::OnContextMenu(wxContextMenuEvent& event)
704{
1e181c7a 705 if ( GetTextPeer()->HasOwnContextMenu() )
524c47aa
SC
706 {
707 event.Skip() ;
708 return ;
709 }
710
711#if wxUSE_MENUS
712 if (m_privateContextMenu == NULL)
713 {
714 m_privateContextMenu = new wxMenu;
715 m_privateContextMenu->Append(wxID_UNDO, _("&Undo"));
716 m_privateContextMenu->Append(wxID_REDO, _("&Redo"));
717 m_privateContextMenu->AppendSeparator();
718 m_privateContextMenu->Append(wxID_CUT, _("Cu&t"));
719 m_privateContextMenu->Append(wxID_COPY, _("&Copy"));
720 m_privateContextMenu->Append(wxID_PASTE, _("&Paste"));
721 m_privateContextMenu->Append(wxID_CLEAR, _("&Delete"));
722 m_privateContextMenu->AppendSeparator();
723 m_privateContextMenu->Append(wxID_SELECTALL, _("Select &All"));
724 }
725
726 if (m_privateContextMenu != NULL)
727 PopupMenu(m_privateContextMenu);
728#endif
729}
730
731bool wxTextCtrl::MacSetupCursor( const wxPoint& pt )
732{
1e181c7a 733 if ( !GetTextPeer()->SetupCursor( pt ) )
524c47aa
SC
734 return wxWindow::MacSetupCursor( pt ) ;
735 else
736 return true ;
737}
738
739// ----------------------------------------------------------------------------
740// implementation base class
741// ----------------------------------------------------------------------------
742
1e181c7a 743void wxTextWidgetImpl::SetStyle(long WXUNUSED(start),
524c47aa
SC
744 long WXUNUSED(end),
745 const wxTextAttr& WXUNUSED(style))
746{
747}
748
1e181c7a 749void wxTextWidgetImpl::Copy()
524c47aa
SC
750{
751}
752
1e181c7a 753void wxTextWidgetImpl::Cut()
524c47aa
SC
754{
755}
756
1e181c7a 757void wxTextWidgetImpl::Paste()
524c47aa
SC
758{
759}
760
1e181c7a 761bool wxTextWidgetImpl::CanPaste() const
524c47aa
SC
762{
763 return false ;
764}
765
1e181c7a 766void wxTextWidgetImpl::SetEditable(bool WXUNUSED(editable))
524c47aa
SC
767{
768}
769
0b6a49c2 770long wxTextWidgetImpl::GetLastPosition() const
524c47aa
SC
771{
772 return GetStringValue().length() ;
773}
774
1e181c7a 775void wxTextWidgetImpl::Replace( long from , long to , const wxString &val )
524c47aa
SC
776{
777 SetSelection( from , to ) ;
778 WriteText( val ) ;
779}
780
1e181c7a 781void wxTextWidgetImpl::Remove( long from , long to )
524c47aa
SC
782{
783 SetSelection( from , to ) ;
784 WriteText( wxEmptyString) ;
785}
786
1e181c7a 787void wxTextWidgetImpl::Clear()
524c47aa
SC
788{
789 SetStringValue( wxEmptyString ) ;
790}
791
1e181c7a 792bool wxTextWidgetImpl::CanUndo() const
524c47aa
SC
793{
794 return false ;
795}
796
1e181c7a 797void wxTextWidgetImpl::Undo()
524c47aa
SC
798{
799}
800
1e181c7a 801bool wxTextWidgetImpl::CanRedo() const
524c47aa
SC
802{
803 return false ;
804}
805
1e181c7a 806void wxTextWidgetImpl::Redo()
524c47aa
SC
807{
808}
809
1e181c7a 810long wxTextWidgetImpl::XYToPosition(long WXUNUSED(x), long WXUNUSED(y)) const
524c47aa
SC
811{
812 return 0 ;
813}
814
1e181c7a 815bool wxTextWidgetImpl::PositionToXY(long WXUNUSED(pos),
524c47aa
SC
816 long *WXUNUSED(x),
817 long *WXUNUSED(y)) const
818{
819 return false ;
820}
821
1e181c7a 822void wxTextWidgetImpl::ShowPosition( long WXUNUSED(pos) )
524c47aa
SC
823{
824}
825
1e181c7a 826int wxTextWidgetImpl::GetNumberOfLines() const
524c47aa
SC
827{
828 ItemCount lines = 0 ;
829 wxString content = GetStringValue() ;
830 lines = 1;
831
832 for (size_t i = 0; i < content.length() ; i++)
833 {
834 if (content[i] == '\r')
835 lines++;
836 }
837
838 return lines ;
839}
840
1e181c7a 841wxString wxTextWidgetImpl::GetLineText(long lineNo) const
524c47aa
SC
842{
843 // TODO: change this if possible to reflect real lines
844 wxString content = GetStringValue() ;
845
846 // Find line first
847 int count = 0;
848 for (size_t i = 0; i < content.length() ; i++)
849 {
850 if (count == lineNo)
851 {
852 // Add chars in line then
853 wxString tmp;
854
855 for (size_t j = i; j < content.length(); j++)
856 {
857 if (content[j] == '\n')
858 return tmp;
859
860 tmp += content[j];
861 }
862
863 return tmp;
864 }
865
866 if (content[i] == '\n')
867 count++;
868 }
869
870 return wxEmptyString ;
871}
872
1e181c7a 873int wxTextWidgetImpl::GetLineLength(long lineNo) const
524c47aa
SC
874{
875 // TODO: change this if possible to reflect real lines
876 wxString content = GetStringValue() ;
877
878 // Find line first
879 int count = 0;
880 for (size_t i = 0; i < content.length() ; i++)
881 {
882 if (count == lineNo)
883 {
884 // Count chars in line then
885 count = 0;
886 for (size_t j = i; j < content.length(); j++)
887 {
888 count++;
889 if (content[j] == '\n')
890 return count;
891 }
892
893 return count;
894 }
895
896 if (content[i] == '\n')
897 count++;
898 }
899
900 return 0 ;
901}
902
524c47aa 903#endif // wxUSE_TEXTCTRL