5 * Nicolas Boichat, July 2004
10 Copyright (C) 2004-2006 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 /* Windows debug builds set _DEBUG which is used by wxWidgets to select their
25 * debug memory allocator. Unfortunately it conflicts with Bacula's SmartAlloc.
26 * So we turn _DEBUG off since we aren't interested in things it enables.
33 #include "wxbmainframe.h" // class's header file
35 #include "wxbrestorepanel.h"
37 #include "wxbconfigfileeditor.h"
41 #include "wxwin16x16.xpm"
43 #include <wx/arrimpl.cpp>
45 #include <wx/stattext.h>
46 #include <wx/statline.h>
47 #include <wx/config.h>
49 #include <wx/filename.h>
51 #undef Yield /* MinGW defines Yield */
53 // ----------------------------------------------------------------------------
54 // event tables and other macros for wxWindows
55 // ----------------------------------------------------------------------------
57 // ----------------------------------------------------------------------------
59 // ----------------------------------------------------------------------------
61 // IDs for the controls and the menu commands
67 // it is important for the id corresponding to the "About" command to have
68 // this standard value as otherwise it won't be handled properly under Mac
69 // (where it is special and put into the "Apple" menu)
70 Minimal_About = wxID_ABOUT,
82 * wxbTHREAD_EVENT declaration, used by csprint
85 DEFINE_EVENT_TYPE(wxbTHREAD_EVENT)
87 typedef void (wxEvtHandler::*wxThreadEventFunction)(wxbThreadEvent&);
89 #define EVT_THREAD_EVENT(id, fn) \
90 DECLARE_EVENT_TABLE_ENTRY( \
91 wxbTHREAD_EVENT, id, wxID_ANY, \
92 (wxObjectEventFunction)(wxEventFunction)(wxThreadEventFunction)&fn, \
96 // the event tables connect the wxWindows events with the functions (event
97 // handlers) which process them. It can be also done at run-time, but for the
98 // simple menu events like this the static method is much simpler.
99 BEGIN_EVENT_TABLE(wxbMainFrame, wxFrame)
100 EVT_MENU(Minimal_Quit, wxbMainFrame::OnQuit)
101 EVT_MENU(Minimal_About, wxbMainFrame::OnAbout)
102 EVT_MENU(ChangeConfigFile, wxbMainFrame::OnChangeConfig)
103 EVT_MENU(EditConfigFile, wxbMainFrame::OnEditConfig)
104 EVT_MENU(MenuConnect, wxbMainFrame::OnConnect)
105 EVT_MENU(MenuDisconnect, wxbMainFrame::OnDisconnect)
106 EVT_TEXT_ENTER(TypeText, wxbMainFrame::OnEnter)
107 EVT_THREAD_EVENT(Thread, wxbMainFrame::OnPrint)
108 EVT_BUTTON(SendButton, wxbMainFrame::OnEnter)
111 // ----------------------------------------------------------------------------
113 // ----------------------------------------------------------------------------
116 * wxbThreadEvent constructor
118 wxbThreadEvent::wxbThreadEvent(int id): wxEvent(id, wxbTHREAD_EVENT) {
119 m_eventObject = NULL;
123 * wxbThreadEvent destructor
125 wxbThreadEvent::~wxbThreadEvent()
127 if (m_eventObject != NULL) {
128 delete m_eventObject;
133 * wxbThreadEvent copy constructor
135 wxbThreadEvent::wxbThreadEvent(const wxbThreadEvent& te)
137 this->m_eventType = te.m_eventType;
138 this->m_id = te.m_id;
139 if (te.m_eventObject != NULL) {
140 this->m_eventObject = new wxbPrintObject(*((wxbPrintObject*)te.m_eventObject));
143 this->m_eventObject = NULL;
145 this->m_skipped = te.m_skipped;
146 this->m_timeStamp = te.m_timeStamp;
150 * Must be implemented (abstract in wxEvent)
152 wxEvent* wxbThreadEvent::Clone() const
154 return new wxbThreadEvent(*this);
158 * Gets the wxbPrintObject attached to this event, containing data sent by director
160 wxbPrintObject* wxbThreadEvent::GetEventPrintObject()
162 return (wxbPrintObject*)m_eventObject;
166 * Sets the wxbPrintObject attached to this event
168 void wxbThreadEvent::SetEventPrintObject(wxbPrintObject* object)
170 m_eventObject = (wxObject*)object;
173 // ----------------------------------------------------------------------------
175 // ----------------------------------------------------------------------------
177 wxbMainFrame *wxbMainFrame::frame = NULL;
180 * Singleton constructor
182 wxbMainFrame* wxbMainFrame::CreateInstance(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
184 frame = new wxbMainFrame(title, pos, size, style);
189 * Returns singleton instance
191 wxbMainFrame* wxbMainFrame::GetInstance()
199 wxbMainFrame::~wxbMainFrame()
201 wxConfig::Get()->Write(wxT("/Position/X"), (long)GetPosition().x);
202 wxConfig::Get()->Write(wxT("/Position/Y"), (long)GetPosition().y);
203 wxConfig::Get()->Write(wxT("/Size/Width"), (long)GetSize().GetWidth());
204 wxConfig::Get()->Write(wxT("/Size/Height"), (long)GetSize().GetHeight());
206 if (ct != NULL) { // && (!ct->IsRunning())
213 * Private constructor
215 wxbMainFrame::wxbMainFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
216 : wxFrame(NULL, -1, title, pos, size, style)
218 lockedbyconsole = false;
224 // set the frame icon
225 SetIcon(wxIcon(wxwin16x16_xpm));
229 menuFile = new wxMenu;
231 // the "About" item should be in the help menu
232 wxMenu *helpMenu = new wxMenu;
233 helpMenu->Append(Minimal_About, _("&About...\tF1"), _("Show about dialog"));
235 menuFile->Append(MenuConnect, _("Connect"), _("Connect to the director"));
236 menuFile->Append(MenuDisconnect, _("Disconnect"), _("Disconnect of the director"));
237 menuFile->AppendSeparator();
238 menuFile->Append(ChangeConfigFile, _("Change of configuration file"), _("Change your default configuration file"));
239 menuFile->Append(EditConfigFile, _("Edit your configuration file"), _("Edit your configuration file"));
240 menuFile->AppendSeparator();
241 menuFile->Append(Minimal_Quit, _("E&xit\tAlt-X"), _("Quit this program"));
243 // now append the freshly created menu to the menu bar...
244 wxMenuBar *menuBar = new wxMenuBar();
245 menuBar->Append(menuFile, _("&File"));
246 menuBar->Append(helpMenu, _("&Help"));
248 // ... and attach this menu bar to the frame
250 #endif // wxUSE_MENUS
254 SetStatusText(wxString::Format(_("Welcome to bacula wx-console %s (%s)!\n"), wxT(VERSION), wxT(BDATE)));
256 wxPanel* global = new wxPanel(this, -1);
258 notebook = new wxNotebook(global, -1);
262 wxPanel* consolePanel = new wxPanel(notebook, -1);
263 notebook->AddPage(consolePanel, _("Console"));
265 consoleCtrl = new wxTextCtrl(consolePanel,-1,wxT(""),wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH);
266 wxFont font(10, wxMODERN, wxNORMAL, wxNORMAL);
267 #if defined __WXGTK12__ && !defined __WXGTK20__ // Fix for "chinese" fonts under gtk+ 1.2
268 font.SetDefaultEncoding(wxFONTENCODING_ISO8859_1);
269 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, font));
270 Print(_("Warning : Unicode is disabled because you are using wxWidgets for GTK+ 1.2.\n"), CS_DEBUG);
272 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, font));
273 #if (wxUSE_UNICODE == 0) && __WXGTK20__
274 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);
278 helpCtrl = new wxStaticText(consolePanel, -1, _("Type your command below:"));
280 wxFlexGridSizer *consoleSizer = new wxFlexGridSizer(4, 1, 0, 0);
281 consoleSizer->AddGrowableCol(0);
282 consoleSizer->AddGrowableRow(0);
284 typeCtrl = new wxbHistoryTextCtrl(helpCtrl, consolePanel,TypeText,wxT(""),wxDefaultPosition,wxSize(200,20));
285 sendButton = new wxButton(consolePanel, SendButton, _("Send"));
287 wxFlexGridSizer *typeSizer = new wxFlexGridSizer(1, 2, 0, 0);
288 typeSizer->AddGrowableCol(0);
289 typeSizer->AddGrowableRow(0);
291 //typeSizer->Add(new wxStaticText(consolePanel, -1, _("Command: ")), 0, wxALIGN_CENTER | wxALL, 0);
292 typeSizer->Add(typeCtrl, 1, wxEXPAND | wxALL, 0);
293 typeSizer->Add(sendButton, 1, wxEXPAND | wxLEFT, 5);
295 consoleSizer->Add(consoleCtrl, 1, wxEXPAND | wxALL, 0);
296 consoleSizer->Add(new wxStaticLine(consolePanel, -1), 0, wxEXPAND | wxALL, 0);
297 consoleSizer->Add(helpCtrl, 1, wxEXPAND | wxALL, 2);
298 consoleSizer->Add(typeSizer, 0, wxEXPAND | wxALL, 2);
300 consolePanel->SetAutoLayout( TRUE );
301 consolePanel->SetSizer( consoleSizer );
302 consoleSizer->SetSizeHints( consolePanel );
304 // Creates the list of panels which are included in notebook, and that need to receive director information
306 panels = new wxbPanel* [2];
307 panels[0] = new wxbRestorePanel(notebook);
310 for (int i = 0; panels[i] != NULL; i++) {
311 notebook->AddPage(panels[i], panels[i]->GetTitle());
314 wxBoxSizer* globalSizer = new wxBoxSizer(wxHORIZONTAL);
316 #if wxCHECK_VERSION(2, 6, 0)
317 globalSizer->Add(notebook, 1, wxEXPAND, 0);
319 globalSizer->Add(new wxNotebookSizer(notebook), 1, wxEXPAND, 0);
322 global->SetSizer( globalSizer );
323 globalSizer->SetSizeHints( global );
325 wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
327 sizer->Add(global, 1, wxEXPAND | wxALL, 0);
330 sizer->SetSizeHints( this );
332 EnableConsole(false);
334 consoleBuffer = wxT("");
336 configfile = wxT("");
340 * Starts the thread interacting with the director
341 * If config is not empty, uses this config file.
343 void wxbMainFrame::StartConsoleThread(const wxString& config) {
344 menuFile->Enable(MenuConnect, false);
345 menuFile->Enable(MenuDisconnect, false);
346 menuFile->Enable(ChangeConfigFile, false);
347 menuFile->Enable(EditConfigFile, false);
354 if (promptparser == NULL) {
355 promptparser = new wxbPromptParser();
358 if (config == wxT("")) {
359 configfile = wxT("");
361 if (((wxTheApp->argc % 2) != 1)) {
362 Print(_("Error while parsing command line arguments, using defaults.\n"), CS_DEBUG);
363 Print(_("Usage: wx-console [-c configfile] [-w tmp]\n"), CS_DEBUG);
366 for (int c = 1; c < wxTheApp->argc; c += 2) {
367 if ((wxTheApp->argc >= c+2) && (wxString(wxTheApp->argv[c]) == wxT("-c"))) {
368 configfile = wxTheApp->argv[c+1];
370 if ((wxTheApp->argc >= c+2) && (wxString(wxTheApp->argv[c]) == wxT("-w"))) {
371 console_thread::SetWorkingDirectory(wxTheApp->argv[c+1]);
373 if (wxTheApp->argv[c][0] != '-') {
374 Print(_("Error while parsing command line arguments, using defaults.\n"), CS_DEBUG);
375 Print(_("Usage: wx-console [-c configfile] [-w tmp]\n"), CS_DEBUG);
381 if (configfile == wxT("")) {
382 wxConfig::Set(new wxConfig(wxT("wx-console"), wxT("bacula")));
383 if (!wxConfig::Get()->Read(wxT("/ConfigFile"), &configfile)) {
385 wxFileName filename(::wxGetHomeDir());
386 filename.MakeAbsolute();
387 configfile = filename.GetLongPath();
388 if (!IsPathSeparator(configfile.Last())
390 configfile += "Library/Preferences/org.bacula.wxconsole.conf";
392 wxFileName filename(::wxGetCwd(), wxT("wx-console.conf"));
393 filename.MakeAbsolute();
394 configfile = filename.GetLongPath();
396 configfile.Replace(wxT("\\"), wxT("/"));
399 wxConfig::Get()->Write(wxT("/ConfigFile"), configfile);
401 int answer = wxMessageBox(
403 "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)"),
406 wxYES_NO | wxICON_QUESTION, this);
407 if (answer == wxYES) {
408 wxbConfigFileEditor(this, configfile).ShowModal();
417 wxString err = console_thread::LoadConfig(configfile);
419 while (err != wxT("")) {
420 int answer = wxMessageBox(
422 "Unable to read %s\nError: %s\nDo you want to choose another one? (Press no to edit this file)"),
423 configfile.c_str(), err.c_str()),
424 _("Unable to read configuration file"),
425 wxYES_NO | wxCANCEL | wxICON_ERROR, this);
426 if (answer == wxNO) {
427 wxbConfigFileEditor(this, configfile).ShowModal();
428 err = console_thread::LoadConfig(configfile);
430 else if (answer == wxCANCEL) {
435 else { // (answer == wxYES)
436 configfile = wxFileSelector(_("Please choose a configuration file to use"));
437 if ( !configfile.empty() ) {
438 err = console_thread::LoadConfig(configfile);
447 if ((err == wxT("")) && (config == wxT(""))) {
448 answer = wxMessageBox(
449 _("This configuration file has been successfully read, use it as default?"),
450 _("Configuration file read successfully"),
451 wxYES_NO | wxICON_QUESTION, this);
452 if (answer == wxYES) {
453 wxConfigBase::Get()->Write(wxT("/ConfigFile"), configfile);
459 // former was csprint
460 Print(wxString::Format(_("Using this configuration file: %s\n"), configfile.c_str()), CS_DEBUG);
462 ct = new console_thread();
465 SetStatusText(_("Connecting to the director..."));
468 /* Register a new wxbDataParser */
469 void wxbMainFrame::Register(wxbDataParser* dp) {
473 /* Unregister a wxbDataParser */
474 void wxbMainFrame::Unregister(wxbDataParser* dp) {
476 if ((index = parsers.Index(dp)) != wxNOT_FOUND) {
477 parsers.RemoveAt(index);
480 Print(_("Failed to unregister a data parser !"), CS_DEBUG);
486 void wxbMainFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
488 Print(_("Quitting.\n"), CS_DEBUG);
494 console_thread::FreeLib();
500 void wxbMainFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
503 msg.Printf(_("Welcome to Bacula wx-console.\nWritten by Nicolas Boichat <nicolas@boichat.ch>\n(C) 2005 Kern Sibbald\n"));
505 wxMessageBox(msg, _("About Bacula wx-console"), wxOK | wxICON_INFORMATION, this);
508 void wxbMainFrame::OnChangeConfig(wxCommandEvent& event) {
509 wxString oriconfigfile;
510 wxConfig::Get()->Read(wxT("/ConfigFile"), &oriconfigfile);
511 wxString configfile = wxFileSelector(_("Please choose your default configuration file"));
512 if ( !configfile.empty() ) {
513 if (oriconfigfile != configfile) {
514 int answer = wxMessageBox(
515 _("Use this configuration file as default?"),
516 _("Configuration file"),
517 wxYES_NO | wxICON_QUESTION, this);
518 if (answer == wxYES) {
519 wxConfigBase::Get()->Write(wxT("/ConfigFile"), configfile);
520 wxConfigBase::Get()->Flush();
521 StartConsoleThread(wxT(""));
526 StartConsoleThread(configfile);
530 void wxbMainFrame::OnEditConfig(wxCommandEvent& event) {
532 wxConfig::Get()->Read(wxT("/ConfigFile"), &configfile);
533 int stat = wxbConfigFileEditor(this, configfile).ShowModal();
535 StartConsoleThread(configfile);
539 void wxbMainFrame::OnConnect(wxCommandEvent& event) {
540 StartConsoleThread(configfile);
543 void wxbMainFrame::OnDisconnect(wxCommandEvent& event) {
550 void wxbMainFrame::OnEnter(wxCommandEvent& WXUNUSED(event))
552 lockedbyconsole = true;
554 typeCtrl->HistoryAdd(typeCtrl->GetValue());
555 wxString str = typeCtrl->GetValue() + wxT("\n");
560 * Called when data is arriving from director
562 void wxbMainFrame::OnPrint(wxbThreadEvent& event) {
563 wxbPrintObject* po = event.GetEventPrintObject();
565 Print(po->str, po->status);
569 * Prints data received from director to the console, and forwards it to the panels
571 void wxbMainFrame::Print(wxString str, int status)
573 if (lockedbyconsole) {
574 EnableConsole(false);
577 if (status == CS_REMOVEPROMPT) {
578 if (consoleCtrl->GetLastPosition() > 0) {
579 consoleCtrl->Remove(consoleCtrl->GetLastPosition()-1, consoleCtrl->GetLastPosition()+1);
584 if (status == CS_TERMINATED) {
585 consoleCtrl->AppendText(consoleBuffer);
586 consoleBuffer = wxT("");
587 SetStatusText(_("Console thread terminated."));
589 consoleCtrl->PageDown();
591 consoleCtrl->ScrollLines(1);
595 int answer = wxMessageBox( _("Connection to the director lost. Quit program?"),
596 _("Connection lost"),
597 wxYES_NO | wxICON_EXCLAMATION, this);
598 if (answer == wxYES) {
602 menuFile->Enable(MenuConnect, true);
603 menuFile->SetLabel(MenuConnect, _("Connect"));
604 menuFile->SetHelpString(MenuConnect, _("Connect to the director"));
605 menuFile->Enable(MenuDisconnect, false);
606 menuFile->Enable(ChangeConfigFile, true);
607 menuFile->Enable(EditConfigFile, true);
611 if (status == CS_CONNECTED) {
612 SetStatusText(_("Connected to the director."));
613 typeCtrl->ClearCommandList();
616 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxT(".help"), true);
620 for (i = 0; i < (int)dt->GetCount(); i++) {
623 if ((j = str.Find(' ')) > -1) {
624 typeCtrl->AddCommand(str.Mid(0, j), str.Mid(j+1));
629 if ((parsed) || (!retries))
631 dt = wxbUtils::WaitForEnd(wxT(""), true);
634 menuFile->Enable(MenuConnect, true);
635 menuFile->SetLabel(MenuConnect, _("Reconnect"));
636 menuFile->SetHelpString(MenuConnect, _("Reconnect to the director"));
637 menuFile->Enable(MenuDisconnect, true);
638 menuFile->Enable(ChangeConfigFile, true);
639 menuFile->Enable(EditConfigFile, true);
642 if (status == CS_DISCONNECTED) {
643 consoleCtrl->AppendText(consoleBuffer);
644 consoleBuffer = wxT("");
646 consoleCtrl->PageDown();
648 consoleCtrl->ScrollLines(1);
650 SetStatusText(_("Disconnected of the director."));
655 // CS_DEBUG is often sent by panels,
656 // and resend it to them would sometimes cause infinite loops
658 /* One promptcaught is normal, so we must have two true Print values to be
659 * sure that the prompt has effectively been caught.
661 int promptcaught = -1;
663 if (status != CS_DEBUG) {
664 for (unsigned int i = 0; i < parsers.GetCount(); i++) {
665 promptcaught += parsers[i]->Print(str, status) ? 1 : 0;
668 if ((status == CS_PROMPT) && (promptcaught < 1) && (promptparser->isPrompt())) {
669 Print(_("Unexpected question has been received.\n"), CS_DEBUG);
670 // Print(wxString("(") << promptparser->getIntroString() << "/-/" << promptparser->getQuestionString() << ")\n", CS_DEBUG);
673 if (promptparser->getIntroString() != wxT("")) {
674 message << promptparser->getIntroString() << wxT("\n");
676 message << promptparser->getQuestionString();
678 if (promptparser->getChoices()) {
679 wxString *choices = new wxString[promptparser->getChoices()->GetCount()];
680 int *numbers = new int[promptparser->getChoices()->GetCount()];
683 for (unsigned int i = 0; i < promptparser->getChoices()->GetCount(); i++) {
684 if ((*promptparser->getChoices())[i] != wxT("")) {
685 choices[n] = (*promptparser->getChoices())[i];
691 int res = ::wxGetSingleChoiceIndex(message,
692 _("wx-console: unexpected director's question."), n, choices, this);
693 if (res == -1) { //Cancel pressed
697 if (promptparser->isNumericalChoice()) {
698 Send(wxString() << numbers[res] << wxT("\n"));
701 Send(wxString() << choices[res] << wxT("\n"));
708 Send(::wxGetTextFromUser(message,
709 _("wx-console: unexpected director's question."),
710 wxT(""), this) + wxT("\n"));
715 if (status == CS_END) {
716 if (lockedbyconsole) {
718 lockedbyconsole = false;
723 if (status == CS_DEBUG) {
724 consoleCtrl->AppendText(consoleBuffer);
725 consoleBuffer = wxT("");
727 consoleCtrl->PageDown();
729 consoleCtrl->ScrollLines(1);
731 consoleCtrl->SetDefaultStyle(wxTextAttr(wxColour(0, 128, 0)));
734 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK));
736 consoleBuffer << wxbUtils::ConvertToPrintable(str);
737 if (status == CS_PROMPT) {
738 if (lockedbyconsole) {
741 //consoleBuffer << wxT("<P>");
744 if ((status == CS_END) || (status == CS_PROMPT) || (str.Find(wxT("\n")) > -1)) {
745 consoleCtrl->AppendText(consoleBuffer);
746 consoleBuffer = wxT("");
749 consoleCtrl->PageDown();
751 consoleCtrl->ScrollLines(1);
755 //consoleCtrl->ShowPosition(consoleCtrl->GetLastPosition());
757 /*if (status != CS_DEBUG) {
758 consoleCtrl->AppendText("@");
760 //consoleCtrl->SetInsertionPointEnd();
764 * Sends data to the director
766 void wxbMainFrame::Send(wxString str)
769 /* wxString may contain everything in UNICODE
770 * -> convert to UTF-8 and send to director
772 ct->Write (str.mb_str(wxConvUTF8));
773 typeCtrl->SetValue(wxT(""));
774 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxRED));
775 consoleCtrl->AppendText(wxbUtils::ConvertToPrintable(str));
776 //consoleCtrl->PageDown();
779 /* if ((consoleCtrl->GetNumberOfLines()-1) > nlines) {
780 nlines = consoleCtrl->GetNumberOfLines()-1;
783 consoleCtrl->ShowPosition(nlines);*/
787 void wxbMainFrame::EnablePanels() {
788 for (int i = 0; panels[i] != NULL; i++) {
789 panels[i]->EnablePanel(true);
794 /* Disable panels, except the one passed as parameter */
795 void wxbMainFrame::DisablePanels(void* except) {
796 for (int i = 0; panels[i] != NULL; i++) {
797 if (panels[i] != except) {
798 panels[i]->EnablePanel(false);
801 panels[i]->EnablePanel(true);
804 if (this != except) {
805 EnableConsole(false);
809 /* Enable or disable console typing */
810 void wxbMainFrame::EnableConsole(bool enable) {
811 typeCtrl->Enable(enable);
812 sendButton->Enable(enable);
814 typeCtrl->SetFocus();
819 * Used by csprint, which is called by console thread.
821 * In GTK and perhaps X11, only the main thread is allowed to interact with
822 * graphical components, so by firing an event, the main loop will call OnPrint.
824 * Calling OnPrint directly from console thread produces "unexpected async replies".
826 void firePrintEvent(wxString str, int status)
828 wxbPrintObject* po = new wxbPrintObject(str, status);
830 wxbThreadEvent evt(Thread);
831 evt.SetEventPrintObject(po);
833 if (wxbMainFrame::GetInstance()) {
834 wxbMainFrame::GetInstance()->AddPendingEvent(evt);
838 //wxString csBuffer; /* Temporary buffer for receiving data from console thread */
841 * Called by console thread, this function forwards data line by line and end
842 * signals to the GUI.
845 void csprint(wxString str, int status)
847 firePrintEvent(str, status);
851 void csprint(const char* str, int status)
854 firePrintEvent(wxString(str,wxConvUTF8), status);
857 firePrintEvent(wxT(""), status);