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 ammended 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, _T("&About...\tF1"), _T("Show about dialog"));
229 menuFile->Append(MenuConnect, _T("Connect"), _T("Connect to the director"));
230 menuFile->Append(MenuDisconnect, _T("Disconnect"), _T("Disconnect of the director"));
231 menuFile->AppendSeparator();
232 menuFile->Append(ChangeConfigFile, _T("Change of configuration file"), _T("Change your default configuration file"));
233 menuFile->Append(EditConfigFile, _T("Edit your configuration file"), _T("Edit your configuration file"));
234 menuFile->AppendSeparator();
235 menuFile->Append(Minimal_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
237 // now append the freshly created menu to the menu bar...
238 wxMenuBar *menuBar = new wxMenuBar();
239 menuBar->Append(menuFile, _T("&File"));
240 menuBar->Append(helpMenu, _T("&Help"));
242 // ... and attach this menu bar to the frame
244 #endif // wxUSE_MENUS
248 SetStatusText(wxString(wxT("Welcome to bacula wx-console ")) << wxString(wxT(VERSION)) << wxString (wxT(" (")) << wxString(wxT(BDATE)) << wxString(wxT(")!\n")));
250 wxPanel* global = new wxPanel(this, -1);
252 notebook = new wxNotebook(global, -1);
256 wxPanel* consolePanel = new wxPanel(notebook, -1);
257 notebook->AddPage(consolePanel, wxT("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(wxT("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(wxT("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, wxT("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, wxT("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(wxT("Error while parsing command line arguments, using defaults.\n"), CS_DEBUG);
357 Print(wxT("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(wxT("Error while parsing command line arguments, using defaults.\n"), CS_DEBUG);
369 Print(wxT("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(
396 wxString(wxT("It seems that it is the first time you run wx-console.\n")) <<
397 wxString(wxT("This file (")) << configfile << wxString(wxT(") has been choosen as default configuration file.\n")) <<
398 wxString(wxT("Do 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(
415 wxString(wxT("Unable to read ")) << configfile << wxString(wxT("\n")) <<
416 err << wxString(wxT("\nDo you want to choose another one? (Press no to edit this file)")),
417 wxT("Unable to read configuration file"),
418 wxYES_NO | wxCANCEL | wxICON_ERROR, this);
419 if (answer == wxNO) {
420 wxbConfigFileEditor(this, configfile).ShowModal();
421 err = console_thread::LoadConfig(configfile);
423 else if (answer == wxCANCEL) {
428 else { // (answer == wxYES)
429 configfile = wxFileSelector(wxT("Please choose a configuration file to use"));
430 if ( !configfile.empty() ) {
431 err = console_thread::LoadConfig(configfile);
440 if ((err == wxT("")) && (config == wxT(""))) {
441 answer = wxMessageBox(
442 wxT("This configuration file has been successfully read, use it as default?"),
443 wxT("Configuration file read successfully"),
444 wxYES_NO | wxICON_QUESTION, this);
445 if (answer == wxYES) {
446 wxConfigBase::Get()->Write(wxT("/ConfigFile"), configfile);
452 // former was csprint
453 Print(wxString(wxT("Using this configuration file: ")) << configfile << wxT("\n"), CS_DEBUG);
455 ct = new console_thread();
458 SetStatusText(wxT("Connecting to the director..."));
461 /* Register a new wxbDataParser */
462 void wxbMainFrame::Register(wxbDataParser* dp) {
466 /* Unregister a wxbDataParser */
467 void wxbMainFrame::Unregister(wxbDataParser* dp) {
469 if ((index = parsers.Index(dp)) != wxNOT_FOUND) {
470 parsers.RemoveAt(index);
473 Print(wxT("Failed to unregister a data parser !"), CS_DEBUG);
479 void wxbMainFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
481 Print(wxT("Quitting.\n"), CS_DEBUG);
487 console_thread::FreeLib();
493 void wxbMainFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
496 msg.Printf( _T("Welcome to Bacula wx-console.\nWritten by Nicolas Boichat <nicolas@boichat.ch>\n(C) 2004 Kern Sibbald and John Walker\n"));
498 wxMessageBox(msg, _T("About Bacula wx-console"), wxOK | wxICON_INFORMATION, this);
501 void wxbMainFrame::OnChangeConfig(wxCommandEvent& event) {
502 wxString oriconfigfile;
503 wxConfig::Get()->Read(wxT("/ConfigFile"), &oriconfigfile);
504 wxString configfile = wxFileSelector(wxT("Please choose your default configuration file"));
505 if ( !configfile.empty() ) {
506 if (oriconfigfile != configfile) {
507 int answer = wxMessageBox(
508 wxT("Use this configuration file as default?"),
509 wxT("Configuration file"),
510 wxYES_NO | wxICON_QUESTION, this);
511 if (answer == wxYES) {
512 wxConfigBase::Get()->Write(wxT("/ConfigFile"), configfile);
513 wxConfigBase::Get()->Flush();
514 StartConsoleThread(wxT(""));
519 StartConsoleThread(configfile);
523 void wxbMainFrame::OnEditConfig(wxCommandEvent& event) {
525 wxConfig::Get()->Read(wxT("/ConfigFile"), &configfile);
526 int stat = wxbConfigFileEditor(this, configfile).ShowModal();
528 StartConsoleThread(configfile);
532 void wxbMainFrame::OnConnect(wxCommandEvent& event) {
533 StartConsoleThread(configfile);
536 void wxbMainFrame::OnDisconnect(wxCommandEvent& event) {
543 void wxbMainFrame::OnEnter(wxCommandEvent& WXUNUSED(event))
545 lockedbyconsole = true;
547 typeCtrl->HistoryAdd(typeCtrl->GetValue());
548 wxString str = typeCtrl->GetValue() + wxT("\n");
553 * Called when data is arriving from director
555 void wxbMainFrame::OnPrint(wxbThreadEvent& event) {
556 wxbPrintObject* po = event.GetEventPrintObject();
558 Print(po->str, po->status);
562 * Prints data received from director to the console, and forwards it to the panels
564 void wxbMainFrame::Print(wxString str, int status)
566 if (lockedbyconsole) {
567 EnableConsole(false);
570 if (status == CS_TERMINATED) {
571 consoleCtrl->AppendText(consoleBuffer);
572 consoleBuffer = wxT("");
573 SetStatusText(wxT("Console thread terminated."));
574 consoleCtrl->PageDown();
577 int answer = wxMessageBox(wxT("Connection to the director lost. Quit program?"), wxT("Connection lost"),
578 wxYES_NO | wxICON_EXCLAMATION, this);
579 if (answer == wxYES) {
583 menuFile->Enable(MenuConnect, true);
584 menuFile->SetLabel(MenuConnect, wxT("Connect"));
585 menuFile->SetHelpString(MenuConnect, wxT("Connect to the director"));
586 menuFile->Enable(MenuDisconnect, false);
587 menuFile->Enable(ChangeConfigFile, true);
588 menuFile->Enable(EditConfigFile, true);
592 if (status == CS_CONNECTED) {
593 SetStatusText(wxT("Connected to the director."));
594 typeCtrl->ClearCommandList();
595 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxT(".help"), true);
598 for (i = 0; i < (int)dt->GetCount(); i++) {
601 if ((j = str.Find(' ')) > -1) {
602 typeCtrl->AddCommand(str.Mid(0, j), str.Mid(j+1));
606 menuFile->Enable(MenuConnect, true);
607 menuFile->SetLabel(MenuConnect, wxT("Reconnect"));
608 menuFile->SetHelpString(MenuConnect, wxT("Reconnect to the director"));
609 menuFile->Enable(MenuDisconnect, true);
610 menuFile->Enable(ChangeConfigFile, true);
611 menuFile->Enable(EditConfigFile, true);
614 if (status == CS_DISCONNECTED) {
615 consoleCtrl->AppendText(consoleBuffer);
616 consoleBuffer = wxT("");
617 consoleCtrl->PageDown();
618 SetStatusText(wxT("Disconnected of the director."));
623 // CS_DEBUG is often sent by panels,
624 // and resend it to them would sometimes cause infinite loops
626 /* One promptcaught is normal, so we must have two true Print values to be
627 * sure that the prompt has effectively been caught.
629 int promptcaught = -1;
631 if (status != CS_DEBUG) {
632 for (unsigned int i = 0; i < parsers.GetCount(); i++) {
633 promptcaught += parsers[i]->Print(str, status) ? 1 : 0;
636 if ((status == CS_PROMPT) && (promptcaught < 1) && (promptparser->isPrompt())) {
637 Print(wxT("Unexpected question has been received.\n"), CS_DEBUG);
638 // Print(wxString("(") << promptparser->getIntroString() << "/-/" << promptparser->getQuestionString() << ")\n", CS_DEBUG);
641 if (promptparser->getIntroString() != wxT("")) {
642 message << promptparser->getIntroString() << wxT("\n");
644 message << promptparser->getQuestionString();
646 if (promptparser->getChoices()) {
647 wxString *choices = new wxString[promptparser->getChoices()->GetCount()];
648 int *numbers = new int[promptparser->getChoices()->GetCount()];
651 for (unsigned int i = 0; i < promptparser->getChoices()->GetCount(); i++) {
652 if ((*promptparser->getChoices())[i] != wxT("")) {
653 choices[n] = (*promptparser->getChoices())[i];
659 int res = ::wxGetSingleChoiceIndex(message,
660 wxT("wx-console: unexpected director's question."), n, choices, this);
661 if (res == -1) { //Cancel pressed
665 if (promptparser->isNumericalChoice()) {
666 Send(wxString() << numbers[res] << wxT("\n"));
669 Send(wxString() << choices[res] << wxT("\n"));
674 Send(::wxGetTextFromUser(message,
675 wxT("wx-console: unexpected director's question."), wxT(""), this) + wxT("\n"));
680 if (status == CS_END) {
681 if (lockedbyconsole) {
683 lockedbyconsole = false;
688 if (status == CS_DEBUG) {
689 consoleCtrl->AppendText(consoleBuffer);
690 consoleBuffer = wxT("");
691 consoleCtrl->PageDown();
692 consoleCtrl->SetDefaultStyle(wxTextAttr(wxColour(0, 128, 0)));
695 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK));
697 consoleBuffer << wxbUtils::ConvertToPrintable(str);
698 if (status == CS_PROMPT) {
699 if (lockedbyconsole) {
702 //consoleBuffer << "<P>";
705 if ((status == CS_END) || (status == CS_PROMPT) || (str.Find(wxT("\n")) > -1)) {
706 consoleCtrl->AppendText(consoleBuffer);
707 consoleBuffer = wxT("");
709 consoleCtrl->PageDown();
712 // consoleCtrl->ShowPosition(consoleCtrl->GetLastPosition());
714 /*if (status != CS_DEBUG) {
715 consoleCtrl->AppendText("@");
717 //consoleCtrl->SetInsertionPointEnd();
719 /* if ((consoleCtrl->GetNumberOfLines()-1) > nlines) {
720 nlines = consoleCtrl->GetNumberOfLines()-1;
723 if (status == CS_END) {
724 consoleCtrl->ShowPosition(nlines);
729 * Sends data to the director
731 void wxbMainFrame::Send(wxString str)
734 ct->Write(str.mb_str(wxConvUTF8));
735 typeCtrl->SetValue(wxT(""));
736 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxRED));
737 consoleCtrl->AppendText(wxbUtils::ConvertToPrintable(str));
738 consoleCtrl->PageDown();
741 /* if ((consoleCtrl->GetNumberOfLines()-1) > nlines) {
742 nlines = consoleCtrl->GetNumberOfLines()-1;
745 consoleCtrl->ShowPosition(nlines);*/
749 void wxbMainFrame::EnablePanels() {
750 for (int i = 0; panels[i] != NULL; i++) {
751 panels[i]->EnablePanel(true);
756 /* Disable panels, except the one passed as parameter */
757 void wxbMainFrame::DisablePanels(void* except) {
758 for (int i = 0; panels[i] != NULL; i++) {
759 if (panels[i] != except) {
760 panels[i]->EnablePanel(false);
763 panels[i]->EnablePanel(true);
766 if (this != except) {
767 EnableConsole(false);
771 /* Enable or disable console typing */
772 void wxbMainFrame::EnableConsole(bool enable) {
773 typeCtrl->Enable(enable);
774 sendButton->Enable(enable);
776 typeCtrl->SetFocus();
781 * Used by csprint, which is called by console thread.
783 * In GTK and perhaps X11, only the main thread is allowed to interact with
784 * graphical components, so by firing an event, the main loop will call OnPrint.
786 * Calling OnPrint directly from console thread produces "unexpected async replies".
788 void firePrintEvent(wxString str, int status)
790 wxbPrintObject* po = new wxbPrintObject(str, status);
792 wxbThreadEvent evt(Thread);
793 evt.SetEventPrintObject(po);
795 if (wxbMainFrame::GetInstance()) {
796 wxbMainFrame::GetInstance()->AddPendingEvent(evt);
800 //wxString csBuffer; /* Temporary buffer for receiving data from console thread */
803 * Called by console thread, this function forwards data line by line and end
804 * signals to the GUI.
807 void csprint(wxString str, int status)
809 firePrintEvent(str, status);
813 void csprint(const char* str, int status)
816 firePrintEvent(wxString(str,wxConvUTF8), status);
819 firePrintEvent(wxT(""), status);