From 195c335ccce4faef31a378c5a19aed721222b5cf Mon Sep 17 00:00:00 2001 From: Toshi Nagata Date: Mon, 10 Oct 2022 22:59:21 +0900 Subject: [PATCH] call_subprocess now accepts an array of arguments, so that arguments containing spaces can be used without quotation --- MolLib/Molecule.h | 2 +- MolLib/Ruby_bind/Molby_extern.h | 2 +- MolLib/Ruby_bind/ruby_bind.c | 57 +++++++++++++++++++++++---- Scripts/crystal.rb | 2 +- Scripts/gamess.rb | 86 +++++++++++++++++++++++++++++++---------- Scripts/md.rb | 20 +++++----- Scripts/mopac6.rb | 4 +- wxSources/MoleculeView.cpp | 5 +-- wxSources/MyApp.cpp | 28 +++++++++----- wxSources/MyApp.h | 2 +- wxSources/MyDocument.cpp | 17 +++++--- wxSources/MyDocument.h | 2 +- 12 files changed, 163 insertions(+), 64 deletions(-) diff --git a/MolLib/Molecule.h b/MolLib/Molecule.h index 716bc92..f8ce732 100755 --- a/MolLib/Molecule.h +++ b/MolLib/Molecule.h @@ -616,7 +616,7 @@ STUB void MoleculeCallback_enableModificationFromGUI(Molecule *mol); STUB void MoleculeCallback_cannotModifyMoleculeDuringMDError(Molecule *mol); -STUB int MoleculeCallback_callSubProcessAsync(Molecule *mol, const char *cmd, int (*callback)(Molecule *, int), int (*timerCallback)(Molecule *, int), FILE *output, FILE *errout); +STUB int MoleculeCallback_callSubProcessAsync(Molecule *mol, const char **argv, int (*callback)(Molecule *, int), int (*timerCallback)(Molecule *, int), FILE *output, FILE *errout); /* This is also defined in Molby_extern.h, but it may be called from functions in Molecule.c */ STUB int MyAppCallback_checkInterrupt(void); diff --git a/MolLib/Ruby_bind/Molby_extern.h b/MolLib/Ruby_bind/Molby_extern.h index a4896c8..005937c 100755 --- a/MolLib/Ruby_bind/Molby_extern.h +++ b/MolLib/Ruby_bind/Molby_extern.h @@ -79,7 +79,7 @@ STUB char *MyAppCallback_getDocumentHomeDir(void); STUB int MyAppCallback_registerScriptMenu(const char *title); STUB int MyAppCallback_lookupScriptMenu(const char *title); STUB RubyValue MyAppCallback_executeScriptFromFile(const char *path, int *status); -STUB 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); +STUB int MyAppCallback_callSubProcess(const char **argv, const char *procname, int (*callback)(void *), void *callback_data, FILE *output, FILE *errout, int *exitstatus_p, int *pid_p); STUB void MyAppCallback_beginUndoGrouping(void); STUB void MyAppCallback_endUndoGrouping(void); STUB int MyAppCallback_switchToFilterMode(void); diff --git a/MolLib/Ruby_bind/ruby_bind.c b/MolLib/Ruby_bind/ruby_bind.c index 9d7452e..6172847 100644 --- a/MolLib/Ruby_bind/ruby_bind.c +++ b/MolLib/Ruby_bind/ruby_bind.c @@ -192,7 +192,7 @@ static VALUE s_Kernel_MessageBox(int argc, VALUE *argv, VALUE self) { char *str, *title, *s; - int buttons, icon; + int buttons, icon, retval; VALUE sval, tval, bval, ival; rb_scan_args(argc, argv, "22", &sval, &tval, &bval, &ival); str = StringValuePtr(sval); @@ -219,8 +219,8 @@ s_Kernel_MessageBox(int argc, VALUE *argv, VALUE self) else rb_raise(rb_eMolbyError, "the icon specification should be either :info, :warning or :error"); } else icon = 1; - MyAppCallback_messageBox(str, title, buttons, icon); - return Qnil; + retval = MyAppCallback_messageBox(str, title, buttons, icon); + return (retval ? Qtrue : Qfalse); } /* @@ -998,6 +998,10 @@ s_Kernel_CallSubProcess_Callback(void *data) * * Call subprocess. A progress dialog window is displayed, with a message * "Running #{process_name}...". + * cmd is either a single string of an array of string. If it is a single string, then + * it will be given to wxExecute as a single argument. In this case, the string can be + * split into arguments by whitespace. If this behavior is not intended, then use an array + * containing a single string. * A callback proc can be given, which is called periodically during execution. If the proc returns * nil or false, then the execution will be interrupted. * If stdout_file or stderr_file is a filename, then the message will be sent to the file; if the @@ -1012,7 +1016,7 @@ s_Kernel_CallSubProcess(int argc, VALUE *argv, VALUE self) VALUE save_interruptFlag; int n, exitstatus, pid; char *sout, *serr; - const char *pnamestr; + const char *pnamestr, **cmdargv; FILE *fpout, *fperr; rb_scan_args(argc, argv, "23", &cmd, &procname, &cproc, &stdout_val, &stderr_val); @@ -1060,9 +1064,23 @@ s_Kernel_CallSubProcess(int argc, VALUE *argv, VALUE self) if (procname != Qnil) pnamestr = StringValuePtr(procname); else pnamestr = NULL; - n = MyAppCallback_callSubProcess(StringValuePtr(cmd), pnamestr, (cproc == Qnil ? NULL : s_Kernel_CallSubProcess_Callback), (cproc == Qnil ? NULL : (void *)cproc), fpout, fperr, &exitstatus, &pid); + if (rb_obj_is_kind_of(cmd, rb_cString)) { + cmdargv = calloc(sizeof(cmdargv[0]), 3); + cmdargv[0] = StringValuePtr(cmd); + cmdargv[1] = ""; + cmdargv[2] = NULL; + } else { + cmd = rb_ary_to_ary(cmd); + cmdargv = calloc(sizeof(cmdargv[0]), RARRAY_LEN(cmd) + 1); + for (n = 0; n < RARRAY_LEN(cmd); n++) { + cmdargv[n] = StringValuePtr(RARRAY_PTR(cmd)[n]); + } + cmdargv[n] = NULL; + } + n = MyAppCallback_callSubProcess(cmdargv, pnamestr, (cproc == Qnil ? NULL : s_Kernel_CallSubProcess_Callback), (cproc == Qnil ? NULL : (void *)cproc), fpout, fperr, &exitstatus, &pid); s_SetInterruptFlag(self, save_interruptFlag); - + free(cmdargv); + if (fpout != NULL && fpout != (FILE *)1) fclose(fpout); if (fperr != NULL && fperr != (FILE *)1) @@ -1085,7 +1103,11 @@ s_Kernel_Backquote(VALUE self, VALUE cmd) char *buf; int n, exitstatus, pid; VALUE val; - n = MyAppCallback_callSubProcess(StringValuePtr(cmd), NULL, DUMMY_CALLBACK, &buf, NULL, NULL, &exitstatus, &pid); + const char *cmdargv[3]; + cmdargv[0] = StringValuePtr(cmd); + cmdargv[1] = ""; + cmdargv[2] = NULL; + n = MyAppCallback_callSubProcess(cmdargv, NULL, DUMMY_CALLBACK, &buf, NULL, NULL, &exitstatus, &pid); /* fprintf(stderr, "n = %d, exitstatus = %d, pid = %d\n", n, exitstatus, pid); */ if (n >= 0 && buf != NULL) { val = Ruby_NewEncodedStringValue(buf, 0); @@ -11506,6 +11528,10 @@ s_Molecule_CallSubProcessAsync_TimerCallback(Molecule *mol, int tcount) * call_subprocess_async(cmd [, end_callback [, timer_callback [, standard_output_file [, error_output_file]]]]) * * Call subprocess asynchronically. + * cmd is either a single string of an array of string. If it is a single string, then + * it will be given to wxExecute as a single argument. In this case, the string can be + * split into arguments by whitespace. If this behavior is not intended, then use an array + * containing a single string. * If end_callback is given, it will be called (with two arguments self and termination status) * when the subprocess terminated. * If timer_callback is given, it will be called (also with two arguments, self and timer count). @@ -11522,6 +11548,7 @@ s_Molecule_CallSubProcessAsync(int argc, VALUE *argv, VALUE self) VALUE cmd, end_proc, timer_proc, stdout_val, stderr_val; Molecule *mol; char *sout, *serr; + const char **cmdargv; int n; FILE *fpout, *fperr; rb_scan_args(argc, argv, "14", &cmd, &end_proc, &timer_proc, &stdout_val, &stderr_val); @@ -11569,7 +11596,21 @@ s_Molecule_CallSubProcessAsync(int argc, VALUE *argv, VALUE self) /* Register procs as instance variables */ rb_ivar_set(self, rb_intern("end_proc"), end_proc); rb_ivar_set(self, rb_intern("timer_proc"), timer_proc); - n = MoleculeCallback_callSubProcessAsync(mol, StringValuePtr(cmd), s_Molecule_CallSubProcessAsync_EndCallback, (timer_proc == Qnil ? NULL : s_Molecule_CallSubProcessAsync_TimerCallback), fpout, fperr); + + if (rb_obj_is_kind_of(cmd, rb_cString)) { + cmdargv = calloc(sizeof(cmdargv[0]), 3); + cmdargv[0] = StringValuePtr(cmd); + cmdargv[1] = ""; + cmdargv[2] = NULL; + } else { + cmd = rb_ary_to_ary(cmd); + cmdargv = calloc(sizeof(cmdargv[0]), RARRAY_LEN(cmd) + 1); + for (n = 0; n < RARRAY_LEN(cmd); n++) { + cmdargv[n] = StringValuePtr(RARRAY_PTR(cmd)[n]); + } + cmdargv[n] = NULL; + } + n = MoleculeCallback_callSubProcessAsync(mol, cmdargv, s_Molecule_CallSubProcessAsync_EndCallback, (timer_proc == Qnil ? NULL : s_Molecule_CallSubProcessAsync_TimerCallback), fpout, fperr); if (fpout != NULL && fpout != (FILE *)1) fclose(fpout); if (fperr != NULL && fperr != (FILE *)1) diff --git a/Scripts/crystal.rb b/Scripts/crystal.rb index 45a46f7..5ba0a5b 100755 --- a/Scripts/crystal.rb +++ b/Scripts/crystal.rb @@ -1531,7 +1531,7 @@ def cmd_show_ortep if FileTest.exist?("TEP001.PRN") File.unlink("TEP001.PRN") end - pid = call_subprocess(tepexe, "Running ORTEP", nil, "NUL", "NUL") + pid = call_subprocess([tepexe], "Running ORTEP", nil, "NUL", "NUL") if FileTest.exist?("TEP001.PRN") File.rename("TEP001.PRN", "TEP001.ps") end diff --git a/Scripts/gamess.rb b/Scripts/gamess.rb index 44425bc..346f8bf 100755 --- a/Scripts/gamess.rb +++ b/Scripts/gamess.rb @@ -782,7 +782,6 @@ class Molecule lineno += last_i + 1 end end - print("% ") true } @@ -1607,21 +1606,57 @@ class Molecule end end - # Execute JUNPA + def Molecule.is_java_available + if $platform == "win" + f = get_global_settings("java_home") + if f + ENV["JAVA_HOME"] = f + if !ENV["PATH"].split(";").find { |e| e == "#{f}\\bin" } + ENV["PATH"] = "#{f}\\bin;" + ENV["PATH"] + end + end + end + return call_subprocess("java -version", nil) + end + + def Molecule.make_java_available + if $platform == "win" + fname = Dialog.open_panel("Locate JDK Folder (if you have one):", "c:\\", nil, true) + return false if fname == nil + fname.sub!(/\//, "\\") + if File.exists?("#{fname}\\bin\\java.exe") + set_global_settings("java_home", fname) + if Molecule.is_java_available() + return true + end + end + error_message_box("Cannot run Java. Please examine your installation again.") + return false + elsif $platform == "mac" + message_box("Please download OpenJDK, and move it into /Library/Java/JavaVirtualMachines folder.", "Install Java", :ok) + return false + else + message_box("Please install Java virtual machine.", "Install Java", :ok) + return false + end + end + + # Execute JANPA # inppath is the input file minus extention # mol is the molecule (may be nil) def Molecule.execute_janpa(inppath, mol, spherical) # nbo_desc = # JANPA janpa_dir = "#{ResourcePath}/JANPA" status = 0 + outfile = "#{inppath}.janpa.log" if spherical - cmd1 = "java -jar #{janpa_dir}/molden2molden.jar -NormalizeBF -i #{inppath}.da.molden -o #{inppath}.in.molden >#{inppath}.janpa.log" - cmd2 = "" + cmd1 = ["java", "-jar", "#{janpa_dir}/molden2molden.jar", "-NormalizeBF", "-i", "#{inppath}.da.molden", "-o", "#{inppath}.in.molden"] + cmd2 = nil else - cmd1 = "java -jar #{janpa_dir}/molden2molden.jar -frompsi4v1mo -NormalizeBF -cart2pure -i #{inppath}.da.molden -o #{inppath}.in.molden >#{inppath}.janpa.log" - cmd2 = "java -jar #{janpa_dir}/molden2molden.jar -frompsi4v1mo -NormalizeBF -cart2pure -i #{inppath}.molden -o #{inppath}.spherical.molden >>#{inppath}.janpa.log" + cmd1 = ["java", "-jar", "#{janpa_dir}/molden2molden.jar", "-frompsi4v1mo", "-NormalizeBF", "-cart2pure", "-i", "#{inppath}.da.molden", "-o", "#{inppath}.in.molden"] + cmd2 = ["java", "-jar", "#{janpa_dir}/molden2molden.jar", "-frompsi4v1mo", "-NormalizeBF", "-cart2pure", "-i", "#{inppath}.molden", "-o", "#{inppath}.spherical.molden"] end - cmd3 = "java -jar #{janpa_dir}/janpa.jar -i #{inppath}.in.molden" + cmd3 = ["java", "-jar", "#{janpa_dir}/janpa.jar", "-i", "#{inppath}.in.molden"] ["nao", "pnao", "aho", "lho", "lpo", "clpo"].each { |type| generate = (get_global_settings("psi4.#{type}").to_i != 0) if type == "pnao" || type == "nao" || type == "lho" @@ -1629,17 +1664,19 @@ class Molecule generate ||= (get_global_settings("psi4.plho").to_i != 0) end if generate - cmd3 += " -#{type.upcase}_Molden_File #{inppath}.#{type.upcase}.molden" + cmd3.push("-#{type.upcase}_Molden_File", "#{inppath}.#{type.upcase}.molden") end } - cmd3 += " >>#{inppath}.janpa.log" - show_progress_panel("Executing JANPA...") - flag = system(cmd1) - if flag && cmd2 != "" - flag = system(cmd2) - if flag - flag = system(cmd3) - end + # show_progress_panel("Executing JANPA...") + procname = "molden2molden" + flag = call_subprocess(cmd1, procname, nil, outfile) + if flag && cmd2 != nil + procname = "molden2molden" + flag = call_subprocess(cmd2, procname, nil, ">>#{outfile}") + end + if flag + procname = "janpa" + flag = call_subprocess(cmd3, procname, nil, ">>#{outfile}") end if flag if mol @@ -1676,9 +1713,9 @@ class Molecule ENV["PATH"] = "#{psi4folder}/bin:#{psi4folder}/condabin:" + ENV["PATH"] end Dir.chdir(inpdir) - cmdline = "psi4 #{inpbase}" + cmdargv = ["psi4", "#{inpbase}"] if ncpus > 0 - cmdline += " -n #{ncpus}" + cmdargv.push("-n", "#{ncpus}") end hf_type = nil nalpha = nil @@ -1689,7 +1726,7 @@ class Molecule if File.exists?(outfile) n = 1 while true - outbackfile = inpdir + "/" + inpbody + "~" + (n == 1 ? "" : "{#n}") + ".out" + outbackfile = inpdir + "/" + inpbody + "~" + (n == 1 ? "" : "#{n}") + ".out" break if !File.exists?(outbackfile) n += 1 end @@ -1880,14 +1917,14 @@ class Molecule } if mol - pid = mol.call_subprocess_async(cmdline, term_callback, timer_callback) + pid = mol.call_subprocess_async(cmdargv, term_callback, timer_callback) if pid < 0 # This may not happen on OSX or Linux (don't know for MSW) error_message_box("Psi4 failed to start. Please examine Psi4 installation.") return -1 end else - status = call_subprocess(cmdline, "Running Psi4") + status = call_subprocess(cmdargv, "Running Psi4") term_callback.call(nil, status) return status end @@ -2133,6 +2170,13 @@ class Molecule end if hash["execute_local"] == 1 @hf_type = hash["scftype"] + if hash["run_janpa"] == 1 + if !Molecule.is_java_available() + if !Molecule.make_java_available() + return nil + end + end + end Molecule.execute_psi4(fname, self) end else diff --git a/Scripts/md.rb b/Scripts/md.rb index fa28cd3..ba80acc 100755 --- a/Scripts/md.rb +++ b/Scripts/md.rb @@ -456,24 +456,24 @@ class Molecule ENV["AMBERHOME"] = amberhome end if calc_charge != 0 - opt = "-nc #{nc} -c bcc" + opt = ["-nc", "#{nc}", "-c", "bcc"] if optimize_structure == 0 - opt += " -ek 'maxcyc=0'" + opt.push(" -ek", "'maxcyc=0'") end else - opt = "" + opt = [] end if guess_atom_types == 0 - opt += " -j 0" + opt.push("-j", "0") end - n = call_subprocess("#{ante_dir}/antechamber -i mol.pdb -fi pdb -o mol.ac -fo ac #{opt}", "Antechamber") + n = call_subprocess(["#{ante_dir}/antechamber", "-i", "mol.pdb", "-fi", "pdb", "-o", "mol.ac", "-fo", "ac"] + opt, "Antechamber") if n != 0 error_message_box("Antechamber failed: status = #{n}.") Dir.chdir(cwd) return n else if guess_atom_types != 0 - n = call_subprocess("#{ante_dir}/parmchk -i mol.ac -f ac -o frcmod", "Parmchk") + n = call_subprocess(["#{ante_dir}/parmchk", "-i", "mol.ac", "-f", "ac", "-o", "frcmod"], "Parmchk") if n != 0 error_message_box("Parmchk failed: status = #{n}.") Dir.chdir(cwd) @@ -1326,9 +1326,9 @@ class Molecule } # Create resp input by respgen - status = call_subprocess("\"#{ante_dir}/respgen\" -i respgen_in.ac -o resp.input1 -f resp1", "respgen (stage 1)") + status = call_subprocess(["#{ante_dir}/respgen", "-i", "respgen_in.ac", "-o", "resp.input1", "-f", "resp1"], "respgen (stage 1)") if status == 0 - status = call_subprocess("\"#{ante_dir}/respgen\" -i respgen_in.ac -o resp.input2 -f resp2", "respgen (stage 2)") + status = call_subprocess(["#{ante_dir}/respgen", "-i", "respgen_in.ac", "-o", "resp.input2", "-f", "resp2"], "respgen (stage 2)") end if status != 0 error_message_box("Cannot run respgen: status = #{status}") @@ -1353,9 +1353,9 @@ class Molecule } # Run resp - status = call_subprocess("\"#{ante_dir}/resp\" -O -i resp.input1 -o resp.output1 -e resp.esp -t qout_stage1", "resp (stage 1)") + status = call_subprocess(["#{ante_dir}/resp", "-O", "-i", "resp.input1", "-o", "resp.output1", "-e", "resp.esp", "-t", "qout_stage1"], "resp (stage 1)") if status == 0 - status = call_subprocess("\"#{ante_dir}/resp\" -O -i resp.input2 -o resp.output2 -e resp.esp -q qout_stage1 -t qout_stage2", "resp (stage 2)") + status = call_subprocess(["#{ante_dir}/resp", "-O", "-i", "resp.input2", "-o", "resp.output2", "-e", "resp.esp", "-q", "qout_stage1", "-t", "qout_stage2"], "resp (stage 2)") if status == 255 && File.exist?("punch") status = 0 # Ignore error at the second stage end diff --git a/Scripts/mopac6.rb b/Scripts/mopac6.rb index 04cb78d..51e9261 100755 --- a/Scripts/mopac6.rb +++ b/Scripts/mopac6.rb @@ -79,9 +79,9 @@ class Molecule # Execute mopac Dir.chdir(scrdir) if mol - pid = mol.call_subprocess_async(mopexe, term_callback, timer_callback, "NUL", "NUL") + pid = mol.call_subprocess_async([mopexe], term_callback, timer_callback, "NUL", "NUL") else - pid = call_subprocess(mopexe, "Running MOPAC", nil, "NUL", "NUL") + pid = call_subprocess([mopexe], "Running MOPAC", nil, "NUL", "NUL") term_callback.call(nil, pid) end Dir.chdir(cwd) diff --git a/wxSources/MoleculeView.cpp b/wxSources/MoleculeView.cpp index 4ce711b..5556ce4 100755 --- a/wxSources/MoleculeView.cpp +++ b/wxSources/MoleculeView.cpp @@ -574,9 +574,6 @@ MoleculeView::OnClose(bool deleteWindow) // Dispose relationship between this and Molecule (MainView) MainView_setViewObject(mview, NULL); mview = NULL; - // We do not know about the frame anymore - frame = NULL; - canvas = NULL; // Remove this from the active view list sActiveViews.Remove(this); @@ -588,7 +585,7 @@ MoleculeView::OnClose(bool deleteWindow) if (deleteWindow) { saveFrame->Destroy(); - } + } else saveFrame->Hide(); // Check if all windows are gone wxGetApp().CheckIfAllWindowsAreGone(saveFrame); diff --git a/wxSources/MyApp.cpp b/wxSources/MyApp.cpp index dc4e965..ab495a9 100755 --- a/wxSources/MyApp.cpp +++ b/wxSources/MyApp.cpp @@ -1412,13 +1412,12 @@ MyApp::OnEndProcess(wxProcessEvent &event) #endif int -MyApp::CallSubProcess(const char *cmdline, const char *procname, int (*callback)(void *), void *callback_data, FILE *fpout, FILE *fperr, int *exitstatus_p, int *pid_p) +MyApp::CallSubProcess(const char **argv, 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; bool progress_panel = false; char buf[256]; - wxString cmdstr(cmdline, WX_DEFAULT_CONV); wxLongLong startTime, lastTime, presentTime; if (m_process != NULL) @@ -1456,13 +1455,23 @@ MyApp::CallSubProcess(const char *cmdline, const char *procname, int (*callback) // Create proc object and call subprocess m_process = new wxBetterProcess(this, -1); m_process->Redirect(); - int flag = wxEXEC_ASYNC; + int flag = wxEXEC_ASYNC | wxEXEC_HIDE_CONSOLE; flag |= wxEXEC_MAKE_GROUP_LEADER; - long pid = ::wxExecute(cmdstr, flag, m_process); + long pid; + if (argv[1] != NULL && argv[1][0] == 0) { + // If the second argument is an empty string, then we handle the first string + // as a single argument. (On the other hand, if the second argument is NULL, + // then argv is given to wxExecute as an array containing a single string.) + pid = ::wxExecute(argv[0], flag, m_process); + } else { + // Array of arguments + pid = ::wxExecute(argv, flag, m_process); + } if (pid == 0) { if (progress_panel) HideProgressPanel(); delete m_process; + m_process = NULL; #if LOG_SUBPROCESS fprintf(fplog, "Cannot start '%s'\n", cmdline); fclose(fplog); @@ -1922,9 +1931,9 @@ wxBetterProcess::GetLineSub(wxString &outStr, wxInputStream *stream, wxMemoryBuf } if (pp != NULL) { // Return one line and string length - outStr = wxString(p, wxConvUTF8, pp - p + 1); + outStr = wxString(p, WX_DEFAULT_CONV, pp - p + 1); memmove(p, pp + 1, len - (pp - p + 1)); - m_stdout.SetDataLen(len - (pp - p + 1)); + mbuf.SetDataLen(len - (pp - p + 1)); return pp - p + 1; } } @@ -2399,11 +2408,12 @@ void MyAppCallback_endUndoGrouping(void) } } -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) +int MyAppCallback_callSubProcess(const char **argv, const char *procname, int (*callback)(void *), void *callback_data, FILE *output, FILE *errout, int *exitstatus_p, int *pid_p) { if (!gUseGUI) - return system(cmdline); - return wxGetApp().CallSubProcess(cmdline, procname, callback, callback_data, output, errout, exitstatus_p, pid_p); + return ::wxExecute(argv, wxEXEC_SYNC | wxEXEC_HIDE_CONSOLE); + else + return wxGetApp().CallSubProcess(argv, procname, callback, callback_data, output, errout, exitstatus_p, pid_p); } void MyAppCallback_showConsoleWindow(void) diff --git a/wxSources/MyApp.h b/wxSources/MyApp.h index e3a3764..df27e1e 100755 --- a/wxSources/MyApp.h +++ b/wxSources/MyApp.h @@ -225,7 +225,7 @@ class MyApp: public wxApp void OnBringAllWindowsToFront(wxCommandEvent &event); // void OnEndProcess(wxProcessEvent &event); - int CallSubProcess(const char *cmdline, const char *procname, int (*callback)(void *) = NULL, void *callback_data = NULL, FILE *fpout = NULL, FILE *fperr = NULL, int *exitstatus_p = NULL, int *pid_p = NULL); + int CallSubProcess(const char **argv, const char *procname, int (*callback)(void *) = NULL, void *callback_data = NULL, FILE *fpout = NULL, FILE *fperr = NULL, int *exitstatus_p = NULL, int *pid_p = NULL); void OnActivate(wxActivateEvent &event); diff --git a/wxSources/MyDocument.cpp b/wxSources/MyDocument.cpp index 4941bcf..1bbc49f 100755 --- a/wxSources/MyDocument.cpp +++ b/wxSources/MyDocument.cpp @@ -1131,7 +1131,7 @@ MyDocument::OnSubThreadTerminated(wxCommandEvent &event) /* Run a subprocess asynchronically */ long -MyDocument::RunSubProcess(const char *cmd, int (*callback)(Molecule *, int), int (*timerCallback)(Molecule *, int), FILE *output, FILE *errout) +MyDocument::RunSubProcess(const char **argv, int (*callback)(Molecule *, int), int (*timerCallback)(Molecule *, int), FILE *output, FILE *errout) { if (sCheckIsSubThreadRunning(mol, subThreadKind)) return -1; /* subProcess (or MM/MD subThread) is already running */ @@ -1139,13 +1139,20 @@ MyDocument::RunSubProcess(const char *cmd, int (*callback)(Molecule *, int), int mol->mutex = new wxMutex; mol->requestAbortThread = 0; - wxString cmdstr(cmd, WX_DEFAULT_CONV); subProcess = new wxProcess(this, -1); subProcess->Redirect(); subProcessStdout = output; subProcessStderr = errout; - subProcessPID = ::wxExecute(cmdstr, wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER, subProcess); + if (argv[1] != NULL && argv[1][0] == 0) { + // If the second argument is an empty string, then we handle the first string + // as a single argument. (On the other hand, if the second argument is NULL, + // then argv is given to wxExecute as an array containing a single string.) + subProcessPID = ::wxExecute(argv[0], wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER, subProcess); + } else { + // Array of arguments + subProcessPID = ::wxExecute(argv, wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER, subProcess); + } if (subProcessPID == 0) { subProcess->Detach(); subProcess = NULL; @@ -1769,13 +1776,13 @@ MoleculeCallback_cannotModifyMoleculeDuringMDError(Molecule *mol) } int -MoleculeCallback_callSubProcessAsync(Molecule *mol, const char *cmd, int (*callback)(Molecule *, int), int (*timerCallback)(Molecule *, int), FILE *output, FILE *errout) +MoleculeCallback_callSubProcessAsync(Molecule *mol, const char **argv, int (*callback)(Molecule *, int), int (*timerCallback)(Molecule *, int), FILE *output, FILE *errout) { if (!gUseGUI) return -1; MyDocument *doc = MyDocumentFromMolecule(mol); if (doc != NULL) - return doc->RunSubProcess(cmd, callback, timerCallback, output, errout); + return doc->RunSubProcess(argv, callback, timerCallback, output, errout); else return -1; } diff --git a/wxSources/MyDocument.h b/wxSources/MyDocument.h index 4ca8b0b..296bfe1 100755 --- a/wxSources/MyDocument.h +++ b/wxSources/MyDocument.h @@ -129,7 +129,7 @@ public: void OnMinimize(wxCommandEvent &event); void OnStopMDRun(wxCommandEvent &event); - long RunSubProcess(const char *cmd, int (*callback)(Molecule *, int), int (*timerCallback)(Molecule *, int), FILE *output, FILE *errout); + long RunSubProcess(const char **argv, int (*callback)(Molecule *, int), int (*timerCallback)(Molecule *, int), FILE *output, FILE *errout); void OnEndSubProcess(wxProcessEvent &event); void FlushSubProcessOutput(); -- 2.11.0