1 ///////////////////////////////////////////////////////////////////////////// 
   8 // Copyright:   (c) AUTHOR 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation "textctrl.h" 
  21   #include <sys/types.h> 
  30 #include "wx/button.h" 
  31 #include "wx/toplevel.h" 
  32 #include "wx/textctrl.h" 
  33 #include "wx/notebook.h" 
  34 #include "wx/tabctrl.h" 
  35 #include "wx/settings.h" 
  36 #include "wx/filefn.h" 
  39 #if defined(__BORLANDC__) && !defined(__WIN32__) 
  41 #elif !defined(__MWERKS__) && !defined(__GNUWIN32) && !defined(__DARWIN__) 
  45 #include "wx/mac/uma.h" 
  49 #if wxUSE_MLTE == 0 // old textctrl implementation 
  51 #if !USE_SHARED_LIBRARY 
  52 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl
, wxControl
) 
  54 BEGIN_EVENT_TABLE(wxTextCtrl
, wxControl
) 
  55     EVT_DROP_FILES(wxTextCtrl::OnDropFiles
) 
  56     EVT_CHAR(wxTextCtrl::OnChar
) 
  57     EVT_MENU(wxID_CUT
, wxTextCtrl::OnCut
) 
  58     EVT_MENU(wxID_COPY
, wxTextCtrl::OnCopy
) 
  59     EVT_MENU(wxID_PASTE
, wxTextCtrl::OnPaste
) 
  60     EVT_MENU(wxID_UNDO
, wxTextCtrl::OnUndo
) 
  61     EVT_MENU(wxID_REDO
, wxTextCtrl::OnRedo
) 
  63     EVT_UPDATE_UI(wxID_CUT
, wxTextCtrl::OnUpdateCut
) 
  64     EVT_UPDATE_UI(wxID_COPY
, wxTextCtrl::OnUpdateCopy
) 
  65     EVT_UPDATE_UI(wxID_PASTE
, wxTextCtrl::OnUpdatePaste
) 
  66     EVT_UPDATE_UI(wxID_UNDO
, wxTextCtrl::OnUpdateUndo
) 
  67     EVT_UPDATE_UI(wxID_REDO
, wxTextCtrl::OnUpdateRedo
) 
  72 wxTextCtrl::wxTextCtrl() 
  76 const short kVerticalMargin 
= 2 ; 
  77 const short kHorizontalMargin 
= 2 ; 
  79 bool wxTextCtrl::Create(wxWindow 
*parent
, wxWindowID id
, 
  82            const wxSize
& size
, long style
, 
  83            const wxValidator
& validator
, 
  86     // base initialization 
  87     if ( !CreateBase(parent
, id
, pos
, size
, style
, validator
, name
) ) 
  90     wxSize mySize 
= size 
; 
  91     if ( UMAHasAppearance() ) 
  93         m_macHorizontalBorder 
= 5 ; // additional pixels around the real control 
  94         m_macVerticalBorder 
= 5 ; 
  98         m_macHorizontalBorder 
= 0 ; // additional pixels around the real control 
  99         m_macVerticalBorder 
= 0 ; 
 106     if ( mySize
.y 
== -1 ) 
 108         if ( UMAHasAppearance() ) 
 113         mySize
.y 
+= 2 * m_macVerticalBorder 
; 
 116     MacPreControlCreate( parent 
, id 
,  "" , pos 
, mySize 
,style
, validator 
, name 
, &bounds 
, title 
) ; 
 118     if ( m_windowStyle 
& wxTE_MULTILINE 
) 
 120         wxASSERT_MSG( !(m_windowStyle 
& wxTE_PROCESS_ENTER
), 
 121                       wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") ); 
 123         m_windowStyle 
|= wxTE_PROCESS_ENTER
; 
 127     m_macControl 
= ::NewControl( parent
->MacGetRootWindow() , &bounds 
, "\p" , true , 0 , 0 , 1,  
 128         ( style 
& wxTE_PASSWORD 
) ? kControlEditTextPasswordProc 
: kControlEditTextProc 
, (long) this ) ; 
 129     MacPostControlCreate() ; 
 137         ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
 138         (*teH
)->lineHeight 
= -1 ; 
 141     if( wxApp::s_macDefaultEncodingIsPC 
) 
 142         value 
= wxMacMakeMacStringFromPC( st 
) ; 
 145     ::SetControlData( m_macControl
, 0, ( m_windowStyle 
& wxTE_PASSWORD 
) ? kControlEditTextPasswordTag 
: kControlEditTextTextTag 
, value
.Length() , (char*) ((const char*)value
) ) ; 
 150 wxString 
wxTextCtrl::GetValue() const 
 153     ::GetControlData( m_macControl
, 0, ( m_windowStyle 
& wxTE_PASSWORD 
) ? kControlEditTextPasswordTag 
: kControlEditTextTextTag 
, 32767 , wxBuffer 
, &actualsize
) ; 
 154     wxBuffer
[actualsize
] = 0 ; 
 155     if( wxApp::s_macDefaultEncodingIsPC 
) 
 156         return wxMacMakePCStringFromMac( wxBuffer 
) ; 
 158         return wxString(wxBuffer
); 
 161 void wxTextCtrl::GetSelection(long* from
, long* to
) const 
 163    ControlEditTextSelectionRec selection 
; 
 167    ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
 169     *from 
= (**teH
).selStart
; 
 170     *to 
= (**teH
).selEnd
; 
 173 void wxTextCtrl::SetValue(const wxString
& st
) 
 177     if( wxApp::s_macDefaultEncodingIsPC 
) 
 178         value 
= wxMacMakeMacStringFromPC( st 
) ; 
 181     ::SetControlData( m_macControl
, 0, ( m_windowStyle 
& wxTE_PASSWORD 
) ? kControlEditTextPasswordTag 
: kControlEditTextTextTag 
, value
.Length() , (char*) ((const char*)value
) ) ; 
 182     WindowRef window 
= MacGetRootWindow() ; 
 185         wxWindow
* win 
= wxFindWinFromMacWindow( window 
) ; 
 188             wxMacDrawingHelper 
help( win 
) ; 
 189             // the mac control manager always assumes to have the origin at 0,0 
 192             bool            hasTabBehind 
= false ; 
 193             wxWindow
* parent 
= GetParent() ; 
 196                 if( parent
->IsTopLevel() ) 
 198 //                    ::SetThemeWindowBackground( win->MacGetRootWindow() , kThemeBrushDialogBackgroundActive , false ) ; 
 202                 if( parent
->IsKindOf( CLASSINFO( wxNotebook 
) ) ||  parent
->IsKindOf( CLASSINFO( wxTabCtrl 
) )) 
 204                     if ( ((wxControl
*)parent
)->GetMacControl() ) 
 205                         SetUpControlBackground( ((wxControl
*)parent
)->GetMacControl() , -1 , true ) ; 
 209                 parent 
= parent
->GetParent() ; 
 212             UMADrawControl( m_macControl 
) ; 
 213 //            ::SetThemeWindowBackground( win->MacGetWindowData()->m_macWindow , win->MacGetWindowData()->m_macWindowBackgroundTheme , false ) ; 
 218 // Clipboard operations 
 219 void wxTextCtrl::Copy() 
 226                   ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
 233 void wxTextCtrl::Cut() 
 240                   ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
 244                     //  MacInvalidateControl() ; 
 248 void wxTextCtrl::Paste() 
 255         ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
 258         WindowRef window 
= MacGetRootWindow() ; 
 261             wxWindow
* win 
= wxFindWinFromMacWindow( window 
) ; 
 264                 wxMacDrawingHelper 
help( win 
) ; 
 265                 // the mac control manager always assumes to have the origin at 0,0 
 268                 bool            hasTabBehind 
= false ; 
 269                 wxWindow
* parent 
= GetParent() ; 
 272                     if( parent
->IsTopLevel() ) 
 274 //                        ::SetThemeWindowBackground( win->MacGetWindowData()->m_macWindow , kThemeBrushDialogBackgroundActive , false ) ; 
 278                     if( parent
->IsKindOf( CLASSINFO( wxNotebook 
) ) ||  parent
->IsKindOf( CLASSINFO( wxTabCtrl 
) )) 
 280                         if ( ((wxControl
*)parent
)->GetMacControl() ) 
 281                             SetUpControlBackground( ((wxControl
*)parent
)->GetMacControl() , -1 , true ) ; 
 285                     parent 
= parent
->GetParent() ; 
 288                 UMADrawControl( m_macControl 
) ; 
 289 //                ::SetThemeWindowBackground( win->MacGetWindowData()->m_macWindow , win->MacGetWindowData()->m_macWindowBackgroundTheme , false ) ; 
 295 bool wxTextCtrl::CanCopy() const 
 297     // Can copy if there's a selection 
 299     GetSelection(& from
, & to
); 
 303 bool wxTextCtrl::CanCut() const 
 305     // Can cut if there's a selection 
 307     GetSelection(& from
, & to
); 
 311 bool wxTextCtrl::CanPaste() const 
 318     OSStatus err 
= noErr
; 
 321     err 
= GetCurrentScrap( &scrapRef 
); 
 322     if ( err 
!= noTypeErr 
&& err 
!= memFullErr 
)     
 324         ScrapFlavorFlags    flavorFlags
; 
 327         if (( err 
= GetScrapFlavorFlags( scrapRef
, 'TEXT', &flavorFlags 
)) == noErr
) 
 329             if (( err 
= GetScrapFlavorSize( scrapRef
, 'TEXT', &byteCount 
)) == noErr
) 
 338     if ( GetScrap( NULL 
, 'TEXT' , &offset 
) > 0 ) 
 346 void wxTextCtrl::SetEditable(bool editable
) 
 349         UMAActivateControl( m_macControl 
) ; 
 351         UMADeactivateControl( m_macControl 
) ; 
 354 void wxTextCtrl::SetInsertionPoint(long pos
) 
 356     SetSelection( pos 
, pos 
) ; 
 359 void wxTextCtrl::SetInsertionPointEnd() 
 361     long pos 
= GetLastPosition(); 
 362     SetInsertionPoint(pos
); 
 365 long wxTextCtrl::GetInsertionPoint() const 
 367    ControlEditTextSelectionRec selection 
; 
 371    ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
 372 //   ::GetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection , &size ) ; 
 373     return (**teH
).selStart 
; 
 376 long wxTextCtrl::GetLastPosition() const 
 378    ControlEditTextSelectionRec selection 
; 
 382    ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
 384 //   ::GetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection , &size ) ; 
 385     return (**teH
).teLength 
; 
 388 void wxTextCtrl::Replace(long from
, long to
, const wxString
& value
) 
 393     ControlEditTextSelectionRec selection 
; 
 395     selection
.selStart 
= from 
; 
 396     selection
.selEnd 
= to 
; 
 397     ::SetControlData( m_macControl 
, 0, kControlEditTextSelectionTag 
, sizeof( selection 
) , (char*) &selection 
) ; 
 398         ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
 399     TESetSelect( from 
, to  
, teH 
) ; 
 401         TEInsert( value 
, value
.Length() , teH 
) ; 
 405 void wxTextCtrl::Remove(long from
, long to
) 
 410     ControlEditTextSelectionRec selection 
; 
 412     selection
.selStart 
= from 
; 
 413     selection
.selEnd 
= to 
; 
 414     ::SetControlData( m_macControl 
, 0, kControlEditTextSelectionTag 
, sizeof( selection 
) , (char*) &selection 
) ; 
 415     ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
 420 void wxTextCtrl::SetSelection(long from
, long to
) 
 422    ControlEditTextSelectionRec selection 
; 
 426    ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
 428    selection
.selStart 
= from 
; 
 429    selection
.selEnd 
= to 
; 
 431    ::SetControlData( m_macControl 
, 0, kControlEditTextSelectionTag 
, sizeof( selection 
) , (char*) &selection 
) ; 
 432    TESetSelect( selection
.selStart 
, selection
.selEnd 
, teH 
) ; 
 435 bool wxTextCtrl::LoadFile(const wxString
& file
) 
 437     if ( wxTextCtrlBase::LoadFile(file
) ) 
 445 void wxTextCtrl::WriteText(const wxString
& text
) 
 450     memcpy( wxBuffer
, text 
, text
.Length() ) ; 
 451     wxBuffer
[text
.Length() ] = 0 ; 
 452 //    wxMacConvertNewlines( wxBuffer , wxBuffer ) ; 
 454     ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
 456         TEInsert( wxBuffer 
, strlen( wxBuffer
) , teH 
) ; 
 460 void wxTextCtrl::AppendText(const wxString
& text
) 
 462     SetInsertionPointEnd(); 
 466 void wxTextCtrl::Clear() 
 468     ::SetControlData( m_macControl
, 0, ( m_windowStyle 
& wxTE_PASSWORD 
) ? kControlEditTextPasswordTag 
: kControlEditTextTextTag 
, 0 , (char*) ((const char*)NULL
) ) ; 
 472 bool wxTextCtrl::IsModified() const 
 477 bool wxTextCtrl::IsEditable() const 
 482 bool wxTextCtrl::AcceptsFocus() const 
 484     // we don't want focus if we can't be edited 
 485     return IsEditable() && wxControl::AcceptsFocus(); 
 488 wxSize 
wxTextCtrl::DoGetBestSize() const 
 493         if ( UMAHasAppearance() ) 
 497     hText 
+= 2 * m_macHorizontalBorder 
; 
 500     wxGetCharSize(GetHWND(), &cx, &cy, &GetFont()); 
 502     int wText = DEFAULT_ITEM_WIDTH; 
 504     int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy); 
 506     return wxSize(wText, hText); 
 508     if ( m_windowStyle 
& wxTE_MULTILINE 
) 
 510         hText 
*= wxMin(GetNumberOfLines(), 5); 
 512     //else: for single line control everything is ok 
 513     return wxSize(wText
, hText
); 
 516 // ---------------------------------------------------------------------------- 
 518 // ---------------------------------------------------------------------------- 
 520 void wxTextCtrl::Undo() 
 527 void wxTextCtrl::Redo() 
 534 bool wxTextCtrl::CanUndo() const 
 539 bool wxTextCtrl::CanRedo() const 
 544 // Makes 'unmodified' 
 545 void wxTextCtrl::DiscardEdits() 
 550 int wxTextCtrl::GetNumberOfLines() const 
 553     ::GetControlData( m_macControl
, 0, ( m_windowStyle 
& wxTE_PASSWORD 
) ? kControlEditTextPasswordTag 
: kControlEditTextTextTag 
, 32767 , wxBuffer 
, &actualsize
) ; 
 556     for (int i 
= 0; i 
< actualsize
; i
++) 
 558         if (wxBuffer
[i
] == '\r') count
++; 
 564 long wxTextCtrl::XYToPosition(long x
, long y
) const 
 570 bool wxTextCtrl::PositionToXY(long pos
, long *x
, long *y
) const 
 575 void wxTextCtrl::ShowPosition(long pos
) 
 580 int wxTextCtrl::GetLineLength(long lineNo
) const 
 583     ::GetControlData( m_macControl
, 0, ( m_windowStyle 
& wxTE_PASSWORD 
) ? kControlEditTextPasswordTag 
: kControlEditTextTextTag 
, 32767 , wxBuffer 
, &actualsize
) ; 
 587     for (int i 
= 0; i 
< actualsize
; i
++) 
 591             // Count chars in line then 
 593             for (int j 
= i
; j 
< actualsize
; j
++) 
 596                 if (wxBuffer
[j
] == '\r') return count
; 
 601         if (wxBuffer
[i
] == '\r') count
++; 
 607 wxString 
wxTextCtrl::GetLineText(long lineNo
) const 
 610     ::GetControlData( m_macControl
, 0, ( m_windowStyle 
& wxTE_PASSWORD 
) ? kControlEditTextPasswordTag 
: kControlEditTextTextTag 
, 32767 , wxBuffer 
, &actualsize
) ; 
 614     for (int i 
= 0; i 
< actualsize
; i
++) 
 618             // Add chars in line then 
 621             for (int j 
= i
; j 
< actualsize
; j
++) 
 623                 if (wxBuffer
[j
] == '\r') 
 631         if (wxBuffer
[i
] == '\r') count
++; 
 641 void wxTextCtrl::Command(wxCommandEvent 
& event
) 
 643     SetValue (event
.GetString()); 
 644     ProcessCommand (event
); 
 647 void wxTextCtrl::OnDropFiles(wxDropFilesEvent
& event
) 
 649     // By default, load the first file into the text window. 
 650     if (event
.GetNumberOfFiles() > 0) 
 652         LoadFile(event
.GetFiles()[0]); 
 656 void wxTextCtrl::OnChar(wxKeyEvent
& key_event
) 
 658     bool eat_key 
= FALSE
; 
 660     switch ( key_event
.KeyCode() ) 
 663             if (m_windowStyle 
& wxPROCESS_ENTER
) 
 665                 wxCommandEvent 
event(wxEVT_COMMAND_TEXT_ENTER
, m_windowId
); 
 666                 event
.SetEventObject( this ); 
 667                 event
.SetString( GetValue() ); 
 668                 if ( GetEventHandler()->ProcessEvent(event
) ) 
 671             if ( !(m_windowStyle 
& wxTE_MULTILINE
) ) 
 673                 wxWindow 
*parent 
= GetParent(); 
 674                 while( parent 
&& !parent
->IsTopLevel() && parent
->GetDefaultItem() == NULL 
) { 
 675                   parent 
= parent
->GetParent() ; 
 677                 if ( parent 
&& parent
->GetDefaultItem() ) 
 679                     wxButton 
*def 
= wxDynamicCast(parent
->GetDefaultItem(), 
 681                     if ( def 
&& def
->IsEnabled() ) 
 683                         wxCommandEvent 
event(wxEVT_COMMAND_BUTTON_CLICKED
, def
->GetId() ); 
 684                         event
.SetEventObject(def
); 
 690                 // this will make wxWindows eat the ENTER key so that 
 691                 // we actually prevent line wrapping in a single line 
 699             // always produce navigation event - even if we process TAB 
 700             // ourselves the fact that we got here means that the user code 
 701             // decided to skip processing of this TAB - probably to let it 
 702             // do its default job. 
 704                 wxNavigationKeyEvent eventNav
; 
 705                 eventNav
.SetDirection(!key_event
.ShiftDown()); 
 706                 eventNav
.SetWindowChange(key_event
.ControlDown()); 
 707                 eventNav
.SetEventObject(this); 
 709                 if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav
) ) 
 718     EventRecord 
*ev 
= wxTheApp
->MacGetCurrentEvent(); 
 719     short keychar 
= short(ev
->message 
& charCodeMask
); 
 722         short keycode 
= short(ev
->message 
& keyCodeMask
) >> 8 ; 
 723         ::HandleControlKey( m_macControl 
, keycode 
, keychar 
, ev
->modifiers 
); 
 725     if ( keychar 
>= 0x20 || 
 726          key_event
.KeyCode() == WXK_RETURN 
|| 
 727          key_event
.KeyCode() == WXK_DELETE 
||  
 728          key_event
.KeyCode() == WXK_BACK
) 
 730         wxCommandEvent 
event(wxEVT_COMMAND_TEXT_UPDATED
, m_windowId
); 
 731         event
.SetString( GetValue() ) ; 
 732         event
.SetEventObject( this ); 
 733         GetEventHandler()->ProcessEvent(event
); 
 737 // ---------------------------------------------------------------------------- 
 738 // standard handlers for standard edit menu events 
 739 // ---------------------------------------------------------------------------- 
 741 void wxTextCtrl::OnCut(wxCommandEvent
& event
) 
 746 void wxTextCtrl::OnCopy(wxCommandEvent
& event
) 
 751 void wxTextCtrl::OnPaste(wxCommandEvent
& event
) 
 756 void wxTextCtrl::OnUndo(wxCommandEvent
& event
) 
 761 void wxTextCtrl::OnRedo(wxCommandEvent
& event
) 
 766 void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent
& event
) 
 768     event
.Enable( CanCut() ); 
 771 void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent
& event
) 
 773     event
.Enable( CanCopy() ); 
 776 void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent
& event
) 
 778     event
.Enable( CanPaste() ); 
 781 void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent
& event
) 
 783     event
.Enable( CanUndo() ); 
 786 void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent
& event
) 
 788     event
.Enable( CanRedo() ); 
 793 extern wxApp 
*wxTheApp 
; 
 794 // CS:We will replace the TextEdit by using the MultiLanguageTextEngine based on the following code written by apple 
 800         mUPControl implementation. 
 803         © Copyright 2000 Apple Computer, Inc. All rights reserved. 
 806         IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc. 
 807         ("Apple") in consideration of your agreement to the following terms, and your 
 808         use, installation, modification or redistribution of this Apple software 
 809         constitutes acceptance of these terms.  If you do not agree with these terms, 
 810         please do not use, install, modify or redistribute this Apple software. 
 812         In consideration of your agreement to abide by the following terms, and subject 
 813         to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs 
 814         copyrights in this original Apple software (the "Apple Software"), to use, 
 815         reproduce, modify and redistribute the Apple Software, with or without 
 816         modifications, in source and/or binary forms; provided that if you redistribute 
 817         the Apple Software in its entirety and without modifications, you must retain 
 818         this notice and the following text and disclaimers in all such redistributions of 
 819         the Apple Software.  Neither the name, trademarks, service marks or logos of 
 820         Apple Computer, Inc. may be used to endorse or promote products derived from the 
 821         Apple Software without specific prior written permission from Apple.  Except as 
 822         expressly stated in this notice, no other rights or licenses, express or implied, 
 823         are granted by Apple herein, including but not limited to any patent rights that 
 824         may be infringed by your derivative works or by other works in which the Apple 
 825         Software may be incorporated. 
 827         The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO 
 828         WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED 
 829         WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 830         PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN 
 831         COMBINATION WITH YOUR PRODUCTS. 
 833         IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR 
 834         CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
 835         GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 836         ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION 
 837         OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT 
 838         (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN 
 839         ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 841     Change History (most recent first): 
 842         Fri, Jan 28, 2000 -- created 
 845 #include "MacTextEditor.h" 
 849 /* kmUPTextPart is the part code we return to indicate the user has clicked 
 850     in the text area of our control */ 
 851 #define kmUPTextPart 1 
 853 /* kmUPScrollPart is the part code we return to indicate the user has clicked 
 854     in the scroll bar part of the control. */ 
 855 #define kmUPScrollPart 2 
 858 /* routines for using existing user pane controls. 
 859     These routines are useful for cases where you would like to use an 
 860     existing user pane control in, say, a dialog window as a scrolling 
 863 /* mUPOpenControl initializes a user pane control so it will be drawn 
 864     and will behave as a scrolling text edit field inside of a window. 
 865     This routine performs all of the initialization steps necessary, 
 866     except it does not create the user pane control itself.  theControl 
 867     should refer to a user pane control that you have either created 
 868     yourself or extracted from a dialog's control heirarchy using 
 869     the GetDialogItemAsControl routine.  */ 
 870 OSStatus 
mUPOpenControl(ControlHandle theControl
); 
 872 /* mUPCloseControl deallocates all of the structures allocated 
 873     by mUPOpenControl.  */ 
 874 OSStatus 
mUPCloseControl(ControlHandle theControl
); 
 878 /* routines for creating new scrolling text user pane controls. 
 879     These routines allow you to create new scrolling text 
 880     user pane controls. */ 
 882 /* mUPCreateControl creates a new user pane control and then it passes it 
 883     to mUPOpenControl to initialize it as a scrolling text user pane control. */ 
 884 OSStatus 
mUPCreateControl(WindowPtr theWindow
, Rect 
*bounds
, ControlHandle 
*theControl
); 
 886 /* mUPDisposeControl calls mUPCloseControl and then it calls DisposeControl. */ 
 887 OSStatus 
mUPDisposeControl(ControlHandle theControl
); 
 890 /* Utility Routines */ 
 892     /* mUPSetText replaces the contents of the selection with the unicode 
 893     text described by the text and count parameters:. 
 894         text = pointer to unicode text buffer 
 895         count = number of bytes in the buffer.  */ 
 896 OSStatus 
mUPSetText(ControlHandle theControl
, char* text
, long count
); 
 898 /* mUPGetText returns the current text data being displayed inside of 
 899     the mUPControl.  When noErr is returned, *theText contain a new 
 900     handle containing all of the Unicode text copied from the current 
 901     selection.  It is the caller's responsibiliby to dispose of this handle. */ 
 902 OSStatus 
mUPGetText(ControlHandle theControl
, Handle 
*theText
); 
 905 /* mUPSetSelection sets the text selection and autoscrolls the text view 
 906     so either the cursor or the selction is in the view. */ 
 907 void mUPSetSelection(ControlHandle theControl
, long selStart
, long selEnd
); 
 911 /* IsmUPControl returns true if theControl is not NULL 
 912     and theControl refers to a mUP Control.  */ 
 913 Boolean 
IsmUPControl(ControlHandle theControl
); 
 917 /* Edit commands for mUP Controls. */ 
 926 /* mUPDoEditCommand performs the editing command specified 
 927     in the editCommand parameter.  The mUPControl's text 
 928     and scroll bar are redrawn and updated as necessary. */ 
 929 void mUPDoEditCommand(ControlHandle theControl
, short editCommand
); 
 934 /* mUPGetContents returns the entire contents of the control including the text 
 935     and the formatting information. */ 
 936 OSStatus 
mUPGetContents(ControlHandle theControl
, Handle 
*theContents
); 
 937 /* mUPSetContents replaces the contents of the selection with the data stored in the handle. */ 
 938 OSStatus 
mUPSetContents(ControlHandle theControl
, Handle theContents
); 
 944 /* kUserClickedToFocusPart is a part code we pass to the SetKeyboardFocus 
 945     routine.  In our focus switching routine this part code is understood 
 946     as meaning 'the user has clicked in the control and we need to switch 
 947     the current focus to ourselves before we can continue'. */ 
 948 #define kUserClickedToFocusPart 100 
 951 /* kmUPClickScrollDelayTicks is a time measurement in ticks used to 
 952     slow the speed of 'auto scrolling' inside of our clickloop routine. 
 953     This value prevents the text from wizzzzzing by while the mouse 
 954     is being held down inside of the text area. */ 
 955 #define kmUPClickScrollDelayTicks 3 
 958 /* STPTextPaneVars is a structure used for storing the the mUP Control's 
 959     internal variables and state information.  A handle to this record is 
 960     stored in the pane control's reference value field using the 
 961     SetControlReference routine. */ 
 964         /* OS records referenced */ 
 965     TXNObject fTXNRec
; /* the txn record */ 
 966     TXNFrameID fTXNFrame
; /* the txn frame ID */ 
 967     ControlHandle fUserPaneRec
;  /* handle to the user pane control */ 
 968     WindowPtr fOwner
; /* window containing control */ 
 969     GrafPtr fDrawingEnvironment
; /* grafport where control is drawn */ 
 971     Boolean fInFocus
; /* true while the focus rect is drawn around the control */ 
 972     Boolean fIsActive
; /* true while the control is drawn in the active state */ 
 973     Boolean fTEActive
; /* reflects the activation state of the text edit record */  
 974     Boolean fInDialogWindow
; /* true if displayed in a dialog window */  
 975         /* calculated locations */ 
 976     Rect fRTextArea
; /* area where the text is drawn */ 
 977     Rect fRFocusOutline
;  /* rectangle used to draw the focus box */ 
 978     Rect fRTextOutline
; /* rectangle used to draw the border */ 
 979     RgnHandle fTextBackgroundRgn
; /* background region for the text, erased before calling TEUpdate */ 
 980         /* our focus advance override routine */ 
 981     EventHandlerUPP handlerUPP
; 
 982     EventHandlerRef handlerRef
; 
 988 /* Univerals Procedure Pointer variables used by the 
 989     mUP Control.  These variables are set up 
 990     the first time that mUPOpenControl is called. */ 
 991 ControlUserPaneDrawUPP gTPDrawProc 
= NULL
; 
 992 ControlUserPaneHitTestUPP gTPHitProc 
= NULL
; 
 993 ControlUserPaneTrackingUPP gTPTrackProc 
= NULL
; 
 994 ControlUserPaneIdleUPP gTPIdleProc 
= NULL
; 
 995 ControlUserPaneKeyDownUPP gTPKeyProc 
= NULL
; 
 996 ControlUserPaneActivateUPP gTPActivateProc 
= NULL
; 
 997 ControlUserPaneFocusUPP gTPFocusProc 
= NULL
; 
 999     /* events handled by our focus advance override routine */ 
1001 static const EventTypeSpec gMLTEEvents
[] = { { kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent 
} }; 
1002 #define kMLTEEventCount (sizeof( gMLTEEvents ) / sizeof( EventTypeSpec )) 
1006 /* TPActivatePaneText activates or deactivates the text edit record 
1007     according to the value of setActive.  The primary purpose of this 
1008     routine is to ensure each call is only made once. */ 
1009 static void TPActivatePaneText(STPTextPaneVars 
**tpvars
, Boolean setActive
) { 
1010     STPTextPaneVars 
*varsp
; 
1012     if (varsp
->fTEActive 
!= setActive
) { 
1014         varsp
->fTEActive 
= setActive
; 
1016         TXNActivate(varsp
->fTXNRec
, varsp
->fTXNFrame
, varsp
->fTEActive
); 
1018         if (varsp
->fInFocus
) 
1019             TXNFocus( varsp
->fTXNRec
, varsp
->fTEActive
); 
1024 /* TPFocusPaneText set the focus state for the text record. */ 
1025 static void TPFocusPaneText(STPTextPaneVars 
**tpvars
, Boolean setFocus
) { 
1026     STPTextPaneVars 
*varsp
; 
1028     if (varsp
->fInFocus 
!= setFocus
) { 
1029         varsp
->fInFocus 
= setFocus
; 
1030         TXNFocus( varsp
->fTXNRec
, varsp
->fInFocus
); 
1035 /* TPPaneDrawProc is called to redraw the control and for update events 
1036     referring to the control.  This routine erases the text area's background, 
1037     and redraws the text.  This routine assumes the scroll bar has been 
1038     redrawn by a call to DrawControls. */ 
1039 static pascal void TPPaneDrawProc(ControlRef theControl
, ControlPartCode thePart
) { 
1040     STPTextPaneVars 
**tpvars
, *varsp
; 
1043         /* set up our globals */ 
1044     tpvars 
= (STPTextPaneVars 
**) GetControlReference(theControl
); 
1045     if (tpvars 
!= NULL
) { 
1046         state 
= HGetState((Handle
) tpvars
); 
1047         HLock((Handle
) tpvars
); 
1050             /* save the drawing state */ 
1051         SetPort((**tpvars
).fDrawingEnvironment
); 
1052             /* verify our boundary */ 
1053         GetControlBounds(theControl
, &bounds
); 
1054         if ( ! EqualRect(&bounds
, &varsp
->fRTextArea
) ) { 
1055             SetRect(&varsp
->fRFocusOutline
, bounds
.left
, bounds
.top
, bounds
.right
, bounds
.bottom
); 
1056             SetRect(&varsp
->fRTextOutline
, bounds
.left
, bounds
.top
, bounds
.right
, bounds
.bottom
); 
1057             SetRect(&varsp
->fRTextArea
, bounds
.left
, bounds
.top
, bounds
.right
, bounds
.bottom
); 
1058             RectRgn(varsp
->fTextBackgroundRgn
, &varsp
->fRTextOutline
); 
1059             TXNSetFrameBounds(  varsp
->fTXNRec
, bounds
.top
, bounds
.left
, bounds
.bottom
, bounds
.right
, varsp
->fTXNFrame
); 
1062             /* update the text region */ 
1063         EraseRgn(varsp
->fTextBackgroundRgn
); 
1064         TXNDraw(varsp
->fTXNRec
, NULL
); 
1065             /* restore the drawing environment */ 
1066             /* draw the text frame and focus frame (if necessary) */ 
1067         DrawThemeEditTextFrame(&varsp
->fRTextOutline
, varsp
->fIsActive 
? kThemeStateActive
: kThemeStateInactive
); 
1068         if ((**tpvars
).fIsActive 
&& varsp
->fInFocus
) DrawThemeFocusRect(&varsp
->fRFocusOutline
, true); 
1069             /* release our globals */ 
1070         HSetState((Handle
) tpvars
, state
); 
1075 /* TPPaneHitTestProc is called when the control manager would 
1076     like to determine what part of the control the mouse resides over. 
1077     We also call this routine from our tracking proc to determine how 
1078     to handle mouse clicks. */ 
1079 static pascal ControlPartCode 
TPPaneHitTestProc(ControlHandle theControl
, Point where
) { 
1080     STPTextPaneVars 
**tpvars
; 
1081     ControlPartCode result
; 
1083         /* set up our locals and lock down our globals*/ 
1085     tpvars 
= (STPTextPaneVars 
**) GetControlReference(theControl
); 
1086     if (tpvars 
!= NULL
) { 
1087         state 
= HGetState((Handle
) tpvars
); 
1088         HLock((Handle
) tpvars
); 
1089             /* find the region where we clicked */ 
1090         if (PtInRect(where
, &(**tpvars
).fRTextArea
)) { 
1091             result 
= kmUPTextPart
; 
1093             /* release oure globals */ 
1094         HSetState((Handle
) tpvars
, state
); 
1103 /* TPPaneTrackingProc is called when the mouse is being held down 
1104     over our control.  This routine handles clicks in the text area 
1105     and in the scroll bar. */ 
1106 static pascal ControlPartCode 
TPPaneTrackingProc(ControlHandle theControl
, Point startPt
, ControlActionUPP actionProc
) { 
1107     STPTextPaneVars 
**tpvars
, *varsp
; 
1109     ControlPartCode partCodeResult
; 
1110         /* make sure we have some variables... */ 
1112     tpvars 
= (STPTextPaneVars 
**) GetControlReference(theControl
); 
1113     if (tpvars 
!= NULL
) { 
1115         state 
= HGetState((Handle
) tpvars
); 
1116         HLock((Handle
) tpvars
); 
1118             /* we don't do any of these functions unless we're in focus */ 
1119         if ( ! varsp
->fInFocus
) { 
1121             owner 
= GetControlOwner(theControl
); 
1122             ClearKeyboardFocus(owner
); 
1123             SetKeyboardFocus(owner
, theControl
, kUserClickedToFocusPart
); 
1125             /* find the location for the click */ 
1126         switch (TPPaneHitTestProc(theControl
, startPt
)) { 
1128                 /* handle clicks in the text part */ 
1130                 {   SetPort((**tpvars
).fDrawingEnvironment
); 
1131                     TXNClick( varsp
->fTXNRec
, GetCurrentEventRecord()); 
1137         HSetState((Handle
) tpvars
, state
); 
1139     return partCodeResult
; 
1143 /* TPPaneIdleProc is our user pane idle routine.  When our text field 
1144     is active and in focus, we use this routine to set the cursor. */ 
1145 static pascal void TPPaneIdleProc(ControlHandle theControl
) { 
1146     STPTextPaneVars 
**tpvars
, *varsp
; 
1148     tpvars 
= (STPTextPaneVars 
**) GetControlReference(theControl
); 
1149     if (tpvars 
!= NULL
) { 
1150             /* if we're not active, then we have nothing to say about the cursor */ 
1151         if ((**tpvars
).fIsActive
) { 
1155                 /* lock down the globals */ 
1156             state 
= HGetState((Handle
) tpvars
); 
1157             HLock((Handle
) tpvars
); 
1159                 /* get the current mouse coordinates (in our window) */ 
1161             SetPort(GetWindowPort(GetControlOwner(theControl
))); 
1163             SetPort((GrafPtr
) GetWindowPort(GetControlOwner(theControl
))); 
1166                 /* there's a 'focus thing' and an 'unfocused thing' */ 
1167             if (varsp
->fInFocus
) { 
1168                     /* flash the cursor */ 
1169                 SetPort((**tpvars
).fDrawingEnvironment
); 
1170                 TXNIdle(varsp
->fTXNRec
); 
1171                 /* set the cursor */ 
1172                 if (PtInRect(mousep
, &varsp
->fRTextArea
)) { 
1174                     RectRgn((theRgn 
= NewRgn()), &varsp
->fRTextArea
); 
1175                     TXNAdjustCursor(varsp
->fTXNRec
, theRgn
); 
1177                  } else SetThemeCursor(kThemeArrowCursor
); 
1179                 /* if it's in our bounds, set the cursor */ 
1180                 GetControlBounds(theControl
, &bounds
); 
1181                 if (PtInRect(mousep
, &bounds
)) 
1182                     SetThemeCursor(kThemeArrowCursor
); 
1185             HSetState((Handle
) tpvars
, state
); 
1191 /* TPPaneKeyDownProc is called whenever a keydown event is directed 
1192     at our control.  Here, we direct the keydown event to the text 
1193     edit record and redraw the scroll bar and text field as appropriate. */ 
1194 static pascal ControlPartCode 
TPPaneKeyDownProc(ControlHandle theControl
, 
1195                             SInt16 keyCode
, SInt16 charCode
, SInt16 modifiers
) { 
1196     STPTextPaneVars 
**tpvars
; 
1197     tpvars 
= (STPTextPaneVars 
**) GetControlReference(theControl
); 
1198     if (tpvars 
!= NULL
) { 
1199         if ((**tpvars
).fInFocus
) { 
1200                 /* turn autoscrolling on and send the key event to text edit */ 
1201             SetPort((**tpvars
).fDrawingEnvironment
); 
1202             TXNKeyDown( (**tpvars
).fTXNRec
, GetCurrentEventRecord()); 
1205     return kControlEntireControl
; 
1209 /* TPPaneActivateProc is called when the window containing 
1210     the user pane control receives activate events. Here, we redraw 
1211     the control and it's text as necessary for the activation state. */ 
1212 static pascal void TPPaneActivateProc(ControlHandle theControl
, Boolean activating
) { 
1214     STPTextPaneVars 
**tpvars
, *varsp
; 
1217     tpvars 
= (STPTextPaneVars 
**) GetControlReference(theControl
); 
1218     if (tpvars 
!= NULL
) { 
1219         state 
= HGetState((Handle
) tpvars
); 
1220         HLock((Handle
) tpvars
); 
1222             /* de/activate the text edit record */ 
1223         SetPort((**tpvars
).fDrawingEnvironment
); 
1224             GetControlBounds(theControl
, &bounds
); 
1225             varsp
->fIsActive 
= activating
; 
1226             TPActivatePaneText(tpvars
, varsp
->fIsActive 
&& varsp
->fInFocus
); 
1227             /* redraw the frame */ 
1228         DrawThemeEditTextFrame(&varsp
->fRTextOutline
, varsp
->fIsActive 
? kThemeStateActive
: kThemeStateInactive
); 
1229         if (varsp
->fInFocus
) DrawThemeFocusRect(&varsp
->fRFocusOutline
, varsp
->fIsActive
); 
1230         HSetState((Handle
) tpvars
, state
); 
1235 /* TPPaneFocusProc is called when every the focus changes to or 
1236     from our control.  Herein, switch the focus appropriately 
1237     according to the parameters and redraw the control as 
1239 static pascal ControlPartCode 
TPPaneFocusProc(ControlHandle theControl
, ControlFocusPart action
) { 
1240     ControlPartCode focusResult
; 
1241     STPTextPaneVars 
**tpvars
, *varsp
; 
1244     focusResult 
= kControlFocusNoPart
; 
1245     tpvars 
= (STPTextPaneVars 
**) GetControlReference(theControl
); 
1246     if (tpvars 
!= NULL
) { 
1247         state 
= HGetState((Handle
) tpvars
); 
1248         HLock((Handle
) tpvars
); 
1250             /* if kControlFocusPrevPart and kControlFocusNextPart are received when the user is 
1251             tabbing forwards (or shift tabbing backwards) through the items in the dialog, 
1252             and kControlFocusNextPart will be received.  When the user clicks in our field 
1253             and it is not the current focus, then the constant kUserClickedToFocusPart will 
1254             be received.  The constant kControlFocusNoPart will be received when our control 
1255             is the current focus and the user clicks in another control.  In your focus routine, 
1256             you should respond to these codes as follows: 
1258             kControlFocusNoPart - turn off focus and return kControlFocusNoPart.  redraw 
1259                 the control and the focus rectangle as necessary. 
1261             kControlFocusPrevPart or kControlFocusNextPart - toggle focus on or off 
1262                 depending on its current state.  redraw the control and the focus rectangle 
1263                 as appropriate for the new focus state.  If the focus state is 'off', return the constant 
1264                 kControlFocusNoPart, otherwise return a non-zero part code. 
1265             kUserClickedToFocusPart - is a constant defined for this example.  You should 
1266                 define your own value for handling click-to-focus type events. */ 
1267             /* save the drawing state */ 
1268         SetPort((**tpvars
).fDrawingEnvironment
); 
1269             /* calculate the next highlight state */ 
1272             case kControlFocusNoPart
: 
1273                 TPFocusPaneText(tpvars
, false); 
1274                 focusResult 
= kControlFocusNoPart
; 
1276             case kUserClickedToFocusPart
: 
1277                 TPFocusPaneText(tpvars
, true); 
1280             case kControlFocusPrevPart
: 
1281             case kControlFocusNextPart
: 
1282                 TPFocusPaneText(tpvars
, ( ! varsp
->fInFocus
)); 
1283                 focusResult 
= varsp
->fInFocus 
? 1 : kControlFocusNoPart
; 
1286             TPActivatePaneText(tpvars
, varsp
->fIsActive 
&& varsp
->fInFocus
); 
1287             /* redraw the text fram and focus rectangle to indicate the 
1289         DrawThemeEditTextFrame(&varsp
->fRTextOutline
, varsp
->fIsActive 
? kThemeStateActive
: kThemeStateInactive
); 
1290         DrawThemeFocusRect(&varsp
->fRFocusOutline
, varsp
->fIsActive 
&& varsp
->fInFocus
); 
1292         HSetState((Handle
) tpvars
, state
); 
1307 //This our carbon event handler for unicode key downs 
1309 static pascal OSStatus 
FocusAdvanceOverride(EventHandlerCallRef myHandler
, EventRef event
, void* userData
) { 
1311     STPTextPaneVars 
**tpvars
; 
1313     unsigned short mUnicodeText
; 
1314     ByteCount charCounts
=0; 
1315         /* get our window pointer */ 
1316     tpvars 
= (STPTextPaneVars 
**) userData
; 
1317     window 
= (**tpvars
).fOwner
; 
1318         //find out how many bytes are needed 
1319     err 
= GetEventParameter(event
, kEventParamTextInputSendText
, 
1320                 typeUnicodeText
, NULL
, 0, &charCounts
, NULL
); 
1321     if (err 
!= noErr
) goto bail
; 
1322         /* we're only looking at single characters */ 
1323     if (charCounts 
!= 2) { err 
= eventNotHandledErr
; goto bail
; } 
1324         /* get the character */ 
1325     err 
= GetEventParameter(event
, kEventParamTextInputSendText
,  
1326                 typeUnicodeText
, NULL
, sizeof(mUnicodeText
), 
1327                 &charCounts
, (char*) &mUnicodeText
); 
1328     if (err 
!= noErr
) goto bail
; 
1329         /* if it's not the tab key, forget it... */ 
1330     if ((mUnicodeText 
!= '\t')) { err 
= eventNotHandledErr
; goto bail
; } 
1331         /* advance the keyboard focus */ 
1332     AdvanceKeyboardFocus(window
); 
1333         /* noErr lets the CEM know we handled the event */ 
1336     return eventNotHandledErr
; 
1341 /* mUPOpenControl initializes a user pane control so it will be drawn 
1342         and will behave as a scrolling text edit field inside of a window. 
1343         This routine performs all of the initialization steps necessary, 
1344         except it does not create the user pane control itself.  theControl 
1345         should refer to a user pane control that you have either created 
1346         yourself or extracted from a dialog's control heirarchy using 
1347         the GetDialogItemAsControl routine.  */ 
1348 OSStatus 
mUPOpenControl(ControlHandle theControl
, bool multiline
) { 
1350         WindowPtr theWindow
; 
1351         STPTextPaneVars 
**tpvars
, *varsp
; 
1353         RGBColor rgbWhite 
= {0xFFFF, 0xFFFF, 0xFFFF}; 
1354         TXNBackground tback
; 
1356                 /* set up our globals */ 
1357         if (gTPDrawProc 
== NULL
) gTPDrawProc 
= NewControlUserPaneDrawUPP(TPPaneDrawProc
); 
1358         if (gTPHitProc 
== NULL
) gTPHitProc 
= NewControlUserPaneHitTestUPP(TPPaneHitTestProc
); 
1359         if (gTPTrackProc 
== NULL
) gTPTrackProc 
= NewControlUserPaneTrackingUPP(TPPaneTrackingProc
); 
1360         if (gTPIdleProc 
== NULL
) gTPIdleProc 
= NewControlUserPaneIdleUPP(TPPaneIdleProc
); 
1361         if (gTPKeyProc 
== NULL
) gTPKeyProc 
= NewControlUserPaneKeyDownUPP(TPPaneKeyDownProc
); 
1362         if (gTPActivateProc 
== NULL
) gTPActivateProc 
= NewControlUserPaneActivateUPP(TPPaneActivateProc
); 
1363         if (gTPFocusProc 
== NULL
) gTPFocusProc 
= NewControlUserPaneFocusUPP(TPPaneFocusProc
); 
1365                 /* allocate our private storage */ 
1366         tpvars 
= (STPTextPaneVars 
**) NewHandleClear(sizeof(STPTextPaneVars
)); 
1367         SetControlReference(theControl
, (long) tpvars
); 
1368         HLock((Handle
) tpvars
); 
1370                 /* set the initial settings for our private data */ 
1371         varsp
->fInFocus 
= false; 
1372         varsp
->fIsActive 
= true; 
1373         varsp
->fTEActive 
= false; 
1374         varsp
->fUserPaneRec 
= theControl
; 
1375         theWindow 
= varsp
->fOwner 
= GetControlOwner(theControl
); 
1377     varsp
->fDrawingEnvironment 
= GetWindowPort(varsp
->fOwner
); 
1379     varsp
->fDrawingEnvironment 
= (GrafPtr
) GetWindowPort(varsp
->fOwner
); 
1381     varsp
->fInDialogWindow 
= ( GetWindowKind(varsp
->fOwner
) == kDialogWindowKind 
); 
1382         /* set up the user pane procedures */ 
1383     SetControlData(theControl
, kControlEntireControl
, kControlUserPaneDrawProcTag
, sizeof(gTPDrawProc
), &gTPDrawProc
); 
1384     SetControlData(theControl
, kControlEntireControl
, kControlUserPaneHitTestProcTag
, sizeof(gTPHitProc
), &gTPHitProc
); 
1385     SetControlData(theControl
, kControlEntireControl
, kControlUserPaneTrackingProcTag
, sizeof(gTPTrackProc
), &gTPTrackProc
); 
1386     SetControlData(theControl
, kControlEntireControl
, kControlUserPaneIdleProcTag
, sizeof(gTPIdleProc
), &gTPIdleProc
); 
1387     SetControlData(theControl
, kControlEntireControl
, kControlUserPaneKeyDownProcTag
, sizeof(gTPKeyProc
), &gTPKeyProc
); 
1388     SetControlData(theControl
, kControlEntireControl
, kControlUserPaneActivateProcTag
, sizeof(gTPActivateProc
), &gTPActivateProc
); 
1389     SetControlData(theControl
, kControlEntireControl
, kControlUserPaneFocusProcTag
, sizeof(gTPFocusProc
), &gTPFocusProc
); 
1390         /* calculate the rectangles used by the control */ 
1391     GetControlBounds(theControl
, &bounds
); 
1392     SetRect(&varsp
->fRFocusOutline
, bounds
.left
, bounds
.top
, bounds
.right
, bounds
.bottom
); 
1393     SetRect(&varsp
->fRTextOutline
, bounds
.left
, bounds
.top
, bounds
.right
, bounds
.bottom
); 
1394     SetRect(&varsp
->fRTextArea
, bounds
.left
, bounds
.top
, bounds
.right
, bounds
.bottom
); 
1395         /* calculate the background region for the text.  In this case, it's kindof 
1396         and irregular region because we're setting the scroll bar a little ways inside 
1397         of the text area. */ 
1398     RectRgn((varsp
->fTextBackgroundRgn 
= NewRgn()), &varsp
->fRTextOutline
); 
1400         /* set up the drawing environment */ 
1401     SetPort(varsp
->fDrawingEnvironment
); 
1403         /* create the new edit field */ 
1404     TXNNewObject(NULL
, varsp
->fOwner
, &varsp
->fRTextArea
, 
1405         kTXNWantVScrollBarMask 
| kTXNAlwaysWrapAtViewEdgeMask
, 
1406         kTXNTextEditStyleFrameType
, 
1408         kTXNSystemDefaultEncoding
,  
1409         &varsp
->fTXNRec
, &varsp
->fTXNFrame
, (TXNObjectRefcon
) tpvars
); 
1411         /* set the field's background */ 
1412     tback
.bgType 
= kTXNBackgroundTypeRGB
; 
1413     tback
.bg
.color 
= rgbWhite
; 
1414     TXNSetBackground( varsp
->fTXNRec
, &tback
); 
1416         /* install our focus advance override routine */ 
1418     varsp
->handlerUPP 
= NewEventHandlerUPP(FocusAdvanceOverride
); 
1419     err 
= InstallWindowEventHandler( varsp
->fOwner
, varsp
->handlerUPP
, 
1420         kMLTEEventCount
, gMLTEEvents
, tpvars
, &varsp
->handlerRef 
); 
1422         /* unlock our storage */ 
1423     HUnlock((Handle
) tpvars
); 
1424         /* perform final activations and setup for our text field.  Here, 
1425         we assume that the window is going to be the 'active' window. */ 
1426     TPActivatePaneText(tpvars
, varsp
->fIsActive 
&& varsp
->fInFocus
); 
1433 /* mUPCloseControl deallocates all of the structures allocated 
1434     by mUPOpenControl.  */ 
1435 OSStatus 
mUPCloseControl(ControlHandle theControl
) { 
1436     STPTextPaneVars 
**tpvars
; 
1438     tpvars 
= (STPTextPaneVars 
**) GetControlReference(theControl
); 
1439         /* release our sub records */ 
1440     TXNDeleteObject((**tpvars
).fTXNRec
); 
1441         /* remove our focus advance override */ 
1442     RemoveEventHandler((**tpvars
).handlerRef
); 
1443     DisposeEventHandlerUPP((**tpvars
).handlerUPP
); 
1444         /* delete our private storage */ 
1445     DisposeHandle((Handle
) tpvars
); 
1446         /* zero the control reference */ 
1447     SetControlReference(theControl
, 0); 
1454     /* mUPSetText replaces the contents of the selection with the unicode 
1455     text described by the text and count parameters:. 
1456         text = pointer to unicode text buffer 
1457         count = number of bytes in the buffer.  */ 
1458 OSStatus 
mUPSetText(ControlHandle theControl
, char* text
, long count
) { 
1459     STPTextPaneVars 
**tpvars
; 
1461     tpvars 
= (STPTextPaneVars 
**) GetControlReference(theControl
); 
1462         /* set the text in the record */ 
1463     return TXNSetData( (**tpvars
).fTXNRec
, kTXNUnicodeTextData
, text
, count
, 
1464         kTXNUseCurrentSelection
, kTXNUseCurrentSelection
); 
1470 /* mUPSetSelection sets the text selection and autoscrolls the text view 
1471     so either the cursor or the selction is in the view. */ 
1472 void mUPSetSelection(ControlHandle theControl
, long selStart
, long selEnd
) { 
1473     STPTextPaneVars 
**tpvars
; 
1474         /* set up our locals */ 
1475     tpvars 
= (STPTextPaneVars 
**) GetControlReference(theControl
); 
1476         /* and our drawing environment as the operation 
1477         may force a redraw in the text area. */ 
1478     SetPort((**tpvars
).fDrawingEnvironment
); 
1479         /* change the selection */ 
1480     TXNSetSelection( (**tpvars
).fTXNRec
, selStart
, selEnd
); 
1487 /* mUPGetText returns the current text data being displayed inside of 
1488     the mUPControl.  When noErr is returned, *theText contain a new 
1489     handle containing all of the Unicode text copied from the current 
1490     selection.  It is the caller's responsibiliby to dispose of this handle. */ 
1491 OSStatus 
mUPGetText(ControlHandle theControl
, Handle 
*theText
) { 
1492     STPTextPaneVars 
**tpvars
; 
1495     tpvars 
= (STPTextPaneVars 
**) GetControlReference(theControl
); 
1496         /* extract the text from the record */ 
1497     err 
= TXNGetData( (**tpvars
).fTXNRec
, kTXNUseCurrentSelection
, kTXNUseCurrentSelection
, theText
); 
1504 /* mUPCreateControl creates a new user pane control and then it passes it 
1505     to mUPOpenControl to initialize it as a scrolling text user pane control. */ 
1506 OSStatus 
mUPCreateControl(WindowPtr theWindow
, Rect 
*bounds
, ControlHandle 
*theControl
) { 
1508         /* the following feature set can be specified in CNTL resources by using 
1509         the value 1214.  When creating a user pane control, we pass this value 
1510         in the 'value' parameter. */ 
1511     featurSet 
= kControlSupportsEmbedding 
| kControlSupportsFocus 
| kControlWantsIdle
 
1512             | kControlWantsActivate 
| kControlHandlesTracking 
| kControlHasSpecialBackground
 
1513             | kControlGetsFocusOnClick 
| kControlSupportsLiveFeedback
; 
1514         /* create the control */ 
1515     *theControl 
= NewControl(theWindow
, bounds
, "\p", true, featurSet
, 0, featurSet
, kControlUserPaneProc
, 0); 
1516         /* set up the mUP specific features and data */ 
1517     mUPOpenControl(*theControl
); 
1523 /* mUPDisposeControl calls mUPCloseControl and then it calls DisposeControl. */ 
1524 OSStatus 
mUPDisposeControl(ControlHandle theControl
) { 
1525         /* deallocate the mUP specific data */ 
1526     mUPCloseControl(theControl
); 
1527         /* deallocate the user pane control itself */ 
1528     DisposeControl(theControl
); 
1535 /* IsmUPControl returns true if theControl is not NULL 
1536     and theControl refers to a mUP Control.  */ 
1537 Boolean 
IsmUPControl(ControlHandle theControl
) { 
1539     ControlUserPaneFocusUPP localFocusProc
; 
1540         /* a NULL control is not a mUP control */ 
1541     if (theControl 
== NULL
) return false; 
1542         /* check if the control is using our focus procedure */ 
1543     theSize 
= sizeof(localFocusProc
); 
1544     if (GetControlData(theControl
, kControlEntireControl
, kControlUserPaneFocusProcTag
, 
1545         sizeof(localFocusProc
), &localFocusProc
, &theSize
) != noErr
) return false; 
1546     if (localFocusProc 
!= gTPFocusProc
) return false; 
1547         /* all tests passed, it's a mUP control */ 
1552 /* mUPDoEditCommand performs the editing command specified 
1553     in the editCommand parameter.  The mUPControl's text 
1554     and scroll bar are redrawn and updated as necessary. */ 
1555 void mUPDoEditCommand(ControlHandle theControl
, short editCommand
) { 
1556     STPTextPaneVars 
**tpvars
; 
1557         /* set up our locals */ 
1558     tpvars 
= (STPTextPaneVars 
**) GetControlReference(theControl
); 
1559         /* and our drawing environment as the operation 
1560         may force a redraw in the text area. */ 
1561     SetPort((**tpvars
).fDrawingEnvironment
); 
1562         /* perform the editing command */ 
1563     switch (editCommand
) { 
1565             ClearCurrentScrap(); 
1566             TXNCut((**tpvars
).fTXNRec
);  
1567             TXNConvertToPublicScrap(); 
1570             ClearCurrentScrap(); 
1571             TXNCopy((**tpvars
).fTXNRec
); 
1572             TXNConvertToPublicScrap(); 
1575             TXNConvertFromPublicScrap(); 
1576             TXNPaste((**tpvars
).fTXNRec
); 
1579             TXNClear((**tpvars
).fTXNRec
); 
1587 /* mUPGetContents returns the entire contents of the control including the text 
1588     and the formatting information. */ 
1589 OSStatus 
mUPGetContents(ControlHandle theControl
, Handle 
*theContents
) { 
1590     STPTextPaneVars 
**tpvars
; 
1603     tpvars 
= (STPTextPaneVars 
**) GetControlReference(theControl
); 
1604     if (theContents 
== NULL
) return paramErr
; 
1605         /* create a temporary file */ 
1606     err 
= FindFolder(kOnSystemDisk
, kTemporaryFolderType
, true, &vRefNum
, &dirID
); 
1607     if (err 
!= noErr
) goto bail
; 
1608     FSMakeFSSpec(vRefNum
, dirID
, "\pmUPGetContents", &tspec
); 
1609     err 
= FSpCreate(&tspec
, 'trsh', 'trsh', smSystemScript
); 
1610     if (err 
!= noErr
) goto bail
; 
1613     err 
= FSpOpenDF(&tspec
, fsRdWrPerm
, &trefnum
); 
1614     if (err 
!= noErr
) goto bail
; 
1616     err 
= TXNSave( (**tpvars
).fTXNRec
, kTXNTextensionFile
, 0, kTXNSystemDefaultEncoding
, &tspec
, trefnum
, 0); 
1617     if (err 
!= noErr
) goto bail
; 
1618         /* get the file length and set the position */ 
1619     err 
= GetEOF(trefnum
, &bytecount
); 
1620     if (err 
!= noErr
) goto bail
; 
1621     err 
= SetFPos(trefnum
, fsFromStart
, 0); 
1622     if (err 
!= noErr
) goto bail
; 
1623         /* copy the data fork to a handle */ 
1624     localdata 
= NewHandle(bytecount
); 
1625     if (localdata 
== NULL
) { err 
= memFullErr
; goto bail
; } 
1627     err 
= FSRead(trefnum
, &bytecount
, *localdata
); 
1629     if (err 
!= noErr
) goto bail
; 
1631     *theContents 
= localdata
; 
1638     if (trefnum 
!= 0) FSClose(trefnum
); 
1639     if (texists
) FSpDelete(&tspec
); 
1640     if (localdata 
!= NULL
) DisposeHandle(localdata
); 
1647 /* mUPSetContents replaces the contents of the selection with the data stored in the handle. */ 
1648 OSStatus 
mUPSetContents(ControlHandle theControl
, Handle theContents
) { 
1649     STPTextPaneVars 
**tpvars
; 
1661     tpvars 
= (STPTextPaneVars 
**) GetControlReference(theControl
); 
1662     if (theContents 
== NULL
) return paramErr
; 
1663         /* create a temporary file */ 
1664     err 
= FindFolder(kOnSystemDisk
,  kTemporaryFolderType
, true, &vRefNum
, &dirID
); 
1665     if (err 
!= noErr
) goto bail
; 
1666     FSMakeFSSpec(vRefNum
, dirID
, "\pmUPSetContents", &tspec
); 
1667     err 
= FSpCreate(&tspec
, 'trsh', 'trsh', smSystemScript
); 
1668     if (err 
!= noErr
) goto bail
; 
1671     err 
= FSpOpenDF(&tspec
, fsRdWrPerm
, &trefnum
); 
1672     if (err 
!= noErr
) goto bail
; 
1673         /* save the data to the temporary file */ 
1674     state 
= HGetState(theContents
); 
1676     bytecount 
= GetHandleSize(theContents
); 
1677     err 
= FSWrite(trefnum
, &bytecount
, *theContents
); 
1678     HSetState(theContents
, state
); 
1679     if (err 
!= noErr
) goto bail
; 
1680         /* reset the file position */ 
1681     err 
= SetFPos(trefnum
, fsFromStart
, 0); 
1682     if (err 
!= noErr
) goto bail
; 
1684     err 
= TXNSetDataFromFile((**tpvars
).fTXNRec
, trefnum
, kTXNTextensionFile
, bytecount
, kTXNUseCurrentSelection
, kTXNUseCurrentSelection
); 
1685     if (err 
!= noErr
) goto bail
; 
1692     if (trefnum 
!= 0) FSClose(trefnum
); 
1693     if (texists
) FSpDelete(&tspec
); 
1697 #if !USE_SHARED_LIBRARY 
1698 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl
, wxControl
) 
1700 BEGIN_EVENT_TABLE(wxTextCtrl
, wxControl
) 
1701     EVT_DROP_FILES(wxTextCtrl::OnDropFiles
) 
1702     EVT_CHAR(wxTextCtrl::OnChar
) 
1703     EVT_MENU(wxID_CUT
, wxTextCtrl::OnCut
) 
1704     EVT_MENU(wxID_COPY
, wxTextCtrl::OnCopy
) 
1705     EVT_MENU(wxID_PASTE
, wxTextCtrl::OnPaste
) 
1706     EVT_MENU(wxID_UNDO
, wxTextCtrl::OnUndo
) 
1707     EVT_MENU(wxID_REDO
, wxTextCtrl::OnRedo
) 
1709     EVT_UPDATE_UI(wxID_CUT
, wxTextCtrl::OnUpdateCut
) 
1710     EVT_UPDATE_UI(wxID_COPY
, wxTextCtrl::OnUpdateCopy
) 
1711     EVT_UPDATE_UI(wxID_PASTE
, wxTextCtrl::OnUpdatePaste
) 
1712     EVT_UPDATE_UI(wxID_UNDO
, wxTextCtrl::OnUpdateUndo
) 
1713     EVT_UPDATE_UI(wxID_REDO
, wxTextCtrl::OnUpdateRedo
) 
1718 wxTextCtrl::wxTextCtrl() 
1722 const short kVerticalMargin 
= 2 ; 
1723 const short kHorizontalMargin 
= 2 ; 
1725 bool wxTextCtrl::Create(wxWindow 
*parent
, wxWindowID id
, 
1728            const wxSize
& size
, long style
, 
1729            const wxValidator
& validator
, 
1730            const wxString
& name
) 
1732     // base initialization 
1733     if ( !CreateBase(parent
, id
, pos
, size
, style
, validator
, name
) ) 
1736     wxSize mySize 
= size 
; 
1737     if ( UMAHasAppearance() ) 
1739         m_macHorizontalBorder 
= 5 ; // additional pixels around the real control 
1740         m_macVerticalBorder 
= 5 ; 
1744         m_macHorizontalBorder 
= 0 ; // additional pixels around the real control 
1745         m_macVerticalBorder 
= 0 ; 
1752     if ( mySize
.y 
== -1 ) 
1754         if ( UMAHasAppearance() ) 
1759         mySize
.y 
+= 2 * m_macVerticalBorder 
; 
1762     MacPreControlCreate( parent 
, id 
,  "" , pos 
, mySize 
,style
, validator 
, name 
, &bounds 
, title 
) ; 
1764     if ( m_windowStyle 
& wxTE_MULTILINE 
) 
1766         wxASSERT_MSG( !(m_windowStyle 
& wxTE_PROCESS_ENTER
), 
1767                       wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") ); 
1769         m_windowStyle 
|= wxTE_PROCESS_ENTER
; 
1773     if ( style 
& wxTE_PASSWORD 
) 
1775       m_macControl 
= ::NewControl( parent
->MacGetRootWindow() , &bounds 
, "\p" , true , 0 , 0 , 1,  
1776         kControlEditTextPasswordProc 
, (long) this ) ; 
1780     if ( mUPCreateControl(parent
->MacGetRootWindow(), &bounds
, &m_macControl
) != noErr 
)  
1783     MacPostControlCreate() ; 
1787     if( wxApp::s_macDefaultEncodingIsPC 
) 
1788         value 
= wxMacMakeMacStringFromPC( st 
) ; 
1792     if ( style 
& wxTE_PASSWORD 
) 
1794       ::SetControlData( m_macControl
, 0, ( m_windowStyle 
& wxTE_PASSWORD 
) ? kControlEditTextPasswordTag 
: kControlEditTextTextTag 
, value
.Length() , (char*) ((const char*)value
) ) ; 
1798     STPTextPaneVars 
**tpvars
; 
1800     tpvars 
= (STPTextPaneVars 
**) GetControlReference(m_macControl
); 
1801         /* set the text in the record */ 
1802     TXNSetData( (**tpvars
).fTXNRec
, kTXNTextData
,  (const char*)value
, value
.Length(), 
1803       kTXNStartOffset
, kTXNEndOffset
); 
1809 wxString 
wxTextCtrl::GetValue() const 
1812   if ( m_windowStyle 
& wxTE_PASSWORD 
) 
1814       ::GetControlData( m_macControl
, 0, ( m_windowStyle 
& wxTE_PASSWORD 
) ? kControlEditTextPasswordTag 
: kControlEditTextTextTag 
, 32767 , wxBuffer 
, &actualsize
) ; 
1818     STPTextPaneVars 
**tpvars
; 
1821     tpvars 
= (STPTextPaneVars 
**) GetControlReference(m_macControl
); 
1822         /* extract the text from the record */ 
1824     err 
= TXNGetDataEncoded( (**tpvars
).fTXNRec
, kTXNStartOffset
, kTXNEndOffset
, &theText 
, kTXNTextData 
); 
1832       actualsize 
= GetHandleSize( theText 
) ; 
1833       strncpy( wxBuffer 
, *theText 
, actualsize 
) ; 
1834       DisposeHandle( theText 
) ; 
1837     wxBuffer
[actualsize
] = 0 ; 
1838     if( wxApp::s_macDefaultEncodingIsPC 
) 
1839         return wxMacMakePCStringFromMac( wxBuffer 
) ; 
1841         return wxString(wxBuffer
); 
1844 void wxTextCtrl::GetSelection(long* from
, long* to
) const 
1846   if ( m_windowStyle 
& wxTE_PASSWORD 
) 
1848    ControlEditTextSelectionRec selection 
; 
1852    ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
1854     *from 
= (**teH
).selStart
; 
1855     *to 
= (**teH
).selEnd
; 
1859         STPTextPaneVars 
**tpvars
; 
1862         tpvars 
= (STPTextPaneVars 
**) GetControlReference(m_macControl
); 
1864         TXNGetSelection(  (**tpvars
).fTXNRec 
, (TXNOffset
*) from 
, (TXNOffset
*) to 
) ; 
1869 void wxTextCtrl::SetValue(const wxString
& st
) 
1873     if( wxApp::s_macDefaultEncodingIsPC 
) 
1874         value 
= wxMacMakeMacStringFromPC( st 
) ; 
1877   if ( m_windowStyle 
& wxTE_PASSWORD 
) 
1879       ::SetControlData( m_macControl
, 0, ( m_windowStyle 
& wxTE_PASSWORD 
) ? kControlEditTextPasswordTag 
: kControlEditTextTextTag 
, value
.Length() , (char*) ((const char*)value
) ) ; 
1883     STPTextPaneVars 
**tpvars
; 
1885     tpvars 
= (STPTextPaneVars 
**) GetControlReference(m_macControl
); 
1886         /* set the text in the record */ 
1887     TXNSetData( (**tpvars
).fTXNRec
, kTXNTextData
,  (const char*)value
, value
.Length(), 
1888       kTXNStartOffset
, kTXNEndOffset
); 
1890     WindowRef window 
= MacGetRootWindow() ; 
1893         wxWindow
* win 
= wxFindWinFromMacWindow( window 
) ; 
1896             wxMacDrawingHelper 
help( win 
) ; 
1897             // the mac control manager always assumes to have the origin at 0,0 
1898             SetOrigin( 0 , 0 ) ; 
1900             bool            hasTabBehind 
= false ; 
1901             wxWindow
* parent 
= GetParent() ; 
1904                 if( parent
->MacGetWindowData() ) 
1906                     UMASetThemeWindowBackground( win
->MacGetWindowData()->m_macWindow 
, kThemeBrushDialogBackgroundActive 
, false ) ; 
1910                 if( parent
->IsKindOf( CLASSINFO( wxNotebook 
) ) ||  parent
->IsKindOf( CLASSINFO( wxTabCtrl 
) )) 
1912                     if ( ((wxControl
*)parent
)->GetMacControl() ) 
1913                         SetUpControlBackground( ((wxControl
*)parent
)->GetMacControl() , -1 , true ) ; 
1917                 parent 
= parent
->GetParent() ; 
1920             UMADrawControl( m_macControl 
) ; 
1921             UMASetThemeWindowBackground( win
->MacGetWindowData()->m_macWindow 
, win
->MacGetWindowData()->m_macWindowBackgroundTheme 
, false ) ; 
1926 // Clipboard operations 
1927 void wxTextCtrl::Copy() 
1931       if ( m_windowStyle 
& wxTE_PASSWORD 
) 
1936                  ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
1938                 ClearCurrentScrap(); 
1943           mUPDoEditCommand( m_macControl 
, kmUPCopy 
) ; 
1948 void wxTextCtrl::Cut() 
1952       if ( m_windowStyle 
& wxTE_PASSWORD 
) 
1957                 ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
1959                 ClearCurrentScrap(); 
1961                 //      MacInvalidateControl() ; 
1965           mUPDoEditCommand( m_macControl 
, kmUPCut 
) ; 
1970 void wxTextCtrl::Paste() 
1974     if ( m_windowStyle 
& wxTE_PASSWORD 
) 
1979                 ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
1982                 WindowRef window 
= MacGetRootWindow() ; 
1985                         wxWindow
* win 
= wxFindWinFromMacWindow( window 
) ; 
1988                                 wxMacDrawingHelper 
help( win 
) ; 
1989                                 // the mac control manager always assumes to have the origin at 0,0 
1990                                 SetOrigin( 0 , 0 ) ; 
1992                                 bool                    hasTabBehind 
= false ; 
1993                                 wxWindow
* parent 
= GetParent() ; 
1996                                         if( parent
->MacGetWindowData() ) 
1998                                                 ::SetThemeWindowBackground( win
->MacGetWindowData()->m_macWindow 
, kThemeBrushDialogBackgroundActive 
, false ) ; 
2002                                         if( parent
->IsKindOf( CLASSINFO( wxNotebook 
) ) ||  parent
->IsKindOf( CLASSINFO( wxTabCtrl 
) )) 
2004                                                 if ( ((wxControl
*)parent
)->GetMacControl() ) 
2005                                                         SetUpControlBackground( ((wxControl
*)parent
)->GetMacControl() , -1 , true ) ; 
2009                                         parent 
= parent
->GetParent() ; 
2012                                 UMADrawControl( m_macControl 
) ; 
2013                                 ::SetThemeWindowBackground( win
->MacGetWindowData()->m_macWindow 
, win
->MacGetWindowData()->m_macWindowBackgroundTheme 
, false ) ; 
2019           mUPDoEditCommand( m_macControl 
, kmUPPaste 
) ; 
2024 bool wxTextCtrl::CanCopy() const 
2026     // Can copy if there's a selection 
2028     GetSelection(& from
, & to
); 
2029     return (from 
!= to
); 
2032 bool wxTextCtrl::CanCut() const 
2034     // Can cut if there's a selection 
2036     GetSelection(& from
, & to
); 
2037     return (from 
!= to
); 
2040 bool wxTextCtrl::CanPaste() const 
2047     OSStatus err 
= noErr
; 
2050     err 
= GetCurrentScrap( &scrapRef 
); 
2051     if ( err 
!= noTypeErr 
&& err 
!= memFullErr 
)     
2053         ScrapFlavorFlags    flavorFlags
; 
2056         if (( err 
= GetScrapFlavorFlags( scrapRef
, 'TEXT', &flavorFlags 
)) == noErr
) 
2058             if (( err 
= GetScrapFlavorSize( scrapRef
, 'TEXT', &byteCount 
)) == noErr
) 
2067     if ( GetScrap( NULL 
, 'TEXT' , &offset 
) > 0 ) 
2075 void wxTextCtrl::SetEditable(bool editable
) 
2078         UMAActivateControl( m_macControl 
) ; 
2080         UMADeactivateControl( m_macControl 
) ; 
2083 void wxTextCtrl::SetInsertionPoint(long pos
) 
2085     SetSelection( pos 
, pos 
) ; 
2088 void wxTextCtrl::SetInsertionPointEnd() 
2090     long pos 
= GetLastPosition(); 
2091     SetInsertionPoint(pos
); 
2094 long wxTextCtrl::GetInsertionPoint() const 
2097   GetSelection( &begin 
, &end 
) ; 
2101 long wxTextCtrl::GetLastPosition() const 
2103     if ( m_windowStyle 
& wxTE_PASSWORD 
) 
2106    ControlEditTextSelectionRec selection 
; 
2110    ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
2112 //   ::GetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection , &size ) ; 
2113     return (**teH
).teLength 
; 
2117      STPTextPaneVars
**  tpvars 
= (STPTextPaneVars 
**) GetControlReference(m_macControl
); 
2119     int actualsize 
= 0 ; 
2121         OSErr err 
= TXNGetDataEncoded( (**tpvars
).fTXNRec
, kTXNStartOffset
, kTXNEndOffset
, &theText 
, kTXNTextData 
); 
2129           actualsize 
= GetHandleSize( theText 
) ; 
2130           DisposeHandle( theText 
) ; 
2136 void wxTextCtrl::Replace(long from
, long to
, const wxString
& value
) 
2138   if ( m_windowStyle 
& wxTE_PASSWORD 
) 
2143     ControlEditTextSelectionRec selection 
; 
2145         selection
.selStart 
= from 
; 
2146         selection
.selEnd 
= to 
; 
2147         ::SetControlData( m_macControl 
, 0, kControlEditTextSelectionTag 
, sizeof( selection 
) , (char*) &selection 
) ; 
2148                 ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
2149         TESetSelect( from 
, to  
, teH 
) ; 
2151                 TEInsert( value 
, value
.Length() , teH 
) ; 
2160 void wxTextCtrl::Remove(long from
, long to
) 
2162   if ( m_windowStyle 
& wxTE_PASSWORD 
) 
2167     ControlEditTextSelectionRec selection 
; 
2169         selection
.selStart 
= from 
; 
2170         selection
.selEnd 
= to 
; 
2171         ::SetControlData( m_macControl 
, 0, kControlEditTextSelectionTag 
, sizeof( selection 
) , (char*) &selection 
) ; 
2172         ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
2182 void wxTextCtrl::SetSelection(long from
, long to
) 
2184   if ( m_windowStyle 
& wxTE_PASSWORD 
) 
2186    ControlEditTextSelectionRec selection 
; 
2190    ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
2192    selection
.selStart 
= from 
; 
2193    selection
.selEnd 
= to 
; 
2195    ::SetControlData( m_macControl 
, 0, kControlEditTextSelectionTag 
, sizeof( selection 
) , (char*) &selection 
) ; 
2196    TESetSelect( selection
.selStart 
, selection
.selEnd 
, teH 
) ; 
2200     STPTextPaneVars 
**tpvars
; 
2201         /* set up our locals */ 
2202     tpvars 
= (STPTextPaneVars 
**) GetControlReference(m_macControl
); 
2203         /* and our drawing environment as the operation 
2204         may force a redraw in the text area. */ 
2205     SetPort((**tpvars
).fDrawingEnvironment
); 
2206         /* change the selection */ 
2207     TXNSetSelection( (**tpvars
).fTXNRec
, from
, to
); 
2211 bool wxTextCtrl::LoadFile(const wxString
& file
) 
2213     if ( wxTextCtrlBase::LoadFile(file
) ) 
2221 void wxTextCtrl::WriteText(const wxString
& text
) 
2224     if( wxApp::s_macDefaultEncodingIsPC 
) 
2225         value 
= wxMacMakeMacStringFromPC( text 
) ; 
2228     if ( m_windowStyle 
& wxTE_PASSWORD 
) 
2233       ::GetControlData( m_macControl 
, 0, kControlEditTextTEHandleTag 
, sizeof( TEHandle 
) , (char*) &teH 
, &size 
) ; 
2234         TEInsert( value 
, value
.Length() , teH 
) ; 
2238         STPTextPaneVars 
**tpvars
; 
2240         tpvars 
= (STPTextPaneVars 
**) GetControlReference(m_macControl
); 
2241             /* set the text in the record */ 
2242         TXNSetData( (**tpvars
).fTXNRec
, kTXNTextData
,  (const char*)value
, value
.Length(), 
2243           kTXNUseCurrentSelection
, kTXNUseCurrentSelection
); 
2248 void wxTextCtrl::AppendText(const wxString
& text
) 
2250     SetInsertionPointEnd(); 
2254 void wxTextCtrl::Clear() 
2256   if ( m_windowStyle 
& wxTE_PASSWORD 
) 
2259     ::SetControlData( m_macControl
, 0, ( m_windowStyle 
& wxTE_PASSWORD 
) ? kControlEditTextPasswordTag 
: kControlEditTextTextTag 
, 0 , (char*) ((const char*)NULL
) ) ; 
2263     mUPDoEditCommand( m_macControl 
, kmUPClear
) ; 
2268 bool wxTextCtrl::IsModified() const 
2273 bool wxTextCtrl::IsEditable() const 
2278 bool wxTextCtrl::AcceptsFocus() const 
2280     // we don't want focus if we can't be edited 
2281     return IsEditable() && wxControl::AcceptsFocus(); 
2284 wxSize 
wxTextCtrl::DoGetBestSize() const 
2289         if ( UMAHasAppearance() ) 
2293     hText 
+= 2 * m_macHorizontalBorder 
; 
2296     wxGetCharSize(GetHWND(), &cx, &cy, &GetFont()); 
2298     int wText = DEFAULT_ITEM_WIDTH; 
2300     int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy); 
2302     return wxSize(wText, hText); 
2304     if ( m_windowStyle 
& wxTE_MULTILINE 
) 
2306         hText 
*= wxMin(GetNumberOfLines(), 5); 
2308     //else: for single line control everything is ok 
2309     return wxSize(wText
, hText
); 
2312 // ---------------------------------------------------------------------------- 
2314 // ---------------------------------------------------------------------------- 
2316 void wxTextCtrl::Undo() 
2323 void wxTextCtrl::Redo() 
2330 bool wxTextCtrl::CanUndo() const 
2335 bool wxTextCtrl::CanRedo() const 
2340 // Makes 'unmodified' 
2341 void wxTextCtrl::DiscardEdits() 
2346 int wxTextCtrl::GetNumberOfLines() const 
2348   // TODO change this if possible to reflect real lines 
2349   wxString content 
= GetValue() ; 
2352         for (int i 
= 0; i 
< content
.Length() ; i
++) 
2354             if (content
[i
] == '\r') count
++; 
2360 long wxTextCtrl::XYToPosition(long x
, long y
) const 
2366 bool wxTextCtrl::PositionToXY(long pos
, long *x
, long *y
) const 
2371 void wxTextCtrl::ShowPosition(long pos
) 
2376 int wxTextCtrl::GetLineLength(long lineNo
) const 
2378   // TODO change this if possible to reflect real lines 
2379   wxString content 
= GetValue() ; 
2383         for (int i 
= 0; i 
< content
.Length() ; i
++) 
2385             if (count 
== lineNo
) 
2387                 // Count chars in line then 
2389                 for (int j 
= i
; j 
< content
.Length(); j
++) 
2392                     if (content
[j
] == '\r') return count
; 
2397             if (content
[i
] == '\r') count
++; 
2402 wxString 
wxTextCtrl::GetLineText(long lineNo
) const 
2404   // TODO change this if possible to reflect real lines 
2405   wxString content 
= GetValue() ; 
2409         for (int i 
= 0; i 
< content
.Length() ; i
++) 
2411             if (count 
== lineNo
) 
2413                 // Add chars in line then 
2416                 for (int j 
= i
; j 
< content
.Length(); j
++) 
2418                     if (content
[j
] == '\r') 
2426             if (content
[i
] == '\r') count
++; 
2428     return wxString(""); 
2435 void wxTextCtrl::Command(wxCommandEvent 
& event
) 
2437     SetValue (event
.GetString()); 
2438     ProcessCommand (event
); 
2441 void wxTextCtrl::OnDropFiles(wxDropFilesEvent
& event
) 
2443     // By default, load the first file into the text window. 
2444     if (event
.GetNumberOfFiles() > 0) 
2446         LoadFile(event
.GetFiles()[0]); 
2450 void wxTextCtrl::OnChar(wxKeyEvent
& event
) 
2452     switch ( event
.KeyCode() ) 
2455             if (m_windowStyle 
& wxPROCESS_ENTER
) 
2457                 wxCommandEvent 
event(wxEVT_COMMAND_TEXT_ENTER
, m_windowId
); 
2458                 event
.SetEventObject( this ); 
2459                 if ( GetEventHandler()->ProcessEvent(event
) ) 
2462             if ( !(m_windowStyle 
& wxTE_MULTILINE
) ) 
2464                 wxWindow 
*parent 
= GetParent(); 
2465                 while( parent 
&& !parent
->IsTopLevel() && parent
->GetDefaultItem() == NULL 
) { 
2466                   parent 
= parent
->GetParent() ; 
2468                 if ( parent 
&& parent
->GetDefaultItem() ) 
2470                     wxButton 
*def 
= wxDynamicCast(parent
->GetDefaultItem(), 
2472                     if ( def 
&& def
->IsEnabled() ) 
2474                         wxCommandEvent 
event(wxEVT_COMMAND_BUTTON_CLICKED
, def
->GetId() ); 
2475                         event
.SetEventObject(def
); 
2476                         def
->Command(event
); 
2481             //else: multiline controls need Enter for themselves 
2486             // always produce navigation event - even if we process TAB 
2487             // ourselves the fact that we got here means that the user code 
2488             // decided to skip processing of this TAB - probably to let it 
2489             // do its default job. 
2491                 wxNavigationKeyEvent eventNav
; 
2492                 eventNav
.SetDirection(!event
.ShiftDown()); 
2493                 eventNav
.SetWindowChange(event
.ControlDown()); 
2494                 eventNav
.SetEventObject(this); 
2496                 if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav
) ) 
2504     EventRecord 
*ev 
= wxTheApp
->MacGetCurrentEvent() ; 
2507     keychar 
= short(ev
->message 
& charCodeMask
); 
2508     keycode 
= short(ev
->message 
& keyCodeMask
) >> 8 ; 
2509     UMAHandleControlKey( m_macControl 
, keycode 
, keychar 
, ev
->modifiers 
) ; 
2510     if ( keychar 
>= 0x20 || event
.KeyCode() == WXK_RETURN 
|| event
.KeyCode() == WXK_DELETE 
|| event
.KeyCode() == WXK_BACK
) 
2512         wxCommandEvent 
event(wxEVT_COMMAND_TEXT_UPDATED
, m_windowId
); 
2513         event
.SetString( GetValue() ) ; 
2514         event
.SetEventObject( this ); 
2515         GetEventHandler()->ProcessEvent(event
); 
2520 // ---------------------------------------------------------------------------- 
2521 // standard handlers for standard edit menu events 
2522 // ---------------------------------------------------------------------------- 
2524 void wxTextCtrl::OnCut(wxCommandEvent
& event
) 
2529 void wxTextCtrl::OnCopy(wxCommandEvent
& event
) 
2534 void wxTextCtrl::OnPaste(wxCommandEvent
& event
) 
2539 void wxTextCtrl::OnUndo(wxCommandEvent
& event
) 
2544 void wxTextCtrl::OnRedo(wxCommandEvent
& event
) 
2549 void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent
& event
) 
2551     event
.Enable( CanCut() ); 
2554 void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent
& event
) 
2556     event
.Enable( CanCopy() ); 
2559 void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent
& event
) 
2561     event
.Enable( CanPaste() ); 
2564 void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent
& event
) 
2566     event
.Enable( CanUndo() ); 
2569 void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent
& event
) 
2571     event
.Enable( CanRedo() );