combobox and textctrl fixes
[wxWidgets.git] / src / mac / carbon / textctrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: textctrl.cpp
3 // Purpose: wxTextCtrl
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id$
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "textctrl.h"
14 #endif
15
16 #include "wx/defs.h"
17
18 #if wxUSE_TEXTCTRL
19
20
21 #ifdef __DARWIN__
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #else
25 #include <stat.h>
26 #endif
27
28 #include "wx/msgdlg.h"
29
30 #if wxUSE_STD_IOSTREAM
31 #if wxUSE_IOSTREAMH
32 #include <fstream.h>
33 #else
34 #include <fstream>
35 #endif
36 #endif
37
38 #include "wx/app.h"
39 #include "wx/dc.h"
40 #include "wx/button.h"
41 #include "wx/toplevel.h"
42 #include "wx/textctrl.h"
43 #include "wx/notebook.h"
44 #include "wx/tabctrl.h"
45 #include "wx/settings.h"
46 #include "wx/filefn.h"
47 #include "wx/utils.h"
48
49 #if defined(__BORLANDC__) && !defined(__WIN32__)
50 #include <alloc.h>
51 #elif !defined(__MWERKS__) && !defined(__GNUWIN32) && !defined(__DARWIN__)
52 #include <malloc.h>
53 #endif
54
55 #ifndef __DARWIN__
56 #include <Scrap.h>
57 #endif
58 #include <MacTextEditor.h>
59 #include <ATSUnicode.h>
60 #include <TextCommon.h>
61 #include <TextEncodingConverter.h>
62 #include "wx/mac/uma.h"
63
64 class wxMacFunctor
65 {
66 public :
67 wxMacFunctor(){}
68 virtual ~wxMacFunctor() {}
69 virtual void* operator()() = 0 ;
70 static void* CallBackProc(void *param)
71 {
72 wxMacFunctor* f = (wxMacFunctor*) param ;
73 void *result = (*f)() ;
74 return result ;
75 }
76 } ;
77
78 template<typename classtype,typename param1type>
79 class wxMacObjectFunctor1 : public wxMacFunctor
80 {
81 typedef void (classtype::*function)( param1type p1 ) ;
82 typedef void (classtype::*ref_function)( const param1type& p1 ) ;
83 public :
84 wxMacObjectFunctor1( classtype *obj , function f , param1type p1 ) :
85 wxMacFunctor( )
86 {
87 m_object = obj ;
88 m_function = f ;
89 m_param1 = p1 ;
90 }
91
92 wxMacObjectFunctor1( classtype *obj , ref_function f , param1type p1 ) :
93 wxMacFunctor( )
94 {
95 m_object = obj ;
96 m_refFunction = f ;
97 m_param1 = p1 ;
98 }
99
100 ~wxMacObjectFunctor1() {}
101
102 virtual void* operator()()
103 {
104 (m_object->*m_function)(m_param1) ;
105 return NULL ;
106 }
107 private :
108 classtype* m_object ;
109 param1type m_param1 ;
110 union
111 {
112 function m_function ;
113 ref_function m_refFunction ;
114 } ;
115 } ;
116
117 template<typename classtype, typename param1type>
118 void* wxMacMPRemoteCall( classtype *object , void (classtype::*function)( param1type p1 ) , param1type p1 )
119 {
120 wxMacObjectFunctor1<classtype,param1type> params(object,function,p1) ;
121 void *result =
122 MPRemoteCall( wxMacFunctor::CallBackProc , &params , kMPOwningProcessRemoteContext ) ;
123 return result ;
124 }
125
126 template<typename classtype, typename param1type>
127 void* wxMacMPRemoteCall( classtype *object , void (classtype::*function)( const param1type& p1 ) , param1type p1 )
128 {
129 wxMacObjectFunctor1<classtype,param1type> params(object,function,p1) ;
130 void *result =
131 MPRemoteCall( wxMacFunctor::CallBackProc , &params , kMPOwningProcessRemoteContext ) ;
132 return result ;
133 }
134
135 template<typename classtype, typename param1type>
136 void* wxMacMPRemoteGUICall( classtype *object , void (classtype::*function)( param1type p1 ) , param1type p1 )
137 {
138 wxMutexGuiLeave() ;
139 void *result = wxMacMPRemoteCall( object , function , p1 ) ;
140 wxMutexGuiEnter() ;
141 return result ;
142 }
143
144 template<typename classtype, typename param1type>
145 void* wxMacMPRemoteGUICall( classtype *object , void (classtype::*function)( const param1type& p1 ) , param1type p1 )
146 {
147 wxMutexGuiLeave() ;
148 void *result = wxMacMPRemoteCall( object , function , p1 ) ;
149 wxMutexGuiEnter() ;
150 return result ;
151 }
152 // common interface for all implementations
153 class wxMacTextControl : public wxMacControl
154 {
155 public :
156 wxMacTextControl() ;
157 ~wxMacTextControl() ;
158
159 virtual wxString GetStringValue() const = 0 ;
160 virtual void SetStringValue( const wxString &val ) = 0 ;
161 virtual void SetStyle(long start, long end, const wxTextAttr& style) ;
162 virtual void Copy() ;
163 virtual void Cut() ;
164 virtual void Paste() ;
165 virtual bool CanPaste() const ;
166 virtual void SetEditable(bool editable) ;
167 virtual long GetLastPosition() const ;
168 virtual void Replace( long from , long to , const wxString str ) ;
169 virtual void Remove( long from , long to ) = 0 ;
170 virtual void SetSelection( long from , long to ) = 0 ;
171 virtual void GetSelection( long* from, long* to) const = 0 ;
172 virtual void WriteText(const wxString& str) = 0 ;
173
174 virtual void Clear() ;
175 virtual bool CanUndo() const;
176 virtual void Undo() ;
177 virtual bool CanRedo() const;
178 virtual void Redo() ;
179 virtual int GetNumberOfLines() const ;
180 virtual long XYToPosition(long x, long y) const;
181 virtual bool PositionToXY(long pos, long *x, long *y) const ;
182 virtual void ShowPosition( long WXUNUSED(pos) ) ;
183 virtual int GetLineLength(long lineNo) const ;
184 virtual wxString GetLineText(long lineNo) const ;
185 } ;
186
187 // common parts for implementations based on MLTE
188
189 class wxMacMLTEControl : public wxMacTextControl
190 {
191 public :
192 virtual wxString GetStringValue() const ;
193 virtual void SetStringValue( const wxString &str) ;
194
195 static int ConvertAttribute( const wxTextAttr& style , TXNTypeAttributes attr[] ) ;
196 static TXNFrameOptions FrameOptionsFromWXStyle( long wxStyle ) ;
197 void AdjustCreationAttributes( const wxColour& background , bool visible ) ;
198
199 virtual void SetFont( const wxFont & font , const wxColour& foreground , long windowStyle ) ;
200 virtual void SetStyle(long start, long end, const wxTextAttr& style) ;
201 virtual void Copy() ;
202 virtual void Cut() ;
203 virtual void Paste() ;
204 virtual bool CanPaste() const ;
205 virtual void SetEditable(bool editable) ;
206 virtual long GetLastPosition() const ;
207 virtual void Replace( long from , long to , const wxString str ) ;
208 virtual void Remove( long from , long to ) ;
209 virtual void GetSelection( long* from, long* to) const ;
210 virtual void SetSelection( long from , long to ) ;
211
212 virtual void WriteText(const wxString& str) ;
213 virtual void Clear() ;
214
215 virtual bool CanUndo() const ;
216 virtual void Undo() ;
217 virtual bool CanRedo() const;
218 virtual void Redo() ;
219 virtual int GetNumberOfLines() const ;
220 virtual long XYToPosition(long x, long y) const ;
221 virtual bool PositionToXY(long pos, long *x, long *y) const ;
222 virtual void ShowPosition( long pos ) ;
223 virtual int GetLineLength(long lineNo) const ;
224 virtual wxString GetLineText(long lineNo) const ;
225
226 void SetTXNData( const wxString& st , TXNOffset start , TXNOffset end ) ;
227
228 protected :
229 TXNObject m_txn ;
230 } ;
231
232 #if TARGET_API_MAC_OSX
233
234 // implementation available under OSX
235
236 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
237
238 class wxMacMLTEHIViewControl : public wxMacMLTEControl
239 {
240 public :
241 wxMacMLTEHIViewControl( wxWindow *wxPeer,
242 const wxString& str,
243 const wxPoint& pos,
244 const wxSize& size, long style ) ;
245 virtual OSStatus SetFocus( ControlFocusPart focusPart ) ;
246 virtual bool HasFocus() const ;
247 virtual bool NeedsFocusRect() const ;
248 protected :
249 HIViewRef m_scrollView ;
250 HIViewRef m_textView ;
251 } ;
252
253 #endif
254
255 class wxMacUnicodeTextControl : public wxMacTextControl
256 {
257 public :
258 wxMacUnicodeTextControl( wxWindow *wxPeer,
259 const wxString& str,
260 const wxPoint& pos,
261 const wxSize& size, long style ) ;
262 ~wxMacUnicodeTextControl();
263 virtual void VisibilityChanged(bool shown);
264 virtual wxString GetStringValue() const ;
265 virtual void SetStringValue( const wxString &str) ;
266 virtual void Copy();
267 virtual void Cut();
268 virtual void Paste();
269 virtual bool CanPaste() const;
270 virtual void SetEditable(bool editable) ;
271 virtual void Remove( long from , long to ) ;
272 virtual void GetSelection( long* from, long* to) const ;
273 virtual void SetSelection( long from , long to ) ;
274 virtual void WriteText(const wxString& str) ;
275 protected :
276 // contains the tag for the content (is different for password and non-password controls)
277 OSType m_valueTag ;
278 } ;
279
280 #else
281
282 // implementation available under classic
283
284 class STPTextPaneVars ;
285
286 class wxMacMLTEClassicControl : public wxMacMLTEControl
287 {
288 public :
289 wxMacMLTEClassicControl( wxWindow *wxPeer,
290 const wxString& str,
291 const wxPoint& pos,
292 const wxSize& size, long style ) ;
293 ~wxMacMLTEClassicControl() ;
294 virtual void VisibilityChanged(bool shown) ;
295 protected :
296 OSStatus DoCreate();
297 public :
298 // hack to make public until we have migrated all procs
299 STPTextPaneVars* m_macTXNvars ;
300 } ;
301
302 #endif
303 // built-in TextCtrl
304
305
306 #define TE_UNLIMITED_LENGTH 0xFFFFFFFFUL
307
308 #if !USE_SHARED_LIBRARY
309 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
310
311 BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
312 EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
313 EVT_CHAR(wxTextCtrl::OnChar)
314 EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
315 EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
316 EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
317 EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
318 EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
319
320 EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
321 EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
322 EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
323 EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
324 EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
325 END_EVENT_TABLE()
326 #endif
327
328 // Text item
329 void wxTextCtrl::Init()
330 {
331 m_editable = true ;
332 m_dirty = false;
333
334 m_maxLength = TE_UNLIMITED_LENGTH ;
335 }
336
337 wxTextCtrl::~wxTextCtrl()
338 {
339 }
340
341
342 bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
343 const wxString& str,
344 const wxPoint& pos,
345 const wxSize& size, long style,
346 const wxValidator& validator,
347 const wxString& name)
348 {
349 m_macIsUserPane = FALSE ;
350 m_editable = true ;
351
352 if ( !HasFlag(wxNO_BORDER) )
353 style |= wxSUNKEN_BORDER ;
354
355 if ( !wxTextCtrlBase::Create(parent, id, pos, size, style & ~(wxHSCROLL|wxVSCROLL), validator, name) )
356 return FALSE;
357
358 wxSize mySize = size ;
359
360 Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
361
362 if ( m_windowStyle & wxTE_MULTILINE )
363 {
364 wxASSERT_MSG( !(m_windowStyle & wxTE_PROCESS_ENTER),
365 wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") );
366
367 m_windowStyle |= wxTE_PROCESS_ENTER;
368 style |= wxTE_PROCESS_ENTER ;
369 }
370 #if TARGET_API_MAC_OSX
371 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
372 if ( UMAGetSystemVersion() >= 0x1030 )
373 {
374 m_peer = new wxMacMLTEHIViewControl( this , str , pos , size , style ) ;
375 }
376 else
377 #endif
378 {
379 m_peer = new wxMacUnicodeTextControl( this , str , pos , size , style ) ;
380 }
381 #else
382 m_peer = new wxMacMLTEClassicControl( this , str , pos , size , style ) ;
383 #endif
384
385 MacPostControlCreate(pos,size) ;
386
387 if ( m_windowStyle & wxTE_READONLY)
388 {
389 SetEditable( false ) ;
390 }
391
392
393 return TRUE;
394 }
395
396 void wxTextCtrl::MacVisibilityChanged()
397 {
398 GetPeer()->VisibilityChanged( MacIsReallyShown() ) ;
399 }
400
401 void wxTextCtrl::MacEnabledStateChanged()
402 {
403 }
404
405 wxString wxTextCtrl::GetValue() const
406 {
407 return GetPeer()->GetStringValue() ;
408 }
409
410 void wxTextCtrl::GetSelection(long* from, long* to) const
411 {
412 GetPeer()->GetSelection( from , to ) ;
413 }
414
415 void wxTextCtrl::SetValue(const wxString& str)
416 {
417 // optimize redraws
418 if ( GetValue() == str )
419 return ;
420
421 GetPeer()->SetStringValue(str) ;
422 }
423
424 void wxTextCtrl::SetMaxLength(unsigned long len)
425 {
426 m_maxLength = len ;
427 }
428
429 bool wxTextCtrl::SetFont( const wxFont& font )
430 {
431 if ( !wxTextCtrlBase::SetFont( font ) )
432 return FALSE ;
433
434 GetPeer()->SetFont( font , GetForegroundColour() , GetWindowStyle() ) ;
435 return true ;
436 }
437
438 bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
439 {
440 GetPeer()->SetStyle( start , end , style ) ;
441 return true ;
442 }
443
444 bool wxTextCtrl::SetDefaultStyle(const wxTextAttr& style)
445 {
446 wxTextCtrlBase::SetDefaultStyle( style ) ;
447 SetStyle( kTXNUseCurrentSelection , kTXNUseCurrentSelection , GetDefaultStyle() ) ;
448 return TRUE ;
449 }
450
451 // Clipboard operations
452 void wxTextCtrl::Copy()
453 {
454 if (CanCopy())
455 {
456 GetPeer()->Copy() ;
457 }
458 }
459
460 void wxTextCtrl::Cut()
461 {
462 if (CanCut())
463 {
464 GetPeer()->Cut() ;
465
466 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
467 event.SetString( GetValue() ) ;
468 event.SetEventObject( this );
469 GetEventHandler()->ProcessEvent(event);
470 }
471 }
472
473 void wxTextCtrl::Paste()
474 {
475 if (CanPaste())
476 {
477 GetPeer()->Paste() ;
478 // eventually we should add setting the default style again
479
480 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
481 event.SetString( GetValue() ) ;
482 event.SetEventObject( this );
483 GetEventHandler()->ProcessEvent(event);
484 }
485 }
486
487 bool wxTextCtrl::CanCopy() const
488 {
489 // Can copy if there's a selection
490 long from, to;
491 GetSelection(& from, & to);
492 return (from != to);
493 }
494
495 bool wxTextCtrl::CanCut() const
496 {
497 if ( !IsEditable() )
498 {
499 return false ;
500 }
501 // Can cut if there's a selection
502 long from, to;
503 GetSelection(& from, & to);
504 return (from != to);
505 }
506
507 bool wxTextCtrl::CanPaste() const
508 {
509 if (!IsEditable())
510 return FALSE;
511
512 return GetPeer()->CanPaste() ;
513 }
514
515 void wxTextCtrl::SetEditable(bool editable)
516 {
517 if ( editable != m_editable )
518 {
519 m_editable = editable ;
520 GetPeer()->SetEditable( editable ) ;
521 }
522 }
523
524 void wxTextCtrl::SetInsertionPoint(long pos)
525 {
526 SetSelection( pos , pos ) ;
527 }
528
529 void wxTextCtrl::SetInsertionPointEnd()
530 {
531 long pos = GetLastPosition();
532 SetInsertionPoint(pos);
533 }
534
535 long wxTextCtrl::GetInsertionPoint() const
536 {
537 long begin,end ;
538 GetSelection( &begin , &end ) ;
539 return begin ;
540 }
541
542 long wxTextCtrl::GetLastPosition() const
543 {
544 return GetPeer()->GetLastPosition( ) ;
545 }
546
547 void wxTextCtrl::Replace(long from, long to, const wxString& str)
548 {
549 GetPeer()->Replace( from , to , str) ;
550 }
551
552 void wxTextCtrl::Remove(long from, long to)
553 {
554 GetPeer()->Remove( from , to ) ;
555 }
556
557 void wxTextCtrl::SetSelection(long from, long to)
558 {
559 GetPeer()->SetSelection( from , to ) ;
560 }
561
562 bool wxTextCtrl::LoadFile(const wxString& file)
563 {
564 if ( wxTextCtrlBase::LoadFile(file) )
565 {
566 return TRUE;
567 }
568
569 return FALSE;
570 }
571
572 void wxTextCtrl::WriteText(const wxString& str)
573 {
574 // TODO this MPRemoting will be moved into a remoting peer proxy for any command
575 if ( !wxIsMainThread() )
576 {
577 // unfortunately CW 8 is not able to correctly deduce the template types, so we have
578 // to instantiate explicitely
579 wxMacMPRemoteGUICall<wxTextCtrl,wxString>( this , &wxTextCtrl::WriteText , str ) ;
580 return ;
581 }
582 else
583 {
584 GetPeer()->WriteText( str ) ;
585 }
586 }
587
588 void wxTextCtrl::AppendText(const wxString& text)
589 {
590 SetInsertionPointEnd();
591 WriteText(text);
592 }
593
594 void wxTextCtrl::Clear()
595 {
596 GetPeer()->Clear() ;
597 }
598
599 bool wxTextCtrl::IsModified() const
600 {
601 return m_dirty;
602 }
603
604 bool wxTextCtrl::IsEditable() const
605 {
606 return IsEnabled() && m_editable ;
607 }
608
609 bool wxTextCtrl::AcceptsFocus() const
610 {
611 // we don't want focus if we can't be edited
612 return /*IsEditable() && */ wxControl::AcceptsFocus();
613 }
614
615 wxSize wxTextCtrl::DoGetBestSize() const
616 {
617 int wText = 100 ;
618
619 int hText;
620
621 switch( m_windowVariant )
622 {
623 case wxWINDOW_VARIANT_NORMAL :
624 hText = 22 ;
625 break ;
626 case wxWINDOW_VARIANT_SMALL :
627 hText = 19 ;
628 break ;
629 case wxWINDOW_VARIANT_MINI :
630 hText= 15 ;
631 break ;
632 default :
633 hText = 22 ;
634 break ;
635 }
636
637 if ( HasFlag(wxNO_BORDER) )
638 hText -= 6 ;
639
640 if ( m_windowStyle & wxTE_MULTILINE )
641 {
642 hText *= 5 ;
643 }
644
645 return wxSize(wText, hText);
646 }
647
648 // ----------------------------------------------------------------------------
649 // Undo/redo
650 // ----------------------------------------------------------------------------
651
652 void wxTextCtrl::Undo()
653 {
654 if (CanUndo())
655 {
656 GetPeer()->Undo() ;
657 }
658 }
659
660 void wxTextCtrl::Redo()
661 {
662 if (CanRedo())
663 {
664 GetPeer()->Redo() ;
665 }
666 }
667
668 bool wxTextCtrl::CanUndo() const
669 {
670 if ( !IsEditable() )
671 {
672 return false ;
673 }
674 return GetPeer()->CanUndo() ;
675 }
676
677 bool wxTextCtrl::CanRedo() const
678 {
679 if ( !IsEditable() )
680 {
681 return false ;
682 }
683 return GetPeer()->CanRedo() ;
684 }
685
686 void wxTextCtrl::MarkDirty()
687 {
688 m_dirty = true;
689 }
690
691 void wxTextCtrl::DiscardEdits()
692 {
693 m_dirty = false;
694 }
695
696 int wxTextCtrl::GetNumberOfLines() const
697 {
698 return GetPeer()->GetNumberOfLines() ;
699 }
700
701 long wxTextCtrl::XYToPosition(long x, long y) const
702 {
703 return GetPeer()->XYToPosition( x , y ) ;
704 }
705
706 bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
707 {
708 return GetPeer()->PositionToXY(pos , x , y ) ;
709 }
710
711 void wxTextCtrl::ShowPosition(long pos)
712 {
713 return GetPeer()->ShowPosition(pos) ;
714 }
715
716 int wxTextCtrl::GetLineLength(long lineNo) const
717 {
718 return GetPeer()->GetLineLength(lineNo) ;
719 }
720
721 wxString wxTextCtrl::GetLineText(long lineNo) const
722 {
723 return GetPeer()->GetLineText(lineNo) ;
724 }
725
726 /*
727 * Text item
728 */
729
730 void wxTextCtrl::Command(wxCommandEvent & event)
731 {
732 SetValue (event.GetString());
733 ProcessCommand (event);
734 }
735
736 void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
737 {
738 // By default, load the first file into the text window.
739 if (event.GetNumberOfFiles() > 0)
740 {
741 LoadFile(event.GetFiles()[0]);
742 }
743 }
744
745 void wxTextCtrl::OnChar(wxKeyEvent& event)
746 {
747 int key = event.GetKeyCode() ;
748 bool eat_key = false ;
749
750 if ( key == 'c' && event.MetaDown() )
751 {
752 if ( CanCopy() )
753 Copy() ;
754 return ;
755 }
756
757 if ( !IsEditable() && key != WXK_LEFT && key != WXK_RIGHT && key != WXK_DOWN && key != WXK_UP && key != WXK_TAB &&
758 !( key == WXK_RETURN && ( (m_windowStyle & wxPROCESS_ENTER) || (m_windowStyle & wxTE_MULTILINE) ) )
759 /* && key != WXK_PRIOR && key != WXK_NEXT && key != WXK_HOME && key != WXK_END */
760 )
761 {
762 // eat it
763 return ;
764 }
765
766 // assume that any key not processed yet is going to modify the control
767 m_dirty = true;
768
769 if ( key == 'v' && event.MetaDown() )
770 {
771 if ( CanPaste() )
772 Paste() ;
773 return ;
774 }
775 if ( key == 'x' && event.MetaDown() )
776 {
777 if ( CanCut() )
778 Cut() ;
779 return ;
780 }
781 switch ( key )
782 {
783 case WXK_RETURN:
784 if (m_windowStyle & wxPROCESS_ENTER)
785 {
786 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
787 event.SetEventObject( this );
788 event.SetString( GetValue() );
789 if ( GetEventHandler()->ProcessEvent(event) )
790 return;
791 }
792 if ( !(m_windowStyle & wxTE_MULTILINE) )
793 {
794 wxWindow *parent = GetParent();
795 while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL ) {
796 parent = parent->GetParent() ;
797 }
798 if ( parent && parent->GetDefaultItem() )
799 {
800 wxButton *def = wxDynamicCast(parent->GetDefaultItem(),
801 wxButton);
802 if ( def && def->IsEnabled() )
803 {
804 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
805 event.SetEventObject(def);
806 def->Command(event);
807 return ;
808 }
809 }
810
811 // this will make wxWidgets eat the ENTER key so that
812 // we actually prevent line wrapping in a single line
813 // text control
814 eat_key = TRUE;
815 }
816
817 break;
818
819 case WXK_TAB:
820 if ( !(m_windowStyle & wxTE_PROCESS_TAB))
821 {
822 int flags = 0;
823 if (!event.ShiftDown())
824 flags |= wxNavigationKeyEvent::IsForward ;
825 if (event.ControlDown())
826 flags |= wxNavigationKeyEvent::WinChange ;
827 Navigate(flags);
828 return;
829 }
830 else
831 {
832 // This is necessary (don't know why) or the tab will not
833 // be inserted.
834 WriteText(wxT("\t"));
835 }
836
837 break;
838 }
839
840 if (!eat_key)
841 {
842 // perform keystroke handling
843 if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL )
844 CallNextEventHandler((EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() , (EventRef) wxTheApp->MacGetCurrentEvent() ) ;
845 else
846 {
847 EventRecord rec ;
848 if ( wxMacConvertEventToRecord( (EventRef) wxTheApp->MacGetCurrentEvent() , &rec ) )
849 {
850 EventRecord *ev = &rec ;
851 short keycode ;
852 short keychar ;
853 keychar = short(ev->message & charCodeMask);
854 keycode = short(ev->message & keyCodeMask) >> 8 ;
855
856 m_peer->HandleKey( keycode , keychar , ev->modifiers ) ;
857 }
858 }
859 }
860 if ( ( key >= 0x20 && key < WXK_START ) ||
861 key == WXK_RETURN ||
862 key == WXK_DELETE ||
863 key == WXK_BACK)
864 {
865 wxCommandEvent event1(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
866 event1.SetString( GetValue() ) ;
867 event1.SetEventObject( this );
868 wxPostEvent(GetEventHandler(),event1);
869 }
870 }
871
872 // ----------------------------------------------------------------------------
873 // standard handlers for standard edit menu events
874 // ----------------------------------------------------------------------------
875
876 void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
877 {
878 Cut();
879 }
880
881 void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event))
882 {
883 Copy();
884 }
885
886 void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event))
887 {
888 Paste();
889 }
890
891 void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event))
892 {
893 Undo();
894 }
895
896 void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event))
897 {
898 Redo();
899 }
900
901 void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
902 {
903 event.Enable( CanCut() );
904 }
905
906 void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
907 {
908 event.Enable( CanCopy() );
909 }
910
911 void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
912 {
913 event.Enable( CanPaste() );
914 }
915
916 void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
917 {
918 event.Enable( CanUndo() );
919 }
920
921 void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
922 {
923 event.Enable( CanRedo() );
924 }
925
926 bool wxTextCtrl::MacSetupCursor( const wxPoint& pt )
927 {
928 return true ;
929 }
930
931 // user pane implementation
932
933 void wxTextCtrl::MacControlUserPaneDrawProc(wxInt16 part)
934 {
935 }
936
937 wxInt16 wxTextCtrl::MacControlUserPaneHitTestProc(wxInt16 x, wxInt16 y)
938 {
939 return kControlNoPart ;
940 }
941
942 wxInt16 wxTextCtrl::MacControlUserPaneTrackingProc(wxInt16 x, wxInt16 y, void* actionProc)
943 {
944 return kControlNoPart ;
945 }
946
947 void wxTextCtrl::MacControlUserPaneIdleProc()
948 {
949 }
950
951 wxInt16 wxTextCtrl::MacControlUserPaneKeyDownProc(wxInt16 keyCode, wxInt16 charCode, wxInt16 modifiers)
952 {
953 return kControlNoPart ;
954 }
955
956 void wxTextCtrl::MacControlUserPaneActivateProc(bool activating)
957 {
958 }
959
960 wxInt16 wxTextCtrl::MacControlUserPaneFocusProc(wxInt16 action)
961 {
962 return kControlNoPart ;
963 }
964
965 void wxTextCtrl::MacControlUserPaneBackgroundProc(void* info)
966 {
967 }
968
969 // ----------------------------------------------------------------------------
970 // implementation base class
971 // ----------------------------------------------------------------------------
972
973 wxMacTextControl::wxMacTextControl()
974 {
975 }
976
977 wxMacTextControl::~wxMacTextControl()
978 {
979 }
980
981 void wxMacTextControl::SetStyle(long start, long end, const wxTextAttr& style)
982 {
983 }
984
985 void wxMacTextControl::Copy()
986 {
987 }
988
989 void wxMacTextControl::Cut()
990 {
991 }
992
993 void wxMacTextControl::Paste()
994 {
995 }
996
997 bool wxMacTextControl::CanPaste() const
998 {
999 return false ;
1000 }
1001
1002 void wxMacTextControl::SetEditable(bool editable)
1003 {
1004 }
1005
1006 long wxMacTextControl::GetLastPosition() const
1007 {
1008 return GetStringValue().Length() ;
1009 }
1010
1011 void wxMacTextControl::Replace( long from , long to , const wxString str )
1012 {
1013 }
1014
1015 void wxMacTextControl::Clear()
1016 {
1017 SetStringValue( wxEmptyString ) ;
1018 }
1019
1020 bool wxMacTextControl::CanUndo() const
1021 {
1022 return false ;
1023 }
1024
1025 void wxMacTextControl::Undo() { }
1026
1027 bool wxMacTextControl::CanRedo() const
1028 {
1029 return false ;
1030 }
1031
1032 void wxMacTextControl::Redo()
1033 {
1034 }
1035
1036 long wxMacTextControl::XYToPosition(long x, long y) const
1037 {
1038 return 0 ;
1039 }
1040
1041 bool wxMacTextControl::PositionToXY(long pos, long *x, long *y) const
1042 {
1043 return false ;
1044 }
1045
1046 void wxMacTextControl::ShowPosition( long WXUNUSED(pos) )
1047 {
1048 }
1049
1050 int wxMacTextControl::GetNumberOfLines() const
1051 {
1052 ItemCount lines = 0 ;
1053 wxString content = GetStringValue() ;
1054 lines = 1;
1055 for (size_t i = 0; i < content.Length() ; i++)
1056 {
1057 if (content[i] == '\r') lines++;
1058 }
1059 return lines ;
1060 }
1061
1062 wxString wxMacTextControl::GetLineText(long lineNo) const
1063 {
1064 // TODO change this if possible to reflect real lines
1065 wxString content = GetStringValue() ;
1066
1067 // Find line first
1068 int count = 0;
1069 for (size_t i = 0; i < content.Length() ; i++)
1070 {
1071 if (count == lineNo)
1072 {
1073 // Add chars in line then
1074 wxString tmp;
1075
1076 for (size_t j = i; j < content.Length(); j++)
1077 {
1078 if (content[j] == '\n')
1079 return tmp;
1080
1081 tmp += content[j];
1082 }
1083
1084 return tmp;
1085 }
1086 if (content[i] == '\n') count++;
1087 }
1088 return wxEmptyString ;
1089 }
1090
1091 int wxMacTextControl::GetLineLength(long lineNo) const
1092 {
1093 // TODO change this if possible to reflect real lines
1094 wxString content = GetStringValue() ;
1095
1096 // Find line first
1097 int count = 0;
1098 for (size_t i = 0; i < content.Length() ; i++)
1099 {
1100 if (count == lineNo)
1101 {
1102 // Count chars in line then
1103 count = 0;
1104 for (size_t j = i; j < content.Length(); j++)
1105 {
1106 count++;
1107 if (content[j] == '\n') return count;
1108 }
1109
1110 return count;
1111 }
1112 if (content[i] == '\n') count++;
1113 }
1114 return 0 ;
1115 }
1116
1117 // ----------------------------------------------------------------------------
1118 // standard unicode control implementation
1119 // ----------------------------------------------------------------------------
1120
1121 #if TARGET_API_MAC_OSX
1122
1123 wxMacUnicodeTextControl::wxMacUnicodeTextControl( wxWindow *wxPeer,
1124 const wxString& str,
1125 const wxPoint& pos,
1126 const wxSize& size, long style )
1127 {
1128 m_font = wxPeer->GetFont() ;
1129 m_windowStyle = style ;
1130 Rect bounds = wxMacGetBoundsForControl( wxPeer , pos , size ) ;
1131 wxString st = str ;
1132 wxMacConvertNewlines13To10( &st ) ;
1133 wxMacCFStringHolder cf(st , m_font.GetEncoding()) ;
1134 CFStringRef cfr = cf ;
1135 Boolean isPassword = ( m_windowStyle & wxTE_PASSWORD ) != 0 ;
1136 m_valueTag = isPassword ? kControlEditTextPasswordCFStringTag : kControlEditTextCFStringTag ;
1137 CreateEditUnicodeTextControl( MAC_WXHWND(wxPeer->MacGetTopLevelWindowRef()), &bounds , cfr , isPassword , NULL , &m_controlRef ) ;
1138
1139 if ( !(m_windowStyle & wxTE_MULTILINE) )
1140 {
1141 SetData<Boolean>( kControlEditTextPart , kControlEditTextSingleLineTag , true ) ;
1142 }
1143 }
1144
1145 wxMacUnicodeTextControl::~wxMacUnicodeTextControl()
1146 {
1147 }
1148
1149 void wxMacUnicodeTextControl::VisibilityChanged(bool shown)
1150 {
1151 if ( !(m_windowStyle & wxTE_MULTILINE) && shown )
1152 {
1153 // work around a refresh issue insofar as not always the entire content is shown even if this would be possible
1154 ControlEditTextSelectionRec sel ;
1155 CFStringRef value = NULL ;
1156
1157 verify_noerr( GetData<ControlEditTextSelectionRec>( 0, kControlEditTextSelectionTag, &sel ) );
1158 verify_noerr( GetData<CFStringRef>( 0, m_valueTag , &value ) );
1159 verify_noerr( SetData<CFStringRef>( 0, m_valueTag, &value ) );
1160 verify_noerr( SetData<ControlEditTextSelectionRec>( 0, kControlEditTextSelectionTag, &sel ) );
1161
1162 CFRelease( value ) ;
1163 }
1164 }
1165 wxString wxMacUnicodeTextControl::GetStringValue() const
1166 {
1167 wxString result ;
1168 CFStringRef value = GetData<CFStringRef>(0,m_valueTag) ;
1169 if ( value )
1170 {
1171 wxMacCFStringHolder cf(value) ;
1172 result = cf.AsString() ;
1173 }
1174 wxMacConvertNewlines10To13( &result ) ;
1175 return result ;
1176 }
1177 void wxMacUnicodeTextControl::SetStringValue( const wxString &str)
1178 {
1179 wxString st = str ;
1180 wxMacConvertNewlines13To10( &st ) ;
1181 wxMacCFStringHolder cf(st , m_font.GetEncoding() ) ;
1182 verify_noerr( SetData<CFStringRef>( 0, m_valueTag , cf ) ) ;
1183 }
1184 void wxMacUnicodeTextControl::Copy()
1185 {
1186 SendHICommand( kHICommandCopy ) ;
1187 }
1188 void wxMacUnicodeTextControl::Cut()
1189 {
1190 SendHICommand( kHICommandCut ) ;
1191 }
1192 void wxMacUnicodeTextControl::Paste()
1193 {
1194 SendHICommand( kHICommandPaste ) ;
1195 }
1196 bool wxMacUnicodeTextControl::CanPaste() const
1197 {
1198 return true ;
1199 }
1200 void wxMacUnicodeTextControl::SetEditable(bool editable)
1201 {
1202 SetData<Boolean>( 0 , kControlEditTextLockedTag , (Boolean) !editable ) ;
1203 }
1204 void wxMacUnicodeTextControl::Remove( long from , long to )
1205 {
1206 }
1207
1208 void wxMacUnicodeTextControl::GetSelection( long* from, long* to) const
1209 {
1210 ControlEditTextSelectionRec sel ;
1211 verify_noerr(GetData<ControlEditTextSelectionRec>( 0, kControlEditTextSelectionTag, &sel ) ) ;
1212 if ( from ) *from = sel.selStart ;
1213 if ( to ) *to = sel.selEnd ;
1214 }
1215
1216 void wxMacUnicodeTextControl::SetSelection( long from , long to )
1217 {
1218 ControlEditTextSelectionRec sel ;
1219 sel.selStart = from ;
1220 sel.selEnd = to ;
1221 SetData<ControlEditTextSelectionRec>( 0 , kControlEditTextSelectionTag, &sel ) ;
1222 }
1223
1224 void wxMacUnicodeTextControl::WriteText(const wxString& str)
1225 {
1226 wxString st = str ;
1227 wxMacConvertNewlines13To10( &st ) ;
1228 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
1229 wxMacCFStringHolder cf(st , m_font.GetEncoding() ) ;
1230 CFStringRef value = cf ;
1231 SetData<CFStringRef>( 0, kControlEditTextInsertCFStringRefTag, &value );
1232 #else
1233 wxString val = GetStringValue() ;
1234 long start , end ;
1235 GetSelection( &start , &end ) ;
1236 val.Remove( start , end - start ) ;
1237 val.insert( start , str ) ;
1238 SetStringValue( val ) ;
1239 SetInsertionPoint( start + str.Length() ) ;
1240 #endif
1241 }
1242
1243 #endif
1244
1245 // ----------------------------------------------------------------------------
1246 // MLTE control implementation (common part)
1247 // ----------------------------------------------------------------------------
1248
1249 #if TARGET_API_MAC_OSX == 0
1250 // declaration needed because of one line in the code...
1251 static void TPUpdateVisibility(ControlRef theControl) ;
1252 #endif
1253
1254 // if mlte is on read only , no changes at all are allowed, not even from
1255 // procedural API, in order to allow changes via API all the same we must undo
1256 // the readonly status while we are executing, this class helps to do so
1257
1258 class EditHelper
1259 {
1260 public :
1261 EditHelper( TXNObject txn )
1262 {
1263 TXNControlTag tag[] = { kTXNIOPrivilegesTag } ;
1264 m_txn = txn ;
1265 TXNGetTXNObjectControls( m_txn , 1 , tag , m_data ) ;
1266 if ( m_data[0].uValue == kTXNReadOnly )
1267 {
1268 TXNControlData data[] = { { kTXNReadWrite } } ;
1269 TXNSetTXNObjectControls( m_txn , false , 1 , tag , data ) ;
1270 }
1271 }
1272 ~EditHelper()
1273 {
1274 TXNControlTag tag[] = { kTXNIOPrivilegesTag } ;
1275 if ( m_data[0].uValue == kTXNReadOnly )
1276 {
1277 TXNSetTXNObjectControls( m_txn , false , 1 , tag , m_data ) ;
1278 }
1279 }
1280 protected :
1281 TXNObject m_txn ;
1282 TXNControlData m_data[1] ;
1283 } ;
1284
1285 wxString wxMacMLTEControl::GetStringValue() const
1286 {
1287 wxString result ;
1288 OSStatus err ;
1289 Size actualSize = 0;
1290 {
1291 #if wxUSE_UNICODE
1292 Handle theText ;
1293 err = TXNGetDataEncoded( m_txn , kTXNStartOffset, kTXNEndOffset, &theText , kTXNUnicodeTextData );
1294 // all done
1295 if ( err )
1296 {
1297 actualSize = 0 ;
1298 }
1299 else
1300 {
1301 actualSize = GetHandleSize( theText ) / sizeof( UniChar) ;
1302 if ( actualSize > 0 )
1303 {
1304 wxChar *ptr = NULL ;
1305 #if SIZEOF_WCHAR_T == 2
1306 ptr = new wxChar[actualSize + 1 ] ;
1307 wxStrncpy( ptr , (wxChar*) *theText , actualSize ) ;
1308
1309 #else
1310 SetHandleSize( theText , ( actualSize + 1 ) * sizeof( UniChar ) ) ;
1311 HLock( theText ) ;
1312 (((UniChar*)*theText)[actualSize]) = 0 ;
1313 wxMBConvUTF16BE converter ;
1314 size_t noChars = converter.MB2WC( NULL , (const char*)*theText , 0 ) ;
1315 ptr = new wxChar[noChars + 1] ;
1316
1317 noChars = converter.MB2WC( ptr , (const char*)*theText , noChars ) ;
1318 ptr[noChars] = 0 ;
1319 HUnlock( theText ) ;
1320 #endif
1321 ptr[actualSize] = 0 ;
1322 result = wxString( ptr ) ;
1323 delete[] ptr ;
1324 }
1325 DisposeHandle( theText ) ;
1326 }
1327 #else
1328 Handle theText ;
1329 err = TXNGetDataEncoded( ((TXNObject) m_macTXN), kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData );
1330 // all done
1331 if ( err )
1332 {
1333 actualSize = 0 ;
1334 }
1335 else
1336 {
1337 actualSize = GetHandleSize( theText ) ;
1338 if ( actualSize > 0 )
1339 {
1340 HLock( theText ) ;
1341 result = wxString( *theText , wxConvLocal , actualSize ) ;
1342 HUnlock( theText ) ;
1343 }
1344 DisposeHandle( theText ) ;
1345 }
1346 #endif
1347 }
1348 wxMacConvertNewlines10To13( &result ) ;
1349 return result ;
1350 }
1351
1352 void wxMacMLTEControl::SetStringValue( const wxString &str)
1353 {
1354 wxString st = str ;
1355 wxMacConvertNewlines13To10( &st ) ;
1356 EditHelper help(m_txn) ;
1357
1358 // wxMacWindowClipper c( this ) ;
1359 #if !TARGET_API_MAC_OSX
1360 // otherwise scrolling might have problems ?
1361 TPUpdateVisibility( m_controlRef ) ;
1362 #endif
1363 SetTXNData( st , kTXNStartOffset, kTXNEndOffset ) ;
1364 TXNSetSelection( m_txn, 0, 0);
1365 TXNShowSelection( m_txn, kTXNShowStart);
1366 }
1367
1368 TXNFrameOptions wxMacMLTEControl::FrameOptionsFromWXStyle( long wxStyle )
1369 {
1370 TXNFrameOptions frameOptions =
1371 kTXNDontDrawCaretWhenInactiveMask ;
1372 if ( ! ( wxStyle & wxTE_NOHIDESEL ) )
1373 frameOptions |= kTXNDontDrawSelectionWhenInactiveMask ;
1374
1375 if ( wxStyle & wxTE_MULTILINE )
1376 {
1377 if ( ! ( wxStyle & wxTE_DONTWRAP ) )
1378 frameOptions |= kTXNAlwaysWrapAtViewEdgeMask ;
1379 else
1380 {
1381 frameOptions |= kTXNAlwaysWrapAtViewEdgeMask ;
1382 frameOptions |= kTXNWantHScrollBarMask ;
1383 }
1384
1385 if ( !(wxStyle & wxTE_NO_VSCROLL ) )
1386 frameOptions |= kTXNWantVScrollBarMask ;
1387 }
1388 else
1389 frameOptions |= kTXNSingleLineOnlyMask ;
1390
1391 if ( wxStyle & wxHSCROLL )
1392 frameOptions |= kTXNWantHScrollBarMask ;
1393
1394 return frameOptions ;
1395 }
1396
1397 void wxMacMLTEControl::AdjustCreationAttributes( const wxColour &background, bool visible )
1398 {
1399 TXNControlTag iControlTags[3] = { kTXNDoFontSubstitution, kTXNWordWrapStateTag };
1400 TXNControlData iControlData[3] = { {false}, {kTXNNoAutoWrap} };
1401 int toptag = 2 ;
1402 #if TARGET_API_MAC_OSX
1403 iControlTags[2] = kTXNVisibilityTag ;
1404 iControlData[2].uValue = visible ;
1405 toptag++ ;
1406 #endif
1407
1408 if ( m_windowStyle & wxTE_MULTILINE )
1409 {
1410 if (m_windowStyle & wxTE_DONTWRAP)
1411 iControlData[1].uValue = kTXNNoAutoWrap ;
1412 else
1413 iControlData[1].uValue = kTXNAutoWrap ;
1414
1415 }
1416 verify_noerr( TXNSetTXNObjectControls( m_txn, false, toptag,
1417 iControlTags, iControlData )) ;
1418
1419 // setting the default font
1420
1421 Str255 fontName ;
1422 SInt16 fontSize ;
1423 Style fontStyle ;
1424
1425 GetThemeFont(kThemeSystemFont , GetApplicationScript() , fontName , &fontSize , &fontStyle ) ;
1426
1427 TXNTypeAttributes typeAttr[] =
1428 {
1429 { kTXNQDFontNameAttribute , kTXNQDFontNameAttributeSize , { (void*) fontName } } ,
1430 { kTXNQDFontSizeAttribute , kTXNFontSizeAttributeSize , { (void*) (fontSize << 16) } } ,
1431 { kTXNQDFontStyleAttribute , kTXNQDFontStyleAttributeSize , { (void*) normal } } ,
1432 } ;
1433
1434 verify_noerr( TXNSetTypeAttributes (m_txn, sizeof( typeAttr ) / sizeof(TXNTypeAttributes) , typeAttr,
1435 kTXNStartOffset,
1436 kTXNEndOffset) );
1437
1438 if ( m_windowStyle & wxTE_PASSWORD )
1439 {
1440 UniChar c = 0xA5 ;
1441 verify_noerr(TXNEchoMode( m_txn , c , 0 , true )) ;
1442 }
1443
1444 TXNBackground tback;
1445 tback.bgType = kTXNBackgroundTypeRGB;
1446 tback.bg.color = MAC_WXCOLORREF( background.GetPixel() );
1447 TXNSetBackground( m_txn , &tback);
1448 }
1449
1450 int wxMacMLTEControl::ConvertAttribute( const wxTextAttr& style , TXNTypeAttributes typeAttr[] )
1451 {
1452 Str255 fontName = "\pMonaco" ;
1453 SInt16 fontSize = 12 ;
1454 Style fontStyle = normal ;
1455 RGBColor color ;
1456 int attrCounter = 0 ;
1457 if ( style.HasFont() )
1458 {
1459 const wxFont &font = style.GetFont() ;
1460 wxMacStringToPascal( font.GetFaceName() , fontName ) ;
1461 fontSize = font.GetPointSize() ;
1462 if ( font.GetUnderlined() )
1463 fontStyle |= underline ;
1464 if ( font.GetWeight() == wxBOLD )
1465 fontStyle |= bold ;
1466 if ( font.GetStyle() == wxITALIC )
1467 fontStyle |= italic ;
1468
1469 typeAttr[attrCounter].tag = kTXNQDFontNameAttribute ;
1470 typeAttr[attrCounter].size = kTXNQDFontNameAttributeSize ;
1471 typeAttr[attrCounter].data.dataPtr = (void*) fontName ;
1472 typeAttr[attrCounter+1].tag = kTXNQDFontSizeAttribute ;
1473 typeAttr[attrCounter+1].size = kTXNFontSizeAttributeSize ;
1474 typeAttr[attrCounter+1].data.dataValue = (fontSize << 16) ;
1475 typeAttr[attrCounter+2].tag = kTXNQDFontStyleAttribute ;
1476 typeAttr[attrCounter+2].size = kTXNQDFontStyleAttributeSize ;
1477 typeAttr[attrCounter+2].data.dataValue = fontStyle ;
1478 attrCounter += 3 ;
1479
1480 }
1481 if ( style.HasTextColour() )
1482 {
1483 typeAttr[attrCounter].tag = kTXNQDFontColorAttribute ;
1484 typeAttr[attrCounter].size = kTXNQDFontColorAttributeSize ;
1485 typeAttr[attrCounter].data.dataPtr = (void*) &color ;
1486 color = MAC_WXCOLORREF(style.GetTextColour().GetPixel()) ;
1487 attrCounter += 1 ;
1488 }
1489 return attrCounter ;
1490 }
1491
1492 void wxMacMLTEControl::SetFont( const wxFont & font , const wxColour& foreground , long windowStyle )
1493 {
1494 EditHelper help(m_txn) ;
1495 wxTextAttr style(wxNullColour,wxNullColour,font) ;
1496 TXNTypeAttributes typeAttr[4] ;
1497 int attrCounter = ConvertAttribute( style , typeAttr ) ;
1498 if ( attrCounter > 0 )
1499 {
1500 verify_noerr( TXNSetTypeAttributes ( m_txn , attrCounter , typeAttr, kTXNStartOffset,kTXNEndOffset) );
1501 }
1502 }
1503 void wxMacMLTEControl::SetStyle(long start, long end, const wxTextAttr& style)
1504 {
1505 EditHelper help(m_txn) ;
1506 TXNTypeAttributes typeAttr[4] ;
1507 int attrCounter = ConvertAttribute( style , typeAttr ) ;
1508 if ( attrCounter > 0 )
1509 {
1510 verify_noerr( TXNSetTypeAttributes ( m_txn , attrCounter , typeAttr, start,end) );
1511 }
1512 }
1513
1514 void wxMacMLTEControl::Copy()
1515 {
1516 ClearCurrentScrap();
1517 TXNCopy(m_txn);
1518 TXNConvertToPublicScrap();
1519 }
1520
1521 void wxMacMLTEControl::Cut()
1522 {
1523 ClearCurrentScrap();
1524 TXNCut(m_txn);
1525 TXNConvertToPublicScrap();
1526 }
1527
1528 void wxMacMLTEControl::Paste()
1529 {
1530 TXNConvertFromPublicScrap();
1531 TXNPaste(m_txn);
1532 }
1533
1534 bool wxMacMLTEControl::CanPaste() const
1535 {
1536 return TXNIsScrapPastable() ;
1537 }
1538
1539 void wxMacMLTEControl::SetEditable(bool editable)
1540 {
1541 TXNControlTag tag[] = { kTXNIOPrivilegesTag } ;
1542 TXNControlData data[] = { { editable ? kTXNReadWrite : kTXNReadOnly } } ;
1543 TXNSetTXNObjectControls( m_txn , false , sizeof(tag) / sizeof (TXNControlTag) , tag , data ) ;
1544 }
1545
1546 long wxMacMLTEControl::GetLastPosition() const
1547 {
1548 long actualsize = 0 ;
1549
1550 Handle theText ;
1551 OSErr err = TXNGetDataEncoded( m_txn, kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData );
1552 /* all done */
1553 if ( err )
1554 {
1555 actualsize = 0 ;
1556 }
1557 else
1558 {
1559 actualsize = GetHandleSize( theText ) ;
1560 DisposeHandle( theText ) ;
1561 }
1562
1563 return actualsize ;
1564 }
1565
1566 void wxMacMLTEControl::Replace( long from , long to , const wxString str )
1567 {
1568 wxString value = str ;
1569 wxMacConvertNewlines13To10( &value ) ;
1570
1571 EditHelper help( m_txn ) ;
1572
1573 TXNSetSelection(m_txn , from , to ) ;
1574 TXNClear( m_txn ) ;
1575 SetTXNData( str , kTXNUseCurrentSelection, kTXNUseCurrentSelection ) ;
1576 }
1577
1578 void wxMacMLTEControl::Remove( long from , long to )
1579 {
1580 EditHelper help( m_txn ) ;
1581
1582 TXNSetSelection(m_txn , from , to ) ;
1583 TXNClear( m_txn ) ;
1584 }
1585
1586 void wxMacMLTEControl::GetSelection( long* from, long* to) const
1587 {
1588 TXNGetSelection( m_txn , (TXNOffset*) from , (TXNOffset*) to ) ;
1589 }
1590
1591 void wxMacMLTEControl::SetSelection( long from , long to )
1592 {
1593 /* change the selection */
1594 if ((from == -1) && (to == -1))
1595 TXNSelectAll(m_txn);
1596 else
1597 TXNSetSelection( m_txn, from, to);
1598 TXNShowSelection( m_txn, kTXNShowStart);
1599 }
1600
1601 void wxMacMLTEControl::WriteText(const wxString& str)
1602 {
1603 EditHelper helper( m_txn ) ;
1604 wxString st = str ;
1605 wxMacConvertNewlines13To10( &st ) ;
1606
1607 long start , end , dummy ;
1608 GetSelection( &start , &dummy ) ;
1609 SetTXNData( st , kTXNUseCurrentSelection, kTXNUseCurrentSelection ) ;
1610 GetSelection( &dummy , &end ) ;
1611 // TODO SetStyle( start , end , GetDefaultStyle() ) ;
1612 }
1613
1614 void wxMacMLTEControl::Clear()
1615 {
1616 EditHelper st(m_txn) ;
1617 TXNSetSelection( m_txn , kTXNStartOffset , kTXNEndOffset ) ;
1618 TXNClear(m_txn);
1619 }
1620
1621 bool wxMacMLTEControl::CanUndo() const
1622 {
1623 return TXNCanUndo( m_txn , NULL ) ;
1624 }
1625
1626 void wxMacMLTEControl::Undo()
1627 {
1628 TXNUndo( m_txn ) ;
1629 }
1630
1631 bool wxMacMLTEControl::CanRedo() const
1632 {
1633 return TXNCanRedo( m_txn , NULL ) ;
1634 }
1635
1636 void wxMacMLTEControl::Redo()
1637 {
1638 TXNRedo( m_txn ) ;
1639 }
1640
1641 int wxMacMLTEControl::GetNumberOfLines() const
1642 {
1643 ItemCount lines = 0 ;
1644 TXNGetLineCount(m_txn, &lines ) ;
1645 return lines ;
1646 }
1647
1648 long wxMacMLTEControl::XYToPosition(long x, long y) const
1649 {
1650 Point curpt ;
1651
1652 long lastpos = GetLastPosition() ;
1653
1654 // TODO find a better implementation : while we can get the
1655 // line metrics of a certain line, we don't get its starting
1656 // position, so it would probably be rather a binary search
1657 // for the start position
1658 long xpos = 0 ;
1659 long ypos = 0 ;
1660 int lastHeight = 0 ;
1661
1662 ItemCount n ;
1663 for ( n = 0 ; n <= (ItemCount) lastpos ; ++n )
1664 {
1665 if ( y == ypos && x == xpos )
1666 return n ;
1667
1668 TXNOffsetToPoint( m_txn , n , &curpt);
1669
1670 if ( curpt.v > lastHeight )
1671 {
1672 xpos = 0 ;
1673 if ( n > 0 )
1674 ++ypos ;
1675 lastHeight = curpt.v ;
1676 }
1677 else
1678 ++xpos ;
1679 }
1680 return 0 ;
1681 }
1682
1683 bool wxMacMLTEControl::PositionToXY(long pos, long *x, long *y) const
1684 {
1685 Point curpt ;
1686
1687 long lastpos = GetLastPosition() ;
1688
1689 if ( y ) *y = 0 ;
1690 if ( x ) *x = 0 ;
1691
1692 if ( pos <= lastpos )
1693 {
1694 // TODO find a better implementation : while we can get the
1695 // line metrics of a certain line, we don't get its starting
1696 // position, so it would probably be rather a binary search
1697 // for the start position
1698 long xpos = 0 ;
1699 long ypos = 0 ;
1700 int lastHeight = 0 ;
1701
1702 ItemCount n ;
1703 for ( n = 0 ; n <= (ItemCount) pos ; ++n )
1704 {
1705 TXNOffsetToPoint(m_txn , n , &curpt);
1706
1707 if ( curpt.v > lastHeight )
1708 {
1709 xpos = 0 ;
1710 if ( n > 0 )
1711 ++ypos ;
1712 lastHeight = curpt.v ;
1713 }
1714 else
1715 ++xpos ;
1716 }
1717 if ( y ) *y = ypos ;
1718 if ( x ) *x = xpos ;
1719 }
1720
1721 return FALSE ;
1722 }
1723
1724 void wxMacMLTEControl::ShowPosition( long pos )
1725 {
1726 #if TARGET_RT_MAC_MACHO && defined(AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER)
1727 {
1728 Point current ;
1729 Point desired ;
1730 TXNOffset selstart , selend ;
1731 TXNGetSelection( m_txn , &selstart , &selend) ;
1732 TXNOffsetToPoint( m_txn, selstart , &current);
1733 TXNOffsetToPoint( m_txn, pos , &desired);
1734 //TODO use HIPoints for 10.3 and above
1735 if ( (UInt32) TXNScroll != (UInt32) kUnresolvedCFragSymbolAddress )
1736 {
1737 OSErr theErr = noErr;
1738 SInt32 dv = desired.v - current.v ;
1739 SInt32 dh = desired.h - current.h ;
1740 TXNShowSelection( m_txn , true ) ;
1741 theErr = TXNScroll( m_txn, kTXNScrollUnitsInPixels , kTXNScrollUnitsInPixels , &dv , &dh );
1742 wxASSERT_MSG( theErr == noErr, _T("TXNScroll returned an error!") );
1743 }
1744 }
1745 #endif
1746 }
1747
1748 void wxMacMLTEControl::SetTXNData( const wxString& st , TXNOffset start , TXNOffset end )
1749 {
1750 #if wxUSE_UNICODE
1751 #if SIZEOF_WCHAR_T == 2
1752 size_t len = st.Len() ;
1753 TXNSetData( m_txn , kTXNUnicodeTextData, (void*)st.wc_str(), len * 2,
1754 start, end);
1755 #else
1756 wxMBConvUTF16BE converter ;
1757 ByteCount byteBufferLen = converter.WC2MB( NULL , st.wc_str() , 0 ) ;
1758 UniChar *unibuf = (UniChar*) malloc(byteBufferLen) ;
1759 converter.WC2MB( (char*) unibuf , st.wc_str() , byteBufferLen ) ;
1760 TXNSetData( m_txn , kTXNUnicodeTextData, (void*)unibuf, byteBufferLen ,
1761 start, end);
1762 free( unibuf ) ;
1763 #endif
1764 #else
1765 wxCharBuffer text = st.mb_str(wxConvLocal) ;
1766 TXNSetData( m_txn , kTXNTextData, (void*)text.data(), strlen( text ) ,
1767 start, end);
1768 #endif
1769 }
1770
1771
1772 wxString wxMacMLTEControl::GetLineText(long lineNo) const
1773 {
1774 wxString line ;
1775 Point curpt ;
1776 wxString content = GetStringValue() ;
1777
1778 if ( lineNo < GetNumberOfLines() )
1779 {
1780 // TODO find a better implementation : while we can get the
1781 // line metrics of a certain line, we don't get its starting
1782 // position, so it would probably be rather a binary search
1783 // for the start position
1784 long xpos = 0 ;
1785 long ypos = 0 ;
1786 int lastHeight = 0 ;
1787 long lastpos = GetLastPosition() ;
1788
1789 ItemCount n ;
1790 for ( n = 0 ; n <= (ItemCount)lastpos ; ++n )
1791 {
1792 TXNOffsetToPoint( m_txn, n , &curpt);
1793
1794 if ( curpt.v > lastHeight )
1795 {
1796 if ( ypos == lineNo )
1797 return line ;
1798
1799 xpos = 0 ;
1800 if ( n > 0 )
1801 ++ypos ;
1802 lastHeight = curpt.v ;
1803 }
1804 else
1805 {
1806 if ( ypos == lineNo )
1807 line += content[n] ;
1808 ++xpos ;
1809 }
1810 }
1811 }
1812 return line ;
1813 }
1814
1815 int wxMacMLTEControl::GetLineLength(long lineNo) const
1816 {
1817 Point curpt ;
1818 if ( lineNo < GetNumberOfLines() )
1819 {
1820 // TODO find a better implementation : while we can get the
1821 // line metrics of a certain line, we don't get its starting
1822 // position, so it would probably be rather a binary search
1823 // for the start position
1824 long xpos = 0 ;
1825 long ypos = 0 ;
1826 int lastHeight = 0 ;
1827 long lastpos = GetLastPosition() ;
1828
1829 ItemCount n ;
1830 for ( n = 0 ; n <= (ItemCount) lastpos ; ++n )
1831 {
1832 TXNOffsetToPoint( m_txn , n , &curpt);
1833
1834 if ( curpt.v > lastHeight )
1835 {
1836 if ( ypos == lineNo )
1837 return xpos ;
1838
1839 xpos = 0 ;
1840 if ( n > 0 )
1841 ++ypos ;
1842 lastHeight = curpt.v ;
1843 }
1844 else
1845 ++xpos ;
1846 }
1847 }
1848 return 0 ;
1849 }
1850
1851
1852 // ----------------------------------------------------------------------------
1853 // MLTE control implementation (classic part)
1854 // ----------------------------------------------------------------------------
1855
1856 #if !TARGET_API_MAC_OSX
1857
1858 // CS:TODO we still have a problem getting properly at the text events of a control because under Carbon
1859 // the MLTE engine registers itself for the key events thus the normal flow never occurs, the only measure for the
1860 // moment is to avoid setting the true focus on the control, the proper solution at the end would be to have
1861 // an alternate path for carbon key events that routes automatically into the same wx flow of events
1862
1863 /* part codes */
1864
1865 /* kmUPTextPart is the part code we return to indicate the user has clicked
1866 in the text area of our control */
1867 #define kmUPTextPart 1
1868
1869
1870 /* routines for using existing user pane controls.
1871 These routines are useful for cases where you would like to use an
1872 existing user pane control in, say, a dialog window as a scrolling
1873 text edit field.*/
1874
1875 /* Utility Routines */
1876
1877 /* kUserClickedToFocusPart is a part code we pass to the SetKeyboardFocus
1878 routine. In our focus switching routine this part code is understood
1879 as meaning 'the user has clicked in the control and we need to switch
1880 the current focus to ourselves before we can continue'. */
1881 #define kUserClickedToFocusPart 100
1882
1883 /* STPTextPaneVars is a structure used for storing the the mUP Control's
1884 internal variables and state information. A handle to this record is
1885 stored in the pane control's reference value field using the
1886 SetControlReference routine. */
1887
1888 class STPTextPaneVars {
1889 public :
1890 /* OS records referenced */
1891 TXNObject fTXNRec; /* the txn record */
1892 TXNFrameID fTXNFrame; /* the txn frame ID */
1893 ControlRef fUserPaneRec; /* handle to the user pane control */
1894 WindowPtr fOwner; /* window containing control */
1895 GrafPtr fDrawingEnvironment; /* grafport where control is drawn */
1896 /* flags */
1897 Boolean fInFocus; /* true while the focus rect is drawn around the control */
1898 Boolean fIsActive; /* true while the control is drawn in the active state */
1899 Boolean fTXNObjectActive; /* reflects the activation state of the text edit record */
1900 Boolean fFocusDrawState; /* true if focus is drawn (default: true) */
1901 /* calculated locations */
1902 Rect fRBounds; /* control bounds */
1903 Rect fRTextArea; /* area where the text is drawn */
1904 Rect fRFocusOutline; /* rectangle used to draw the focus box */
1905 Rect fRTextOutline; /* rectangle used to draw the border */
1906 RgnHandle fRTextOutlineRegion; /* background region for the text, erased before calling TEUpdate */
1907 /* our focus advance override routine */
1908 EventHandlerUPP handlerUPP;
1909 EventHandlerRef handlerRef;
1910 bool fNoBorders ;
1911 bool fMultiline ;
1912 bool fVisible ;
1913 } ;
1914
1915 /* Univerals Procedure Pointer variables used by the
1916 mUP Control. These variables are set up
1917 the first time that mUPOpenControl is called. */
1918 ControlUserPaneDrawUPP gTPDrawProc = NULL;
1919 ControlUserPaneHitTestUPP gTPHitProc = NULL;
1920 ControlUserPaneTrackingUPP gTPTrackProc = NULL;
1921 ControlUserPaneIdleUPP gTPIdleProc = NULL;
1922 ControlUserPaneKeyDownUPP gTPKeyProc = NULL;
1923 ControlUserPaneActivateUPP gTPActivateProc = NULL;
1924 ControlUserPaneFocusUPP gTPFocusProc = NULL;
1925
1926 // one place for calculating all
1927 static void TPCalculateBounds(STPTextPaneVars *varsp, const Rect& bounds)
1928 {
1929 SetRect(&varsp->fRBounds, bounds.left, bounds.top, bounds.right, bounds.bottom);
1930 SetRect(&varsp->fRFocusOutline, bounds.left, bounds.top, bounds.right, bounds.bottom);
1931 // eventually make TextOutline inset 1,1
1932 SetRect(&varsp->fRTextOutline, bounds.left, bounds.top, bounds.right, bounds.bottom);
1933 if ( !varsp->fNoBorders )
1934 {
1935 SetRect(&varsp->fRTextArea, bounds.left + 2 , bounds.top + (varsp->fMultiline ? 0 : 2) ,
1936 bounds.right - (varsp->fMultiline ? 0 : 2), bounds.bottom - (varsp->fMultiline ? 0 : 2));
1937 }
1938 else
1939 {
1940 SetRect(&varsp->fRTextArea, bounds.left , bounds.top ,
1941 bounds.right, bounds.bottom);
1942 }
1943 }
1944
1945 OSStatus MLTESetObjectVisibility( STPTextPaneVars *varsp, Boolean vis , long wxStyle)
1946 {
1947 OSStatus err = noErr ;
1948 #if TARGET_API_MAC_OSX
1949 TXNControlTag iControlTags[1] = { kTXNVisibilityTag };
1950 TXNControlData iControlData[1] = {{ vis }};
1951 err = ::TXNSetTXNObjectControls( varsp->fTXNRec, false, 1, iControlTags, iControlData );
1952 #endif
1953 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(varsp->fUserPaneRec);
1954 if ( vis && textctrl )
1955 {
1956 Rect bounds ;
1957 UMAGetControlBoundsInWindowCoords( varsp->fUserPaneRec, &bounds);
1958 TPCalculateBounds( varsp , bounds ) ;
1959 wxMacWindowClipper cl(textctrl) ;
1960 TXNSetFrameBounds( varsp->fTXNRec, varsp->fRTextArea.top, varsp->fRTextArea.left,
1961 varsp->fRTextArea.bottom, varsp->fRTextArea.right, varsp->fTXNFrame);
1962 TXNShowSelection( varsp->fTXNRec, kTXNShowStart);
1963 }
1964 return err ;
1965 }
1966
1967 // make sure we don't miss changes as carbon events are not available for these under classic
1968 static void TPUpdateVisibility(ControlRef theControl) {
1969 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
1970 if ( textctrl == NULL )
1971 return ;
1972
1973 STPTextPaneVars *varsp = (STPTextPaneVars *) ((wxMacMLTEClassicControl*)textctrl->GetPeer())->m_macTXNvars ;
1974
1975 Rect bounds ;
1976 UMAGetControlBoundsInWindowCoords(theControl, &bounds);
1977 if ( textctrl->MacIsReallyShown() != varsp->fVisible )
1978 {
1979 // invalidate old position
1980 // InvalWindowRect( GetControlOwner( theControl ) , &varsp->fRBounds ) ;
1981 varsp->fVisible = textctrl->MacIsReallyShown() ;
1982 }
1983 if ( !EqualRect( &bounds , &varsp->fRBounds ) )
1984 {
1985 // old position
1986 Rect oldBounds = varsp->fRBounds ;
1987 TPCalculateBounds( varsp , bounds ) ;
1988 // we only recalculate when visible, otherwise scrollbars get drawn at incorrect places
1989 if ( varsp->fVisible )
1990 {
1991 wxMacWindowClipper cl(textctrl) ;
1992 TXNSetFrameBounds( varsp->fTXNRec, varsp->fRTextArea.top, varsp->fRTextArea.left,
1993 varsp->fRTextArea.bottom, varsp->fRTextArea.right, varsp->fTXNFrame);
1994 }
1995 InvalWindowRect( GetControlOwner( theControl ) , &oldBounds ) ;
1996 InvalWindowRect( GetControlOwner( theControl ) , &varsp->fRBounds ) ;
1997 }
1998 }
1999
2000 // make correct activations
2001 static void TPActivatePaneText(STPTextPaneVars *varsp, Boolean setActive) {
2002
2003 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(varsp->fUserPaneRec);
2004 if (varsp->fTXNObjectActive != setActive && textctrl->MacIsReallyShown() )
2005 {
2006 varsp->fTXNObjectActive = setActive;
2007 TXNActivate(varsp->fTXNRec, varsp->fTXNFrame, varsp->fTXNObjectActive);
2008 if (varsp->fInFocus)
2009 TXNFocus( varsp->fTXNRec, varsp->fTXNObjectActive);
2010 }
2011 }
2012
2013 // update focus outlines
2014 static void TPRedrawFocusOutline(STPTextPaneVars *varsp) {
2015
2016 /* state changed */
2017 if (varsp->fFocusDrawState != (varsp->fIsActive && varsp->fInFocus))
2018 {
2019 varsp->fFocusDrawState = (varsp->fIsActive && varsp->fInFocus);
2020 DrawThemeFocusRect(&varsp->fRFocusOutline, varsp->fFocusDrawState);
2021 }
2022 }
2023
2024 // update TXN focus state
2025 static void TPFocusPaneText(STPTextPaneVars *varsp, Boolean setFocus) {
2026 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(varsp->fUserPaneRec);
2027
2028 if (varsp->fInFocus != setFocus && textctrl->MacIsReallyShown()) {
2029 varsp->fInFocus = setFocus;
2030 TXNFocus( varsp->fTXNRec, varsp->fInFocus);
2031 }
2032 }
2033
2034 // draw the control
2035 static pascal void TPPaneDrawProc(ControlRef theControl, ControlPartCode thePart) {
2036 /* set up our globals */
2037
2038 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
2039 if ( textctrl == NULL )
2040 return ;
2041 TPUpdateVisibility( theControl ) ;
2042
2043 STPTextPaneVars *varsp = (STPTextPaneVars *) ((wxMacMLTEClassicControl*)textctrl->GetPeer())->m_macTXNvars ;
2044 if ( textctrl->MacIsReallyShown() )
2045 {
2046 wxMacWindowClipper clipper( textctrl ) ;
2047 TXNDraw(varsp->fTXNRec, NULL);
2048 if ( !varsp->fNoBorders )
2049 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
2050 TPRedrawFocusOutline( varsp ) ;
2051 }
2052
2053 }
2054
2055
2056 /* TPPaneHitTestProc is called when the control manager would
2057 like to determine what part of the control the mouse resides over.
2058 We also call this routine from our tracking proc to determine how
2059 to handle mouse clicks. */
2060 static pascal ControlPartCode TPPaneHitTestProc(ControlRef theControl, Point where) {
2061 ControlPartCode result;
2062 /* set up our locals and lock down our globals*/
2063 result = 0;
2064 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
2065 if ( textctrl == NULL )
2066 return 0 ;
2067 TPUpdateVisibility( theControl ) ;
2068 STPTextPaneVars *varsp = (STPTextPaneVars *) ((wxMacMLTEClassicControl*)textctrl->GetPeer())->m_macTXNvars ;
2069 if (textctrl->MacIsReallyShown() )
2070 {
2071 if (PtInRect(where, &varsp->fRBounds))
2072 result = kmUPTextPart;
2073 else
2074 result = 0;
2075 }
2076 return result;
2077 }
2078
2079
2080
2081
2082
2083 /* TPPaneTrackingProc is called when the mouse is being held down
2084 over our control. This routine handles clicks in the text area
2085 and in the scroll bar. */
2086 static pascal ControlPartCode TPPaneTrackingProc(ControlRef theControl, Point startPt, ControlActionUPP actionProc) {
2087
2088 ControlPartCode partCodeResult;
2089 /* make sure we have some variables... */
2090 partCodeResult = 0;
2091 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
2092 if ( textctrl == NULL )
2093 return 0;
2094 TPUpdateVisibility( theControl ) ;
2095 STPTextPaneVars *varsp = (STPTextPaneVars *) ((wxMacMLTEClassicControl*)textctrl->GetPeer())->m_macTXNvars ;
2096 if (textctrl->MacIsReallyShown() )
2097 {
2098 /* we don't do any of these functions unless we're in focus */
2099 if ( ! varsp->fInFocus) {
2100 WindowPtr owner;
2101 owner = GetControlOwner(theControl);
2102 ClearKeyboardFocus(owner);
2103 SetKeyboardFocus(owner, theControl, kUserClickedToFocusPart);
2104 }
2105 /* find the location for the click */
2106 // for compositing, we must convert these into toplevel window coordinates, because hittesting expects them
2107 if ( textctrl->MacGetTopLevelWindow()->MacUsesCompositing() )
2108 {
2109 int x = 0 , y = 0 ;
2110 textctrl->MacClientToRootWindow( &x , &y ) ;
2111 startPt.h += x ;
2112 startPt.v += y ;
2113 }
2114
2115 switch (TPPaneHitTestProc(theControl, startPt))
2116 {
2117
2118 /* handle clicks in the text part */
2119 case kmUPTextPart:
2120 {
2121 wxMacWindowClipper clipper( textctrl ) ;
2122
2123 EventRecord rec ;
2124 ConvertEventRefToEventRecord( (EventRef) wxTheApp->MacGetCurrentEvent() , &rec ) ;
2125 TXNClick( varsp->fTXNRec, &rec );
2126
2127 }
2128 break;
2129
2130 }
2131 }
2132 return partCodeResult;
2133 }
2134
2135
2136 /* TPPaneIdleProc is our user pane idle routine. When our text field
2137 is active and in focus, we use this routine to set the cursor. */
2138 static pascal void TPPaneIdleProc(ControlRef theControl) {
2139 /* set up locals */
2140 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
2141 if ( textctrl == NULL )
2142 return ;
2143 TPUpdateVisibility( theControl ) ;
2144 STPTextPaneVars *varsp = (STPTextPaneVars *) ((wxMacMLTEClassicControl*)textctrl->GetPeer())->m_macTXNvars ;
2145 if (textctrl->MacIsReallyShown()) {
2146 /* if we're not active, then we have nothing to say about the cursor */
2147 if (varsp->fIsActive) {
2148 Rect bounds;
2149 Point mousep;
2150
2151 wxMacWindowClipper clipper( textctrl ) ;
2152 GetMouse(&mousep);
2153 /* there's a 'focus thing' and an 'unfocused thing' */
2154 if (varsp->fInFocus) {
2155 /* flash the cursor */
2156 SetPort(varsp->fDrawingEnvironment);
2157 TXNIdle(varsp->fTXNRec);
2158 /* set the cursor */
2159 if (PtInRect(mousep, &varsp->fRTextArea)) {
2160 RgnHandle theRgn;
2161 RectRgn((theRgn = NewRgn()), &varsp->fRTextArea);
2162 TXNAdjustCursor(varsp->fTXNRec, theRgn);
2163 DisposeRgn(theRgn);
2164 }
2165 else
2166 {
2167 // SetThemeCursor(kThemeArrowCursor);
2168 }
2169 } else {
2170 /* if it's in our bounds, set the cursor */
2171 UMAGetControlBoundsInWindowCoords(theControl, &bounds);
2172 if (PtInRect(mousep, &bounds))
2173 {
2174 // SetThemeCursor(kThemeArrowCursor);
2175 }
2176 }
2177 }
2178 }
2179 }
2180
2181
2182 /* TPPaneKeyDownProc is called whenever a keydown event is directed
2183 at our control. Here, we direct the keydown event to the text
2184 edit record and redraw the scroll bar and text field as appropriate. */
2185 static pascal ControlPartCode TPPaneKeyDownProc(ControlRef theControl,
2186 SInt16 keyCode, SInt16 charCode, SInt16 modifiers) {
2187
2188 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
2189 if ( textctrl == NULL )
2190 return 0;
2191 TPUpdateVisibility( theControl ) ;
2192
2193 STPTextPaneVars *varsp = (STPTextPaneVars *) ((wxMacMLTEClassicControl*)textctrl->GetPeer())->m_macTXNvars ;
2194 if (varsp->fInFocus)
2195 {
2196 /* turn autoscrolling on and send the key event to text edit */
2197 wxMacWindowClipper clipper( textctrl ) ;
2198 EventRecord ev ;
2199 memset( &ev , 0 , sizeof( ev ) ) ;
2200 ev.what = keyDown ;
2201 ev.modifiers = modifiers ;
2202 ev.message = (( keyCode << 8 ) & keyCodeMask ) + ( charCode & charCodeMask ) ;
2203 TXNKeyDown( varsp->fTXNRec, &ev);
2204 }
2205 return kControlEntireControl;
2206 }
2207
2208
2209 /* TPPaneActivateProc is called when the window containing
2210 the user pane control receives activate events. Here, we redraw
2211 the control and it's text as necessary for the activation state. */
2212 static pascal void TPPaneActivateProc(ControlRef theControl, Boolean activating) {
2213 /* set up locals */
2214 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
2215
2216 if ( textctrl == NULL )
2217 return ;
2218 TPUpdateVisibility( theControl ) ;
2219
2220 STPTextPaneVars *varsp = (STPTextPaneVars *) ((wxMacMLTEClassicControl*)textctrl->GetPeer())->m_macTXNvars ;
2221
2222 varsp->fIsActive = activating;
2223 wxMacWindowClipper clipper( textctrl ) ;
2224 TPActivatePaneText(varsp, varsp->fIsActive && varsp->fInFocus);
2225 /* redraw the frame */
2226 if ( textctrl->MacIsReallyShown() )
2227 {
2228 if ( !varsp->fNoBorders )
2229 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
2230 TPRedrawFocusOutline( varsp ) ;
2231 }
2232 }
2233
2234
2235 /* TPPaneFocusProc is called when every the focus changes to or
2236 from our control. Herein, switch the focus appropriately
2237 according to the parameters and redraw the control as
2238 necessary. */
2239 static pascal ControlPartCode TPPaneFocusProc(ControlRef theControl, ControlFocusPart action) {
2240 ControlPartCode focusResult;
2241
2242 focusResult = kControlFocusNoPart;
2243 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
2244 if ( textctrl == NULL )
2245 return 0;
2246 TPUpdateVisibility( theControl ) ;
2247 STPTextPaneVars *varsp = (STPTextPaneVars *) ((wxMacMLTEClassicControl*)textctrl->GetPeer())->m_macTXNvars ;
2248 /* if kControlFocusPrevPart and kControlFocusNextPart are received when the user is
2249 tabbing forwards (or shift tabbing backwards) through the items in the dialog,
2250 and kControlFocusNextPart will be received. When the user clicks in our field
2251 and it is not the current focus, then the constant kUserClickedToFocusPart will
2252 be received. The constant kControlFocusNoPart will be received when our control
2253 is the current focus and the user clicks in another control. In your focus routine,
2254 you should respond to these codes as follows:
2255
2256 kControlFocusNoPart - turn off focus and return kControlFocusNoPart. redraw
2257 the control and the focus rectangle as necessary.
2258
2259 kControlFocusPrevPart or kControlFocusNextPart - toggle focus on or off
2260 depending on its current state. redraw the control and the focus rectangle
2261 as appropriate for the new focus state. If the focus state is 'off', return the constant
2262 kControlFocusNoPart, otherwise return a non-zero part code.
2263 kUserClickedToFocusPart - is a constant defined for this example. You should
2264 define your own value for handling click-to-focus type events. */
2265 /* calculate the next highlight state */
2266 switch (action) {
2267 default:
2268 case kControlFocusNoPart:
2269 TPFocusPaneText(varsp, false);
2270 focusResult = kControlFocusNoPart;
2271 break;
2272 case kUserClickedToFocusPart:
2273 TPFocusPaneText(varsp, true);
2274 focusResult = 1;
2275 break;
2276 case kControlFocusPrevPart:
2277 case kControlFocusNextPart:
2278 TPFocusPaneText(varsp, ( ! varsp->fInFocus));
2279 focusResult = varsp->fInFocus ? 1 : kControlFocusNoPart;
2280 break;
2281 }
2282 TPActivatePaneText(varsp, varsp->fIsActive && varsp->fInFocus);
2283 /* redraw the text fram and focus rectangle to indicate the
2284 new focus state */
2285 if ( textctrl->MacIsReallyShown() )
2286 {
2287 wxMacWindowClipper c( textctrl ) ;
2288 if ( !varsp->fNoBorders )
2289 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
2290 TPRedrawFocusOutline( varsp ) ;
2291 }
2292 return focusResult;
2293 }
2294
2295 wxMacMLTEClassicControl::wxMacMLTEClassicControl( wxWindow *wxPeer,
2296 const wxString& str,
2297 const wxPoint& pos,
2298 const wxSize& size, long style )
2299 {
2300 m_font = wxPeer->GetFont() ;
2301 m_windowStyle = style ;
2302 Rect bounds = wxMacGetBoundsForControl( wxPeer , pos , size ) ;
2303 wxString st = str ;
2304 wxMacConvertNewlines13To10( &st ) ;
2305
2306 wxMacConvertNewlines13To10( &st ) ;
2307
2308 short featurSet;
2309
2310 featurSet = kControlSupportsEmbedding | kControlSupportsFocus | kControlWantsIdle
2311 | kControlWantsActivate | kControlHandlesTracking | kControlHasSpecialBackground
2312 | kControlGetsFocusOnClick | kControlSupportsLiveFeedback;
2313 /* create the control */
2314
2315 verify_noerr( ::CreateUserPaneControl( MAC_WXHWND(wxPeer->GetParent()->MacGetTopLevelWindowRef()), &bounds, featurSet, &m_controlRef ) );
2316
2317 {
2318 // wxMacWindowClipper c(wxPeer) ;
2319 DoCreate();
2320 }
2321
2322 if ( wxPeer->MacIsReallyShown() )
2323 MLTESetObjectVisibility( (STPTextPaneVars*) m_macTXNvars, true , style ) ;
2324
2325 {
2326 // wxMacWindowClipper clipper( wxPeer ) ;
2327
2328 TPUpdateVisibility( m_controlRef ) ;
2329
2330 SetTXNData( st , kTXNStartOffset, kTXNEndOffset ) ;
2331
2332 TXNSetSelection( m_txn, 0, 0);
2333 TXNShowSelection( m_txn, kTXNShowStart);
2334 }
2335
2336 AdjustCreationAttributes( *wxWHITE , true ) ;
2337 }
2338
2339 wxMacMLTEClassicControl::~wxMacMLTEClassicControl()
2340 {
2341 // SetControlReference(m_controlRef , 0) ;
2342 TXNDeleteObject(m_txn);
2343 free(m_macTXNvars);
2344 }
2345
2346 void wxMacMLTEClassicControl::VisibilityChanged(bool shown)
2347 {
2348 MLTESetObjectVisibility((STPTextPaneVars*) m_macTXNvars , shown , m_windowStyle ) ;
2349 if ( !shown )
2350 InvalWindowRect( GetControlOwner( m_controlRef ) , &((STPTextPaneVars *)m_macTXNvars)->fRBounds ) ;
2351 }
2352
2353 OSStatus wxMacMLTEClassicControl::DoCreate()
2354 {
2355 Rect bounds;
2356 WindowRef theWindow;
2357
2358 OSStatus err = noErr ;
2359
2360 /* set up our globals */
2361 if (gTPDrawProc == NULL) gTPDrawProc = NewControlUserPaneDrawUPP(TPPaneDrawProc);
2362 if (gTPHitProc == NULL) gTPHitProc = NewControlUserPaneHitTestUPP(TPPaneHitTestProc);
2363 if (gTPTrackProc == NULL) gTPTrackProc = NewControlUserPaneTrackingUPP(TPPaneTrackingProc);
2364 if (gTPIdleProc == NULL) gTPIdleProc = NewControlUserPaneIdleUPP(TPPaneIdleProc);
2365 if (gTPKeyProc == NULL) gTPKeyProc = NewControlUserPaneKeyDownUPP(TPPaneKeyDownProc);
2366 if (gTPActivateProc == NULL) gTPActivateProc = NewControlUserPaneActivateUPP(TPPaneActivateProc);
2367 if (gTPFocusProc == NULL) gTPFocusProc = NewControlUserPaneFocusUPP(TPPaneFocusProc);
2368
2369 /* allocate our private storage */
2370 m_macTXNvars = (STPTextPaneVars *) malloc(sizeof(STPTextPaneVars));
2371
2372 /* set the initial settings for our private data */
2373 m_macTXNvars->fMultiline = m_windowStyle & wxTE_MULTILINE ;
2374 m_macTXNvars->fNoBorders = m_windowStyle & wxNO_BORDER ;
2375 m_macTXNvars->fInFocus = false;
2376 m_macTXNvars->fIsActive = true;
2377 m_macTXNvars->fTXNObjectActive = false;
2378 m_macTXNvars->fFocusDrawState = false ;
2379 m_macTXNvars->fUserPaneRec = m_controlRef ;
2380 m_macTXNvars->fVisible = true ;
2381
2382 theWindow = m_macTXNvars->fOwner = GetControlOwner(m_controlRef);
2383
2384 m_macTXNvars->fDrawingEnvironment = (GrafPtr) GetWindowPort(theWindow);
2385
2386 /* set up the user pane procedures */
2387 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneDrawProcTag, sizeof(gTPDrawProc), &gTPDrawProc);
2388 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneHitTestProcTag, sizeof(gTPHitProc), &gTPHitProc);
2389 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneTrackingProcTag, sizeof(gTPTrackProc), &gTPTrackProc);
2390 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneIdleProcTag, sizeof(gTPIdleProc), &gTPIdleProc);
2391 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneKeyDownProcTag, sizeof(gTPKeyProc), &gTPKeyProc);
2392 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneActivateProcTag, sizeof(gTPActivateProc), &gTPActivateProc);
2393 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneFocusProcTag, sizeof(gTPFocusProc), &gTPFocusProc);
2394
2395 /* calculate the rectangles used by the control */
2396 UMAGetControlBoundsInWindowCoords(m_controlRef, &bounds);
2397 m_macTXNvars->fRTextOutlineRegion = NewRgn() ;
2398 TPCalculateBounds( m_macTXNvars , bounds ) ;
2399
2400 /* set up the drawing environment */
2401 SetPort(m_macTXNvars->fDrawingEnvironment);
2402
2403 /* create the new edit field */
2404
2405 TXNFrameOptions frameOptions = FrameOptionsFromWXStyle( m_windowStyle ) ;
2406
2407 verify_noerr(TXNNewObject(NULL, m_macTXNvars->fOwner, &m_macTXNvars->fRTextArea,
2408 frameOptions ,
2409 kTXNTextEditStyleFrameType,
2410 kTXNTextensionFile,
2411 kTXNSystemDefaultEncoding,
2412 &m_macTXNvars->fTXNRec, &m_macTXNvars->fTXNFrame, (TXNObjectRefcon) m_macTXNvars));
2413 m_txn = m_macTXNvars->fTXNRec ;
2414
2415 /* perform final activations and setup for our text field. Here,
2416 we assume that the window is going to be the 'active' window. */
2417 TPActivatePaneText(m_macTXNvars, m_macTXNvars->fIsActive && m_macTXNvars->fInFocus);
2418 /* all done */
2419 return err;
2420 }
2421
2422
2423 #endif
2424
2425 // ----------------------------------------------------------------------------
2426 // MLTE control implementation (OSX part)
2427 // ----------------------------------------------------------------------------
2428
2429 #if TARGET_API_MAC_OSX
2430
2431 wxMacMLTEHIViewControl::wxMacMLTEHIViewControl( wxWindow *wxPeer,
2432 const wxString& str,
2433 const wxPoint& pos,
2434 const wxSize& size, long style )
2435 {
2436 m_font = wxPeer->GetFont() ;
2437 m_windowStyle = style ;
2438 Rect bounds = wxMacGetBoundsForControl( wxPeer , pos , size ) ;
2439 wxString st = str ;
2440 wxMacConvertNewlines13To10( &st ) ;
2441
2442 HIRect hr = { bounds.left , bounds.top , bounds.right - bounds.left , bounds.bottom- bounds.top } ;
2443
2444 m_scrollView = NULL ;
2445 TXNFrameOptions frameOptions = FrameOptionsFromWXStyle( style ) ;
2446 if ( frameOptions & (kTXNWantVScrollBarMask|kTXNWantHScrollBarMask) )
2447 {
2448 HIScrollViewCreate(( frameOptions & kTXNWantHScrollBarMask ? kHIScrollViewOptionsHorizScroll : 0) |
2449 ( frameOptions & kTXNWantVScrollBarMask ? kHIScrollViewOptionsVertScroll: 0 ) , &m_scrollView ) ;
2450
2451 HIViewSetFrame( m_scrollView, &hr );
2452 HIViewSetVisible( m_scrollView, true );
2453 }
2454
2455 m_textView = NULL ;
2456 HITextViewCreate( NULL , 0, frameOptions , &m_textView ) ;
2457 m_txn = HITextViewGetTXNObject( m_textView) ;
2458 HIViewSetVisible( m_textView , true ) ;
2459 if ( m_scrollView )
2460 {
2461 HIViewAddSubview( m_scrollView , m_textView ) ;
2462 m_controlRef = m_scrollView ;
2463 wxPeer->MacInstallEventHandler( (WXWidget) m_textView ) ;
2464 }
2465 else
2466 {
2467 HIViewSetFrame( m_textView, &hr );
2468 m_controlRef = m_textView ;
2469 }
2470
2471
2472 SetTXNData( st , kTXNStartOffset, kTXNEndOffset ) ;
2473
2474 TXNSetSelection( m_txn, 0, 0);
2475 TXNShowSelection( m_txn, kTXNShowStart);
2476
2477 AdjustCreationAttributes( *wxWHITE , true ) ;
2478 }
2479
2480 OSStatus wxMacMLTEHIViewControl::SetFocus( ControlFocusPart focusPart )
2481 {
2482 return SetKeyboardFocus( GetControlOwner( m_textView ) ,
2483 m_textView , focusPart ) ;
2484 }
2485
2486 bool wxMacMLTEHIViewControl::HasFocus() const
2487 {
2488 ControlRef control ;
2489 GetKeyboardFocus( GetUserFocusWindow() , &control ) ;
2490 return control == m_textView ;
2491 }
2492
2493 bool wxMacMLTEHIViewControl::NeedsFocusRect() const
2494 {
2495 return true ;
2496 }
2497
2498 #endif
2499
2500 #endif // wxUSE_TEXTCTRL