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