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