]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/tools/configtool/standalone/wxwin/packagesdlg.cpp
Cleanup CVS ipmorted branch
[karo-tx-redboot.git] / tools / src / tools / configtool / standalone / wxwin / packagesdlg.cpp
1 //####COPYRIGHTBEGIN####
2 //
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 //
6 // This program is part of the eCos host tools.
7 //
8 // This program is free software; you can redistribute it and/or modify it
9 // under the terms of the GNU General Public License as published by the Free
10 // Software Foundation; either version 2 of the License, or (at your option)
11 // any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16 // more details.
17 //
18 // You should have received a copy of the GNU General Public License along with
19 // this program; if not, write to the Free Software Foundation, Inc.,
20 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 //
22 // ----------------------------------------------------------------------------
23 //
24 //####COPYRIGHTEND####
25 // packages :
26 //
27 //===========================================================================
28 //#####DESCRIPTIONBEGIN####
29 //
30 // Author(s):   julians
31 // Contact(s):  julians
32 // Date:        2000/09/28
33 // Version:     $Id: packagesdlg.cpp,v 1.9 2001/12/14 17:34:03 julians Exp $
34 // Purpose:
35 // Description: Implementation file for ecPackagesDialog
36 // Requires:
37 // Provides:
38 // See also:
39 // Known bugs:
40 // Usage:
41 //
42 //####DESCRIPTIONEND####
43 //
44 //===========================================================================
45
46 // ============================================================================
47 // declarations
48 // ============================================================================
49
50 // ----------------------------------------------------------------------------
51 // headers
52 // ----------------------------------------------------------------------------
53 #ifdef __GNUG__
54 #pragma implementation "packagesdlg.h"
55 #endif
56
57 // Includes other headers for precompiled compilation
58 #include "ecpch.h"
59
60 #ifdef __BORLANDC__
61 #pragma hdrstop
62 #endif
63
64 #include "wx/cshelp.h"
65 #include "wx/valgen.h"
66 #include "wx/tokenzr.h"
67
68 #include "configtool.h"
69 #include "packagesdlg.h"
70 #include "configtooldoc.h"
71 #include "ecutils.h"
72
73 BEGIN_EVENT_TABLE(ecPackagesDialog, ecDialog)
74     EVT_BUTTON(wxID_OK, ecPackagesDialog::OnOK)
75     EVT_BUTTON(wxID_CANCEL, ecPackagesDialog::OnCancel)
76     EVT_BUTTON(ecID_PACKAGES_DIALOG_ADD, ecPackagesDialog::OnAdd)
77     EVT_BUTTON(ecID_PACKAGES_DIALOG_REMOVE, ecPackagesDialog::OnRemove)
78     EVT_LISTBOX_DCLICK(ecID_PACKAGES_DIALOG_AVAILABLE_LIST, ecPackagesDialog::OnDblClickListBox1)
79     EVT_LISTBOX_DCLICK(ecID_PACKAGES_DIALOG_USE_LIST, ecPackagesDialog::OnDblClickListBox2)
80     EVT_LISTBOX(ecID_PACKAGES_DIALOG_AVAILABLE_LIST, ecPackagesDialog::OnClickListBox1)
81     EVT_LISTBOX(ecID_PACKAGES_DIALOG_USE_LIST, ecPackagesDialog::OnClickListBox2)
82     EVT_LISTBOX(ecID_PACKAGES_DIALOG_VERSION, ecPackagesDialog::OnSelectVersion)
83     EVT_INIT_DIALOG(ecPackagesDialog::OnInitDialog)
84     EVT_BUTTON(ecID_PACKAGES_DIALOG_CLEAR, ecPackagesDialog::OnClearKeywords)
85     EVT_CHECKBOX(ecID_PACKAGES_DIALOG_OMIT_HARDWARE, ecPackagesDialog::OnClickOmitHardwarePackages)
86     EVT_CHECKBOX(ecID_PACKAGES_DIALOG_EXACT_MATCH, ecPackagesDialog::OnClickExactMatch)
87     EVT_TEXT(ecID_PACKAGES_DIALOG_KEYWORDS, ecPackagesDialog::OnUpdateKeywordText)
88     EVT_IDLE(ecPackagesDialog::OnIdle)
89 END_EVENT_TABLE()
90
91 // ----------------------------------------------------------------------------
92 // main frame
93 // ----------------------------------------------------------------------------
94
95 // Frame constructor
96 ecPackagesDialog::ecPackagesDialog(wxWindow* parent):
97 m_timer(this)
98 {
99     m_bHardwarePackageSelected = FALSE;
100     m_keywords = wxEmptyString;
101     m_updateLists = FALSE;
102     m_updateInterval = 600; // Milliseconds
103     wxStartTimer();
104     
105     SetExtraStyle(wxDIALOG_EX_CONTEXTHELP);
106     
107     ecDialog::Create(parent, ecID_PACKAGES_DIALOG, _("Packages"),
108         wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER);
109     
110     CreateControls(this);
111     
112     m_timer.Start(200);
113     
114     Centre(wxBOTH);
115 }
116
117 ecPackagesDialog::~ecPackagesDialog()
118 {
119     m_timer.Stop();
120 }
121
122 // TODO: implement wxLB_SORT style in wxGTK.
123 void ecPackagesDialog::CreateControls(wxWindow* parent)
124 {
125     wxSizer *item0 = new wxBoxSizer( wxVERTICAL );
126     
127     wxSizer *item1 = new wxBoxSizer( wxHORIZONTAL );
128     
129     wxSizer *item2 = new wxBoxSizer( wxVERTICAL );
130     
131     wxStaticText *item3 = new wxStaticText( parent, wxID_STATIC, _("Available &packages:"), wxDefaultPosition, wxDefaultSize, 0 );
132     item2->Add( item3, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
133     
134     wxString *strs4 = (wxString*) NULL;
135     wxListBox *item4 = new wxListBox( parent, ecID_PACKAGES_DIALOG_AVAILABLE_LIST, wxDefaultPosition, wxSize(230,190), 0, strs4, wxLB_SORT|wxLB_HSCROLL );
136     item2->Add( item4, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxBOTTOM, 5 );
137     
138     item1->Add( item2, 1, wxGROW|wxALIGN_CENTER_HORIZONTAL|wxALL, 0 );
139     
140     wxSizer *item5 = new wxBoxSizer( wxVERTICAL );
141     
142     wxButton *item6 = new wxButton( parent, ecID_PACKAGES_DIALOG_ADD, _("&Add >>"), wxDefaultPosition, wxDefaultSize, 0 );
143     item5->Add( item6, 0, wxALIGN_CENTRE|wxALL, 5 );
144     
145     wxButton *item7 = new wxButton( parent, ecID_PACKAGES_DIALOG_REMOVE, _("<< &Remove"), wxDefaultPosition, wxDefaultSize, 0 );
146     item5->Add( item7, 0, wxALIGN_CENTRE|wxALL, 5 );
147     
148     item1->Add( item5, 0, wxALIGN_CENTRE|wxALL, 0 );
149     
150     wxSizer *item8 = new wxBoxSizer( wxVERTICAL );
151     
152     wxStaticText *item9 = new wxStaticText( parent, wxID_STATIC, _("&Use these packages:"), wxDefaultPosition, wxDefaultSize, 0 );
153     item8->Add( item9, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
154     
155     wxString *strs10 = (wxString*) NULL;
156     wxListBox *item10 = new wxListBox( parent, ecID_PACKAGES_DIALOG_USE_LIST, wxDefaultPosition, wxSize(230,190), 0, strs10, wxLB_SORT|wxLB_HSCROLL );
157     item8->Add( item10, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxBOTTOM, 5 );
158     
159     item1->Add( item8, 1, wxGROW|wxALIGN_CENTER_HORIZONTAL|wxALL, 0 );
160     
161     item0->Add( item1, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
162     
163     wxStaticText *item11 = new wxStaticText( parent, wxID_STATIC, _("&Version:"), wxDefaultPosition, wxDefaultSize, 0 );
164     item0->Add( item11, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
165     
166     wxString *strs12 = (wxString*) NULL;
167     wxChoice *item12 = new wxChoice( parent, ecID_PACKAGES_DIALOG_VERSION, wxDefaultPosition, wxSize(100,-1), 0, strs12, 0 );
168     item0->Add( item12, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 10 );
169     
170     wxTextCtrl *item13 = new wxTextCtrl( parent, ecID_PACKAGES_DIALOG_DESCRIPTION, _(""), wxDefaultPosition, wxSize(80,110), wxTE_MULTILINE );
171     item0->Add( item13, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxBOTTOM, 10 );
172     
173     wxStaticText *item14 = new wxStaticText( parent, wxID_STATIC, _("&Keywords:"), wxDefaultPosition, wxDefaultSize, 0 );
174     item0->Add( item14, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
175     
176     wxSizer *item15 = new wxBoxSizer( wxHORIZONTAL );
177     
178     wxTextCtrl *item16 = new wxTextCtrl( parent, ecID_PACKAGES_DIALOG_KEYWORDS, _(""), wxDefaultPosition, wxSize(80,-1), 0 );
179     item15->Add( item16, 1, wxALIGN_CENTRE|wxALL, 5 );
180     
181     wxButton *item17 = new wxButton( parent, ecID_PACKAGES_DIALOG_CLEAR, _("C&lear"), wxDefaultPosition, wxDefaultSize, 0 );
182     item15->Add( item17, 0, wxALIGN_CENTRE|wxALL, 5 );
183     
184     item0->Add( item15, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
185     
186     wxSizer *item18 = new wxBoxSizer( wxHORIZONTAL );
187     
188     wxCheckBox *item19 = new wxCheckBox( parent, ecID_PACKAGES_DIALOG_OMIT_HARDWARE, _("&Omit hardware packages"), wxDefaultPosition, wxDefaultSize, 0 );
189     item18->Add( item19, 0, wxALIGN_CENTRE|wxALL, 5 );
190     
191     wxCheckBox *item20 = new wxCheckBox( parent, ecID_PACKAGES_DIALOG_EXACT_MATCH, _("&Match exactly"), wxDefaultPosition, wxDefaultSize, 0 );
192     item18->Add( item20, 0, wxALIGN_CENTRE|wxALL, 5 );
193     
194     item18->Add( 20, 20, 1, wxALIGN_CENTRE|wxALL, 5 );
195     
196     wxButton *item21 = new wxButton( parent, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0 );
197     item21->SetDefault();
198     item18->Add( item21, 0, wxALIGN_CENTRE|wxALL, 5 );
199     
200     wxButton *item22 = new wxButton( parent, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
201     item18->Add( item22, 0, wxALIGN_CENTRE|wxALL, 5 );
202     
203     item0->Add( item18, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxBOTTOM, 5 );
204     
205 #if 0
206     wxSizer *item0 = new wxBoxSizer( wxVERTICAL );
207     
208     wxSizer *item1 = new wxBoxSizer( wxHORIZONTAL );
209     
210     wxSizer *item2 = new wxBoxSizer( wxVERTICAL );
211     
212     wxStaticText *item3 = new wxStaticText( parent, wxID_STATIC, _("Available &packages:"), wxDefaultPosition, wxDefaultSize, 0 );
213     item2->Add( item3, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
214     
215     wxString *strs4 = (wxString*) NULL;
216     wxListBox *item4 = new wxListBox( parent, ecID_PACKAGES_DIALOG_AVAILABLE_LIST, wxDefaultPosition, wxSize(230,190), 0, strs4, wxLB_SORT|wxLB_HSCROLL );
217     item2->Add( item4, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxBOTTOM, 5 );
218     
219     item1->Add( item2, 1, wxGROW|wxALIGN_CENTER_HORIZONTAL|wxALL, 0 );
220     
221     wxSizer *item5 = new wxBoxSizer( wxVERTICAL );
222     
223     wxButton *item6 = new wxButton( parent, ecID_PACKAGES_DIALOG_ADD, _("&Add >>"), wxDefaultPosition, wxDefaultSize, 0 );
224     item5->Add( item6, 0, wxALIGN_CENTRE|wxALL, 5 );
225     
226     wxButton *item7 = new wxButton( parent, ecID_PACKAGES_DIALOG_REMOVE, _("<< &Remove"), wxDefaultPosition, wxDefaultSize, 0 );
227     item5->Add( item7, 0, wxALIGN_CENTRE|wxALL, 5 );
228     
229     item1->Add( item5, 0, wxALIGN_CENTRE|wxALL, 0 );
230     
231     wxSizer *item8 = new wxBoxSizer( wxVERTICAL );
232     
233     wxStaticText *item9 = new wxStaticText( parent, wxID_STATIC, _("&Use these packages:"), wxDefaultPosition, wxDefaultSize, 0 );
234     item8->Add( item9, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
235     
236     wxString *strs10 = (wxString*) NULL;
237     wxListBox *item10 = new wxListBox( parent, ecID_PACKAGES_DIALOG_USE_LIST, wxDefaultPosition, wxSize(230,190), 0, strs10, wxLB_SORT|wxLB_HSCROLL );
238     item8->Add( item10, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxBOTTOM, 5 );
239     
240     item1->Add( item8, 1, wxGROW|wxALIGN_CENTER_HORIZONTAL|wxALL, 0 );
241     
242     item0->Add( item1, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
243     
244     wxStaticText *item11 = new wxStaticText( parent, wxID_STATIC, _("&Version:"), wxDefaultPosition, wxDefaultSize, 0 );
245     item0->Add( item11, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
246     
247     wxString *strs12 = (wxString*) NULL;
248     wxChoice *item12 = new wxChoice( parent, ecID_PACKAGES_DIALOG_VERSION, wxDefaultPosition, wxSize(100,-1), 0, strs12, 0 );
249     item0->Add( item12, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 10 );
250     
251     wxTextCtrl *item13 = new wxTextCtrl( parent, ecID_PACKAGES_DIALOG_DESCRIPTION, _(""), wxDefaultPosition, wxSize(80,110), wxTE_MULTILINE );
252     item0->Add( item13, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxBOTTOM, 10 );
253     
254     wxStaticText *item14 = new wxStaticText( parent, wxID_STATIC, _("&Keywords:"), wxDefaultPosition, wxDefaultSize, 0 );
255     item0->Add( item14, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 10 );
256     
257     wxSizer *item15 = new wxBoxSizer( wxHORIZONTAL );
258     
259     wxTextCtrl *item16 = new wxTextCtrl( parent, ecID_PACKAGES_DIALOG_KEYWORDS, _(""), wxDefaultPosition, wxSize(80,-1), 0 );
260     item15->Add( item16, 1, wxALIGN_CENTRE|wxALL, 5 );
261     
262     wxButton *item17 = new wxButton( parent, ecID_PACKAGES_DIALOG_CLEAR, _("C&lear"), wxDefaultPosition, wxDefaultSize, 0 );
263     item15->Add( item17, 0, wxALIGN_CENTRE|wxALL, 5 );
264     
265     item0->Add( item15, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 5 );
266     
267     wxSizer *item18 = new wxBoxSizer( wxHORIZONTAL );
268     
269     wxCheckBox *item19 = new wxCheckBox( parent, ecID_PACKAGES_DIALOG_OMIT_HARDWARE, _("Omit hardware packages"), wxDefaultPosition, wxDefaultSize, 0 );
270     item18->Add( item19, 0, wxALIGN_CENTRE|wxALL, 5 );
271     
272     item18->Add( 20, 20, 1, wxALIGN_CENTRE|wxALL, 5 );
273     
274     wxButton *item20 = new wxButton( parent, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0 );
275     item20->SetDefault();
276     item18->Add( item20, 0, wxALIGN_CENTRE|wxALL, 5 );
277     
278     wxButton *item21 = new wxButton( parent, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
279     item18->Add( item21, 0, wxALIGN_CENTRE|wxALL, 5 );
280     
281     item0->Add( item18, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxBOTTOM, 5 );
282 #endif
283     
284 #ifdef __WXGTK__
285     wxButton *contextButton = new wxContextHelpButton( parent );
286     item18->Add( contextButton, 0, wxALIGN_CENTRE|wxALL, 5 );
287 #endif
288     
289     parent->FindWindow( ecID_PACKAGES_DIALOG_KEYWORDS )->SetFocus();
290     
291     parent->SetAutoLayout( TRUE );
292     parent->SetSizer( item0 );
293     parent->Layout();
294     item0->Fit( parent );
295     //item0->SetSizeHints( parent );
296     
297     // Add context-sensitive help text
298     parent->FindWindow( ecID_PACKAGES_DIALOG_AVAILABLE_LIST )->SetHelpText(_("Displays the list of packages available, but not currently loaded."));
299     parent->FindWindow( ecID_PACKAGES_DIALOG_USE_LIST )->SetHelpText(_("Displays the list of packages currently loaded."));
300     parent->FindWindow( ecID_PACKAGES_DIALOG_ADD )->SetHelpText(_("Add one or more packages to the list to be loaded."));
301     parent->FindWindow( ecID_PACKAGES_DIALOG_REMOVE )->SetHelpText(_("Removes one or more packages from the list to be loaded."));
302     parent->FindWindow( ecID_PACKAGES_DIALOG_VERSION )->SetHelpText(_("Displays the version of the selected packages."));
303     parent->FindWindow( ecID_PACKAGES_DIALOG_DESCRIPTION )->SetHelpText(_("Displays a description of the selected package (blank if more than one package is selected)."));
304     parent->FindWindow( ecID_PACKAGES_DIALOG_KEYWORDS )->SetHelpText(_("Enter keywords here to restrict displayed packages."));
305     parent->FindWindow( ecID_PACKAGES_DIALOG_CLEAR )->SetHelpText(_("Clears the keyword field."));
306     parent->FindWindow( ecID_PACKAGES_DIALOG_OMIT_HARDWARE)->SetHelpText(_("Check this to omit hardware packages, uncheck to show all packages."));
307     parent->FindWindow( ecID_PACKAGES_DIALOG_EXACT_MATCH )->SetHelpText(_("Check this to display exact matches between keyword and aliases (case insensitive)."));
308     parent->FindWindow( wxID_OK )->SetHelpText(_("Closes the dialog and saves any changes you have made."));
309     parent->FindWindow( wxID_CANCEL )->SetHelpText(_("Closes the dialog without saving any changes you have made."));
310     
311 #if __WXGTK__
312     parent->FindWindow( wxID_CONTEXT_HELP )->SetHelpText(_("Invokes context-sensitive help for the clicked-on window."));
313 #endif
314     
315     // Add validators
316     parent->FindWindow( ecID_PACKAGES_DIALOG_DESCRIPTION )->SetValidator(wxGenericValidator(& m_packageDescription));
317     parent->FindWindow( ecID_PACKAGES_DIALOG_KEYWORDS )->SetValidator(wxGenericValidator(& m_keywords));
318     parent->FindWindow( ecID_PACKAGES_DIALOG_OMIT_HARDWARE )->SetValidator(wxGenericValidator(& wxGetApp().GetSettings().m_omitHardwarePackages));
319     parent->FindWindow( ecID_PACKAGES_DIALOG_EXACT_MATCH )->SetValidator(wxGenericValidator(& wxGetApp().GetSettings().m_matchPackageNamesExactly));
320 }
321
322 void ecPackagesDialog::OnInitDialog(wxInitDialogEvent& event)
323 {
324     // Note: InitControls must be here, because data will be added
325     // between construction of the dialog, and OnInitDialog.
326     InitControls();
327     TransferDataToWindow();
328 }
329
330 void ecPackagesDialog::InitControls()
331 {
332     Fill();
333 }
334
335 void ecPackagesDialog::OnCancel(wxCommandEvent& event)
336 {
337     event.Skip();
338 }
339
340 void ecPackagesDialog::OnOK(wxCommandEvent& event)
341 {
342     TransferDataFromWindow();
343     event.Skip();
344 }
345
346 // For each word in keywords, is it contained in 'str'?
347 bool ecPackagesDialog::MatchesKeyword(wxArrayString& keywords, const wxString& str)
348 {
349     // _Every_ keyword must match
350     size_t i;
351     for (i = 0; i < keywords.GetCount(); i++)
352     {
353         if (str.Find(keywords[i]) == -1)
354             return FALSE;
355     }
356     return TRUE;
357 }
358
359 void ecPackagesDialog::Fill()
360 {
361     wxListBox* availableList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_AVAILABLE_LIST );
362     wxListBox* useList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_USE_LIST );
363     ecConfigToolDoc * pDoc = wxGetApp().GetConfigToolDoc ();
364
365     // wxGTK doesn't deselect items properly when clearing, I think
366     int i;
367     for (i = 0; i < availableList->GetCount(); i++)
368         if (availableList->Selected(i))
369             availableList->Deselect(i);
370     for (i = 0; i < useList->GetCount(); i++)
371         if (useList->Selected(i))
372             useList->Deselect(i);
373     
374     availableList->Clear();
375     useList->Clear();
376     ClearDescription();
377     
378     wxString s2(m_keywords);
379     s2.MakeLower();
380     
381     // Tokenize
382     wxArrayString keywords;
383     wxStringTokenizer tok(s2);
384     while (tok.HasMoreTokens())
385     {
386         keywords.Add(tok.GetNextToken());
387     }
388     
389     // Initialize the controls
390     for (i = 0; i < GetCount()-1; i++)
391     {
392         const wxString& str = m_items[i];
393         wxListBox* lb = m_arnItems[i] ? useList : availableList;
394         
395         wxString macroName(pDoc->GetPackageName (str));
396         
397         // check if the package is a hardware package
398         
399         if ((!wxGetApp().GetSettings().m_omitHardwarePackages) || !pDoc->GetCdlPkgData ()->is_hardware_package (ecUtils::UnicodeToStdStr (macroName)))
400         {
401             bool matches = TRUE;
402             
403             if (!m_keywords.IsEmpty())
404             {
405                 // Descriptive name
406                 wxString s1(str);
407                 s1.MakeLower();
408
409                 // macro name
410                 wxString s3(macroName);
411                 s3.MakeLower();
412
413                 // Match all aliases
414                 const std::vector<std::string> & aliases = pDoc->GetCdlPkgData ()->get_package_aliases (ecUtils::UnicodeToStdStr (macroName));
415                     
416                 if (wxGetApp().GetSettings().m_matchPackageNamesExactly)
417                 {
418                     int noMatches = 0;
419
420                     if (s2 == s1 || s2 == s3)
421                         noMatches ++;
422
423                     size_t j;
424                     for (j = 0; j < aliases.size(); j ++)
425                     {
426                         wxString alias(aliases[j].c_str());
427                         alias.MakeLower();
428                         if (s2 == alias)
429                             noMatches ++;
430                     }
431
432                     matches = (noMatches > 0);                   
433
434                 }
435                 else
436                 {
437                     // Concatenate all possible text together, and match against that
438                     wxString toMatch;
439                     
440                     toMatch += s1;
441                     
442                     toMatch += s3;
443                     
444                     size_t j;
445                     for (j = 0; j < aliases.size(); j ++)
446                     {
447                         wxString alias(aliases[j].c_str());
448                         alias.MakeLower();
449                         toMatch += alias;
450                     }
451                     
452                     matches = MatchesKeyword(keywords, toMatch);
453                 }
454             }
455             
456             if (matches)
457                 lb->Append(str, (void*) i);
458         }
459     }
460     
461     UpdateAddRemoveButtons();
462     
463     if (availableList->GetCount() == 1)
464     {
465         availableList->SetSelection(0);
466         UpdatePackageDescription();
467         UpdateVersionList ();
468         UpdateHardwareSelectionFlag ();
469     }
470     else if (useList->GetCount() == 1)
471     {
472         useList->SetSelection(0);
473         UpdatePackageDescription();
474         UpdateVersionList ();
475         UpdateHardwareSelectionFlag ();
476     }
477     wxTextCtrl* textCtrl = (wxTextCtrl*) FindWindow( ecID_PACKAGES_DIALOG_KEYWORDS );
478     // Necessary or TransferDataToWindow will cause insertion position to change
479     textCtrl->SetInsertionPointEnd();
480 }
481
482 void ecPackagesDialog::Add(wxListBox* from, wxListBox* to)
483 {
484     wxListBox* useList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_USE_LIST );
485     
486     wxArrayInt selections;
487     wxStringList selectionsStrings;
488     int n = from -> GetSelections( selections );
489     
490     if (n > 0)
491     {
492         int i;
493         for (i = 0; i < selections.GetCount(); i++)
494         {
495             wxString str = from -> GetString(selections[i]);
496             selectionsStrings.Add(str);
497         }
498         
499         // Now delete from one list and remove from t'other
500         for (i = 0; i < selectionsStrings.Number(); i++)
501         {
502             wxString str = selectionsStrings[i];
503             
504             // Remove
505             int toDelete =  from -> FindString(str);
506             int itemIndex = -1;
507             if (toDelete > -1)
508             {
509                 itemIndex = (int) from -> GetClientData(toDelete);
510                 from -> Delete(toDelete);
511             }
512             
513             wxASSERT (itemIndex > -1);
514             
515             // Add
516             to -> Append(str, (void*) itemIndex);
517             
518             if (to == useList)
519             {
520                 m_added.Add(str);
521             }
522             else
523             {
524                 m_added.Remove(str);
525             }
526             
527             // Select it
528             int addedIndex = to->FindString(str);
529             to->Select(addedIndex);
530             
531         }
532         //ClearDescription();
533         ClearSelections(* from);
534         UpdateHardwareSelectionFlag();
535         UpdatePackageDescription();
536         to->SetFocus();
537     }
538 }
539
540 void ecPackagesDialog::OnAdd(wxCommandEvent& event)
541 {
542     if (m_bHardwarePackageSelected)
543     {
544         HardwarePackageMessageBox ();
545         return;
546     }
547     wxListBox* availableList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_AVAILABLE_LIST );
548     wxListBox* useList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_USE_LIST );
549     
550     Add(availableList, useList);
551     
552     UpdateAddRemoveButtons();
553 }
554
555 void ecPackagesDialog::OnRemove(wxCommandEvent& event)
556 {
557     if (m_bHardwarePackageSelected)
558     {
559         HardwarePackageMessageBox ();
560         return;
561     }
562     
563     wxListBox* availableList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_AVAILABLE_LIST );
564     wxListBox* useList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_USE_LIST );
565     
566     Add(useList, availableList);
567     
568     UpdateAddRemoveButtons();
569 }
570
571 void ecPackagesDialog::OnDblClickListBox1(wxCommandEvent& event)
572 {
573     if (m_bHardwarePackageSelected)
574     {
575         HardwarePackageMessageBox ();
576         return;
577     }
578     
579     wxListBox* availableList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_AVAILABLE_LIST );
580     wxListBox* useList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_USE_LIST );
581     
582     Add(availableList, useList);
583     
584     UpdateAddRemoveButtons();
585 }
586
587 void ecPackagesDialog::OnDblClickListBox2(wxCommandEvent& event)
588 {
589     if (m_bHardwarePackageSelected)
590     {
591         HardwarePackageMessageBox ();
592         return;
593     }
594     
595     wxListBox* availableList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_AVAILABLE_LIST );
596     wxListBox* useList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_USE_LIST );
597     
598     Add(useList, availableList);
599     
600     UpdateAddRemoveButtons();
601 }
602
603 void ecPackagesDialog::OnClickListBox1(wxCommandEvent& event)
604 {
605     wxListBox* availableList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_AVAILABLE_LIST );
606     wxListBox* useList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_USE_LIST );
607     
608 #if 0    
609     int sel = event.GetSelection();
610     if (sel > -1)
611     {
612         // TODO: check that this works for multiple-selection listboxes
613         DisplayDescription(availableList->GetString(sel));
614     }
615 #endif
616     
617     ClearSelections(*useList);
618     UpdatePackageDescription ();
619     UpdateVersionList ();
620     UpdateHardwareSelectionFlag ();
621     UpdateAddRemoveButtons();
622 }
623
624 void ecPackagesDialog::OnClickListBox2(wxCommandEvent& event)
625 {
626     wxListBox* availableList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_AVAILABLE_LIST );
627     wxListBox* useList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_USE_LIST );
628     
629 #if 0    
630     int sel = event.GetSelection();
631     if (sel > -1)
632     {
633         // TODO: check that this works for multiple-selection listboxes
634         DisplayDescription(useList->GetString(sel));
635     }
636 #endif
637     
638     ClearSelections(*availableList);
639     UpdatePackageDescription ();
640     UpdateVersionList ();
641     UpdateHardwareSelectionFlag ();
642     UpdateAddRemoveButtons();
643 }
644
645 void ecPackagesDialog::OnSelectVersion(wxCommandEvent& event)
646 {
647     wxListBox* availableList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_AVAILABLE_LIST );
648     wxListBox* useList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_USE_LIST );
649     wxChoice* versionChoice = (wxChoice*) FindWindow( ecID_PACKAGES_DIALOG_VERSION );
650     
651     if (-1 == versionChoice->GetSelection ()) // if there is no version selection
652         return; // do nothing
653     
654     wxListBox * pListBox = NULL;
655     
656     wxArrayInt selected1, selected2;
657     availableList->GetSelections(selected1);
658     useList->GetSelections(selected2);
659     
660     int nListSelCount = selected1.GetCount ();
661     if (nListSelCount > 0)
662     {
663         pListBox = availableList;
664     }
665     else
666     {
667         nListSelCount = selected2.GetCount ();
668         if (nListSelCount)
669             pListBox = useList;
670     }
671     
672     wxASSERT (pListBox);
673     
674     if (!pListBox)
675         return;
676     
677     // retrieve the list box indices of the selected packages
678     
679     wxArrayInt* selected = (pListBox == availableList ? & selected1 : & selected2);
680     
681     int nIndex;
682     for (nIndex = 0; nIndex < nListSelCount; nIndex++) // for each selected package
683     {
684         // set the package version to that specified in the version combo box
685         wxString str = versionChoice->GetString(nIndex);
686         
687         // itemIndex is the index into the list of item names. It gets stored with all the listbox items.
688         int itemIndex = (int) pListBox->GetClientData((*selected)[nIndex]);
689         m_currentVersions[(size_t)itemIndex] = str;
690     }
691 }
692
693 void ecPackagesDialog::OnClearKeywords(wxCommandEvent& event)
694 {
695     wxTextCtrl* textCtrl = (wxTextCtrl*) FindWindow( ecID_PACKAGES_DIALOG_KEYWORDS );
696     textCtrl->SetValue(wxT(""));
697     TransferDataFromWindow();
698     Fill();
699     m_updateLists = FALSE;
700     wxStartTimer();
701     FindWindow( ecID_PACKAGES_DIALOG_KEYWORDS )->SetFocus();
702 }
703
704 void ecPackagesDialog::OnUpdateKeywordText(wxCommandEvent& event)
705 {
706     // Work around a bug in GTK+ that sends a text update command when
707     // clicking on one of the listboxes.
708     wxTextCtrl* textCtrl = (wxTextCtrl*) FindWindow( ecID_PACKAGES_DIALOG_KEYWORDS );
709     wxString value = textCtrl->GetValue();
710     if (value == m_keywords)
711         return;
712     
713     TransferDataFromWindow();
714     m_updateLists = TRUE;
715     wxStartTimer();
716 }
717
718 void ecPackagesDialog::OnClickOmitHardwarePackages(wxCommandEvent& event)
719 {
720     TransferDataFromWindow();
721     Fill();
722 }
723
724 void ecPackagesDialog::OnClickExactMatch(wxCommandEvent& event)
725 {
726     TransferDataFromWindow();
727     Fill();
728 }
729
730 void ecPackagesDialog::OnIdle(wxIdleEvent& event)
731 {
732     long elapsed = wxGetElapsedTime(FALSE);
733     if (m_updateLists && (elapsed > m_updateInterval))
734     {
735         m_updateLists = FALSE;
736         Fill();
737         wxStartTimer();
738     }
739 }
740
741 void ecPackagesDialog::Insert(const wxString& str, bool added, const wxString& descr, const wxString& version)
742 {
743     wxListBox* availableList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_AVAILABLE_LIST );
744     wxListBox* useList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_USE_LIST );
745     
746     m_items.Add(str);
747     m_descriptions.Add(str);
748     m_currentVersions.Add(version);
749     m_arnItems.Add(added);
750     
751     if (added)
752         m_added.Add(str);
753     
754     //(added ? useList : availableList) -> Append(str);
755 }
756
757 bool ecPackagesDialog::IsAdded(const wxString& str)
758 {
759     return (m_added.Index(str) != wxNOT_FOUND);
760     
761     //  return (((wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_USE_LIST ))->FindString(str) > -1) ;
762 }
763
764 static int ecPositionInStringList(const wxStringList& list, const wxString& item)
765 {
766     int i;
767     for (i = 0 ; i < list.Number(); i++)
768         if (list[i] == item)
769             return i;
770         else
771             i ++;
772         return -1;
773 }
774
775 void ecPackagesDialog::DisplayDescription(const wxString& item)
776 {
777     //wxTextCtrl* descrCtrl = (wxTextCtrl*) FindWindow( ecID_PACKAGES_DIALOG_DESCRIPTION ) ;
778     ecConfigToolDoc * pDoc = wxGetApp().GetConfigToolDoc ();
779     
780     //    int pos = ecPositionInStringList(m_items, item);
781     //    if (pos > -1)
782     {
783         wxString text;
784         //        wxString descr = m_descriptions[pos];
785         //        text += descr;
786         //        text += wxT("\n");
787         
788         wxString macroName(pDoc->GetPackageName (item));
789         
790         // Match all aliases
791         const std::vector<std::string> & aliases = pDoc->GetCdlPkgData ()->get_package_aliases (ecUtils::UnicodeToStdStr (macroName));
792         
793         size_t j;
794         for (j = 0; j < aliases.size(); j ++)
795         {
796             if (j == 1)
797                 text += wxT(".\nAliases: ");
798             else if (j > 1)
799                 text += wxT(", ");
800             
801             wxString alias(aliases[j].c_str());
802             text += alias;
803         }
804         text += wxT("\nMacro: ");
805         text += macroName;
806         text += wxT("\n\n");
807         
808         wxString descr = pDoc->GetCdlPkgData ()->get_package_description (ecUtils::UnicodeToStdStr (macroName)).c_str ();
809         
810         text += ecUtils::StripExtraWhitespace (descr);
811         
812         m_packageDescription = text;
813         
814         //descrCtrl->SetValue(text);
815     }
816 }
817
818 void ecPackagesDialog::ClearDescription()
819 {
820     wxTextCtrl* descrCtrl = (wxTextCtrl*) FindWindow( ecID_PACKAGES_DIALOG_DESCRIPTION ) ;
821     descrCtrl->SetValue(wxEmptyString);
822 }
823
824 wxString ecPackagesDialog::GetVersion (const wxString& item)
825 {
826     int nCount;
827     for (nCount = GetCount() - 1; nCount >= 0; --nCount)
828     {
829         if (m_items [nCount] == item)
830         {
831             return m_currentVersions [nCount];
832         }
833     }
834     wxASSERT (FALSE);
835     return wxEmptyString;
836 }
837
838 void ecPackagesDialog::UpdateHardwareSelectionFlag()
839 {
840     m_bHardwarePackageSelected = FALSE;
841     
842     wxListBox* availableList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_AVAILABLE_LIST );
843     wxListBox* useList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_USE_LIST );
844     wxListBox * pListBox = NULL;
845     
846     wxArrayInt selections1, selections2;
847     wxArrayInt* selections = NULL;
848     availableList->GetSelections(selections1);
849     useList->GetSelections(selections2);
850     
851     int nListSelCount = selections1.GetCount ();
852     if (nListSelCount)
853     {
854         pListBox = availableList;
855         selections = & selections1;
856     }
857     else
858     {
859         nListSelCount = selections2.GetCount ();
860         if (nListSelCount)
861         {
862             pListBox = useList;
863             selections = & selections2;
864         }
865     }
866     
867     if (pListBox) // if there are packages selected
868     {
869         ecConfigToolDoc * pDoc = wxGetApp().GetConfigToolDoc ();
870         
871         // retrieve the list box indices of the selected packages
872         
873         //int * arnIndices = new int [nListSelCount];
874         //pListBox->GetSelItems (nListSelCount, arnIndices);
875         
876         int nIndex;
877         for (nIndex = 0; nIndex < nListSelCount; nIndex++) // for each selected package
878         {
879             wxString strPackageAlias = pListBox->GetString((*selections)[nIndex]);
880             
881             // check if the package is a hardware package
882             
883             //TRACE (_T("Checking '%s' for hardware status\n"), strPackageAlias);
884             if (pDoc->GetCdlPkgData ()->is_hardware_package (ecUtils::UnicodeToStdStr (pDoc->GetPackageName (strPackageAlias))))
885             {
886                 m_bHardwarePackageSelected = TRUE;
887                 break;
888             }
889         }
890     }
891 }
892
893 void ecPackagesDialog::HardwarePackageMessageBox()
894 {
895     // TODO: could give the user the choice of going to the template dialog.
896     wxMessageBox (wxT("Add and remove hardware packages by selecting a new hardware template."),
897         wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK, this);
898 }
899
900 void ecPackagesDialog::UpdatePackageDescription ()
901 {
902     ecConfigToolDoc * pDoc = wxGetApp().GetConfigToolDoc ();
903     
904     wxListBox* availableList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_AVAILABLE_LIST );
905     wxListBox* useList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_USE_LIST );
906     
907     wxListBox * pListBox = NULL;
908     
909     wxArrayInt selections1, selections2;
910     wxArrayInt* selections = NULL;
911     availableList->GetSelections(selections1);
912     useList->GetSelections(selections2);
913     
914     if (1 == selections1.GetCount ())
915     {
916         pListBox = availableList;
917         selections = & selections1;
918     }
919     else if (1 == selections2.GetCount ())
920     {
921         pListBox = useList;
922         selections = & selections2;
923     }
924     
925     if (pListBox && selections)
926     {
927         int nIndex = (*selections)[0];
928         wxString strPackageAlias = pListBox->GetString(nIndex);
929         
930         DisplayDescription(strPackageAlias);
931         //m_packageDescription = pDoc->GetCdlPkgData ()->get_package_description (ecUtils::UnicodeToStdStr (pDoc->GetPackageName (strPackageAlias))).c_str ();
932         //m_packageDescription = ecUtils::StripExtraWhitespace (m_packageDescription);
933     }
934     else
935     {
936         m_packageDescription = wxEmptyString;
937     }
938     TransferDataToWindow ();
939 }
940
941 void ecPackagesDialog::UpdateVersionList ()
942 {
943     ecConfigToolDoc * pDoc = wxGetApp().GetConfigToolDoc ();
944     
945     wxListBox* availableList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_AVAILABLE_LIST );
946     wxListBox* useList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_USE_LIST );
947     wxChoice* versionChoice = (wxChoice*) FindWindow( ecID_PACKAGES_DIALOG_VERSION );
948     
949     versionChoice->Clear(); // clear the version combo box
950     
951     wxArrayInt selections1, selections2;
952     wxArrayInt* selections = NULL;
953     availableList->GetSelections(selections1);
954     useList->GetSelections(selections2);
955     wxListBox* pListBox = NULL;
956     
957     if (selections1.GetCount () > 0)
958     {
959         pListBox = availableList;
960         selections = & selections1;
961     }
962     else if (selections2.GetCount () > 0)
963     {
964         pListBox = useList;
965         selections = & selections2;
966     }
967     
968     if (pListBox) // if there are packages selected
969     {
970         std::list<std::string> common_versions;
971         bool bCommonSelectedVersion = true;
972         int nCommonVersionIndex=-1;
973         int nListSelCount = selections->GetCount();
974         
975         // retrieve the list box indices of the selected packages
976         
977         //int * arnIndices = new int [nListSelCount];
978         //pListBox->GetSelItems (nListSelCount, arnIndices);
979         int nIndex;
980         for (nIndex = 0; nIndex < nListSelCount; nIndex++) // for each selected package
981         {
982             // retrieve the first package alias
983             wxString strPackageAlias = pListBox->GetString ((*selections)[nIndex]);
984             
985             // retrieve the dialog item array index for use in
986             // comparing current version strings
987             const int nVersionIndex = (int) pListBox->GetClientData ((*selections)[nIndex]);
988             
989             // retrieve the installed version array
990             
991             //TRACE (_T("Retrieving versions for '%s'\n"), strPackageAlias);
992             const std::vector<std::string>& versions = pDoc->GetCdlPkgData ()->get_package_versions (ecUtils::UnicodeToStdStr (pDoc->GetPackageName (strPackageAlias)));
993             
994             if (0 == nIndex) // if this is the first selected package
995             {
996                 // use the version array to initialise a linked list of version
997                 // strings held in common between the selected packages
998                 unsigned int uCount;
999                 for (uCount = 0; uCount < versions.size (); uCount++)
1000                 {
1001                     //TRACE (_T("Adding common version '%s'\n"), wxString (versions [uCount].c_str ()));
1002                     common_versions.push_back (versions [uCount]);
1003                 }
1004                 nCommonVersionIndex = nVersionIndex; // save the item array index
1005             }
1006             else // this is not the first selected package
1007             {
1008                 std::list<std::string>::iterator i_common_versions = common_versions.begin ();
1009                 while (i_common_versions != common_versions.end ()) // iterate through the common versions
1010                 {
1011                     if (versions.end () == std::find (versions.begin (), versions.end (), * i_common_versions)) // if the common version is not in the versions list
1012                     {
1013                         //TRACE (_T("Removing common version '%s'\n"), CString (i_common_versions->c_str ()));
1014                         common_versions.erase (i_common_versions++); // remove the version from the common versions list
1015                     }
1016                     else
1017                     {
1018                         i_common_versions++;
1019                     }
1020                 }
1021                 if (bCommonSelectedVersion) // if the selected versions of all preceding packages are identical
1022                 {
1023                     // check if the selected version of this package matches that of the preceding ones
1024                     bCommonSelectedVersion = (m_currentVersions [nVersionIndex] == m_currentVersions [nCommonVersionIndex]);
1025                 }
1026             }
1027         }
1028         
1029         // add the common versions to the version combo box
1030         
1031         std::list<std::string>::iterator i_common_versions;
1032         for (i_common_versions = common_versions.begin (); i_common_versions != common_versions.end (); i_common_versions++)
1033         {
1034             //TRACE (_T("Adding version '%s'\n"), CString (i_common_versions->c_str ()));
1035             versionChoice->Append(wxString (i_common_versions->c_str ()));
1036         }
1037         
1038         // select the common current version (if any) in the version combo box
1039         
1040         if (bCommonSelectedVersion)
1041         {
1042             //TRACE (_T("Selecting version '%s'\n"), m_arstrVersions [nCommonVersionIndex]);
1043             versionChoice->SetStringSelection (m_currentVersions [nCommonVersionIndex]);
1044         }
1045         
1046         // enable the version combo box only if there are multiple common versions
1047         
1048         versionChoice->Enable (common_versions.size () > 1);
1049     }
1050     else // there are no packages selected
1051     {
1052         versionChoice->Enable (FALSE); // disable the version combo box
1053     }
1054 }
1055
1056 void ecPackagesDialog::UpdateAddRemoveButtons()
1057 {
1058     wxListBox* availableList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_AVAILABLE_LIST );
1059     wxListBox* useList = (wxListBox*) FindWindow( ecID_PACKAGES_DIALOG_USE_LIST );
1060     
1061     wxArrayInt selections1, selections2;
1062     availableList->GetSelections(selections1);
1063     useList->GetSelections(selections2);
1064     
1065     FindWindow( ecID_PACKAGES_DIALOG_ADD )->Enable( selections1.GetCount() > 0 );
1066     FindWindow( ecID_PACKAGES_DIALOG_REMOVE )->Enable( selections2.GetCount() > 0 );
1067 }
1068
1069 void ecPackagesDialog::ClearSelections(wxListBox& lbox)
1070 {
1071     int i;
1072     for (i = 0; i < lbox.Number(); i++)
1073     {
1074         lbox.Deselect(i);
1075     }
1076 }
1077
1078 void ecPackagesTimer::Notify()
1079 {
1080     static bool s_inNotify = FALSE;
1081     
1082     if (s_inNotify)
1083         return;
1084     
1085     s_inNotify = TRUE;
1086     
1087     // On Windows, simply having the timer going will ping the message queue
1088     // and cause idle processing to happen.
1089     // On Unix, this doesn't happen so we have to do the processing explicitly.
1090 #ifdef __WXMSW__
1091     // Nothing to do
1092 #else
1093     if ( m_dialog )
1094     {
1095         wxIdleEvent event;
1096         m_dialog->OnIdle(event);
1097     }
1098 #endif
1099     
1100     s_inNotify = FALSE;
1101 }