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