#include "wx/stdpaths.h"
#include "wx/textfile.h"
#include "wx/process.h"
+#include "wx/utils.h"
+#include "wx/sound.h"
+#include "wx/time.h"
#include "MyApp.h"
#include "MyDocument.h"
#include "ProgressFrame.h"
#include "GlobalParameterFrame.h"
#include "GlobalParameterFilesFrame.h"
+#include "RubyDialogFrame.h"
#include "MyMBConv.h"
#if defined(__WXMSW__)
#endif
#include "../MolLib/MolLib.h"
-#include "../MolLib/Ruby_bind/Molby.h"
+#include "../MolLib/Ruby_bind/Molby_extern.h"
#include "../MolLib/Missing.h"
#include <wchar.h>
#include <CoreFoundation/CoreFoundation.h>
#undef T_DATA
#include <Carbon/Carbon.h>
-#include "wx/mac/carbon/private.h"
+// #include "wx/mac/carbon/private.h"
#include <sys/wait.h> /* for waitpid() */
#endif
#pragma mark ====== MyApp ======
+const char *gSettingQuitOnCloseLastWindow = "quit_on_close_last_window";
+
MyFrame *frame = (MyFrame *) NULL;
+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_KEY_DOWN(MyApp::OnChar)
- //EVT_MOUSE_EVENTS(MyApp::OnMouseEvent)
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_ReadParameters, MyApp::OnReadParameters)
EVT_MENU(myMenuID_ViewGlobalParameters, MyApp::OnViewGlobalParameters)
EVT_MENU(myMenuID_ViewParameterFilesList, MyApp::OnViewParameterFilesList)
- EVT_MENU(myMenuID_ImportAmberLib, MyApp::OnImportAmberLib)
+ 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()
// Find the path of the directory where the relevant resources are to be found.
// 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_processTerminated = false;
- m_processExitCode = 0;
+ m_progressDialog = NULL;
+ m_process = NULL;
+// m_processTerminated = false;
+// m_processExitCode = 0;
countScriptMenu = 0;
- scriptMenuCommands = NULL;
scriptMenuTitles = NULL;
+ scriptMenuPositions = NULL;
scriptMenuModifiedEventPosted = false;
parameterFrame = NULL;
parameterFilesFrame = NULL;
m_CountNamedFragments = 0;
m_NamedFragments = (char **)(-1); /* Will be set to NULL after Ruby interpreter is initialized */
m_pendingFilesToOpen = NULL;
+ m_CountTimerDocs = 0;
+ m_TimerDocs = NULL;
+ m_Timer = NULL;
+
#if defined(__WXMSW__)
m_checker = NULL;
m_ipcServiceName = 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__
m_checker = new wxSingleInstanceChecker(name);
if (m_checker->IsAnotherRunning()) {
// Make a connection with the other instance and ask for opening the file(s)
- wxString files;
- wxConnectionBase *connection;
- while (argc > 1) {
- files.append(argv[1]);
- files.append(wxT("\n"));
- argc--;
- argv++;
- }
- m_client = new MyClient;
- connection = m_client->MakeConnection(wxT("localhost"), *m_ipcServiceName, MOLBY_IPC_TOPIC);
- if (connection == NULL) {
- wxLogError(wxT("Molby is already running; please shut it down and retry"));
+ if (argc > 1) {
+ wxString files;
+ wxConnectionBase *connection;
+ int i;
+ for (i = 1; i < argc; i++) {
+ files.append(argv[i]);
+ files.append(wxT("\n"));
+ }
+ m_client = new MyClient;
+ connection = m_client->MakeConnection(wxT("localhost"), *m_ipcServiceName, MOLBY_IPC_TOPIC);
+ if (connection == NULL) {
+ wxLogError(wxT("Molby is already running; please shut it down and retry"));
+ delete m_client;
+ return false;
+ }
+ connection->Execute(files);
delete m_client;
- return false;
}
- connection->Execute(files);
- delete m_client;
return false;
} else {
m_server = new MyServer;
new wxDocTemplate(m_docManager, _T("SHELX Input File"), _T("*.ins;*.res"), _T(""), _T("ins"), _T("Molecule Doc"), _T("Molecule View"), CLASSINFO(MyDocument), CLASSINFO(MoleculeView));
new wxDocTemplate(m_docManager, _T("Crystallographic Information File"), _T("*.cif"), _T(""), _T("cif"), _T("Molecule Doc"), _T("Molecule View"), CLASSINFO(MyDocument), CLASSINFO(MoleculeView));
new wxDocTemplate(m_docManager, _T("Cartesian"), _T("*.xyz"), _T(""), _T("xyz"), _T("Molecule Doc"), _T("Molecule View"), CLASSINFO(MyDocument), CLASSINFO(MoleculeView));
+ 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__
#ifdef __X__
frame->SetIcon(wxIcon(_T("doc.xbm")));
#endif
-
+
wxMenuBar *menu_bar = CreateMenuBar(0);
#ifdef __WXMAC__
frame->Centre(wxBOTH);
-#if defined(__WXMAC__)
+#if defined(__WXMAC__) || defined(__WXMSW__)
frame->Move(-10000, -10000); // Set invisible
frame->Show(false);
#else
frame->Show(true);
#endif
-
+
SetTopWindow(frame);
-
+
// Load default settings from the preference file
LoadDefaultSettings();
{
extern int gRevisionNumber;
static const char fname[] = "startup.rb";
+ InitResourcePath(argc, argv);
wxString dirname = FindResourcePath();
dirname += wxFILE_SEP_PATH;
/* Build the predefined fragments menu */
m_NamedFragments = NULL;
- UpdatePredefinedFragmentMenu(GetMainFrame()->GetMenuBar());
+ // UpdatePredefinedFragmentMenu(GetMainFrame()->GetMenuBar());
UpdatePredefinedFragmentMenu(consoleFrame->GetMenuBar());
}
for (i = 1; i < argc; i++) {
files.append(argv[i]);
files.append(wxT("\n"));
- argc--;
- argv++;
}
- OnOpenFiles(files);
+ RequestOpenFilesByEvent(files);
}
+ gInitCompleted = true;
+
return 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
file_menu->Append(wxID_CLOSE, _T("&Close\tCtrl-W"));
file_menu->Append(wxID_SAVE, _T("&Save\tCtrl-S"));
file_menu->Append(wxID_SAVEAS, _T("Save &As..."));
- file_menu->Append(wxID_REVERT, _T("Revert..."));
+ file_menu->Append(wxID_REVERT, _T("Revert to Saved"));
file_menu->AppendSeparator();
file_menu->Append(myMenuID_Import, _T("Import..."));
file_menu->Append(myMenuID_Export, _T("Export..."));
+ file_menu->Append(myMenuID_ExportGraphic, _T("Export Graphic..."));
file_menu->AppendSeparator();
file_menu->Append(wxID_PRINT, _T("&Print...\tCtrl-P"));
create_parameter_menu->Append(myMenuID_CreateNewVdwCutoffParameter, _T("Vdw Cutoff"));
edit_menu->Append(myMenuID_CreateNewAtom, _T("Create New Atom\tCtrl-I"));
edit_menu->Append(myMenuID_CreateNewParameter, _T("Create New Parameter"), create_parameter_menu);
+ edit_menu->Append(myMenuID_CreatePiAnchor, _T("Create Pi Anchor"));
edit_menu->AppendSeparator();
wxMenu *add_hydrogen_menu = new wxMenu;
add_hydrogen_menu->Append(myMenuID_AddHydrogenSp3, _T("Tetrahedral sp3"));
if (out_edit_menu != NULL)
*out_edit_menu = edit_menu; // Should be associated with the command processor if available
- wxMenu *show_menu = new wxMenu;
- show_menu->Append(myMenuID_FitToScreen, _T("Fit To Screen\tCtrl-T"));
- show_menu->Append(myMenuID_CenterSelection, _T("Center Selection"));
- show_menu->AppendSeparator();
- show_menu->Append(myMenuID_ShowUnitCell, _T("Show Unit Cell"), _T(""), wxITEM_CHECK);
-/* show_menu->Append(myMenuID_ShowPeriodicBox, _T("Show Periodic Box"), _T(""), wxITEM_CHECK); */
- show_menu->Append(myMenuID_ShowHydrogens, _T("Show Hydrogen Atoms"), _T(""), wxITEM_CHECK);
- show_menu->Append(myMenuID_ShowDummyAtoms, _T("Show Dummy Atoms"), _T(""), wxITEM_CHECK);
- show_menu->Append(myMenuID_ShowExpandedAtoms, _T("Show Expanded Atoms"), _T(""), wxITEM_CHECK);
- show_menu->Append(myMenuID_ShowEllipsoids, _T("Show Ellipsoids"), _T(""), wxITEM_CHECK);
- show_menu->Append(myMenuID_ShowRotationCenter, _T("Show Rotation Center"), _T(""), wxITEM_CHECK);
- show_menu->AppendSeparator();
- show_menu->Append(myMenuID_HideSelected, _T("Hide Selected"), _T(""));
- show_menu->Append(myMenuID_HideUnselected, _T("Hide Unselected"), _T(""));
- show_menu->Append(myMenuID_HideReverse, _T("Hide Reverse"), _T(""));
- show_menu->Append(myMenuID_ShowAllAtoms, _T("Show All Atoms"), _T(""));
- show_menu->AppendSeparator();
- show_menu->Append(myMenuID_ShowGraphite, _T("Show Graphite..."));
- show_menu->AppendSeparator();
- show_menu->Append(myMenuID_LineMode, _T("Line Mode"), _T(""), wxITEM_CHECK);
+ wxMenu *view_menu = new wxMenu;
+ view_menu->Append(myMenuID_FitToScreen, _T("Fit To Screen\tCtrl-T"));
+ view_menu->Append(myMenuID_CenterSelection, _T("Center Selection"));
+/* view_menu->AppendSeparator();
+ view_menu->Append(myMenuID_ShowUnitCell, _T("Show Unit Cell"), _T(""), wxITEM_CHECK);
+ view_menu->Append(myMenuID_ShowHydrogens, _T("Show Hydrogen Atoms"), _T(""), wxITEM_CHECK);
+ view_menu->Append(myMenuID_ShowDummyAtoms, _T("Show Dummy Atoms"), _T(""), wxITEM_CHECK);
+ view_menu->Append(myMenuID_ShowExpandedAtoms, _T("Show Expanded Atoms"), _T(""), wxITEM_CHECK);
+ view_menu->Append(myMenuID_ShowEllipsoids, _T("Show Ellipsoids"), _T(""), wxITEM_CHECK);
+ view_menu->Append(myMenuID_ShowRotationCenter, _T("Show Rotation Center"), _T(""), wxITEM_CHECK); */
+ view_menu->AppendSeparator();
+ view_menu->Append(myMenuID_HideSelected, _T("Hide Selected"), _T(""));
+ view_menu->Append(myMenuID_HideUnselected, _T("Hide Unselected"), _T(""));
+ view_menu->Append(myMenuID_HideReverse, _T("Hide Reverse"), _T(""));
+ view_menu->Append(myMenuID_ShowAllAtoms, _T("Show All Atoms"), _T(""));
+// view_menu->AppendSeparator();
+// view_menu->Append(myMenuID_ShowGraphite, _T("Show Graphite..."));
+// view_menu->AppendSeparator();
+// view_menu->Append(myMenuID_LineMode, _T("Line Mode"), _T(""), wxITEM_CHECK);
wxMenu *md_menu = new wxMenu;
md_menu->Append(myMenuID_MolecularDynamics, _T("Molecular Dynamics..."));
md_menu->Append(myMenuID_Minimize, _T("Minimize..."));
md_menu->Append(myMenuID_StopMDRun, _T("Stop\tCtrl-."));
md_menu->AppendSeparator();
-// md_menu->Append(myMenuID_ReadParameters, _T("Read Parameters..."));
md_menu->Append(myMenuID_ViewGlobalParameters, _T("View Global Parameters..."));
md_menu->Append(myMenuID_ViewParameterFilesList, _T("Load/Unload Global Parameters..."));
- md_menu->AppendSeparator();
- md_menu->Append(myMenuID_DefinePeriodicBox, _T("Define Unit Cell..."));
- md_menu->Append(myMenuID_ShowPeriodicImage, _T("Show Periodic Image..."));
-/* md_menu->Append(myMenuID_PressureControl, _T("Pressure Control...")); */
-/* md_menu->Append(myMenuID_DefineSymmetry, _T("Define Symmetry Operations..."));
- md_menu->Append(myMenuID_ExpandBySymmetry, _T("Expand by Symmetry...")); */
- md_menu->AppendSeparator();
-
- wxMenu *md_tools_menu = new wxMenu;
- md_tools_menu->Append(myMenuID_RunAntechamber, _T("Antechamber/parmchk..."));
- md_tools_menu->Append(myMenuID_RunResp, _T("GAMESS/RESP..."));
- md_tools_menu->Append(myMenuID_CreateSanderInput, _T("Create SANDER input..."));
- md_tools_menu->Append(myMenuID_ImportAmberLib, _T("Import AMBER Lib..."));
- md_tools_menu->Append(myMenuID_ImportAmberFrcmod, _T("Import AMBER Frcmod..."));
- md_menu->Append(myMenuID_MDTools, _T("Tools"), md_tools_menu);
-
- wxMenu *qc_menu = new wxMenu;
- qc_menu->Append(myMenuID_CreateGamessInput, _T("Create GAMESS input..."));
- qc_menu->Append(myMenuID_CreateMOCube, _T("Create MO cube..."));
wxMenu *script_menu = new wxMenu;
script_menu->Append(myMenuID_ExecuteScript, _T("Execute Script..."));
- script_menu->Append(myMenuID_OpenConsoleWindow, _T("Open Console Window..."));
+ script_menu->Append(myMenuID_OpenConsoleWindow, _T("Open Console Window"));
script_menu->Append(myMenuID_EmptyConsoleWindow, _T("Empty Console Window"));
script_menu->AppendSeparator();
countNonCustomScriptMenu = script_menu->GetMenuItemCount();
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(show_menu, _T("Show"));
+ menu_bar->Append(view_menu, _T("View"));
menu_bar->Append(md_menu, _T("MM/MD"));
- menu_bar->Append(qc_menu, _T("QChem"));
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;
-
- 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)
}
-int
-MyApp::AppendConsoleMessage(const char *mes)
-{
- wxTextCtrl *textCtrl;
- if (consoleFrame != NULL && (textCtrl = consoleFrame->textCtrl) != NULL) {
- wxString string(mes, WX_DEFAULT_CONV);
- textCtrl->AppendText(string);
- return string.Len();
- } else return 0;
-}
-
-void
-MyApp::FlushConsoleMessage()
-{
- wxTextCtrl *textCtrl = consoleFrame->textCtrl;
- textCtrl->Refresh();
- textCtrl->Update();
-}
-
-void
-MyApp::SetConsoleColor(int color)
-{
- wxTextCtrl *textCtrl = consoleFrame->textCtrl;
- static wxTextAttr *col[4];
- if (col[0] == NULL) {
- col[0] = new wxTextAttr(*wxBLACK);
- col[1] = new wxTextAttr(*wxRED);
- col[2] = new wxTextAttr(*wxGREEN);
- col[3] = new wxTextAttr(*wxBLUE);
- }
- textCtrl->SetDefaultStyle(*(col[color % 4]));
-}
-
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;
- }
-}
-
-/*
-#warning "TODO: Move this to MyDocument and 'import parameters' "
-
- void
-MyApp::OnReadParameters(wxCommandEvent& event)
-{
- wxFileDialog *dialog = new wxFileDialog(NULL, _T("Choose Parameter File"), _T(""), _T(""), _T("All files (*.*)|*.*"), wxFD_OPEN | wxFD_CHANGE_DIR | wxFD_FILE_MUST_EXIST);
- if (dialog->ShowModal() == wxID_OK) {
- char *p = strdup((const char *)(dialog->GetPath().mb_str(wxConvFile)));
- char *wbuf;
- ParameterReadFromFile(NULL, p, &wbuf, NULL);
- if (wbuf != NULL) {
- SetConsoleColor(1);
- AppendConsoleMessage(wbuf);
- SetConsoleColor(0);
- free(wbuf);
- }
- free(p);
- }
- dialog->Destroy();
+ if (m_progressDialog != NULL)
+ return m_progressDialog->WasCancelled();
+ else {
+ if (::wxGetKeyState(WXK_ESCAPE))
+ return 1;
+ else return 0;
+ }
}
-*/
void
MyApp::OnOpenConsoleWindow(wxCommandEvent& event)
}
void
-MyApp::OnImportAmberLib(wxCommandEvent &event)
-{
- MolActionCreateAndPerform(NULL, SCRIPT_ACTION(""), "cmd_import_amberlib");
+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
return -1;
}
-void
-MyApp::RegisterScriptMenu(const char *cmd, const char *title)
+int
+MyApp::RegisterScriptMenu(const char *title)
{
int i;
- if (cmd[0] == 0 && title[0] == 0)
- i = countScriptMenu; /* A sepearator */
- else {
+
+ // Already registered? (If it is not a separator item)
+ const char *p;
+ p = strrchr(title, '\t');
+ if (p == NULL)
+ p = title;
+ else p++;
+ if (p[0] != 0 && p[0] != '-') {
for (i = 0; i < countScriptMenu; i++) {
- if (strcmp(cmd, scriptMenuCommands[i]) == 0) {
- free(scriptMenuTitles[i]);
- scriptMenuTitles[i] = strdup(title);
- break;
- } else if (strcmp(title, scriptMenuTitles[i]) == 0) {
- free(scriptMenuCommands[i]);
- scriptMenuCommands[i] = strdup(cmd);
- break;
+ if (strcmp(title, scriptMenuTitles[i]) == 0) {
+ return i;
}
}
}
- if (i >= countScriptMenu) {
- if (countScriptMenu == 0) {
- scriptMenuTitles = (char **)malloc(sizeof(char *));
- scriptMenuCommands = (char **)malloc(sizeof(char *));
- } else {
- scriptMenuTitles = (char **)realloc(scriptMenuTitles, sizeof(char *) * (countScriptMenu + 1));
- scriptMenuCommands = (char **)realloc(scriptMenuCommands, sizeof(char *) * (countScriptMenu + 1));
- }
- scriptMenuTitles[countScriptMenu] = strdup(title);
- scriptMenuCommands[countScriptMenu] = strdup(cmd);
- countScriptMenu++;
+
+ // Not yet
+ if (countScriptMenu == 0) {
+ scriptMenuTitles = (char **)malloc(sizeof(char *));
+ scriptMenuPositions = (int *)malloc(sizeof(int));
+ } else {
+ scriptMenuTitles = (char **)realloc(scriptMenuTitles, sizeof(char *) * (countScriptMenu + 1));
+ scriptMenuPositions = (int *)realloc(scriptMenuPositions, sizeof(int) * (countScriptMenu + 1));
}
+ scriptMenuTitles[countScriptMenu] = strdup(title);
+ scriptMenuPositions[countScriptMenu] = -1;
+ countScriptMenu++;
+
if (!scriptMenuModifiedEventPosted) {
wxCommandEvent myEvent(MyDocumentEvent, MyDocumentEvent_scriptMenuModified);
wxPostEvent(this, myEvent);
scriptMenuModifiedEventPosted = true;
}
+
+ return countScriptMenu - 1;
}
void
MyApp::UpdateScriptMenu(wxMenuBar *mbar)
{
- int i;
-
- wxMenu *smenu = mbar->GetMenu(myMenuIndex_Script);
- if (smenu == NULL)
- return;
-
- // Remove all custom items
- for (i = smenu->GetMenuItemCount() - 1; i >= countNonCustomScriptMenu; i--) {
- wxMenuItem *item = smenu->FindItemByPosition(i);
- if (!item->IsSeparator()) {
- int n = item->GetId();
- Disconnect(n, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyApp::OnScriptMenuSelected), NULL, this);
- }
- smenu->Remove(item);
- delete item;
- }
-
- // Build script menu from internal array
+ int i, mid;
+ bool checkable;
for (i = 0; i < countScriptMenu; i++) {
- const char *title = scriptMenuTitles[i];
- if (title == NULL || title[0] == 0) {
- smenu->AppendSeparator();
- } else {
- wxString stitle(scriptMenuTitles[i], WX_DEFAULT_CONV);
- wxMenuItem *item = new wxMenuItem(smenu, myMenuID_CustomScript + i, stitle);
- smenu->Append(item);
+ // Find Menu to be inserted
+ const char *s = scriptMenuTitles[i], *p;
+ wxMenu *menu = NULL;
+ int depth = 1;
+ while ((p = strchr(s, '\t')) != NULL) {
+ // Find existing menu
+ wxString menuTitle(s, WX_DEFAULT_CONV, p - s);
+ if (menu == NULL) {
+ mid = mbar->FindMenu(menuTitle);
+ if (mid == wxNOT_FOUND) {
+ // Create a new menu before "Script" menu
+ wxMenu *newMenu = new wxMenu;
+ int sid = mbar->FindMenu(_T("Script"));
+ if (sid == wxNOT_FOUND) {
+ mbar->Append(newMenu, menuTitle);
+ sid = mbar->GetMenuCount() - 1;
+ } else {
+ mbar->Insert(sid, newMenu, menuTitle);
+ }
+ menu = mbar->GetMenu(sid);
+ } else {
+ menu = mbar->GetMenu(mid);
+ }
+ } else {
+ mid = menu->FindItem(menuTitle);
+ if (mid == wxNOT_FOUND) {
+ // Create a new menu at the end
+ wxMenu *newMenu1 = new wxMenu;
+ menu->Append(myMenuID_CustomScript + i + depth * 1000, menuTitle, newMenu1);
+ menu = newMenu1;
+ } else {
+ menu = menu->FindItem(mid)->GetSubMenu();
+ }
+ }
+ s = p + 1;
+ depth++;
+ }
+ if (menu == NULL) {
+ // The new item should be under "Script" menu
+ mid = mbar->FindMenu(_T("Script"));
+ menu = mbar->GetMenu(mid);
}
+ if (*s == 0 || *s == '-') {
+ // Separator item
+ wxMenuItem *sitem;
+ int count = menu->GetMenuItemCount();
+ if (scriptMenuPositions[i] >= 0 && scriptMenuPositions[i] < count) {
+ sitem = menu->FindItemByPosition(scriptMenuPositions[i]);
+ if (sitem != NULL && sitem->IsSeparator())
+ continue; // Already present
+ }
+ if (count != 0 && !menu->FindItemByPosition(count - 1)->IsSeparator()) {
+ menu->AppendSeparator();
+ scriptMenuPositions[i] = count;
+ }
+ continue;
+ }
+ if (*s == '^') {
+ // Checkable item
+ checkable = true;
+ s++;
+ } else checkable = false;
+ // Check if the item is already existing
+ wxString itemTitle(s, WX_DEFAULT_CONV);
+ wxMenu *omenu;
+ wxMenuItem *item;
+ item = mbar->FindItem(myMenuID_CustomScript + i, &omenu);
+ if (item != NULL) {
+ if (omenu == menu && item->GetItemLabel() == itemTitle) {
+ // The menu is already existing with correct position and title
+ continue;
+ }
+ // The menu title does not match; remove this menu item
+ Disconnect(myMenuID_CustomScript + i, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyApp::OnScriptMenuSelected), NULL, this);
+ omenu->Remove(item);
+ delete item;
+ }
+ // Create menu item
+ menu->Append(myMenuID_CustomScript + i, itemTitle, wxEmptyString, (checkable ? wxITEM_CHECK : wxITEM_NORMAL));
+ scriptMenuPositions[i] = menu->GetMenuItemCount() - 1;
+ Connect(myMenuID_CustomScript + i, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyApp::OnScriptMenuSelected), NULL, this);
}
- Connect(myMenuID_CustomScript, myMenuID_CustomScript + countScriptMenu - 1, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyApp::OnScriptMenuSelected), NULL, this);
}
void
MyApp::OnScriptMenuModified(wxCommandEvent& event)
{
scriptMenuModifiedEventPosted = false;
- UpdateScriptMenu(GetMainFrame()->GetMenuBar());
UpdateScriptMenu(consoleFrame->GetMenuBar());
event.Skip();
}
void
MyApp::OnScriptMenuSelected(wxCommandEvent& event)
{
- char *cmd;
- int methodType;
MainView *mview;
Molecule *mol;
int index = event.GetId() - myMenuID_CustomScript;
if (index < 0 || index >= countScriptMenu)
return;
- cmd = scriptMenuCommands[index];
- methodType = Ruby_methodType("Molecule", cmd);
- if (methodType == 0)
- return;
mview = MainViewCallback_activeView();
if (mview == NULL)
mol = NULL;
else mol = mview->mol;
- if (methodType == 1 && mol != NULL) /* Instance method (with no arguments) */
- MolActionCreateAndPerform(mol, SCRIPT_ACTION(""), cmd);
- else if (methodType == 2) /* Class method (with molecule as an only argument) */
- MolActionCreateAndPerform(NULL, SCRIPT_ACTION("M"), cmd, mol);
- else return;
+ MolActionCreateAndPerform(NULL, SCRIPT_ACTION("iM"), "lambda { |n, m| $script_menu_commands[n].call(m) }", index, mol);
}
void
}
m_NamedFragments = NULL;
m_CountNamedFragments = 0;
- if (MolActionCreateAndPerform(NULL, SCRIPT_ACTION(";i"), "proc { $named_fragments.length }", &n) != 0 || n <= 0)
+ if (MolActionCreateAndPerform(NULL, SCRIPT_ACTION(";i"), "lambda { $named_fragments.length }", &n) != 0 || n <= 0)
return;
m_CountNamedFragments = n;
m_NamedFragments = (char **)calloc(sizeof(char *), n * 2);
for (i = 0; i < n; i++) {
- if (MolActionCreateAndPerform(NULL, SCRIPT_ACTION("i;s"), "proc { |i| $named_fragments[i][0] }", i, &m_NamedFragments[i * 2]) != 0 ||
- MolActionCreateAndPerform(NULL, SCRIPT_ACTION("i;s"), "proc { |i| $named_fragments[i][1] }", i, &m_NamedFragments[i * 2 + 1]) != 0)
+ if (MolActionCreateAndPerform(NULL, SCRIPT_ACTION("i;s"), "lambda { |i| $named_fragments[i][0] }", i, &m_NamedFragments[i * 2]) != 0 ||
+ MolActionCreateAndPerform(NULL, SCRIPT_ACTION("i;s"), "lambda { |i| $named_fragments[i][1] }", i, &m_NamedFragments[i * 2 + 1]) != 0)
break;
}
if (i < n) {
MainView *mview = MainViewCallback_activeView();
if (uid >= myMenuID_CustomScript && uid < myMenuID_CustomScript + countScriptMenu) {
// Check the script menu
- char *cmd;
- int methodType;
+ // 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;
int index = uid - myMenuID_CustomScript;
- cmd = scriptMenuCommands[index];
- methodType = Ruby_methodType("Molecule", cmd);
- event.Enable(false);
- if (methodType != 0) {
- if (mview == NULL)
- mol = NULL;
- else mol = mview->mol;
- if (methodType == 1 && mol != NULL) /* Instance method (with no arguments) */
- event.Enable(true);
- else if (methodType == 2) /* Class method (with molecule as an only argument) */
- event.Enable(true);
+ if (mview == NULL)
+ mol = NULL;
+ else mol = mview->mol;
+ checked = -1;
+ title = NULL;
+ enabled = Ruby_UpdateUI(index, mol, &checked, &title);
+ 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.SetText(wtext);
+ free(title);
}
+ 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:
case myMenuID_EmptyConsoleWindow:
case myMenuID_ViewParameterFilesList:
case myMenuID_ViewGlobalParameters:
- case myMenuID_MDTools:
- case myMenuID_ImportAmberLib:
event.Enable(true);
return;
default:
cline.Prepend(_T("execute_script('"));
cline += _T("')");
MyAppCallback_setConsoleColor(3);
- wxGetApp().AppendConsoleMessage((const char *)(cline.mb_str(wxConvFile)));
- wxGetApp().AppendConsoleMessage("\n");
+ MyAppCallback_showScriptMessage("%s", (const char *)(cline.mb_str(wxConvFile)));
+ MyAppCallback_showScriptMessage("\n");
MyAppCallback_setConsoleColor(0);
retval = MyAppCallback_executeScriptFromFile((const char *)(path.mb_str(wxConvFile)), &status);
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::OnActivate(wxActivateEvent &event)
{
-#if defined(__WXMAC__)
+#if defined(__WXMAC__) || defined(__WXMSW__)
MyFrame *frame = GetMainFrame();
- frame->Show(false); /* Sometimes this "parent" frame gets visible and screw up the menus */
+ if (frame != NULL)
+ frame->Show(false); /* Sometimes this "parent" frame gets visible and screw up the menus */
#endif
event.Skip();
}
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;
}
+#endif
int
-MyApp::CallSubProcess(const char *cmdline, const char *procname)
+MyApp::CallSubProcess(const char *cmdline, const char *procname, int (*callback)(void *), void *callback_data, FILE *fpout, FILE *fperr, int *exitstatus_p, int *pid_p)
{
- const int sEndProcessMessageID = 2;
int status = 0;
+ int callback_result = 0;
+ bool progress_panel = false;
char buf[256];
- size_t len, len_total;
wxString cmdstr(cmdline, WX_DEFAULT_CONV);
+ wxLongLong startTime, lastTime, presentTime;
+
+ if (m_process != NULL)
+ return -1; // Another process is already running (CallSubProcess() allows only one subprocess)
+
#if defined(__WXMSW__)
extern int myKillAllChildren(long pid, wxSignal sig, wxKillError *krc);
#endif
// Show progress panel
- if (procname == NULL)
- procname = "subprocess";
- snprintf(buf, sizeof buf, "Running %s...", procname);
- ShowProgressPanel(buf);
+ if (procname != NULL) {
+ snprintf(buf, sizeof buf, "Running %s...", procname);
+ ShowProgressPanel(buf);
+ progress_panel = true;
+ }
+ 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);
+ 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
- wxProcess *proc = new wxProcess(wxGetApp().GetProgressFrame(), sEndProcessMessageID);
- proc->Redirect();
+ m_process = new wxBetterProcess(this, -1);
+ m_process->Redirect();
int flag = wxEXEC_ASYNC;
-//#if !__WXMSW__
flag |= wxEXEC_MAKE_GROUP_LEADER;
-//#endif
- m_processTerminated = false;
- m_processExitCode = 0;
- long pid = ::wxExecute(cmdstr, flag, proc);
+ long pid = ::wxExecute(cmdstr, flag, m_process);
if (pid == 0) {
- // MyAppCallback_errorMessageBox("Cannot start %s", procname);
- proc->Detach();
- HideProgressPanel();
+ if (progress_panel)
+ HideProgressPanel();
+ delete m_process;
#if LOG_SUBPROCESS
+ fprintf(fplog, "Cannot start '%s'\n", cmdline);
fclose(fplog);
#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 = proc->GetInputStream();
- wxInputStream *err = proc->GetErrorStream();
- len_total = 0;
- while (1) {
- if (m_processTerminated || !wxProcess::Exists(pid)) {
- if (m_processExitCode != 0) {
- /* Error from subprocess */
- // MyAppCallback_errorMessageBox("%s failed with exit code %d.", procname, m_processExitCode);
- status = (m_processExitCode & 255);
- } else status = 0;
- break;
- }
-#if defined(__WXMAC__)
- if (waitpid(pid, &status, WNOHANG) != 0) {
- /* Already finished, although not detected by wxProcess */
- /* This sometimes happens on ppc Mac */
- proc->Detach();
- status = WEXITSTATUS(status);
- break;
- }
+ 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
+ dateTime.SetToCurrent();
+ fprintf(fplog, "%s[STDOUT]%s", (const char *)(dateTime.FormatISOCombined(' ')), (const char *)bufstr);
+ fflush(fplog);
#endif
+ 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 (++nn >= 100) {
- fprintf(fplog, "[DEBUG]pid %ld exists\n", pid);
- nn = 0;
- }
+ dateTime.SetToCurrent();
+ fprintf(fplog, "%s[STDERR]%s", (const char *)(dateTime.FormatISOCombined(' ')), buf);
+ fflush(fplog);
#endif
- if (wxGetApp().IsInterrupted()) {
- /* User interrupt */
- int kflag = wxKILL_CHILDREN;
- wxKillError rc;
- if (
+ 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) {
+ dateTime.SetToCurrent();
+ fprintf(fplog, "%s[DEBUG]pid %ld exists\n", (const char *)(dateTime.FormatISOCombined(' ')), pid);
+ fflush(fplog);
+ nn = 0;
+ }
+#endif
+ 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
+ ::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 status = -2; /* User interrupt */
- proc->Detach();
- break;
- }
- while (in->CanRead()) {
- in->Read(buf, sizeof buf - 1);
- if ((len = in->LastRead()) > 0) {
- buf[len] = 0;
- len_total += len;
-#if LOG_SUBPROCESS
- fprintf(fplog, "%s", buf);
+ ) {
+ 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 (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__
+ {
+ /* 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
- MyAppCallback_setConsoleColor(0);
- MyAppCallback_showScriptMessage("%s", buf);
+ *((char **)callback_data) = membuf;
+ }
+ }
+
+ return status;
+}
+
+static int sTimerCount = 0;
+
+void
+MyApp::EnableTimerForDocument(MyDocument *doc)
+{
+ int i;
+ if (doc == NULL)
+ return;
+ for (i = 0; i < m_CountTimerDocs; i++) {
+ if (m_TimerDocs[i] == doc)
+ return;
+ }
+ m_TimerDocs = (MyDocument **)realloc(m_TimerDocs, sizeof(MyDocument *) * (m_CountTimerDocs + 1));
+ m_TimerDocs[m_CountTimerDocs++] = doc;
+ if (m_Timer == NULL)
+ m_Timer = new wxTimer(this, -1);
+ if (!m_Timer->IsRunning())
+ m_Timer->Start(100, wxTIMER_CONTINUOUS);
+}
+
+void
+MyApp::DisableTimerForDocument(MyDocument *doc)
+{
+ int i;
+ if (doc == NULL)
+ return;
+ for (i = 0; i < m_CountTimerDocs; i++) {
+ if (m_TimerDocs[i] == doc) {
+ // Remove this document from the array
+ if (i < m_CountTimerDocs - 1) {
+ memmove(&m_TimerDocs[i], &m_TimerDocs[i + 1], sizeof(MyDocument *) * (m_CountTimerDocs - 1 - i));
+ }
+ m_CountTimerDocs--;
+ if (m_CountTimerDocs == 0) {
+ free(m_TimerDocs);
+ m_TimerDocs = NULL;
+ m_Timer->Stop();
}
+ break;
}
- while (err->CanRead()) {
- err->Read(buf, sizeof buf - 1);
- if ((len = err->LastRead()) > 0) {
- buf[len] = 0;
- len_total += len;
-#if LOG_SUBPROCESS
- fprintf(fplog, "%s", buf);
-#endif
- MyAppCallback_setConsoleColor(1);
- MyAppCallback_showScriptMessage("\n%s", buf);
- MyAppCallback_setConsoleColor(0);
+ }
+}
+
+void
+MyApp::TimerInvoked(wxTimerEvent &event)
+{
+ int i;
+ sTimerCount++;
+ for (i = 0; i < m_CountTimerDocs; i++) {
+ m_TimerDocs[i]->TimerCallback(sTimerCount);
+ }
+}
+
+void
+MyApp::CheckIfAllWindowsAreGoneHandler(wxCommandEvent &event)
+{
+ int m = 0;
+ wxWindowList::iterator iter;
+ wxTopLevelWindow *win;
+ for (iter = wxTopLevelWindows.begin(); iter != wxTopLevelWindows.end(); ++iter) {
+ win = (wxTopLevelWindow *)(*iter);
+ if (win != m_frameToBeDestroyed && win->IsShown())
+ m++;
+ }
+ if (m == 0) {
+ const char *p = MyAppCallback_getGlobalSettings(gSettingQuitOnCloseLastWindow);
+ int quitFlag = 1;
+ if (p != NULL && *p != 0)
+ quitFlag = (atoi(p) != 0);
+ if (quitFlag || MyAppCallback_messageBox("Do you want to quit Molby?", "Quit Molby", 3, 2)) {
+
+ for (iter = wxTopLevelWindows.begin(); iter != wxTopLevelWindows.end(); ++iter) {
+ win = (wxTopLevelWindow *)(*iter);
+ if (win != m_frameToBeDestroyed)
+ win->Destroy(); // Avoid double destruction
}
+ } else {
+ // Show console window to avoid window-less state
+ consoleFrame->Show();
}
}
-#if LOG_SUBPROCESS
- fclose(fplog);
+}
+
+void
+MyApp::CheckIfAllWindowsAreGone(wxTopLevelWindow *frame)
+{
+ /* On Windows, we should avoid the situation where all windows are hidden and
+ still the program is running. So that we check whether all windows are gone
+ and if so ask the user to quit the program. If user chooses not to quit, then
+ the console window is reopened and the program continues to run. */
+ m_frameToBeDestroyed = frame;
+ wxCommandEvent myEvent(MyDocumentEvent, myMenuID_Internal_CheckIfAllWindowsAreGone);
+ 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);
+}
- HideProgressPanel();
-/* if (len_total > 0)
- MyAppCallback_showRubyPrompt(); */
- return status;
+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) ======
* This is the top-level window of the application.
*/
-IMPLEMENT_CLASS(MyFrame, wxDocMDIParentFrame)
-BEGIN_EVENT_TABLE(MyFrame, wxDocMDIParentFrame)
+IMPLEMENT_CLASS(MyFrame, wxDocParentFrame)
+BEGIN_EVENT_TABLE(MyFrame, wxDocParentFrame)
EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
END_EVENT_TABLE()
MyFrame::MyFrame(wxDocManager *manager, wxFrame *frame, const wxString& title,
const wxPoint& pos, const wxSize& size, long type):
- wxDocMDIParentFrame(manager, frame, wxID_ANY, title, pos, size, type, _T("myFrame"))
+ wxDocParentFrame(manager, frame, wxID_ANY, title, pos, size, type, _T("myFrame"))
{
editMenu = (wxMenu *) NULL;
#if defined(__WXMAC__)
/* Avoid this "dummy" top-level window to appear in the window menu.
It should not happen because MyApp::OnActivate() tries to hide this window,
but this is still here just in case. */
- OSStatus sts;
- sts = ChangeWindowAttributes((WindowRef)m_macWindow, 0, kWindowInWindowMenuAttribute);
+// OSStatus sts;
+// sts = ChangeWindowAttributes((WindowRef)m_macWindow, 0, kWindowInWindowMenuAttribute);
/* printf("m_macWindow = %p, status = %d\n", m_macWindow, (int)sts); */
#endif
}
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"
- "wxWidgets %d.%d.%d, Copyright (c) 1992-2008 Julian Smart, \n"
- " Robert Roebling, Vadim Zeitlin and other members of the \n"
- " wxWidgets team\n"
- " Portions (c) 1996 Artificial Intelligence Applications Institute\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, "
+ "Oak Ridge National Laboratory Report ORNL-6895, "
+ "1996.\n"
+ "wxWidgets %d.%d.%d, http://www.wxwidgets.org/\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_showScriptMessage(const char *fmt, ...)
-{
- if (fmt != NULL) {
- char *p;
- va_list ap;
- int retval;
- va_start(ap, fmt);
- if (strchr(fmt, '%') == NULL) {
- /* No format characters */
- return wxGetApp().AppendConsoleMessage(fmt);
- } else if (strcmp(fmt, "%s") == 0) {
- /* Direct output of one string */
- p = va_arg(ap, char *);
- return wxGetApp().AppendConsoleMessage(p);
- }
-#if 1
- vasprintf(&p, fmt, ap);
-#else
- /* Use safe wxString method */
- /* Not necessary any longer; vasprintf() is implemented in Missing.c */
- {
- wxString str;
- str.PrintfV(wxString::FromUTF8(fmt).GetData(), ap);
- p = strdup((const char *)str.mb_str(WX_DEFAULT_CONV));
- }
-#endif
- if (p != NULL) {
- retval = wxGetApp().AppendConsoleMessage(p);
- free(p);
- return retval;
- } else return 0;
- } else {
- wxGetApp().FlushConsoleMessage();
- return 0;
- }
- return 0;
-}
-
-void
-MyAppCallback_setConsoleColor(int color)
-{
- wxGetApp().SetConsoleColor(color);
-}
-
-void
-MyAppCallback_showRubyPrompt(void)
-{
- MyAppCallback_setConsoleColor(0);
- MyAppCallback_showScriptMessage("%% ");
-}
-
-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;
int retval;
wxString pstr(prompt, WX_DEFAULT_CONV);
+ wxString defstr(buf, WX_DEFAULT_CONV);
{ // 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, _T(""), 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);
+ MyAppCallback_showScriptMessage("*** %s ***\n%s\n", message, title);
+ MyAppCallback_setConsoleColor(0);
+ return 1;
+ }
if (flags == 0)
flags = 1;
wxflags = ((flags & 1) ? wxOK : 0) | ((flags & 2) ? wxCANCEL : 0);
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
}
-void
-MyAppCallback_registerScriptMenu(const char *cmd, const char *title)
+int
+MyAppCallback_registerScriptMenu(const char *title)
{
- wxGetApp().RegisterScriptMenu(cmd, 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);
}
/* Check the encoding specification, and if present convert it to default encoding */
- {
+ if (0) {
char *lp = script, *eolp;
int n = 0;
while (n < 2) { /* Check the first two lines */
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 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);
+ 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)
+{
+ 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;
+ else if (flag == 3)
+ uflag = wxSOUND_ASYNC | wxSOUND_LOOP;
+ wxString fnamestr(filename, wxConvFile);
+ bool retval = wxSound::Play(fnamestr, uflag);
+ return retval;
+}
+
+void MyAppCallback_stopSound(void)
+{
+ if (!gUseGUI)
+ return;
+ wxSound::Stop();
+}
+
+void MyAppCallback_initImageHandlers(void)
+{
+ static bool handlers_init = false;
+ if (!handlers_init) {
+ wxInitAllImageHandlers();
+ handlers_init = true;
+ }
}