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