1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "textctrl.h"
21 #include <sys/types.h>
27 #include "wx/msgdlg.h"
29 #if wxUSE_STD_IOSTREAM
39 #include "wx/button.h"
40 #include "wx/toplevel.h"
41 #include "wx/textctrl.h"
42 #include "wx/notebook.h"
43 #include "wx/tabctrl.h"
44 #include "wx/settings.h"
45 #include "wx/filefn.h"
48 #if defined(__BORLANDC__) && !defined(__WIN32__)
50 #elif !defined(__MWERKS__) && !defined(__GNUWIN32) && !defined(__DARWIN__)
57 #include <MacTextEditor.h>
58 #include <ATSUnicode.h>
59 #include <TextCommon.h>
60 #include <TextEncodingConverter.h>
61 #include "wx/mac/uma.h"
63 #define TE_UNLIMITED_LENGTH 0xFFFFFFFFUL
64 #if TARGET_API_MAC_OSX
65 #define wxMAC_USE_MLTE 0
66 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
67 #define wxMAC_USE_MLTE_HIVIEW 1
69 #define wxMAC_USE_MLTE_HIVIEW 0
72 // there is no unicodetextctrl on classic, and hopefully MLTE works better there
73 #define wxMAC_USE_MLTE 1
74 #define wxMAC_USE_MLTE_HIVIEW 0
79 TXNFrameOptions
FrameOptionsFromWXStyle( long wxStyle
)
81 TXNFrameOptions frameOptions
=
82 kTXNDontDrawCaretWhenInactiveMask
;
83 if ( ! ( wxStyle
& wxTE_NOHIDESEL
) )
84 frameOptions
|= kTXNDontDrawSelectionWhenInactiveMask
;
86 if ( wxStyle
& wxTE_MULTILINE
)
88 if ( ! ( wxStyle
& wxTE_DONTWRAP
) )
89 frameOptions
|= kTXNAlwaysWrapAtViewEdgeMask
;
92 frameOptions
|= kTXNAlwaysWrapAtViewEdgeMask
;
93 frameOptions
|= kTXNWantHScrollBarMask
;
96 if ( !(wxStyle
& wxTE_NO_VSCROLL
) )
97 frameOptions
|= kTXNWantVScrollBarMask
;
100 frameOptions
|= kTXNSingleLineOnlyMask
;
101 return frameOptions
;
104 void AdjustAttributesFromWXStyle( TXNObject txn
, long wxStyle
, bool visible
)
106 TXNControlTag iControlTags
[3] = { kTXNDoFontSubstitution
, kTXNWordWrapStateTag
};
107 TXNControlData iControlData
[3] = { {false}, {kTXNNoAutoWrap
} };
109 #if TARGET_API_MAC_OSX
110 iControlTags
[2] = kTXNVisibilityTag
;
111 iControlData
[2].uValue
= visible
;
115 if ( wxStyle
& wxTE_MULTILINE
)
117 if (wxStyle
& wxTE_DONTWRAP
)
118 iControlData
[1].uValue
= kTXNNoAutoWrap
;
120 iControlData
[1].uValue
= kTXNAutoWrap
;
123 verify_noerr( TXNSetTXNObjectControls( txn
, false, toptag
,
124 iControlTags
, iControlData
)) ;
130 GetThemeFont(kThemeSystemFont
, GetApplicationScript() , fontName
, &fontSize
, &fontStyle
) ;
132 TXNTypeAttributes typeAttr
[] =
134 { kTXNQDFontNameAttribute
, kTXNQDFontNameAttributeSize
, { (void*) fontName
} } ,
135 { kTXNQDFontSizeAttribute
, kTXNFontSizeAttributeSize
, { (void*) (fontSize
<< 16) } } ,
136 { kTXNQDFontStyleAttribute
, kTXNQDFontStyleAttributeSize
, { (void*) normal
} } ,
139 verify_noerr( TXNSetTypeAttributes (txn
, sizeof( typeAttr
) / sizeof(TXNTypeAttributes
) , typeAttr
,
145 #if !wxMAC_USE_MLTE_HIVIEW
147 // CS:TODO we still have a problem getting properly at the text events of a control because under Carbon
148 // the MLTE engine registers itself for the key events thus the normal flow never occurs, the only measure for the
149 // moment is to avoid setting the true focus on the control, the proper solution at the end would be to have
150 // an alternate path for carbon key events that routes automatically into the same wx flow of events
154 /* kmUPTextPart is the part code we return to indicate the user has clicked
155 in the text area of our control */
156 #define kmUPTextPart 1
159 /* routines for using existing user pane controls.
160 These routines are useful for cases where you would like to use an
161 existing user pane control in, say, a dialog window as a scrolling
164 /* Utility Routines */
166 /* kUserClickedToFocusPart is a part code we pass to the SetKeyboardFocus
167 routine. In our focus switching routine this part code is understood
168 as meaning 'the user has clicked in the control and we need to switch
169 the current focus to ourselves before we can continue'. */
170 #define kUserClickedToFocusPart 100
172 /* STPTextPaneVars is a structure used for storing the the mUP Control's
173 internal variables and state information. A handle to this record is
174 stored in the pane control's reference value field using the
175 SetControlReference routine. */
178 /* OS records referenced */
179 TXNObject fTXNRec
; /* the txn record */
180 TXNFrameID fTXNFrame
; /* the txn frame ID */
181 ControlRef fUserPaneRec
; /* handle to the user pane control */
182 WindowPtr fOwner
; /* window containing control */
183 GrafPtr fDrawingEnvironment
; /* grafport where control is drawn */
185 Boolean fInFocus
; /* true while the focus rect is drawn around the control */
186 Boolean fIsActive
; /* true while the control is drawn in the active state */
187 Boolean fTXNObjectActive
; /* reflects the activation state of the text edit record */
188 Boolean fFocusDrawState
; /* true if focus is drawn (default: true) */
189 /* calculated locations */
190 Rect fRBounds
; /* control bounds */
191 Rect fRTextArea
; /* area where the text is drawn */
192 Rect fRFocusOutline
; /* rectangle used to draw the focus box */
193 Rect fRTextOutline
; /* rectangle used to draw the border */
194 RgnHandle fRTextOutlineRegion
; /* background region for the text, erased before calling TEUpdate */
195 /* our focus advance override routine */
196 EventHandlerUPP handlerUPP
;
197 EventHandlerRef handlerRef
;
203 /* mUPOpenControl initializes a user pane control so it will be drawn
204 and will behave as a scrolling text edit field inside of a window.
205 This routine performs all of the initialization steps necessary,
206 except it does not create the user pane control itself. theControl
207 should refer to a user pane control that you have either created
208 yourself or extracted from a dialog's control heirarchy using
209 the GetDialogItemAsControl routine. */
210 OSStatus
mUPOpenControl(STPTextPaneVars
* &handle
, ControlRef theControl
, long wxStyle
);
215 /* Univerals Procedure Pointer variables used by the
216 mUP Control. These variables are set up
217 the first time that mUPOpenControl is called. */
218 ControlUserPaneDrawUPP gTPDrawProc
= NULL
;
219 ControlUserPaneHitTestUPP gTPHitProc
= NULL
;
220 ControlUserPaneTrackingUPP gTPTrackProc
= NULL
;
221 ControlUserPaneIdleUPP gTPIdleProc
= NULL
;
222 ControlUserPaneKeyDownUPP gTPKeyProc
= NULL
;
223 ControlUserPaneActivateUPP gTPActivateProc
= NULL
;
224 ControlUserPaneFocusUPP gTPFocusProc
= NULL
;
226 // one place for calculating all
227 static void TPCalculateBounds(STPTextPaneVars
*varsp
, const Rect
& bounds
)
229 SetRect(&varsp
->fRBounds
, bounds
.left
, bounds
.top
, bounds
.right
, bounds
.bottom
);
230 SetRect(&varsp
->fRFocusOutline
, bounds
.left
, bounds
.top
, bounds
.right
, bounds
.bottom
);
231 // eventually make TextOutline inset 1,1
232 SetRect(&varsp
->fRTextOutline
, bounds
.left
, bounds
.top
, bounds
.right
, bounds
.bottom
);
233 if ( !varsp
->fNoBorders
)
235 SetRect(&varsp
->fRTextArea
, bounds
.left
+ 2 , bounds
.top
+ (varsp
->fMultiline
? 0 : 2) ,
236 bounds
.right
- (varsp
->fMultiline
? 0 : 2), bounds
.bottom
- (varsp
->fMultiline
? 0 : 2));
240 SetRect(&varsp
->fRTextArea
, bounds
.left
, bounds
.top
,
241 bounds
.right
, bounds
.bottom
);
245 OSStatus
MLTESetObjectVisibility( STPTextPaneVars
*varsp
, Boolean vis
, long wxStyle
)
247 OSStatus err
= noErr
;
248 #if TARGET_API_MAC_OSX
249 TXNControlTag iControlTags
[1] = { kTXNVisibilityTag
};
250 TXNControlData iControlData
[1] = {{ vis
}};
251 err
= ::TXNSetTXNObjectControls( varsp
->fTXNRec
, false, 1, iControlTags
, iControlData
);
253 wxTextCtrl
* textctrl
= (wxTextCtrl
*) GetControlReference(varsp
->fUserPaneRec
);
254 if ( vis
&& textctrl
)
257 UMAGetControlBoundsInWindowCoords( varsp
->fUserPaneRec
, &bounds
);
258 TPCalculateBounds( varsp
, bounds
) ;
259 wxMacWindowClipper
cl(textctrl
) ;
260 TXNSetFrameBounds( varsp
->fTXNRec
, varsp
->fRTextArea
.top
, varsp
->fRTextArea
.left
,
261 varsp
->fRTextArea
.bottom
, varsp
->fRTextArea
.right
, varsp
->fTXNFrame
);
262 TXNShowSelection( varsp
->fTXNRec
, kTXNShowStart
);
267 // make sure we don't miss changes as carbon events are not available for these under classic
268 static void TPUpdateVisibility(ControlRef theControl
) {
269 wxTextCtrl
* textctrl
= (wxTextCtrl
*) GetControlReference(theControl
);
270 if ( textctrl
== NULL
)
273 STPTextPaneVars
*varsp
= (STPTextPaneVars
*) textctrl
->m_macTXNvars
;
276 UMAGetControlBoundsInWindowCoords(theControl
, &bounds
);
277 if ( textctrl
->MacIsReallyShown() != varsp
->fVisible
)
279 // invalidate old position
280 // InvalWindowRect( GetControlOwner( theControl ) , &varsp->fRBounds ) ;
281 varsp
->fVisible
= textctrl
->MacIsReallyShown() ;
283 if ( !EqualRect( &bounds
, &varsp
->fRBounds
) )
286 Rect oldBounds
= varsp
->fRBounds
;
287 TPCalculateBounds( varsp
, bounds
) ;
288 // we only recalculate when visible, otherwise scrollbars get drawn at incorrect places
289 if ( varsp
->fVisible
)
291 wxMacWindowClipper
cl(textctrl
) ;
292 TXNSetFrameBounds( varsp
->fTXNRec
, varsp
->fRTextArea
.top
, varsp
->fRTextArea
.left
,
293 varsp
->fRTextArea
.bottom
, varsp
->fRTextArea
.right
, varsp
->fTXNFrame
);
295 InvalWindowRect( GetControlOwner( theControl
) , &oldBounds
) ;
296 InvalWindowRect( GetControlOwner( theControl
) , &varsp
->fRBounds
) ;
300 // make correct activations
301 static void TPActivatePaneText(STPTextPaneVars
*varsp
, Boolean setActive
) {
303 wxTextCtrl
* textctrl
= (wxTextCtrl
*) GetControlReference(varsp
->fUserPaneRec
);
304 if (varsp
->fTXNObjectActive
!= setActive
&& textctrl
->MacIsReallyShown() )
306 varsp
->fTXNObjectActive
= setActive
;
307 TXNActivate(varsp
->fTXNRec
, varsp
->fTXNFrame
, varsp
->fTXNObjectActive
);
309 TXNFocus( varsp
->fTXNRec
, varsp
->fTXNObjectActive
);
313 // update focus outlines
314 static void TPRedrawFocusOutline(STPTextPaneVars
*varsp
) {
317 if (varsp
->fFocusDrawState
!= (varsp
->fIsActive
&& varsp
->fInFocus
))
319 varsp
->fFocusDrawState
= (varsp
->fIsActive
&& varsp
->fInFocus
);
320 DrawThemeFocusRect(&varsp
->fRFocusOutline
, varsp
->fFocusDrawState
);
324 // update TXN focus state
325 static void TPFocusPaneText(STPTextPaneVars
*varsp
, Boolean setFocus
) {
326 wxTextCtrl
* textctrl
= (wxTextCtrl
*) GetControlReference(varsp
->fUserPaneRec
);
328 if (varsp
->fInFocus
!= setFocus
&& textctrl
->MacIsReallyShown()) {
329 varsp
->fInFocus
= setFocus
;
330 TXNFocus( varsp
->fTXNRec
, varsp
->fInFocus
);
335 static pascal void TPPaneDrawProc(ControlRef theControl
, ControlPartCode thePart
) {
336 /* set up our globals */
338 wxTextCtrl
* textctrl
= (wxTextCtrl
*) GetControlReference(theControl
);
339 if ( textctrl
== NULL
)
341 TPUpdateVisibility( theControl
) ;
343 STPTextPaneVars
*varsp
= (STPTextPaneVars
*) textctrl
->m_macTXNvars
;
344 if ( textctrl
->MacIsReallyShown() )
346 wxMacWindowClipper
clipper( textctrl
) ;
347 TXNDraw(varsp
->fTXNRec
, NULL
);
348 if ( !varsp
->fNoBorders
)
349 DrawThemeEditTextFrame(&varsp
->fRTextOutline
, varsp
->fIsActive
? kThemeStateActive
: kThemeStateInactive
);
350 TPRedrawFocusOutline( varsp
) ;
356 /* TPPaneHitTestProc is called when the control manager would
357 like to determine what part of the control the mouse resides over.
358 We also call this routine from our tracking proc to determine how
359 to handle mouse clicks. */
360 static pascal ControlPartCode
TPPaneHitTestProc(ControlRef theControl
, Point where
) {
361 ControlPartCode result
;
362 /* set up our locals and lock down our globals*/
364 wxTextCtrl
* textctrl
= (wxTextCtrl
*) GetControlReference(theControl
);
365 if ( textctrl
== NULL
)
367 TPUpdateVisibility( theControl
) ;
368 STPTextPaneVars
*varsp
= (STPTextPaneVars
*) textctrl
->m_macTXNvars
;
369 if (textctrl
->MacIsReallyShown() )
371 if (PtInRect(where
, &varsp
->fRBounds
))
372 result
= kmUPTextPart
;
383 /* TPPaneTrackingProc is called when the mouse is being held down
384 over our control. This routine handles clicks in the text area
385 and in the scroll bar. */
386 static pascal ControlPartCode
TPPaneTrackingProc(ControlRef theControl
, Point startPt
, ControlActionUPP actionProc
) {
388 ControlPartCode partCodeResult
;
389 /* make sure we have some variables... */
391 wxTextCtrl
* textctrl
= (wxTextCtrl
*) GetControlReference(theControl
);
392 if ( textctrl
== NULL
)
394 TPUpdateVisibility( theControl
) ;
395 STPTextPaneVars
*varsp
= (STPTextPaneVars
*) textctrl
->m_macTXNvars
;
396 if (textctrl
->MacIsReallyShown() )
398 /* we don't do any of these functions unless we're in focus */
399 if ( ! varsp
->fInFocus
) {
401 owner
= GetControlOwner(theControl
);
402 ClearKeyboardFocus(owner
);
403 SetKeyboardFocus(owner
, theControl
, kUserClickedToFocusPart
);
405 /* find the location for the click */
406 // for compositing, we must convert these into toplevel window coordinates, because hittesting expects them
407 if ( textctrl
->MacGetTopLevelWindow()->MacUsesCompositing() )
410 textctrl
->MacClientToRootWindow( &x
, &y
) ;
415 switch (TPPaneHitTestProc(theControl
, startPt
))
418 /* handle clicks in the text part */
421 wxMacWindowClipper
clipper( textctrl
) ;
424 ConvertEventRefToEventRecord( (EventRef
) wxTheApp
->MacGetCurrentEvent() , &rec
) ;
425 TXNClick( varsp
->fTXNRec
, &rec
);
432 return partCodeResult
;
436 /* TPPaneIdleProc is our user pane idle routine. When our text field
437 is active and in focus, we use this routine to set the cursor. */
438 static pascal void TPPaneIdleProc(ControlRef theControl
) {
440 wxTextCtrl
* textctrl
= (wxTextCtrl
*) GetControlReference(theControl
);
441 if ( textctrl
== NULL
)
443 TPUpdateVisibility( theControl
) ;
444 STPTextPaneVars
*varsp
= (STPTextPaneVars
*) textctrl
->m_macTXNvars
;
445 if (textctrl
->MacIsReallyShown()) {
446 /* if we're not active, then we have nothing to say about the cursor */
447 if (varsp
->fIsActive
) {
451 wxMacWindowClipper
clipper( textctrl
) ;
453 /* there's a 'focus thing' and an 'unfocused thing' */
454 if (varsp
->fInFocus
) {
455 /* flash the cursor */
456 SetPort(varsp
->fDrawingEnvironment
);
457 TXNIdle(varsp
->fTXNRec
);
459 if (PtInRect(mousep
, &varsp
->fRTextArea
)) {
461 RectRgn((theRgn
= NewRgn()), &varsp
->fRTextArea
);
462 TXNAdjustCursor(varsp
->fTXNRec
, theRgn
);
467 // SetThemeCursor(kThemeArrowCursor);
470 /* if it's in our bounds, set the cursor */
471 UMAGetControlBoundsInWindowCoords(theControl
, &bounds
);
472 if (PtInRect(mousep
, &bounds
))
474 // SetThemeCursor(kThemeArrowCursor);
482 /* TPPaneKeyDownProc is called whenever a keydown event is directed
483 at our control. Here, we direct the keydown event to the text
484 edit record and redraw the scroll bar and text field as appropriate. */
485 static pascal ControlPartCode
TPPaneKeyDownProc(ControlRef theControl
,
486 SInt16 keyCode
, SInt16 charCode
, SInt16 modifiers
) {
488 wxTextCtrl
* textctrl
= (wxTextCtrl
*) GetControlReference(theControl
);
489 if ( textctrl
== NULL
)
491 TPUpdateVisibility( theControl
) ;
493 STPTextPaneVars
*varsp
= (STPTextPaneVars
*) textctrl
->m_macTXNvars
;
496 /* turn autoscrolling on and send the key event to text edit */
497 wxMacWindowClipper
clipper( textctrl
) ;
499 memset( &ev
, 0 , sizeof( ev
) ) ;
501 ev
.modifiers
= modifiers
;
502 ev
.message
= (( keyCode
<< 8 ) & keyCodeMask
) + ( charCode
& charCodeMask
) ;
503 TXNKeyDown( varsp
->fTXNRec
, &ev
);
505 return kControlEntireControl
;
509 /* TPPaneActivateProc is called when the window containing
510 the user pane control receives activate events. Here, we redraw
511 the control and it's text as necessary for the activation state. */
512 static pascal void TPPaneActivateProc(ControlRef theControl
, Boolean activating
) {
514 wxTextCtrl
* textctrl
= (wxTextCtrl
*) GetControlReference(theControl
);
516 if ( textctrl
== NULL
)
518 TPUpdateVisibility( theControl
) ;
520 STPTextPaneVars
*varsp
= (STPTextPaneVars
*) textctrl
->m_macTXNvars
;
522 varsp
->fIsActive
= activating
;
523 wxMacWindowClipper
clipper( textctrl
) ;
524 TPActivatePaneText(varsp
, varsp
->fIsActive
&& varsp
->fInFocus
);
525 /* redraw the frame */
526 if ( textctrl
->MacIsReallyShown() )
528 if ( !varsp
->fNoBorders
)
529 DrawThemeEditTextFrame(&varsp
->fRTextOutline
, varsp
->fIsActive
? kThemeStateActive
: kThemeStateInactive
);
530 TPRedrawFocusOutline( varsp
) ;
535 /* TPPaneFocusProc is called when every the focus changes to or
536 from our control. Herein, switch the focus appropriately
537 according to the parameters and redraw the control as
539 static pascal ControlPartCode
TPPaneFocusProc(ControlRef theControl
, ControlFocusPart action
) {
540 ControlPartCode focusResult
;
542 focusResult
= kControlFocusNoPart
;
543 wxTextCtrl
* textctrl
= (wxTextCtrl
*) GetControlReference(theControl
);
544 if ( textctrl
== NULL
)
546 TPUpdateVisibility( theControl
) ;
547 STPTextPaneVars
*varsp
= (STPTextPaneVars
*) textctrl
->m_macTXNvars
;
548 /* if kControlFocusPrevPart and kControlFocusNextPart are received when the user is
549 tabbing forwards (or shift tabbing backwards) through the items in the dialog,
550 and kControlFocusNextPart will be received. When the user clicks in our field
551 and it is not the current focus, then the constant kUserClickedToFocusPart will
552 be received. The constant kControlFocusNoPart will be received when our control
553 is the current focus and the user clicks in another control. In your focus routine,
554 you should respond to these codes as follows:
556 kControlFocusNoPart - turn off focus and return kControlFocusNoPart. redraw
557 the control and the focus rectangle as necessary.
559 kControlFocusPrevPart or kControlFocusNextPart - toggle focus on or off
560 depending on its current state. redraw the control and the focus rectangle
561 as appropriate for the new focus state. If the focus state is 'off', return the constant
562 kControlFocusNoPart, otherwise return a non-zero part code.
563 kUserClickedToFocusPart - is a constant defined for this example. You should
564 define your own value for handling click-to-focus type events. */
565 /* calculate the next highlight state */
568 case kControlFocusNoPart
:
569 TPFocusPaneText(varsp
, false);
570 focusResult
= kControlFocusNoPart
;
572 case kUserClickedToFocusPart
:
573 TPFocusPaneText(varsp
, true);
576 case kControlFocusPrevPart
:
577 case kControlFocusNextPart
:
578 TPFocusPaneText(varsp
, ( ! varsp
->fInFocus
));
579 focusResult
= varsp
->fInFocus
? 1 : kControlFocusNoPart
;
582 TPActivatePaneText(varsp
, varsp
->fIsActive
&& varsp
->fInFocus
);
583 /* redraw the text fram and focus rectangle to indicate the
585 if ( textctrl
->MacIsReallyShown() )
587 wxMacWindowClipper
c( textctrl
) ;
588 if ( !varsp
->fNoBorders
)
589 DrawThemeEditTextFrame(&varsp
->fRTextOutline
, varsp
->fIsActive
? kThemeStateActive
: kThemeStateInactive
);
590 TPRedrawFocusOutline( varsp
) ;
596 /* mUPOpenControl initializes a user pane control so it will be drawn
597 and will behave as a scrolling text edit field inside of a window.
598 This routine performs all of the initialization steps necessary,
599 except it does not create the user pane control itself. theControl
600 should refer to a user pane control that you have either created
601 yourself or extracted from a dialog's control heirarchy using
602 the GetDialogItemAsControl routine. */
603 OSStatus
mUPOpenControl(STPTextPaneVars
* &handle
, ControlRef theControl
, long wxStyle
)
607 STPTextPaneVars
*varsp
;
608 OSStatus err
= noErr
;
610 /* set up our globals */
611 if (gTPDrawProc
== NULL
) gTPDrawProc
= NewControlUserPaneDrawUPP(TPPaneDrawProc
);
612 if (gTPHitProc
== NULL
) gTPHitProc
= NewControlUserPaneHitTestUPP(TPPaneHitTestProc
);
613 if (gTPTrackProc
== NULL
) gTPTrackProc
= NewControlUserPaneTrackingUPP(TPPaneTrackingProc
);
614 if (gTPIdleProc
== NULL
) gTPIdleProc
= NewControlUserPaneIdleUPP(TPPaneIdleProc
);
615 if (gTPKeyProc
== NULL
) gTPKeyProc
= NewControlUserPaneKeyDownUPP(TPPaneKeyDownProc
);
616 if (gTPActivateProc
== NULL
) gTPActivateProc
= NewControlUserPaneActivateUPP(TPPaneActivateProc
);
617 if (gTPFocusProc
== NULL
) gTPFocusProc
= NewControlUserPaneFocusUPP(TPPaneFocusProc
);
619 /* allocate our private storage */
620 varsp
= (STPTextPaneVars
*) malloc(sizeof(STPTextPaneVars
));
623 /* set the initial settings for our private data */
624 varsp
->fMultiline
= wxStyle
& wxTE_MULTILINE
;
625 varsp
->fNoBorders
= wxStyle
& wxNO_BORDER
;
626 varsp
->fInFocus
= false;
627 varsp
->fIsActive
= true;
628 varsp
->fTXNObjectActive
= false;
629 varsp
->fFocusDrawState
= false ;
630 varsp
->fUserPaneRec
= theControl
;
631 varsp
->fVisible
= true ;
633 theWindow
= varsp
->fOwner
= GetControlOwner(theControl
);
635 varsp
->fDrawingEnvironment
= (GrafPtr
) GetWindowPort(theWindow
);
637 /* set up the user pane procedures */
638 SetControlData(theControl
, kControlEntireControl
, kControlUserPaneDrawProcTag
, sizeof(gTPDrawProc
), &gTPDrawProc
);
639 SetControlData(theControl
, kControlEntireControl
, kControlUserPaneHitTestProcTag
, sizeof(gTPHitProc
), &gTPHitProc
);
640 SetControlData(theControl
, kControlEntireControl
, kControlUserPaneTrackingProcTag
, sizeof(gTPTrackProc
), &gTPTrackProc
);
641 SetControlData(theControl
, kControlEntireControl
, kControlUserPaneIdleProcTag
, sizeof(gTPIdleProc
), &gTPIdleProc
);
642 SetControlData(theControl
, kControlEntireControl
, kControlUserPaneKeyDownProcTag
, sizeof(gTPKeyProc
), &gTPKeyProc
);
643 SetControlData(theControl
, kControlEntireControl
, kControlUserPaneActivateProcTag
, sizeof(gTPActivateProc
), &gTPActivateProc
);
644 SetControlData(theControl
, kControlEntireControl
, kControlUserPaneFocusProcTag
, sizeof(gTPFocusProc
), &gTPFocusProc
);
646 /* calculate the rectangles used by the control */
647 UMAGetControlBoundsInWindowCoords(theControl
, &bounds
);
648 varsp
->fRTextOutlineRegion
= NewRgn() ;
649 TPCalculateBounds( varsp
, bounds
) ;
651 /* set up the drawing environment */
652 SetPort(varsp
->fDrawingEnvironment
);
654 /* create the new edit field */
656 TXNFrameOptions frameOptions
= FrameOptionsFromWXStyle( wxStyle
) ;
658 verify_noerr(TXNNewObject(NULL
, varsp
->fOwner
, &varsp
->fRTextArea
,
660 kTXNTextEditStyleFrameType
,
662 kTXNSystemDefaultEncoding
,
663 &varsp
->fTXNRec
, &varsp
->fTXNFrame
, (TXNObjectRefcon
) varsp
));
665 AdjustAttributesFromWXStyle( varsp
->fTXNRec
, wxStyle
, varsp
->fVisible
) ;
666 /* perform final activations and setup for our text field. Here,
667 we assume that the window is going to be the 'active' window. */
668 TPActivatePaneText(varsp
, varsp
->fIsActive
&& varsp
->fInFocus
);
674 struct STPTextPaneVars
680 static void SetTXNData( STPTextPaneVars
*varsp
, TXNObject txn
, const wxString
& st
, TXNOffset start
, TXNOffset end
)
683 #if SIZEOF_WCHAR_T == 2
684 size_t len
= st
.Len() ;
685 TXNSetData( txn
, kTXNUnicodeTextData
, (void*)st
.wc_str(), len
* 2,
688 wxMBConvUTF16BE converter
;
689 ByteCount byteBufferLen
= converter
.WC2MB( NULL
, st
.wc_str() , 0 ) ;
690 UniChar
*unibuf
= (UniChar
*) malloc(byteBufferLen
) ;
691 converter
.WC2MB( (char*) unibuf
, st
.wc_str() , byteBufferLen
) ;
692 TXNSetData( txn
, kTXNUnicodeTextData
, (void*)unibuf
, byteBufferLen
,
697 wxCharBuffer text
= st
.mb_str(wxConvLocal
) ;
698 TXNSetData( txn
, kTXNTextData
, (void*)text
.data(), strlen( text
) ,
706 #if !USE_SHARED_LIBRARY
707 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl
, wxControl
)
709 BEGIN_EVENT_TABLE(wxTextCtrl
, wxControl
)
710 EVT_DROP_FILES(wxTextCtrl::OnDropFiles
)
711 EVT_CHAR(wxTextCtrl::OnChar
)
712 EVT_MENU(wxID_CUT
, wxTextCtrl::OnCut
)
713 EVT_MENU(wxID_COPY
, wxTextCtrl::OnCopy
)
714 EVT_MENU(wxID_PASTE
, wxTextCtrl::OnPaste
)
715 EVT_MENU(wxID_UNDO
, wxTextCtrl::OnUndo
)
716 EVT_MENU(wxID_REDO
, wxTextCtrl::OnRedo
)
718 EVT_UPDATE_UI(wxID_CUT
, wxTextCtrl::OnUpdateCut
)
719 EVT_UPDATE_UI(wxID_COPY
, wxTextCtrl::OnUpdateCopy
)
720 EVT_UPDATE_UI(wxID_PASTE
, wxTextCtrl::OnUpdatePaste
)
721 EVT_UPDATE_UI(wxID_UNDO
, wxTextCtrl::OnUpdateUndo
)
722 EVT_UPDATE_UI(wxID_REDO
, wxTextCtrl::OnUpdateRedo
)
727 void wxTextCtrl::Init()
730 m_macTXNvars
= NULL
;
735 m_maxLength
= TE_UNLIMITED_LENGTH
;
738 wxTextCtrl::~wxTextCtrl()
741 SetControlReference(*m_peer
, 0) ;
742 #if !wxMAC_USE_MLTE_HIVIEW
743 TXNDeleteObject((TXNObject
)m_macTXN
);
745 /* delete our private storage */
747 /* zero the control reference */
752 bool wxTextCtrl::Create(wxWindow
*parent
, wxWindowID id
,
755 const wxSize
& size
, long style
,
756 const wxValidator
& validator
,
757 const wxString
& name
)
759 m_macIsUserPane
= FALSE
;
762 m_macTXNvars
= NULL
;
765 // base initialization
766 if ( !wxTextCtrlBase::Create(parent
, id
, pos
, size
, style
& ~(wxHSCROLL
|wxVSCROLL
), validator
, name
) )
769 wxSize mySize
= size
;
771 Rect bounds
= wxMacGetBoundsForControl( this , pos
, size
) ;
773 if ( m_windowStyle
& wxTE_MULTILINE
)
775 wxASSERT_MSG( !(m_windowStyle
& wxTE_PROCESS_ENTER
),
776 wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") );
778 m_windowStyle
|= wxTE_PROCESS_ENTER
;
782 wxMacConvertNewlines13To10( &st
) ;
785 #if wxMAC_USE_MLTE_HIVIEW
786 HIRect hr
= { bounds
.left
, bounds
.top
, bounds
.right
- bounds
.left
, bounds
.bottom
- bounds
.top
} ;
787 HIViewRef scrollView
= NULL
;
788 TXNFrameOptions frameOptions
= FrameOptionsFromWXStyle( style
) ;
790 if ( frameOptions
& (kTXNWantVScrollBarMask
|kTXNWantHScrollBarMask
) )
792 HIScrollViewCreate(( frameOptions
& kTXNWantHScrollBarMask
? kHIScrollViewOptionsHorizScroll
: 0) |
793 ( frameOptions
& kTXNWantVScrollBarMask
? kHIScrollViewOptionsVertScroll
: 0 ) , &scrollView
) ;
795 HIViewSetFrame( scrollView
, &hr
);
796 HIViewSetVisible( scrollView
, true );
799 HITextViewCreate( NULL
, 0, frameOptions
, (ControlRef
*) &textView
) ;
800 m_macTXN
= HITextViewGetTXNObject( textView
) ;
801 AdjustAttributesFromWXStyle( (TXNObject
) m_macTXN
, style
, true ) ;
802 HIViewSetVisible( (ControlRef
) textView
, true ) ;
805 HIViewAddSubview( scrollView
, textView
) ;
806 m_peer
= scrollView
;
815 featurSet
= kControlSupportsEmbedding
| kControlSupportsFocus
| kControlWantsIdle
816 | kControlWantsActivate
| kControlHandlesTracking
| kControlHasSpecialBackground
817 | kControlGetsFocusOnClick
| kControlSupportsLiveFeedback
;
818 /* create the control */
819 m_peer
= new wxMacControl() ;
820 verify_noerr( CreateUserPaneControl( MAC_WXHWND(GetParent()->MacGetTopLevelWindowRef()) , &bounds
, featurSet
, , *m_peer
) );
823 wxMacWindowClipper
c(this) ;
824 STPTextPaneVars
*varsp
;
825 mUPOpenControl( varsp
, *m_peer
, m_windowStyle
);
826 m_macTXNvars
= varsp
;
827 m_macTXN
= varsp
->fTXNRec
;
830 if ( style
& wxTE_PASSWORD
)
833 verify_noerr(TXNEchoMode( (TXNObject
) m_macTXN
, c
, 0 , true )) ;
836 MacPostControlCreate(pos
,size
) ;
838 #if !wxMAC_USE_MLTE_HIVIEW
839 if ( MacIsReallyShown() )
840 MLTESetObjectVisibility( (STPTextPaneVars
*) m_macTXNvars
, true , GetWindowStyle() ) ;
844 wxMacWindowClipper
clipper( this ) ;
845 #if !wxMAC_USE_MLTE_HIVIEW
846 TPUpdateVisibility( *m_peer
) ;
848 SetTXNData( (STPTextPaneVars
*)m_macTXNvars
, (TXNObject
) m_macTXN
, st
, kTXNStartOffset
, kTXNEndOffset
) ;
850 TXNSetSelection( (TXNObject
) m_macTXN
, 0, 0);
851 TXNShowSelection( (TXNObject
) m_macTXN
, kTXNShowStart
);
854 // in case MLTE is catching events before we get the chance to do so, we'd have to reintroduce the tlw-handler in front :
855 // parent->MacGetTopLevelWindow()->MacInstallTopLevelWindowEventHandler() ;
857 SetBackgroundColour( *wxWHITE
) ;
860 tback
.bgType
= kTXNBackgroundTypeRGB
;
861 tback
.bg
.color
= MAC_WXCOLORREF( GetBackgroundColour().GetPixel() );
862 TXNSetBackground( (TXNObject
) m_macTXN
, &tback
);
865 wxMacCFStringHolder
cf(st
, m_font
.GetEncoding()) ;
866 CFStringRef cfr
= cf
;
867 Boolean isPassword
= ( m_windowStyle
& wxTE_PASSWORD
) != 0 ;
868 m_peer
= new wxMacControl() ;
869 CreateEditUnicodeTextControl( MAC_WXHWND(parent
->MacGetTopLevelWindowRef()), &bounds
, cfr
, isPassword
, NULL
, *m_peer
) ;
871 if ( !(m_windowStyle
& wxTE_MULTILINE
) )
873 Boolean singleline
= true ;
874 ::SetControlData( *m_peer
, kControlEditTextPart
, kControlEditTextSingleLineTag
, sizeof( singleline
) , &singleline
) ;
876 MacPostControlCreate(pos
,size
) ;
879 if ( m_windowStyle
& wxTE_READONLY
)
881 SetEditable( false ) ;
888 void wxTextCtrl::MacVisibilityChanged()
891 #if !wxMAC_USE_MLTE_HIVIEW
892 MLTESetObjectVisibility((STPTextPaneVars
*) m_macTXNvars
, MacIsReallyShown() , GetWindowStyle() ) ;
893 if ( !MacIsReallyShown() )
894 InvalWindowRect( GetControlOwner( *m_peer
) , &((STPTextPaneVars
*)m_macTXNvars
)->fRBounds
) ;
897 if ( !(m_windowStyle
& wxTE_MULTILINE
) && MacIsReallyShown() )
899 // work around a refresh issue insofar as not always the entire content is shown even if this would be possible
900 ControlEditTextSelectionRec sel
;
901 CFStringRef value
= NULL
;
902 Size actualSize
= 0 ;
903 ResType datatag
= GetWindowStyle() & wxTE_PASSWORD
?
904 kControlEditTextPasswordCFStringTag
: kControlEditTextCFStringTag
;
906 verify_noerr( GetControlData( *m_peer
, 0, kControlEditTextSelectionTag
,
907 sizeof(ControlEditTextSelectionRec
), &sel
, &actualSize
) );
908 verify_noerr( GetControlData( *m_peer
, 0, datatag
, sizeof(CFStringRef
), &value
, &actualSize
) );
910 verify_noerr( SetControlData( *m_peer
, 0, datatag
, sizeof(CFStringRef
), &value
) );
911 verify_noerr( SetControlData( *m_peer
, 0, kControlEditTextSelectionTag
, sizeof(ControlEditTextSelectionRec
), &sel
) );
918 void wxTextCtrl::MacEnabledStateChanged()
923 wxString
wxTextCtrl::GetValue() const
932 err
= TXNGetDataEncoded( ((TXNObject
) m_macTXN
), kTXNStartOffset
, kTXNEndOffset
, &theText
, kTXNUnicodeTextData
);
940 actualSize
= GetHandleSize( theText
) / sizeof( UniChar
) ;
941 if ( actualSize
> 0 )
944 #if SIZEOF_WCHAR_T == 2
945 ptr
= new wxChar
[actualSize
+ 1 ] ;
946 wxStrncpy( ptr
, (wxChar
*) *theText
, actualSize
) ;
949 SetHandleSize( theText
, ( actualSize
+ 1 ) * sizeof( UniChar
) ) ;
951 (((UniChar
*)*theText
)[actualSize
]) = 0 ;
952 wxMBConvUTF16BE converter
;
953 size_t noChars
= converter
.MB2WC( NULL
, (const char*)*theText
, 0 ) ;
954 ptr
= new wxChar
[noChars
+ 1] ;
956 noChars
= converter
.MB2WC( ptr
, (const char*)*theText
, noChars
) ;
960 ptr
[actualSize
] = 0 ;
961 result
= wxString( ptr
) ;
964 DisposeHandle( theText
) ;
968 err
= TXNGetDataEncoded( ((TXNObject
) m_macTXN
), kTXNStartOffset
, kTXNEndOffset
, &theText
, kTXNTextData
);
976 actualSize
= GetHandleSize( theText
) ;
977 if ( actualSize
> 0 )
980 result
= wxString( *theText
, wxConvLocal
, actualSize
) ;
983 DisposeHandle( theText
) ;
988 CFStringRef value
= NULL
;
989 Size actualSize
= 0 ;
991 verify_noerr( GetControlData( *m_peer
, 0, GetWindowStyle() & wxTE_PASSWORD
?
992 kControlEditTextPasswordCFStringTag
: kControlEditTextCFStringTag
,
993 sizeof(CFStringRef
), &value
, &actualSize
) );
996 wxMacCFStringHolder
cf(value
) ;
997 result
= cf
.AsString() ;
1000 wxMacConvertNewlines10To13( &result
) ;
1004 void wxTextCtrl::GetSelection(long* from
, long* to
) const
1007 TXNGetSelection( (TXNObject
) m_macTXN
, (TXNOffset
*) from
, (TXNOffset
*) to
) ;
1009 ControlEditTextSelectionRec sel
;
1011 verify_noerr( GetControlData( *m_peer
, 0, kControlEditTextSelectionTag
,
1012 sizeof(ControlEditTextSelectionRec
), &sel
, &actualSize
) );
1013 if ( from
) *from
= sel
.selStart
;
1014 if ( to
) *to
= sel
.selEnd
;
1018 void wxTextCtrl::SetValue(const wxString
& str
)
1021 if ( GetValue() == str
)
1025 wxMacConvertNewlines13To10( &st
) ;
1028 wxMacWindowClipper
c( this ) ;
1029 bool formerEditable
= m_editable
;
1030 if ( !formerEditable
)
1033 #if !wxMAC_USE_MLTE_HIVIEW
1034 // otherwise scrolling might have problems ?
1035 TPUpdateVisibility( ( (STPTextPaneVars
*)m_macTXNvars
)->fUserPaneRec
) ;
1037 SetTXNData( (STPTextPaneVars
*)m_macTXNvars
, (TXNObject
) m_macTXN
, st
, kTXNStartOffset
, kTXNEndOffset
) ;
1038 TXNSetSelection( (TXNObject
) m_macTXN
, 0, 0);
1039 TXNShowSelection( (TXNObject
) m_macTXN
, kTXNShowStart
);
1040 if ( !formerEditable
)
1041 SetEditable(formerEditable
) ;
1044 wxMacCFStringHolder
cf(st
, m_font
.GetEncoding() ) ;
1045 CFStringRef value
= cf
;
1046 verify_noerr( SetControlData( *m_peer
, 0, GetWindowStyle() & wxTE_PASSWORD
?
1047 kControlEditTextPasswordCFStringTag
: kControlEditTextCFStringTag
,
1048 sizeof(CFStringRef
), &value
) );
1052 void wxTextCtrl::SetMaxLength(unsigned long len
)
1057 bool wxTextCtrl::SetFont( const wxFont
& font
)
1059 if ( !wxTextCtrlBase::SetFont( font
) )
1063 wxMacWindowClipper
c( this ) ;
1064 bool formerEditable
= m_editable
;
1065 if ( !formerEditable
)
1068 TXNTypeAttributes typeAttr
[4] ;
1069 Str255 fontName
= "\pMonaco" ;
1070 SInt16 fontSize
= 12 ;
1071 Style fontStyle
= normal
;
1072 int attrCounter
= 0 ;
1074 wxMacStringToPascal( font
.GetFaceName() , fontName
) ;
1075 fontSize
= font
.MacGetFontSize() ;
1076 fontStyle
= font
.MacGetFontStyle() ;
1078 typeAttr
[attrCounter
].tag
= kTXNQDFontNameAttribute
;
1079 typeAttr
[attrCounter
].size
= kTXNQDFontNameAttributeSize
;
1080 typeAttr
[attrCounter
].data
.dataPtr
= (void*) fontName
;
1081 typeAttr
[attrCounter
+1].tag
= kTXNQDFontSizeAttribute
;
1082 typeAttr
[attrCounter
+1].size
= kTXNFontSizeAttributeSize
;
1083 typeAttr
[attrCounter
+1].data
.dataValue
= (fontSize
<< 16) ;
1084 typeAttr
[attrCounter
+2].tag
= kTXNQDFontStyleAttribute
;
1085 typeAttr
[attrCounter
+2].size
= kTXNQDFontStyleAttributeSize
;
1086 typeAttr
[attrCounter
+2].data
.dataValue
= fontStyle
;
1089 typeAttr[attrCounter].tag = kTXNQDFontColorAttribute ;
1090 typeAttr[attrCounter].size = kTXNQDFontColorAttributeSize ;
1091 typeAttr[attrCounter].data.dataPtr = (void*) &color ;
1092 color = MAC_WXCOLORREF(GetForegroundColour().GetPixel()) ;
1095 verify_noerr( TXNSetTypeAttributes ((TXNObject
)m_macTXN
, attrCounter
, typeAttr
, kTXNStartOffset
,kTXNEndOffset
) );
1097 if ( !formerEditable
)
1098 SetEditable(formerEditable
) ;
1103 bool wxTextCtrl::SetStyle(long start
, long end
, const wxTextAttr
& style
)
1106 bool formerEditable
= m_editable
;
1107 if ( !formerEditable
)
1109 TXNTypeAttributes typeAttr
[4] ;
1110 Str255 fontName
= "\pMonaco" ;
1111 SInt16 fontSize
= 12 ;
1112 Style fontStyle
= normal
;
1114 int attrCounter
= 0 ;
1115 if ( style
.HasFont() )
1117 const wxFont
&font
= style
.GetFont() ;
1118 wxMacStringToPascal( font
.GetFaceName() , fontName
) ;
1119 fontSize
= font
.GetPointSize() ;
1120 if ( font
.GetUnderlined() )
1121 fontStyle
|= underline
;
1122 if ( font
.GetWeight() == wxBOLD
)
1124 if ( font
.GetStyle() == wxITALIC
)
1125 fontStyle
|= italic
;
1127 typeAttr
[attrCounter
].tag
= kTXNQDFontNameAttribute
;
1128 typeAttr
[attrCounter
].size
= kTXNQDFontNameAttributeSize
;
1129 typeAttr
[attrCounter
].data
.dataPtr
= (void*) fontName
;
1130 typeAttr
[attrCounter
+1].tag
= kTXNQDFontSizeAttribute
;
1131 typeAttr
[attrCounter
+1].size
= kTXNFontSizeAttributeSize
;
1132 typeAttr
[attrCounter
+1].data
.dataValue
= (fontSize
<< 16) ;
1133 typeAttr
[attrCounter
+2].tag
= kTXNQDFontStyleAttribute
;
1134 typeAttr
[attrCounter
+2].size
= kTXNQDFontStyleAttributeSize
;
1135 typeAttr
[attrCounter
+2].data
.dataValue
= fontStyle
;
1139 if ( style
.HasTextColour() )
1141 typeAttr
[attrCounter
].tag
= kTXNQDFontColorAttribute
;
1142 typeAttr
[attrCounter
].size
= kTXNQDFontColorAttributeSize
;
1143 typeAttr
[attrCounter
].data
.dataPtr
= (void*) &color
;
1144 color
= MAC_WXCOLORREF(style
.GetTextColour().GetPixel()) ;
1148 if ( attrCounter
> 0 )
1150 verify_noerr( TXNSetTypeAttributes ((TXNObject
)m_macTXN
, attrCounter
, typeAttr
, start
,end
) );
1152 if ( !formerEditable
)
1153 SetEditable(formerEditable
) ;
1158 bool wxTextCtrl::SetDefaultStyle(const wxTextAttr
& style
)
1160 wxTextCtrlBase::SetDefaultStyle( style
) ;
1161 SetStyle( kTXNUseCurrentSelection
, kTXNUseCurrentSelection
, GetDefaultStyle() ) ;
1165 // Clipboard operations
1166 void wxTextCtrl::Copy()
1171 ClearCurrentScrap();
1172 TXNCopy((TXNObject
)m_macTXN
);
1173 TXNConvertToPublicScrap();
1175 m_peer
->SendHICommand( kHICommandCopy
) ;
1180 void wxTextCtrl::Cut()
1185 ClearCurrentScrap();
1186 TXNCut((TXNObject
)m_macTXN
);
1187 TXNConvertToPublicScrap();
1189 m_peer
->SendHICommand( kHICommandCut
) ;
1191 wxCommandEvent
event(wxEVT_COMMAND_TEXT_UPDATED
, m_windowId
);
1192 event
.SetString( GetValue() ) ;
1193 event
.SetEventObject( this );
1194 GetEventHandler()->ProcessEvent(event
);
1198 void wxTextCtrl::Paste()
1203 TXNConvertFromPublicScrap();
1204 TXNPaste((TXNObject
)m_macTXN
);
1205 SetStyle( kTXNUseCurrentSelection
, kTXNUseCurrentSelection
, GetDefaultStyle() ) ;
1207 m_peer
->SendHICommand( kHICommandPaste
) ;
1209 wxCommandEvent
event(wxEVT_COMMAND_TEXT_UPDATED
, m_windowId
);
1210 event
.SetString( GetValue() ) ;
1211 event
.SetEventObject( this );
1212 GetEventHandler()->ProcessEvent(event
);
1216 bool wxTextCtrl::CanCopy() const
1218 // Can copy if there's a selection
1220 GetSelection(& from
, & to
);
1221 return (from
!= to
);
1224 bool wxTextCtrl::CanCut() const
1226 if ( !IsEditable() )
1230 // Can cut if there's a selection
1232 GetSelection(& from
, & to
);
1233 return (from
!= to
);
1236 bool wxTextCtrl::CanPaste() const
1242 return TXNIsScrapPastable() ;
1248 void wxTextCtrl::SetEditable(bool editable
)
1250 if ( editable
!= m_editable
)
1252 m_editable
= editable
;
1254 TXNControlTag tag
[] = { kTXNIOPrivilegesTag
} ;
1255 TXNControlData data
[] = { { editable
? kTXNReadWrite
: kTXNReadOnly
} } ;
1256 TXNSetTXNObjectControls( (TXNObject
) m_macTXN
, false , sizeof(tag
) / sizeof (TXNControlTag
) , tag
, data
) ;
1258 Boolean value
= !editable
;
1259 ::SetControlData( *m_peer
, 0, kControlEditTextLockedTag
, sizeof( value
) , &value
) ;
1264 void wxTextCtrl::SetInsertionPoint(long pos
)
1266 SetSelection( pos
, pos
) ;
1269 void wxTextCtrl::SetInsertionPointEnd()
1271 long pos
= GetLastPosition();
1272 SetInsertionPoint(pos
);
1275 long wxTextCtrl::GetInsertionPoint() const
1278 GetSelection( &begin
, &end
) ;
1282 long wxTextCtrl::GetLastPosition() const
1284 long actualsize
= 0 ;
1287 OSErr err
= TXNGetDataEncoded( (TXNObject
) m_macTXN
, kTXNStartOffset
, kTXNEndOffset
, &theText
, kTXNTextData
);
1295 actualsize
= GetHandleSize( theText
) ;
1296 DisposeHandle( theText
) ;
1302 void wxTextCtrl::Replace(long from
, long to
, const wxString
& str
)
1305 wxString value
= str
;
1306 wxMacConvertNewlines13To10( &value
) ;
1308 bool formerEditable
= m_editable
;
1309 if ( !formerEditable
)
1311 TXNSetSelection( ((TXNObject
) m_macTXN
) , from
, to
) ;
1312 TXNClear( ((TXNObject
) m_macTXN
) ) ;
1313 SetTXNData( (STPTextPaneVars
*)m_macTXNvars
, (TXNObject
) m_macTXN
, str
, kTXNUseCurrentSelection
, kTXNUseCurrentSelection
) ;
1314 if ( !formerEditable
)
1315 SetEditable( formerEditable
) ;
1321 void wxTextCtrl::Remove(long from
, long to
)
1324 bool formerEditable
= m_editable
;
1325 if ( !formerEditable
)
1327 TXNSetSelection( ((TXNObject
) m_macTXN
) , from
, to
) ;
1328 TXNClear( ((TXNObject
) m_macTXN
) ) ;
1329 if ( !formerEditable
)
1330 SetEditable( formerEditable
) ;
1336 void wxTextCtrl::SetSelection(long from
, long to
)
1339 /* change the selection */
1340 if ((from
== -1) && (to
== -1))
1341 TXNSelectAll((TXNObject
) m_macTXN
);
1343 TXNSetSelection( (TXNObject
) m_macTXN
, from
, to
);
1344 TXNShowSelection( (TXNObject
) m_macTXN
, kTXNShowStart
);
1346 ControlEditTextSelectionRec sel
;
1347 sel
.selStart
= from
;
1349 verify_noerr( SetControlData( *m_peer
, 0, kControlEditTextSelectionTag
,
1350 sizeof(ControlEditTextSelectionRec
), &sel
) );
1355 bool wxTextCtrl::LoadFile(const wxString
& file
)
1357 if ( wxTextCtrlBase::LoadFile(file
) )
1369 virtual ~wxMacFunctor() {}
1370 virtual void* operator()() = 0 ;
1371 static void* CallBackProc(void *param
)
1373 wxMacFunctor
* f
= (wxMacFunctor
*) param
;
1374 void *result
= (*f
)() ;
1379 template<typename classtype
,typename param1type
>
1380 class wxMacObjectFunctor1
: public wxMacFunctor
1382 typedef void (classtype::*function
)( param1type p1
) ;
1383 typedef void (classtype::*ref_function
)( const param1type
& p1
) ;
1385 wxMacObjectFunctor1( classtype
*obj
, function f
, param1type p1
) :
1393 wxMacObjectFunctor1( classtype
*obj
, ref_function f
, param1type p1
) :
1401 ~wxMacObjectFunctor1() {}
1403 virtual void* operator()()
1405 (m_object
->*m_function
)(m_param1
) ;
1409 classtype
* m_object
;
1410 param1type m_param1
;
1413 function m_function
;
1414 ref_function m_refFunction
;
1418 template<typename classtype
, typename param1type
>
1419 void* wxMacMPRemoteCall( classtype
*object
, void (classtype::*function
)( param1type p1
) , param1type p1
)
1421 wxMacObjectFunctor1
<classtype
,param1type
> params(object
,function
,p1
) ;
1423 MPRemoteCall( wxMacFunctor::CallBackProc
, ¶ms
, kMPOwningProcessRemoteContext
) ;
1427 template<typename classtype
, typename param1type
>
1428 void* wxMacMPRemoteCall( classtype
*object
, void (classtype::*function
)( const param1type
& p1
) , param1type p1
)
1430 wxMacObjectFunctor1
<classtype
,param1type
> params(object
,function
,p1
) ;
1432 MPRemoteCall( wxMacFunctor::CallBackProc
, ¶ms
, kMPOwningProcessRemoteContext
) ;
1436 template<typename classtype
, typename param1type
>
1437 void* wxMacMPRemoteGUICall( classtype
*object
, void (classtype::*function
)( param1type p1
) , param1type p1
)
1440 void *result
= wxMacMPRemoteCall( object
, function
, p1
) ;
1445 template<typename classtype
, typename param1type
>
1446 void* wxMacMPRemoteGUICall( classtype
*object
, void (classtype::*function
)( const param1type
& p1
) , param1type p1
)
1449 void *result
= wxMacMPRemoteCall( object
, function
, p1
) ;
1454 void wxTextCtrl::WriteText(const wxString
& str
)
1456 if ( !wxIsMainThread() )
1458 // unfortunately CW 8 is not able to correctly deduce the template types, so we have
1459 // to instantiate explicitely
1460 wxMacMPRemoteGUICall
<wxTextCtrl
,wxString
>( this , &wxTextCtrl::WriteText
, str
) ;
1466 wxMacConvertNewlines13To10( &st
) ;
1468 bool formerEditable
= m_editable
;
1469 if ( !formerEditable
)
1472 wxMacWindowStateSaver
s( this ) ;
1473 long start
, end
, dummy
;
1474 GetSelection( &start
, &dummy
) ;
1475 SetTXNData( (STPTextPaneVars
*)m_macTXNvars
, (TXNObject
) m_macTXN
, st
, kTXNUseCurrentSelection
, kTXNUseCurrentSelection
) ;
1476 GetSelection( &dummy
, &end
) ;
1477 SetStyle( start
, end
, GetDefaultStyle() ) ;
1479 if ( !formerEditable
)
1480 SetEditable( formerEditable
) ;
1482 MacRedrawControl() ;
1484 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
1485 wxMacCFStringHolder
cf(st
, m_font
.GetEncoding() ) ;
1486 CFStringRef value
= cf
;
1487 SetControlData( *m_peer
, 0, kControlEditTextInsertCFStringRefTag
,
1488 sizeof(CFStringRef
), &value
);
1490 wxString val
= GetValue() ;
1492 GetSelection( &start
, &end
) ;
1493 val
.Remove( start
, end
- start
) ;
1494 val
.insert( start
, str
) ;
1496 SetInsertionPoint( start
+ str
.Length() ) ;
1502 void wxTextCtrl::AppendText(const wxString
& text
)
1504 SetInsertionPointEnd();
1508 void wxTextCtrl::Clear()
1511 bool formerEditable
= m_editable
;
1512 if ( !formerEditable
)
1514 TXNSetSelection( (TXNObject
)m_macTXN
, kTXNStartOffset
, kTXNEndOffset
) ;
1515 TXNClear((TXNObject
)m_macTXN
);
1517 if ( !formerEditable
)
1518 SetEditable( formerEditable
) ;
1522 SetValue(wxEmptyString
) ;
1526 bool wxTextCtrl::IsModified() const
1531 bool wxTextCtrl::IsEditable() const
1533 return IsEnabled() && m_editable
;
1536 bool wxTextCtrl::AcceptsFocus() const
1538 // we don't want focus if we can't be edited
1539 return /*IsEditable() && */ wxControl::AcceptsFocus();
1542 wxSize
wxTextCtrl::DoGetBestSize() const
1548 switch( m_windowVariant
)
1550 case wxWINDOW_VARIANT_NORMAL
:
1553 case wxWINDOW_VARIANT_SMALL
:
1556 case wxWINDOW_VARIANT_MINI
:
1565 // unicode text control is using client size, ie 3 pixels on every side
1566 // TODO make this fit into normal window size concept, probably having
1567 // to reintroduce the margin vars
1571 if ( m_windowStyle
& wxTE_MULTILINE
)
1576 return wxSize(wText
, hText
);
1579 // ----------------------------------------------------------------------------
1581 // ----------------------------------------------------------------------------
1583 void wxTextCtrl::Undo()
1588 TXNUndo((TXNObject
)m_macTXN
);
1593 void wxTextCtrl::Redo()
1598 TXNRedo((TXNObject
)m_macTXN
);
1603 bool wxTextCtrl::CanUndo() const
1605 if ( !IsEditable() )
1610 return TXNCanUndo((TXNObject
)m_macTXN
,NULL
);
1616 bool wxTextCtrl::CanRedo() const
1618 if ( !IsEditable() )
1623 return TXNCanRedo((TXNObject
)m_macTXN
,NULL
);
1629 // Makes modifie or unmodified
1630 void wxTextCtrl::MarkDirty()
1635 void wxTextCtrl::DiscardEdits()
1640 int wxTextCtrl::GetNumberOfLines() const
1642 ItemCount lines
= 0 ;
1644 TXNGetLineCount((TXNObject
)m_macTXN
, &lines
) ;
1646 wxString content
= GetValue() ;
1648 for (size_t i
= 0; i
< content
.Length() ; i
++)
1650 if (content
[i
] == '\r') lines
++;
1656 long wxTextCtrl::XYToPosition(long x
, long y
) const
1661 long lastpos
= GetLastPosition() ;
1663 // TODO find a better implementation : while we can get the
1664 // line metrics of a certain line, we don't get its starting
1665 // position, so it would probably be rather a binary search
1666 // for the start position
1669 int lastHeight
= 0 ;
1672 for ( n
= 0 ; n
<= (ItemCount
) lastpos
; ++n
)
1674 if ( y
== ypos
&& x
== xpos
)
1677 TXNOffsetToPoint( (TXNObject
) m_macTXN
, n
, &curpt
);
1679 if ( curpt
.v
> lastHeight
)
1684 lastHeight
= curpt
.v
;
1693 bool wxTextCtrl::PositionToXY(long pos
, long *x
, long *y
) const
1698 long lastpos
= GetLastPosition() ;
1703 if ( pos
<= lastpos
)
1705 // TODO find a better implementation : while we can get the
1706 // line metrics of a certain line, we don't get its starting
1707 // position, so it would probably be rather a binary search
1708 // for the start position
1711 int lastHeight
= 0 ;
1714 for ( n
= 0 ; n
<= (ItemCount
) pos
; ++n
)
1716 TXNOffsetToPoint( (TXNObject
) m_macTXN
, n
, &curpt
);
1718 if ( curpt
.v
> lastHeight
)
1723 lastHeight
= curpt
.v
;
1728 if ( y
) *y
= ypos
;
1729 if ( x
) *x
= xpos
;
1738 void wxTextCtrl::ShowPosition(long pos
)
1741 #if TARGET_RT_MAC_MACHO && defined(AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER)
1745 TXNOffset selstart
, selend
;
1746 TXNGetSelection( (TXNObject
) m_macTXN
, &selstart
, &selend
) ;
1747 TXNOffsetToPoint( (TXNObject
) m_macTXN
, selstart
, ¤t
);
1748 TXNOffsetToPoint( (TXNObject
) m_macTXN
, pos
, &desired
);
1749 //TODO use HIPoints for 10.3 and above
1750 if ( (UInt32
) TXNScroll
!= (UInt32
) kUnresolvedCFragSymbolAddress
)
1752 OSErr theErr
= noErr
;
1753 SInt32 dv
= desired
.v
- current
.v
;
1754 SInt32 dh
= desired
.h
- current
.h
;
1755 TXNShowSelection( (TXNObject
) m_macTXN
, true ) ;
1756 theErr
= TXNScroll( (TXNObject
) m_macTXN
, kTXNScrollUnitsInPixels
, kTXNScrollUnitsInPixels
, &dv
, &dh
);
1757 wxASSERT_MSG( theErr
== noErr
, _T("TXNScroll returned an error!") );
1764 int wxTextCtrl::GetLineLength(long lineNo
) const
1768 if ( lineNo
< GetNumberOfLines() )
1770 // TODO find a better implementation : while we can get the
1771 // line metrics of a certain line, we don't get its starting
1772 // position, so it would probably be rather a binary search
1773 // for the start position
1776 int lastHeight
= 0 ;
1777 long lastpos
= GetLastPosition() ;
1780 for ( n
= 0 ; n
<= (ItemCount
) lastpos
; ++n
)
1782 TXNOffsetToPoint( (TXNObject
) m_macTXN
, n
, &curpt
);
1784 if ( curpt
.v
> lastHeight
)
1786 if ( ypos
== lineNo
)
1792 lastHeight
= curpt
.v
;
1799 // TODO change this if possible to reflect real lines
1800 wxString content
= GetValue() ;
1804 for (size_t i
= 0; i
< content
.Length() ; i
++)
1806 if (count
== lineNo
)
1808 // Count chars in line then
1810 for (size_t j
= i
; j
< content
.Length(); j
++)
1813 if (content
[j
] == '\n') return count
;
1818 if (content
[i
] == '\n') count
++;
1824 wxString
wxTextCtrl::GetLineText(long lineNo
) const
1829 wxString content
= GetValue() ;
1831 if ( lineNo
< GetNumberOfLines() )
1833 // TODO find a better implementation : while we can get the
1834 // line metrics of a certain line, we don't get its starting
1835 // position, so it would probably be rather a binary search
1836 // for the start position
1839 int lastHeight
= 0 ;
1840 long lastpos
= GetLastPosition() ;
1843 for ( n
= 0 ; n
<= (ItemCount
)lastpos
; ++n
)
1845 TXNOffsetToPoint( (TXNObject
) m_macTXN
, n
, &curpt
);
1847 if ( curpt
.v
> lastHeight
)
1849 if ( ypos
== lineNo
)
1855 lastHeight
= curpt
.v
;
1859 if ( ypos
== lineNo
)
1860 line
+= content
[n
] ;
1867 // TODO change this if possible to reflect real lines
1868 wxString content
= GetValue() ;
1872 for (size_t i
= 0; i
< content
.Length() ; i
++)
1874 if (count
== lineNo
)
1876 // Add chars in line then
1879 for (size_t j
= i
; j
< content
.Length(); j
++)
1881 if (content
[j
] == '\n')
1889 if (content
[i
] == '\n') count
++;
1891 return wxEmptyString
;
1899 void wxTextCtrl::Command(wxCommandEvent
& event
)
1901 SetValue (event
.GetString());
1902 ProcessCommand (event
);
1905 void wxTextCtrl::OnDropFiles(wxDropFilesEvent
& event
)
1907 // By default, load the first file into the text window.
1908 if (event
.GetNumberOfFiles() > 0)
1910 LoadFile(event
.GetFiles()[0]);
1914 void wxTextCtrl::OnChar(wxKeyEvent
& event
)
1916 int key
= event
.GetKeyCode() ;
1917 bool eat_key
= false ;
1919 if ( key
== 'c' && event
.MetaDown() )
1926 if ( !IsEditable() && key
!= WXK_LEFT
&& key
!= WXK_RIGHT
&& key
!= WXK_DOWN
&& key
!= WXK_UP
&& key
!= WXK_TAB
&&
1927 !( key
== WXK_RETURN
&& ( (m_windowStyle
& wxPROCESS_ENTER
) || (m_windowStyle
& wxTE_MULTILINE
) ) )
1928 /* && key != WXK_PRIOR && key != WXK_NEXT && key != WXK_HOME && key != WXK_END */
1935 // assume that any key not processed yet is going to modify the control
1938 if ( key
== 'v' && event
.MetaDown() )
1944 if ( key
== 'x' && event
.MetaDown() )
1953 if (m_windowStyle
& wxPROCESS_ENTER
)
1955 wxCommandEvent
event(wxEVT_COMMAND_TEXT_ENTER
, m_windowId
);
1956 event
.SetEventObject( this );
1957 event
.SetString( GetValue() );
1958 if ( GetEventHandler()->ProcessEvent(event
) )
1961 if ( !(m_windowStyle
& wxTE_MULTILINE
) )
1963 wxWindow
*parent
= GetParent();
1964 while( parent
&& !parent
->IsTopLevel() && parent
->GetDefaultItem() == NULL
) {
1965 parent
= parent
->GetParent() ;
1967 if ( parent
&& parent
->GetDefaultItem() )
1969 wxButton
*def
= wxDynamicCast(parent
->GetDefaultItem(),
1971 if ( def
&& def
->IsEnabled() )
1973 wxCommandEvent
event(wxEVT_COMMAND_BUTTON_CLICKED
, def
->GetId() );
1974 event
.SetEventObject(def
);
1975 def
->Command(event
);
1980 // this will make wxWidgets eat the ENTER key so that
1981 // we actually prevent line wrapping in a single line
1989 // always produce navigation event - even if we process TAB
1990 // ourselves the fact that we got here means that the user code
1991 // decided to skip processing of this TAB - probably to let it
1992 // do its default job.
1994 wxNavigationKeyEvent eventNav
;
1995 eventNav
.SetDirection(!event
.ShiftDown());
1996 eventNav
.SetWindowChange(event
.ControlDown());
1997 eventNav
.SetEventObject(this);
1999 if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav
) )
2010 // perform keystroke handling
2011 if ( wxTheApp
->MacGetCurrentEvent() != NULL
&& wxTheApp
->MacGetCurrentEventHandlerCallRef() != NULL
)
2012 CallNextEventHandler((EventHandlerCallRef
)wxTheApp
->MacGetCurrentEventHandlerCallRef() , (EventRef
) wxTheApp
->MacGetCurrentEvent() ) ;
2016 if ( wxMacConvertEventToRecord( (EventRef
) wxTheApp
->MacGetCurrentEvent() , &rec
) )
2018 EventRecord
*ev
= &rec
;
2021 keychar
= short(ev
->message
& charCodeMask
);
2022 keycode
= short(ev
->message
& keyCodeMask
) >> 8 ;
2024 ::HandleControlKey( *m_peer
, keycode
, keychar
, ev
->modifiers
) ;
2028 if ( ( key
>= 0x20 && key
< WXK_START
) ||
2029 key
== WXK_RETURN
||
2030 key
== WXK_DELETE
||
2033 wxCommandEvent
event1(wxEVT_COMMAND_TEXT_UPDATED
, m_windowId
);
2034 event1
.SetString( GetValue() ) ;
2035 event1
.SetEventObject( this );
2036 wxPostEvent(GetEventHandler(),event1
);
2040 // ----------------------------------------------------------------------------
2041 // standard handlers for standard edit menu events
2042 // ----------------------------------------------------------------------------
2044 void wxTextCtrl::OnCut(wxCommandEvent
& WXUNUSED(event
))
2049 void wxTextCtrl::OnCopy(wxCommandEvent
& WXUNUSED(event
))
2054 void wxTextCtrl::OnPaste(wxCommandEvent
& WXUNUSED(event
))
2059 void wxTextCtrl::OnUndo(wxCommandEvent
& WXUNUSED(event
))
2064 void wxTextCtrl::OnRedo(wxCommandEvent
& WXUNUSED(event
))
2069 void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent
& event
)
2071 event
.Enable( CanCut() );
2074 void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent
& event
)
2076 event
.Enable( CanCopy() );
2079 void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent
& event
)
2081 event
.Enable( CanPaste() );
2084 void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent
& event
)
2086 event
.Enable( CanUndo() );
2089 void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent
& event
)
2091 event
.Enable( CanRedo() );
2094 bool wxTextCtrl::MacSetupCursor( const wxPoint
& pt
)
2099 // user pane implementation
2101 void wxTextCtrl::MacControlUserPaneDrawProc(wxInt16 part
)
2105 wxInt16
wxTextCtrl::MacControlUserPaneHitTestProc(wxInt16 x
, wxInt16 y
)
2107 return kControlNoPart
;
2110 wxInt16
wxTextCtrl::MacControlUserPaneTrackingProc(wxInt16 x
, wxInt16 y
, void* actionProc
)
2112 return kControlNoPart
;
2115 void wxTextCtrl::MacControlUserPaneIdleProc()
2119 wxInt16
wxTextCtrl::MacControlUserPaneKeyDownProc(wxInt16 keyCode
, wxInt16 charCode
, wxInt16 modifiers
)
2121 return kControlNoPart
;
2124 void wxTextCtrl::MacControlUserPaneActivateProc(bool activating
)
2128 wxInt16
wxTextCtrl::MacControlUserPaneFocusProc(wxInt16 action
)
2130 return kControlNoPart
;
2133 void wxTextCtrl::MacControlUserPaneBackgroundProc(void* info
)