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