+13-08-2004 :
+ - general : implemented command completion and interactive help.
+
 06-08-2004 :
  - wxbRestorePanel : now parsing '+' sent by the director when building
      tree.
 
 
 wxbUtils : add clients, jobs, filesets, pools... list, merge patch file (wxbnewutils.patch)
 
-general : add a tab containing messages
+general : do not show some commands results (for example .help)
 
-wxbMainFrame : Implement command completion (tab)
+general : add a tab containing messages
 
 wxbConfigFileEditor : create a more precise editor, with something like
    a tree structure
 
 #include "wxbhistorytextctrl.h"
 
 BEGIN_EVENT_TABLE(wxbHistoryTextCtrl, wxTextCtrl)
+   EVT_KEY_DOWN(wxbHistoryTextCtrl::OnKeyDown)
    EVT_KEY_UP(wxbHistoryTextCtrl::OnKeyUp)
 END_EVENT_TABLE()
 
-wxbHistoryTextCtrl::wxbHistoryTextCtrl(wxWindow* parent, wxWindowID id, 
+wxbHistoryTextCtrl::wxbHistoryTextCtrl(wxStaticText* help, 
+      wxWindow* parent, wxWindowID id, 
       const wxString& value, const wxPoint& pos, 
       const wxSize& size , 
       const wxValidator& validator, 
       const wxString& name): 
          wxTextCtrl(parent, id, value, pos, size, 
             wxTE_PROCESS_ENTER, validator, name) {
+   this->help = help;
    index = 0;
    history.Add("");
 }
 
+void wxbHistoryTextCtrl::AddCommand(wxString cmd, wxString description) {
+   commands[cmd] = description;
+}
+
+void wxbHistoryTextCtrl::ClearCommandList() {
+   commands.clear();
+}
+
 void wxbHistoryTextCtrl::HistoryAdd(wxString cmd) {
    if (cmd == "") return;
    index = history.Count();
    history.Add("");
 }
 
+void wxbHistoryTextCtrl::SetValue(const wxString& value) {
+   if (value == "") {
+      help->SetLabel("Type your command below:");
+   }
+   wxTextCtrl::SetValue(value);
+}
+
+void wxbHistoryTextCtrl::OnKeyDown(wxKeyEvent& event) {
+   if (event.m_keyCode == WXK_TAB) {
+
+   }
+   else {
+      event.Skip();
+   }
+}
+
 void wxbHistoryTextCtrl::OnKeyUp(wxKeyEvent& event) {
    if (event.m_keyCode == WXK_UP) {
       if (index > 0) {
          SetInsertionPointEnd();
       }      
    }
+   else if (GetValue() != "") {
+      wxbCommands::iterator it;
+      wxString key;
+      wxString helptext = "Unknown command.";
+      int found = 0;      
+      for( it = commands.begin(); it != commands.end(); ++it ) {         
+         if (it->first.Find(GetValue()) == 0) {
+            found++;
+            if (found > 2) {
+               helptext += " " + it->first;
+            }
+            else if (found > 1) {
+               helptext = "Possible completions: " + key + " " + it->first;
+            }
+            else { // (found == 1)
+               helptext = it->first + ": " + it->second;
+               key = it->first;
+            }
+         }
+         else if (GetValue().Find(it->first) == 0) {
+            helptext = it->first + ": " + it->second;
+            found = 0;
+            break;
+         }
+      }
+      
+      help->SetLabel(helptext);
+            
+      if (event.m_keyCode == WXK_TAB) {
+         if (found == 1) {
+            SetValue(key);
+            SetInsertionPointEnd();
+         }
+      }
+      else {
+         event.Skip();
+      }
+   }
    else {
+      help->SetLabel("Type your command below:");
       event.Skip();
    }
 }
 
 
 #include <wx/treectrl.h>
 
+WX_DECLARE_STRING_HASH_MAP( wxString, wxbCommands );
+
 class wxbHistoryTextCtrl: public wxTextCtrl {
    public:
-      wxbHistoryTextCtrl(wxWindow* parent, wxWindowID id, 
+      wxbHistoryTextCtrl(wxStaticText* help, wxWindow* parent, wxWindowID id, 
          const wxString& value = "", const wxPoint& pos = wxDefaultPosition,
          const wxSize& size = wxDefaultSize, 
          const wxValidator& validator = wxDefaultValidator, 
          const wxString& name = wxTextCtrlNameStr);
          
       void HistoryAdd(wxString cmd);
+      
+      void AddCommand(wxString cmd, wxString description);
+      void ClearCommandList();
+      
+      virtual void SetValue(const wxString& value);
    private:
       wxArrayString history;
+      wxbCommands commands;
       int index;
+      wxStaticText* help;
       
       void OnKeyUp(wxKeyEvent& event);
+      void OnKeyDown(wxKeyEvent& event);
       
       DECLARE_EVENT_TABLE();
 };
 
 #include <wx/arrimpl.cpp>
 
 #include <wx/stattext.h>
-
+#include <wx/statline.h>
 #include <wx/config.h>
 
 #include <wx/filename.h>
    consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, font));
 #endif
 
-   wxFlexGridSizer *consoleSizer = new wxFlexGridSizer(2, 1, 0, 0);
+   helpCtrl = new wxStaticText(consolePanel, -1, "Type your command below:");
+
+   wxFlexGridSizer *consoleSizer = new wxFlexGridSizer(4, 1, 0, 0);
    consoleSizer->AddGrowableCol(0);
    consoleSizer->AddGrowableRow(0);
 
-   typeCtrl = new wxbHistoryTextCtrl(consolePanel,TypeText,"",wxDefaultPosition,wxSize(200,20));
+   typeCtrl = new wxbHistoryTextCtrl(helpCtrl, consolePanel,TypeText,"",wxDefaultPosition,wxSize(200,20));
    sendButton = new wxButton(consolePanel, SendButton, "Send");
    
-   wxFlexGridSizer *typeSizer = new wxFlexGridSizer(1, 3, 0, 0);
-   typeSizer->AddGrowableCol(1);
+   wxFlexGridSizer *typeSizer = new wxFlexGridSizer(1, 2, 0, 0);
+   typeSizer->AddGrowableCol(0);
    typeSizer->AddGrowableRow(0);
 
-   typeSizer->Add(new wxStaticText(consolePanel, -1, "Command: "), 0, wxALIGN_CENTER | wxALL, 0);
+   //typeSizer->Add(new wxStaticText(consolePanel, -1, "Command: "), 0, wxALIGN_CENTER | wxALL, 0);
    typeSizer->Add(typeCtrl, 1, wxEXPAND | wxALL, 0);
    typeSizer->Add(sendButton, 1, wxEXPAND | wxLEFT, 5);
 
    consoleSizer->Add(consoleCtrl, 1, wxEXPAND | wxALL, 0);
-   consoleSizer->Add(typeSizer, 0, wxEXPAND | wxALL, 0);
+   consoleSizer->Add(new wxStaticLine(consolePanel, -1), 0, wxEXPAND | wxALL, 0);
+   consoleSizer->Add(helpCtrl, 1, wxEXPAND | wxALL, 2);
+   consoleSizer->Add(typeSizer, 0, wxEXPAND | wxALL, 2);
 
    consolePanel->SetAutoLayout( TRUE );
    consolePanel->SetSizer( consoleSizer );
    
    if (status == CS_CONNECTED) {
       SetStatusText("Connected to the director.");
+      typeCtrl->ClearCommandList();
+      wxbDataTokenizer* dt = wxbUtils::WaitForEnd(".help", true);
+      int i, j;
+      wxString str;
+      for (i = 0; i < dt->GetCount(); i++) {
+         str = (*dt)[i];
+         str.RemoveLast();
+         if ((j = str.Find(' ')) > -1) {
+            typeCtrl->AddCommand(str.Mid(0, j), str.Mid(j+1));
+         }
+      }
       EnablePanels();
       menuFile->Enable(MenuConnect, true);
       menuFile->SetLabel(MenuConnect, "Reconnect");
 
 
    wxNotebook *notebook; /* main notebook */
    wxTextCtrl *consoleCtrl; /* wxTextCtrl containing graphical console */
+   wxStaticText *helpCtrl; /* wxStaticText showing help messages */
    wxbHistoryTextCtrl *typeCtrl; /* wxbHistoryTextCtrl for console user input */
    wxButton *sendButton; /* wxButton used to send data */