]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/textctrl.cpp
security fix to wxSingleInstanceChecker: check if the lock file was really created...
[wxWidgets.git] / src / mac / carbon / textctrl.cpp
CommitLineData
e9576ca5
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: textctrl.cpp
3// Purpose: wxTextCtrl
a31a5f85 4// Author: Stefan Csomor
e9576ca5 5// Modified by:
a31a5f85 6// Created: 1998-01-01
e9576ca5 7// RCS-ID: $Id$
a31a5f85 8// Copyright: (c) Stefan Csomor
65571936 9// Licence: wxWindows licence
e9576ca5
SC
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "textctrl.h"
14#endif
15
fedad417
GD
16#include "wx/defs.h"
17
18#if wxUSE_TEXTCTRL
19
f5c6eb5c 20#ifdef __DARWIN__
03e11df5
GD
21 #include <sys/types.h>
22 #include <sys/stat.h>
e9576ca5 23#else
03e11df5 24 #include <stat.h>
e9576ca5 25#endif
2b5f62a0 26
3a05d58d
SC
27#include "wx/msgdlg.h"
28
2b5f62a0
VZ
29#if wxUSE_STD_IOSTREAM
30 #if wxUSE_IOSTREAMH
31 #include <fstream.h>
32 #else
33 #include <fstream>
34 #endif
35#endif
e9576ca5 36
03e11df5 37#include "wx/app.h"
5fde6fcc 38#include "wx/dc.h"
03e11df5 39#include "wx/button.h"
422644a3 40#include "wx/toplevel.h"
e9576ca5 41#include "wx/textctrl.h"
90b22aca
SC
42#include "wx/notebook.h"
43#include "wx/tabctrl.h"
e9576ca5
SC
44#include "wx/settings.h"
45#include "wx/filefn.h"
46#include "wx/utils.h"
47
48#if defined(__BORLANDC__) && !defined(__WIN32__)
03e11df5 49 #include <alloc.h>
f5c6eb5c 50#elif !defined(__MWERKS__) && !defined(__GNUWIN32) && !defined(__DARWIN__)
03e11df5 51 #include <malloc.h>
e9576ca5
SC
52#endif
53
66a09d47
SC
54#ifndef __DARWIN__
55#include <Scrap.h>
1b2b1638
SC
56#endif
57#include <MacTextEditor.h>
7688f0a1
SC
58#include <ATSUnicode.h>
59#include <TextCommon.h>
60#include <TextEncodingConverter.h>
1b2b1638 61#include "wx/mac/uma.h"
72055702 62
29b30405 63#define TE_UNLIMITED_LENGTH 0xFFFFFFFFUL
587bc950 64#if TARGET_API_MAC_OSX
1f20a739 65 #define wxMAC_USE_MLTE 0
479815ca 66 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
587bc950 67 #define wxMAC_USE_MLTE_HIVIEW 1
479815ca
JS
68 #else
69 #define wxMAC_USE_MLTE_HIVIEW 0
70 #endif
587bc950
SC
71#else
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
75#endif
76
77#if wxMAC_USE_MLTE
78
79TXNFrameOptions FrameOptionsFromWXStyle( long wxStyle )
80{
81 TXNFrameOptions frameOptions =
82 kTXNDontDrawCaretWhenInactiveMask ;
83 if ( ! ( wxStyle & wxTE_NOHIDESEL ) )
84 frameOptions |= kTXNDontDrawSelectionWhenInactiveMask ;
85
86 if ( wxStyle & wxTE_MULTILINE )
87 {
88 if ( ! ( wxStyle & wxTE_DONTWRAP ) )
89 frameOptions |= kTXNAlwaysWrapAtViewEdgeMask ;
90 else
91 {
92 frameOptions |= kTXNAlwaysWrapAtViewEdgeMask ;
93 frameOptions |= kTXNWantHScrollBarMask ;
94 }
95
96 if ( !(wxStyle & wxTE_NO_VSCROLL ) )
97 frameOptions |= kTXNWantVScrollBarMask ;
98 }
99 else
100 frameOptions |= kTXNSingleLineOnlyMask ;
101 return frameOptions ;
102}
103
104void AdjustAttributesFromWXStyle( TXNObject txn , long wxStyle , bool visible )
105{
106 TXNControlTag iControlTags[3] = { kTXNDoFontSubstitution, kTXNWordWrapStateTag };
107 TXNControlData iControlData[3] = { {false}, {kTXNNoAutoWrap} };
108 int toptag = 2 ;
109#if TARGET_API_MAC_OSX
110 iControlTags[2] = kTXNVisibilityTag ;
111 iControlData[2].uValue = visible ;
112 toptag++ ;
113#endif
114
115 if ( wxStyle & wxTE_MULTILINE )
116 {
117 if (wxStyle & wxTE_DONTWRAP)
118 iControlData[1].uValue = kTXNNoAutoWrap ;
119 else
120 iControlData[1].uValue = kTXNAutoWrap ;
121
122 }
123 verify_noerr( TXNSetTXNObjectControls( txn, false, toptag,
124 iControlTags, iControlData )) ;
125
126 Str255 fontName ;
127 SInt16 fontSize ;
128 Style fontStyle ;
129
130 GetThemeFont(kThemeSystemFont , GetApplicationScript() , fontName , &fontSize , &fontStyle ) ;
131
132 TXNTypeAttributes typeAttr[] =
133 {
134 { kTXNQDFontNameAttribute , kTXNQDFontNameAttributeSize , { (void*) fontName } } ,
135 { kTXNQDFontSizeAttribute , kTXNFontSizeAttributeSize , { (void*) (fontSize << 16) } } ,
136 { kTXNQDFontStyleAttribute , kTXNQDFontStyleAttributeSize , { (void*) normal } } ,
137 } ;
138
139 verify_noerr( TXNSetTypeAttributes (txn, sizeof( typeAttr ) / sizeof(TXNTypeAttributes) , typeAttr,
140 kTXNStartOffset,
141 kTXNEndOffset) );
142
143}
144
145#if !wxMAC_USE_MLTE_HIVIEW
29b30405 146
7759d157
SC
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
72055702 151
72055702
SC
152/* part codes */
153
154/* kmUPTextPart is the part code we return to indicate the user has clicked
ed8c2780 155 in the text area of our control */
72055702
SC
156#define kmUPTextPart 1
157
72055702
SC
158
159/* routines for using existing user pane controls.
ed8c2780
RR
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
162 text edit field.*/
ef4a634b 163
72055702
SC
164/* Utility Routines */
165
72055702 166/* kUserClickedToFocusPart is a part code we pass to the SetKeyboardFocus
ed8c2780
RR
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'. */
72055702
SC
170#define kUserClickedToFocusPart 100
171
72055702 172/* STPTextPaneVars is a structure used for storing the the mUP Control's
ed8c2780
RR
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. */
72055702
SC
176
177typedef struct {
ed8c2780
RR
178 /* OS records referenced */
179 TXNObject fTXNRec; /* the txn record */
180 TXNFrameID fTXNFrame; /* the txn frame ID */
facd6764 181 ControlRef fUserPaneRec; /* handle to the user pane control */
ed8c2780
RR
182 WindowPtr fOwner; /* window containing control */
183 GrafPtr fDrawingEnvironment; /* grafport where control is drawn */
184 /* flags */
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 */
facd6764
SC
187 Boolean fTXNObjectActive; /* reflects the activation state of the text edit record */
188 Boolean fFocusDrawState; /* true if focus is drawn (default: true) */
ed8c2780 189 /* calculated locations */
facd6764 190 Rect fRBounds; /* control bounds */
ed8c2780
RR
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 */
facd6764 194 RgnHandle fRTextOutlineRegion; /* background region for the text, erased before calling TEUpdate */
ed8c2780
RR
195 /* our focus advance override routine */
196 EventHandlerUPP handlerUPP;
197 EventHandlerRef handlerRef;
facd6764 198 bool fNoBorders ;
29e4a190 199 bool fMultiline ;
facd6764 200 bool fVisible ;
72055702
SC
201} STPTextPaneVars;
202
facd6764
SC
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. */
210OSStatus mUPOpenControl(STPTextPaneVars* &handle, ControlRef theControl, long wxStyle);
211
72055702
SC
212
213
214
215/* Univerals Procedure Pointer variables used by the
ed8c2780
RR
216 mUP Control. These variables are set up
217 the first time that mUPOpenControl is called. */
72055702
SC
218ControlUserPaneDrawUPP gTPDrawProc = NULL;
219ControlUserPaneHitTestUPP gTPHitProc = NULL;
220ControlUserPaneTrackingUPP gTPTrackProc = NULL;
221ControlUserPaneIdleUPP gTPIdleProc = NULL;
222ControlUserPaneKeyDownUPP gTPKeyProc = NULL;
223ControlUserPaneActivateUPP gTPActivateProc = NULL;
224ControlUserPaneFocusUPP gTPFocusProc = NULL;
225
facd6764
SC
226// one place for calculating all
227static void TPCalculateBounds(STPTextPaneVars *varsp, const Rect& bounds)
228{
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 )
234 {
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));
237 }
238 else
239 {
240 SetRect(&varsp->fRTextArea, bounds.left , bounds.top ,
241 bounds.right, bounds.bottom);
242 }
243}
244
245OSStatus MLTESetObjectVisibility( STPTextPaneVars *varsp, Boolean vis , long wxStyle)
246{
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 );
252#endif
f0091567
SC
253 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(varsp->fUserPaneRec);
254 if ( vis && textctrl )
facd6764
SC
255 {
256 Rect bounds ;
257 UMAGetControlBoundsInWindowCoords( varsp->fUserPaneRec, &bounds);
258 TPCalculateBounds( varsp , bounds ) ;
957165f1 259 wxMacWindowClipper cl(textctrl) ;
facd6764
SC
260 TXNSetFrameBounds( varsp->fTXNRec, varsp->fRTextArea.top, varsp->fRTextArea.left,
261 varsp->fRTextArea.bottom, varsp->fRTextArea.right, varsp->fTXNFrame);
262 TXNShowSelection( varsp->fTXNRec, kTXNShowStart);
263 }
264 return err ;
265}
266
267// make sure we don't miss changes as carbon events are not available for these under classic
268static void TPUpdateVisibility(ControlRef theControl) {
269 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
270 if ( textctrl == NULL )
271 return ;
272
273 STPTextPaneVars *varsp = (STPTextPaneVars *) textctrl->m_macTXNvars ;
ef4a634b 274
facd6764
SC
275 Rect bounds ;
276 UMAGetControlBoundsInWindowCoords(theControl, &bounds);
277 if ( textctrl->MacIsReallyShown() != varsp->fVisible )
278 {
279 // invalidate old position
280 // InvalWindowRect( GetControlOwner( theControl ) , &varsp->fRBounds ) ;
281 varsp->fVisible = textctrl->MacIsReallyShown() ;
282 }
283 if ( !EqualRect( &bounds , &varsp->fRBounds ) )
284 {
285 // old position
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 )
290 {
957165f1 291 wxMacWindowClipper cl(textctrl) ;
f0091567 292 TXNSetFrameBounds( varsp->fTXNRec, varsp->fRTextArea.top, varsp->fRTextArea.left,
facd6764
SC
293 varsp->fRTextArea.bottom, varsp->fRTextArea.right, varsp->fTXNFrame);
294 }
295 InvalWindowRect( GetControlOwner( theControl ) , &oldBounds ) ;
296 InvalWindowRect( GetControlOwner( theControl ) , &varsp->fRBounds ) ;
297 }
298}
ef4a634b 299
facd6764
SC
300// make correct activations
301static void TPActivatePaneText(STPTextPaneVars *varsp, Boolean setActive) {
7759d157 302
facd6764
SC
303 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(varsp->fUserPaneRec);
304 if (varsp->fTXNObjectActive != setActive && textctrl->MacIsReallyShown() )
305 {
306 varsp->fTXNObjectActive = setActive;
307 TXNActivate(varsp->fTXNRec, varsp->fTXNFrame, varsp->fTXNObjectActive);
ed8c2780 308 if (varsp->fInFocus)
facd6764 309 TXNFocus( varsp->fTXNRec, varsp->fTXNObjectActive);
ed8c2780 310 }
72055702
SC
311}
312
facd6764
SC
313// update focus outlines
314static void TPRedrawFocusOutline(STPTextPaneVars *varsp) {
72055702 315
facd6764
SC
316 /* state changed */
317 if (varsp->fFocusDrawState != (varsp->fIsActive && varsp->fInFocus))
318 {
319 varsp->fFocusDrawState = (varsp->fIsActive && varsp->fInFocus);
320 DrawThemeFocusRect(&varsp->fRFocusOutline, varsp->fFocusDrawState);
321 }
322}
323
324// update TXN focus state
325static void TPFocusPaneText(STPTextPaneVars *varsp, Boolean setFocus) {
326 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(varsp->fUserPaneRec);
327
328 if (varsp->fInFocus != setFocus && textctrl->MacIsReallyShown()) {
ed8c2780
RR
329 varsp->fInFocus = setFocus;
330 TXNFocus( varsp->fTXNRec, varsp->fInFocus);
331 }
72055702
SC
332}
333
facd6764 334// draw the control
72055702 335static pascal void TPPaneDrawProc(ControlRef theControl, ControlPartCode thePart) {
ed8c2780 336 /* set up our globals */
ef4a634b 337
facd6764
SC
338 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
339 if ( textctrl == NULL )
340 return ;
341 TPUpdateVisibility( theControl ) ;
342
343 STPTextPaneVars *varsp = (STPTextPaneVars *) textctrl->m_macTXNvars ;
344 if ( textctrl->MacIsReallyShown() )
345 {
346 wxMacWindowClipper clipper( textctrl ) ;
347 TXNDraw(varsp->fTXNRec, NULL);
348 if ( !varsp->fNoBorders )
349 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
350 TPRedrawFocusOutline( varsp ) ;
ed8c2780 351 }
facd6764 352
72055702
SC
353}
354
355
356/* TPPaneHitTestProc is called when the control manager would
ed8c2780
RR
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. */
facd6764 360static pascal ControlPartCode TPPaneHitTestProc(ControlRef theControl, Point where) {
ed8c2780 361 ControlPartCode result;
ed8c2780
RR
362 /* set up our locals and lock down our globals*/
363 result = 0;
facd6764
SC
364 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
365 if ( textctrl == NULL )
366 return 0 ;
367 TPUpdateVisibility( theControl ) ;
368 STPTextPaneVars *varsp = (STPTextPaneVars *) textctrl->m_macTXNvars ;
369 if (textctrl->MacIsReallyShown() )
370 {
371 if (PtInRect(where, &varsp->fRBounds))
ed8c2780 372 result = kmUPTextPart;
facd6764
SC
373 else
374 result = 0;
ed8c2780
RR
375 }
376 return result;
72055702
SC
377}
378
379
380
381
382
383/* TPPaneTrackingProc is called when the mouse is being held down
ed8c2780
RR
384 over our control. This routine handles clicks in the text area
385 and in the scroll bar. */
facd6764
SC
386static pascal ControlPartCode TPPaneTrackingProc(ControlRef theControl, Point startPt, ControlActionUPP actionProc) {
387
ed8c2780 388 ControlPartCode partCodeResult;
facd6764 389 /* make sure we have some variables... */
ed8c2780 390 partCodeResult = 0;
facd6764
SC
391 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
392 if ( textctrl == NULL )
393 return 0;
394 TPUpdateVisibility( theControl ) ;
395 STPTextPaneVars *varsp = (STPTextPaneVars *) textctrl->m_macTXNvars ;
396 if (textctrl->MacIsReallyShown() )
397 {
398 /* we don't do any of these functions unless we're in focus */
ed8c2780
RR
399 if ( ! varsp->fInFocus) {
400 WindowPtr owner;
401 owner = GetControlOwner(theControl);
402 ClearKeyboardFocus(owner);
403 SetKeyboardFocus(owner, theControl, kUserClickedToFocusPart);
404 }
facd6764
SC
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() )
408 {
409 int x = 0 , y = 0 ;
410 textctrl->MacClientToRootWindow( &x , &y ) ;
411 startPt.h += x ;
412 startPt.v += y ;
413 }
ef4a634b 414
facd6764
SC
415 switch (TPPaneHitTestProc(theControl, startPt))
416 {
417
418 /* handle clicks in the text part */
ed8c2780 419 case kmUPTextPart:
facd6764
SC
420 {
421 wxMacWindowClipper clipper( textctrl ) ;
422
423 EventRecord rec ;
424 ConvertEventRefToEventRecord( (EventRef) wxTheApp->MacGetCurrentEvent() , &rec ) ;
425 TXNClick( varsp->fTXNRec, &rec );
426
427 }
ed8c2780 428 break;
facd6764 429
ed8c2780 430 }
ed8c2780
RR
431 }
432 return partCodeResult;
72055702
SC
433}
434
435
436/* TPPaneIdleProc is our user pane idle routine. When our text field
ed8c2780 437 is active and in focus, we use this routine to set the cursor. */
facd6764 438static pascal void TPPaneIdleProc(ControlRef theControl) {
ed8c2780 439 /* set up locals */
facd6764
SC
440 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
441 if ( textctrl == NULL )
442 return ;
443 TPUpdateVisibility( theControl ) ;
444 STPTextPaneVars *varsp = (STPTextPaneVars *) textctrl->m_macTXNvars ;
445 if (textctrl->MacIsReallyShown()) {
ed8c2780 446 /* if we're not active, then we have nothing to say about the cursor */
facd6764 447 if (varsp->fIsActive) {
ed8c2780
RR
448 Rect bounds;
449 Point mousep;
facd6764
SC
450
451 wxMacWindowClipper clipper( textctrl ) ;
ed8c2780
RR
452 GetMouse(&mousep);
453 /* there's a 'focus thing' and an 'unfocused thing' */
454 if (varsp->fInFocus) {
455 /* flash the cursor */
facd6764 456 SetPort(varsp->fDrawingEnvironment);
ed8c2780
RR
457 TXNIdle(varsp->fTXNRec);
458 /* set the cursor */
459 if (PtInRect(mousep, &varsp->fRTextArea)) {
460 RgnHandle theRgn;
461 RectRgn((theRgn = NewRgn()), &varsp->fRTextArea);
462 TXNAdjustCursor(varsp->fTXNRec, theRgn);
463 DisposeRgn(theRgn);
ef4a634b
RD
464 }
465 else
2b5f62a0
VZ
466 {
467 // SetThemeCursor(kThemeArrowCursor);
468 }
ed8c2780
RR
469 } else {
470 /* if it's in our bounds, set the cursor */
facd6764 471 UMAGetControlBoundsInWindowCoords(theControl, &bounds);
ed8c2780 472 if (PtInRect(mousep, &bounds))
2b5f62a0
VZ
473 {
474 // SetThemeCursor(kThemeArrowCursor);
475 }
ed8c2780 476 }
ed8c2780
RR
477 }
478 }
72055702
SC
479}
480
481
482/* TPPaneKeyDownProc is called whenever a keydown event is directed
ed8c2780
RR
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. */
facd6764 485static pascal ControlPartCode TPPaneKeyDownProc(ControlRef theControl,
ed8c2780 486 SInt16 keyCode, SInt16 charCode, SInt16 modifiers) {
facd6764
SC
487
488 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
489 if ( textctrl == NULL )
490 return 0;
491 TPUpdateVisibility( theControl ) ;
492
493 STPTextPaneVars *varsp = (STPTextPaneVars *) textctrl->m_macTXNvars ;
494 if (varsp->fInFocus)
495 {
496 /* turn autoscrolling on and send the key event to text edit */
497 wxMacWindowClipper clipper( textctrl ) ;
498 EventRecord ev ;
499 memset( &ev , 0 , sizeof( ev ) ) ;
500 ev.what = keyDown ;
501 ev.modifiers = modifiers ;
502 ev.message = (( keyCode << 8 ) & keyCodeMask ) + ( charCode & charCodeMask ) ;
503 TXNKeyDown( varsp->fTXNRec, &ev);
ed8c2780
RR
504 }
505 return kControlEntireControl;
72055702
SC
506}
507
508
509/* TPPaneActivateProc is called when the window containing
ed8c2780
RR
510 the user pane control receives activate events. Here, we redraw
511 the control and it's text as necessary for the activation state. */
facd6764 512static pascal void TPPaneActivateProc(ControlRef theControl, Boolean activating) {
ed8c2780 513 /* set up locals */
facd6764
SC
514 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
515
516 if ( textctrl == NULL )
517 return ;
518 TPUpdateVisibility( theControl ) ;
519
520 STPTextPaneVars *varsp = (STPTextPaneVars *) textctrl->m_macTXNvars ;
521
522 varsp->fIsActive = activating;
523 wxMacWindowClipper clipper( textctrl ) ;
524 TPActivatePaneText(varsp, varsp->fIsActive && varsp->fInFocus);
525 /* redraw the frame */
526 if ( textctrl->MacIsReallyShown() )
527 {
528 if ( !varsp->fNoBorders )
529 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
530 TPRedrawFocusOutline( varsp ) ;
ed8c2780 531 }
72055702
SC
532}
533
534
535/* TPPaneFocusProc is called when every the focus changes to or
ed8c2780
RR
536 from our control. Herein, switch the focus appropriately
537 according to the parameters and redraw the control as
538 necessary. */
facd6764 539static pascal ControlPartCode TPPaneFocusProc(ControlRef theControl, ControlFocusPart action) {
ed8c2780 540 ControlPartCode focusResult;
facd6764 541
ed8c2780 542 focusResult = kControlFocusNoPart;
facd6764
SC
543 wxTextCtrl* textctrl = (wxTextCtrl*) GetControlReference(theControl);
544 if ( textctrl == NULL )
545 return 0;
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:
555
556 kControlFocusNoPart - turn off focus and return kControlFocusNoPart. redraw
557 the control and the focus rectangle as necessary.
558
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 */
566 switch (action) {
567 default:
568 case kControlFocusNoPart:
569 TPFocusPaneText(varsp, false);
570 focusResult = kControlFocusNoPart;
571 break;
572 case kUserClickedToFocusPart:
573 TPFocusPaneText(varsp, true);
574 focusResult = 1;
575 break;
576 case kControlFocusPrevPart:
577 case kControlFocusNextPart:
578 TPFocusPaneText(varsp, ( ! varsp->fInFocus));
579 focusResult = varsp->fInFocus ? 1 : kControlFocusNoPart;
580 break;
581 }
582 TPActivatePaneText(varsp, varsp->fIsActive && varsp->fInFocus);
583 /* redraw the text fram and focus rectangle to indicate the
584 new focus state */
585 if ( textctrl->MacIsReallyShown() )
586 {
587 wxMacWindowClipper c( textctrl ) ;
588 if ( !varsp->fNoBorders )
589 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
590 TPRedrawFocusOutline( varsp ) ;
ed8c2780 591 }
1b2b1638 592 return focusResult;
72055702
SC
593}
594
72055702 595
1b2b1638 596/* mUPOpenControl initializes a user pane control so it will be drawn
29e4a190
RR
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. */
facd6764 603OSStatus mUPOpenControl(STPTextPaneVars* &handle, ControlRef theControl, long wxStyle )
1b2b1638 604{
29e4a190
RR
605 Rect bounds;
606 WindowRef theWindow;
facd6764 607 STPTextPaneVars *varsp;
29b30405 608 OSStatus err = noErr ;
ef4a634b 609
29e4a190
RR
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);
ef4a634b 618
29e4a190 619 /* allocate our private storage */
facd6764
SC
620 varsp = (STPTextPaneVars *) malloc(sizeof(STPTextPaneVars));
621 handle = varsp ;
622
29e4a190 623 /* set the initial settings for our private data */
29b30405 624 varsp->fMultiline = wxStyle & wxTE_MULTILINE ;
facd6764 625 varsp->fNoBorders = wxStyle & wxNO_BORDER ;
29e4a190
RR
626 varsp->fInFocus = false;
627 varsp->fIsActive = true;
facd6764
SC
628 varsp->fTXNObjectActive = false;
629 varsp->fFocusDrawState = false ;
29e4a190 630 varsp->fUserPaneRec = theControl;
facd6764
SC
631 varsp->fVisible = true ;
632
29e4a190 633 theWindow = varsp->fOwner = GetControlOwner(theControl);
1b2b1638
SC
634
635 varsp->fDrawingEnvironment = (GrafPtr) GetWindowPort(theWindow);
72055702 636
1b2b1638
SC
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);
f0091567 645
1b2b1638 646 /* calculate the rectangles used by the control */
facd6764
SC
647 UMAGetControlBoundsInWindowCoords(theControl, &bounds);
648 varsp->fRTextOutlineRegion = NewRgn() ;
649 TPCalculateBounds( varsp , bounds ) ;
72055702 650
1b2b1638
SC
651 /* set up the drawing environment */
652 SetPort(varsp->fDrawingEnvironment);
653
654 /* create the new edit field */
ef4a634b 655
587bc950 656 TXNFrameOptions frameOptions = FrameOptionsFromWXStyle( wxStyle ) ;
ef4a634b 657
facd6764 658 verify_noerr(TXNNewObject(NULL, varsp->fOwner, &varsp->fRTextArea,
2b5f62a0 659 frameOptions ,
1b2b1638
SC
660 kTXNTextEditStyleFrameType,
661 kTXNTextensionFile,
ef4a634b 662 kTXNSystemDefaultEncoding,
facd6764
SC
663 &varsp->fTXNRec, &varsp->fTXNFrame, (TXNObjectRefcon) varsp));
664
587bc950 665 AdjustAttributesFromWXStyle( varsp->fTXNRec , wxStyle , varsp->fVisible ) ;
1b2b1638
SC
666 /* perform final activations and setup for our text field. Here,
667 we assume that the window is going to be the 'active' window. */
facd6764 668 TPActivatePaneText(varsp, varsp->fIsActive && varsp->fInFocus);
ed8c2780 669 /* all done */
29b30405 670 return err;
72055702
SC
671}
672
587bc950
SC
673#else
674struct STPTextPaneVars
675{
676} ;
1b2b1638 677
72055702
SC
678#endif
679
facd6764 680static void SetTXNData( STPTextPaneVars *varsp, TXNObject txn , const wxString& st , TXNOffset start , TXNOffset end )
6bdd4f5d
SC
681{
682#if wxUSE_UNICODE
6bdd4f5d 683#if SIZEOF_WCHAR_T == 2
79a73b4f 684 size_t len = st.Len() ;
6bdd4f5d
SC
685 TXNSetData( txn , kTXNUnicodeTextData, (void*)st.wc_str(), len * 2,
686 start, end);
687#else
6bdd4f5d 688 wxMBConvUTF16BE converter ;
79a73b4f
SC
689 ByteCount byteBufferLen = converter.WC2MB( NULL , st.wc_str() , 0 ) ;
690 UniChar *unibuf = (UniChar*) malloc(byteBufferLen) ;
6bdd4f5d 691 converter.WC2MB( (char*) unibuf , st.wc_str() , byteBufferLen ) ;
79a73b4f 692 TXNSetData( txn , kTXNUnicodeTextData, (void*)unibuf, byteBufferLen ,
6bdd4f5d
SC
693 start, end);
694 free( unibuf ) ;
695#endif
696#else
697 wxCharBuffer text = st.mb_str(wxConvLocal) ;
698 TXNSetData( txn , kTXNTextData, (void*)text.data(), strlen( text ) ,
699 start, end);
facd6764 700#endif
6bdd4f5d
SC
701}
702
587bc950
SC
703
704#endif
705
706#if !USE_SHARED_LIBRARY
707IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
708
709BEGIN_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)
717
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)
723END_EVENT_TABLE()
724#endif
725
72055702 726// Text item
1fa29bdc 727void wxTextCtrl::Init()
72055702 728{
402679b0
SC
729 m_macTXN = NULL ;
730 m_macTXNvars = NULL ;
1fa29bdc 731
1b2b1638 732 m_editable = true ;
1fa29bdc
VZ
733 m_dirty = false;
734
29b30405 735 m_maxLength = TE_UNLIMITED_LENGTH ;
1b2b1638
SC
736}
737
738wxTextCtrl::~wxTextCtrl()
739{
587bc950 740#if wxMAC_USE_MLTE
facd6764 741 SetControlReference((ControlRef)m_macControl, 0) ;
587bc950 742#if !wxMAC_USE_MLTE_HIVIEW
facd6764 743 TXNDeleteObject((TXNObject)m_macTXN);
587bc950 744#endif
facd6764
SC
745 /* delete our private storage */
746 free(m_macTXNvars);
747 /* zero the control reference */
587bc950 748#endif
72055702
SC
749}
750
72055702
SC
751
752bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
939fba6c 753 const wxString& str,
72055702
SC
754 const wxPoint& pos,
755 const wxSize& size, long style,
756 const wxValidator& validator,
757 const wxString& name)
758{
facd6764
SC
759 m_macIsUserPane = FALSE ;
760
e40298d5
JS
761 m_macTXN = NULL ;
762 m_macTXNvars = NULL ;
e40298d5 763 m_editable = true ;
ef4a634b 764
72055702 765 // base initialization
b657d5db 766 if ( !wxTextCtrlBase::Create(parent, id, pos, size, style & ~(wxHSCROLL|wxVSCROLL), validator, name) )
72055702
SC
767 return FALSE;
768
ed8c2780 769 wxSize mySize = size ;
ef4a634b 770
facd6764 771 Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ;
72055702
SC
772
773 if ( m_windowStyle & wxTE_MULTILINE )
774 {
775 wxASSERT_MSG( !(m_windowStyle & wxTE_PROCESS_ENTER),
776 wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") );
777
778 m_windowStyle |= wxTE_PROCESS_ENTER;
779 }
780
939fba6c 781 wxString st = str ;
8aa701ed 782 wxMacConvertNewlines13To10( &st ) ;
587bc950 783#if wxMAC_USE_MLTE
29e4a190 784 {
587bc950
SC
785#if wxMAC_USE_MLTE_HIVIEW
786 HIRect hr = { bounds.left , bounds.top , bounds.right - bounds.left , bounds.bottom- bounds.top } ;
d3016f30
SC
787 HIViewRef scrollView = NULL ;
788 TXNFrameOptions frameOptions = FrameOptionsFromWXStyle( style ) ;
789
790 if ( frameOptions & (kTXNWantVScrollBarMask|kTXNWantHScrollBarMask) )
791 {
792 HIScrollViewCreate(( frameOptions & kTXNWantHScrollBarMask ? kHIScrollViewOptionsHorizScroll : 0) |
793 ( frameOptions & kTXNWantVScrollBarMask ? kHIScrollViewOptionsVertScroll: 0 ) , &scrollView ) ;
794
795 HIViewSetFrame( scrollView, &hr );
796 HIViewSetVisible( scrollView, true );
797 }
798 HIViewRef textView ;
799 HITextViewCreate( NULL , 0, frameOptions , (ControlRef*) &textView ) ;
800 m_macTXN = HITextViewGetTXNObject( textView) ;
801 AdjustAttributesFromWXStyle( (TXNObject) m_macTXN , style , true ) ;
802 HIViewSetVisible( (ControlRef) textView , true ) ;
803 if ( scrollView )
804 {
805 HIViewAddSubview( scrollView , textView ) ;
c6f9fb05 806 m_macControl = (WXWidget) scrollView ;
d3016f30
SC
807 }
808 else
809 {
c6f9fb05 810 m_macControl = (WXWidget) textView ;
d3016f30 811 }
587bc950 812#else
1b2b1638
SC
813 short featurSet;
814
29b30405 815 featurSet = kControlSupportsEmbedding | kControlSupportsFocus | kControlWantsIdle
1b2b1638
SC
816 | kControlWantsActivate | kControlHandlesTracking | kControlHasSpecialBackground
817 | kControlGetsFocusOnClick | kControlSupportsLiveFeedback;
818 /* create the control */
7548762c
SC
819 verify_noerr( CreateUserPaneControl( MAC_WXHWND(GetParent()->MacGetTopLevelWindowRef()) , &bounds, featurSet , (ControlRef*) &m_macControl) ) ;
820
facd6764
SC
821 wxMacWindowClipper c(this) ;
822 STPTextPaneVars *varsp ;
823 mUPOpenControl( varsp, (ControlRef) m_macControl, m_windowStyle );
824 m_macTXNvars = varsp ;
825 m_macTXN = varsp->fTXNRec ;
587bc950
SC
826#endif
827
facd6764
SC
828 if ( style & wxTE_PASSWORD )
829 {
830 UniChar c = 0xA5 ;
831 verify_noerr(TXNEchoMode( (TXNObject) m_macTXN , c , 0 , true )) ;
832 }
29e4a190 833 }
facd6764
SC
834 MacPostControlCreate(pos,size) ;
835
587bc950 836#if !wxMAC_USE_MLTE_HIVIEW
facd6764
SC
837 if ( MacIsReallyShown() )
838 MLTESetObjectVisibility( (STPTextPaneVars*) m_macTXNvars, true , GetWindowStyle() ) ;
587bc950 839#endif
ed8c2780 840
ed8c2780 841 {
facd6764 842 wxMacWindowClipper clipper( this ) ;
587bc950 843#if !wxMAC_USE_MLTE_HIVIEW
facd6764 844 TPUpdateVisibility( (ControlRef) m_macControl ) ;
587bc950 845#endif
facd6764
SC
846 SetTXNData( (STPTextPaneVars *)m_macTXNvars , (TXNObject) m_macTXN , st , kTXNStartOffset, kTXNEndOffset ) ;
847
2b5f62a0 848 TXNSetSelection( (TXNObject) m_macTXN, 0, 0);
e600c175 849 TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart);
1b2b1638 850 }
bd3169a7
SC
851
852 // in case MLTE is catching events before we get the chance to do so, we'd have to reintroduce the tlw-handler in front :
853 // parent->MacGetTopLevelWindow()->MacInstallTopLevelWindowEventHandler() ;
ef4a634b 854
facd6764
SC
855 SetBackgroundColour( *wxWHITE ) ;
856
857 TXNBackground tback;
858 tback.bgType = kTXNBackgroundTypeRGB;
859 tback.bg.color = MAC_WXCOLORREF( GetBackgroundColour().GetPixel() );
860 TXNSetBackground( (TXNObject) m_macTXN , &tback);
861
f0091567 862#else
587bc950 863 wxMacCFStringHolder cf(st , m_font.GetEncoding()) ;
7f1de2b2
SC
864 CFStringRef cfr = cf ;
865 Boolean isPassword = ( m_windowStyle & wxTE_PASSWORD ) != 0 ;
866 CreateEditUnicodeTextControl( MAC_WXHWND(parent->MacGetTopLevelWindowRef()), &bounds , cfr , isPassword , NULL , (ControlRef*) &m_macControl ) ;
867 if ( !(m_windowStyle & wxTE_MULTILINE) )
868 {
869 Boolean singleline = true ;
870 ::SetControlData( (ControlHandle) m_macControl, kControlEditTextPart , kControlEditTextSingleLineTag , sizeof( singleline ) , &singleline ) ;
871 }
587bc950 872 MacPostControlCreate(pos,size) ;
7f1de2b2 873
f0091567 874#endif
7f1de2b2
SC
875 if ( m_windowStyle & wxTE_READONLY)
876 {
877 SetEditable( false ) ;
878 }
f0091567 879
facd6764 880
e40298d5 881 return TRUE;
72055702
SC
882}
883
facd6764
SC
884void wxTextCtrl::MacVisibilityChanged()
885{
7f1de2b2
SC
886#if wxMAC_USE_MLTE
887#if !wxMAC_USE_MLTE_HIVIEW
facd6764
SC
888 MLTESetObjectVisibility((STPTextPaneVars*) m_macTXNvars , MacIsReallyShown() , GetWindowStyle() ) ;
889 if ( !MacIsReallyShown() )
890 InvalWindowRect( GetControlOwner( (ControlHandle) m_macControl ) , &((STPTextPaneVars *)m_macTXNvars)->fRBounds ) ;
587bc950 891#endif
7f1de2b2
SC
892#else
893 if ( !(m_windowStyle & wxTE_MULTILINE) && MacIsReallyShown() )
894 {
895 // work around a refresh issue insofar as not always the entire content is shown even if this would be possible
896 ControlEditTextSelectionRec sel ;
897 CFStringRef value = NULL ;
898 Size actualSize = 0 ;
899 ResType datatag = GetWindowStyle() & wxTE_PASSWORD ?
900 kControlEditTextPasswordCFStringTag : kControlEditTextCFStringTag ;
901
902 verify_noerr( GetControlData( (ControlRef) m_macControl , 0, kControlEditTextSelectionTag,
903 sizeof(ControlEditTextSelectionRec), &sel, &actualSize ) );
904 verify_noerr( GetControlData( (ControlRef) m_macControl , 0, datatag , sizeof(CFStringRef), &value, &actualSize ) );
905
906 verify_noerr( SetControlData( (ControlRef) m_macControl , 0, datatag, sizeof(CFStringRef), &value ) );
907 verify_noerr( SetControlData( (ControlRef) m_macControl , 0, kControlEditTextSelectionTag, sizeof(ControlEditTextSelectionRec), &sel ) );
908
909 CFRelease( value ) ;
910 }
911#endif
facd6764
SC
912}
913
914void wxTextCtrl::MacEnabledStateChanged()
915{
916}
917
918
72055702
SC
919wxString wxTextCtrl::GetValue() const
920{
c5c9378c 921 wxString result ;
587bc950 922#if wxMAC_USE_MLTE
c5c9378c 923 OSStatus err ;
587bc950 924 Size actualSize = 0;
29e4a190 925 {
427ff662 926#if wxUSE_UNICODE
29e4a190 927 Handle theText ;
427ff662 928 err = TXNGetDataEncoded( ((TXNObject) m_macTXN), kTXNStartOffset, kTXNEndOffset, &theText , kTXNUnicodeTextData );
29e4a190
RR
929 // all done
930 if ( err )
931 {
c5c9378c 932 actualSize = 0 ;
29e4a190
RR
933 }
934 else
935 {
7688f0a1 936 actualSize = GetHandleSize( theText ) / sizeof( UniChar) ;
427ff662
SC
937 if ( actualSize > 0 )
938 {
facd6764
SC
939 wxChar *ptr = NULL ;
940#if SIZEOF_WCHAR_T == 2
941 ptr = new wxChar[actualSize + 1 ] ;
427ff662 942 wxStrncpy( ptr , (wxChar*) *theText , actualSize ) ;
facd6764 943
6bdd4f5d 944#else
facd6764 945 SetHandleSize( theText , ( actualSize + 1 ) * sizeof( UniChar ) ) ;
6bdd4f5d 946 HLock( theText ) ;
facd6764
SC
947 (((UniChar*)*theText)[actualSize]) = 0 ;
948 wxMBConvUTF16BE converter ;
949 size_t noChars = converter.MB2WC( NULL , (const char*)*theText , 0 ) ;
950 ptr = new wxChar[noChars + 1] ;
951
952 noChars = converter.MB2WC( ptr , (const char*)*theText , noChars ) ;
953 ptr[noChars] = 0 ;
6bdd4f5d
SC
954 HUnlock( theText ) ;
955#endif
e40298d5 956 ptr[actualSize] = 0 ;
facd6764
SC
957 result = wxString( ptr ) ;
958 delete[] ptr ;
e40298d5
JS
959 }
960 DisposeHandle( theText ) ;
29e4a190 961 }
427ff662
SC
962#else
963 Handle theText ;
964 err = TXNGetDataEncoded( ((TXNObject) m_macTXN), kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData );
965 // all done
966 if ( err )
967 {
968 actualSize = 0 ;
969 }
970 else
971 {
972 actualSize = GetHandleSize( theText ) ;
973 if ( actualSize > 0 )
974 {
975 HLock( theText ) ;
939fba6c 976 result = wxString( *theText , wxConvLocal , actualSize ) ;
427ff662
SC
977 HUnlock( theText ) ;
978 }
979 DisposeHandle( theText ) ;
980 }
981#endif
29e4a190 982 }
587bc950
SC
983#else
984 CFStringRef value = NULL ;
985 Size actualSize = 0 ;
986
987 verify_noerr( GetControlData( (ControlRef) m_macControl , 0, GetWindowStyle() & wxTE_PASSWORD ?
988 kControlEditTextPasswordCFStringTag : kControlEditTextCFStringTag,
989 sizeof(CFStringRef), &value, &actualSize ) );
990 if ( value )
991 {
992 wxMacCFStringHolder cf(value) ;
993 result = cf.AsString() ;
994 }
995#endif
8aa701ed 996 wxMacConvertNewlines10To13( &result ) ;
427ff662 997 return result ;
72055702
SC
998}
999
1000void wxTextCtrl::GetSelection(long* from, long* to) const
587bc950
SC
1001{
1002#if wxMAC_USE_MLTE
facd6764 1003 TXNGetSelection( (TXNObject) m_macTXN , (TXNOffset*) from , (TXNOffset*) to ) ;
587bc950
SC
1004#else
1005 ControlEditTextSelectionRec sel ;
1006 Size actualSize ;
1007 verify_noerr( GetControlData( (ControlRef) m_macControl , 0, kControlEditTextSelectionTag,
1008 sizeof(ControlEditTextSelectionRec), &sel, &actualSize ) );
1009 if ( from ) *from = sel.selStart ;
1010 if ( to ) *to = sel.selEnd ;
1011#endif
72055702
SC
1012}
1013
939fba6c 1014void wxTextCtrl::SetValue(const wxString& str)
72055702 1015{
facd6764
SC
1016 // optimize redraws
1017 if ( GetValue() == str )
1018 return ;
1019
939fba6c 1020 wxString st = str ;
8aa701ed 1021 wxMacConvertNewlines13To10( &st ) ;
587bc950 1022#if wxMAC_USE_MLTE
29e4a190 1023 {
facd6764 1024 wxMacWindowClipper c( this ) ;
68698f03 1025 bool formerEditable = m_editable ;
2b5f62a0
VZ
1026 if ( !formerEditable )
1027 SetEditable(true) ;
facd6764 1028
587bc950 1029#if !wxMAC_USE_MLTE_HIVIEW
facd6764
SC
1030 // otherwise scrolling might have problems ?
1031 TPUpdateVisibility( ( (STPTextPaneVars *)m_macTXNvars)->fUserPaneRec ) ;
587bc950 1032#endif
facd6764 1033 SetTXNData( (STPTextPaneVars *)m_macTXNvars , (TXNObject) m_macTXN , st , kTXNStartOffset, kTXNEndOffset ) ;
2b5f62a0 1034 TXNSetSelection( (TXNObject) m_macTXN, 0, 0);
e600c175 1035 TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart);
2b5f62a0
VZ
1036 if ( !formerEditable )
1037 SetEditable(formerEditable) ;
29e4a190 1038 }
587bc950
SC
1039#else
1040 wxMacCFStringHolder cf(st , m_font.GetEncoding() ) ;
1041 CFStringRef value = cf ;
1042 verify_noerr( SetControlData( (ControlRef) m_macControl , 0, GetWindowStyle() & wxTE_PASSWORD ?
1043 kControlEditTextPasswordCFStringTag : kControlEditTextCFStringTag,
1044 sizeof(CFStringRef), &value ) );
1045#endif
72055702
SC
1046}
1047
ef4a634b 1048void wxTextCtrl::SetMaxLength(unsigned long len)
29b30405
SC
1049{
1050 m_maxLength = len ;
1051}
1052
facd6764
SC
1053bool wxTextCtrl::SetFont( const wxFont& font )
1054{
1055 if ( !wxTextCtrlBase::SetFont( font ) )
1056 return FALSE ;
1057
587bc950 1058#if wxMAC_USE_MLTE
facd6764
SC
1059 wxMacWindowClipper c( this ) ;
1060 bool formerEditable = m_editable ;
1061 if ( !formerEditable )
1062 SetEditable(true) ;
1063
1064 TXNTypeAttributes typeAttr[4] ;
1065 Str255 fontName = "\pMonaco" ;
1066 SInt16 fontSize = 12 ;
1067 Style fontStyle = normal ;
1068 int attrCounter = 0 ;
1069
1070 wxMacStringToPascal( font.GetFaceName() , fontName ) ;
1071 fontSize = font.MacGetFontSize() ;
1072 fontStyle = font.MacGetFontStyle() ;
1073
1074 typeAttr[attrCounter].tag = kTXNQDFontNameAttribute ;
1075 typeAttr[attrCounter].size = kTXNQDFontNameAttributeSize ;
1076 typeAttr[attrCounter].data.dataPtr = (void*) fontName ;
1077 typeAttr[attrCounter+1].tag = kTXNQDFontSizeAttribute ;
1078 typeAttr[attrCounter+1].size = kTXNFontSizeAttributeSize ;
1079 typeAttr[attrCounter+1].data.dataValue = (fontSize << 16) ;
1080 typeAttr[attrCounter+2].tag = kTXNQDFontStyleAttribute ;
1081 typeAttr[attrCounter+2].size = kTXNQDFontStyleAttributeSize ;
1082 typeAttr[attrCounter+2].data.dataValue = fontStyle ;
1083 attrCounter += 3 ;
1084 /*
1085 typeAttr[attrCounter].tag = kTXNQDFontColorAttribute ;
1086 typeAttr[attrCounter].size = kTXNQDFontColorAttributeSize ;
1087 typeAttr[attrCounter].data.dataPtr = (void*) &color ;
1088 color = MAC_WXCOLORREF(GetForegroundColour().GetPixel()) ;
1089 attrCounter += 1 ;
1090 */
1091 verify_noerr( TXNSetTypeAttributes ((TXNObject)m_macTXN, attrCounter , typeAttr, kTXNStartOffset,kTXNEndOffset) );
1092
1093 if ( !formerEditable )
1094 SetEditable(formerEditable) ;
587bc950 1095#endif
facd6764
SC
1096 return true ;
1097}
1098
29b30405
SC
1099bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
1100{
587bc950 1101#if wxMAC_USE_MLTE
facd6764
SC
1102 bool formerEditable = m_editable ;
1103 if ( !formerEditable )
1104 SetEditable(true) ;
1105 TXNTypeAttributes typeAttr[4] ;
1106 Str255 fontName = "\pMonaco" ;
1107 SInt16 fontSize = 12 ;
1108 Style fontStyle = normal ;
1109 RGBColor color ;
1110 int attrCounter = 0 ;
1111 if ( style.HasFont() )
29b30405 1112 {
facd6764
SC
1113 const wxFont &font = style.GetFont() ;
1114 wxMacStringToPascal( font.GetFaceName() , fontName ) ;
1115 fontSize = font.GetPointSize() ;
1116 if ( font.GetUnderlined() )
1117 fontStyle |= underline ;
1118 if ( font.GetWeight() == wxBOLD )
1119 fontStyle |= bold ;
1120 if ( font.GetStyle() == wxITALIC )
1121 fontStyle |= italic ;
1122
1123 typeAttr[attrCounter].tag = kTXNQDFontNameAttribute ;
1124 typeAttr[attrCounter].size = kTXNQDFontNameAttributeSize ;
1125 typeAttr[attrCounter].data.dataPtr = (void*) fontName ;
1126 typeAttr[attrCounter+1].tag = kTXNQDFontSizeAttribute ;
1127 typeAttr[attrCounter+1].size = kTXNFontSizeAttributeSize ;
1128 typeAttr[attrCounter+1].data.dataValue = (fontSize << 16) ;
1129 typeAttr[attrCounter+2].tag = kTXNQDFontStyleAttribute ;
1130 typeAttr[attrCounter+2].size = kTXNQDFontStyleAttributeSize ;
1131 typeAttr[attrCounter+2].data.dataValue = fontStyle ;
1132 attrCounter += 3 ;
1133
1134 }
1135 if ( style.HasTextColour() )
1136 {
1137 typeAttr[attrCounter].tag = kTXNQDFontColorAttribute ;
1138 typeAttr[attrCounter].size = kTXNQDFontColorAttributeSize ;
1139 typeAttr[attrCounter].data.dataPtr = (void*) &color ;
1140 color = MAC_WXCOLORREF(style.GetTextColour().GetPixel()) ;
1141 attrCounter += 1 ;
1142 }
ef4a634b 1143
facd6764
SC
1144 if ( attrCounter > 0 )
1145 {
1146 verify_noerr( TXNSetTypeAttributes ((TXNObject)m_macTXN, attrCounter , typeAttr, start,end) );
29b30405 1147 }
facd6764
SC
1148 if ( !formerEditable )
1149 SetEditable(formerEditable) ;
587bc950 1150#endif
29b30405
SC
1151 return TRUE ;
1152}
1153
1154bool wxTextCtrl::SetDefaultStyle(const wxTextAttr& style)
1155{
1156 wxTextCtrlBase::SetDefaultStyle( style ) ;
1157 SetStyle( kTXNUseCurrentSelection , kTXNUseCurrentSelection , GetDefaultStyle() ) ;
1158 return TRUE ;
1159}
1160
72055702
SC
1161// Clipboard operations
1162void wxTextCtrl::Copy()
1163{
1164 if (CanCopy())
1165 {
587bc950 1166#if wxMAC_USE_MLTE
facd6764
SC
1167 ClearCurrentScrap();
1168 TXNCopy((TXNObject)m_macTXN);
1169 TXNConvertToPublicScrap();
587bc950 1170#endif
32b5be3d 1171 }
72055702
SC
1172}
1173
1174void wxTextCtrl::Cut()
1175{
1176 if (CanCut())
1177 {
587bc950 1178#if wxMAC_USE_MLTE
facd6764
SC
1179 ClearCurrentScrap();
1180 TXNCut((TXNObject)m_macTXN);
1181 TXNConvertToPublicScrap();
587bc950 1182#endif
1b2b1638
SC
1183 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
1184 event.SetString( GetValue() ) ;
1185 event.SetEventObject( this );
1186 GetEventHandler()->ProcessEvent(event);
29e4a190 1187 }
72055702
SC
1188}
1189
1190void wxTextCtrl::Paste()
1191{
1192 if (CanPaste())
1193 {
587bc950 1194#if wxMAC_USE_MLTE
facd6764
SC
1195 TXNConvertFromPublicScrap();
1196 TXNPaste((TXNObject)m_macTXN);
1197 SetStyle( kTXNUseCurrentSelection , kTXNUseCurrentSelection , GetDefaultStyle() ) ;
587bc950 1198#endif
1b2b1638
SC
1199 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
1200 event.SetString( GetValue() ) ;
1201 event.SetEventObject( this );
1202 GetEventHandler()->ProcessEvent(event);
32b5be3d 1203 }
72055702
SC
1204}
1205
1206bool wxTextCtrl::CanCopy() const
1207{
1208 // Can copy if there's a selection
1209 long from, to;
1210 GetSelection(& from, & to);
1211 return (from != to);
1212}
1213
1214bool wxTextCtrl::CanCut() const
1215{
1b2b1638
SC
1216 if ( !IsEditable() )
1217 {
1218 return false ;
1219 }
72055702
SC
1220 // Can cut if there's a selection
1221 long from, to;
1222 GetSelection(& from, & to);
1223 return (from != to);
1224}
1225
1226bool wxTextCtrl::CanPaste() const
1227{
1228 if (!IsEditable())
1229 return FALSE;
1230
587bc950 1231#if wxMAC_USE_MLTE
facd6764 1232 return TXNIsScrapPastable() ;
587bc950
SC
1233#else
1234 return true ;
1235#endif
72055702
SC
1236}
1237
1238void wxTextCtrl::SetEditable(bool editable)
1239{
1b2b1638
SC
1240 if ( editable != m_editable )
1241 {
1242 m_editable = editable ;
587bc950 1243#if wxMAC_USE_MLTE
facd6764
SC
1244 TXNControlTag tag[] = { kTXNIOPrivilegesTag } ;
1245 TXNControlData data[] = { { editable ? kTXNReadWrite : kTXNReadOnly } } ;
1246 TXNSetTXNObjectControls( (TXNObject) m_macTXN , false , sizeof(tag) / sizeof (TXNControlTag) , tag , data ) ;
7f1de2b2
SC
1247#else
1248 Boolean value = !editable ;
1249 ::SetControlData( (ControlHandle) m_macControl, 0, kControlEditTextLockedTag , sizeof( value ) , &value ) ;
587bc950 1250#endif
1b2b1638 1251 }
72055702
SC
1252}
1253
1254void wxTextCtrl::SetInsertionPoint(long pos)
1255{
ed8c2780 1256 SetSelection( pos , pos ) ;
72055702
SC
1257}
1258
1259void wxTextCtrl::SetInsertionPointEnd()
1260{
1261 long pos = GetLastPosition();
1262 SetInsertionPoint(pos);
1263}
1264
1265long wxTextCtrl::GetInsertionPoint() const
1266{
e40298d5
JS
1267 long begin,end ;
1268 GetSelection( &begin , &end ) ;
1269 return begin ;
72055702
SC
1270}
1271
1272long wxTextCtrl::GetLastPosition() const
1273{
587bc950
SC
1274 long actualsize = 0 ;
1275#if wxMAC_USE_MLTE
7548762c 1276 Handle theText ;
facd6764
SC
1277 OSErr err = TXNGetDataEncoded( (TXNObject) m_macTXN, kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData );
1278 /* all done */
1279 if ( err )
32b5be3d 1280 {
facd6764 1281 actualsize = 0 ;
32b5be3d
RR
1282 }
1283 else
1284 {
facd6764
SC
1285 actualsize = GetHandleSize( theText ) ;
1286 DisposeHandle( theText ) ;
32b5be3d 1287 }
587bc950 1288#endif
facd6764 1289 return actualsize ;
72055702
SC
1290}
1291
939fba6c 1292void wxTextCtrl::Replace(long from, long to, const wxString& str)
72055702 1293{
587bc950 1294#if wxMAC_USE_MLTE
939fba6c 1295 wxString value = str ;
de0bc932 1296 wxMacConvertNewlines13To10( &value ) ;
facd6764
SC
1297
1298 bool formerEditable = m_editable ;
1299 if ( !formerEditable )
1300 SetEditable(true) ;
1301 TXNSetSelection( ((TXNObject) m_macTXN) , from , to ) ;
1302 TXNClear( ((TXNObject) m_macTXN) ) ;
1303 SetTXNData( (STPTextPaneVars *)m_macTXNvars , (TXNObject) m_macTXN , str , kTXNUseCurrentSelection, kTXNUseCurrentSelection ) ;
1304 if ( !formerEditable )
1305 SetEditable( formerEditable ) ;
1306
32b5be3d 1307 Refresh() ;
587bc950 1308#endif
72055702
SC
1309}
1310
1311void wxTextCtrl::Remove(long from, long to)
1312{
587bc950 1313#if wxMAC_USE_MLTE
facd6764
SC
1314 bool formerEditable = m_editable ;
1315 if ( !formerEditable )
1316 SetEditable(true) ;
1317 TXNSetSelection( ((TXNObject) m_macTXN) , from , to ) ;
1318 TXNClear( ((TXNObject) m_macTXN) ) ;
1319 if ( !formerEditable )
1320 SetEditable( formerEditable ) ;
ef4a634b 1321
ed8c2780 1322 Refresh() ;
587bc950 1323#endif
72055702
SC
1324}
1325
1326void wxTextCtrl::SetSelection(long from, long to)
1327{
587bc950 1328#if wxMAC_USE_MLTE
facd6764
SC
1329 /* change the selection */
1330 if ((from == -1) && (to == -1))
1331 TXNSelectAll((TXNObject) m_macTXN);
e40298d5 1332 else
587bc950 1333 TXNSetSelection( (TXNObject) m_macTXN, from, to);
facd6764 1334 TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart);
587bc950
SC
1335#else
1336 ControlEditTextSelectionRec sel ;
1337 sel.selStart = from ;
1338 sel.selEnd = to ;
1339 verify_noerr( SetControlData( (ControlRef) m_macControl , 0, kControlEditTextSelectionTag,
1340 sizeof(ControlEditTextSelectionRec), &sel ) );
1341
1342#endif
72055702
SC
1343}
1344
1345bool wxTextCtrl::LoadFile(const wxString& file)
1346{
1347 if ( wxTextCtrlBase::LoadFile(file) )
1348 {
1349 return TRUE;
1350 }
1351
1352 return FALSE;
1353}
1354
7548762c
SC
1355class wxMacFunctor
1356{
1357public :
1358 wxMacFunctor(){}
1359 virtual ~wxMacFunctor() {}
1360 virtual void* operator()() = 0 ;
1361 static void* CallBackProc(void *param)
1362 {
1363 wxMacFunctor* f = (wxMacFunctor*) param ;
1364 void *result = (*f)() ;
1365 return result ;
1366 }
1367} ;
1368
1369template<typename classtype,typename param1type>
1370class wxMacObjectFunctor1 : public wxMacFunctor
1371{
1372 typedef void (classtype::*function)( param1type p1 ) ;
1373 typedef void (classtype::*ref_function)( const param1type& p1 ) ;
1374public :
1375 wxMacObjectFunctor1( classtype *obj , function f , param1type p1 ) :
1376 wxMacFunctor( )
1377 {
1378 m_object = obj ;
1379 m_function = f ;
1380 m_param1 = p1 ;
1381 }
1382
1383 wxMacObjectFunctor1( classtype *obj , ref_function f , param1type p1 ) :
1384 wxMacFunctor( )
1385 {
1386 m_object = obj ;
1387 m_refFunction = f ;
1388 m_param1 = p1 ;
1389 }
1390
1391 ~wxMacObjectFunctor1() {}
1392
1393 virtual void* operator()()
1394 {
1395 (m_object->*m_function)(m_param1) ;
1396 return NULL ;
1397 }
1398private :
1399 classtype* m_object ;
1400 param1type m_param1 ;
1401 union
1402 {
1403 function m_function ;
1404 ref_function m_refFunction ;
1405 } ;
1406} ;
1407
1408template<typename classtype, typename param1type>
1409void* wxMacMPRemoteCall( classtype *object , void (classtype::*function)( param1type p1 ) , param1type p1 )
1410{
1411 wxMacObjectFunctor1<classtype,param1type> params(object,function,p1) ;
1412 void *result =
1413 MPRemoteCall( wxMacFunctor::CallBackProc , &params , kMPOwningProcessRemoteContext ) ;
1414 return result ;
1415}
1416
1417template<typename classtype, typename param1type>
1418void* wxMacMPRemoteCall( classtype *object , void (classtype::*function)( const param1type& p1 ) , param1type p1 )
1419{
1420 wxMacObjectFunctor1<classtype,param1type> params(object,function,p1) ;
1421 void *result =
1422 MPRemoteCall( wxMacFunctor::CallBackProc , &params , kMPOwningProcessRemoteContext ) ;
1423 return result ;
1424}
1425
1426template<typename classtype, typename param1type>
1427void* wxMacMPRemoteGUICall( classtype *object , void (classtype::*function)( param1type p1 ) , param1type p1 )
1428{
1429 wxMutexGuiLeave() ;
1430 void *result = wxMacMPRemoteCall( object , function , p1 ) ;
1431 wxMutexGuiEnter() ;
1432 return result ;
1433}
1434
1435template<typename classtype, typename param1type>
1436void* wxMacMPRemoteGUICall( classtype *object , void (classtype::*function)( const param1type& p1 ) , param1type p1 )
1437{
1438 wxMutexGuiLeave() ;
1439 void *result = wxMacMPRemoteCall( object , function , p1 ) ;
1440 wxMutexGuiEnter() ;
1441 return result ;
1442}
1443
939fba6c 1444void wxTextCtrl::WriteText(const wxString& str)
ef4a634b 1445{
7548762c 1446 if ( !wxIsMainThread() )
587bc950 1447 {
cfeff6f7
SC
1448 // unfortunately CW 8 is not able to correctly deduce the template types, so we have
1449 // to instantiate explicitely
1450 wxMacMPRemoteGUICall<wxTextCtrl,wxString>( this , &wxTextCtrl::WriteText , str ) ;
7548762c 1451 return ;
587bc950 1452 }
7548762c
SC
1453 else
1454 {
1455 wxString st = str ;
1456 wxMacConvertNewlines13To10( &st ) ;
1457 #if wxMAC_USE_MLTE
1458 bool formerEditable = m_editable ;
1459 if ( !formerEditable )
1460 SetEditable(true) ;
1461 {
1462 wxMacWindowStateSaver s( this ) ;
1463 long start , end , dummy ;
1464 GetSelection( &start , &dummy ) ;
1465 SetTXNData( (STPTextPaneVars *)m_macTXNvars , (TXNObject) m_macTXN , st , kTXNUseCurrentSelection, kTXNUseCurrentSelection ) ;
1466 GetSelection( &dummy , &end ) ;
1467 SetStyle( start , end , GetDefaultStyle() ) ;
1468 }
1469 if ( !formerEditable )
1470 SetEditable( formerEditable ) ;
facd6764 1471
7548762c
SC
1472 MacRedrawControl() ;
1473 #else
1474 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
1475 wxMacCFStringHolder cf(st , m_font.GetEncoding() ) ;
1476 CFStringRef value = cf ;
1477 SetControlData( (ControlRef) m_macControl , 0, kControlEditTextInsertCFStringRefTag,
1478 sizeof(CFStringRef), &value );
1479 #else
1480 wxString val = GetValue() ;
1481 long start , end ;
1482 GetSelection( &start , &end ) ;
1483 val.Remove( start , end - start ) ;
1484 val.insert( start , str ) ;
1485 SetValue( val ) ;
57ab966b 1486 SetInsertionPoint( start + str.Length() ) ;
7548762c
SC
1487 #endif
1488 #endif
1489 }
72055702
SC
1490}
1491
1492void wxTextCtrl::AppendText(const wxString& text)
1493{
1494 SetInsertionPointEnd();
1495 WriteText(text);
1496}
1497
1498void wxTextCtrl::Clear()
1499{
587bc950 1500#if wxMAC_USE_MLTE
facd6764
SC
1501 bool formerEditable = m_editable ;
1502 if ( !formerEditable )
1503 SetEditable(true) ;
1504 TXNSetSelection( (TXNObject)m_macTXN , kTXNStartOffset , kTXNEndOffset ) ;
1505 TXNClear((TXNObject)m_macTXN);
1506
1507 if ( !formerEditable )
1508 SetEditable( formerEditable ) ;
1509
32b5be3d 1510 Refresh() ;
587bc950
SC
1511#else
1512 SetValue(wxEmptyString) ;
1513#endif
72055702
SC
1514}
1515
1516bool wxTextCtrl::IsModified() const
1517{
1fa29bdc 1518 return m_dirty;
72055702
SC
1519}
1520
1521bool wxTextCtrl::IsEditable() const
1522{
1b2b1638 1523 return IsEnabled() && m_editable ;
72055702
SC
1524}
1525
1526bool wxTextCtrl::AcceptsFocus() const
1527{
1528 // we don't want focus if we can't be edited
1b2b1638 1529 return /*IsEditable() && */ wxControl::AcceptsFocus();
72055702
SC
1530}
1531
1532wxSize wxTextCtrl::DoGetBestSize() const
1533{
1534 int wText = 100 ;
ef4a634b 1535
402679b0 1536 int hText;
facd6764
SC
1537
1538 switch( m_windowVariant )
29e4a190 1539 {
facd6764
SC
1540 case wxWINDOW_VARIANT_NORMAL :
1541 hText = 22 ;
1542 break ;
1543 case wxWINDOW_VARIANT_SMALL :
1544 hText = 19 ;
1545 break ;
1546 case wxWINDOW_VARIANT_MINI :
1547 hText= 15 ;
1548 break ;
1549 default :
1550 hText = 22 ;
1551 break ;
29e4a190 1552 }
72055702 1553
cfeff6f7
SC
1554#if !wxMAC_USE_MLTE
1555 // unicode text control is using client size, ie 3 pixels on every side
1556 // TODO make this fit into normal window size concept, probably having
1557 // to reintroduce the margin vars
1558 hText -= 6 ;
1559#endif
1560
72055702
SC
1561 if ( m_windowStyle & wxTE_MULTILINE )
1562 {
402679b0 1563 hText *= 5 ;
72055702 1564 }
facd6764 1565
72055702
SC
1566 return wxSize(wText, hText);
1567}
1568
1569// ----------------------------------------------------------------------------
1570// Undo/redo
1571// ----------------------------------------------------------------------------
1572
1573void wxTextCtrl::Undo()
1574{
1575 if (CanUndo())
1576 {
587bc950 1577#if wxMAC_USE_MLTE
facd6764 1578 TXNUndo((TXNObject)m_macTXN);
587bc950 1579#endif
72055702
SC
1580 }
1581}
1582
1583void wxTextCtrl::Redo()
1584{
1585 if (CanRedo())
1586 {
587bc950 1587#if wxMAC_USE_MLTE
facd6764 1588 TXNRedo((TXNObject)m_macTXN);
587bc950 1589#endif
72055702
SC
1590 }
1591}
1592
1593bool wxTextCtrl::CanUndo() const
1594{
65334b43
SC
1595 if ( !IsEditable() )
1596 {
1597 return false ;
1598 }
587bc950 1599#if wxMAC_USE_MLTE
facd6764 1600 return TXNCanUndo((TXNObject)m_macTXN,NULL);
587bc950
SC
1601#else
1602 return false ;
1603#endif
72055702
SC
1604}
1605
1606bool wxTextCtrl::CanRedo() const
1607{
65334b43
SC
1608 if ( !IsEditable() )
1609 {
1610 return false ;
1611 }
587bc950 1612#if wxMAC_USE_MLTE
facd6764 1613 return TXNCanRedo((TXNObject)m_macTXN,NULL);
587bc950
SC
1614#else
1615 return false ;
1616#endif
72055702
SC
1617}
1618
3a9fa0d6
VZ
1619// Makes modifie or unmodified
1620void wxTextCtrl::MarkDirty()
1621{
1622 m_dirty = true;
1623}
1624
72055702
SC
1625void wxTextCtrl::DiscardEdits()
1626{
1fa29bdc 1627 m_dirty = false;
72055702
SC
1628}
1629
1630int wxTextCtrl::GetNumberOfLines() const
1631{
587bc950
SC
1632 ItemCount lines = 0 ;
1633#if wxMAC_USE_MLTE
facd6764 1634 TXNGetLineCount((TXNObject)m_macTXN, &lines ) ;
587bc950 1635#endif
facd6764 1636 return lines ;
72055702
SC
1637}
1638
1639long wxTextCtrl::XYToPosition(long x, long y) const
1640{
587bc950 1641#if wxMAC_USE_MLTE
bd3169a7
SC
1642 Point curpt ;
1643
1644 long lastpos = GetLastPosition() ;
1645
1646 // TODO find a better implementation : while we can get the
1647 // line metrics of a certain line, we don't get its starting
1648 // position, so it would probably be rather a binary search
1649 // for the start position
1650 long xpos = 0 ;
1651 long ypos = 0 ;
1652 int lastHeight = 0 ;
1653
1654 ItemCount n ;
ebe86b1e 1655 for ( n = 0 ; n <= (ItemCount) lastpos ; ++n )
bd3169a7
SC
1656 {
1657 if ( y == ypos && x == xpos )
1658 return n ;
1659
1660 TXNOffsetToPoint( (TXNObject) m_macTXN, n , &curpt);
1661
1662 if ( curpt.v > lastHeight )
1663 {
1664 xpos = 0 ;
1665 if ( n > 0 )
1666 ++ypos ;
1667 lastHeight = curpt.v ;
1668 }
1669 else
1670 ++xpos ;
1671 }
587bc950 1672#endif
72055702
SC
1673 return 0;
1674}
1675
1676bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
1677{
587bc950 1678#if wxMAC_USE_MLTE
bd3169a7
SC
1679 Point curpt ;
1680
1681 long lastpos = GetLastPosition() ;
1682
1683 if ( y ) *y = 0 ;
1684 if ( x ) *x = 0 ;
1685
1686 if ( pos <= lastpos )
1687 {
1688 // TODO find a better implementation : while we can get the
1689 // line metrics of a certain line, we don't get its starting
1690 // position, so it would probably be rather a binary search
1691 // for the start position
1692 long xpos = 0 ;
1693 long ypos = 0 ;
1694 int lastHeight = 0 ;
1695
1696 ItemCount n ;
ebe86b1e 1697 for ( n = 0 ; n <= (ItemCount) pos ; ++n )
bd3169a7
SC
1698 {
1699 TXNOffsetToPoint( (TXNObject) m_macTXN, n , &curpt);
1700
1701 if ( curpt.v > lastHeight )
1702 {
1703 xpos = 0 ;
1704 if ( n > 0 )
1705 ++ypos ;
1706 lastHeight = curpt.v ;
1707 }
1708 else
1709 ++xpos ;
1710 }
1711 if ( y ) *y = ypos ;
1712 if ( x ) *x = xpos ;
1713 }
587bc950
SC
1714#else
1715 if ( y ) *y = 0 ;
1716 if ( x ) *x = 0 ;
1717#endif
72055702
SC
1718 return FALSE ;
1719}
1720
1721void wxTextCtrl::ShowPosition(long pos)
1722{
587bc950 1723#if wxMAC_USE_MLTE
3a05d58d 1724#if TARGET_RT_MAC_MACHO && defined(AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER)
3a05d58d 1725 {
f8e089e0
SC
1726 Point current ;
1727 Point desired ;
1728 TXNOffset selstart , selend ;
3a05d58d 1729 TXNGetSelection( (TXNObject) m_macTXN , &selstart , &selend) ;
f8e089e0
SC
1730 TXNOffsetToPoint( (TXNObject) m_macTXN, selstart , &current);
1731 TXNOffsetToPoint( (TXNObject) m_macTXN, pos , &desired);
1732 //TODO use HIPoints for 10.3 and above
1733 if ( (UInt32) TXNScroll != (UInt32) kUnresolvedCFragSymbolAddress )
1734 {
1735 OSErr theErr = noErr;
1736 SInt32 dv = desired.v - current.v ;
1737 SInt32 dh = desired.h - current.h ;
1738 TXNShowSelection( (TXNObject) m_macTXN , true ) ;
3a05d58d 1739 theErr = TXNScroll( (TXNObject) m_macTXN, kTXNScrollUnitsInPixels , kTXNScrollUnitsInPixels , &dv , &dh );
f8e089e0
SC
1740 wxASSERT_MSG( theErr == noErr, _T("TXNScroll returned an error!") );
1741 }
3a05d58d
SC
1742 }
1743#endif
587bc950 1744#endif
72055702
SC
1745}
1746
1747int wxTextCtrl::GetLineLength(long lineNo) const
1748{
587bc950 1749#if wxMAC_USE_MLTE
bd3169a7
SC
1750 Point curpt ;
1751 if ( lineNo < GetNumberOfLines() )
32b5be3d 1752 {
bd3169a7
SC
1753 // TODO find a better implementation : while we can get the
1754 // line metrics of a certain line, we don't get its starting
1755 // position, so it would probably be rather a binary search
1756 // for the start position
1757 long xpos = 0 ;
1758 long ypos = 0 ;
1759 int lastHeight = 0 ;
1760 long lastpos = GetLastPosition() ;
1761
1762 ItemCount n ;
ebe86b1e 1763 for ( n = 0 ; n <= (ItemCount) lastpos ; ++n )
32b5be3d 1764 {
bd3169a7
SC
1765 TXNOffsetToPoint( (TXNObject) m_macTXN, n , &curpt);
1766
1767 if ( curpt.v > lastHeight )
32b5be3d 1768 {
bd3169a7
SC
1769 if ( ypos == lineNo )
1770 return xpos ;
1771
1772 xpos = 0 ;
1773 if ( n > 0 )
1774 ++ypos ;
1775 lastHeight = curpt.v ;
29e4a190 1776 }
bd3169a7
SC
1777 else
1778 ++xpos ;
29e4a190 1779 }
29e4a190 1780 }
587bc950 1781#endif
72055702
SC
1782 return 0;
1783}
1784
1785wxString wxTextCtrl::GetLineText(long lineNo) const
1786{
bd3169a7 1787 wxString line ;
587bc950 1788#if wxMAC_USE_MLTE
7548762c 1789 Point curpt ;
e40298d5 1790 wxString content = GetValue() ;
9c641c05 1791
bd3169a7 1792 if ( lineNo < GetNumberOfLines() )
32b5be3d 1793 {
bd3169a7
SC
1794 // TODO find a better implementation : while we can get the
1795 // line metrics of a certain line, we don't get its starting
1796 // position, so it would probably be rather a binary search
1797 // for the start position
1798 long xpos = 0 ;
1799 long ypos = 0 ;
1800 int lastHeight = 0 ;
1801 long lastpos = GetLastPosition() ;
1802
1803 ItemCount n ;
ebe86b1e 1804 for ( n = 0 ; n <= (ItemCount)lastpos ; ++n )
32b5be3d 1805 {
bd3169a7 1806 TXNOffsetToPoint( (TXNObject) m_macTXN, n , &curpt);
ef4a634b 1807
bd3169a7 1808 if ( curpt.v > lastHeight )
29e4a190 1809 {
bd3169a7
SC
1810 if ( ypos == lineNo )
1811 return line ;
1812
1813 xpos = 0 ;
1814 if ( n > 0 )
1815 ++ypos ;
1816 lastHeight = curpt.v ;
1817 }
1818 else
1819 {
1820 if ( ypos == lineNo )
1821 line += content[n] ;
1822 ++xpos ;
29e4a190 1823 }
29e4a190 1824 }
29e4a190 1825 }
587bc950 1826#endif
bd3169a7 1827 return line ;
72055702
SC
1828}
1829
1830/*
1831 * Text item
1832 */
ef4a634b 1833
72055702
SC
1834void wxTextCtrl::Command(wxCommandEvent & event)
1835{
1836 SetValue (event.GetString());
1837 ProcessCommand (event);
1838}
1839
1840void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
1841{
1842 // By default, load the first file into the text window.
1843 if (event.GetNumberOfFiles() > 0)
1844 {
1845 LoadFile(event.GetFiles()[0]);
1846 }
1847}
1848
1849void wxTextCtrl::OnChar(wxKeyEvent& event)
1850{
1b2b1638
SC
1851 int key = event.GetKeyCode() ;
1852 bool eat_key = false ;
ef4a634b 1853
e600c175
SC
1854 if ( key == 'c' && event.MetaDown() )
1855 {
1856 if ( CanCopy() )
1857 Copy() ;
1858 return ;
1859 }
ef4a634b
RD
1860
1861 if ( !IsEditable() && key != WXK_LEFT && key != WXK_RIGHT && key != WXK_DOWN && key != WXK_UP && key != WXK_TAB &&
1862 !( key == WXK_RETURN && ( (m_windowStyle & wxPROCESS_ENTER) || (m_windowStyle & wxTE_MULTILINE) ) )
1b2b1638
SC
1863/* && key != WXK_PRIOR && key != WXK_NEXT && key != WXK_HOME && key != WXK_END */
1864 )
1865 {
1866 // eat it
1867 return ;
1868 }
1fa29bdc
VZ
1869
1870 // assume that any key not processed yet is going to modify the control
1871 m_dirty = true;
1872
e600c175
SC
1873 if ( key == 'v' && event.MetaDown() )
1874 {
1875 if ( CanPaste() )
1876 Paste() ;
1877 return ;
1878 }
1879 if ( key == 'x' && event.MetaDown() )
1880 {
1881 if ( CanCut() )
1882 Cut() ;
1883 return ;
1884 }
1b2b1638 1885 switch ( key )
72055702
SC
1886 {
1887 case WXK_RETURN:
ed8c2780
RR
1888 if (m_windowStyle & wxPROCESS_ENTER)
1889 {
72055702
SC
1890 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
1891 event.SetEventObject( this );
1b2b1638 1892 event.SetString( GetValue() );
72055702
SC
1893 if ( GetEventHandler()->ProcessEvent(event) )
1894 return;
ef4a634b 1895 }
72055702
SC
1896 if ( !(m_windowStyle & wxTE_MULTILINE) )
1897 {
ed8c2780 1898 wxWindow *parent = GetParent();
9c641c05
SC
1899 while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL ) {
1900 parent = parent->GetParent() ;
ed8c2780 1901 }
9c641c05 1902 if ( parent && parent->GetDefaultItem() )
ed8c2780 1903 {
9c641c05 1904 wxButton *def = wxDynamicCast(parent->GetDefaultItem(),
72055702 1905 wxButton);
ed8c2780
RR
1906 if ( def && def->IsEnabled() )
1907 {
1908 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
1909 event.SetEventObject(def);
1910 def->Command(event);
1911 return ;
72055702 1912 }
ed8c2780 1913 }
ef4a634b 1914
77ffb593 1915 // this will make wxWidgets eat the ENTER key so that
1b2b1638
SC
1916 // we actually prevent line wrapping in a single line
1917 // text control
1918 eat_key = TRUE;
72055702 1919 }
72055702
SC
1920
1921 break;
1922
1923 case WXK_TAB:
1924 // always produce navigation event - even if we process TAB
1925 // ourselves the fact that we got here means that the user code
1926 // decided to skip processing of this TAB - probably to let it
1927 // do its default job.
1928 {
1929 wxNavigationKeyEvent eventNav;
1930 eventNav.SetDirection(!event.ShiftDown());
1931 eventNav.SetWindowChange(event.ControlDown());
1932 eventNav.SetEventObject(this);
1933
1934 if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav) )
1935 return;
1b2b1638 1936
ed8c2780 1937 event.Skip() ;
1b2b1638 1938 return;
72055702
SC
1939 }
1940 break;
1941 }
ef4a634b 1942
1b2b1638 1943 if (!eat_key)
ed8c2780 1944 {
1ea39a03 1945 // perform keystroke handling
facd6764 1946 if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL )
1ea39a03
SC
1947 CallNextEventHandler((EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() , (EventRef) wxTheApp->MacGetCurrentEvent() ) ;
1948 else
1ea39a03
SC
1949 {
1950 EventRecord rec ;
1951 if ( wxMacConvertEventToRecord( (EventRef) wxTheApp->MacGetCurrentEvent() , &rec ) )
1952 {
1953 EventRecord *ev = &rec ;
1954 short keycode ;
1955 short keychar ;
1956 keychar = short(ev->message & charCodeMask);
1957 keycode = short(ev->message & keyCodeMask) >> 8 ;
1958
facd6764 1959 ::HandleControlKey( (ControlRef) m_macControl , keycode , keychar , ev->modifiers ) ;
1ea39a03
SC
1960 }
1961 }
1b2b1638 1962 }
e600c175 1963 if ( ( key >= 0x20 && key < WXK_START ) ||
45c8d9e5 1964 key == WXK_RETURN ||
ef4a634b 1965 key == WXK_DELETE ||
45c8d9e5 1966 key == WXK_BACK)
1b2b1638
SC
1967 {
1968 wxCommandEvent event1(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
1969 event1.SetString( GetValue() ) ;
1970 event1.SetEventObject( this );
45c8d9e5 1971 wxPostEvent(GetEventHandler(),event1);
ed8c2780 1972 }
72055702
SC
1973}
1974
1975// ----------------------------------------------------------------------------
1976// standard handlers for standard edit menu events
1977// ----------------------------------------------------------------------------
1978
eb22f2a6 1979void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
72055702
SC
1980{
1981 Cut();
1982}
1983
eb22f2a6 1984void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event))
72055702
SC
1985{
1986 Copy();
1987}
1988
eb22f2a6 1989void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event))
72055702
SC
1990{
1991 Paste();
1992}
1993
eb22f2a6 1994void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event))
72055702
SC
1995{
1996 Undo();
1997}
1998
eb22f2a6 1999void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event))
72055702
SC
2000{
2001 Redo();
2002}
2003
2004void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
2005{
2006 event.Enable( CanCut() );
2007}
2008
2009void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
2010{
2011 event.Enable( CanCopy() );
2012}
2013
2014void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
2015{
2016 event.Enable( CanPaste() );
2017}
2018
2019void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
2020{
2021 event.Enable( CanUndo() );
2022}
2023
2024void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
2025{
2026 event.Enable( CanRedo() );
2027}
2028
2b5f62a0
VZ
2029bool wxTextCtrl::MacSetupCursor( const wxPoint& pt )
2030{
facd6764
SC
2031 return true ;
2032}
2033
2034// user pane implementation
2035
2036void wxTextCtrl::MacControlUserPaneDrawProc(wxInt16 part)
2037{
2038}
2039
2040wxInt16 wxTextCtrl::MacControlUserPaneHitTestProc(wxInt16 x, wxInt16 y)
2041{
2042 return kControlNoPart ;
2043}
2044
2045wxInt16 wxTextCtrl::MacControlUserPaneTrackingProc(wxInt16 x, wxInt16 y, void* actionProc)
2046{
2047 return kControlNoPart ;
2048}
2049
2050void wxTextCtrl::MacControlUserPaneIdleProc()
2051{
2052}
2053
2054wxInt16 wxTextCtrl::MacControlUserPaneKeyDownProc(wxInt16 keyCode, wxInt16 charCode, wxInt16 modifiers)
2055{
2056 return kControlNoPart ;
2057}
2058
2059void wxTextCtrl::MacControlUserPaneActivateProc(bool activating)
2060{
2061}
2062
2063wxInt16 wxTextCtrl::MacControlUserPaneFocusProc(wxInt16 action)
2064{
2065 return kControlNoPart ;
2066}
2067
2068void wxTextCtrl::MacControlUserPaneBackgroundProc(void* info)
2069{
2b5f62a0 2070}
72055702 2071
fedad417
GD
2072#endif
2073 // wxUSE_TEXTCTRL