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