5 * Nicolas Boichat, July 2004
10 Copyright (C) 2004-2005 Kern Sibbald
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 version 2 as amended with additional clauses defined in the
15 file LICENSE in the main source directory.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 the file LICENSE for additional details.
24 #include "wxbmainframe.h" // class's header file
26 #include "wxbrestorepanel.h"
28 #include "wxbconfigfileeditor.h"
32 #include "wxwin16x16.xpm"
34 #include <wx/arrimpl.cpp>
36 #include <wx/stattext.h>
37 #include <wx/statline.h>
38 #include <wx/config.h>
40 #include <wx/filename.h>
42 #undef Yield /* MinGW defines Yield */
44 // ----------------------------------------------------------------------------
45 // event tables and other macros for wxWindows
46 // ----------------------------------------------------------------------------
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 // IDs for the controls and the menu commands
58 // it is important for the id corresponding to the "About" command to have
59 // this standard value as otherwise it won't be handled properly under Mac
60 // (where it is special and put into the "Apple" menu)
61 Minimal_About = wxID_ABOUT,
73 * wxbTHREAD_EVENT declaration, used by csprint
75 BEGIN_DECLARE_EVENT_TYPES()
76 DECLARE_EVENT_TYPE(wxbTHREAD_EVENT, 1)
77 END_DECLARE_EVENT_TYPES()
79 DEFINE_EVENT_TYPE(wxbTHREAD_EVENT)
81 typedef void (wxEvtHandler::*wxThreadEventFunction)(wxbThreadEvent&);
83 #define EVT_THREAD_EVENT(id, fn) \
84 DECLARE_EVENT_TABLE_ENTRY( \
85 wxbTHREAD_EVENT, id, wxID_ANY, \
86 (wxObjectEventFunction)(wxEventFunction)(wxThreadEventFunction)&fn, \
90 // the event tables connect the wxWindows events with the functions (event
91 // handlers) which process them. It can be also done at run-time, but for the
92 // simple menu events like this the static method is much simpler.
93 BEGIN_EVENT_TABLE(wxbMainFrame, wxFrame)
94 EVT_MENU(Minimal_Quit, wxbMainFrame::OnQuit)
95 EVT_MENU(Minimal_About, wxbMainFrame::OnAbout)
96 EVT_MENU(ChangeConfigFile, wxbMainFrame::OnChangeConfig)
97 EVT_MENU(EditConfigFile, wxbMainFrame::OnEditConfig)
98 EVT_MENU(MenuConnect, wxbMainFrame::OnConnect)
99 EVT_MENU(MenuDisconnect, wxbMainFrame::OnDisconnect)
100 EVT_TEXT_ENTER(TypeText, wxbMainFrame::OnEnter)
101 EVT_THREAD_EVENT(Thread, wxbMainFrame::OnPrint)
102 EVT_BUTTON(SendButton, wxbMainFrame::OnEnter)
105 // ----------------------------------------------------------------------------
107 // ----------------------------------------------------------------------------
110 * wxbThreadEvent constructor
112 wxbThreadEvent::wxbThreadEvent(int id): wxEvent(id, wxbTHREAD_EVENT) {
113 m_eventObject = NULL;
117 * wxbThreadEvent destructor
119 wxbThreadEvent::~wxbThreadEvent()
121 if (m_eventObject != NULL) {
122 delete m_eventObject;
127 * wxbThreadEvent copy constructor
129 wxbThreadEvent::wxbThreadEvent(const wxbThreadEvent& te)
131 this->m_eventType = te.m_eventType;
132 this->m_id = te.m_id;
133 if (te.m_eventObject != NULL) {
134 this->m_eventObject = new wxbPrintObject(*((wxbPrintObject*)te.m_eventObject));
137 this->m_eventObject = NULL;
139 this->m_skipped = te.m_skipped;
140 this->m_timeStamp = te.m_timeStamp;
144 * Must be implemented (abstract in wxEvent)
146 wxEvent* wxbThreadEvent::Clone() const
148 return new wxbThreadEvent(*this);
152 * Gets the wxbPrintObject attached to this event, containing data sent by director
154 wxbPrintObject* wxbThreadEvent::GetEventPrintObject()
156 return (wxbPrintObject*)m_eventObject;
160 * Sets the wxbPrintObject attached to this event
162 void wxbThreadEvent::SetEventPrintObject(wxbPrintObject* object)
164 m_eventObject = (wxObject*)object;
167 // ----------------------------------------------------------------------------
169 // ----------------------------------------------------------------------------
171 wxbMainFrame *wxbMainFrame::frame = NULL;
174 * Singleton constructor
176 wxbMainFrame* wxbMainFrame::CreateInstance(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
178 frame = new wxbMainFrame(title, pos, size, style);
183 * Returns singleton instance
185 wxbMainFrame* wxbMainFrame::GetInstance()
193 wxbMainFrame::~wxbMainFrame()
195 wxConfig::Get()->Write(wxT("/Position/X"), (long)GetPosition().x);
196 wxConfig::Get()->Write(wxT("/Position/Y"), (long)GetPosition().y);
197 wxConfig::Get()->Write(wxT("/Size/Width"), (long)GetSize().GetWidth());
198 wxConfig::Get()->Write(wxT("/Size/Height"), (long)GetSize().GetHeight());
200 if (ct != NULL) { // && (!ct->IsRunning())
207 * Private constructor
209 wxbMainFrame::wxbMainFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
210 : wxFrame(NULL, -1, title, pos, size, style)
212 lockedbyconsole = false;
218 // set the frame icon
219 SetIcon(wxIcon(wxwin16x16_xpm));
223 menuFile = new wxMenu;
225 // the "About" item should be in the help menu
226 wxMenu *helpMenu = new wxMenu;
227 helpMenu->Append(Minimal_About, _("&About...\tF1"), _("Show about dialog"));
229 menuFile->Append(MenuConnect, _("Connect"), _("Connect to the director"));
230 menuFile->Append(MenuDisconnect, _("Disconnect"), _("Disconnect of the director"));
231 menuFile->AppendSeparator();
232 menuFile->Append(ChangeConfigFile, _("Change of configuration file"), _("Change your default configuration file"));
233 menuFile->Append(EditConfigFile, _("Edit your configuration file"), _("Edit your configuration file"));
234 menuFile->AppendSeparator();
235 menuFile->Append(Minimal_Quit, _("E&xit\tAlt-X"), _("Quit this program"));
237 // now append the freshly created menu to the menu bar...
238 wxMenuBar *menuBar = new wxMenuBar();
239 menuBar->Append(menuFile, _("&File"));
240 menuBar->Append(helpMenu, _("&Help"));
242 // ... and attach this menu bar to the frame
244 #endif // wxUSE_MENUS
248 SetStatusText(wxString::Format(_("Welcome to bacula wx-console %s (%s)!\n"), wxT(VERSION), wxT(BDATE)));
250 wxPanel* global = new wxPanel(this, -1);
252 notebook = new wxNotebook(global, -1);
256 wxPanel* consolePanel = new wxPanel(notebook, -1);
257 notebook->AddPage(consolePanel, _("Console"));
259 consoleCtrl = new wxTextCtrl(consolePanel,-1,wxT(""),wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH);
260 wxFont font(10, wxMODERN, wxNORMAL, wxNORMAL);
261 #if defined __WXGTK12__ && !defined __WXGTK20__ // Fix for "chinese" fonts under gtk+ 1.2
262 font.SetDefaultEncoding(wxFONTENCODING_ISO8859_1);
263 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, font));
264 Print(_("Warning : Unicode is disabled because you are using wxWidgets for GTK+ 1.2.\n"), CS_DEBUG);
266 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, font));
267 #if (wxUSE_UNICODE == 0) && __WXGTK20__
268 Print(_("Warning : There is a problem with wxWidgets for GTK+ 2.0 without Unicode support when handling non-ASCII filenames: Every non-ASCII character in such filenames will be replaced by an interrogation mark.\nIf this behaviour disturbs you, please build wx-console against a Unicode version of wxWidgets for GTK+ 2.0.\n---\n"), CS_DEBUG);
272 helpCtrl = new wxStaticText(consolePanel, -1, _("Type your command below:"));
274 wxFlexGridSizer *consoleSizer = new wxFlexGridSizer(4, 1, 0, 0);
275 consoleSizer->AddGrowableCol(0);
276 consoleSizer->AddGrowableRow(0);
278 typeCtrl = new wxbHistoryTextCtrl(helpCtrl, consolePanel,TypeText,wxT(""),wxDefaultPosition,wxSize(200,20));
279 sendButton = new wxButton(consolePanel, SendButton, _("Send"));
281 wxFlexGridSizer *typeSizer = new wxFlexGridSizer(1, 2, 0, 0);
282 typeSizer->AddGrowableCol(0);
283 typeSizer->AddGrowableRow(0);
285 //typeSizer->Add(new wxStaticText(consolePanel, -1, _("Command: ")), 0, wxALIGN_CENTER | wxALL, 0);
286 typeSizer->Add(typeCtrl, 1, wxEXPAND | wxALL, 0);
287 typeSizer->Add(sendButton, 1, wxEXPAND | wxLEFT, 5);
289 consoleSizer->Add(consoleCtrl, 1, wxEXPAND | wxALL, 0);
290 consoleSizer->Add(new wxStaticLine(consolePanel, -1), 0, wxEXPAND | wxALL, 0);
291 consoleSizer->Add(helpCtrl, 1, wxEXPAND | wxALL, 2);
292 consoleSizer->Add(typeSizer, 0, wxEXPAND | wxALL, 2);
294 consolePanel->SetAutoLayout( TRUE );
295 consolePanel->SetSizer( consoleSizer );
296 consoleSizer->SetSizeHints( consolePanel );
298 // Creates the list of panels which are included in notebook, and that need to receive director information
300 panels = new wxbPanel* [2];
301 panels[0] = new wxbRestorePanel(notebook);
304 for (int i = 0; panels[i] != NULL; i++) {
305 notebook->AddPage(panels[i], panels[i]->GetTitle());
308 wxBoxSizer* globalSizer = new wxBoxSizer(wxHORIZONTAL);
310 #if wxCHECK_VERSION(2, 6, 0)
311 globalSizer->Add(notebook, 1, wxEXPAND, 0);
313 globalSizer->Add(new wxNotebookSizer(notebook), 1, wxEXPAND, 0);
316 global->SetSizer( globalSizer );
317 globalSizer->SetSizeHints( global );
319 wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
321 sizer->Add(global, 1, wxEXPAND | wxALL, 0);
324 sizer->SetSizeHints( this );
326 EnableConsole(false);
328 consoleBuffer = wxT("");
330 configfile = wxT("");
334 * Starts the thread interacting with the director
335 * If config is not empty, uses this config file.
337 void wxbMainFrame::StartConsoleThread(const wxString& config) {
338 menuFile->Enable(MenuConnect, false);
339 menuFile->Enable(MenuDisconnect, false);
340 menuFile->Enable(ChangeConfigFile, false);
341 menuFile->Enable(EditConfigFile, false);
348 if (promptparser == NULL) {
349 promptparser = new wxbPromptParser();
352 if (config == wxT("")) {
353 configfile = wxT("");
355 if (((wxTheApp->argc % 2) != 1)) {
356 Print(_("Error while parsing command line arguments, using defaults.\n"), CS_DEBUG);
357 Print(_("Usage: wx-console [-c configfile] [-w tmp]\n"), CS_DEBUG);
360 for (int c = 1; c < wxTheApp->argc; c += 2) {
361 if ((wxTheApp->argc >= c+2) && (wxString(wxTheApp->argv[c]) == wxT("-c"))) {
362 configfile = wxTheApp->argv[c+1];
364 if ((wxTheApp->argc >= c+2) && (wxString(wxTheApp->argv[c]) == wxT("-w"))) {
365 console_thread::SetWorkingDirectory(wxTheApp->argv[c+1]);
367 if (wxTheApp->argv[c][0] != '-') {
368 Print(_("Error while parsing command line arguments, using defaults.\n"), CS_DEBUG);
369 Print(_("Usage: wx-console [-c configfile] [-w tmp]\n"), CS_DEBUG);
375 if (configfile == wxT("")) {
376 wxConfig::Set(new wxConfig(wxT("wx-console"), wxT("bacula")));
377 if (!wxConfig::Get()->Read(wxT("/ConfigFile"), &configfile)) {
379 wxFileName filename(::wxGetHomeDir());
380 filename.MakeAbsolute();
381 configfile = filename.GetLongPath();
382 if (configfile.Last() != '/')
384 configfile += "Library/Preferences/org.bacula.wxconsole.conf";
386 wxFileName filename(::wxGetCwd(), wxT("wx-console.conf"));
387 filename.MakeAbsolute();
388 configfile = filename.GetLongPath();
390 configfile.Replace(wxT("\\"), wxT("/"));
393 wxConfig::Get()->Write(wxT("/ConfigFile"), configfile);
395 int answer = wxMessageBox(
397 "It seems that it is the first time you run wx-console.\nThis file (%s) has been choosen as default configuration file.\nDo you want to edit it? (if you click No you will have to select another file)"),
400 wxYES_NO | wxICON_QUESTION, this);
401 if (answer == wxYES) {
402 wxbConfigFileEditor(this, configfile).ShowModal();
411 wxString err = console_thread::LoadConfig(configfile);
413 while (err != wxT("")) {
414 int answer = wxMessageBox(
416 "Unable to read %s\nError: %s\nDo you want to choose another one? (Press no to edit this file)"),
417 configfile.c_str(), err.c_str()),
418 _("Unable to read configuration file"),
419 wxYES_NO | wxCANCEL | wxICON_ERROR, this);
420 if (answer == wxNO) {
421 wxbConfigFileEditor(this, configfile).ShowModal();
422 err = console_thread::LoadConfig(configfile);
424 else if (answer == wxCANCEL) {
429 else { // (answer == wxYES)
430 configfile = wxFileSelector(_("Please choose a configuration file to use"));
431 if ( !configfile.empty() ) {
432 err = console_thread::LoadConfig(configfile);
441 if ((err == wxT("")) && (config == wxT(""))) {
442 answer = wxMessageBox(
443 _("This configuration file has been successfully read, use it as default?"),
444 _("Configuration file read successfully"),
445 wxYES_NO | wxICON_QUESTION, this);
446 if (answer == wxYES) {
447 wxConfigBase::Get()->Write(wxT("/ConfigFile"), configfile);
453 // former was csprint
454 Print(wxString::Format(_("Using this configuration file: %s\n"), configfile.c_str()), CS_DEBUG);
456 ct = new console_thread();
459 SetStatusText(_("Connecting to the director..."));
462 /* Register a new wxbDataParser */
463 void wxbMainFrame::Register(wxbDataParser* dp) {
467 /* Unregister a wxbDataParser */
468 void wxbMainFrame::Unregister(wxbDataParser* dp) {
470 if ((index = parsers.Index(dp)) != wxNOT_FOUND) {
471 parsers.RemoveAt(index);
474 Print(_("Failed to unregister a data parser !"), CS_DEBUG);
480 void wxbMainFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
482 Print(_("Quitting.\n"), CS_DEBUG);
488 console_thread::FreeLib();
494 void wxbMainFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
497 msg.Printf(_("Welcome to Bacula wx-console.\nWritten by Nicolas Boichat <nicolas@boichat.ch>\n(C) 2005 Kern Sibbald\n"));
499 wxMessageBox(msg, _("About Bacula wx-console"), wxOK | wxICON_INFORMATION, this);
502 void wxbMainFrame::OnChangeConfig(wxCommandEvent& event) {
503 wxString oriconfigfile;
504 wxConfig::Get()->Read(wxT("/ConfigFile"), &oriconfigfile);
505 wxString configfile = wxFileSelector(_("Please choose your default configuration file"));
506 if ( !configfile.empty() ) {
507 if (oriconfigfile != configfile) {
508 int answer = wxMessageBox(
509 _("Use this configuration file as default?"),
510 _("Configuration file"),
511 wxYES_NO | wxICON_QUESTION, this);
512 if (answer == wxYES) {
513 wxConfigBase::Get()->Write(wxT("/ConfigFile"), configfile);
514 wxConfigBase::Get()->Flush();
515 StartConsoleThread(wxT(""));
520 StartConsoleThread(configfile);
524 void wxbMainFrame::OnEditConfig(wxCommandEvent& event) {
526 wxConfig::Get()->Read(wxT("/ConfigFile"), &configfile);
527 int stat = wxbConfigFileEditor(this, configfile).ShowModal();
529 StartConsoleThread(configfile);
533 void wxbMainFrame::OnConnect(wxCommandEvent& event) {
534 StartConsoleThread(configfile);
537 void wxbMainFrame::OnDisconnect(wxCommandEvent& event) {
544 void wxbMainFrame::OnEnter(wxCommandEvent& WXUNUSED(event))
546 lockedbyconsole = true;
548 typeCtrl->HistoryAdd(typeCtrl->GetValue());
549 wxString str = typeCtrl->GetValue() + wxT("\n");
554 * Called when data is arriving from director
556 void wxbMainFrame::OnPrint(wxbThreadEvent& event) {
557 wxbPrintObject* po = event.GetEventPrintObject();
559 Print(po->str, po->status);
563 * Prints data received from director to the console, and forwards it to the panels
565 void wxbMainFrame::Print(wxString str, int status)
567 if (lockedbyconsole) {
568 EnableConsole(false);
571 if (status == CS_REMOVEPROMPT) {
572 if (consoleCtrl->GetLastPosition() > 0) {
573 consoleCtrl->Remove(consoleCtrl->GetLastPosition()-1, consoleCtrl->GetLastPosition()+1);
578 if (status == CS_TERMINATED) {
579 consoleCtrl->AppendText(consoleBuffer);
580 consoleBuffer = wxT("");
581 SetStatusText(_("Console thread terminated."));
583 consoleCtrl->PageDown();
585 consoleCtrl->ScrollLines(1);
589 int answer = wxMessageBox( _("Connection to the director lost. Quit program?"),
590 _("Connection lost"),
591 wxYES_NO | wxICON_EXCLAMATION, this);
592 if (answer == wxYES) {
596 menuFile->Enable(MenuConnect, true);
597 menuFile->SetLabel(MenuConnect, _("Connect"));
598 menuFile->SetHelpString(MenuConnect, _("Connect to the director"));
599 menuFile->Enable(MenuDisconnect, false);
600 menuFile->Enable(ChangeConfigFile, true);
601 menuFile->Enable(EditConfigFile, true);
605 if (status == CS_CONNECTED) {
606 SetStatusText(_("Connected to the director."));
607 typeCtrl->ClearCommandList();
610 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxT(".help"), true);
614 for (i = 0; i < (int)dt->GetCount(); i++) {
617 if ((j = str.Find(' ')) > -1) {
618 typeCtrl->AddCommand(str.Mid(0, j), str.Mid(j+1));
623 if ((parsed) || (!retries))
625 dt = wxbUtils::WaitForEnd(wxT(""), true);
628 menuFile->Enable(MenuConnect, true);
629 menuFile->SetLabel(MenuConnect, _("Reconnect"));
630 menuFile->SetHelpString(MenuConnect, _("Reconnect to the director"));
631 menuFile->Enable(MenuDisconnect, true);
632 menuFile->Enable(ChangeConfigFile, true);
633 menuFile->Enable(EditConfigFile, true);
636 if (status == CS_DISCONNECTED) {
637 consoleCtrl->AppendText(consoleBuffer);
638 consoleBuffer = wxT("");
640 consoleCtrl->PageDown();
642 consoleCtrl->ScrollLines(1);
644 SetStatusText(_("Disconnected of the director."));
649 // CS_DEBUG is often sent by panels,
650 // and resend it to them would sometimes cause infinite loops
652 /* One promptcaught is normal, so we must have two true Print values to be
653 * sure that the prompt has effectively been caught.
655 int promptcaught = -1;
657 if (status != CS_DEBUG) {
658 for (unsigned int i = 0; i < parsers.GetCount(); i++) {
659 promptcaught += parsers[i]->Print(str, status) ? 1 : 0;
662 if ((status == CS_PROMPT) && (promptcaught < 1) && (promptparser->isPrompt())) {
663 Print(_("Unexpected question has been received.\n"), CS_DEBUG);
664 // Print(wxString("(") << promptparser->getIntroString() << "/-/" << promptparser->getQuestionString() << ")\n", CS_DEBUG);
667 if (promptparser->getIntroString() != wxT("")) {
668 message << promptparser->getIntroString() << wxT("\n");
670 message << promptparser->getQuestionString();
672 if (promptparser->getChoices()) {
673 wxString *choices = new wxString[promptparser->getChoices()->GetCount()];
674 int *numbers = new int[promptparser->getChoices()->GetCount()];
677 for (unsigned int i = 0; i < promptparser->getChoices()->GetCount(); i++) {
678 if ((*promptparser->getChoices())[i] != wxT("")) {
679 choices[n] = (*promptparser->getChoices())[i];
685 int res = ::wxGetSingleChoiceIndex(message,
686 _("wx-console: unexpected director's question."), n, choices, this);
687 if (res == -1) { //Cancel pressed
691 if (promptparser->isNumericalChoice()) {
692 Send(wxString() << numbers[res] << wxT("\n"));
695 Send(wxString() << choices[res] << wxT("\n"));
702 Send(::wxGetTextFromUser(message,
703 _("wx-console: unexpected director's question."),
704 wxT(""), this) + wxT("\n"));
709 if (status == CS_END) {
710 if (lockedbyconsole) {
712 lockedbyconsole = false;
717 if (status == CS_DEBUG) {
718 consoleCtrl->AppendText(consoleBuffer);
719 consoleBuffer = wxT("");
721 consoleCtrl->PageDown();
723 consoleCtrl->ScrollLines(1);
725 consoleCtrl->SetDefaultStyle(wxTextAttr(wxColour(0, 128, 0)));
728 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK));
730 consoleBuffer << wxbUtils::ConvertToPrintable(str);
731 if (status == CS_PROMPT) {
732 if (lockedbyconsole) {
735 //consoleBuffer << wxT("<P>");
738 if ((status == CS_END) || (status == CS_PROMPT) || (str.Find(wxT("\n")) > -1)) {
739 consoleCtrl->AppendText(consoleBuffer);
740 consoleBuffer = wxT("");
743 consoleCtrl->PageDown();
745 consoleCtrl->ScrollLines(1);
749 //consoleCtrl->ShowPosition(consoleCtrl->GetLastPosition());
751 /*if (status != CS_DEBUG) {
752 consoleCtrl->AppendText("@");
754 //consoleCtrl->SetInsertionPointEnd();
758 * Sends data to the director
760 void wxbMainFrame::Send(wxString str)
763 ct->Write(str.mb_str(*wxConvCurrent));
764 typeCtrl->SetValue(wxT(""));
765 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxRED));
766 consoleCtrl->AppendText(wxbUtils::ConvertToPrintable(str));
767 //consoleCtrl->PageDown();
770 /* if ((consoleCtrl->GetNumberOfLines()-1) > nlines) {
771 nlines = consoleCtrl->GetNumberOfLines()-1;
774 consoleCtrl->ShowPosition(nlines);*/
778 void wxbMainFrame::EnablePanels() {
779 for (int i = 0; panels[i] != NULL; i++) {
780 panels[i]->EnablePanel(true);
785 /* Disable panels, except the one passed as parameter */
786 void wxbMainFrame::DisablePanels(void* except) {
787 for (int i = 0; panels[i] != NULL; i++) {
788 if (panels[i] != except) {
789 panels[i]->EnablePanel(false);
792 panels[i]->EnablePanel(true);
795 if (this != except) {
796 EnableConsole(false);
800 /* Enable or disable console typing */
801 void wxbMainFrame::EnableConsole(bool enable) {
802 typeCtrl->Enable(enable);
803 sendButton->Enable(enable);
805 typeCtrl->SetFocus();
810 * Used by csprint, which is called by console thread.
812 * In GTK and perhaps X11, only the main thread is allowed to interact with
813 * graphical components, so by firing an event, the main loop will call OnPrint.
815 * Calling OnPrint directly from console thread produces "unexpected async replies".
817 void firePrintEvent(wxString str, int status)
819 wxbPrintObject* po = new wxbPrintObject(str, status);
821 wxbThreadEvent evt(Thread);
822 evt.SetEventPrintObject(po);
824 if (wxbMainFrame::GetInstance()) {
825 wxbMainFrame::GetInstance()->AddPendingEvent(evt);
829 //wxString csBuffer; /* Temporary buffer for receiving data from console thread */
832 * Called by console thread, this function forwards data line by line and end
833 * signals to the GUI.
836 void csprint(wxString str, int status)
838 firePrintEvent(str, status);
842 void csprint(const char* str, int status)
845 firePrintEvent(wxString(str,wxConvUTF8), status);
848 firePrintEvent(wxT(""), status);