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