]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/textctrl.cpp
Common code for the same handling of wxSL_INVERSE.
[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
3d1a4878 12#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
e9576ca5
SC
13#pragma implementation "textctrl.h"
14#endif
15
3d1a4878 16#include "wx/wxprec.h"
fedad417
GD
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{
7d8268a1 73public :
5ca0d812
SC
74 wxMacFunctor(){}
75 virtual ~wxMacFunctor() {}
76 virtual void* operator()() = 0 ;
7d8268a1 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 ) ;
7d8268a1 90public :
5ca0d812
SC
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 107 ~wxMacObjectFunctor1() {}
7d8268a1
WS
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
7d8268a1 124template<typename classtype, typename param1type>
5ca0d812
SC
125void* wxMacMPRemoteCall( classtype *object , void (classtype::*function)( param1type p1 ) , param1type p1 )
126{
7d8268a1
WS
127 wxMacObjectFunctor1<classtype,param1type> params(object,function,p1) ;
128 void *result =
5ca0d812
SC
129 MPRemoteCall( wxMacFunctor::CallBackProc , &params , kMPOwningProcessRemoteContext ) ;
130 return result ;
131}
587bc950 132
7d8268a1 133template<typename classtype, typename param1type>
5ca0d812
SC
134void* wxMacMPRemoteCall( classtype *object , void (classtype::*function)( const param1type& p1 ) , param1type p1 )
135{
7d8268a1
WS
136 wxMacObjectFunctor1<classtype,param1type> params(object,function,p1) ;
137 void *result =
5ca0d812
SC
138 MPRemoteCall( wxMacFunctor::CallBackProc , &params , kMPOwningProcessRemoteContext ) ;
139 return result ;
587bc950
SC
140}
141
7d8268a1 142template<typename classtype, typename param1type>
5ca0d812
SC
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
7d8268a1 151template<typename classtype, typename param1type>
5ca0d812
SC
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() ;
7d8268a1 165
5ca0d812
SC
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) ;
7d8268a1 174 virtual wxTextPos GetLastPosition() const ;
5ca0d812
SC
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;
7d8268a1 183 virtual void Undo() ;
5ca0d812
SC
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) ;
7d8268a1 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) ;
7d8268a1 213 virtual wxTextPos GetLastPosition() const ;
5ca0d812
SC
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 ) ;
7d8268a1 218
5ca0d812
SC
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
7d8268a1 246class wxMacMLTEHIViewControl : public wxMacMLTEControl
5ca0d812
SC
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) ;
eda3f2b4 303 virtual bool NeedsFocusRect() const;
5ca0d812
SC
304protected :
305 OSStatus DoCreate();
306public :
307 // hack to make public until we have migrated all procs
308 STPTextPaneVars* m_macTXNvars ;
309} ;
facd6764 310
5ca0d812 311#define TE_UNLIMITED_LENGTH 0xFFFFFFFFUL
72055702 312
5ca0d812
SC
313#if !USE_SHARED_LIBRARY
314IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
72055702 315
5ca0d812 316BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
7ea087b7 317 EVT_ERASE_BACKGROUND( wxTextCtrl::OnEraseBackground )
5ca0d812
SC
318 EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
319 EVT_CHAR(wxTextCtrl::OnChar)
320 EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
321 EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
322 EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
323 EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
324 EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
325
326 EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
327 EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
328 EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
329 EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
330 EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
331END_EVENT_TABLE()
332#endif
333
334// Text item
335void wxTextCtrl::Init()
facd6764 336{
5ca0d812
SC
337 m_editable = true ;
338 m_dirty = false;
339
340 m_maxLength = TE_UNLIMITED_LENGTH ;
facd6764
SC
341}
342
5ca0d812 343wxTextCtrl::~wxTextCtrl()
facd6764 344{
facd6764
SC
345}
346
ef4a634b 347
5ca0d812
SC
348bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
349 const wxString& str,
350 const wxPoint& pos,
351 const wxSize& size, long style,
352 const wxValidator& validator,
353 const wxString& name)
354{
7d8268a1 355 m_macIsUserPane = false ;
5ca0d812
SC
356 m_editable = true ;
357
9c4e5c70
SC
358 if ( ! ( style & wxNO_BORDER) )
359 style = ( style & ~wxBORDER_MASK) | wxSUNKEN_BORDER ;
7d8268a1 360
5ca0d812 361 if ( !wxTextCtrlBase::Create(parent, id, pos, size, style & ~(wxHSCROLL|wxVSCROLL), validator, name) )
7d8268a1 362 return false;
ef4a634b 363
7d8268a1 364 Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
5ca0d812
SC
365
366 if ( m_windowStyle & wxTE_MULTILINE )
facd6764 367 {
5ca0d812
SC
368 wxASSERT_MSG( !(m_windowStyle & wxTE_PROCESS_ENTER),
369 wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") );
370
371 m_windowStyle |= wxTE_PROCESS_ENTER;
372 style |= wxTE_PROCESS_ENTER ;
ed8c2780 373 }
3556e470 374
788e118f
SC
375#if TARGET_API_MAC_OSX
376#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
377 if ( UMAGetSystemVersion() >= 0x1030 )
378 {
379 m_peer = new wxMacMLTEHIViewControl( this , str , pos , size , style ) ;
380 }
788e118f 381#endif
3556e470
SC
382#if !wxMAC_AWAYS_USE_MLTE
383 if ( !m_peer )
7d8268a1 384 {
788e118f
SC
385 m_peer = new wxMacUnicodeTextControl( this , str , pos , size , style ) ;
386 }
5ca0d812 387#endif
3556e470
SC
388#endif
389 if ( !m_peer )
390 {
391 // this control draws the border itself
392 if ( !HasFlag(wxNO_BORDER) )
395480fb 393 {
3556e470 394 m_windowStyle &= ~wxSUNKEN_BORDER ;
7d8268a1
WS
395 bounds = wxMacGetBoundsForControl( this , pos , size ) ;
396 }
3556e470
SC
397 m_peer = new wxMacMLTEClassicControl( this , str , pos , size , style ) ;
398 }
788e118f 399
5ca0d812 400 MacPostControlCreate(pos,size) ;
72055702 401
5ca0d812
SC
402 if ( m_windowStyle & wxTE_READONLY)
403 {
404 SetEditable( false ) ;
405 }
72055702 406
7d8268a1 407 return true;
facd6764
SC
408}
409
7d8268a1 410void wxTextCtrl::MacVisibilityChanged()
5ca0d812
SC
411{
412 GetPeer()->VisibilityChanged( MacIsReallyShown() ) ;
413}
facd6764 414
7d8268a1 415void wxTextCtrl::MacEnabledStateChanged()
5ca0d812 416{
72055702
SC
417}
418
5ca0d812
SC
419wxString wxTextCtrl::GetValue() const
420{
421 return GetPeer()->GetStringValue() ;
422}
ef4a634b 423
5ca0d812 424void wxTextCtrl::GetSelection(long* from, long* to) const
7d8268a1 425{
5ca0d812
SC
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) ;
e8b4fd4b
RD
436
437 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
438 event.SetString( GetValue() ) ;
439 event.SetEventObject( this );
440 GetEventHandler()->ProcessEvent(event);
72055702
SC
441}
442
5ca0d812
SC
443void wxTextCtrl::SetMaxLength(unsigned long len)
444{
445 m_maxLength = len ;
446}
72055702 447
5ca0d812
SC
448bool wxTextCtrl::SetFont( const wxFont& font )
449{
450 if ( !wxTextCtrlBase::SetFont( font ) )
7d8268a1
WS
451 return false ;
452
5ca0d812
SC
453 GetPeer()->SetFont( font , GetForegroundColour() , GetWindowStyle() ) ;
454 return true ;
455}
456
457bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
458{
459 GetPeer()->SetStyle( start , end , style ) ;
460 return true ;
461}
462
463bool wxTextCtrl::SetDefaultStyle(const wxTextAttr& style)
464{
465 wxTextCtrlBase::SetDefaultStyle( style ) ;
466 SetStyle( kTXNUseCurrentSelection , kTXNUseCurrentSelection , GetDefaultStyle() ) ;
7d8268a1 467 return true ;
5ca0d812
SC
468}
469
470// Clipboard operations
471void wxTextCtrl::Copy()
472{
473 if (CanCopy())
facd6764 474 {
7d8268a1 475 GetPeer()->Copy() ;
ed8c2780 476 }
72055702
SC
477}
478
5ca0d812
SC
479void wxTextCtrl::Cut()
480{
481 if (CanCut())
482 {
7d8268a1 483 GetPeer()->Cut() ;
72055702 484
5ca0d812 485 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
5ca0d812
SC
486 event.SetEventObject( this );
487 GetEventHandler()->ProcessEvent(event);
488 }
489}
72055702 490
5ca0d812
SC
491void wxTextCtrl::Paste()
492{
493 if (CanPaste())
494 {
7d8268a1 495 GetPeer()->Paste() ;
5ca0d812 496 // eventually we should add setting the default style again
72055702 497
5ca0d812 498 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
5ca0d812
SC
499 event.SetEventObject( this );
500 GetEventHandler()->ProcessEvent(event);
501 }
502}
72055702 503
5ca0d812
SC
504bool wxTextCtrl::CanCopy() const
505{
506 // Can copy if there's a selection
507 long from, to;
508 GetSelection(& from, & to);
509 return (from != to);
510}
ef4a634b 511
5ca0d812
SC
512bool wxTextCtrl::CanCut() const
513{
514 if ( !IsEditable() )
515 {
516 return false ;
ed8c2780 517 }
5ca0d812
SC
518 // Can cut if there's a selection
519 long from, to;
520 GetSelection(& from, & to);
521 return (from != to);
72055702
SC
522}
523
5ca0d812
SC
524bool wxTextCtrl::CanPaste() const
525{
526 if (!IsEditable())
7d8268a1 527 return false;
72055702 528
5ca0d812
SC
529 return GetPeer()->CanPaste() ;
530}
facd6764 531
5ca0d812
SC
532void wxTextCtrl::SetEditable(bool editable)
533{
534 if ( editable != m_editable )
535 {
536 m_editable = editable ;
537 GetPeer()->SetEditable( editable ) ;
ed8c2780 538 }
72055702
SC
539}
540
5ca0d812
SC
541void wxTextCtrl::SetInsertionPoint(long pos)
542{
543 SetSelection( pos , pos ) ;
544}
72055702 545
5ca0d812
SC
546void wxTextCtrl::SetInsertionPointEnd()
547{
7d8268a1 548 wxTextPos pos = GetLastPosition();
5ca0d812
SC
549 SetInsertionPoint(pos);
550}
facd6764 551
5ca0d812
SC
552long wxTextCtrl::GetInsertionPoint() const
553{
554 long begin,end ;
555 GetSelection( &begin , &end ) ;
556 return begin ;
557}
facd6764 558
7d8268a1 559wxTextPos wxTextCtrl::GetLastPosition() const
5ca0d812
SC
560{
561 return GetPeer()->GetLastPosition( ) ;
72055702
SC
562}
563
5ca0d812
SC
564void wxTextCtrl::Replace(long from, long to, const wxString& str)
565{
566 GetPeer()->Replace( from , to , str) ;
567}
72055702 568
5ca0d812
SC
569void wxTextCtrl::Remove(long from, long to)
570{
571 GetPeer()->Remove( from , to ) ;
572}
facd6764 573
5ca0d812
SC
574void wxTextCtrl::SetSelection(long from, long to)
575{
576 GetPeer()->SetSelection( from , to ) ;
577}
578
579bool wxTextCtrl::LoadFile(const wxString& file)
580{
581 if ( wxTextCtrlBase::LoadFile(file) )
facd6764 582 {
7d8268a1 583 return true;
ed8c2780 584 }
5ca0d812 585
7d8268a1 586 return false;
72055702
SC
587}
588
5ca0d812
SC
589void wxTextCtrl::WriteText(const wxString& str)
590{
591 // TODO this MPRemoting will be moved into a remoting peer proxy for any command
592 if ( !wxIsMainThread() )
593 {
7d8268a1 594 // unfortunately CW 8 is not able to correctly deduce the template types, so we have
5ca0d812
SC
595 // to instantiate explicitely
596 wxMacMPRemoteGUICall<wxTextCtrl,wxString>( this , &wxTextCtrl::WriteText , str ) ;
597 return ;
598 }
599 else
600 {
601 GetPeer()->WriteText( str ) ;
602 }
603}
72055702 604
5ca0d812
SC
605void wxTextCtrl::AppendText(const wxString& text)
606{
607 SetInsertionPointEnd();
608 WriteText(text);
609}
facd6764 610
5ca0d812
SC
611void wxTextCtrl::Clear()
612{
613 GetPeer()->Clear() ;
614}
facd6764 615
5ca0d812
SC
616bool wxTextCtrl::IsModified() const
617{
618 return m_dirty;
619}
facd6764 620
5ca0d812
SC
621bool wxTextCtrl::IsEditable() const
622{
623 return IsEnabled() && m_editable ;
72055702
SC
624}
625
5ca0d812
SC
626bool wxTextCtrl::AcceptsFocus() const
627{
628 // we don't want focus if we can't be edited
629 return /*IsEditable() && */ wxControl::AcceptsFocus();
630}
72055702 631
5ca0d812 632wxSize wxTextCtrl::DoGetBestSize() const
1b2b1638 633{
5ca0d812 634 int wText = 100 ;
ef4a634b 635
5ca0d812 636 int hText;
ef4a634b 637
72463754
SC
638 // these are the numbers from the HIG, we reduce them by the borders
639 // first
640
5ca0d812
SC
641 switch( m_windowVariant )
642 {
643 case wxWINDOW_VARIANT_NORMAL :
72463754 644 hText = 22 - 6 ;
5ca0d812
SC
645 break ;
646 case wxWINDOW_VARIANT_SMALL :
72463754 647 hText = 19 - 6 ;
5ca0d812
SC
648 break ;
649 case wxWINDOW_VARIANT_MINI :
72463754 650 hText= 15 - 6 ;
5ca0d812
SC
651 break ;
652 default :
72463754 653 hText = 22 - 6;
7d8268a1 654 break ;
5ca0d812 655 }
72055702 656
72463754
SC
657 // as the above numbers have some free space around the text
658 // we get 5 lines like this anyway
5ca0d812
SC
659 if ( m_windowStyle & wxTE_MULTILINE )
660 {
661 hText *= 5 ;
662 }
ef4a634b 663
72463754
SC
664 if ( !HasFlag(wxNO_BORDER) )
665 hText += 6 ;
666
5ca0d812
SC
667 return wxSize(wText, hText);
668}
ef4a634b 669
5ca0d812
SC
670// ----------------------------------------------------------------------------
671// Undo/redo
672// ----------------------------------------------------------------------------
facd6764 673
5ca0d812
SC
674void wxTextCtrl::Undo()
675{
676 if (CanUndo())
677 {
678 GetPeer()->Undo() ;
679 }
72055702
SC
680}
681
5ca0d812 682void wxTextCtrl::Redo()
587bc950 683{
5ca0d812
SC
684 if (CanRedo())
685 {
686 GetPeer()->Redo() ;
687 }
688}
1b2b1638 689
5ca0d812
SC
690bool wxTextCtrl::CanUndo() const
691{
7d8268a1 692 if ( !IsEditable() )
5ca0d812 693 {
7d8268a1 694 return false ;
5ca0d812
SC
695 }
696 return GetPeer()->CanUndo() ;
697}
72055702 698
5ca0d812 699bool wxTextCtrl::CanRedo() const
6bdd4f5d 700{
7d8268a1 701 if ( !IsEditable() )
5ca0d812 702 {
7d8268a1 703 return false ;
5ca0d812
SC
704 }
705 return GetPeer()->CanRedo() ;
6bdd4f5d
SC
706}
707
5ca0d812
SC
708void wxTextCtrl::MarkDirty()
709{
710 m_dirty = true;
711}
587bc950 712
5ca0d812
SC
713void wxTextCtrl::DiscardEdits()
714{
715 m_dirty = false;
716}
587bc950 717
5ca0d812
SC
718int wxTextCtrl::GetNumberOfLines() const
719{
720 return GetPeer()->GetNumberOfLines() ;
721}
587bc950 722
5ca0d812
SC
723long wxTextCtrl::XYToPosition(long x, long y) const
724{
725 return GetPeer()->XYToPosition( x , y ) ;
726}
587bc950 727
5ca0d812 728bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
72055702 729{
5ca0d812
SC
730 return GetPeer()->PositionToXY(pos , x , y ) ;
731}
1fa29bdc 732
5ca0d812
SC
733void wxTextCtrl::ShowPosition(long pos)
734{
735 return GetPeer()->ShowPosition(pos) ;
736}
1fa29bdc 737
5ca0d812
SC
738int wxTextCtrl::GetLineLength(long lineNo) const
739{
740 return GetPeer()->GetLineLength(lineNo) ;
1b2b1638
SC
741}
742
5ca0d812 743wxString wxTextCtrl::GetLineText(long lineNo) const
1b2b1638 744{
5ca0d812 745 return GetPeer()->GetLineText(lineNo) ;
72055702
SC
746}
747
5ca0d812
SC
748/*
749 * Text item
750 */
72055702 751
5ca0d812 752void wxTextCtrl::Command(wxCommandEvent & event)
72055702 753{
5ca0d812
SC
754 SetValue (event.GetString());
755 ProcessCommand (event);
756}
72055702 757
5ca0d812
SC
758void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
759{
760 // By default, load the first file into the text window.
761 if (event.GetNumberOfFiles() > 0)
762 {
763 LoadFile(event.GetFiles()[0]);
764 }
765}
ef4a634b 766
7ea087b7
SC
767void wxTextCtrl::OnEraseBackground(wxEraseEvent& event)
768{
769 // all erasing should be done by the real mac control implementation
770 // while this is true for MLTE under classic, the HITextView is somehow
771 // transparent but background erase is not working correctly, so intercept
772 // things while we can...
395480fb 773 event.Skip() ;
7ea087b7
SC
774}
775
5ca0d812
SC
776void wxTextCtrl::OnChar(wxKeyEvent& event)
777{
778 int key = event.GetKeyCode() ;
779 bool eat_key = false ;
72055702 780
5ca0d812 781 if ( key == 'c' && event.MetaDown() )
72055702 782 {
5ca0d812
SC
783 if ( CanCopy() )
784 Copy() ;
785 return ;
72055702
SC
786 }
787
5ca0d812
SC
788 if ( !IsEditable() && key != WXK_LEFT && key != WXK_RIGHT && key != WXK_DOWN && key != WXK_UP && key != WXK_TAB &&
789 !( key == WXK_RETURN && ( (m_windowStyle & wxPROCESS_ENTER) || (m_windowStyle & wxTE_MULTILINE) ) )
790/* && key != WXK_PRIOR && key != WXK_NEXT && key != WXK_HOME && key != WXK_END */
791 )
29e4a190 792 {
5ca0d812
SC
793 // eat it
794 return ;
795 }
d3016f30 796
bdf0c19c
KH
797 // Check if we have reached the max # of chars, but still allow navigation and deletion
798 if ( !IsMultiLine() && GetValue().Length() >= m_maxLength &&
799 key != WXK_LEFT && key != WXK_RIGHT && key != WXK_TAB &&
800 key != WXK_BACK && !( key == WXK_RETURN && (m_windowStyle & wxPROCESS_ENTER) )
801 )
802 {
803 // eat it, we don't want to add more than allowed # of characters
804 return;
805 }
806
5ca0d812
SC
807 // assume that any key not processed yet is going to modify the control
808 m_dirty = true;
587bc950 809
5ca0d812
SC
810 if ( key == 'v' && event.MetaDown() )
811 {
812 if ( CanPaste() )
813 Paste() ;
814 return ;
29e4a190 815 }
5ca0d812 816 if ( key == 'x' && event.MetaDown() )
ed8c2780 817 {
5ca0d812
SC
818 if ( CanCut() )
819 Cut() ;
820 return ;
1b2b1638 821 }
5ca0d812
SC
822 switch ( key )
823 {
824 case WXK_RETURN:
825 if (m_windowStyle & wxPROCESS_ENTER)
826 {
827 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
828 event.SetEventObject( this );
829 event.SetString( GetValue() );
830 if ( GetEventHandler()->ProcessEvent(event) )
831 return;
832 }
833 if ( !(m_windowStyle & wxTE_MULTILINE) )
834 {
835 wxWindow *parent = GetParent();
836 while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL ) {
837 parent = parent->GetParent() ;
838 }
839 if ( parent && parent->GetDefaultItem() )
840 {
841 wxButton *def = wxDynamicCast(parent->GetDefaultItem(),
842 wxButton);
843 if ( def && def->IsEnabled() )
844 {
845 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
846 event.SetEventObject(def);
847 def->Command(event);
848 return ;
849 }
850 }
851
852 // this will make wxWidgets eat the ENTER key so that
853 // we actually prevent line wrapping in a single line
854 // text control
7d8268a1 855 eat_key = true;
5ca0d812 856 }
ef4a634b 857
5ca0d812 858 break;
facd6764 859
5ca0d812
SC
860 case WXK_TAB:
861 if ( !(m_windowStyle & wxTE_PROCESS_TAB))
862 {
863 int flags = 0;
864 if (!event.ShiftDown())
865 flags |= wxNavigationKeyEvent::IsForward ;
866 if (event.ControlDown())
867 flags |= wxNavigationKeyEvent::WinChange ;
868 Navigate(flags);
869 return;
870 }
871 else
872 {
873 // This is necessary (don't know why) or the tab will not
874 // be inserted.
875 WriteText(wxT("\t"));
876 }
7d8268a1 877
5ca0d812
SC
878 break;
879 }
facd6764 880
5ca0d812 881 if (!eat_key)
7f1de2b2 882 {
5ca0d812
SC
883 // perform keystroke handling
884 if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL )
885 CallNextEventHandler((EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() , (EventRef) wxTheApp->MacGetCurrentEvent() ) ;
7d8268a1 886 else
5ca0d812
SC
887 {
888 EventRecord rec ;
889 if ( wxMacConvertEventToRecord( (EventRef) wxTheApp->MacGetCurrentEvent() , &rec ) )
890 {
891 EventRecord *ev = &rec ;
892 short keycode ;
893 short keychar ;
894 keychar = short(ev->message & charCodeMask);
895 keycode = short(ev->message & keyCodeMask) >> 8 ;
896
897 m_peer->HandleKey( keycode , keychar , ev->modifiers ) ;
898 }
899 }
7f1de2b2 900 }
5ca0d812
SC
901 if ( ( key >= 0x20 && key < WXK_START ) ||
902 key == WXK_RETURN ||
903 key == WXK_DELETE ||
904 key == WXK_BACK)
7f1de2b2 905 {
5ca0d812 906 wxCommandEvent event1(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
5ca0d812
SC
907 event1.SetEventObject( this );
908 wxPostEvent(GetEventHandler(),event1);
7f1de2b2 909 }
5ca0d812 910}
facd6764 911
5ca0d812
SC
912// ----------------------------------------------------------------------------
913// standard handlers for standard edit menu events
914// ----------------------------------------------------------------------------
915
916void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
917{
918 Cut();
72055702
SC
919}
920
5ca0d812 921void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event))
facd6764 922{
5ca0d812
SC
923 Copy();
924}
7f1de2b2 925
5ca0d812
SC
926void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event))
927{
928 Paste();
facd6764
SC
929}
930
5ca0d812 931void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event))
facd6764 932{
5ca0d812 933 Undo();
facd6764
SC
934}
935
5ca0d812
SC
936void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event))
937{
938 Redo();
939}
facd6764 940
5ca0d812 941void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
72055702 942{
5ca0d812 943 event.Enable( CanCut() );
72055702
SC
944}
945
5ca0d812
SC
946void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
947{
948 event.Enable( CanCopy() );
72055702
SC
949}
950
5ca0d812 951void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
72055702 952{
5ca0d812 953 event.Enable( CanPaste() );
72055702
SC
954}
955
5ca0d812 956void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
29b30405 957{
5ca0d812 958 event.Enable( CanUndo() );
29b30405
SC
959}
960
5ca0d812 961void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
facd6764 962{
5ca0d812 963 event.Enable( CanRedo() );
facd6764
SC
964}
965
5ca0d812 966bool wxTextCtrl::MacSetupCursor( const wxPoint& pt )
29b30405 967{
5ca0d812
SC
968 return true ;
969}
20b69855 970#if !TARGET_API_MAC_OSX
5ca0d812 971// user pane implementation
ef4a634b 972
7d8268a1 973void wxTextCtrl::MacControlUserPaneDrawProc(wxInt16 part)
5ca0d812 974{
29b30405
SC
975}
976
7d8268a1 977wxInt16 wxTextCtrl::MacControlUserPaneHitTestProc(wxInt16 x, wxInt16 y)
29b30405 978{
5ca0d812 979 return kControlNoPart ;
29b30405
SC
980}
981
7d8268a1 982wxInt16 wxTextCtrl::MacControlUserPaneTrackingProc(wxInt16 x, wxInt16 y, void* actionProc)
72055702 983{
5ca0d812 984 return kControlNoPart ;
72055702
SC
985}
986
7d8268a1 987void wxTextCtrl::MacControlUserPaneIdleProc()
72055702 988{
72055702
SC
989}
990
7d8268a1 991wxInt16 wxTextCtrl::MacControlUserPaneKeyDownProc(wxInt16 keyCode, wxInt16 charCode, wxInt16 modifiers)
72055702 992{
5ca0d812 993 return kControlNoPart ;
72055702
SC
994}
995
7d8268a1 996void wxTextCtrl::MacControlUserPaneActivateProc(bool activating)
72055702 997{
72055702
SC
998}
999
7d8268a1 1000wxInt16 wxTextCtrl::MacControlUserPaneFocusProc(wxInt16 action)
72055702 1001{
5ca0d812 1002 return kControlNoPart ;
72055702
SC
1003}
1004
7d8268a1 1005void wxTextCtrl::MacControlUserPaneBackgroundProc(void* info)
72055702 1006{
5ca0d812 1007}
20b69855 1008#endif
5ca0d812
SC
1009// ----------------------------------------------------------------------------
1010// implementation base class
1011// ----------------------------------------------------------------------------
1012
7d8268a1 1013wxMacTextControl::wxMacTextControl()
5ca0d812 1014{
72055702
SC
1015}
1016
7d8268a1 1017wxMacTextControl::~wxMacTextControl()
72055702 1018{
72055702
SC
1019}
1020
7d8268a1 1021void wxMacTextControl::SetStyle(long start, long end, const wxTextAttr& style)
72055702 1022{
72055702
SC
1023}
1024
7d8268a1 1025void wxMacTextControl::Copy()
72055702 1026{
72055702
SC
1027}
1028
7d8268a1 1029void wxMacTextControl::Cut()
72055702 1030{
72055702
SC
1031}
1032
7d8268a1 1033void wxMacTextControl::Paste()
72055702 1034{
72055702
SC
1035}
1036
7d8268a1
WS
1037bool wxMacTextControl::CanPaste() const
1038{
5ca0d812
SC
1039 return false ;
1040}
1041
7d8268a1 1042void wxMacTextControl::SetEditable(bool editable)
72055702 1043{
7d8268a1 1044}
facd6764 1045
7d8268a1 1046wxTextPos wxMacTextControl::GetLastPosition() const
5ca0d812
SC
1047{
1048 return GetStringValue().Length() ;
1049}
facd6764 1050
7d8268a1 1051void wxMacTextControl::Replace( long from , long to , const wxString str )
5ca0d812 1052{
72055702
SC
1053}
1054
7d8268a1 1055void wxMacTextControl::Clear()
72055702 1056{
5ca0d812 1057 SetStringValue( wxEmptyString ) ;
72055702
SC
1058}
1059
7d8268a1 1060bool wxMacTextControl::CanUndo() const
72055702 1061{
5ca0d812
SC
1062 return false ;
1063}
587bc950 1064
7d8268a1 1065void wxMacTextControl::Undo() { }
5ca0d812
SC
1066
1067bool wxMacTextControl::CanRedo() const
1068{
1069 return false ;
7d8268a1 1070}
5ca0d812 1071
7d8268a1 1072void wxMacTextControl::Redo()
5ca0d812 1073{
72055702
SC
1074}
1075
5ca0d812 1076long wxMacTextControl::XYToPosition(long x, long y) const
72055702 1077{
5ca0d812
SC
1078 return 0 ;
1079}
72055702 1080
7d8268a1 1081bool wxMacTextControl::PositionToXY(long pos, long *x, long *y) const
5ca0d812
SC
1082{
1083 return false ;
72055702
SC
1084}
1085
7d8268a1
WS
1086void wxMacTextControl::ShowPosition( long WXUNUSED(pos) )
1087{
1088}
5ca0d812 1089
7d8268a1 1090int wxMacTextControl::GetNumberOfLines() const
7548762c 1091{
5ca0d812
SC
1092 ItemCount lines = 0 ;
1093 wxString content = GetStringValue() ;
1094 lines = 1;
1095 for (size_t i = 0; i < content.Length() ; i++)
7548762c 1096 {
5ca0d812 1097 if (content[i] == '\r') lines++;
7548762c 1098 }
5ca0d812
SC
1099 return lines ;
1100}
7548762c 1101
5ca0d812 1102wxString wxMacTextControl::GetLineText(long lineNo) const
7548762c 1103{
5ca0d812
SC
1104 // TODO change this if possible to reflect real lines
1105 wxString content = GetStringValue() ;
7d8268a1 1106
5ca0d812
SC
1107 // Find line first
1108 int count = 0;
1109 for (size_t i = 0; i < content.Length() ; i++)
7548762c 1110 {
5ca0d812
SC
1111 if (count == lineNo)
1112 {
1113 // Add chars in line then
1114 wxString tmp;
7d8268a1 1115
5ca0d812
SC
1116 for (size_t j = i; j < content.Length(); j++)
1117 {
1118 if (content[j] == '\n')
1119 return tmp;
7d8268a1 1120
5ca0d812
SC
1121 tmp += content[j];
1122 }
7d8268a1 1123
5ca0d812
SC
1124 return tmp;
1125 }
1126 if (content[i] == '\n') count++;
7548762c 1127 }
5ca0d812
SC
1128 return wxEmptyString ;
1129}
7548762c 1130
5ca0d812
SC
1131int wxMacTextControl::GetLineLength(long lineNo) const
1132{
1133 // TODO change this if possible to reflect real lines
1134 wxString content = GetStringValue() ;
7d8268a1 1135
5ca0d812
SC
1136 // Find line first
1137 int count = 0;
1138 for (size_t i = 0; i < content.Length() ; i++)
7548762c 1139 {
5ca0d812
SC
1140 if (count == lineNo)
1141 {
1142 // Count chars in line then
1143 count = 0;
1144 for (size_t j = i; j < content.Length(); j++)
1145 {
1146 count++;
1147 if (content[j] == '\n') return count;
1148 }
7d8268a1 1149
5ca0d812
SC
1150 return count;
1151 }
1152 if (content[i] == '\n') count++;
7548762c 1153 }
5ca0d812
SC
1154 return 0 ;
1155}
7548762c 1156
5ca0d812
SC
1157// ----------------------------------------------------------------------------
1158// standard unicode control implementation
1159// ----------------------------------------------------------------------------
1160
1161#if TARGET_API_MAC_OSX
1162
1163wxMacUnicodeTextControl::wxMacUnicodeTextControl( wxWindow *wxPeer,
1164 const wxString& str,
1165 const wxPoint& pos,
1166 const wxSize& size, long style )
1167{
1168 m_font = wxPeer->GetFont() ;
1169 m_windowStyle = style ;
7d8268a1 1170 Rect bounds = wxMacGetBoundsForControl( wxPeer , pos , size ) ;
5ca0d812 1171 wxString st = str ;
395480fb 1172 wxMacConvertNewlines10To13( &st ) ;
5ca0d812
SC
1173 wxMacCFStringHolder cf(st , m_font.GetEncoding()) ;
1174 CFStringRef cfr = cf ;
1175 Boolean isPassword = ( m_windowStyle & wxTE_PASSWORD ) != 0 ;
1176 m_valueTag = isPassword ? kControlEditTextPasswordCFStringTag : kControlEditTextCFStringTag ;
1177 CreateEditUnicodeTextControl( MAC_WXHWND(wxPeer->MacGetTopLevelWindowRef()), &bounds , cfr , isPassword , NULL , &m_controlRef ) ;
7d8268a1 1178
5ca0d812 1179 if ( !(m_windowStyle & wxTE_MULTILINE) )
7548762c 1180 {
5ca0d812 1181 SetData<Boolean>( kControlEditTextPart , kControlEditTextSingleLineTag , true ) ;
7548762c 1182 }
5ca0d812 1183}
7548762c 1184
5ca0d812 1185wxMacUnicodeTextControl::~wxMacUnicodeTextControl()
7548762c 1186{
7548762c
SC
1187}
1188
7d8268a1 1189void wxMacUnicodeTextControl::VisibilityChanged(bool shown)
7548762c 1190{
5ca0d812
SC
1191 if ( !(m_windowStyle & wxTE_MULTILINE) && shown )
1192 {
1193 // work around a refresh issue insofar as not always the entire content is shown even if this would be possible
1194 ControlEditTextSelectionRec sel ;
1195 CFStringRef value = NULL ;
7548762c 1196
5ca0d812
SC
1197 verify_noerr( GetData<ControlEditTextSelectionRec>( 0, kControlEditTextSelectionTag, &sel ) );
1198 verify_noerr( GetData<CFStringRef>( 0, m_valueTag , &value ) );
1199 verify_noerr( SetData<CFStringRef>( 0, m_valueTag, &value ) );
1200 verify_noerr( SetData<ControlEditTextSelectionRec>( 0, kControlEditTextSelectionTag, &sel ) );
7d8268a1 1201
5ca0d812
SC
1202 CFRelease( value ) ;
1203 }
1204}
7d8268a1 1205wxString wxMacUnicodeTextControl::GetStringValue() const
7548762c 1206{
5ca0d812
SC
1207 wxString result ;
1208 CFStringRef value = GetData<CFStringRef>(0,m_valueTag) ;
1209 if ( value )
1210 {
1211 wxMacCFStringHolder cf(value) ;
1212 result = cf.AsString() ;
1213 }
2e7573f7 1214#if '\n' == 10
395480fb
SC
1215 wxMacConvertNewlines13To10( &result ) ;
1216#else
5ca0d812 1217 wxMacConvertNewlines10To13( &result ) ;
395480fb 1218#endif
7548762c
SC
1219 return result ;
1220}
7d8268a1 1221void wxMacUnicodeTextControl::SetStringValue( const wxString &str)
5ca0d812
SC
1222{
1223 wxString st = str ;
395480fb 1224 wxMacConvertNewlines10To13( &st ) ;
5ca0d812
SC
1225 wxMacCFStringHolder cf(st , m_font.GetEncoding() ) ;
1226 verify_noerr( SetData<CFStringRef>( 0, m_valueTag , cf ) ) ;
1227}
1228void wxMacUnicodeTextControl::Copy()
1229{
1230 SendHICommand( kHICommandCopy ) ;
1231}
1232void wxMacUnicodeTextControl::Cut()
1233{
1234 SendHICommand( kHICommandCut ) ;
1235}
1236void wxMacUnicodeTextControl::Paste()
1237{
1238 SendHICommand( kHICommandPaste ) ;
1239}
1240bool wxMacUnicodeTextControl::CanPaste() const
1241{
1242 return true ;
1243}
7d8268a1 1244void wxMacUnicodeTextControl::SetEditable(bool editable)
5ca0d812
SC
1245{
1246 SetData<Boolean>( 0 , kControlEditTextLockedTag , (Boolean) !editable ) ;
1247}
7d8268a1 1248void wxMacUnicodeTextControl::Remove( long from , long to )
5ca0d812
SC
1249{
1250}
7548762c 1251
5ca0d812 1252void wxMacUnicodeTextControl::GetSelection( long* from, long* to) const
7548762c 1253{
5ca0d812
SC
1254 ControlEditTextSelectionRec sel ;
1255 verify_noerr(GetData<ControlEditTextSelectionRec>( 0, kControlEditTextSelectionTag, &sel ) ) ;
1256 if ( from ) *from = sel.selStart ;
1257 if ( to ) *to = sel.selEnd ;
7548762c
SC
1258}
1259
7d8268a1 1260void wxMacUnicodeTextControl::SetSelection( long from , long to )
ef4a634b 1261{
5ca0d812
SC
1262 ControlEditTextSelectionRec sel ;
1263 sel.selStart = from ;
1264 sel.selEnd = to ;
1265 SetData<ControlEditTextSelectionRec>( 0 , kControlEditTextSelectionTag, &sel ) ;
1266}
facd6764 1267
5ca0d812
SC
1268void wxMacUnicodeTextControl::WriteText(const wxString& str)
1269{
1270 wxString st = str ;
395480fb 1271 wxMacConvertNewlines10To13( &st ) ;
7548762c
SC
1272 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
1273 wxMacCFStringHolder cf(st , m_font.GetEncoding() ) ;
1274 CFStringRef value = cf ;
5ca0d812 1275 SetData<CFStringRef>( 0, kControlEditTextInsertCFStringRefTag, &value );
7548762c 1276 #else
5ca0d812 1277 wxString val = GetStringValue() ;
7548762c
SC
1278 long start , end ;
1279 GetSelection( &start , &end ) ;
1280 val.Remove( start , end - start ) ;
1281 val.insert( start , str ) ;
5ca0d812 1282 SetStringValue( val ) ;
7ea087b7 1283 SetSelection( start + str.Length() , start + str.Length() ) ;
7548762c 1284 #endif
72055702
SC
1285}
1286
5ca0d812 1287#endif
facd6764 1288
5ca0d812
SC
1289// ----------------------------------------------------------------------------
1290// MLTE control implementation (common part)
1291// ----------------------------------------------------------------------------
facd6764 1292
7d8268a1 1293#if TARGET_API_MAC_OSX == 0
5ca0d812
SC
1294// declaration needed because of one line in the code...
1295static void TPUpdateVisibility(ControlRef theControl) ;
587bc950 1296#endif
72055702 1297
7d8268a1 1298// if mlte is on read only , no changes at all are allowed, not even from
5ca0d812
SC
1299// procedural API, in order to allow changes via API all the same we must undo
1300// the readonly status while we are executing, this class helps to do so
72055702 1301
5ca0d812 1302class EditHelper
72055702 1303{
5ca0d812
SC
1304public :
1305 EditHelper( TXNObject txn )
1306 {
1307 TXNControlTag tag[] = { kTXNIOPrivilegesTag } ;
1308 m_txn = txn ;
1309 TXNGetTXNObjectControls( m_txn , 1 , tag , m_data ) ;
1310 if ( m_data[0].uValue == kTXNReadOnly )
1311 {
1312 TXNControlData data[] = { { kTXNReadWrite } } ;
1313 TXNSetTXNObjectControls( m_txn , false , 1 , tag , data ) ;
1314 }
1315 }
7d8268a1 1316 ~EditHelper()
5ca0d812
SC
1317 {
1318 TXNControlTag tag[] = { kTXNIOPrivilegesTag } ;
1319 if ( m_data[0].uValue == kTXNReadOnly )
1320 {
1321 TXNSetTXNObjectControls( m_txn , false , 1 , tag , m_data ) ;
1322 }
1323 }
1324 protected :
1325 TXNObject m_txn ;
1326 TXNControlData m_data[1] ;
1327} ;
72055702 1328
7d8268a1 1329wxString wxMacMLTEControl::GetStringValue() const
72055702 1330{
5ca0d812
SC
1331 wxString result ;
1332 OSStatus err ;
1333 Size actualSize = 0;
1334 {
1335#if wxUSE_UNICODE
1336 Handle theText ;
1337 err = TXNGetDataEncoded( m_txn , kTXNStartOffset, kTXNEndOffset, &theText , kTXNUnicodeTextData );
1338 // all done
1339 if ( err )
1340 {
1341 actualSize = 0 ;
1342 }
1343 else
1344 {
1345 actualSize = GetHandleSize( theText ) / sizeof( UniChar) ;
1346 if ( actualSize > 0 )
1347 {
1348 wxChar *ptr = NULL ;
7d8268a1
WS
1349#if SIZEOF_WCHAR_T == 2
1350 ptr = new wxChar[actualSize + 1 ] ;
5ca0d812 1351 wxStrncpy( ptr , (wxChar*) *theText , actualSize ) ;
5ca0d812
SC
1352#else
1353 SetHandleSize( theText , ( actualSize + 1 ) * sizeof( UniChar ) ) ;
1354 HLock( theText ) ;
1355 (((UniChar*)*theText)[actualSize]) = 0 ;
1356 wxMBConvUTF16BE converter ;
1357 size_t noChars = converter.MB2WC( NULL , (const char*)*theText , 0 ) ;
1358 ptr = new wxChar[noChars + 1] ;
7d8268a1 1359
5ca0d812
SC
1360 noChars = converter.MB2WC( ptr , (const char*)*theText , noChars ) ;
1361 ptr[noChars] = 0 ;
1362 HUnlock( theText ) ;
1363#endif
1364 ptr[actualSize] = 0 ;
1365 result = wxString( ptr ) ;
1366 delete[] ptr ;
1367 }
1368 DisposeHandle( theText ) ;
1369 }
1370#else
1371 Handle theText ;
0263da03 1372 err = TXNGetDataEncoded( m_txn , kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData );
5ca0d812
SC
1373 // all done
1374 if ( err )
1375 {
1376 actualSize = 0 ;
1377 }
1378 else
1379 {
1380 actualSize = GetHandleSize( theText ) ;
1381 if ( actualSize > 0 )
1382 {
1383 HLock( theText ) ;
1384 result = wxString( *theText , wxConvLocal , actualSize ) ;
1385 HUnlock( theText ) ;
1386 }
1387 DisposeHandle( theText ) ;
1388 }
1389#endif
1390 }
2e7573f7 1391#if '\n' == 10
395480fb
SC
1392 wxMacConvertNewlines13To10( &result ) ;
1393#else
5ca0d812 1394 wxMacConvertNewlines10To13( &result ) ;
395480fb 1395#endif
5ca0d812 1396 return result ;
72055702
SC
1397}
1398
7d8268a1 1399void wxMacMLTEControl::SetStringValue( const wxString &str)
72055702 1400{
5ca0d812 1401 wxString st = str ;
395480fb
SC
1402
1403 wxMacConvertNewlines10To13( &st ) ;
5ca0d812 1404 EditHelper help(m_txn) ;
ef4a634b 1405
5ca0d812
SC
1406 // wxMacWindowClipper c( this ) ;
1407#if !TARGET_API_MAC_OSX
1408 // otherwise scrolling might have problems ?
1409 TPUpdateVisibility( m_controlRef ) ;
1410#endif
1411 SetTXNData( st , kTXNStartOffset, kTXNEndOffset ) ;
1412 TXNSetSelection( m_txn, 0, 0);
1413 TXNShowSelection( m_txn, kTXNShowStart);
1414}
facd6764 1415
5ca0d812
SC
1416TXNFrameOptions wxMacMLTEControl::FrameOptionsFromWXStyle( long wxStyle )
1417{
1418 TXNFrameOptions frameOptions =
1419 kTXNDontDrawCaretWhenInactiveMask ;
1420 if ( ! ( wxStyle & wxTE_NOHIDESEL ) )
1421 frameOptions |= kTXNDontDrawSelectionWhenInactiveMask ;
1422
1423 if ( wxStyle & wxTE_MULTILINE )
29e4a190 1424 {
5ca0d812
SC
1425 if ( ! ( wxStyle & wxTE_DONTWRAP ) )
1426 frameOptions |= kTXNAlwaysWrapAtViewEdgeMask ;
1427 else
1428 {
1429 frameOptions |= kTXNAlwaysWrapAtViewEdgeMask ;
1430 frameOptions |= kTXNWantHScrollBarMask ;
1431 }
72055702 1432
5ca0d812
SC
1433 if ( !(wxStyle & wxTE_NO_VSCROLL ) )
1434 frameOptions |= kTXNWantVScrollBarMask ;
1435 }
1436 else
1437 frameOptions |= kTXNSingleLineOnlyMask ;
7d8268a1 1438
5ca0d812
SC
1439 if ( wxStyle & wxHSCROLL )
1440 frameOptions |= kTXNWantHScrollBarMask ;
7d8268a1 1441
5ca0d812
SC
1442 return frameOptions ;
1443}
cfeff6f7 1444
5ca0d812
SC
1445void wxMacMLTEControl::AdjustCreationAttributes( const wxColour &background, bool visible )
1446{
1447 TXNControlTag iControlTags[3] = { kTXNDoFontSubstitution, kTXNWordWrapStateTag };
1448 TXNControlData iControlData[3] = { {false}, {kTXNNoAutoWrap} };
1449 int toptag = 2 ;
1450#if TARGET_API_MAC_OSX
1451 iControlTags[2] = kTXNVisibilityTag ;
1452 iControlData[2].uValue = visible ;
1453 toptag++ ;
7d8268a1
WS
1454#endif
1455
72055702
SC
1456 if ( m_windowStyle & wxTE_MULTILINE )
1457 {
5ca0d812
SC
1458 if (m_windowStyle & wxTE_DONTWRAP)
1459 iControlData[1].uValue = kTXNNoAutoWrap ;
1460 else
1461 iControlData[1].uValue = kTXNAutoWrap ;
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
7d8268a1 1497void wxMacMLTEControl::SetBackground( const wxBrush &brush )
7ea087b7
SC
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{
7d8268a1 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 ;
eda3f2b4 1525
5ca0d812
SC
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
7d8268a1 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}
7d8268a1
WS
1556void wxMacMLTEControl::SetStyle(long start, long end, const wxTextAttr& style)
1557{
5ca0d812 1558 EditHelper help(m_txn) ;
8623a883 1559 TXNSetAttribute( style , start,end ) ;
7d8268a1
WS
1560}
1561
1562void wxMacMLTEControl::Copy()
5ca0d812
SC
1563{
1564 ClearCurrentScrap();
1565 TXNCopy(m_txn);
1566 TXNConvertToPublicScrap();
72055702
SC
1567}
1568
7d8268a1 1569void wxMacMLTEControl::Cut()
3a9fa0d6 1570{
5ca0d812
SC
1571 ClearCurrentScrap();
1572 TXNCut(m_txn);
1573 TXNConvertToPublicScrap();
3a9fa0d6
VZ
1574}
1575
7d8268a1 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
7d8268a1 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
7d8268a1 1594wxTextPos wxMacMLTEControl::GetLastPosition() const
5ca0d812 1595{
7d8268a1 1596 wxTextPos actualsize = 0 ;
5ca0d812
SC
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
7d8268a1 1614void wxMacMLTEControl::Replace( long from , long to , const wxString str )
5ca0d812
SC
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
7d8268a1 1639void wxMacMLTEControl::SetSelection( long from , long to )
5ca0d812
SC
1640{
1641 /* change the selection */
1642 if ((from == -1) && (to == -1))
7d8268a1 1643 TXNSelectAll(m_txn);
5ca0d812 1644 else
7d8268a1 1645 TXNSetSelection( m_txn, from, to);
5ca0d812
SC
1646 TXNShowSelection( m_txn, kTXNShowStart);
1647}
1648
7d8268a1 1649void wxMacMLTEControl::WriteText(const wxString& str)
5ca0d812
SC
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
7d8268a1 1662void wxMacMLTEControl::Clear()
5ca0d812
SC
1663{
1664 EditHelper st(m_txn) ;
1665 TXNSetSelection( m_txn , kTXNStartOffset , kTXNEndOffset ) ;
1666 TXNClear(m_txn);
1667}
1668
7d8268a1 1669bool wxMacMLTEControl::CanUndo() const
5ca0d812
SC
1670{
1671 return TXNCanUndo( m_txn , NULL ) ;
1672}
1673
7d8268a1 1674void wxMacMLTEControl::Undo()
5ca0d812 1675{
7d8268a1
WS
1676 TXNUndo( m_txn ) ;
1677}
5ca0d812
SC
1678
1679bool wxMacMLTEControl::CanRedo() const
1680{
1681 return TXNCanRedo( m_txn , NULL ) ;
7d8268a1 1682}
5ca0d812 1683
7d8268a1
WS
1684void wxMacMLTEControl::Redo()
1685{
5ca0d812
SC
1686 TXNRedo( m_txn ) ;
1687}
1688
7d8268a1 1689int wxMacMLTEControl::GetNumberOfLines() const
5ca0d812
SC
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 ;
7d8268a1
WS
1699
1700 wxTextPos lastpos = GetLastPosition() ;
1701
1702 // TODO find a better implementation : while we can get the
5ca0d812
SC
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
7d8268a1 1706 long xpos = 0 ;
5ca0d812
SC
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 ;
7d8268a1 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 1733 Point curpt ;
7d8268a1
WS
1734
1735 wxTextPos lastpos = GetLastPosition() ;
1736
bd3169a7
SC
1737 if ( y ) *y = 0 ;
1738 if ( x ) *x = 0 ;
7d8268a1 1739
bd3169a7
SC
1740 if ( pos <= lastpos )
1741 {
7d8268a1 1742 // TODO find a better implementation : while we can get the
bd3169a7
SC
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
7d8268a1 1746 long xpos = 0 ;
bd3169a7
SC
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
7d8268a1 1769 return false ;
72055702
SC
1770}
1771
7d8268a1 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 1788 TXNShowSelection( m_txn , true ) ;
7d8268a1 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
7d8268a1 1800 size_t len = st.Len() ;
5ca0d812
SC
1801 TXNSetData( m_txn , kTXNUnicodeTextData, (void*)st.wc_str(), len * 2,
1802 start, end);
1803#else
7d8268a1
WS
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 ) ;
5ca0d812
SC
1808 TXNSetData( m_txn , kTXNUnicodeTextData, (void*)unibuf, byteBufferLen ,
1809 start, end);
7d8268a1 1810 free( unibuf ) ;
587bc950 1811#endif
5ca0d812 1812#else
7d8268a1 1813 wxCharBuffer text = st.mb_str(wxConvLocal) ;
5ca0d812
SC
1814 TXNSetData( m_txn , kTXNTextData, (void*)text.data(), strlen( text ) ,
1815 start, end);
7d8268a1 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 ;
7d8268a1
WS
1827
1828 Fixed lineWidth,
ae25e5cc
RN
1829 lineHeight,
1830 currentHeight = 0;
7d8268a1 1831
ae25e5cc
RN
1832 // get the first possible position in the control
1833 Point firstPoint;
1834 TXNOffsetToPoint(m_txn, 0, &firstPoint);
7d8268a1 1835
ae25e5cc
RN
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 }
7d8268a1 1843
eab19a7c 1844 Point thePoint = { firstPoint.v + (currentHeight >> 16), firstPoint.h + (0) };
ae25e5cc
RN
1845 TXNOffset theOffset;
1846 TXNPointToOffset(m_txn, thePoint, &theOffset);
7d8268a1 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 ;
7d8268a1
WS
1866
1867 Fixed lineWidth,
ae25e5cc
RN
1868 lineHeight,
1869 currentHeight = 0;
7d8268a1 1870
ae25e5cc
RN
1871 // get the first possible position in the control
1872 Point firstPoint;
1873 TXNOffsetToPoint(m_txn, 0, &firstPoint);
7d8268a1 1874
ae25e5cc
RN
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 }
7d8268a1 1882
eab19a7c 1883 Point thePoint = { firstPoint.v + (currentHeight >> 16), firstPoint.h + (0) };
ae25e5cc
RN
1884 TXNOffset theOffset;
1885 TXNPointToOffset(m_txn, thePoint, &theOffset);
7d8268a1 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 */
7d8268a1 1945 Boolean fFocusDrawState; /* true if focus is drawn (default: true) */
5ca0d812
SC
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
7d8268a1 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 {
7d8268a1 1980 SetRect(&varsp->fRTextArea, bounds.left + 2 , bounds.top + (varsp->fMultiline ? 0 : 2) ,
5ca0d812
SC
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 1992 OSStatus err = noErr ;
5ca0d812 1993 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(varsp->fUserPaneRec);
0ff2493d 1994 if ( textctrl )
e600c175 1995 {
0ff2493d 1996#if TARGET_API_MAC_OSX
7d8268a1
WS
1997 TXNControlTag iControlTags[1] = { kTXNVisibilityTag };
1998 TXNControlData iControlData[1] = {{ vis }};
1999 err = ::TXNSetTXNObjectControls( varsp->fTXNRec, false, 1, iControlTags, iControlData );
0ff2493d 2000#endif
5ca0d812
SC
2001 Rect bounds ;
2002 UMAGetControlBoundsInWindowCoords( varsp->fUserPaneRec, &bounds);
2003 TPCalculateBounds( varsp , bounds ) ;
7d8268a1
WS
2004 if ( vis )
2005 {
2006 wxMacWindowClipper cl(textctrl) ;
2007 TXNSetFrameBounds( varsp->fTXNRec, varsp->fRTextArea.top, varsp->fRTextArea.left,
2008 varsp->fRTextArea.bottom, varsp->fRTextArea.right, varsp->fTXNFrame);
2009 TXNShowSelection( varsp->fTXNRec, kTXNShowStart);
2010 }
2011 else
2012 {
0ff2493d 2013#if TARGET_API_MAC_OSX
7d8268a1
WS
2014 // in 10.2 the scrollbars are still actively redrawn when using only the code above
2015 if ( UMAGetSystemVersion() < 0x1030 )
2016 {
2017 TXNSetFrameBounds( varsp->fTXNRec, varsp->fRTextArea.top + 20000 , varsp->fRTextArea.left + 20000 ,
2018 varsp->fRTextArea.bottom + 20000 , varsp->fRTextArea.right + 20000 , varsp->fTXNFrame);
2019 }
0ff2493d 2020#endif
7d8268a1 2021 }
5ca0d812
SC
2022 }
2023 return err ;
2024}
2025
2026// make sure we don't miss changes as carbon events are not available for these under classic
2027static void TPUpdateVisibility(ControlRef theControl) {
2028 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
2029 if ( textctrl == NULL )
e600c175 2030 return ;
7d8268a1 2031
5ca0d812 2032 STPTextPaneVars *varsp = (STPTextPaneVars *) ((wxMacMLTEClassicControl*)textctrl->GetPeer())->m_macTXNvars ;
7d8268a1 2033
5ca0d812
SC
2034 Rect bounds ;
2035 UMAGetControlBoundsInWindowCoords(theControl, &bounds);
2036 if ( textctrl->MacIsReallyShown() != varsp->fVisible )
2037 {
2038 // invalidate old position
2039 // InvalWindowRect( GetControlOwner( theControl ) , &varsp->fRBounds ) ;
2040 varsp->fVisible = textctrl->MacIsReallyShown() ;
2041 }
2042 if ( !EqualRect( &bounds , &varsp->fRBounds ) )
2043 {
2044 // old position
2045 Rect oldBounds = varsp->fRBounds ;
2046 TPCalculateBounds( varsp , bounds ) ;
2047 // we only recalculate when visible, otherwise scrollbars get drawn at incorrect places
2048 if ( varsp->fVisible )
2049 {
2050 wxMacWindowClipper cl(textctrl) ;
2051 TXNSetFrameBounds( varsp->fTXNRec, varsp->fRTextArea.top, varsp->fRTextArea.left,
2052 varsp->fRTextArea.bottom, varsp->fRTextArea.right, varsp->fTXNFrame);
2053 }
2054 InvalWindowRect( GetControlOwner( theControl ) , &oldBounds ) ;
2055 InvalWindowRect( GetControlOwner( theControl ) , &varsp->fRBounds ) ;
e600c175 2056 }
5ca0d812 2057}
ef4a634b 2058
5ca0d812
SC
2059// make correct activations
2060static void TPActivatePaneText(STPTextPaneVars *varsp, Boolean setActive) {
5ca0d812 2061 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(varsp->fUserPaneRec);
7d8268a1 2062 if (varsp->fTXNObjectActive != setActive && textctrl->MacIsReallyShown() )
1b2b1638 2063 {
5ca0d812
SC
2064 varsp->fTXNObjectActive = setActive;
2065 TXNActivate(varsp->fTXNRec, varsp->fTXNFrame, varsp->fTXNObjectActive);
2066 if (varsp->fInFocus)
2067 TXNFocus( varsp->fTXNRec, varsp->fTXNObjectActive);
1b2b1638 2068 }
5ca0d812 2069}
1fa29bdc 2070
5ca0d812
SC
2071// update focus outlines
2072static void TPRedrawFocusOutline(STPTextPaneVars *varsp) {
5ca0d812 2073 /* state changed */
7d8268a1
WS
2074 if (varsp->fFocusDrawState != (varsp->fIsActive && varsp->fInFocus))
2075 {
2076 varsp->fFocusDrawState = (varsp->fIsActive && varsp->fInFocus);
2077 // DrawThemeFocusRect(&varsp->fRFocusOutline, varsp->fFocusDrawState);
2078 }
5ca0d812 2079}
1fa29bdc 2080
5ca0d812
SC
2081// update TXN focus state
2082static void TPFocusPaneText(STPTextPaneVars *varsp, Boolean setFocus) {
2083 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(varsp->fUserPaneRec);
7d8268a1 2084
5ca0d812
SC
2085 if (varsp->fInFocus != setFocus && textctrl->MacIsReallyShown()) {
2086 varsp->fInFocus = setFocus;
2087 TXNFocus( varsp->fTXNRec, varsp->fInFocus);
e600c175 2088 }
5ca0d812
SC
2089}
2090
2091// draw the control
2092static pascal void TPPaneDrawProc(ControlRef theControl, ControlPartCode thePart) {
2093 /* set up our globals */
7d8268a1 2094
5ca0d812
SC
2095 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
2096 if ( textctrl == NULL )
e600c175 2097 return ;
5ca0d812 2098 TPUpdateVisibility( theControl ) ;
7d8268a1 2099
5ca0d812
SC
2100 STPTextPaneVars *varsp = (STPTextPaneVars *) ((wxMacMLTEClassicControl*)textctrl->GetPeer())->m_macTXNvars ;
2101 if ( textctrl->MacIsReallyShown() )
2102 {
2103 wxMacWindowClipper clipper( textctrl ) ;
2104 TXNDraw(varsp->fTXNRec, NULL);
2105 if ( !varsp->fNoBorders )
7d8268a1 2106 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
5ca0d812 2107 TPRedrawFocusOutline( varsp ) ;
e600c175 2108 }
5ca0d812
SC
2109}
2110
2111
2112/* TPPaneHitTestProc is called when the control manager would
2113like to determine what part of the control the mouse resides over.
2114We also call this routine from our tracking proc to determine how
2115to handle mouse clicks. */
2116static pascal ControlPartCode TPPaneHitTestProc(ControlRef theControl, Point where) {
2117 ControlPartCode result;
2118 /* set up our locals and lock down our globals*/
2119 result = 0;
2120 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
2121 if ( textctrl == NULL )
2122 return 0 ;
2123 TPUpdateVisibility( theControl ) ;
2124 STPTextPaneVars *varsp = (STPTextPaneVars *) ((wxMacMLTEClassicControl*)textctrl->GetPeer())->m_macTXNvars ;
7d8268a1 2125 if (textctrl->MacIsReallyShown() )
72055702 2126 {
5ca0d812
SC
2127 if (PtInRect(where, &varsp->fRBounds))
2128 result = kmUPTextPart;
7d8268a1 2129 else
3556e470
SC
2130 {
2131 // sometimes we get the coords also in control local coordinates, therefore test again
2132 if ( textctrl->MacGetTopLevelWindow()->MacUsesCompositing() )
2133 {
2134 int x = 0 , y = 0 ;
2135 textctrl->MacClientToRootWindow( &x , &y ) ;
2136 where.h += x ;
2137 where.v += y ;
2138 }
2139 if (PtInRect(where, &varsp->fRBounds))
2140 result = kmUPTextPart;
7d8268a1 2141 else
3556e470
SC
2142 result = 0;
2143 }
5ca0d812
SC
2144 }
2145 return result;
2146}
2147
2148
2149
2150
2151
2152/* TPPaneTrackingProc is called when the mouse is being held down
2153over our control. This routine handles clicks in the text area
2154and in the scroll bar. */
2155static pascal ControlPartCode TPPaneTrackingProc(ControlRef theControl, Point startPt, ControlActionUPP actionProc) {
7d8268a1 2156
5ca0d812 2157 ControlPartCode partCodeResult;
7d8268a1 2158 /* make sure we have some variables... */
5ca0d812
SC
2159 partCodeResult = 0;
2160 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
2161 if ( textctrl == NULL )
2162 return 0;
2163 TPUpdateVisibility( theControl ) ;
2164 STPTextPaneVars *varsp = (STPTextPaneVars *) ((wxMacMLTEClassicControl*)textctrl->GetPeer())->m_macTXNvars ;
7d8268a1
WS
2165 if (textctrl->MacIsReallyShown() )
2166 {
2167 /* we don't do any of these functions unless we're in focus */
5ca0d812
SC
2168 if ( ! varsp->fInFocus) {
2169 WindowPtr owner;
2170 owner = GetControlOwner(theControl);
2171 ClearKeyboardFocus(owner);
2172 SetKeyboardFocus(owner, theControl, kUserClickedToFocusPart);
2173 }
7d8268a1 2174 /* find the location for the click */
5ca0d812
SC
2175 // for compositing, we must convert these into toplevel window coordinates, because hittesting expects them
2176 if ( textctrl->MacGetTopLevelWindow()->MacUsesCompositing() )
2177 {
2178 int x = 0 , y = 0 ;
2179 textctrl->MacClientToRootWindow( &x , &y ) ;
2180 startPt.h += x ;
2181 startPt.v += y ;
2182 }
7d8268a1
WS
2183
2184 switch (TPPaneHitTestProc(theControl, startPt))
5ca0d812 2185 {
7d8268a1 2186 /* handle clicks in the text part */
5ca0d812 2187 case kmUPTextPart:
7d8268a1
WS
2188 {
2189 wxMacWindowClipper clipper( textctrl ) ;
2190
2191 EventRecord rec ;
2192 ConvertEventRefToEventRecord( (EventRef) wxTheApp->MacGetCurrentEvent() , &rec ) ;
2193 TXNClick( varsp->fTXNRec, &rec );
2194
2195 }
5ca0d812 2196 break;
7d8268a1 2197
5ca0d812
SC
2198 }
2199 }
2200 return partCodeResult;
2201}
2202
2203
2204/* TPPaneIdleProc is our user pane idle routine. When our text field
2205is active and in focus, we use this routine to set the cursor. */
2206static pascal void TPPaneIdleProc(ControlRef theControl) {
2207 /* set up locals */
2208 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
2209 if ( textctrl == NULL )
2210 return ;
2211 TPUpdateVisibility( theControl ) ;
2212 STPTextPaneVars *varsp = (STPTextPaneVars *) ((wxMacMLTEClassicControl*)textctrl->GetPeer())->m_macTXNvars ;
2213 if (textctrl->MacIsReallyShown()) {
2214 /* if we're not active, then we have nothing to say about the cursor */
2215 if (varsp->fIsActive) {
2216 Rect bounds;
2217 Point mousep;
7d8268a1 2218
5ca0d812
SC
2219 wxMacWindowClipper clipper( textctrl ) ;
2220 GetMouse(&mousep);
2221 /* there's a 'focus thing' and an 'unfocused thing' */
2222 if (varsp->fInFocus) {
2223 /* flash the cursor */
2224 SetPort(varsp->fDrawingEnvironment);
2225 TXNIdle(varsp->fTXNRec);
2226 /* set the cursor */
2227 if (PtInRect(mousep, &varsp->fRTextArea)) {
2228 RgnHandle theRgn;
2229 RectRgn((theRgn = NewRgn()), &varsp->fRTextArea);
2230 TXNAdjustCursor(varsp->fTXNRec, theRgn);
2231 DisposeRgn(theRgn);
ed8c2780 2232 }
5ca0d812 2233 else
ed8c2780 2234 {
5ca0d812
SC
2235 // SetThemeCursor(kThemeArrowCursor);
2236 }
2237 } else {
2238 /* if it's in our bounds, set the cursor */
2239 UMAGetControlBoundsInWindowCoords(theControl, &bounds);
2240 if (PtInRect(mousep, &bounds))
2241 {
2242 // SetThemeCursor(kThemeArrowCursor);
ed8c2780 2243 }
72055702 2244 }
5ca0d812
SC
2245 }
2246 }
2247}
72055702 2248
72055702 2249
5ca0d812
SC
2250/* TPPaneKeyDownProc is called whenever a keydown event is directed
2251at our control. Here, we direct the keydown event to the text
2252edit record and redraw the scroll bar and text field as appropriate. */
2253static pascal ControlPartCode TPPaneKeyDownProc(ControlRef theControl,
2254 SInt16 keyCode, SInt16 charCode, SInt16 modifiers) {
7d8268a1 2255
5ca0d812
SC
2256 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
2257 if ( textctrl == NULL )
2258 return 0;
2259 TPUpdateVisibility( theControl ) ;
7d8268a1 2260
5ca0d812 2261 STPTextPaneVars *varsp = (STPTextPaneVars *) ((wxMacMLTEClassicControl*)textctrl->GetPeer())->m_macTXNvars ;
7d8268a1 2262 if (varsp->fInFocus)
5ca0d812
SC
2263 {
2264 /* turn autoscrolling on and send the key event to text edit */
2265 wxMacWindowClipper clipper( textctrl ) ;
2266 EventRecord ev ;
2267 memset( &ev , 0 , sizeof( ev ) ) ;
2268 ev.what = keyDown ;
2269 ev.modifiers = modifiers ;
2270 ev.message = (( keyCode << 8 ) & keyCodeMask ) + ( charCode & charCodeMask ) ;
2271 TXNKeyDown( varsp->fTXNRec, &ev);
72055702 2272 }
5ca0d812
SC
2273 return kControlEntireControl;
2274}
ef4a634b 2275
1ea39a03 2276
5ca0d812
SC
2277/* TPPaneActivateProc is called when the window containing
2278the user pane control receives activate events. Here, we redraw
2279the control and it's text as necessary for the activation state. */
2280static pascal void TPPaneActivateProc(ControlRef theControl, Boolean activating) {
2281 /* set up locals */
2282 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
7d8268a1 2283
5ca0d812
SC
2284 if ( textctrl == NULL )
2285 return ;
2286 TPUpdateVisibility( theControl ) ;
7d8268a1 2287
5ca0d812 2288 STPTextPaneVars *varsp = (STPTextPaneVars *) ((wxMacMLTEClassicControl*)textctrl->GetPeer())->m_macTXNvars ;
7d8268a1 2289
5ca0d812
SC
2290 varsp->fIsActive = activating;
2291 wxMacWindowClipper clipper( textctrl ) ;
2292 TPActivatePaneText(varsp, varsp->fIsActive && varsp->fInFocus);
2293 /* redraw the frame */
2294 if ( textctrl->MacIsReallyShown() )
1b2b1638 2295 {
5ca0d812 2296 if ( !varsp->fNoBorders )
7d8268a1 2297 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
5ca0d812 2298 TPRedrawFocusOutline( varsp ) ;
ed8c2780 2299 }
72055702
SC
2300}
2301
72055702 2302
5ca0d812
SC
2303/* TPPaneFocusProc is called when every the focus changes to or
2304from our control. Herein, switch the focus appropriately
2305according to the parameters and redraw the control as
2306necessary. */
2307static pascal ControlPartCode TPPaneFocusProc(ControlRef theControl, ControlFocusPart action) {
2308 ControlPartCode focusResult;
7d8268a1 2309
5ca0d812
SC
2310 focusResult = kControlFocusNoPart;
2311 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
2312 if ( textctrl == NULL )
2313 return 0;
2314 TPUpdateVisibility( theControl ) ;
2315 STPTextPaneVars *varsp = (STPTextPaneVars *) ((wxMacMLTEClassicControl*)textctrl->GetPeer())->m_macTXNvars ;
2316 /* if kControlFocusPrevPart and kControlFocusNextPart are received when the user is
2317 tabbing forwards (or shift tabbing backwards) through the items in the dialog,
2318 and kControlFocusNextPart will be received. When the user clicks in our field
2319 and it is not the current focus, then the constant kUserClickedToFocusPart will
2320 be received. The constant kControlFocusNoPart will be received when our control
2321 is the current focus and the user clicks in another control. In your focus routine,
2322 you should respond to these codes as follows:
7d8268a1 2323
5ca0d812
SC
2324 kControlFocusNoPart - turn off focus and return kControlFocusNoPart. redraw
2325 the control and the focus rectangle as necessary.
7d8268a1 2326
5ca0d812
SC
2327 kControlFocusPrevPart or kControlFocusNextPart - toggle focus on or off
2328 depending on its current state. redraw the control and the focus rectangle
2329 as appropriate for the new focus state. If the focus state is 'off', return the constant
2330 kControlFocusNoPart, otherwise return a non-zero part code.
2331 kUserClickedToFocusPart - is a constant defined for this example. You should
2332 define your own value for handling click-to-focus type events. */
2333 /* calculate the next highlight state */
2334 switch (action) {
2335 default:
2336 case kControlFocusNoPart:
2337 TPFocusPaneText(varsp, false);
2338 focusResult = kControlFocusNoPart;
2339 break;
2340 case kUserClickedToFocusPart:
2341 TPFocusPaneText(varsp, true);
2342 focusResult = 1;
2343 break;
2344 case kControlFocusPrevPart:
2345 case kControlFocusNextPart:
2346 TPFocusPaneText(varsp, ( ! varsp->fInFocus));
2347 focusResult = varsp->fInFocus ? 1 : kControlFocusNoPart;
2348 break;
2349 }
2350 TPActivatePaneText(varsp, varsp->fIsActive && varsp->fInFocus);
2351 /* redraw the text fram and focus rectangle to indicate the
2352 new focus state */
2353 if ( textctrl->MacIsReallyShown() )
2354 {
2355 wxMacWindowClipper c( textctrl ) ;
2356 if ( !varsp->fNoBorders )
7d8268a1 2357 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
5ca0d812
SC
2358 TPRedrawFocusOutline( varsp ) ;
2359 }
2360 return focusResult;
72055702
SC
2361}
2362
5ca0d812
SC
2363wxMacMLTEClassicControl::wxMacMLTEClassicControl( wxWindow *wxPeer,
2364 const wxString& str,
2365 const wxPoint& pos,
7d8268a1 2366 const wxSize& size, long style )
72055702 2367{
5ca0d812
SC
2368 m_font = wxPeer->GetFont() ;
2369 m_windowStyle = style ;
7d8268a1 2370 Rect bounds = wxMacGetBoundsForControl( wxPeer , pos , size ) ;
5ca0d812 2371 wxString st = str ;
395480fb 2372 wxMacConvertNewlines10To13( &st ) ;
72055702 2373
5ca0d812 2374 short featurSet;
72055702 2375
5ca0d812
SC
2376 featurSet = kControlSupportsEmbedding | kControlSupportsFocus | kControlWantsIdle
2377 | kControlWantsActivate | kControlHandlesTracking | kControlHasSpecialBackground
2378 | kControlGetsFocusOnClick | kControlSupportsLiveFeedback;
2379 /* create the control */
72055702 2380
5ca0d812 2381 verify_noerr( ::CreateUserPaneControl( MAC_WXHWND(wxPeer->GetParent()->MacGetTopLevelWindowRef()), &bounds, featurSet, &m_controlRef ) );
7d8268a1 2382
5ca0d812
SC
2383 {
2384// wxMacWindowClipper c(wxPeer) ;
2385 DoCreate();
2386 }
7d8268a1 2387
5ca0d812
SC
2388 if ( wxPeer->MacIsReallyShown() )
2389 MLTESetObjectVisibility( (STPTextPaneVars*) m_macTXNvars, true , style ) ;
72055702 2390
5ca0d812 2391 {
7d8268a1 2392 // wxMacWindowClipper clipper( wxPeer ) ;
72055702 2393
5ca0d812
SC
2394 TPUpdateVisibility( m_controlRef ) ;
2395
2396 SetTXNData( st , kTXNStartOffset, kTXNEndOffset ) ;
2397
2398 TXNSetSelection( m_txn, 0, 0);
2399 TXNShowSelection( m_txn, kTXNShowStart);
7d8268a1
WS
2400 }
2401
5ca0d812 2402 AdjustCreationAttributes( *wxWHITE , true ) ;
72055702
SC
2403}
2404
5ca0d812 2405wxMacMLTEClassicControl::~wxMacMLTEClassicControl()
72055702 2406{
5ca0d812
SC
2407// SetControlReference(m_controlRef , 0) ;
2408 TXNDeleteObject(m_txn);
2409 free(m_macTXNvars);
72055702
SC
2410}
2411
7d8268a1 2412void wxMacMLTEClassicControl::VisibilityChanged(bool shown)
72055702 2413{
5ca0d812
SC
2414 MLTESetObjectVisibility((STPTextPaneVars*) m_macTXNvars , shown , m_windowStyle ) ;
2415 if ( !shown )
2416 InvalWindowRect( GetControlOwner( m_controlRef ) , &((STPTextPaneVars *)m_macTXNvars)->fRBounds ) ;
72055702
SC
2417}
2418
7d8268a1 2419bool wxMacMLTEClassicControl::NeedsFocusRect() const
eda3f2b4
SC
2420{
2421 return true;
2422}
2423
5ca0d812 2424OSStatus wxMacMLTEClassicControl::DoCreate()
2b5f62a0 2425{
5ca0d812
SC
2426 Rect bounds;
2427 WindowRef theWindow;
2428
2429 OSStatus err = noErr ;
7d8268a1 2430
5ca0d812
SC
2431 /* set up our globals */
2432 if (gTPDrawProc == NULL) gTPDrawProc = NewControlUserPaneDrawUPP(TPPaneDrawProc);
2433 if (gTPHitProc == NULL) gTPHitProc = NewControlUserPaneHitTestUPP(TPPaneHitTestProc);
2434 if (gTPTrackProc == NULL) gTPTrackProc = NewControlUserPaneTrackingUPP(TPPaneTrackingProc);
2435 if (gTPIdleProc == NULL) gTPIdleProc = NewControlUserPaneIdleUPP(TPPaneIdleProc);
2436 if (gTPKeyProc == NULL) gTPKeyProc = NewControlUserPaneKeyDownUPP(TPPaneKeyDownProc);
2437 if (gTPActivateProc == NULL) gTPActivateProc = NewControlUserPaneActivateUPP(TPPaneActivateProc);
2438 if (gTPFocusProc == NULL) gTPFocusProc = NewControlUserPaneFocusUPP(TPPaneFocusProc);
7d8268a1 2439
5ca0d812
SC
2440 /* allocate our private storage */
2441 m_macTXNvars = (STPTextPaneVars *) malloc(sizeof(STPTextPaneVars));
7d8268a1 2442
5ca0d812
SC
2443 /* set the initial settings for our private data */
2444 m_macTXNvars->fMultiline = m_windowStyle & wxTE_MULTILINE ;
2445 m_macTXNvars->fNoBorders = m_windowStyle & wxNO_BORDER ;
2446 m_macTXNvars->fInFocus = false;
2447 m_macTXNvars->fIsActive = true;
7d8268a1 2448 m_macTXNvars->fTXNObjectActive = false;
5ca0d812
SC
2449 m_macTXNvars->fFocusDrawState = false ;
2450 m_macTXNvars->fUserPaneRec = m_controlRef ;
2451 m_macTXNvars->fVisible = true ;
7d8268a1 2452
5ca0d812 2453 theWindow = m_macTXNvars->fOwner = GetControlOwner(m_controlRef);
7d8268a1 2454
5ca0d812 2455 m_macTXNvars->fDrawingEnvironment = (GrafPtr) GetWindowPort(theWindow);
7d8268a1 2456
5ca0d812
SC
2457 /* set up the user pane procedures */
2458 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneDrawProcTag, sizeof(gTPDrawProc), &gTPDrawProc);
2459 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneHitTestProcTag, sizeof(gTPHitProc), &gTPHitProc);
2460 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneTrackingProcTag, sizeof(gTPTrackProc), &gTPTrackProc);
2461 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneIdleProcTag, sizeof(gTPIdleProc), &gTPIdleProc);
2462 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneKeyDownProcTag, sizeof(gTPKeyProc), &gTPKeyProc);
2463 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneActivateProcTag, sizeof(gTPActivateProc), &gTPActivateProc);
2464 SetControlData(m_controlRef, kControlEntireControl, kControlUserPaneFocusProcTag, sizeof(gTPFocusProc), &gTPFocusProc);
7d8268a1 2465
5ca0d812
SC
2466 /* calculate the rectangles used by the control */
2467 UMAGetControlBoundsInWindowCoords(m_controlRef, &bounds);
2468 m_macTXNvars->fRTextOutlineRegion = NewRgn() ;
2469 TPCalculateBounds( m_macTXNvars , bounds ) ;
7d8268a1 2470
5ca0d812
SC
2471 /* set up the drawing environment */
2472 SetPort(m_macTXNvars->fDrawingEnvironment);
7d8268a1 2473
5ca0d812 2474 /* create the new edit field */
7d8268a1 2475
5ca0d812 2476 TXNFrameOptions frameOptions = FrameOptionsFromWXStyle( m_windowStyle ) ;
7d8268a1 2477
5ca0d812
SC
2478 verify_noerr(TXNNewObject(NULL, m_macTXNvars->fOwner, &m_macTXNvars->fRTextArea,
2479 frameOptions ,
2480 kTXNTextEditStyleFrameType,
2481 kTXNTextensionFile,
2482 kTXNSystemDefaultEncoding,
2483 &m_macTXNvars->fTXNRec, &m_macTXNvars->fTXNFrame, (TXNObjectRefcon) m_macTXNvars));
2484 m_txn = m_macTXNvars->fTXNRec ;
7d8268a1 2485
5ca0d812
SC
2486 /* perform final activations and setup for our text field. Here,
2487 we assume that the window is going to be the 'active' window. */
2488 TPActivatePaneText(m_macTXNvars, m_macTXNvars->fIsActive && m_macTXNvars->fInFocus);
2489 /* all done */
2490 return err;
facd6764
SC
2491}
2492
5ca0d812
SC
2493// ----------------------------------------------------------------------------
2494// MLTE control implementation (OSX part)
2495// ----------------------------------------------------------------------------
facd6764 2496
5ca0d812 2497#if TARGET_API_MAC_OSX
facd6764 2498
3b92f0e0
SC
2499#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
2500
5ca0d812
SC
2501wxMacMLTEHIViewControl::wxMacMLTEHIViewControl( wxWindow *wxPeer,
2502 const wxString& str,
2503 const wxPoint& pos,
7d8268a1 2504 const wxSize& size, long style )
facd6764 2505{
5ca0d812
SC
2506 m_font = wxPeer->GetFont() ;
2507 m_windowStyle = style ;
7d8268a1 2508 Rect bounds = wxMacGetBoundsForControl( wxPeer , pos , size ) ;
5ca0d812 2509 wxString st = str ;
395480fb 2510 wxMacConvertNewlines10To13( &st ) ;
7d8268a1 2511
5ca0d812 2512 HIRect hr = { bounds.left , bounds.top , bounds.right - bounds.left , bounds.bottom- bounds.top } ;
facd6764 2513
5ca0d812
SC
2514 m_scrollView = NULL ;
2515 TXNFrameOptions frameOptions = FrameOptionsFromWXStyle( style ) ;
2516 if ( frameOptions & (kTXNWantVScrollBarMask|kTXNWantHScrollBarMask) )
2517 {
7d8268a1 2518 HIScrollViewCreate(( frameOptions & kTXNWantHScrollBarMask ? kHIScrollViewOptionsHorizScroll : 0) |
5ca0d812 2519 ( frameOptions & kTXNWantVScrollBarMask ? kHIScrollViewOptionsVertScroll: 0 ) , &m_scrollView ) ;
7d8268a1
WS
2520
2521 HIViewSetFrame( m_scrollView, &hr );
2522 HIViewSetVisible( m_scrollView, true );
5ca0d812 2523 }
7d8268a1 2524
5ca0d812
SC
2525 m_textView = NULL ;
2526 HITextViewCreate( NULL , 0, frameOptions , &m_textView ) ;
2527 m_txn = HITextViewGetTXNObject( m_textView) ;
2528 HIViewSetVisible( m_textView , true ) ;
2529 if ( m_scrollView )
2530 {
2531 HIViewAddSubview( m_scrollView , m_textView ) ;
2532 m_controlRef = m_scrollView ;
2533 wxPeer->MacInstallEventHandler( (WXWidget) m_textView ) ;
2534 }
2535 else
2536 {
7d8268a1 2537 HIViewSetFrame( m_textView, &hr );
5ca0d812
SC
2538 m_controlRef = m_textView ;
2539 }
7d8268a1 2540
5ca0d812
SC
2541 SetTXNData( st , kTXNStartOffset, kTXNEndOffset ) ;
2542
2543 TXNSetSelection( m_txn, 0, 0);
2544 TXNShowSelection( m_txn, kTXNShowStart);
2545
2546 AdjustCreationAttributes( *wxWHITE , true ) ;
facd6764
SC
2547}
2548
7d8268a1 2549OSStatus wxMacMLTEHIViewControl::SetFocus( ControlFocusPart focusPart )
facd6764 2550{
7d8268a1 2551 return SetKeyboardFocus( GetControlOwner( m_textView ) ,
5ca0d812 2552 m_textView , focusPart ) ;
facd6764
SC
2553}
2554
7d8268a1 2555bool wxMacMLTEHIViewControl::HasFocus() const
facd6764 2556{
5ca0d812
SC
2557 ControlRef control ;
2558 GetKeyboardFocus( GetUserFocusWindow() , &control ) ;
2559 return control == m_textView ;
facd6764
SC
2560}
2561
7d8268a1 2562bool wxMacMLTEHIViewControl::NeedsFocusRect() const
facd6764 2563{
7b8373b3 2564 return m_windowStyle & wxNO_BORDER ? false : true;
2b5f62a0 2565}
72055702 2566
3b92f0e0
SC
2567#endif // MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
2568
2569
fedad417 2570#endif
5ca0d812
SC
2571
2572#endif // wxUSE_TEXTCTRL