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