X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/de0439842539961ed4a41781a7729227cfb6953e..fdd74b41b0a94b214aab4b7b03e75b60e877bd4e:/src/mac/carbon/textctrl.cpp?ds=inline diff --git a/src/mac/carbon/textctrl.cpp b/src/mac/carbon/textctrl.cpp index 64d585d233..b1ae31ebe5 100644 --- a/src/mac/carbon/textctrl.cpp +++ b/src/mac/carbon/textctrl.cpp @@ -1,11 +1,11 @@ ///////////////////////////////////////////////////////////////////////////// // Name: textctrl.cpp // Purpose: wxTextCtrl -// Author: AUTHOR +// Author: Stefan Csomor // Modified by: -// Created: ??/??/98 +// Created: 1998-01-01 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR +// Copyright: (c) Stefan Csomor // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -23,760 +23,131 @@ #else #include #endif -#include -#include "wx/app.h" -#include "wx/dc.h" -#include "wx/button.h" -#include "wx/toplevel.h" -#include "wx/textctrl.h" -#include "wx/notebook.h" -#include "wx/tabctrl.h" -#include "wx/settings.h" -#include "wx/filefn.h" -#include "wx/utils.h" - -#if defined(__BORLANDC__) && !defined(__WIN32__) - #include -#elif !defined(__MWERKS__) && !defined(__GNUWIN32) && !defined(__DARWIN__) - #include -#endif - -#include "wx/mac/uma.h" - -#define wxUSE_MLTE 0 - -#if wxUSE_MLTE == 0 // old textctrl implementation - -#if !USE_SHARED_LIBRARY -IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl) - -BEGIN_EVENT_TABLE(wxTextCtrl, wxControl) - EVT_DROP_FILES(wxTextCtrl::OnDropFiles) - EVT_CHAR(wxTextCtrl::OnChar) - EVT_MENU(wxID_CUT, wxTextCtrl::OnCut) - EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy) - EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste) - EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo) - EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo) - - EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut) - EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy) - EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste) - EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo) - EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo) -END_EVENT_TABLE() -#endif - -// Text item -wxTextCtrl::wxTextCtrl() -{ -} - -const short kVerticalMargin = 2 ; -const short kHorizontalMargin = 2 ; - -bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, - const wxString& st, - const wxPoint& pos, - const wxSize& size, long style, - const wxValidator& validator, - const wxString& name) -{ - // base initialization - if ( !CreateBase(parent, id, pos, size, style, validator, name) ) - return FALSE; - - wxSize mySize = size ; - if ( UMAHasAppearance() ) - { - m_macHorizontalBorder = 5 ; // additional pixels around the real control - m_macVerticalBorder = 5 ; - } - else - { - m_macHorizontalBorder = 0 ; // additional pixels around the real control - m_macVerticalBorder = 0 ; - } - - - Rect bounds ; - Str255 title ; - - if ( mySize.y == -1 ) - { - if ( UMAHasAppearance() ) - mySize.y = 13 ; - else - mySize.y = 24 ; - - mySize.y += 2 * m_macVerticalBorder ; - } - - MacPreControlCreate( parent , id , "" , pos , mySize ,style, validator , name , &bounds , title ) ; - - if ( m_windowStyle & wxTE_MULTILINE ) - { - wxASSERT_MSG( !(m_windowStyle & wxTE_PROCESS_ENTER), - wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") ); - - m_windowStyle |= wxTE_PROCESS_ENTER; - } - - - m_macControl = ::NewControl( parent->MacGetRootWindow() , &bounds , "\p" , true , 0 , 0 , 1, - ( style & wxTE_PASSWORD ) ? kControlEditTextPasswordProc : kControlEditTextProc , (long) this ) ; - MacPostControlCreate() ; - - wxString value ; - - { - TEHandle teH ; - long size ; - - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - (*teH)->lineHeight = -1 ; - } - - if( wxApp::s_macDefaultEncodingIsPC ) - value = wxMacMakeMacStringFromPC( st ) ; - else - value = st ; - ::SetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ; - - return TRUE; -} - -wxString wxTextCtrl::GetValue() const -{ - Size actualsize; - ::GetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 32767 , wxBuffer , &actualsize) ; - wxBuffer[actualsize] = 0 ; - if( wxApp::s_macDefaultEncodingIsPC ) - return wxMacMakePCStringFromMac( wxBuffer ) ; - else - return wxString(wxBuffer); -} - -void wxTextCtrl::GetSelection(long* from, long* to) const -{ - ControlEditTextSelectionRec selection ; - TEHandle teH ; - long size ; - - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - - *from = (**teH).selStart; - *to = (**teH).selEnd; -} - -void wxTextCtrl::SetValue(const wxString& st) -{ - wxString value ; - - if( wxApp::s_macDefaultEncodingIsPC ) - value = wxMacMakeMacStringFromPC( st ) ; - else - value = st ; - ::SetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ; - MacRedrawControl() ; -} - -// Clipboard operations -void wxTextCtrl::Copy() -{ - if (CanCopy()) - { - TEHandle teH ; - long size ; - - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - TECopy( teH ) ; - ClearCurrentScrap(); - TEToScrap() ; - } -} - -void wxTextCtrl::Cut() -{ - if (CanCut()) - { - TEHandle teH ; - long size ; - - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - TECut( teH ) ; - ClearCurrentScrap(); - TEToScrap() ; - // MacInvalidateControl() ; - } -} - -void wxTextCtrl::Paste() -{ - if (CanPaste()) - { - TEHandle teH ; - long size ; - - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - TEFromScrap() ; - TEPaste( teH ) ; - MacRedrawControl() ; - } -} - -bool wxTextCtrl::CanCopy() const -{ - // Can copy if there's a selection - long from, to; - GetSelection(& from, & to); - return (from != to); -} - -bool wxTextCtrl::CanCut() const -{ - // Can cut if there's a selection - long from, to; - GetSelection(& from, & to); - return (from != to); -} - -bool wxTextCtrl::CanPaste() const -{ - if (!IsEditable()) - return FALSE; - - long offset ; -#if TARGET_CARBON - OSStatus err = noErr; - ScrapRef scrapRef; - - err = GetCurrentScrap( &scrapRef ); - if ( err != noTypeErr && err != memFullErr ) - { - ScrapFlavorFlags flavorFlags; - Size byteCount; - - if (( err = GetScrapFlavorFlags( scrapRef, 'TEXT', &flavorFlags )) == noErr) - { - if (( err = GetScrapFlavorSize( scrapRef, 'TEXT', &byteCount )) == noErr) - { - return TRUE ; - } - } - } - return FALSE; - -#else - if ( GetScrap( NULL , 'TEXT' , &offset ) > 0 ) - { - return TRUE ; - } -#endif - return FALSE ; -} - -void wxTextCtrl::SetEditable(bool editable) -{ - if ( editable ) - UMAActivateControl( m_macControl ) ; - else - UMADeactivateControl( m_macControl ) ; -} - -void wxTextCtrl::SetInsertionPoint(long pos) -{ - SetSelection( pos , pos ) ; -} - -void wxTextCtrl::SetInsertionPointEnd() -{ - long pos = GetLastPosition(); - SetInsertionPoint(pos); -} - -long wxTextCtrl::GetInsertionPoint() const -{ - ControlEditTextSelectionRec selection ; - TEHandle teH ; - long size ; - - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; -// ::GetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection , &size ) ; - return (**teH).selStart ; -} - -long wxTextCtrl::GetLastPosition() const -{ - ControlEditTextSelectionRec selection ; - TEHandle teH ; - long size ; - - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - -// ::GetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection , &size ) ; - return (**teH).teLength ; -} - -void wxTextCtrl::Replace(long from, long to, const wxString& value) -{ - TEHandle teH ; - long size ; - - ControlEditTextSelectionRec selection ; - - selection.selStart = from ; - selection.selEnd = to ; - ::SetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ; - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - TESetSelect( from , to , teH ) ; - TEDelete( teH ) ; - TEInsert( value , value.Length() , teH ) ; - Refresh() ; -} - -void wxTextCtrl::Remove(long from, long to) -{ - TEHandle teH ; - long size ; - - ControlEditTextSelectionRec selection ; - - selection.selStart = from ; - selection.selEnd = to ; - ::SetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ; - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - TEDelete( teH ) ; - Refresh() ; -} - -void wxTextCtrl::SetSelection(long from, long to) -{ - ControlEditTextSelectionRec selection ; - TEHandle teH ; - long size ; - - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - - selection.selStart = from ; - selection.selEnd = to ; - - ::SetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ; - TESetSelect( selection.selStart , selection.selEnd , teH ) ; -} - -bool wxTextCtrl::LoadFile(const wxString& file) -{ - if ( wxTextCtrlBase::LoadFile(file) ) - { - return TRUE; - } - - return FALSE; -} - -void wxTextCtrl::WriteText(const wxString& text) -{ - TEHandle teH ; - long size ; - - memcpy( wxBuffer, text , text.Length() ) ; - wxBuffer[text.Length() ] = 0 ; -// wxMacConvertNewlines( wxBuffer , wxBuffer ) ; - - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - - TEInsert( wxBuffer , strlen( wxBuffer) , teH ) ; - Refresh() ; -} - -void wxTextCtrl::AppendText(const wxString& text) -{ - SetInsertionPointEnd(); - WriteText(text); -} - -void wxTextCtrl::Clear() -{ - ::SetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 0 , (char*) ((const char*)NULL) ) ; - Refresh() ; -} - -bool wxTextCtrl::IsModified() const -{ - return TRUE; -} - -bool wxTextCtrl::IsEditable() const -{ - return IsEnabled(); -} - -bool wxTextCtrl::AcceptsFocus() const -{ - // we don't want focus if we can't be edited - return IsEditable() && wxControl::AcceptsFocus(); -} - -wxSize wxTextCtrl::DoGetBestSize() const -{ - int wText = 100 ; - - int hText ; - if ( UMAHasAppearance() ) - hText = 13 ; - else - hText = 24 ; - hText += 2 * m_macHorizontalBorder ; -/* - int cx, cy; - wxGetCharSize(GetHWND(), &cx, &cy, &GetFont()); - - int wText = DEFAULT_ITEM_WIDTH; - - int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy); - - return wxSize(wText, hText); -*/ - if ( m_windowStyle & wxTE_MULTILINE ) - { - hText *= wxMin(GetNumberOfLines(), 5); - } - //else: for single line control everything is ok - return wxSize(wText, hText); -} - -// ---------------------------------------------------------------------------- -// Undo/redo -// ---------------------------------------------------------------------------- - -void wxTextCtrl::Undo() -{ - if (CanUndo()) - { - } -} - -void wxTextCtrl::Redo() -{ - if (CanRedo()) - { - } -} - -bool wxTextCtrl::CanUndo() const -{ - return FALSE ; -} - -bool wxTextCtrl::CanRedo() const -{ - return FALSE ; -} - -// Makes 'unmodified' -void wxTextCtrl::DiscardEdits() -{ - // TODO -} - -int wxTextCtrl::GetNumberOfLines() const -{ - Size actualsize; - ::GetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 32767 , wxBuffer , &actualsize) ; - - int count = 1; - for (int i = 0; i < actualsize; i++) - { - if (wxBuffer[i] == '\r') count++; - } - - return count; -} - -long wxTextCtrl::XYToPosition(long x, long y) const -{ - // TODO - return 0; -} - -bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const -{ - return FALSE ; -} - -void wxTextCtrl::ShowPosition(long pos) -{ - // TODO -} - -int wxTextCtrl::GetLineLength(long lineNo) const -{ - Size actualsize; - ::GetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 32767 , wxBuffer , &actualsize) ; - - // Find line first - int count = 0; - for (int i = 0; i < actualsize; i++) - { - if (count == lineNo) - { - // Count chars in line then - count = 0; - for (int j = i; j < actualsize; j++) - { - count++; - if (wxBuffer[j] == '\r') return count; - } - - return count; - } - if (wxBuffer[i] == '\r') count++; - } - - return 0; -} - -wxString wxTextCtrl::GetLineText(long lineNo) const -{ - Size actualsize; - ::GetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 32767 , wxBuffer , &actualsize) ; - - // Find line first - int count = 0; - for (int i = 0; i < actualsize; i++) - { - if (count == lineNo) - { - // Add chars in line then - wxString tmp(""); - - for (int j = i; j < actualsize; j++) - { - if (wxBuffer[j] == '\r') - return tmp; - - tmp += wxBuffer[j]; - } - - return tmp; - } - if (wxBuffer[i] == '\r') count++; - } - - return wxString(""); -} - -/* - * Text item - */ - -void wxTextCtrl::Command(wxCommandEvent & event) -{ - SetValue (event.GetString()); - ProcessCommand (event); -} - -void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event) -{ - // By default, load the first file into the text window. - if (event.GetNumberOfFiles() > 0) - { - LoadFile(event.GetFiles()[0]); - } -} +#include "wx/msgdlg.h" -void wxTextCtrl::OnChar(wxKeyEvent& key_event) -{ - bool eat_key = FALSE; - - switch ( key_event.KeyCode() ) - { - case WXK_RETURN: - if (m_windowStyle & wxPROCESS_ENTER) - { - wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId); - event.SetEventObject( this ); - event.SetString( GetValue() ); - if ( GetEventHandler()->ProcessEvent(event) ) - return; - } - if ( !(m_windowStyle & wxTE_MULTILINE) ) - { - wxWindow *parent = GetParent(); - while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL ) { - parent = parent->GetParent() ; - } - if ( parent && parent->GetDefaultItem() ) - { - wxButton *def = wxDynamicCast(parent->GetDefaultItem(), - wxButton); - if ( def && def->IsEnabled() ) - { - wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() ); - event.SetEventObject(def); - def->Command(event); - return ; - } - } - - // this will make wxWindows eat the ENTER key so that - // we actually prevent line wrapping in a single line - // text control - eat_key = TRUE; - } - - break; +#if wxUSE_STD_IOSTREAM + #if wxUSE_IOSTREAMH + #include + #else + #include + #endif +#endif - case WXK_TAB: - // always produce navigation event - even if we process TAB - // ourselves the fact that we got here means that the user code - // decided to skip processing of this TAB - probably to let it - // do its default job. - { - wxNavigationKeyEvent eventNav; - eventNav.SetDirection(!key_event.ShiftDown()); - eventNav.SetWindowChange(key_event.ControlDown()); - eventNav.SetEventObject(this); +#include "wx/app.h" +#include "wx/dc.h" +#include "wx/button.h" +#include "wx/toplevel.h" +#include "wx/textctrl.h" +#include "wx/notebook.h" +#include "wx/tabctrl.h" +#include "wx/settings.h" +#include "wx/filefn.h" +#include "wx/utils.h" - if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav) ) - return; +#if defined(__BORLANDC__) && !defined(__WIN32__) + #include +#elif !defined(__MWERKS__) && !defined(__GNUWIN32) && !defined(__DARWIN__) + #include +#endif - key_event.Skip() ; - return; - } - break; - } - - EventRecord *ev = wxTheApp->MacGetCurrentEvent(); - short keychar = short(ev->message & charCodeMask); - if (!eat_key) - { - short keycode = short(ev->message & keyCodeMask) >> 8 ; - ::HandleControlKey( m_macControl , keycode , keychar , ev->modifiers ); - } - if ( keychar >= 0x20 || - key_event.KeyCode() == WXK_RETURN || - key_event.KeyCode() == WXK_DELETE || - key_event.KeyCode() == WXK_BACK) - { - wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId); - event.SetString( GetValue() ) ; - event.SetEventObject( this ); - GetEventHandler()->ProcessEvent(event); - } -} +#ifndef __DARWIN__ +#include +#endif +#include +#include +#include +#include +#include "wx/mac/uma.h" -// ---------------------------------------------------------------------------- -// standard handlers for standard edit menu events -// ---------------------------------------------------------------------------- +#define TE_UNLIMITED_LENGTH 0xFFFFFFFFUL +#if TARGET_API_MAC_OSX + #define wxMAC_USE_MLTE 0 + #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 + #define wxMAC_USE_MLTE_HIVIEW 1 + #else + #define wxMAC_USE_MLTE_HIVIEW 0 + #endif +#else + // there is no unicodetextctrl on classic, and hopefully MLTE works better there + #define wxMAC_USE_MLTE 1 + #define wxMAC_USE_MLTE_HIVIEW 0 +#endif -void wxTextCtrl::OnCut(wxCommandEvent& event) -{ - Cut(); -} +#if wxMAC_USE_MLTE -void wxTextCtrl::OnCopy(wxCommandEvent& event) +TXNFrameOptions FrameOptionsFromWXStyle( long wxStyle ) { - Copy(); -} + TXNFrameOptions frameOptions = + kTXNDontDrawCaretWhenInactiveMask ; + if ( ! ( wxStyle & wxTE_NOHIDESEL ) ) + frameOptions |= kTXNDontDrawSelectionWhenInactiveMask ; -void wxTextCtrl::OnPaste(wxCommandEvent& event) -{ - Paste(); -} + if ( wxStyle & wxTE_MULTILINE ) + { + if ( ! ( wxStyle & wxTE_DONTWRAP ) ) + frameOptions |= kTXNAlwaysWrapAtViewEdgeMask ; + else + { + frameOptions |= kTXNAlwaysWrapAtViewEdgeMask ; + frameOptions |= kTXNWantHScrollBarMask ; + } -void wxTextCtrl::OnUndo(wxCommandEvent& event) -{ - Undo(); + if ( !(wxStyle & wxTE_NO_VSCROLL ) ) + frameOptions |= kTXNWantVScrollBarMask ; + } + else + frameOptions |= kTXNSingleLineOnlyMask ; + return frameOptions ; } -void wxTextCtrl::OnRedo(wxCommandEvent& event) +void AdjustAttributesFromWXStyle( TXNObject txn , long wxStyle , bool visible ) { - Redo(); -} + TXNControlTag iControlTags[3] = { kTXNDoFontSubstitution, kTXNWordWrapStateTag }; + TXNControlData iControlData[3] = { {false}, {kTXNNoAutoWrap} }; + int toptag = 2 ; +#if TARGET_API_MAC_OSX + iControlTags[2] = kTXNVisibilityTag ; + iControlData[2].uValue = visible ; + toptag++ ; +#endif + + if ( wxStyle & wxTE_MULTILINE ) + { + if (wxStyle & wxTE_DONTWRAP) + iControlData[1].uValue = kTXNNoAutoWrap ; + else + iControlData[1].uValue = kTXNAutoWrap ; + + } + verify_noerr( TXNSetTXNObjectControls( txn, false, toptag, + iControlTags, iControlData )) ; -void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event) -{ - event.Enable( CanCut() ); -} + Str255 fontName ; + SInt16 fontSize ; + Style fontStyle ; -void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event) -{ - event.Enable( CanCopy() ); -} + GetThemeFont(kThemeSystemFont , GetApplicationScript() , fontName , &fontSize , &fontStyle ) ; -void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event) -{ - event.Enable( CanPaste() ); -} + TXNTypeAttributes typeAttr[] = + { + { kTXNQDFontNameAttribute , kTXNQDFontNameAttributeSize , { (void*) fontName } } , + { kTXNQDFontSizeAttribute , kTXNFontSizeAttributeSize , { (void*) (fontSize << 16) } } , + { kTXNQDFontStyleAttribute , kTXNQDFontStyleAttributeSize , { (void*) normal } } , + } ; -void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event) -{ - event.Enable( CanUndo() ); -} + verify_noerr( TXNSetTypeAttributes (txn, sizeof( typeAttr ) / sizeof(TXNTypeAttributes) , typeAttr, + kTXNStartOffset, + kTXNEndOffset) ); -void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event) -{ - event.Enable( CanRedo() ); } -#else - -extern wxApp *wxTheApp ; -// CS:We will replace the TextEdit by using the MultiLanguageTextEngine based on the following code written by apple - -/* - File: mUPControl.c - - Description: - mUPControl implementation. +#if !wxMAC_USE_MLTE_HIVIEW - Copyright: - © Copyright 2000 Apple Computer, Inc. All rights reserved. - - Disclaimer: - IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. - ("Apple") in consideration of your agreement to the following terms, and your - use, installation, modification or redistribution of this Apple software - constitutes acceptance of these terms. If you do not agree with these terms, - please do not use, install, modify or redistribute this Apple software. - - In consideration of your agreement to abide by the following terms, and subject - to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs - copyrights in this original Apple software (the "Apple Software"), to use, - reproduce, modify and redistribute the Apple Software, with or without - modifications, in source and/or binary forms; provided that if you redistribute - the Apple Software in its entirety and without modifications, you must retain - this notice and the following text and disclaimers in all such redistributions of - the Apple Software. Neither the name, trademarks, service marks or logos of - Apple Computer, Inc. may be used to endorse or promote products derived from the - Apple Software without specific prior written permission from Apple. Except as - expressly stated in this notice, no other rights or licenses, express or implied, - are granted by Apple herein, including but not limited to any patent rights that - may be infringed by your derivative works or by other works in which the Apple - Software may be incorporated. - - The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO - WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED - WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN - COMBINATION WITH YOUR PRODUCTS. - - IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION - OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT - (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - Change History (most recent first): - Fri, Jan 28, 2000 -- created -*/ - -#include "MacTextEditor.h" +// CS:TODO we still have a problem getting properly at the text events of a control because under Carbon +// the MLTE engine registers itself for the key events thus the normal flow never occurs, the only measure for the +// moment is to avoid setting the true focus on the control, the proper solution at the end would be to have +// an alternate path for carbon key events that routes automatically into the same wx flow of events /* part codes */ @@ -784,111 +155,20 @@ extern wxApp *wxTheApp ; in the text area of our control */ #define kmUPTextPart 1 -/* kmUPScrollPart is the part code we return to indicate the user has clicked - in the scroll bar part of the control. */ -#define kmUPScrollPart 2 - /* routines for using existing user pane controls. These routines are useful for cases where you would like to use an existing user pane control in, say, a dialog window as a scrolling text edit field.*/ - -/* mUPOpenControl initializes a user pane control so it will be drawn - and will behave as a scrolling text edit field inside of a window. - This routine performs all of the initialization steps necessary, - except it does not create the user pane control itself. theControl - should refer to a user pane control that you have either created - yourself or extracted from a dialog's control heirarchy using - the GetDialogItemAsControl routine. */ -OSStatus mUPOpenControl(ControlHandle theControl); - -/* mUPCloseControl deallocates all of the structures allocated - by mUPOpenControl. */ -OSStatus mUPCloseControl(ControlHandle theControl); - - - -/* routines for creating new scrolling text user pane controls. - These routines allow you to create new scrolling text - user pane controls. */ - -/* mUPCreateControl creates a new user pane control and then it passes it - to mUPOpenControl to initialize it as a scrolling text user pane control. */ -OSStatus mUPCreateControl(WindowPtr theWindow, Rect *bounds, ControlHandle *theControl); - -/* mUPDisposeControl calls mUPCloseControl and then it calls DisposeControl. */ -OSStatus mUPDisposeControl(ControlHandle theControl); - /* Utility Routines */ - /* mUPSetText replaces the contents of the selection with the unicode - text described by the text and count parameters:. - text = pointer to unicode text buffer - count = number of bytes in the buffer. */ -OSStatus mUPSetText(ControlHandle theControl, char* text, long count); - -/* mUPGetText returns the current text data being displayed inside of - the mUPControl. When noErr is returned, *theText contain a new - handle containing all of the Unicode text copied from the current - selection. It is the caller's responsibiliby to dispose of this handle. */ -OSStatus mUPGetText(ControlHandle theControl, Handle *theText); - - -/* mUPSetSelection sets the text selection and autoscrolls the text view - so either the cursor or the selction is in the view. */ -void mUPSetSelection(ControlHandle theControl, long selStart, long selEnd); - - - -/* IsmUPControl returns true if theControl is not NULL - and theControl refers to a mUP Control. */ -Boolean IsmUPControl(ControlHandle theControl); - - - -/* Edit commands for mUP Controls. */ -enum { - kmUPCut = 1, - kmUPCopy = 2, - kmUPPaste = 3, - kmUPClear = 4 -}; - - -/* mUPDoEditCommand performs the editing command specified - in the editCommand parameter. The mUPControl's text - and scroll bar are redrawn and updated as necessary. */ -void mUPDoEditCommand(ControlHandle theControl, short editCommand); - - - - -/* mUPGetContents returns the entire contents of the control including the text - and the formatting information. */ -OSStatus mUPGetContents(ControlHandle theControl, Handle *theContents); -/* mUPSetContents replaces the contents of the selection with the data stored in the handle. */ -OSStatus mUPSetContents(ControlHandle theControl, Handle theContents); - -enum { - kShiftKeyCode = 56 -}; - /* kUserClickedToFocusPart is a part code we pass to the SetKeyboardFocus routine. In our focus switching routine this part code is understood as meaning 'the user has clicked in the control and we need to switch the current focus to ourselves before we can continue'. */ #define kUserClickedToFocusPart 100 - -/* kmUPClickScrollDelayTicks is a time measurement in ticks used to - slow the speed of 'auto scrolling' inside of our clickloop routine. - This value prevents the text from wizzzzzing by while the mouse - is being held down inside of the text area. */ -#define kmUPClickScrollDelayTicks 3 - - /* STPTextPaneVars is a structure used for storing the the mUP Control's internal variables and state information. A handle to this record is stored in the pane control's reference value field using the @@ -898,24 +178,37 @@ typedef struct { /* OS records referenced */ TXNObject fTXNRec; /* the txn record */ TXNFrameID fTXNFrame; /* the txn frame ID */ - ControlHandle fUserPaneRec; /* handle to the user pane control */ + ControlRef fUserPaneRec; /* handle to the user pane control */ WindowPtr fOwner; /* window containing control */ GrafPtr fDrawingEnvironment; /* grafport where control is drawn */ /* flags */ Boolean fInFocus; /* true while the focus rect is drawn around the control */ Boolean fIsActive; /* true while the control is drawn in the active state */ - Boolean fTEActive; /* reflects the activation state of the text edit record */ - Boolean fInDialogWindow; /* true if displayed in a dialog window */ + Boolean fTXNObjectActive; /* reflects the activation state of the text edit record */ + Boolean fFocusDrawState; /* true if focus is drawn (default: true) */ /* calculated locations */ + Rect fRBounds; /* control bounds */ Rect fRTextArea; /* area where the text is drawn */ Rect fRFocusOutline; /* rectangle used to draw the focus box */ Rect fRTextOutline; /* rectangle used to draw the border */ - RgnHandle fTextBackgroundRgn; /* background region for the text, erased before calling TEUpdate */ + RgnHandle fRTextOutlineRegion; /* background region for the text, erased before calling TEUpdate */ /* our focus advance override routine */ EventHandlerUPP handlerUPP; EventHandlerRef handlerRef; + bool fNoBorders ; + bool fMultiline ; + bool fVisible ; } STPTextPaneVars; +/* mUPOpenControl initializes a user pane control so it will be drawn + and will behave as a scrolling text edit field inside of a window. + This routine performs all of the initialization steps necessary, + except it does not create the user pane control itself. theControl + should refer to a user pane control that you have either created + yourself or extracted from a dialog's control heirarchy using + the GetDialogItemAsControl routine. */ +OSStatus mUPOpenControl(STPTextPaneVars* &handle, ControlRef theControl, long wxStyle); + @@ -930,79 +223,133 @@ ControlUserPaneKeyDownUPP gTPKeyProc = NULL; ControlUserPaneActivateUPP gTPActivateProc = NULL; ControlUserPaneFocusUPP gTPFocusProc = NULL; - /* events handled by our focus advance override routine */ -#if TARGET_CARBON -static const EventTypeSpec gMLTEEvents[] = { { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } }; -#define kMLTEEventCount (sizeof( gMLTEEvents ) / sizeof( EventTypeSpec )) +// one place for calculating all +static void TPCalculateBounds(STPTextPaneVars *varsp, const Rect& bounds) +{ + SetRect(&varsp->fRBounds, bounds.left, bounds.top, bounds.right, bounds.bottom); + SetRect(&varsp->fRFocusOutline, bounds.left, bounds.top, bounds.right, bounds.bottom); + // eventually make TextOutline inset 1,1 + SetRect(&varsp->fRTextOutline, bounds.left, bounds.top, bounds.right, bounds.bottom); + if ( !varsp->fNoBorders ) + { + SetRect(&varsp->fRTextArea, bounds.left + 2 , bounds.top + (varsp->fMultiline ? 0 : 2) , + bounds.right - (varsp->fMultiline ? 0 : 2), bounds.bottom - (varsp->fMultiline ? 0 : 2)); + } + else + { + SetRect(&varsp->fRTextArea, bounds.left , bounds.top , + bounds.right, bounds.bottom); + } +} + +OSStatus MLTESetObjectVisibility( STPTextPaneVars *varsp, Boolean vis , long wxStyle) +{ + OSStatus err = noErr ; +#if TARGET_API_MAC_OSX + TXNControlTag iControlTags[1] = { kTXNVisibilityTag }; + TXNControlData iControlData[1] = {{ vis }}; + err = ::TXNSetTXNObjectControls( varsp->fTXNRec, false, 1, iControlTags, iControlData ); #endif + wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(varsp->fUserPaneRec); + if ( vis && textctrl ) + { + Rect bounds ; + UMAGetControlBoundsInWindowCoords( varsp->fUserPaneRec, &bounds); + TPCalculateBounds( varsp , bounds ) ; + wxMacWindowClipper cl(textctrl) ; + TXNSetFrameBounds( varsp->fTXNRec, varsp->fRTextArea.top, varsp->fRTextArea.left, + varsp->fRTextArea.bottom, varsp->fRTextArea.right, varsp->fTXNFrame); + TXNShowSelection( varsp->fTXNRec, kTXNShowStart); + } + return err ; +} +// make sure we don't miss changes as carbon events are not available for these under classic +static void TPUpdateVisibility(ControlRef theControl) { + wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl); + if ( textctrl == NULL ) + return ; -/* TPActivatePaneText activates or deactivates the text edit record - according to the value of setActive. The primary purpose of this - routine is to ensure each call is only made once. */ -static void TPActivatePaneText(STPTextPaneVars **tpvars, Boolean setActive) { - STPTextPaneVars *varsp; - varsp = *tpvars; - if (varsp->fTEActive != setActive) { - - varsp->fTEActive = setActive; - - TXNActivate(varsp->fTXNRec, varsp->fTXNFrame, varsp->fTEActive); - + STPTextPaneVars *varsp = (STPTextPaneVars *) textctrl->m_macTXNvars ; + + Rect bounds ; + UMAGetControlBoundsInWindowCoords(theControl, &bounds); + if ( textctrl->MacIsReallyShown() != varsp->fVisible ) + { + // invalidate old position + // InvalWindowRect( GetControlOwner( theControl ) , &varsp->fRBounds ) ; + varsp->fVisible = textctrl->MacIsReallyShown() ; + } + if ( !EqualRect( &bounds , &varsp->fRBounds ) ) + { + // old position + Rect oldBounds = varsp->fRBounds ; + TPCalculateBounds( varsp , bounds ) ; + // we only recalculate when visible, otherwise scrollbars get drawn at incorrect places + if ( varsp->fVisible ) + { + wxMacWindowClipper cl(textctrl) ; + TXNSetFrameBounds( varsp->fTXNRec, varsp->fRTextArea.top, varsp->fRTextArea.left, + varsp->fRTextArea.bottom, varsp->fRTextArea.right, varsp->fTXNFrame); + } + InvalWindowRect( GetControlOwner( theControl ) , &oldBounds ) ; + InvalWindowRect( GetControlOwner( theControl ) , &varsp->fRBounds ) ; + } +} + +// make correct activations +static void TPActivatePaneText(STPTextPaneVars *varsp, Boolean setActive) { + + wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(varsp->fUserPaneRec); + if (varsp->fTXNObjectActive != setActive && textctrl->MacIsReallyShown() ) + { + varsp->fTXNObjectActive = setActive; + TXNActivate(varsp->fTXNRec, varsp->fTXNFrame, varsp->fTXNObjectActive); if (varsp->fInFocus) - TXNFocus( varsp->fTXNRec, varsp->fTEActive); + TXNFocus( varsp->fTXNRec, varsp->fTXNObjectActive); } } +// update focus outlines +static void TPRedrawFocusOutline(STPTextPaneVars *varsp) { -/* TPFocusPaneText set the focus state for the text record. */ -static void TPFocusPaneText(STPTextPaneVars **tpvars, Boolean setFocus) { - STPTextPaneVars *varsp; - varsp = *tpvars; - if (varsp->fInFocus != setFocus) { + /* state changed */ + if (varsp->fFocusDrawState != (varsp->fIsActive && varsp->fInFocus)) + { + varsp->fFocusDrawState = (varsp->fIsActive && varsp->fInFocus); + DrawThemeFocusRect(&varsp->fRFocusOutline, varsp->fFocusDrawState); + } +} + +// update TXN focus state +static void TPFocusPaneText(STPTextPaneVars *varsp, Boolean setFocus) { + wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(varsp->fUserPaneRec); + + if (varsp->fInFocus != setFocus && textctrl->MacIsReallyShown()) { varsp->fInFocus = setFocus; TXNFocus( varsp->fTXNRec, varsp->fInFocus); } } - -/* TPPaneDrawProc is called to redraw the control and for update events - referring to the control. This routine erases the text area's background, - and redraws the text. This routine assumes the scroll bar has been - redrawn by a call to DrawControls. */ +// draw the control static pascal void TPPaneDrawProc(ControlRef theControl, ControlPartCode thePart) { - STPTextPaneVars **tpvars, *varsp; - char state; - Rect bounds; /* set up our globals */ - tpvars = (STPTextPaneVars **) GetControlReference(theControl); - if (tpvars != NULL) { - state = HGetState((Handle) tpvars); - HLock((Handle) tpvars); - varsp = *tpvars; - - /* save the drawing state */ - SetPort((**tpvars).fDrawingEnvironment); - /* verify our boundary */ - GetControlBounds(theControl, &bounds); - if ( ! EqualRect(&bounds, &varsp->fRTextArea) ) { - SetRect(&varsp->fRFocusOutline, bounds.left, bounds.top, bounds.right, bounds.bottom); - SetRect(&varsp->fRTextOutline, bounds.left, bounds.top, bounds.right, bounds.bottom); - SetRect(&varsp->fRTextArea, bounds.left, bounds.top, bounds.right, bounds.bottom); - RectRgn(varsp->fTextBackgroundRgn, &varsp->fRTextOutline); - TXNSetFrameBounds( varsp->fTXNRec, bounds.top, bounds.left, bounds.bottom, bounds.right, varsp->fTXNFrame); - } - /* update the text region */ - EraseRgn(varsp->fTextBackgroundRgn); + wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl); + if ( textctrl == NULL ) + return ; + TPUpdateVisibility( theControl ) ; + + STPTextPaneVars *varsp = (STPTextPaneVars *) textctrl->m_macTXNvars ; + if ( textctrl->MacIsReallyShown() ) + { + wxMacWindowClipper clipper( textctrl ) ; TXNDraw(varsp->fTXNRec, NULL); - /* restore the drawing environment */ - /* draw the text frame and focus frame (if necessary) */ - DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive); - if ((**tpvars).fIsActive && varsp->fInFocus) DrawThemeFocusRect(&varsp->fRFocusOutline, true); - /* release our globals */ - HSetState((Handle) tpvars, state); + if ( !varsp->fNoBorders ) + DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive); + TPRedrawFocusOutline( varsp ) ; } + } @@ -1010,22 +357,21 @@ static pascal void TPPaneDrawProc(ControlRef theControl, ControlPartCode thePart like to determine what part of the control the mouse resides over. We also call this routine from our tracking proc to determine how to handle mouse clicks. */ -static pascal ControlPartCode TPPaneHitTestProc(ControlHandle theControl, Point where) { - STPTextPaneVars **tpvars; +static pascal ControlPartCode TPPaneHitTestProc(ControlRef theControl, Point where) { ControlPartCode result; - char state; /* set up our locals and lock down our globals*/ result = 0; - tpvars = (STPTextPaneVars **) GetControlReference(theControl); - if (tpvars != NULL) { - state = HGetState((Handle) tpvars); - HLock((Handle) tpvars); - /* find the region where we clicked */ - if (PtInRect(where, &(**tpvars).fRTextArea)) { + wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl); + if ( textctrl == NULL ) + return 0 ; + TPUpdateVisibility( theControl ) ; + STPTextPaneVars *varsp = (STPTextPaneVars *) textctrl->m_macTXNvars ; + if (textctrl->MacIsReallyShown() ) + { + if (PtInRect(where, &varsp->fRBounds)) result = kmUPTextPart; - } else result = 0; - /* release oure globals */ - HSetState((Handle) tpvars, state); + else + result = 0; } return result; } @@ -1037,38 +383,51 @@ static pascal ControlPartCode TPPaneHitTestProc(ControlHandle theControl, Point /* TPPaneTrackingProc is called when the mouse is being held down over our control. This routine handles clicks in the text area and in the scroll bar. */ -static pascal ControlPartCode TPPaneTrackingProc(ControlHandle theControl, Point startPt, ControlActionUPP actionProc) { - STPTextPaneVars **tpvars, *varsp; - char state; +static pascal ControlPartCode TPPaneTrackingProc(ControlRef theControl, Point startPt, ControlActionUPP actionProc) { + ControlPartCode partCodeResult; - /* make sure we have some variables... */ + /* make sure we have some variables... */ partCodeResult = 0; - tpvars = (STPTextPaneVars **) GetControlReference(theControl); - if (tpvars != NULL) { - /* lock 'em down */ - state = HGetState((Handle) tpvars); - HLock((Handle) tpvars); - varsp = *tpvars; - /* we don't do any of these functions unless we're in focus */ + wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl); + if ( textctrl == NULL ) + return 0; + TPUpdateVisibility( theControl ) ; + STPTextPaneVars *varsp = (STPTextPaneVars *) textctrl->m_macTXNvars ; + if (textctrl->MacIsReallyShown() ) + { + /* we don't do any of these functions unless we're in focus */ if ( ! varsp->fInFocus) { WindowPtr owner; owner = GetControlOwner(theControl); ClearKeyboardFocus(owner); SetKeyboardFocus(owner, theControl, kUserClickedToFocusPart); } - /* find the location for the click */ - switch (TPPaneHitTestProc(theControl, startPt)) { - - /* handle clicks in the text part */ + /* find the location for the click */ + // for compositing, we must convert these into toplevel window coordinates, because hittesting expects them + if ( textctrl->MacGetTopLevelWindow()->MacUsesCompositing() ) + { + int x = 0 , y = 0 ; + textctrl->MacClientToRootWindow( &x , &y ) ; + startPt.h += x ; + startPt.v += y ; + } + + switch (TPPaneHitTestProc(theControl, startPt)) + { + + /* handle clicks in the text part */ case kmUPTextPart: - { SetPort((**tpvars).fDrawingEnvironment); - TXNClick( varsp->fTXNRec, GetCurrentEventRecord()); - } + { + wxMacWindowClipper clipper( textctrl ) ; + + EventRecord rec ; + ConvertEventRefToEventRecord( (EventRef) wxTheApp->MacGetCurrentEvent() , &rec ) ; + TXNClick( varsp->fTXNRec, &rec ); + + } break; - + } - - HSetState((Handle) tpvars, state); } return partCodeResult; } @@ -1076,31 +435,25 @@ static pascal ControlPartCode TPPaneTrackingProc(ControlHandle theControl, Point /* TPPaneIdleProc is our user pane idle routine. When our text field is active and in focus, we use this routine to set the cursor. */ -static pascal void TPPaneIdleProc(ControlHandle theControl) { - STPTextPaneVars **tpvars, *varsp; +static pascal void TPPaneIdleProc(ControlRef theControl) { /* set up locals */ - tpvars = (STPTextPaneVars **) GetControlReference(theControl); - if (tpvars != NULL) { + wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl); + if ( textctrl == NULL ) + return ; + TPUpdateVisibility( theControl ) ; + STPTextPaneVars *varsp = (STPTextPaneVars *) textctrl->m_macTXNvars ; + if (textctrl->MacIsReallyShown()) { /* if we're not active, then we have nothing to say about the cursor */ - if ((**tpvars).fIsActive) { - char state; + if (varsp->fIsActive) { Rect bounds; Point mousep; - /* lock down the globals */ - state = HGetState((Handle) tpvars); - HLock((Handle) tpvars); - varsp = *tpvars; - /* get the current mouse coordinates (in our window) */ -#if TARGET_CARBON - SetPort(GetWindowPort(GetControlOwner(theControl))); -#else - SetPort((GrafPtr) GetWindowPort(GetControlOwner(theControl))); -#endif + + wxMacWindowClipper clipper( textctrl ) ; GetMouse(&mousep); /* there's a 'focus thing' and an 'unfocused thing' */ if (varsp->fInFocus) { /* flash the cursor */ - SetPort((**tpvars).fDrawingEnvironment); + SetPort(varsp->fDrawingEnvironment); TXNIdle(varsp->fTXNRec); /* set the cursor */ if (PtInRect(mousep, &varsp->fRTextArea)) { @@ -1108,15 +461,19 @@ static pascal void TPPaneIdleProc(ControlHandle theControl) { RectRgn((theRgn = NewRgn()), &varsp->fRTextArea); TXNAdjustCursor(varsp->fTXNRec, theRgn); DisposeRgn(theRgn); - } else SetThemeCursor(kThemeArrowCursor); + } + else + { + // SetThemeCursor(kThemeArrowCursor); + } } else { /* if it's in our bounds, set the cursor */ - GetControlBounds(theControl, &bounds); + UMAGetControlBoundsInWindowCoords(theControl, &bounds); if (PtInRect(mousep, &bounds)) - SetThemeCursor(kThemeArrowCursor); + { + // SetThemeCursor(kThemeArrowCursor); + } } - - HSetState((Handle) tpvars, state); } } } @@ -1125,16 +482,25 @@ static pascal void TPPaneIdleProc(ControlHandle theControl) { /* TPPaneKeyDownProc is called whenever a keydown event is directed at our control. Here, we direct the keydown event to the text edit record and redraw the scroll bar and text field as appropriate. */ -static pascal ControlPartCode TPPaneKeyDownProc(ControlHandle theControl, +static pascal ControlPartCode TPPaneKeyDownProc(ControlRef theControl, SInt16 keyCode, SInt16 charCode, SInt16 modifiers) { - STPTextPaneVars **tpvars; - tpvars = (STPTextPaneVars **) GetControlReference(theControl); - if (tpvars != NULL) { - if ((**tpvars).fInFocus) { - /* turn autoscrolling on and send the key event to text edit */ - SetPort((**tpvars).fDrawingEnvironment); - TXNKeyDown( (**tpvars).fTXNRec, GetCurrentEventRecord()); - } + + wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl); + if ( textctrl == NULL ) + return 0; + TPUpdateVisibility( theControl ) ; + + STPTextPaneVars *varsp = (STPTextPaneVars *) textctrl->m_macTXNvars ; + if (varsp->fInFocus) + { + /* turn autoscrolling on and send the key event to text edit */ + wxMacWindowClipper clipper( textctrl ) ; + EventRecord ev ; + memset( &ev , 0 , sizeof( ev ) ) ; + ev.what = keyDown ; + ev.modifiers = modifiers ; + ev.message = (( keyCode << 8 ) & keyCodeMask ) + ( charCode & charCodeMask ) ; + TXNKeyDown( varsp->fTXNRec, &ev); } return kControlEntireControl; } @@ -1143,176 +509,131 @@ static pascal ControlPartCode TPPaneKeyDownProc(ControlHandle theControl, /* TPPaneActivateProc is called when the window containing the user pane control receives activate events. Here, we redraw the control and it's text as necessary for the activation state. */ -static pascal void TPPaneActivateProc(ControlHandle theControl, Boolean activating) { - Rect bounds; - STPTextPaneVars **tpvars, *varsp; - char state; - /* set up locals */ - tpvars = (STPTextPaneVars **) GetControlReference(theControl); - if (tpvars != NULL) { - state = HGetState((Handle) tpvars); - HLock((Handle) tpvars); - varsp = *tpvars; - /* de/activate the text edit record */ - SetPort((**tpvars).fDrawingEnvironment); - GetControlBounds(theControl, &bounds); - varsp->fIsActive = activating; - TPActivatePaneText(tpvars, varsp->fIsActive && varsp->fInFocus); - /* redraw the frame */ - DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive); - if (varsp->fInFocus) DrawThemeFocusRect(&varsp->fRFocusOutline, varsp->fIsActive); - HSetState((Handle) tpvars, state); - } -} - - -/* TPPaneFocusProc is called when every the focus changes to or - from our control. Herein, switch the focus appropriately - according to the parameters and redraw the control as - necessary. */ -static pascal ControlPartCode TPPaneFocusProc(ControlHandle theControl, ControlFocusPart action) { - ControlPartCode focusResult; - STPTextPaneVars **tpvars, *varsp; - char state; +static pascal void TPPaneActivateProc(ControlRef theControl, Boolean activating) { /* set up locals */ - focusResult = kControlFocusNoPart; - tpvars = (STPTextPaneVars **) GetControlReference(theControl); - if (tpvars != NULL) { - state = HGetState((Handle) tpvars); - HLock((Handle) tpvars); - varsp = *tpvars; - /* if kControlFocusPrevPart and kControlFocusNextPart are received when the user is - tabbing forwards (or shift tabbing backwards) through the items in the dialog, - and kControlFocusNextPart will be received. When the user clicks in our field - and it is not the current focus, then the constant kUserClickedToFocusPart will - be received. The constant kControlFocusNoPart will be received when our control - is the current focus and the user clicks in another control. In your focus routine, - you should respond to these codes as follows: - - kControlFocusNoPart - turn off focus and return kControlFocusNoPart. redraw - the control and the focus rectangle as necessary. - - kControlFocusPrevPart or kControlFocusNextPart - toggle focus on or off - depending on its current state. redraw the control and the focus rectangle - as appropriate for the new focus state. If the focus state is 'off', return the constant - kControlFocusNoPart, otherwise return a non-zero part code. - kUserClickedToFocusPart - is a constant defined for this example. You should - define your own value for handling click-to-focus type events. */ - /* save the drawing state */ - SetPort((**tpvars).fDrawingEnvironment); - /* calculate the next highlight state */ - switch (action) { - default: - case kControlFocusNoPart: - TPFocusPaneText(tpvars, false); - focusResult = kControlFocusNoPart; - break; - case kUserClickedToFocusPart: - TPFocusPaneText(tpvars, true); - focusResult = 1; - break; - case kControlFocusPrevPart: - case kControlFocusNextPart: - TPFocusPaneText(tpvars, ( ! varsp->fInFocus)); - focusResult = varsp->fInFocus ? 1 : kControlFocusNoPart; - break; - } - TPActivatePaneText(tpvars, varsp->fIsActive && varsp->fInFocus); - /* redraw the text fram and focus rectangle to indicate the - new focus state */ - DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive); - DrawThemeFocusRect(&varsp->fRFocusOutline, varsp->fIsActive && varsp->fInFocus); - /* done */ - HSetState((Handle) tpvars, state); - } - return focusResult; -} - - - - + wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl); + + if ( textctrl == NULL ) + return ; + TPUpdateVisibility( theControl ) ; + + STPTextPaneVars *varsp = (STPTextPaneVars *) textctrl->m_macTXNvars ; + varsp->fIsActive = activating; + wxMacWindowClipper clipper( textctrl ) ; + TPActivatePaneText(varsp, varsp->fIsActive && varsp->fInFocus); + /* redraw the frame */ + if ( textctrl->MacIsReallyShown() ) + { + if ( !varsp->fNoBorders ) + DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive); + TPRedrawFocusOutline( varsp ) ; + } +} +/* TPPaneFocusProc is called when every the focus changes to or + from our control. Herein, switch the focus appropriately + according to the parameters and redraw the control as + necessary. */ +static pascal ControlPartCode TPPaneFocusProc(ControlRef theControl, ControlFocusPart action) { + ControlPartCode focusResult; + focusResult = kControlFocusNoPart; + wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl); + if ( textctrl == NULL ) + return 0; + TPUpdateVisibility( theControl ) ; + STPTextPaneVars *varsp = (STPTextPaneVars *) textctrl->m_macTXNvars ; + /* if kControlFocusPrevPart and kControlFocusNextPart are received when the user is + tabbing forwards (or shift tabbing backwards) through the items in the dialog, + and kControlFocusNextPart will be received. When the user clicks in our field + and it is not the current focus, then the constant kUserClickedToFocusPart will + be received. The constant kControlFocusNoPart will be received when our control + is the current focus and the user clicks in another control. In your focus routine, + you should respond to these codes as follows: + + kControlFocusNoPart - turn off focus and return kControlFocusNoPart. redraw + the control and the focus rectangle as necessary. + + kControlFocusPrevPart or kControlFocusNextPart - toggle focus on or off + depending on its current state. redraw the control and the focus rectangle + as appropriate for the new focus state. If the focus state is 'off', return the constant + kControlFocusNoPart, otherwise return a non-zero part code. + kUserClickedToFocusPart - is a constant defined for this example. You should + define your own value for handling click-to-focus type events. */ + /* calculate the next highlight state */ + switch (action) { + default: + case kControlFocusNoPart: + TPFocusPaneText(varsp, false); + focusResult = kControlFocusNoPart; + break; + case kUserClickedToFocusPart: + TPFocusPaneText(varsp, true); + focusResult = 1; + break; + case kControlFocusPrevPart: + case kControlFocusNextPart: + TPFocusPaneText(varsp, ( ! varsp->fInFocus)); + focusResult = varsp->fInFocus ? 1 : kControlFocusNoPart; + break; + } + TPActivatePaneText(varsp, varsp->fIsActive && varsp->fInFocus); + /* redraw the text fram and focus rectangle to indicate the + new focus state */ + if ( textctrl->MacIsReallyShown() ) + { + wxMacWindowClipper c( textctrl ) ; + if ( !varsp->fNoBorders ) + DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive); + TPRedrawFocusOutline( varsp ) ; + } + return focusResult; +} +/* mUPOpenControl initializes a user pane control so it will be drawn + and will behave as a scrolling text edit field inside of a window. + This routine performs all of the initialization steps necessary, + except it does not create the user pane control itself. theControl + should refer to a user pane control that you have either created + yourself or extracted from a dialog's control heirarchy using + the GetDialogItemAsControl routine. */ +OSStatus mUPOpenControl(STPTextPaneVars* &handle, ControlRef theControl, long wxStyle ) +{ + Rect bounds; + WindowRef theWindow; + STPTextPaneVars *varsp; + OSStatus err = noErr ; -//This our carbon event handler for unicode key downs -#if TARGET_CARBON -static pascal OSStatus FocusAdvanceOverride(EventHandlerCallRef myHandler, EventRef event, void* userData) { - WindowRef window; - STPTextPaneVars **tpvars; - OSStatus err; - unsigned short mUnicodeText; - ByteCount charCounts=0; - /* get our window pointer */ - tpvars = (STPTextPaneVars **) userData; - window = (**tpvars).fOwner; - //find out how many bytes are needed - err = GetEventParameter(event, kEventParamTextInputSendText, - typeUnicodeText, NULL, 0, &charCounts, NULL); - if (err != noErr) goto bail; - /* we're only looking at single characters */ - if (charCounts != 2) { err = eventNotHandledErr; goto bail; } - /* get the character */ - err = GetEventParameter(event, kEventParamTextInputSendText, - typeUnicodeText, NULL, sizeof(mUnicodeText), - &charCounts, (char*) &mUnicodeText); - if (err != noErr) goto bail; - /* if it's not the tab key, forget it... */ - if ((mUnicodeText != '\t')) { err = eventNotHandledErr; goto bail; } - /* advance the keyboard focus */ - AdvanceKeyboardFocus(window); - /* noErr lets the CEM know we handled the event */ - return noErr; -bail: - return eventNotHandledErr; -} -#endif + /* set up our globals */ + if (gTPDrawProc == NULL) gTPDrawProc = NewControlUserPaneDrawUPP(TPPaneDrawProc); + if (gTPHitProc == NULL) gTPHitProc = NewControlUserPaneHitTestUPP(TPPaneHitTestProc); + if (gTPTrackProc == NULL) gTPTrackProc = NewControlUserPaneTrackingUPP(TPPaneTrackingProc); + if (gTPIdleProc == NULL) gTPIdleProc = NewControlUserPaneIdleUPP(TPPaneIdleProc); + if (gTPKeyProc == NULL) gTPKeyProc = NewControlUserPaneKeyDownUPP(TPPaneKeyDownProc); + if (gTPActivateProc == NULL) gTPActivateProc = NewControlUserPaneActivateUPP(TPPaneActivateProc); + if (gTPFocusProc == NULL) gTPFocusProc = NewControlUserPaneFocusUPP(TPPaneFocusProc); + + /* allocate our private storage */ + varsp = (STPTextPaneVars *) malloc(sizeof(STPTextPaneVars)); + handle = varsp ; + + /* set the initial settings for our private data */ + varsp->fMultiline = wxStyle & wxTE_MULTILINE ; + varsp->fNoBorders = wxStyle & wxNO_BORDER ; + varsp->fInFocus = false; + varsp->fIsActive = true; + varsp->fTXNObjectActive = false; + varsp->fFocusDrawState = false ; + varsp->fUserPaneRec = theControl; + varsp->fVisible = true ; + + theWindow = varsp->fOwner = GetControlOwner(theControl); + varsp->fDrawingEnvironment = (GrafPtr) GetWindowPort(theWindow); -/* mUPOpenControl initializes a user pane control so it will be drawn - and will behave as a scrolling text edit field inside of a window. - This routine performs all of the initialization steps necessary, - except it does not create the user pane control itself. theControl - should refer to a user pane control that you have either created - yourself or extracted from a dialog's control heirarchy using - the GetDialogItemAsControl routine. */ -OSStatus mUPOpenControl(ControlHandle theControl, bool multiline) { - Rect bounds; - WindowPtr theWindow; - STPTextPaneVars **tpvars, *varsp; - OSStatus err; - RGBColor rgbWhite = {0xFFFF, 0xFFFF, 0xFFFF}; - TXNBackground tback; - - /* set up our globals */ - if (gTPDrawProc == NULL) gTPDrawProc = NewControlUserPaneDrawUPP(TPPaneDrawProc); - if (gTPHitProc == NULL) gTPHitProc = NewControlUserPaneHitTestUPP(TPPaneHitTestProc); - if (gTPTrackProc == NULL) gTPTrackProc = NewControlUserPaneTrackingUPP(TPPaneTrackingProc); - if (gTPIdleProc == NULL) gTPIdleProc = NewControlUserPaneIdleUPP(TPPaneIdleProc); - if (gTPKeyProc == NULL) gTPKeyProc = NewControlUserPaneKeyDownUPP(TPPaneKeyDownProc); - if (gTPActivateProc == NULL) gTPActivateProc = NewControlUserPaneActivateUPP(TPPaneActivateProc); - if (gTPFocusProc == NULL) gTPFocusProc = NewControlUserPaneFocusUPP(TPPaneFocusProc); - - /* allocate our private storage */ - tpvars = (STPTextPaneVars **) NewHandleClear(sizeof(STPTextPaneVars)); - SetControlReference(theControl, (long) tpvars); - HLock((Handle) tpvars); - varsp = *tpvars; - /* set the initial settings for our private data */ - varsp->fInFocus = false; - varsp->fIsActive = true; - varsp->fTEActive = false; - varsp->fUserPaneRec = theControl; - theWindow = varsp->fOwner = GetControlOwner(theControl); -#if TARGET_CARBON - varsp->fDrawingEnvironment = GetWindowPort(varsp->fOwner); -#else - varsp->fDrawingEnvironment = (GrafPtr) GetWindowPort(varsp->fOwner); -#endif - varsp->fInDialogWindow = ( GetWindowKind(varsp->fOwner) == kDialogWindowKind ); /* set up the user pane procedures */ SetControlData(theControl, kControlEntireControl, kControlUserPaneDrawProcTag, sizeof(gTPDrawProc), &gTPDrawProc); SetControlData(theControl, kControlEntireControl, kControlUserPaneHitTestProcTag, sizeof(gTPHitProc), &gTPHitProc); @@ -1321,312 +642,66 @@ OSStatus mUPOpenControl(ControlHandle theControl, bool multiline) { SetControlData(theControl, kControlEntireControl, kControlUserPaneKeyDownProcTag, sizeof(gTPKeyProc), &gTPKeyProc); SetControlData(theControl, kControlEntireControl, kControlUserPaneActivateProcTag, sizeof(gTPActivateProc), &gTPActivateProc); SetControlData(theControl, kControlEntireControl, kControlUserPaneFocusProcTag, sizeof(gTPFocusProc), &gTPFocusProc); + /* calculate the rectangles used by the control */ - GetControlBounds(theControl, &bounds); - SetRect(&varsp->fRFocusOutline, bounds.left, bounds.top, bounds.right, bounds.bottom); - SetRect(&varsp->fRTextOutline, bounds.left, bounds.top, bounds.right, bounds.bottom); - SetRect(&varsp->fRTextArea, bounds.left, bounds.top, bounds.right, bounds.bottom); - /* calculate the background region for the text. In this case, it's kindof - and irregular region because we're setting the scroll bar a little ways inside - of the text area. */ - RectRgn((varsp->fTextBackgroundRgn = NewRgn()), &varsp->fRTextOutline); + UMAGetControlBoundsInWindowCoords(theControl, &bounds); + varsp->fRTextOutlineRegion = NewRgn() ; + TPCalculateBounds( varsp , bounds ) ; /* set up the drawing environment */ SetPort(varsp->fDrawingEnvironment); /* create the new edit field */ - TXNNewObject(NULL, varsp->fOwner, &varsp->fRTextArea, - kTXNWantVScrollBarMask | kTXNAlwaysWrapAtViewEdgeMask, + + TXNFrameOptions frameOptions = FrameOptionsFromWXStyle( wxStyle ) ; + + verify_noerr(TXNNewObject(NULL, varsp->fOwner, &varsp->fRTextArea, + frameOptions , kTXNTextEditStyleFrameType, kTXNTextensionFile, - kTXNSystemDefaultEncoding, - &varsp->fTXNRec, &varsp->fTXNFrame, (TXNObjectRefcon) tpvars); - - /* set the field's background */ - tback.bgType = kTXNBackgroundTypeRGB; - tback.bg.color = rgbWhite; - TXNSetBackground( varsp->fTXNRec, &tback); - - /* install our focus advance override routine */ -#if TARGET_CARBON - varsp->handlerUPP = NewEventHandlerUPP(FocusAdvanceOverride); - err = InstallWindowEventHandler( varsp->fOwner, varsp->handlerUPP, - kMLTEEventCount, gMLTEEvents, tpvars, &varsp->handlerRef ); -#endif - /* unlock our storage */ - HUnlock((Handle) tpvars); + kTXNSystemDefaultEncoding, + &varsp->fTXNRec, &varsp->fTXNFrame, (TXNObjectRefcon) varsp)); + + AdjustAttributesFromWXStyle( varsp->fTXNRec , wxStyle , varsp->fVisible ) ; /* perform final activations and setup for our text field. Here, we assume that the window is going to be the 'active' window. */ - TPActivatePaneText(tpvars, varsp->fIsActive && varsp->fInFocus); - /* all done */ - return noErr; -} - - - -/* mUPCloseControl deallocates all of the structures allocated - by mUPOpenControl. */ -OSStatus mUPCloseControl(ControlHandle theControl) { - STPTextPaneVars **tpvars; - /* set up locals */ - tpvars = (STPTextPaneVars **) GetControlReference(theControl); - /* release our sub records */ - TXNDeleteObject((**tpvars).fTXNRec); - /* remove our focus advance override */ - RemoveEventHandler((**tpvars).handlerRef); - DisposeEventHandlerUPP((**tpvars).handlerUPP); - /* delete our private storage */ - DisposeHandle((Handle) tpvars); - /* zero the control reference */ - SetControlReference(theControl, 0); - return noErr; -} - - - - - /* mUPSetText replaces the contents of the selection with the unicode - text described by the text and count parameters:. - text = pointer to unicode text buffer - count = number of bytes in the buffer. */ -OSStatus mUPSetText(ControlHandle theControl, char* text, long count) { - STPTextPaneVars **tpvars; - /* set up locals */ - tpvars = (STPTextPaneVars **) GetControlReference(theControl); - /* set the text in the record */ - return TXNSetData( (**tpvars).fTXNRec, kTXNUnicodeTextData, text, count, - kTXNUseCurrentSelection, kTXNUseCurrentSelection); - - return noErr; -} - - -/* mUPSetSelection sets the text selection and autoscrolls the text view - so either the cursor or the selction is in the view. */ -void mUPSetSelection(ControlHandle theControl, long selStart, long selEnd) { - STPTextPaneVars **tpvars; - /* set up our locals */ - tpvars = (STPTextPaneVars **) GetControlReference(theControl); - /* and our drawing environment as the operation - may force a redraw in the text area. */ - SetPort((**tpvars).fDrawingEnvironment); - /* change the selection */ - TXNSetSelection( (**tpvars).fTXNRec, selStart, selEnd); -} - - - - - -/* mUPGetText returns the current text data being displayed inside of - the mUPControl. When noErr is returned, *theText contain a new - handle containing all of the Unicode text copied from the current - selection. It is the caller's responsibiliby to dispose of this handle. */ -OSStatus mUPGetText(ControlHandle theControl, Handle *theText) { - STPTextPaneVars **tpvars; - OSStatus err; - /* set up locals */ - tpvars = (STPTextPaneVars **) GetControlReference(theControl); - /* extract the text from the record */ - err = TXNGetData( (**tpvars).fTXNRec, kTXNUseCurrentSelection, kTXNUseCurrentSelection, theText); + TPActivatePaneText(varsp, varsp->fIsActive && varsp->fInFocus); /* all done */ return err; } +#else +struct STPTextPaneVars +{ +} ; +#endif -/* mUPCreateControl creates a new user pane control and then it passes it - to mUPOpenControl to initialize it as a scrolling text user pane control. */ -OSStatus mUPCreateControl(WindowPtr theWindow, Rect *bounds, ControlHandle *theControl) { - short featurSet; - /* the following feature set can be specified in CNTL resources by using - the value 1214. When creating a user pane control, we pass this value - in the 'value' parameter. */ - featurSet = kControlSupportsEmbedding | kControlSupportsFocus | kControlWantsIdle - | kControlWantsActivate | kControlHandlesTracking | kControlHasSpecialBackground - | kControlGetsFocusOnClick | kControlSupportsLiveFeedback; - /* create the control */ - *theControl = NewControl(theWindow, bounds, "\p", true, featurSet, 0, featurSet, kControlUserPaneProc, 0); - /* set up the mUP specific features and data */ - mUPOpenControl(*theControl); - /* all done.... */ - return noErr; -} - - -/* mUPDisposeControl calls mUPCloseControl and then it calls DisposeControl. */ -OSStatus mUPDisposeControl(ControlHandle theControl) { - /* deallocate the mUP specific data */ - mUPCloseControl(theControl); - /* deallocate the user pane control itself */ - DisposeControl(theControl); - return noErr; -} - - - - -/* IsmUPControl returns true if theControl is not NULL - and theControl refers to a mUP Control. */ -Boolean IsmUPControl(ControlHandle theControl) { - Size theSize; - ControlUserPaneFocusUPP localFocusProc; - /* a NULL control is not a mUP control */ - if (theControl == NULL) return false; - /* check if the control is using our focus procedure */ - theSize = sizeof(localFocusProc); - if (GetControlData(theControl, kControlEntireControl, kControlUserPaneFocusProcTag, - sizeof(localFocusProc), &localFocusProc, &theSize) != noErr) return false; - if (localFocusProc != gTPFocusProc) return false; - /* all tests passed, it's a mUP control */ - return true; -} - - -/* mUPDoEditCommand performs the editing command specified - in the editCommand parameter. The mUPControl's text - and scroll bar are redrawn and updated as necessary. */ -void mUPDoEditCommand(ControlHandle theControl, short editCommand) { - STPTextPaneVars **tpvars; - /* set up our locals */ - tpvars = (STPTextPaneVars **) GetControlReference(theControl); - /* and our drawing environment as the operation - may force a redraw in the text area. */ - SetPort((**tpvars).fDrawingEnvironment); - /* perform the editing command */ - switch (editCommand) { - case kmUPCut: - ClearCurrentScrap(); - TXNCut((**tpvars).fTXNRec); - TXNConvertToPublicScrap(); - break; - case kmUPCopy: - ClearCurrentScrap(); - TXNCopy((**tpvars).fTXNRec); - TXNConvertToPublicScrap(); - break; - case kmUPPaste: - TXNConvertFromPublicScrap(); - TXNPaste((**tpvars).fTXNRec); - break; - case kmUPClear: - TXNClear((**tpvars).fTXNRec); - break; - } -} - - - - -/* mUPGetContents returns the entire contents of the control including the text - and the formatting information. */ -OSStatus mUPGetContents(ControlHandle theControl, Handle *theContents) { - STPTextPaneVars **tpvars; - OSStatus err; - short vRefNum; - long dirID; - FSSpec tspec; - short trefnum; - Boolean texists; - long bytecount; - Handle localdata; - /* set up locals */ - trefnum = 0; - texists = false; - localdata = NULL; - tpvars = (STPTextPaneVars **) GetControlReference(theControl); - if (theContents == NULL) return paramErr; - /* create a temporary file */ - err = FindFolder(kOnSystemDisk, kTemporaryFolderType, true, &vRefNum, &dirID); - if (err != noErr) goto bail; - FSMakeFSSpec(vRefNum, dirID, "\pmUPGetContents", &tspec); - err = FSpCreate(&tspec, 'trsh', 'trsh', smSystemScript); - if (err != noErr) goto bail; - texists = true; - /* open the file */ - err = FSpOpenDF(&tspec, fsRdWrPerm, &trefnum); - if (err != noErr) goto bail; - /* save the data */ - err = TXNSave( (**tpvars).fTXNRec, kTXNTextensionFile, 0, kTXNSystemDefaultEncoding, &tspec, trefnum, 0); - if (err != noErr) goto bail; - /* get the file length and set the position */ - err = GetEOF(trefnum, &bytecount); - if (err != noErr) goto bail; - err = SetFPos(trefnum, fsFromStart, 0); - if (err != noErr) goto bail; - /* copy the data fork to a handle */ - localdata = NewHandle(bytecount); - if (localdata == NULL) { err = memFullErr; goto bail; } - HLock(localdata); - err = FSRead(trefnum, &bytecount, *localdata); - HUnlock(localdata); - if (err != noErr) goto bail; - /* store result */ - *theContents = localdata; - /* clean up */ - FSClose(trefnum); - FSpDelete(&tspec); - /* all done */ - return noErr; -bail: - if (trefnum != 0) FSClose(trefnum); - if (texists) FSpDelete(&tspec); - if (localdata != NULL) DisposeHandle(localdata); - return err; +static void SetTXNData( STPTextPaneVars *varsp, TXNObject txn , const wxString& st , TXNOffset start , TXNOffset end ) +{ +#if wxUSE_UNICODE +#if SIZEOF_WCHAR_T == 2 + size_t len = st.Len() ; + TXNSetData( txn , kTXNUnicodeTextData, (void*)st.wc_str(), len * 2, + start, end); +#else + wxMBConvUTF16BE converter ; + ByteCount byteBufferLen = converter.WC2MB( NULL , st.wc_str() , 0 ) ; + UniChar *unibuf = (UniChar*) malloc(byteBufferLen) ; + converter.WC2MB( (char*) unibuf , st.wc_str() , byteBufferLen ) ; + TXNSetData( txn , kTXNUnicodeTextData, (void*)unibuf, byteBufferLen , + start, end); + free( unibuf ) ; +#endif +#else + wxCharBuffer text = st.mb_str(wxConvLocal) ; + TXNSetData( txn , kTXNTextData, (void*)text.data(), strlen( text ) , + start, end); +#endif } - - -/* mUPSetContents replaces the contents of the selection with the data stored in the handle. */ -OSStatus mUPSetContents(ControlHandle theControl, Handle theContents) { - STPTextPaneVars **tpvars; - OSStatus err; - short vRefNum; - long dirID; - FSSpec tspec; - short trefnum; - Boolean texists; - long bytecount; - char state; - /* set up locals */ - trefnum = 0; - texists = false; - tpvars = (STPTextPaneVars **) GetControlReference(theControl); - if (theContents == NULL) return paramErr; - /* create a temporary file */ - err = FindFolder(kOnSystemDisk, kTemporaryFolderType, true, &vRefNum, &dirID); - if (err != noErr) goto bail; - FSMakeFSSpec(vRefNum, dirID, "\pmUPSetContents", &tspec); - err = FSpCreate(&tspec, 'trsh', 'trsh', smSystemScript); - if (err != noErr) goto bail; - texists = true; - /* open the file */ - err = FSpOpenDF(&tspec, fsRdWrPerm, &trefnum); - if (err != noErr) goto bail; - /* save the data to the temporary file */ - state = HGetState(theContents); - HLock(theContents); - bytecount = GetHandleSize(theContents); - err = FSWrite(trefnum, &bytecount, *theContents); - HSetState(theContents, state); - if (err != noErr) goto bail; - /* reset the file position */ - err = SetFPos(trefnum, fsFromStart, 0); - if (err != noErr) goto bail; - /* load the data */ - err = TXNSetDataFromFile((**tpvars).fTXNRec, trefnum, kTXNTextensionFile, bytecount, kTXNUseCurrentSelection, kTXNUseCurrentSelection); - if (err != noErr) goto bail; - /* clean up */ - FSClose(trefnum); - FSpDelete(&tspec); - /* all done */ - return noErr; -bail: - if (trefnum != 0) FSClose(trefnum); - if (texists) FSpDelete(&tspec); - return err; -} +#endif #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl) @@ -1649,179 +724,441 @@ END_EVENT_TABLE() #endif // Text item -wxTextCtrl::wxTextCtrl() +void wxTextCtrl::Init() { + m_macTXN = NULL ; + m_macTXNvars = NULL ; + + m_editable = true ; + m_dirty = false; + + m_maxLength = TE_UNLIMITED_LENGTH ; +} + +wxTextCtrl::~wxTextCtrl() +{ +#if wxMAC_USE_MLTE + SetControlReference(*m_peer, 0) ; +#if !wxMAC_USE_MLTE_HIVIEW + TXNDeleteObject((TXNObject)m_macTXN); +#endif + /* delete our private storage */ + free(m_macTXNvars); + /* zero the control reference */ +#endif } -const short kVerticalMargin = 2 ; -const short kHorizontalMargin = 2 ; bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, - const wxString& st, + const wxString& str, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name) { + m_macIsUserPane = FALSE ; + + m_macTXN = NULL ; + m_macTXNvars = NULL ; + m_editable = true ; + // base initialization - if ( !CreateBase(parent, id, pos, size, style, validator, name) ) + if ( !wxTextCtrlBase::Create(parent, id, pos, size, style & ~(wxHSCROLL|wxVSCROLL), validator, name) ) return FALSE; wxSize mySize = size ; - if ( UMAHasAppearance() ) - { - m_macHorizontalBorder = 5 ; // additional pixels around the real control - m_macVerticalBorder = 5 ; - } - else - { - m_macHorizontalBorder = 0 ; // additional pixels around the real control - m_macVerticalBorder = 0 ; - } + Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ; - Rect bounds ; - Str255 title ; + if ( m_windowStyle & wxTE_MULTILINE ) + { + wxASSERT_MSG( !(m_windowStyle & wxTE_PROCESS_ENTER), + wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") ); + + m_windowStyle |= wxTE_PROCESS_ENTER; + } - if ( mySize.y == -1 ) + wxString st = str ; + wxMacConvertNewlines13To10( &st ) ; +#if wxMAC_USE_MLTE { - if ( UMAHasAppearance() ) - mySize.y = 13 ; +#if wxMAC_USE_MLTE_HIVIEW + HIRect hr = { bounds.left , bounds.top , bounds.right - bounds.left , bounds.bottom- bounds.top } ; + HIViewRef scrollView = NULL ; + TXNFrameOptions frameOptions = FrameOptionsFromWXStyle( style ) ; + + if ( frameOptions & (kTXNWantVScrollBarMask|kTXNWantHScrollBarMask) ) + { + HIScrollViewCreate(( frameOptions & kTXNWantHScrollBarMask ? kHIScrollViewOptionsHorizScroll : 0) | + ( frameOptions & kTXNWantVScrollBarMask ? kHIScrollViewOptionsVertScroll: 0 ) , &scrollView ) ; + + HIViewSetFrame( scrollView, &hr ); + HIViewSetVisible( scrollView, true ); + } + HIViewRef textView ; + HITextViewCreate( NULL , 0, frameOptions , (ControlRef*) &textView ) ; + m_macTXN = HITextViewGetTXNObject( textView) ; + AdjustAttributesFromWXStyle( (TXNObject) m_macTXN , style , true ) ; + HIViewSetVisible( (ControlRef) textView , true ) ; + if ( scrollView ) + { + HIViewAddSubview( scrollView , textView ) ; + m_peer = scrollView ; + } else - mySize.y = 24 ; + { + m_peer = textView ; + } +#else + short featurSet; + + featurSet = kControlSupportsEmbedding | kControlSupportsFocus | kControlWantsIdle + | kControlWantsActivate | kControlHandlesTracking | kControlHasSpecialBackground + | kControlGetsFocusOnClick | kControlSupportsLiveFeedback; + /* create the control */ + m_peer = new wxMacControl() ; + verify_noerr( ::CreateUserPaneControl( MAC_WXHWND(GetParent()->MacGetTopLevelWindowRef()), &bounds, featurSet, *m_peer ) ); - mySize.y += 2 * m_macVerticalBorder ; - } + wxMacWindowClipper c(this) ; + STPTextPaneVars *varsp ; + mUPOpenControl( varsp, *m_peer, m_windowStyle ); + m_macTXNvars = varsp ; + m_macTXN = varsp->fTXNRec ; +#endif - MacPreControlCreate( parent , id , "" , pos , mySize ,style, validator , name , &bounds , title ) ; + if ( style & wxTE_PASSWORD ) + { + UniChar c = 0xA5 ; + verify_noerr(TXNEchoMode( (TXNObject) m_macTXN , c , 0 , true )) ; + } + } + MacPostControlCreate(pos,size) ; + +#if !wxMAC_USE_MLTE_HIVIEW + if ( MacIsReallyShown() ) + MLTESetObjectVisibility( (STPTextPaneVars*) m_macTXNvars, true , GetWindowStyle() ) ; +#endif - if ( m_windowStyle & wxTE_MULTILINE ) { - wxASSERT_MSG( !(m_windowStyle & wxTE_PROCESS_ENTER), - wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") ); + wxMacWindowClipper clipper( this ) ; +#if !wxMAC_USE_MLTE_HIVIEW + TPUpdateVisibility( *m_peer ) ; +#endif + SetTXNData( (STPTextPaneVars *)m_macTXNvars , (TXNObject) m_macTXN , st , kTXNStartOffset, kTXNEndOffset ) ; - m_windowStyle |= wxTE_PROCESS_ENTER; + TXNSetSelection( (TXNObject) m_macTXN, 0, 0); + TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart); } + + // in case MLTE is catching events before we get the chance to do so, we'd have to reintroduce the tlw-handler in front : + // parent->MacGetTopLevelWindow()->MacInstallTopLevelWindowEventHandler() ; + + SetBackgroundColour( *wxWHITE ) ; + TXNBackground tback; + tback.bgType = kTXNBackgroundTypeRGB; + tback.bg.color = MAC_WXCOLORREF( GetBackgroundColour().GetPixel() ); + TXNSetBackground( (TXNObject) m_macTXN , &tback); - if ( style & wxTE_PASSWORD ) +#else + wxMacCFStringHolder cf(st , m_font.GetEncoding()) ; + CFStringRef cfr = cf ; + Boolean isPassword = ( m_windowStyle & wxTE_PASSWORD ) != 0 ; + m_peer = new wxMacControl() ; + CreateEditUnicodeTextControl( MAC_WXHWND(parent->MacGetTopLevelWindowRef()), &bounds , cfr , isPassword , NULL , *m_peer ) ; + + if ( !(m_windowStyle & wxTE_MULTILINE) ) { - m_macControl = ::NewControl( parent->MacGetRootWindow() , &bounds , "\p" , true , 0 , 0 , 1, - kControlEditTextPasswordProc , (long) this ) ; + Boolean singleline = true ; + ::SetControlData( *m_peer, kControlEditTextPart , kControlEditTextSingleLineTag , sizeof( singleline ) , &singleline ) ; } - else + MacPostControlCreate(pos,size) ; + +#endif + if ( m_windowStyle & wxTE_READONLY) { - if ( mUPCreateControl(parent->MacGetRootWindow(), &bounds, &m_macControl) != noErr ) - return FALSE ; + SetEditable( false ) ; } - MacPostControlCreate() ; - - wxString value ; - - if( wxApp::s_macDefaultEncodingIsPC ) - value = wxMacMakeMacStringFromPC( st ) ; - else - value = st ; - if ( style & wxTE_PASSWORD ) + + return TRUE; +} + +void wxTextCtrl::MacVisibilityChanged() +{ +#if wxMAC_USE_MLTE +#if !wxMAC_USE_MLTE_HIVIEW + MLTESetObjectVisibility((STPTextPaneVars*) m_macTXNvars , MacIsReallyShown() , GetWindowStyle() ) ; + if ( !MacIsReallyShown() ) + InvalWindowRect( GetControlOwner( *m_peer ) , &((STPTextPaneVars *)m_macTXNvars)->fRBounds ) ; +#endif +#else + if ( !(m_windowStyle & wxTE_MULTILINE) && MacIsReallyShown() ) { - ::SetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ; - } - else - { - STPTextPaneVars **tpvars; - /* set up locals */ - tpvars = (STPTextPaneVars **) GetControlReference(m_macControl); - /* set the text in the record */ - TXNSetData( (**tpvars).fTXNRec, kTXNTextData, (const char*)value, value.Length(), - kTXNStartOffset, kTXNEndOffset); - } - - return TRUE; + // work around a refresh issue insofar as not always the entire content is shown even if this would be possible + ControlEditTextSelectionRec sel ; + CFStringRef value = NULL ; + Size actualSize = 0 ; + ResType datatag = GetWindowStyle() & wxTE_PASSWORD ? + kControlEditTextPasswordCFStringTag : kControlEditTextCFStringTag ; + + verify_noerr( GetControlData( *m_peer , 0, kControlEditTextSelectionTag, + sizeof(ControlEditTextSelectionRec), &sel, &actualSize ) ); + verify_noerr( GetControlData( *m_peer , 0, datatag , sizeof(CFStringRef), &value, &actualSize ) ); + + verify_noerr( SetControlData( *m_peer , 0, datatag, sizeof(CFStringRef), &value ) ); + verify_noerr( SetControlData( *m_peer , 0, kControlEditTextSelectionTag, sizeof(ControlEditTextSelectionRec), &sel ) ); + + CFRelease( value ) ; + } +#endif +} + +void wxTextCtrl::MacEnabledStateChanged() +{ } + wxString wxTextCtrl::GetValue() const { - Size actualsize; - if ( m_windowStyle & wxTE_PASSWORD ) - { - ::GetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 32767 , wxBuffer , &actualsize) ; - } - else - { - STPTextPaneVars **tpvars; - OSStatus err; - /* set up locals */ - tpvars = (STPTextPaneVars **) GetControlReference(m_macControl); - /* extract the text from the record */ - Handle theText ; - err = TXNGetDataEncoded( (**tpvars).fTXNRec, kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData ); - /* all done */ - if ( err ) + wxString result ; +#if wxMAC_USE_MLTE + OSStatus err ; + Size actualSize = 0; { - actualsize = 0 ; +#if wxUSE_UNICODE + Handle theText ; + err = TXNGetDataEncoded( ((TXNObject) m_macTXN), kTXNStartOffset, kTXNEndOffset, &theText , kTXNUnicodeTextData ); + // all done + if ( err ) + { + actualSize = 0 ; + } + else + { + actualSize = GetHandleSize( theText ) / sizeof( UniChar) ; + if ( actualSize > 0 ) + { + wxChar *ptr = NULL ; +#if SIZEOF_WCHAR_T == 2 + ptr = new wxChar[actualSize + 1 ] ; + wxStrncpy( ptr , (wxChar*) *theText , actualSize ) ; + +#else + SetHandleSize( theText , ( actualSize + 1 ) * sizeof( UniChar ) ) ; + HLock( theText ) ; + (((UniChar*)*theText)[actualSize]) = 0 ; + wxMBConvUTF16BE converter ; + size_t noChars = converter.MB2WC( NULL , (const char*)*theText , 0 ) ; + ptr = new wxChar[noChars + 1] ; + + noChars = converter.MB2WC( ptr , (const char*)*theText , noChars ) ; + ptr[noChars] = 0 ; + HUnlock( theText ) ; +#endif + ptr[actualSize] = 0 ; + result = wxString( ptr ) ; + delete[] ptr ; + } + DisposeHandle( theText ) ; + } +#else + Handle theText ; + err = TXNGetDataEncoded( ((TXNObject) m_macTXN), kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData ); + // all done + if ( err ) + { + actualSize = 0 ; + } + else + { + actualSize = GetHandleSize( theText ) ; + if ( actualSize > 0 ) + { + HLock( theText ) ; + result = wxString( *theText , wxConvLocal , actualSize ) ; + HUnlock( theText ) ; + } + DisposeHandle( theText ) ; + } +#endif } - else +#else + CFStringRef value = NULL ; + Size actualSize = 0 ; + + verify_noerr( GetControlData( *m_peer , 0, GetWindowStyle() & wxTE_PASSWORD ? + kControlEditTextPasswordCFStringTag : kControlEditTextCFStringTag, + sizeof(CFStringRef), &value, &actualSize ) ); + if ( value ) { - actualsize = GetHandleSize( theText ) ; - strncpy( wxBuffer , *theText , actualsize ) ; - DisposeHandle( theText ) ; - } - } - wxBuffer[actualsize] = 0 ; - if( wxApp::s_macDefaultEncodingIsPC ) - return wxMacMakePCStringFromMac( wxBuffer ) ; - else - return wxString(wxBuffer); + wxMacCFStringHolder cf(value) ; + result = cf.AsString() ; + } +#endif + wxMacConvertNewlines10To13( &result ) ; + return result ; } void wxTextCtrl::GetSelection(long* from, long* to) const +{ +#if wxMAC_USE_MLTE + TXNGetSelection( (TXNObject) m_macTXN , (TXNOffset*) from , (TXNOffset*) to ) ; +#else + ControlEditTextSelectionRec sel ; + Size actualSize ; + verify_noerr( GetControlData( *m_peer , 0, kControlEditTextSelectionTag, + sizeof(ControlEditTextSelectionRec), &sel, &actualSize ) ); + if ( from ) *from = sel.selStart ; + if ( to ) *to = sel.selEnd ; +#endif +} + +void wxTextCtrl::SetValue(const wxString& str) { - if ( m_windowStyle & wxTE_PASSWORD ) - { - ControlEditTextSelectionRec selection ; - TEHandle teH ; - long size ; - - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; + // optimize redraws + if ( GetValue() == str ) + return ; + + wxString st = str ; + wxMacConvertNewlines13To10( &st ) ; +#if wxMAC_USE_MLTE + { + wxMacWindowClipper c( this ) ; + bool formerEditable = m_editable ; + if ( !formerEditable ) + SetEditable(true) ; + +#if !wxMAC_USE_MLTE_HIVIEW + // otherwise scrolling might have problems ? + TPUpdateVisibility( ( (STPTextPaneVars *)m_macTXNvars)->fUserPaneRec ) ; +#endif + SetTXNData( (STPTextPaneVars *)m_macTXNvars , (TXNObject) m_macTXN , st , kTXNStartOffset, kTXNEndOffset ) ; + TXNSetSelection( (TXNObject) m_macTXN, 0, 0); + TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart); + if ( !formerEditable ) + SetEditable(formerEditable) ; + } +#else + wxMacCFStringHolder cf(st , m_font.GetEncoding() ) ; + CFStringRef value = cf ; + verify_noerr( SetControlData( *m_peer , 0, GetWindowStyle() & wxTE_PASSWORD ? + kControlEditTextPasswordCFStringTag : kControlEditTextCFStringTag, + sizeof(CFStringRef), &value ) ); +#endif +} - *from = (**teH).selStart; - *to = (**teH).selEnd; - } - else - { - STPTextPaneVars **tpvars; +void wxTextCtrl::SetMaxLength(unsigned long len) +{ + m_maxLength = len ; +} - /* set up locals */ - tpvars = (STPTextPaneVars **) GetControlReference(m_macControl); +bool wxTextCtrl::SetFont( const wxFont& font ) +{ + if ( !wxTextCtrlBase::SetFont( font ) ) + return FALSE ; + +#if wxMAC_USE_MLTE + wxMacWindowClipper c( this ) ; + bool formerEditable = m_editable ; + if ( !formerEditable ) + SetEditable(true) ; + + TXNTypeAttributes typeAttr[4] ; + Str255 fontName = "\pMonaco" ; + SInt16 fontSize = 12 ; + Style fontStyle = normal ; + int attrCounter = 0 ; + + wxMacStringToPascal( font.GetFaceName() , fontName ) ; + fontSize = font.MacGetFontSize() ; + fontStyle = font.MacGetFontStyle() ; + + typeAttr[attrCounter].tag = kTXNQDFontNameAttribute ; + typeAttr[attrCounter].size = kTXNQDFontNameAttributeSize ; + typeAttr[attrCounter].data.dataPtr = (void*) fontName ; + typeAttr[attrCounter+1].tag = kTXNQDFontSizeAttribute ; + typeAttr[attrCounter+1].size = kTXNFontSizeAttributeSize ; + typeAttr[attrCounter+1].data.dataValue = (fontSize << 16) ; + typeAttr[attrCounter+2].tag = kTXNQDFontStyleAttribute ; + typeAttr[attrCounter+2].size = kTXNQDFontStyleAttributeSize ; + typeAttr[attrCounter+2].data.dataValue = fontStyle ; + attrCounter += 3 ; + /* + typeAttr[attrCounter].tag = kTXNQDFontColorAttribute ; + typeAttr[attrCounter].size = kTXNQDFontColorAttributeSize ; + typeAttr[attrCounter].data.dataPtr = (void*) &color ; + color = MAC_WXCOLORREF(GetForegroundColour().GetPixel()) ; + attrCounter += 1 ; + */ + verify_noerr( TXNSetTypeAttributes ((TXNObject)m_macTXN, attrCounter , typeAttr, kTXNStartOffset,kTXNEndOffset) ); + + if ( !formerEditable ) + SetEditable(formerEditable) ; +#endif + return true ; +} + +bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style) +{ +#if wxMAC_USE_MLTE + bool formerEditable = m_editable ; + if ( !formerEditable ) + SetEditable(true) ; + TXNTypeAttributes typeAttr[4] ; + Str255 fontName = "\pMonaco" ; + SInt16 fontSize = 12 ; + Style fontStyle = normal ; + RGBColor color ; + int attrCounter = 0 ; + if ( style.HasFont() ) + { + const wxFont &font = style.GetFont() ; + wxMacStringToPascal( font.GetFaceName() , fontName ) ; + fontSize = font.GetPointSize() ; + if ( font.GetUnderlined() ) + fontStyle |= underline ; + if ( font.GetWeight() == wxBOLD ) + fontStyle |= bold ; + if ( font.GetStyle() == wxITALIC ) + fontStyle |= italic ; + + typeAttr[attrCounter].tag = kTXNQDFontNameAttribute ; + typeAttr[attrCounter].size = kTXNQDFontNameAttributeSize ; + typeAttr[attrCounter].data.dataPtr = (void*) fontName ; + typeAttr[attrCounter+1].tag = kTXNQDFontSizeAttribute ; + typeAttr[attrCounter+1].size = kTXNFontSizeAttributeSize ; + typeAttr[attrCounter+1].data.dataValue = (fontSize << 16) ; + typeAttr[attrCounter+2].tag = kTXNQDFontStyleAttribute ; + typeAttr[attrCounter+2].size = kTXNQDFontStyleAttributeSize ; + typeAttr[attrCounter+2].data.dataValue = fontStyle ; + attrCounter += 3 ; - TXNGetSelection( (**tpvars).fTXNRec , (TXNOffset*) from , (TXNOffset*) to ) ; + } + if ( style.HasTextColour() ) + { + typeAttr[attrCounter].tag = kTXNQDFontColorAttribute ; + typeAttr[attrCounter].size = kTXNQDFontColorAttributeSize ; + typeAttr[attrCounter].data.dataPtr = (void*) &color ; + color = MAC_WXCOLORREF(style.GetTextColour().GetPixel()) ; + attrCounter += 1 ; + } - } + if ( attrCounter > 0 ) + { + verify_noerr( TXNSetTypeAttributes ((TXNObject)m_macTXN, attrCounter , typeAttr, start,end) ); + } + if ( !formerEditable ) + SetEditable(formerEditable) ; +#endif + return TRUE ; } -void wxTextCtrl::SetValue(const wxString& st) +bool wxTextCtrl::SetDefaultStyle(const wxTextAttr& style) { - wxString value ; - - if( wxApp::s_macDefaultEncodingIsPC ) - value = wxMacMakeMacStringFromPC( st ) ; - else - value = st ; - if ( m_windowStyle & wxTE_PASSWORD ) - { - ::SetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ; - } - else - { - STPTextPaneVars **tpvars; - /* set up locals */ - tpvars = (STPTextPaneVars **) GetControlReference(m_macControl); - /* set the text in the record */ - TXNSetData( (**tpvars).fTXNRec, kTXNTextData, (const char*)value, value.Length(), - kTXNStartOffset, kTXNEndOffset); - } - MacRedrawControl() ; + wxTextCtrlBase::SetDefaultStyle( style ) ; + SetStyle( kTXNUseCurrentSelection , kTXNUseCurrentSelection , GetDefaultStyle() ) ; + return TRUE ; } // Clipboard operations @@ -1829,64 +1166,50 @@ void wxTextCtrl::Copy() { if (CanCopy()) { - if ( m_windowStyle & wxTE_PASSWORD ) - { - TEHandle teH ; - long size ; - - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - TECopy( teH ) ; - ClearCurrentScrap(); - TEToScrap() ; - } - else - { - mUPDoEditCommand( m_macControl , kmUPCopy ) ; - } - } +#if wxMAC_USE_MLTE + ClearCurrentScrap(); + TXNCopy((TXNObject)m_macTXN); + TXNConvertToPublicScrap(); +#else + m_peer->SendHICommand( kHICommandCopy ) ; +#endif + } } void wxTextCtrl::Cut() { if (CanCut()) { - if ( m_windowStyle & wxTE_PASSWORD ) - { - TEHandle teH ; - long size ; - - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - TECut( teH ) ; - ClearCurrentScrap(); - TEToScrap() ; - // MacInvalidateControl() ; - } - else - { - mUPDoEditCommand( m_macControl , kmUPCut ) ; - } - } +#if wxMAC_USE_MLTE + ClearCurrentScrap(); + TXNCut((TXNObject)m_macTXN); + TXNConvertToPublicScrap(); +#else + m_peer->SendHICommand( kHICommandCut ) ; +#endif + wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId); + event.SetString( GetValue() ) ; + event.SetEventObject( this ); + GetEventHandler()->ProcessEvent(event); + } } void wxTextCtrl::Paste() { if (CanPaste()) { - if ( m_windowStyle & wxTE_PASSWORD ) - { - TEHandle teH ; - long size ; - - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - TEFromScrap() ; - TEPaste( teH ) ; - MacRedrawControl() ; - } - else - { - mUPDoEditCommand( m_macControl , kmUPPaste ) ; - } - } +#if wxMAC_USE_MLTE + TXNConvertFromPublicScrap(); + TXNPaste((TXNObject)m_macTXN); + SetStyle( kTXNUseCurrentSelection , kTXNUseCurrentSelection , GetDefaultStyle() ) ; +#else + m_peer->SendHICommand( kHICommandPaste ) ; +#endif + wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId); + event.SetString( GetValue() ) ; + event.SetEventObject( this ); + GetEventHandler()->ProcessEvent(event); + } } bool wxTextCtrl::CanCopy() const @@ -1899,6 +1222,10 @@ bool wxTextCtrl::CanCopy() const bool wxTextCtrl::CanCut() const { + if ( !IsEditable() ) + { + return false ; + } // Can cut if there's a selection long from, to; GetSelection(& from, & to); @@ -1908,44 +1235,29 @@ bool wxTextCtrl::CanCut() const bool wxTextCtrl::CanPaste() const { if (!IsEditable()) - return FALSE; - - long offset ; -#if TARGET_CARBON - OSStatus err = noErr; - ScrapRef scrapRef; - - err = GetCurrentScrap( &scrapRef ); - if ( err != noTypeErr && err != memFullErr ) - { - ScrapFlavorFlags flavorFlags; - Size byteCount; - - if (( err = GetScrapFlavorFlags( scrapRef, 'TEXT', &flavorFlags )) == noErr) - { - if (( err = GetScrapFlavorSize( scrapRef, 'TEXT', &byteCount )) == noErr) - { - return TRUE ; - } - } - } - return FALSE; - + return FALSE; + +#if wxMAC_USE_MLTE + return TXNIsScrapPastable() ; #else - if ( GetScrap( NULL , 'TEXT' , &offset ) > 0 ) - { - return TRUE ; - } + return true ; #endif - return FALSE ; } void wxTextCtrl::SetEditable(bool editable) { - if ( editable ) - UMAActivateControl( m_macControl ) ; - else - UMADeactivateControl( m_macControl ) ; + if ( editable != m_editable ) + { + m_editable = editable ; +#if wxMAC_USE_MLTE + TXNControlTag tag[] = { kTXNIOPrivilegesTag } ; + TXNControlData data[] = { { editable ? kTXNReadWrite : kTXNReadOnly } } ; + TXNSetTXNObjectControls( (TXNObject) m_macTXN , false , sizeof(tag) / sizeof (TXNControlTag) , tag , data ) ; +#else + Boolean value = !editable ; + ::SetControlData( *m_peer, 0, kControlEditTextLockedTag , sizeof( value ) , &value ) ; +#endif + } } void wxTextCtrl::SetInsertionPoint(long pos) @@ -1961,119 +1273,82 @@ void wxTextCtrl::SetInsertionPointEnd() long wxTextCtrl::GetInsertionPoint() const { - long begin,end ; - GetSelection( &begin , &end ) ; - return begin ; + long begin,end ; + GetSelection( &begin , &end ) ; + return begin ; } long wxTextCtrl::GetLastPosition() const { - if ( m_windowStyle & wxTE_PASSWORD ) - { - - ControlEditTextSelectionRec selection ; - TEHandle teH ; - long size ; - - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - -// ::GetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection , &size ) ; - return (**teH).teLength ; - } - else - { - STPTextPaneVars** tpvars = (STPTextPaneVars **) GetControlReference(m_macControl); - - int actualsize = 0 ; - Handle theText ; - OSErr err = TXNGetDataEncoded( (**tpvars).fTXNRec, kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData ); - /* all done */ - if ( err ) - { - actualsize = 0 ; - } - else - { - actualsize = GetHandleSize( theText ) ; - DisposeHandle( theText ) ; - } - return actualsize ; - } -} - -void wxTextCtrl::Replace(long from, long to, const wxString& value) -{ - if ( m_windowStyle & wxTE_PASSWORD ) - { - TEHandle teH ; - long size ; - - ControlEditTextSelectionRec selection ; - - selection.selStart = from ; - selection.selEnd = to ; - ::SetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ; - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - TESetSelect( from , to , teH ) ; - TEDelete( teH ) ; - TEInsert( value , value.Length() , teH ) ; - } - else - { - // TODO - } - Refresh() ; + long actualsize = 0 ; +#if wxMAC_USE_MLTE + Handle theText ; + OSErr err = TXNGetDataEncoded( (TXNObject) m_macTXN, kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData ); + /* all done */ + if ( err ) + { + actualsize = 0 ; + } + else + { + actualsize = GetHandleSize( theText ) ; + DisposeHandle( theText ) ; + } +#endif + return actualsize ; +} + +void wxTextCtrl::Replace(long from, long to, const wxString& str) +{ +#if wxMAC_USE_MLTE + wxString value = str ; + wxMacConvertNewlines13To10( &value ) ; + + bool formerEditable = m_editable ; + if ( !formerEditable ) + SetEditable(true) ; + TXNSetSelection( ((TXNObject) m_macTXN) , from , to ) ; + TXNClear( ((TXNObject) m_macTXN) ) ; + SetTXNData( (STPTextPaneVars *)m_macTXNvars , (TXNObject) m_macTXN , str , kTXNUseCurrentSelection, kTXNUseCurrentSelection ) ; + if ( !formerEditable ) + SetEditable( formerEditable ) ; + + Refresh() ; +#endif } void wxTextCtrl::Remove(long from, long to) { - if ( m_windowStyle & wxTE_PASSWORD ) - { - TEHandle teH ; - long size ; - - ControlEditTextSelectionRec selection ; - - selection.selStart = from ; - selection.selEnd = to ; - ::SetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ; - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - TEDelete( teH ) ; - } - else - { - //TODO - } +#if wxMAC_USE_MLTE + bool formerEditable = m_editable ; + if ( !formerEditable ) + SetEditable(true) ; + TXNSetSelection( ((TXNObject) m_macTXN) , from , to ) ; + TXNClear( ((TXNObject) m_macTXN) ) ; + if ( !formerEditable ) + SetEditable( formerEditable ) ; + Refresh() ; +#endif } void wxTextCtrl::SetSelection(long from, long to) { - if ( m_windowStyle & wxTE_PASSWORD ) - { - ControlEditTextSelectionRec selection ; - TEHandle teH ; - long size ; - - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - - selection.selStart = from ; - selection.selEnd = to ; - - ::SetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ; - TESetSelect( selection.selStart , selection.selEnd , teH ) ; - } - else - { - STPTextPaneVars **tpvars; - /* set up our locals */ - tpvars = (STPTextPaneVars **) GetControlReference(m_macControl); - /* and our drawing environment as the operation - may force a redraw in the text area. */ - SetPort((**tpvars).fDrawingEnvironment); - /* change the selection */ - TXNSetSelection( (**tpvars).fTXNRec, from, to); - } +#if wxMAC_USE_MLTE + /* change the selection */ + if ((from == -1) && (to == -1)) + TXNSelectAll((TXNObject) m_macTXN); + else + TXNSetSelection( (TXNObject) m_macTXN, from, to); + TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart); +#else + ControlEditTextSelectionRec sel ; + sel.selStart = from ; + sel.selEnd = to ; + verify_noerr( SetControlData( *m_peer , 0, kControlEditTextSelectionTag, + sizeof(ControlEditTextSelectionRec), &sel ) ); + +#endif } bool wxTextCtrl::LoadFile(const wxString& file) @@ -2086,31 +1361,141 @@ bool wxTextCtrl::LoadFile(const wxString& file) return FALSE; } -void wxTextCtrl::WriteText(const wxString& text) +class wxMacFunctor +{ +public : + wxMacFunctor(){} + virtual ~wxMacFunctor() {} + virtual void* operator()() = 0 ; + static void* CallBackProc(void *param) + { + wxMacFunctor* f = (wxMacFunctor*) param ; + void *result = (*f)() ; + return result ; + } +} ; + +template +class wxMacObjectFunctor1 : public wxMacFunctor +{ + typedef void (classtype::*function)( param1type p1 ) ; + typedef void (classtype::*ref_function)( const param1type& p1 ) ; +public : + wxMacObjectFunctor1( classtype *obj , function f , param1type p1 ) : + wxMacFunctor( ) + { + m_object = obj ; + m_function = f ; + m_param1 = p1 ; + } + + wxMacObjectFunctor1( classtype *obj , ref_function f , param1type p1 ) : + wxMacFunctor( ) + { + m_object = obj ; + m_refFunction = f ; + m_param1 = p1 ; + } + + ~wxMacObjectFunctor1() {} + + virtual void* operator()() + { + (m_object->*m_function)(m_param1) ; + return NULL ; + } +private : + classtype* m_object ; + param1type m_param1 ; + union + { + function m_function ; + ref_function m_refFunction ; + } ; +} ; + +template +void* wxMacMPRemoteCall( classtype *object , void (classtype::*function)( param1type p1 ) , param1type p1 ) +{ + wxMacObjectFunctor1 params(object,function,p1) ; + void *result = + MPRemoteCall( wxMacFunctor::CallBackProc , ¶ms , kMPOwningProcessRemoteContext ) ; + return result ; +} + +template +void* wxMacMPRemoteCall( classtype *object , void (classtype::*function)( const param1type& p1 ) , param1type p1 ) +{ + wxMacObjectFunctor1 params(object,function,p1) ; + void *result = + MPRemoteCall( wxMacFunctor::CallBackProc , ¶ms , kMPOwningProcessRemoteContext ) ; + return result ; +} + +template +void* wxMacMPRemoteGUICall( classtype *object , void (classtype::*function)( param1type p1 ) , param1type p1 ) { - wxString value ; - if( wxApp::s_macDefaultEncodingIsPC ) - value = wxMacMakeMacStringFromPC( text ) ; + wxMutexGuiLeave() ; + void *result = wxMacMPRemoteCall( object , function , p1 ) ; + wxMutexGuiEnter() ; + return result ; +} + +template +void* wxMacMPRemoteGUICall( classtype *object , void (classtype::*function)( const param1type& p1 ) , param1type p1 ) +{ + wxMutexGuiLeave() ; + void *result = wxMacMPRemoteCall( object , function , p1 ) ; + wxMutexGuiEnter() ; + return result ; +} + +void wxTextCtrl::WriteText(const wxString& str) +{ + if ( !wxIsMainThread() ) + { + // unfortunately CW 8 is not able to correctly deduce the template types, so we have + // to instantiate explicitely + wxMacMPRemoteGUICall( this , &wxTextCtrl::WriteText , str ) ; + return ; + } else - value = text ; - if ( m_windowStyle & wxTE_PASSWORD ) { - TEHandle teH ; - long size ; - - ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ; - TEInsert( value , value.Length() , teH ) ; - } - else + wxString st = str ; + wxMacConvertNewlines13To10( &st ) ; + #if wxMAC_USE_MLTE + bool formerEditable = m_editable ; + if ( !formerEditable ) + SetEditable(true) ; { - STPTextPaneVars **tpvars; - /* set up locals */ - tpvars = (STPTextPaneVars **) GetControlReference(m_macControl); - /* set the text in the record */ - TXNSetData( (**tpvars).fTXNRec, kTXNTextData, (const char*)value, value.Length(), - kTXNUseCurrentSelection, kTXNUseCurrentSelection); + wxMacWindowStateSaver s( this ) ; + long start , end , dummy ; + GetSelection( &start , &dummy ) ; + SetTXNData( (STPTextPaneVars *)m_macTXNvars , (TXNObject) m_macTXN , st , kTXNUseCurrentSelection, kTXNUseCurrentSelection ) ; + GetSelection( &dummy , &end ) ; + SetStyle( start , end , GetDefaultStyle() ) ; } - Refresh() ; + if ( !formerEditable ) + SetEditable( formerEditable ) ; + + MacRedrawControl() ; + #else + #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 + wxMacCFStringHolder cf(st , m_font.GetEncoding() ) ; + CFStringRef value = cf ; + SetControlData( *m_peer , 0, kControlEditTextInsertCFStringRefTag, + sizeof(CFStringRef), &value ); + #else + wxString val = GetValue() ; + long start , end ; + GetSelection( &start , &end ) ; + val.Remove( start , end - start ) ; + val.insert( start , str ) ; + SetValue( val ) ; + SetInsertionPoint( start + str.Length() ) ; + #endif + #endif + } } void wxTextCtrl::AppendText(const wxString& text) @@ -2121,59 +1506,72 @@ void wxTextCtrl::AppendText(const wxString& text) void wxTextCtrl::Clear() { - if ( m_windowStyle & wxTE_PASSWORD ) - { +#if wxMAC_USE_MLTE + bool formerEditable = m_editable ; + if ( !formerEditable ) + SetEditable(true) ; + TXNSetSelection( (TXNObject)m_macTXN , kTXNStartOffset , kTXNEndOffset ) ; + TXNClear((TXNObject)m_macTXN); + + if ( !formerEditable ) + SetEditable( formerEditable ) ; - ::SetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 0 , (char*) ((const char*)NULL) ) ; - } - else - { - mUPDoEditCommand( m_macControl , kmUPClear) ; - } - Refresh() ; + Refresh() ; +#else + SetValue(wxEmptyString) ; +#endif } bool wxTextCtrl::IsModified() const { - return TRUE; + return m_dirty; } bool wxTextCtrl::IsEditable() const { - return IsEnabled(); + return IsEnabled() && m_editable ; } bool wxTextCtrl::AcceptsFocus() const { // we don't want focus if we can't be edited - return IsEditable() && wxControl::AcceptsFocus(); + return /*IsEditable() && */ wxControl::AcceptsFocus(); } wxSize wxTextCtrl::DoGetBestSize() const { int wText = 100 ; - - int hText ; - if ( UMAHasAppearance() ) - hText = 13 ; - else - hText = 24 ; - hText += 2 * m_macHorizontalBorder ; -/* - int cx, cy; - wxGetCharSize(GetHWND(), &cx, &cy, &GetFont()); - int wText = DEFAULT_ITEM_WIDTH; + int hText; - int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy); + switch( m_windowVariant ) + { + case wxWINDOW_VARIANT_NORMAL : + hText = 22 ; + break ; + case wxWINDOW_VARIANT_SMALL : + hText = 19 ; + break ; + case wxWINDOW_VARIANT_MINI : + hText= 15 ; + break ; + default : + hText = 22 ; + break ; + } + +#if !wxMAC_USE_MLTE + // unicode text control is using client size, ie 3 pixels on every side + // TODO make this fit into normal window size concept, probably having + // to reintroduce the margin vars + hText -= 6 ; +#endif - return wxSize(wText, hText); -*/ if ( m_windowStyle & wxTE_MULTILINE ) { - hText *= wxMin(GetNumberOfLines(), 5); + hText *= 5 ; } - //else: for single line control everything is ok + return wxSize(wText, hText); } @@ -2185,6 +1583,9 @@ void wxTextCtrl::Undo() { if (CanUndo()) { +#if wxMAC_USE_MLTE + TXNUndo((TXNObject)m_macTXN); +#endif } } @@ -2192,114 +1593,308 @@ void wxTextCtrl::Redo() { if (CanRedo()) { +#if wxMAC_USE_MLTE + TXNRedo((TXNObject)m_macTXN); +#endif } } bool wxTextCtrl::CanUndo() const { - return FALSE ; + if ( !IsEditable() ) + { + return false ; + } +#if wxMAC_USE_MLTE + return TXNCanUndo((TXNObject)m_macTXN,NULL); +#else + return false ; +#endif } bool wxTextCtrl::CanRedo() const { - return FALSE ; + if ( !IsEditable() ) + { + return false ; + } +#if wxMAC_USE_MLTE + return TXNCanRedo((TXNObject)m_macTXN,NULL); +#else + return false ; +#endif +} + +// Makes modifie or unmodified +void wxTextCtrl::MarkDirty() +{ + m_dirty = true; } -// Makes 'unmodified' void wxTextCtrl::DiscardEdits() { - // TODO + m_dirty = false; } int wxTextCtrl::GetNumberOfLines() const { - // TODO change this if possible to reflect real lines - wxString content = GetValue() ; - - int count = 1; - for (int i = 0; i < content.Length() ; i++) - { - if (content[i] == '\r') count++; - } - - return count; + ItemCount lines = 0 ; +#if wxMAC_USE_MLTE + TXNGetLineCount((TXNObject)m_macTXN, &lines ) ; +#else + wxString content = GetValue() ; + lines = 1; + for (size_t i = 0; i < content.Length() ; i++) + { + if (content[i] == '\r') lines++; + } +#endif + return lines ; } long wxTextCtrl::XYToPosition(long x, long y) const { - // TODO +#if wxMAC_USE_MLTE + Point curpt ; + + long lastpos = GetLastPosition() ; + + // TODO find a better implementation : while we can get the + // line metrics of a certain line, we don't get its starting + // position, so it would probably be rather a binary search + // for the start position + long xpos = 0 ; + long ypos = 0 ; + int lastHeight = 0 ; + + ItemCount n ; + for ( n = 0 ; n <= (ItemCount) lastpos ; ++n ) + { + if ( y == ypos && x == xpos ) + return n ; + + TXNOffsetToPoint( (TXNObject) m_macTXN, n , &curpt); + + if ( curpt.v > lastHeight ) + { + xpos = 0 ; + if ( n > 0 ) + ++ypos ; + lastHeight = curpt.v ; + } + else + ++xpos ; + } +#endif return 0; } bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const { +#if wxMAC_USE_MLTE + Point curpt ; + + long lastpos = GetLastPosition() ; + + if ( y ) *y = 0 ; + if ( x ) *x = 0 ; + + if ( pos <= lastpos ) + { + // TODO find a better implementation : while we can get the + // line metrics of a certain line, we don't get its starting + // position, so it would probably be rather a binary search + // for the start position + long xpos = 0 ; + long ypos = 0 ; + int lastHeight = 0 ; + + ItemCount n ; + for ( n = 0 ; n <= (ItemCount) pos ; ++n ) + { + TXNOffsetToPoint( (TXNObject) m_macTXN, n , &curpt); + + if ( curpt.v > lastHeight ) + { + xpos = 0 ; + if ( n > 0 ) + ++ypos ; + lastHeight = curpt.v ; + } + else + ++xpos ; + } + if ( y ) *y = ypos ; + if ( x ) *x = xpos ; + } +#else + if ( y ) *y = 0 ; + if ( x ) *x = 0 ; +#endif return FALSE ; } void wxTextCtrl::ShowPosition(long pos) { - // TODO +#if wxMAC_USE_MLTE +#if TARGET_RT_MAC_MACHO && defined(AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER) + { + Point current ; + Point desired ; + TXNOffset selstart , selend ; + TXNGetSelection( (TXNObject) m_macTXN , &selstart , &selend) ; + TXNOffsetToPoint( (TXNObject) m_macTXN, selstart , ¤t); + TXNOffsetToPoint( (TXNObject) m_macTXN, pos , &desired); + //TODO use HIPoints for 10.3 and above + if ( (UInt32) TXNScroll != (UInt32) kUnresolvedCFragSymbolAddress ) + { + OSErr theErr = noErr; + SInt32 dv = desired.v - current.v ; + SInt32 dh = desired.h - current.h ; + TXNShowSelection( (TXNObject) m_macTXN , true ) ; + theErr = TXNScroll( (TXNObject) m_macTXN, kTXNScrollUnitsInPixels , kTXNScrollUnitsInPixels , &dv , &dh ); + wxASSERT_MSG( theErr == noErr, _T("TXNScroll returned an error!") ); + } + } +#endif +#endif } int wxTextCtrl::GetLineLength(long lineNo) const { - // TODO change this if possible to reflect real lines - wxString content = GetValue() ; - - // Find line first - int count = 0; - for (int i = 0; i < content.Length() ; i++) - { - if (count == lineNo) - { - // Count chars in line then - count = 0; - for (int j = i; j < content.Length(); j++) - { - count++; - if (content[j] == '\r') return count; - } - - return count; - } - if (content[i] == '\r') count++; - } +#if wxMAC_USE_MLTE + Point curpt ; + if ( lineNo < GetNumberOfLines() ) + { + // TODO find a better implementation : while we can get the + // line metrics of a certain line, we don't get its starting + // position, so it would probably be rather a binary search + // for the start position + long xpos = 0 ; + long ypos = 0 ; + int lastHeight = 0 ; + long lastpos = GetLastPosition() ; + + ItemCount n ; + for ( n = 0 ; n <= (ItemCount) lastpos ; ++n ) + { + TXNOffsetToPoint( (TXNObject) m_macTXN, n , &curpt); + + if ( curpt.v > lastHeight ) + { + if ( ypos == lineNo ) + return xpos ; + + xpos = 0 ; + if ( n > 0 ) + ++ypos ; + lastHeight = curpt.v ; + } + else + ++xpos ; + } + } +#else + // TODO change this if possible to reflect real lines + wxString content = GetValue() ; + + // Find line first + int count = 0; + for (size_t i = 0; i < content.Length() ; i++) + { + if (count == lineNo) + { + // Count chars in line then + count = 0; + for (size_t j = i; j < content.Length(); j++) + { + count++; + if (content[j] == '\n') return count; + } + + return count; + } + if (content[i] == '\n') count++; + } +#endif return 0; } wxString wxTextCtrl::GetLineText(long lineNo) const { - // TODO change this if possible to reflect real lines - wxString content = GetValue() ; +#if wxMAC_USE_MLTE + wxString line ; + Point curpt ; + wxString content = GetValue() ; - // Find line first - int count = 0; - for (int i = 0; i < content.Length() ; i++) - { - if (count == lineNo) - { - // Add chars in line then - wxString tmp(""); - - for (int j = i; j < content.Length(); j++) - { - if (content[j] == '\r') - return tmp; - - tmp += content[j]; - } - - return tmp; - } - if (content[i] == '\r') count++; - } - return wxString(""); + if ( lineNo < GetNumberOfLines() ) + { + // TODO find a better implementation : while we can get the + // line metrics of a certain line, we don't get its starting + // position, so it would probably be rather a binary search + // for the start position + long xpos = 0 ; + long ypos = 0 ; + int lastHeight = 0 ; + long lastpos = GetLastPosition() ; + + ItemCount n ; + for ( n = 0 ; n <= (ItemCount)lastpos ; ++n ) + { + TXNOffsetToPoint( (TXNObject) m_macTXN, n , &curpt); + + if ( curpt.v > lastHeight ) + { + if ( ypos == lineNo ) + return line ; + + xpos = 0 ; + if ( n > 0 ) + ++ypos ; + lastHeight = curpt.v ; + } + else + { + if ( ypos == lineNo ) + line += content[n] ; + ++xpos ; + } + } + } + return line ; +#else + // TODO change this if possible to reflect real lines + wxString content = GetValue() ; + + // Find line first + int count = 0; + for (size_t i = 0; i < content.Length() ; i++) + { + if (count == lineNo) + { + // Add chars in line then + wxString tmp; + + for (size_t j = i; j < content.Length(); j++) + { + if (content[j] == '\n') + return tmp; + + tmp += content[j]; + } + + return tmp; + } + if (content[i] == '\n') count++; + } + return wxEmptyString ; +#endif } /* * Text item */ - + void wxTextCtrl::Command(wxCommandEvent & event) { SetValue (event.GetString()); @@ -2317,16 +1912,51 @@ void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event) void wxTextCtrl::OnChar(wxKeyEvent& event) { - switch ( event.KeyCode() ) + int key = event.GetKeyCode() ; + bool eat_key = false ; + + if ( key == 'c' && event.MetaDown() ) + { + if ( CanCopy() ) + Copy() ; + return ; + } + + if ( !IsEditable() && key != WXK_LEFT && key != WXK_RIGHT && key != WXK_DOWN && key != WXK_UP && key != WXK_TAB && + !( key == WXK_RETURN && ( (m_windowStyle & wxPROCESS_ENTER) || (m_windowStyle & wxTE_MULTILINE) ) ) +/* && key != WXK_PRIOR && key != WXK_NEXT && key != WXK_HOME && key != WXK_END */ + ) + { + // eat it + return ; + } + + // assume that any key not processed yet is going to modify the control + m_dirty = true; + + if ( key == 'v' && event.MetaDown() ) + { + if ( CanPaste() ) + Paste() ; + return ; + } + if ( key == 'x' && event.MetaDown() ) + { + if ( CanCut() ) + Cut() ; + return ; + } + switch ( key ) { case WXK_RETURN: if (m_windowStyle & wxPROCESS_ENTER) { wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId); event.SetEventObject( this ); + event.SetString( GetValue() ); if ( GetEventHandler()->ProcessEvent(event) ) return; - } + } if ( !(m_windowStyle & wxTE_MULTILINE) ) { wxWindow *parent = GetParent(); @@ -2345,71 +1975,93 @@ void wxTextCtrl::OnChar(wxKeyEvent& event) return ; } } + + // this will make wxWidgets eat the ENTER key so that + // we actually prevent line wrapping in a single line + // text control + eat_key = TRUE; } - //else: multiline controls need Enter for themselves break; case WXK_TAB: - // always produce navigation event - even if we process TAB - // ourselves the fact that we got here means that the user code - // decided to skip processing of this TAB - probably to let it - // do its default job. + if ( !(m_windowStyle & wxTE_PROCESS_TAB)) { - wxNavigationKeyEvent eventNav; - eventNav.SetDirection(!event.ShiftDown()); - eventNav.SetWindowChange(event.ControlDown()); - eventNav.SetEventObject(this); - - if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav) ) - return; - event.Skip() ; - return ; + int flags = 0; + if (!event.ShiftDown()) + flags |= wxNavigationKeyEvent::IsForward ; + if (event.ControlDown()) + flags |= wxNavigationKeyEvent::WinChange ; + Navigate(flags); + return; } + else + { + // This is necessary (don't know why) or the tab will not + // be inserted. + WriteText(wxT("\t")); + } + break; } - EventRecord *ev = wxTheApp->MacGetCurrentEvent() ; - short keycode ; - short keychar ; - keychar = short(ev->message & charCodeMask); - keycode = short(ev->message & keyCodeMask) >> 8 ; - UMAHandleControlKey( m_macControl , keycode , keychar , ev->modifiers ) ; - if ( keychar >= 0x20 || event.KeyCode() == WXK_RETURN || event.KeyCode() == WXK_DELETE || event.KeyCode() == WXK_BACK) + if (!eat_key) { - wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId); - event.SetString( GetValue() ) ; - event.SetEventObject( this ); - GetEventHandler()->ProcessEvent(event); - } + // perform keystroke handling + if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL ) + CallNextEventHandler((EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() , (EventRef) wxTheApp->MacGetCurrentEvent() ) ; + else + { + EventRecord rec ; + if ( wxMacConvertEventToRecord( (EventRef) wxTheApp->MacGetCurrentEvent() , &rec ) ) + { + EventRecord *ev = &rec ; + short keycode ; + short keychar ; + keychar = short(ev->message & charCodeMask); + keycode = short(ev->message & keyCodeMask) >> 8 ; + ::HandleControlKey( *m_peer , keycode , keychar , ev->modifiers ) ; + } + } + } + if ( ( key >= 0x20 && key < WXK_START ) || + key == WXK_RETURN || + key == WXK_DELETE || + key == WXK_BACK) + { + wxCommandEvent event1(wxEVT_COMMAND_TEXT_UPDATED, m_windowId); + event1.SetString( GetValue() ) ; + event1.SetEventObject( this ); + wxPostEvent(GetEventHandler(),event1); + } } // ---------------------------------------------------------------------------- // standard handlers for standard edit menu events // ---------------------------------------------------------------------------- -void wxTextCtrl::OnCut(wxCommandEvent& event) +void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event)) { Cut(); } -void wxTextCtrl::OnCopy(wxCommandEvent& event) +void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event)) { Copy(); } -void wxTextCtrl::OnPaste(wxCommandEvent& event) +void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event)) { Paste(); } -void wxTextCtrl::OnUndo(wxCommandEvent& event) +void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event)) { Undo(); } -void wxTextCtrl::OnRedo(wxCommandEvent& event) +void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event)) { Redo(); } @@ -2439,7 +2091,48 @@ void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event) event.Enable( CanRedo() ); } -#endif +bool wxTextCtrl::MacSetupCursor( const wxPoint& pt ) +{ + return true ; +} + +// user pane implementation + +void wxTextCtrl::MacControlUserPaneDrawProc(wxInt16 part) +{ +} + +wxInt16 wxTextCtrl::MacControlUserPaneHitTestProc(wxInt16 x, wxInt16 y) +{ + return kControlNoPart ; +} + +wxInt16 wxTextCtrl::MacControlUserPaneTrackingProc(wxInt16 x, wxInt16 y, void* actionProc) +{ + return kControlNoPart ; +} + +void wxTextCtrl::MacControlUserPaneIdleProc() +{ +} + +wxInt16 wxTextCtrl::MacControlUserPaneKeyDownProc(wxInt16 keyCode, wxInt16 charCode, wxInt16 modifiers) +{ + return kControlNoPart ; +} + +void wxTextCtrl::MacControlUserPaneActivateProc(bool activating) +{ +} + +wxInt16 wxTextCtrl::MacControlUserPaneFocusProc(wxInt16 action) +{ + return kControlNoPart ; +} + +void wxTextCtrl::MacControlUserPaneBackgroundProc(void* info) +{ +} #endif // wxUSE_TEXTCTRL