]> git.saurik.com Git - wxWidgets.git/blob - src/mac/textctrl.cpp
wxThread::Delete() doesn't wait until the next event occurs before waking up any...
[wxWidgets.git] / src / mac / textctrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: textctrl.cpp
3 // Purpose: wxTextCtrl
4 // Author: AUTHOR
5 // Modified by:
6 // Created: ??/??/98
7 // RCS-ID: $Id$
8 // Copyright: (c) AUTHOR
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 #include <fstream.h>
27
28 #include "wx/app.h"
29 #include "wx/dc.h"
30 #include "wx/button.h"
31 #include "wx/toplevel.h"
32 #include "wx/textctrl.h"
33 #include "wx/notebook.h"
34 #include "wx/tabctrl.h"
35 #include "wx/settings.h"
36 #include "wx/filefn.h"
37 #include "wx/utils.h"
38
39 #if defined(__BORLANDC__) && !defined(__WIN32__)
40 #include <alloc.h>
41 #elif !defined(__MWERKS__) && !defined(__GNUWIN32) && !defined(__DARWIN__)
42 #include <malloc.h>
43 #endif
44
45 #ifndef __DARWIN__
46 #include <Scrap.h>
47 #endif
48 #include <MacTextEditor.h>
49 #include "ATSUnicode.h"
50 #include "TextCommon.h"
51 #include "TextEncodingConverter.h"
52 #include "wx/mac/uma.h"
53
54 extern wxApp *wxTheApp ;
55
56 // CS:TODO we still have a problem getting properly at the text events of a control because under Carbon
57 // the MLTE engine registers itself for the key events thus the normal flow never occurs, the only measure for the
58 // moment is to avoid setting the true focus on the control, the proper solution at the end would be to have
59 // an alternate path for carbon key events that routes automatically into the same wx flow of events
60
61 #include "MacTextEditor.h"
62
63 /* part codes */
64
65 /* kmUPTextPart is the part code we return to indicate the user has clicked
66 in the text area of our control */
67 #define kmUPTextPart 1
68
69 /* kmUPScrollPart is the part code we return to indicate the user has clicked
70 in the scroll bar part of the control. */
71 #define kmUPScrollPart 2
72
73
74 /* routines for using existing user pane controls.
75 These routines are useful for cases where you would like to use an
76 existing user pane control in, say, a dialog window as a scrolling
77 text edit field.*/
78
79 /* mUPOpenControl initializes a user pane control so it will be drawn
80 and will behave as a scrolling text edit field inside of a window.
81 This routine performs all of the initialization steps necessary,
82 except it does not create the user pane control itself. theControl
83 should refer to a user pane control that you have either created
84 yourself or extracted from a dialog's control heirarchy using
85 the GetDialogItemAsControl routine. */
86 OSStatus mUPOpenControl(ControlHandle theControl, bool multiline);
87
88 /* Utility Routines */
89
90 enum {
91 kShiftKeyCode = 56
92 };
93
94 /* kUserClickedToFocusPart is a part code we pass to the SetKeyboardFocus
95 routine. In our focus switching routine this part code is understood
96 as meaning 'the user has clicked in the control and we need to switch
97 the current focus to ourselves before we can continue'. */
98 #define kUserClickedToFocusPart 100
99
100
101 /* kmUPClickScrollDelayTicks is a time measurement in ticks used to
102 slow the speed of 'auto scrolling' inside of our clickloop routine.
103 This value prevents the text from wizzzzzing by while the mouse
104 is being held down inside of the text area. */
105 #define kmUPClickScrollDelayTicks 3
106
107
108 /* STPTextPaneVars is a structure used for storing the the mUP Control's
109 internal variables and state information. A handle to this record is
110 stored in the pane control's reference value field using the
111 SetControlReference routine. */
112
113 typedef struct {
114 /* OS records referenced */
115 TXNObject fTXNRec; /* the txn record */
116 TXNFrameID fTXNFrame; /* the txn frame ID */
117 ControlHandle fUserPaneRec; /* handle to the user pane control */
118 WindowPtr fOwner; /* window containing control */
119 GrafPtr fDrawingEnvironment; /* grafport where control is drawn */
120 /* flags */
121 Boolean fInFocus; /* true while the focus rect is drawn around the control */
122 Boolean fIsActive; /* true while the control is drawn in the active state */
123 Boolean fTEActive; /* reflects the activation state of the text edit record */
124 Boolean fInDialogWindow; /* true if displayed in a dialog window */
125 /* calculated locations */
126 Rect fRTextArea; /* area where the text is drawn */
127 Rect fRFocusOutline; /* rectangle used to draw the focus box */
128 Rect fRTextOutline; /* rectangle used to draw the border */
129 RgnHandle fTextBackgroundRgn; /* background region for the text, erased before calling TEUpdate */
130 /* our focus advance override routine */
131 EventHandlerUPP handlerUPP;
132 EventHandlerRef handlerRef;
133 bool fMultiline ;
134 } STPTextPaneVars;
135
136
137
138
139 /* Univerals Procedure Pointer variables used by the
140 mUP Control. These variables are set up
141 the first time that mUPOpenControl is called. */
142 ControlUserPaneDrawUPP gTPDrawProc = NULL;
143 ControlUserPaneHitTestUPP gTPHitProc = NULL;
144 ControlUserPaneTrackingUPP gTPTrackProc = NULL;
145 ControlUserPaneIdleUPP gTPIdleProc = NULL;
146 ControlUserPaneKeyDownUPP gTPKeyProc = NULL;
147 ControlUserPaneActivateUPP gTPActivateProc = NULL;
148 ControlUserPaneFocusUPP gTPFocusProc = NULL;
149
150 /* TPActivatePaneText activates or deactivates the text edit record
151 according to the value of setActive. The primary purpose of this
152 routine is to ensure each call is only made once. */
153 static void TPActivatePaneText(STPTextPaneVars **tpvars, Boolean setActive) {
154 STPTextPaneVars *varsp;
155 varsp = *tpvars;
156 if (varsp->fTEActive != setActive) {
157
158 varsp->fTEActive = setActive;
159
160 TXNActivate(varsp->fTXNRec, varsp->fTXNFrame, varsp->fTEActive);
161
162 if (varsp->fInFocus)
163 TXNFocus( varsp->fTXNRec, varsp->fTEActive);
164 }
165 }
166
167
168 /* TPFocusPaneText set the focus state for the text record. */
169 static void TPFocusPaneText(STPTextPaneVars **tpvars, Boolean setFocus) {
170 STPTextPaneVars *varsp;
171 varsp = *tpvars;
172 if (varsp->fInFocus != setFocus) {
173 varsp->fInFocus = setFocus;
174 TXNFocus( varsp->fTXNRec, varsp->fInFocus);
175 }
176 }
177
178
179 /* TPPaneDrawProc is called to redraw the control and for update events
180 referring to the control. This routine erases the text area's background,
181 and redraws the text. This routine assumes the scroll bar has been
182 redrawn by a call to DrawControls. */
183 static pascal void TPPaneDrawProc(ControlRef theControl, ControlPartCode thePart) {
184 STPTextPaneVars **tpvars, *varsp;
185 char state;
186 Rect bounds;
187 /* set up our globals */
188
189 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
190 if (tpvars != NULL) {
191 state = HGetState((Handle) tpvars);
192 HLock((Handle) tpvars);
193 varsp = *tpvars;
194
195 /* save the drawing state */
196 SetPort((**tpvars).fDrawingEnvironment);
197 /* verify our boundary */
198 GetControlBounds(theControl, &bounds);
199 if ( ! EqualRect(&bounds, &varsp->fRFocusOutline) ) {
200 // scrollbar is on the border, we add one
201 Rect oldbounds = varsp->fRFocusOutline ;
202 InsetRect( &oldbounds , -1 , -1 ) ;
203
204 InvalWindowRect( GetControlOwner( theControl ) , &oldbounds ) ;
205 SetRect(&varsp->fRFocusOutline, bounds.left, bounds.top, bounds.right, bounds.bottom);
206 SetRect(&varsp->fRTextOutline, bounds.left, bounds.top, bounds.right, bounds.bottom);
207 SetRect(&varsp->fRTextArea, bounds.left + 2 , bounds.top + (varsp->fMultiline ? 0 : 2) ,
208 bounds.right - (varsp->fMultiline ? 0 : 2), bounds.bottom - (varsp->fMultiline ? 0 : 2));
209 RectRgn(varsp->fTextBackgroundRgn, &varsp->fRTextOutline);
210 TXNSetFrameBounds( varsp->fTXNRec, varsp->fRTextArea.top, varsp->fRTextArea.left,
211 varsp->fRTextArea.bottom, varsp->fRTextArea.right, varsp->fTXNFrame);
212 }
213
214 /* update the text region */
215 RGBColor white = { 65535 , 65535 , 65535 } ;
216 RGBBackColor( &white ) ;
217 EraseRgn(varsp->fTextBackgroundRgn);
218 TXNDraw(varsp->fTXNRec, NULL);
219 /* restore the drawing environment */
220 /* draw the text frame and focus frame (if necessary) */
221 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
222 if ((**tpvars).fIsActive && varsp->fInFocus) DrawThemeFocusRect(&varsp->fRFocusOutline, true);
223 /* release our globals */
224 HSetState((Handle) tpvars, state);
225 }
226 }
227
228
229 /* TPPaneHitTestProc is called when the control manager would
230 like to determine what part of the control the mouse resides over.
231 We also call this routine from our tracking proc to determine how
232 to handle mouse clicks. */
233 static pascal ControlPartCode TPPaneHitTestProc(ControlHandle theControl, Point where) {
234 STPTextPaneVars **tpvars;
235 ControlPartCode result;
236 char state;
237 /* set up our locals and lock down our globals*/
238 result = 0;
239 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
240 if (tpvars != NULL) {
241 state = HGetState((Handle) tpvars);
242 HLock((Handle) tpvars);
243 /* find the region where we clicked */
244 if (PtInRect(where, &(**tpvars).fRTextArea)) {
245 result = kmUPTextPart;
246 } else result = 0;
247 /* release oure globals */
248 HSetState((Handle) tpvars, state);
249 }
250 return result;
251 }
252
253
254
255
256
257 /* TPPaneTrackingProc is called when the mouse is being held down
258 over our control. This routine handles clicks in the text area
259 and in the scroll bar. */
260 static pascal ControlPartCode TPPaneTrackingProc(ControlHandle theControl, Point startPt, ControlActionUPP actionProc) {
261 STPTextPaneVars **tpvars, *varsp;
262 char state;
263 ControlPartCode partCodeResult;
264 /* make sure we have some variables... */
265 partCodeResult = 0;
266 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
267 if (tpvars != NULL) {
268 /* lock 'em down */
269 state = HGetState((Handle) tpvars);
270 HLock((Handle) tpvars);
271 varsp = *tpvars;
272 /* we don't do any of these functions unless we're in focus */
273 if ( ! varsp->fInFocus) {
274 WindowPtr owner;
275 owner = GetControlOwner(theControl);
276 ClearKeyboardFocus(owner);
277 SetKeyboardFocus(owner, theControl, kUserClickedToFocusPart);
278 }
279 /* find the location for the click */
280 switch (TPPaneHitTestProc(theControl, startPt)) {
281
282 /* handle clicks in the text part */
283 case kmUPTextPart:
284 { SetPort((**tpvars).fDrawingEnvironment);
285 TXNClick( varsp->fTXNRec, (const EventRecord*) wxTheApp->MacGetCurrentEvent());
286 }
287 break;
288
289 }
290
291 HSetState((Handle) tpvars, state);
292 }
293 return partCodeResult;
294 }
295
296
297 /* TPPaneIdleProc is our user pane idle routine. When our text field
298 is active and in focus, we use this routine to set the cursor. */
299 static pascal void TPPaneIdleProc(ControlHandle theControl) {
300 STPTextPaneVars **tpvars, *varsp;
301 /* set up locals */
302 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
303 if (tpvars != NULL) {
304 /* if we're not active, then we have nothing to say about the cursor */
305 if ((**tpvars).fIsActive) {
306 char state;
307 Rect bounds;
308 Point mousep;
309 /* lock down the globals */
310 state = HGetState((Handle) tpvars);
311 HLock((Handle) tpvars);
312 varsp = *tpvars;
313 /* get the current mouse coordinates (in our window) */
314 SetPortWindowPort(GetControlOwner(theControl));
315 GetMouse(&mousep);
316 /* there's a 'focus thing' and an 'unfocused thing' */
317 if (varsp->fInFocus) {
318 /* flash the cursor */
319 SetPort((**tpvars).fDrawingEnvironment);
320 TXNIdle(varsp->fTXNRec);
321 /* set the cursor */
322 if (PtInRect(mousep, &varsp->fRTextArea)) {
323 RgnHandle theRgn;
324 RectRgn((theRgn = NewRgn()), &varsp->fRTextArea);
325 TXNAdjustCursor(varsp->fTXNRec, theRgn);
326 DisposeRgn(theRgn);
327 } else SetThemeCursor(kThemeArrowCursor);
328 } else {
329 /* if it's in our bounds, set the cursor */
330 GetControlBounds(theControl, &bounds);
331 if (PtInRect(mousep, &bounds))
332 SetThemeCursor(kThemeArrowCursor);
333 }
334
335 HSetState((Handle) tpvars, state);
336 }
337 }
338 }
339
340
341 /* TPPaneKeyDownProc is called whenever a keydown event is directed
342 at our control. Here, we direct the keydown event to the text
343 edit record and redraw the scroll bar and text field as appropriate. */
344 static pascal ControlPartCode TPPaneKeyDownProc(ControlHandle theControl,
345 SInt16 keyCode, SInt16 charCode, SInt16 modifiers) {
346 STPTextPaneVars **tpvars;
347 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
348 if (tpvars != NULL) {
349 if ((**tpvars).fInFocus) {
350 /* turn autoscrolling on and send the key event to text edit */
351 SetPort((**tpvars).fDrawingEnvironment);
352 EventRecord ev ;
353 memset( &ev , 0 , sizeof( ev ) ) ;
354 ev.what = keyDown ;
355 ev.modifiers = modifiers ;
356 ev.message = (( keyCode & keyCodeMask ) << 8 ) + ( charCode & charCodeMask ) ;
357 TXNKeyDown( (**tpvars).fTXNRec, &ev);
358 }
359 }
360 return kControlEntireControl;
361 }
362
363
364 /* TPPaneActivateProc is called when the window containing
365 the user pane control receives activate events. Here, we redraw
366 the control and it's text as necessary for the activation state. */
367 static pascal void TPPaneActivateProc(ControlHandle theControl, Boolean activating) {
368 Rect bounds;
369 STPTextPaneVars **tpvars, *varsp;
370 char state;
371 /* set up locals */
372 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
373 if (tpvars != NULL) {
374 state = HGetState((Handle) tpvars);
375 HLock((Handle) tpvars);
376 varsp = *tpvars;
377 /* de/activate the text edit record */
378 SetPort((**tpvars).fDrawingEnvironment);
379 GetControlBounds(theControl, &bounds);
380 varsp->fIsActive = activating;
381 TPActivatePaneText(tpvars, varsp->fIsActive && varsp->fInFocus);
382 /* redraw the frame */
383 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
384 if (varsp->fInFocus) DrawThemeFocusRect(&varsp->fRFocusOutline, varsp->fIsActive);
385 HSetState((Handle) tpvars, state);
386 }
387 }
388
389
390 /* TPPaneFocusProc is called when every the focus changes to or
391 from our control. Herein, switch the focus appropriately
392 according to the parameters and redraw the control as
393 necessary. */
394 static pascal ControlPartCode TPPaneFocusProc(ControlHandle theControl, ControlFocusPart action) {
395 ControlPartCode focusResult;
396 STPTextPaneVars **tpvars, *varsp;
397 char state;
398 /* set up locals */
399 focusResult = kControlFocusNoPart;
400 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
401 if (tpvars != NULL) {
402 state = HGetState((Handle) tpvars);
403 HLock((Handle) tpvars);
404 varsp = *tpvars;
405 /* if kControlFocusPrevPart and kControlFocusNextPart are received when the user is
406 tabbing forwards (or shift tabbing backwards) through the items in the dialog,
407 and kControlFocusNextPart will be received. When the user clicks in our field
408 and it is not the current focus, then the constant kUserClickedToFocusPart will
409 be received. The constant kControlFocusNoPart will be received when our control
410 is the current focus and the user clicks in another control. In your focus routine,
411 you should respond to these codes as follows:
412
413 kControlFocusNoPart - turn off focus and return kControlFocusNoPart. redraw
414 the control and the focus rectangle as necessary.
415
416 kControlFocusPrevPart or kControlFocusNextPart - toggle focus on or off
417 depending on its current state. redraw the control and the focus rectangle
418 as appropriate for the new focus state. If the focus state is 'off', return the constant
419 kControlFocusNoPart, otherwise return a non-zero part code.
420 kUserClickedToFocusPart - is a constant defined for this example. You should
421 define your own value for handling click-to-focus type events. */
422 /* save the drawing state */
423 SetPort((**tpvars).fDrawingEnvironment);
424 /* calculate the next highlight state */
425 switch (action) {
426 default:
427 case kControlFocusNoPart:
428 TPFocusPaneText(tpvars, false);
429 focusResult = kControlFocusNoPart;
430 break;
431 case kUserClickedToFocusPart:
432 TPFocusPaneText(tpvars, true);
433 focusResult = 1;
434 break;
435 case kControlFocusPrevPart:
436 case kControlFocusNextPart:
437 TPFocusPaneText(tpvars, ( ! varsp->fInFocus));
438 focusResult = varsp->fInFocus ? 1 : kControlFocusNoPart;
439 break;
440 }
441 TPActivatePaneText(tpvars, varsp->fIsActive && varsp->fInFocus);
442 /* redraw the text fram and focus rectangle to indicate the
443 new focus state */
444 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
445 DrawThemeFocusRect(&varsp->fRFocusOutline, varsp->fIsActive && varsp->fInFocus);
446 /* done */
447 HSetState((Handle) tpvars, state);
448 }
449 return focusResult;
450 }
451
452
453 /* mUPOpenControl initializes a user pane control so it will be drawn
454 and will behave as a scrolling text edit field inside of a window.
455 This routine performs all of the initialization steps necessary,
456 except it does not create the user pane control itself. theControl
457 should refer to a user pane control that you have either created
458 yourself or extracted from a dialog's control heirarchy using
459 the GetDialogItemAsControl routine. */
460 OSStatus mUPOpenControl(ControlHandle theControl, bool multiline)
461 {
462 Rect bounds;
463 WindowRef theWindow;
464 STPTextPaneVars **tpvars, *varsp;
465 OSStatus err;
466 RGBColor rgbWhite = {0xFFFF, 0xFFFF, 0xFFFF};
467 TXNBackground tback;
468
469 /* set up our globals */
470 if (gTPDrawProc == NULL) gTPDrawProc = NewControlUserPaneDrawUPP(TPPaneDrawProc);
471 if (gTPHitProc == NULL) gTPHitProc = NewControlUserPaneHitTestUPP(TPPaneHitTestProc);
472 if (gTPTrackProc == NULL) gTPTrackProc = NewControlUserPaneTrackingUPP(TPPaneTrackingProc);
473 if (gTPIdleProc == NULL) gTPIdleProc = NewControlUserPaneIdleUPP(TPPaneIdleProc);
474 if (gTPKeyProc == NULL) gTPKeyProc = NewControlUserPaneKeyDownUPP(TPPaneKeyDownProc);
475 if (gTPActivateProc == NULL) gTPActivateProc = NewControlUserPaneActivateUPP(TPPaneActivateProc);
476 if (gTPFocusProc == NULL) gTPFocusProc = NewControlUserPaneFocusUPP(TPPaneFocusProc);
477
478 /* allocate our private storage */
479 tpvars = (STPTextPaneVars **) NewHandleClear(sizeof(STPTextPaneVars));
480 SetControlReference(theControl, (long) tpvars);
481 HLock((Handle) tpvars);
482 varsp = *tpvars;
483 /* set the initial settings for our private data */
484 varsp->fMultiline = multiline ;
485 varsp->fInFocus = false;
486 varsp->fIsActive = true;
487 varsp->fTEActive = true; // in order to get a deactivate
488 varsp->fUserPaneRec = theControl;
489 theWindow = varsp->fOwner = GetControlOwner(theControl);
490
491 varsp->fDrawingEnvironment = (GrafPtr) GetWindowPort(theWindow);
492
493 varsp->fInDialogWindow = ( GetWindowKind(varsp->fOwner) == kDialogWindowKind );
494 /* set up the user pane procedures */
495 SetControlData(theControl, kControlEntireControl, kControlUserPaneDrawProcTag, sizeof(gTPDrawProc), &gTPDrawProc);
496 SetControlData(theControl, kControlEntireControl, kControlUserPaneHitTestProcTag, sizeof(gTPHitProc), &gTPHitProc);
497 SetControlData(theControl, kControlEntireControl, kControlUserPaneTrackingProcTag, sizeof(gTPTrackProc), &gTPTrackProc);
498 SetControlData(theControl, kControlEntireControl, kControlUserPaneIdleProcTag, sizeof(gTPIdleProc), &gTPIdleProc);
499 SetControlData(theControl, kControlEntireControl, kControlUserPaneKeyDownProcTag, sizeof(gTPKeyProc), &gTPKeyProc);
500 SetControlData(theControl, kControlEntireControl, kControlUserPaneActivateProcTag, sizeof(gTPActivateProc), &gTPActivateProc);
501 SetControlData(theControl, kControlEntireControl, kControlUserPaneFocusProcTag, sizeof(gTPFocusProc), &gTPFocusProc);
502 /* calculate the rectangles used by the control */
503 GetControlBounds(theControl, &bounds);
504 SetRect(&varsp->fRFocusOutline, bounds.left, bounds.top, bounds.right, bounds.bottom);
505 SetRect(&varsp->fRTextOutline, bounds.left, bounds.top, bounds.right, bounds.bottom);
506 SetRect(&varsp->fRTextArea, bounds.left + 2 , bounds.top + (varsp->fMultiline ? 0 : 2) ,
507 bounds.right - (varsp->fMultiline ? 0 : 2), bounds.bottom - (varsp->fMultiline ? 0 : 2));
508 /* calculate the background region for the text. In this case, it's kindof
509 and irregular region because we're setting the scroll bar a little ways inside
510 of the text area. */
511 RectRgn((varsp->fTextBackgroundRgn = NewRgn()), &varsp->fRTextOutline);
512
513 /* set up the drawing environment */
514 SetPort(varsp->fDrawingEnvironment);
515
516 /* create the new edit field */
517 TXNNewObject(NULL, varsp->fOwner, &varsp->fRTextArea,
518 ( multiline ? kTXNWantVScrollBarMask : 0 ) |
519 kTXNDontDrawCaretWhenInactiveMask |
520 kTXNDontDrawSelectionWhenInactiveMask |
521 kTXNAlwaysWrapAtViewEdgeMask,
522 kTXNTextEditStyleFrameType,
523 kTXNTextensionFile,
524 kTXNSystemDefaultEncoding,
525 &varsp->fTXNRec, &varsp->fTXNFrame, (TXNObjectRefcon) tpvars);
526
527 Str255 fontName ;
528 SInt16 fontSize ;
529 Style fontStyle ;
530
531 GetThemeFont(kThemeSmallSystemFont , GetApplicationScript() , fontName , &fontSize , &fontStyle ) ;
532
533 TXNTypeAttributes typeAttr[] =
534 {
535 { kTXNQDFontNameAttribute , kTXNQDFontNameAttributeSize , { (void*) fontName } } ,
536 { kTXNQDFontSizeAttribute , kTXNFontSizeAttributeSize , { (void*) (fontSize << 16) } } ,
537 { kTXNQDFontStyleAttribute , kTXNQDFontStyleAttributeSize , { (void*) normal } } ,
538 } ;
539
540 OSStatus status = TXNSetTypeAttributes (varsp->fTXNRec, sizeof( typeAttr ) / sizeof(TXNTypeAttributes) , typeAttr,
541 kTXNStartOffset,
542 kTXNEndOffset);
543 /* set the field's background */
544 tback.bgType = kTXNBackgroundTypeRGB;
545 tback.bg.color = rgbWhite;
546 TXNSetBackground( varsp->fTXNRec, &tback);
547
548 /* unlock our storage */
549 HUnlock((Handle) tpvars);
550 /* perform final activations and setup for our text field. Here,
551 we assume that the window is going to be the 'active' window. */
552 TPActivatePaneText(tpvars, varsp->fIsActive && varsp->fInFocus);
553 /* all done */
554 return noErr;
555 }
556
557
558
559
560 #if !USE_SHARED_LIBRARY
561 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
562
563 BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
564 EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
565 EVT_CHAR(wxTextCtrl::OnChar)
566 EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
567 EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
568 EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
569 EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
570 EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
571
572 EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
573 EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
574 EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
575 EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
576 EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
577 END_EVENT_TABLE()
578 #endif
579
580 // Text item
581 wxTextCtrl::wxTextCtrl()
582 {
583 m_macTE = NULL ;
584 m_macTXN = NULL ;
585 m_macTXNvars = NULL ;
586 m_macUsesTXN = false ;
587 m_editable = true ;
588 }
589
590 wxTextCtrl::~wxTextCtrl()
591 {
592 if ( m_macUsesTXN )
593 {
594 SetControlReference((ControlHandle)m_macControl, 0) ;
595 TXNDeleteObject((TXNObject)m_macTXN);
596 /* delete our private storage */
597 DisposeHandle((Handle) m_macTXNvars);
598 /* zero the control reference */
599 }
600 }
601
602 const short kVerticalMargin = 2 ;
603 const short kHorizontalMargin = 2 ;
604
605 bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
606 const wxString& st,
607 const wxPoint& pos,
608 const wxSize& size, long style,
609 const wxValidator& validator,
610 const wxString& name)
611 {
612 m_macTE = NULL ;
613 m_macTXN = NULL ;
614 m_macTXNvars = NULL ;
615 m_macUsesTXN = false ;
616 m_editable = true ;
617
618 m_macUsesTXN = ! (style & wxTE_PASSWORD ) ;
619
620 m_macUsesTXN &= (TXNInitTextension != (void*) kUnresolvedCFragSymbolAddress) ;
621
622 // base initialization
623 if ( !CreateBase(parent, id, pos, size, style, validator, name) )
624 return FALSE;
625
626 wxSize mySize = size ;
627 if ( m_macUsesTXN )
628 {
629 m_macHorizontalBorder = 5 ; // additional pixels around the real control
630 m_macVerticalBorder = 3 ;
631 }
632 else
633 {
634 m_macHorizontalBorder = 5 ; // additional pixels around the real control
635 m_macVerticalBorder = 5 ;
636 }
637
638
639 Rect bounds ;
640 Str255 title ;
641 /*
642 if ( mySize.y == -1 )
643 {
644 mySize.y = 13 ;
645 if ( m_windowStyle & wxTE_MULTILINE )
646 mySize.y *= 5 ;
647
648 mySize.y += 2 * m_macVerticalBorder ;
649 }
650 */
651 MacPreControlCreate( parent , id , "" , pos , mySize ,style, validator , name , &bounds , title ) ;
652
653 if ( m_windowStyle & wxTE_MULTILINE )
654 {
655 wxASSERT_MSG( !(m_windowStyle & wxTE_PROCESS_ENTER),
656 wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") );
657
658 m_windowStyle |= wxTE_PROCESS_ENTER;
659 }
660
661
662 if ( !m_macUsesTXN )
663 {
664 m_macControl = ::NewControl( MAC_WXHWND(parent->MacGetRootWindow()) , &bounds , "\p" , true , 0 , 0 , 1,
665 (style & wxTE_PASSWORD) ? kControlEditTextPasswordProc : kControlEditTextProc , (long) this ) ;
666 long size ;
667 ::GetControlData((ControlHandle) m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &((TEHandle) m_macTE) , &size ) ;
668
669 }
670 else
671 {
672 short featurSet;
673
674 featurSet = kControlSupportsEmbedding | kControlSupportsFocus // | kControlWantsIdle
675 | kControlWantsActivate | kControlHandlesTracking | kControlHasSpecialBackground
676 | kControlGetsFocusOnClick | kControlSupportsLiveFeedback;
677 /* create the control */
678 m_macControl = NewControl(MAC_WXHWND(parent->MacGetRootWindow()), &bounds, "\p", true, featurSet, 0, featurSet, kControlUserPaneProc, 0);
679 /* set up the mUP specific features and data */
680 mUPOpenControl((ControlHandle) m_macControl, m_windowStyle & wxTE_MULTILINE );
681 if ( parent )
682 {
683 parent->MacGetTopLevelWindow()->MacInstallEventHandler() ;
684 }
685 }
686 MacPostControlCreate() ;
687
688 wxString value ;
689
690 if( wxApp::s_macDefaultEncodingIsPC )
691 value = wxMacMakeMacStringFromPC( st ) ;
692 else
693 value = st ;
694
695 if ( !m_macUsesTXN )
696 {
697 ::SetControlData( (ControlHandle) m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ;
698 }
699 else
700 {
701 STPTextPaneVars **tpvars;
702 /* set up locals */
703 tpvars = (STPTextPaneVars **) GetControlReference((ControlHandle) m_macControl);
704 /* set the text in the record */
705 TXNSetData( (**tpvars).fTXNRec, kTXNTextData, (void*)value.c_str(), value.Length(),
706 kTXNStartOffset, kTXNEndOffset);
707 m_macTXN = (**tpvars).fTXNRec ;
708 m_macTXNvars = tpvars ;
709 m_macUsesTXN = true ;
710 }
711
712 return TRUE;
713 }
714
715 wxString wxTextCtrl::GetValue() const
716 {
717 Size actualsize;
718 if ( !m_macUsesTXN )
719 {
720 ::GetControlData( (ControlHandle) m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 32767 , wxBuffer , &actualsize) ;
721 }
722 else
723 {
724 Handle theText ;
725 OSStatus err = TXNGetDataEncoded( ((TXNObject) m_macTXN), kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData );
726 /* all done */
727 if ( err )
728 {
729 actualsize = 0 ;
730 }
731 else
732 {
733 actualsize = GetHandleSize( theText ) ;
734 if (actualsize != 0)
735 strncpy( wxBuffer , *theText , actualsize ) ;
736 DisposeHandle( theText ) ;
737 }
738 }
739 wxBuffer[actualsize] = 0 ;
740 if( wxApp::s_macDefaultEncodingIsPC )
741 return wxMacMakePCStringFromMac( wxBuffer ) ;
742 else
743 return wxString(wxBuffer);
744 }
745
746 void wxTextCtrl::GetSelection(long* from, long* to) const
747 {
748 if ( !m_macUsesTXN )
749 {
750 *from = (**((TEHandle) m_macTE)).selStart;
751 *to = (**((TEHandle) m_macTE)).selEnd;
752 }
753 else
754 {
755 TXNGetSelection( ((TXNObject) m_macTXN) , (TXNOffset*) from , (TXNOffset*) to ) ;
756 }
757 }
758
759 void wxTextCtrl::SetValue(const wxString& st)
760 {
761 wxString value ;
762
763 if( wxApp::s_macDefaultEncodingIsPC )
764 value = wxMacMakeMacStringFromPC( st ) ;
765 else
766 value = st ;
767 if ( !m_macUsesTXN )
768 {
769 ::SetControlData((ControlHandle) m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ;
770 }
771 else
772 {
773 TXNSetData( ((TXNObject) m_macTXN), kTXNTextData, (void*)value.c_str(), value.Length(),
774 kTXNStartOffset, kTXNEndOffset);
775 }
776 MacRedrawControl() ;
777 }
778
779 // Clipboard operations
780 void wxTextCtrl::Copy()
781 {
782 if (CanCopy())
783 {
784 if ( !m_macUsesTXN )
785 {
786 TECopy( ((TEHandle) m_macTE) ) ;
787 ClearCurrentScrap();
788 TEToScrap() ;
789 MacRedrawControl() ;
790 }
791 else
792 {
793 ClearCurrentScrap();
794 TXNCopy((TXNObject)m_macTXN);
795 TXNConvertToPublicScrap();
796 }
797 }
798 }
799
800 void wxTextCtrl::Cut()
801 {
802 if (CanCut())
803 {
804 if ( !m_macUsesTXN )
805 {
806 TECut( ((TEHandle) m_macTE) ) ;
807 ClearCurrentScrap();
808 TEToScrap() ;
809 MacRedrawControl() ;
810 }
811 else
812 {
813 ClearCurrentScrap();
814 TXNCut((TXNObject)m_macTXN);
815 TXNConvertToPublicScrap();
816 }
817 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
818 event.SetString( GetValue() ) ;
819 event.SetEventObject( this );
820 GetEventHandler()->ProcessEvent(event);
821 }
822 }
823
824 void wxTextCtrl::Paste()
825 {
826 if (CanPaste())
827 {
828 if ( !m_macUsesTXN )
829 {
830 TEFromScrap() ;
831 TEPaste( (TEHandle) m_macTE ) ;
832 MacRedrawControl() ;
833 }
834 else
835 {
836 TXNConvertFromPublicScrap();
837 TXNPaste((TXNObject)m_macTXN);
838 }
839 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
840 event.SetString( GetValue() ) ;
841 event.SetEventObject( this );
842 GetEventHandler()->ProcessEvent(event);
843 }
844 }
845
846 bool wxTextCtrl::CanCopy() const
847 {
848 // Can copy if there's a selection
849 long from, to;
850 GetSelection(& from, & to);
851 return (from != to);
852 }
853
854 bool wxTextCtrl::CanCut() const
855 {
856 if ( !IsEditable() )
857 {
858 return false ;
859 }
860 // Can cut if there's a selection
861 long from, to;
862 GetSelection(& from, & to);
863 return (from != to);
864 }
865
866 bool wxTextCtrl::CanPaste() const
867 {
868 if (!IsEditable())
869 return FALSE;
870
871 long offset ;
872 #if TARGET_CARBON
873 OSStatus err = noErr;
874 ScrapRef scrapRef;
875
876 err = GetCurrentScrap( &scrapRef );
877 if ( err != noTypeErr && err != memFullErr )
878 {
879 ScrapFlavorFlags flavorFlags;
880 Size byteCount;
881
882 if (( err = GetScrapFlavorFlags( scrapRef, 'TEXT', &flavorFlags )) == noErr)
883 {
884 if (( err = GetScrapFlavorSize( scrapRef, 'TEXT', &byteCount )) == noErr)
885 {
886 return TRUE ;
887 }
888 }
889 }
890 return FALSE;
891
892 #else
893 if ( GetScrap( NULL , 'TEXT' , &offset ) > 0 )
894 {
895 return TRUE ;
896 }
897 #endif
898 return FALSE ;
899 }
900
901 void wxTextCtrl::SetEditable(bool editable)
902 {
903 if ( editable != m_editable )
904 {
905 m_editable = editable ;
906 if ( editable )
907 UMAActivateControl( (ControlHandle) m_macControl ) ;
908 else
909 UMADeactivateControl((ControlHandle) m_macControl ) ;
910 }
911 }
912
913 void wxTextCtrl::SetInsertionPoint(long pos)
914 {
915 SetSelection( pos , pos ) ;
916 }
917
918 void wxTextCtrl::SetInsertionPointEnd()
919 {
920 long pos = GetLastPosition();
921 SetInsertionPoint(pos);
922 }
923
924 long wxTextCtrl::GetInsertionPoint() const
925 {
926 long begin,end ;
927 GetSelection( &begin , &end ) ;
928 return begin ;
929 }
930
931 long wxTextCtrl::GetLastPosition() const
932 {
933 if ( !m_macUsesTXN )
934 {
935 return (**((TEHandle) m_macTE)).teLength ;
936 }
937 else
938 {
939 Handle theText ;
940 long actualsize ;
941 OSErr err = TXNGetDataEncoded( (TXNObject) m_macTXN, kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData );
942 /* all done */
943 if ( err )
944 {
945 actualsize = 0 ;
946 }
947 else
948 {
949 actualsize = GetHandleSize( theText ) ;
950 DisposeHandle( theText ) ;
951 }
952 return actualsize ;
953 }
954 }
955
956 void wxTextCtrl::Replace(long from, long to, const wxString& value)
957 {
958 if ( !m_macUsesTXN )
959 {
960 ControlEditTextSelectionRec selection ;
961
962 selection.selStart = from ;
963 selection.selEnd = to ;
964 ::SetControlData((ControlHandle) m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
965 TESetSelect( from , to , ((TEHandle) m_macTE) ) ;
966 TEDelete( ((TEHandle) m_macTE) ) ;
967 TEInsert( value , value.Length() , ((TEHandle) m_macTE) ) ;
968 }
969 else
970 {
971 TXNSetSelection( ((TXNObject) m_macTXN) , from , to ) ;
972 TXNClear( ((TXNObject) m_macTXN) ) ;
973 TXNSetData( ((TXNObject) m_macTXN), kTXNTextData, (void*)value.c_str(), value.Length(),
974 kTXNUseCurrentSelection, kTXNUseCurrentSelection);
975 }
976 Refresh() ;
977 }
978
979 void wxTextCtrl::Remove(long from, long to)
980 {
981 if ( !m_macUsesTXN )
982 {
983 ControlEditTextSelectionRec selection ;
984
985 selection.selStart = from ;
986 selection.selEnd = to ;
987 ::SetControlData( (ControlHandle) m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
988 TEDelete( ((TEHandle) m_macTE) ) ;
989 }
990 else
991 {
992 TXNSetSelection( ((TXNObject) m_macTXN) , from , to ) ;
993 TXNClear( ((TXNObject) m_macTXN) ) ;
994 }
995 Refresh() ;
996 }
997
998 void wxTextCtrl::SetSelection(long from, long to)
999 {
1000
1001 if ( !m_macUsesTXN )
1002 {
1003 ControlEditTextSelectionRec selection ;
1004 selection.selStart = from ;
1005 selection.selEnd = to ;
1006
1007 TESetSelect( selection.selStart , selection.selEnd , ((TEHandle) m_macTE) ) ;
1008 ::SetControlData((ControlHandle) m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
1009 }
1010 else
1011 {
1012 STPTextPaneVars **tpvars;
1013 /* set up our locals */
1014 tpvars = (STPTextPaneVars **) GetControlReference((ControlHandle) m_macControl);
1015 /* and our drawing environment as the operation
1016 may force a redraw in the text area. */
1017 SetPort((**tpvars).fDrawingEnvironment);
1018 /* change the selection */
1019 TXNSetSelection( (**tpvars).fTXNRec, from, to);
1020 }
1021 }
1022
1023 bool wxTextCtrl::LoadFile(const wxString& file)
1024 {
1025 if ( wxTextCtrlBase::LoadFile(file) )
1026 {
1027 return TRUE;
1028 }
1029
1030 return FALSE;
1031 }
1032
1033 void wxTextCtrl::WriteText(const wxString& text)
1034 {
1035 wxString value ;
1036 if( wxApp::s_macDefaultEncodingIsPC )
1037 value = wxMacMakeMacStringFromPC( text ) ;
1038 else
1039 value = text ;
1040 if ( !m_macUsesTXN )
1041 {
1042 TEInsert( value , value.Length() , ((TEHandle) m_macTE) ) ;
1043 }
1044 else
1045 {
1046 TXNSetData( ((TXNObject) m_macTXN), kTXNTextData, (void*) (const char*)value, value.Length(),
1047 kTXNUseCurrentSelection, kTXNUseCurrentSelection);
1048 }
1049 MacRedrawControl() ;
1050 }
1051
1052 void wxTextCtrl::AppendText(const wxString& text)
1053 {
1054 SetInsertionPointEnd();
1055 WriteText(text);
1056 }
1057
1058 void wxTextCtrl::Clear()
1059 {
1060 if ( !IsEditable() )
1061 {
1062 return ;
1063 }
1064 if ( !m_macUsesTXN )
1065 {
1066 ::SetControlData((ControlHandle) m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 0 , (char*) ((const char*)NULL) ) ;
1067 }
1068 else
1069 {
1070 ClearCurrentScrap();
1071 TXNClear((TXNObject)m_macTXN);
1072 }
1073 Refresh() ;
1074 }
1075
1076 bool wxTextCtrl::IsModified() const
1077 {
1078 return TRUE;
1079 }
1080
1081 bool wxTextCtrl::IsEditable() const
1082 {
1083 return IsEnabled() && m_editable ;
1084 }
1085
1086 bool wxTextCtrl::AcceptsFocus() const
1087 {
1088 // we don't want focus if we can't be edited
1089 return /*IsEditable() && */ wxControl::AcceptsFocus();
1090 }
1091
1092 wxSize wxTextCtrl::DoGetBestSize() const
1093 {
1094 int wText = 100 ;
1095
1096 int hText;
1097 if ( m_macUsesTXN )
1098 {
1099 hText = 17 ;
1100 }
1101 else
1102 {
1103 hText = 13 ;
1104 }
1105 /*
1106 int cx, cy;
1107 wxGetCharSize(GetHWND(), &cx, &cy, &GetFont());
1108
1109 int wText = DEFAULT_ITEM_WIDTH;
1110
1111 int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
1112
1113 return wxSize(wText, hText);
1114 */
1115 if ( m_windowStyle & wxTE_MULTILINE )
1116 {
1117 hText *= 5 ;
1118 }
1119 hText += 2 * m_macVerticalBorder ;
1120 wText += 2 * m_macHorizontalBorder ;
1121 //else: for single line control everything is ok
1122 return wxSize(wText, hText);
1123 }
1124
1125 // ----------------------------------------------------------------------------
1126 // Undo/redo
1127 // ----------------------------------------------------------------------------
1128
1129 void wxTextCtrl::Undo()
1130 {
1131 if (CanUndo())
1132 {
1133 }
1134 }
1135
1136 void wxTextCtrl::Redo()
1137 {
1138 if (CanRedo())
1139 {
1140 }
1141 }
1142
1143 bool wxTextCtrl::CanUndo() const
1144 {
1145 return FALSE ;
1146 }
1147
1148 bool wxTextCtrl::CanRedo() const
1149 {
1150 return FALSE ;
1151 }
1152
1153 // Makes 'unmodified'
1154 void wxTextCtrl::DiscardEdits()
1155 {
1156 // TODO
1157 }
1158
1159 int wxTextCtrl::GetNumberOfLines() const
1160 {
1161 // TODO change this if possible to reflect real lines
1162 wxString content = GetValue() ;
1163
1164 int count = 1;
1165 for (int i = 0; i < content.Length() ; i++)
1166 {
1167 if (content[i] == '\r') count++;
1168 }
1169
1170 return count;
1171 }
1172
1173 long wxTextCtrl::XYToPosition(long x, long y) const
1174 {
1175 // TODO
1176 return 0;
1177 }
1178
1179 bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
1180 {
1181 return FALSE ;
1182 }
1183
1184 void wxTextCtrl::ShowPosition(long pos)
1185 {
1186 // TODO
1187 }
1188
1189 int wxTextCtrl::GetLineLength(long lineNo) const
1190 {
1191 // TODO change this if possible to reflect real lines
1192 wxString content = GetValue() ;
1193
1194 // Find line first
1195 int count = 0;
1196 for (int i = 0; i < content.Length() ; i++)
1197 {
1198 if (count == lineNo)
1199 {
1200 // Count chars in line then
1201 count = 0;
1202 for (int j = i; j < content.Length(); j++)
1203 {
1204 count++;
1205 if (content[j] == '\r') return count;
1206 }
1207
1208 return count;
1209 }
1210 if (content[i] == '\r') count++;
1211 }
1212 return 0;
1213 }
1214
1215 wxString wxTextCtrl::GetLineText(long lineNo) const
1216 {
1217 // TODO change this if possible to reflect real lines
1218 wxString content = GetValue() ;
1219
1220 // Find line first
1221 int count = 0;
1222 for (int i = 0; i < content.Length() ; i++)
1223 {
1224 if (count == lineNo)
1225 {
1226 // Add chars in line then
1227 wxString tmp("");
1228
1229 for (int j = i; j < content.Length(); j++)
1230 {
1231 if (content[j] == '\r')
1232 return tmp;
1233
1234 tmp += content[j];
1235 }
1236
1237 return tmp;
1238 }
1239 if (content[i] == '\r') count++;
1240 }
1241 return "" ;
1242 }
1243
1244 /*
1245 * Text item
1246 */
1247
1248 void wxTextCtrl::Command(wxCommandEvent & event)
1249 {
1250 SetValue (event.GetString());
1251 ProcessCommand (event);
1252 }
1253
1254 void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
1255 {
1256 // By default, load the first file into the text window.
1257 if (event.GetNumberOfFiles() > 0)
1258 {
1259 LoadFile(event.GetFiles()[0]);
1260 }
1261 }
1262
1263 void wxTextCtrl::OnChar(wxKeyEvent& event)
1264 {
1265 int key = event.GetKeyCode() ;
1266 bool eat_key = false ;
1267
1268 if ( !IsEditable() && key != WXK_LEFT && key != WXK_RIGHT && key != WXK_DOWN && key != WXK_UP && key != WXK_TAB &&
1269 !( key == WXK_RETURN && ( (m_windowStyle & wxPROCESS_ENTER) || (m_windowStyle & wxTE_MULTILINE) ) )
1270 /* && key != WXK_PRIOR && key != WXK_NEXT && key != WXK_HOME && key != WXK_END */
1271 )
1272 {
1273 // eat it
1274 return ;
1275 }
1276 switch ( key )
1277 {
1278 case WXK_RETURN:
1279 if (m_windowStyle & wxPROCESS_ENTER)
1280 {
1281 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
1282 event.SetEventObject( this );
1283 event.SetString( GetValue() );
1284 if ( GetEventHandler()->ProcessEvent(event) )
1285 return;
1286 }
1287 if ( !(m_windowStyle & wxTE_MULTILINE) )
1288 {
1289 wxWindow *parent = GetParent();
1290 while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL ) {
1291 parent = parent->GetParent() ;
1292 }
1293 if ( parent && parent->GetDefaultItem() )
1294 {
1295 wxButton *def = wxDynamicCast(parent->GetDefaultItem(),
1296 wxButton);
1297 if ( def && def->IsEnabled() )
1298 {
1299 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
1300 event.SetEventObject(def);
1301 def->Command(event);
1302 return ;
1303 }
1304 }
1305
1306 // this will make wxWindows eat the ENTER key so that
1307 // we actually prevent line wrapping in a single line
1308 // text control
1309 eat_key = TRUE;
1310 }
1311
1312 break;
1313
1314 case WXK_TAB:
1315 // always produce navigation event - even if we process TAB
1316 // ourselves the fact that we got here means that the user code
1317 // decided to skip processing of this TAB - probably to let it
1318 // do its default job.
1319 {
1320 wxNavigationKeyEvent eventNav;
1321 eventNav.SetDirection(!event.ShiftDown());
1322 eventNav.SetWindowChange(event.ControlDown());
1323 eventNav.SetEventObject(this);
1324
1325 if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav) )
1326 return;
1327
1328 event.Skip() ;
1329 return;
1330 }
1331 break;
1332 }
1333
1334 EventRecord *ev = (EventRecord*) wxTheApp->MacGetCurrentEvent();
1335 short keychar = short(ev->message & charCodeMask);
1336 if (!eat_key)
1337 {
1338 short keycode = short(ev->message & keyCodeMask) >> 8 ;
1339 ::HandleControlKey( (ControlHandle) m_macControl , keycode , keychar , ev->modifiers );
1340 }
1341 if ( keychar >= 0x20 ||
1342 event.KeyCode() == WXK_RETURN ||
1343 event.KeyCode() == WXK_DELETE ||
1344 event.KeyCode() == WXK_BACK)
1345 {
1346 wxCommandEvent event1(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
1347 event1.SetString( GetValue() ) ;
1348 event1.SetEventObject( this );
1349 GetEventHandler()->ProcessEvent(event1);
1350 }
1351 }
1352
1353 void wxTextCtrl::MacSuperShown( bool show )
1354 {
1355 bool former = m_macControlIsShown ;
1356 wxControl::MacSuperShown( show ) ;
1357 if ( (former != m_macControlIsShown) && m_macUsesTXN )
1358 {
1359 if ( m_macControlIsShown )
1360 TXNSetFrameBounds( (TXNObject) m_macTXN, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.top, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.left,
1361 (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.bottom,(**(STPTextPaneVars **)m_macTXNvars).fRTextArea.right, (**(STPTextPaneVars **)m_macTXNvars).fTXNFrame);
1362 else
1363 TXNSetFrameBounds( (TXNObject) m_macTXN, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.top + 30000, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.left,
1364 (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.bottom + 30000, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.right, (**(STPTextPaneVars **)m_macTXNvars).fTXNFrame);
1365 }
1366 }
1367
1368 bool wxTextCtrl::Show(bool show)
1369 {
1370 bool former = m_macControlIsShown ;
1371
1372 bool retval = wxControl::Show( show ) ;
1373
1374 if ( former != m_macControlIsShown )
1375 {
1376 if ( m_macControlIsShown )
1377 TXNSetFrameBounds( (TXNObject) m_macTXN, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.top, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.left,
1378 (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.bottom,(**(STPTextPaneVars **)m_macTXNvars).fRTextArea.right, (**(STPTextPaneVars **)m_macTXNvars).fTXNFrame);
1379 else
1380 TXNSetFrameBounds( (TXNObject) m_macTXN, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.top + 30000, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.left,
1381 (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.bottom + 30000, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.right, (**(STPTextPaneVars **)m_macTXNvars).fTXNFrame);
1382 }
1383
1384 return retval ;
1385 }
1386
1387 // ----------------------------------------------------------------------------
1388 // standard handlers for standard edit menu events
1389 // ----------------------------------------------------------------------------
1390
1391 void wxTextCtrl::OnCut(wxCommandEvent& event)
1392 {
1393 Cut();
1394 }
1395
1396 void wxTextCtrl::OnCopy(wxCommandEvent& event)
1397 {
1398 Copy();
1399 }
1400
1401 void wxTextCtrl::OnPaste(wxCommandEvent& event)
1402 {
1403 Paste();
1404 }
1405
1406 void wxTextCtrl::OnUndo(wxCommandEvent& event)
1407 {
1408 Undo();
1409 }
1410
1411 void wxTextCtrl::OnRedo(wxCommandEvent& event)
1412 {
1413 Redo();
1414 }
1415
1416 void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
1417 {
1418 event.Enable( CanCut() );
1419 }
1420
1421 void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
1422 {
1423 event.Enable( CanCopy() );
1424 }
1425
1426 void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
1427 {
1428 event.Enable( CanPaste() );
1429 }
1430
1431 void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
1432 {
1433 event.Enable( CanUndo() );
1434 }
1435
1436 void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
1437 {
1438 event.Enable( CanRedo() );
1439 }
1440
1441
1442
1443 #endif
1444 // wxUSE_TEXTCTRL