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