]> git.saurik.com Git - wxWidgets.git/blob - src/osx/textctrl_osx.cpp
hook the docview-specific customization of event handling logic at TryValidator(...
[wxWidgets.git] / src / osx / textctrl_osx.cpp
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"
50
51 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxTextCtrlBase)
52
53 BEGIN_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)
73 END_EVENT_TABLE()
74
75
76 void 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
86 wxTextCtrl::~wxTextCtrl()
87 {
88 #if wxUSE_MENUS
89 delete m_privateContextMenu;
90 #endif
91 }
92
93 bool 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
118
119 m_peer = wxWidgetImpl::CreateTextControl( this, GetParent(), GetId(), str, pos, size, style, GetExtraStyle() );
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
135 wxTextWidgetImpl* wxTextCtrl::GetTextPeer() const
136 {
137 return dynamic_cast<wxTextWidgetImpl*> (m_peer);
138 }
139
140 void wxTextCtrl::MacSuperChangedPosition()
141 {
142 wxWindow::MacSuperChangedPosition() ;
143 #if wxOSX_USE_CARBON
144 GetPeer()->SuperChangedPosition() ;
145 #endif
146 }
147
148 void wxTextCtrl::MacVisibilityChanged()
149 {
150 #if wxOSX_USE_CARBON
151 GetPeer()->VisibilityChanged( GetPeer()->IsVisible() );
152 #endif
153 }
154
155 void wxTextCtrl::MacCheckSpelling(bool check)
156 {
157 GetTextPeer()->CheckSpelling(check);
158 }
159
160 wxString wxTextCtrl::GetValue() const
161 {
162 return GetTextPeer()->GetStringValue() ;
163 }
164
165 void wxTextCtrl::GetSelection(long* from, long* to) const
166 {
167 GetTextPeer()->GetSelection( from , to ) ;
168 }
169
170 void wxTextCtrl::DoSetValue(const wxString& str, int flags)
171 {
172 // optimize redraws
173 if ( GetValue() == str )
174 return;
175
176 GetTextPeer()->SetStringValue( str ) ;
177
178 if ( (flags & SetValue_SendEvent) && m_triggerOnSetValue )
179 {
180 SendTextUpdatedEvent();
181 }
182 }
183
184 void wxTextCtrl::SetMaxLength(unsigned long len)
185 {
186 m_maxLength = len ;
187 }
188
189 bool wxTextCtrl::SetFont( const wxFont& font )
190 {
191 if ( !wxTextCtrlBase::SetFont( font ) )
192 return false ;
193
194 GetPeer()->SetFont( font , GetForegroundColour() , GetWindowStyle(), false /* dont ignore black */ ) ;
195
196 return true ;
197 }
198
199 bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
200 {
201 GetTextPeer()->SetStyle( start , end , style ) ;
202
203 return true ;
204 }
205
206 bool 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
216 void wxTextCtrl::Copy()
217 {
218 if (CanCopy())
219 GetTextPeer()->Copy() ;
220 }
221
222 void wxTextCtrl::Cut()
223 {
224 if (CanCut())
225 {
226 GetTextPeer()->Cut() ;
227
228 wxCommandEvent event( wxEVT_COMMAND_TEXT_UPDATED, m_windowId );
229 event.SetEventObject( this );
230 HandleWindowEvent( event );
231 }
232 }
233
234 void wxTextCtrl::Paste()
235 {
236 if (CanPaste())
237 {
238 GetTextPeer()->Paste() ;
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
248 bool 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
257 bool 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
269 bool wxTextCtrl::CanPaste() const
270 {
271 if (!IsEditable())
272 return false;
273
274 return GetTextPeer()->CanPaste() ;
275 }
276
277 void wxTextCtrl::SetEditable(bool editable)
278 {
279 if ( editable != m_editable )
280 {
281 m_editable = editable ;
282 GetTextPeer()->SetEditable( editable ) ;
283 }
284 }
285
286 void wxTextCtrl::SetInsertionPoint(long pos)
287 {
288 SetSelection( pos , pos ) ;
289 }
290
291 void wxTextCtrl::SetInsertionPointEnd()
292 {
293 long pos = GetLastPosition();
294 SetInsertionPoint( pos );
295 }
296
297 long wxTextCtrl::GetInsertionPoint() const
298 {
299 long begin, end ;
300 GetSelection( &begin , &end ) ;
301
302 return begin ;
303 }
304
305 wxTextPos wxTextCtrl::GetLastPosition() const
306 {
307 return GetTextPeer()->GetLastPosition() ;
308 }
309
310 void wxTextCtrl::Replace(long from, long to, const wxString& str)
311 {
312 GetTextPeer()->Replace( from , to , str ) ;
313 }
314
315 void wxTextCtrl::Remove(long from, long to)
316 {
317 GetTextPeer()->Remove( from , to ) ;
318 }
319
320 void wxTextCtrl::SetSelection(long from, long to)
321 {
322 GetTextPeer()->SetSelection( from , to ) ;
323 }
324
325 void wxTextCtrl::WriteText(const wxString& str)
326 {
327 GetTextPeer()->WriteText( str ) ;
328 }
329
330 void wxTextCtrl::AppendText(const wxString& text)
331 {
332 SetInsertionPointEnd();
333 WriteText( text );
334 }
335
336 void wxTextCtrl::Clear()
337 {
338 GetTextPeer()->Clear() ;
339 }
340
341 bool wxTextCtrl::IsModified() const
342 {
343 return m_dirty;
344 }
345
346 bool wxTextCtrl::IsEditable() const
347 {
348 return IsEnabled() && m_editable ;
349 }
350
351 bool wxTextCtrl::AcceptsFocus() const
352 {
353 // we don't want focus if we can't be edited
354 return /*IsEditable() && */ wxControl::AcceptsFocus();
355 }
356
357 wxSize 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
399 void wxTextCtrl::Undo()
400 {
401 if (CanUndo())
402 GetTextPeer()->Undo() ;
403 }
404
405 void wxTextCtrl::Redo()
406 {
407 if (CanRedo())
408 GetTextPeer()->Redo() ;
409 }
410
411 bool wxTextCtrl::CanUndo() const
412 {
413 if ( !IsEditable() )
414 return false ;
415
416 return GetTextPeer()->CanUndo() ;
417 }
418
419 bool wxTextCtrl::CanRedo() const
420 {
421 if ( !IsEditable() )
422 return false ;
423
424 return GetTextPeer()->CanRedo() ;
425 }
426
427 void wxTextCtrl::MarkDirty()
428 {
429 m_dirty = true;
430 }
431
432 void wxTextCtrl::DiscardEdits()
433 {
434 m_dirty = false;
435 }
436
437 int wxTextCtrl::GetNumberOfLines() const
438 {
439 return GetTextPeer()->GetNumberOfLines() ;
440 }
441
442 long wxTextCtrl::XYToPosition(long x, long y) const
443 {
444 return GetTextPeer()->XYToPosition( x , y ) ;
445 }
446
447 bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
448 {
449 return GetTextPeer()->PositionToXY( pos , x , y ) ;
450 }
451
452 void wxTextCtrl::ShowPosition(long pos)
453 {
454 return GetTextPeer()->ShowPosition(pos) ;
455 }
456
457 int wxTextCtrl::GetLineLength(long lineNo) const
458 {
459 return GetTextPeer()->GetLineLength(lineNo) ;
460 }
461
462 wxString wxTextCtrl::GetLineText(long lineNo) const
463 {
464 return GetTextPeer()->GetLineText(lineNo) ;
465 }
466
467 void wxTextCtrl::Command(wxCommandEvent & event)
468 {
469 SetValue(event.GetString());
470 ProcessCommand(event);
471 }
472
473 void 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
480 void 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
624 void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
625 {
626 Cut();
627 }
628
629 void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event))
630 {
631 Copy();
632 }
633
634 void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event))
635 {
636 Paste();
637 }
638
639 void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event))
640 {
641 Undo();
642 }
643
644 void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event))
645 {
646 Redo();
647 }
648
649 void 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
658 void wxTextCtrl::OnSelectAll(wxCommandEvent& WXUNUSED(event))
659 {
660 SetSelection(-1, -1);
661 }
662
663 void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
664 {
665 event.Enable( CanCut() );
666 }
667
668 void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
669 {
670 event.Enable( CanCopy() );
671 }
672
673 void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
674 {
675 event.Enable( CanPaste() );
676 }
677
678 void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
679 {
680 event.Enable( CanUndo() );
681 }
682
683 void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
684 {
685 event.Enable( CanRedo() );
686 }
687
688 void 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
696 void 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
703 void wxTextCtrl::OnContextMenu(wxContextMenuEvent& event)
704 {
705 if ( GetTextPeer()->HasOwnContextMenu() )
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
731 bool wxTextCtrl::MacSetupCursor( const wxPoint& pt )
732 {
733 if ( !GetTextPeer()->SetupCursor( pt ) )
734 return wxWindow::MacSetupCursor( pt ) ;
735 else
736 return true ;
737 }
738
739 // ----------------------------------------------------------------------------
740 // implementation base class
741 // ----------------------------------------------------------------------------
742
743 void wxTextWidgetImpl::SetStyle(long WXUNUSED(start),
744 long WXUNUSED(end),
745 const wxTextAttr& WXUNUSED(style))
746 {
747 }
748
749 void wxTextWidgetImpl::Copy()
750 {
751 }
752
753 void wxTextWidgetImpl::Cut()
754 {
755 }
756
757 void wxTextWidgetImpl::Paste()
758 {
759 }
760
761 bool wxTextWidgetImpl::CanPaste() const
762 {
763 return false ;
764 }
765
766 void wxTextWidgetImpl::SetEditable(bool WXUNUSED(editable))
767 {
768 }
769
770 long wxTextWidgetImpl::GetLastPosition() const
771 {
772 return GetStringValue().length() ;
773 }
774
775 void wxTextWidgetImpl::Replace( long from , long to , const wxString &val )
776 {
777 SetSelection( from , to ) ;
778 WriteText( val ) ;
779 }
780
781 void wxTextWidgetImpl::Remove( long from , long to )
782 {
783 SetSelection( from , to ) ;
784 WriteText( wxEmptyString) ;
785 }
786
787 void wxTextWidgetImpl::Clear()
788 {
789 SetStringValue( wxEmptyString ) ;
790 }
791
792 bool wxTextWidgetImpl::CanUndo() const
793 {
794 return false ;
795 }
796
797 void wxTextWidgetImpl::Undo()
798 {
799 }
800
801 bool wxTextWidgetImpl::CanRedo() const
802 {
803 return false ;
804 }
805
806 void wxTextWidgetImpl::Redo()
807 {
808 }
809
810 long wxTextWidgetImpl::XYToPosition(long WXUNUSED(x), long WXUNUSED(y)) const
811 {
812 return 0 ;
813 }
814
815 bool wxTextWidgetImpl::PositionToXY(long WXUNUSED(pos),
816 long *WXUNUSED(x),
817 long *WXUNUSED(y)) const
818 {
819 return false ;
820 }
821
822 void wxTextWidgetImpl::ShowPosition( long WXUNUSED(pos) )
823 {
824 }
825
826 int wxTextWidgetImpl::GetNumberOfLines() const
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
841 wxString wxTextWidgetImpl::GetLineText(long lineNo) const
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
873 int wxTextWidgetImpl::GetLineLength(long lineNo) const
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
903 #endif // wxUSE_TEXTCTRL