]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/combobxc.cpp
Prevent assert and crash if an attempt is made to make a bitmap with
[wxWidgets.git] / src / mac / carbon / combobxc.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/combobxc.cpp
3 // Purpose: wxComboBox class using HIView ComboBox
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id$
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #include "wx/combobox.h"
15
16 #ifndef WX_PRECOMP
17 #include "wx/button.h"
18 #include "wx/menu.h"
19 #endif
20
21 #include "wx/mac/uma.h"
22 #if TARGET_API_MAC_OSX
23 #ifndef __HIVIEW__
24 #include <HIToolbox/HIView.h>
25 #endif
26 #endif
27
28 IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl)
29
30 #if TARGET_API_MAC_OSX
31 #define USE_HICOMBOBOX 1 //use hi combobox define
32 #else
33 #define USE_HICOMBOBOX 0
34 #endif
35
36 static int nextPopUpMenuId = 1000;
37 MenuHandle NewUniqueMenu()
38 {
39 MenuHandle handle = NewMenu( nextPopUpMenuId , "\pMenu" );
40 nextPopUpMenuId++;
41 return handle;
42 }
43
44 #if USE_HICOMBOBOX
45 static const EventTypeSpec eventList[] =
46 {
47 { kEventClassTextField , kEventTextAccepted } ,
48 };
49
50 static pascal OSStatus wxMacComboBoxEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
51 {
52 OSStatus result = eventNotHandledErr;
53 wxComboBox* cb = (wxComboBox*) data;
54
55 wxMacCarbonEvent cEvent( event );
56
57 switch( cEvent.GetClass() )
58 {
59 case kEventClassTextField :
60 switch( cEvent.GetKind() )
61 {
62 case kEventTextAccepted :
63 {
64 wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, cb->GetId() );
65 event.SetInt( cb->GetSelection() );
66 event.SetString( cb->GetStringSelection() );
67 event.SetEventObject( cb );
68 cb->GetEventHandler()->ProcessEvent( event );
69 }
70 break;
71 default :
72 break;
73 }
74 break;
75 default :
76 break;
77 }
78
79
80 return result;
81 }
82
83 DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacComboBoxEventHandler )
84
85 #endif
86
87 // ----------------------------------------------------------------------------
88 // constants
89 // ----------------------------------------------------------------------------
90
91 // the margin between the text control and the choice
92 static const wxCoord MARGIN = 2;
93 #if TARGET_API_MAC_OSX
94 static const int POPUPWIDTH = 24;
95 #else
96 static const int POPUPWIDTH = 18;
97 #endif
98 static const int POPUPHEIGHT = 23;
99
100 // ----------------------------------------------------------------------------
101 // wxComboBoxText: text control forwards events to combobox
102 // ----------------------------------------------------------------------------
103
104 class wxComboBoxText : public wxTextCtrl
105 {
106 public:
107 wxComboBoxText( wxComboBox * cb )
108 : wxTextCtrl( cb , 1 )
109 {
110 m_cb = cb;
111 }
112
113 protected:
114 void OnChar( wxKeyEvent& event )
115 {
116 if ( event.GetKeyCode() == WXK_RETURN )
117 {
118 wxString value = GetValue();
119
120 if ( m_cb->GetCount() == 0 )
121 {
122 // make Enter generate "selected" event if there is only one item
123 // in the combobox - without it, it's impossible to select it at
124 // all!
125 wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
126 event.SetInt( 0 );
127 event.SetString( value );
128 event.SetEventObject( m_cb );
129 m_cb->GetEventHandler()->ProcessEvent( event );
130 }
131 else
132 {
133 // add the item to the list if it's not there yet
134 if ( m_cb->FindString(value) == wxNOT_FOUND )
135 {
136 m_cb->Append(value);
137 m_cb->SetStringSelection(value);
138
139 // and generate the selected event for it
140 wxCommandEvent event( wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
141 event.SetInt( m_cb->GetCount() - 1 );
142 event.SetString( value );
143 event.SetEventObject( m_cb );
144 m_cb->GetEventHandler()->ProcessEvent( event );
145 }
146
147 // This will invoke the dialog default action, such
148 // as the clicking the default button.
149
150 wxWindow *parent = GetParent();
151 while( parent && !parent->IsTopLevel() && parent->GetDefaultItem() == NULL ) {
152 parent = parent->GetParent();
153 }
154 if ( parent && parent->GetDefaultItem() )
155 {
156 wxButton *def = wxDynamicCast(parent->GetDefaultItem(),
157 wxButton);
158 if ( def && def->IsEnabled() )
159 {
160 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, def->GetId() );
161 event.SetEventObject(def);
162 def->Command(event);
163 return;
164 }
165 }
166
167 return;
168 }
169 }
170
171 event.Skip();
172 }
173 private:
174 wxComboBox *m_cb;
175
176 DECLARE_EVENT_TABLE()
177 };
178
179 BEGIN_EVENT_TABLE(wxComboBoxText, wxTextCtrl)
180 EVT_CHAR( wxComboBoxText::OnChar)
181 END_EVENT_TABLE()
182
183 class wxComboBoxChoice : public wxChoice
184 {
185 public:
186 wxComboBoxChoice(wxComboBox *cb, int style)
187 : wxChoice( cb , 1 )
188 {
189 m_cb = cb;
190 }
191
192 protected:
193 void OnChoice( wxCommandEvent& e )
194 {
195 wxString s = e.GetString();
196
197 m_cb->DelegateChoice( s );
198 wxCommandEvent event2(wxEVT_COMMAND_COMBOBOX_SELECTED, m_cb->GetId() );
199 event2.SetInt(m_cb->GetSelection());
200 event2.SetEventObject(m_cb);
201 event2.SetString(m_cb->GetStringSelection());
202 m_cb->ProcessCommand(event2);
203 }
204 virtual wxSize DoGetBestSize() const
205 {
206 wxSize sz = wxChoice::DoGetBestSize();
207 sz.x = POPUPWIDTH;
208 return sz;
209 }
210
211 private:
212 wxComboBox *m_cb;
213
214 DECLARE_EVENT_TABLE()
215 };
216
217 BEGIN_EVENT_TABLE(wxComboBoxChoice, wxChoice)
218 EVT_CHOICE(wxID_ANY, wxComboBoxChoice::OnChoice)
219 END_EVENT_TABLE()
220
221 wxComboBox::~wxComboBox()
222 {
223 // delete client objects
224 FreeData();
225
226 // delete the controls now, don't leave them alive even though they would
227 // still be eventually deleted by our parent - but it will be too late, the
228 // user code expects them to be gone now
229 if (m_text != NULL) {
230 delete m_text;
231 m_text = NULL;
232 }
233 if (m_choice != NULL) {
234 delete m_choice;
235 m_choice = NULL;
236 }
237 }
238
239
240 // ----------------------------------------------------------------------------
241 // geometry
242 // ----------------------------------------------------------------------------
243
244 wxSize wxComboBox::DoGetBestSize() const
245 {
246 #if USE_HICOMBOBOX
247 return wxControl::DoGetBestSize();
248 #else
249 wxSize size = m_choice->GetBestSize();
250
251 if ( m_text != NULL )
252 {
253 wxSize sizeText = m_text->GetBestSize();
254
255 size.x = POPUPWIDTH + sizeText.x + MARGIN;
256 }
257
258 return size;
259 #endif
260 }
261
262 void wxComboBox::DoMoveWindow(int x, int y, int width, int height) {
263 #if USE_HICOMBOBOX
264 wxControl::DoMoveWindow(x, y, width, height);
265 #else
266 height = POPUPHEIGHT;
267
268 wxControl::DoMoveWindow(x, y, width, height);
269
270 if ( m_text == NULL )
271 {
272 // we might not be fully constructed yet, therefore watch out...
273 if ( m_choice )
274 m_choice->SetSize(0, 0 , width, wxDefaultCoord);
275 }
276 else
277 {
278 wxCoord wText = width - POPUPWIDTH - MARGIN;
279 m_text->SetSize(0, 0, wText, height);
280 m_choice->SetSize(0 + wText + MARGIN, 0, POPUPWIDTH, wxDefaultCoord);
281 }
282 #endif
283 }
284
285
286
287 // ----------------------------------------------------------------------------
288 // operations forwarded to the subcontrols
289 // ----------------------------------------------------------------------------
290
291 bool wxComboBox::Enable(bool enable)
292 {
293 if ( !wxControl::Enable(enable) )
294 return false;
295
296 return true;
297 }
298
299 bool wxComboBox::Show(bool show)
300 {
301 if ( !wxControl::Show(show) )
302 return false;
303
304 return true;
305 }
306
307 void wxComboBox::SetFocus()
308 {
309 #if USE_HICOMBOBOX
310 wxControl::SetFocus();
311 #else
312 if ( m_text != NULL) {
313 m_text->SetFocus();
314 }
315 #endif
316 }
317
318
319 void wxComboBox::DelegateTextChanged( const wxString& value )
320 {
321 SetStringSelection( value );
322 }
323
324
325 void wxComboBox::DelegateChoice( const wxString& value )
326 {
327 SetStringSelection( value );
328 }
329
330
331 bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
332 const wxString& value,
333 const wxPoint& pos,
334 const wxSize& size,
335 const wxArrayString& choices,
336 long style,
337 const wxValidator& validator,
338 const wxString& name)
339 {
340 wxCArrayString chs( choices );
341
342 return Create( parent, id, value, pos, size, chs.GetCount(),
343 chs.GetStrings(), style, validator, name );
344 }
345
346
347 bool wxComboBox::Create(wxWindow *parent, wxWindowID id,
348 const wxString& value,
349 const wxPoint& pos,
350 const wxSize& size,
351 int n, const wxString choices[],
352 long style,
353 const wxValidator& validator,
354 const wxString& name)
355 {
356 m_text = NULL;
357 m_choice = NULL;
358 #if USE_HICOMBOBOX
359 m_macIsUserPane = false;
360 #endif
361 if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style ,
362 wxDefaultValidator, name) )
363 {
364 return false;
365 }
366 #if USE_HICOMBOBOX
367 Rect bounds = wxMacGetBoundsForControl( this , pos , size );
368 HIRect hiRect;
369
370 hiRect.origin.x = 20; //bounds.left;
371 hiRect.origin.y = 25; //bounds.top;
372 hiRect.size.width = 120;// bounds.right - bounds.left;
373 hiRect.size.height = 24;
374
375 //For some reason, this code causes the combo box not to be displayed at all.
376 //hiRect.origin.x = bounds.left;
377 //hiRect.origin.y = bounds.top;
378 //hiRect.size.width = bounds.right - bounds.left;
379 //hiRect.size.height = bounds.bottom - bounds.top;
380 //printf("left = %d, right = %d, top = %d, bottom = %d\n", bounds.left, bounds.right, bounds.top, bounds.bottom);
381 //printf("x = %d, y = %d, width = %d, height = %d\n", hibounds.origin.x, hibounds.origin.y, hibounds.size.width, hibounds.size.height);
382 m_peer = new wxMacControl(this);
383 verify_noerr( HIComboBoxCreate( &hiRect, CFSTR(""), NULL, NULL, kHIComboBoxStandardAttributes, m_peer->GetControlRefAddr() ) );
384
385
386 m_peer->SetMinimum( 0 );
387 m_peer->SetMaximum( 100);
388 if ( n > 0 )
389 m_peer->SetValue( 1 );
390
391 MacPostControlCreate(pos,size);
392
393 for ( int i = 0; i < n; i++ )
394 {
395 DoAppend( choices[ i ] );
396 }
397
398 HIViewSetVisible( m_peer->GetControlRef(), true );
399 SetSelection(0);
400 EventHandlerRef comboEventHandler;
401 InstallControlEventHandler( m_peer->GetControlRef(), GetwxMacComboBoxEventHandlerUPP(),
402 GetEventTypeCount(eventList), eventList, this,
403 (EventHandlerRef *)&comboEventHandler);
404 #else
405 m_choice = new wxComboBoxChoice(this, style );
406
407 m_choice = new wxComboBoxChoice(this, style );
408 m_choice->SetSizeHints( wxSize( POPUPWIDTH , POPUPHEIGHT ) );
409
410 wxSize csize = size;
411 if ( style & wxCB_READONLY )
412 {
413 m_text = NULL;
414 }
415 else
416 {
417 m_text = new wxComboBoxText(this);
418 if ( size.y == wxDefaultCoord ) {
419 csize.y = m_text->GetSize().y;
420 }
421 }
422
423 DoSetSize(pos.x, pos.y, csize.x, csize.y);
424
425 for ( int i = 0; i < n; i++ )
426 {
427 m_choice->DoAppend( choices[ i ] );
428 }
429 SetBestSize(csize); // Needed because it is a wxControlWithItems
430 #endif
431
432 return true;
433 }
434
435 wxString wxComboBox::GetValue() const
436 {
437 #if USE_HICOMBOBOX
438 CFStringRef myString;
439 HIComboBoxCopyTextItemAtIndex( m_peer->GetControlRef(), (CFIndex)GetSelection(), &myString );
440 return wxMacCFStringHolder( myString, m_font.GetEncoding() ).AsString();
441 #else
442 wxString result;
443
444 if ( m_text == NULL )
445 {
446 result = m_choice->GetString( m_choice->GetSelection() );
447 }
448 else
449 {
450 result = m_text->GetValue();
451 }
452
453 return result;
454 #endif
455 }
456
457 void wxComboBox::SetValue(const wxString& value)
458 {
459 #if USE_HICOMBOBOX
460
461 #else
462 int s = FindString (value);
463 if (s == wxNOT_FOUND && !HasFlag(wxCB_READONLY) )
464 {
465 m_choice->Append(value);
466 }
467 SetStringSelection( value );
468 #endif
469 }
470
471 // Clipboard operations
472 void wxComboBox::Copy()
473 {
474 if ( m_text != NULL )
475 {
476 m_text->Copy();
477 }
478 }
479
480 void wxComboBox::Cut()
481 {
482 if ( m_text != NULL )
483 {
484 m_text->Cut();
485 }
486 }
487
488 void wxComboBox::Paste()
489 {
490 if ( m_text != NULL )
491 {
492 m_text->Paste();
493 }
494 }
495
496 void wxComboBox::SetEditable(bool editable)
497 {
498 if ( ( m_text == NULL ) && editable )
499 {
500 m_text = new wxComboBoxText( this );
501 }
502 else if ( ( m_text != NULL ) && !editable )
503 {
504 delete m_text;
505 m_text = NULL;
506 }
507
508 int currentX, currentY;
509 GetPosition( &currentX, &currentY );
510
511 int currentW, currentH;
512 GetSize( &currentW, &currentH );
513
514 DoMoveWindow( currentX, currentY, currentW, currentH );
515 }
516
517 void wxComboBox::SetInsertionPoint(long pos)
518 {
519 // TODO
520 }
521
522 void wxComboBox::SetInsertionPointEnd()
523 {
524 // TODO
525 }
526
527 long wxComboBox::GetInsertionPoint() const
528 {
529 // TODO
530 return 0;
531 }
532
533 wxTextPos wxComboBox::GetLastPosition() const
534 {
535 // TODO
536 return 0;
537 }
538
539 void wxComboBox::Replace(long from, long to, const wxString& value)
540 {
541 // TODO
542 }
543
544 void wxComboBox::Remove(long from, long to)
545 {
546 // TODO
547 }
548
549 void wxComboBox::SetSelection(long from, long to)
550 {
551 // TODO
552 }
553
554 int wxComboBox::DoAppend(const wxString& item)
555 {
556 #if USE_HICOMBOBOX
557 CFIndex outIndex;
558 HIComboBoxAppendTextItem( m_peer->GetControlRef(), wxMacCFStringHolder( item, m_font.GetEncoding() ), &outIndex );
559 //SetControl32BitMaximum( m_peer->GetControlRef(), GetCount() );
560 return (int) outIndex;
561 #else
562 return m_choice->DoAppend( item );
563 #endif
564 }
565
566 int wxComboBox::DoInsert(const wxString& item, unsigned int pos)
567 {
568 #if USE_HICOMBOBOX
569 HIComboBoxInsertTextItemAtIndex( m_peer->GetControlRef(), (CFIndex)pos, wxMacCFStringHolder(item, m_font.GetEncoding()) );
570
571 //SetControl32BitMaximum( m_peer->GetControlRef(), GetCount() );
572
573 return pos;
574 #else
575 return m_choice->DoInsert( item , pos );
576 #endif
577 }
578
579 void wxComboBox::DoSetItemClientData(unsigned int n, void* clientData)
580 {
581 #if USE_HICOMBOBOX
582 return; //TODO
583 #else
584 return m_choice->DoSetItemClientData( n , clientData );
585 #endif
586 }
587
588 void* wxComboBox::DoGetItemClientData(unsigned int n) const
589 {
590 #if USE_HICOMBOBOX
591 return NULL; //TODO
592 #else
593 return m_choice->DoGetItemClientData( n );
594 #endif
595 }
596
597 void wxComboBox::DoSetItemClientObject(unsigned int n, wxClientData* clientData)
598 {
599 #if USE_HICOMBOBOX
600 return; //TODO
601 #else
602 return m_choice->DoSetItemClientObject( n , clientData );
603 #endif
604 }
605
606 wxClientData* wxComboBox::DoGetItemClientObject(unsigned int n) const
607 {
608 #if USE_HICOMBOBOX
609 return NULL;
610 #else
611 return m_choice->DoGetItemClientObject( n );
612 #endif
613 }
614
615 void wxComboBox::FreeData()
616 {
617 if (HasClientObjectData())
618 {
619 unsigned int count = GetCount();
620 for ( unsigned int n = 0; n < count; n++ )
621 {
622 SetClientObject( n, NULL );
623 }
624 }
625 }
626
627 unsigned int wxComboBox::GetCount() const {
628 #if USE_HICOMBOBOX
629 return (unsigned int) HIComboBoxGetItemCount( m_peer->GetControlRef() );
630 #else
631 return m_choice->GetCount();
632 #endif
633 }
634
635 void wxComboBox::Delete(unsigned int n)
636 {
637 #if USE_HICOMBOBOX
638 HIComboBoxRemoveItemAtIndex( m_peer->GetControlRef(), (CFIndex)n );
639 #else
640 // force client object deletion
641 if( HasClientObjectData() )
642 SetClientObject( n, NULL );
643 m_choice->Delete( n );
644 #endif
645 }
646
647 void wxComboBox::Clear()
648 {
649 FreeData();
650 #if USE_HICOMBOBOX
651 for ( CFIndex i = GetCount() - 1; i >= 0; ++ i )
652 verify_noerr( HIComboBoxRemoveItemAtIndex( m_peer->GetControlRef(), i ) );
653 m_peer->SetData<CFStringRef>(kHIComboBoxEditTextPart,kControlEditTextCFStringTag,CFSTR(""));
654 #else
655 m_choice->Clear();
656 #endif
657 }
658
659 int wxComboBox::GetSelection() const
660 {
661 #if USE_HICOMBOBOX
662 return FindString( GetStringSelection() );
663 #else
664 return m_choice->GetSelection();
665 #endif
666 }
667
668 void wxComboBox::SetSelection(int n)
669 {
670 #if USE_HICOMBOBOX
671 SetControl32BitValue( m_peer->GetControlRef() , n + 1 );
672 #else
673 m_choice->SetSelection( n );
674
675 if ( m_text != NULL )
676 {
677 m_text->SetValue(GetString(n));
678 }
679 #endif
680 }
681
682 int wxComboBox::FindString(const wxString& s, bool bCase) const
683 {
684 #if USE_HICOMBOBOX
685 for( unsigned int i = 0 ; i < GetCount() ; i++ )
686 {
687 if (GetString(i).IsSameAs(s, bCase) )
688 return i ;
689 }
690 return wxNOT_FOUND;
691 #else
692 return m_choice->FindString( s, bCase );
693 #endif
694 }
695
696 wxString wxComboBox::GetString(unsigned int n) const
697 {
698 #if USE_HICOMBOBOX
699 CFStringRef itemText;
700 HIComboBoxCopyTextItemAtIndex( m_peer->GetControlRef(), (CFIndex)n, &itemText );
701 return wxMacCFStringHolder(itemText).AsString();
702 #else
703 return m_choice->GetString( n );
704 #endif
705 }
706
707 wxString wxComboBox::GetStringSelection() const
708 {
709 #if USE_HICOMBOBOX
710 return wxMacCFStringHolder(m_peer->GetData<CFStringRef>(kHIComboBoxEditTextPart,kControlEditTextCFStringTag)).AsString();
711 #else
712 int sel = GetSelection ();
713 if (sel != wxNOT_FOUND)
714 return wxString(this->GetString((unsigned int)sel));
715 else
716 return wxEmptyString;
717 #endif
718 }
719
720 void wxComboBox::SetString(unsigned int n, const wxString& s)
721 {
722 #if USE_HICOMBOBOX
723 verify_noerr ( HIComboBoxInsertTextItemAtIndex( m_peer->GetControlRef(), (CFIndex) n,
724 wxMacCFStringHolder(s, m_font.GetEncoding()) ) );
725 verify_noerr ( HIComboBoxRemoveItemAtIndex( m_peer->GetControlRef(), (CFIndex) n + 1 ) );
726 #else
727 m_choice->SetString( n , s );
728 #endif
729 }
730
731 bool wxComboBox::IsEditable() const
732 {
733 #if USE_HICOMBOBOX
734 // TODO
735 return !HasFlag(wxCB_READONLY);
736 #else
737 return m_text != NULL && !HasFlag(wxCB_READONLY);
738 #endif
739 }
740
741 void wxComboBox::Undo()
742 {
743 #if USE_HICOMBOBOX
744 // TODO
745 #else
746 if (m_text != NULL)
747 m_text->Undo();
748 #endif
749 }
750
751 void wxComboBox::Redo()
752 {
753 #if USE_HICOMBOBOX
754 // TODO
755 #else
756 if (m_text != NULL)
757 m_text->Redo();
758 #endif
759 }
760
761 void wxComboBox::SelectAll()
762 {
763 #if USE_HICOMBOBOX
764 // TODO
765 #else
766 if (m_text != NULL)
767 m_text->SelectAll();
768 #endif
769 }
770
771 bool wxComboBox::CanCopy() const
772 {
773 #if USE_HICOMBOBOX
774 // TODO
775 return false;
776 #else
777 if (m_text != NULL)
778 return m_text->CanCopy();
779 else
780 return false;
781 #endif
782 }
783
784 bool wxComboBox::CanCut() const
785 {
786 #if USE_HICOMBOBOX
787 // TODO
788 return false;
789 #else
790 if (m_text != NULL)
791 return m_text->CanCut();
792 else
793 return false;
794 #endif
795 }
796
797 bool wxComboBox::CanPaste() const
798 {
799 #if USE_HICOMBOBOX
800 // TODO
801 return false;
802 #else
803 if (m_text != NULL)
804 return m_text->CanPaste();
805 else
806 return false;
807 #endif
808 }
809
810 bool wxComboBox::CanUndo() const
811 {
812 #if USE_HICOMBOBOX
813 // TODO
814 return false;
815 #else
816 if (m_text != NULL)
817 return m_text->CanUndo();
818 else
819 return false;
820 #endif
821 }
822
823 bool wxComboBox::CanRedo() const
824 {
825 #if USE_HICOMBOBOX
826 // TODO
827 return false;
828 #else
829 if (m_text != NULL)
830 return m_text->CanRedo();
831 else
832 return false;
833 #endif
834 }
835
836 wxInt32 wxComboBox::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) )
837 {
838 wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_SELECTED, m_windowId );
839 event.SetInt(GetSelection());
840 event.SetEventObject(this);
841 event.SetString(GetStringSelection());
842 ProcessCommand(event);
843 return noErr;
844 }