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