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