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