cleanup - reformat
[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 #include "wx/wxprec.h"
13
14 #if wxUSE_TEXTCTRL
15
16
17 #ifdef __DARWIN__
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #else
21 #include <stat.h>
22 #endif
23
24 #include "wx/msgdlg.h"
25
26 #if wxUSE_STD_IOSTREAM
27 #if wxUSE_IOSTREAMH
28 #include <fstream.h>
29 #else
30 #include <fstream>
31 #endif
32 #endif
33
34 #include "wx/app.h"
35 #include "wx/dc.h"
36 #include "wx/button.h"
37 #include "wx/toplevel.h"
38 #include "wx/textctrl.h"
39 #include "wx/settings.h"
40 #include "wx/filefn.h"
41 #include "wx/utils.h"
42 #include "wx/sysopt.h"
43 #include "wx/menu.h"
44 #include "wx/intl.h"
45
46 #if defined(__BORLANDC__) && !defined(__WIN32__)
47 #include <alloc.h>
48 #elif !defined(__MWERKS__) && !defined(__GNUWIN32) && !defined(__DARWIN__)
49 #include <malloc.h>
50 #endif
51
52 #ifndef __DARWIN__
53 #include <Scrap.h>
54 #endif
55
56 #ifndef __DARWIN__
57 #include <MacTextEditor.h>
58 #include <ATSUnicode.h>
59 #include <TextCommon.h>
60 #include <TextEncodingConverter.h>
61 #endif
62
63 #include "wx/mac/uma.h"
64
65
66 // if this is set to 1 then under OSX 10.2 the 'classic' MLTE implementation will be used
67 // if set to 0 then the unicode textctrl will be used
68 #ifndef wxMAC_AWAYS_USE_MLTE
69 #define wxMAC_AWAYS_USE_MLTE 1
70 #endif
71
72 #ifndef __WXMAC_OSX__
73 enum
74 {
75 kTXNVisibilityTag = 'visb' // set the visibility state of the object
76 };
77 #endif
78
79
80 class wxMacFunctor
81 {
82 public :
83 wxMacFunctor() {}
84 virtual ~wxMacFunctor() {}
85
86 virtual void* operator()() = 0 ;
87
88 static void* CallBackProc(void *param)
89 {
90 wxMacFunctor* f = (wxMacFunctor*) param ;
91 void *result = (*f)() ;
92 return result ;
93 }
94 } ;
95
96 template<typename classtype, typename param1type>
97
98 class wxMacObjectFunctor1 : public wxMacFunctor
99 {
100 typedef void (classtype::*function)( param1type p1 ) ;
101 typedef void (classtype::*ref_function)( const param1type& p1 ) ;
102 public :
103 wxMacObjectFunctor1( classtype *obj , function f , param1type p1 ) :
104 wxMacFunctor()
105 {
106 m_object = obj ;
107 m_function = f ;
108 m_param1 = p1 ;
109 }
110
111 wxMacObjectFunctor1( classtype *obj , ref_function f , param1type p1 ) :
112 wxMacFunctor()
113 {
114 m_object = obj ;
115 m_refFunction = f ;
116 m_param1 = p1 ;
117 }
118
119 ~wxMacObjectFunctor1() {}
120
121 virtual void* operator()()
122 {
123 (m_object->*m_function)(m_param1) ;
124 return NULL ;
125 }
126
127 private :
128 classtype* m_object ;
129 param1type m_param1 ;
130 union
131 {
132 function m_function ;
133 ref_function m_refFunction ;
134 } ;
135 } ;
136
137 template<typename classtype, typename param1type>
138 void* wxMacMPRemoteCall( classtype *object , void (classtype::*function)( param1type p1 ) , param1type p1 )
139 {
140 wxMacObjectFunctor1<classtype, param1type> params(object, function, p1) ;
141 void *result =
142 MPRemoteCall( wxMacFunctor::CallBackProc , &params , kMPOwningProcessRemoteContext ) ;
143 return result ;
144 }
145
146 template<typename classtype, typename param1type>
147 void* wxMacMPRemoteCall( classtype *object , void (classtype::*function)( const param1type& p1 ) , param1type p1 )
148 {
149 wxMacObjectFunctor1<classtype,param1type> params(object, function, p1) ;
150 void *result =
151 MPRemoteCall( wxMacFunctor::CallBackProc , &params , kMPOwningProcessRemoteContext ) ;
152 return result ;
153 }
154
155 template<typename classtype, typename param1type>
156 void* wxMacMPRemoteGUICall( classtype *object , void (classtype::*function)( param1type p1 ) , param1type p1 )
157 {
158 wxMutexGuiLeave() ;
159 void *result = wxMacMPRemoteCall( object , function , p1 ) ;
160 wxMutexGuiEnter() ;
161 return result ;
162 }
163
164 template<typename classtype, typename param1type>
165 void* wxMacMPRemoteGUICall( classtype *object , void (classtype::*function)( const param1type& p1 ) , param1type p1 )
166 {
167 wxMutexGuiLeave() ;
168 void *result = wxMacMPRemoteCall( object , function , p1 ) ;
169 wxMutexGuiEnter() ;
170 return result ;
171 }
172
173 // common interface for all implementations
174 class wxMacTextControl : public wxMacControl
175 {
176 public :
177 wxMacTextControl( wxTextCtrl *peer ) ;
178 ~wxMacTextControl() ;
179
180 virtual wxString GetStringValue() const = 0 ;
181 virtual void SetStringValue( const wxString &val ) = 0 ;
182 virtual void SetStyle(long start, long end, const wxTextAttr& style) ;
183 virtual void Copy() ;
184 virtual void Cut() ;
185 virtual void Paste() ;
186 virtual bool CanPaste() const ;
187 virtual void SetEditable(bool editable) ;
188 virtual wxTextPos GetLastPosition() const ;
189 virtual void Replace( long from , long to , const wxString &str ) ;
190 virtual void Remove( long from , long to ) ;
191 virtual void SetSelection( long from , long to ) = 0 ;
192 virtual void GetSelection( long* from, long* to) const = 0 ;
193 virtual void WriteText(const wxString& str) = 0 ;
194
195 virtual bool HasOwnContextMenu() const
196 { return false ; }
197
198 virtual bool SetupCursor( const wxPoint& pt )
199 { return false ; }
200
201 virtual void Clear() ;
202 virtual bool CanUndo() const;
203 virtual void Undo() ;
204 virtual bool CanRedo() const;
205 virtual void Redo() ;
206 virtual int GetNumberOfLines() const ;
207 virtual long XYToPosition(long x, long y) const;
208 virtual bool PositionToXY(long pos, long *x, long *y) const ;
209 virtual void ShowPosition( long WXUNUSED(pos) ) ;
210 virtual int GetLineLength(long lineNo) const ;
211 virtual wxString GetLineText(long lineNo) const ;
212
213 #ifndef __WXMAC_OSX__
214 virtual void MacControlUserPaneDrawProc(wxInt16 part) = 0 ;
215 virtual wxInt16 MacControlUserPaneHitTestProc(wxInt16 x, wxInt16 y) = 0 ;
216 virtual wxInt16 MacControlUserPaneTrackingProc(wxInt16 x, wxInt16 y, void* actionProc) = 0 ;
217 virtual void MacControlUserPaneIdleProc() = 0 ;
218 virtual wxInt16 MacControlUserPaneKeyDownProc(wxInt16 keyCode, wxInt16 charCode, wxInt16 modifiers) = 0 ;
219 virtual void MacControlUserPaneActivateProc(bool activating) = 0 ;
220 virtual wxInt16 MacControlUserPaneFocusProc(wxInt16 action) = 0 ;
221 virtual void MacControlUserPaneBackgroundProc(void* info) = 0 ;
222 #endif
223 } ;
224
225 // common parts for implementations based on MLTE
226
227 class wxMacMLTEControl : public wxMacTextControl
228 {
229 public :
230 wxMacMLTEControl( wxTextCtrl *peer ) ;
231 virtual wxString GetStringValue() const ;
232 virtual void SetStringValue( const wxString &str) ;
233
234 static TXNFrameOptions FrameOptionsFromWXStyle( long wxStyle ) ;
235
236 void AdjustCreationAttributes( const wxColour& background , bool visible ) ;
237
238 virtual void SetFont( const wxFont & font , const wxColour& foreground , long windowStyle ) ;
239 virtual void SetBackground( const wxBrush &brush) ;
240 virtual void SetStyle(long start, long end, const wxTextAttr& style) ;
241 virtual void Copy() ;
242 virtual void Cut() ;
243 virtual void Paste() ;
244 virtual bool CanPaste() const ;
245 virtual void SetEditable(bool editable) ;
246 virtual wxTextPos GetLastPosition() const ;
247 virtual void Replace( long from , long to , const wxString &str ) ;
248 virtual void Remove( long from , long to ) ;
249 virtual void GetSelection( long* from, long* to) const ;
250 virtual void SetSelection( long from , long to ) ;
251
252 virtual void WriteText(const wxString& str) ;
253
254 virtual bool HasOwnContextMenu() const
255 {
256 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
257 if ( UMAGetSystemVersion() >= 0x1040 )
258 {
259 TXNCommandEventSupportOptions options ;
260 TXNGetCommandEventSupport( m_txn , & options ) ;
261 return options & kTXNSupportEditCommandProcessing ;
262 }
263 #endif
264
265 return false ;
266 }
267
268 virtual void Clear() ;
269
270 virtual bool CanUndo() const ;
271 virtual void Undo() ;
272 virtual bool CanRedo() const;
273 virtual void Redo() ;
274 virtual int GetNumberOfLines() const ;
275 virtual long XYToPosition(long x, long y) const ;
276 virtual bool PositionToXY(long pos, long *x, long *y) const ;
277 virtual void ShowPosition( long pos ) ;
278 virtual int GetLineLength(long lineNo) const ;
279 virtual wxString GetLineText(long lineNo) const ;
280
281 void SetTXNData( const wxString& st , TXNOffset start , TXNOffset end ) ;
282
283 protected :
284 void TXNSetAttribute( const wxTextAttr& style , long from , long to ) ;
285
286 TXNObject m_txn ;
287 } ;
288
289 #if TARGET_API_MAC_OSX
290
291 // implementation available under OSX
292
293 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
294
295 class wxMacMLTEHIViewControl : public wxMacMLTEControl
296 {
297 public :
298 wxMacMLTEHIViewControl( wxTextCtrl *wxPeer,
299 const wxString& str,
300 const wxPoint& pos,
301 const wxSize& size, long style ) ;
302 virtual OSStatus SetFocus( ControlFocusPart focusPart ) ;
303 virtual bool HasFocus() const ;
304 virtual void SetBackground( const wxBrush &brush) ;
305
306 protected :
307 HIViewRef m_scrollView ;
308 HIViewRef m_textView ;
309 };
310
311 #endif
312
313 class wxMacUnicodeTextControl : public wxMacTextControl
314 {
315 public :
316 wxMacUnicodeTextControl( wxTextCtrl *wxPeer,
317 const wxString& str,
318 const wxPoint& pos,
319 const wxSize& size, long style ) ;
320 ~wxMacUnicodeTextControl();
321
322 virtual void VisibilityChanged(bool shown);
323 virtual wxString GetStringValue() const ;
324 virtual void SetStringValue( const wxString &str) ;
325 virtual void Copy();
326 virtual void Cut();
327 virtual void Paste();
328 virtual bool CanPaste() const;
329 virtual void SetEditable(bool editable) ;
330 virtual void GetSelection( long* from, long* to) const ;
331 virtual void SetSelection( long from , long to ) ;
332 virtual void WriteText(const wxString& str) ;
333
334 protected :
335 // contains the tag for the content (is different for password and non-password controls)
336 OSType m_valueTag ;
337 };
338
339 #endif
340
341 // 'classic' MLTE implementation
342
343 class wxMacMLTEClassicControl : public wxMacMLTEControl
344 {
345 public :
346 wxMacMLTEClassicControl( wxTextCtrl *wxPeer,
347 const wxString& str,
348 const wxPoint& pos,
349 const wxSize& size, long style ) ;
350 ~wxMacMLTEClassicControl() ;
351 virtual void VisibilityChanged(bool shown) ;
352 virtual void SuperChangedPosition() ;
353
354 virtual void MacControlUserPaneDrawProc(wxInt16 part) ;
355 virtual wxInt16 MacControlUserPaneHitTestProc(wxInt16 x, wxInt16 y) ;
356 virtual wxInt16 MacControlUserPaneTrackingProc(wxInt16 x, wxInt16 y, void* actionProc) ;
357 virtual void MacControlUserPaneIdleProc() ;
358 virtual wxInt16 MacControlUserPaneKeyDownProc(wxInt16 keyCode, wxInt16 charCode, wxInt16 modifiers) ;
359 virtual void MacControlUserPaneActivateProc(bool activating) ;
360 virtual wxInt16 MacControlUserPaneFocusProc(wxInt16 action) ;
361 virtual void MacControlUserPaneBackgroundProc(void* info) ;
362
363 virtual bool SetupCursor( const wxPoint& WXUNUSED(pt) ) { MacControlUserPaneIdleProc() ; return true ;}
364
365 virtual void SetRect( Rect *r ) ;
366
367 protected :
368 OSStatus DoCreate();
369
370 void MacUpdatePosition() ;
371 void MacActivatePaneText(bool setActive) ;
372 void MacFocusPaneText(bool setFocus) ;
373 void MacSetObjectVisibility(bool vis) ;
374
375 private :
376 TXNFrameID m_txnFrameID ;
377 GrafPtr m_txnPort ;
378 WindowRef m_txnWindow ;
379 // bounds of the control as we last did set the txn frames
380 Rect m_txnControlBounds ;
381 Rect m_txnVisBounds ;
382
383 #ifdef __WXMAC_OSX__
384 static pascal void TXNScrollActionProc( ControlRef controlRef , ControlPartCode partCode ) ;
385 static pascal void TXNScrollInfoProc(
386 SInt32 iValue, SInt32 iMaximumValue,
387 TXNScrollBarOrientation iScrollBarOrientation, SInt32 iRefCon ) ;
388
389 ControlRef m_sbHorizontal ;
390 SInt32 m_lastHorizontalValue ;
391 ControlRef m_sbVertical ;
392 SInt32 m_lastVerticalValue ;
393 #endif
394 };
395
396 #define TE_UNLIMITED_LENGTH 0xFFFFFFFFUL
397
398
399 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
400
401 BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
402 EVT_ERASE_BACKGROUND( wxTextCtrl::OnEraseBackground )
403 EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
404 EVT_CHAR(wxTextCtrl::OnChar)
405 EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
406 EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
407 EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
408 EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
409 EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
410 EVT_MENU(wxID_CLEAR, wxTextCtrl::OnDelete)
411 EVT_MENU(wxID_SELECTALL, wxTextCtrl::OnSelectAll)
412
413 EVT_CONTEXT_MENU(wxTextCtrl::OnContextMenu)
414
415 EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
416 EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
417 EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
418 EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
419 EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
420 EVT_UPDATE_UI(wxID_CLEAR, wxTextCtrl::OnUpdateDelete)
421 EVT_UPDATE_UI(wxID_SELECTALL, wxTextCtrl::OnUpdateSelectAll)
422 END_EVENT_TABLE()
423
424
425 // Text item
426 void wxTextCtrl::Init()
427 {
428 m_editable = true ;
429 m_dirty = false;
430
431 m_privateContextMenu = NULL;
432
433 m_maxLength = TE_UNLIMITED_LENGTH ;
434 }
435
436 wxTextCtrl::~wxTextCtrl()
437 {
438 delete m_privateContextMenu;
439 }
440
441 bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
442 const wxString& str,
443 const wxPoint& pos,
444 const wxSize& size, long style,
445 const wxValidator& validator,
446 const wxString& name)
447 {
448 m_macIsUserPane = false ;
449 m_editable = true ;
450
451 if ( ! ( style & wxNO_BORDER) )
452 style = ( style & ~wxBORDER_MASK) | wxSUNKEN_BORDER ;
453
454 if ( !wxTextCtrlBase::Create(parent, id, pos, size, style & ~(wxHSCROLL|wxVSCROLL), validator, name) )
455 return false;
456
457 if ( m_windowStyle & wxTE_MULTILINE )
458 {
459 wxASSERT_MSG( !(m_windowStyle & wxTE_PROCESS_ENTER),
460 wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") );
461
462 m_windowStyle |= wxTE_PROCESS_ENTER;
463 style |= wxTE_PROCESS_ENTER ;
464 }
465
466 bool forceMLTE = false ;
467
468 #if wxUSE_SYSTEM_OPTIONS
469 if ( (wxSystemOptions::HasOption(wxMAC_TEXTCONTROL_USE_MLTE) ) && ( wxSystemOptions::GetOptionInt( wxMAC_TEXTCONTROL_USE_MLTE ) == 1) )
470 {
471 forceMLTE = true ;
472 }
473 #endif
474
475 #ifdef __WXMAC_OSX__
476 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
477 if ( UMAGetSystemVersion() >= 0x1030 && forceMLTE == false )
478 {
479 if ( m_windowStyle & wxTE_MULTILINE )
480 m_peer = new wxMacMLTEHIViewControl( this , str , pos , size , style ) ;
481 }
482 #endif
483
484 if ( !m_peer )
485 {
486 if ( !(m_windowStyle & wxTE_MULTILINE) && forceMLTE == false )
487 m_peer = new wxMacUnicodeTextControl( this , str , pos , size , style ) ;
488 }
489 #endif
490
491 if ( !m_peer )
492 {
493 m_peer = new wxMacMLTEClassicControl( this , str , pos , size , style ) ;
494 }
495
496 MacPostControlCreate(pos,size) ;
497
498 // only now the embedding is correct and we can do a positioning update
499
500 MacSuperChangedPosition() ;
501
502 if ( m_windowStyle & wxTE_READONLY)
503 SetEditable( false ) ;
504
505 SetCursor( wxCursor( wxCURSOR_IBEAM ) ) ;
506
507 return true;
508 }
509
510 void wxTextCtrl::MacSuperChangedPosition()
511 {
512 wxWindow::MacSuperChangedPosition() ;
513 GetPeer()->SuperChangedPosition() ;
514 }
515
516 void wxTextCtrl::MacVisibilityChanged()
517 {
518 GetPeer()->VisibilityChanged( MacIsReallyShown() ) ;
519 }
520
521 void wxTextCtrl::MacEnabledStateChanged()
522 {
523 }
524
525 wxString wxTextCtrl::GetValue() const
526 {
527 return GetPeer()->GetStringValue() ;
528 }
529
530 void wxTextCtrl::GetSelection(long* from, long* to) const
531 {
532 GetPeer()->GetSelection( from , to ) ;
533 }
534
535 void wxTextCtrl::SetValue(const wxString& str)
536 {
537 // optimize redraws
538 if ( GetValue() == str )
539 return ;
540
541 GetPeer()->SetStringValue(str) ;
542
543 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
544 event.SetString( GetValue() ) ;
545 event.SetEventObject( this );
546 GetEventHandler()->ProcessEvent(event);
547 }
548
549 void wxTextCtrl::SetMaxLength(unsigned long len)
550 {
551 m_maxLength = len ;
552 }
553
554 bool wxTextCtrl::SetFont( const wxFont& font )
555 {
556 if ( !wxTextCtrlBase::SetFont( font ) )
557 return false ;
558
559 GetPeer()->SetFont( font , GetForegroundColour() , GetWindowStyle() ) ;
560
561 return true ;
562 }
563
564 bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
565 {
566 GetPeer()->SetStyle( start , end , style ) ;
567
568 return true ;
569 }
570
571 bool wxTextCtrl::SetDefaultStyle(const wxTextAttr& style)
572 {
573 wxTextCtrlBase::SetDefaultStyle( style ) ;
574 SetStyle( kTXNUseCurrentSelection , kTXNUseCurrentSelection , GetDefaultStyle() ) ;
575
576 return true ;
577 }
578
579 // Clipboard operations
580
581 void wxTextCtrl::Copy()
582 {
583 if (CanCopy())
584 GetPeer()->Copy() ;
585 }
586
587 void wxTextCtrl::Cut()
588 {
589 if (CanCut())
590 {
591 GetPeer()->Cut() ;
592
593 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
594 event.SetEventObject( this );
595 GetEventHandler()->ProcessEvent(event);
596 }
597 }
598
599 void wxTextCtrl::Paste()
600 {
601 if (CanPaste())
602 {
603 GetPeer()->Paste() ;
604
605 // TODO: eventually we should add setting the default style again
606
607 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
608 event.SetEventObject( this );
609 GetEventHandler()->ProcessEvent(event);
610 }
611 }
612
613 bool wxTextCtrl::CanCopy() const
614 {
615 // Can copy if there's a selection
616 long from, to;
617 GetSelection(& from, & to);
618 return (from != to);
619 }
620
621 bool wxTextCtrl::CanCut() const
622 {
623 if ( !IsEditable() )
624 return false ;
625
626 // Can cut if there's a selection
627 long from, to;
628 GetSelection(& from, & to);
629 return (from != to);
630 }
631
632 bool wxTextCtrl::CanPaste() const
633 {
634 if (!IsEditable())
635 return false;
636
637 return GetPeer()->CanPaste() ;
638 }
639
640 void wxTextCtrl::SetEditable(bool editable)
641 {
642 if ( editable != m_editable )
643 {
644 m_editable = editable ;
645 GetPeer()->SetEditable( editable ) ;
646 }
647 }
648
649 void wxTextCtrl::SetInsertionPoint(long pos)
650 {
651 SetSelection( pos , pos ) ;
652 }
653
654 void wxTextCtrl::SetInsertionPointEnd()
655 {
656 wxTextPos pos = GetLastPosition();
657 SetInsertionPoint(pos);
658 }
659
660 long wxTextCtrl::GetInsertionPoint() const
661 {
662 long begin,end ;
663 GetSelection( &begin , &end ) ;
664 return begin ;
665 }
666
667 wxTextPos wxTextCtrl::GetLastPosition() const
668 {
669 return GetPeer()->GetLastPosition( ) ;
670 }
671
672 void wxTextCtrl::Replace(long from, long to, const wxString& str)
673 {
674 GetPeer()->Replace( from , to , str) ;
675 }
676
677 void wxTextCtrl::Remove(long from, long to)
678 {
679 GetPeer()->Remove( from , to ) ;
680 }
681
682 void wxTextCtrl::SetSelection(long from, long to)
683 {
684 GetPeer()->SetSelection( from , to ) ;
685 }
686
687 bool wxTextCtrl::LoadFile(const wxString& file)
688 {
689 if ( wxTextCtrlBase::LoadFile(file) )
690 return true;
691
692 return false;
693 }
694
695 void wxTextCtrl::WriteText(const wxString& str)
696 {
697 // TODO: this MPRemoting will be moved into a remoting peer proxy for any command
698 if ( !wxIsMainThread() )
699 {
700 // unfortunately CW 8 is not able to correctly deduce the template types,
701 // so we have to instantiate explicitly
702 wxMacMPRemoteGUICall<wxTextCtrl,wxString>( this , &wxTextCtrl::WriteText , str ) ;
703 return ;
704 }
705 else
706 {
707 GetPeer()->WriteText( str ) ;
708 }
709 }
710
711 void wxTextCtrl::AppendText(const wxString& text)
712 {
713 SetInsertionPointEnd();
714 WriteText(text);
715 }
716
717 void wxTextCtrl::Clear()
718 {
719 GetPeer()->Clear() ;
720 }
721
722 bool wxTextCtrl::IsModified() const
723 {
724 return m_dirty;
725 }
726
727 bool wxTextCtrl::IsEditable() const
728 {
729 return IsEnabled() && m_editable ;
730 }
731
732 bool wxTextCtrl::AcceptsFocus() const
733 {
734 // we don't want focus if we can't be edited
735 return /*IsEditable() && */ wxControl::AcceptsFocus();
736 }
737
738 wxSize wxTextCtrl::DoGetBestSize() const
739 {
740 int wText = 100 ;
741
742 int hText;
743
744 // these are the numbers from the HIG:
745 // we reduce them by the borders first
746
747 switch ( m_windowVariant )
748 {
749 case wxWINDOW_VARIANT_NORMAL :
750 hText = 22 - 6 ;
751 break ;
752
753 case wxWINDOW_VARIANT_SMALL :
754 hText = 19 - 6 ;
755 break ;
756
757 case wxWINDOW_VARIANT_MINI :
758 hText= 15 - 6 ;
759 break ;
760
761 default :
762 hText = 22 - 6;
763 break ;
764 }
765
766 // as the above numbers have some free space around the text
767 // we get 5 lines like this anyway
768 if ( m_windowStyle & wxTE_MULTILINE )
769 hText *= 5 ;
770
771 if ( !HasFlag(wxNO_BORDER) )
772 hText += 6 ;
773
774 return wxSize(wText, hText);
775 }
776
777 // ----------------------------------------------------------------------------
778 // Undo/redo
779 // ----------------------------------------------------------------------------
780
781 void wxTextCtrl::Undo()
782 {
783 if (CanUndo())
784 GetPeer()->Undo() ;
785 }
786
787 void wxTextCtrl::Redo()
788 {
789 if (CanRedo())
790 GetPeer()->Redo() ;
791 }
792
793 bool wxTextCtrl::CanUndo() const
794 {
795 if ( !IsEditable() )
796 return false ;
797
798 return GetPeer()->CanUndo() ;
799 }
800
801 bool wxTextCtrl::CanRedo() const
802 {
803 if ( !IsEditable() )
804 return false ;
805
806 return GetPeer()->CanRedo() ;
807 }
808
809 void wxTextCtrl::MarkDirty()
810 {
811 m_dirty = true;
812 }
813
814 void wxTextCtrl::DiscardEdits()
815 {
816 m_dirty = false;
817 }
818
819 int wxTextCtrl::GetNumberOfLines() const
820 {
821 return GetPeer()->GetNumberOfLines() ;
822 }
823
824 long wxTextCtrl::XYToPosition(long x, long y) const
825 {
826 return GetPeer()->XYToPosition( x , y ) ;
827 }
828
829 bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
830 {
831 return GetPeer()->PositionToXY(pos , x , y ) ;
832 }
833
834 void wxTextCtrl::ShowPosition(long pos)
835 {
836 return GetPeer()->ShowPosition(pos) ;
837 }
838
839 int wxTextCtrl::GetLineLength(long lineNo) const
840 {
841 return GetPeer()->GetLineLength(lineNo) ;
842 }
843
844 wxString wxTextCtrl::GetLineText(long lineNo) const
845 {
846 return GetPeer()->GetLineText(lineNo) ;
847 }
848
849 void wxTextCtrl::Command(wxCommandEvent & event)
850 {
851 SetValue (event.GetString());
852 ProcessCommand (event);
853 }
854
855 void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
856 {
857 // By default, load the first file into the text window.
858 if (event.GetNumberOfFiles() > 0)
859 LoadFile(event.GetFiles()[0]);
860 }
861
862 void wxTextCtrl::OnEraseBackground(wxEraseEvent& event)
863 {
864 // all erasing should be done by the real mac control implementation
865 // while this is true for MLTE under classic, the HITextView is somehow
866 // transparent but background erase is not working correctly, so intercept
867 // things while we can...
868 event.Skip() ;
869 }
870
871 void wxTextCtrl::OnChar(wxKeyEvent& event)
872 {
873 int key = event.GetKeyCode() ;
874 bool eat_key = false ;
875
876 if ( key == 'c' && event.MetaDown() )
877 {
878 if ( CanCopy() )
879 Copy() ;
880
881 return ;
882 }
883
884 if ( !IsEditable() && key != WXK_LEFT && key != WXK_RIGHT && key != WXK_DOWN && key != WXK_UP && key != WXK_TAB &&
885 !( key == WXK_RETURN && ( (m_windowStyle & wxPROCESS_ENTER) || (m_windowStyle & wxTE_MULTILINE) ) )
886 // && key != WXK_PRIOR && key != WXK_NEXT && key != WXK_HOME && key != WXK_END
887 )
888 {
889 // eat it
890 return ;
891 }
892
893 // Check if we have reached the max # of chars, but still allow navigation and deletion
894 if ( !IsMultiLine() && GetValue().Length() >= m_maxLength &&
895 key != WXK_LEFT && key != WXK_RIGHT && key != WXK_TAB &&
896 key != WXK_BACK && !( key == WXK_RETURN && (m_windowStyle & wxPROCESS_ENTER) )
897 )
898 {
899 // eat it, we don't want to add more than allowed # of characters
900 return;
901 }
902
903 // assume that any key not processed yet is going to modify the control
904 m_dirty = true;
905
906 if ( key == 'v' && event.MetaDown() )
907 {
908 if ( CanPaste() )
909 Paste() ;
910
911 return ;
912 }
913
914 if ( key == 'x' && event.MetaDown() )
915 {
916 if ( CanCut() )
917 Cut() ;
918
919 return ;
920 }
921
922 switch ( key )
923 {
924 case WXK_RETURN:
925 if (m_windowStyle & wxPROCESS_ENTER)
926 {
927 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
928 event.SetEventObject( this );
929 event.SetString( GetValue() );
930 if ( GetEventHandler()->ProcessEvent(event) )
931 return;
932 }
933
934 if ( !(m_windowStyle & wxTE_MULTILINE) )
935 {
936 wxWindow *parent = GetParent();
937 while ( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL )
938 {
939 parent = parent->GetParent() ;
940 }
941
942 if ( parent && parent->GetDefaultItem() )
943 {
944 wxButton *def = wxDynamicCast(parent->GetDefaultItem(), wxButton);
945 if ( def && def->IsEnabled() )
946 {
947 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
948 event.SetEventObject(def);
949 def->Command(event);
950
951 return ;
952 }
953 }
954
955 // this will make wxWidgets eat the ENTER key so that
956 // we actually prevent line wrapping in a single line
957 // text control
958 eat_key = true;
959 }
960 break;
961
962 case WXK_TAB:
963 if ( !(m_windowStyle & wxTE_PROCESS_TAB))
964 {
965 int flags = 0;
966 if (!event.ShiftDown())
967 flags |= wxNavigationKeyEvent::IsForward ;
968 if (event.ControlDown())
969 flags |= wxNavigationKeyEvent::WinChange ;
970 Navigate(flags);
971
972 return;
973 }
974 else
975 {
976 // This is necessary (don't know why);
977 // otherwise the tab will not be inserted.
978 WriteText(wxT("\t"));
979 }
980 break;
981
982 default:
983 break;
984 }
985
986 if (!eat_key)
987 {
988 // perform keystroke handling
989 if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL )
990 CallNextEventHandler((EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() , (EventRef) wxTheApp->MacGetCurrentEvent() ) ;
991 else
992 {
993 EventRecord rec ;
994 if ( wxMacConvertEventToRecord( (EventRef) wxTheApp->MacGetCurrentEvent() , &rec ) )
995 {
996 EventRecord *ev = &rec ;
997 short keycode ;
998 short keychar ;
999 keychar = short(ev->message & charCodeMask);
1000 keycode = short(ev->message & keyCodeMask) >> 8 ;
1001
1002 m_peer->HandleKey( keycode , keychar , ev->modifiers ) ;
1003 }
1004 }
1005 }
1006
1007 if ( ( key >= 0x20 && key < WXK_START ) ||
1008 key == WXK_RETURN ||
1009 key == WXK_DELETE ||
1010 key == WXK_BACK)
1011 {
1012 wxCommandEvent event1(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
1013 event1.SetEventObject( this );
1014 wxPostEvent(GetEventHandler(),event1);
1015 }
1016 }
1017
1018 // ----------------------------------------------------------------------------
1019 // standard handlers for standard edit menu events
1020 // ----------------------------------------------------------------------------
1021
1022 void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
1023 {
1024 Cut();
1025 }
1026
1027 void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event))
1028 {
1029 Copy();
1030 }
1031
1032 void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event))
1033 {
1034 Paste();
1035 }
1036
1037 void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event))
1038 {
1039 Undo();
1040 }
1041
1042 void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event))
1043 {
1044 Redo();
1045 }
1046
1047 void wxTextCtrl::OnDelete(wxCommandEvent& WXUNUSED(event))
1048 {
1049 long from, to;
1050 GetSelection(& from, & to);
1051 if (from != -1 && to != -1)
1052 Remove(from, to);
1053 }
1054
1055 void wxTextCtrl::OnSelectAll(wxCommandEvent& WXUNUSED(event))
1056 {
1057 SetSelection(-1, -1);
1058 }
1059
1060 void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
1061 {
1062 event.Enable( CanCut() );
1063 }
1064
1065 void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
1066 {
1067 event.Enable( CanCopy() );
1068 }
1069
1070 void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
1071 {
1072 event.Enable( CanPaste() );
1073 }
1074
1075 void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
1076 {
1077 event.Enable( CanUndo() );
1078 }
1079
1080 void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
1081 {
1082 event.Enable( CanRedo() );
1083 }
1084
1085 void wxTextCtrl::OnUpdateDelete(wxUpdateUIEvent& event)
1086 {
1087 long from, to;
1088 GetSelection(& from, & to);
1089 event.Enable(from != -1 && to != -1 && from != to && IsEditable()) ;
1090 }
1091
1092 void wxTextCtrl::OnUpdateSelectAll(wxUpdateUIEvent& event)
1093 {
1094 event.Enable(GetLastPosition() > 0);
1095 }
1096
1097 // CS: Context Menus only work with MLTE implementations or non-multiline HIViews at the moment
1098
1099 void wxTextCtrl::OnContextMenu(wxContextMenuEvent& event)
1100 {
1101 if ( GetPeer()->HasOwnContextMenu() )
1102 {
1103 event.Skip() ;
1104 return ;
1105 }
1106
1107 if (m_privateContextMenu == NULL)
1108 {
1109 m_privateContextMenu = new wxMenu;
1110 m_privateContextMenu->Append(wxID_UNDO, _("&Undo"));
1111 m_privateContextMenu->Append(wxID_REDO, _("&Redo"));
1112 m_privateContextMenu->AppendSeparator();
1113 m_privateContextMenu->Append(wxID_CUT, _("Cu&t"));
1114 m_privateContextMenu->Append(wxID_COPY, _("&Copy"));
1115 m_privateContextMenu->Append(wxID_PASTE, _("&Paste"));
1116 m_privateContextMenu->Append(wxID_CLEAR, _("&Delete"));
1117 m_privateContextMenu->AppendSeparator();
1118 m_privateContextMenu->Append(wxID_SELECTALL, _("Select &All"));
1119 }
1120
1121 if (m_privateContextMenu != NULL)
1122 PopupMenu(m_privateContextMenu);
1123 }
1124
1125 bool wxTextCtrl::MacSetupCursor( const wxPoint& pt )
1126 {
1127 if ( !GetPeer()->SetupCursor(pt) )
1128 return wxWindow::MacSetupCursor( pt ) ;
1129 else
1130 return true ;
1131 }
1132
1133 #if !TARGET_API_MAC_OSX
1134
1135 // user pane implementation
1136
1137 void wxTextCtrl::MacControlUserPaneDrawProc(wxInt16 part)
1138 {
1139 GetPeer()->MacControlUserPaneDrawProc( part ) ;
1140 }
1141
1142 wxInt16 wxTextCtrl::MacControlUserPaneHitTestProc(wxInt16 x, wxInt16 y)
1143 {
1144 return GetPeer()->MacControlUserPaneHitTestProc( x , y ) ;
1145 }
1146
1147 wxInt16 wxTextCtrl::MacControlUserPaneTrackingProc(wxInt16 x, wxInt16 y, void* actionProc)
1148 {
1149 return GetPeer()->MacControlUserPaneTrackingProc( x , y , actionProc ) ;
1150 }
1151
1152 void wxTextCtrl::MacControlUserPaneIdleProc()
1153 {
1154 GetPeer()->MacControlUserPaneIdleProc( ) ;
1155 }
1156
1157 wxInt16 wxTextCtrl::MacControlUserPaneKeyDownProc(wxInt16 keyCode, wxInt16 charCode, wxInt16 modifiers)
1158 {
1159 return GetPeer()->MacControlUserPaneKeyDownProc( keyCode , charCode , modifiers ) ;
1160 }
1161
1162 void wxTextCtrl::MacControlUserPaneActivateProc(bool activating)
1163 {
1164 GetPeer()->MacControlUserPaneActivateProc( activating ) ;
1165 }
1166
1167 wxInt16 wxTextCtrl::MacControlUserPaneFocusProc(wxInt16 action)
1168 {
1169 return GetPeer()->MacControlUserPaneFocusProc( action ) ;
1170 }
1171
1172 void wxTextCtrl::MacControlUserPaneBackgroundProc(void* info)
1173 {
1174 GetPeer()->MacControlUserPaneBackgroundProc( info ) ;
1175 }
1176
1177 #endif
1178
1179 // ----------------------------------------------------------------------------
1180 // implementation base class
1181 // ----------------------------------------------------------------------------
1182
1183 wxMacTextControl::wxMacTextControl(wxTextCtrl* peer) :
1184 wxMacControl( peer )
1185 {
1186 }
1187
1188 wxMacTextControl::~wxMacTextControl()
1189 {
1190 }
1191
1192 void wxMacTextControl::SetStyle(long start, long end, const wxTextAttr& style)
1193 {
1194 }
1195
1196 void wxMacTextControl::Copy()
1197 {
1198 }
1199
1200 void wxMacTextControl::Cut()
1201 {
1202 }
1203
1204 void wxMacTextControl::Paste()
1205 {
1206 }
1207
1208 bool wxMacTextControl::CanPaste() const
1209 {
1210 return false ;
1211 }
1212
1213 void wxMacTextControl::SetEditable(bool editable)
1214 {
1215 }
1216
1217 wxTextPos wxMacTextControl::GetLastPosition() const
1218 {
1219 return GetStringValue().Length() ;
1220 }
1221
1222 void wxMacTextControl::Replace( long from , long to , const wxString &val )
1223 {
1224 SetSelection( from , to ) ;
1225 WriteText( val ) ;
1226 }
1227
1228 void wxMacTextControl::Remove( long from , long to )
1229 {
1230 SetSelection( from , to ) ;
1231 WriteText( wxEmptyString) ;
1232 }
1233
1234 void wxMacTextControl::Clear()
1235 {
1236 SetStringValue( wxEmptyString ) ;
1237 }
1238
1239 bool wxMacTextControl::CanUndo() const
1240 {
1241 return false ;
1242 }
1243
1244 void wxMacTextControl::Undo()
1245 {
1246 }
1247
1248 bool wxMacTextControl::CanRedo() const
1249 {
1250 return false ;
1251 }
1252
1253 void wxMacTextControl::Redo()
1254 {
1255 }
1256
1257 long wxMacTextControl::XYToPosition(long x, long y) const
1258 {
1259 return 0 ;
1260 }
1261
1262 bool wxMacTextControl::PositionToXY(long pos, long *x, long *y) const
1263 {
1264 return false ;
1265 }
1266
1267 void wxMacTextControl::ShowPosition( long WXUNUSED(pos) )
1268 {
1269 }
1270
1271 int wxMacTextControl::GetNumberOfLines() const
1272 {
1273 ItemCount lines = 0 ;
1274 wxString content = GetStringValue() ;
1275 lines = 1;
1276
1277 for (size_t i = 0; i < content.Length() ; i++)
1278 {
1279 if (content[i] == '\r')
1280 lines++;
1281 }
1282
1283 return lines ;
1284 }
1285
1286 wxString wxMacTextControl::GetLineText(long lineNo) const
1287 {
1288 // TODO: change this if possible to reflect real lines
1289 wxString content = GetStringValue() ;
1290
1291 // Find line first
1292 int count = 0;
1293 for (size_t i = 0; i < content.Length() ; i++)
1294 {
1295 if (count == lineNo)
1296 {
1297 // Add chars in line then
1298 wxString tmp;
1299
1300 for (size_t j = i; j < content.Length(); j++)
1301 {
1302 if (content[j] == '\n')
1303 return tmp;
1304
1305 tmp += content[j];
1306 }
1307
1308 return tmp;
1309 }
1310
1311 if (content[i] == '\n')
1312 count++;
1313 }
1314
1315 return wxEmptyString ;
1316 }
1317
1318 int wxMacTextControl::GetLineLength(long lineNo) const
1319 {
1320 // TODO: change this if possible to reflect real lines
1321 wxString content = GetStringValue() ;
1322
1323 // Find line first
1324 int count = 0;
1325 for (size_t i = 0; i < content.Length() ; i++)
1326 {
1327 if (count == lineNo)
1328 {
1329 // Count chars in line then
1330 count = 0;
1331 for (size_t j = i; j < content.Length(); j++)
1332 {
1333 count++;
1334 if (content[j] == '\n')
1335 return count;
1336 }
1337
1338 return count;
1339 }
1340
1341 if (content[i] == '\n')
1342 count++;
1343 }
1344
1345 return 0 ;
1346 }
1347
1348 // ----------------------------------------------------------------------------
1349 // standard unicode control implementation
1350 // ----------------------------------------------------------------------------
1351
1352 #if TARGET_API_MAC_OSX
1353
1354 wxMacUnicodeTextControl::wxMacUnicodeTextControl( wxTextCtrl *wxPeer,
1355 const wxString& str,
1356 const wxPoint& pos,
1357 const wxSize& size, long style ) : wxMacTextControl( wxPeer )
1358 {
1359 m_font = wxPeer->GetFont() ;
1360 m_windowStyle = style ;
1361 Rect bounds = wxMacGetBoundsForControl( wxPeer , pos , size ) ;
1362 wxString st = str ;
1363 wxMacConvertNewlines10To13( &st ) ;
1364 wxMacCFStringHolder cf(st , m_font.GetEncoding()) ;
1365 CFStringRef cfr = cf ;
1366 Boolean isPassword = ( m_windowStyle & wxTE_PASSWORD ) != 0 ;
1367 m_valueTag = isPassword ? kControlEditTextPasswordCFStringTag : kControlEditTextCFStringTag ;
1368 CreateEditUnicodeTextControl(
1369 MAC_WXHWND(wxPeer->MacGetTopLevelWindowRef()), &bounds , cfr ,
1370 isPassword , NULL , &m_controlRef ) ;
1371
1372 if ( !(m_windowStyle & wxTE_MULTILINE) )
1373 SetData<Boolean>( kControlEditTextPart , kControlEditTextSingleLineTag , true ) ;
1374 }
1375
1376 wxMacUnicodeTextControl::~wxMacUnicodeTextControl()
1377 {
1378 }
1379
1380 void wxMacUnicodeTextControl::VisibilityChanged(bool shown)
1381 {
1382 if ( !(m_windowStyle & wxTE_MULTILINE) && shown )
1383 {
1384 // work around a refresh issue insofar as not always the entire content is shown,
1385 // even if this would be possible
1386 ControlEditTextSelectionRec sel ;
1387 CFStringRef value = NULL ;
1388
1389 verify_noerr( GetData<ControlEditTextSelectionRec>( 0, kControlEditTextSelectionTag, &sel ) );
1390 verify_noerr( GetData<CFStringRef>( 0, m_valueTag , &value ) );
1391 verify_noerr( SetData<CFStringRef>( 0, m_valueTag, &value ) );
1392 verify_noerr( SetData<ControlEditTextSelectionRec>( 0, kControlEditTextSelectionTag, &sel ) );
1393
1394 CFRelease( value ) ;
1395 }
1396 }
1397
1398 wxString wxMacUnicodeTextControl::GetStringValue() const
1399 {
1400 wxString result ;
1401 CFStringRef value = GetData<CFStringRef>(0,m_valueTag) ;
1402 if ( value )
1403 {
1404 wxMacCFStringHolder cf(value) ;
1405 result = cf.AsString() ;
1406 }
1407
1408 #if '\n' == 10
1409 wxMacConvertNewlines13To10( &result ) ;
1410 #else
1411 wxMacConvertNewlines10To13( &result ) ;
1412 #endif
1413
1414 return result ;
1415 }
1416
1417 void wxMacUnicodeTextControl::SetStringValue( const wxString &str)
1418 {
1419 wxString st = str ;
1420 wxMacConvertNewlines10To13( &st ) ;
1421 wxMacCFStringHolder cf(st , m_font.GetEncoding() ) ;
1422 verify_noerr( SetData<CFStringRef>( 0, m_valueTag , cf ) ) ;
1423 }
1424
1425 void wxMacUnicodeTextControl::Copy()
1426 {
1427 SendHICommand( kHICommandCopy ) ;
1428 }
1429
1430 void wxMacUnicodeTextControl::Cut()
1431 {
1432 SendHICommand( kHICommandCut ) ;
1433 }
1434
1435 void wxMacUnicodeTextControl::Paste()
1436 {
1437 SendHICommand( kHICommandPaste ) ;
1438 }
1439
1440 bool wxMacUnicodeTextControl::CanPaste() const
1441 {
1442 return true ;
1443 }
1444
1445 void wxMacUnicodeTextControl::SetEditable(bool editable)
1446 {
1447 SetData<Boolean>( 0 , kControlEditTextLockedTag , (Boolean) !editable ) ;
1448 }
1449
1450 void wxMacUnicodeTextControl::GetSelection( long* from, long* to) const
1451 {
1452 ControlEditTextSelectionRec sel ;
1453 verify_noerr(GetData<ControlEditTextSelectionRec>( 0, kControlEditTextSelectionTag, &sel ) ) ;
1454 if ( from ) *from = sel.selStart ;
1455 if ( to ) *to = sel.selEnd ;
1456 }
1457
1458 void wxMacUnicodeTextControl::SetSelection( long from , long to )
1459 {
1460 ControlEditTextSelectionRec sel ;
1461 if ((from == -1) && (to == -1))
1462 {
1463 from = 0 ;
1464 to = 32767 ; // sel has 16 bit signed values, max is 32767
1465 }
1466
1467 sel.selStart = from ;
1468 sel.selEnd = to ;
1469 SetData<ControlEditTextSelectionRec>( 0 , kControlEditTextSelectionTag, &sel ) ;
1470 }
1471
1472 void wxMacUnicodeTextControl::WriteText(const wxString& str)
1473 {
1474 wxString st = str ;
1475 wxMacConvertNewlines10To13( &st ) ;
1476 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
1477 wxMacCFStringHolder cf(st , m_font.GetEncoding() ) ;
1478 CFStringRef value = cf ;
1479 SetData<CFStringRef>( 0, kControlEditTextInsertCFStringRefTag, &value );
1480 #else
1481 wxString val = GetStringValue() ;
1482 long start , end ;
1483 GetSelection( &start , &end ) ;
1484 val.Remove( start , end - start ) ;
1485 val.insert( start , str ) ;
1486 SetStringValue( val ) ;
1487 SetSelection( start + str.Length() , start + str.Length() ) ;
1488 #endif
1489 }
1490
1491 #endif
1492
1493 // ----------------------------------------------------------------------------
1494 // MLTE control implementation (common part)
1495 // ----------------------------------------------------------------------------
1496
1497 // if MTLE is read only, no changes at all are allowed, not even from
1498 // procedural API, in order to allow changes via API all the same we must undo
1499 // the readonly status while we are executing, this class helps to do so
1500
1501 class wxMacEditHelper
1502 {
1503 public :
1504 wxMacEditHelper( TXNObject txn )
1505 {
1506 TXNControlTag tag[] = { kTXNIOPrivilegesTag } ;
1507 m_txn = txn ;
1508 TXNGetTXNObjectControls( m_txn , 1 , tag , m_data ) ;
1509 if ( m_data[0].uValue == kTXNReadOnly )
1510 {
1511 TXNControlData data[] = { { kTXNReadWrite } } ;
1512 TXNSetTXNObjectControls( m_txn , false , 1 , tag , data ) ;
1513 }
1514 }
1515
1516 ~wxMacEditHelper()
1517 {
1518 TXNControlTag tag[] = { kTXNIOPrivilegesTag } ;
1519 if ( m_data[0].uValue == kTXNReadOnly )
1520 TXNSetTXNObjectControls( m_txn , false , 1 , tag , m_data ) ;
1521 }
1522
1523 protected :
1524 TXNObject m_txn ;
1525 TXNControlData m_data[1] ;
1526 } ;
1527
1528 wxMacMLTEControl::wxMacMLTEControl( wxTextCtrl *peer ) : wxMacTextControl( peer )
1529 {
1530 SetNeedsFocusRect( true ) ;
1531 }
1532
1533 wxString wxMacMLTEControl::GetStringValue() const
1534 {
1535 wxString result ;
1536 OSStatus err ;
1537 Size actualSize = 0;
1538 {
1539 #if wxUSE_UNICODE
1540 Handle theText ;
1541 err = TXNGetDataEncoded( m_txn , kTXNStartOffset, kTXNEndOffset, &theText , kTXNUnicodeTextData );
1542
1543 // all done
1544 if ( err != noErr )
1545 {
1546 actualSize = 0 ;
1547 }
1548 else
1549 {
1550 actualSize = GetHandleSize( theText ) / sizeof( UniChar) ;
1551 if ( actualSize > 0 )
1552 {
1553 wxChar *ptr = NULL ;
1554
1555 #if SIZEOF_WCHAR_T == 2
1556 ptr = new wxChar[actualSize + 1 ] ;
1557 wxStrncpy( ptr , (wxChar*) *theText , actualSize ) ;
1558 #else
1559 SetHandleSize( theText , ( actualSize + 1 ) * sizeof( UniChar ) ) ;
1560 HLock( theText ) ;
1561 (((UniChar*)*theText)[actualSize]) = 0 ;
1562 wxMBConvUTF16 converter ;
1563 size_t noChars = converter.MB2WC( NULL , (const char*)*theText , 0 ) ;
1564 ptr = new wxChar[noChars + 1] ;
1565
1566 noChars = converter.MB2WC( ptr , (const char*)*theText , noChars ) ;
1567 ptr[noChars] = 0 ;
1568 HUnlock( theText ) ;
1569 #endif
1570
1571 ptr[actualSize] = 0 ;
1572 result = wxString( ptr ) ;
1573 delete[] ptr ;
1574 }
1575
1576 DisposeHandle( theText ) ;
1577 }
1578 #else
1579 Handle theText ;
1580 err = TXNGetDataEncoded( m_txn , kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData );
1581 // all done
1582 if ( err )
1583 {
1584 actualSize = 0 ;
1585 }
1586 else
1587 {
1588 actualSize = GetHandleSize( theText ) ;
1589 if ( actualSize > 0 )
1590 {
1591 HLock( theText ) ;
1592 result = wxString( *theText , wxConvLocal , actualSize ) ;
1593 HUnlock( theText ) ;
1594 }
1595
1596 DisposeHandle( theText ) ;
1597 }
1598 #endif
1599 }
1600
1601 #if '\n' == 10
1602 wxMacConvertNewlines13To10( &result ) ;
1603 #else
1604 wxMacConvertNewlines10To13( &result ) ;
1605 #endif
1606
1607 return result ;
1608 }
1609
1610 void wxMacMLTEControl::SetStringValue( const wxString &str)
1611 {
1612 wxString st = str ;
1613
1614 wxMacConvertNewlines10To13( &st ) ;
1615 {
1616 wxMacWindowClipper c( m_peer ) ;
1617 {
1618 wxMacEditHelper help(m_txn) ;
1619 SetTXNData( st , kTXNStartOffset, kTXNEndOffset ) ;
1620 }
1621 TXNSetSelection( m_txn, 0, 0 );
1622 TXNShowSelection( m_txn, kTXNShowStart );
1623 }
1624 }
1625
1626 TXNFrameOptions wxMacMLTEControl::FrameOptionsFromWXStyle( long wxStyle )
1627 {
1628 TXNFrameOptions frameOptions =
1629 kTXNDontDrawCaretWhenInactiveMask
1630 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3
1631 | kTXNDoFontSubstitutionMask
1632 #endif
1633 ;
1634
1635 if ( ! ( wxStyle & wxTE_NOHIDESEL ) )
1636 frameOptions |= kTXNDontDrawSelectionWhenInactiveMask ;
1637
1638 if ( wxStyle & wxTE_MULTILINE )
1639 {
1640 if ( ! ( wxStyle & wxTE_DONTWRAP ) )
1641 frameOptions |= kTXNAlwaysWrapAtViewEdgeMask ;
1642 else
1643 {
1644 frameOptions |= kTXNAlwaysWrapAtViewEdgeMask ;
1645 frameOptions |= kTXNWantHScrollBarMask ;
1646 }
1647
1648 if ( !(wxStyle & wxTE_NO_VSCROLL ) )
1649 {
1650 frameOptions |= kTXNWantVScrollBarMask ;
1651 if ( frameOptions & kTXNWantHScrollBarMask )
1652 frameOptions |= kTXNDrawGrowIconMask ;
1653 }
1654 }
1655 else
1656 frameOptions |= kTXNSingleLineOnlyMask ;
1657
1658 if ( wxStyle & wxHSCROLL )
1659 frameOptions |= kTXNWantHScrollBarMask ;
1660
1661 return frameOptions ;
1662 }
1663
1664 void wxMacMLTEControl::AdjustCreationAttributes( const wxColour &background, bool visible )
1665 {
1666 TXNControlTag iControlTags[] =
1667 {
1668 kTXNDoFontSubstitution,
1669 kTXNWordWrapStateTag ,
1670 };
1671 TXNControlData iControlData[] =
1672 {
1673 {true},
1674 {kTXNNoAutoWrap},
1675 };
1676
1677 int toptag = WXSIZEOF( iControlTags ) ;
1678
1679 if ( m_windowStyle & wxTE_MULTILINE )
1680 {
1681 if (m_windowStyle & wxTE_DONTWRAP)
1682 iControlData[1].uValue = kTXNNoAutoWrap ;
1683 else
1684 iControlData[1].uValue = kTXNAutoWrap ;
1685 }
1686 verify_noerr( TXNSetTXNObjectControls( m_txn, false, toptag,
1687 iControlTags, iControlData )) ;
1688
1689 // setting the default font:
1690 // under 10.2 this causes a visible caret, therefore we avoid it
1691
1692 if ( UMAGetSystemVersion() >= 0x1030 )
1693 {
1694 Str255 fontName ;
1695 SInt16 fontSize ;
1696 Style fontStyle ;
1697
1698 GetThemeFont(kThemeSystemFont , GetApplicationScript() , fontName , &fontSize , &fontStyle ) ;
1699
1700 TXNTypeAttributes typeAttr[] =
1701 {
1702 { kTXNQDFontNameAttribute , kTXNQDFontNameAttributeSize , { (void*) fontName } } ,
1703 { kTXNQDFontSizeAttribute , kTXNFontSizeAttributeSize , { (void*) (fontSize << 16) } } ,
1704 { kTXNQDFontStyleAttribute , kTXNQDFontStyleAttributeSize , { (void*) normal } } ,
1705 } ;
1706
1707 verify_noerr( TXNSetTypeAttributes (m_txn, sizeof( typeAttr ) / sizeof(TXNTypeAttributes) , typeAttr,
1708 kTXNStartOffset,
1709 kTXNEndOffset) );
1710 }
1711
1712 if ( m_windowStyle & wxTE_PASSWORD )
1713 {
1714 UniChar c = 0xA5 ;
1715 verify_noerr(TXNEchoMode( m_txn , c , 0 , true )) ;
1716 }
1717
1718 TXNBackground tback;
1719 tback.bgType = kTXNBackgroundTypeRGB;
1720 tback.bg.color = MAC_WXCOLORREF( background.GetPixel() );
1721 TXNSetBackground( m_txn , &tback);
1722
1723 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
1724 if ( UMAGetSystemVersion() >= 0x1040 )
1725 {
1726 TXNCommandEventSupportOptions options ;
1727 if ( TXNGetCommandEventSupport( m_txn, &options ) == noErr )
1728 {
1729 options |=
1730 kTXNSupportEditCommandProcessing
1731 | kTXNSupportEditCommandUpdating
1732 | kTXNSupportSpellCheckCommandProcessing
1733 | kTXNSupportSpellCheckCommandUpdating
1734 | kTXNSupportFontCommandProcessing
1735 | kTXNSupportFontCommandUpdating;
1736
1737 TXNSetCommandEventSupport( m_txn , options ) ;
1738 }
1739 }
1740 #endif
1741 }
1742
1743 void wxMacMLTEControl::SetBackground( const wxBrush &brush )
1744 {
1745 // currently only solid background are supported
1746 TXNBackground tback;
1747 tback.bgType = kTXNBackgroundTypeRGB;
1748 tback.bg.color = MAC_WXCOLORREF( brush.GetColour().GetPixel() );
1749 TXNSetBackground( m_txn , &tback);
1750 }
1751
1752 void wxMacMLTEControl::TXNSetAttribute( const wxTextAttr& style , long from , long to)
1753 {
1754 TXNTypeAttributes typeAttr[4] ;
1755 Str255 fontName = "\pMonaco" ;
1756 SInt16 fontSize = 12 ;
1757 Style fontStyle = normal ;
1758 RGBColor color ;
1759 int attrCounter = 0 ;
1760
1761 if ( style.HasFont() )
1762 {
1763 const wxFont &font = style.GetFont() ;
1764 wxMacStringToPascal( font.GetFaceName() , fontName ) ;
1765 fontSize = font.GetPointSize() ;
1766 if ( font.GetUnderlined() )
1767 fontStyle |= underline ;
1768 if ( font.GetWeight() == wxBOLD )
1769 fontStyle |= bold ;
1770 if ( font.GetStyle() == wxITALIC )
1771 fontStyle |= italic ;
1772
1773 typeAttr[attrCounter].tag = kTXNQDFontNameAttribute ;
1774 typeAttr[attrCounter].size = kTXNQDFontNameAttributeSize ;
1775 typeAttr[attrCounter].data.dataPtr = (void*) fontName ;
1776 typeAttr[attrCounter+1].tag = kTXNQDFontSizeAttribute ;
1777 typeAttr[attrCounter+1].size = kTXNFontSizeAttributeSize ;
1778 typeAttr[attrCounter+1].data.dataValue = (fontSize << 16) ;
1779 typeAttr[attrCounter+2].tag = kTXNQDFontStyleAttribute ;
1780 typeAttr[attrCounter+2].size = kTXNQDFontStyleAttributeSize ;
1781 typeAttr[attrCounter+2].data.dataValue = fontStyle ;
1782 attrCounter += 3 ;
1783 }
1784
1785 if ( style.HasTextColour() )
1786 {
1787 typeAttr[attrCounter].tag = kTXNQDFontColorAttribute ;
1788 typeAttr[attrCounter].size = kTXNQDFontColorAttributeSize ;
1789 typeAttr[attrCounter].data.dataPtr = (void*) &color ;
1790 color = MAC_WXCOLORREF(style.GetTextColour().GetPixel()) ;
1791 attrCounter += 1 ;
1792 }
1793
1794 if ( attrCounter > 0 )
1795 {
1796 verify_noerr( TXNSetTypeAttributes ( m_txn , attrCounter , typeAttr, from , to) );
1797 }
1798 }
1799
1800 void wxMacMLTEControl::SetFont( const wxFont & font , const wxColour& foreground , long windowStyle )
1801 {
1802 wxMacEditHelper help(m_txn) ;
1803 TXNSetAttribute( wxTextAttr(foreground,wxNullColour,font) , kTXNStartOffset,kTXNEndOffset ) ;
1804 }
1805
1806 void wxMacMLTEControl::SetStyle(long start, long end, const wxTextAttr& style)
1807 {
1808 wxMacEditHelper help(m_txn) ;
1809 TXNSetAttribute( style , start,end ) ;
1810 }
1811
1812 void wxMacMLTEControl::Copy()
1813 {
1814 ClearCurrentScrap();
1815 TXNCopy(m_txn);
1816 TXNConvertToPublicScrap();
1817 }
1818
1819 void wxMacMLTEControl::Cut()
1820 {
1821 ClearCurrentScrap();
1822 TXNCut(m_txn);
1823 TXNConvertToPublicScrap();
1824 }
1825
1826 void wxMacMLTEControl::Paste()
1827 {
1828 TXNConvertFromPublicScrap();
1829 TXNPaste(m_txn);
1830 }
1831
1832 bool wxMacMLTEControl::CanPaste() const
1833 {
1834 return TXNIsScrapPastable() ;
1835 }
1836
1837 void wxMacMLTEControl::SetEditable(bool editable)
1838 {
1839 TXNControlTag tag[] = { kTXNIOPrivilegesTag } ;
1840 TXNControlData data[] = { { editable ? kTXNReadWrite : kTXNReadOnly } } ;
1841 TXNSetTXNObjectControls( m_txn , false , WXSIZEOF(tag) , tag , data ) ;
1842 }
1843
1844 wxTextPos wxMacMLTEControl::GetLastPosition() const
1845 {
1846 wxTextPos actualsize = 0 ;
1847
1848 Handle theText ;
1849 OSErr err = TXNGetDataEncoded( m_txn, kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData );
1850
1851 // all done
1852 if ( err == noErr )
1853 {
1854 actualsize = GetHandleSize( theText ) ;
1855 DisposeHandle( theText ) ;
1856 }
1857 else
1858 {
1859 actualsize = 0 ;
1860 }
1861
1862 return actualsize ;
1863 }
1864
1865 void wxMacMLTEControl::Replace( long from , long to , const wxString &str )
1866 {
1867 wxString value = str ;
1868 wxMacConvertNewlines10To13( &value ) ;
1869
1870 wxMacEditHelper help( m_txn ) ;
1871 wxMacWindowClipper c( m_peer ) ;
1872
1873 TXNSetSelection(m_txn , from , to ) ;
1874 TXNClear( m_txn ) ;
1875 SetTXNData( value , kTXNUseCurrentSelection, kTXNUseCurrentSelection ) ;
1876 }
1877
1878 void wxMacMLTEControl::Remove( long from , long to )
1879 {
1880 wxMacWindowClipper c( m_peer ) ;
1881 wxMacEditHelper help( m_txn ) ;
1882 TXNSetSelection(m_txn , from , to ) ;
1883 TXNClear( m_txn ) ;
1884 }
1885
1886 void wxMacMLTEControl::GetSelection( long* from, long* to) const
1887 {
1888 TXNGetSelection( m_txn , (TXNOffset*) from , (TXNOffset*) to ) ;
1889 }
1890
1891 void wxMacMLTEControl::SetSelection( long from , long to )
1892 {
1893 wxMacWindowClipper c( m_peer ) ;
1894
1895 // change the selection
1896 if ((from == -1) && (to == -1))
1897 TXNSelectAll(m_txn);
1898 else
1899 TXNSetSelection( m_txn, from, to );
1900 TXNShowSelection( m_txn, kTXNShowStart );
1901 }
1902
1903 void wxMacMLTEControl::WriteText(const wxString& str)
1904 {
1905 wxString st = str ;
1906 wxMacConvertNewlines10To13( &st ) ;
1907
1908 long start , end , dummy ;
1909 GetSelection( &start , &dummy ) ;
1910 wxMacWindowClipper c( m_peer ) ;
1911 {
1912 wxMacEditHelper helper( m_txn ) ;
1913 SetTXNData( st , kTXNUseCurrentSelection, kTXNUseCurrentSelection ) ;
1914 }
1915
1916 GetSelection( &dummy , &end ) ;
1917
1918 // TODO: SetStyle( start , end , GetDefaultStyle() ) ;
1919 }
1920
1921 void wxMacMLTEControl::Clear()
1922 {
1923 wxMacWindowClipper c( m_peer ) ;
1924 wxMacEditHelper st(m_txn) ;
1925 TXNSetSelection( m_txn , kTXNStartOffset , kTXNEndOffset ) ;
1926 TXNClear(m_txn);
1927 }
1928
1929 bool wxMacMLTEControl::CanUndo() const
1930 {
1931 return TXNCanUndo( m_txn , NULL ) ;
1932 }
1933
1934 void wxMacMLTEControl::Undo()
1935 {
1936 TXNUndo( m_txn ) ;
1937 }
1938
1939 bool wxMacMLTEControl::CanRedo() const
1940 {
1941 return TXNCanRedo( m_txn , NULL ) ;
1942 }
1943
1944 void wxMacMLTEControl::Redo()
1945 {
1946 TXNRedo( m_txn ) ;
1947 }
1948
1949 int wxMacMLTEControl::GetNumberOfLines() const
1950 {
1951 ItemCount lines = 0 ;
1952 TXNGetLineCount( m_txn, &lines ) ;
1953
1954 return lines ;
1955 }
1956
1957 long wxMacMLTEControl::XYToPosition(long x, long y) const
1958 {
1959 Point curpt ;
1960 wxTextPos lastpos ;
1961
1962 // TODO: find a better implementation : while we can get the
1963 // line metrics of a certain line, we don't get its starting
1964 // position, so it would probably be rather a binary search
1965 // for the start position
1966 long xpos = 0 ;
1967 long ypos = 0 ;
1968 int lastHeight = 0 ;
1969 ItemCount n ;
1970
1971 lastpos = GetLastPosition() ;
1972 for ( n = 0 ; n <= (ItemCount) lastpos ; ++n )
1973 {
1974 if ( y == ypos && x == xpos )
1975 return n ;
1976
1977 TXNOffsetToPoint( m_txn , n , &curpt );
1978
1979 if ( curpt.v > lastHeight )
1980 {
1981 xpos = 0 ;
1982 if ( n > 0 )
1983 ++ypos ;
1984 lastHeight = curpt.v ;
1985 }
1986 else
1987 ++xpos ;
1988 }
1989
1990 return 0 ;
1991 }
1992
1993 bool wxMacMLTEControl::PositionToXY(long pos, long *x, long *y) const
1994 {
1995 Point curpt ;
1996 wxTextPos lastpos ;
1997
1998 if ( y )
1999 *y = 0 ;
2000 if ( x )
2001 *x = 0 ;
2002
2003 lastpos = GetLastPosition() ;
2004 if ( pos <= lastpos )
2005 {
2006 // TODO find a better implementation : while we can get the
2007 // line metrics of a certain line, we don't get its starting
2008 // position, so it would probably be rather a binary search
2009 // for the start position
2010 long xpos = 0 ;
2011 long ypos = 0 ;
2012 int lastHeight = 0 ;
2013
2014 ItemCount n ;
2015 for ( n = 0 ; n <= (ItemCount) pos ; ++n )
2016 {
2017 TXNOffsetToPoint(m_txn , n , &curpt);
2018
2019 if ( curpt.v > lastHeight )
2020 {
2021 xpos = 0 ;
2022 if ( n > 0 )
2023 ++ypos ;
2024 lastHeight = curpt.v ;
2025 }
2026 else
2027 ++xpos ;
2028 }
2029
2030 if ( y )
2031 *y = ypos ;
2032 if ( x )
2033 *x = xpos ;
2034 }
2035
2036 return false ;
2037 }
2038
2039 void wxMacMLTEControl::ShowPosition( long pos )
2040 {
2041 #if TARGET_RT_MAC_MACHO && defined(AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER)
2042 {
2043 Point current, desired ;
2044 TXNOffset selstart, selend;
2045
2046 TXNGetSelection( m_txn, &selstart, &selend );
2047 TXNOffsetToPoint( m_txn, selstart, &current );
2048 TXNOffsetToPoint( m_txn, pos, &desired );
2049
2050 // TODO: use HIPoints for 10.3 and above
2051 if ( (UInt32)TXNScroll != (UInt32)kUnresolvedCFragSymbolAddress )
2052 {
2053 OSErr theErr = noErr;
2054 SInt32 dv = desired.v - current.v ;
2055 SInt32 dh = desired.h - current.h ;
2056 TXNShowSelection( m_txn, kTXNShowEnd ) ; // NB: should this be kTXNShowStart or kTXNShowEnd ??
2057 theErr = TXNScroll( m_txn, kTXNScrollUnitsInPixels , kTXNScrollUnitsInPixels , &dv , &dh );
2058
2059 // there will be an error returned for classic MLTE implementation when the control is
2060 // invisible, but HITextView works correctly, so we don't assert that one
2061 // wxASSERT_MSG( theErr == noErr, _T("TXNScroll returned an error!") );
2062 }
2063 }
2064 #endif
2065 }
2066
2067 void wxMacMLTEControl::SetTXNData( const wxString& st, TXNOffset start, TXNOffset end )
2068 {
2069 #if wxUSE_UNICODE
2070 #if SIZEOF_WCHAR_T == 2
2071 size_t len = st.Len() ;
2072 TXNSetData( m_txn, kTXNUnicodeTextData, (void*)st.wc_str(), len * 2, start, end );
2073 #else
2074 wxMBConvUTF16 converter ;
2075 ByteCount byteBufferLen = converter.WC2MB( NULL , st.wc_str() , 0 ) ;
2076 UniChar *unibuf = (UniChar*) malloc( byteBufferLen ) ;
2077 converter.WC2MB( (char*)unibuf, st.wc_str(), byteBufferLen ) ;
2078 TXNSetData( m_txn, kTXNUnicodeTextData, (void*)unibuf, byteBufferLen, start, end ) ;
2079 free( unibuf ) ;
2080 #endif
2081 #else
2082 wxCharBuffer text = st.mb_str(wxConvLocal) ;
2083 TXNSetData( m_txn, kTXNTextData, (void*)text.data(), strlen( text ), start, end ) ;
2084 #endif
2085 }
2086
2087 wxString wxMacMLTEControl::GetLineText(long lineNo) const
2088 {
2089 wxString line ;
2090
2091 if ( lineNo < GetNumberOfLines() )
2092 {
2093 Point firstPoint;
2094 Fixed lineWidth, lineHeight, currentHeight;
2095 long ypos ;
2096
2097 // get the first possible position in the control
2098 TXNOffsetToPoint(m_txn, 0, &firstPoint);
2099
2100 // Iterate through the lines until we reach the one we want,
2101 // adding to our current y pixel point position
2102 ypos = 0 ;
2103 currentHeight = 0;
2104 while (ypos < lineNo)
2105 {
2106 TXNGetLineMetrics(m_txn, ypos++, &lineWidth, &lineHeight);
2107 currentHeight += lineHeight;
2108 }
2109
2110 Point thePoint = { firstPoint.v + (currentHeight >> 16), firstPoint.h + (0) };
2111 TXNOffset theOffset;
2112 TXNPointToOffset(m_txn, thePoint, &theOffset);
2113
2114 wxString content = GetStringValue() ;
2115 Point currentPoint = thePoint;
2116 while (thePoint.v == currentPoint.v && theOffset < content.length())
2117 {
2118 line += content[theOffset];
2119 TXNOffsetToPoint(m_txn, ++theOffset, &currentPoint);
2120 }
2121 }
2122
2123 return line ;
2124 }
2125
2126 int wxMacMLTEControl::GetLineLength(long lineNo) const
2127 {
2128 int theLength = 0;
2129
2130 if ( lineNo < GetNumberOfLines() )
2131 {
2132 Point firstPoint;
2133 Fixed lineWidth, lineHeight, currentHeight;
2134 long ypos ;
2135
2136 // get the first possible position in the control
2137 TXNOffsetToPoint(m_txn, 0, &firstPoint);
2138
2139 // Iterate through the lines until we reach the one we want,
2140 // adding to our current y pixel point position
2141 ypos = 0;
2142 currentHeight = 0;
2143 while (ypos < lineNo)
2144 {
2145 TXNGetLineMetrics(m_txn, ypos++, &lineWidth, &lineHeight);
2146 currentHeight += lineHeight;
2147 }
2148
2149 Point thePoint = { firstPoint.v + (currentHeight >> 16), firstPoint.h + (0) };
2150 TXNOffset theOffset;
2151 TXNPointToOffset(m_txn, thePoint, &theOffset);
2152
2153 wxString content = GetStringValue() ;
2154 Point currentPoint = thePoint;
2155 while (thePoint.v == currentPoint.v && theOffset < content.length())
2156 {
2157 ++theLength;
2158 TXNOffsetToPoint(m_txn, ++theOffset, &currentPoint);
2159 }
2160 }
2161
2162 return theLength ;
2163 }
2164
2165
2166 // ----------------------------------------------------------------------------
2167 // MLTE control implementation (classic part)
2168 // ----------------------------------------------------------------------------
2169
2170 // OS X Notes : We still don't have a full replacement for MLTE, so this implementation
2171 // has to live on. We have different problems coming from outdated implementations on the
2172 // various OS X versions. Most deal with the scrollbars: they are not correctly embedded
2173 // while this can be solved on 10.3 by reassigning them the correct place, on 10.2 there is
2174 // no way out, therefore we are using our own implementation and our own scrollbars ....
2175
2176 #ifdef __WXMAC_OSX__
2177
2178 TXNScrollInfoUPP gTXNScrollInfoProc = NULL ;
2179 ControlActionUPP gTXNScrollActionProc = NULL ;
2180
2181 pascal void wxMacMLTEClassicControl::TXNScrollInfoProc(
2182 SInt32 iValue, SInt32 iMaximumValue,
2183 TXNScrollBarOrientation iScrollBarOrientation, SInt32 iRefCon)
2184 {
2185 wxMacMLTEClassicControl* mlte = (wxMacMLTEClassicControl*) iRefCon ;
2186 SInt32 value = wxMax( iValue , 0 ) ;
2187 SInt32 maximum = wxMax( iMaximumValue , 0 ) ;
2188
2189 if ( iScrollBarOrientation == kTXNHorizontal )
2190 {
2191 if ( mlte->m_sbHorizontal )
2192 {
2193 SetControl32BitValue( mlte->m_sbHorizontal , value ) ;
2194 SetControl32BitMaximum( mlte->m_sbHorizontal , maximum ) ;
2195 mlte->m_lastHorizontalValue = value ;
2196 }
2197 }
2198 else if ( iScrollBarOrientation == kTXNVertical )
2199 {
2200 if ( mlte->m_sbVertical )
2201 {
2202 SetControl32BitValue( mlte->m_sbVertical , value ) ;
2203 SetControl32BitMaximum( mlte->m_sbVertical , maximum ) ;
2204 mlte->m_lastVerticalValue = value ;
2205 }
2206 }
2207 }
2208
2209 pascal void wxMacMLTEClassicControl::TXNScrollActionProc( ControlRef controlRef , ControlPartCode partCode )
2210 {
2211 wxMacMLTEClassicControl* mlte = (wxMacMLTEClassicControl*) GetControlReference( controlRef ) ;
2212 if ( mlte == NULL )
2213 return ;
2214
2215 if ( controlRef != mlte->m_sbVertical && controlRef != mlte->m_sbHorizontal )
2216 return ;
2217
2218 OSStatus err ;
2219 bool isHorizontal = ( controlRef == mlte->m_sbHorizontal ) ;
2220
2221 SInt32 minimum = 0 ;
2222 SInt32 maximum = GetControl32BitMaximum( controlRef ) ;
2223 SInt32 value = GetControl32BitValue( controlRef ) ;
2224 SInt32 delta = 0;
2225
2226 switch ( partCode )
2227 {
2228
2229 case kControlDownButtonPart :
2230 delta = 10 ;
2231 break ;
2232
2233 case kControlUpButtonPart :
2234 delta = -10 ;
2235 break ;
2236
2237 case kControlPageDownPart :
2238 delta = GetControlViewSize( controlRef ) ;
2239 break ;
2240
2241 case kControlPageUpPart :
2242 delta = -GetControlViewSize( controlRef ) ;
2243 break ;
2244
2245 case kControlIndicatorPart :
2246 delta = value -
2247 ( isHorizontal ? mlte->m_lastHorizontalValue : mlte->m_lastVerticalValue ) ;
2248 break ;
2249
2250 default :
2251 break ;
2252 }
2253
2254 if ( delta != 0 )
2255 {
2256 SInt32 newValue = value ;
2257
2258 if ( partCode != kControlIndicatorPart )
2259 {
2260 if ( value + delta < minimum )
2261 delta = minimum - value ;
2262 if ( value + delta > maximum )
2263 delta = maximum - value ;
2264
2265 SetControl32BitValue( controlRef , value + delta ) ;
2266 newValue = value + delta ;
2267 }
2268
2269 SInt32 verticalDelta = isHorizontal ? 0 : delta ;
2270 SInt32 horizontalDelta = isHorizontal ? delta : 0 ;
2271
2272 err = TXNScroll( mlte->m_txn , kTXNScrollUnitsInPixels, kTXNScrollUnitsInPixels,
2273 &verticalDelta , &horizontalDelta );
2274
2275 if ( isHorizontal )
2276 mlte->m_lastHorizontalValue = newValue ;
2277 else
2278 mlte->m_lastVerticalValue = newValue ;
2279 }
2280 }
2281 #endif
2282
2283 // make correct activations
2284 void wxMacMLTEClassicControl::MacActivatePaneText(bool setActive)
2285 {
2286 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(m_controlRef);
2287
2288 wxMacWindowClipper clipper( textctrl ) ;
2289 TXNActivate(m_txn, m_txnFrameID, setActive);
2290
2291 ControlRef controlFocus = 0 ;
2292 GetKeyboardFocus( m_txnWindow , &controlFocus ) ;
2293 if ( controlFocus == m_controlRef )
2294 TXNFocus( m_txn, setActive );
2295 }
2296
2297 void wxMacMLTEClassicControl::MacFocusPaneText(bool setFocus)
2298 {
2299 TXNFocus( m_txn, setFocus);
2300 }
2301
2302 // guards against inappropriate redraw (hidden objects drawing onto window)
2303
2304 void wxMacMLTEClassicControl::MacSetObjectVisibility(bool vis)
2305 {
2306 ControlRef controlFocus = 0 ;
2307 GetKeyboardFocus( m_txnWindow , &controlFocus ) ;
2308
2309 if ( !vis && (controlFocus == m_controlRef ) )
2310 SetKeyboardFocus( m_txnWindow , m_controlRef , kControlFocusNoPart ) ;
2311
2312 TXNControlTag iControlTags[1] = { kTXNVisibilityTag };
2313 TXNControlData iControlData[1] = { {(UInt32) false } };
2314
2315 verify_noerr( TXNGetTXNObjectControls( m_txn , 1, iControlTags, iControlData ) ) ;
2316
2317 if ( iControlData[0].uValue != vis )
2318 {
2319 iControlData[0].uValue = vis ;
2320 verify_noerr( TXNSetTXNObjectControls( m_txn, false , 1, iControlTags, iControlData )) ;
2321 }
2322
2323 // we right now are always clipping as partial visibility (overlapped) visibility
2324 // is also a problem, if we run into further problems we might set the FrameBounds to an empty
2325 // rect here
2326 }
2327
2328 // make sure that the TXNObject is at the right position
2329
2330 void wxMacMLTEClassicControl::MacUpdatePosition()
2331 {
2332 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(m_controlRef);
2333 if ( textctrl == NULL )
2334 return ;
2335
2336 Rect bounds ;
2337 UMAGetControlBoundsInWindowCoords(m_controlRef, &bounds);
2338
2339 wxRect visRect = textctrl->MacGetClippedClientRect() ;
2340 Rect visBounds = { visRect.y , visRect.x , visRect.y + visRect.height , visRect.x + visRect.width } ;
2341 int x , y ;
2342 x = y = 0 ;
2343 textctrl->MacWindowToRootWindow( &x , &y ) ;
2344 OffsetRect( &visBounds , x , y ) ;
2345
2346 if ( !EqualRect( &bounds , &m_txnControlBounds ) || !EqualRect( &visBounds , &m_txnVisBounds) )
2347 {
2348 m_txnControlBounds = bounds ;
2349 m_txnVisBounds = visBounds ;
2350 wxMacWindowClipper cl(textctrl) ;
2351
2352 #ifdef __WXMAC_OSX__
2353 bool isCompositing = textctrl->MacGetTopLevelWindow()->MacUsesCompositing() ;
2354 if ( m_sbHorizontal || m_sbVertical )
2355 {
2356 int w = bounds.right - bounds.left ;
2357 int h = bounds.bottom - bounds.top ;
2358
2359 if ( m_sbHorizontal )
2360 {
2361 Rect sbBounds ;
2362
2363 sbBounds.left = -1 ;
2364 sbBounds.top = h - 14 ;
2365 sbBounds.right = w + 1 ;
2366 sbBounds.bottom = h + 1 ;
2367
2368 if ( !isCompositing )
2369 OffsetRect( &sbBounds , m_txnControlBounds.left , m_txnControlBounds.top ) ;
2370
2371 SetControlBounds( m_sbHorizontal , &sbBounds ) ;
2372 SetControlViewSize( m_sbHorizontal , w ) ;
2373 }
2374 if ( m_sbVertical )
2375 {
2376 Rect sbBounds ;
2377
2378 sbBounds.left = w - 14 ;
2379 sbBounds.top = -1 ;
2380 sbBounds.right = w + 1 ;
2381 sbBounds.bottom = m_sbHorizontal ? h - 14 : h + 1 ;
2382
2383 if ( !isCompositing )
2384 OffsetRect( &sbBounds , m_txnControlBounds.left , m_txnControlBounds.top ) ;
2385
2386 SetControlBounds( m_sbVertical , &sbBounds ) ;
2387 SetControlViewSize( m_sbVertical , h ) ;
2388 }
2389 }
2390
2391 Rect oldviewRect ;
2392 TXNLongRect olddestRect ;
2393 TXNGetRectBounds( m_txn , &oldviewRect , &olddestRect , NULL ) ;
2394
2395 Rect viewRect = { m_txnControlBounds.top, m_txnControlBounds.left,
2396 m_txnControlBounds.bottom - ( m_sbHorizontal ? 14 : 0 ) ,
2397 m_txnControlBounds.right - ( m_sbVertical ? 14 : 0 ) } ;
2398 TXNLongRect destRect = { m_txnControlBounds.top, m_txnControlBounds.left,
2399 m_txnControlBounds.bottom - ( m_sbHorizontal ? 14 : 0 ) ,
2400 m_txnControlBounds.right - ( m_sbVertical ? 14 : 0 ) } ;
2401
2402 if ( olddestRect.right >= 10000 )
2403 destRect.right = destRect.left + 32000 ;
2404
2405 if ( olddestRect.bottom >= 0x20000000 )
2406 destRect.bottom = destRect.top + 0x40000000 ;
2407
2408 SectRect( &viewRect , &visBounds , &viewRect ) ;
2409 TXNSetRectBounds( m_txn , &viewRect , &destRect , true ) ;
2410
2411 #if 0
2412 TXNSetFrameBounds(
2413 m_txn,
2414 m_txnControlBounds.top,
2415 m_txnControlBounds.left,
2416 m_txnControlBounds.bottom - (m_sbHorizontal ? 14 : 0),
2417 m_txnControlBounds.right - (m_sbVertical ? 14 : 0),
2418 m_txnFrameID );
2419 #endif
2420 #else
2421
2422 TXNSetFrameBounds( m_txn, m_txnControlBounds.top, m_txnControlBounds.left,
2423 wxMax( m_txnControlBounds.bottom , m_txnControlBounds.top ) ,
2424 wxMax( m_txnControlBounds.right , m_txnControlBounds.left ) , m_txnFrameID);
2425 #endif
2426 // the SetFrameBounds method unter classic sometimes does not correctly scroll a selection into sight after a
2427 // movement, therefore we have to force it
2428
2429 // this problem has been reported in OSX as well, so we use this here once again
2430
2431 TXNLongRect textRect ;
2432 TXNGetRectBounds( m_txn , NULL , NULL , &textRect ) ;
2433 if ( textRect.left < m_txnControlBounds.left )
2434 TXNShowSelection( m_txn , kTXNShowStart ) ;
2435 }
2436 }
2437
2438 void wxMacMLTEClassicControl::SetRect( Rect *r )
2439 {
2440 wxMacControl::SetRect( r ) ;
2441 MacUpdatePosition() ;
2442 }
2443
2444 void wxMacMLTEClassicControl::MacControlUserPaneDrawProc(wxInt16 thePart)
2445 {
2446 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(m_controlRef);
2447 if ( textctrl == NULL )
2448 return ;
2449
2450 if ( textctrl->MacIsReallyShown() )
2451 {
2452 wxMacWindowClipper clipper( textctrl ) ;
2453 TXNDraw( m_txn , NULL ) ;
2454 }
2455 }
2456
2457 wxInt16 wxMacMLTEClassicControl::MacControlUserPaneHitTestProc(wxInt16 x, wxInt16 y)
2458 {
2459 Point where = { y , x } ;
2460 ControlPartCode result = kControlNoPart;
2461
2462 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(m_controlRef);
2463 if ( (textctrl != NULL) && textctrl->MacIsReallyShown() )
2464 {
2465 if (PtInRect( where, &m_txnControlBounds ))
2466 {
2467 result = kControlEditTextPart ;
2468 }
2469 else
2470 {
2471 // sometimes we get the coords also in control local coordinates, therefore test again
2472 if ( textctrl->MacGetTopLevelWindow()->MacUsesCompositing() )
2473 {
2474 int x = 0 , y = 0 ;
2475 textctrl->MacClientToRootWindow( &x , &y ) ;
2476 where.h += x ;
2477 where.v += y ;
2478 }
2479
2480 if (PtInRect(where, &m_txnControlBounds))
2481 result = kControlEditTextPart ;
2482 }
2483 }
2484
2485 return result;
2486 }
2487
2488 wxInt16 wxMacMLTEClassicControl::MacControlUserPaneTrackingProc( wxInt16 x, wxInt16 y, void* actionProc )
2489 {
2490 ControlPartCode result = kControlNoPart;
2491
2492 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(m_controlRef);
2493 if ( (textctrl != NULL) && textctrl->MacIsReallyShown() )
2494 {
2495 Point startPt = { y , x } ;
2496 // for compositing, we must convert these into toplevel window coordinates, because hittesting expects them
2497 if ( textctrl->MacGetTopLevelWindow()->MacUsesCompositing() )
2498 {
2499 int x = 0 , y = 0 ;
2500 textctrl->MacClientToRootWindow( &x , &y ) ;
2501 startPt.h += x ;
2502 startPt.v += y ;
2503 }
2504
2505 switch (MacControlUserPaneHitTestProc( startPt.h , startPt.v ))
2506 {
2507 case kControlEditTextPart :
2508 {
2509 wxMacWindowClipper clipper( textctrl ) ;
2510
2511 EventRecord rec ;
2512 ConvertEventRefToEventRecord( (EventRef) wxTheApp->MacGetCurrentEvent() , &rec ) ;
2513 TXNClick( m_txn, &rec );
2514 }
2515 break;
2516
2517 default :
2518 break;
2519 }
2520 }
2521
2522 return result;
2523 }
2524
2525 void wxMacMLTEClassicControl::MacControlUserPaneIdleProc()
2526 {
2527 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(m_controlRef);
2528 if ( textctrl == NULL )
2529 return ;
2530
2531 if (textctrl->MacIsReallyShown())
2532 {
2533 if (IsControlActive(m_controlRef))
2534 {
2535 Point mousep;
2536
2537 wxMacWindowClipper clipper( textctrl ) ;
2538 GetMouse(&mousep);
2539
2540 TXNIdle(m_txn);
2541
2542 if (PtInRect(mousep, &m_txnControlBounds))
2543 {
2544 RgnHandle theRgn = NewRgn();
2545 RectRgn(theRgn, &m_txnControlBounds);
2546 TXNAdjustCursor(m_txn, theRgn);
2547 DisposeRgn(theRgn);
2548 }
2549 }
2550 }
2551 }
2552
2553 wxInt16 wxMacMLTEClassicControl::MacControlUserPaneKeyDownProc (wxInt16 keyCode, wxInt16 charCode, wxInt16 modifiers)
2554 {
2555 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(m_controlRef);
2556 if ( textctrl == NULL )
2557 return kControlNoPart;
2558
2559 wxMacWindowClipper clipper( textctrl ) ;
2560
2561 EventRecord ev ;
2562 memset( &ev , 0 , sizeof( ev ) ) ;
2563 ev.what = keyDown ;
2564 ev.modifiers = modifiers ;
2565 ev.message = ((keyCode << 8) & keyCodeMask) | (charCode & charCodeMask);
2566 TXNKeyDown( m_txn , &ev );
2567
2568 return kControlEntireControl;
2569 }
2570
2571 void wxMacMLTEClassicControl::MacControlUserPaneActivateProc( bool activating)
2572 {
2573 MacActivatePaneText( activating );
2574 }
2575
2576 wxInt16 wxMacMLTEClassicControl::MacControlUserPaneFocusProc(wxInt16 action)
2577 {
2578 ControlPartCode focusResult;
2579
2580 focusResult = kControlFocusNoPart;
2581 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(m_controlRef);
2582 if ( textctrl == NULL )
2583 return 0;
2584
2585 wxMacWindowClipper clipper( textctrl ) ;
2586
2587 ControlRef controlFocus = NULL ;
2588 GetKeyboardFocus( m_txnWindow , &controlFocus ) ;
2589 bool wasFocused = ( controlFocus == m_controlRef ) ;
2590
2591 switch (action)
2592 {
2593 case kControlFocusPrevPart:
2594 case kControlFocusNextPart:
2595 MacFocusPaneText( ( !wasFocused));
2596 focusResult = (!wasFocused) ? (ControlPartCode) kControlEditTextPart : (ControlPartCode) kControlFocusNoPart;
2597 break;
2598
2599 case kControlFocusNoPart:
2600 default:
2601 MacFocusPaneText( false );
2602 focusResult = kControlFocusNoPart;
2603 break;
2604 }
2605
2606 return focusResult;
2607 }
2608
2609 void wxMacMLTEClassicControl::MacControlUserPaneBackgroundProc( void *info )
2610 {
2611 }
2612
2613 wxMacMLTEClassicControl::wxMacMLTEClassicControl( wxTextCtrl *wxPeer,
2614 const wxString& str,
2615 const wxPoint& pos,
2616 const wxSize& size, long style ) : wxMacMLTEControl( wxPeer )
2617 {
2618 m_font = wxPeer->GetFont() ;
2619 m_windowStyle = style ;
2620 Rect bounds = wxMacGetBoundsForControl( wxPeer , pos , size ) ;
2621
2622 short featureSet;
2623
2624 featureSet = kControlSupportsEmbedding | kControlSupportsFocus | kControlWantsIdle
2625 | kControlWantsActivate | kControlHandlesTracking // | kControlHasSpecialBackground
2626 | kControlGetsFocusOnClick | kControlSupportsLiveFeedback;
2627
2628 verify_noerr( ::CreateUserPaneControl( MAC_WXHWND(wxPeer->GetParent()->MacGetTopLevelWindowRef()), &bounds, featureSet, &m_controlRef ) );
2629
2630 DoCreate();
2631
2632 AdjustCreationAttributes( *wxWHITE , true ) ;
2633
2634 MacSetObjectVisibility( wxPeer->MacIsReallyShown() ) ;
2635
2636 {
2637 wxString st = str ;
2638 wxMacConvertNewlines10To13( &st ) ;
2639 wxMacWindowClipper clipper( m_peer ) ;
2640 SetTXNData( st , kTXNStartOffset, kTXNEndOffset ) ;
2641 TXNSetSelection( m_txn, 0, 0);
2642 }
2643 }
2644
2645 wxMacMLTEClassicControl::~wxMacMLTEClassicControl()
2646 {
2647 TXNDeleteObject(m_txn);
2648 m_txn = NULL ;
2649 }
2650
2651 void wxMacMLTEClassicControl::VisibilityChanged(bool shown)
2652 {
2653 MacSetObjectVisibility( shown ) ;
2654 wxMacControl::VisibilityChanged( shown ) ;
2655 }
2656
2657 void wxMacMLTEClassicControl::SuperChangedPosition()
2658 {
2659 MacUpdatePosition() ;
2660 wxMacControl::SuperChangedPosition() ;
2661 }
2662
2663 #ifdef __WXMAC_OSX__
2664
2665 ControlUserPaneDrawUPP gTPDrawProc = NULL;
2666 ControlUserPaneHitTestUPP gTPHitProc = NULL;
2667 ControlUserPaneTrackingUPP gTPTrackProc = NULL;
2668 ControlUserPaneIdleUPP gTPIdleProc = NULL;
2669 ControlUserPaneKeyDownUPP gTPKeyProc = NULL;
2670 ControlUserPaneActivateUPP gTPActivateProc = NULL;
2671 ControlUserPaneFocusUPP gTPFocusProc = NULL;
2672
2673 static pascal void wxMacControlUserPaneDrawProc(ControlRef control, SInt16 part)
2674 {
2675 wxTextCtrl *textCtrl = wxDynamicCast( wxFindControlFromMacControl(control) , wxTextCtrl ) ;
2676 wxMacMLTEClassicControl * win = textCtrl ? (wxMacMLTEClassicControl*)(textCtrl->GetPeer()) : NULL ;
2677 if ( win )
2678 win->MacControlUserPaneDrawProc(part) ;
2679 }
2680
2681 static pascal ControlPartCode wxMacControlUserPaneHitTestProc(ControlRef control, Point where)
2682 {
2683 wxTextCtrl *textCtrl = wxDynamicCast( wxFindControlFromMacControl(control) , wxTextCtrl ) ;
2684 wxMacMLTEClassicControl * win = textCtrl ? (wxMacMLTEClassicControl*)(textCtrl->GetPeer()) : NULL ;
2685 if ( win )
2686 return win->MacControlUserPaneHitTestProc(where.h , where.v) ;
2687 else
2688 return kControlNoPart ;
2689 }
2690
2691 static pascal ControlPartCode wxMacControlUserPaneTrackingProc(ControlRef control, Point startPt, ControlActionUPP actionProc)
2692 {
2693 wxTextCtrl *textCtrl = wxDynamicCast( wxFindControlFromMacControl(control) , wxTextCtrl ) ;
2694 wxMacMLTEClassicControl * win = textCtrl ? (wxMacMLTEClassicControl*)(textCtrl->GetPeer()) : NULL ;
2695 if ( win )
2696 return win->MacControlUserPaneTrackingProc( startPt.h , startPt.v , (void*) actionProc) ;
2697 else
2698 return kControlNoPart ;
2699 }
2700
2701 static pascal void wxMacControlUserPaneIdleProc(ControlRef control)
2702 {
2703 wxTextCtrl *textCtrl = wxDynamicCast( wxFindControlFromMacControl(control) , wxTextCtrl ) ;
2704 wxMacMLTEClassicControl * win = textCtrl ? (wxMacMLTEClassicControl*)(textCtrl->GetPeer()) : NULL ;
2705 if ( win )
2706 win->MacControlUserPaneIdleProc() ;
2707 }
2708
2709 static pascal ControlPartCode wxMacControlUserPaneKeyDownProc(ControlRef control, SInt16 keyCode, SInt16 charCode, SInt16 modifiers)
2710 {
2711 wxTextCtrl *textCtrl = wxDynamicCast( wxFindControlFromMacControl(control) , wxTextCtrl ) ;
2712 wxMacMLTEClassicControl * win = textCtrl ? (wxMacMLTEClassicControl*)(textCtrl->GetPeer()) : NULL ;
2713 if ( win )
2714 return win->MacControlUserPaneKeyDownProc(keyCode,charCode,modifiers) ;
2715 else
2716 return kControlNoPart ;
2717 }
2718
2719 static pascal void wxMacControlUserPaneActivateProc(ControlRef control, Boolean activating)
2720 {
2721 wxTextCtrl *textCtrl = wxDynamicCast( wxFindControlFromMacControl(control) , wxTextCtrl ) ;
2722 wxMacMLTEClassicControl * win = textCtrl ? (wxMacMLTEClassicControl*)(textCtrl->GetPeer()) : NULL ;
2723 if ( win )
2724 win->MacControlUserPaneActivateProc(activating) ;
2725 }
2726
2727 static pascal ControlPartCode wxMacControlUserPaneFocusProc(ControlRef control, ControlFocusPart action)
2728 {
2729 wxTextCtrl *textCtrl = wxDynamicCast( wxFindControlFromMacControl(control) , wxTextCtrl ) ;
2730 wxMacMLTEClassicControl * win = textCtrl ? (wxMacMLTEClassicControl*)(textCtrl->GetPeer()) : NULL ;
2731 if ( win )
2732 return win->MacControlUserPaneFocusProc(action) ;
2733 else
2734 return kControlNoPart ;
2735 }
2736
2737 #if 0
2738 static pascal void wxMacControlUserPaneBackgroundProc(ControlRef control, ControlBackgroundPtr info)
2739 {
2740 wxTextCtrl *textCtrl = wxDynamicCast( wxFindControlFromMacControl(control) , wxTextCtrl ) ;
2741 wxMacMLTEClassicControl * win = textCtrl ? (wxMacMLTEClassicControl*)(textCtrl->GetPeer()) : NULL ;
2742 if ( win )
2743 win->MacControlUserPaneBackgroundProc(info) ;
2744 }
2745 #endif
2746
2747 #endif // __WXMAC_OSX__
2748
2749 // TXNRegisterScrollInfoProc
2750
2751 OSStatus wxMacMLTEClassicControl::DoCreate()
2752 {
2753 Rect bounds;
2754
2755 OSStatus err = noErr ;
2756
2757 // set up our globals
2758 #ifdef __WXMAC_OSX__
2759 if (gTPDrawProc == NULL) gTPDrawProc = NewControlUserPaneDrawUPP(wxMacControlUserPaneDrawProc);
2760 if (gTPHitProc == NULL) gTPHitProc = NewControlUserPaneHitTestUPP(wxMacControlUserPaneHitTestProc);
2761 if (gTPTrackProc == NULL) gTPTrackProc = NewControlUserPaneTrackingUPP(wxMacControlUserPaneTrackingProc);
2762 if (gTPIdleProc == NULL) gTPIdleProc = NewControlUserPaneIdleUPP(wxMacControlUserPaneIdleProc);
2763 if (gTPKeyProc == NULL) gTPKeyProc = NewControlUserPaneKeyDownUPP(wxMacControlUserPaneKeyDownProc);
2764 if (gTPActivateProc == NULL) gTPActivateProc = NewControlUserPaneActivateUPP(wxMacControlUserPaneActivateProc);
2765 if (gTPFocusProc == NULL) gTPFocusProc = NewControlUserPaneFocusUPP(wxMacControlUserPaneFocusProc);
2766
2767 if (gTXNScrollInfoProc == NULL ) gTXNScrollInfoProc = NewTXNScrollInfoUPP(TXNScrollInfoProc) ;
2768 if (gTXNScrollActionProc == NULL ) gTXNScrollActionProc = NewControlActionUPP(TXNScrollActionProc) ;
2769 #endif
2770
2771 // set the initial settings for our private data
2772
2773 m_txnWindow = GetControlOwner(m_controlRef);
2774 m_txnPort = (GrafPtr) GetWindowPort(m_txnWindow);
2775
2776 #ifdef __WXMAC_OSX__
2777 // set up the user pane procedures
2778 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneDrawProcTag, sizeof(gTPDrawProc), &gTPDrawProc);
2779 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneHitTestProcTag, sizeof(gTPHitProc), &gTPHitProc);
2780 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneTrackingProcTag, sizeof(gTPTrackProc), &gTPTrackProc);
2781 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneIdleProcTag, sizeof(gTPIdleProc), &gTPIdleProc);
2782 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneKeyDownProcTag, sizeof(gTPKeyProc), &gTPKeyProc);
2783 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneActivateProcTag, sizeof(gTPActivateProc), &gTPActivateProc);
2784 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneFocusProcTag, sizeof(gTPFocusProc), &gTPFocusProc);
2785 #endif
2786 // calculate the rectangles used by the control
2787 UMAGetControlBoundsInWindowCoords(m_controlRef, &bounds);
2788
2789 m_txnControlBounds = bounds ;
2790 m_txnVisBounds = bounds ;
2791
2792 CGrafPtr origPort ;
2793 GDHandle origDev ;
2794
2795 GetGWorld( &origPort , &origDev ) ;
2796 SetPort( m_txnPort );
2797
2798 // create the new edit field
2799 TXNFrameOptions frameOptions = FrameOptionsFromWXStyle( m_windowStyle ) ;
2800
2801 #ifdef __WXMAC_OSX__
2802 // the scrollbars are not correctly embedded but are inserted at the root:
2803 // this gives us problems as we have erratic redraws even over the structure area
2804
2805 m_sbHorizontal = 0 ;
2806 m_sbVertical = 0 ;
2807 m_lastHorizontalValue = 0 ;
2808 m_lastVerticalValue = 0 ;
2809
2810 Rect sb = { 0 , 0 , 0 , 0 } ;
2811 if ( frameOptions & kTXNWantVScrollBarMask )
2812 {
2813 CreateScrollBarControl( m_txnWindow , &sb , 0 , 0 , 100 , 1 , true , gTXNScrollActionProc , &m_sbVertical ) ;
2814 SetControlReference( m_sbVertical , (SInt32) this ) ;
2815 SetControlAction( m_sbVertical, gTXNScrollActionProc );
2816 ShowControl( m_sbVertical ) ;
2817 EmbedControl( m_sbVertical , m_controlRef ) ;
2818 frameOptions &= ~kTXNWantVScrollBarMask ;
2819 }
2820
2821 if ( frameOptions & kTXNWantHScrollBarMask )
2822 {
2823 CreateScrollBarControl( m_txnWindow , &sb , 0 , 0 , 100 , 1 , true , gTXNScrollActionProc , &m_sbHorizontal ) ;
2824 SetControlReference( m_sbHorizontal , (SInt32) this ) ;
2825 SetControlAction( m_sbHorizontal, gTXNScrollActionProc );
2826 ShowControl( m_sbHorizontal ) ;
2827 EmbedControl( m_sbHorizontal , m_controlRef ) ;
2828 frameOptions &= ~(kTXNWantHScrollBarMask | kTXNDrawGrowIconMask);
2829 }
2830
2831 #endif
2832
2833 verify_noerr(TXNNewObject(NULL, m_txnWindow , &bounds,
2834 frameOptions ,
2835 kTXNTextEditStyleFrameType,
2836 kTXNTextensionFile,
2837 kTXNSystemDefaultEncoding,
2838 &m_txn, &m_txnFrameID, NULL ) );
2839
2840 #if 0
2841 TXNControlTag iControlTags[] = { kTXNUseCarbonEvents };
2842 TXNControlData iControlData[] = { {(UInt32) &cInfo } };
2843 int toptag = WXSIZEOF( iControlTags ) ;
2844 TXNCarbonEventInfo cInfo ;
2845 cInfo.useCarbonEvents = false ;
2846 cInfo.filler = 0 ;
2847 cInfo.flags = 0 ;
2848 cInfo.fDictionary = NULL ;
2849
2850 verify_noerr( TXNSetTXNObjectControls( m_txn, false , toptag, iControlTags, iControlData )) ;
2851 #endif
2852
2853 #ifdef __WXMAC_OSX__
2854 TXNRegisterScrollInfoProc( m_txn, gTXNScrollInfoProc, (SInt32) this);
2855 #endif
2856
2857 SetGWorld( origPort , origDev ) ;
2858 return err;
2859 }
2860
2861 // ----------------------------------------------------------------------------
2862 // MLTE control implementation (OSX part)
2863 // ----------------------------------------------------------------------------
2864
2865 #if TARGET_API_MAC_OSX
2866
2867 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
2868
2869 wxMacMLTEHIViewControl::wxMacMLTEHIViewControl( wxTextCtrl *wxPeer,
2870 const wxString& str,
2871 const wxPoint& pos,
2872 const wxSize& size, long style ) : wxMacMLTEControl( wxPeer )
2873 {
2874 m_font = wxPeer->GetFont() ;
2875 m_windowStyle = style ;
2876 Rect bounds = wxMacGetBoundsForControl( wxPeer , pos , size ) ;
2877 wxString st = str ;
2878 wxMacConvertNewlines10To13( &st ) ;
2879
2880 HIRect hr = { { bounds.left , bounds.top} ,
2881 { bounds.right - bounds.left , bounds.bottom - bounds.top} } ;
2882
2883 m_scrollView = NULL ;
2884 TXNFrameOptions frameOptions = FrameOptionsFromWXStyle( style ) ;
2885 if ( frameOptions & (kTXNWantVScrollBarMask|kTXNWantHScrollBarMask) )
2886 {
2887 HIScrollViewCreate(( frameOptions & kTXNWantHScrollBarMask ? kHIScrollViewOptionsHorizScroll : 0) |
2888 ( frameOptions & kTXNWantVScrollBarMask ? kHIScrollViewOptionsVertScroll: 0 ) , &m_scrollView ) ;
2889
2890 HIViewSetFrame( m_scrollView, &hr );
2891 HIViewSetVisible( m_scrollView, true );
2892 }
2893
2894 m_textView = NULL ;
2895 HITextViewCreate( NULL , 0, frameOptions , &m_textView ) ;
2896 m_txn = HITextViewGetTXNObject( m_textView) ;
2897 HIViewSetVisible( m_textView , true ) ;
2898 if ( m_scrollView )
2899 {
2900 HIViewAddSubview( m_scrollView , m_textView ) ;
2901 m_controlRef = m_scrollView ;
2902 wxPeer->MacInstallEventHandler( (WXWidget) m_textView ) ;
2903 }
2904 else
2905 {
2906 HIViewSetFrame( m_textView, &hr );
2907 m_controlRef = m_textView ;
2908 }
2909
2910 AdjustCreationAttributes( *wxWHITE , true ) ;
2911
2912 wxMacWindowClipper c( m_peer ) ;
2913 SetTXNData( st , kTXNStartOffset, kTXNEndOffset ) ;
2914
2915 TXNSetSelection( m_txn, 0, 0 );
2916 TXNShowSelection( m_txn, kTXNShowStart );
2917 }
2918
2919 OSStatus wxMacMLTEHIViewControl::SetFocus( ControlFocusPart focusPart )
2920 {
2921 return SetKeyboardFocus( GetControlOwner( m_textView ), m_textView, focusPart ) ;
2922 }
2923
2924 bool wxMacMLTEHIViewControl::HasFocus() const
2925 {
2926 ControlRef control ;
2927 GetKeyboardFocus( GetUserFocusWindow() , &control ) ;
2928 return control == m_textView ;
2929 }
2930
2931 void wxMacMLTEHIViewControl::SetBackground( const wxBrush &brush )
2932 {
2933 wxMacMLTEControl::SetBackground( brush ) ;
2934
2935 #if 0
2936 CGColorSpaceRef rgbSpace = CGColorSpaceCreateDeviceRGB();
2937 RGBColor col = MAC_WXCOLORREF(brush.GetColour().GetPixel()) ;
2938
2939 float component[4] ;
2940 component[0] = col.red / 65536.0 ;
2941 component[1] = col.green / 65536.0 ;
2942 component[2] = col.blue / 65536.0 ;
2943 component[3] = 1.0 ; // alpha
2944
2945 CGColorRef color = CGColorCreate (rgbSpace , component );
2946 HITextViewSetBackgroundColor( m_textView , color ) ;
2947 CGColorSpaceRelease( rgbSpace );
2948 #endif
2949 }
2950
2951 #endif // MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
2952
2953
2954 #endif
2955
2956 #endif // wxUSE_TEXTCTRL