]> git.saurik.com Git - wxWidgets.git/blame - src/mac/textctrl.cpp
fix for always terminating intermediate UniChar String for 4 bytes wchar_t
[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>
7688f0a1
SC
58#include <ATSUnicode.h>
59#include <TextCommon.h>
60#include <TextEncodingConverter.h>
1b2b1638 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 71
72055702
SC
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
6bdd4f5d
SC
660static void SetTXNData( TXNObject txn , const wxString& st , TXNOffset start , TXNOffset end )
661{
662#if wxUSE_UNICODE
6bdd4f5d 663#if SIZEOF_WCHAR_T == 2
79a73b4f 664 size_t len = st.Len() ;
6bdd4f5d
SC
665 TXNSetData( txn , kTXNUnicodeTextData, (void*)st.wc_str(), len * 2,
666 start, end);
667#else
6bdd4f5d 668 wxMBConvUTF16BE converter ;
79a73b4f
SC
669 ByteCount byteBufferLen = converter.WC2MB( NULL , st.wc_str() , 0 ) ;
670 UniChar *unibuf = (UniChar*) malloc(byteBufferLen) ;
6bdd4f5d 671 converter.WC2MB( (char*) unibuf , st.wc_str() , byteBufferLen ) ;
79a73b4f 672 TXNSetData( txn , kTXNUnicodeTextData, (void*)unibuf, byteBufferLen ,
6bdd4f5d
SC
673 start, end);
674 free( unibuf ) ;
675#endif
676#else
677 wxCharBuffer text = st.mb_str(wxConvLocal) ;
678 TXNSetData( txn , kTXNTextData, (void*)text.data(), strlen( text ) ,
679 start, end);
680#endif
681}
682
72055702 683// Text item
1fa29bdc 684void wxTextCtrl::Init()
72055702 685{
402679b0
SC
686 m_macTE = NULL ;
687 m_macTXN = NULL ;
688 m_macTXNvars = NULL ;
1b2b1638 689 m_macUsesTXN = false ;
1fa29bdc 690
1b2b1638 691 m_editable = true ;
1fa29bdc
VZ
692 m_dirty = false;
693
29b30405 694 m_maxLength = TE_UNLIMITED_LENGTH ;
1b2b1638
SC
695}
696
697wxTextCtrl::~wxTextCtrl()
698{
699 if ( m_macUsesTXN )
700 {
402679b0 701 SetControlReference((ControlHandle)m_macControl, 0) ;
1b2b1638 702 TXNDeleteObject((TXNObject)m_macTXN);
1b2b1638
SC
703 /* delete our private storage */
704 DisposeHandle((Handle) m_macTXNvars);
705 /* zero the control reference */
1b2b1638 706 }
72055702
SC
707}
708
709const short kVerticalMargin = 2 ;
710const short kHorizontalMargin = 2 ;
711
712bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
939fba6c 713 const wxString& str,
72055702
SC
714 const wxPoint& pos,
715 const wxSize& size, long style,
716 const wxValidator& validator,
717 const wxString& name)
718{
e40298d5
JS
719 m_macTE = NULL ;
720 m_macTXN = NULL ;
721 m_macTXNvars = NULL ;
722 m_macUsesTXN = false ;
723 m_editable = true ;
ef4a634b
RD
724
725 m_macUsesTXN = ! (style & wxTE_PASSWORD ) ;
726
e40298d5 727 m_macUsesTXN &= (TXNInitTextension != (void*) kUnresolvedCFragSymbolAddress) ;
ef4a634b 728
72055702 729 // base initialization
b657d5db 730 if ( !wxTextCtrlBase::Create(parent, id, pos, size, style & ~(wxHSCROLL|wxVSCROLL), validator, name) )
72055702
SC
731 return FALSE;
732
ed8c2780 733 wxSize mySize = size ;
29e4a190
RR
734 if ( m_macUsesTXN )
735 {
736 m_macHorizontalBorder = 5 ; // additional pixels around the real control
737 m_macVerticalBorder = 3 ;
738 }
739 else
ed8c2780
RR
740 {
741 m_macHorizontalBorder = 5 ; // additional pixels around the real control
742 m_macVerticalBorder = 5 ;
743 }
ed8c2780
RR
744
745
746 Rect bounds ;
747 Str255 title ;
402679b0 748 /*
ed8c2780
RR
749 if ( mySize.y == -1 )
750 {
402679b0
SC
751 mySize.y = 13 ;
752 if ( m_windowStyle & wxTE_MULTILINE )
753 mySize.y *= 5 ;
ef4a634b 754
ed8c2780
RR
755 mySize.y += 2 * m_macVerticalBorder ;
756 }
402679b0 757 */
427ff662 758 MacPreControlCreate( parent , id , wxEmptyString , pos , mySize ,style, validator , name , &bounds , title ) ;
72055702
SC
759
760 if ( m_windowStyle & wxTE_MULTILINE )
761 {
762 wxASSERT_MSG( !(m_windowStyle & wxTE_PROCESS_ENTER),
763 wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") );
764
765 m_windowStyle |= wxTE_PROCESS_ENTER;
766 }
767
29b30405
SC
768 if ( m_windowStyle & wxTE_READONLY)
769 {
770 m_editable = FALSE ;
771 }
72055702 772
939fba6c 773 wxString st = str ;
8aa701ed 774 wxMacConvertNewlines13To10( &st ) ;
1b2b1638 775 if ( !m_macUsesTXN )
9c641c05 776 {
d77d9398 777 m_macControl = ::NewControl( MAC_WXHWND(parent->MacGetRootWindow()) , &bounds , "\p" , false , 0 , 0 , 1,
29e4a190
RR
778 (style & wxTE_PASSWORD) ? kControlEditTextPasswordProc : kControlEditTextProc , (long) this ) ;
779 long size ;
73bdd73a 780 ::GetControlData((ControlHandle) m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*)((TEHandle *)&m_macTE) , &size ) ;
1b2b1638 781
ed8c2780 782 }
29e4a190
RR
783 else
784 {
1b2b1638
SC
785 short featurSet;
786
29b30405 787 featurSet = kControlSupportsEmbedding | kControlSupportsFocus | kControlWantsIdle
1b2b1638
SC
788 | kControlWantsActivate | kControlHandlesTracking | kControlHasSpecialBackground
789 | kControlGetsFocusOnClick | kControlSupportsLiveFeedback;
790 /* create the control */
d77d9398 791 m_macControl = NewControl(MAC_WXHWND(parent->MacGetRootWindow()), &bounds, "\p", false , featurSet, 0, featurSet, kControlUserPaneProc, 0);
1b2b1638 792 /* set up the mUP specific features and data */
2b5f62a0 793 mUPOpenControl((ControlHandle) m_macControl, m_windowStyle );
29e4a190 794 }
ed8c2780
RR
795 MacPostControlCreate() ;
796
29e4a190
RR
797 if ( !m_macUsesTXN )
798 {
939fba6c 799 wxCharBuffer text = st.mb_str(wxConvLocal) ;
427ff662 800 ::SetControlData( (ControlHandle) m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , strlen(text) , text ) ;
1b2b1638 801 }
ed8c2780 802 else
ed8c2780 803 {
1b2b1638 804 STPTextPaneVars **tpvars;
29e4a190 805 /* set up locals */
1b2b1638 806 tpvars = (STPTextPaneVars **) GetControlReference((ControlHandle) m_macControl);
29e4a190 807 /* set the text in the record */
1b2b1638 808 m_macTXN = (**tpvars).fTXNRec ;
6bdd4f5d 809 SetTXNData( (TXNObject) m_macTXN , st , kTXNStartOffset, kTXNEndOffset ) ;
1b2b1638
SC
810 m_macTXNvars = tpvars ;
811 m_macUsesTXN = true ;
2b5f62a0 812 TXNSetSelection( (TXNObject) m_macTXN, 0, 0);
e600c175 813 TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart);
1b2b1638 814 }
ef4a634b 815
e40298d5 816 return TRUE;
72055702
SC
817}
818
819wxString wxTextCtrl::GetValue() const
820{
c5c9378c
SC
821 Size actualSize = 0;
822 wxString result ;
823 OSStatus err ;
29e4a190
RR
824 if ( !m_macUsesTXN )
825 {
e40298d5 826 err = ::GetControlDataSize((ControlHandle) m_macControl, 0,
c5c9378c 827 ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag, &actualSize ) ;
ef4a634b 828
427ff662
SC
829 if ( err )
830 return wxEmptyString ;
ef4a634b 831
427ff662
SC
832 if ( actualSize > 0 )
833 {
ef4a634b 834 wxCharBuffer buf(actualSize) ;
e40298d5 835 ::GetControlData( (ControlHandle) m_macControl, 0,
ef4a634b 836 ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag,
427ff662 837 actualSize , buf.data() , &actualSize ) ;
939fba6c 838 result = wxString( buf , wxConvLocal) ;
c5c9378c 839 }
29e4a190
RR
840 }
841 else
842 {
427ff662 843#if wxUSE_UNICODE
29e4a190 844 Handle theText ;
427ff662 845 err = TXNGetDataEncoded( ((TXNObject) m_macTXN), kTXNStartOffset, kTXNEndOffset, &theText , kTXNUnicodeTextData );
29e4a190
RR
846 // all done
847 if ( err )
848 {
c5c9378c 849 actualSize = 0 ;
29e4a190
RR
850 }
851 else
852 {
7688f0a1 853 actualSize = GetHandleSize( theText ) / sizeof( UniChar) ;
427ff662
SC
854 if ( actualSize > 0 )
855 {
856 wxChar *ptr = result.GetWriteBuf(actualSize*sizeof(wxChar)) ;
6bdd4f5d 857#if SIZEOF_WCHAR_T == 2
427ff662 858 wxStrncpy( ptr , (wxChar*) *theText , actualSize ) ;
6bdd4f5d
SC
859#else
860 wxMBConvUTF16BE converter ;
861 HLock( theText ) ;
79a73b4f 862 converter.MB2WC( ptr , (const char*)*theText , actualSize ) ;
6bdd4f5d
SC
863 HUnlock( theText ) ;
864#endif
e40298d5 865 ptr[actualSize] = 0 ;
7688f0a1 866 result.UngetWriteBuf( actualSize *sizeof(wxChar) ) ;
e40298d5
JS
867 }
868 DisposeHandle( theText ) ;
29e4a190 869 }
427ff662
SC
870#else
871 Handle theText ;
872 err = TXNGetDataEncoded( ((TXNObject) m_macTXN), kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData );
873 // all done
874 if ( err )
875 {
876 actualSize = 0 ;
877 }
878 else
879 {
880 actualSize = GetHandleSize( theText ) ;
881 if ( actualSize > 0 )
882 {
883 HLock( theText ) ;
939fba6c 884 result = wxString( *theText , wxConvLocal , actualSize ) ;
427ff662
SC
885 HUnlock( theText ) ;
886 }
887 DisposeHandle( theText ) ;
888 }
889#endif
29e4a190 890 }
8aa701ed 891 wxMacConvertNewlines10To13( &result ) ;
427ff662 892 return result ;
72055702
SC
893}
894
895void wxTextCtrl::GetSelection(long* from, long* to) const
896{
1b2b1638 897 if ( !m_macUsesTXN )
72055702 898 {
1b2b1638
SC
899 *from = (**((TEHandle) m_macTE)).selStart;
900 *to = (**((TEHandle) m_macTE)).selEnd;
72055702
SC
901 }
902 else
903 {
3a05d58d 904 TXNGetSelection( (TXNObject) m_macTXN , (TXNOffset*) from , (TXNOffset*) to ) ;
72055702
SC
905 }
906}
907
939fba6c 908void wxTextCtrl::SetValue(const wxString& str)
72055702 909{
939fba6c 910 wxString st = str ;
8aa701ed 911 wxMacConvertNewlines13To10( &st ) ;
29e4a190
RR
912 if ( !m_macUsesTXN )
913 {
939fba6c 914 wxCharBuffer text = st.mb_str(wxConvLocal) ;
427ff662 915 ::SetControlData( (ControlHandle) m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , strlen(text) , text ) ;
29e4a190
RR
916 }
917 else
918 {
68698f03 919 bool formerEditable = m_editable ;
2b5f62a0
VZ
920 if ( !formerEditable )
921 SetEditable(true) ;
6bdd4f5d 922 SetTXNData( (TXNObject) m_macTXN , st , kTXNStartOffset, kTXNEndOffset ) ;
2b5f62a0 923 TXNSetSelection( (TXNObject) m_macTXN, 0, 0);
e600c175 924 TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart);
2b5f62a0
VZ
925 if ( !formerEditable )
926 SetEditable(formerEditable) ;
29e4a190 927 }
1b2b1638 928 MacRedrawControl() ;
72055702
SC
929}
930
ef4a634b 931void wxTextCtrl::SetMaxLength(unsigned long len)
29b30405
SC
932{
933 m_maxLength = len ;
934}
935
936bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
937{
938 if ( m_macUsesTXN )
939 {
68698f03 940 bool formerEditable = m_editable ;
2b5f62a0
VZ
941 if ( !formerEditable )
942 SetEditable(true) ;
943 TXNTypeAttributes typeAttr[4] ;
944 Str255 fontName = "\pMonaco" ;
945 SInt16 fontSize = 12 ;
946 Style fontStyle = normal ;
947 RGBColor color ;
948 int attrCounter = 0 ;
949 if ( style.HasFont() )
950 {
951 const wxFont &font = style.GetFont() ;
427ff662 952 wxMacStringToPascal( font.GetFaceName() , fontName ) ;
2b5f62a0
VZ
953 fontSize = font.GetPointSize() ;
954 if ( font.GetUnderlined() )
955 fontStyle |= underline ;
956 if ( font.GetWeight() == wxBOLD )
957 fontStyle |= bold ;
958 if ( font.GetStyle() == wxITALIC )
959 fontStyle |= italic ;
ef4a634b 960
2b5f62a0
VZ
961 typeAttr[attrCounter].tag = kTXNQDFontNameAttribute ;
962 typeAttr[attrCounter].size = kTXNQDFontNameAttributeSize ;
963 typeAttr[attrCounter].data.dataPtr = (void*) fontName ;
964 typeAttr[attrCounter+1].tag = kTXNQDFontSizeAttribute ;
965 typeAttr[attrCounter+1].size = kTXNFontSizeAttributeSize ;
966 typeAttr[attrCounter+1].data.dataValue = (fontSize << 16) ;
967 typeAttr[attrCounter+2].tag = kTXNQDFontStyleAttribute ;
968 typeAttr[attrCounter+2].size = kTXNQDFontStyleAttributeSize ;
969 typeAttr[attrCounter+2].data.dataValue = fontStyle ;
970 attrCounter += 3 ;
ef4a634b 971
2b5f62a0
VZ
972 }
973 if ( style.HasTextColour() )
974 {
975 typeAttr[attrCounter].tag = kTXNQDFontColorAttribute ;
976 typeAttr[attrCounter].size = kTXNQDFontColorAttributeSize ;
977 typeAttr[attrCounter].data.dataPtr = (void*) &color ;
978 color = MAC_WXCOLORREF(style.GetTextColour().GetPixel()) ;
979 attrCounter += 1 ;
980 }
ef4a634b 981
29b30405
SC
982 if ( attrCounter > 0 )
983 {
a40af6f9
VZ
984#ifdef __WXDEBUG__
985 OSStatus status =
986#endif // __WXDEBUG__
987 TXNSetTypeAttributes ((TXNObject)m_macTXN, attrCounter , typeAttr, start,end);
427ff662 988 wxASSERT_MSG( status == noErr , wxT("Couldn't set text attributes") ) ;
29b30405 989 }
2b5f62a0
VZ
990 if ( !formerEditable )
991 SetEditable(formerEditable) ;
29b30405
SC
992 }
993 return TRUE ;
994}
995
996bool wxTextCtrl::SetDefaultStyle(const wxTextAttr& style)
997{
998 wxTextCtrlBase::SetDefaultStyle( style ) ;
999 SetStyle( kTXNUseCurrentSelection , kTXNUseCurrentSelection , GetDefaultStyle() ) ;
1000 return TRUE ;
1001}
1002
72055702
SC
1003// Clipboard operations
1004void wxTextCtrl::Copy()
1005{
1006 if (CanCopy())
1007 {
1b2b1638 1008 if ( !m_macUsesTXN )
72055702 1009 {
29e4a190
RR
1010 TECopy( ((TEHandle) m_macTE) ) ;
1011 ClearCurrentScrap();
1012 TEToScrap() ;
1013 MacRedrawControl() ;
1014 }
1015 else
1016 {
32b5be3d 1017 ClearCurrentScrap();
ef4a634b 1018 TXNCopy((TXNObject)m_macTXN);
1b2b1638 1019 TXNConvertToPublicScrap();
29e4a190 1020 }
32b5be3d 1021 }
72055702
SC
1022}
1023
1024void wxTextCtrl::Cut()
1025{
1026 if (CanCut())
1027 {
1b2b1638 1028 if ( !m_macUsesTXN )
32b5be3d 1029 {
29e4a190
RR
1030 TECut( ((TEHandle) m_macTE) ) ;
1031 ClearCurrentScrap();
1032 TEToScrap() ;
1033 MacRedrawControl() ;
32b5be3d 1034 }
29e4a190
RR
1035 else
1036 {
1b2b1638 1037 ClearCurrentScrap();
ef4a634b 1038 TXNCut((TXNObject)m_macTXN);
1b2b1638 1039 TXNConvertToPublicScrap();
29e4a190 1040 }
1b2b1638
SC
1041 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
1042 event.SetString( GetValue() ) ;
1043 event.SetEventObject( this );
1044 GetEventHandler()->ProcessEvent(event);
29e4a190 1045 }
72055702
SC
1046}
1047
1048void wxTextCtrl::Paste()
1049{
1050 if (CanPaste())
1051 {
1b2b1638
SC
1052 if ( !m_macUsesTXN )
1053 {
1054 TEFromScrap() ;
1055 TEPaste( (TEHandle) m_macTE ) ;
1056 MacRedrawControl() ;
1057 }
29e4a190
RR
1058 else
1059 {
1b2b1638 1060 TXNConvertFromPublicScrap();
ef4a634b 1061 TXNPaste((TXNObject)m_macTXN);
e600c175 1062 SetStyle( kTXNUseCurrentSelection , kTXNUseCurrentSelection , GetDefaultStyle() ) ;
29e4a190 1063 }
1b2b1638
SC
1064 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
1065 event.SetString( GetValue() ) ;
1066 event.SetEventObject( this );
1067 GetEventHandler()->ProcessEvent(event);
32b5be3d 1068 }
72055702
SC
1069}
1070
1071bool wxTextCtrl::CanCopy() const
1072{
1073 // Can copy if there's a selection
1074 long from, to;
1075 GetSelection(& from, & to);
1076 return (from != to);
1077}
1078
1079bool wxTextCtrl::CanCut() const
1080{
1b2b1638
SC
1081 if ( !IsEditable() )
1082 {
1083 return false ;
1084 }
72055702
SC
1085 // Can cut if there's a selection
1086 long from, to;
1087 GetSelection(& from, & to);
1088 return (from != to);
1089}
1090
1091bool wxTextCtrl::CanPaste() const
1092{
1093 if (!IsEditable())
1094 return FALSE;
1095
72055702 1096#if TARGET_CARBON
ed8c2780
RR
1097 OSStatus err = noErr;
1098 ScrapRef scrapRef;
ef4a634b 1099
ed8c2780 1100 err = GetCurrentScrap( &scrapRef );
ef4a634b 1101 if ( err != noTypeErr && err != memFullErr )
ed8c2780 1102 {
29e4a190
RR
1103 ScrapFlavorFlags flavorFlags;
1104 Size byteCount;
ef4a634b 1105
ed8c2780
RR
1106 if (( err = GetScrapFlavorFlags( scrapRef, 'TEXT', &flavorFlags )) == noErr)
1107 {
1108 if (( err = GetScrapFlavorSize( scrapRef, 'TEXT', &byteCount )) == noErr)
1109 {
1110 return TRUE ;
1111 }
1112 }
1113 }
1114 return FALSE;
ef4a634b 1115
72055702 1116#else
49b45dcd 1117 long offset ;
ed8c2780
RR
1118 if ( GetScrap( NULL , 'TEXT' , &offset ) > 0 )
1119 {
1120 return TRUE ;
1121 }
72055702 1122#endif
ed8c2780 1123 return FALSE ;
72055702
SC
1124}
1125
1126void wxTextCtrl::SetEditable(bool editable)
1127{
1b2b1638
SC
1128 if ( editable != m_editable )
1129 {
1130 m_editable = editable ;
e600c175
SC
1131 if ( !m_macUsesTXN )
1132 {
1133 if ( editable )
2b5f62a0 1134 UMAActivateControl( (ControlHandle) m_macControl ) ;
e600c175 1135 else
2b5f62a0 1136 UMADeactivateControl((ControlHandle) m_macControl ) ;
e600c175 1137 }
1b2b1638 1138 else
e600c175
SC
1139 {
1140 TXNControlTag tag[] = { kTXNIOPrivilegesTag } ;
49b45dcd 1141 TXNControlData data[] = { { editable ? kTXNReadWrite : kTXNReadOnly } } ;
e600c175
SC
1142 TXNSetTXNObjectControls( (TXNObject) m_macTXN , false , sizeof(tag) / sizeof (TXNControlTag) , tag , data ) ;
1143 }
1b2b1638 1144 }
72055702
SC
1145}
1146
1147void wxTextCtrl::SetInsertionPoint(long pos)
1148{
ed8c2780 1149 SetSelection( pos , pos ) ;
72055702
SC
1150}
1151
1152void wxTextCtrl::SetInsertionPointEnd()
1153{
1154 long pos = GetLastPosition();
1155 SetInsertionPoint(pos);
1156}
1157
1158long wxTextCtrl::GetInsertionPoint() const
1159{
e40298d5
JS
1160 long begin,end ;
1161 GetSelection( &begin , &end ) ;
1162 return begin ;
72055702
SC
1163}
1164
1165long wxTextCtrl::GetLastPosition() const
1166{
1b2b1638 1167 if ( !m_macUsesTXN )
32b5be3d 1168 {
e40298d5 1169 return (**((TEHandle) m_macTE)).teLength ;
32b5be3d
RR
1170 }
1171 else
1172 {
e40298d5
JS
1173 Handle theText ;
1174 long actualsize ;
1175 OSErr err = TXNGetDataEncoded( (TXNObject) m_macTXN, kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData );
1176 /* all done */
1177 if ( err )
1178 {
1179 actualsize = 0 ;
1180 }
1181 else
1182 {
1183 actualsize = GetHandleSize( theText ) ;
1184 DisposeHandle( theText ) ;
1185 }
1186 return actualsize ;
32b5be3d 1187 }
72055702
SC
1188}
1189
939fba6c 1190void wxTextCtrl::Replace(long from, long to, const wxString& str)
72055702 1191{
939fba6c 1192 wxString value = str ;
de0bc932 1193 wxMacConvertNewlines13To10( &value ) ;
e40298d5
JS
1194 if ( !m_macUsesTXN )
1195 {
29e4a190 1196 ControlEditTextSelectionRec selection ;
ef4a634b 1197
29e4a190
RR
1198 selection.selStart = from ;
1199 selection.selEnd = to ;
1200 ::SetControlData((ControlHandle) m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
1201 TESetSelect( from , to , ((TEHandle) m_macTE) ) ;
1202 TEDelete( ((TEHandle) m_macTE) ) ;
1203 TEInsert( value , value.Length() , ((TEHandle) m_macTE) ) ;
1204 }
1205 else
1206 {
68698f03 1207 bool formerEditable = m_editable ;
2b5f62a0
VZ
1208 if ( !formerEditable )
1209 SetEditable(true) ;
1210 TXNSetSelection( ((TXNObject) m_macTXN) , from , to ) ;
1211 TXNClear( ((TXNObject) m_macTXN) ) ;
6bdd4f5d 1212 SetTXNData( (TXNObject) m_macTXN , str , kTXNUseCurrentSelection, kTXNUseCurrentSelection ) ;
2b5f62a0
VZ
1213 if ( !formerEditable )
1214 SetEditable( formerEditable ) ;
29e4a190 1215 }
32b5be3d 1216 Refresh() ;
72055702
SC
1217}
1218
1219void wxTextCtrl::Remove(long from, long to)
1220{
e40298d5
JS
1221 if ( !m_macUsesTXN )
1222 {
1223 ControlEditTextSelectionRec selection ;
ef4a634b 1224
e40298d5
JS
1225 selection.selStart = from ;
1226 selection.selEnd = to ;
1227 ::SetControlData( (ControlHandle) m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
1228 TEDelete( ((TEHandle) m_macTE) ) ;
1229 }
1230 else
1231 {
68698f03 1232 bool formerEditable = m_editable ;
e40298d5
JS
1233 if ( !formerEditable )
1234 SetEditable(true) ;
ef4a634b
RD
1235 TXNSetSelection( ((TXNObject) m_macTXN) , from , to ) ;
1236 TXNClear( ((TXNObject) m_macTXN) ) ;
e40298d5
JS
1237 if ( !formerEditable )
1238 SetEditable( formerEditable ) ;
1239 }
ed8c2780 1240 Refresh() ;
72055702
SC
1241}
1242
1243void wxTextCtrl::SetSelection(long from, long to)
1244{
e40298d5
JS
1245 if ( !m_macUsesTXN )
1246 {
1247 ControlEditTextSelectionRec selection ;
ea161895
SC
1248 if ((from == -1) && (to == -1))
1249 {
1250 selection.selStart = 0 ;
1251 selection.selEnd = 32767 ;
1252 }
1253 else
1254 {
1255 selection.selStart = from ;
1256 selection.selEnd = to ;
1257 }
ef4a634b 1258
e40298d5
JS
1259 TESetSelect( selection.selStart , selection.selEnd , ((TEHandle) m_macTE) ) ;
1260 ::SetControlData((ControlHandle) m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
1261 }
1262 else
1263 {
1264 STPTextPaneVars **tpvars;
29e4a190 1265 /* set up our locals */
e40298d5 1266 tpvars = (STPTextPaneVars **) GetControlReference((ControlHandle) m_macControl);
29e4a190
RR
1267 /* and our drawing environment as the operation
1268 may force a redraw in the text area. */
e40298d5 1269 SetPort((**tpvars).fDrawingEnvironment);
29e4a190 1270 /* change the selection */
ea161895
SC
1271 if ((from == -1) && (to == -1))
1272 TXNSelectAll((TXNObject) m_macTXN);
1273 else
1274 TXNSetSelection( (**tpvars).fTXNRec, from, to);
e40298d5
JS
1275 TXNShowSelection( (TXNObject) m_macTXN, kTXNShowStart);
1276 }
72055702
SC
1277}
1278
1279bool wxTextCtrl::LoadFile(const wxString& file)
1280{
1281 if ( wxTextCtrlBase::LoadFile(file) )
1282 {
1283 return TRUE;
1284 }
1285
1286 return FALSE;
1287}
1288
939fba6c 1289void wxTextCtrl::WriteText(const wxString& str)
ef4a634b 1290{
939fba6c 1291 wxString st = str ;
8aa701ed 1292 wxMacConvertNewlines13To10( &st ) ;
1b2b1638 1293 if ( !m_macUsesTXN )
72055702 1294 {
939fba6c 1295 wxCharBuffer text = st.mb_str(wxConvLocal) ;
427ff662 1296 TEInsert( text , strlen(text) , ((TEHandle) m_macTE) ) ;
29e4a190
RR
1297 }
1298 else
1299 {
68698f03 1300 bool formerEditable = m_editable ;
2b5f62a0
VZ
1301 if ( !formerEditable )
1302 SetEditable(true) ;
1303 long start , end , dummy ;
1304 GetSelection( &start , &dummy ) ;
6bdd4f5d 1305 SetTXNData( (TXNObject) m_macTXN , st , kTXNUseCurrentSelection, kTXNUseCurrentSelection ) ;
2b5f62a0 1306 GetSelection( &dummy , &end ) ;
29b30405 1307 SetStyle( start , end , GetDefaultStyle() ) ;
2b5f62a0
VZ
1308 if ( !formerEditable )
1309 SetEditable( formerEditable ) ;
29e4a190
RR
1310 }
1311 MacRedrawControl() ;
72055702
SC
1312}
1313
1314void wxTextCtrl::AppendText(const wxString& text)
1315{
1316 SetInsertionPointEnd();
1317 WriteText(text);
1318}
1319
1320void wxTextCtrl::Clear()
1321{
e40298d5
JS
1322 if ( !m_macUsesTXN )
1323 {
1324 ::SetControlData((ControlHandle) m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 0 , (char*) ((const char*)NULL) ) ;
1325 }
1326 else
1327 {
9c34dd9d 1328 TXNSetSelection( (TXNObject)m_macTXN , kTXNStartOffset , kTXNEndOffset ) ;
ef4a634b 1329 TXNClear((TXNObject)m_macTXN);
e40298d5 1330 }
32b5be3d 1331 Refresh() ;
72055702
SC
1332}
1333
1334bool wxTextCtrl::IsModified() const
1335{
1fa29bdc 1336 return m_dirty;
72055702
SC
1337}
1338
1339bool wxTextCtrl::IsEditable() const
1340{
1b2b1638 1341 return IsEnabled() && m_editable ;
72055702
SC
1342}
1343
1344bool wxTextCtrl::AcceptsFocus() const
1345{
1346 // we don't want focus if we can't be edited
1b2b1638 1347 return /*IsEditable() && */ wxControl::AcceptsFocus();
72055702
SC
1348}
1349
1350wxSize wxTextCtrl::DoGetBestSize() const
1351{
1352 int wText = 100 ;
ef4a634b 1353
402679b0 1354 int hText;
29e4a190
RR
1355 if ( m_macUsesTXN )
1356 {
1357 hText = 17 ;
1358 }
1359 else
1360 {
1361 hText = 13 ;
1362 }
72055702
SC
1363/*
1364 int cx, cy;
1365 wxGetCharSize(GetHWND(), &cx, &cy, &GetFont());
1366
1367 int wText = DEFAULT_ITEM_WIDTH;
1368
1369 int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
1370
1371 return wxSize(wText, hText);
1372*/
1373 if ( m_windowStyle & wxTE_MULTILINE )
1374 {
402679b0 1375 hText *= 5 ;
72055702 1376 }
402679b0
SC
1377 hText += 2 * m_macVerticalBorder ;
1378 wText += 2 * m_macHorizontalBorder ;
72055702
SC
1379 //else: for single line control everything is ok
1380 return wxSize(wText, hText);
1381}
1382
1383// ----------------------------------------------------------------------------
1384// Undo/redo
1385// ----------------------------------------------------------------------------
1386
1387void wxTextCtrl::Undo()
1388{
1389 if (CanUndo())
1390 {
65334b43
SC
1391 if ( m_macUsesTXN )
1392 {
1393 TXNUndo((TXNObject)m_macTXN);
1394 }
72055702
SC
1395 }
1396}
1397
1398void wxTextCtrl::Redo()
1399{
1400 if (CanRedo())
1401 {
65334b43
SC
1402 if ( m_macUsesTXN )
1403 {
1404 TXNRedo((TXNObject)m_macTXN);
1405 }
72055702
SC
1406 }
1407}
1408
1409bool wxTextCtrl::CanUndo() const
1410{
65334b43
SC
1411 if ( !IsEditable() )
1412 {
1413 return false ;
1414 }
1415 if ( m_macUsesTXN )
1416 {
1417 return TXNCanUndo((TXNObject)m_macTXN,NULL);
1418 }
72055702
SC
1419 return FALSE ;
1420}
1421
1422bool wxTextCtrl::CanRedo() const
1423{
65334b43
SC
1424 if ( !IsEditable() )
1425 {
1426 return false ;
1427 }
1428 if ( m_macUsesTXN )
1429 {
1430 return TXNCanRedo((TXNObject)m_macTXN,NULL);
1431 }
72055702
SC
1432 return FALSE ;
1433}
1434
3a9fa0d6
VZ
1435// Makes modifie or unmodified
1436void wxTextCtrl::MarkDirty()
1437{
1438 m_dirty = true;
1439}
1440
72055702
SC
1441void wxTextCtrl::DiscardEdits()
1442{
1fa29bdc 1443 m_dirty = false;
72055702
SC
1444}
1445
1446int wxTextCtrl::GetNumberOfLines() const
1447{
3a05d58d 1448 if ( m_macUsesTXN )
29e4a190 1449 {
f8e089e0
SC
1450 ItemCount lines ;
1451 TXNGetLineCount((TXNObject)m_macTXN, &lines ) ;
1452 return lines ;
3a05d58d
SC
1453 }
1454 else
1455 {
f8e089e0
SC
1456 wxString content = GetValue() ;
1457
1458 int count = 1;
1459 for (size_t i = 0; i < content.Length() ; i++)
1460 {
1461 if (content[i] == '\r') count++;
1462 }
1463 return count;
32b5be3d 1464 }
72055702
SC
1465}
1466
1467long wxTextCtrl::XYToPosition(long x, long y) const
1468{
1469 // TODO
1470 return 0;
1471}
1472
1473bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
1474{
1475 return FALSE ;
1476}
1477
1478void wxTextCtrl::ShowPosition(long pos)
1479{
3a05d58d
SC
1480#if TARGET_RT_MAC_MACHO && defined(AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER)
1481 if ( m_macUsesTXN )
1482 {
f8e089e0
SC
1483 Point current ;
1484 Point desired ;
1485 TXNOffset selstart , selend ;
3a05d58d 1486 TXNGetSelection( (TXNObject) m_macTXN , &selstart , &selend) ;
f8e089e0
SC
1487 TXNOffsetToPoint( (TXNObject) m_macTXN, selstart , &current);
1488 TXNOffsetToPoint( (TXNObject) m_macTXN, pos , &desired);
1489 //TODO use HIPoints for 10.3 and above
1490 if ( (UInt32) TXNScroll != (UInt32) kUnresolvedCFragSymbolAddress )
1491 {
1492 OSErr theErr = noErr;
1493 SInt32 dv = desired.v - current.v ;
1494 SInt32 dh = desired.h - current.h ;
1495 TXNShowSelection( (TXNObject) m_macTXN , true ) ;
3a05d58d 1496 theErr = TXNScroll( (TXNObject) m_macTXN, kTXNScrollUnitsInPixels , kTXNScrollUnitsInPixels , &dv , &dh );
f8e089e0
SC
1497 wxASSERT_MSG( theErr == noErr, _T("TXNScroll returned an error!") );
1498 }
3a05d58d
SC
1499 }
1500#endif
72055702
SC
1501}
1502
1503int wxTextCtrl::GetLineLength(long lineNo) const
1504{
e40298d5
JS
1505 // TODO change this if possible to reflect real lines
1506 wxString content = GetValue() ;
ef4a634b 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 // Count chars in line then
1515 count = 0;
49b45dcd 1516 for (size_t j = i; j < content.Length(); j++)
32b5be3d
RR
1517 {
1518 count++;
939fba6c 1519 if (content[j] == '\n') return count;
29e4a190 1520 }
ef4a634b 1521
29e4a190
RR
1522 return count;
1523 }
939fba6c 1524 if (content[i] == '\n') count++;
29e4a190 1525 }
72055702
SC
1526 return 0;
1527}
1528
1529wxString wxTextCtrl::GetLineText(long lineNo) const
1530{
e40298d5
JS
1531 // TODO change this if possible to reflect real lines
1532 wxString content = GetValue() ;
9c641c05 1533
29e4a190
RR
1534 // Find line first
1535 int count = 0;
49b45dcd 1536 for (size_t i = 0; i < content.Length() ; i++)
32b5be3d
RR
1537 {
1538 if (count == lineNo)
1539 {
1540 // Add chars in line then
427ff662 1541 wxString tmp;
ef4a634b 1542
49b45dcd 1543 for (size_t j = i; j < content.Length(); j++)
29e4a190 1544 {
939fba6c 1545 if (content[j] == '\n')
29e4a190 1546 return tmp;
ef4a634b 1547
29e4a190
RR
1548 tmp += content[j];
1549 }
ef4a634b 1550
29e4a190
RR
1551 return tmp;
1552 }
939fba6c 1553 if (content[i] == '\n') count++;
29e4a190 1554 }
427ff662 1555 return wxEmptyString ;
72055702
SC
1556}
1557
1558/*
1559 * Text item
1560 */
ef4a634b 1561
72055702
SC
1562void wxTextCtrl::Command(wxCommandEvent & event)
1563{
1564 SetValue (event.GetString());
1565 ProcessCommand (event);
1566}
1567
1568void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
1569{
1570 // By default, load the first file into the text window.
1571 if (event.GetNumberOfFiles() > 0)
1572 {
1573 LoadFile(event.GetFiles()[0]);
1574 }
1575}
1576
1577void wxTextCtrl::OnChar(wxKeyEvent& event)
1578{
1b2b1638
SC
1579 int key = event.GetKeyCode() ;
1580 bool eat_key = false ;
ef4a634b 1581
e600c175
SC
1582 if ( key == 'c' && event.MetaDown() )
1583 {
1584 if ( CanCopy() )
1585 Copy() ;
1586 return ;
1587 }
ef4a634b
RD
1588
1589 if ( !IsEditable() && key != WXK_LEFT && key != WXK_RIGHT && key != WXK_DOWN && key != WXK_UP && key != WXK_TAB &&
1590 !( key == WXK_RETURN && ( (m_windowStyle & wxPROCESS_ENTER) || (m_windowStyle & wxTE_MULTILINE) ) )
1b2b1638
SC
1591/* && key != WXK_PRIOR && key != WXK_NEXT && key != WXK_HOME && key != WXK_END */
1592 )
1593 {
1594 // eat it
1595 return ;
1596 }
1fa29bdc
VZ
1597
1598 // assume that any key not processed yet is going to modify the control
1599 m_dirty = true;
1600
e600c175
SC
1601 if ( key == 'v' && event.MetaDown() )
1602 {
1603 if ( CanPaste() )
1604 Paste() ;
1605 return ;
1606 }
1607 if ( key == 'x' && event.MetaDown() )
1608 {
1609 if ( CanCut() )
1610 Cut() ;
1611 return ;
1612 }
1b2b1638 1613 switch ( key )
72055702
SC
1614 {
1615 case WXK_RETURN:
ed8c2780
RR
1616 if (m_windowStyle & wxPROCESS_ENTER)
1617 {
72055702
SC
1618 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
1619 event.SetEventObject( this );
1b2b1638 1620 event.SetString( GetValue() );
72055702
SC
1621 if ( GetEventHandler()->ProcessEvent(event) )
1622 return;
ef4a634b 1623 }
72055702
SC
1624 if ( !(m_windowStyle & wxTE_MULTILINE) )
1625 {
ed8c2780 1626 wxWindow *parent = GetParent();
9c641c05
SC
1627 while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL ) {
1628 parent = parent->GetParent() ;
ed8c2780 1629 }
9c641c05 1630 if ( parent && parent->GetDefaultItem() )
ed8c2780 1631 {
9c641c05 1632 wxButton *def = wxDynamicCast(parent->GetDefaultItem(),
72055702 1633 wxButton);
ed8c2780
RR
1634 if ( def && def->IsEnabled() )
1635 {
1636 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
1637 event.SetEventObject(def);
1638 def->Command(event);
1639 return ;
72055702 1640 }
ed8c2780 1641 }
ef4a634b 1642
1b2b1638
SC
1643 // this will make wxWindows eat the ENTER key so that
1644 // we actually prevent line wrapping in a single line
1645 // text control
1646 eat_key = TRUE;
72055702 1647 }
72055702
SC
1648
1649 break;
1650
1651 case WXK_TAB:
1652 // always produce navigation event - even if we process TAB
1653 // ourselves the fact that we got here means that the user code
1654 // decided to skip processing of this TAB - probably to let it
1655 // do its default job.
1656 {
1657 wxNavigationKeyEvent eventNav;
1658 eventNav.SetDirection(!event.ShiftDown());
1659 eventNav.SetWindowChange(event.ControlDown());
1660 eventNav.SetEventObject(this);
1661
1662 if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav) )
1663 return;
1b2b1638 1664
ed8c2780 1665 event.Skip() ;
1b2b1638 1666 return;
72055702
SC
1667 }
1668 break;
1669 }
ef4a634b 1670
1b2b1638 1671 if (!eat_key)
ed8c2780 1672 {
1ea39a03
SC
1673 // perform keystroke handling
1674#if TARGET_CARBON
1675 if ( m_macUsesTXN && wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL )
1676 CallNextEventHandler((EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() , (EventRef) wxTheApp->MacGetCurrentEvent() ) ;
1677 else
1ea39a03
SC
1678 {
1679 EventRecord rec ;
1680 if ( wxMacConvertEventToRecord( (EventRef) wxTheApp->MacGetCurrentEvent() , &rec ) )
1681 {
1682 EventRecord *ev = &rec ;
1683 short keycode ;
1684 short keychar ;
1685 keychar = short(ev->message & charCodeMask);
1686 keycode = short(ev->message & keyCodeMask) >> 8 ;
1687
1688 ::HandleControlKey( (ControlHandle) m_macControl , keycode , keychar , ev->modifiers ) ;
1689 }
1690 }
d16477fd
SC
1691#else
1692 EventRecord *ev = (EventRecord*) wxTheApp->MacGetCurrentEvent() ;
1693 short keycode ;
1694 short keychar ;
1695 keychar = short(ev->message & charCodeMask);
1696 keycode = short(ev->message & keyCodeMask) >> 8 ;
1697
1698 ::HandleControlKey( (ControlHandle) m_macControl , keycode , keychar , ev->modifiers ) ;
1699#endif
1b2b1638 1700 }
e600c175 1701 if ( ( key >= 0x20 && key < WXK_START ) ||
45c8d9e5 1702 key == WXK_RETURN ||
ef4a634b 1703 key == WXK_DELETE ||
45c8d9e5 1704 key == WXK_BACK)
1b2b1638
SC
1705 {
1706 wxCommandEvent event1(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
1707 event1.SetString( GetValue() ) ;
1708 event1.SetEventObject( this );
45c8d9e5 1709 wxPostEvent(GetEventHandler(),event1);
ed8c2780 1710 }
72055702
SC
1711}
1712
ef4a634b 1713void wxTextCtrl::MacSuperShown( bool show )
fd4393b8
SC
1714{
1715 bool former = m_macControlIsShown ;
1716 wxControl::MacSuperShown( show ) ;
1717 if ( (former != m_macControlIsShown) && m_macUsesTXN )
1718 {
1719 if ( m_macControlIsShown )
ef4a634b 1720 TXNSetFrameBounds( (TXNObject) m_macTXN, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.top, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.left,
29e4a190 1721 (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.bottom,(**(STPTextPaneVars **)m_macTXNvars).fRTextArea.right, (**(STPTextPaneVars **)m_macTXNvars).fTXNFrame);
fd4393b8 1722 else
ef4a634b 1723 TXNSetFrameBounds( (TXNObject) m_macTXN, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.top + 30000, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.left,
29e4a190 1724 (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.bottom + 30000, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.right, (**(STPTextPaneVars **)m_macTXNvars).fTXNFrame);
fd4393b8
SC
1725 }
1726}
1727
ef4a634b 1728bool wxTextCtrl::Show(bool show)
fd4393b8
SC
1729{
1730 bool former = m_macControlIsShown ;
ef4a634b 1731
fd4393b8 1732 bool retval = wxControl::Show( show ) ;
ef4a634b 1733
2eefc6d5 1734 if ( former != m_macControlIsShown && m_macUsesTXN )
fd4393b8
SC
1735 {
1736 if ( m_macControlIsShown )
ef4a634b 1737 TXNSetFrameBounds( (TXNObject) m_macTXN, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.top, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.left,
29e4a190 1738 (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.bottom,(**(STPTextPaneVars **)m_macTXNvars).fRTextArea.right, (**(STPTextPaneVars **)m_macTXNvars).fTXNFrame);
fd4393b8 1739 else
ef4a634b 1740 TXNSetFrameBounds( (TXNObject) m_macTXN, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.top + 30000, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.left,
29e4a190 1741 (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.bottom + 30000, (**(STPTextPaneVars **)m_macTXNvars).fRTextArea.right, (**(STPTextPaneVars **)m_macTXNvars).fTXNFrame);
fd4393b8 1742 }
ef4a634b 1743
fd4393b8
SC
1744 return retval ;
1745}
1746
72055702
SC
1747// ----------------------------------------------------------------------------
1748// standard handlers for standard edit menu events
1749// ----------------------------------------------------------------------------
1750
eb22f2a6 1751void wxTextCtrl::OnCut(wxCommandEvent& WXUNUSED(event))
72055702
SC
1752{
1753 Cut();
1754}
1755
eb22f2a6 1756void wxTextCtrl::OnCopy(wxCommandEvent& WXUNUSED(event))
72055702
SC
1757{
1758 Copy();
1759}
1760
eb22f2a6 1761void wxTextCtrl::OnPaste(wxCommandEvent& WXUNUSED(event))
72055702
SC
1762{
1763 Paste();
1764}
1765
eb22f2a6 1766void wxTextCtrl::OnUndo(wxCommandEvent& WXUNUSED(event))
72055702
SC
1767{
1768 Undo();
1769}
1770
eb22f2a6 1771void wxTextCtrl::OnRedo(wxCommandEvent& WXUNUSED(event))
72055702
SC
1772{
1773 Redo();
1774}
1775
1776void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
1777{
1778 event.Enable( CanCut() );
1779}
1780
1781void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
1782{
1783 event.Enable( CanCopy() );
1784}
1785
1786void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
1787{
1788 event.Enable( CanPaste() );
1789}
1790
1791void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
1792{
1793 event.Enable( CanUndo() );
1794}
1795
1796void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
1797{
1798 event.Enable( CanRedo() );
1799}
1800
2b5f62a0
VZ
1801bool wxTextCtrl::MacSetupCursor( const wxPoint& pt )
1802{
1803 if ( m_macUsesTXN )
1804 return true ;
1805 else
1806 return wxWindow::MacSetupCursor( pt ) ;
1807}
72055702 1808
fedad417
GD
1809#endif
1810 // wxUSE_TEXTCTRL