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