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