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