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