]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/carbon/textctrl.cpp
Documented wxListCtrl::GetColumnCount
[wxWidgets.git] / src / mac / carbon / textctrl.cpp
index 38dcae22f06556cb13c348027b9b7170d00b8910..4f8d67ae6d564e5fe39ae15879eaeb3d4d2b1659 100644 (file)
 #include "TextEncodingConverter.h"
 #include "wx/mac/uma.h"
 
+#define TE_UNLIMITED_LENGTH 0xFFFFFFFFUL
+
 extern wxApp *wxTheApp ;
+extern wxControl *wxFindControlFromMacControl(ControlHandle inControl ) ;
 
 // 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
@@ -83,7 +86,7 @@ extern wxApp *wxTheApp ;
     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);
+OSStatus mUPOpenControl(ControlHandle theControl, long wxStyle);
 
 /* Utility Routines */
 
@@ -194,8 +197,10 @@ static pascal void TPPaneDrawProc(ControlRef theControl, ControlPartCode thePart
             
             /* save the drawing state */
         SetPort((**tpvars).fDrawingEnvironment);
-            /* verify our boundary */
+           /* verify our boundary */
         GetControlBounds(theControl, &bounds);
+
+        wxMacWindowClipper clipper( wxFindControlFromMacControl(theControl ) ) ;
         if ( ! EqualRect(&bounds, &varsp->fRFocusOutline) ) {
             // scrollbar is on the border, we add one
             Rect oldbounds = varsp->fRFocusOutline ;
@@ -222,6 +227,7 @@ static pascal void TPPaneDrawProc(ControlRef theControl, ControlPartCode thePart
         if ((**tpvars).fIsActive && varsp->fInFocus) DrawThemeFocusRect(&varsp->fRFocusOutline, true);
             /* release our globals */
         HSetState((Handle) tpvars, state);
+
     }
 }
 
@@ -282,6 +288,7 @@ static pascal ControlPartCode TPPaneTrackingProc(ControlHandle theControl, Point
                 /* handle clicks in the text part */
             case kmUPTextPart:
                 {   SetPort((**tpvars).fDrawingEnvironment);
+                    wxMacWindowClipper clipper( wxFindControlFromMacControl(theControl ) ) ;
                     TXNClick( varsp->fTXNRec, (const EventRecord*) wxTheApp->MacGetCurrentEvent());
                 }
                 break;
@@ -312,6 +319,7 @@ static pascal void TPPaneIdleProc(ControlHandle theControl) {
             varsp = *tpvars;
                 /* get the current mouse coordinates (in our window) */
             SetPortWindowPort(GetControlOwner(theControl));
+            wxMacWindowClipper clipper( wxFindControlFromMacControl(theControl ) ) ;
             GetMouse(&mousep);
                 /* there's a 'focus thing' and an 'unfocused thing' */
             if (varsp->fInFocus) {
@@ -349,6 +357,7 @@ static pascal ControlPartCode TPPaneKeyDownProc(ControlHandle theControl,
         if ((**tpvars).fInFocus) {
                 /* turn autoscrolling on and send the key event to text edit */
             SetPort((**tpvars).fDrawingEnvironment);
+            wxMacWindowClipper clipper( wxFindControlFromMacControl(theControl ) ) ;
             EventRecord ev ;
             memset( &ev , 0 , sizeof( ev ) ) ;
             ev.what = keyDown ;
@@ -376,6 +385,7 @@ static pascal void TPPaneActivateProc(ControlHandle theControl, Boolean activati
         varsp = *tpvars;
             /* de/activate the text edit record */
         SetPort((**tpvars).fDrawingEnvironment);
+        wxMacWindowClipper clipper( wxFindControlFromMacControl(theControl ) ) ;
             GetControlBounds(theControl, &bounds);
             varsp->fIsActive = activating;
             TPActivatePaneText(tpvars, varsp->fIsActive && varsp->fInFocus);
@@ -421,6 +431,7 @@ static pascal ControlPartCode TPPaneFocusProc(ControlHandle theControl, ControlF
                 define your own value for handling click-to-focus type events. */
             /* save the drawing state */
         SetPort((**tpvars).fDrawingEnvironment);
+        wxMacWindowClipper clipper( wxFindControlFromMacControl(theControl ) ) ;
             /* calculate the next highlight state */
         switch (action) {
             default:
@@ -457,12 +468,12 @@ static pascal ControlPartCode TPPaneFocusProc(ControlHandle theControl, ControlF
     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
+OSStatus mUPOpenControl(ControlHandle theControl, long wxStyle 
 {
     Rect bounds;
     WindowRef theWindow;
     STPTextPaneVars **tpvars, *varsp;
-    OSStatus err;
+    OSStatus err = noErr ;
     RGBColor rgbWhite = {0xFFFF, 0xFFFF, 0xFFFF};
     TXNBackground tback;
     
@@ -481,7 +492,7 @@ OSStatus mUPOpenControl(ControlHandle theControl, bool multiline)
     HLock((Handle) tpvars);
     varsp = *tpvars;
         /* set the initial settings for our private data */
-    varsp->fMultiline = multiline ;
+    varsp->fMultiline = wxStyle & wxTE_MULTILINE ;
     varsp->fInFocus = false;
     varsp->fIsActive = true;
     varsp->fTEActive = true; // in order to get a deactivate
@@ -514,11 +525,33 @@ OSStatus mUPOpenControl(ControlHandle theControl, bool multiline)
     SetPort(varsp->fDrawingEnvironment);
 
         /* create the new edit field */
+        
+    TXNFrameOptions frameOptions = 
+        kTXNDontDrawCaretWhenInactiveMask ;
+    if ( ! ( wxStyle & wxTE_NOHIDESEL ) )
+           frameOptions |= kTXNDontDrawSelectionWhenInactiveMask ;
+       
+       if ( wxStyle & wxTE_MULTILINE )
+       {
+           if ( ! ( wxStyle & wxTE_DONTWRAP ) )
+               frameOptions |= kTXNAlwaysWrapAtViewEdgeMask ;
+           else
+           {
+               frameOptions |= kTXNAlwaysWrapAtViewEdgeMask ;
+               frameOptions |= kTXNWantHScrollBarMask ;
+           }
+               
+           if ( !(wxStyle & wxTE_NO_VSCROLL ) )
+               frameOptions |= kTXNWantVScrollBarMask ;
+       }
+       else
+           frameOptions |= kTXNSingleLineOnlyMask ;
+           
+       if ( wxStyle & wxTE_READONLY )
+           frameOptions |= kTXNReadOnlyMask ;
+  
     TXNNewObject(NULL, varsp->fOwner, &varsp->fRTextArea,
-      ( multiline ? kTXNWantVScrollBarMask : 0 ) |
-        kTXNDontDrawCaretWhenInactiveMask |
-        kTXNDontDrawSelectionWhenInactiveMask |
-        kTXNAlwaysWrapAtViewEdgeMask ,
+           frameOptions ,
         kTXNTextEditStyleFrameType,
         kTXNTextensionFile,
         kTXNSystemDefaultEncoding, 
@@ -537,9 +570,9 @@ OSStatus mUPOpenControl(ControlHandle theControl, bool multiline)
             {   kTXNQDFontStyleAttribute , kTXNQDFontStyleAttributeSize , {  (void*) normal } } ,
         } ;
 
-    OSStatus status = TXNSetTypeAttributes (varsp->fTXNRec, sizeof( typeAttr ) / sizeof(TXNTypeAttributes) , typeAttr,
-      kTXNStartOffset,
-      kTXNEndOffset);
+    err = TXNSetTypeAttributes (varsp->fTXNRec, sizeof( typeAttr ) / sizeof(TXNTypeAttributes) , typeAttr,
+          kTXNStartOffset,
+          kTXNEndOffset);
         /* set the field's background */
     tback.bgType = kTXNBackgroundTypeRGB;
     tback.bg.color = rgbWhite;
@@ -551,7 +584,7 @@ OSStatus mUPOpenControl(ControlHandle theControl, bool multiline)
         we assume that the window is going to be the 'active' window. */
     TPActivatePaneText(tpvars, varsp->fIsActive && varsp->fInFocus);
         /* all done */
-    return noErr;
+    return err;
 }
 
 
@@ -585,6 +618,7 @@ wxTextCtrl::wxTextCtrl()
   m_macTXNvars = NULL ;
   m_macUsesTXN = false ;
   m_editable = true ;
+  m_maxLength = TE_UNLIMITED_LENGTH ;
 }
 
 wxTextCtrl::~wxTextCtrl()
@@ -658,6 +692,10 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
         m_windowStyle |= wxTE_PROCESS_ENTER;
     }
 
+    if ( m_windowStyle & wxTE_READONLY)
+    {
+        m_editable = FALSE ;
+    }
 
     if ( !m_macUsesTXN )
     {
@@ -671,13 +709,13 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
     {
         short featurSet;
 
-        featurSet = kControlSupportsEmbedding | kControlSupportsFocus // | kControlWantsIdle
+        featurSet = kControlSupportsEmbedding | kControlSupportsFocus  | kControlWantsIdle
                 | kControlWantsActivate | kControlHandlesTracking | kControlHasSpecialBackground
                 | kControlGetsFocusOnClick | kControlSupportsLiveFeedback;
             /* create the control */
         m_macControl = NewControl(MAC_WXHWND(parent->MacGetRootWindow()), &bounds, "\p", true, featurSet, 0, featurSet, kControlUserPaneProc, 0);
             /* set up the mUP specific features and data */
-        mUPOpenControl((ControlHandle) m_macControl, m_windowStyle & wxTE_MULTILINE );
+       mUPOpenControl((ControlHandle) m_macControl, m_windowStyle );
         if ( parent )
         {
             parent->MacGetTopLevelWindow()->MacInstallEventHandler() ;
@@ -707,6 +745,8 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
         m_macTXN =  (**tpvars).fTXNRec ;
         m_macTXNvars = tpvars ;
         m_macUsesTXN = true ;
+       TXNSetSelection( (TXNObject) m_macTXN, 0, 0);
+        TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart);
     }
   
   return TRUE;
@@ -784,13 +824,85 @@ void wxTextCtrl::SetValue(const wxString& st)
     }
     else
     {
-        TXNSetData( ((TXNObject) m_macTXN), kTXNTextData,  (void*)value.c_str(), value.Length(),
-                    kTXNStartOffset, kTXNEndOffset);
+        bool formerEditable = IsEditable() ;
+        SetEditable(true) ;
+       TXNSetData( ((TXNObject) m_macTXN), kTXNTextData,  (void*)value.c_str(), value.Length(),
+         kTXNStartOffset, kTXNEndOffset);
+       TXNSetSelection( (TXNObject) m_macTXN, 0, 0);
+        TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart);
+        SetEditable(formerEditable) ;
     }
-    
     MacRedrawControl() ;
 }
 
+void wxTextCtrl::SetMaxLength(unsigned long len) 
+{
+    m_maxLength = len ;
+}
+
+bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
+{
+    if ( m_macUsesTXN )
+    {
+        bool formerEditable = IsEditable() ;
+        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() ;
+                   CopyCStringToPascal( font.GetFaceName().c_str() , 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 ;
+                   
+               }
+               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 )
+        {
+            OSStatus status = TXNSetTypeAttributes ((TXNObject)m_macTXN, attrCounter , typeAttr,
+                start,end);
+            wxASSERT_MSG( status == noErr , "Couldn't set text attributes" ) ;
+        }
+        SetEditable(formerEditable) ;
+    }
+    return TRUE ;
+}
+
+bool wxTextCtrl::SetDefaultStyle(const wxTextAttr& style)
+{
+    wxTextCtrlBase::SetDefaultStyle( style ) ;
+    SetStyle( kTXNUseCurrentSelection , kTXNUseCurrentSelection , GetDefaultStyle() ) ;
+    return TRUE ;
+}
+
 // Clipboard operations
 void wxTextCtrl::Copy()
 {
@@ -850,6 +962,7 @@ void wxTextCtrl::Paste()
         {
             TXNConvertFromPublicScrap();
             TXNPaste((TXNObject)m_macTXN); 
+            SetStyle( kTXNUseCurrentSelection , kTXNUseCurrentSelection , GetDefaultStyle() ) ;
         }
         wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
         event.SetString( GetValue() ) ;
@@ -883,7 +996,6 @@ bool wxTextCtrl::CanPaste() const
     if (!IsEditable())
         return FALSE;
 
-    long offset ;
 #if TARGET_CARBON
     OSStatus err = noErr;
     ScrapRef scrapRef;
@@ -905,6 +1017,7 @@ bool wxTextCtrl::CanPaste() const
     return FALSE;
     
 #else
+    long offset ;
     if ( GetScrap( NULL , 'TEXT' , &offset ) > 0 )
     {
         return TRUE ;
@@ -918,10 +1031,19 @@ void wxTextCtrl::SetEditable(bool editable)
     if ( editable != m_editable )
     {
         m_editable = editable ;
-    if ( editable )
-            UMAActivateControl( (ControlHandle) m_macControl ) ;
+        if ( !m_macUsesTXN )
+        {
+            if ( editable )
+               UMAActivateControl( (ControlHandle) m_macControl ) ;
+            else
+               UMADeactivateControl((ControlHandle)  m_macControl ) ;
+        }
         else
-            UMADeactivateControl((ControlHandle)  m_macControl ) ;
+        {
+            TXNControlTag tag[] = { kTXNIOPrivilegesTag } ;
+            TXNControlData data[] = { { editable ? kTXNReadWrite : kTXNReadOnly } } ;
+            TXNSetTXNObjectControls( (TXNObject) m_macTXN , false , sizeof(tag) / sizeof (TXNControlTag) , tag , data ) ;
+        }
     }
 }
 
@@ -983,10 +1105,13 @@ void wxTextCtrl::Replace(long from, long to, const wxString& value)
     }
     else
     {
-      TXNSetSelection( ((TXNObject) m_macTXN) , from , to ) ;
-      TXNClear( ((TXNObject) m_macTXN) ) ;
-      TXNSetData( ((TXNObject) m_macTXN), kTXNTextData,  (void*)value.c_str(), value.Length(),
-        kTXNUseCurrentSelection, kTXNUseCurrentSelection);
+        bool formerEditable = IsEditable() ;
+        SetEditable(true) ;
+           TXNSetSelection( ((TXNObject) m_macTXN) , from , to ) ;
+           TXNClear( ((TXNObject) m_macTXN) ) ;
+           TXNSetData( ((TXNObject) m_macTXN), kTXNTextData,  (void*)value.c_str(), value.Length(),
+           kTXNUseCurrentSelection, kTXNUseCurrentSelection);
+           SetEditable( formerEditable ) ;
     }
     Refresh() ;
 }
@@ -1004,8 +1129,11 @@ void wxTextCtrl::Remove(long from, long to)
   }
   else
   {
+    bool formerEditable = IsEditable() ;
+    SetEditable(true) ;
     TXNSetSelection( ((TXNObject) m_macTXN) , from , to ) ; 
     TXNClear( ((TXNObject) m_macTXN) ) ; 
+    SetEditable( formerEditable ) ;
   }
     Refresh() ;
 }
@@ -1032,6 +1160,7 @@ void wxTextCtrl::SetSelection(long from, long to)
     SetPort((**tpvars).fDrawingEnvironment);
         /* change the selection */
     TXNSetSelection( (**tpvars).fTXNRec, from, to);
+    TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart);
   }
 }
 
@@ -1058,8 +1187,15 @@ void wxTextCtrl::WriteText(const wxString& text)
     }
     else
     {
+        bool formerEditable = IsEditable() ;
+        SetEditable(true) ;
+           long start , end , dummy ;
+           GetSelection( &start , &dummy ) ;
         TXNSetData( ((TXNObject) m_macTXN), kTXNTextData, (void*) (const char*)value, value.Length(),
           kTXNUseCurrentSelection, kTXNUseCurrentSelection);
+       GetSelection( &dummy , &end ) ;
+        SetStyle( start , end , GetDefaultStyle() ) ;
+       SetEditable( formerEditable ) ;
     }
     MacRedrawControl() ;
 }
@@ -1082,8 +1218,8 @@ void wxTextCtrl::Clear()
   }
   else
   {
-            ClearCurrentScrap();
-            TXNClear((TXNObject)m_macTXN); 
+        TXNSetSelection( (TXNObject)m_macTXN , kTXNStartOffset , kTXNEndOffset ) ;
+        TXNClear((TXNObject)m_macTXN); 
   }
     Refresh() ;
 }
@@ -1177,7 +1313,7 @@ int wxTextCtrl::GetNumberOfLines() const
   wxString content = GetValue() ;
     
     int count = 1;
-    for (int i = 0; i < content.Length() ; i++)
+    for (size_t i = 0; i < content.Length() ; i++)
     {
         if (content[i] == '\r') count++;
     }
@@ -1208,13 +1344,13 @@ int wxTextCtrl::GetLineLength(long lineNo) const
     
     // Find line first
     int count = 0;
-    for (int i = 0; i < content.Length() ; i++)
+    for (size_t i = 0; i < content.Length() ; i++)
     {
         if (count == lineNo)
         {
             // Count chars in line then
             count = 0;
-            for (int j = i; j < content.Length(); j++)
+            for (size_t j = i; j < content.Length(); j++)
             {
                 count++;
                 if (content[j] == '\r') return count;
@@ -1234,14 +1370,14 @@ wxString wxTextCtrl::GetLineText(long lineNo) const
 
     // Find line first
     int count = 0;
-    for (int i = 0; i < content.Length() ; i++)
+    for (size_t i = 0; i < content.Length() ; i++)
     {
         if (count == lineNo)
         {
             // Add chars in line then
             wxString tmp("");
             
-            for (int j = i; j < content.Length(); j++)
+            for (size_t j = i; j < content.Length(); j++)
             {
                 if (content[j] == '\r')
                     return tmp;
@@ -1280,6 +1416,13 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
     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 */
@@ -1288,6 +1431,18 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
         // eat it
         return ;
     }
+    if ( key == 'v' && event.MetaDown() )
+    {
+        if ( CanPaste() )
+            Paste() ;
+        return ;
+    }
+    if ( key == 'x' && event.MetaDown() )
+    {
+        if ( CanCut() )
+            Cut() ;
+        return ;
+    }
     switch ( key )
     {
         case WXK_RETURN:
@@ -1351,7 +1506,7 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
         // default handling
         event.Skip() ;
     }
-    if ( key >= 0x20 ||
+    if ( ( key >= 0x20 && key < WXK_START ) ||
          key == WXK_RETURN ||
          key == WXK_DELETE || 
          key == WXK_BACK)