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