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