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
) );
822 wxMacWindowClipper
c(this) ;
823 STPTextPaneVars
*varsp
;
824 mUPOpenControl( varsp
, *m_peer
, m_windowStyle
);
825 m_macTXNvars
= varsp
;
826 m_macTXN
= varsp
->fTXNRec
;
829 if ( style
& wxTE_PASSWORD
)
832 verify_noerr(TXNEchoMode( (TXNObject
) m_macTXN
, c
, 0 , true )) ;
835 MacPostControlCreate(pos
,size
) ;
837 #if !wxMAC_USE_MLTE_HIVIEW
838 if ( MacIsReallyShown() )
839 MLTESetObjectVisibility( (STPTextPaneVars
*) m_macTXNvars
, true , GetWindowStyle() ) ;
843 wxMacWindowClipper
clipper( this ) ;
844 #if !wxMAC_USE_MLTE_HIVIEW
845 TPUpdateVisibility( *m_peer
) ;
847 SetTXNData( (STPTextPaneVars
*)m_macTXNvars
, (TXNObject
) m_macTXN
, st
, kTXNStartOffset
, kTXNEndOffset
) ;
849 TXNSetSelection( (TXNObject
) m_macTXN
, 0, 0);
850 TXNShowSelection( (TXNObject
) m_macTXN
, kTXNShowStart
);
853 // in case MLTE is catching events before we get the chance to do so, we'd have to reintroduce the tlw-handler in front :
854 // parent->MacGetTopLevelWindow()->MacInstallTopLevelWindowEventHandler() ;
856 SetBackgroundColour( *wxWHITE
) ;
859 tback
.bgType
= kTXNBackgroundTypeRGB
;
860 tback
.bg
.color
= MAC_WXCOLORREF( GetBackgroundColour().GetPixel() );
861 TXNSetBackground( (TXNObject
) m_macTXN
, &tback
);
864 wxMacCFStringHolder
cf(st
, m_font
.GetEncoding()) ;
865 CFStringRef cfr
= cf
;
866 Boolean isPassword
= ( m_windowStyle
& wxTE_PASSWORD
) != 0 ;
867 m_peer
= new wxMacControl() ;
868 CreateEditUnicodeTextControl( MAC_WXHWND(parent
->MacGetTopLevelWindowRef()), &bounds
, cfr
, isPassword
, NULL
, *m_peer
) ;
870 if ( !(m_windowStyle
& wxTE_MULTILINE
) )
872 Boolean singleline
= true ;
873 ::SetControlData( *m_peer
, kControlEditTextPart
, kControlEditTextSingleLineTag
, sizeof( singleline
) , &singleline
) ;
875 MacPostControlCreate(pos
,size
) ;
878 if ( m_windowStyle
& wxTE_READONLY
)
880 SetEditable( false ) ;
887 void wxTextCtrl::MacVisibilityChanged()
890 #if !wxMAC_USE_MLTE_HIVIEW
891 MLTESetObjectVisibility((STPTextPaneVars
*) m_macTXNvars
, MacIsReallyShown() , GetWindowStyle() ) ;
892 if ( !MacIsReallyShown() )
893 InvalWindowRect( GetControlOwner( *m_peer
) , &((STPTextPaneVars
*)m_macTXNvars
)->fRBounds
) ;
896 if ( !(m_windowStyle
& wxTE_MULTILINE
) && MacIsReallyShown() )
898 // work around a refresh issue insofar as not always the entire content is shown even if this would be possible
899 ControlEditTextSelectionRec sel
;
900 CFStringRef value
= NULL
;
901 Size actualSize
= 0 ;
902 ResType datatag
= GetWindowStyle() & wxTE_PASSWORD
?
903 kControlEditTextPasswordCFStringTag
: kControlEditTextCFStringTag
;
905 verify_noerr( GetControlData( *m_peer
, 0, kControlEditTextSelectionTag
,
906 sizeof(ControlEditTextSelectionRec
), &sel
, &actualSize
) );
907 verify_noerr( GetControlData( *m_peer
, 0, datatag
, sizeof(CFStringRef
), &value
, &actualSize
) );
909 verify_noerr( SetControlData( *m_peer
, 0, datatag
, sizeof(CFStringRef
), &value
) );
910 verify_noerr( SetControlData( *m_peer
, 0, kControlEditTextSelectionTag
, sizeof(ControlEditTextSelectionRec
), &sel
) );
917 void wxTextCtrl::MacEnabledStateChanged()
922 wxString
wxTextCtrl::GetValue() const
931 err
= TXNGetDataEncoded( ((TXNObject
) m_macTXN
), kTXNStartOffset
, kTXNEndOffset
, &theText
, kTXNUnicodeTextData
);
939 actualSize
= GetHandleSize( theText
) / sizeof( UniChar
) ;
940 if ( actualSize
> 0 )
943 #if SIZEOF_WCHAR_T == 2
944 ptr
= new wxChar
[actualSize
+ 1 ] ;
945 wxStrncpy( ptr
, (wxChar
*) *theText
, actualSize
) ;
948 SetHandleSize( theText
, ( actualSize
+ 1 ) * sizeof( UniChar
) ) ;
950 (((UniChar
*)*theText
)[actualSize
]) = 0 ;
951 wxMBConvUTF16BE converter
;
952 size_t noChars
= converter
.MB2WC( NULL
, (const char*)*theText
, 0 ) ;
953 ptr
= new wxChar
[noChars
+ 1] ;
955 noChars
= converter
.MB2WC( ptr
, (const char*)*theText
, noChars
) ;
959 ptr
[actualSize
] = 0 ;
960 result
= wxString( ptr
) ;
963 DisposeHandle( theText
) ;
967 err
= TXNGetDataEncoded( ((TXNObject
) m_macTXN
), kTXNStartOffset
, kTXNEndOffset
, &theText
, kTXNTextData
);
975 actualSize
= GetHandleSize( theText
) ;
976 if ( actualSize
> 0 )
979 result
= wxString( *theText
, wxConvLocal
, actualSize
) ;
982 DisposeHandle( theText
) ;
987 CFStringRef value
= NULL
;
988 Size actualSize
= 0 ;
990 verify_noerr( GetControlData( *m_peer
, 0, GetWindowStyle() & wxTE_PASSWORD
?
991 kControlEditTextPasswordCFStringTag
: kControlEditTextCFStringTag
,
992 sizeof(CFStringRef
), &value
, &actualSize
) );
995 wxMacCFStringHolder
cf(value
) ;
996 result
= cf
.AsString() ;
999 wxMacConvertNewlines10To13( &result
) ;
1003 void wxTextCtrl::GetSelection(long* from
, long* to
) const
1006 TXNGetSelection( (TXNObject
) m_macTXN
, (TXNOffset
*) from
, (TXNOffset
*) to
) ;
1008 ControlEditTextSelectionRec sel
;
1010 verify_noerr( GetControlData( *m_peer
, 0, kControlEditTextSelectionTag
,
1011 sizeof(ControlEditTextSelectionRec
), &sel
, &actualSize
) );
1012 if ( from
) *from
= sel
.selStart
;
1013 if ( to
) *to
= sel
.selEnd
;
1017 void wxTextCtrl::SetValue(const wxString
& str
)
1020 if ( GetValue() == str
)
1024 wxMacConvertNewlines13To10( &st
) ;
1027 wxMacWindowClipper
c( this ) ;
1028 bool formerEditable
= m_editable
;
1029 if ( !formerEditable
)
1032 #if !wxMAC_USE_MLTE_HIVIEW
1033 // otherwise scrolling might have problems ?
1034 TPUpdateVisibility( ( (STPTextPaneVars
*)m_macTXNvars
)->fUserPaneRec
) ;
1036 SetTXNData( (STPTextPaneVars
*)m_macTXNvars
, (TXNObject
) m_macTXN
, st
, kTXNStartOffset
, kTXNEndOffset
) ;
1037 TXNSetSelection( (TXNObject
) m_macTXN
, 0, 0);
1038 TXNShowSelection( (TXNObject
) m_macTXN
, kTXNShowStart
);
1039 if ( !formerEditable
)
1040 SetEditable(formerEditable
) ;
1043 wxMacCFStringHolder
cf(st
, m_font
.GetEncoding() ) ;
1044 CFStringRef value
= cf
;
1045 verify_noerr( SetControlData( *m_peer
, 0, GetWindowStyle() & wxTE_PASSWORD
?
1046 kControlEditTextPasswordCFStringTag
: kControlEditTextCFStringTag
,
1047 sizeof(CFStringRef
), &value
) );
1051 void wxTextCtrl::SetMaxLength(unsigned long len
)
1056 bool wxTextCtrl::SetFont( const wxFont
& font
)
1058 if ( !wxTextCtrlBase::SetFont( font
) )
1062 wxMacWindowClipper
c( this ) ;
1063 bool formerEditable
= m_editable
;
1064 if ( !formerEditable
)
1067 TXNTypeAttributes typeAttr
[4] ;
1068 Str255 fontName
= "\pMonaco" ;
1069 SInt16 fontSize
= 12 ;
1070 Style fontStyle
= normal
;
1071 int attrCounter
= 0 ;
1073 wxMacStringToPascal( font
.GetFaceName() , fontName
) ;
1074 fontSize
= font
.MacGetFontSize() ;
1075 fontStyle
= font
.MacGetFontStyle() ;
1077 typeAttr
[attrCounter
].tag
= kTXNQDFontNameAttribute
;
1078 typeAttr
[attrCounter
].size
= kTXNQDFontNameAttributeSize
;
1079 typeAttr
[attrCounter
].data
.dataPtr
= (void*) fontName
;
1080 typeAttr
[attrCounter
+1].tag
= kTXNQDFontSizeAttribute
;
1081 typeAttr
[attrCounter
+1].size
= kTXNFontSizeAttributeSize
;
1082 typeAttr
[attrCounter
+1].data
.dataValue
= (fontSize
<< 16) ;
1083 typeAttr
[attrCounter
+2].tag
= kTXNQDFontStyleAttribute
;
1084 typeAttr
[attrCounter
+2].size
= kTXNQDFontStyleAttributeSize
;
1085 typeAttr
[attrCounter
+2].data
.dataValue
= fontStyle
;
1088 typeAttr[attrCounter].tag = kTXNQDFontColorAttribute ;
1089 typeAttr[attrCounter].size = kTXNQDFontColorAttributeSize ;
1090 typeAttr[attrCounter].data.dataPtr = (void*) &color ;
1091 color = MAC_WXCOLORREF(GetForegroundColour().GetPixel()) ;
1094 verify_noerr( TXNSetTypeAttributes ((TXNObject
)m_macTXN
, attrCounter
, typeAttr
, kTXNStartOffset
,kTXNEndOffset
) );
1096 if ( !formerEditable
)
1097 SetEditable(formerEditable
) ;
1102 bool wxTextCtrl::SetStyle(long start
, long end
, const wxTextAttr
& style
)
1105 bool formerEditable
= m_editable
;
1106 if ( !formerEditable
)
1108 TXNTypeAttributes typeAttr
[4] ;
1109 Str255 fontName
= "\pMonaco" ;
1110 SInt16 fontSize
= 12 ;
1111 Style fontStyle
= normal
;
1113 int attrCounter
= 0 ;
1114 if ( style
.HasFont() )
1116 const wxFont
&font
= style
.GetFont() ;
1117 wxMacStringToPascal( font
.GetFaceName() , fontName
) ;
1118 fontSize
= font
.GetPointSize() ;
1119 if ( font
.GetUnderlined() )
1120 fontStyle
|= underline
;
1121 if ( font
.GetWeight() == wxBOLD
)
1123 if ( font
.GetStyle() == wxITALIC
)
1124 fontStyle
|= italic
;
1126 typeAttr
[attrCounter
].tag
= kTXNQDFontNameAttribute
;
1127 typeAttr
[attrCounter
].size
= kTXNQDFontNameAttributeSize
;
1128 typeAttr
[attrCounter
].data
.dataPtr
= (void*) fontName
;
1129 typeAttr
[attrCounter
+1].tag
= kTXNQDFontSizeAttribute
;
1130 typeAttr
[attrCounter
+1].size
= kTXNFontSizeAttributeSize
;
1131 typeAttr
[attrCounter
+1].data
.dataValue
= (fontSize
<< 16) ;
1132 typeAttr
[attrCounter
+2].tag
= kTXNQDFontStyleAttribute
;
1133 typeAttr
[attrCounter
+2].size
= kTXNQDFontStyleAttributeSize
;
1134 typeAttr
[attrCounter
+2].data
.dataValue
= fontStyle
;
1138 if ( style
.HasTextColour() )
1140 typeAttr
[attrCounter
].tag
= kTXNQDFontColorAttribute
;
1141 typeAttr
[attrCounter
].size
= kTXNQDFontColorAttributeSize
;
1142 typeAttr
[attrCounter
].data
.dataPtr
= (void*) &color
;
1143 color
= MAC_WXCOLORREF(style
.GetTextColour().GetPixel()) ;
1147 if ( attrCounter
> 0 )
1149 verify_noerr( TXNSetTypeAttributes ((TXNObject
)m_macTXN
, attrCounter
, typeAttr
, start
,end
) );
1151 if ( !formerEditable
)
1152 SetEditable(formerEditable
) ;
1157 bool wxTextCtrl::SetDefaultStyle(const wxTextAttr
& style
)
1159 wxTextCtrlBase::SetDefaultStyle( style
) ;
1160 SetStyle( kTXNUseCurrentSelection
, kTXNUseCurrentSelection
, GetDefaultStyle() ) ;
1164 // Clipboard operations
1165 void wxTextCtrl::Copy()
1170 ClearCurrentScrap();
1171 TXNCopy((TXNObject
)m_macTXN
);
1172 TXNConvertToPublicScrap();
1174 m_peer
->SendHICommand( kHICommandCopy
) ;
1179 void wxTextCtrl::Cut()
1184 ClearCurrentScrap();
1185 TXNCut((TXNObject
)m_macTXN
);
1186 TXNConvertToPublicScrap();
1188 m_peer
->SendHICommand( kHICommandCut
) ;
1190 wxCommandEvent
event(wxEVT_COMMAND_TEXT_UPDATED
, m_windowId
);
1191 event
.SetString( GetValue() ) ;
1192 event
.SetEventObject( this );
1193 GetEventHandler()->ProcessEvent(event
);
1197 void wxTextCtrl::Paste()
1202 TXNConvertFromPublicScrap();
1203 TXNPaste((TXNObject
)m_macTXN
);
1204 SetStyle( kTXNUseCurrentSelection
, kTXNUseCurrentSelection
, GetDefaultStyle() ) ;
1206 m_peer
->SendHICommand( kHICommandPaste
) ;
1208 wxCommandEvent
event(wxEVT_COMMAND_TEXT_UPDATED
, m_windowId
);
1209 event
.SetString( GetValue() ) ;
1210 event
.SetEventObject( this );
1211 GetEventHandler()->ProcessEvent(event
);
1215 bool wxTextCtrl::CanCopy() const
1217 // Can copy if there's a selection
1219 GetSelection(& from
, & to
);
1220 return (from
!= to
);
1223 bool wxTextCtrl::CanCut() const
1225 if ( !IsEditable() )
1229 // Can cut if there's a selection
1231 GetSelection(& from
, & to
);
1232 return (from
!= to
);
1235 bool wxTextCtrl::CanPaste() const
1241 return TXNIsScrapPastable() ;
1247 void wxTextCtrl::SetEditable(bool editable
)
1249 if ( editable
!= m_editable
)
1251 m_editable
= editable
;
1253 TXNControlTag tag
[] = { kTXNIOPrivilegesTag
} ;
1254 TXNControlData data
[] = { { editable
? kTXNReadWrite
: kTXNReadOnly
} } ;
1255 TXNSetTXNObjectControls( (TXNObject
) m_macTXN
, false , sizeof(tag
) / sizeof (TXNControlTag
) , tag
, data
) ;
1257 Boolean value
= !editable
;
1258 ::SetControlData( *m_peer
, 0, kControlEditTextLockedTag
, sizeof( value
) , &value
) ;
1263 void wxTextCtrl::SetInsertionPoint(long pos
)
1265 SetSelection( pos
, pos
) ;
1268 void wxTextCtrl::SetInsertionPointEnd()
1270 long pos
= GetLastPosition();
1271 SetInsertionPoint(pos
);
1274 long wxTextCtrl::GetInsertionPoint() const
1277 GetSelection( &begin
, &end
) ;
1281 long wxTextCtrl::GetLastPosition() const
1283 long actualsize
= 0 ;
1286 OSErr err
= TXNGetDataEncoded( (TXNObject
) m_macTXN
, kTXNStartOffset
, kTXNEndOffset
, &theText
, kTXNTextData
);
1294 actualsize
= GetHandleSize( theText
) ;
1295 DisposeHandle( theText
) ;
1301 void wxTextCtrl::Replace(long from
, long to
, const wxString
& str
)
1304 wxString value
= str
;
1305 wxMacConvertNewlines13To10( &value
) ;
1307 bool formerEditable
= m_editable
;
1308 if ( !formerEditable
)
1310 TXNSetSelection( ((TXNObject
) m_macTXN
) , from
, to
) ;
1311 TXNClear( ((TXNObject
) m_macTXN
) ) ;
1312 SetTXNData( (STPTextPaneVars
*)m_macTXNvars
, (TXNObject
) m_macTXN
, str
, kTXNUseCurrentSelection
, kTXNUseCurrentSelection
) ;
1313 if ( !formerEditable
)
1314 SetEditable( formerEditable
) ;
1320 void wxTextCtrl::Remove(long from
, long to
)
1323 bool formerEditable
= m_editable
;
1324 if ( !formerEditable
)
1326 TXNSetSelection( ((TXNObject
) m_macTXN
) , from
, to
) ;
1327 TXNClear( ((TXNObject
) m_macTXN
) ) ;
1328 if ( !formerEditable
)
1329 SetEditable( formerEditable
) ;
1335 void wxTextCtrl::SetSelection(long from
, long to
)
1338 /* change the selection */
1339 if ((from
== -1) && (to
== -1))
1340 TXNSelectAll((TXNObject
) m_macTXN
);
1342 TXNSetSelection( (TXNObject
) m_macTXN
, from
, to
);
1343 TXNShowSelection( (TXNObject
) m_macTXN
, kTXNShowStart
);
1345 ControlEditTextSelectionRec sel
;
1346 sel
.selStart
= from
;
1348 verify_noerr( SetControlData( *m_peer
, 0, kControlEditTextSelectionTag
,
1349 sizeof(ControlEditTextSelectionRec
), &sel
) );
1354 bool wxTextCtrl::LoadFile(const wxString
& file
)
1356 if ( wxTextCtrlBase::LoadFile(file
) )
1368 virtual ~wxMacFunctor() {}
1369 virtual void* operator()() = 0 ;
1370 static void* CallBackProc(void *param
)
1372 wxMacFunctor
* f
= (wxMacFunctor
*) param
;
1373 void *result
= (*f
)() ;
1378 template<typename classtype
,typename param1type
>
1379 class wxMacObjectFunctor1
: public wxMacFunctor
1381 typedef void (classtype::*function
)( param1type p1
) ;
1382 typedef void (classtype::*ref_function
)( const param1type
& p1
) ;
1384 wxMacObjectFunctor1( classtype
*obj
, function f
, param1type p1
) :
1392 wxMacObjectFunctor1( classtype
*obj
, ref_function f
, param1type p1
) :
1400 ~wxMacObjectFunctor1() {}
1402 virtual void* operator()()
1404 (m_object
->*m_function
)(m_param1
) ;
1408 classtype
* m_object
;
1409 param1type m_param1
;
1412 function m_function
;
1413 ref_function m_refFunction
;
1417 template<typename classtype
, typename param1type
>
1418 void* wxMacMPRemoteCall( classtype
*object
, void (classtype::*function
)( param1type p1
) , param1type p1
)
1420 wxMacObjectFunctor1
<classtype
,param1type
> params(object
,function
,p1
) ;
1422 MPRemoteCall( wxMacFunctor::CallBackProc
, ¶ms
, kMPOwningProcessRemoteContext
) ;
1426 template<typename classtype
, typename param1type
>
1427 void* wxMacMPRemoteCall( classtype
*object
, void (classtype::*function
)( const param1type
& p1
) , param1type p1
)
1429 wxMacObjectFunctor1
<classtype
,param1type
> params(object
,function
,p1
) ;
1431 MPRemoteCall( wxMacFunctor::CallBackProc
, ¶ms
, kMPOwningProcessRemoteContext
) ;
1435 template<typename classtype
, typename param1type
>
1436 void* wxMacMPRemoteGUICall( classtype
*object
, void (classtype::*function
)( param1type p1
) , param1type p1
)
1439 void *result
= wxMacMPRemoteCall( object
, function
, p1
) ;
1444 template<typename classtype
, typename param1type
>
1445 void* wxMacMPRemoteGUICall( classtype
*object
, void (classtype::*function
)( const param1type
& p1
) , param1type p1
)
1448 void *result
= wxMacMPRemoteCall( object
, function
, p1
) ;
1453 void wxTextCtrl::WriteText(const wxString
& str
)
1455 if ( !wxIsMainThread() )
1457 // unfortunately CW 8 is not able to correctly deduce the template types, so we have
1458 // to instantiate explicitely
1459 wxMacMPRemoteGUICall
<wxTextCtrl
,wxString
>( this , &wxTextCtrl::WriteText
, str
) ;
1465 wxMacConvertNewlines13To10( &st
) ;
1467 bool formerEditable
= m_editable
;
1468 if ( !formerEditable
)
1471 wxMacWindowStateSaver
s( this ) ;
1472 long start
, end
, dummy
;
1473 GetSelection( &start
, &dummy
) ;
1474 SetTXNData( (STPTextPaneVars
*)m_macTXNvars
, (TXNObject
) m_macTXN
, st
, kTXNUseCurrentSelection
, kTXNUseCurrentSelection
) ;
1475 GetSelection( &dummy
, &end
) ;
1476 SetStyle( start
, end
, GetDefaultStyle() ) ;
1478 if ( !formerEditable
)
1479 SetEditable( formerEditable
) ;
1481 MacRedrawControl() ;
1483 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
1484 wxMacCFStringHolder
cf(st
, m_font
.GetEncoding() ) ;
1485 CFStringRef value
= cf
;
1486 SetControlData( *m_peer
, 0, kControlEditTextInsertCFStringRefTag
,
1487 sizeof(CFStringRef
), &value
);
1489 wxString val
= GetValue() ;
1491 GetSelection( &start
, &end
) ;
1492 val
.Remove( start
, end
- start
) ;
1493 val
.insert( start
, str
) ;
1495 SetInsertionPoint( start
+ str
.Length() ) ;
1501 void wxTextCtrl::AppendText(const wxString
& text
)
1503 SetInsertionPointEnd();
1507 void wxTextCtrl::Clear()
1510 bool formerEditable
= m_editable
;
1511 if ( !formerEditable
)
1513 TXNSetSelection( (TXNObject
)m_macTXN
, kTXNStartOffset
, kTXNEndOffset
) ;
1514 TXNClear((TXNObject
)m_macTXN
);
1516 if ( !formerEditable
)
1517 SetEditable( formerEditable
) ;
1521 SetValue(wxEmptyString
) ;
1525 bool wxTextCtrl::IsModified() const
1530 bool wxTextCtrl::IsEditable() const
1532 return IsEnabled() && m_editable
;
1535 bool wxTextCtrl::AcceptsFocus() const
1537 // we don't want focus if we can't be edited
1538 return /*IsEditable() && */ wxControl::AcceptsFocus();
1541 wxSize
wxTextCtrl::DoGetBestSize() const
1547 switch( m_windowVariant
)
1549 case wxWINDOW_VARIANT_NORMAL
:
1552 case wxWINDOW_VARIANT_SMALL
:
1555 case wxWINDOW_VARIANT_MINI
:
1564 // unicode text control is using client size, ie 3 pixels on every side
1565 // TODO make this fit into normal window size concept, probably having
1566 // to reintroduce the margin vars
1570 if ( m_windowStyle
& wxTE_MULTILINE
)
1575 return wxSize(wText
, hText
);
1578 // ----------------------------------------------------------------------------
1580 // ----------------------------------------------------------------------------
1582 void wxTextCtrl::Undo()
1587 TXNUndo((TXNObject
)m_macTXN
);
1592 void wxTextCtrl::Redo()
1597 TXNRedo((TXNObject
)m_macTXN
);
1602 bool wxTextCtrl::CanUndo() const
1604 if ( !IsEditable() )
1609 return TXNCanUndo((TXNObject
)m_macTXN
,NULL
);
1615 bool wxTextCtrl::CanRedo() const
1617 if ( !IsEditable() )
1622 return TXNCanRedo((TXNObject
)m_macTXN
,NULL
);
1628 // Makes modifie or unmodified
1629 void wxTextCtrl::MarkDirty()
1634 void wxTextCtrl::DiscardEdits()
1639 int wxTextCtrl::GetNumberOfLines() const
1641 ItemCount lines
= 0 ;
1643 TXNGetLineCount((TXNObject
)m_macTXN
, &lines
) ;
1645 wxString content
= GetValue() ;
1647 for (size_t i
= 0; i
< content
.Length() ; i
++)
1649 if (content
[i
] == '\r') lines
++;
1655 long wxTextCtrl::XYToPosition(long x
, long y
) const
1660 long lastpos
= GetLastPosition() ;
1662 // TODO find a better implementation : while we can get the
1663 // line metrics of a certain line, we don't get its starting
1664 // position, so it would probably be rather a binary search
1665 // for the start position
1668 int lastHeight
= 0 ;
1671 for ( n
= 0 ; n
<= (ItemCount
) lastpos
; ++n
)
1673 if ( y
== ypos
&& x
== xpos
)
1676 TXNOffsetToPoint( (TXNObject
) m_macTXN
, n
, &curpt
);
1678 if ( curpt
.v
> lastHeight
)
1683 lastHeight
= curpt
.v
;
1692 bool wxTextCtrl::PositionToXY(long pos
, long *x
, long *y
) const
1697 long lastpos
= GetLastPosition() ;
1702 if ( pos
<= lastpos
)
1704 // TODO find a better implementation : while we can get the
1705 // line metrics of a certain line, we don't get its starting
1706 // position, so it would probably be rather a binary search
1707 // for the start position
1710 int lastHeight
= 0 ;
1713 for ( n
= 0 ; n
<= (ItemCount
) pos
; ++n
)
1715 TXNOffsetToPoint( (TXNObject
) m_macTXN
, n
, &curpt
);
1717 if ( curpt
.v
> lastHeight
)
1722 lastHeight
= curpt
.v
;
1727 if ( y
) *y
= ypos
;
1728 if ( x
) *x
= xpos
;
1737 void wxTextCtrl::ShowPosition(long pos
)
1740 #if TARGET_RT_MAC_MACHO && defined(AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER)
1744 TXNOffset selstart
, selend
;
1745 TXNGetSelection( (TXNObject
) m_macTXN
, &selstart
, &selend
) ;
1746 TXNOffsetToPoint( (TXNObject
) m_macTXN
, selstart
, ¤t
);
1747 TXNOffsetToPoint( (TXNObject
) m_macTXN
, pos
, &desired
);
1748 //TODO use HIPoints for 10.3 and above
1749 if ( (UInt32
) TXNScroll
!= (UInt32
) kUnresolvedCFragSymbolAddress
)
1751 OSErr theErr
= noErr
;
1752 SInt32 dv
= desired
.v
- current
.v
;
1753 SInt32 dh
= desired
.h
- current
.h
;
1754 TXNShowSelection( (TXNObject
) m_macTXN
, true ) ;
1755 theErr
= TXNScroll( (TXNObject
) m_macTXN
, kTXNScrollUnitsInPixels
, kTXNScrollUnitsInPixels
, &dv
, &dh
);
1756 wxASSERT_MSG( theErr
== noErr
, _T("TXNScroll returned an error!") );
1763 int wxTextCtrl::GetLineLength(long lineNo
) const
1767 if ( lineNo
< GetNumberOfLines() )
1769 // TODO find a better implementation : while we can get the
1770 // line metrics of a certain line, we don't get its starting
1771 // position, so it would probably be rather a binary search
1772 // for the start position
1775 int lastHeight
= 0 ;
1776 long lastpos
= GetLastPosition() ;
1779 for ( n
= 0 ; n
<= (ItemCount
) lastpos
; ++n
)
1781 TXNOffsetToPoint( (TXNObject
) m_macTXN
, n
, &curpt
);
1783 if ( curpt
.v
> lastHeight
)
1785 if ( ypos
== lineNo
)
1791 lastHeight
= curpt
.v
;
1798 // TODO change this if possible to reflect real lines
1799 wxString content
= GetValue() ;
1803 for (size_t i
= 0; i
< content
.Length() ; i
++)
1805 if (count
== lineNo
)
1807 // Count chars in line then
1809 for (size_t j
= i
; j
< content
.Length(); j
++)
1812 if (content
[j
] == '\n') return count
;
1817 if (content
[i
] == '\n') count
++;
1823 wxString
wxTextCtrl::GetLineText(long lineNo
) const
1828 wxString content
= GetValue() ;
1830 if ( lineNo
< GetNumberOfLines() )
1832 // TODO find a better implementation : while we can get the
1833 // line metrics of a certain line, we don't get its starting
1834 // position, so it would probably be rather a binary search
1835 // for the start position
1838 int lastHeight
= 0 ;
1839 long lastpos
= GetLastPosition() ;
1842 for ( n
= 0 ; n
<= (ItemCount
)lastpos
; ++n
)
1844 TXNOffsetToPoint( (TXNObject
) m_macTXN
, n
, &curpt
);
1846 if ( curpt
.v
> lastHeight
)
1848 if ( ypos
== lineNo
)
1854 lastHeight
= curpt
.v
;
1858 if ( ypos
== lineNo
)
1859 line
+= content
[n
] ;
1866 // TODO change this if possible to reflect real lines
1867 wxString content
= GetValue() ;
1871 for (size_t i
= 0; i
< content
.Length() ; i
++)
1873 if (count
== lineNo
)
1875 // Add chars in line then
1878 for (size_t j
= i
; j
< content
.Length(); j
++)
1880 if (content
[j
] == '\n')
1888 if (content
[i
] == '\n') count
++;
1890 return wxEmptyString
;
1898 void wxTextCtrl::Command(wxCommandEvent
& event
)
1900 SetValue (event
.GetString());
1901 ProcessCommand (event
);
1904 void wxTextCtrl::OnDropFiles(wxDropFilesEvent
& event
)
1906 // By default, load the first file into the text window.
1907 if (event
.GetNumberOfFiles() > 0)
1909 LoadFile(event
.GetFiles()[0]);
1913 void wxTextCtrl::OnChar(wxKeyEvent
& event
)
1915 int key
= event
.GetKeyCode() ;
1916 bool eat_key
= false ;
1918 if ( key
== 'c' && event
.MetaDown() )
1925 if ( !IsEditable() && key
!= WXK_LEFT
&& key
!= WXK_RIGHT
&& key
!= WXK_DOWN
&& key
!= WXK_UP
&& key
!= WXK_TAB
&&
1926 !( key
== WXK_RETURN
&& ( (m_windowStyle
& wxPROCESS_ENTER
) || (m_windowStyle
& wxTE_MULTILINE
) ) )
1927 /* && key != WXK_PRIOR && key != WXK_NEXT && key != WXK_HOME && key != WXK_END */
1934 // assume that any key not processed yet is going to modify the control
1937 if ( key
== 'v' && event
.MetaDown() )
1943 if ( key
== 'x' && event
.MetaDown() )
1952 if (m_windowStyle
& wxPROCESS_ENTER
)
1954 wxCommandEvent
event(wxEVT_COMMAND_TEXT_ENTER
, m_windowId
);
1955 event
.SetEventObject( this );
1956 event
.SetString( GetValue() );
1957 if ( GetEventHandler()->ProcessEvent(event
) )
1960 if ( !(m_windowStyle
& wxTE_MULTILINE
) )
1962 wxWindow
*parent
= GetParent();
1963 while( parent
&& !parent
->IsTopLevel() && parent
->GetDefaultItem() == NULL
) {
1964 parent
= parent
->GetParent() ;
1966 if ( parent
&& parent
->GetDefaultItem() )
1968 wxButton
*def
= wxDynamicCast(parent
->GetDefaultItem(),
1970 if ( def
&& def
->IsEnabled() )
1972 wxCommandEvent
event(wxEVT_COMMAND_BUTTON_CLICKED
, def
->GetId() );
1973 event
.SetEventObject(def
);
1974 def
->Command(event
);
1979 // this will make wxWidgets eat the ENTER key so that
1980 // we actually prevent line wrapping in a single line
1988 // always produce navigation event - even if we process TAB
1989 // ourselves the fact that we got here means that the user code
1990 // decided to skip processing of this TAB - probably to let it
1991 // do its default job.
1993 wxNavigationKeyEvent eventNav
;
1994 eventNav
.SetDirection(!event
.ShiftDown());
1995 eventNav
.SetWindowChange(event
.ControlDown());
1996 eventNav
.SetEventObject(this);
1998 if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav
) )
2009 // perform keystroke handling
2010 if ( wxTheApp
->MacGetCurrentEvent() != NULL
&& wxTheApp
->MacGetCurrentEventHandlerCallRef() != NULL
)
2011 CallNextEventHandler((EventHandlerCallRef
)wxTheApp
->MacGetCurrentEventHandlerCallRef() , (EventRef
) wxTheApp
->MacGetCurrentEvent() ) ;
2015 if ( wxMacConvertEventToRecord( (EventRef
) wxTheApp
->MacGetCurrentEvent() , &rec
) )
2017 EventRecord
*ev
= &rec
;
2020 keychar
= short(ev
->message
& charCodeMask
);
2021 keycode
= short(ev
->message
& keyCodeMask
) >> 8 ;
2023 ::HandleControlKey( *m_peer
, keycode
, keychar
, ev
->modifiers
) ;
2027 if ( ( key
>= 0x20 && key
< WXK_START
) ||
2028 key
== WXK_RETURN
||
2029 key
== WXK_DELETE
||
2032 wxCommandEvent
event1(wxEVT_COMMAND_TEXT_UPDATED
, m_windowId
);
2033 event1
.SetString( GetValue() ) ;
2034 event1
.SetEventObject( this );
2035 wxPostEvent(GetEventHandler(),event1
);
2039 // ----------------------------------------------------------------------------
2040 // standard handlers for standard edit menu events
2041 // ----------------------------------------------------------------------------
2043 void wxTextCtrl::OnCut(wxCommandEvent
& WXUNUSED(event
))
2048 void wxTextCtrl::OnCopy(wxCommandEvent
& WXUNUSED(event
))
2053 void wxTextCtrl::OnPaste(wxCommandEvent
& WXUNUSED(event
))
2058 void wxTextCtrl::OnUndo(wxCommandEvent
& WXUNUSED(event
))
2063 void wxTextCtrl::OnRedo(wxCommandEvent
& WXUNUSED(event
))
2068 void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent
& event
)
2070 event
.Enable( CanCut() );
2073 void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent
& event
)
2075 event
.Enable( CanCopy() );
2078 void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent
& event
)
2080 event
.Enable( CanPaste() );
2083 void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent
& event
)
2085 event
.Enable( CanUndo() );
2088 void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent
& event
)
2090 event
.Enable( CanRedo() );
2093 bool wxTextCtrl::MacSetupCursor( const wxPoint
& pt
)
2098 // user pane implementation
2100 void wxTextCtrl::MacControlUserPaneDrawProc(wxInt16 part
)
2104 wxInt16
wxTextCtrl::MacControlUserPaneHitTestProc(wxInt16 x
, wxInt16 y
)
2106 return kControlNoPart
;
2109 wxInt16
wxTextCtrl::MacControlUserPaneTrackingProc(wxInt16 x
, wxInt16 y
, void* actionProc
)
2111 return kControlNoPart
;
2114 void wxTextCtrl::MacControlUserPaneIdleProc()
2118 wxInt16
wxTextCtrl::MacControlUserPaneKeyDownProc(wxInt16 keyCode
, wxInt16 charCode
, wxInt16 modifiers
)
2120 return kControlNoPart
;
2123 void wxTextCtrl::MacControlUserPaneActivateProc(bool activating
)
2127 wxInt16
wxTextCtrl::MacControlUserPaneFocusProc(wxInt16 action
)
2129 return kControlNoPart
;
2132 void wxTextCtrl::MacControlUserPaneBackgroundProc(void* info
)