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