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