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