OSDN Git Service

Copyright and License description for JANPA are included
[molby/Molby.git] / MolLib / Ruby_bind / ruby_bind.c
index 3cf97c4..7658636 100644 (file)
@@ -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);
 }
 
 /*
@@ -388,6 +388,84 @@ s_Kernel_ExportToClipboard(VALUE self, VALUE sval)
 
 /*
  *  call-seq:
+ *     hartree_to_kcal(val)
+ *
+ *  Convert hartree to kcal/mol
+ */
+static VALUE
+s_Kernel_HartreeToKcal(VALUE self, VALUE fval)
+{
+    double d = NUM2DBL(rb_Float(fval));
+    return rb_float_new(d * 627.5094740630557);
+}
+
+/*
+ *  call-seq:
+ *     kcal_to_hartree(val)
+ *
+ *  Convert kcal/mol to hartree
+ */
+static VALUE
+s_Kernel_KcalToHartree(VALUE self, VALUE fval)
+{
+    double d = NUM2DBL(rb_Float(fval));
+    return rb_float_new(d / 627.5094740630557);
+}
+
+/*
+ *  call-seq:
+ *     hartree_to_kj(val)
+ *
+ *  Convert hartree to kJ/mol
+ */
+static VALUE
+s_Kernel_HartreeToKJ(VALUE self, VALUE fval)
+{
+    double d = NUM2DBL(rb_Float(fval));
+    return rb_float_new(d * 2625.4996394798253);
+}
+
+/*
+ *  call-seq:
+ *     kj_to_hartree(val)
+ *
+ *  Convert kJ/mol to hartree
+ */
+static VALUE
+s_Kernel_KJToHartree(VALUE self, VALUE fval)
+{
+    double d = NUM2DBL(rb_Float(fval));
+    return rb_float_new(d / 2625.4996394798253);
+}
+
+/*
+ *  call-seq:
+ *     bohr_to_angstrom(val)
+ *
+ *  Convert bohr to angstrom
+ */
+static VALUE
+s_Kernel_BohrToAngstrom(VALUE self, VALUE fval)
+{
+    double d = NUM2DBL(rb_Float(fval));
+    return rb_float_new(d * 0.529177210903);
+}
+
+/*
+ *  call-seq:
+ *     angstrom_to_bohr(val)
+ *
+ *  Convert angstrom to bohr
+ */
+static VALUE
+s_Kernel_AngstromToBohr(VALUE self, VALUE fval)
+{
+    double d = NUM2DBL(rb_Float(fval));
+    return rb_float_new(d / 0.529177210903);
+}
+
+/*
+ *  call-seq:
  *     stdout.write(str)
  *
  *  Put the message in the main text view in black color.
@@ -753,13 +831,13 @@ s_Kernel_RegisterMenu(int argc, VALUE *argv, VALUE self)
                sNonEmptySym = ID2SYM(rb_intern("non_empty"));
                sSelectionSym = ID2SYM(rb_intern("selection"));
                sMolProc = rb_eval_string("lambda { |m| m != nil }");
+        rb_define_variable("$is_a_molecule_proc", &sMolProc);
                sNonEmptyProc = rb_eval_string("lambda { |m| m.is_a?(Molecule) && m.natoms > 0 }");
+        rb_define_variable("$is_molecule_not_empty_proc", &sNonEmptyProc);
                sSelectionProc = rb_eval_string("lambda { |m| m.is_a?(Molecule) && m.selection.count > 0 }");
+        rb_define_variable("$has_molecule_selection_proc", &sSelectionProc);
                sTrueProc = rb_eval_string("lambda { |m| true }");
-               rb_global_variable(&sMolProc);
-               rb_global_variable(&sNonEmptyProc);
-               rb_global_variable(&sSelectionProc);
-               rb_global_variable(&sTrueProc);
+        rb_define_variable("$always_true_proc", &sTrueProc);
        }
        
        if (pval == Qnil) {
@@ -789,7 +867,7 @@ static VALUE
 s_Ruby_UpdateUI_handler(VALUE data)
 {
        void **p = (void **)data;
-       int index = (int)p[0];
+       int index = (intptr_t)p[0];
        Molecule *mol = (Molecule *)p[1];
        int *outChecked = (int *)p[2];
        char **outTitle = (char **)p[3];
@@ -920,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
@@ -934,6 +1016,7 @@ s_Kernel_CallSubProcess(int argc, VALUE *argv, VALUE self)
     VALUE save_interruptFlag;
        int n, exitstatus, pid;
        char *sout, *serr;
+    const char *pnamestr, **cmdargv;
        FILE *fpout, *fperr;
 
        rb_scan_args(argc, argv, "23", &cmd, &procname, &cproc, &stdout_val, &stderr_val);
@@ -978,9 +1061,26 @@ s_Kernel_CallSubProcess(int argc, VALUE *argv, VALUE self)
        }
     
     save_interruptFlag = s_SetInterruptFlag(self, Qnil);
-       n = MyAppCallback_callSubProcess(StringValuePtr(cmd), StringValuePtr(procname), (cproc == Qnil ? NULL : s_Kernel_CallSubProcess_Callback), (cproc == Qnil ? NULL : (void *)cproc), fpout, fperr, &exitstatus, &pid);
+    if (procname != Qnil)
+        pnamestr = StringValuePtr(procname);
+    else pnamestr = NULL;
+    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)
@@ -1003,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);
@@ -5292,7 +5396,7 @@ s_Molecule_Savedcd(VALUE self, VALUE fname)
 static VALUE
 s_Molecule_LoadSave(int argc, VALUE *argv, VALUE self, int loadFlag)
 {
-       VALUE rval;
+    VALUE rval, argv0;
        char *argstr, *methname, *p, *type = "";
        ID mid = 0;
        int i;
@@ -5302,7 +5406,8 @@ s_Molecule_LoadSave(int argc, VALUE *argv, VALUE self, int loadFlag)
        if (argc == 0)
                return Qnil;
 
-       if (argc == 0 || (argstr = StringValuePtr(argv[0])) == NULL)
+    argv0 = argv[0]; /* Keep as a local variable to avoid GC  */
+       if (argc == 0 || (argstr = StringValuePtr(argv0)) == NULL)
                rb_raise(rb_eMolbyError, "the first argument must be either filename or \":filetype\"");
        if (argstr[0] == ':') {
                /*  Call "loadXXX" (or "saveXXX") for type ":XXX"  */
@@ -5357,7 +5462,7 @@ s_Molecule_LoadSave(int argc, VALUE *argv, VALUE self, int loadFlag)
                }
        }
 failure:
-       rval = rb_str_to_str(argv[0]);
+       rval = rb_str_to_str(argv0);
        asprintf(&p, "Failed to %s file %s", (loadFlag ? "load" : "save"), type);
        s_Molecule_RaiseOnLoadSave(1, loadFlag, p, StringValuePtr(rval));
        return Qnil;  /*  Does not reach here  */
@@ -5368,7 +5473,7 @@ success:
                Molecule *mol;
        /*      Atom *ap; */
                Data_Get_Struct(self, Molecule, mol);
-               MoleculeSetPath(mol, StringValuePtr(argv[0]));
+               MoleculeSetPath(mol, StringValuePtr(argv0));
                
                /*  Check if all occupancy factors are zero; if that is the case, then all set to 1.0  */
        /*      for (i = 0, ap = mol->atoms; i < mol->natoms; i++, ap = ATOM_NEXT(ap)) {
@@ -8626,7 +8731,7 @@ s_Molecule_FitCoordinates(int argc, VALUE *argv, VALUE self)
        VALUE gval, rval, wval;
        IntGroup *ig;
        IntGroupIterator iter;
-       int nn, errno, i, j, in, status;
+       int nn, errnum, i, j, in, status;
        Vector *ref;
        Double *weights, dval[3];
        Transform tr;
@@ -8647,7 +8752,7 @@ s_Molecule_FitCoordinates(int argc, VALUE *argv, VALUE self)
        if (rb_obj_is_kind_of(rval, rb_cNumeric)) {
                int fn = NUM2INT(rb_Integer(rval));
                if (fn < 0 || fn >= MoleculeGetNumberOfFrames(mol)) {
-                       errno = 1;
+                       errnum = 1;
                        status = fn;
                        goto err;
                }
@@ -8660,7 +8765,7 @@ s_Molecule_FitCoordinates(int argc, VALUE *argv, VALUE self)
        } else if (rb_obj_is_kind_of(rval, rb_cLAMatrix)) {
                LAMatrix *m = LAMatrixFromValue(rval, NULL, 0, 0);
                if (m->row * m->column < nn * 3) {
-                       errno = 2;
+                       errnum = 2;
                        goto err;
                }
                for (i = 0; i < nn; i++) {
@@ -8672,24 +8777,24 @@ s_Molecule_FitCoordinates(int argc, VALUE *argv, VALUE self)
                VALUE aval;
                rval = rb_protect(rb_ary_to_ary, rval, &status);
                if (status != 0) {
-                       errno = 3;
+                       errnum = 3;
                        goto err;
                }
                if (RARRAY_LEN(rval) < nn) {
-                       errno = 2;
+                       errnum = 2;
                        goto err;
                }
                if (rb_obj_is_kind_of((RARRAY_PTR(rval))[0], rb_cNumeric)) {
                        /*  Array of 3*nn numbers  */
                        if (RARRAY_LEN(rval) < nn * 3) {
-                               errno = 2;
+                               errnum = 2;
                                goto err;
                        }
                        for (i = 0; i < nn; i++) {
                                for (j = 0; j < 3; j++) {
                                        aval = rb_protect(rb_Float, (RARRAY_PTR(rval))[i * 3 + j], &status);
                                        if (status != 0) {
-                                               errno = 3;
+                                               errnum = 3;
                                                goto err;
                                        }
                                        dval[j] = NUM2DBL(aval);
@@ -8707,18 +8812,18 @@ s_Molecule_FitCoordinates(int argc, VALUE *argv, VALUE self)
                                } else {
                                        aval = rb_protect(rb_ary_to_ary, aval, &status);
                                        if (status != 0) {
-                                               errno = 3;
+                                               errnum = 3;
                                                goto err;
                                        }
                                        if (RARRAY_LEN(aval) < 3) {
-                                               errno = 4;
+                                               errnum = 4;
                                                status = i;
                                                goto err;
                                        }
                                        for (j = 0; j < 3; j++) {
                                                VALUE aaval = rb_protect(rb_Float, (RARRAY_PTR(aval))[j], &status);
                                                if (status != 0) {
-                                                       errno = 3;
+                                                       errnum = 3;
                                                        goto err;
                                                }
                                                dval[j] = NUM2DBL(aaval);
@@ -8740,17 +8845,17 @@ s_Molecule_FitCoordinates(int argc, VALUE *argv, VALUE self)
        } else {
                wval = rb_protect(rb_ary_to_ary, wval, &status);
                if (status != 0) {
-                       errno = 3;
+                       errnum = 3;
                        goto err;
                }
                if (RARRAY_LEN(wval) < nn) {
-                       errno = 5;
+                       errnum = 5;
                        goto err;
                }
                for (i = 0; i < nn; i++) {
                        VALUE wwval = rb_protect(rb_Float, (RARRAY_PTR(wval))[i], &status);
                        if (status != 0) {
-                               errno = 3;
+                               errnum = 3;
                                goto err;
                        }
                        weights[i] = NUM2DBL(wwval);
@@ -8758,27 +8863,27 @@ s_Molecule_FitCoordinates(int argc, VALUE *argv, VALUE self)
        }
        dval[0] = s_Molecule_FitCoordinates_Sub(mol, ig, ref, weights, tr);
        if (dval[0] < 0) {
-               errno = 6;
+               errnum = 6;
                goto err;
        }
-       errno = 0;
+       errnum = 0;
 err:
        IntGroupIteratorRelease(&iter);
        free(ref);
        free(weights);
-       if (errno == 0) {
+       if (errnum == 0) {
                return rb_ary_new3(2, ValueFromTransform(&tr), rb_float_new(dval[0]));
-       } else if (errno == 1) {
+       } else if (errnum == 1) {
                rb_raise(rb_eMolbyError, "frame index (%d) is out of range", status);
-       } else if (errno == 2) {
+       } else if (errnum == 2) {
                rb_raise(rb_eMolbyError, "insufficient number of reference coordinates");
-       } else if (errno == 3) {
+       } else if (errnum == 3) {
                rb_jump_tag(status);
-       } else if (errno == 4) {
+       } else if (errnum == 4) {
                rb_raise(rb_eMolbyError, "less than 3 elements for index %d of reference coordinates", status);
-       } else if (errno == 5) {
+       } else if (errnum == 5) {
                rb_raise(rb_eMolbyError, "insufficient number of weight values");
-       } else if (errno == 6) {
+       } else if (errnum == 6) {
                rb_raise(rb_eMolbyError, "matrix calculation failed during coordinate fitting");
        }
        return Qnil;  /*  Not reached  */
@@ -10586,22 +10691,56 @@ s_Molecule_ClearBasisSet(VALUE self)
 
 /*
  *  call-seq:
- *     add_gaussian_orbital_shell(atom_index, sym, no_of_primitives)
+ *     add_gaussian_orbital_shell(atom_index, sym, no_of_primitives[, additional_exponent])
  *
  *  To be used internally. Add a gaussian orbital shell with the atom index, symmetry code,
- *  and the number of primitives. Symmetry code: 0, S-type; 1, P-type; -1, SP-type; 2, D-type;
- *  -2, D5-type.
+ *  and the number of primitives.
+ *  Additional exponent is for JANPA only; implements an additinal r^N component that
+ *  appears in cartesian->spherical conversion.
+ *  Symmetry code: 0, S-type; 1, P-type; -1, SP-type; 2, D-type; -2, D5-type;
+ *                 3, F-type; -3, F7-type; 4, G-type; -4, G9-type.
+ *  Or: "s", S-type; "p", P-type; "sp", SP-type; "d", D-type; "d5", D5-type;
+ *      "f", F-type; "f7", F7-type; "g", G-type; "g9", G9-type
  */
 static VALUE
-s_Molecule_AddGaussianOrbitalShell(VALUE self, VALUE aval, VALUE symval, VALUE npval)
+s_Molecule_AddGaussianOrbitalShell(int argc, VALUE *argv, VALUE self)
 {
        Molecule *mol;
-       int sym, nprims, a_idx, n;
-    Data_Get_Struct(self, Molecule, mol);
+    int sym, nprims, a_idx, n, add_exp;
+    VALUE aval, symval, npval, addval;
+    Data_Get_Struct(self, Molecule, mol);
+    rb_scan_args(argc, argv, "31", &aval, &symval, &npval, &addval);
+    if (rb_obj_is_kind_of(symval, rb_cString)) {
+        const char *p = StringValuePtr(symval);
+        if (strcasecmp(p, "s") == 0)
+            sym = 0;
+        else if (strcasecmp(p, "p") == 0)
+            sym = 1;
+        else if (strcasecmp(p, "sp") == 0)
+            sym = -1;
+        else if (strcasecmp(p, "d") == 0)
+            sym = 2;
+        else if (strcasecmp(p, "d5") == 0)
+            sym = -2;
+        else if (strcasecmp(p, "f") == 0)
+            sym = 3;
+        else if (strcasecmp(p, "f7") == 0)
+            sym = -3;
+        else if (strcasecmp(p, "g") == 0)
+            sym = 4;
+        else if (strcasecmp(p, "g9") == 0)
+            sym = -4;
+        else
+            rb_raise(rb_eArgError, "Unknown orbital type '%s'", p);
+    } else {
+        sym = NUM2INT(rb_Integer(symval));
+    }
        a_idx = NUM2INT(rb_Integer(aval));
-       sym = NUM2INT(rb_Integer(symval));
        nprims = NUM2INT(rb_Integer(npval));
-       n = MoleculeAddGaussianOrbitalShell(mol, a_idx, sym, nprims);
+    if (addval != Qnil)
+        add_exp = NUM2INT(rb_Integer(addval));
+    else add_exp = 0;
+       n = MoleculeAddGaussianOrbitalShell(mol, a_idx, sym, nprims, add_exp);
        if (n == -1)
                rb_raise(rb_eMolbyError, "Molecule is emptry");
        else if (n == -2)
@@ -11424,6 +11563,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).
@@ -11440,6 +11583,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);
@@ -11487,7 +11631,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)
@@ -11759,7 +11917,7 @@ Init_Molby(void)
        rb_define_method(rb_cMolecule, "nelpots", s_Molecule_NElpots, 0);
        rb_define_method(rb_cMolecule, "elpot", s_Molecule_Elpot, 1);
        rb_define_method(rb_cMolecule, "clear_basis_set", s_Molecule_ClearBasisSet, 0);
-       rb_define_method(rb_cMolecule, "add_gaussian_orbital_shell", s_Molecule_AddGaussianOrbitalShell, 3);
+       rb_define_method(rb_cMolecule, "add_gaussian_orbital_shell", s_Molecule_AddGaussianOrbitalShell, -1);
        rb_define_method(rb_cMolecule, "add_gaussian_primitive_coefficients", s_Molecule_AddGaussianPrimitiveCoefficients, 3);
        rb_define_method(rb_cMolecule, "get_gaussian_shell_info", s_Molecule_GetGaussianShellInfo, 1);
        rb_define_method(rb_cMolecule, "get_gaussian_primitive_coefficients", s_Molecule_GetGaussianPrimitiveCoefficients, 1);
@@ -11935,6 +12093,12 @@ Init_Molby(void)
        rb_define_method(rb_mKernel, "play_sound", s_Kernel_PlaySound, -1);
        rb_define_method(rb_mKernel, "stop_sound", s_Kernel_StopSound, 0);
        rb_define_method(rb_mKernel, "export_to_clipboard", s_Kernel_ExportToClipboard, 1);
+    rb_define_method(rb_mKernel, "hartree_to_kcal", s_Kernel_HartreeToKcal, 1);
+    rb_define_method(rb_mKernel, "hartree_to_kj", s_Kernel_HartreeToKJ, 1);
+    rb_define_method(rb_mKernel, "kcal_to_hartree", s_Kernel_KcalToHartree, 1);
+    rb_define_method(rb_mKernel, "kj_to_hartree", s_Kernel_KJToHartree, 1);
+    rb_define_method(rb_mKernel, "bohr_to_angstrom", s_Kernel_BohrToAngstrom, 1);
+    rb_define_method(rb_mKernel, "angstrom_to_bohr", s_Kernel_AngstromToBohr, 1);
 
        /*  class IO  */
        rb_define_method(rb_cIO, "gets_any_eol", s_IO_gets_any_eol, 0);
@@ -12220,7 +12384,9 @@ Molby_getDescription(char **versionString, char **auxString)
                  "%s\n"
                  "FFTW 3.3.2, http://www.fftw.org/\n"
                  "  Copyright (C) 2003, 2007-11 Matteo Frigo"
-                 "  and Massachusetts Institute of Technology",
+                 "  and Massachusetts Institute of Technology\n"
+                 "JANPA 2.01, https://janpa.sourceforge.net/\n"
+                 "  Copyright (C) 2014, Tymofii Nikolaienko",
                  MyAppCallback_getGUIDescriptionString(),
                  gRubyVersion, gRubyCopyright);
     } else {
@@ -12230,7 +12396,9 @@ Molby_getDescription(char **versionString, char **auxString)
                  "%s\n"
                  "FFTW 3.3.2, http://www.fftw.org/\n"
                  "  Copyright (C) 2003, 2007-11 Matteo Frigo"
-                 "  and Massachusetts Institute of Technology",
+                 "  and Massachusetts Institute of Technology\n"
+                 "JANPA 2.01, https://janpa.sourceforge.net/\n"
+                 "  Copyright (C) 2014, Tymofii Nikolaienko",
                  gRubyVersion, gRubyCopyright);
 
     }