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