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