#include "ProgressFrame.h"
#include "GlobalParameterFrame.h"
#include "GlobalParameterFilesFrame.h"
+#include "RubyDialogFrame.h"
#include "MyMBConv.h"
#if defined(__WXMSW__)
bool gInitCompleted = false;
+int gSuppressConsole = 0; // Non-zero if console output should be suppressed in non-GUI mode
+int gUseGUI = 1;
+
IMPLEMENT_APP(MyApp)
//IMPLEMENT_CLASS(MyApp, wxApp)
BEGIN_EVENT_TABLE(MyApp, wxApp)
EVT_COMMAND(MyDocumentEvent_scriptMenuModified, MyDocumentEvent, MyApp::OnScriptMenuModified)
- EVT_COMMAND(MyDocumentEvent_openFilesByIPC, MyDocumentEvent, MyApp::OnOpenFilesByIPC)
+ EVT_COMMAND(MyDocumentEvent_openFilesByEvent, MyDocumentEvent, MyApp::OnOpenFilesByEvent)
EVT_UPDATE_UI_RANGE(myMenuID_MyFirstMenuItem, myMenuID_MyLastMenuItem, MyApp::OnUpdateUI)
EVT_MENU(myMenuID_ExecuteScript, MyApp::OnExecuteScript)
EVT_MENU(myMenuID_OpenConsoleWindow, MyApp::OnOpenConsoleWindow)
EVT_MENU(myMenuID_EmptyConsoleWindow, MyApp::OnEmptyConsoleWindow)
EVT_MENU(myMenuID_ViewGlobalParameters, MyApp::OnViewGlobalParameters)
EVT_MENU(myMenuID_ViewParameterFilesList, MyApp::OnViewParameterFilesList)
+ EVT_MENU(myMenuID_BringAllWindowsToFront, MyApp::OnBringAllWindowsToFront)
+ EVT_MENU(wxID_HELP, MyApp::OnHelp)
#if defined(__WXMAC__)
EVT_ACTIVATE(MyApp::OnActivate)
#endif
- EVT_END_PROCESS(-1, MyApp::OnEndProcess)
+// EVT_END_PROCESS(-1, MyApp::OnEndProcess)
EVT_TIMER(-1, MyApp::TimerInvoked)
EVT_COMMAND(myMenuID_Internal_CheckIfAllWindowsAreGone, MyDocumentEvent, MyApp::CheckIfAllWindowsAreGoneHandler)
END_EVENT_TABLE()
// Windows: the directory in which the application executable is located.
// UNIX: ?
wxString
-MyApp::FindResourcePath()
+MyApp::InitResourcePath(int& argc, wxChar **argv)
{
#if defined(__WXMAC__)
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef ref = CFBundleCopyResourcesDirectoryURL(mainBundle);
if (ref != NULL) {
- UInt8 buffer[256];
+ UInt8 buffer[4096];
if (CFURLGetFileSystemRepresentation(ref, true, buffer, sizeof buffer)) {
wxString dirname((const char *)buffer, WX_DEFAULT_CONV);
CFRelease(ref);
+ m_resourcePath = dirname;
return dirname;
}
CFRelease(ref);
}
+ m_resourcePath = wxEmptyString;
return wxEmptyString;
#elif defined(__WXMSW__)
wxString str;
- wxString argv0 = wxTheApp->argv[0];
+ wxString argv0 = argv[0];
// Fix dosish path (when invoked from MSYS console, the path may be unix-like)
// Note: absolute paths like /c/Molby/... (== c:\Molby\...) is not supported
{
}
// Is it an absolute path?
if (wxIsAbsolutePath(argv0)) {
- return wxPathOnly(argv0);
+ m_resourcePath = wxPathOnly(argv0);
+ return m_resourcePath;
} else {
// Is it a relative path?
wxString currentDir = wxGetCwd();
if (currentDir.Last() != wxFILE_SEP_PATH)
currentDir += wxFILE_SEP_PATH;
str = currentDir + argv0;
- if (wxFileExists(str))
- return wxPathOnly(str);
+ if (wxFileExists(str)) {
+ m_resourcePath = wxPathOnly(str);
+ return m_resourcePath;
+ }
}
// Search PATH
wxPathList pathList;
pathList.AddEnvList(wxT("PATH"));
str = pathList.FindAbsoluteValidPath(argv0);
- if (!str.IsEmpty())
- return wxPathOnly(str);
- return wxEmptyString;
+ if (!str.IsEmpty()) {
+ m_resourcePath = wxPathOnly(str);
+ return m_resourcePath;
+ }
+ m_resourcePath = wxEmptyString;
+ return m_resourcePath;
#else
#error "FindResourcePath is not defined for UNIXes."
#endif
}
+wxString
+MyApp::FindResourcePath()
+{
+ return wxGetApp().m_resourcePath;
+}
+
MyApp::MyApp(void)
{
m_docManager = NULL;
- m_progressFrame = NULL;
+ m_progressDialog = NULL;
m_process = NULL;
- m_processTerminated = false;
- m_processExitCode = 0;
+// m_processTerminated = false;
+// m_processExitCode = 0;
countScriptMenu = 0;
scriptMenuTitles = NULL;
scriptMenuPositions = NULL;
#endif
}
+// We override Initialize() instead of OnInit, because wxAppBase::Initialize() calls OnInitGui(), which
+// makes the program run as a GUI application.
+// So, we intercept here, and go directly to the execution in the batch mode.
+// Otherwise, we call the inherited version of Initialize() and the program will run as a normal application.
+bool MyApp::Initialize(int& argc, wxChar **argv)
+{
+ // Called with a batch mode?
+ if (argc > 1 && wcscmp(argv[1], L"-b") == 0) {
+
+ // Disable any wxLog functionality (otherwise ::exit() may crash)
+ wxLog::EnableLogging(false);
+
+ gUseGUI = 0;
+ gSuppressConsole = 1;
+
+ if (argc > 2 && wcscmp(argv[2], L"-v") == 0)
+ gSuppressConsole = 0;
+
+ // We need these parameters in FindResourcePath(), so we assign them here
+ //this->argc = argc;
+ //this->argv = argv;
+
+ // Initialize the internal m_resourcePath member
+ InitResourcePath(argc, argv);
+
+ static const char fname[] = "startup.rb";
+ wxString dirname = FindResourcePath();
+
+ dirname += wxFILE_SEP_PATH;
+ dirname += wxT("Scripts");
+ wxString cwd = wxGetCwd();
+ wxSetWorkingDirectory(dirname);
+
+ wxString fnamestr(fname, wxConvFile);
+ Molby_startup(wxFileExists(fnamestr) ? fname : NULL, (const char *)dirname.mb_str(wxConvFile));
+
+ wxSetWorkingDirectory(cwd);
+
+ // Build ARGV
+ int c = (gSuppressConsole ? 2 : 3);
+ int i = 1;
+ int status;
+ if (c >= argc) {
+ if (gSuppressConsole) {
+ fprintf(stderr, "The script is not given\n");
+ exit(1);
+ } else exit(0); // Show startup message and exit
+ }
+ wxString argv_script;
+ while (i + c < argc) {
+ wxString arg(argv[i + c]);
+ arg.Replace(wxT("\'"), wxT("\\\'"));
+ argv_script += wxString::Format(wxT("ARGV[%d] = \'"), i - 1);
+ argv_script += arg;
+ argv_script += wxT("\'\n");
+ i++;
+ }
+ gSuppressConsole = 0; // Console output is no longer suppressed (startup is done)
+ status = Molby_loadScript(argv_script.mb_str(wxConvFile), 0);
+ if (status == 0) {
+ wxString arg2(argv[c]);
+ status = Molby_loadScript(arg2.mb_str(wxConvFile), 1);
+ }
+ if (status != 0) {
+ Ruby_showError(status);
+ }
+ // Force exit
+ ::exit(status);
+ } else {
+ // Call the inherited version
+ return wxApp::Initialize(argc, argv);
+ }
+}
+
bool MyApp::OnInit(void)
{
// Set defaults
-#ifdef __WXMAC__
+#if defined(__WXMAC__) || defined(__WXOSX__)
wxSystemOptions::SetOption(wxT("mac.listctrl.always_use_generic"), 1);
wxSystemOptions::SetOption(wxT("osx.openfiledialog.always-show-types"), 1);
+ wxSystemOptions::SetOption(wxOSX_FILEDIALOG_ALWAYS_SHOW_TYPES, 1);
#endif
#if __WXMSW__
new wxDocTemplate(m_docManager, _T("Z Matrix"), _T("*.zmat"), _T(""), _T("zmat"), _T("Molecule Doc"), _T("Molecule View"), CLASSINFO(MyDocument), CLASSINFO(MoleculeView));
new wxDocTemplate(m_docManager, _T("Any Molecule"), _T("*.*"), _T(""), _T(""), _T("Molecule Doc"), _T("Molecule View"), CLASSINFO(MyDocument), CLASSINFO(MoleculeView));
+ // Init image handlers
+ MyAppCallback_initImageHandlers();
+
// Create the main frame window
frame = new MyFrame((wxDocManager *) m_docManager, (wxFrame *) NULL,
- _T("Molby"), wxPoint(0, 0), wxSize(800, 600),
+ _T("Molby"), wxDefaultPosition, wxDefaultSize,
wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE);
+ frame->SetClientSize(FromFrameDIP(frame, wxSize(800, 600)));
// Give it an icon (this is ignored in MDI mode: uses resources)
#ifdef __WXMSW__
{
extern int gRevisionNumber;
static const char fname[] = "startup.rb";
+ InitResourcePath(argc, argv);
wxString dirname = FindResourcePath();
dirname += wxFILE_SEP_PATH;
files.append(argv[i]);
files.append(wxT("\n"));
}
- OnOpenFiles(files);
+ RequestOpenFilesByEvent(files);
}
gInitCompleted = true;
// kind == 0: main menu
// kind == 1: molecule window
// kind == 2: console window
+// kind == 3: Ruby dialog (non-modal)
wxMenuBar *
MyApp::CreateMenuBar(int kind, wxMenu **out_file_history_menu, wxMenu **out_edit_menu)
{
+
+#if __WXMSW__
+ if (kind == 3) {
+
+ // Simplified menu
+ wxMenu *file_menu = new wxMenu;
+ file_menu->Append(wxID_CLOSE, _T("&Close\tCtrl-W"));
+
+ wxMenu *edit_menu = new wxMenu;
+ edit_menu->Append(wxID_UNDO, _T("&Undo\tCtrl-Z"));
+ edit_menu->Append(wxID_REDO, _T("&Redo"));
+ edit_menu->AppendSeparator();
+ edit_menu->Append(wxID_CUT, _T("Cut\tCtrl-X"));
+ edit_menu->Append(wxID_COPY, _T("Copy\tCtrl-C"));
+ edit_menu->Append(wxID_PASTE, _T("Paste\tCtrl-V"));
+ edit_menu->Append(wxID_CLEAR, _T("Clear"));
+ edit_menu->AppendSeparator();
+ edit_menu->Append(wxID_SELECTALL, _T("Select All\tCtrl-A"));
+
+ wxMenu *help_menu = new wxMenu;
+ help_menu->Append(wxID_ABOUT, _T("&About...\tF1"));
+ help_menu->Append(wxID_HELP, _T("&Molby Help"));
+
+ wxMenuBar *menu_bar = new wxMenuBar;
+
+ menu_bar->Append(file_menu, _T("&File"));
+ menu_bar->Append(edit_menu, _T("&Edit"));
+ menu_bar->Append(help_menu, _T("&Help"));
+
+ return menu_bar;
+ }
+#endif
- //// Make a menubar
wxMenu *file_menu = new wxMenu;
+ wxMenu *file_history_menu = NULL;
file_menu->Append(wxID_NEW, _T("&New...\tCtrl-N"));
file_menu->Append(wxID_OPEN, _T("&Open...\tCtrl-O"));
if (out_file_history_menu != NULL) {
- *out_file_history_menu = new wxMenu;
+ file_history_menu = new wxMenu;
+ *out_file_history_menu = file_history_menu;
file_menu->AppendSubMenu(*out_file_history_menu, _T("Open Recent"));
m_docManager->FileHistoryAddFilesToMenu(*out_file_history_menu);
m_docManager->FileHistoryUseMenu(*out_file_history_menu); // Should be removed when menu is discarded
wxMenu *help_menu = new wxMenu;
help_menu->Append(wxID_ABOUT, _T("&About...\tF1"));
-
+ help_menu->Append(wxID_HELP, _T("&Molby Help"));
+
wxMenuBar *menu_bar = new wxMenuBar;
menu_bar->Append(file_menu, _T("&File"));
menu_bar->Append(view_menu, _T("View"));
menu_bar->Append(md_menu, _T("MM/MD"));
menu_bar->Append(script_menu, _T("&Script"));
+
+#if defined(__WXMAC__)
+ wxMenu *window_menu = new wxMenu;
+ window_menu->Append(myMenuID_BringAllWindowsToFront, _T("Bring All to Front"));
+ window_menu->AppendSeparator();
+ menu_bar->Append(window_menu, _T("Window"));
+#endif
+
menu_bar->Append(help_menu, _T("&Help"));
UpdateScriptMenu(menu_bar);
return menu_bar;
}
-#if __WXMAC__
+#if defined(__WXMAC__) || defined(__WXOSX__)
/* When the application is launched without any documents, an empty document is opened.
This should be implemented by overriding this special method; parsing argc/argv does
not work, because the list of files is passed through an Apple Event. */
void
MyApp::MacNewFile()
{
+ if (m_docManager == NULL)
+ return; // Initialization is not yet complete
m_docManager->CreateDocument(_T(""), wxDOC_NEW);
}
void
MyApp::MacOpenFile(const wxString &fileName)
{
- wxString files(fileName);
- OnOpenFiles(files);
+ wxString file(fileName);
+ RequestOpenFilesByEvent(file);
}
-/* Open given files: instead of calling MacOpenFile() for each entry, build a file list
- and call MyApp::OnOpenFiles() */
-short
-MyApp::MacHandleAEODoc(const WXEVENTREF event, WXEVENTREF WXUNUSED(reply))
-{
- AEDescList docList;
- AEKeyword keywd;
- DescType returnedType;
- Size actualSize;
- long itemsInList;
- OSErr err;
- short i;
-
- return noErr; /* TODO: handle open Apple event */
-
- err = AEGetParamDesc((AppleEvent *)event, keyDirectObject, typeAEList, &docList);
- if (err != noErr)
- return err;
-
- err = AECountItems(&docList, &itemsInList);
- if (err != noErr)
- return err;
-
- ProcessSerialNumber PSN ;
- PSN.highLongOfPSN = 0 ;
- PSN.lowLongOfPSN = kCurrentProcess ;
- SetFrontProcess( &PSN ) ;
-
- wxString fName, fNameList;
- FSRef theRef ;
-
- for (i = 1; i <= itemsInList; i++)
- {
- AEGetNthPtr(
- &docList, i, typeFSRef, &keywd, &returnedType,
- (Ptr)&theRef, sizeof(theRef), &actualSize);
- // fName = wxMacFSRefToPath( &theRef ) ;
- fNameList.append(fName);
- fNameList.append(wxT("\n"));
+void
+MyApp::MacOpenFiles(const wxArrayString &fileNames)
+{
+ wxString fnames;
+ int i, n;
+ n = fileNames.GetCount();
+ for (i = 0; i < n; i++) {
+ fnames = fnames + fileNames[i];
+ if (i < n - 1)
+ fnames = fnames + wxT("\n");
}
-
- OnOpenFiles(fNameList);
-
- return noErr;
+ OnOpenFiles(fnames);
}
-#endif
+#endif // WXMAC
int
MyApp::OnExit(void)
void
MyApp::ShowProgressPanel(const char *mes)
{
- wxString string((mes ? mes : ""), WX_DEFAULT_CONV);
- if (m_progressFrame == NULL) {
+ wxString string((mes ? mes : ""), WX_DEFAULT_CONV);
+ if (m_progressDialog == NULL) {
+ m_progressDialog = new wxProgressDialog(wxT("Progress"), mes, 100, NULL, wxPD_APP_MODAL | wxPD_CAN_ABORT);
+ }
+/*
#if __WXMAC__
{
wxMenuBar *mbar = ((wxFrame *)GetTopWindow())->GetMenuBar();
m_progressFrame = new ProgressFrame(_T("Progress"), string);
m_progressCanceled = false;
m_progressValue = -1;
- }
+*/
}
void
MyApp::HideProgressPanel()
{
- if (m_progressFrame != NULL) {
+ if (m_progressDialog != NULL) {
+ m_progressDialog->Hide();
+ m_progressDialog->Destroy();
+ m_progressDialog = NULL;
+ }
+/*
+ if (m_progressFrame != NULL) {
m_progressFrame->Hide();
m_progressFrame->Destroy();
m_progressFrame = NULL;
}
#endif
}
+*/
}
void
MyApp::SetProgressValue(double dval)
{
- if (m_progressFrame != NULL) {
- m_progressFrame->SetProgressValue(dval);
- }
+ if (m_progressDialog != NULL) {
+ if (dval >= 0)
+ m_progressDialog->Update((int)(dval * 100));
+ else
+ m_progressDialog->Pulse();
+ }
}
void
MyApp::SetProgressMessage(const char *mes)
{
- if (m_progressFrame != NULL) {
+ if (m_progressDialog != NULL) {
wxString string((mes ? mes : ""), WX_DEFAULT_CONV);
- m_progressFrame->SetProgressMessage(string);
+ m_progressDialog->Update(0, string);
}
}
int
MyApp::IsInterrupted()
{
- if (m_progressFrame != NULL)
- return m_progressFrame->CheckInterrupt();
- else {
- if (::wxGetKeyState(WXK_ESCAPE))
- return 1;
- else return 0;
- }
+ if (m_progressDialog != NULL)
+ return m_progressDialog->WasCancelled();
+ else {
+ if (::wxGetKeyState(WXK_ESCAPE))
+ return 1;
+ else return 0;
+ }
}
void
parameterFilesFrame->Raise();
}
+void
+MyApp::OnBringAllWindowsToFront(wxCommandEvent &event)
+{
+ int size = 0, n;
+ wxWindowList::iterator iter;
+ wxTopLevelWindow **wins;
+ size = wxTopLevelWindows.size();
+ if (size > 0) {
+ wins = (wxTopLevelWindow **)calloc(sizeof(wxTopLevelWindow *), size);
+ for (iter = wxTopLevelWindows.begin(), n = 0; iter != wxTopLevelWindows.end(); ++iter, ++n) {
+ wins[n] = (wxTopLevelWindow *)(*iter);
+ }
+ for (n = 0; n < size; n++) {
+ if (wins[n]->IsShown())
+ wins[n]->Raise();
+ }
+ }
+}
+
int
MyApp::LookupScriptMenu(const char *title)
{
MainView *mview = MainViewCallback_activeView();
if (uid >= myMenuID_CustomScript && uid < myMenuID_CustomScript + countScriptMenu) {
// Check the script menu
+ // If the frontmost window is RubyDialogFrame, then disable any script menu command
+ wxWindow *w;
+#if defined(__WXMAC__)
+ void *MacGetActiveWindow(void);
+ w = wxDynamicCast(wxNonOwnedWindow::GetFromWXWindow((WXWindow)MacGetActiveWindow()), wxWindow);
+#else
+ w = wxGetActiveWindow();
+#endif
+ if (wxDynamicCast(w, RubyDialogFrame) != NULL) {
+ event.Enable(false);
+ return;
+ }
Molecule *mol;
int enabled, checked;
char *title;
checked = -1;
title = NULL;
enabled = Ruby_UpdateUI(index, mol, &checked, &title);
- if (checked >= 0)
+ if (checked >= 0
+#if wxCHECK_VERSION(3,2,0)
+ && event.IsCheckable()
+#endif
+ )
event.Check(checked != 0);
if (title != NULL) {
wxString wtext(title, WX_DEFAULT_CONV);
event.Enable(enabled != 0);
} else if (uid >= myMenuID_PredefinedFragment && uid <= myMenuID_PredefinedFragment + m_CountNamedFragments) {
event.Enable(true);
+#if defined(__WXMAC__)
+ } else if (uid >= wxID_OSX_MENU_FIRST && uid <= wxID_OSX_MENU_LAST) {
+ event.Enable(true);
+#endif
} else {
switch (uid) {
case myMenuID_ExecuteScript:
if (retval == (RubyValue)6 && status == -1)
MyAppCallback_errorMessageBox("Cannot open Ruby script %s", (const char *)path.mb_str(wxConvFile));
else if (status != 0)
- Molby_showError(status);
+ Ruby_showError(status);
}
dialog->Destroy();
}
}
void
-MyApp::RequestOpenFilesByIPC(wxString& files)
+MyApp::RequestOpenFilesByEvent(wxString& files)
{
+ /* We do not respond to "open file" event (either via IPC [MSW] or Apple Event [Mac])
+ while we are running something else */
+ if (m_progressDialog != NULL || gMolbyIsCheckingInterrupt || gMolbyRunLevel > 0)
+ return;
+
if (m_pendingFilesToOpen != NULL)
m_pendingFilesToOpen->Append(files);
else
m_pendingFilesToOpen = new wxString(files);
- wxCommandEvent myEvent(MyDocumentEvent, MyDocumentEvent_openFilesByIPC);
+ if (!m_pendingFilesToOpen->EndsWith(wxT("\n")))
+ m_pendingFilesToOpen->Append(wxT("\n"));
+ wxCommandEvent myEvent(MyDocumentEvent, MyDocumentEvent_openFilesByEvent);
wxPostEvent(this, myEvent);
}
void
-MyApp::OnOpenFilesByIPC(wxCommandEvent& event)
+MyApp::OnOpenFilesByEvent(wxCommandEvent& event)
{
if (m_pendingFilesToOpen == NULL)
return;
+ if (!gInitCompleted) {
+ // Repost this event and try again later
+ wxCommandEvent myEvent(MyDocumentEvent, MyDocumentEvent_openFilesByEvent);
+ wxPostEvent(this, myEvent);
+ return;
+ }
OnOpenFiles(*m_pendingFilesToOpen);
delete m_pendingFilesToOpen;
m_pendingFilesToOpen = NULL;
if (retval == (RubyValue)6 && status == -1)
MyAppCallback_errorMessageBox("Cannot open Ruby script: %s", (const char *)file.mb_str(wxConvFile));
else
- Molby_showError(status);
+ Ruby_showError(status);
return false;
}
} else {
static FILE *fplog;
#endif
+#if 0
void
MyApp::OnEndProcess(wxProcessEvent &event)
{
if (fplog != NULL)
fprintf(fplog, "OnEndProcess called\n");
#endif
- delete m_process;
- m_process = NULL;
+// delete m_process;
+// m_process = NULL;
}
+#endif
int
-MyApp::CallSubProcess(const char *cmdline, const char *procname, int (*callback)(void *), void *callback_data, FILE *fpout, FILE *fperr)
+MyApp::CallSubProcess(const char *cmdline, const char *procname, int (*callback)(void *), void *callback_data, FILE *fpout, FILE *fperr, int *exitstatus_p, int *pid_p)
{
int status = 0;
int callback_result = 0;
- int count = 0;
bool progress_panel = false;
char buf[256];
- size_t len, len_total;
wxString cmdstr(cmdline, WX_DEFAULT_CONV);
- wxLongLong startTime;
-
+ wxLongLong startTime, lastTime, presentTime;
+
if (m_process != NULL)
return -1; // Another process is already running (CallSubProcess() allows only one subprocess)
// Show progress panel
if (procname != NULL) {
snprintf(buf, sizeof buf, "Running %s...", procname);
- ShowProgressPanel(buf);
+ ShowProgressPanel(buf);
progress_panel = true;
}
- startTime = wxGetUTCTimeMillis();
+ startTime = lastTime = wxGetUTCTimeMillis();
// Create log file in the document home directory
#if LOG_SUBPROCESS
+ wxDateTime dateTime;
+ dateTime.SetToCurrent();
int nn = 0;
{
char *dochome = MyAppCallback_getDocumentHomeDir();
- snprintf(buf, sizeof buf, "%s/%s.log", dochome, (procname ? procname : "subprocess"));
+ snprintf(buf, sizeof buf, "%s/molby_subprocess.log", dochome);
free(dochome);
- fplog = fopen(buf, "w");
+ fplog = fopen(buf, "a");
if (fplog == NULL)
return -1;
}
#endif
// Create proc object and call subprocess
- m_process = new wxProcess(this, -1);
+ m_process = new wxBetterProcess(this, -1);
m_process->Redirect();
int flag = wxEXEC_ASYNC;
flag |= wxEXEC_MAKE_GROUP_LEADER;
- m_processTerminated = false;
- m_processExitCode = 0;
long pid = ::wxExecute(cmdstr, flag, m_process);
if (pid == 0) {
- if (procname != NULL)
- HideProgressPanel();
+ if (progress_panel)
+ HideProgressPanel();
delete m_process;
#if LOG_SUBPROCESS
fprintf(fplog, "Cannot start '%s'\n", cmdline);
#endif
return -1;
}
+ if (pid_p != NULL)
+ *pid_p = pid;
#if LOG_SUBPROCESS
- fprintf(fplog, "[DEBUG]pid = %ld\n", pid);
+ fprintf(fplog, "%s[DEBUG]pid = %ld\n", (const char *)(dateTime.FormatISOCombined(' ')), pid);
fflush(fplog);
#endif
// Wait until process ends or user interrupts
- wxInputStream *in;
- wxInputStream *err;
- len_total = 0;
- char *membuf = NULL;
- int memsize = 0;
- bool processShouldTerminate = false;
- while (1) {
- while (m_process != NULL && (m_process->IsInputAvailable())) {
- in = m_process->GetInputStream();
- in->Read(buf, sizeof buf - 1);
- if ((len = in->LastRead()) > 0) {
- buf[len] = 0;
- len_total += len;
-#if LOG_SUBPROCESS
- fprintf(fplog, "%s", buf);
- fflush(fplog);
-#endif
- if (callback == DUMMY_CALLBACK) {
- if (memsize < len_total + 1) {
- char *p = (char *)realloc(membuf, len_total + 1);
- if (p != NULL) {
- membuf = p;
- memmove(membuf + len_total - len, buf, len + 1);
- memsize = len_total + 1;
- }
- }
- } else if (fpout != NULL && fpout != (FILE *)1) {
- fputs(buf, fpout);
- } else if (fpout == (FILE *)1) {
- MyAppCallback_setConsoleColor(0);
- MyAppCallback_showScriptMessage("%s", buf);
- }
- }
- }
- while (m_process != NULL && (m_process->IsErrorAvailable())) {
- err = m_process->GetErrorStream();
- err->Read(buf, sizeof buf - 1);
- if ((len = err->LastRead()) > 0) {
- buf[len] = 0;
- len_total += len;
+ wxMemoryBuffer memBuffer; // Buffer to store standard output
+ bool interrupted = false;
+ wxString bufstr;
+ wxString buferrstr;
+ while (1) {
+ int len1, len2;
+ lastTime = wxGetUTCTimeMillis();
+ while ((len1 = m_process->GetLine(bufstr)) > 0) {
#if LOG_SUBPROCESS
- fprintf(fplog, "%s", buf);
- fflush(fplog);
-#endif
- if (fperr != NULL && fperr != (FILE *)1) {
- fputs(buf, fperr);
- } else if (fpout == (FILE *)1) {
- MyAppCallback_setConsoleColor(1);
- MyAppCallback_showScriptMessage("\n%s", buf);
- MyAppCallback_setConsoleColor(0);
- }
- }
- }
- if (progress_panel == false) {
- ::wxSafeYield(NULL); // This seems necessary to get OnEndProcess called
- if (++count == 40) {
- ShowProgressPanel("Running subprocess...");
- progress_panel = true;
- }
- }
- if (m_processTerminated) {
- // OnEndProcess has been called
- if (m_processExitCode != 0) {
- /* Error from subprocess */
- status = (m_processExitCode & 255);
- } else status = 0;
- break;
- }
-
- /* In some cases, wxProcess cannot detect the termination of the subprocess. */
- /* So here are the platform-dependent examination */
- /* 2014.3.23. This part of code is removed, in the hope that as of 3.0.0
- wxWidgets now reports the termination of the subprocess correctly. (T.Nagata) */
-#if __WXMSW__
- if (0) {
- // get the process handle to operate on
- HANDLE hProcess = ::OpenProcess(SYNCHRONIZE |
- PROCESS_TERMINATE |
- PROCESS_QUERY_INFORMATION,
- false, // not inheritable
- (DWORD)pid);
- if (hProcess == NULL) {
- if (::GetLastError() != ERROR_ACCESS_DENIED) {
- processShouldTerminate = true;
- status = 255;
- }
- } else {
- DWORD exitCode;
- if (::GetExitCodeProcess(hProcess, &exitCode) && exitCode != STILL_ACTIVE) {
- processShouldTerminate = true;
- status = exitCode & 255;
- }
- ::CloseHandle(hProcess);
- }
- }
-#else
- if (0 && waitpid(pid, &status, WNOHANG) != 0) {
- processShouldTerminate = true;
- //proc->Detach();
- status = WEXITSTATUS(status);
- //break;
- }
+ dateTime.SetToCurrent();
+ fprintf(fplog, "%s[STDOUT]%s", (const char *)(dateTime.FormatISOCombined(' ')), (const char *)bufstr);
+ fflush(fplog);
#endif
- if (processShouldTerminate) {
- int count1;
+ if (callback == DUMMY_CALLBACK) {
+ const char *p = (const char *)bufstr;
+ memBuffer.AppendData(p, strlen(bufstr));
+ } else if (fpout != NULL && fpout != (FILE *)1) {
+ fputs((const char *)bufstr, fpout);
+ } else if (fpout == (FILE *)1) {
+ MyAppCallback_setConsoleColor(0);
+ MyAppCallback_showScriptMessage("%s", (const char *)bufstr);
+ }
+ presentTime = wxGetUTCTimeMillis();
+ if (presentTime > lastTime + 25) {
+ presentTime = lastTime;
+ break;
+ }
+ }
+ while ((len2 = m_process->GetErrorLine(buferrstr)) > 0) {
#if LOG_SUBPROCESS
- if (fplog) {
- fprintf(fplog, "OnEndProcess *NOT* called\n");
- fflush(fplog);
- }
+ dateTime.SetToCurrent();
+ fprintf(fplog, "%s[STDERR]%s", (const char *)(dateTime.FormatISOCombined(' ')), buf);
+ fflush(fplog);
#endif
- for (count1 = 100; count1 > 0; count1--) {
- if (!wxProcess::Exists(pid))
- break;
- ::wxMilliSleep(10);
- }
- if (count1 == 0)
- m_process->Detach();
- {
- char *dochome = MyAppCallback_getDocumentHomeDir();
- FILE *fp1;
- snprintf(buf, sizeof buf, "%s/%s.log", dochome, (procname ? procname : "subprocess"));
- free(dochome);
- fp1 = fopen(buf, "w");
- if (fp1 != NULL) {
- fprintf(fp1, "OnEndProcess *NOT* called: count1 = %d\n", count1);
- ::wxMilliSleep(500);
- if (m_processTerminated)
- fprintf(fp1, "It looks like OnEndProcess is called after our checking.\n");
- fclose(fp1);
- }
- }
-
- break;
- }
-
+ if (fperr != NULL && fperr != (FILE *)1) {
+ fputs((const char *)buferrstr, fperr);
+ } else if (fpout == (FILE *)1) {
+ MyAppCallback_setConsoleColor(1);
+ MyAppCallback_showScriptMessage("\n%s", (const char *)buferrstr);
+ MyAppCallback_setConsoleColor(0);
+ }
+ presentTime = wxGetUTCTimeMillis();
+ if (presentTime > lastTime + 25) {
+ presentTime = lastTime;
+ break;
+ }
+ }
+ if (len1 < 0 && len2 < 0) {
+ // The standard/error outputs are exhausted; the process should have terminated
+ // (Normally, this should be detected by wxBetterProcess::OnTerminate())
+ interrupted = true;
+ }
+ ::wxMilliSleep(25);
+ if (callback != NULL && callback != DUMMY_CALLBACK) {
+ callback_result = (*callback)(callback_data);
+ if (callback_result != 0)
+ interrupted = true;
+ }
+ ::wxSafeYield(); // This allows updating console and wxProcess status
+ if (progress_panel) {
+ SetProgressValue(-1);
+ if (IsInterrupted())
+ interrupted = true;
+ }
+
#if LOG_SUBPROCESS
- if (++nn >= 10) {
- fprintf(fplog, "[DEBUG]pid %ld exists\n", pid);
- fflush(fplog);
- nn = 0;
- }
+ if (++nn >= 10) {
+ dateTime.SetToCurrent();
+ fprintf(fplog, "%s[DEBUG]pid %ld exists\n", (const char *)(dateTime.FormatISOCombined(' ')), pid);
+ fflush(fplog);
+ nn = 0;
+ }
#endif
- ::wxMilliSleep(25);
- if (wxGetApp().IsInterrupted() || (callback != NULL && callback != DUMMY_CALLBACK && (callback_result = (*callback)(callback_data)) != 0)) {
- /* User interrupt */
- int kflag = wxKILL_CHILDREN;
- wxKillError rc;
- if (
+ if (m_process->IsTerminated() || !wxProcess::Exists(pid)) {
+ /* The subprocess has terminated */
+ status = m_process->GetStatus();
+ break;
+ } else if (interrupted) {
+ /* User interrupt */
+ int kflag = wxKILL_CHILDREN;
+ wxKillError rc;
+ if (
#if __WXMSW__
- myKillAllChildren(pid, wxSIGKILL, &rc) != 0
+ myKillAllChildren(pid, wxSIGKILL, &rc) != 0
#else
- ::wxKill(pid, wxSIGTERM, &rc, kflag) != 0
-#endif
- ) {
- switch (rc) {
- case wxKILL_BAD_SIGNAL: status = -3; break; /* No such signal */
- case wxKILL_ACCESS_DENIED: status = -4; break; /* Permission denied */
- case wxKILL_NO_PROCESS: status = -5; break; /* No such process */
- default: status = -6; break; /* unknown error */
- }
- } else {
- if (callback_result != 0)
- status = -3; /* Interrupt from callback */
- else
- status = -2; /* User interrupt */
- }
- m_process->Detach();
- break;
- }
- }
-#if LOG_SUBPROCESS
- fclose(fplog);
+ ::wxKill(pid, wxSIGTERM, &rc, kflag) != 0
#endif
+ ) {
+ switch (rc) {
+ case wxKILL_BAD_SIGNAL: status = -3; break; /* No such signal */
+ case wxKILL_ACCESS_DENIED: status = -4; break; /* Permission denied */
+ case wxKILL_NO_PROCESS: status = -5; break; /* No such process */
+ default: status = -6; break; /* unknown error */
+ }
+ } else {
+ if (callback_result != 0)
+ status = -3; /* Interrupt from callback */
+ else
+ status = -2; /* User interrupt */
+ }
+ m_process->Detach();
+ m_process = NULL;
+ break;
+ }
+ }
+
+ if (exitstatus_p != NULL)
+ *exitstatus_p = status;
- if (progress_panel)
- HideProgressPanel();
+ if (progress_panel) {
+ HideProgressPanel();
+ }
+
+ if (m_process != NULL) {
+ m_process->Detach();
+ m_process = NULL;
+ }
if (callback == DUMMY_CALLBACK) {
+ char *membuf = NULL;
+ size_t memsize = 0;
+ memBuffer.AppendByte(0);
+ memsize = memBuffer.GetDataLen();
+ membuf = (char *)malloc(memsize);
+ if (membuf != NULL) {
+ memmove(membuf, memBuffer.GetData(), memsize);
#if __WXMSW__
- if (membuf != NULL) {
- /* Convert "\r\n" to "\n" */
- char *p, *pend;
- p = pend = membuf + strlen(membuf);
- while (--p >= membuf) {
- if (*p == '\r') {
- memmove(p, p + 1, pend - p);
- pend--;
- }
- }
- }
+ {
+ /* Convert "\r\n" to "\n" */
+ char *p, *pend;
+ p = pend = membuf + strlen(membuf) + 1;
+ while (--p >= membuf) {
+ if (*p == '\r') {
+ memmove(p, p + 1, pend - p);
+ pend--;
+ }
+ }
+ }
#endif
- *((char **)callback_data) = membuf;
+ *((char **)callback_data) = membuf;
+ }
}
return status;
this->AddPendingEvent(myEvent);
}
+void
+MyApp::OnHelp(wxCommandEvent& WXUNUSED(event) )
+{
+ static wxString url;
+ if (url.IsEmpty()) {
+ url = FindResourcePath();
+#if defined(__WXMSW__)
+ if (url.SubString(0, 1) == wxT("\\\\")) {
+ // Network drive: convert to the drive letter
+ wxBetterProcess *process = new wxBetterProcess(this, -1);
+ process->Redirect();
+ long pid = ::wxExecute("net use", wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER, process);
+ if (pid != 0) {
+ wxRegEx re(wxT("^[[:space:]]+([A-Za-z]:)[[:space:]]+(.*)$"));
+ wxString bufstr;
+ while (process->GetLine(bufstr) >= 0) {
+ bufstr = bufstr.Trim();
+ if (!bufstr.IsEmpty() && re.Matches(bufstr)) {
+ wxString dr = re.GetMatch(bufstr, 1);
+ wxString path = re.GetMatch(bufstr, 2);
+ if (url.Left(path.Length()) == path) {
+ url = dr + url.Mid(path.Length());
+ break;
+ }
+ }
+ }
+ process->Detach();
+ }
+ }
+#endif
+ url.Replace(wxFILE_SEP_PATH, wxT("/"));
+ url += "/MolbyDoc/ja/index.html";
+ }
+ wxLaunchDefaultBrowser(wxT("file:///") + url);
+}
+
+int
+MyApp::FilterEvent(wxEvent &event)
+{
+#if 0
+ static FILE *fp_eventlog = NULL;
+ if (fp_eventlog == NULL) {
+ char buf[32];
+ int i = 0;
+ while (1) {
+ snprintf(buf, sizeof buf, "Molby_eventlog_%d.log", i);
+ fp_eventlog = fopen(buf, "r");
+ if (fp_eventlog == NULL) {
+ fp_eventlog = fopen(buf, "wt");
+ break;
+ } else {
+ fclose(fp_eventlog);
+ i++;
+ }
+ }
+ }
+ if (fp_eventlog != NULL) {
+ fprintf(fp_eventlog, "%d %d\n", event.GetEventType(), event.GetId());
+ }
+ fflush(fp_eventlog);
+ }
+#endif
+ return -1;
+}
+
+#pragma mark ====== AboutBox ======
+
+IMPLEMENT_CLASS(AboutDialog, wxDialog)
+BEGIN_EVENT_TABLE(AboutDialog, wxDialog)
+END_EVENT_TABLE()
+
+AboutDialog::AboutDialog():
+ wxDialog(NULL, -1, wxT("About Molby"))
+{
+ // vsizer1 --> hsizer1 --> Molby icon
+ // | |-> vsizer2 --> "Molby"
+ // | |-> version strings
+ // |
+ // |-> copyright messages
+
+ const char *s1;
+ char *s2, *s3;
+ s1 = "Molby";
+ Molby_getDescription(&s2, &s3);
+ wxString str1(s1, WX_DEFAULT_CONV);
+ wxString str2(s2, WX_DEFAULT_CONV);
+ wxString str3(s3, WX_DEFAULT_CONV);
+ free(s2);
+ free(s3);
+#if defined(__WXMSW__)
+ wxFont *textFont0 = new wxFont(FromFrameDIP(this, 12), wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD);
+ wxFont *textFont1 = new wxFont(FromFrameDIP(this, 10), wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
+ wxFont *textFont2 = new wxFont(FromFrameDIP(this, 9), wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
+#else
+ wxFont *textFont0 = new wxFont(FromFrameDIP(this, 14), wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD);
+ wxFont *textFont1 = new wxFont(FromFrameDIP(this, 12), wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
+ wxFont *textFont2 = new wxFont(FromFrameDIP(this, 11), wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
+#endif
+ wxBoxSizer *vsizer1 = new wxBoxSizer(wxVERTICAL);
+ wxBoxSizer *vsizer2 = new wxBoxSizer(wxVERTICAL);
+ wxBoxSizer *hsizer1 = new wxBoxSizer(wxHORIZONTAL);
+ wxString tifname = wxGetApp().FindResourcePath() + wxFILE_SEP_PATH + wxT("bitmaps/molby_icon64.png");
+ wxBitmap *molbyBitmap = new wxBitmap(tifname, wxBITMAP_TYPE_PNG);
+ wxStaticText *stext1 = new wxStaticText(this, -1, wxT("Molby"));
+ stext1->SetFont(*textFont0);
+ wxStaticText *stext2 = new wxStaticText(this, -1, str2);
+ stext2->SetFont(*textFont1);
+ wxStaticBitmap *staticBitmap = new wxStaticBitmap(this, -1, *molbyBitmap);
+ vsizer2->Add(stext1, 0, wxALL | wxEXPAND, FromFrameDIP(this, 2));
+ vsizer2->Add(stext2, 0, wxALL | wxEXPAND, FromFrameDIP(this, 2));
+ hsizer1->AddSpacer(FromFrameDIP(this, 20));
+ hsizer1->Add(staticBitmap, 0, 0, FromFrameDIP(this, 10));
+ hsizer1->AddSpacer(FromFrameDIP(this, 20));
+ hsizer1->Add(vsizer2, 0, wxALL | wxEXPAND, FromFrameDIP(this, 5));
+ wxStaticText *stext3 = new wxStaticText(this, -1, str3);
+ stext3->SetFont(*textFont2);
+ vsizer1->Add(hsizer1, 0, wxALL | wxEXPAND, FromFrameDIP(this, 5));
+ vsizer1->Add(stext3, 0, wxALL | wxEXPAND, FromFrameDIP(this, 5));
+ vsizer1->Add(this->CreateButtonSizer(wxOK), 0, wxALL | wxEXPAND, FromFrameDIP(this, 10));
+ vsizer1->Layout();
+ this->SetSizerAndFit(vsizer1);
+ this->Centre();
+}
+
#pragma mark ====== MyFrame (top-level window) ======
/*
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
{
- char *s;
- s = Molby_getDescription();
- wxString str(s, WX_DEFAULT_CONV);
- (void)wxMessageBox(str, _T("Molby"));
- free(s);
+ AboutDialog *d = new AboutDialog();
+ if ( d->ShowModal() == wxID_OK )
+ d->Destroy();
}
MyFrame *GetMainFrame(void)
return frame;
}
+#if 0
+#pragma mark ====== Better wxProcess ======
+#endif
+
+void
+wxBetterProcess::OnTerminate(int pid, int status)
+{
+ m_terminated = true;
+ m_status = status;
+}
+wxKillError
+wxBetterProcess::KillProcess(wxSignal sig, int flags)
+{
+ wxKillError retval = wxProcess::Kill(this->GetPid(), sig, flags);
+ if (retval == wxKILL_OK)
+ m_killSignal = sig;
+ return retval;
+}
+
+int
+wxBetterProcess::GetLineSub(wxString &outStr, wxInputStream *stream, wxMemoryBuffer &mbuf)
+{
+ int err = wxSTREAM_NO_ERROR;
+ int trial = 0;
+ char *p, *pp;
+ long len;
+ char buf[1024];
+ if (stream == NULL)
+ return -3; // No stderr stream
+ while (1) {
+ p = (char *)mbuf.GetData();
+ len = mbuf.GetDataLen();
+ if (len > 0) {
+ pp = (char *)memchr(p, '\n', len);
+ if (pp == NULL)
+ pp = (char *)memchr(p, '\r', len);
+ if (pp == NULL && stream->GetLastError() == wxSTREAM_EOF) {
+ // If EOF, then return all remaining data (without '\n')
+ pp = p + mbuf.GetDataLen() - 1; // Point to the last char
+ }
+ if (pp != NULL) {
+ // Return one line and string length
+ outStr = wxString(p, wxConvUTF8, pp - p + 1);
+ memmove(p, pp + 1, len - (pp - p + 1));
+ m_stdout.SetDataLen(len - (pp - p + 1));
+ return pp - p + 1;
+ }
+ }
+ if (trial > 0) {
+ // stream->Read() is called only once
+ outStr = _T("");
+ if (err == wxSTREAM_EOF)
+ return -1; // EOF and no data left
+ return 0; // Not EOF, but no data is available at present
+ }
+ len = 0;
+ if (stream->CanRead()) {
+ // We need to read by one character because wxInputStream has
+ // no way to give the available number of bytes
+ stream->Read(buf, sizeof buf);
+ err = stream->GetLastError();
+ if (err != wxSTREAM_NO_ERROR && err != wxSTREAM_EOF)
+ return -2; // Some read error
+ len = stream->LastRead();
+ } else err = stream->GetLastError();
+ if (len > 0)
+ mbuf.AppendData(buf, len);
+ trial++;
+ }
+}
+
+int
+wxBetterProcess::GetLine(wxString &outStr)
+{
+ return GetLineSub(outStr, this->GetInputStream(), m_stdout);
+}
+
+int
+wxBetterProcess::GetErrorLine(wxString &outStr)
+{
+ return GetLineSub(outStr, this->GetErrorStream(), m_stderr);
+}
+
+int
+wxBetterProcess::PutLine(wxString str)
+{
+ wxOutputStream *stream = this->GetOutputStream();
+ if (stream == NULL)
+ return -3; // No stdin stream
+ const char *p = str.utf8_str();
+ long len = strlen(p);
+ if (len > 0)
+ m_stdin.AppendData(p, len);
+ char *pp = (char *)m_stdin.GetData();
+ len = m_stdin.GetDataLen();
+ if (len == 0)
+ return 0;
+ stream->Write(pp, len);
+ long len2 = stream->LastWrite();
+ if (len2 > 0) {
+ memmove(pp, pp + len2, len - len2);
+ m_stdin.SetDataLen(len - len2);
+ }
+ return len2;
+}
+
+void
+wxBetterProcess::CloseOutput()
+{
+ // We must flush the data in the internal buffer before closing the output
+ while (PutLine("") > 0) {}
+ wxProcess::CloseOutput(); // Call the original version
+}
+
#pragma mark ====== Plain-C interface ======
char *
if (desc == NULL) {
asprintf(&desc,
"AmberTools 1.3, http://ambermd.org/\n"
- " Copyright (C) Junmei Wang, Ross C. Walker, \n"
- " Michael F. Crowley, Scott Brozell and David A. Case\n"
+ " Copyright (C) Junmei Wang, Ross C. Walker, "
+ "Michael F. Crowley, Scott Brozell and David A. Case\n"
"ORTEP-III, http://web.ornl.gov/sci/ortep/\n"
- " Michael N. Burnett and Carroll K. Johnson, \n"
- " Oak Ridge National Laboratory Report ORNL-6895,\n"
- " 1996.\n"
+ " Michael N. Burnett and Carroll K. Johnson, "
+ "Oak Ridge National Laboratory Report ORNL-6895, "
+ "1996.\n"
"wxWidgets %d.%d.%d, http://www.wxwidgets.org/\n"
- " Copyright (C) 1992-2013 Julian Smart, Vadim\n"
- " Zeitlin, Stefan Csomor, Robert Roebling,\n"
- " and other members of the wxWidgets team\n"
- " Portions (C) 1996 Artificial Intelligence \n"
- " Applications Institute\n",
+#if wxCHECK_VERSION(3,2,0)
+ " Copyright (C) 1992-2022 Julian Smart, Vadim "
+#else
+ " Copyright (C) 1992-2013 Julian Smart, Vadim "
+#endif
+ "Zeitlin, Stefan Csomor, Robert Roebling,\n"
+ " and other members of the wxWidgets team\n"
+ " Portions (C) 1996 Artificial Intelligence "
+ "Applications Institute\n",
wxMAJOR_VERSION, wxMINOR_VERSION, wxRELEASE_NUMBER);
}
return desc;
void
MyAppCallback_loadGlobalSettings(void)
{
+ if (!gUseGUI)
+ return;
wxGetApp().LoadDefaultSettings();
}
void
MyAppCallback_saveGlobalSettings(void)
{
+ if (!gUseGUI)
+ return;
wxGetApp().SaveDefaultSettings();
}
char *
MyAppCallback_getGlobalSettings(const char *key)
{
- wxString wxkey(key, WX_DEFAULT_CONV);
- wxString wxvalue = wxGetApp().GetDefaultSetting(wxkey);
- return strdup(wxvalue.mb_str(WX_DEFAULT_CONV));
+ if (!gUseGUI)
+ return NULL;
+ wxString wxkey(key, WX_DEFAULT_CONV);
+ wxString wxvalue = wxGetApp().GetDefaultSetting(wxkey);
+ return strdup(wxvalue.mb_str(WX_DEFAULT_CONV));
}
void
MyAppCallback_setGlobalSettings(const char *key, const char *value)
{
+ if (!gUseGUI)
+ return;
wxString wxkey(key, WX_DEFAULT_CONV);
wxString wxvalue(value, WX_DEFAULT_CONV);
wxGetApp().SetDefaultSetting(wxkey, wxvalue);
int
MyAppCallback_getGlobalSettingsWithType(const char *key, int type, void *ptr)
{
- int retval;
+ int retval, temp;
char *s = MyAppCallback_getGlobalSettings(key);
char desc[] = SCRIPT_ACTION("s; ");
desc[sizeof(desc) - 2] = type;
+ temp = gMolActionNoErrorDialog;
+ gMolActionNoErrorDialog = 1;
retval = MolActionCreateAndPerform(NULL, desc, "eval", s, ptr);
free(s);
+ gMolActionNoErrorDialog = temp;
return retval;
}
{
const char *cmd = "set_global_settings";
switch (type) {
- case 'i': return MolActionCreateAndPerform(NULL, SCRIPT_ACTION("i"), cmd, *((const Int *)ptr));
- case 'd': return MolActionCreateAndPerform(NULL, SCRIPT_ACTION("d"), cmd, *((const Double *)ptr));
- case 's': return MolActionCreateAndPerform(NULL, SCRIPT_ACTION("s"), cmd, (const char *)ptr);
- case 'v': return MolActionCreateAndPerform(NULL, SCRIPT_ACTION("v"), cmd, (const Vector *)ptr);
- case 't': return MolActionCreateAndPerform(NULL, SCRIPT_ACTION("t"), cmd, (const Transform *)ptr);
+ case 'i': return MolActionCreateAndPerform(NULL, SCRIPT_ACTION("si"), cmd, key, *((const Int *)ptr));
+ case 'd': return MolActionCreateAndPerform(NULL, SCRIPT_ACTION("sd"), cmd, key, *((const Double *)ptr));
+ case 's': return MolActionCreateAndPerform(NULL, SCRIPT_ACTION("ss"), cmd, key, (const char *)ptr);
+ case 'v': return MolActionCreateAndPerform(NULL, SCRIPT_ACTION("sv"), cmd, key, (const Vector *)ptr);
+ case 't': return MolActionCreateAndPerform(NULL, SCRIPT_ACTION("st"), cmd, key, (const Transform *)ptr);
default:
MyAppCallback_errorMessageBox("Internal error: unsupported format '%c' at line %d, file %s", type, __LINE__, __FILE__);
return -2;
int
MyAppCallback_checkInterrupt(void)
{
- return wxGetApp().IsInterrupted();
+ if (!gUseGUI)
+ return 0;
+ return wxGetApp().IsInterrupted();
}
void
MyAppCallback_showProgressPanel(const char *msg)
{
- wxGetApp().ShowProgressPanel(msg);
+ if (!gUseGUI)
+ return;
+ wxGetApp().ShowProgressPanel(msg);
}
void
MyAppCallback_hideProgressPanel(void)
{
- wxGetApp().HideProgressPanel();
+ if (!gUseGUI)
+ return;
+ wxGetApp().HideProgressPanel();
}
void
MyAppCallback_setProgressValue(double dval)
{
- wxGetApp().SetProgressValue(dval);
+ if (!gUseGUI)
+ return;
+ wxGetApp().SetProgressValue(dval);
}
void
MyAppCallback_setProgressMessage(const char *msg)
{
- wxGetApp().SetProgressMessage(msg);
+ if (!gUseGUI)
+ return;
+ wxGetApp().SetProgressMessage(msg);
}
int
MyAppCallback_getTextWithPrompt(const char *prompt, char *buf, int bufsize)
{
+ if (!gUseGUI) {
+ buf[0] = 0;
+ return 0;
+ }
wxDialog *dialog = new wxDialog(NULL, -1, _T("Input request"), wxDefaultPosition);
wxStaticText *stext;
wxTextCtrl *tctrl;
{ // Vertical sizer containing [prompt, textbox, buttons]
wxBoxSizer *sizer1;
sizer1 = new wxBoxSizer(wxVERTICAL);
- stext = new wxStaticText(dialog, -1, pstr, wxDefaultPosition, wxSize(200, 22));
- sizer1->Add(stext, 0, wxEXPAND | wxALL, 6);
- tctrl = new wxTextCtrl(dialog, -1, defstr, wxDefaultPosition, wxSize(200, 22));
- sizer1->Add(tctrl, 0, wxEXPAND | wxALL, 6);
+ stext = new wxStaticText(dialog, -1, pstr, wxDefaultPosition, FromFrameDIP(dialog, wxSize(200, 22)));
+ sizer1->Add(stext, 0, wxEXPAND | wxALL, FromFrameDIP(dialog, 6));
+ tctrl = new wxTextCtrl(dialog, -1, defstr, wxDefaultPosition, FromFrameDIP(dialog, wxSize(200, 22)));
+ sizer1->Add(tctrl, 0, wxEXPAND | wxALL, FromFrameDIP(dialog, 6));
wxSizer *bsizer = dialog->CreateButtonSizer(wxOK | wxCANCEL);
- sizer1->Add(bsizer, 0, wxEXPAND | wxALL, 6);
+ sizer1->Add(bsizer, 0, wxEXPAND | wxALL, FromFrameDIP(dialog, 6));
sizer1->Layout();
dialog->SetSizerAndFit(sizer1);
dialog->Centre(wxBOTH);
+ tctrl->SelectAll();
tctrl->SetFocus();
}
if (dialog->ShowModal() == wxID_OK) {
int
MyAppCallback_messageBox(const char *message, const char *title, int flags, int icon)
{
+ if (!gUseGUI) {
+ printf("%s\n%s\n", title, message);
+ return 1;
+ }
+
int wxflags, wxicon, retval;
if (!wxGetApp().IsMainLoopRunning()) {
MyAppCallback_setConsoleColor(1);
void
MyAppCallback_errorMessageBox(const char *fmt, ...)
{
+ if (!gUseGUI) {
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ return;
+ }
char *s;
int need_free = 0;
va_list ap;
return (s == NULL ? NULL : strdup(s));
}
+#if __WXMSW__
+#include <Shlobj.h>
+#endif
+
char *
MyAppCallback_getDocumentHomeDir(void)
{
- char *s;
#if __WXMSW__
- char *ss;
- s = getenv("USERPROFILE");
- asprintf(&ss, "%s\\My Documents", s);
- return ss;
+ char appData[MAX_PATH * 2];
+ HRESULT hResult;
+ hResult = SHGetFolderPathA(NULL, CSIDL_PERSONAL, NULL, 0, appData);
+ if (hResult == S_OK) {
+ return strdup(appData);
+ } else {
+ return MyAppCallback_getHomeDir();
+ }
#else
+ char *s;
s = getenv("HOME");
return (s == NULL ? NULL : strdup(s));
#endif
int
MyAppCallback_registerScriptMenu(const char *title)
{
+ if (!gUseGUI)
+ return -1;
return wxGetApp().RegisterScriptMenu(title);
}
int
MyAppCallback_lookupScriptMenu(const char *title)
{
+ if (!gUseGUI)
+ return 0;
return wxGetApp().LookupScriptMenu(title);
}
RubyValue
MyAppCallback_executeScriptFromFile(const char *cpath, int *status)
{
+ if (!gUseGUI) {
+ return 0;
+ }
+
RubyValue retval;
wxString cwd = wxFileName::GetCwd();
wxString path(cpath, wxConvFile);
void MyAppCallback_beginUndoGrouping(void)
{
+ if (!gUseGUI)
+ return;
wxList &doclist = wxGetApp().DocManager()->GetDocuments();
wxList::iterator iter;
for (iter = doclist.begin(); iter != doclist.end(); ++iter) {
void MyAppCallback_endUndoGrouping(void)
{
+ if (!gUseGUI)
+ return;
wxList &doclist = wxGetApp().DocManager()->GetDocuments();
wxList::iterator iter;
for (iter = doclist.begin(); iter != doclist.end(); ++iter) {
}
}
-int MyAppCallback_callSubProcess(const char *cmdline, const char *procname, int (*callback)(void *), void *callback_data, FILE *output, FILE *errout)
+int MyAppCallback_callSubProcess(const char *cmdline, const char *procname, int (*callback)(void *), void *callback_data, FILE *output, FILE *errout, int *exitstatus_p, int *pid_p)
{
- return wxGetApp().CallSubProcess(cmdline, procname, callback, callback_data, output, errout);
+ if (!gUseGUI)
+ return system(cmdline);
+ return wxGetApp().CallSubProcess(cmdline, procname, callback, callback_data, output, errout, exitstatus_p, pid_p);
}
void MyAppCallback_showConsoleWindow(void)
{
+ if (!gUseGUI)
+ return;
ConsoleFrame *frame = wxGetApp().GetConsoleFrame();
frame->Show(true);
frame->Raise();
void MyAppCallback_hideConsoleWindow(void)
{
+ if (!gUseGUI)
+ return;
ConsoleFrame *frame = wxGetApp().GetConsoleFrame();
frame->Hide();
}
void MyAppCallback_bell(void)
{
- wxBell();
+ if (!gUseGUI)
+ return;
+ wxBell();
}
int MyAppCallback_playSound(const char *filename, int flag)
{
+ if (!gUseGUI)
+ return 0;
unsigned uflag = wxSOUND_SYNC;
if (flag == 1)
uflag = wxSOUND_ASYNC;
void MyAppCallback_stopSound(void)
{
+ if (!gUseGUI)
+ return;
wxSound::Stop();
}