+ if ( vis )
+ {
+ Rect bounds ;
+ UMAGetControlBoundsInWindowCoords( varsp->fUserPaneRec, &bounds);
+ TPCalculateBounds( varsp , bounds ) ;
+ 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 ;
+
+ 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 )
+ {
+ 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->fTXNObjectActive);
+ }
+}
+
+// update focus outlines
+static void TPRedrawFocusOutline(STPTextPaneVars *varsp) {
+
+ /* 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);
+ }
+}
+
+// draw the control
+static pascal void TPPaneDrawProc(ControlRef theControl, ControlPartCode thePart) {
+ /* set up our globals */
+
+ 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);
+ if ( !varsp->fNoBorders )
+ DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
+ TPRedrawFocusOutline( varsp ) ;
+ }
+
+}
+
+
+/* TPPaneHitTestProc is called when the control manager would
+ 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(ControlRef theControl, Point where) {
+ ControlPartCode result;
+ /* set up our locals and lock down our globals*/
+ result = 0;
+ 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;
+ }
+ return result;
+}
+
+
+
+
+
+/* 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(ControlRef theControl, Point startPt, ControlActionUPP actionProc) {
+
+ ControlPartCode partCodeResult;
+ /* make sure we have some variables... */
+ partCodeResult = 0;
+ 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 */
+ // 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:
+ {
+ wxMacWindowClipper clipper( textctrl ) ;
+
+ EventRecord rec ;
+ ConvertEventRefToEventRecord( (EventRef) wxTheApp->MacGetCurrentEvent() , &rec ) ;
+ TXNClick( varsp->fTXNRec, &rec );
+
+ }
+ break;
+
+ }
+ }
+ return partCodeResult;
+}
+
+
+/* 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(ControlRef theControl) {
+ /* set up locals */
+ 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 (varsp->fIsActive) {
+ Rect bounds;
+ Point mousep;
+
+ wxMacWindowClipper clipper( textctrl ) ;
+ GetMouse(&mousep);
+ /* there's a 'focus thing' and an 'unfocused thing' */
+ if (varsp->fInFocus) {
+ /* flash the cursor */
+ SetPort(varsp->fDrawingEnvironment);
+ TXNIdle(varsp->fTXNRec);
+ /* set the cursor */
+ if (PtInRect(mousep, &varsp->fRTextArea)) {
+ RgnHandle theRgn;
+ RectRgn((theRgn = NewRgn()), &varsp->fRTextArea);
+ TXNAdjustCursor(varsp->fTXNRec, theRgn);
+ DisposeRgn(theRgn);
+ }
+ else
+ {
+ // SetThemeCursor(kThemeArrowCursor);
+ }
+ } else {
+ /* if it's in our bounds, set the cursor */
+ UMAGetControlBoundsInWindowCoords(theControl, &bounds);
+ if (PtInRect(mousep, &bounds))
+ {
+ // SetThemeCursor(kThemeArrowCursor);
+ }
+ }
+ }
+ }
+}
+
+
+/* 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(ControlRef theControl,
+ SInt16 keyCode, SInt16 charCode, SInt16 modifiers) {
+
+ 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;
+}
+
+
+/* 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(ControlRef theControl, Boolean activating) {
+ /* set up locals */
+ 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 ;
+
+ /* 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);
+
+ /* set up the user pane procedures */
+ SetControlData(theControl, kControlEntireControl, kControlUserPaneDrawProcTag, sizeof(gTPDrawProc), &gTPDrawProc);
+ SetControlData(theControl, kControlEntireControl, kControlUserPaneHitTestProcTag, sizeof(gTPHitProc), &gTPHitProc);
+ SetControlData(theControl, kControlEntireControl, kControlUserPaneTrackingProcTag, sizeof(gTPTrackProc), &gTPTrackProc);
+ SetControlData(theControl, kControlEntireControl, kControlUserPaneIdleProcTag, sizeof(gTPIdleProc), &gTPIdleProc);
+ 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 */
+ UMAGetControlBoundsInWindowCoords(theControl, &bounds);
+ varsp->fRTextOutlineRegion = NewRgn() ;
+ TPCalculateBounds( varsp , bounds ) ;
+
+ /* set up the drawing environment */
+ 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 ;
+
+ verify_noerr(TXNNewObject(NULL, varsp->fOwner, &varsp->fRTextArea,
+ frameOptions ,
+ kTXNTextEditStyleFrameType,
+ kTXNTextensionFile,
+ kTXNSystemDefaultEncoding,
+ &varsp->fTXNRec, &varsp->fTXNFrame, (TXNObjectRefcon) varsp));
+
+ TXNControlTag iControlTags[3] = { kTXNDoFontSubstitution, kTXNWordWrapStateTag };
+ TXNControlData iControlData[3] = { {false}, {kTXNAutoWrap} };
+ int toptag = 2 ;
+#if TARGET_API_MAC_OSX
+ iControlTags[2] = kTXNVisibilityTag ;
+ iControlData[2].uValue = false ;
+ toptag++ ;
+#endif
+ iControlData[1].uValue = varsp->fVisible ;
+
+ if ( (wxStyle & wxTE_MULTILINE) && (wxStyle & wxTE_DONTWRAP) )
+ iControlData[2].uValue = kTXNNoAutoWrap ;
+
+ verify_noerr( TXNSetTXNObjectControls( varsp->fTXNRec, false, toptag,
+ iControlTags, iControlData )) ;
+
+ Str255 fontName ;
+ SInt16 fontSize ;
+ Style fontStyle ;
+
+ GetThemeFont(kThemeSmallSystemFont , GetApplicationScript() , fontName , &fontSize , &fontStyle ) ;
+
+ TXNTypeAttributes typeAttr[] =
+ {
+ { kTXNQDFontNameAttribute , kTXNQDFontNameAttributeSize , { (void*) fontName } } ,
+ { kTXNQDFontSizeAttribute , kTXNFontSizeAttributeSize , { (void*) (fontSize << 16) } } ,
+ { kTXNQDFontStyleAttribute , kTXNQDFontStyleAttributeSize , { (void*) normal } } ,
+ } ;
+
+ err = TXNSetTypeAttributes (varsp->fTXNRec, sizeof( typeAttr ) / sizeof(TXNTypeAttributes) , typeAttr,
+ kTXNStartOffset,
+ kTXNEndOffset);
+
+
+ /* perform final activations and setup for our text field. Here,
+ we assume that the window is going to be the 'active' window. */
+ TPActivatePaneText(varsp, varsp->fIsActive && varsp->fInFocus);
+ /* all done */
+ return err;
+}
+
+