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.
26 #include "wxbmainframe.h" // class's header file
28 #include "wxbrestorepanel.h"
30 #include "wxbconfigfileeditor.h"
34 #include "wxwin16x16.xpm"
36 #include <wx/arrimpl.cpp>
38 #include <wx/stattext.h>
39 #include <wx/statline.h>
40 #include <wx/config.h>
42 #include <wx/filename.h>
44 #undef Yield /* MinGW defines Yield */
46 // ----------------------------------------------------------------------------
47 // event tables and other macros for wxWindows
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 // IDs for the controls and the menu commands
60 // it is important for the id corresponding to the "About" command to have
61 // this standard value as otherwise it won't be handled properly under Mac
62 // (where it is special and put into the "Apple" menu)
63 Minimal_About = wxID_ABOUT,
75 * wxbTHREAD_EVENT declaration, used by csprint
77 BEGIN_DECLARE_EVENT_TYPES()
78 DECLARE_EVENT_TYPE(wxbTHREAD_EVENT, 1)
79 END_DECLARE_EVENT_TYPES()
81 DEFINE_EVENT_TYPE(wxbTHREAD_EVENT)
83 typedef void (wxEvtHandler::*wxThreadEventFunction)(wxbThreadEvent&);
85 #define EVT_THREAD_EVENT(id, fn) \
86 DECLARE_EVENT_TABLE_ENTRY( \
87 wxbTHREAD_EVENT, id, wxID_ANY, \
88 (wxObjectEventFunction)(wxEventFunction)(wxThreadEventFunction)&fn, \
92 // the event tables connect the wxWindows events with the functions (event
93 // handlers) which process them. It can be also done at run-time, but for the
94 // simple menu events like this the static method is much simpler.
95 BEGIN_EVENT_TABLE(wxbMainFrame, wxFrame)
96 EVT_MENU(Minimal_Quit, wxbMainFrame::OnQuit)
97 EVT_MENU(Minimal_About, wxbMainFrame::OnAbout)
98 EVT_MENU(ChangeConfigFile, wxbMainFrame::OnChangeConfig)
99 EVT_MENU(EditConfigFile, wxbMainFrame::OnEditConfig)
100 EVT_MENU(MenuConnect, wxbMainFrame::OnConnect)
101 EVT_MENU(MenuDisconnect, wxbMainFrame::OnDisconnect)
102 EVT_TEXT_ENTER(TypeText, wxbMainFrame::OnEnter)
103 EVT_THREAD_EVENT(Thread, wxbMainFrame::OnPrint)
104 EVT_BUTTON(SendButton, wxbMainFrame::OnEnter)
107 // ----------------------------------------------------------------------------
109 // ----------------------------------------------------------------------------
112 * wxbThreadEvent constructor
114 wxbThreadEvent::wxbThreadEvent(int id): wxEvent(id, wxbTHREAD_EVENT) {
115 m_eventObject = NULL;
119 * wxbThreadEvent destructor
121 wxbThreadEvent::~wxbThreadEvent()
123 if (m_eventObject != NULL) {
124 delete m_eventObject;
129 * wxbThreadEvent copy constructor
131 wxbThreadEvent::wxbThreadEvent(const wxbThreadEvent& te)
133 this->m_eventType = te.m_eventType;
134 this->m_id = te.m_id;
135 if (te.m_eventObject != NULL) {
136 this->m_eventObject = new wxbPrintObject(*((wxbPrintObject*)te.m_eventObject));
139 this->m_eventObject = NULL;
141 this->m_skipped = te.m_skipped;
142 this->m_timeStamp = te.m_timeStamp;
146 * Must be implemented (abstract in wxEvent)
148 wxEvent* wxbThreadEvent::Clone() const
150 return new wxbThreadEvent(*this);
154 * Gets the wxbPrintObject attached to this event, containing data sent by director
156 wxbPrintObject* wxbThreadEvent::GetEventPrintObject()
158 return (wxbPrintObject*)m_eventObject;
162 * Sets the wxbPrintObject attached to this event
164 void wxbThreadEvent::SetEventPrintObject(wxbPrintObject* object)
166 m_eventObject = (wxObject*)object;
169 // ----------------------------------------------------------------------------
171 // ----------------------------------------------------------------------------
173 wxbMainFrame *wxbMainFrame::frame = NULL;
176 * Singleton constructor
178 wxbMainFrame* wxbMainFrame::CreateInstance(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
180 frame = new wxbMainFrame(title, pos, size, style);
185 * Returns singleton instance
187 wxbMainFrame* wxbMainFrame::GetInstance()
195 wxbMainFrame::~wxbMainFrame()
197 wxConfig::Get()->Write(wxT("/Position/X"), (long)GetPosition().x);
198 wxConfig::Get()->Write(wxT("/Position/Y"), (long)GetPosition().y);
199 wxConfig::Get()->Write(wxT("/Size/Width"), (long)GetSize().GetWidth());
200 wxConfig::Get()->Write(wxT("/Size/Height"), (long)GetSize().GetHeight());
202 if (ct != NULL) { // && (!ct->IsRunning())
209 * Private constructor
211 wxbMainFrame::wxbMainFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
212 : wxFrame(NULL, -1, title, pos, size, style)
214 lockedbyconsole = false;
220 // set the frame icon
221 SetIcon(wxIcon(wxwin16x16_xpm));
225 menuFile = new wxMenu;
227 // the "About" item should be in the help menu
228 wxMenu *helpMenu = new wxMenu;
229 helpMenu->Append(Minimal_About, _("&About...\tF1"), _("Show about dialog"));
231 menuFile->Append(MenuConnect, _("Connect"), _("Connect to the director"));
232 menuFile->Append(MenuDisconnect, _("Disconnect"), _("Disconnect of the director"));
233 menuFile->AppendSeparator();
234 menuFile->Append(ChangeConfigFile, _("Change of configuration file"), _("Change your default configuration file"));
235 menuFile->Append(EditConfigFile, _("Edit your configuration file"), _("Edit your configuration file"));
236 menuFile->AppendSeparator();
237 menuFile->Append(Minimal_Quit, _("E&xit\tAlt-X"), _("Quit this program"));
239 // now append the freshly created menu to the menu bar...
240 wxMenuBar *menuBar = new wxMenuBar();
241 menuBar->Append(menuFile, _("&File"));
242 menuBar->Append(helpMenu, _("&Help"));
244 // ... and attach this menu bar to the frame
246 #endif // wxUSE_MENUS
250 SetStatusText(wxString::Format(_("Welcome to bacula wx-console %s (%s)!\n"), wxT(VERSION), wxT(BDATE)));
252 wxPanel* global = new wxPanel(this, -1);
254 notebook = new wxNotebook(global, -1);
258 wxPanel* consolePanel = new wxPanel(notebook, -1);
259 notebook->AddPage(consolePanel, _("Console"));
261 consoleCtrl = new wxTextCtrl(consolePanel,-1,wxT(""),wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH);
262 wxFont font(10, wxMODERN, wxNORMAL, wxNORMAL);
263 #if defined __WXGTK12__ && !defined __WXGTK20__ // Fix for "chinese" fonts under gtk+ 1.2
264 font.SetDefaultEncoding(wxFONTENCODING_ISO8859_1);
265 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, font));
266 Print(_("Warning : Unicode is disabled because you are using wxWidgets for GTK+ 1.2.\n"), CS_DEBUG);
268 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK, wxNullColour, font));
269 #if (wxUSE_UNICODE == 0) && __WXGTK20__
270 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);
274 helpCtrl = new wxStaticText(consolePanel, -1, _("Type your command below:"));
276 wxFlexGridSizer *consoleSizer = new wxFlexGridSizer(4, 1, 0, 0);
277 consoleSizer->AddGrowableCol(0);
278 consoleSizer->AddGrowableRow(0);
280 typeCtrl = new wxbHistoryTextCtrl(helpCtrl, consolePanel,TypeText,wxT(""),wxDefaultPosition,wxSize(200,20));
281 sendButton = new wxButton(consolePanel, SendButton, _("Send"));
283 wxFlexGridSizer *typeSizer = new wxFlexGridSizer(1, 2, 0, 0);
284 typeSizer->AddGrowableCol(0);
285 typeSizer->AddGrowableRow(0);
287 //typeSizer->Add(new wxStaticText(consolePanel, -1, _("Command: ")), 0, wxALIGN_CENTER | wxALL, 0);
288 typeSizer->Add(typeCtrl, 1, wxEXPAND | wxALL, 0);
289 typeSizer->Add(sendButton, 1, wxEXPAND | wxLEFT, 5);
291 consoleSizer->Add(consoleCtrl, 1, wxEXPAND | wxALL, 0);
292 consoleSizer->Add(new wxStaticLine(consolePanel, -1), 0, wxEXPAND | wxALL, 0);
293 consoleSizer->Add(helpCtrl, 1, wxEXPAND | wxALL, 2);
294 consoleSizer->Add(typeSizer, 0, wxEXPAND | wxALL, 2);
296 consolePanel->SetAutoLayout( TRUE );
297 consolePanel->SetSizer( consoleSizer );
298 consoleSizer->SetSizeHints( consolePanel );
300 // Creates the list of panels which are included in notebook, and that need to receive director information
302 panels = new wxbPanel* [2];
303 panels[0] = new wxbRestorePanel(notebook);
306 for (int i = 0; panels[i] != NULL; i++) {
307 notebook->AddPage(panels[i], panels[i]->GetTitle());
310 wxBoxSizer* globalSizer = new wxBoxSizer(wxHORIZONTAL);
312 #if wxCHECK_VERSION(2, 6, 0)
313 globalSizer->Add(notebook, 1, wxEXPAND, 0);
315 globalSizer->Add(new wxNotebookSizer(notebook), 1, wxEXPAND, 0);
318 global->SetSizer( globalSizer );
319 globalSizer->SetSizeHints( global );
321 wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
323 sizer->Add(global, 1, wxEXPAND | wxALL, 0);
326 sizer->SetSizeHints( this );
328 EnableConsole(false);
330 consoleBuffer = wxT("");
332 configfile = wxT("");
336 * Starts the thread interacting with the director
337 * If config is not empty, uses this config file.
339 void wxbMainFrame::StartConsoleThread(const wxString& config) {
340 menuFile->Enable(MenuConnect, false);
341 menuFile->Enable(MenuDisconnect, false);
342 menuFile->Enable(ChangeConfigFile, false);
343 menuFile->Enable(EditConfigFile, false);
350 if (promptparser == NULL) {
351 promptparser = new wxbPromptParser();
354 if (config == wxT("")) {
355 configfile = wxT("");
357 if (((wxTheApp->argc % 2) != 1)) {
358 Print(_("Error while parsing command line arguments, using defaults.\n"), CS_DEBUG);
359 Print(_("Usage: wx-console [-c configfile] [-w tmp]\n"), CS_DEBUG);
362 for (int c = 1; c < wxTheApp->argc; c += 2) {
363 if ((wxTheApp->argc >= c+2) && (wxString(wxTheApp->argv[c]) == wxT("-c"))) {
364 configfile = wxTheApp->argv[c+1];
366 if ((wxTheApp->argc >= c+2) && (wxString(wxTheApp->argv[c]) == wxT("-w"))) {
367 console_thread::SetWorkingDirectory(wxTheApp->argv[c+1]);
369 if (wxTheApp->argv[c][0] != '-') {
370 Print(_("Error while parsing command line arguments, using defaults.\n"), CS_DEBUG);
371 Print(_("Usage: wx-console [-c configfile] [-w tmp]\n"), CS_DEBUG);
377 if (configfile == wxT("")) {
378 wxConfig::Set(new wxConfig(wxT("wx-console"), wxT("bacula")));
379 if (!wxConfig::Get()->Read(wxT("/ConfigFile"), &configfile)) {
381 wxFileName filename(::wxGetHomeDir());
382 filename.MakeAbsolute();
383 configfile = filename.GetLongPath();
384 if (configfile.Last() != '/')
386 configfile += "Library/Preferences/org.bacula.wxconsole.conf";
388 wxFileName filename(::wxGetCwd(), wxT("wx-console.conf"));
389 filename.MakeAbsolute();
390 configfile = filename.GetLongPath();
392 configfile.Replace(wxT("\\"), wxT("/"));
395 wxConfig::Get()->Write(wxT("/ConfigFile"), configfile);
397 int answer = wxMessageBox(
399 "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)"),
402 wxYES_NO | wxICON_QUESTION, this);
403 if (answer == wxYES) {
404 wxbConfigFileEditor(this, configfile).ShowModal();
413 wxString err = console_thread::LoadConfig(configfile);
415 while (err != wxT("")) {
416 int answer = wxMessageBox(
418 "Unable to read %s\nError: %s\nDo you want to choose another one? (Press no to edit this file)"),
419 configfile.c_str(), err.c_str()),
420 _("Unable to read configuration file"),
421 wxYES_NO | wxCANCEL | wxICON_ERROR, this);
422 if (answer == wxNO) {
423 wxbConfigFileEditor(this, configfile).ShowModal();
424 err = console_thread::LoadConfig(configfile);
426 else if (answer == wxCANCEL) {
431 else { // (answer == wxYES)
432 configfile = wxFileSelector(_("Please choose a configuration file to use"));
433 if ( !configfile.empty() ) {
434 err = console_thread::LoadConfig(configfile);
443 if ((err == wxT("")) && (config == wxT(""))) {
444 answer = wxMessageBox(
445 _("This configuration file has been successfully read, use it as default?"),
446 _("Configuration file read successfully"),
447 wxYES_NO | wxICON_QUESTION, this);
448 if (answer == wxYES) {
449 wxConfigBase::Get()->Write(wxT("/ConfigFile"), configfile);
455 // former was csprint
456 Print(wxString::Format(_("Using this configuration file: %s\n"), configfile.c_str()), CS_DEBUG);
458 ct = new console_thread();
461 SetStatusText(_("Connecting to the director..."));
464 /* Register a new wxbDataParser */
465 void wxbMainFrame::Register(wxbDataParser* dp) {
469 /* Unregister a wxbDataParser */
470 void wxbMainFrame::Unregister(wxbDataParser* dp) {
472 if ((index = parsers.Index(dp)) != wxNOT_FOUND) {
473 parsers.RemoveAt(index);
476 Print(_("Failed to unregister a data parser !"), CS_DEBUG);
482 void wxbMainFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
484 Print(_("Quitting.\n"), CS_DEBUG);
490 console_thread::FreeLib();
496 void wxbMainFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
499 msg.Printf(_("Welcome to Bacula wx-console.\nWritten by Nicolas Boichat <nicolas@boichat.ch>\n(C) 2005 Kern Sibbald\n"));
501 wxMessageBox(msg, _("About Bacula wx-console"), wxOK | wxICON_INFORMATION, this);
504 void wxbMainFrame::OnChangeConfig(wxCommandEvent& event) {
505 wxString oriconfigfile;
506 wxConfig::Get()->Read(wxT("/ConfigFile"), &oriconfigfile);
507 wxString configfile = wxFileSelector(_("Please choose your default configuration file"));
508 if ( !configfile.empty() ) {
509 if (oriconfigfile != configfile) {
510 int answer = wxMessageBox(
511 _("Use this configuration file as default?"),
512 _("Configuration file"),
513 wxYES_NO | wxICON_QUESTION, this);
514 if (answer == wxYES) {
515 wxConfigBase::Get()->Write(wxT("/ConfigFile"), configfile);
516 wxConfigBase::Get()->Flush();
517 StartConsoleThread(wxT(""));
522 StartConsoleThread(configfile);
526 void wxbMainFrame::OnEditConfig(wxCommandEvent& event) {
528 wxConfig::Get()->Read(wxT("/ConfigFile"), &configfile);
529 int stat = wxbConfigFileEditor(this, configfile).ShowModal();
531 StartConsoleThread(configfile);
535 void wxbMainFrame::OnConnect(wxCommandEvent& event) {
536 StartConsoleThread(configfile);
539 void wxbMainFrame::OnDisconnect(wxCommandEvent& event) {
546 void wxbMainFrame::OnEnter(wxCommandEvent& WXUNUSED(event))
548 lockedbyconsole = true;
550 typeCtrl->HistoryAdd(typeCtrl->GetValue());
551 wxString str = typeCtrl->GetValue() + wxT("\n");
556 * Called when data is arriving from director
558 void wxbMainFrame::OnPrint(wxbThreadEvent& event) {
559 wxbPrintObject* po = event.GetEventPrintObject();
561 Print(po->str, po->status);
565 * Prints data received from director to the console, and forwards it to the panels
567 void wxbMainFrame::Print(wxString str, int status)
569 if (lockedbyconsole) {
570 EnableConsole(false);
573 if (status == CS_REMOVEPROMPT) {
574 if (consoleCtrl->GetLastPosition() > 0) {
575 consoleCtrl->Remove(consoleCtrl->GetLastPosition()-1, consoleCtrl->GetLastPosition()+1);
580 if (status == CS_TERMINATED) {
581 consoleCtrl->AppendText(consoleBuffer);
582 consoleBuffer = wxT("");
583 SetStatusText(_("Console thread terminated."));
585 consoleCtrl->PageDown();
587 consoleCtrl->ScrollLines(1);
591 int answer = wxMessageBox( _("Connection to the director lost. Quit program?"),
592 _("Connection lost"),
593 wxYES_NO | wxICON_EXCLAMATION, this);
594 if (answer == wxYES) {
598 menuFile->Enable(MenuConnect, true);
599 menuFile->SetLabel(MenuConnect, _("Connect"));
600 menuFile->SetHelpString(MenuConnect, _("Connect to the director"));
601 menuFile->Enable(MenuDisconnect, false);
602 menuFile->Enable(ChangeConfigFile, true);
603 menuFile->Enable(EditConfigFile, true);
607 if (status == CS_CONNECTED) {
608 SetStatusText(_("Connected to the director."));
609 typeCtrl->ClearCommandList();
612 wxbDataTokenizer* dt = wxbUtils::WaitForEnd(wxT(".help"), true);
616 for (i = 0; i < (int)dt->GetCount(); i++) {
619 if ((j = str.Find(' ')) > -1) {
620 typeCtrl->AddCommand(str.Mid(0, j), str.Mid(j+1));
625 if ((parsed) || (!retries))
627 dt = wxbUtils::WaitForEnd(wxT(""), true);
630 menuFile->Enable(MenuConnect, true);
631 menuFile->SetLabel(MenuConnect, _("Reconnect"));
632 menuFile->SetHelpString(MenuConnect, _("Reconnect to the director"));
633 menuFile->Enable(MenuDisconnect, true);
634 menuFile->Enable(ChangeConfigFile, true);
635 menuFile->Enable(EditConfigFile, true);
638 if (status == CS_DISCONNECTED) {
639 consoleCtrl->AppendText(consoleBuffer);
640 consoleBuffer = wxT("");
642 consoleCtrl->PageDown();
644 consoleCtrl->ScrollLines(1);
646 SetStatusText(_("Disconnected of the director."));
651 // CS_DEBUG is often sent by panels,
652 // and resend it to them would sometimes cause infinite loops
654 /* One promptcaught is normal, so we must have two true Print values to be
655 * sure that the prompt has effectively been caught.
657 int promptcaught = -1;
659 if (status != CS_DEBUG) {
660 for (unsigned int i = 0; i < parsers.GetCount(); i++) {
661 promptcaught += parsers[i]->Print(str, status) ? 1 : 0;
664 if ((status == CS_PROMPT) && (promptcaught < 1) && (promptparser->isPrompt())) {
665 Print(_("Unexpected question has been received.\n"), CS_DEBUG);
666 // Print(wxString("(") << promptparser->getIntroString() << "/-/" << promptparser->getQuestionString() << ")\n", CS_DEBUG);
669 if (promptparser->getIntroString() != wxT("")) {
670 message << promptparser->getIntroString() << wxT("\n");
672 message << promptparser->getQuestionString();
674 if (promptparser->getChoices()) {
675 wxString *choices = new wxString[promptparser->getChoices()->GetCount()];
676 int *numbers = new int[promptparser->getChoices()->GetCount()];
679 for (unsigned int i = 0; i < promptparser->getChoices()->GetCount(); i++) {
680 if ((*promptparser->getChoices())[i] != wxT("")) {
681 choices[n] = (*promptparser->getChoices())[i];
687 int res = ::wxGetSingleChoiceIndex(message,
688 _("wx-console: unexpected director's question."), n, choices, this);
689 if (res == -1) { //Cancel pressed
693 if (promptparser->isNumericalChoice()) {
694 Send(wxString() << numbers[res] << wxT("\n"));
697 Send(wxString() << choices[res] << wxT("\n"));
704 Send(::wxGetTextFromUser(message,
705 _("wx-console: unexpected director's question."),
706 wxT(""), this) + wxT("\n"));
711 if (status == CS_END) {
712 if (lockedbyconsole) {
714 lockedbyconsole = false;
719 if (status == CS_DEBUG) {
720 consoleCtrl->AppendText(consoleBuffer);
721 consoleBuffer = wxT("");
723 consoleCtrl->PageDown();
725 consoleCtrl->ScrollLines(1);
727 consoleCtrl->SetDefaultStyle(wxTextAttr(wxColour(0, 128, 0)));
730 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxBLACK));
732 consoleBuffer << wxbUtils::ConvertToPrintable(str);
733 if (status == CS_PROMPT) {
734 if (lockedbyconsole) {
737 //consoleBuffer << wxT("<P>");
740 if ((status == CS_END) || (status == CS_PROMPT) || (str.Find(wxT("\n")) > -1)) {
741 consoleCtrl->AppendText(consoleBuffer);
742 consoleBuffer = wxT("");
745 consoleCtrl->PageDown();
747 consoleCtrl->ScrollLines(1);
751 //consoleCtrl->ShowPosition(consoleCtrl->GetLastPosition());
753 /*if (status != CS_DEBUG) {
754 consoleCtrl->AppendText("@");
756 //consoleCtrl->SetInsertionPointEnd();
760 * Sends data to the director
762 void wxbMainFrame::Send(wxString str)
765 /* wxString may contain everything in UNICODE
766 * -> convert to UTF-8 and send to director
768 ct->Write (str.mb_str(wxConvUTF8));
769 typeCtrl->SetValue(wxT(""));
770 consoleCtrl->SetDefaultStyle(wxTextAttr(*wxRED));
771 consoleCtrl->AppendText(wxbUtils::ConvertToPrintable(str));
772 //consoleCtrl->PageDown();
775 /* if ((consoleCtrl->GetNumberOfLines()-1) > nlines) {
776 nlines = consoleCtrl->GetNumberOfLines()-1;
779 consoleCtrl->ShowPosition(nlines);*/
783 void wxbMainFrame::EnablePanels() {
784 for (int i = 0; panels[i] != NULL; i++) {
785 panels[i]->EnablePanel(true);
790 /* Disable panels, except the one passed as parameter */
791 void wxbMainFrame::DisablePanels(void* except) {
792 for (int i = 0; panels[i] != NULL; i++) {
793 if (panels[i] != except) {
794 panels[i]->EnablePanel(false);
797 panels[i]->EnablePanel(true);
800 if (this != except) {
801 EnableConsole(false);
805 /* Enable or disable console typing */
806 void wxbMainFrame::EnableConsole(bool enable) {
807 typeCtrl->Enable(enable);
808 sendButton->Enable(enable);
810 typeCtrl->SetFocus();
815 * Used by csprint, which is called by console thread.
817 * In GTK and perhaps X11, only the main thread is allowed to interact with
818 * graphical components, so by firing an event, the main loop will call OnPrint.
820 * Calling OnPrint directly from console thread produces "unexpected async replies".
822 void firePrintEvent(wxString str, int status)
824 wxbPrintObject* po = new wxbPrintObject(str, status);
826 wxbThreadEvent evt(Thread);
827 evt.SetEventPrintObject(po);
829 if (wxbMainFrame::GetInstance()) {
830 wxbMainFrame::GetInstance()->AddPendingEvent(evt);
834 //wxString csBuffer; /* Temporary buffer for receiving data from console thread */
837 * Called by console thread, this function forwards data line by line and end
838 * signals to the GUI.
841 void csprint(wxString str, int status)
843 firePrintEvent(str, status);
847 void csprint(const char* str, int status)
850 firePrintEvent(wxString(str,wxConvUTF8), status);
853 firePrintEvent(wxT(""), status);