]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/textctrl.cpp
rely on built-in best size...
[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
21fd5529 741 SetControlReference(*m_peer, 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 ) ;
21fd5529 806 m_peer = scrollView ;
d3016f30
SC
807 }
808 else
809 {
21fd5529 810 m_peer = 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 */
21fd5529 819 m_peer = new wxMacControl() ;
be060748 820 verify_noerr( ::CreateUserPaneControl( MAC_WXHWND(GetParent()->MacGetTopLevelWindowRef()), &bounds, featurSet, *m_peer ) );
7548762c 821
facd6764
SC
822 wxMacWindowClipper c(this) ;
823 STPTextPaneVars *varsp ;
21fd5529 824 mUPOpenControl( varsp, *m_peer, m_windowStyle );
facd6764
SC
825 m_macTXNvars = varsp ;
826 m_macTXN = varsp->fTXNRec ;
587bc950
SC
827#endif
828
facd6764
SC
829 if ( style & wxTE_PASSWORD )
830 {
831 UniChar c = 0xA5 ;
832 verify_noerr(TXNEchoMode( (TXNObject) m_macTXN , c , 0 , true )) ;
833 }
29e4a190 834 }
facd6764
SC
835 MacPostControlCreate(pos,size) ;
836
587bc950 837#if !wxMAC_USE_MLTE_HIVIEW
facd6764
SC
838 if ( MacIsReallyShown() )
839 MLTESetObjectVisibility( (STPTextPaneVars*) m_macTXNvars, true , GetWindowStyle() ) ;
587bc950 840#endif
ed8c2780 841
ed8c2780 842 {
facd6764 843 wxMacWindowClipper clipper( this ) ;
587bc950 844#if !wxMAC_USE_MLTE_HIVIEW
21fd5529 845 TPUpdateVisibility( *m_peer ) ;
587bc950 846#endif
facd6764
SC
847 SetTXNData( (STPTextPaneVars *)m_macTXNvars , (TXNObject) m_macTXN , st , kTXNStartOffset, kTXNEndOffset ) ;
848
2b5f62a0 849 TXNSetSelection( (TXNObject) m_macTXN, 0, 0);
e600c175 850 TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart);
1b2b1638 851 }
bd3169a7
SC
852
853 // in case MLTE is catching events before we get the chance to do so, we'd have to reintroduce the tlw-handler in front :
854 // parent->MacGetTopLevelWindow()->MacInstallTopLevelWindowEventHandler() ;
ef4a634b 855
facd6764
SC
856 SetBackgroundColour( *wxWHITE ) ;
857
858 TXNBackground tback;
859 tback.bgType = kTXNBackgroundTypeRGB;
860 tback.bg.color = MAC_WXCOLORREF( GetBackgroundColour().GetPixel() );
861 TXNSetBackground( (TXNObject) m_macTXN , &tback);
862
f0091567 863#else
587bc950 864 wxMacCFStringHolder cf(st , m_font.GetEncoding()) ;
7f1de2b2
SC
865 CFStringRef cfr = cf ;
866 Boolean isPassword = ( m_windowStyle & wxTE_PASSWORD ) != 0 ;
21fd5529
SC
867 m_peer = new wxMacControl() ;
868 CreateEditUnicodeTextControl( MAC_WXHWND(parent->MacGetTopLevelWindowRef()), &bounds , cfr , isPassword , NULL , *m_peer ) ;
869
7f1de2b2
SC
870 if ( !(m_windowStyle & wxTE_MULTILINE) )
871 {
872 Boolean singleline = true ;
21fd5529 873 ::SetControlData( *m_peer, kControlEditTextPart , kControlEditTextSingleLineTag , sizeof( singleline ) , &singleline ) ;
7f1de2b2 874 }
587bc950 875 MacPostControlCreate(pos,size) ;
7f1de2b2 876
f0091567 877#endif
7f1de2b2
SC
878 if ( m_windowStyle & wxTE_READONLY)
879 {
880 SetEditable( false ) ;
881 }
f0091567 882
facd6764 883
e40298d5 884 return TRUE;
72055702
SC
885}
886
facd6764
SC
887void wxTextCtrl::MacVisibilityChanged()
888{
7f1de2b2
SC
889#if wxMAC_USE_MLTE
890#if !wxMAC_USE_MLTE_HIVIEW
facd6764
SC
891 MLTESetObjectVisibility((STPTextPaneVars*) m_macTXNvars , MacIsReallyShown() , GetWindowStyle() ) ;
892 if ( !MacIsReallyShown() )
21fd5529 893 InvalWindowRect( GetControlOwner( *m_peer ) , &((STPTextPaneVars *)m_macTXNvars)->fRBounds ) ;
587bc950 894#endif
7f1de2b2
SC
895#else
896 if ( !(m_windowStyle & wxTE_MULTILINE) && MacIsReallyShown() )
897 {
898 // work around a refresh issue insofar as not always the entire content is shown even if this would be possible
899 ControlEditTextSelectionRec sel ;
900 CFStringRef value = NULL ;
901 Size actualSize = 0 ;
902 ResType datatag = GetWindowStyle() & wxTE_PASSWORD ?
903 kControlEditTextPasswordCFStringTag : kControlEditTextCFStringTag ;
904
21fd5529 905 verify_noerr( GetControlData( *m_peer , 0, kControlEditTextSelectionTag,
7f1de2b2 906 sizeof(ControlEditTextSelectionRec), &sel, &actualSize ) );
21fd5529 907 verify_noerr( GetControlData( *m_peer , 0, datatag , sizeof(CFStringRef), &value, &actualSize ) );
7f1de2b2 908
21fd5529
SC
909 verify_noerr( SetControlData( *m_peer , 0, datatag, sizeof(CFStringRef), &value ) );
910 verify_noerr( SetControlData( *m_peer , 0, kControlEditTextSelectionTag, sizeof(ControlEditTextSelectionRec), &sel ) );
7f1de2b2
SC
911
912 CFRelease( value ) ;
913 }
914#endif
facd6764
SC
915}
916
917void wxTextCtrl::MacEnabledStateChanged()
918{
919}
920
921
72055702
SC
922wxString wxTextCtrl::GetValue() const
923{
c5c9378c 924 wxString result ;
587bc950 925#if wxMAC_USE_MLTE
c5c9378c 926 OSStatus err ;
587bc950 927 Size actualSize = 0;
29e4a190 928 {
427ff662 929#if wxUSE_UNICODE
29e4a190 930 Handle theText ;
427ff662 931 err = TXNGetDataEncoded( ((TXNObject) m_macTXN), kTXNStartOffset, kTXNEndOffset, &theText , kTXNUnicodeTextData );
29e4a190
RR
932 // all done
933 if ( err )
934 {
c5c9378c 935 actualSize = 0 ;
29e4a190
RR
936 }
937 else
938 {
7688f0a1 939 actualSize = GetHandleSize( theText ) / sizeof( UniChar) ;
427ff662
SC
940 if ( actualSize > 0 )
941 {
facd6764
SC
942 wxChar *ptr = NULL ;
943#if SIZEOF_WCHAR_T == 2
944 ptr = new wxChar[actualSize + 1 ] ;
427ff662 945 wxStrncpy( ptr , (wxChar*) *theText , actualSize ) ;
facd6764 946
6bdd4f5d 947#else
facd6764 948 SetHandleSize( theText , ( actualSize + 1 ) * sizeof( UniChar ) ) ;
6bdd4f5d 949 HLock( theText ) ;
facd6764
SC
950 (((UniChar*)*theText)[actualSize]) = 0 ;
951 wxMBConvUTF16BE converter ;
952 size_t noChars = converter.MB2WC( NULL , (const char*)*theText , 0 ) ;
953 ptr = new wxChar[noChars + 1] ;
954
955 noChars = converter.MB2WC( ptr , (const char*)*theText , noChars ) ;
956 ptr[noChars] = 0 ;
6bdd4f5d
SC
957 HUnlock( theText ) ;
958#endif
e40298d5 959 ptr[actualSize] = 0 ;
facd6764
SC
960 result = wxString( ptr ) ;
961 delete[] ptr ;
e40298d5
JS
962 }
963 DisposeHandle( theText ) ;
29e4a190 964 }
427ff662
SC
965#else
966 Handle theText ;
967 err = TXNGetDataEncoded( ((TXNObject) m_macTXN), kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData );
968 // all done
969 if ( err )
970 {
971 actualSize = 0 ;
972 }
973 else
974 {
975 actualSize = GetHandleSize( theText ) ;
976 if ( actualSize > 0 )
977 {
978 HLock( theText ) ;
939fba6c 979 result = wxString( *theText , wxConvLocal , actualSize ) ;
427ff662
SC
980 HUnlock( theText ) ;
981 }
982 DisposeHandle( theText ) ;
983 }
984#endif
29e4a190 985 }
587bc950
SC
986#else
987 CFStringRef value = NULL ;
988 Size actualSize = 0 ;
989
21fd5529 990 verify_noerr( GetControlData( *m_peer , 0, GetWindowStyle() & wxTE_PASSWORD ?
587bc950
SC
991 kControlEditTextPasswordCFStringTag : kControlEditTextCFStringTag,
992 sizeof(CFStringRef), &value, &actualSize ) );
993 if ( value )
994 {
995 wxMacCFStringHolder cf(value) ;
996 result = cf.AsString() ;
997 }
998#endif
8aa701ed 999 wxMacConvertNewlines10To13( &result ) ;
427ff662 1000 return result ;
72055702
SC
1001}
1002
1003void wxTextCtrl::GetSelection(long* from, long* to) const
587bc950
SC
1004{
1005#if wxMAC_USE_MLTE
facd6764 1006 TXNGetSelection( (TXNObject) m_macTXN , (TXNOffset*) from , (TXNOffset*) to ) ;
587bc950
SC
1007#else
1008 ControlEditTextSelectionRec sel ;
1009 Size actualSize ;
21fd5529 1010 verify_noerr( GetControlData( *m_peer , 0, kControlEditTextSelectionTag,
587bc950
SC
1011 sizeof(ControlEditTextSelectionRec), &sel, &actualSize ) );
1012 if ( from ) *from = sel.selStart ;
1013 if ( to ) *to = sel.selEnd ;
1014#endif
72055702
SC
1015}
1016
939fba6c 1017void wxTextCtrl::SetValue(const wxString& str)
72055702 1018{
facd6764
SC
1019 // optimize redraws
1020 if ( GetValue() == str )
1021 return ;
1022
939fba6c 1023 wxString st = str ;
8aa701ed 1024 wxMacConvertNewlines13To10( &st ) ;
587bc950 1025#if wxMAC_USE_MLTE
29e4a190 1026 {
facd6764 1027 wxMacWindowClipper c( this ) ;
68698f03 1028 bool formerEditable = m_editable ;
2b5f62a0
VZ
1029 if ( !formerEditable )
1030 SetEditable(true) ;
facd6764 1031
587bc950 1032#if !wxMAC_USE_MLTE_HIVIEW
facd6764
SC
1033 // otherwise scrolling might have problems ?
1034 TPUpdateVisibility( ( (STPTextPaneVars *)m_macTXNvars)->fUserPaneRec ) ;
587bc950 1035#endif
facd6764 1036 SetTXNData( (STPTextPaneVars *)m_macTXNvars , (TXNObject) m_macTXN , st , kTXNStartOffset, kTXNEndOffset ) ;
2b5f62a0 1037 TXNSetSelection( (TXNObject) m_macTXN, 0, 0);
e600c175 1038 TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart);
2b5f62a0
VZ
1039 if ( !formerEditable )
1040 SetEditable(formerEditable) ;
29e4a190 1041 }
587bc950
SC
1042#else
1043 wxMacCFStringHolder cf(st , m_font.GetEncoding() ) ;
1044 CFStringRef value = cf ;
21fd5529 1045 verify_noerr( SetControlData( *m_peer , 0, GetWindowStyle() & wxTE_PASSWORD ?
587bc950
SC
1046 kControlEditTextPasswordCFStringTag : kControlEditTextCFStringTag,
1047 sizeof(CFStringRef), &value ) );
1048#endif
72055702
SC
1049}
1050
ef4a634b 1051void wxTextCtrl::SetMaxLength(unsigned long len)
29b30405
SC
1052{
1053 m_maxLength = len ;
1054}
1055
facd6764
SC
1056bool wxTextCtrl::SetFont( const wxFont& font )
1057{
1058 if ( !wxTextCtrlBase::SetFont( font ) )
1059 return FALSE ;
1060
587bc950 1061#if wxMAC_USE_MLTE
facd6764
SC
1062 wxMacWindowClipper c( this ) ;
1063 bool formerEditable = m_editable ;
1064 if ( !formerEditable )
1065 SetEditable(true) ;
1066
1067 TXNTypeAttributes typeAttr[4] ;
1068 Str255 fontName = "\pMonaco" ;
1069 SInt16 fontSize = 12 ;
1070 Style fontStyle = normal ;
1071 int attrCounter = 0 ;
1072
1073 wxMacStringToPascal( font.GetFaceName() , fontName ) ;
1074 fontSize = font.MacGetFontSize() ;
1075 fontStyle = font.MacGetFontStyle() ;
1076
1077 typeAttr[attrCounter].tag = kTXNQDFontNameAttribute ;
1078 typeAttr[attrCounter].size = kTXNQDFontNameAttributeSize ;
1079 typeAttr[attrCounter].data.dataPtr = (void*) fontName ;
1080 typeAttr[attrCounter+1].tag = kTXNQDFontSizeAttribute ;
1081 typeAttr[attrCounter+1].size = kTXNFontSizeAttributeSize ;
1082 typeAttr[attrCounter+1].data.dataValue = (fontSize << 16) ;
1083 typeAttr[attrCounter+2].tag = kTXNQDFontStyleAttribute ;
1084 typeAttr[attrCounter+2].size = kTXNQDFontStyleAttributeSize ;
1085 typeAttr[attrCounter+2].data.dataValue = fontStyle ;
1086 attrCounter += 3 ;
1087 /*
1088 typeAttr[attrCounter].tag = kTXNQDFontColorAttribute ;
1089 typeAttr[attrCounter].size = kTXNQDFontColorAttributeSize ;
1090 typeAttr[attrCounter].data.dataPtr = (void*) &color ;
1091 color = MAC_WXCOLORREF(GetForegroundColour().GetPixel()) ;
1092 attrCounter += 1 ;
1093 */
1094 verify_noerr( TXNSetTypeAttributes ((TXNObject)m_macTXN, attrCounter , typeAttr, kTXNStartOffset,kTXNEndOffset) );
1095
1096 if ( !formerEditable )
1097 SetEditable(formerEditable) ;
587bc950 1098#endif
facd6764
SC
1099 return true ;
1100}
1101
29b30405
SC
1102bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
1103{
587bc950 1104#if wxMAC_USE_MLTE
facd6764
SC
1105 bool formerEditable = m_editable ;
1106 if ( !formerEditable )
1107 SetEditable(true) ;
1108 TXNTypeAttributes typeAttr[4] ;
1109 Str255 fontName = "\pMonaco" ;
1110 SInt16 fontSize = 12 ;
1111 Style fontStyle = normal ;
1112 RGBColor color ;
1113 int attrCounter = 0 ;
1114 if ( style.HasFont() )
29b30405 1115 {
facd6764
SC
1116 const wxFont &font = style.GetFont() ;
1117 wxMacStringToPascal( font.GetFaceName() , fontName ) ;
1118 fontSize = font.GetPointSize() ;
1119 if ( font.GetUnderlined() )
1120 fontStyle |= underline ;
1121 if ( font.GetWeight() == wxBOLD )
1122 fontStyle |= bold ;
1123 if ( font.GetStyle() == wxITALIC )
1124 fontStyle |= italic ;
1125
1126 typeAttr[attrCounter].tag = kTXNQDFontNameAttribute ;
1127 typeAttr[attrCounter].size = kTXNQDFontNameAttributeSize ;
1128 typeAttr[attrCounter].data.dataPtr = (void*) fontName ;
1129 typeAttr[attrCounter+1].tag = kTXNQDFontSizeAttribute ;
1130 typeAttr[attrCounter+1].size = kTXNFontSizeAttributeSize ;
1131 typeAttr[attrCounter+1].data.dataValue = (fontSize << 16) ;
1132 typeAttr[attrCounter+2].tag = kTXNQDFontStyleAttribute ;
1133 typeAttr[attrCounter+2].size = kTXNQDFontStyleAttributeSize ;
1134 typeAttr[attrCounter+2].data.dataValue = fontStyle ;
1135 attrCounter += 3 ;
1136
1137 }
1138 if ( style.HasTextColour() )
1139 {
1140 typeAttr[attrCounter].tag = kTXNQDFontColorAttribute ;
1141 typeAttr[attrCounter].size = kTXNQDFontColorAttributeSize ;
1142 typeAttr[attrCounter].data.dataPtr = (void*) &color ;
1143 color = MAC_WXCOLORREF(style.GetTextColour().GetPixel()) ;
1144 attrCounter += 1 ;
1145 }
ef4a634b 1146
facd6764
SC
1147 if ( attrCounter > 0 )
1148 {
1149 verify_noerr( TXNSetTypeAttributes ((TXNObject)m_macTXN, attrCounter , typeAttr, start,end) );
29b30405 1150 }
facd6764
SC
1151 if ( !formerEditable )
1152 SetEditable(formerEditable) ;
587bc950 1153#endif
29b30405
SC
1154 return TRUE ;
1155}
1156
1157bool wxTextCtrl::SetDefaultStyle(const wxTextAttr& style)
1158{
1159 wxTextCtrlBase::SetDefaultStyle( style ) ;
1160 SetStyle( kTXNUseCurrentSelection , kTXNUseCurrentSelection , GetDefaultStyle() ) ;
1161 return TRUE ;
1162}
1163
72055702
SC
1164// Clipboard operations
1165void wxTextCtrl::Copy()
1166{
1167 if (CanCopy())
1168 {
587bc950 1169#if wxMAC_USE_MLTE
facd6764
SC
1170 ClearCurrentScrap();
1171 TXNCopy((TXNObject)m_macTXN);
1172 TXNConvertToPublicScrap();
21fd5529
SC
1173#else
1174 m_peer->SendHICommand( kHICommandCopy ) ;
587bc950 1175#endif
32b5be3d 1176 }
72055702
SC
1177}
1178
1179void wxTextCtrl::Cut()
1180{
1181 if (CanCut())
1182 {
587bc950 1183#if wxMAC_USE_MLTE
facd6764
SC
1184 ClearCurrentScrap();
1185 TXNCut((TXNObject)m_macTXN);
1186 TXNConvertToPublicScrap();
21fd5529
SC
1187#else
1188 m_peer->SendHICommand( kHICommandCut ) ;
587bc950 1189#endif
1b2b1638
SC
1190 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
1191 event.SetString( GetValue() ) ;
1192 event.SetEventObject( this );
1193 GetEventHandler()->ProcessEvent(event);
29e4a190 1194 }
72055702
SC
1195}
1196
1197void wxTextCtrl::Paste()
1198{
1199 if (CanPaste())
1200 {
587bc950 1201#if wxMAC_USE_MLTE
facd6764
SC
1202 TXNConvertFromPublicScrap();
1203 TXNPaste((TXNObject)m_macTXN);
1204 SetStyle( kTXNUseCurrentSelection , kTXNUseCurrentSelection , GetDefaultStyle() ) ;
21fd5529
SC
1205#else
1206 m_peer->SendHICommand( kHICommandPaste ) ;
587bc950 1207#endif
1b2b1638
SC
1208 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
1209 event.SetString( GetValue() ) ;
1210 event.SetEventObject( this );
1211 GetEventHandler()->ProcessEvent(event);
32b5be3d 1212 }
72055702
SC
1213}
1214
1215bool wxTextCtrl::CanCopy() const
1216{
1217 // Can copy if there's a selection
1218 long from, to;
1219 GetSelection(& from, & to);
1220 return (from != to);
1221}
1222
1223bool wxTextCtrl::CanCut() const
1224{
1b2b1638
SC
1225 if ( !IsEditable() )
1226 {
1227 return false ;
1228 }
72055702
SC
1229 // Can cut if there's a selection
1230 long from, to;
1231 GetSelection(& from, & to);
1232 return (from != to);
1233}
1234
1235bool wxTextCtrl::CanPaste() const
1236{
1237 if (!IsEditable())
1238 return FALSE;
1239
587bc950 1240#if wxMAC_USE_MLTE
facd6764 1241 return TXNIsScrapPastable() ;
587bc950
SC
1242#else
1243 return true ;
1244#endif
72055702
SC
1245}
1246
1247void wxTextCtrl::SetEditable(bool editable)
1248{
1b2b1638
SC
1249 if ( editable != m_editable )
1250 {
1251 m_editable = editable ;
587bc950 1252#if wxMAC_USE_MLTE
facd6764
SC
1253 TXNControlTag tag[] = { kTXNIOPrivilegesTag } ;
1254 TXNControlData data[] = { { editable ? kTXNReadWrite : kTXNReadOnly } } ;
1255 TXNSetTXNObjectControls( (TXNObject) m_macTXN , false , sizeof(tag) / sizeof (TXNControlTag) , tag , data ) ;
7f1de2b2
SC
1256#else
1257 Boolean value = !editable ;
21fd5529 1258 ::SetControlData( *m_peer, 0, kControlEditTextLockedTag , sizeof( value ) , &value ) ;
587bc950 1259#endif
1b2b1638 1260 }
72055702
SC
1261}
1262
1263void wxTextCtrl::SetInsertionPoint(long pos)
1264{
ed8c2780 1265 SetSelection( pos , pos ) ;
72055702
SC
1266}
1267
1268void wxTextCtrl::SetInsertionPointEnd()
1269{
1270 long pos = GetLastPosition();
1271 SetInsertionPoint(pos);
1272}
1273
1274long wxTextCtrl::GetInsertionPoint() const
1275{
e40298d5
JS
1276 long begin,end ;
1277 GetSelection( &begin , &end ) ;
1278 return begin ;
72055702
SC
1279}
1280
1281long wxTextCtrl::GetLastPosition() const
1282{
587bc950
SC
1283 long actualsize = 0 ;
1284#if wxMAC_USE_MLTE
7548762c 1285 Handle theText ;
facd6764
SC
1286 OSErr err = TXNGetDataEncoded( (TXNObject) m_macTXN, kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData );
1287 /* all done */
1288 if ( err )
32b5be3d 1289 {
facd6764 1290 actualsize = 0 ;
32b5be3d
RR
1291 }
1292 else
1293 {
facd6764
SC
1294 actualsize = GetHandleSize( theText ) ;
1295 DisposeHandle( theText ) ;
32b5be3d 1296 }
587bc950 1297#endif
facd6764 1298 return actualsize ;
72055702
SC
1299}
1300
939fba6c 1301void wxTextCtrl::Replace(long from, long to, const wxString& str)
72055702 1302{
587bc950 1303#if wxMAC_USE_MLTE
939fba6c 1304 wxString value = str ;
de0bc932 1305 wxMacConvertNewlines13To10( &value ) ;
facd6764
SC
1306
1307 bool formerEditable = m_editable ;
1308 if ( !formerEditable )
1309 SetEditable(true) ;
1310 TXNSetSelection( ((TXNObject) m_macTXN) , from , to ) ;
1311 TXNClear( ((TXNObject) m_macTXN) ) ;
1312 SetTXNData( (STPTextPaneVars *)m_macTXNvars , (TXNObject) m_macTXN , str , kTXNUseCurrentSelection, kTXNUseCurrentSelection ) ;
1313 if ( !formerEditable )
1314 SetEditable( formerEditable ) ;
1315
32b5be3d 1316 Refresh() ;
587bc950 1317#endif
72055702
SC
1318}
1319
1320void wxTextCtrl::Remove(long from, long to)
1321{
587bc950 1322#if wxMAC_USE_MLTE
facd6764
SC
1323 bool formerEditable = m_editable ;
1324 if ( !formerEditable )
1325 SetEditable(true) ;
1326 TXNSetSelection( ((TXNObject) m_macTXN) , from , to ) ;
1327 TXNClear( ((TXNObject) m_macTXN) ) ;
1328 if ( !formerEditable )
1329 SetEditable( formerEditable ) ;
ef4a634b 1330
ed8c2780 1331 Refresh() ;
587bc950 1332#endif
72055702
SC
1333}
1334
1335void wxTextCtrl::SetSelection(long from, long to)
1336{
587bc950 1337#if wxMAC_USE_MLTE
facd6764
SC
1338 /* change the selection */
1339 if ((from == -1) && (to == -1))
1340 TXNSelectAll((TXNObject) m_macTXN);
e40298d5 1341 else
587bc950 1342 TXNSetSelection( (TXNObject) m_macTXN, from, to);
facd6764 1343 TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart);
587bc950
SC
1344#else
1345 ControlEditTextSelectionRec sel ;
1346 sel.selStart = from ;
1347 sel.selEnd = to ;
21fd5529 1348 verify_noerr( SetControlData( *m_peer , 0, kControlEditTextSelectionTag,
587bc950
SC
1349 sizeof(ControlEditTextSelectionRec), &sel ) );
1350
1351#endif
72055702
SC
1352}
1353
1354bool wxTextCtrl::LoadFile(const wxString& file)
1355{
1356 if ( wxTextCtrlBase::LoadFile(file) )
1357 {
1358 return TRUE;
1359 }
1360
1361 return FALSE;
1362}
1363
7548762c
SC
1364class wxMacFunctor
1365{
1366public :
1367 wxMacFunctor(){}
1368 virtual ~wxMacFunctor() {}
1369 virtual void* operator()() = 0 ;
1370 static void* CallBackProc(void *param)
1371 {
1372 wxMacFunctor* f = (wxMacFunctor*) param ;
1373 void *result = (*f)() ;
1374 return result ;
1375 }
1376} ;
1377
1378template<typename classtype,typename param1type>
1379class wxMacObjectFunctor1 : public wxMacFunctor
1380{
1381 typedef void (classtype::*function)( param1type p1 ) ;
1382 typedef void (classtype::*ref_function)( const param1type& p1 ) ;
1383public :
1384 wxMacObjectFunctor1( classtype *obj , function f , param1type p1 ) :
1385 wxMacFunctor( )
1386 {
1387 m_object = obj ;
1388 m_function = f ;
1389 m_param1 = p1 ;
1390 }
1391
1392 wxMacObjectFunctor1( classtype *obj , ref_function f , param1type p1 ) :
1393 wxMacFunctor( )
1394 {
1395 m_object = obj ;
1396 m_refFunction = f ;
1397 m_param1 = p1 ;
1398 }
1399
1400 ~wxMacObjectFunctor1() {}
1401
1402 virtual void* operator()()
1403 {
1404 (m_object->*m_function)(m_param1) ;
1405 return NULL ;
1406 }
1407private :
1408 classtype* m_object ;
1409 param1type m_param1 ;
1410 union
1411 {
1412 function m_function ;
1413 ref_function m_refFunction ;
1414 } ;
1415} ;
1416
1417template<typename classtype, typename param1type>
1418void* wxMacMPRemoteCall( classtype *object , void (classtype::*function)( 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* wxMacMPRemoteCall( classtype *object , void (classtype::*function)( const param1type& p1 ) , param1type p1 )
1428{
1429 wxMacObjectFunctor1<classtype,param1type> params(object,function,p1) ;
1430 void *result =
1431 MPRemoteCall( wxMacFunctor::CallBackProc , &params , kMPOwningProcessRemoteContext ) ;
1432 return result ;
1433}
1434
1435template<typename classtype, typename param1type>
1436void* wxMacMPRemoteGUICall( classtype *object , void (classtype::*function)( param1type p1 ) , param1type p1 )
1437{
1438 wxMutexGuiLeave() ;
1439 void *result = wxMacMPRemoteCall( object , function , p1 ) ;
1440 wxMutexGuiEnter() ;
1441 return result ;
1442}
1443
1444template<typename classtype, typename param1type>
1445void* wxMacMPRemoteGUICall( classtype *object , void (classtype::*function)( const param1type& p1 ) , param1type p1 )
1446{
1447 wxMutexGuiLeave() ;
1448 void *result = wxMacMPRemoteCall( object , function , p1 ) ;
1449 wxMutexGuiEnter() ;
1450 return result ;
1451}
1452
939fba6c 1453void wxTextCtrl::WriteText(const wxString& str)
ef4a634b 1454{
7548762c 1455 if ( !wxIsMainThread() )
587bc950 1456 {
cfeff6f7
SC
1457 // unfortunately CW 8 is not able to correctly deduce the template types, so we have
1458 // to instantiate explicitely
1459 wxMacMPRemoteGUICall<wxTextCtrl,wxString>( this , &wxTextCtrl::WriteText , str ) ;
7548762c 1460 return ;
587bc950 1461 }
7548762c
SC
1462 else
1463 {
1464 wxString st = str ;
1465 wxMacConvertNewlines13To10( &st ) ;
1466 #if wxMAC_USE_MLTE
1467 bool formerEditable = m_editable ;
1468 if ( !formerEditable )
1469 SetEditable(true) ;
1470 {
1471 wxMacWindowStateSaver s( this ) ;
1472 long start , end , dummy ;
1473 GetSelection( &start , &dummy ) ;
1474 SetTXNData( (STPTextPaneVars *)m_macTXNvars , (TXNObject) m_macTXN , st , kTXNUseCurrentSelection, kTXNUseCurrentSelection ) ;
1475 GetSelection( &dummy , &end ) ;
1476 SetStyle( start , end , GetDefaultStyle() ) ;
1477 }
1478 if ( !formerEditable )
1479 SetEditable( formerEditable ) ;
facd6764 1480
7548762c
SC
1481 MacRedrawControl() ;
1482 #else
1483 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
1484 wxMacCFStringHolder cf(st , m_font.GetEncoding() ) ;
1485 CFStringRef value = cf ;
21fd5529 1486 SetControlData( *m_peer , 0, kControlEditTextInsertCFStringRefTag,
7548762c
SC
1487 sizeof(CFStringRef), &value );
1488 #else
1489 wxString val = GetValue() ;
1490 long start , end ;
1491 GetSelection( &start , &end ) ;
1492 val.Remove( start , end - start ) ;
1493 val.insert( start , str ) ;
1494 SetValue( val ) ;
57ab966b 1495 SetInsertionPoint( start + str.Length() ) ;
7548762c
SC
1496 #endif
1497 #endif
1498 }
72055702
SC
1499}
1500
1501void wxTextCtrl::AppendText(const wxString& text)
1502{
1503 SetInsertionPointEnd();
1504 WriteText(text);
1505}
1506
1507void wxTextCtrl::Clear()
1508{
587bc950 1509#if wxMAC_USE_MLTE
facd6764
SC
1510 bool formerEditable = m_editable ;
1511 if ( !formerEditable )
1512 SetEditable(true) ;
1513 TXNSetSelection( (TXNObject)m_macTXN , kTXNStartOffset , kTXNEndOffset ) ;
1514 TXNClear((TXNObject)m_macTXN);
1515
1516 if ( !formerEditable )
1517 SetEditable( formerEditable ) ;
1518
32b5be3d 1519 Refresh() ;
587bc950
SC
1520#else
1521 SetValue(wxEmptyString) ;
1522#endif
72055702
SC
1523}
1524
1525bool wxTextCtrl::IsModified() const
1526{
1fa29bdc 1527 return m_dirty;
72055702
SC
1528}
1529
1530bool wxTextCtrl::IsEditable() const
1531{
1b2b1638 1532 return IsEnabled() && m_editable ;
72055702
SC
1533}
1534
1535bool wxTextCtrl::AcceptsFocus() const
1536{
1537 // we don't want focus if we can't be edited
1b2b1638 1538 return /*IsEditable() && */ wxControl::AcceptsFocus();
72055702
SC
1539}
1540
1541wxSize wxTextCtrl::DoGetBestSize() const
1542{
1543 int wText = 100 ;
ef4a634b 1544
402679b0 1545 int hText;
facd6764
SC
1546
1547 switch( m_windowVariant )
29e4a190 1548 {
facd6764
SC
1549 case wxWINDOW_VARIANT_NORMAL :
1550 hText = 22 ;
1551 break ;
1552 case wxWINDOW_VARIANT_SMALL :
1553 hText = 19 ;
1554 break ;
1555 case wxWINDOW_VARIANT_MINI :
1556 hText= 15 ;
1557 break ;
1558 default :
1559 hText = 22 ;
1560 break ;
29e4a190 1561 }
72055702 1562
cfeff6f7
SC
1563#if !wxMAC_USE_MLTE
1564 // unicode text control is using client size, ie 3 pixels on every side
1565 // TODO make this fit into normal window size concept, probably having
1566 // to reintroduce the margin vars
1567 hText -= 6 ;
1568#endif
1569
72055702
SC
1570 if ( m_windowStyle & wxTE_MULTILINE )
1571 {
402679b0 1572 hText *= 5 ;
72055702 1573 }
facd6764 1574
72055702
SC
1575 return wxSize(wText, hText);
1576}
1577
1578// ----------------------------------------------------------------------------
1579// Undo/redo
1580// ----------------------------------------------------------------------------
1581
1582void wxTextCtrl::Undo()
1583{
1584 if (CanUndo())
1585 {
587bc950 1586#if wxMAC_USE_MLTE
facd6764 1587 TXNUndo((TXNObject)m_macTXN);
587bc950 1588#endif
72055702
SC
1589 }
1590}
1591
1592void wxTextCtrl::Redo()
1593{
1594 if (CanRedo())
1595 {
587bc950 1596#if wxMAC_USE_MLTE
facd6764 1597 TXNRedo((TXNObject)m_macTXN);
587bc950 1598#endif
72055702
SC
1599 }
1600}
1601
1602bool wxTextCtrl::CanUndo() const
1603{
65334b43
SC
1604 if ( !IsEditable() )
1605 {
1606 return false ;
1607 }
587bc950 1608#if wxMAC_USE_MLTE
facd6764 1609 return TXNCanUndo((TXNObject)m_macTXN,NULL);
587bc950
SC
1610#else
1611 return false ;
1612#endif
72055702
SC
1613}
1614
1615bool wxTextCtrl::CanRedo() const
1616{
65334b43
SC
1617 if ( !IsEditable() )
1618 {
1619 return false ;
1620 }
587bc950 1621#if wxMAC_USE_MLTE
facd6764 1622 return TXNCanRedo((TXNObject)m_macTXN,NULL);
587bc950
SC
1623#else
1624 return false ;
1625#endif
72055702
SC
1626}
1627
3a9fa0d6
VZ
1628// Makes modifie or unmodified
1629void wxTextCtrl::MarkDirty()
1630{
1631 m_dirty = true;
1632}
1633
72055702
SC
1634void wxTextCtrl::DiscardEdits()
1635{
1fa29bdc 1636 m_dirty = false;
72055702
SC
1637}
1638
1639int wxTextCtrl::GetNumberOfLines() const
1640{
587bc950
SC
1641 ItemCount lines = 0 ;
1642#if wxMAC_USE_MLTE
facd6764 1643 TXNGetLineCount((TXNObject)m_macTXN, &lines ) ;
21fd5529
SC
1644#else
1645 wxString content = GetValue() ;
1646 lines = 1;
1647 for (size_t i = 0; i < content.Length() ; i++)
1648 {
1649 if (content[i] == '\r') lines++;
1650 }
587bc950 1651#endif
facd6764 1652 return lines ;
72055702
SC
1653}
1654
1655long wxTextCtrl::XYToPosition(long x, long y) const
1656{
587bc950 1657#if wxMAC_USE_MLTE
bd3169a7
SC
1658 Point curpt ;
1659
1660 long lastpos = GetLastPosition() ;
1661
1662 // TODO find a better implementation : while we can get the
1663 // line metrics of a certain line, we don't get its starting
1664 // position, so it would probably be rather a binary search
1665 // for the start position
1666 long xpos = 0 ;
1667 long ypos = 0 ;
1668 int lastHeight = 0 ;
1669
1670 ItemCount n ;
ebe86b1e 1671 for ( n = 0 ; n <= (ItemCount) lastpos ; ++n )
bd3169a7
SC
1672 {
1673 if ( y == ypos && x == xpos )
1674 return n ;
1675
1676 TXNOffsetToPoint( (TXNObject) m_macTXN, n , &curpt);
1677
1678 if ( curpt.v > lastHeight )
1679 {
1680 xpos = 0 ;
1681 if ( n > 0 )
1682 ++ypos ;
1683 lastHeight = curpt.v ;
1684 }
1685 else
1686 ++xpos ;
1687 }
587bc950 1688#endif
72055702
SC
1689 return 0;
1690}
1691
1692bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
1693{
587bc950 1694#if wxMAC_USE_MLTE
bd3169a7
SC
1695 Point curpt ;
1696
1697 long lastpos = GetLastPosition() ;
1698
1699 if ( y ) *y = 0 ;
1700 if ( x ) *x = 0 ;
1701
1702 if ( pos <= lastpos )
1703 {
1704 // TODO find a better implementation : while we can get the
1705 // line metrics of a certain line, we don't get its starting
1706 // position, so it would probably be rather a binary search
1707 // for the start position
1708 long xpos = 0 ;
1709 long ypos = 0 ;
1710 int lastHeight = 0 ;
1711
1712 ItemCount n ;
ebe86b1e 1713 for ( n = 0 ; n <= (ItemCount) pos ; ++n )
bd3169a7
SC
1714 {
1715 TXNOffsetToPoint( (TXNObject) m_macTXN, n , &curpt);
1716
1717 if ( curpt.v > lastHeight )
1718 {
1719 xpos = 0 ;
1720 if ( n > 0 )
1721 ++ypos ;
1722 lastHeight = curpt.v ;
1723 }
1724 else
1725 ++xpos ;
1726 }
1727 if ( y ) *y = ypos ;
1728 if ( x ) *x = xpos ;
1729 }
587bc950
SC
1730#else
1731 if ( y ) *y = 0 ;
1732 if ( x ) *x = 0 ;
1733#endif
72055702
SC
1734 return FALSE ;
1735}
1736
1737void wxTextCtrl::ShowPosition(long pos)
1738{
587bc950 1739#if wxMAC_USE_MLTE
3a05d58d 1740#if TARGET_RT_MAC_MACHO && defined(AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER)
3a05d58d 1741 {
f8e089e0
SC
1742 Point current ;
1743 Point desired ;
1744 TXNOffset selstart , selend ;
3a05d58d 1745 TXNGetSelection( (TXNObject) m_macTXN , &selstart , &selend) ;
f8e089e0
SC
1746 TXNOffsetToPoint( (TXNObject) m_macTXN, selstart , &current);
1747 TXNOffsetToPoint( (TXNObject) m_macTXN, pos , &desired);
1748 //TODO use HIPoints for 10.3 and above
1749 if ( (UInt32) TXNScroll != (UInt32) kUnresolvedCFragSymbolAddress )
1750 {
1751 OSErr theErr = noErr;
1752 SInt32 dv = desired.v - current.v ;
1753 SInt32 dh = desired.h - current.h ;
1754 TXNShowSelection( (TXNObject) m_macTXN , true ) ;
3a05d58d 1755 theErr = TXNScroll( (TXNObject) m_macTXN, kTXNScrollUnitsInPixels , kTXNScrollUnitsInPixels , &dv , &dh );
f8e089e0
SC
1756 wxASSERT_MSG( theErr == noErr, _T("TXNScroll returned an error!") );
1757 }
3a05d58d
SC
1758 }
1759#endif
587bc950 1760#endif
72055702
SC
1761}
1762
1763int wxTextCtrl::GetLineLength(long lineNo) const
1764{
587bc950 1765#if wxMAC_USE_MLTE
bd3169a7
SC
1766 Point curpt ;
1767 if ( lineNo < GetNumberOfLines() )
32b5be3d 1768 {
bd3169a7
SC
1769 // TODO find a better implementation : while we can get the
1770 // line metrics of a certain line, we don't get its starting
1771 // position, so it would probably be rather a binary search
1772 // for the start position
1773 long xpos = 0 ;
1774 long ypos = 0 ;
1775 int lastHeight = 0 ;
1776 long lastpos = GetLastPosition() ;
1777
1778 ItemCount n ;
ebe86b1e 1779 for ( n = 0 ; n <= (ItemCount) lastpos ; ++n )
32b5be3d 1780 {
bd3169a7
SC
1781 TXNOffsetToPoint( (TXNObject) m_macTXN, n , &curpt);
1782
1783 if ( curpt.v > lastHeight )
32b5be3d 1784 {
bd3169a7
SC
1785 if ( ypos == lineNo )
1786 return xpos ;
1787
1788 xpos = 0 ;
1789 if ( n > 0 )
1790 ++ypos ;
1791 lastHeight = curpt.v ;
29e4a190 1792 }
bd3169a7
SC
1793 else
1794 ++xpos ;
29e4a190 1795 }
29e4a190 1796 }
21fd5529
SC
1797#else
1798 // TODO change this if possible to reflect real lines
1799 wxString content = GetValue() ;
1800
1801 // Find line first
1802 int count = 0;
1803 for (size_t i = 0; i < content.Length() ; i++)
1804 {
1805 if (count == lineNo)
1806 {
1807 // Count chars in line then
1808 count = 0;
1809 for (size_t j = i; j < content.Length(); j++)
1810 {
1811 count++;
1812 if (content[j] == '\n') return count;
1813 }
1814
1815 return count;
1816 }
1817 if (content[i] == '\n') count++;
1818 }
587bc950 1819#endif
72055702
SC
1820 return 0;
1821}
1822
1823wxString wxTextCtrl::GetLineText(long lineNo) const
1824{
587bc950 1825#if wxMAC_USE_MLTE
21fd5529 1826 wxString line ;
7548762c 1827 Point curpt ;
e40298d5 1828 wxString content = GetValue() ;
9c641c05 1829
bd3169a7 1830 if ( lineNo < GetNumberOfLines() )
32b5be3d 1831 {
bd3169a7
SC
1832 // TODO find a better implementation : while we can get the
1833 // line metrics of a certain line, we don't get its starting
1834 // position, so it would probably be rather a binary search
1835 // for the start position
1836 long xpos = 0 ;
1837 long ypos = 0 ;
1838 int lastHeight = 0 ;
1839 long lastpos = GetLastPosition() ;
1840
1841 ItemCount n ;
ebe86b1e 1842 for ( n = 0 ; n <= (ItemCount)lastpos ; ++n )
32b5be3d 1843 {
bd3169a7 1844 TXNOffsetToPoint( (TXNObject) m_macTXN, n , &curpt);
ef4a634b 1845
bd3169a7 1846 if ( curpt.v > lastHeight )
29e4a190 1847 {
bd3169a7
SC
1848 if ( ypos == lineNo )
1849 return line ;
1850
1851 xpos = 0 ;
1852 if ( n > 0 )
1853 ++ypos ;
1854 lastHeight = curpt.v ;
1855 }
1856 else
1857 {
1858 if ( ypos == lineNo )
1859 line += content[n] ;
1860 ++xpos ;
29e4a190 1861 }
29e4a190 1862 }
29e4a190 1863 }
bd3169a7 1864 return line ;
21fd5529
SC
1865#else
1866 // TODO change this if possible to reflect real lines
1867 wxString content = GetValue() ;
1868
1869 // Find line first
1870 int count = 0;
1871 for (size_t i = 0; i < content.Length() ; i++)
1872 {
1873 if (count == lineNo)
1874 {
1875 // Add chars in line then
1876 wxString tmp;
1877
1878 for (size_t j = i; j < content.Length(); j++)
1879 {
1880 if (content[j] == '\n')
1881 return tmp;
1882
1883 tmp += content[j];
1884 }
1885
1886 return tmp;
1887 }
1888 if (content[i] == '\n') count++;
1889 }
1890 return wxEmptyString ;
1891#endif
72055702
SC
1892}
1893
1894/*
1895 * Text item
1896 */
ef4a634b 1897
72055702
SC
1898void wxTextCtrl::Command(wxCommandEvent & event)
1899{
1900 SetValue (event.GetString());
1901 ProcessCommand (event);
1902}
1903
1904void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
1905{
1906 // By default, load the first file into the text window.
1907 if (event.GetNumberOfFiles() > 0)
1908 {
1909 LoadFile(event.GetFiles()[0]);
1910 }
1911}
1912
1913void wxTextCtrl::OnChar(wxKeyEvent& event)
1914{
1b2b1638
SC
1915 int key = event.GetKeyCode() ;
1916 bool eat_key = false ;
ef4a634b 1917
e600c175
SC
1918 if ( key == 'c' && event.MetaDown() )
1919 {
1920 if ( CanCopy() )
1921 Copy() ;
1922 return ;
1923 }
ef4a634b
RD
1924
1925 if ( !IsEditable() && key != WXK_LEFT && key != WXK_RIGHT && key != WXK_DOWN && key != WXK_UP && key != WXK_TAB &&
1926 !( key == WXK_RETURN && ( (m_windowStyle & wxPROCESS_ENTER) || (m_windowStyle & wxTE_MULTILINE) ) )
1b2b1638
SC
1927/* && key != WXK_PRIOR && key != WXK_NEXT && key != WXK_HOME && key != WXK_END */
1928 )
1929 {
1930 // eat it
1931 return ;
1932 }
1fa29bdc
VZ
1933
1934 // assume that any key not processed yet is going to modify the control
1935 m_dirty = true;
1936
e600c175
SC
1937 if ( key == 'v' && event.MetaDown() )
1938 {
1939 if ( CanPaste() )
1940 Paste() ;
1941 return ;
1942 }
1943 if ( key == 'x' && event.MetaDown() )
1944 {
1945 if ( CanCut() )
1946 Cut() ;
1947 return ;
1948 }
1b2b1638 1949 switch ( key )
72055702
SC
1950 {
1951 case WXK_RETURN:
ed8c2780
RR
1952 if (m_windowStyle & wxPROCESS_ENTER)
1953 {
72055702
SC
1954 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
1955 event.SetEventObject( this );
1b2b1638 1956 event.SetString( GetValue() );
72055702
SC
1957 if ( GetEventHandler()->ProcessEvent(event) )
1958 return;
ef4a634b 1959 }
72055702
SC
1960 if ( !(m_windowStyle & wxTE_MULTILINE) )
1961 {
ed8c2780 1962 wxWindow *parent = GetParent();
9c641c05
SC
1963 while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL ) {
1964 parent = parent->GetParent() ;
ed8c2780 1965 }
9c641c05 1966 if ( parent && parent->GetDefaultItem() )
ed8c2780 1967 {
9c641c05 1968 wxButton *def = wxDynamicCast(parent->GetDefaultItem(),
72055702 1969 wxButton);
ed8c2780
RR
1970 if ( def && def->IsEnabled() )
1971 {
1972 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
1973 event.SetEventObject(def);
1974 def->Command(event);
1975 return ;
72055702 1976 }
ed8c2780 1977 }
ef4a634b 1978
77ffb593 1979 // this will make wxWidgets eat the ENTER key so that
1b2b1638
SC
1980 // we actually prevent line wrapping in a single line
1981 // text control
1982 eat_key = TRUE;
72055702 1983 }
72055702
SC
1984
1985 break;
1986
1987 case WXK_TAB:
5f6cfda7 1988 if ( !(m_windowStyle & wxTE_PROCESS_TAB))
72055702 1989 {
eedc82f4
JS
1990 int flags = 0;
1991 if (!event.ShiftDown())
1992 flags |= wxNavigationKeyEvent::IsForward ;
1993 if (event.ControlDown())
1994 flags |= wxNavigationKeyEvent::WinChange ;
1995 Navigate(flags);
6ad49e18
JS
1996 return;
1997 }
1998 else
1999 {
2000 // This is necessary (don't know why) or the tab will not
2001 // be inserted.
2002 WriteText(wxT("\t"));
72055702 2003 }
6ad49e18 2004
72055702
SC
2005 break;
2006 }
ef4a634b 2007
1b2b1638 2008 if (!eat_key)
ed8c2780 2009 {
1ea39a03 2010 // perform keystroke handling
facd6764 2011 if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL )
1ea39a03
SC
2012 CallNextEventHandler((EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() , (EventRef) wxTheApp->MacGetCurrentEvent() ) ;
2013 else
1ea39a03
SC
2014 {
2015 EventRecord rec ;
2016 if ( wxMacConvertEventToRecord( (EventRef) wxTheApp->MacGetCurrentEvent() , &rec ) )
2017 {
2018 EventRecord *ev = &rec ;
2019 short keycode ;
2020 short keychar ;
2021 keychar = short(ev->message & charCodeMask);
2022 keycode = short(ev->message & keyCodeMask) >> 8 ;
2023
21fd5529 2024 ::HandleControlKey( *m_peer , keycode , keychar , ev->modifiers ) ;
1ea39a03
SC
2025 }
2026 }
1b2b1638 2027 }
e600c175 2028 if ( ( key >= 0x20 && key < WXK_START ) ||
45c8d9e5 2029 key == WXK_RETURN ||
ef4a634b 2030 key == WXK_DELETE ||
45c8d9e5 2031 key == WXK_BACK)
1b2b1638
SC
2032 {
2033 wxCommandEvent event1(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
2034 event1.SetString( GetValue() ) ;
2035 event1.SetEventObject( this );
45c8d9e5 2036 wxPostEvent(GetEventHandler(),event1);
ed8c2780 2037 }
72055702
SC
2038}
2039
2040// ----------------------------------------------------------------------------
2041// standard handlers for standard edit menu events
2042// ----------------------------------------------------------------------------
2043
eb22f2a6 2044void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
72055702
SC
2045{
2046 Cut();
2047}
2048
eb22f2a6 2049void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event))
72055702
SC
2050{
2051 Copy();
2052}
2053
eb22f2a6 2054void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event))
72055702
SC
2055{
2056 Paste();
2057}
2058
eb22f2a6 2059void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event))
72055702
SC
2060{
2061 Undo();
2062}
2063
eb22f2a6 2064void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event))
72055702
SC
2065{
2066 Redo();
2067}
2068
2069void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
2070{
2071 event.Enable( CanCut() );
2072}
2073
2074void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
2075{
2076 event.Enable( CanCopy() );
2077}
2078
2079void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
2080{
2081 event.Enable( CanPaste() );
2082}
2083
2084void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
2085{
2086 event.Enable( CanUndo() );
2087}
2088
2089void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
2090{
2091 event.Enable( CanRedo() );
2092}
2093
2b5f62a0
VZ
2094bool wxTextCtrl::MacSetupCursor( const wxPoint& pt )
2095{
facd6764
SC
2096 return true ;
2097}
2098
2099// user pane implementation
2100
2101void wxTextCtrl::MacControlUserPaneDrawProc(wxInt16 part)
2102{
2103}
2104
2105wxInt16 wxTextCtrl::MacControlUserPaneHitTestProc(wxInt16 x, wxInt16 y)
2106{
2107 return kControlNoPart ;
2108}
2109
2110wxInt16 wxTextCtrl::MacControlUserPaneTrackingProc(wxInt16 x, wxInt16 y, void* actionProc)
2111{
2112 return kControlNoPart ;
2113}
2114
2115void wxTextCtrl::MacControlUserPaneIdleProc()
2116{
2117}
2118
2119wxInt16 wxTextCtrl::MacControlUserPaneKeyDownProc(wxInt16 keyCode, wxInt16 charCode, wxInt16 modifiers)
2120{
2121 return kControlNoPart ;
2122}
2123
2124void wxTextCtrl::MacControlUserPaneActivateProc(bool activating)
2125{
2126}
2127
2128wxInt16 wxTextCtrl::MacControlUserPaneFocusProc(wxInt16 action)
2129{
2130 return kControlNoPart ;
2131}
2132
2133void wxTextCtrl::MacControlUserPaneBackgroundProc(void* info)
2134{
2b5f62a0 2135}
72055702 2136
fedad417
GD
2137#endif
2138 // wxUSE_TEXTCTRL