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