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