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