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