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