1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/classic/textctrl.cpp
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
20 #include "wx/textctrl.h"
26 #include "wx/button.h"
27 #include "wx/settings.h"
28 #include "wx/msgdlg.h"
32 #include <sys/types.h>
38 #if wxUSE_STD_IOSTREAM
46 #include "wx/toplevel.h"
47 #include "wx/notebook.h"
48 #include "wx/tabctrl.h"
49 #include "wx/filefn.h"
51 #if defined(__BORLANDC__) && !defined(__WIN32__)
53 #elif !defined(__MWERKS__) && !defined(__GNUWIN32) && !defined(__DARWIN__)
60 #include <MacTextEditor.h>
61 #include <ATSUnicode.h>
62 #include <TextCommon.h>
63 #include <TextEncodingConverter.h>
64 #include "wx/mac/uma.h"
66 #define TE_UNLIMITED_LENGTH 0xFFFFFFFFUL
68 extern wxControl
*wxFindControlFromMacControl(ControlHandle inControl
) ;
70 // CS:TODO we still have a problem getting properly at the text events of a control because under Carbon
71 // the MLTE engine registers itself for the key events thus the normal flow never occurs, the only measure for the
72 // moment is to avoid setting the true focus on the control, the proper solution at the end would be to have
73 // an alternate path for carbon key events that routes automatically into the same wx flow of events
77 /* kmUPTextPart is the part code we return to indicate the user has clicked
78 in the text area of our control */
79 #define kmUPTextPart 1
81 /* kmUPScrollPart is the part code we return to indicate the user has clicked
82 in the scroll bar part of the control. */
83 #define kmUPScrollPart 2
86 /* routines for using existing user pane controls.
87 These routines are useful for cases where you would like to use an
88 existing user pane control in, say, a dialog window as a scrolling
91 /* mUPOpenControl initializes a user pane control so it will be drawn
92 and will behave as a scrolling text edit field inside of a window.
93 This routine performs all of the initialization steps necessary,
94 except it does not create the user pane control itself. theControl
95 should refer to a user pane control that you have either created
96 yourself or extracted from a dialog's control heirarchy using
97 the GetDialogItemAsControl routine. */
98 OSStatus
mUPOpenControl(ControlHandle theControl
, long wxStyle
);
100 /* Utility Routines */
106 /* kUserClickedToFocusPart is a part code we pass to the SetKeyboardFocus
107 routine. In our focus switching routine this part code is understood
108 as meaning 'the user has clicked in the control and we need to switch
109 the current focus to ourselves before we can continue'. */
110 #define kUserClickedToFocusPart 100
113 /* kmUPClickScrollDelayTicks is a time measurement in ticks used to
114 slow the speed of 'auto scrolling' inside of our clickloop routine.
115 This value prevents the text from wizzzzzing by while the mouse
116 is being held down inside of the text area. */
117 #define kmUPClickScrollDelayTicks 3
120 /* STPTextPaneVars is a structure used for storing the the mUP Control's
121 internal variables and state information. A handle to this record is
122 stored in the pane control's reference value field using the
123 SetControlReference routine. */
126 /* OS records referenced */
127 TXNObject fTXNRec
; /* the txn record */
128 TXNFrameID fTXNFrame
; /* the txn frame ID */
129 ControlHandle fUserPaneRec
; /* handle to the user pane control */
130 WindowPtr fOwner
; /* window containing control */
131 GrafPtr fDrawingEnvironment
; /* grafport where control is drawn */
133 Boolean fInFocus
; /* true while the focus rect is drawn around the control */
134 Boolean fIsActive
; /* true while the control is drawn in the active state */
135 Boolean fTEActive
; /* reflects the activation state of the text edit record */
136 Boolean fInDialogWindow
; /* true if displayed in a dialog window */
137 /* calculated locations */
138 Rect fRTextArea
; /* area where the text is drawn */
139 Rect fRFocusOutline
; /* rectangle used to draw the focus box */
140 Rect fRTextOutline
; /* rectangle used to draw the border */
141 RgnHandle fTextBackgroundRgn
; /* background region for the text, erased before calling TEUpdate */
142 /* our focus advance override routine */
143 EventHandlerUPP handlerUPP
;
144 EventHandlerRef handlerRef
;
151 /* Univerals Procedure Pointer variables used by the
152 mUP Control. These variables are set up
153 the first time that mUPOpenControl is called. */
154 ControlUserPaneDrawUPP gTPDrawProc
= NULL
;
155 ControlUserPaneHitTestUPP gTPHitProc
= NULL
;
156 ControlUserPaneTrackingUPP gTPTrackProc
= NULL
;
157 ControlUserPaneIdleUPP gTPIdleProc
= NULL
;
158 ControlUserPaneKeyDownUPP gTPKeyProc
= NULL
;
159 ControlUserPaneActivateUPP gTPActivateProc
= NULL
;
160 ControlUserPaneFocusUPP gTPFocusProc
= NULL
;
162 /* TPActivatePaneText activates or deactivates the text edit record
163 according to the value of setActive. The primary purpose of this
164 routine is to ensure each call is only made once. */
165 static void TPActivatePaneText(STPTextPaneVars
**tpvars
, Boolean setActive
) {
166 STPTextPaneVars
*varsp
;
168 if (varsp
->fTEActive
!= setActive
) {
170 varsp
->fTEActive
= setActive
;
172 TXNActivate(varsp
->fTXNRec
, varsp
->fTXNFrame
, varsp
->fTEActive
);
175 TXNFocus( varsp
->fTXNRec
, varsp
->fTEActive
);
180 /* TPFocusPaneText set the focus state for the text record. */
181 static void TPFocusPaneText(STPTextPaneVars
**tpvars
, Boolean setFocus
) {
182 STPTextPaneVars
*varsp
;
184 if (varsp
->fInFocus
!= setFocus
) {
185 varsp
->fInFocus
= setFocus
;
186 TXNFocus( varsp
->fTXNRec
, varsp
->fInFocus
);
191 /* TPPaneDrawProc is called to redraw the control and for update events
192 referring to the control. This routine erases the text area's background,
193 and redraws the text. This routine assumes the scroll bar has been
194 redrawn by a call to DrawControls. */
195 static pascal void TPPaneDrawProc(ControlRef theControl
, ControlPartCode thePart
) {
196 STPTextPaneVars
**tpvars
, *varsp
;
199 /* set up our globals */
201 tpvars
= (STPTextPaneVars
**) GetControlReference(theControl
);
202 if (tpvars
!= NULL
) {
203 state
= HGetState((Handle
) tpvars
);
204 HLock((Handle
) tpvars
);
207 /* save the drawing state */
208 SetPort((**tpvars
).fDrawingEnvironment
);
209 /* verify our boundary */
210 GetControlBounds(theControl
, &bounds
);
212 wxMacWindowClipper
clipper( wxFindControlFromMacControl(theControl
) ) ;
213 if ( ! EqualRect(&bounds
, &varsp
->fRFocusOutline
) ) {
214 // scrollbar is on the border, we add one
215 Rect oldbounds
= varsp
->fRFocusOutline
;
216 InsetRect( &oldbounds
, -1 , -1 ) ;
218 if ( IsControlVisible( theControl
) )
219 InvalWindowRect( GetControlOwner( theControl
) , &oldbounds
) ;
220 SetRect(&varsp
->fRFocusOutline
, bounds
.left
, bounds
.top
, bounds
.right
, bounds
.bottom
);
221 SetRect(&varsp
->fRTextOutline
, bounds
.left
, bounds
.top
, bounds
.right
, bounds
.bottom
);
222 SetRect(&varsp
->fRTextArea
, bounds
.left
+ 2 , bounds
.top
+ (varsp
->fMultiline
? 0 : 2) ,
223 bounds
.right
- (varsp
->fMultiline
? 0 : 2), bounds
.bottom
- (varsp
->fMultiline
? 0 : 2));
224 RectRgn(varsp
->fTextBackgroundRgn
, &varsp
->fRTextOutline
);
225 if ( IsControlVisible( theControl
) )
226 TXNSetFrameBounds( varsp
->fTXNRec
, varsp
->fRTextArea
.top
, varsp
->fRTextArea
.left
,
227 varsp
->fRTextArea
.bottom
, varsp
->fRTextArea
.right
, varsp
->fTXNFrame
);
229 TXNSetFrameBounds( varsp
->fTXNRec
, varsp
->fRTextArea
.top
+ 30000 , varsp
->fRTextArea
.left
+ 30000 ,
230 varsp
->fRTextArea
.bottom
+ 30000 , varsp
->fRTextArea
.right
+ 30000 , varsp
->fTXNFrame
);
234 if ( IsControlVisible( theControl
) )
236 /* update the text region */
237 RGBColor white
= { 65535 , 65535 , 65535 } ;
238 RGBBackColor( &white
) ;
239 EraseRgn(varsp
->fTextBackgroundRgn
);
240 TXNDraw(varsp
->fTXNRec
, NULL
);
241 /* restore the drawing environment */
242 /* draw the text frame and focus frame (if necessary) */
243 DrawThemeEditTextFrame(&varsp
->fRTextOutline
, varsp
->fIsActive
? kThemeStateActive
: kThemeStateInactive
);
244 if ((**tpvars
).fIsActive
&& varsp
->fInFocus
)
245 DrawThemeFocusRect(&varsp
->fRFocusOutline
, true);
246 /* release our globals */
247 HSetState((Handle
) tpvars
, state
);
253 /* TPPaneHitTestProc is called when the control manager would
254 like to determine what part of the control the mouse resides over.
255 We also call this routine from our tracking proc to determine how
256 to handle mouse clicks. */
257 static pascal ControlPartCode
TPPaneHitTestProc(ControlHandle theControl
, Point where
) {
258 STPTextPaneVars
**tpvars
;
259 ControlPartCode result
;
261 /* set up our locals and lock down our globals*/
263 tpvars
= (STPTextPaneVars
**) GetControlReference(theControl
);
264 if (tpvars
!= NULL
&& IsControlVisible( theControl
) ) {
265 state
= HGetState((Handle
) tpvars
);
266 HLock((Handle
) tpvars
);
267 /* find the region where we clicked */
268 if (PtInRect(where
, &(**tpvars
).fRTextArea
)) {
269 result
= kmUPTextPart
;
271 /* release oure globals */
272 HSetState((Handle
) tpvars
, state
);
281 /* TPPaneTrackingProc is called when the mouse is being held down
282 over our control. This routine handles clicks in the text area
283 and in the scroll bar. */
284 static pascal ControlPartCode
TPPaneTrackingProc(ControlHandle theControl
, Point startPt
, ControlActionUPP actionProc
) {
285 STPTextPaneVars
**tpvars
, *varsp
;
287 ControlPartCode partCodeResult
;
288 /* make sure we have some variables... */
290 tpvars
= (STPTextPaneVars
**) GetControlReference(theControl
);
291 if (tpvars
!= NULL
&& IsControlVisible( theControl
) ) {
293 state
= HGetState((Handle
) tpvars
);
294 HLock((Handle
) tpvars
);
296 /* we don't do any of these functions unless we're in focus */
297 if ( ! varsp
->fInFocus
) {
299 owner
= GetControlOwner(theControl
);
300 ClearKeyboardFocus(owner
);
301 SetKeyboardFocus(owner
, theControl
, kUserClickedToFocusPart
);
303 /* find the location for the click */
304 switch (TPPaneHitTestProc(theControl
, startPt
)) {
306 /* handle clicks in the text part */
308 { SetPort((**tpvars
).fDrawingEnvironment
);
309 wxMacWindowClipper
clipper( wxFindControlFromMacControl(theControl
) ) ;
311 TXNClick( varsp
->fTXNRec
, (const EventRecord
*) wxTheApp
->MacGetCurrentEvent());
314 ConvertEventRefToEventRecord( (EventRef
) wxTheApp
->MacGetCurrentEvent() , &rec
) ;
315 TXNClick( varsp
->fTXNRec
, &rec
);
322 HSetState((Handle
) tpvars
, state
);
324 return partCodeResult
;
328 /* TPPaneIdleProc is our user pane idle routine. When our text field
329 is active and in focus, we use this routine to set the cursor. */
330 static pascal void TPPaneIdleProc(ControlHandle theControl
) {
331 STPTextPaneVars
**tpvars
, *varsp
;
333 tpvars
= (STPTextPaneVars
**) GetControlReference(theControl
);
334 if (tpvars
!= NULL
&& IsControlVisible( theControl
) ) {
335 /* if we're not active, then we have nothing to say about the cursor */
336 if ((**tpvars
).fIsActive
) {
340 /* lock down the globals */
341 state
= HGetState((Handle
) tpvars
);
342 HLock((Handle
) tpvars
);
344 /* get the current mouse coordinates (in our window) */
345 SetPortWindowPort(GetControlOwner(theControl
));
346 wxMacWindowClipper
clipper( wxFindControlFromMacControl(theControl
) ) ;
348 /* there's a 'focus thing' and an 'unfocused thing' */
349 if (varsp
->fInFocus
) {
350 /* flash the cursor */
351 SetPort((**tpvars
).fDrawingEnvironment
);
352 TXNIdle(varsp
->fTXNRec
);
354 if (PtInRect(mousep
, &varsp
->fRTextArea
)) {
356 RectRgn((theRgn
= NewRgn()), &varsp
->fRTextArea
);
357 TXNAdjustCursor(varsp
->fTXNRec
, theRgn
);
362 // SetThemeCursor(kThemeArrowCursor);
365 /* if it's in our bounds, set the cursor */
366 GetControlBounds(theControl
, &bounds
);
367 if (PtInRect(mousep
, &bounds
))
369 // SetThemeCursor(kThemeArrowCursor);
373 HSetState((Handle
) tpvars
, state
);
379 /* TPPaneKeyDownProc is called whenever a keydown event is directed
380 at our control. Here, we direct the keydown event to the text
381 edit record and redraw the scroll bar and text field as appropriate. */
382 static pascal ControlPartCode
TPPaneKeyDownProc(ControlHandle theControl
,
383 SInt16 keyCode
, SInt16 charCode
, SInt16 modifiers
) {
384 STPTextPaneVars
**tpvars
;
385 tpvars
= (STPTextPaneVars
**) GetControlReference(theControl
);
386 if (tpvars
!= NULL
) {
387 if ((**tpvars
).fInFocus
) {
388 /* turn autoscrolling on and send the key event to text edit */
389 SetPort((**tpvars
).fDrawingEnvironment
);
390 wxMacWindowClipper
clipper( wxFindControlFromMacControl(theControl
) ) ;
392 memset( &ev
, 0 , sizeof( ev
) ) ;
394 ev
.modifiers
= modifiers
;
395 ev
.message
= (( keyCode
<< 8 ) & keyCodeMask
) + ( charCode
& charCodeMask
) ;
396 TXNKeyDown( (**tpvars
).fTXNRec
, &ev
);
399 return kControlEntireControl
;
403 /* TPPaneActivateProc is called when the window containing
404 the user pane control receives activate events. Here, we redraw
405 the control and it's text as necessary for the activation state. */
406 static pascal void TPPaneActivateProc(ControlHandle theControl
, Boolean activating
) {
408 STPTextPaneVars
**tpvars
, *varsp
;
411 tpvars
= (STPTextPaneVars
**) GetControlReference(theControl
);
412 if (tpvars
!= NULL
) {
413 state
= HGetState((Handle
) tpvars
);
414 HLock((Handle
) tpvars
);
416 /* de/activate the text edit record */
417 SetPort((**tpvars
).fDrawingEnvironment
);
418 wxMacWindowClipper
clipper( wxFindControlFromMacControl(theControl
) ) ;
419 GetControlBounds(theControl
, &bounds
);
420 varsp
->fIsActive
= activating
;
421 TPActivatePaneText(tpvars
, varsp
->fIsActive
&& varsp
->fInFocus
);
422 /* redraw the frame */
423 if ( IsControlVisible( theControl
) )
425 DrawThemeEditTextFrame(&varsp
->fRTextOutline
, varsp
->fIsActive
? kThemeStateActive
: kThemeStateInactive
);
427 DrawThemeFocusRect(&varsp
->fRFocusOutline
, varsp
->fIsActive
);
429 HSetState((Handle
) tpvars
, state
);
434 /* TPPaneFocusProc is called when every the focus changes to or
435 from our control. Herein, switch the focus appropriately
436 according to the parameters and redraw the control as
438 static pascal ControlPartCode
TPPaneFocusProc(ControlHandle theControl
, ControlFocusPart action
) {
439 ControlPartCode focusResult
;
440 STPTextPaneVars
**tpvars
, *varsp
;
443 focusResult
= kControlFocusNoPart
;
444 tpvars
= (STPTextPaneVars
**) GetControlReference(theControl
);
445 if (tpvars
!= NULL
) {
446 state
= HGetState((Handle
) tpvars
);
447 HLock((Handle
) tpvars
);
449 /* if kControlFocusPrevPart and kControlFocusNextPart are received when the user is
450 tabbing forwards (or shift tabbing backwards) through the items in the dialog,
451 and kControlFocusNextPart will be received. When the user clicks in our field
452 and it is not the current focus, then the constant kUserClickedToFocusPart will
453 be received. The constant kControlFocusNoPart will be received when our control
454 is the current focus and the user clicks in another control. In your focus routine,
455 you should respond to these codes as follows:
457 kControlFocusNoPart - turn off focus and return kControlFocusNoPart. redraw
458 the control and the focus rectangle as necessary.
460 kControlFocusPrevPart or kControlFocusNextPart - toggle focus on or off
461 depending on its current state. redraw the control and the focus rectangle
462 as appropriate for the new focus state. If the focus state is 'off', return the constant
463 kControlFocusNoPart, otherwise return a non-zero part code.
464 kUserClickedToFocusPart - is a constant defined for this example. You should
465 define your own value for handling click-to-focus type events. */
466 /* calculate the next highlight state */
469 case kControlFocusNoPart
:
470 TPFocusPaneText(tpvars
, false);
471 focusResult
= kControlFocusNoPart
;
473 case kUserClickedToFocusPart
:
474 TPFocusPaneText(tpvars
, true);
477 case kControlFocusPrevPart
:
478 case kControlFocusNextPart
:
479 TPFocusPaneText(tpvars
, ( ! varsp
->fInFocus
));
480 focusResult
= varsp
->fInFocus
? 1 : kControlFocusNoPart
;
483 TPActivatePaneText(tpvars
, varsp
->fIsActive
&& varsp
->fInFocus
);
484 /* redraw the text fram and focus rectangle to indicate the
486 if ( IsControlVisible( theControl
) )
488 /* save the drawing state */
489 SetPort((**tpvars
).fDrawingEnvironment
);
490 wxMacWindowClipper
clipper( wxFindControlFromMacControl(theControl
) ) ;
491 DrawThemeEditTextFrame(&varsp
->fRTextOutline
, varsp
->fIsActive
? kThemeStateActive
: kThemeStateInactive
);
492 DrawThemeFocusRect(&varsp
->fRFocusOutline
, varsp
->fIsActive
&& varsp
->fInFocus
);
495 HSetState((Handle
) tpvars
, state
);
501 /* mUPOpenControl initializes a user pane control so it will be drawn
502 and will behave as a scrolling text edit field inside of a window.
503 This routine performs all of the initialization steps necessary,
504 except it does not create the user pane control itself. theControl
505 should refer to a user pane control that you have either created
506 yourself or extracted from a dialog's control heirarchy using
507 the GetDialogItemAsControl routine. */
508 OSStatus
mUPOpenControl(ControlHandle theControl
, long wxStyle
)
512 STPTextPaneVars
**tpvars
, *varsp
;
513 OSStatus err
= noErr
;
514 RGBColor rgbWhite
= {0xFFFF, 0xFFFF, 0xFFFF};
517 /* set up our globals */
518 if (gTPDrawProc
== NULL
) gTPDrawProc
= NewControlUserPaneDrawUPP(TPPaneDrawProc
);
519 if (gTPHitProc
== NULL
) gTPHitProc
= NewControlUserPaneHitTestUPP(TPPaneHitTestProc
);
520 if (gTPTrackProc
== NULL
) gTPTrackProc
= NewControlUserPaneTrackingUPP(TPPaneTrackingProc
);
521 if (gTPIdleProc
== NULL
) gTPIdleProc
= NewControlUserPaneIdleUPP(TPPaneIdleProc
);
522 if (gTPKeyProc
== NULL
) gTPKeyProc
= NewControlUserPaneKeyDownUPP(TPPaneKeyDownProc
);
523 if (gTPActivateProc
== NULL
) gTPActivateProc
= NewControlUserPaneActivateUPP(TPPaneActivateProc
);
524 if (gTPFocusProc
== NULL
) gTPFocusProc
= NewControlUserPaneFocusUPP(TPPaneFocusProc
);
526 /* allocate our private storage */
527 tpvars
= (STPTextPaneVars
**) NewHandleClear(sizeof(STPTextPaneVars
));
528 SetControlReference(theControl
, (long) tpvars
);
529 HLock((Handle
) tpvars
);
531 /* set the initial settings for our private data */
532 varsp
->fMultiline
= wxStyle
& wxTE_MULTILINE
;
533 varsp
->fInFocus
= false;
534 varsp
->fIsActive
= true;
535 varsp
->fTEActive
= true; // in order to get a deactivate
536 varsp
->fUserPaneRec
= theControl
;
537 theWindow
= varsp
->fOwner
= GetControlOwner(theControl
);
539 varsp
->fDrawingEnvironment
= (GrafPtr
) GetWindowPort(theWindow
);
541 varsp
->fInDialogWindow
= ( GetWindowKind(varsp
->fOwner
) == kDialogWindowKind
);
542 /* set up the user pane procedures */
543 SetControlData(theControl
, kControlEntireControl
, kControlUserPaneDrawProcTag
, sizeof(gTPDrawProc
), &gTPDrawProc
);
544 SetControlData(theControl
, kControlEntireControl
, kControlUserPaneHitTestProcTag
, sizeof(gTPHitProc
), &gTPHitProc
);
545 SetControlData(theControl
, kControlEntireControl
, kControlUserPaneTrackingProcTag
, sizeof(gTPTrackProc
), &gTPTrackProc
);
546 SetControlData(theControl
, kControlEntireControl
, kControlUserPaneIdleProcTag
, sizeof(gTPIdleProc
), &gTPIdleProc
);
547 SetControlData(theControl
, kControlEntireControl
, kControlUserPaneKeyDownProcTag
, sizeof(gTPKeyProc
), &gTPKeyProc
);
548 SetControlData(theControl
, kControlEntireControl
, kControlUserPaneActivateProcTag
, sizeof(gTPActivateProc
), &gTPActivateProc
);
549 SetControlData(theControl
, kControlEntireControl
, kControlUserPaneFocusProcTag
, sizeof(gTPFocusProc
), &gTPFocusProc
);
550 /* calculate the rectangles used by the control */
551 GetControlBounds(theControl
, &bounds
);
552 SetRect(&varsp
->fRFocusOutline
, bounds
.left
, bounds
.top
, bounds
.right
, bounds
.bottom
);
553 SetRect(&varsp
->fRTextOutline
, bounds
.left
, bounds
.top
, bounds
.right
, bounds
.bottom
);
554 SetRect(&varsp
->fRTextArea
, bounds
.left
+ 2 , bounds
.top
+ (varsp
->fMultiline
? 0 : 2) ,
555 bounds
.right
- (varsp
->fMultiline
? 0 : 2), bounds
.bottom
- (varsp
->fMultiline
? 0 : 2));
556 /* calculate the background region for the text. In this case, it's kindof
557 and irregular region because we're setting the scroll bar a little ways inside
559 RectRgn((varsp
->fTextBackgroundRgn
= NewRgn()), &varsp
->fRTextOutline
);
561 /* set up the drawing environment */
562 SetPort(varsp
->fDrawingEnvironment
);
564 /* create the new edit field */
566 TXNFrameOptions frameOptions
=
567 kTXNDontDrawCaretWhenInactiveMask
;
568 if ( ! ( wxStyle
& wxTE_NOHIDESEL
) )
569 frameOptions
|= kTXNDontDrawSelectionWhenInactiveMask
;
571 if ( wxStyle
& wxTE_MULTILINE
)
573 if ( ! ( wxStyle
& wxTE_DONTWRAP
) )
574 frameOptions
|= kTXNAlwaysWrapAtViewEdgeMask
;
577 frameOptions
|= kTXNAlwaysWrapAtViewEdgeMask
;
578 frameOptions
|= kTXNWantHScrollBarMask
;
581 if ( !(wxStyle
& wxTE_NO_VSCROLL
) )
582 frameOptions
|= kTXNWantVScrollBarMask
;
585 frameOptions
|= kTXNSingleLineOnlyMask
;
587 if ( wxStyle
& wxTE_READONLY
)
588 frameOptions
|= kTXNReadOnlyMask
;
590 TXNNewObject(NULL
, varsp
->fOwner
, &varsp
->fRTextArea
,
592 kTXNTextEditStyleFrameType
,
594 kTXNSystemDefaultEncoding
,
595 &varsp
->fTXNRec
, &varsp
->fTXNFrame
, (TXNObjectRefcon
) tpvars
);
597 if ( !IsControlVisible( theControl
) )
598 TXNSetFrameBounds( varsp
->fTXNRec
, varsp
->fRTextArea
.top
+ 30000 , varsp
->fRTextArea
.left
+ 30000 ,
599 varsp
->fRTextArea
.bottom
+ 30000 , varsp
->fRTextArea
.right
+ 30000 , varsp
->fTXNFrame
);
602 if ( (wxStyle
& wxTE_MULTILINE
) && (wxStyle
& wxTE_DONTWRAP
) )
604 TXNControlTag tag
= kTXNWordWrapStateTag
;
606 dat
.uValue
= kTXNNoAutoWrap
;
607 TXNSetTXNObjectControls( varsp
->fTXNRec
, false , 1 , &tag
, &dat
) ;
613 GetThemeFont(kThemeSmallSystemFont
, GetApplicationScript() , fontName
, &fontSize
, &fontStyle
) ;
615 TXNTypeAttributes typeAttr
[] =
617 { kTXNQDFontNameAttribute
, kTXNQDFontNameAttributeSize
, { (void*) fontName
} } ,
618 { kTXNQDFontSizeAttribute
, kTXNFontSizeAttributeSize
, { (void*) (fontSize
<< 16) } } ,
619 { kTXNQDFontStyleAttribute
, kTXNQDFontStyleAttributeSize
, { (void*) normal
} } ,
622 err
= TXNSetTypeAttributes (varsp
->fTXNRec
, sizeof( typeAttr
) / sizeof(TXNTypeAttributes
) , typeAttr
,
625 /* set the field's background */
627 tback
.bgType
= kTXNBackgroundTypeRGB
;
628 tback
.bg
.color
= rgbWhite
;
629 TXNSetBackground( varsp
->fTXNRec
, &tback
);
631 /* unlock our storage */
632 HUnlock((Handle
) tpvars
);
633 /* perform final activations and setup for our text field. Here,
634 we assume that the window is going to be the 'active' window. */
635 TPActivatePaneText(tpvars
, varsp
->fIsActive
&& varsp
->fInFocus
);
643 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl
, wxControl
)
645 BEGIN_EVENT_TABLE(wxTextCtrl
, wxControl
)
646 EVT_DROP_FILES(wxTextCtrl::OnDropFiles
)
647 EVT_CHAR(wxTextCtrl::OnChar
)
648 EVT_MENU(wxID_CUT
, wxTextCtrl::OnCut
)
649 EVT_MENU(wxID_COPY
, wxTextCtrl::OnCopy
)
650 EVT_MENU(wxID_PASTE
, wxTextCtrl::OnPaste
)
651 EVT_MENU(wxID_UNDO
, wxTextCtrl::OnUndo
)
652 EVT_MENU(wxID_REDO
, wxTextCtrl::OnRedo
)
654 EVT_UPDATE_UI(wxID_CUT
, wxTextCtrl::OnUpdateCut
)
655 EVT_UPDATE_UI(wxID_COPY
, wxTextCtrl::OnUpdateCopy
)
656 EVT_UPDATE_UI(wxID_PASTE
, wxTextCtrl::OnUpdatePaste
)
657 EVT_UPDATE_UI(wxID_UNDO
, wxTextCtrl::OnUpdateUndo
)
658 EVT_UPDATE_UI(wxID_REDO
, wxTextCtrl::OnUpdateRedo
)
661 static void SetTXNData( TXNObject txn
, const wxString
& st
, TXNOffset start
, TXNOffset end
)
664 #if SIZEOF_WCHAR_T == 2
665 size_t len
= st
.Len() ;
666 TXNSetData( txn
, kTXNUnicodeTextData
, (void*)st
.wc_str(), len
* 2,
669 wxMBConvUTF16BE converter
;
670 ByteCount byteBufferLen
= converter
.WC2MB( NULL
, st
.wc_str() , 0 ) ;
671 UniChar
*unibuf
= (UniChar
*) malloc(byteBufferLen
) ;
672 converter
.WC2MB( (char*) unibuf
, st
.wc_str() , byteBufferLen
) ;
673 TXNSetData( txn
, kTXNUnicodeTextData
, (void*)unibuf
, byteBufferLen
,
678 wxCharBuffer text
= st
.mb_str(wxConvLocal
) ;
679 TXNSetData( txn
, kTXNTextData
, (void*)text
.data(), strlen( text
) ,
685 void wxTextCtrl::Init()
689 m_macTXNvars
= NULL
;
690 m_macUsesTXN
= false ;
695 m_maxLength
= TE_UNLIMITED_LENGTH
;
698 wxTextCtrl::~wxTextCtrl()
702 SetControlReference((ControlHandle
)m_macControl
, 0) ;
703 TXNDeleteObject((TXNObject
)m_macTXN
);
704 /* delete our private storage */
705 DisposeHandle((Handle
) m_macTXNvars
);
706 /* zero the control reference */
710 const short kVerticalMargin
= 2 ;
711 const short kHorizontalMargin
= 2 ;
713 bool wxTextCtrl::Create(wxWindow
*parent
, wxWindowID id
,
716 const wxSize
& size
, long style
,
717 const wxValidator
& validator
,
718 const wxString
& name
)
722 m_macTXNvars
= NULL
;
723 m_macUsesTXN
= false ;
726 m_macUsesTXN
= ! (style
& wxTE_PASSWORD
) ;
728 m_macUsesTXN
&= (TXNInitTextension
!= (void*) kUnresolvedCFragSymbolAddress
) ;
730 // base initialization
731 if ( !wxTextCtrlBase::Create(parent
, id
, pos
, size
, style
& ~(wxHSCROLL
|wxVSCROLL
), validator
, name
) )
734 wxSize mySize
= size
;
737 m_macHorizontalBorder
= 5 ; // additional pixels around the real control
738 m_macVerticalBorder
= 3 ;
742 m_macHorizontalBorder
= 5 ; // additional pixels around the real control
743 m_macVerticalBorder
= 5 ;
750 if ( mySize.y == -1 )
753 if ( m_windowStyle & wxTE_MULTILINE )
756 mySize.y += 2 * m_macVerticalBorder ;
759 MacPreControlCreate( parent
, id
, wxEmptyString
, pos
, mySize
,style
, validator
, name
, &bounds
, title
) ;
761 if ( m_windowStyle
& wxTE_MULTILINE
)
763 wxASSERT_MSG( !(m_windowStyle
& wxTE_PROCESS_ENTER
),
764 wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") );
766 m_windowStyle
|= wxTE_PROCESS_ENTER
;
769 if ( m_windowStyle
& wxTE_READONLY
)
775 wxMacConvertNewlines13To10( &st
) ;
778 m_macControl
= (WXWidget
) ::NewControl( MAC_WXHWND(parent
->MacGetRootWindow()) , &bounds
, "\p" , false , 0 , 0 , 1,
779 (style
& wxTE_PASSWORD
) ? kControlEditTextPasswordProc
: kControlEditTextProc
, (long) this ) ;
781 ::GetControlData((ControlHandle
) m_macControl
, 0, kControlEditTextTEHandleTag
, sizeof( TEHandle
) , (char*)((TEHandle
*)&m_macTE
) , &size
) ;
788 featurSet
= kControlSupportsEmbedding
| kControlSupportsFocus
| kControlWantsIdle
789 | kControlWantsActivate
| kControlHandlesTracking
| kControlHasSpecialBackground
790 | kControlGetsFocusOnClick
| kControlSupportsLiveFeedback
;
791 /* create the control */
792 m_macControl
= (WXWidget
) ::NewControl(MAC_WXHWND(parent
->MacGetRootWindow()), &bounds
, "\p", false , featurSet
, 0, featurSet
, kControlUserPaneProc
, 0);
793 /* set up the mUP specific features and data */
794 mUPOpenControl((ControlHandle
) m_macControl
, m_windowStyle
);
796 MacPostControlCreate() ;
800 wxCharBuffer text
= st
.mb_str(wxConvLocal
) ;
801 ::SetControlData( (ControlHandle
) m_macControl
, 0, ( m_windowStyle
& wxTE_PASSWORD
) ? kControlEditTextPasswordTag
: kControlEditTextTextTag
, strlen(text
) , text
) ;
805 STPTextPaneVars
**tpvars
;
807 tpvars
= (STPTextPaneVars
**) GetControlReference((ControlHandle
) m_macControl
);
808 /* set the text in the record */
809 m_macTXN
= (**tpvars
).fTXNRec
;
810 SetTXNData( (TXNObject
) m_macTXN
, st
, kTXNStartOffset
, kTXNEndOffset
) ;
811 m_macTXNvars
= tpvars
;
812 m_macUsesTXN
= true ;
813 TXNSetSelection( (TXNObject
) m_macTXN
, 0, 0);
814 TXNShowSelection( (TXNObject
) m_macTXN
, kTXNShowStart
);
820 wxString
wxTextCtrl::GetValue() const
827 err
= ::GetControlDataSize((ControlHandle
) m_macControl
, 0,
828 ( m_windowStyle
& wxTE_PASSWORD
) ? kControlEditTextPasswordTag
: kControlEditTextTextTag
, &actualSize
) ;
831 return wxEmptyString
;
833 if ( actualSize
> 0 )
835 wxCharBuffer
buf(actualSize
) ;
836 ::GetControlData( (ControlHandle
) m_macControl
, 0,
837 ( m_windowStyle
& wxTE_PASSWORD
) ? kControlEditTextPasswordTag
: kControlEditTextTextTag
,
838 actualSize
, buf
.data() , &actualSize
) ;
839 result
= wxString( buf
, wxConvLocal
) ;
846 err
= TXNGetDataEncoded( ((TXNObject
) m_macTXN
), kTXNStartOffset
, kTXNEndOffset
, &theText
, kTXNUnicodeTextData
);
854 actualSize
= GetHandleSize( theText
) / sizeof( UniChar
) ;
855 if ( actualSize
> 0 )
857 wxChar
*ptr
= result
.GetWriteBuf(actualSize
*sizeof(wxChar
)) ;
858 #if SIZEOF_WCHAR_T == 2
859 wxStrncpy( ptr
, (wxChar
*) *theText
, actualSize
) ;
861 wxMBConvUTF16BE converter
;
863 converter
.MB2WC( ptr
, (const char*)*theText
, actualSize
) ;
866 ptr
[actualSize
] = 0 ;
867 result
.UngetWriteBuf( actualSize
*sizeof(wxChar
) ) ;
869 DisposeHandle( theText
) ;
873 err
= TXNGetDataEncoded( ((TXNObject
) m_macTXN
), kTXNStartOffset
, kTXNEndOffset
, &theText
, kTXNTextData
);
881 actualSize
= GetHandleSize( theText
) ;
882 if ( actualSize
> 0 )
885 result
= wxString( *theText
, wxConvLocal
, actualSize
) ;
888 DisposeHandle( theText
) ;
892 wxMacConvertNewlines10To13( &result
) ;
896 void wxTextCtrl::GetSelection(long* from
, long* to
) const
900 *from
= (**((TEHandle
) m_macTE
)).selStart
;
901 *to
= (**((TEHandle
) m_macTE
)).selEnd
;
905 TXNGetSelection( (TXNObject
) m_macTXN
, (TXNOffset
*) from
, (TXNOffset
*) to
) ;
909 void wxTextCtrl::SetValue(const wxString
& str
)
912 wxMacConvertNewlines13To10( &st
) ;
915 wxCharBuffer text
= st
.mb_str(wxConvLocal
) ;
916 ::SetControlData( (ControlHandle
) m_macControl
, 0, ( m_windowStyle
& wxTE_PASSWORD
) ? kControlEditTextPasswordTag
: kControlEditTextTextTag
, strlen(text
) , text
) ;
920 bool formerEditable
= m_editable
;
921 if ( !formerEditable
)
923 SetTXNData( (TXNObject
) m_macTXN
, st
, kTXNStartOffset
, kTXNEndOffset
) ;
924 TXNSetSelection( (TXNObject
) m_macTXN
, 0, 0);
925 TXNShowSelection( (TXNObject
) m_macTXN
, kTXNShowStart
);
926 if ( !formerEditable
)
927 SetEditable(formerEditable
) ;
932 void wxTextCtrl::SetMaxLength(unsigned long len
)
937 bool wxTextCtrl::SetStyle(long start
, long end
, const wxTextAttr
& style
)
941 bool formerEditable
= m_editable
;
942 if ( !formerEditable
)
944 TXNTypeAttributes typeAttr
[4] ;
945 Str255 fontName
= "\pMonaco" ;
946 SInt16 fontSize
= 12 ;
947 Style fontStyle
= normal
;
949 int attrCounter
= 0 ;
950 if ( style
.HasFont() )
952 const wxFont
&font
= style
.GetFont() ;
953 wxMacStringToPascal( font
.GetFaceName() , fontName
) ;
954 fontSize
= font
.GetPointSize() ;
955 if ( font
.GetUnderlined() )
956 fontStyle
|= underline
;
957 if ( font
.GetWeight() == wxBOLD
)
959 if ( font
.GetStyle() == wxITALIC
)
960 fontStyle
|= italic
;
962 typeAttr
[attrCounter
].tag
= kTXNQDFontNameAttribute
;
963 typeAttr
[attrCounter
].size
= kTXNQDFontNameAttributeSize
;
964 typeAttr
[attrCounter
].data
.dataPtr
= (void*) fontName
;
965 typeAttr
[attrCounter
+1].tag
= kTXNQDFontSizeAttribute
;
966 typeAttr
[attrCounter
+1].size
= kTXNFontSizeAttributeSize
;
967 typeAttr
[attrCounter
+1].data
.dataValue
= (fontSize
<< 16) ;
968 typeAttr
[attrCounter
+2].tag
= kTXNQDFontStyleAttribute
;
969 typeAttr
[attrCounter
+2].size
= kTXNQDFontStyleAttributeSize
;
970 typeAttr
[attrCounter
+2].data
.dataValue
= fontStyle
;
974 if ( style
.HasTextColour() )
976 typeAttr
[attrCounter
].tag
= kTXNQDFontColorAttribute
;
977 typeAttr
[attrCounter
].size
= kTXNQDFontColorAttributeSize
;
978 typeAttr
[attrCounter
].data
.dataPtr
= (void*) &color
;
979 color
= MAC_WXCOLORREF(style
.GetTextColour().GetPixel()) ;
983 if ( attrCounter
> 0 )
987 #endif // __WXDEBUG__
988 TXNSetTypeAttributes ((TXNObject
)m_macTXN
, attrCounter
, typeAttr
, start
,end
);
989 wxASSERT_MSG( status
== noErr
, wxT("Couldn't set text attributes") ) ;
991 if ( !formerEditable
)
992 SetEditable(formerEditable
) ;
997 bool wxTextCtrl::SetDefaultStyle(const wxTextAttr
& style
)
999 wxTextCtrlBase::SetDefaultStyle( style
) ;
1000 SetStyle( kTXNUseCurrentSelection
, kTXNUseCurrentSelection
, GetDefaultStyle() ) ;
1004 // Clipboard operations
1005 void wxTextCtrl::Copy()
1009 if ( !m_macUsesTXN
)
1011 TECopy( ((TEHandle
) m_macTE
) ) ;
1012 ClearCurrentScrap();
1014 MacRedrawControl() ;
1018 ClearCurrentScrap();
1019 TXNCopy((TXNObject
)m_macTXN
);
1020 TXNConvertToPublicScrap();
1025 void wxTextCtrl::Cut()
1029 if ( !m_macUsesTXN
)
1031 TECut( ((TEHandle
) m_macTE
) ) ;
1032 ClearCurrentScrap();
1034 MacRedrawControl() ;
1038 ClearCurrentScrap();
1039 TXNCut((TXNObject
)m_macTXN
);
1040 TXNConvertToPublicScrap();
1042 wxCommandEvent
event(wxEVT_COMMAND_TEXT_UPDATED
, m_windowId
);
1043 event
.SetEventObject( this );
1044 GetEventHandler()->ProcessEvent(event
);
1048 void wxTextCtrl::Paste()
1052 if ( !m_macUsesTXN
)
1055 TEPaste( (TEHandle
) m_macTE
) ;
1056 MacRedrawControl() ;
1060 TXNConvertFromPublicScrap();
1061 TXNPaste((TXNObject
)m_macTXN
);
1062 SetStyle( kTXNUseCurrentSelection
, kTXNUseCurrentSelection
, GetDefaultStyle() ) ;
1064 wxCommandEvent
event(wxEVT_COMMAND_TEXT_UPDATED
, m_windowId
);
1065 event
.SetEventObject( this );
1066 GetEventHandler()->ProcessEvent(event
);
1070 bool wxTextCtrl::CanCopy() const
1072 // Can copy if there's a selection
1074 GetSelection(& from
, & to
);
1075 return (from
!= to
);
1078 bool wxTextCtrl::CanCut() const
1080 if ( !IsEditable() )
1084 // Can cut if there's a selection
1086 GetSelection(& from
, & to
);
1087 return (from
!= to
);
1090 bool wxTextCtrl::CanPaste() const
1096 OSStatus err
= noErr
;
1099 err
= GetCurrentScrap( &scrapRef
);
1100 if ( err
!= noTypeErr
&& err
!= memFullErr
)
1102 ScrapFlavorFlags flavorFlags
;
1105 if (( err
= GetScrapFlavorFlags( scrapRef
, 'TEXT', &flavorFlags
)) == noErr
)
1107 if (( err
= GetScrapFlavorSize( scrapRef
, 'TEXT', &byteCount
)) == noErr
)
1117 if ( GetScrap( NULL
, 'TEXT' , &offset
) > 0 )
1125 void wxTextCtrl::SetEditable(bool editable
)
1127 if ( editable
!= m_editable
)
1129 m_editable
= editable
;
1130 if ( !m_macUsesTXN
)
1133 UMAActivateControl( (ControlHandle
) m_macControl
) ;
1135 UMADeactivateControl((ControlHandle
) m_macControl
) ;
1139 TXNControlTag tag
[] = { kTXNIOPrivilegesTag
} ;
1140 TXNControlData data
[] = { { editable
? kTXNReadWrite
: kTXNReadOnly
} } ;
1141 TXNSetTXNObjectControls( (TXNObject
) m_macTXN
, false , sizeof(tag
) / sizeof (TXNControlTag
) , tag
, data
) ;
1146 void wxTextCtrl::SetInsertionPoint(long pos
)
1148 SetSelection( pos
, pos
) ;
1151 void wxTextCtrl::SetInsertionPointEnd()
1153 wxTextPos pos
= GetLastPosition();
1154 SetInsertionPoint(pos
);
1157 long wxTextCtrl::GetInsertionPoint() const
1160 GetSelection( &begin
, &end
) ;
1164 wxTextPos
wxTextCtrl::GetLastPosition() const
1166 if ( !m_macUsesTXN
)
1168 return (**((TEHandle
) m_macTE
)).teLength
;
1174 OSErr err
= TXNGetDataEncoded( (TXNObject
) m_macTXN
, kTXNStartOffset
, kTXNEndOffset
, &theText
, kTXNTextData
);
1182 actualsize
= GetHandleSize( theText
) ;
1183 DisposeHandle( theText
) ;
1189 void wxTextCtrl::Replace(long from
, long to
, const wxString
& str
)
1191 wxString value
= str
;
1192 wxMacConvertNewlines13To10( &value
) ;
1193 if ( !m_macUsesTXN
)
1195 ControlEditTextSelectionRec selection
;
1197 selection
.selStart
= from
;
1198 selection
.selEnd
= to
;
1199 ::SetControlData((ControlHandle
) m_macControl
, 0, kControlEditTextSelectionTag
, sizeof( selection
) , (char*) &selection
) ;
1200 TESetSelect( from
, to
, ((TEHandle
) m_macTE
) ) ;
1201 TEDelete( ((TEHandle
) m_macTE
) ) ;
1202 TEInsert( value
, value
.length() , ((TEHandle
) m_macTE
) ) ;
1206 bool formerEditable
= m_editable
;
1207 if ( !formerEditable
)
1209 TXNSetSelection( ((TXNObject
) m_macTXN
) , from
, to
) ;
1210 TXNClear( ((TXNObject
) m_macTXN
) ) ;
1211 SetTXNData( (TXNObject
) m_macTXN
, str
, kTXNUseCurrentSelection
, kTXNUseCurrentSelection
) ;
1212 if ( !formerEditable
)
1213 SetEditable( formerEditable
) ;
1218 void wxTextCtrl::Remove(long from
, long to
)
1220 if ( !m_macUsesTXN
)
1222 ControlEditTextSelectionRec selection
;
1224 selection
.selStart
= from
;
1225 selection
.selEnd
= to
;
1226 ::SetControlData( (ControlHandle
) m_macControl
, 0, kControlEditTextSelectionTag
, sizeof( selection
) , (char*) &selection
) ;
1227 TEDelete( ((TEHandle
) m_macTE
) ) ;
1231 bool formerEditable
= m_editable
;
1232 if ( !formerEditable
)
1234 TXNSetSelection( ((TXNObject
) m_macTXN
) , from
, to
) ;
1235 TXNClear( ((TXNObject
) m_macTXN
) ) ;
1236 if ( !formerEditable
)
1237 SetEditable( formerEditable
) ;
1242 void wxTextCtrl::SetSelection(long from
, long to
)
1244 if ( !m_macUsesTXN
)
1246 ControlEditTextSelectionRec selection
;
1247 if ((from
== -1) && (to
== -1))
1249 selection
.selStart
= 0 ;
1250 selection
.selEnd
= 32767 ;
1254 selection
.selStart
= from
;
1255 selection
.selEnd
= to
;
1258 TESetSelect( selection
.selStart
, selection
.selEnd
, ((TEHandle
) m_macTE
) ) ;
1259 ::SetControlData((ControlHandle
) m_macControl
, 0, kControlEditTextSelectionTag
, sizeof( selection
) , (char*) &selection
) ;
1263 STPTextPaneVars
**tpvars
;
1264 /* set up our locals */
1265 tpvars
= (STPTextPaneVars
**) GetControlReference((ControlHandle
) m_macControl
);
1266 /* and our drawing environment as the operation
1267 may force a redraw in the text area. */
1268 SetPort((**tpvars
).fDrawingEnvironment
);
1269 /* change the selection */
1270 if ((from
== -1) && (to
== -1))
1271 TXNSelectAll((TXNObject
) m_macTXN
);
1273 TXNSetSelection( (**tpvars
).fTXNRec
, from
, to
);
1274 TXNShowSelection( (TXNObject
) m_macTXN
, kTXNShowStart
);
1278 bool wxTextCtrl::LoadFile(const wxString
& file
)
1280 if ( wxTextCtrlBase::LoadFile(file
) )
1288 void wxTextCtrl::WriteText(const wxString
& str
)
1291 wxMacConvertNewlines13To10( &st
) ;
1292 if ( !m_macUsesTXN
)
1294 wxCharBuffer text
= st
.mb_str(wxConvLocal
) ;
1295 TEInsert( text
, strlen(text
) , ((TEHandle
) m_macTE
) ) ;
1299 bool formerEditable
= m_editable
;
1300 if ( !formerEditable
)
1302 long start
, end
, dummy
;
1303 GetSelection( &start
, &dummy
) ;
1304 SetTXNData( (TXNObject
) m_macTXN
, st
, kTXNUseCurrentSelection
, kTXNUseCurrentSelection
) ;
1305 GetSelection( &dummy
, &end
) ;
1306 SetStyle( start
, end
, GetDefaultStyle() ) ;
1307 if ( !formerEditable
)
1308 SetEditable( formerEditable
) ;
1310 MacRedrawControl() ;
1313 void wxTextCtrl::AppendText(const wxString
& text
)
1315 SetInsertionPointEnd();
1319 void wxTextCtrl::Clear()
1321 if ( !m_macUsesTXN
)
1323 ::SetControlData((ControlHandle
) m_macControl
, 0, ( m_windowStyle
& wxTE_PASSWORD
) ? kControlEditTextPasswordTag
: kControlEditTextTextTag
, 0 , (char*) ((const char*)NULL
) ) ;
1327 TXNSetSelection( (TXNObject
)m_macTXN
, kTXNStartOffset
, kTXNEndOffset
) ;
1328 TXNClear((TXNObject
)m_macTXN
);
1333 bool wxTextCtrl::IsModified() const
1338 bool wxTextCtrl::IsEditable() const
1340 return IsEnabled() && m_editable
;
1343 bool wxTextCtrl::AcceptsFocus() const
1345 // we don't want focus if we can't be edited
1346 return /*IsEditable() && */ wxControl::AcceptsFocus();
1349 wxSize
wxTextCtrl::DoGetBestSize() const
1364 wxGetCharSize(GetHWND(), &cx, &cy, &GetFont());
1366 int wText = DEFAULT_ITEM_WIDTH;
1368 int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
1370 return wxSize(wText, hText);
1372 if ( m_windowStyle
& wxTE_MULTILINE
)
1376 hText
+= 2 * m_macVerticalBorder
;
1377 wText
+= 2 * m_macHorizontalBorder
;
1378 //else: for single line control everything is ok
1379 return wxSize(wText
, hText
);
1382 // ----------------------------------------------------------------------------
1384 // ----------------------------------------------------------------------------
1386 void wxTextCtrl::Undo()
1392 TXNUndo((TXNObject
)m_macTXN
);
1397 void wxTextCtrl::Redo()
1403 TXNRedo((TXNObject
)m_macTXN
);
1408 bool wxTextCtrl::CanUndo() const
1410 if ( !IsEditable() )
1416 return TXNCanUndo((TXNObject
)m_macTXN
,NULL
);
1421 bool wxTextCtrl::CanRedo() const
1423 if ( !IsEditable() )
1429 return TXNCanRedo((TXNObject
)m_macTXN
,NULL
);
1434 // Makes modifie or unmodified
1435 void wxTextCtrl::MarkDirty()
1440 void wxTextCtrl::DiscardEdits()
1445 int wxTextCtrl::GetNumberOfLines() const
1450 TXNGetLineCount((TXNObject
)m_macTXN
, &lines
) ;
1455 wxString content
= GetValue() ;
1458 for (size_t i
= 0; i
< content
.length() ; i
++)
1460 if (content
[i
] == '\r') count
++;
1466 long wxTextCtrl::XYToPosition(long x
, long y
) const
1472 bool wxTextCtrl::PositionToXY(long pos
, long *x
, long *y
) const
1477 void wxTextCtrl::ShowPosition(long pos
)
1479 #if TARGET_RT_MAC_MACHO && defined(AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER)
1484 TXNOffset selstart
, selend
;
1485 TXNGetSelection( (TXNObject
) m_macTXN
, &selstart
, &selend
) ;
1486 TXNOffsetToPoint( (TXNObject
) m_macTXN
, selstart
, ¤t
);
1487 TXNOffsetToPoint( (TXNObject
) m_macTXN
, pos
, &desired
);
1488 //TODO use HIPoints for 10.3 and above
1489 if ( (UInt32
) TXNScroll
!= (UInt32
) kUnresolvedCFragSymbolAddress
)
1491 OSErr theErr
= noErr
;
1492 SInt32 dv
= desired
.v
- current
.v
;
1493 SInt32 dh
= desired
.h
- current
.h
;
1494 TXNShowSelection( (TXNObject
) m_macTXN
, true ) ;
1495 theErr
= TXNScroll( (TXNObject
) m_macTXN
, kTXNScrollUnitsInPixels
, kTXNScrollUnitsInPixels
, &dv
, &dh
);
1496 wxASSERT_MSG( theErr
== noErr
, _T("TXNScroll returned an error!") );
1502 int wxTextCtrl::GetLineLength(long lineNo
) const
1504 // TODO change this if possible to reflect real lines
1505 wxString content
= GetValue() ;
1509 for (size_t i
= 0; i
< content
.length() ; i
++)
1511 if (count
== lineNo
)
1513 // Count chars in line then
1515 for (size_t j
= i
; j
< content
.length(); j
++)
1518 if (content
[j
] == '\n') return count
;
1523 if (content
[i
] == '\n') count
++;
1528 wxString
wxTextCtrl::GetLineText(long lineNo
) const
1530 // TODO change this if possible to reflect real lines
1531 wxString content
= GetValue() ;
1535 for (size_t i
= 0; i
< content
.length() ; i
++)
1537 if (count
== lineNo
)
1539 // Add chars in line then
1542 for (size_t j
= i
; j
< content
.length(); j
++)
1544 if (content
[j
] == '\n')
1552 if (content
[i
] == '\n') count
++;
1554 return wxEmptyString
;
1561 void wxTextCtrl::Command(wxCommandEvent
& event
)
1563 SetValue (event
.GetString());
1564 ProcessCommand (event
);
1567 void wxTextCtrl::OnDropFiles(wxDropFilesEvent
& event
)
1569 // By default, load the first file into the text window.
1570 if (event
.GetNumberOfFiles() > 0)
1572 LoadFile(event
.GetFiles()[0]);
1576 void wxTextCtrl::OnChar(wxKeyEvent
& event
)
1578 int key
= event
.GetKeyCode() ;
1579 bool eat_key
= false ;
1581 if ( key
== 'c' && event
.MetaDown() )
1588 if ( !IsEditable() && key
!= WXK_LEFT
&& key
!= WXK_RIGHT
&& key
!= WXK_DOWN
&& key
!= WXK_UP
&& key
!= WXK_TAB
&&
1589 !( key
== WXK_RETURN
&& ( (m_windowStyle
& wxTE_PROCESS_ENTER
) || (m_windowStyle
& wxTE_MULTILINE
) ) )
1590 /* && key != WXK_PAGEUP && key != WXK_PAGEDOWN && key != WXK_HOME && key != WXK_END */
1597 // assume that any key not processed yet is going to modify the control
1600 if ( key
== 'v' && event
.MetaDown() )
1606 if ( key
== 'x' && event
.MetaDown() )
1615 if (m_windowStyle
& wxTE_PROCESS_ENTER
)
1617 wxCommandEvent
event(wxEVT_COMMAND_TEXT_ENTER
, m_windowId
);
1618 event
.SetEventObject( this );
1619 event
.SetString( GetValue() );
1620 if ( GetEventHandler()->ProcessEvent(event
) )
1623 if ( !(m_windowStyle
& wxTE_MULTILINE
) )
1625 wxWindow
*parent
= GetParent();
1626 while( parent
&& !parent
->IsTopLevel() && parent
->GetDefaultItem() == NULL
) {
1627 parent
= parent
->GetParent() ;
1629 if ( parent
&& parent
->GetDefaultItem() )
1631 wxButton
*def
= wxDynamicCast(parent
->GetDefaultItem(),
1633 if ( def
&& def
->IsEnabled() )
1635 wxCommandEvent
event(wxEVT_COMMAND_BUTTON_CLICKED
, def
->GetId() );
1636 event
.SetEventObject(def
);
1637 def
->Command(event
);
1642 // this will make wxWidgets eat the ENTER key so that
1643 // we actually prevent line wrapping in a single line
1651 if ( !(m_windowStyle
& wxTE_PROCESS_TAB
))
1654 if (!event
.ShiftDown())
1655 flags
|= wxNavigationKeyEvent::IsForward
;
1656 if (event
.ControlDown())
1657 flags
|= wxNavigationKeyEvent::WinChange
;
1663 // This is necessary (don't know why) or the tab will not
1665 WriteText(wxT("\t"));
1672 // perform keystroke handling
1674 if ( m_macUsesTXN
&& wxTheApp
->MacGetCurrentEvent() != NULL
&& wxTheApp
->MacGetCurrentEventHandlerCallRef() != NULL
)
1675 CallNextEventHandler((EventHandlerCallRef
)wxTheApp
->MacGetCurrentEventHandlerCallRef() , (EventRef
) wxTheApp
->MacGetCurrentEvent() ) ;
1679 if ( wxMacConvertEventToRecord( (EventRef
) wxTheApp
->MacGetCurrentEvent() , &rec
) )
1681 EventRecord
*ev
= &rec
;
1684 keychar
= short(ev
->message
& charCodeMask
);
1685 keycode
= short(ev
->message
& keyCodeMask
) >> 8 ;
1687 ::HandleControlKey( (ControlHandle
) m_macControl
, keycode
, keychar
, ev
->modifiers
) ;
1691 EventRecord
*ev
= (EventRecord
*) wxTheApp
->MacGetCurrentEvent() ;
1694 keychar
= short(ev
->message
& charCodeMask
);
1695 keycode
= short(ev
->message
& keyCodeMask
) >> 8 ;
1697 ::HandleControlKey( (ControlHandle
) m_macControl
, keycode
, keychar
, ev
->modifiers
) ;
1700 if ( ( key
>= 0x20 && key
< WXK_START
) ||
1701 key
== WXK_RETURN
||
1702 key
== WXK_DELETE
||
1705 wxCommandEvent
event1(wxEVT_COMMAND_TEXT_UPDATED
, m_windowId
);
1706 event1
.SetEventObject( this );
1707 wxPostEvent(GetEventHandler(),event1
);
1711 void wxTextCtrl::MacSuperShown( bool show
)
1713 bool former
= m_macControlIsShown
;
1714 wxControl::MacSuperShown( show
) ;
1715 if ( (former
!= m_macControlIsShown
) && m_macUsesTXN
)
1717 if ( m_macControlIsShown
)
1718 TXNSetFrameBounds( (TXNObject
) m_macTXN
, (**(STPTextPaneVars
**)m_macTXNvars
).fRTextArea
.top
, (**(STPTextPaneVars
**)m_macTXNvars
).fRTextArea
.left
,
1719 (**(STPTextPaneVars
**)m_macTXNvars
).fRTextArea
.bottom
,(**(STPTextPaneVars
**)m_macTXNvars
).fRTextArea
.right
, (**(STPTextPaneVars
**)m_macTXNvars
).fTXNFrame
);
1721 TXNSetFrameBounds( (TXNObject
) m_macTXN
, (**(STPTextPaneVars
**)m_macTXNvars
).fRTextArea
.top
+ 30000, (**(STPTextPaneVars
**)m_macTXNvars
).fRTextArea
.left
,
1722 (**(STPTextPaneVars
**)m_macTXNvars
).fRTextArea
.bottom
+ 30000, (**(STPTextPaneVars
**)m_macTXNvars
).fRTextArea
.right
, (**(STPTextPaneVars
**)m_macTXNvars
).fTXNFrame
);
1726 bool wxTextCtrl::Show(bool show
)
1728 bool former
= m_macControlIsShown
;
1730 bool retval
= wxControl::Show( show
) ;
1732 if ( former
!= m_macControlIsShown
&& m_macUsesTXN
)
1734 if ( m_macControlIsShown
)
1735 TXNSetFrameBounds( (TXNObject
) m_macTXN
, (**(STPTextPaneVars
**)m_macTXNvars
).fRTextArea
.top
, (**(STPTextPaneVars
**)m_macTXNvars
).fRTextArea
.left
,
1736 (**(STPTextPaneVars
**)m_macTXNvars
).fRTextArea
.bottom
,(**(STPTextPaneVars
**)m_macTXNvars
).fRTextArea
.right
, (**(STPTextPaneVars
**)m_macTXNvars
).fTXNFrame
);
1738 TXNSetFrameBounds( (TXNObject
) m_macTXN
, (**(STPTextPaneVars
**)m_macTXNvars
).fRTextArea
.top
+ 30000, (**(STPTextPaneVars
**)m_macTXNvars
).fRTextArea
.left
,
1739 (**(STPTextPaneVars
**)m_macTXNvars
).fRTextArea
.bottom
+ 30000, (**(STPTextPaneVars
**)m_macTXNvars
).fRTextArea
.right
, (**(STPTextPaneVars
**)m_macTXNvars
).fTXNFrame
);
1745 // ----------------------------------------------------------------------------
1746 // standard handlers for standard edit menu events
1747 // ----------------------------------------------------------------------------
1749 void wxTextCtrl::OnCut(wxCommandEvent
& WXUNUSED(event
))
1754 void wxTextCtrl::OnCopy(wxCommandEvent
& WXUNUSED(event
))
1759 void wxTextCtrl::OnPaste(wxCommandEvent
& WXUNUSED(event
))
1764 void wxTextCtrl::OnUndo(wxCommandEvent
& WXUNUSED(event
))
1769 void wxTextCtrl::OnRedo(wxCommandEvent
& WXUNUSED(event
))
1774 void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent
& event
)
1776 event
.Enable( CanCut() );
1779 void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent
& event
)
1781 event
.Enable( CanCopy() );
1784 void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent
& event
)
1786 event
.Enable( CanPaste() );
1789 void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent
& event
)
1791 event
.Enable( CanUndo() );
1794 void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent
& event
)
1796 event
.Enable( CanRedo() );
1799 bool wxTextCtrl::MacSetupCursor( const wxPoint
& pt
)
1804 return wxWindow::MacSetupCursor( pt
) ;