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