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