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.
28 #include "wxbmainframe.h" // class's header file
30 #include "wxbrestorepanel.h"
32 #include "wxbconfigfileeditor.h"
36 #include "wxwin16x16.xpm"
38 #include <wx/arrimpl.cpp>
40 #include <wx/stattext.h>
41 #include <wx/statline.h>
42 #include <wx/config.h>
44 #include <wx/filename.h>
46 #undef Yield /* MinGW defines Yield */
48 // ----------------------------------------------------------------------------
49 // event tables and other macros for wxWindows
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 // ----------------------------------------------------------------------------
56 // IDs for the controls and the menu commands
62 // it is important for the id corresponding to the "About" command to have
63 // this standard value as otherwise it won't be handled properly under Mac
64 // (where it is special and put into the "Apple" menu)
65 Minimal_About = wxID_ABOUT,
77 * wxbTHREAD_EVENT declaration, used by csprint
79 BEGIN_DECLARE_EVENT_TYPES()
80 DECLARE_EVENT_TYPE(wxbTHREAD_EVENT, 1)
81 END_DECLARE_EVENT_TYPES()
83 DEFINE_EVENT_TYPE(wxbTHREAD_EVENT)
85 typedef void (wxEvtHandler::*wxThreadEventFunction)(wxbThreadEvent&);
87 #define EVT_THREAD_EVENT(id, fn) \
88 DECLARE_EVENT_TABLE_ENTRY( \
89 wxbTHREAD_EVENT, id, wxID_ANY, \
90 (wxObjectEventFunction)(wxEventFunction)(wxThreadEventFunction)&fn, \
94 // the event tables connect the wxWindows events with the functions (event
95 // handlers) which process them. It can be also done at run-time, but for the
96 // simple menu events like this the static method is much simpler.
97 BEGIN_EVENT_TABLE(wxbMainFrame, wxFrame)
98 EVT_MENU(Minimal_Quit, wxbMainFrame::OnQuit)
99 EVT_MENU(Minimal_About, wxbMainFrame::OnAbout)
100 EVT_MENU(ChangeConfigFile, wxbMainFrame::OnChangeConfig)
101 EVT_MENU(EditConfigFile, wxbMainFrame::OnEditConfig)
102 EVT_MENU(MenuConnect, wxbMainFrame::OnConnect)
103 EVT_MENU(MenuDisconnect, wxbMainFrame::OnDisconnect)
104 EVT_TEXT_ENTER(TypeText, wxbMainFrame::OnEnter)
105 EVT_THREAD_EVENT(Thread, wxbMainFrame::OnPrint)
106 EVT_BUTTON(SendButton, wxbMainFrame::OnEnter)
109 // ----------------------------------------------------------------------------
111 // ----------------------------------------------------------------------------
114 * wxbThreadEvent constructor
116 wxbThreadEvent::wxbThreadEvent(int id): wxEvent(id, wxbTHREAD_EVENT) {
117 m_eventObject = NULL;
121 * wxbThreadEvent destructor
123 wxbThreadEvent::~wxbThreadEvent()
125 if (m_eventObject != NULL) {
126 delete m_eventObject;
131 * wxbThreadEvent copy constructor
133 wxbThreadEvent::wxbThreadEvent(const wxbThreadEvent& te)
135 this->m_eventType = te.m_eventType;
136 this->m_id = te.m_id;
137 if (te.m_eventObject != NULL) {
138 this->m_eventObject = new wxbPrintObject(*((wxbPrintObject*)te.m_eventObject));
141 this->m_eventObject = NULL;
143 this->m_skipped = te.m_skipped;
144 this->m_timeStamp = te.m_timeStamp;
148 * Must be implemented (abstract in wxEvent)
150 wxEvent* wxbThreadEvent::Clone() const
152 return new wxbThreadEvent(*this);
156 * Gets the wxbPrintObject attached to this event, containing data sent by director
158 wxbPrintObject* wxbThreadEvent::GetEventPrintObject()
160 return (wxbPrintObject*)m_eventObject;
164 * Sets the wxbPrintObject attached to this event
166 void wxbThreadEvent::SetEventPrintObject(wxbPrintObject* object)
168 m_eventObject = (wxObject*)object;
171 // ----------------------------------------------------------------------------
173 // ----------------------------------------------------------------------------
175 wxbMainFrame *wxbMainFrame::frame = NULL;
178 * Singleton constructor
180 wxbMainFrame* wxbMainFrame::CreateInstance(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
182 frame = new wxbMainFrame(title, pos, size, style);
187 * Returns singleton instance
189 wxbMainFrame* wxbMainFrame::GetInstance()
197 wxbMainFrame::~wxbMainFrame()
199 wxConfig::Get()->Write(wxT("/Position/X"), (long)GetPosition().x);
200 wxConfig::Get()->Write(wxT("/Position/Y"), (long)GetPosition().y);
201 wxConfig::Get()->Write(wxT("/Size/Width"), (long)GetSize().GetWidth());
202 wxConfig::Get()->Write(wxT("/Size/Height"), (long)GetSize().GetHeight());
204 if (ct != NULL) { // && (!ct->IsRunning())
211 * Private constructor
213 wxbMainFrame::wxbMainFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
214 : wxFrame(NULL, -1, title, pos, size, style)
216 lockedbyconsole = false;
222 // set the frame icon
223 SetIcon(wxIcon(wxwin16x16_xpm));
227 menuFile = new wxMenu;
229 // the "About" item should be in the help menu
230 wxMenu *helpMenu = new wxMenu;
231 helpMenu->Append(Minimal_About, _("&About...\tF1"), _("Show about dialog"));
233 menuFile->Append(MenuConnect, _("Connect"), _("Connect to the director"));
234 menuFile->Append(MenuDisconnect, _("Disconnect"), _("Disconnect of the director"));
235 menuFile->AppendSeparator();
236 menuFile->Append(ChangeConfigFile, _("Change of configuration file"), _("Change your default configuration file"));
237 menuFile->Append(EditConfigFile, _("Edit your configuration file"), _("Edit your configuration file"));
238 menuFile->AppendSeparator();
239 menuFile->Append(Minimal_Quit, _("E&xit\tAlt-X"), _("Quit this program"));
241 // now append the freshly created menu to the menu bar...
242 wxMenuBar *menuBar = new wxMenuBar();
243 menuBar->Append(menuFile, _("&File"));
244 menuBar->Append(helpMenu, _("&Help"));
246 // ... and attach this menu bar to the frame
248 #endif // wxUSE_MENUS
252 SetStatusText(wxString::Format(_("Welcome to bacula wx-console %s (%s)!\n"), wxT(VERSION), wxT(BDATE)));
254 wxPanel* global = new wxPanel(this, -1);
256 notebook = new wxNotebook(global, -1);
260 wxPanel* consolePanel = new wxPanel(notebook, -1);
261 notebook->AddPage(consolePanel, _("Console"));
263 consoleCtrl = new wxTextCtrl(consolePanel,-1,wxT(""),wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH);
264 wxFont font(10, wxMODERN, wxNORMAL, wxNORMAL);
265 #if defined __WXGTK12__ && !defined __WXGTK20__ // Fix for "chinese" fonts under gtk+ 1.2
266 font.SetDefaultEncoding(wxFONTENCODING_ISO8859_1);
267 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, font));
268 Print(_("Warning : Unicode is disabled because you are using wxWidgets for GTK+ 1.2.\n"), CS_DEBUG);
270 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, font));
271 #if (wxUSE_UNICODE == 0) && __WXGTK20__
272 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);
276 helpCtrl = new wxStaticText(consolePanel, -1, _("Type your command below:"));
278 wxFlexGridSizer *consoleSizer = new wxFlexGridSizer(4, 1, 0, 0);
279 consoleSizer->AddGrowableCol(0);
280 consoleSizer->AddGrowableRow(0);
282 typeCtrl = new wxbHistoryTextCtrl(helpCtrl, consolePanel,TypeText,wxT(""),wxDefaultPosition,wxSize(200,20));
283 sendButton = new wxButton(consolePanel, SendButton, _("Send"));
285 wxFlexGridSizer *typeSizer = new wxFlexGridSizer(1, 2, 0, 0);
286 typeSizer->AddGrowableCol(0);
287 typeSizer->AddGrowableRow(0);
289 //typeSizer->Add(new wxStaticText(consolePanel, -1, _("Command: ")), 0, wxALIGN_CENTER | wxALL, 0);
290 typeSizer->Add(typeCtrl, 1, wxEXPAND | wxALL, 0);
291 typeSizer->Add(sendButton, 1, wxEXPAND | wxLEFT, 5);
293 consoleSizer->Add(consoleCtrl, 1, wxEXPAND | wxALL, 0);
294 consoleSizer->Add(new wxStaticLine(consolePanel, -1), 0, wxEXPAND | wxALL, 0);
295 consoleSizer->Add(helpCtrl, 1, wxEXPAND | wxALL, 2);
296 consoleSizer->Add(typeSizer, 0, wxEXPAND | wxALL, 2);
298 consolePanel->SetAutoLayout( TRUE );
299 consolePanel->SetSizer( consoleSizer );
300 consoleSizer->SetSizeHints( consolePanel );
302 // Creates the list of panels which are included in notebook, and that need to receive director information
304 panels = new wxbPanel* [2];
305 panels[0] = new wxbRestorePanel(notebook);
308 for (int i = 0; panels[i] != NULL; i++) {
309 notebook->AddPage(panels[i], panels[i]->GetTitle());
312 wxBoxSizer* globalSizer = new wxBoxSizer(wxHORIZONTAL);
314 #if wxCHECK_VERSION(2, 6, 0)
315 globalSizer->Add(notebook, 1, wxEXPAND, 0);
317 globalSizer->Add(new wxNotebookSizer(notebook), 1, wxEXPAND, 0);
320 global->SetSizer( globalSizer );
321 globalSizer->SetSizeHints( global );
323 wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
325 sizer->Add(global, 1, wxEXPAND | wxALL, 0);
328 sizer->SetSizeHints( this );
330 EnableConsole(false);
332 consoleBuffer = wxT("");
334 configfile = wxT("");
338 * Starts the thread interacting with the director
339 * If config is not empty, uses this config file.
341 void wxbMainFrame::StartConsoleThread(const wxString& config) {
342 menuFile->Enable(MenuConnect, false);
343 menuFile->Enable(MenuDisconnect, false);
344 menuFile->Enable(ChangeConfigFile, false);
345 menuFile->Enable(EditConfigFile, false);
352 if (promptparser == NULL) {
353 promptparser = new wxbPromptParser();
356 if (config == wxT("")) {
357 configfile = wxT("");
359 if (((wxTheApp->argc % 2) != 1)) {
360 Print(_("Error while parsing command line arguments, using defaults.\n"), CS_DEBUG);
361 Print(_("Usage: wx-console [-c configfile] [-w tmp]\n"), CS_DEBUG);
364 for (int c = 1; c < wxTheApp->argc; c += 2) {
365 if ((wxTheApp->argc >= c+2) && (wxString(wxTheApp->argv[c]) == wxT("-c"))) {
366 configfile = wxTheApp->argv[c+1];
368 if ((wxTheApp->argc >= c+2) && (wxString(wxTheApp->argv[c]) == wxT("-w"))) {
369 console_thread::SetWorkingDirectory(wxTheApp->argv[c+1]);
371 if (wxTheApp->argv[c][0] != '-') {
372 Print(_("Error while parsing command line arguments, using defaults.\n"), CS_DEBUG);
373 Print(_("Usage: wx-console [-c configfile] [-w tmp]\n"), CS_DEBUG);
379 if (configfile == wxT("")) {
380 wxConfig::Set(new wxConfig(wxT("wx-console"), wxT("bacula")));
381 if (!wxConfig::Get()->Read(wxT("/ConfigFile"), &configfile)) {
383 wxFileName filename(::wxGetHomeDir());
384 filename.MakeAbsolute();
385 configfile = filename.GetLongPath();
386 if (configfile.Last() != '/')
388 configfile += "Library/Preferences/org.bacula.wxconsole.conf";
390 wxFileName filename(::wxGetCwd(), wxT("wx-console.conf"));
391 filename.MakeAbsolute();
392 configfile = filename.GetLongPath();
394 configfile.Replace(wxT("\\"), wxT("/"));
397 wxConfig::Get()->Write(wxT("/ConfigFile"), configfile);
399 int answer = wxMessageBox(
401 "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)"),
404 wxYES_NO | wxICON_QUESTION, this);
405 if (answer == wxYES) {
406 wxbConfigFileEditor(this, configfile).ShowModal();
415 wxString err = console_thread::LoadConfig(configfile);
417 while (err != wxT("")) {
418 int answer = wxMessageBox(
420 "Unable to read %s\nError: %s\nDo you want to choose another one? (Press no to edit this file)"),
421 configfile.c_str(), err.c_str()),
422 _("Unable to read configuration file"),
423 wxYES_NO | wxCANCEL | wxICON_ERROR, this);
424 if (answer == wxNO) {
425 wxbConfigFileEditor(this, configfile).ShowModal();
426 err = console_thread::LoadConfig(configfile);
428 else if (answer == wxCANCEL) {
433 else { // (answer == wxYES)
434 configfile = wxFileSelector(_("Please choose a configuration file to use"));
435 if ( !configfile.empty() ) {
436 err = console_thread::LoadConfig(configfile);
445 if ((err == wxT("")) && (config == wxT(""))) {
446 answer = wxMessageBox(
447 _("This configuration file has been successfully read, use it as default?"),
448 _("Configuration file read successfully"),
449 wxYES_NO | wxICON_QUESTION, this);
450 if (answer == wxYES) {
451 wxConfigBase::Get()->Write(wxT("/ConfigFile"), configfile);
457 // former was csprint
458 Print(wxString::Format(_("Using this configuration file: %s\n"), configfile.c_str()), CS_DEBUG);
460 ct = new console_thread();
463 SetStatusText(_("Connecting to the director..."));
466 /* Register a new wxbDataParser */
467 void wxbMainFrame::Register(wxbDataParser* dp) {
471 /* Unregister a wxbDataParser */
472 void wxbMainFrame::Unregister(wxbDataParser* dp) {
474 if ((index = parsers.Index(dp)) != wxNOT_FOUND) {
475 parsers.RemoveAt(index);
478 Print(_("Failed to unregister a data parser !"), CS_DEBUG);
484 void wxbMainFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
486 Print(_("Quitting.\n"), CS_DEBUG);
492 console_thread::FreeLib();
498 void wxbMainFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
501 msg.Printf(_("Welcome to Bacula wx-console.\nWritten by Nicolas Boichat <nicolas@boichat.ch>\n(C) 2005 Kern Sibbald\n"));
503 wxMessageBox(msg, _("About Bacula wx-console"), wxOK | wxICON_INFORMATION, this);
506 void wxbMainFrame::OnChangeConfig(wxCommandEvent& event) {
507 wxString oriconfigfile;
508 wxConfig::Get()->Read(wxT("/ConfigFile"), &oriconfigfile);
509 wxString configfile = wxFileSelector(_("Please choose your default configuration file"));
510 if ( !configfile.empty() ) {
511 if (oriconfigfile != configfile) {
512 int answer = wxMessageBox(
513 _("Use this configuration file as default?"),
514 _("Configuration file"),
515 wxYES_NO | wxICON_QUESTION, this);
516 if (answer == wxYES) {
517 wxConfigBase::Get()->Write(wxT("/ConfigFile"), configfile);
518 wxConfigBase::Get()->Flush();
519 StartConsoleThread(wxT(""));
524 StartConsoleThread(configfile);
528 void wxbMainFrame::OnEditConfig(wxCommandEvent& event) {
530 wxConfig::Get()->Read(wxT("/ConfigFile"), &configfile);
531 int stat = wxbConfigFileEditor(this, configfile).ShowModal();
533 StartConsoleThread(configfile);
537 void wxbMainFrame::OnConnect(wxCommandEvent& event) {
538 StartConsoleThread(configfile);
541 void wxbMainFrame::OnDisconnect(wxCommandEvent& event) {
548 void wxbMainFrame::OnEnter(wxCommandEvent& WXUNUSED(event))
550 lockedbyconsole = true;
552 typeCtrl->HistoryAdd(typeCtrl->GetValue());
553 wxString str = typeCtrl->GetValue() + wxT("\n");
558 * Called when data is arriving from director
560 void wxbMainFrame::OnPrint(wxbThreadEvent& event) {
561 wxbPrintObject* po = event.GetEventPrintObject();
563 Print(po->str, po->status);
567 * Prints data received from director to the console, and forwards it to the panels
569 void wxbMainFrame::Print(wxString str, int status)
571 if (lockedbyconsole) {
572 EnableConsole(false);
575 if (status == CS_REMOVEPROMPT) {
576 if (consoleCtrl->GetLastPosition() > 0) {
577 consoleCtrl->Remove(consoleCtrl->GetLastPosition()-1, consoleCtrl->GetLastPosition()+1);
582 if (status == CS_TERMINATED) {
583 consoleCtrl->AppendText(consoleBuffer);
584 consoleBuffer = wxT("");
585 SetStatusText(_("Console thread terminated."));
587 consoleCtrl->PageDown();
589 consoleCtrl->ScrollLines(1);
593 int answer = wxMessageBox( _("Connection to the director lost. Quit program?"),
594 _("Connection lost"),
595 wxYES_NO | wxICON_EXCLAMATION, this);
596 if (answer == wxYES) {
600 menuFile->Enable(MenuConnect, true);
601 menuFile->SetLabel(MenuConnect, _("Connect"));
602 menuFile->SetHelpString(MenuConnect, _("Connect to the director"));
603 menuFile->Enable(MenuDisconnect, false);
604 menuFile->Enable(ChangeConfigFile, true);
605 menuFile->Enable(EditConfigFile, true);
609 if (status == CS_CONNECTED) {
610 SetStatusText(_("Connected to the director."));
611 typeCtrl->ClearCommandList();
614 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxT(".help"), true);
618 for (i = 0; i < (int)dt->GetCount(); i++) {
621 if ((j = str.Find(' ')) > -1) {
622 typeCtrl->AddCommand(str.Mid(0, j), str.Mid(j+1));
627 if ((parsed) || (!retries))
629 dt = wxbUtils::WaitForEnd(wxT(""), true);
632 menuFile->Enable(MenuConnect, true);
633 menuFile->SetLabel(MenuConnect, _("Reconnect"));
634 menuFile->SetHelpString(MenuConnect, _("Reconnect to the director"));
635 menuFile->Enable(MenuDisconnect, true);
636 menuFile->Enable(ChangeConfigFile, true);
637 menuFile->Enable(EditConfigFile, true);
640 if (status == CS_DISCONNECTED) {
641 consoleCtrl->AppendText(consoleBuffer);
642 consoleBuffer = wxT("");
644 consoleCtrl->PageDown();
646 consoleCtrl->ScrollLines(1);
648 SetStatusText(_("Disconnected of the director."));
653 // CS_DEBUG is often sent by panels,
654 // and resend it to them would sometimes cause infinite loops
656 /* One promptcaught is normal, so we must have two true Print values to be
657 * sure that the prompt has effectively been caught.
659 int promptcaught = -1;
661 if (status != CS_DEBUG) {
662 for (unsigned int i = 0; i < parsers.GetCount(); i++) {
663 promptcaught += parsers[i]->Print(str, status) ? 1 : 0;
666 if ((status == CS_PROMPT) && (promptcaught < 1) && (promptparser->isPrompt())) {
667 Print(_("Unexpected question has been received.\n"), CS_DEBUG);
668 // Print(wxString("(") << promptparser->getIntroString() << "/-/" << promptparser->getQuestionString() << ")\n", CS_DEBUG);
671 if (promptparser->getIntroString() != wxT("")) {
672 message << promptparser->getIntroString() << wxT("\n");
674 message << promptparser->getQuestionString();
676 if (promptparser->getChoices()) {
677 wxString *choices = new wxString[promptparser->getChoices()->GetCount()];
678 int *numbers = new int[promptparser->getChoices()->GetCount()];
681 for (unsigned int i = 0; i < promptparser->getChoices()->GetCount(); i++) {
682 if ((*promptparser->getChoices())[i] != wxT("")) {
683 choices[n] = (*promptparser->getChoices())[i];
689 int res = ::wxGetSingleChoiceIndex(message,
690 _("wx-console: unexpected director's question."), n, choices, this);
691 if (res == -1) { //Cancel pressed
695 if (promptparser->isNumericalChoice()) {
696 Send(wxString() << numbers[res] << wxT("\n"));
699 Send(wxString() << choices[res] << wxT("\n"));
706 Send(::wxGetTextFromUser(message,
707 _("wx-console: unexpected director's question."),
708 wxT(""), this) + wxT("\n"));
713 if (status == CS_END) {
714 if (lockedbyconsole) {
716 lockedbyconsole = false;
721 if (status == CS_DEBUG) {
722 consoleCtrl->AppendText(consoleBuffer);
723 consoleBuffer = wxT("");
725 consoleCtrl->PageDown();
727 consoleCtrl->ScrollLines(1);
729 consoleCtrl->SetDefaultStyle(wxTextAttr(wxColour(0, 128, 0)));
732 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK));
734 consoleBuffer << wxbUtils::ConvertToPrintable(str);
735 if (status == CS_PROMPT) {
736 if (lockedbyconsole) {
739 //consoleBuffer << wxT("<P>");
742 if ((status == CS_END) || (status == CS_PROMPT) || (str.Find(wxT("\n")) > -1)) {
743 consoleCtrl->AppendText(consoleBuffer);
744 consoleBuffer = wxT("");
747 consoleCtrl->PageDown();
749 consoleCtrl->ScrollLines(1);
753 //consoleCtrl->ShowPosition(consoleCtrl->GetLastPosition());
755 /*if (status != CS_DEBUG) {
756 consoleCtrl->AppendText("@");
758 //consoleCtrl->SetInsertionPointEnd();
762 * Sends data to the director
764 void wxbMainFrame::Send(wxString str)
767 /* wxString may contain everything in UNICODE
768 * -> convert to UTF-8 and send to director
770 ct->Write (str.mb_str(wxConvUTF8));
771 typeCtrl->SetValue(wxT(""));
772 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxRED));
773 consoleCtrl->AppendText(wxbUtils::ConvertToPrintable(str));
774 //consoleCtrl->PageDown();
777 /* if ((consoleCtrl->GetNumberOfLines()-1) > nlines) {
778 nlines = consoleCtrl->GetNumberOfLines()-1;
781 consoleCtrl->ShowPosition(nlines);*/
785 void wxbMainFrame::EnablePanels() {
786 for (int i = 0; panels[i] != NULL; i++) {
787 panels[i]->EnablePanel(true);
792 /* Disable panels, except the one passed as parameter */
793 void wxbMainFrame::DisablePanels(void* except) {
794 for (int i = 0; panels[i] != NULL; i++) {
795 if (panels[i] != except) {
796 panels[i]->EnablePanel(false);
799 panels[i]->EnablePanel(true);
802 if (this != except) {
803 EnableConsole(false);
807 /* Enable or disable console typing */
808 void wxbMainFrame::EnableConsole(bool enable) {
809 typeCtrl->Enable(enable);
810 sendButton->Enable(enable);
812 typeCtrl->SetFocus();
817 * Used by csprint, which is called by console thread.
819 * In GTK and perhaps X11, only the main thread is allowed to interact with
820 * graphical components, so by firing an event, the main loop will call OnPrint.
822 * Calling OnPrint directly from console thread produces "unexpected async replies".
824 void firePrintEvent(wxString str, int status)
826 wxbPrintObject* po = new wxbPrintObject(str, status);
828 wxbThreadEvent evt(Thread);
829 evt.SetEventPrintObject(po);
831 if (wxbMainFrame::GetInstance()) {
832 wxbMainFrame::GetInstance()->AddPendingEvent(evt);
836 //wxString csBuffer; /* Temporary buffer for receiving data from console thread */
839 * Called by console thread, this function forwards data line by line and end
840 * signals to the GUI.
843 void csprint(wxString str, int status)
845 firePrintEvent(str, status);
849 void csprint(const char* str, int status)
852 firePrintEvent(wxString(str,wxConvUTF8), status);
855 firePrintEvent(wxT(""), status);