]> git.saurik.com Git - wxWidgets.git/blob - src/mac/textctrl.cpp
Added clipboard cut and paste
[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/panel.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 #include "wx/mac/uma.h"
46
47 #define wxUSE_MLTE 0
48
49 #if wxUSE_MLTE == 0 // old textctrl implementation
50
51 #if !USE_SHARED_LIBRARY
52 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
53
54 BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
55 EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
56 EVT_CHAR(wxTextCtrl::OnChar)
57 EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
58 EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
59 EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
60 EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
61 EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
62
63 EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
64 EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
65 EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
66 EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
67 EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
68 END_EVENT_TABLE()
69 #endif
70
71 // Text item
72 wxTextCtrl::wxTextCtrl()
73 {
74 }
75
76 const short kVerticalMargin = 2 ;
77 const short kHorizontalMargin = 2 ;
78
79 bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
80 const wxString& st,
81 const wxPoint& pos,
82 const wxSize& size, long style,
83 const wxValidator& validator,
84 const wxString& name)
85 {
86 // base initialization
87 if ( !CreateBase(parent, id, pos, size, style, validator, name) )
88 return FALSE;
89
90 wxSize mySize = size ;
91 if ( UMAHasAppearance() )
92 {
93 m_macHorizontalBorder = 5 ; // additional pixels around the real control
94 m_macVerticalBorder = 5 ;
95 }
96 else
97 {
98 m_macHorizontalBorder = 0 ; // additional pixels around the real control
99 m_macVerticalBorder = 0 ;
100 }
101
102
103 Rect bounds ;
104 Str255 title ;
105
106 if ( mySize.y == -1 )
107 {
108 if ( UMAHasAppearance() )
109 mySize.y = 13 ;
110 else
111 mySize.y = 24 ;
112
113 mySize.y += 2 * m_macVerticalBorder ;
114 }
115
116 MacPreControlCreate( parent , id , "" , pos , mySize ,style, validator , name , &bounds , title ) ;
117
118 if ( m_windowStyle & wxTE_MULTILINE )
119 {
120 wxASSERT_MSG( !(m_windowStyle & wxTE_PROCESS_ENTER),
121 wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") );
122
123 m_windowStyle |= wxTE_PROCESS_ENTER;
124 }
125
126
127 m_macControl = ::NewControl( parent->GetMacRootWindow() , &bounds , "\p" , true , 0 , 0 , 1,
128 ( style & wxTE_PASSWORD ) ? kControlEditTextPasswordProc : kControlEditTextProc , (long) this ) ;
129 MacPostControlCreate() ;
130
131 wxString value ;
132
133 {
134 TEHandle teH ;
135 long size ;
136
137 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
138 (*teH)->lineHeight = -1 ;
139 }
140
141 if( wxApp::s_macDefaultEncodingIsPC )
142 value = wxMacMakeMacStringFromPC( st ) ;
143 else
144 value = st ;
145 ::SetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ;
146
147 return TRUE;
148 }
149
150 wxString wxTextCtrl::GetValue() const
151 {
152 Size actualsize;
153 ::GetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 32767 , wxBuffer , &actualsize) ;
154 wxBuffer[actualsize] = 0 ;
155 if( wxApp::s_macDefaultEncodingIsPC )
156 return wxMacMakePCStringFromMac( wxBuffer ) ;
157 else
158 return wxString(wxBuffer);
159 }
160
161 void wxTextCtrl::GetSelection(long* from, long* to) const
162 {
163 ControlEditTextSelectionRec selection ;
164 TEHandle teH ;
165 long size ;
166
167 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
168
169 *from = (**teH).selStart;
170 *to = (**teH).selEnd;
171 }
172
173 void wxTextCtrl::SetValue(const wxString& st)
174 {
175 wxString value ;
176
177 if( wxApp::s_macDefaultEncodingIsPC )
178 value = wxMacMakeMacStringFromPC( st ) ;
179 else
180 value = st ;
181 ::SetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ;
182 WindowRef window = GetMacRootWindow() ;
183 if ( window )
184 {
185 wxWindow* win = wxFindWinFromMacWindow( window ) ;
186 if ( win )
187 {
188 wxMacDrawingHelper help( win ) ;
189 // the mac control manager always assumes to have the origin at 0,0
190 SetOrigin( 0 , 0 ) ;
191
192 bool hasTabBehind = false ;
193 wxWindow* parent = GetParent() ;
194 while ( parent )
195 {
196 if( parent->MacGetWindowData() )
197 {
198 ::SetThemeWindowBackground( win->MacGetWindowData()->m_macWindow , kThemeBrushDialogBackgroundActive , false ) ;
199 break ;
200 }
201
202 if( parent->IsKindOf( CLASSINFO( wxNotebook ) ) || parent->IsKindOf( CLASSINFO( wxTabCtrl ) ))
203 {
204 if ( ((wxControl*)parent)->GetMacControl() )
205 SetUpControlBackground( ((wxControl*)parent)->GetMacControl() , -1 , true ) ;
206 break ;
207 }
208
209 parent = parent->GetParent() ;
210 }
211
212 UMADrawControl( m_macControl ) ;
213 ::SetThemeWindowBackground( win->MacGetWindowData()->m_macWindow , win->MacGetWindowData()->m_macWindowBackgroundTheme , false ) ;
214 }
215 }
216 }
217
218 // Clipboard operations
219 void wxTextCtrl::Copy()
220 {
221 if (CanCopy())
222 {
223 TEHandle teH ;
224 long size ;
225
226 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
227 TECopy( teH ) ;
228 ClearCurrentScrap();
229 TEToScrap() ;
230 }
231 }
232
233 void wxTextCtrl::Cut()
234 {
235 if (CanCut())
236 {
237 TEHandle teH ;
238 long size ;
239
240 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
241 TECut( teH ) ;
242 ClearCurrentScrap();
243 TEToScrap() ;
244 // MacInvalidateControl() ;
245 }
246 }
247
248 void wxTextCtrl::Paste()
249 {
250 if (CanPaste())
251 {
252 TEHandle teH ;
253 long size ;
254
255 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
256 TEFromScrap() ;
257 TEPaste( teH ) ;
258 WindowRef window = GetMacRootWindow() ;
259 if ( window )
260 {
261 wxWindow* win = wxFindWinFromMacWindow( window ) ;
262 if ( win )
263 {
264 wxMacDrawingHelper help( win ) ;
265 // the mac control manager always assumes to have the origin at 0,0
266 SetOrigin( 0 , 0 ) ;
267
268 bool hasTabBehind = false ;
269 wxWindow* parent = GetParent() ;
270 while ( parent )
271 {
272 if( parent->MacGetWindowData() )
273 {
274 ::SetThemeWindowBackground( win->MacGetWindowData()->m_macWindow , kThemeBrushDialogBackgroundActive , false ) ;
275 break ;
276 }
277
278 if( parent->IsKindOf( CLASSINFO( wxNotebook ) ) || parent->IsKindOf( CLASSINFO( wxTabCtrl ) ))
279 {
280 if ( ((wxControl*)parent)->GetMacControl() )
281 SetUpControlBackground( ((wxControl*)parent)->GetMacControl() , -1 , true ) ;
282 break ;
283 }
284
285 parent = parent->GetParent() ;
286 }
287
288 UMADrawControl( m_macControl ) ;
289 ::SetThemeWindowBackground( win->MacGetWindowData()->m_macWindow , win->MacGetWindowData()->m_macWindowBackgroundTheme , false ) ;
290 }
291 }
292 }
293 }
294
295 bool wxTextCtrl::CanCopy() const
296 {
297 // Can copy if there's a selection
298 long from, to;
299 GetSelection(& from, & to);
300 return (from != to);
301 }
302
303 bool wxTextCtrl::CanCut() const
304 {
305 // Can cut if there's a selection
306 long from, to;
307 GetSelection(& from, & to);
308 return (from != to);
309 }
310
311 bool wxTextCtrl::CanPaste() const
312 {
313 if (!IsEditable())
314 return FALSE;
315
316 long offset ;
317 #if TARGET_CARBON
318 OSStatus err = noErr;
319 ScrapRef scrapRef;
320
321 err = GetCurrentScrap( &scrapRef );
322 if ( err != noTypeErr && err != memFullErr )
323 {
324 ScrapFlavorFlags flavorFlags;
325 Size byteCount;
326
327 if (( err = GetScrapFlavorFlags( scrapRef, 'TEXT', &flavorFlags )) == noErr)
328 {
329 if (( err = GetScrapFlavorSize( scrapRef, 'TEXT', &byteCount )) == noErr)
330 {
331 return TRUE ;
332 }
333 }
334 }
335 return FALSE;
336
337 #else
338 if ( GetScrap( NULL , 'TEXT' , &offset ) > 0 )
339 {
340 return TRUE ;
341 }
342 #endif
343 return FALSE ;
344 }
345
346 void wxTextCtrl::SetEditable(bool editable)
347 {
348 if ( editable )
349 UMAActivateControl( m_macControl ) ;
350 else
351 UMADeactivateControl( m_macControl ) ;
352 }
353
354 void wxTextCtrl::SetInsertionPoint(long pos)
355 {
356 SetSelection( pos , pos ) ;
357 }
358
359 void wxTextCtrl::SetInsertionPointEnd()
360 {
361 long pos = GetLastPosition();
362 SetInsertionPoint(pos);
363 }
364
365 long wxTextCtrl::GetInsertionPoint() const
366 {
367 ControlEditTextSelectionRec selection ;
368 TEHandle teH ;
369 long size ;
370
371 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
372 // ::GetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection , &size ) ;
373 return (**teH).selStart ;
374 }
375
376 long wxTextCtrl::GetLastPosition() const
377 {
378 ControlEditTextSelectionRec selection ;
379 TEHandle teH ;
380 long size ;
381
382 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
383
384 // ::GetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection , &size ) ;
385 return (**teH).teLength ;
386 }
387
388 void wxTextCtrl::Replace(long from, long to, const wxString& value)
389 {
390 TEHandle teH ;
391 long size ;
392
393 ControlEditTextSelectionRec selection ;
394
395 selection.selStart = from ;
396 selection.selEnd = to ;
397 ::SetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
398 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
399 TESetSelect( from , to , teH ) ;
400 TEDelete( teH ) ;
401 TEInsert( value , value.Length() , teH ) ;
402 Refresh() ;
403 }
404
405 void wxTextCtrl::Remove(long from, long to)
406 {
407 TEHandle teH ;
408 long size ;
409
410 ControlEditTextSelectionRec selection ;
411
412 selection.selStart = from ;
413 selection.selEnd = to ;
414 ::SetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
415 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
416 TEDelete( teH ) ;
417 Refresh() ;
418 }
419
420 void wxTextCtrl::SetSelection(long from, long to)
421 {
422 ControlEditTextSelectionRec selection ;
423 TEHandle teH ;
424 long size ;
425
426 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
427
428 selection.selStart = from ;
429 selection.selEnd = to ;
430
431 ::SetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
432 TESetSelect( selection.selStart , selection.selEnd , teH ) ;
433 }
434
435 bool wxTextCtrl::LoadFile(const wxString& file)
436 {
437 if ( wxTextCtrlBase::LoadFile(file) )
438 {
439 return TRUE;
440 }
441
442 return FALSE;
443 }
444
445 void wxTextCtrl::WriteText(const wxString& text)
446 {
447 TEHandle teH ;
448 long size ;
449
450 memcpy( wxBuffer, text , text.Length() ) ;
451 wxBuffer[text.Length() ] = 0 ;
452 // wxMacConvertNewlines( wxBuffer , wxBuffer ) ;
453
454 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
455
456 TEInsert( wxBuffer , strlen( wxBuffer) , teH ) ;
457 Refresh() ;
458 }
459
460 void wxTextCtrl::AppendText(const wxString& text)
461 {
462 SetInsertionPointEnd();
463 WriteText(text);
464 }
465
466 void wxTextCtrl::Clear()
467 {
468 ::SetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 0 , (char*) ((const char*)NULL) ) ;
469 Refresh() ;
470 }
471
472 bool wxTextCtrl::IsModified() const
473 {
474 return TRUE;
475 }
476
477 bool wxTextCtrl::IsEditable() const
478 {
479 return IsEnabled();
480 }
481
482 bool wxTextCtrl::AcceptsFocus() const
483 {
484 // we don't want focus if we can't be edited
485 return IsEditable() && wxControl::AcceptsFocus();
486 }
487
488 wxSize wxTextCtrl::DoGetBestSize() const
489 {
490 int wText = 100 ;
491
492 int hText ;
493 if ( UMAHasAppearance() )
494 hText = 13 ;
495 else
496 hText = 24 ;
497 hText += 2 * m_macHorizontalBorder ;
498 /*
499 int cx, cy;
500 wxGetCharSize(GetHWND(), &cx, &cy, &GetFont());
501
502 int wText = DEFAULT_ITEM_WIDTH;
503
504 int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
505
506 return wxSize(wText, hText);
507 */
508 if ( m_windowStyle & wxTE_MULTILINE )
509 {
510 hText *= wxMin(GetNumberOfLines(), 5);
511 }
512 //else: for single line control everything is ok
513 return wxSize(wText, hText);
514 }
515
516 // ----------------------------------------------------------------------------
517 // Undo/redo
518 // ----------------------------------------------------------------------------
519
520 void wxTextCtrl::Undo()
521 {
522 if (CanUndo())
523 {
524 }
525 }
526
527 void wxTextCtrl::Redo()
528 {
529 if (CanRedo())
530 {
531 }
532 }
533
534 bool wxTextCtrl::CanUndo() const
535 {
536 return FALSE ;
537 }
538
539 bool wxTextCtrl::CanRedo() const
540 {
541 return FALSE ;
542 }
543
544 // Makes 'unmodified'
545 void wxTextCtrl::DiscardEdits()
546 {
547 // TODO
548 }
549
550 int wxTextCtrl::GetNumberOfLines() const
551 {
552 Size actualsize;
553 ::GetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 32767 , wxBuffer , &actualsize) ;
554
555 int count = 1;
556 for (int i = 0; i < actualsize; i++)
557 {
558 if (wxBuffer[i] == '\r') count++;
559 }
560
561 return count;
562 }
563
564 long wxTextCtrl::XYToPosition(long x, long y) const
565 {
566 // TODO
567 return 0;
568 }
569
570 bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
571 {
572 return FALSE ;
573 }
574
575 void wxTextCtrl::ShowPosition(long pos)
576 {
577 // TODO
578 }
579
580 int wxTextCtrl::GetLineLength(long lineNo) const
581 {
582 Size actualsize;
583 ::GetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 32767 , wxBuffer , &actualsize) ;
584
585 // Find line first
586 int count = 0;
587 for (int i = 0; i < actualsize; i++)
588 {
589 if (count == lineNo)
590 {
591 // Count chars in line then
592 count = 0;
593 for (int j = i; j < actualsize; j++)
594 {
595 count++;
596 if (wxBuffer[j] == '\r') return count;
597 }
598
599 return count;
600 }
601 if (wxBuffer[i] == '\r') count++;
602 }
603
604 return 0;
605 }
606
607 wxString wxTextCtrl::GetLineText(long lineNo) const
608 {
609 Size actualsize;
610 ::GetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 32767 , wxBuffer , &actualsize) ;
611
612 // Find line first
613 int count = 0;
614 for (int i = 0; i < actualsize; i++)
615 {
616 if (count == lineNo)
617 {
618 // Add chars in line then
619 wxString tmp("");
620
621 for (int j = i; j < actualsize; j++)
622 {
623 if (wxBuffer[j] == '\r')
624 return tmp;
625
626 tmp += wxBuffer[j];
627 }
628
629 return tmp;
630 }
631 if (wxBuffer[i] == '\r') count++;
632 }
633
634 return wxString("");
635 }
636
637 /*
638 * Text item
639 */
640
641 void wxTextCtrl::Command(wxCommandEvent & event)
642 {
643 SetValue (event.GetString());
644 ProcessCommand (event);
645 }
646
647 void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
648 {
649 // By default, load the first file into the text window.
650 if (event.GetNumberOfFiles() > 0)
651 {
652 LoadFile(event.GetFiles()[0]);
653 }
654 }
655
656 void wxTextCtrl::OnChar(wxKeyEvent& key_event)
657 {
658 bool eat_key = FALSE;
659
660 switch ( key_event.KeyCode() )
661 {
662 case WXK_RETURN:
663 if (m_windowStyle & wxPROCESS_ENTER)
664 {
665 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
666 event.SetEventObject( this );
667 event.SetString( GetValue() );
668 if ( GetEventHandler()->ProcessEvent(event) )
669 return;
670 }
671 if ( !(m_windowStyle & wxTE_MULTILINE) )
672 {
673 wxWindow *parent = GetParent();
674 while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL ) {
675 parent = parent->GetParent() ;
676 }
677 if ( parent && parent->GetDefaultItem() )
678 {
679 wxButton *def = wxDynamicCast(parent->GetDefaultItem(),
680 wxButton);
681 if ( def && def->IsEnabled() )
682 {
683 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
684 event.SetEventObject(def);
685 def->Command(event);
686 return ;
687 }
688 }
689
690 // this will make wxWindows eat the ENTER key so that
691 // we actually prevent line wrapping in a single line
692 // text control
693 eat_key = TRUE;
694 }
695
696 break;
697
698 case WXK_TAB:
699 // always produce navigation event - even if we process TAB
700 // ourselves the fact that we got here means that the user code
701 // decided to skip processing of this TAB - probably to let it
702 // do its default job.
703 {
704 wxNavigationKeyEvent eventNav;
705 eventNav.SetDirection(!key_event.ShiftDown());
706 eventNav.SetWindowChange(key_event.ControlDown());
707 eventNav.SetEventObject(this);
708
709 if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav) )
710 return;
711
712 key_event.Skip() ;
713 return;
714 }
715 break;
716 }
717
718 EventRecord *ev = wxTheApp->MacGetCurrentEvent();
719 short keychar = short(ev->message & charCodeMask);
720 if (!eat_key)
721 {
722 short keycode = short(ev->message & keyCodeMask) >> 8 ;
723 ::HandleControlKey( m_macControl , keycode , keychar , ev->modifiers );
724 }
725 if ( keychar >= 0x20 ||
726 key_event.KeyCode() == WXK_RETURN ||
727 key_event.KeyCode() == WXK_DELETE ||
728 key_event.KeyCode() == WXK_BACK)
729 {
730 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
731 event.SetString( GetValue() ) ;
732 event.SetEventObject( this );
733 GetEventHandler()->ProcessEvent(event);
734 }
735 }
736
737 // ----------------------------------------------------------------------------
738 // standard handlers for standard edit menu events
739 // ----------------------------------------------------------------------------
740
741 void wxTextCtrl::OnCut(wxCommandEvent& event)
742 {
743 Cut();
744 }
745
746 void wxTextCtrl::OnCopy(wxCommandEvent& event)
747 {
748 Copy();
749 }
750
751 void wxTextCtrl::OnPaste(wxCommandEvent& event)
752 {
753 Paste();
754 }
755
756 void wxTextCtrl::OnUndo(wxCommandEvent& event)
757 {
758 Undo();
759 }
760
761 void wxTextCtrl::OnRedo(wxCommandEvent& event)
762 {
763 Redo();
764 }
765
766 void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
767 {
768 event.Enable( CanCut() );
769 }
770
771 void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
772 {
773 event.Enable( CanCopy() );
774 }
775
776 void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
777 {
778 event.Enable( CanPaste() );
779 }
780
781 void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
782 {
783 event.Enable( CanUndo() );
784 }
785
786 void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
787 {
788 event.Enable( CanRedo() );
789 }
790
791 #else
792
793 extern wxApp *wxTheApp ;
794 // CS:We will replace the TextEdit by using the MultiLanguageTextEngine based on the following code written by apple
795
796 /*
797 File: mUPControl.c
798
799 Description:
800 mUPControl implementation.
801
802 Copyright:
803 © Copyright 2000 Apple Computer, Inc. All rights reserved.
804
805 Disclaimer:
806 IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
807 ("Apple") in consideration of your agreement to the following terms, and your
808 use, installation, modification or redistribution of this Apple software
809 constitutes acceptance of these terms. If you do not agree with these terms,
810 please do not use, install, modify or redistribute this Apple software.
811
812 In consideration of your agreement to abide by the following terms, and subject
813 to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
814 copyrights in this original Apple software (the "Apple Software"), to use,
815 reproduce, modify and redistribute the Apple Software, with or without
816 modifications, in source and/or binary forms; provided that if you redistribute
817 the Apple Software in its entirety and without modifications, you must retain
818 this notice and the following text and disclaimers in all such redistributions of
819 the Apple Software. Neither the name, trademarks, service marks or logos of
820 Apple Computer, Inc. may be used to endorse or promote products derived from the
821 Apple Software without specific prior written permission from Apple. Except as
822 expressly stated in this notice, no other rights or licenses, express or implied,
823 are granted by Apple herein, including but not limited to any patent rights that
824 may be infringed by your derivative works or by other works in which the Apple
825 Software may be incorporated.
826
827 The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
828 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
829 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
830 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
831 COMBINATION WITH YOUR PRODUCTS.
832
833 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
834 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
835 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
836 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
837 OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
838 (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
839 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
840
841 Change History (most recent first):
842 Fri, Jan 28, 2000 -- created
843 */
844
845 #include "MacTextEditor.h"
846
847 /* part codes */
848
849 /* kmUPTextPart is the part code we return to indicate the user has clicked
850 in the text area of our control */
851 #define kmUPTextPart 1
852
853 /* kmUPScrollPart is the part code we return to indicate the user has clicked
854 in the scroll bar part of the control. */
855 #define kmUPScrollPart 2
856
857
858 /* routines for using existing user pane controls.
859 These routines are useful for cases where you would like to use an
860 existing user pane control in, say, a dialog window as a scrolling
861 text edit field.*/
862
863 /* mUPOpenControl initializes a user pane control so it will be drawn
864 and will behave as a scrolling text edit field inside of a window.
865 This routine performs all of the initialization steps necessary,
866 except it does not create the user pane control itself. theControl
867 should refer to a user pane control that you have either created
868 yourself or extracted from a dialog's control heirarchy using
869 the GetDialogItemAsControl routine. */
870 OSStatus mUPOpenControl(ControlHandle theControl);
871
872 /* mUPCloseControl deallocates all of the structures allocated
873 by mUPOpenControl. */
874 OSStatus mUPCloseControl(ControlHandle theControl);
875
876
877
878 /* routines for creating new scrolling text user pane controls.
879 These routines allow you to create new scrolling text
880 user pane controls. */
881
882 /* mUPCreateControl creates a new user pane control and then it passes it
883 to mUPOpenControl to initialize it as a scrolling text user pane control. */
884 OSStatus mUPCreateControl(WindowPtr theWindow, Rect *bounds, ControlHandle *theControl);
885
886 /* mUPDisposeControl calls mUPCloseControl and then it calls DisposeControl. */
887 OSStatus mUPDisposeControl(ControlHandle theControl);
888
889
890 /* Utility Routines */
891
892 /* mUPSetText replaces the contents of the selection with the unicode
893 text described by the text and count parameters:.
894 text = pointer to unicode text buffer
895 count = number of bytes in the buffer. */
896 OSStatus mUPSetText(ControlHandle theControl, char* text, long count);
897
898 /* mUPGetText returns the current text data being displayed inside of
899 the mUPControl. When noErr is returned, *theText contain a new
900 handle containing all of the Unicode text copied from the current
901 selection. It is the caller's responsibiliby to dispose of this handle. */
902 OSStatus mUPGetText(ControlHandle theControl, Handle *theText);
903
904
905 /* mUPSetSelection sets the text selection and autoscrolls the text view
906 so either the cursor or the selction is in the view. */
907 void mUPSetSelection(ControlHandle theControl, long selStart, long selEnd);
908
909
910
911 /* IsmUPControl returns true if theControl is not NULL
912 and theControl refers to a mUP Control. */
913 Boolean IsmUPControl(ControlHandle theControl);
914
915
916
917 /* Edit commands for mUP Controls. */
918 enum {
919 kmUPCut = 1,
920 kmUPCopy = 2,
921 kmUPPaste = 3,
922 kmUPClear = 4
923 };
924
925
926 /* mUPDoEditCommand performs the editing command specified
927 in the editCommand parameter. The mUPControl's text
928 and scroll bar are redrawn and updated as necessary. */
929 void mUPDoEditCommand(ControlHandle theControl, short editCommand);
930
931
932
933
934 /* mUPGetContents returns the entire contents of the control including the text
935 and the formatting information. */
936 OSStatus mUPGetContents(ControlHandle theControl, Handle *theContents);
937 /* mUPSetContents replaces the contents of the selection with the data stored in the handle. */
938 OSStatus mUPSetContents(ControlHandle theControl, Handle theContents);
939
940 enum {
941 kShiftKeyCode = 56
942 };
943
944 /* kUserClickedToFocusPart is a part code we pass to the SetKeyboardFocus
945 routine. In our focus switching routine this part code is understood
946 as meaning 'the user has clicked in the control and we need to switch
947 the current focus to ourselves before we can continue'. */
948 #define kUserClickedToFocusPart 100
949
950
951 /* kmUPClickScrollDelayTicks is a time measurement in ticks used to
952 slow the speed of 'auto scrolling' inside of our clickloop routine.
953 This value prevents the text from wizzzzzing by while the mouse
954 is being held down inside of the text area. */
955 #define kmUPClickScrollDelayTicks 3
956
957
958 /* STPTextPaneVars is a structure used for storing the the mUP Control's
959 internal variables and state information. A handle to this record is
960 stored in the pane control's reference value field using the
961 SetControlReference routine. */
962
963 typedef struct {
964 /* OS records referenced */
965 TXNObject fTXNRec; /* the txn record */
966 TXNFrameID fTXNFrame; /* the txn frame ID */
967 ControlHandle fUserPaneRec; /* handle to the user pane control */
968 WindowPtr fOwner; /* window containing control */
969 GrafPtr fDrawingEnvironment; /* grafport where control is drawn */
970 /* flags */
971 Boolean fInFocus; /* true while the focus rect is drawn around the control */
972 Boolean fIsActive; /* true while the control is drawn in the active state */
973 Boolean fTEActive; /* reflects the activation state of the text edit record */
974 Boolean fInDialogWindow; /* true if displayed in a dialog window */
975 /* calculated locations */
976 Rect fRTextArea; /* area where the text is drawn */
977 Rect fRFocusOutline; /* rectangle used to draw the focus box */
978 Rect fRTextOutline; /* rectangle used to draw the border */
979 RgnHandle fTextBackgroundRgn; /* background region for the text, erased before calling TEUpdate */
980 /* our focus advance override routine */
981 EventHandlerUPP handlerUPP;
982 EventHandlerRef handlerRef;
983 } STPTextPaneVars;
984
985
986
987
988 /* Univerals Procedure Pointer variables used by the
989 mUP Control. These variables are set up
990 the first time that mUPOpenControl is called. */
991 ControlUserPaneDrawUPP gTPDrawProc = NULL;
992 ControlUserPaneHitTestUPP gTPHitProc = NULL;
993 ControlUserPaneTrackingUPP gTPTrackProc = NULL;
994 ControlUserPaneIdleUPP gTPIdleProc = NULL;
995 ControlUserPaneKeyDownUPP gTPKeyProc = NULL;
996 ControlUserPaneActivateUPP gTPActivateProc = NULL;
997 ControlUserPaneFocusUPP gTPFocusProc = NULL;
998
999 /* events handled by our focus advance override routine */
1000 #if TARGET_CARBON
1001 static const EventTypeSpec gMLTEEvents[] = { { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } };
1002 #define kMLTEEventCount (sizeof( gMLTEEvents ) / sizeof( EventTypeSpec ))
1003 #endif
1004
1005
1006 /* TPActivatePaneText activates or deactivates the text edit record
1007 according to the value of setActive. The primary purpose of this
1008 routine is to ensure each call is only made once. */
1009 static void TPActivatePaneText(STPTextPaneVars **tpvars, Boolean setActive) {
1010 STPTextPaneVars *varsp;
1011 varsp = *tpvars;
1012 if (varsp->fTEActive != setActive) {
1013
1014 varsp->fTEActive = setActive;
1015
1016 TXNActivate(varsp->fTXNRec, varsp->fTXNFrame, varsp->fTEActive);
1017
1018 if (varsp->fInFocus)
1019 TXNFocus( varsp->fTXNRec, varsp->fTEActive);
1020 }
1021 }
1022
1023
1024 /* TPFocusPaneText set the focus state for the text record. */
1025 static void TPFocusPaneText(STPTextPaneVars **tpvars, Boolean setFocus) {
1026 STPTextPaneVars *varsp;
1027 varsp = *tpvars;
1028 if (varsp->fInFocus != setFocus) {
1029 varsp->fInFocus = setFocus;
1030 TXNFocus( varsp->fTXNRec, varsp->fInFocus);
1031 }
1032 }
1033
1034
1035 /* TPPaneDrawProc is called to redraw the control and for update events
1036 referring to the control. This routine erases the text area's background,
1037 and redraws the text. This routine assumes the scroll bar has been
1038 redrawn by a call to DrawControls. */
1039 static pascal void TPPaneDrawProc(ControlRef theControl, ControlPartCode thePart) {
1040 STPTextPaneVars **tpvars, *varsp;
1041 char state;
1042 Rect bounds;
1043 /* set up our globals */
1044 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
1045 if (tpvars != NULL) {
1046 state = HGetState((Handle) tpvars);
1047 HLock((Handle) tpvars);
1048 varsp = *tpvars;
1049
1050 /* save the drawing state */
1051 SetPort((**tpvars).fDrawingEnvironment);
1052 /* verify our boundary */
1053 GetControlBounds(theControl, &bounds);
1054 if ( ! EqualRect(&bounds, &varsp->fRTextArea) ) {
1055 SetRect(&varsp->fRFocusOutline, bounds.left, bounds.top, bounds.right, bounds.bottom);
1056 SetRect(&varsp->fRTextOutline, bounds.left, bounds.top, bounds.right, bounds.bottom);
1057 SetRect(&varsp->fRTextArea, bounds.left, bounds.top, bounds.right, bounds.bottom);
1058 RectRgn(varsp->fTextBackgroundRgn, &varsp->fRTextOutline);
1059 TXNSetFrameBounds( varsp->fTXNRec, bounds.top, bounds.left, bounds.bottom, bounds.right, varsp->fTXNFrame);
1060 }
1061
1062 /* update the text region */
1063 EraseRgn(varsp->fTextBackgroundRgn);
1064 TXNDraw(varsp->fTXNRec, NULL);
1065 /* restore the drawing environment */
1066 /* draw the text frame and focus frame (if necessary) */
1067 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
1068 if ((**tpvars).fIsActive && varsp->fInFocus) DrawThemeFocusRect(&varsp->fRFocusOutline, true);
1069 /* release our globals */
1070 HSetState((Handle) tpvars, state);
1071 }
1072 }
1073
1074
1075 /* TPPaneHitTestProc is called when the control manager would
1076 like to determine what part of the control the mouse resides over.
1077 We also call this routine from our tracking proc to determine how
1078 to handle mouse clicks. */
1079 static pascal ControlPartCode TPPaneHitTestProc(ControlHandle theControl, Point where) {
1080 STPTextPaneVars **tpvars;
1081 ControlPartCode result;
1082 char state;
1083 /* set up our locals and lock down our globals*/
1084 result = 0;
1085 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
1086 if (tpvars != NULL) {
1087 state = HGetState((Handle) tpvars);
1088 HLock((Handle) tpvars);
1089 /* find the region where we clicked */
1090 if (PtInRect(where, &(**tpvars).fRTextArea)) {
1091 result = kmUPTextPart;
1092 } else result = 0;
1093 /* release oure globals */
1094 HSetState((Handle) tpvars, state);
1095 }
1096 return result;
1097 }
1098
1099
1100
1101
1102
1103 /* TPPaneTrackingProc is called when the mouse is being held down
1104 over our control. This routine handles clicks in the text area
1105 and in the scroll bar. */
1106 static pascal ControlPartCode TPPaneTrackingProc(ControlHandle theControl, Point startPt, ControlActionUPP actionProc) {
1107 STPTextPaneVars **tpvars, *varsp;
1108 char state;
1109 ControlPartCode partCodeResult;
1110 /* make sure we have some variables... */
1111 partCodeResult = 0;
1112 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
1113 if (tpvars != NULL) {
1114 /* lock 'em down */
1115 state = HGetState((Handle) tpvars);
1116 HLock((Handle) tpvars);
1117 varsp = *tpvars;
1118 /* we don't do any of these functions unless we're in focus */
1119 if ( ! varsp->fInFocus) {
1120 WindowPtr owner;
1121 owner = GetControlOwner(theControl);
1122 ClearKeyboardFocus(owner);
1123 SetKeyboardFocus(owner, theControl, kUserClickedToFocusPart);
1124 }
1125 /* find the location for the click */
1126 switch (TPPaneHitTestProc(theControl, startPt)) {
1127
1128 /* handle clicks in the text part */
1129 case kmUPTextPart:
1130 { SetPort((**tpvars).fDrawingEnvironment);
1131 TXNClick( varsp->fTXNRec, GetCurrentEventRecord());
1132 }
1133 break;
1134
1135 }
1136
1137 HSetState((Handle) tpvars, state);
1138 }
1139 return partCodeResult;
1140 }
1141
1142
1143 /* TPPaneIdleProc is our user pane idle routine. When our text field
1144 is active and in focus, we use this routine to set the cursor. */
1145 static pascal void TPPaneIdleProc(ControlHandle theControl) {
1146 STPTextPaneVars **tpvars, *varsp;
1147 /* set up locals */
1148 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
1149 if (tpvars != NULL) {
1150 /* if we're not active, then we have nothing to say about the cursor */
1151 if ((**tpvars).fIsActive) {
1152 char state;
1153 Rect bounds;
1154 Point mousep;
1155 /* lock down the globals */
1156 state = HGetState((Handle) tpvars);
1157 HLock((Handle) tpvars);
1158 varsp = *tpvars;
1159 /* get the current mouse coordinates (in our window) */
1160 #if TARGET_CARBON
1161 SetPort(GetWindowPort(GetControlOwner(theControl)));
1162 #else
1163 SetPort((GrafPtr) GetWindowPort(GetControlOwner(theControl)));
1164 #endif
1165 GetMouse(&mousep);
1166 /* there's a 'focus thing' and an 'unfocused thing' */
1167 if (varsp->fInFocus) {
1168 /* flash the cursor */
1169 SetPort((**tpvars).fDrawingEnvironment);
1170 TXNIdle(varsp->fTXNRec);
1171 /* set the cursor */
1172 if (PtInRect(mousep, &varsp->fRTextArea)) {
1173 RgnHandle theRgn;
1174 RectRgn((theRgn = NewRgn()), &varsp->fRTextArea);
1175 TXNAdjustCursor(varsp->fTXNRec, theRgn);
1176 DisposeRgn(theRgn);
1177 } else SetThemeCursor(kThemeArrowCursor);
1178 } else {
1179 /* if it's in our bounds, set the cursor */
1180 GetControlBounds(theControl, &bounds);
1181 if (PtInRect(mousep, &bounds))
1182 SetThemeCursor(kThemeArrowCursor);
1183 }
1184
1185 HSetState((Handle) tpvars, state);
1186 }
1187 }
1188 }
1189
1190
1191 /* TPPaneKeyDownProc is called whenever a keydown event is directed
1192 at our control. Here, we direct the keydown event to the text
1193 edit record and redraw the scroll bar and text field as appropriate. */
1194 static pascal ControlPartCode TPPaneKeyDownProc(ControlHandle theControl,
1195 SInt16 keyCode, SInt16 charCode, SInt16 modifiers) {
1196 STPTextPaneVars **tpvars;
1197 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
1198 if (tpvars != NULL) {
1199 if ((**tpvars).fInFocus) {
1200 /* turn autoscrolling on and send the key event to text edit */
1201 SetPort((**tpvars).fDrawingEnvironment);
1202 TXNKeyDown( (**tpvars).fTXNRec, GetCurrentEventRecord());
1203 }
1204 }
1205 return kControlEntireControl;
1206 }
1207
1208
1209 /* TPPaneActivateProc is called when the window containing
1210 the user pane control receives activate events. Here, we redraw
1211 the control and it's text as necessary for the activation state. */
1212 static pascal void TPPaneActivateProc(ControlHandle theControl, Boolean activating) {
1213 Rect bounds;
1214 STPTextPaneVars **tpvars, *varsp;
1215 char state;
1216 /* set up locals */
1217 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
1218 if (tpvars != NULL) {
1219 state = HGetState((Handle) tpvars);
1220 HLock((Handle) tpvars);
1221 varsp = *tpvars;
1222 /* de/activate the text edit record */
1223 SetPort((**tpvars).fDrawingEnvironment);
1224 GetControlBounds(theControl, &bounds);
1225 varsp->fIsActive = activating;
1226 TPActivatePaneText(tpvars, varsp->fIsActive && varsp->fInFocus);
1227 /* redraw the frame */
1228 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
1229 if (varsp->fInFocus) DrawThemeFocusRect(&varsp->fRFocusOutline, varsp->fIsActive);
1230 HSetState((Handle) tpvars, state);
1231 }
1232 }
1233
1234
1235 /* TPPaneFocusProc is called when every the focus changes to or
1236 from our control. Herein, switch the focus appropriately
1237 according to the parameters and redraw the control as
1238 necessary. */
1239 static pascal ControlPartCode TPPaneFocusProc(ControlHandle theControl, ControlFocusPart action) {
1240 ControlPartCode focusResult;
1241 STPTextPaneVars **tpvars, *varsp;
1242 char state;
1243 /* set up locals */
1244 focusResult = kControlFocusNoPart;
1245 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
1246 if (tpvars != NULL) {
1247 state = HGetState((Handle) tpvars);
1248 HLock((Handle) tpvars);
1249 varsp = *tpvars;
1250 /* if kControlFocusPrevPart and kControlFocusNextPart are received when the user is
1251 tabbing forwards (or shift tabbing backwards) through the items in the dialog,
1252 and kControlFocusNextPart will be received. When the user clicks in our field
1253 and it is not the current focus, then the constant kUserClickedToFocusPart will
1254 be received. The constant kControlFocusNoPart will be received when our control
1255 is the current focus and the user clicks in another control. In your focus routine,
1256 you should respond to these codes as follows:
1257
1258 kControlFocusNoPart - turn off focus and return kControlFocusNoPart. redraw
1259 the control and the focus rectangle as necessary.
1260
1261 kControlFocusPrevPart or kControlFocusNextPart - toggle focus on or off
1262 depending on its current state. redraw the control and the focus rectangle
1263 as appropriate for the new focus state. If the focus state is 'off', return the constant
1264 kControlFocusNoPart, otherwise return a non-zero part code.
1265 kUserClickedToFocusPart - is a constant defined for this example. You should
1266 define your own value for handling click-to-focus type events. */
1267 /* save the drawing state */
1268 SetPort((**tpvars).fDrawingEnvironment);
1269 /* calculate the next highlight state */
1270 switch (action) {
1271 default:
1272 case kControlFocusNoPart:
1273 TPFocusPaneText(tpvars, false);
1274 focusResult = kControlFocusNoPart;
1275 break;
1276 case kUserClickedToFocusPart:
1277 TPFocusPaneText(tpvars, true);
1278 focusResult = 1;
1279 break;
1280 case kControlFocusPrevPart:
1281 case kControlFocusNextPart:
1282 TPFocusPaneText(tpvars, ( ! varsp->fInFocus));
1283 focusResult = varsp->fInFocus ? 1 : kControlFocusNoPart;
1284 break;
1285 }
1286 TPActivatePaneText(tpvars, varsp->fIsActive && varsp->fInFocus);
1287 /* redraw the text fram and focus rectangle to indicate the
1288 new focus state */
1289 DrawThemeEditTextFrame(&varsp->fRTextOutline, varsp->fIsActive ? kThemeStateActive: kThemeStateInactive);
1290 DrawThemeFocusRect(&varsp->fRFocusOutline, varsp->fIsActive && varsp->fInFocus);
1291 /* done */
1292 HSetState((Handle) tpvars, state);
1293 }
1294 return focusResult;
1295 }
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307 //This our carbon event handler for unicode key downs
1308 #if TARGET_CARBON
1309 static pascal OSStatus FocusAdvanceOverride(EventHandlerCallRef myHandler, EventRef event, void* userData) {
1310 WindowRef window;
1311 STPTextPaneVars **tpvars;
1312 OSStatus err;
1313 unsigned short mUnicodeText;
1314 ByteCount charCounts=0;
1315 /* get our window pointer */
1316 tpvars = (STPTextPaneVars **) userData;
1317 window = (**tpvars).fOwner;
1318 //find out how many bytes are needed
1319 err = GetEventParameter(event, kEventParamTextInputSendText,
1320 typeUnicodeText, NULL, 0, &charCounts, NULL);
1321 if (err != noErr) goto bail;
1322 /* we're only looking at single characters */
1323 if (charCounts != 2) { err = eventNotHandledErr; goto bail; }
1324 /* get the character */
1325 err = GetEventParameter(event, kEventParamTextInputSendText,
1326 typeUnicodeText, NULL, sizeof(mUnicodeText),
1327 &charCounts, (char*) &mUnicodeText);
1328 if (err != noErr) goto bail;
1329 /* if it's not the tab key, forget it... */
1330 if ((mUnicodeText != '\t')) { err = eventNotHandledErr; goto bail; }
1331 /* advance the keyboard focus */
1332 AdvanceKeyboardFocus(window);
1333 /* noErr lets the CEM know we handled the event */
1334 return noErr;
1335 bail:
1336 return eventNotHandledErr;
1337 }
1338 #endif
1339
1340
1341 /* mUPOpenControl initializes a user pane control so it will be drawn
1342 and will behave as a scrolling text edit field inside of a window.
1343 This routine performs all of the initialization steps necessary,
1344 except it does not create the user pane control itself. theControl
1345 should refer to a user pane control that you have either created
1346 yourself or extracted from a dialog's control heirarchy using
1347 the GetDialogItemAsControl routine. */
1348 OSStatus mUPOpenControl(ControlHandle theControl, bool multiline) {
1349 Rect bounds;
1350 WindowPtr theWindow;
1351 STPTextPaneVars **tpvars, *varsp;
1352 OSStatus err;
1353 RGBColor rgbWhite = {0xFFFF, 0xFFFF, 0xFFFF};
1354 TXNBackground tback;
1355
1356 /* set up our globals */
1357 if (gTPDrawProc == NULL) gTPDrawProc = NewControlUserPaneDrawUPP(TPPaneDrawProc);
1358 if (gTPHitProc == NULL) gTPHitProc = NewControlUserPaneHitTestUPP(TPPaneHitTestProc);
1359 if (gTPTrackProc == NULL) gTPTrackProc = NewControlUserPaneTrackingUPP(TPPaneTrackingProc);
1360 if (gTPIdleProc == NULL) gTPIdleProc = NewControlUserPaneIdleUPP(TPPaneIdleProc);
1361 if (gTPKeyProc == NULL) gTPKeyProc = NewControlUserPaneKeyDownUPP(TPPaneKeyDownProc);
1362 if (gTPActivateProc == NULL) gTPActivateProc = NewControlUserPaneActivateUPP(TPPaneActivateProc);
1363 if (gTPFocusProc == NULL) gTPFocusProc = NewControlUserPaneFocusUPP(TPPaneFocusProc);
1364
1365 /* allocate our private storage */
1366 tpvars = (STPTextPaneVars **) NewHandleClear(sizeof(STPTextPaneVars));
1367 SetControlReference(theControl, (long) tpvars);
1368 HLock((Handle) tpvars);
1369 varsp = *tpvars;
1370 /* set the initial settings for our private data */
1371 varsp->fInFocus = false;
1372 varsp->fIsActive = true;
1373 varsp->fTEActive = false;
1374 varsp->fUserPaneRec = theControl;
1375 theWindow = varsp->fOwner = GetControlOwner(theControl);
1376 #if TARGET_CARBON
1377 varsp->fDrawingEnvironment = GetWindowPort(varsp->fOwner);
1378 #else
1379 varsp->fDrawingEnvironment = (GrafPtr) GetWindowPort(varsp->fOwner);
1380 #endif
1381 varsp->fInDialogWindow = ( GetWindowKind(varsp->fOwner) == kDialogWindowKind );
1382 /* set up the user pane procedures */
1383 SetControlData(theControl, kControlEntireControl, kControlUserPaneDrawProcTag, sizeof(gTPDrawProc), &gTPDrawProc);
1384 SetControlData(theControl, kControlEntireControl, kControlUserPaneHitTestProcTag, sizeof(gTPHitProc), &gTPHitProc);
1385 SetControlData(theControl, kControlEntireControl, kControlUserPaneTrackingProcTag, sizeof(gTPTrackProc), &gTPTrackProc);
1386 SetControlData(theControl, kControlEntireControl, kControlUserPaneIdleProcTag, sizeof(gTPIdleProc), &gTPIdleProc);
1387 SetControlData(theControl, kControlEntireControl, kControlUserPaneKeyDownProcTag, sizeof(gTPKeyProc), &gTPKeyProc);
1388 SetControlData(theControl, kControlEntireControl, kControlUserPaneActivateProcTag, sizeof(gTPActivateProc), &gTPActivateProc);
1389 SetControlData(theControl, kControlEntireControl, kControlUserPaneFocusProcTag, sizeof(gTPFocusProc), &gTPFocusProc);
1390 /* calculate the rectangles used by the control */
1391 GetControlBounds(theControl, &bounds);
1392 SetRect(&varsp->fRFocusOutline, bounds.left, bounds.top, bounds.right, bounds.bottom);
1393 SetRect(&varsp->fRTextOutline, bounds.left, bounds.top, bounds.right, bounds.bottom);
1394 SetRect(&varsp->fRTextArea, bounds.left, bounds.top, bounds.right, bounds.bottom);
1395 /* calculate the background region for the text. In this case, it's kindof
1396 and irregular region because we're setting the scroll bar a little ways inside
1397 of the text area. */
1398 RectRgn((varsp->fTextBackgroundRgn = NewRgn()), &varsp->fRTextOutline);
1399
1400 /* set up the drawing environment */
1401 SetPort(varsp->fDrawingEnvironment);
1402
1403 /* create the new edit field */
1404 TXNNewObject(NULL, varsp->fOwner, &varsp->fRTextArea,
1405 kTXNWantVScrollBarMask | kTXNAlwaysWrapAtViewEdgeMask,
1406 kTXNTextEditStyleFrameType,
1407 kTXNTextensionFile,
1408 kTXNSystemDefaultEncoding,
1409 &varsp->fTXNRec, &varsp->fTXNFrame, (TXNObjectRefcon) tpvars);
1410
1411 /* set the field's background */
1412 tback.bgType = kTXNBackgroundTypeRGB;
1413 tback.bg.color = rgbWhite;
1414 TXNSetBackground( varsp->fTXNRec, &tback);
1415
1416 /* install our focus advance override routine */
1417 #if TARGET_CARBON
1418 varsp->handlerUPP = NewEventHandlerUPP(FocusAdvanceOverride);
1419 err = InstallWindowEventHandler( varsp->fOwner, varsp->handlerUPP,
1420 kMLTEEventCount, gMLTEEvents, tpvars, &varsp->handlerRef );
1421 #endif
1422 /* unlock our storage */
1423 HUnlock((Handle) tpvars);
1424 /* perform final activations and setup for our text field. Here,
1425 we assume that the window is going to be the 'active' window. */
1426 TPActivatePaneText(tpvars, varsp->fIsActive && varsp->fInFocus);
1427 /* all done */
1428 return noErr;
1429 }
1430
1431
1432
1433 /* mUPCloseControl deallocates all of the structures allocated
1434 by mUPOpenControl. */
1435 OSStatus mUPCloseControl(ControlHandle theControl) {
1436 STPTextPaneVars **tpvars;
1437 /* set up locals */
1438 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
1439 /* release our sub records */
1440 TXNDeleteObject((**tpvars).fTXNRec);
1441 /* remove our focus advance override */
1442 RemoveEventHandler((**tpvars).handlerRef);
1443 DisposeEventHandlerUPP((**tpvars).handlerUPP);
1444 /* delete our private storage */
1445 DisposeHandle((Handle) tpvars);
1446 /* zero the control reference */
1447 SetControlReference(theControl, 0);
1448 return noErr;
1449 }
1450
1451
1452
1453
1454 /* mUPSetText replaces the contents of the selection with the unicode
1455 text described by the text and count parameters:.
1456 text = pointer to unicode text buffer
1457 count = number of bytes in the buffer. */
1458 OSStatus mUPSetText(ControlHandle theControl, char* text, long count) {
1459 STPTextPaneVars **tpvars;
1460 /* set up locals */
1461 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
1462 /* set the text in the record */
1463 return TXNSetData( (**tpvars).fTXNRec, kTXNUnicodeTextData, text, count,
1464 kTXNUseCurrentSelection, kTXNUseCurrentSelection);
1465
1466 return noErr;
1467 }
1468
1469
1470 /* mUPSetSelection sets the text selection and autoscrolls the text view
1471 so either the cursor or the selction is in the view. */
1472 void mUPSetSelection(ControlHandle theControl, long selStart, long selEnd) {
1473 STPTextPaneVars **tpvars;
1474 /* set up our locals */
1475 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
1476 /* and our drawing environment as the operation
1477 may force a redraw in the text area. */
1478 SetPort((**tpvars).fDrawingEnvironment);
1479 /* change the selection */
1480 TXNSetSelection( (**tpvars).fTXNRec, selStart, selEnd);
1481 }
1482
1483
1484
1485
1486
1487 /* mUPGetText returns the current text data being displayed inside of
1488 the mUPControl. When noErr is returned, *theText contain a new
1489 handle containing all of the Unicode text copied from the current
1490 selection. It is the caller's responsibiliby to dispose of this handle. */
1491 OSStatus mUPGetText(ControlHandle theControl, Handle *theText) {
1492 STPTextPaneVars **tpvars;
1493 OSStatus err;
1494 /* set up locals */
1495 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
1496 /* extract the text from the record */
1497 err = TXNGetData( (**tpvars).fTXNRec, kTXNUseCurrentSelection, kTXNUseCurrentSelection, theText);
1498 /* all done */
1499 return err;
1500 }
1501
1502
1503
1504 /* mUPCreateControl creates a new user pane control and then it passes it
1505 to mUPOpenControl to initialize it as a scrolling text user pane control. */
1506 OSStatus mUPCreateControl(WindowPtr theWindow, Rect *bounds, ControlHandle *theControl) {
1507 short featurSet;
1508 /* the following feature set can be specified in CNTL resources by using
1509 the value 1214. When creating a user pane control, we pass this value
1510 in the 'value' parameter. */
1511 featurSet = kControlSupportsEmbedding | kControlSupportsFocus | kControlWantsIdle
1512 | kControlWantsActivate | kControlHandlesTracking | kControlHasSpecialBackground
1513 | kControlGetsFocusOnClick | kControlSupportsLiveFeedback;
1514 /* create the control */
1515 *theControl = NewControl(theWindow, bounds, "\p", true, featurSet, 0, featurSet, kControlUserPaneProc, 0);
1516 /* set up the mUP specific features and data */
1517 mUPOpenControl(*theControl);
1518 /* all done.... */
1519 return noErr;
1520 }
1521
1522
1523 /* mUPDisposeControl calls mUPCloseControl and then it calls DisposeControl. */
1524 OSStatus mUPDisposeControl(ControlHandle theControl) {
1525 /* deallocate the mUP specific data */
1526 mUPCloseControl(theControl);
1527 /* deallocate the user pane control itself */
1528 DisposeControl(theControl);
1529 return noErr;
1530 }
1531
1532
1533
1534
1535 /* IsmUPControl returns true if theControl is not NULL
1536 and theControl refers to a mUP Control. */
1537 Boolean IsmUPControl(ControlHandle theControl) {
1538 Size theSize;
1539 ControlUserPaneFocusUPP localFocusProc;
1540 /* a NULL control is not a mUP control */
1541 if (theControl == NULL) return false;
1542 /* check if the control is using our focus procedure */
1543 theSize = sizeof(localFocusProc);
1544 if (GetControlData(theControl, kControlEntireControl, kControlUserPaneFocusProcTag,
1545 sizeof(localFocusProc), &localFocusProc, &theSize) != noErr) return false;
1546 if (localFocusProc != gTPFocusProc) return false;
1547 /* all tests passed, it's a mUP control */
1548 return true;
1549 }
1550
1551
1552 /* mUPDoEditCommand performs the editing command specified
1553 in the editCommand parameter. The mUPControl's text
1554 and scroll bar are redrawn and updated as necessary. */
1555 void mUPDoEditCommand(ControlHandle theControl, short editCommand) {
1556 STPTextPaneVars **tpvars;
1557 /* set up our locals */
1558 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
1559 /* and our drawing environment as the operation
1560 may force a redraw in the text area. */
1561 SetPort((**tpvars).fDrawingEnvironment);
1562 /* perform the editing command */
1563 switch (editCommand) {
1564 case kmUPCut:
1565 ClearCurrentScrap();
1566 TXNCut((**tpvars).fTXNRec);
1567 TXNConvertToPublicScrap();
1568 break;
1569 case kmUPCopy:
1570 ClearCurrentScrap();
1571 TXNCopy((**tpvars).fTXNRec);
1572 TXNConvertToPublicScrap();
1573 break;
1574 case kmUPPaste:
1575 TXNConvertFromPublicScrap();
1576 TXNPaste((**tpvars).fTXNRec);
1577 break;
1578 case kmUPClear:
1579 TXNClear((**tpvars).fTXNRec);
1580 break;
1581 }
1582 }
1583
1584
1585
1586
1587 /* mUPGetContents returns the entire contents of the control including the text
1588 and the formatting information. */
1589 OSStatus mUPGetContents(ControlHandle theControl, Handle *theContents) {
1590 STPTextPaneVars **tpvars;
1591 OSStatus err;
1592 short vRefNum;
1593 long dirID;
1594 FSSpec tspec;
1595 short trefnum;
1596 Boolean texists;
1597 long bytecount;
1598 Handle localdata;
1599 /* set up locals */
1600 trefnum = 0;
1601 texists = false;
1602 localdata = NULL;
1603 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
1604 if (theContents == NULL) return paramErr;
1605 /* create a temporary file */
1606 err = FindFolder(kOnSystemDisk, kTemporaryFolderType, true, &vRefNum, &dirID);
1607 if (err != noErr) goto bail;
1608 FSMakeFSSpec(vRefNum, dirID, "\pmUPGetContents", &tspec);
1609 err = FSpCreate(&tspec, 'trsh', 'trsh', smSystemScript);
1610 if (err != noErr) goto bail;
1611 texists = true;
1612 /* open the file */
1613 err = FSpOpenDF(&tspec, fsRdWrPerm, &trefnum);
1614 if (err != noErr) goto bail;
1615 /* save the data */
1616 err = TXNSave( (**tpvars).fTXNRec, kTXNTextensionFile, 0, kTXNSystemDefaultEncoding, &tspec, trefnum, 0);
1617 if (err != noErr) goto bail;
1618 /* get the file length and set the position */
1619 err = GetEOF(trefnum, &bytecount);
1620 if (err != noErr) goto bail;
1621 err = SetFPos(trefnum, fsFromStart, 0);
1622 if (err != noErr) goto bail;
1623 /* copy the data fork to a handle */
1624 localdata = NewHandle(bytecount);
1625 if (localdata == NULL) { err = memFullErr; goto bail; }
1626 HLock(localdata);
1627 err = FSRead(trefnum, &bytecount, *localdata);
1628 HUnlock(localdata);
1629 if (err != noErr) goto bail;
1630 /* store result */
1631 *theContents = localdata;
1632 /* clean up */
1633 FSClose(trefnum);
1634 FSpDelete(&tspec);
1635 /* all done */
1636 return noErr;
1637 bail:
1638 if (trefnum != 0) FSClose(trefnum);
1639 if (texists) FSpDelete(&tspec);
1640 if (localdata != NULL) DisposeHandle(localdata);
1641 return err;
1642 }
1643
1644
1645
1646
1647 /* mUPSetContents replaces the contents of the selection with the data stored in the handle. */
1648 OSStatus mUPSetContents(ControlHandle theControl, Handle theContents) {
1649 STPTextPaneVars **tpvars;
1650 OSStatus err;
1651 short vRefNum;
1652 long dirID;
1653 FSSpec tspec;
1654 short trefnum;
1655 Boolean texists;
1656 long bytecount;
1657 char state;
1658 /* set up locals */
1659 trefnum = 0;
1660 texists = false;
1661 tpvars = (STPTextPaneVars **) GetControlReference(theControl);
1662 if (theContents == NULL) return paramErr;
1663 /* create a temporary file */
1664 err = FindFolder(kOnSystemDisk, kTemporaryFolderType, true, &vRefNum, &dirID);
1665 if (err != noErr) goto bail;
1666 FSMakeFSSpec(vRefNum, dirID, "\pmUPSetContents", &tspec);
1667 err = FSpCreate(&tspec, 'trsh', 'trsh', smSystemScript);
1668 if (err != noErr) goto bail;
1669 texists = true;
1670 /* open the file */
1671 err = FSpOpenDF(&tspec, fsRdWrPerm, &trefnum);
1672 if (err != noErr) goto bail;
1673 /* save the data to the temporary file */
1674 state = HGetState(theContents);
1675 HLock(theContents);
1676 bytecount = GetHandleSize(theContents);
1677 err = FSWrite(trefnum, &bytecount, *theContents);
1678 HSetState(theContents, state);
1679 if (err != noErr) goto bail;
1680 /* reset the file position */
1681 err = SetFPos(trefnum, fsFromStart, 0);
1682 if (err != noErr) goto bail;
1683 /* load the data */
1684 err = TXNSetDataFromFile((**tpvars).fTXNRec, trefnum, kTXNTextensionFile, bytecount, kTXNUseCurrentSelection, kTXNUseCurrentSelection);
1685 if (err != noErr) goto bail;
1686 /* clean up */
1687 FSClose(trefnum);
1688 FSpDelete(&tspec);
1689 /* all done */
1690 return noErr;
1691 bail:
1692 if (trefnum != 0) FSClose(trefnum);
1693 if (texists) FSpDelete(&tspec);
1694 return err;
1695 }
1696
1697 #if !USE_SHARED_LIBRARY
1698 IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
1699
1700 BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
1701 EVT_DROP_FILES(wxTextCtrl::OnDropFiles)
1702 EVT_CHAR(wxTextCtrl::OnChar)
1703 EVT_MENU(wxID_CUT, wxTextCtrl::OnCut)
1704 EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy)
1705 EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste)
1706 EVT_MENU(wxID_UNDO, wxTextCtrl::OnUndo)
1707 EVT_MENU(wxID_REDO, wxTextCtrl::OnRedo)
1708
1709 EVT_UPDATE_UI(wxID_CUT, wxTextCtrl::OnUpdateCut)
1710 EVT_UPDATE_UI(wxID_COPY, wxTextCtrl::OnUpdateCopy)
1711 EVT_UPDATE_UI(wxID_PASTE, wxTextCtrl::OnUpdatePaste)
1712 EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo)
1713 EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo)
1714 END_EVENT_TABLE()
1715 #endif
1716
1717 // Text item
1718 wxTextCtrl::wxTextCtrl()
1719 {
1720 }
1721
1722 const short kVerticalMargin = 2 ;
1723 const short kHorizontalMargin = 2 ;
1724
1725 bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id,
1726 const wxString& st,
1727 const wxPoint& pos,
1728 const wxSize& size, long style,
1729 const wxValidator& validator,
1730 const wxString& name)
1731 {
1732 // base initialization
1733 if ( !CreateBase(parent, id, pos, size, style, validator, name) )
1734 return FALSE;
1735
1736 wxSize mySize = size ;
1737 if ( UMAHasAppearance() )
1738 {
1739 m_macHorizontalBorder = 5 ; // additional pixels around the real control
1740 m_macVerticalBorder = 5 ;
1741 }
1742 else
1743 {
1744 m_macHorizontalBorder = 0 ; // additional pixels around the real control
1745 m_macVerticalBorder = 0 ;
1746 }
1747
1748
1749 Rect bounds ;
1750 Str255 title ;
1751
1752 if ( mySize.y == -1 )
1753 {
1754 if ( UMAHasAppearance() )
1755 mySize.y = 13 ;
1756 else
1757 mySize.y = 24 ;
1758
1759 mySize.y += 2 * m_macVerticalBorder ;
1760 }
1761
1762 MacPreControlCreate( parent , id , "" , pos , mySize ,style, validator , name , &bounds , title ) ;
1763
1764 if ( m_windowStyle & wxTE_MULTILINE )
1765 {
1766 wxASSERT_MSG( !(m_windowStyle & wxTE_PROCESS_ENTER),
1767 wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") );
1768
1769 m_windowStyle |= wxTE_PROCESS_ENTER;
1770 }
1771
1772
1773 if ( style & wxTE_PASSWORD )
1774 {
1775 m_macControl = ::NewControl( parent->GetMacRootWindow() , &bounds , "\p" , true , 0 , 0 , 1,
1776 kControlEditTextPasswordProc , (long) this ) ;
1777 }
1778 else
1779 {
1780 if ( mUPCreateControl(parent->GetMacRootWindow(), &bounds, &m_macControl) != noErr )
1781 return FALSE ;
1782 }
1783 MacPostControlCreate() ;
1784
1785 wxString value ;
1786
1787 if( wxApp::s_macDefaultEncodingIsPC )
1788 value = wxMacMakeMacStringFromPC( st ) ;
1789 else
1790 value = st ;
1791
1792 if ( style & wxTE_PASSWORD )
1793 {
1794 ::SetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ;
1795 }
1796 else
1797 {
1798 STPTextPaneVars **tpvars;
1799 /* set up locals */
1800 tpvars = (STPTextPaneVars **) GetControlReference(m_macControl);
1801 /* set the text in the record */
1802 TXNSetData( (**tpvars).fTXNRec, kTXNTextData, (const char*)value, value.Length(),
1803 kTXNStartOffset, kTXNEndOffset);
1804 }
1805
1806 return TRUE;
1807 }
1808
1809 wxString wxTextCtrl::GetValue() const
1810 {
1811 Size actualsize;
1812 if ( m_windowStyle & wxTE_PASSWORD )
1813 {
1814 ::GetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 32767 , wxBuffer , &actualsize) ;
1815 }
1816 else
1817 {
1818 STPTextPaneVars **tpvars;
1819 OSStatus err;
1820 /* set up locals */
1821 tpvars = (STPTextPaneVars **) GetControlReference(m_macControl);
1822 /* extract the text from the record */
1823 Handle theText ;
1824 err = TXNGetDataEncoded( (**tpvars).fTXNRec, kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData );
1825 /* all done */
1826 if ( err )
1827 {
1828 actualsize = 0 ;
1829 }
1830 else
1831 {
1832 actualsize = GetHandleSize( theText ) ;
1833 strncpy( wxBuffer , *theText , actualsize ) ;
1834 DisposeHandle( theText ) ;
1835 }
1836 }
1837 wxBuffer[actualsize] = 0 ;
1838 if( wxApp::s_macDefaultEncodingIsPC )
1839 return wxMacMakePCStringFromMac( wxBuffer ) ;
1840 else
1841 return wxString(wxBuffer);
1842 }
1843
1844 void wxTextCtrl::GetSelection(long* from, long* to) const
1845 {
1846 if ( m_windowStyle & wxTE_PASSWORD )
1847 {
1848 ControlEditTextSelectionRec selection ;
1849 TEHandle teH ;
1850 long size ;
1851
1852 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
1853
1854 *from = (**teH).selStart;
1855 *to = (**teH).selEnd;
1856 }
1857 else
1858 {
1859 STPTextPaneVars **tpvars;
1860
1861 /* set up locals */
1862 tpvars = (STPTextPaneVars **) GetControlReference(m_macControl);
1863
1864 TXNGetSelection( (**tpvars).fTXNRec , (TXNOffset*) from , (TXNOffset*) to ) ;
1865
1866 }
1867 }
1868
1869 void wxTextCtrl::SetValue(const wxString& st)
1870 {
1871 wxString value ;
1872
1873 if( wxApp::s_macDefaultEncodingIsPC )
1874 value = wxMacMakeMacStringFromPC( st ) ;
1875 else
1876 value = st ;
1877 if ( m_windowStyle & wxTE_PASSWORD )
1878 {
1879 ::SetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , value.Length() , (char*) ((const char*)value) ) ;
1880 }
1881 else
1882 {
1883 STPTextPaneVars **tpvars;
1884 /* set up locals */
1885 tpvars = (STPTextPaneVars **) GetControlReference(m_macControl);
1886 /* set the text in the record */
1887 TXNSetData( (**tpvars).fTXNRec, kTXNTextData, (const char*)value, value.Length(),
1888 kTXNStartOffset, kTXNEndOffset);
1889 }
1890 WindowRef window = GetMacRootWindow() ;
1891 if ( window )
1892 {
1893 wxWindow* win = wxFindWinFromMacWindow( window ) ;
1894 if ( win )
1895 {
1896 wxMacDrawingHelper help( win ) ;
1897 // the mac control manager always assumes to have the origin at 0,0
1898 SetOrigin( 0 , 0 ) ;
1899
1900 bool hasTabBehind = false ;
1901 wxWindow* parent = GetParent() ;
1902 while ( parent )
1903 {
1904 if( parent->MacGetWindowData() )
1905 {
1906 UMASetThemeWindowBackground( win->MacGetWindowData()->m_macWindow , kThemeBrushDialogBackgroundActive , false ) ;
1907 break ;
1908 }
1909
1910 if( parent->IsKindOf( CLASSINFO( wxNotebook ) ) || parent->IsKindOf( CLASSINFO( wxTabCtrl ) ))
1911 {
1912 if ( ((wxControl*)parent)->GetMacControl() )
1913 SetUpControlBackground( ((wxControl*)parent)->GetMacControl() , -1 , true ) ;
1914 break ;
1915 }
1916
1917 parent = parent->GetParent() ;
1918 }
1919
1920 UMADrawControl( m_macControl ) ;
1921 UMASetThemeWindowBackground( win->MacGetWindowData()->m_macWindow , win->MacGetWindowData()->m_macWindowBackgroundTheme , false ) ;
1922 }
1923 }
1924 }
1925
1926 // Clipboard operations
1927 void wxTextCtrl::Copy()
1928 {
1929 if (CanCopy())
1930 {
1931 if ( m_windowStyle & wxTE_PASSWORD )
1932 {
1933 TEHandle teH ;
1934 long size ;
1935
1936 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
1937 TECopy( teH ) ;
1938 ClearCurrentScrap();
1939 TEToScrap() ;
1940 }
1941 else
1942 {
1943 mUPDoEditCommand( m_macControl , kmUPCopy ) ;
1944 }
1945 }
1946 }
1947
1948 void wxTextCtrl::Cut()
1949 {
1950 if (CanCut())
1951 {
1952 if ( m_windowStyle & wxTE_PASSWORD )
1953 {
1954 TEHandle teH ;
1955 long size ;
1956
1957 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
1958 TECut( teH ) ;
1959 ClearCurrentScrap();
1960 TEToScrap() ;
1961 // MacInvalidateControl() ;
1962 }
1963 else
1964 {
1965 mUPDoEditCommand( m_macControl , kmUPCut ) ;
1966 }
1967 }
1968 }
1969
1970 void wxTextCtrl::Paste()
1971 {
1972 if (CanPaste())
1973 {
1974 if ( m_windowStyle & wxTE_PASSWORD )
1975 {
1976 TEHandle teH ;
1977 long size ;
1978
1979 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
1980 TEFromScrap() ;
1981 TEPaste( teH ) ;
1982 WindowRef window = GetMacRootWindow() ;
1983 if ( window )
1984 {
1985 wxWindow* win = wxFindWinFromMacWindow( window ) ;
1986 if ( win )
1987 {
1988 wxMacDrawingHelper help( win ) ;
1989 // the mac control manager always assumes to have the origin at 0,0
1990 SetOrigin( 0 , 0 ) ;
1991
1992 bool hasTabBehind = false ;
1993 wxWindow* parent = GetParent() ;
1994 while ( parent )
1995 {
1996 if( parent->MacGetWindowData() )
1997 {
1998 ::SetThemeWindowBackground( win->MacGetWindowData()->m_macWindow , kThemeBrushDialogBackgroundActive , false ) ;
1999 break ;
2000 }
2001
2002 if( parent->IsKindOf( CLASSINFO( wxNotebook ) ) || parent->IsKindOf( CLASSINFO( wxTabCtrl ) ))
2003 {
2004 if ( ((wxControl*)parent)->GetMacControl() )
2005 SetUpControlBackground( ((wxControl*)parent)->GetMacControl() , -1 , true ) ;
2006 break ;
2007 }
2008
2009 parent = parent->GetParent() ;
2010 }
2011
2012 UMADrawControl( m_macControl ) ;
2013 ::SetThemeWindowBackground( win->MacGetWindowData()->m_macWindow , win->MacGetWindowData()->m_macWindowBackgroundTheme , false ) ;
2014 }
2015 }
2016 }
2017 else
2018 {
2019 mUPDoEditCommand( m_macControl , kmUPPaste ) ;
2020 }
2021 }
2022 }
2023
2024 bool wxTextCtrl::CanCopy() const
2025 {
2026 // Can copy if there's a selection
2027 long from, to;
2028 GetSelection(& from, & to);
2029 return (from != to);
2030 }
2031
2032 bool wxTextCtrl::CanCut() const
2033 {
2034 // Can cut if there's a selection
2035 long from, to;
2036 GetSelection(& from, & to);
2037 return (from != to);
2038 }
2039
2040 bool wxTextCtrl::CanPaste() const
2041 {
2042 if (!IsEditable())
2043 return FALSE;
2044
2045 long offset ;
2046 #if TARGET_CARBON
2047 OSStatus err = noErr;
2048 ScrapRef scrapRef;
2049
2050 err = GetCurrentScrap( &scrapRef );
2051 if ( err != noTypeErr && err != memFullErr )
2052 {
2053 ScrapFlavorFlags flavorFlags;
2054 Size byteCount;
2055
2056 if (( err = GetScrapFlavorFlags( scrapRef, 'TEXT', &flavorFlags )) == noErr)
2057 {
2058 if (( err = GetScrapFlavorSize( scrapRef, 'TEXT', &byteCount )) == noErr)
2059 {
2060 return TRUE ;
2061 }
2062 }
2063 }
2064 return FALSE;
2065
2066 #else
2067 if ( GetScrap( NULL , 'TEXT' , &offset ) > 0 )
2068 {
2069 return TRUE ;
2070 }
2071 #endif
2072 return FALSE ;
2073 }
2074
2075 void wxTextCtrl::SetEditable(bool editable)
2076 {
2077 if ( editable )
2078 UMAActivateControl( m_macControl ) ;
2079 else
2080 UMADeactivateControl( m_macControl ) ;
2081 }
2082
2083 void wxTextCtrl::SetInsertionPoint(long pos)
2084 {
2085 SetSelection( pos , pos ) ;
2086 }
2087
2088 void wxTextCtrl::SetInsertionPointEnd()
2089 {
2090 long pos = GetLastPosition();
2091 SetInsertionPoint(pos);
2092 }
2093
2094 long wxTextCtrl::GetInsertionPoint() const
2095 {
2096 long begin,end ;
2097 GetSelection( &begin , &end ) ;
2098 return begin ;
2099 }
2100
2101 long wxTextCtrl::GetLastPosition() const
2102 {
2103 if ( m_windowStyle & wxTE_PASSWORD )
2104 {
2105
2106 ControlEditTextSelectionRec selection ;
2107 TEHandle teH ;
2108 long size ;
2109
2110 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
2111
2112 // ::GetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection , &size ) ;
2113 return (**teH).teLength ;
2114 }
2115 else
2116 {
2117 STPTextPaneVars** tpvars = (STPTextPaneVars **) GetControlReference(m_macControl);
2118
2119 int actualsize = 0 ;
2120 Handle theText ;
2121 OSErr err = TXNGetDataEncoded( (**tpvars).fTXNRec, kTXNStartOffset, kTXNEndOffset, &theText , kTXNTextData );
2122 /* all done */
2123 if ( err )
2124 {
2125 actualsize = 0 ;
2126 }
2127 else
2128 {
2129 actualsize = GetHandleSize( theText ) ;
2130 DisposeHandle( theText ) ;
2131 }
2132 return actualsize ;
2133 }
2134 }
2135
2136 void wxTextCtrl::Replace(long from, long to, const wxString& value)
2137 {
2138 if ( m_windowStyle & wxTE_PASSWORD )
2139 {
2140 TEHandle teH ;
2141 long size ;
2142
2143 ControlEditTextSelectionRec selection ;
2144
2145 selection.selStart = from ;
2146 selection.selEnd = to ;
2147 ::SetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
2148 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
2149 TESetSelect( from , to , teH ) ;
2150 TEDelete( teH ) ;
2151 TEInsert( value , value.Length() , teH ) ;
2152 }
2153 else
2154 {
2155 // TODO
2156 }
2157 Refresh() ;
2158 }
2159
2160 void wxTextCtrl::Remove(long from, long to)
2161 {
2162 if ( m_windowStyle & wxTE_PASSWORD )
2163 {
2164 TEHandle teH ;
2165 long size ;
2166
2167 ControlEditTextSelectionRec selection ;
2168
2169 selection.selStart = from ;
2170 selection.selEnd = to ;
2171 ::SetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
2172 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
2173 TEDelete( teH ) ;
2174 }
2175 else
2176 {
2177 //TODO
2178 }
2179 Refresh() ;
2180 }
2181
2182 void wxTextCtrl::SetSelection(long from, long to)
2183 {
2184 if ( m_windowStyle & wxTE_PASSWORD )
2185 {
2186 ControlEditTextSelectionRec selection ;
2187 TEHandle teH ;
2188 long size ;
2189
2190 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
2191
2192 selection.selStart = from ;
2193 selection.selEnd = to ;
2194
2195 ::SetControlData( m_macControl , 0, kControlEditTextSelectionTag , sizeof( selection ) , (char*) &selection ) ;
2196 TESetSelect( selection.selStart , selection.selEnd , teH ) ;
2197 }
2198 else
2199 {
2200 STPTextPaneVars **tpvars;
2201 /* set up our locals */
2202 tpvars = (STPTextPaneVars **) GetControlReference(m_macControl);
2203 /* and our drawing environment as the operation
2204 may force a redraw in the text area. */
2205 SetPort((**tpvars).fDrawingEnvironment);
2206 /* change the selection */
2207 TXNSetSelection( (**tpvars).fTXNRec, from, to);
2208 }
2209 }
2210
2211 bool wxTextCtrl::LoadFile(const wxString& file)
2212 {
2213 if ( wxTextCtrlBase::LoadFile(file) )
2214 {
2215 return TRUE;
2216 }
2217
2218 return FALSE;
2219 }
2220
2221 void wxTextCtrl::WriteText(const wxString& text)
2222 {
2223 wxString value ;
2224 if( wxApp::s_macDefaultEncodingIsPC )
2225 value = wxMacMakeMacStringFromPC( text ) ;
2226 else
2227 value = text ;
2228 if ( m_windowStyle & wxTE_PASSWORD )
2229 {
2230 TEHandle teH ;
2231 long size ;
2232
2233 ::GetControlData( m_macControl , 0, kControlEditTextTEHandleTag , sizeof( TEHandle ) , (char*) &teH , &size ) ;
2234 TEInsert( value , value.Length() , teH ) ;
2235 }
2236 else
2237 {
2238 STPTextPaneVars **tpvars;
2239 /* set up locals */
2240 tpvars = (STPTextPaneVars **) GetControlReference(m_macControl);
2241 /* set the text in the record */
2242 TXNSetData( (**tpvars).fTXNRec, kTXNTextData, (const char*)value, value.Length(),
2243 kTXNUseCurrentSelection, kTXNUseCurrentSelection);
2244 }
2245 Refresh() ;
2246 }
2247
2248 void wxTextCtrl::AppendText(const wxString& text)
2249 {
2250 SetInsertionPointEnd();
2251 WriteText(text);
2252 }
2253
2254 void wxTextCtrl::Clear()
2255 {
2256 if ( m_windowStyle & wxTE_PASSWORD )
2257 {
2258
2259 ::SetControlData( m_macControl, 0, ( m_windowStyle & wxTE_PASSWORD ) ? kControlEditTextPasswordTag : kControlEditTextTextTag , 0 , (char*) ((const char*)NULL) ) ;
2260 }
2261 else
2262 {
2263 mUPDoEditCommand( m_macControl , kmUPClear) ;
2264 }
2265 Refresh() ;
2266 }
2267
2268 bool wxTextCtrl::IsModified() const
2269 {
2270 return TRUE;
2271 }
2272
2273 bool wxTextCtrl::IsEditable() const
2274 {
2275 return IsEnabled();
2276 }
2277
2278 bool wxTextCtrl::AcceptsFocus() const
2279 {
2280 // we don't want focus if we can't be edited
2281 return IsEditable() && wxControl::AcceptsFocus();
2282 }
2283
2284 wxSize wxTextCtrl::DoGetBestSize() const
2285 {
2286 int wText = 100 ;
2287
2288 int hText ;
2289 if ( UMAHasAppearance() )
2290 hText = 13 ;
2291 else
2292 hText = 24 ;
2293 hText += 2 * m_macHorizontalBorder ;
2294 /*
2295 int cx, cy;
2296 wxGetCharSize(GetHWND(), &cx, &cy, &GetFont());
2297
2298 int wText = DEFAULT_ITEM_WIDTH;
2299
2300 int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
2301
2302 return wxSize(wText, hText);
2303 */
2304 if ( m_windowStyle & wxTE_MULTILINE )
2305 {
2306 hText *= wxMin(GetNumberOfLines(), 5);
2307 }
2308 //else: for single line control everything is ok
2309 return wxSize(wText, hText);
2310 }
2311
2312 // ----------------------------------------------------------------------------
2313 // Undo/redo
2314 // ----------------------------------------------------------------------------
2315
2316 void wxTextCtrl::Undo()
2317 {
2318 if (CanUndo())
2319 {
2320 }
2321 }
2322
2323 void wxTextCtrl::Redo()
2324 {
2325 if (CanRedo())
2326 {
2327 }
2328 }
2329
2330 bool wxTextCtrl::CanUndo() const
2331 {
2332 return FALSE ;
2333 }
2334
2335 bool wxTextCtrl::CanRedo() const
2336 {
2337 return FALSE ;
2338 }
2339
2340 // Makes 'unmodified'
2341 void wxTextCtrl::DiscardEdits()
2342 {
2343 // TODO
2344 }
2345
2346 int wxTextCtrl::GetNumberOfLines() const
2347 {
2348 // TODO change this if possible to reflect real lines
2349 wxString content = GetValue() ;
2350
2351 int count = 1;
2352 for (int i = 0; i < content.Length() ; i++)
2353 {
2354 if (content[i] == '\r') count++;
2355 }
2356
2357 return count;
2358 }
2359
2360 long wxTextCtrl::XYToPosition(long x, long y) const
2361 {
2362 // TODO
2363 return 0;
2364 }
2365
2366 bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
2367 {
2368 return FALSE ;
2369 }
2370
2371 void wxTextCtrl::ShowPosition(long pos)
2372 {
2373 // TODO
2374 }
2375
2376 int wxTextCtrl::GetLineLength(long lineNo) const
2377 {
2378 // TODO change this if possible to reflect real lines
2379 wxString content = GetValue() ;
2380
2381 // Find line first
2382 int count = 0;
2383 for (int i = 0; i < content.Length() ; i++)
2384 {
2385 if (count == lineNo)
2386 {
2387 // Count chars in line then
2388 count = 0;
2389 for (int j = i; j < content.Length(); j++)
2390 {
2391 count++;
2392 if (content[j] == '\r') return count;
2393 }
2394
2395 return count;
2396 }
2397 if (content[i] == '\r') count++;
2398 }
2399 return 0;
2400 }
2401
2402 wxString wxTextCtrl::GetLineText(long lineNo) const
2403 {
2404 // TODO change this if possible to reflect real lines
2405 wxString content = GetValue() ;
2406
2407 // Find line first
2408 int count = 0;
2409 for (int i = 0; i < content.Length() ; i++)
2410 {
2411 if (count == lineNo)
2412 {
2413 // Add chars in line then
2414 wxString tmp("");
2415
2416 for (int j = i; j < content.Length(); j++)
2417 {
2418 if (content[j] == '\r')
2419 return tmp;
2420
2421 tmp += content[j];
2422 }
2423
2424 return tmp;
2425 }
2426 if (content[i] == '\r') count++;
2427 }
2428 return wxString("");
2429 }
2430
2431 /*
2432 * Text item
2433 */
2434
2435 void wxTextCtrl::Command(wxCommandEvent & event)
2436 {
2437 SetValue (event.GetString());
2438 ProcessCommand (event);
2439 }
2440
2441 void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event)
2442 {
2443 // By default, load the first file into the text window.
2444 if (event.GetNumberOfFiles() > 0)
2445 {
2446 LoadFile(event.GetFiles()[0]);
2447 }
2448 }
2449
2450 void wxTextCtrl::OnChar(wxKeyEvent& event)
2451 {
2452 switch ( event.KeyCode() )
2453 {
2454 case WXK_RETURN:
2455 if (m_windowStyle & wxPROCESS_ENTER)
2456 {
2457 wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId);
2458 event.SetEventObject( this );
2459 if ( GetEventHandler()->ProcessEvent(event) )
2460 return;
2461 }
2462 if ( !(m_windowStyle & wxTE_MULTILINE) )
2463 {
2464 wxWindow *parent = GetParent();
2465 while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL ) {
2466 parent = parent->GetParent() ;
2467 }
2468 if ( parent && parent->GetDefaultItem() )
2469 {
2470 wxButton *def = wxDynamicCast(parent->GetDefaultItem(),
2471 wxButton);
2472 if ( def && def->IsEnabled() )
2473 {
2474 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
2475 event.SetEventObject(def);
2476 def->Command(event);
2477 return ;
2478 }
2479 }
2480 }
2481 //else: multiline controls need Enter for themselves
2482
2483 break;
2484
2485 case WXK_TAB:
2486 // always produce navigation event - even if we process TAB
2487 // ourselves the fact that we got here means that the user code
2488 // decided to skip processing of this TAB - probably to let it
2489 // do its default job.
2490 {
2491 wxNavigationKeyEvent eventNav;
2492 eventNav.SetDirection(!event.ShiftDown());
2493 eventNav.SetWindowChange(event.ControlDown());
2494 eventNav.SetEventObject(this);
2495
2496 if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav) )
2497 return;
2498 event.Skip() ;
2499 return ;
2500 }
2501 break;
2502 }
2503
2504 EventRecord *ev = wxTheApp->MacGetCurrentEvent() ;
2505 short keycode ;
2506 short keychar ;
2507 keychar = short(ev->message & charCodeMask);
2508 keycode = short(ev->message & keyCodeMask) >> 8 ;
2509 UMAHandleControlKey( m_macControl , keycode , keychar , ev->modifiers ) ;
2510 if ( keychar >= 0x20 || event.KeyCode() == WXK_RETURN || event.KeyCode() == WXK_DELETE || event.KeyCode() == WXK_BACK)
2511 {
2512 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId);
2513 event.SetString( GetValue() ) ;
2514 event.SetEventObject( this );
2515 GetEventHandler()->ProcessEvent(event);
2516 }
2517
2518 }
2519
2520 // ----------------------------------------------------------------------------
2521 // standard handlers for standard edit menu events
2522 // ----------------------------------------------------------------------------
2523
2524 void wxTextCtrl::OnCut(wxCommandEvent& event)
2525 {
2526 Cut();
2527 }
2528
2529 void wxTextCtrl::OnCopy(wxCommandEvent& event)
2530 {
2531 Copy();
2532 }
2533
2534 void wxTextCtrl::OnPaste(wxCommandEvent& event)
2535 {
2536 Paste();
2537 }
2538
2539 void wxTextCtrl::OnUndo(wxCommandEvent& event)
2540 {
2541 Undo();
2542 }
2543
2544 void wxTextCtrl::OnRedo(wxCommandEvent& event)
2545 {
2546 Redo();
2547 }
2548
2549 void wxTextCtrl::OnUpdateCut(wxUpdateUIEvent& event)
2550 {
2551 event.Enable( CanCut() );
2552 }
2553
2554 void wxTextCtrl::OnUpdateCopy(wxUpdateUIEvent& event)
2555 {
2556 event.Enable( CanCopy() );
2557 }
2558
2559 void wxTextCtrl::OnUpdatePaste(wxUpdateUIEvent& event)
2560 {
2561 event.Enable( CanPaste() );
2562 }
2563
2564 void wxTextCtrl::OnUpdateUndo(wxUpdateUIEvent& event)
2565 {
2566 event.Enable( CanUndo() );
2567 }
2568
2569 void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
2570 {
2571 event.Enable( CanRedo() );
2572 }
2573
2574 #endif
2575
2576 #endif
2577 // wxUSE_TEXTCTRL