]> git.saurik.com Git - wxWidgets.git/blame - src/mac/classic/textctrl.cpp
Add support for generating classes for menus
[wxWidgets.git] / src / mac / classic / textctrl.cpp
CommitLineData
2646f485 1/////////////////////////////////////////////////////////////////////////////
faa94f3e 2// Name: src/mac/classic/textctrl.cpp
2646f485
SC
3// Purpose: wxTextCtrl
4// Author: Stefan Csomor
5// Modified by:
6// Created: 1998-01-01
7// RCS-ID: $Id$
8// Copyright: (c) Stefan Csomor
65571936 9// Licence: wxWindows licence
2646f485
SC
10/////////////////////////////////////////////////////////////////////////////
11
18f3decb
WS
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
2646f485
SC
17
18#if wxUSE_TEXTCTRL
19
670f9935
WS
20#include "wx/textctrl.h"
21
22#ifndef WX_PRECOMP
23 #include "wx/app.h"
de6185e2 24 #include "wx/utils.h"
da80ae71 25 #include "wx/dc.h"
f1e01716 26 #include "wx/button.h"
9eddec69 27 #include "wx/settings.h"
246c5004 28 #include "wx/msgdlg.h"
670f9935
WS
29#endif
30
2646f485 31#ifdef __DARWIN__
670f9935
WS
32 #include <sys/types.h>
33 #include <sys/stat.h>
2646f485 34#else
670f9935 35 #include <stat.h>
2646f485
SC
36#endif
37
2646f485
SC
38#if wxUSE_STD_IOSTREAM
39 #if wxUSE_IOSTREAMH
40 #include <fstream.h>
41 #else
42 #include <fstream>
43 #endif
44#endif
45
2646f485 46#include "wx/toplevel.h"
2646f485
SC
47#include "wx/notebook.h"
48#include "wx/tabctrl.h"
2646f485 49#include "wx/filefn.h"
2646f485
SC
50
51#if defined(__BORLANDC__) && !defined(__WIN32__)
670f9935 52 #include <alloc.h>
2646f485 53#elif !defined(__MWERKS__) && !defined(__GNUWIN32) && !defined(__DARWIN__)
670f9935 54 #include <malloc.h>
2646f485
SC
55#endif
56
57#ifndef __DARWIN__
58#include <Scrap.h>
59#endif
60#include <MacTextEditor.h>
61#include <ATSUnicode.h>
62#include <TextCommon.h>
63#include <TextEncodingConverter.h>
64#include "wx/mac/uma.h"
65
66#define TE_UNLIMITED_LENGTH 0xFFFFFFFFUL
67
68extern wxControl *wxFindControlFromMacControl(ControlHandle inControl ) ;
69
70// CS:TODO we still have a problem getting properly at the text events of a control because under Carbon
71// the MLTE engine registers itself for the key events thus the normal flow never occurs, the only measure for the
72// moment is to avoid setting the true focus on the control, the proper solution at the end would be to have
73// an alternate path for carbon key events that routes automatically into the same wx flow of events
74
75/* part codes */
76
77/* kmUPTextPart is the part code we return to indicate the user has clicked
78 in the text area of our control */
79#define kmUPTextPart 1
80
81/* kmUPScrollPart is the part code we return to indicate the user has clicked
82 in the scroll bar part of the control. */
83#define kmUPScrollPart 2
84
85
86/* routines for using existing user pane controls.
87 These routines are useful for cases where you would like to use an
88 existing user pane control in, say, a dialog window as a scrolling
89 text edit field.*/
90
91/* mUPOpenControl initializes a user pane control so it will be drawn
92 and will behave as a scrolling text edit field inside of a window.
93 This routine performs all of the initialization steps necessary,
94 except it does not create the user pane control itself. theControl
95 should refer to a user pane control that you have either created
96 yourself or extracted from a dialog's control heirarchy using
97 the GetDialogItemAsControl routine. */
98OSStatus mUPOpenControl(ControlHandle theControl, long wxStyle);
99
100/* Utility Routines */
101
102enum {
103 kShiftKeyCode = 56
104};
105
106/* kUserClickedToFocusPart is a part code we pass to the SetKeyboardFocus
107 routine. In our focus switching routine this part code is understood
108 as meaning 'the user has clicked in the control and we need to switch
109 the current focus to ourselves before we can continue'. */
110#define kUserClickedToFocusPart 100
111
112
113/* kmUPClickScrollDelayTicks is a time measurement in ticks used to
114 slow the speed of 'auto scrolling' inside of our clickloop routine.
115 This value prevents the text from wizzzzzing by while the mouse
116 is being held down inside of the text area. */
117#define kmUPClickScrollDelayTicks 3
118
119
120/* STPTextPaneVars is a structure used for storing the the mUP Control's
121 internal variables and state information. A handle to this record is
122 stored in the pane control's reference value field using the
123 SetControlReference routine. */
124
125typedef struct {
126 /* OS records referenced */
127 TXNObject fTXNRec; /* the txn record */
128 TXNFrameID fTXNFrame; /* the txn frame ID */
129 ControlHandle fUserPaneRec; /* handle to the user pane control */
130 WindowPtr fOwner; /* window containing control */
131 GrafPtr fDrawingEnvironment; /* grafport where control is drawn */
132 /* flags */
133 Boolean fInFocus; /* true while the focus rect is drawn around the control */
134 Boolean fIsActive; /* true while the control is drawn in the active state */
135 Boolean fTEActive; /* reflects the activation state of the text edit record */
136 Boolean fInDialogWindow; /* true if displayed in a dialog window */
137 /* calculated locations */
138 Rect fRTextArea; /* area where the text is drawn */
139 Rect fRFocusOutline; /* rectangle used to draw the focus box */
140 Rect fRTextOutline; /* rectangle used to draw the border */
141 RgnHandle fTextBackgroundRgn; /* background region for the text, erased before calling TEUpdate */
142 /* our focus advance override routine */
143 EventHandlerUPP handlerUPP;
144 EventHandlerRef handlerRef;
145 bool fMultiline ;
146} STPTextPaneVars;
147
148
149
150
151/* Univerals Procedure Pointer variables used by the
152 mUP Control. These variables are set up
153 the first time that mUPOpenControl is called. */
154ControlUserPaneDrawUPP gTPDrawProc = NULL;
155ControlUserPaneHitTestUPP gTPHitProc = NULL;
156ControlUserPaneTrackingUPP gTPTrackProc = NULL;
157ControlUserPaneIdleUPP gTPIdleProc = NULL;
158ControlUserPaneKeyDownUPP gTPKeyProc = NULL;
159ControlUserPaneActivateUPP gTPActivateProc = NULL;
160ControlUserPaneFocusUPP gTPFocusProc = NULL;
161
162/* TPActivatePaneText activates or deactivates the text edit record
163 according to the value of setActive. The primary purpose of this
164 routine is to ensure each call is only made once. */
165static void TPActivatePaneText(STPTextPaneVars **tpvars, Boolean setActive) {
166 STPTextPaneVars *varsp;
167 varsp = *tpvars;
168 if (varsp->fTEActive != setActive) {
169
170 varsp->fTEActive = setActive;
171
172 TXNActivate(varsp->fTXNRec, varsp->fTXNFrame, varsp->fTEActive);
173
174 if (varsp->fInFocus)
175 TXNFocus( varsp->fTXNRec, varsp->fTEActive);
176 }
177}
178
179
180/* TPFocusPaneText set the focus state for the text record. */
181static void TPFocusPaneText(STPTextPaneVars **tpvars, Boolean setFocus) {
182 STPTextPaneVars *varsp;
183 varsp = *tpvars;
184 if (varsp->fInFocus != setFocus) {
185 varsp->fInFocus = setFocus;
186 TXNFocus( varsp->fTXNRec, varsp->fInFocus);
187 }
188}
189
190
191/* TPPaneDrawProc is called to redraw the control and for update events
192 referring to the control. This routine erases the text area's background,
193 and redraws the text. This routine assumes the scroll bar has been
194 redrawn by a call to DrawControls. */
195static pascal void TPPaneDrawProc(ControlRef theControl, ControlPartCode thePart) {
196 STPTextPaneVars **tpvars, *varsp;
197 char state;
198 Rect bounds;
199 /* set up our globals */
200
201 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
202 if (tpvars != NULL) {
203 state = HGetState((Handle) tpvars);
204 HLock((Handle) tpvars);
205 varsp = *tpvars;
206
207 /* save the drawing state */
208 SetPort((**tpvars).fDrawingEnvironment);
209 /* verify our boundary */
210 GetControlBounds(theControl, &bounds);
211
212 wxMacWindowClipper clipper( wxFindControlFromMacControl(theControl ) ) ;
213 if ( ! EqualRect(&bounds, &varsp->fRFocusOutline) ) {
214 // scrollbar is on the border, we add one
215 Rect oldbounds = varsp->fRFocusOutline ;
216 InsetRect( &oldbounds , -1 , -1 ) ;
217
218 if ( IsControlVisible( theControl ) )
219 InvalWindowRect( GetControlOwner( theControl ) , &oldbounds ) ;
220 SetRect(&varsp->fRFocusOutline, bounds.left, bounds.top, bounds.right, bounds.bottom);
221 SetRect(&varsp->fRTextOutline, bounds.left, bounds.top, bounds.right, bounds.bottom);
222 SetRect(&varsp->fRTextArea, bounds.left + 2 , bounds.top + (varsp->fMultiline ? 0 : 2) ,
223 bounds.right - (varsp->fMultiline ? 0 : 2), bounds.bottom - (varsp->fMultiline ? 0 : 2));
224 RectRgn(varsp->fTextBackgroundRgn, &varsp->fRTextOutline);
225 if ( IsControlVisible( theControl ) )
226 TXNSetFrameBounds( varsp->fTXNRec, varsp->fRTextArea.top, varsp->fRTextArea.left,
227 varsp->fRTextArea.bottom, varsp->fRTextArea.right, varsp->fTXNFrame);
228 else
229 TXNSetFrameBounds( varsp->fTXNRec, varsp->fRTextArea.top + 30000 , varsp->fRTextArea.left + 30000 ,
230 varsp->fRTextArea.bottom + 30000 , varsp->fRTextArea.right + 30000 , varsp->fTXNFrame);
7d8268a1 231
2646f485
SC
232 }
233
234 if ( IsControlVisible( theControl ) )
235 {
236 /* update the text region */
237 RGBColor white = { 65535 , 65535 , 65535 } ;
238 RGBBackColor( &white ) ;
239 EraseRgn(varsp->fTextBackgroundRgn);
240 TXNDraw(varsp->fTXNRec, NULL);
241 /* restore the drawing environment */
242 /* draw the text frame and focus frame (if necessary) */
243 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
7d8268a1 244 if ((**tpvars).fIsActive && varsp->fInFocus)
2646f485
SC
245 DrawThemeFocusRect(&varsp->fRFocusOutline, true);
246 /* release our globals */
247 HSetState((Handle) tpvars, state);
248 }
249 }
250}
251
252
253/* TPPaneHitTestProc is called when the control manager would
254 like to determine what part of the control the mouse resides over.
255 We also call this routine from our tracking proc to determine how
256 to handle mouse clicks. */
257static pascal ControlPartCode TPPaneHitTestProc(ControlHandle theControl, Point where) {
258 STPTextPaneVars **tpvars;
259 ControlPartCode result;
260 char state;
261 /* set up our locals and lock down our globals*/
262 result = 0;
263 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
264 if (tpvars != NULL && IsControlVisible( theControl) ) {
265 state = HGetState((Handle) tpvars);
266 HLock((Handle) tpvars);
267 /* find the region where we clicked */
268 if (PtInRect(where, &(**tpvars).fRTextArea)) {
269 result = kmUPTextPart;
270 } else result = 0;
271 /* release oure globals */
272 HSetState((Handle) tpvars, state);
273 }
274 return result;
275}
276
277
278
279
280
281/* TPPaneTrackingProc is called when the mouse is being held down
282 over our control. This routine handles clicks in the text area
283 and in the scroll bar. */
284static pascal ControlPartCode TPPaneTrackingProc(ControlHandle theControl, Point startPt, ControlActionUPP actionProc) {
285 STPTextPaneVars **tpvars, *varsp;
286 char state;
287 ControlPartCode partCodeResult;
288 /* make sure we have some variables... */
289 partCodeResult = 0;
290 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
291 if (tpvars != NULL && IsControlVisible( theControl ) ) {
292 /* lock 'em down */
293 state = HGetState((Handle) tpvars);
294 HLock((Handle) tpvars);
295 varsp = *tpvars;
296 /* we don't do any of these functions unless we're in focus */
297 if ( ! varsp->fInFocus) {
298 WindowPtr owner;
299 owner = GetControlOwner(theControl);
300 ClearKeyboardFocus(owner);
301 SetKeyboardFocus(owner, theControl, kUserClickedToFocusPart);
302 }
303 /* find the location for the click */
304 switch (TPPaneHitTestProc(theControl, startPt)) {
305
306 /* handle clicks in the text part */
307 case kmUPTextPart:
308 { SetPort((**tpvars).fDrawingEnvironment);
309 wxMacWindowClipper clipper( wxFindControlFromMacControl(theControl ) ) ;
310#if !TARGET_CARBON
311 TXNClick( varsp->fTXNRec, (const EventRecord*) wxTheApp->MacGetCurrentEvent());
312#else
313 EventRecord rec ;
314 ConvertEventRefToEventRecord( (EventRef) wxTheApp->MacGetCurrentEvent() , &rec ) ;
315 TXNClick( varsp->fTXNRec, &rec );
316#endif
317 }
318 break;
319
320 }
321
322 HSetState((Handle) tpvars, state);
323 }
324 return partCodeResult;
325}
326
327
328/* TPPaneIdleProc is our user pane idle routine. When our text field
329 is active and in focus, we use this routine to set the cursor. */
330static pascal void TPPaneIdleProc(ControlHandle theControl) {
331 STPTextPaneVars **tpvars, *varsp;
332 /* set up locals */
333 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
334 if (tpvars != NULL && IsControlVisible( theControl ) ) {
335 /* if we're not active, then we have nothing to say about the cursor */
336 if ((**tpvars).fIsActive) {
337 char state;
338 Rect bounds;
339 Point mousep;
340 /* lock down the globals */
341 state = HGetState((Handle) tpvars);
342 HLock((Handle) tpvars);
343 varsp = *tpvars;
344 /* get the current mouse coordinates (in our window) */
345 SetPortWindowPort(GetControlOwner(theControl));
346 wxMacWindowClipper clipper( wxFindControlFromMacControl(theControl ) ) ;
347 GetMouse(&mousep);
348 /* there's a 'focus thing' and an 'unfocused thing' */
349 if (varsp->fInFocus) {
350 /* flash the cursor */
351 SetPort((**tpvars).fDrawingEnvironment);
352 TXNIdle(varsp->fTXNRec);
353 /* set the cursor */
354 if (PtInRect(mousep, &varsp->fRTextArea)) {
355 RgnHandle theRgn;
356 RectRgn((theRgn = NewRgn()), &varsp->fRTextArea);
357 TXNAdjustCursor(varsp->fTXNRec, theRgn);
358 DisposeRgn(theRgn);
359 }
360 else
361 {
362 // SetThemeCursor(kThemeArrowCursor);
363 }
364 } else {
365 /* if it's in our bounds, set the cursor */
366 GetControlBounds(theControl, &bounds);
367 if (PtInRect(mousep, &bounds))
368 {
369 // SetThemeCursor(kThemeArrowCursor);
370 }
371 }
372
373 HSetState((Handle) tpvars, state);
374 }
375 }
376}
377
378
379/* TPPaneKeyDownProc is called whenever a keydown event is directed
380 at our control. Here, we direct the keydown event to the text
381 edit record and redraw the scroll bar and text field as appropriate. */
382static pascal ControlPartCode TPPaneKeyDownProc(ControlHandle theControl,
383 SInt16 keyCode, SInt16 charCode, SInt16 modifiers) {
384 STPTextPaneVars **tpvars;
385 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
386 if (tpvars != NULL) {
387 if ((**tpvars).fInFocus) {
388 /* turn autoscrolling on and send the key event to text edit */
389 SetPort((**tpvars).fDrawingEnvironment);
390 wxMacWindowClipper clipper( wxFindControlFromMacControl(theControl ) ) ;
391 EventRecord ev ;
392 memset( &ev , 0 , sizeof( ev ) ) ;
393 ev.what = keyDown ;
394 ev.modifiers = modifiers ;
395 ev.message = (( keyCode << 8 ) & keyCodeMask ) + ( charCode & charCodeMask ) ;
396 TXNKeyDown( (**tpvars).fTXNRec, &ev);
397 }
398 }
399 return kControlEntireControl;
400}
401
402
403/* TPPaneActivateProc is called when the window containing
404 the user pane control receives activate events. Here, we redraw
405 the control and it's text as necessary for the activation state. */
406static pascal void TPPaneActivateProc(ControlHandle theControl, Boolean activating) {
407 Rect bounds;
408 STPTextPaneVars **tpvars, *varsp;
409 char state;
410 /* set up locals */
411 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
412 if (tpvars != NULL) {
413 state = HGetState((Handle) tpvars);
414 HLock((Handle) tpvars);
415 varsp = *tpvars;
416 /* de/activate the text edit record */
417 SetPort((**tpvars).fDrawingEnvironment);
418 wxMacWindowClipper clipper( wxFindControlFromMacControl(theControl ) ) ;
419 GetControlBounds(theControl, &bounds);
420 varsp->fIsActive = activating;
421 TPActivatePaneText(tpvars, varsp->fIsActive && varsp->fInFocus);
422 /* redraw the frame */
423 if ( IsControlVisible( theControl ) )
424 {
425 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
7d8268a1 426 if (varsp->fInFocus)
2646f485
SC
427 DrawThemeFocusRect(&varsp->fRFocusOutline, varsp->fIsActive);
428 }
429 HSetState((Handle) tpvars, state);
430 }
431}
432
433
434/* TPPaneFocusProc is called when every the focus changes to or
435 from our control. Herein, switch the focus appropriately
436 according to the parameters and redraw the control as
437 necessary. */
438static pascal ControlPartCode TPPaneFocusProc(ControlHandle theControl, ControlFocusPart action) {
439 ControlPartCode focusResult;
440 STPTextPaneVars **tpvars, *varsp;
441 char state;
442 /* set up locals */
443 focusResult = kControlFocusNoPart;
444 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
445 if (tpvars != NULL ) {
446 state = HGetState((Handle) tpvars);
447 HLock((Handle) tpvars);
448 varsp = *tpvars;
449 /* if kControlFocusPrevPart and kControlFocusNextPart are received when the user is
450 tabbing forwards (or shift tabbing backwards) through the items in the dialog,
451 and kControlFocusNextPart will be received. When the user clicks in our field
452 and it is not the current focus, then the constant kUserClickedToFocusPart will
453 be received. The constant kControlFocusNoPart will be received when our control
454 is the current focus and the user clicks in another control. In your focus routine,
455 you should respond to these codes as follows:
456
457 kControlFocusNoPart - turn off focus and return kControlFocusNoPart. redraw
458 the control and the focus rectangle as necessary.
459
460 kControlFocusPrevPart or kControlFocusNextPart - toggle focus on or off
461 depending on its current state. redraw the control and the focus rectangle
462 as appropriate for the new focus state. If the focus state is 'off', return the constant
463 kControlFocusNoPart, otherwise return a non-zero part code.
464 kUserClickedToFocusPart - is a constant defined for this example. You should
465 define your own value for handling click-to-focus type events. */
466 /* calculate the next highlight state */
467 switch (action) {
468 default:
469 case kControlFocusNoPart:
470 TPFocusPaneText(tpvars, false);
471 focusResult = kControlFocusNoPart;
472 break;
473 case kUserClickedToFocusPart:
474 TPFocusPaneText(tpvars, true);
475 focusResult = 1;
476 break;
477 case kControlFocusPrevPart:
478 case kControlFocusNextPart:
479 TPFocusPaneText(tpvars, ( ! varsp->fInFocus));
480 focusResult = varsp->fInFocus ? 1 : kControlFocusNoPart;
481 break;
482 }
483 TPActivatePaneText(tpvars, varsp->fIsActive && varsp->fInFocus);
484 /* redraw the text fram and focus rectangle to indicate the
485 new focus state */
486 if ( IsControlVisible( theControl ) )
487 {
488 /* save the drawing state */
7d8268a1
WS
489 SetPort((**tpvars).fDrawingEnvironment);
490 wxMacWindowClipper clipper( wxFindControlFromMacControl(theControl ) ) ;
2646f485
SC
491 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
492 DrawThemeFocusRect(&varsp->fRFocusOutline, varsp->fIsActive && varsp->fInFocus);
493 }
494 /* done */
495 HSetState((Handle) tpvars, state);
496 }
497 return focusResult;
498}
499
500
501/* mUPOpenControl initializes a user pane control so it will be drawn
502 and will behave as a scrolling text edit field inside of a window.
503 This routine performs all of the initialization steps necessary,
504 except it does not create the user pane control itself. theControl
505 should refer to a user pane control that you have either created
506 yourself or extracted from a dialog's control heirarchy using
507 the GetDialogItemAsControl routine. */
508OSStatus mUPOpenControl(ControlHandle theControl, long wxStyle )
509{
510 Rect bounds;
511 WindowRef theWindow;
512 STPTextPaneVars **tpvars, *varsp;
513 OSStatus err = noErr ;
514 RGBColor rgbWhite = {0xFFFF, 0xFFFF, 0xFFFF};
515 TXNBackground tback;
516
517 /* set up our globals */
518 if (gTPDrawProc == NULL) gTPDrawProc = NewControlUserPaneDrawUPP(TPPaneDrawProc);
519 if (gTPHitProc == NULL) gTPHitProc = NewControlUserPaneHitTestUPP(TPPaneHitTestProc);
520 if (gTPTrackProc == NULL) gTPTrackProc = NewControlUserPaneTrackingUPP(TPPaneTrackingProc);
521 if (gTPIdleProc == NULL) gTPIdleProc = NewControlUserPaneIdleUPP(TPPaneIdleProc);
522 if (gTPKeyProc == NULL) gTPKeyProc = NewControlUserPaneKeyDownUPP(TPPaneKeyDownProc);
523 if (gTPActivateProc == NULL) gTPActivateProc = NewControlUserPaneActivateUPP(TPPaneActivateProc);
524 if (gTPFocusProc == NULL) gTPFocusProc = NewControlUserPaneFocusUPP(TPPaneFocusProc);
525
526 /* allocate our private storage */
527 tpvars = (STPTextPaneVars **) NewHandleClear(sizeof(STPTextPaneVars));
528 SetControlReference(theControl, (long) tpvars);
529 HLock((Handle) tpvars);
530 varsp = *tpvars;
531 /* set the initial settings for our private data */
532 varsp->fMultiline = wxStyle & wxTE_MULTILINE ;
533 varsp->fInFocus = false;
534 varsp->fIsActive = true;
535 varsp->fTEActive = true; // in order to get a deactivate
536 varsp->fUserPaneRec = theControl;
537 theWindow = varsp->fOwner = GetControlOwner(theControl);
538
539 varsp->fDrawingEnvironment = (GrafPtr) GetWindowPort(theWindow);
540
541 varsp->fInDialogWindow = ( GetWindowKind(varsp->fOwner) == kDialogWindowKind );
542 /* set up the user pane procedures */
543 SetControlData(theControl, kControlEntireControl, kControlUserPaneDrawProcTag, sizeof(gTPDrawProc), &gTPDrawProc);
544 SetControlData(theControl, kControlEntireControl, kControlUserPaneHitTestProcTag, sizeof(gTPHitProc), &gTPHitProc);
545 SetControlData(theControl, kControlEntireControl, kControlUserPaneTrackingProcTag, sizeof(gTPTrackProc), &gTPTrackProc);
546 SetControlData(theControl, kControlEntireControl, kControlUserPaneIdleProcTag, sizeof(gTPIdleProc), &gTPIdleProc);
547 SetControlData(theControl, kControlEntireControl, kControlUserPaneKeyDownProcTag, sizeof(gTPKeyProc), &gTPKeyProc);
548 SetControlData(theControl, kControlEntireControl, kControlUserPaneActivateProcTag, sizeof(gTPActivateProc), &gTPActivateProc);
549 SetControlData(theControl, kControlEntireControl, kControlUserPaneFocusProcTag, sizeof(gTPFocusProc), &gTPFocusProc);
550 /* calculate the rectangles used by the control */
551 GetControlBounds(theControl, &bounds);
552 SetRect(&varsp->fRFocusOutline, bounds.left, bounds.top, bounds.right, bounds.bottom);
553 SetRect(&varsp->fRTextOutline, bounds.left, bounds.top, bounds.right, bounds.bottom);
554 SetRect(&varsp->fRTextArea, bounds.left + 2 , bounds.top + (varsp->fMultiline ? 0 : 2) ,
555 bounds.right - (varsp->fMultiline ? 0 : 2), bounds.bottom - (varsp->fMultiline ? 0 : 2));
556 /* calculate the background region for the text. In this case, it's kindof
557 and irregular region because we're setting the scroll bar a little ways inside
558 of the text area. */
559 RectRgn((varsp->fTextBackgroundRgn = NewRgn()), &varsp->fRTextOutline);
560
561 /* set up the drawing environment */
562 SetPort(varsp->fDrawingEnvironment);
563
564 /* create the new edit field */
565
566 TXNFrameOptions frameOptions =
567 kTXNDontDrawCaretWhenInactiveMask ;
568 if ( ! ( wxStyle & wxTE_NOHIDESEL ) )
569 frameOptions |= kTXNDontDrawSelectionWhenInactiveMask ;
570
571 if ( wxStyle & wxTE_MULTILINE )
572 {
573 if ( ! ( wxStyle & wxTE_DONTWRAP ) )
574 frameOptions |= kTXNAlwaysWrapAtViewEdgeMask ;
575 else
576 {
577 frameOptions |= kTXNAlwaysWrapAtViewEdgeMask ;
578 frameOptions |= kTXNWantHScrollBarMask ;
579 }
580
581 if ( !(wxStyle & wxTE_NO_VSCROLL ) )
582 frameOptions |= kTXNWantVScrollBarMask ;
583 }
584 else
585 frameOptions |= kTXNSingleLineOnlyMask ;
586
587 if ( wxStyle & wxTE_READONLY )
588 frameOptions |= kTXNReadOnlyMask ;
589
590 TXNNewObject(NULL, varsp->fOwner, &varsp->fRTextArea,
591 frameOptions ,
592 kTXNTextEditStyleFrameType,
593 kTXNTextensionFile,
594 kTXNSystemDefaultEncoding,
595 &varsp->fTXNRec, &varsp->fTXNFrame, (TXNObjectRefcon) tpvars);
596
597 if ( !IsControlVisible( theControl ) )
598 TXNSetFrameBounds( varsp->fTXNRec, varsp->fRTextArea.top + 30000 , varsp->fRTextArea.left + 30000 ,
599 varsp->fRTextArea.bottom + 30000 , varsp->fRTextArea.right + 30000 , varsp->fTXNFrame);
600
601
602 if ( (wxStyle & wxTE_MULTILINE) && (wxStyle & wxTE_DONTWRAP) )
603 {
604 TXNControlTag tag = kTXNWordWrapStateTag ;
605 TXNControlData dat ;
606 dat.uValue = kTXNNoAutoWrap ;
607 TXNSetTXNObjectControls( varsp->fTXNRec , false , 1 , &tag , &dat ) ;
608 }
609 Str255 fontName ;
610 SInt16 fontSize ;
611 Style fontStyle ;
612
613 GetThemeFont(kThemeSmallSystemFont , GetApplicationScript() , fontName , &fontSize , &fontStyle ) ;
614
615 TXNTypeAttributes typeAttr[] =
616 {
617 { kTXNQDFontNameAttribute , kTXNQDFontNameAttributeSize , { (void*) fontName } } ,
618 { kTXNQDFontSizeAttribute , kTXNFontSizeAttributeSize , { (void*) (fontSize << 16) } } ,
619 { kTXNQDFontStyleAttribute , kTXNQDFontStyleAttributeSize , { (void*) normal } } ,
620 } ;
621
622 err = TXNSetTypeAttributes (varsp->fTXNRec, sizeof( typeAttr ) / sizeof(TXNTypeAttributes) , typeAttr,
623 kTXNStartOffset,
624 kTXNEndOffset);
625 /* set the field's background */
626
627 tback.bgType = kTXNBackgroundTypeRGB;
628 tback.bg.color = rgbWhite;
629 TXNSetBackground( varsp->fTXNRec, &tback);
630
631 /* unlock our storage */
632 HUnlock((Handle) tpvars);
633 /* perform final activations and setup for our text field. Here,
634 we assume that the window is going to be the 'active' window. */
635 TPActivatePaneText(tpvars, varsp->fIsActive && varsp->fInFocus);
636 /* all done */
637 return err;
638}
639
640
641
642
2646f485
SC
643IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
644
645BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
646 EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
647 EVT_CHAR(wxTextCtrl::OnChar)
648 EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
649 EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
650 EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
651 EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
652 EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
653
654 EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
655 EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
656 EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
657 EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
658 EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
659END_EVENT_TABLE()
2646f485
SC
660
661static void SetTXNData( TXNObject txn , const wxString& st , TXNOffset start , TXNOffset end )
662{
663#if wxUSE_UNICODE
664#if SIZEOF_WCHAR_T == 2
7d8268a1 665 size_t len = st.Len() ;
2646f485
SC
666 TXNSetData( txn , kTXNUnicodeTextData, (void*)st.wc_str(), len * 2,
667 start, end);
668#else
7d8268a1
WS
669 wxMBConvUTF16BE converter ;
670 ByteCount byteBufferLen = converter.WC2MB( NULL , st.wc_str() , 0 ) ;
671 UniChar *unibuf = (UniChar*) malloc(byteBufferLen) ;
672 converter.WC2MB( (char*) unibuf , st.wc_str() , byteBufferLen ) ;
2646f485
SC
673 TXNSetData( txn , kTXNUnicodeTextData, (void*)unibuf, byteBufferLen ,
674 start, end);
7d8268a1 675 free( unibuf ) ;
2646f485
SC
676#endif
677#else
7d8268a1 678 wxCharBuffer text = st.mb_str(wxConvLocal) ;
2646f485
SC
679 TXNSetData( txn , kTXNTextData, (void*)text.data(), strlen( text ) ,
680 start, end);
7d8268a1 681#endif
2646f485
SC
682}
683
684// Text item
685void wxTextCtrl::Init()
686{
687 m_macTE = NULL ;
688 m_macTXN = NULL ;
689 m_macTXNvars = NULL ;
690 m_macUsesTXN = false ;
691
692 m_editable = true ;
693 m_dirty = false;
694
695 m_maxLength = TE_UNLIMITED_LENGTH ;
696}
697
698wxTextCtrl::~wxTextCtrl()
699{
700 if ( m_macUsesTXN )
701 {
702 SetControlReference((ControlHandle)m_macControl, 0) ;
703 TXNDeleteObject((TXNObject)m_macTXN);
704 /* delete our private storage */
705 DisposeHandle((Handle) m_macTXNvars);
706 /* zero the control reference */
707 }
708}
709
710const short kVerticalMargin = 2 ;
711const short kHorizontalMargin = 2 ;
712
713bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
714 const wxString& str,
715 const wxPoint& pos,
716 const wxSize& size, long style,
717 const wxValidator& validator,
718 const wxString& name)
719{
720 m_macTE = NULL ;
721 m_macTXN = NULL ;
722 m_macTXNvars = NULL ;
723 m_macUsesTXN = false ;
724 m_editable = true ;
725
726 m_macUsesTXN = ! (style & wxTE_PASSWORD ) ;
727
728 m_macUsesTXN &= (TXNInitTextension != (void*) kUnresolvedCFragSymbolAddress) ;
729
730 // base initialization
731 if ( !wxTextCtrlBase::Create(parent, id, pos, size, style & ~(wxHSCROLL|wxVSCROLL), validator, name) )
7d8268a1 732 return false;
2646f485
SC
733
734 wxSize mySize = size ;
735 if ( m_macUsesTXN )
736 {
737 m_macHorizontalBorder = 5 ; // additional pixels around the real control
738 m_macVerticalBorder = 3 ;
739 }
740 else
741 {
742 m_macHorizontalBorder = 5 ; // additional pixels around the real control
743 m_macVerticalBorder = 5 ;
744 }
745
746
747 Rect bounds ;
748 Str255 title ;
749 /*
750 if ( mySize.y == -1 )
751 {
752 mySize.y = 13 ;
753 if ( m_windowStyle & wxTE_MULTILINE )
754 mySize.y *= 5 ;
755
756 mySize.y += 2 * m_macVerticalBorder ;
757 }
758 */
759 MacPreControlCreate( parent , id , wxEmptyString , pos , mySize ,style, validator , name , &bounds , title ) ;
760
761 if ( m_windowStyle & wxTE_MULTILINE )
762 {
763 wxASSERT_MSG( !(m_windowStyle & wxTE_PROCESS_ENTER),
764 wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") );
765
766 m_windowStyle |= wxTE_PROCESS_ENTER;
767 }
768
769 if ( m_windowStyle & wxTE_READONLY)
770 {
7d8268a1 771 m_editable = false ;
2646f485
SC
772 }
773
774 wxString st = str ;
775 wxMacConvertNewlines13To10( &st ) ;
776 if ( !m_macUsesTXN )
777 {
6bc3b8e9 778 m_macControl = (WXWidget) ::NewControl( MAC_WXHWND(parent->MacGetRootWindow()) , &bounds , "\p" , false , 0 , 0 , 1,
2646f485
SC
779 (style & wxTE_PASSWORD) ? kControlEditTextPasswordProc : kControlEditTextProc , (long) this ) ;
780 long size ;
781 ::GetControlData((ControlHandle) m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*)((TEHandle *)&m_macTE) , &size ) ;
782
783 }
784 else
785 {
786 short featurSet;
787
788 featurSet = kControlSupportsEmbedding | kControlSupportsFocus | kControlWantsIdle
789 | kControlWantsActivate | kControlHandlesTracking | kControlHasSpecialBackground
790 | kControlGetsFocusOnClick | kControlSupportsLiveFeedback;
791 /* create the control */
6bc3b8e9 792 m_macControl = (WXWidget) ::NewControl(MAC_WXHWND(parent->MacGetRootWindow()), &bounds, "\p", false , featurSet, 0, featurSet, kControlUserPaneProc, 0);
2646f485
SC
793 /* set up the mUP specific features and data */
794 mUPOpenControl((ControlHandle) m_macControl, m_windowStyle );
795 }
796 MacPostControlCreate() ;
797
798 if ( !m_macUsesTXN )
799 {
7d8268a1 800 wxCharBuffer text = st.mb_str(wxConvLocal) ;
2646f485
SC
801 ::SetControlData( (ControlHandle) m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , strlen(text) , text ) ;
802 }
803 else
804 {
805 STPTextPaneVars **tpvars;
806 /* set up locals */
807 tpvars = (STPTextPaneVars **) GetControlReference((ControlHandle) m_macControl);
808 /* set the text in the record */
809 m_macTXN = (**tpvars).fTXNRec ;
810 SetTXNData( (TXNObject) m_macTXN , st , kTXNStartOffset, kTXNEndOffset ) ;
811 m_macTXNvars = tpvars ;
812 m_macUsesTXN = true ;
813 TXNSetSelection( (TXNObject) m_macTXN, 0, 0);
814 TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart);
815 }
816
7d8268a1 817 return true;
2646f485
SC
818}
819
820wxString wxTextCtrl::GetValue() const
821{
822 Size actualSize = 0;
823 wxString result ;
824 OSStatus err ;
825 if ( !m_macUsesTXN )
826 {
827 err = ::GetControlDataSize((ControlHandle) m_macControl, 0,
828 ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag, &actualSize ) ;
829
7d8268a1
WS
830 if ( err )
831 return wxEmptyString ;
2646f485 832
7d8268a1
WS
833 if ( actualSize > 0 )
834 {
835 wxCharBuffer buf(actualSize) ;
2646f485
SC
836 ::GetControlData( (ControlHandle) m_macControl, 0,
837 ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag,
838 actualSize , buf.data() , &actualSize ) ;
839 result = wxString( buf , wxConvLocal) ;
840 }
841 }
842 else
843 {
844#if wxUSE_UNICODE
845 Handle theText ;
846 err = TXNGetDataEncoded( ((TXNObject) m_macTXN), kTXNStartOffset, kTXNEndOffset, &theText , kTXNUnicodeTextData );
847 // all done
848 if ( err )
849 {
850 actualSize = 0 ;
851 }
852 else
853 {
854 actualSize = GetHandleSize( theText ) / sizeof( UniChar) ;
855 if ( actualSize > 0 )
856 {
857 wxChar *ptr = result.GetWriteBuf(actualSize*sizeof(wxChar)) ;
7d8268a1 858#if SIZEOF_WCHAR_T == 2
2646f485
SC
859 wxStrncpy( ptr , (wxChar*) *theText , actualSize ) ;
860#else
7d8268a1
WS
861 wxMBConvUTF16BE converter ;
862 HLock( theText ) ;
863 converter.MB2WC( ptr , (const char*)*theText , actualSize ) ;
864 HUnlock( theText ) ;
2646f485
SC
865#endif
866 ptr[actualSize] = 0 ;
867 result.UngetWriteBuf( actualSize *sizeof(wxChar) ) ;
868 }
869 DisposeHandle( theText ) ;
870 }
871#else
872 Handle theText ;
873 err = TXNGetDataEncoded( ((TXNObject) m_macTXN), kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData );
874 // all done
875 if ( err )
876 {
877 actualSize = 0 ;
878 }
879 else
880 {
881 actualSize = GetHandleSize( theText ) ;
882 if ( actualSize > 0 )
883 {
884 HLock( theText ) ;
885 result = wxString( *theText , wxConvLocal , actualSize ) ;
886 HUnlock( theText ) ;
887 }
888 DisposeHandle( theText ) ;
889 }
890#endif
891 }
892 wxMacConvertNewlines10To13( &result ) ;
893 return result ;
894}
895
896void wxTextCtrl::GetSelection(long* from, long* to) const
897{
898 if ( !m_macUsesTXN )
899 {
900 *from = (**((TEHandle) m_macTE)).selStart;
901 *to = (**((TEHandle) m_macTE)).selEnd;
902 }
903 else
904 {
905 TXNGetSelection( (TXNObject) m_macTXN , (TXNOffset*) from , (TXNOffset*) to ) ;
906 }
907}
908
909void wxTextCtrl::SetValue(const wxString& str)
910{
911 wxString st = str ;
912 wxMacConvertNewlines13To10( &st ) ;
913 if ( !m_macUsesTXN )
914 {
7d8268a1 915 wxCharBuffer text = st.mb_str(wxConvLocal) ;
2646f485
SC
916 ::SetControlData( (ControlHandle) m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , strlen(text) , text ) ;
917 }
918 else
919 {
920 bool formerEditable = m_editable ;
921 if ( !formerEditable )
922 SetEditable(true) ;
923 SetTXNData( (TXNObject) m_macTXN , st , kTXNStartOffset, kTXNEndOffset ) ;
924 TXNSetSelection( (TXNObject) m_macTXN, 0, 0);
925 TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart);
926 if ( !formerEditable )
927 SetEditable(formerEditable) ;
928 }
929 MacRedrawControl() ;
930}
931
932void wxTextCtrl::SetMaxLength(unsigned long len)
933{
934 m_maxLength = len ;
935}
936
937bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
938{
939 if ( m_macUsesTXN )
940 {
941 bool formerEditable = m_editable ;
942 if ( !formerEditable )
943 SetEditable(true) ;
944 TXNTypeAttributes typeAttr[4] ;
945 Str255 fontName = "\pMonaco" ;
946 SInt16 fontSize = 12 ;
947 Style fontStyle = normal ;
948 RGBColor color ;
949 int attrCounter = 0 ;
950 if ( style.HasFont() )
951 {
952 const wxFont &font = style.GetFont() ;
953 wxMacStringToPascal( font.GetFaceName() , fontName ) ;
954 fontSize = font.GetPointSize() ;
955 if ( font.GetUnderlined() )
956 fontStyle |= underline ;
957 if ( font.GetWeight() == wxBOLD )
958 fontStyle |= bold ;
959 if ( font.GetStyle() == wxITALIC )
960 fontStyle |= italic ;
961
962 typeAttr[attrCounter].tag = kTXNQDFontNameAttribute ;
963 typeAttr[attrCounter].size = kTXNQDFontNameAttributeSize ;
964 typeAttr[attrCounter].data.dataPtr = (void*) fontName ;
965 typeAttr[attrCounter+1].tag = kTXNQDFontSizeAttribute ;
966 typeAttr[attrCounter+1].size = kTXNFontSizeAttributeSize ;
967 typeAttr[attrCounter+1].data.dataValue = (fontSize << 16) ;
968 typeAttr[attrCounter+2].tag = kTXNQDFontStyleAttribute ;
969 typeAttr[attrCounter+2].size = kTXNQDFontStyleAttributeSize ;
970 typeAttr[attrCounter+2].data.dataValue = fontStyle ;
971 attrCounter += 3 ;
972
973 }
974 if ( style.HasTextColour() )
975 {
976 typeAttr[attrCounter].tag = kTXNQDFontColorAttribute ;
977 typeAttr[attrCounter].size = kTXNQDFontColorAttributeSize ;
978 typeAttr[attrCounter].data.dataPtr = (void*) &color ;
979 color = MAC_WXCOLORREF(style.GetTextColour().GetPixel()) ;
980 attrCounter += 1 ;
981 }
982
983 if ( attrCounter > 0 )
984 {
985#ifdef __WXDEBUG__
986 OSStatus status =
987#endif // __WXDEBUG__
988 TXNSetTypeAttributes ((TXNObject)m_macTXN, attrCounter , typeAttr, start,end);
989 wxASSERT_MSG( status == noErr , wxT("Couldn't set text attributes") ) ;
990 }
991 if ( !formerEditable )
992 SetEditable(formerEditable) ;
993 }
7d8268a1 994 return true ;
2646f485
SC
995}
996
997bool wxTextCtrl::SetDefaultStyle(const wxTextAttr& style)
998{
999 wxTextCtrlBase::SetDefaultStyle( style ) ;
1000 SetStyle( kTXNUseCurrentSelection , kTXNUseCurrentSelection , GetDefaultStyle() ) ;
7d8268a1 1001 return true ;
2646f485
SC
1002}
1003
1004// Clipboard operations
1005void wxTextCtrl::Copy()
1006{
1007 if (CanCopy())
1008 {
1009 if ( !m_macUsesTXN )
1010 {
1011 TECopy( ((TEHandle) m_macTE) ) ;
1012 ClearCurrentScrap();
1013 TEToScrap() ;
1014 MacRedrawControl() ;
1015 }
1016 else
1017 {
1018 ClearCurrentScrap();
1019 TXNCopy((TXNObject)m_macTXN);
1020 TXNConvertToPublicScrap();
1021 }
1022 }
1023}
1024
1025void wxTextCtrl::Cut()
1026{
1027 if (CanCut())
1028 {
1029 if ( !m_macUsesTXN )
1030 {
1031 TECut( ((TEHandle) m_macTE) ) ;
1032 ClearCurrentScrap();
1033 TEToScrap() ;
1034 MacRedrawControl() ;
1035 }
1036 else
1037 {
1038 ClearCurrentScrap();
1039 TXNCut((TXNObject)m_macTXN);
1040 TXNConvertToPublicScrap();
1041 }
1042 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
2646f485
SC
1043 event.SetEventObject( this );
1044 GetEventHandler()->ProcessEvent(event);
1045 }
1046}
1047
1048void wxTextCtrl::Paste()
1049{
1050 if (CanPaste())
1051 {
1052 if ( !m_macUsesTXN )
1053 {
1054 TEFromScrap() ;
1055 TEPaste( (TEHandle) m_macTE ) ;
1056 MacRedrawControl() ;
1057 }
1058 else
1059 {
1060 TXNConvertFromPublicScrap();
1061 TXNPaste((TXNObject)m_macTXN);
1062 SetStyle( kTXNUseCurrentSelection , kTXNUseCurrentSelection , GetDefaultStyle() ) ;
1063 }
1064 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
2646f485
SC
1065 event.SetEventObject( this );
1066 GetEventHandler()->ProcessEvent(event);
1067 }
1068}
1069
1070bool wxTextCtrl::CanCopy() const
1071{
1072 // Can copy if there's a selection
1073 long from, to;
1074 GetSelection(& from, & to);
1075 return (from != to);
1076}
1077
1078bool wxTextCtrl::CanCut() const
1079{
1080 if ( !IsEditable() )
1081 {
1082 return false ;
1083 }
1084 // Can cut if there's a selection
1085 long from, to;
1086 GetSelection(& from, & to);
1087 return (from != to);
1088}
1089
1090bool wxTextCtrl::CanPaste() const
1091{
1092 if (!IsEditable())
7d8268a1 1093 return false;
2646f485
SC
1094
1095#if TARGET_CARBON
1096 OSStatus err = noErr;
1097 ScrapRef scrapRef;
1098
1099 err = GetCurrentScrap( &scrapRef );
1100 if ( err != noTypeErr && err != memFullErr )
1101 {
1102 ScrapFlavorFlags flavorFlags;
1103 Size byteCount;
1104
1105 if (( err = GetScrapFlavorFlags( scrapRef, 'TEXT', &flavorFlags )) == noErr)
1106 {
1107 if (( err = GetScrapFlavorSize( scrapRef, 'TEXT', &byteCount )) == noErr)
1108 {
7d8268a1 1109 return true ;
2646f485
SC
1110 }
1111 }
1112 }
7d8268a1 1113 return false;
2646f485
SC
1114
1115#else
1116 long offset ;
1117 if ( GetScrap( NULL , 'TEXT' , &offset ) > 0 )
1118 {
7d8268a1 1119 return true ;
2646f485
SC
1120 }
1121#endif
7d8268a1 1122 return false ;
2646f485
SC
1123}
1124
1125void wxTextCtrl::SetEditable(bool editable)
1126{
1127 if ( editable != m_editable )
1128 {
1129 m_editable = editable ;
1130 if ( !m_macUsesTXN )
1131 {
1132 if ( editable )
1133 UMAActivateControl( (ControlHandle) m_macControl ) ;
1134 else
1135 UMADeactivateControl((ControlHandle) m_macControl ) ;
1136 }
1137 else
1138 {
1139 TXNControlTag tag[] = { kTXNIOPrivilegesTag } ;
1140 TXNControlData data[] = { { editable ? kTXNReadWrite : kTXNReadOnly } } ;
1141 TXNSetTXNObjectControls( (TXNObject) m_macTXN , false , sizeof(tag) / sizeof (TXNControlTag) , tag , data ) ;
1142 }
1143 }
1144}
1145
1146void wxTextCtrl::SetInsertionPoint(long pos)
1147{
1148 SetSelection( pos , pos ) ;
1149}
1150
1151void wxTextCtrl::SetInsertionPointEnd()
1152{
7d8268a1 1153 wxTextPos pos = GetLastPosition();
2646f485
SC
1154 SetInsertionPoint(pos);
1155}
1156
1157long wxTextCtrl::GetInsertionPoint() const
1158{
1159 long begin,end ;
1160 GetSelection( &begin , &end ) ;
1161 return begin ;
1162}
1163
7d8268a1 1164wxTextPos wxTextCtrl::GetLastPosition() const
2646f485
SC
1165{
1166 if ( !m_macUsesTXN )
1167 {
1168 return (**((TEHandle) m_macTE)).teLength ;
1169 }
1170 else
1171 {
1172 Handle theText ;
1173 long actualsize ;
1174 OSErr err = TXNGetDataEncoded( (TXNObject) m_macTXN, kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData );
1175 /* all done */
1176 if ( err )
1177 {
1178 actualsize = 0 ;
1179 }
1180 else
1181 {
1182 actualsize = GetHandleSize( theText ) ;
1183 DisposeHandle( theText ) ;
1184 }
1185 return actualsize ;
1186 }
1187}
1188
1189void wxTextCtrl::Replace(long from, long to, const wxString& str)
1190{
1191 wxString value = str ;
1192 wxMacConvertNewlines13To10( &value ) ;
1193 if ( !m_macUsesTXN )
1194 {
1195 ControlEditTextSelectionRec selection ;
1196
1197 selection.selStart = from ;
1198 selection.selEnd = to ;
1199 ::SetControlData((ControlHandle) m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
1200 TESetSelect( from , to , ((TEHandle) m_macTE) ) ;
1201 TEDelete( ((TEHandle) m_macTE) ) ;
faa94f3e 1202 TEInsert( value , value.length() , ((TEHandle) m_macTE) ) ;
2646f485
SC
1203 }
1204 else
1205 {
1206 bool formerEditable = m_editable ;
1207 if ( !formerEditable )
1208 SetEditable(true) ;
1209 TXNSetSelection( ((TXNObject) m_macTXN) , from , to ) ;
1210 TXNClear( ((TXNObject) m_macTXN) ) ;
1211 SetTXNData( (TXNObject) m_macTXN , str , kTXNUseCurrentSelection, kTXNUseCurrentSelection ) ;
1212 if ( !formerEditable )
1213 SetEditable( formerEditable ) ;
1214 }
1215 Refresh() ;
1216}
1217
1218void wxTextCtrl::Remove(long from, long to)
1219{
1220 if ( !m_macUsesTXN )
1221 {
1222 ControlEditTextSelectionRec selection ;
1223
1224 selection.selStart = from ;
1225 selection.selEnd = to ;
1226 ::SetControlData( (ControlHandle) m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
1227 TEDelete( ((TEHandle) m_macTE) ) ;
1228 }
1229 else
1230 {
1231 bool formerEditable = m_editable ;
1232 if ( !formerEditable )
1233 SetEditable(true) ;
1234 TXNSetSelection( ((TXNObject) m_macTXN) , from , to ) ;
1235 TXNClear( ((TXNObject) m_macTXN) ) ;
1236 if ( !formerEditable )
1237 SetEditable( formerEditable ) ;
1238 }
1239 Refresh() ;
1240}
1241
1242void wxTextCtrl::SetSelection(long from, long to)
1243{
1244 if ( !m_macUsesTXN )
1245 {
1246 ControlEditTextSelectionRec selection ;
1247 if ((from == -1) && (to == -1))
1248 {
7d8268a1
WS
1249 selection.selStart = 0 ;
1250 selection.selEnd = 32767 ;
1251 }
2646f485
SC
1252 else
1253 {
7d8268a1
WS
1254 selection.selStart = from ;
1255 selection.selEnd = to ;
1256 }
2646f485
SC
1257
1258 TESetSelect( selection.selStart , selection.selEnd , ((TEHandle) m_macTE) ) ;
1259 ::SetControlData((ControlHandle) m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
1260 }
1261 else
1262 {
1263 STPTextPaneVars **tpvars;
1264 /* set up our locals */
1265 tpvars = (STPTextPaneVars **) GetControlReference((ControlHandle) m_macControl);
1266 /* and our drawing environment as the operation
1267 may force a redraw in the text area. */
1268 SetPort((**tpvars).fDrawingEnvironment);
1269 /* change the selection */
1270 if ((from == -1) && (to == -1))
7d8268a1 1271 TXNSelectAll((TXNObject) m_macTXN);
2646f485 1272 else
7d8268a1 1273 TXNSetSelection( (**tpvars).fTXNRec, from, to);
2646f485
SC
1274 TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart);
1275 }
1276}
1277
1278bool wxTextCtrl::LoadFile(const wxString& file)
1279{
1280 if ( wxTextCtrlBase::LoadFile(file) )
1281 {
7d8268a1 1282 return true;
2646f485
SC
1283 }
1284
7d8268a1 1285 return false;
2646f485
SC
1286}
1287
1288void wxTextCtrl::WriteText(const wxString& str)
1289{
1290 wxString st = str ;
1291 wxMacConvertNewlines13To10( &st ) ;
1292 if ( !m_macUsesTXN )
1293 {
7d8268a1 1294 wxCharBuffer text = st.mb_str(wxConvLocal) ;
2646f485
SC
1295 TEInsert( text , strlen(text) , ((TEHandle) m_macTE) ) ;
1296 }
1297 else
1298 {
1299 bool formerEditable = m_editable ;
1300 if ( !formerEditable )
1301 SetEditable(true) ;
1302 long start , end , dummy ;
1303 GetSelection( &start , &dummy ) ;
1304 SetTXNData( (TXNObject) m_macTXN , st , kTXNUseCurrentSelection, kTXNUseCurrentSelection ) ;
1305 GetSelection( &dummy , &end ) ;
1306 SetStyle( start , end , GetDefaultStyle() ) ;
1307 if ( !formerEditable )
1308 SetEditable( formerEditable ) ;
1309 }
1310 MacRedrawControl() ;
1311}
1312
1313void wxTextCtrl::AppendText(const wxString& text)
1314{
1315 SetInsertionPointEnd();
1316 WriteText(text);
1317}
1318
1319void wxTextCtrl::Clear()
1320{
1321 if ( !m_macUsesTXN )
1322 {
1323 ::SetControlData((ControlHandle) m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 0 , (char*) ((const char*)NULL) ) ;
1324 }
1325 else
1326 {
1327 TXNSetSelection( (TXNObject)m_macTXN , kTXNStartOffset , kTXNEndOffset ) ;
1328 TXNClear((TXNObject)m_macTXN);
1329 }
1330 Refresh() ;
1331}
1332
1333bool wxTextCtrl::IsModified() const
1334{
1335 return m_dirty;
1336}
1337
1338bool wxTextCtrl::IsEditable() const
1339{
1340 return IsEnabled() && m_editable ;
1341}
1342
1343bool wxTextCtrl::AcceptsFocus() const
1344{
1345 // we don't want focus if we can't be edited
1346 return /*IsEditable() && */ wxControl::AcceptsFocus();
1347}
1348
1349wxSize wxTextCtrl::DoGetBestSize() const
1350{
1351 int wText = 100 ;
1352
1353 int hText;
1354 if ( m_macUsesTXN )
1355 {
1356 hText = 17 ;
1357 }
1358 else
1359 {
1360 hText = 13 ;
1361 }
1362/*
1363 int cx, cy;
1364 wxGetCharSize(GetHWND(), &cx, &cy, &GetFont());
1365
1366 int wText = DEFAULT_ITEM_WIDTH;
1367
1368 int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
1369
1370 return wxSize(wText, hText);
1371*/
1372 if ( m_windowStyle & wxTE_MULTILINE )
1373 {
1374 hText *= 5 ;
1375 }
1376 hText += 2 * m_macVerticalBorder ;
1377 wText += 2 * m_macHorizontalBorder ;
1378 //else: for single line control everything is ok
1379 return wxSize(wText, hText);
1380}
1381
1382// ----------------------------------------------------------------------------
1383// Undo/redo
1384// ----------------------------------------------------------------------------
1385
1386void wxTextCtrl::Undo()
1387{
1388 if (CanUndo())
1389 {
7d8268a1 1390 if ( m_macUsesTXN )
2646f485 1391 {
7d8268a1 1392 TXNUndo((TXNObject)m_macTXN);
2646f485
SC
1393 }
1394 }
1395}
1396
1397void wxTextCtrl::Redo()
1398{
1399 if (CanRedo())
1400 {
7d8268a1 1401 if ( m_macUsesTXN )
2646f485 1402 {
7d8268a1 1403 TXNRedo((TXNObject)m_macTXN);
2646f485
SC
1404 }
1405 }
1406}
1407
1408bool wxTextCtrl::CanUndo() const
1409{
7d8268a1 1410 if ( !IsEditable() )
2646f485 1411 {
7d8268a1 1412 return false ;
2646f485 1413 }
7d8268a1 1414 if ( m_macUsesTXN )
2646f485 1415 {
7d8268a1 1416 return TXNCanUndo((TXNObject)m_macTXN,NULL);
2646f485 1417 }
7d8268a1 1418 return false ;
2646f485
SC
1419}
1420
1421bool wxTextCtrl::CanRedo() const
1422{
7d8268a1 1423 if ( !IsEditable() )
2646f485 1424 {
7d8268a1 1425 return false ;
2646f485 1426 }
7d8268a1 1427 if ( m_macUsesTXN )
2646f485 1428 {
7d8268a1 1429 return TXNCanRedo((TXNObject)m_macTXN,NULL);
2646f485 1430 }
7d8268a1 1431 return false ;
2646f485
SC
1432}
1433
1434// Makes modifie or unmodified
1435void wxTextCtrl::MarkDirty()
1436{
1437 m_dirty = true;
1438}
1439
1440void wxTextCtrl::DiscardEdits()
1441{
1442 m_dirty = false;
1443}
1444
1445int wxTextCtrl::GetNumberOfLines() const
1446{
7d8268a1 1447 if ( m_macUsesTXN )
2646f485
SC
1448 {
1449 ItemCount lines ;
1450 TXNGetLineCount((TXNObject)m_macTXN, &lines ) ;
1451 return lines ;
1452 }
1453 else
7d8268a1 1454 {
2646f485
SC
1455 wxString content = GetValue() ;
1456
1457 int count = 1;
faa94f3e 1458 for (size_t i = 0; i < content.length() ; i++)
2646f485
SC
1459 {
1460 if (content[i] == '\r') count++;
1461 }
1462 return count;
1463 }
1464}
1465
1466long wxTextCtrl::XYToPosition(long x, long y) const
1467{
1468 // TODO
1469 return 0;
1470}
1471
1472bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
1473{
7d8268a1 1474 return false ;
2646f485
SC
1475}
1476
1477void wxTextCtrl::ShowPosition(long pos)
1478{
1479#if TARGET_RT_MAC_MACHO && defined(AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER)
7d8268a1 1480 if ( m_macUsesTXN )
2646f485
SC
1481 {
1482 Point current ;
1483 Point desired ;
1484 TXNOffset selstart , selend ;
1485 TXNGetSelection( (TXNObject) m_macTXN , &selstart , &selend) ;
1486 TXNOffsetToPoint( (TXNObject) m_macTXN, selstart , &current);
1487 TXNOffsetToPoint( (TXNObject) m_macTXN, pos , &desired);
1488 //TODO use HIPoints for 10.3 and above
1489 if ( (UInt32) TXNScroll != (UInt32) kUnresolvedCFragSymbolAddress )
1490 {
1491 OSErr theErr = noErr;
1492 SInt32 dv = desired.v - current.v ;
1493 SInt32 dh = desired.h - current.h ;
1494 TXNShowSelection( (TXNObject) m_macTXN , true ) ;
7d8268a1 1495 theErr = TXNScroll( (TXNObject) m_macTXN, kTXNScrollUnitsInPixels , kTXNScrollUnitsInPixels , &dv , &dh );
2646f485
SC
1496 wxASSERT_MSG( theErr == noErr, _T("TXNScroll returned an error!") );
1497 }
1498 }
1499#endif
1500}
1501
1502int wxTextCtrl::GetLineLength(long lineNo) const
1503{
1504 // TODO change this if possible to reflect real lines
1505 wxString content = GetValue() ;
1506
1507 // Find line first
1508 int count = 0;
faa94f3e 1509 for (size_t i = 0; i < content.length() ; i++)
2646f485
SC
1510 {
1511 if (count == lineNo)
1512 {
1513 // Count chars in line then
1514 count = 0;
faa94f3e 1515 for (size_t j = i; j < content.length(); j++)
2646f485
SC
1516 {
1517 count++;
1518 if (content[j] == '\n') return count;
1519 }
1520
1521 return count;
1522 }
1523 if (content[i] == '\n') count++;
1524 }
1525 return 0;
1526}
1527
1528wxString wxTextCtrl::GetLineText(long lineNo) const
1529{
1530 // TODO change this if possible to reflect real lines
1531 wxString content = GetValue() ;
1532
1533 // Find line first
1534 int count = 0;
faa94f3e 1535 for (size_t i = 0; i < content.length() ; i++)
2646f485
SC
1536 {
1537 if (count == lineNo)
1538 {
1539 // Add chars in line then
1540 wxString tmp;
1541
faa94f3e 1542 for (size_t j = i; j < content.length(); j++)
2646f485
SC
1543 {
1544 if (content[j] == '\n')
1545 return tmp;
1546
1547 tmp += content[j];
1548 }
1549
1550 return tmp;
1551 }
1552 if (content[i] == '\n') count++;
1553 }
1554 return wxEmptyString ;
1555}
1556
1557/*
1558 * Text item
1559 */
1560
1561void wxTextCtrl::Command(wxCommandEvent & event)
1562{
1563 SetValue (event.GetString());
1564 ProcessCommand (event);
1565}
1566
1567void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
1568{
1569 // By default, load the first file into the text window.
1570 if (event.GetNumberOfFiles() > 0)
1571 {
1572 LoadFile(event.GetFiles()[0]);
1573 }
1574}
1575
1576void wxTextCtrl::OnChar(wxKeyEvent& event)
1577{
1578 int key = event.GetKeyCode() ;
1579 bool eat_key = false ;
1580
1581 if ( key == 'c' && event.MetaDown() )
1582 {
1583 if ( CanCopy() )
1584 Copy() ;
1585 return ;
1586 }
1587
1588 if ( !IsEditable() && key != WXK_LEFT && key != WXK_RIGHT && key != WXK_DOWN && key != WXK_UP && key != WXK_TAB &&
8e13c1ec 1589 !( key == WXK_RETURN && ( (m_windowStyle & wxTE_PROCESS_ENTER) || (m_windowStyle & wxTE_MULTILINE) ) )
faa94f3e 1590/* && key != WXK_PAGEUP && key != WXK_PAGEDOWN && key != WXK_HOME && key != WXK_END */
2646f485
SC
1591 )
1592 {
1593 // eat it
1594 return ;
1595 }
1596
1597 // assume that any key not processed yet is going to modify the control
1598 m_dirty = true;
1599
1600 if ( key == 'v' && event.MetaDown() )
1601 {
1602 if ( CanPaste() )
1603 Paste() ;
1604 return ;
1605 }
1606 if ( key == 'x' && event.MetaDown() )
1607 {
1608 if ( CanCut() )
1609 Cut() ;
1610 return ;
1611 }
1612 switch ( key )
1613 {
1614 case WXK_RETURN:
8e13c1ec 1615 if (m_windowStyle & wxTE_PROCESS_ENTER)
2646f485
SC
1616 {
1617 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
1618 event.SetEventObject( this );
1619 event.SetString( GetValue() );
1620 if ( GetEventHandler()->ProcessEvent(event) )
1621 return;
1622 }
1623 if ( !(m_windowStyle & wxTE_MULTILINE) )
1624 {
1625 wxWindow *parent = GetParent();
1626 while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL ) {
1627 parent = parent->GetParent() ;
1628 }
1629 if ( parent && parent->GetDefaultItem() )
1630 {
1631 wxButton *def = wxDynamicCast(parent->GetDefaultItem(),
1632 wxButton);
1633 if ( def && def->IsEnabled() )
1634 {
1635 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
1636 event.SetEventObject(def);
1637 def->Command(event);
1638 return ;
1639 }
1640 }
1641
77ffb593 1642 // this will make wxWidgets eat the ENTER key so that
2646f485
SC
1643 // we actually prevent line wrapping in a single line
1644 // text control
7d8268a1 1645 eat_key = true;
2646f485
SC
1646 }
1647
1648 break;
1649
1650 case WXK_TAB:
5f6cfda7 1651 if ( !(m_windowStyle & wxTE_PROCESS_TAB))
2646f485 1652 {
eedc82f4
JS
1653 int flags = 0;
1654 if (!event.ShiftDown())
1655 flags |= wxNavigationKeyEvent::IsForward ;
1656 if (event.ControlDown())
1657 flags |= wxNavigationKeyEvent::WinChange ;
1658 Navigate(flags);
6ad49e18
JS
1659 return;
1660 }
1661 else
1662 {
1663 // This is necessary (don't know why) or the tab will not
1664 // be inserted.
1665 WriteText(wxT("\t"));
2646f485
SC
1666 }
1667 break;
1668 }
1669
1670 if (!eat_key)
1671 {
1672 // perform keystroke handling
1673#if TARGET_CARBON
1674 if ( m_macUsesTXN && wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL )
1675 CallNextEventHandler((EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() , (EventRef) wxTheApp->MacGetCurrentEvent() ) ;
7d8268a1 1676 else
2646f485
SC
1677 {
1678 EventRecord rec ;
1679 if ( wxMacConvertEventToRecord( (EventRef) wxTheApp->MacGetCurrentEvent() , &rec ) )
1680 {
1681 EventRecord *ev = &rec ;
1682 short keycode ;
1683 short keychar ;
1684 keychar = short(ev->message & charCodeMask);
1685 keycode = short(ev->message & keyCodeMask) >> 8 ;
1686
1687 ::HandleControlKey( (ControlHandle) m_macControl , keycode , keychar , ev->modifiers ) ;
1688 }
1689 }
1690#else
1691 EventRecord *ev = (EventRecord*) wxTheApp->MacGetCurrentEvent() ;
1692 short keycode ;
1693 short keychar ;
1694 keychar = short(ev->message & charCodeMask);
1695 keycode = short(ev->message & keyCodeMask) >> 8 ;
1696
1697 ::HandleControlKey( (ControlHandle) m_macControl , keycode , keychar , ev->modifiers ) ;
1698#endif
1699 }
1700 if ( ( key >= 0x20 && key < WXK_START ) ||
1701 key == WXK_RETURN ||
1702 key == WXK_DELETE ||
1703 key == WXK_BACK)
1704 {
1705 wxCommandEvent event1(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
2646f485
SC
1706 event1.SetEventObject( this );
1707 wxPostEvent(GetEventHandler(),event1);
1708 }
1709}
1710
1711void wxTextCtrl::MacSuperShown( bool show )
1712{
1713 bool former = m_macControlIsShown ;
1714 wxControl::MacSuperShown( show ) ;
1715 if ( (former != m_macControlIsShown) && m_macUsesTXN )
1716 {
1717 if ( m_macControlIsShown )
1718 TXNSetFrameBounds( (TXNObject) m_macTXN, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.top, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.left,
1719 (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.bottom,(**(STPTextPaneVars **)m_macTXNvars).fRTextArea.right, (**(STPTextPaneVars **)m_macTXNvars).fTXNFrame);
1720 else
1721 TXNSetFrameBounds( (TXNObject) m_macTXN, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.top + 30000, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.left,
1722 (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.bottom + 30000, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.right, (**(STPTextPaneVars **)m_macTXNvars).fTXNFrame);
1723 }
1724}
1725
1726bool wxTextCtrl::Show(bool show)
1727{
1728 bool former = m_macControlIsShown ;
1729
1730 bool retval = wxControl::Show( show ) ;
1731
1732 if ( former != m_macControlIsShown && m_macUsesTXN )
1733 {
1734 if ( m_macControlIsShown )
1735 TXNSetFrameBounds( (TXNObject) m_macTXN, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.top, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.left,
1736 (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.bottom,(**(STPTextPaneVars **)m_macTXNvars).fRTextArea.right, (**(STPTextPaneVars **)m_macTXNvars).fTXNFrame);
1737 else
1738 TXNSetFrameBounds( (TXNObject) m_macTXN, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.top + 30000, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.left,
1739 (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.bottom + 30000, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.right, (**(STPTextPaneVars **)m_macTXNvars).fTXNFrame);
1740 }
1741
1742 return retval ;
1743}
1744
1745// ----------------------------------------------------------------------------
1746// standard handlers for standard edit menu events
1747// ----------------------------------------------------------------------------
1748
1749void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
1750{
1751 Cut();
1752}
1753
1754void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event))
1755{
1756 Copy();
1757}
1758
1759void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event))
1760{
1761 Paste();
1762}
1763
1764void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event))
1765{
1766 Undo();
1767}
1768
1769void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event))
1770{
1771 Redo();
1772}
1773
1774void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
1775{
1776 event.Enable( CanCut() );
1777}
1778
1779void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
1780{
1781 event.Enable( CanCopy() );
1782}
1783
1784void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
1785{
1786 event.Enable( CanPaste() );
1787}
1788
1789void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
1790{
1791 event.Enable( CanUndo() );
1792}
1793
1794void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
1795{
1796 event.Enable( CanRedo() );
1797}
1798
1799bool wxTextCtrl::MacSetupCursor( const wxPoint& pt )
1800{
1801 if ( m_macUsesTXN )
1802 return true ;
1803 else
1804 return wxWindow::MacSetupCursor( pt ) ;
1805}
1806
1807#endif
1808 // wxUSE_TEXTCTRL