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