Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

cmd_mol.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2019 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: cmd_mol.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.137 $       $Date: 2020/07/08 04:19:30 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *   text commands for molecule control
00019  ***************************************************************************/
00020 
00021 #include <ctype.h>
00022 #include <stdlib.h>
00023 #include <tcl.h>
00024 
00025 #include "config.h"
00026 #include "utilities.h"
00027 #include "VMDApp.h"
00028 #include "TclCommands.h"
00029 #include "VMDDisplayList.h"
00030 #include "MoleculeList.h"
00031 
00032 // the following uses the Cmdtypes MOL_NEW, MOL_DEL, MOL_ACTIVE,
00033 // MOL_FIX, MOL_ON, MOL_TOP, MOL_SELECT, MOL_REP, MOL_COLOR, MOL_ADDREP,
00034 // MOL_MODREP, MOL_DELREP, MOL_MODREPITEM
00035 
00036 
00037 /*
00038  * NOTES:
00039  *
00040  * 1) When referring to a molecule in a command by a number, the
00041  * unique molecule ID is used, NOT the relative index of the molecule into
00042  * the molecule list.  This is because the relative index changes as molecules
00043  * are added/removed, but the unique ID stays the same until the molecule is
00044  * deleted.
00045  *
00046  */
00047 
00048 
00059 class IdList {
00060 private:
00061   int *idList;
00062   int selectedMols;
00063 
00064   void molname_error(Tcl_Interp *interp, const char *fullname, const char *errpart) {
00065     char *errmsg = new char[200 + strlen(fullname) + strlen(errpart)];
00066     sprintf(errmsg, 
00067       "Illegal molecule specification '%s': Could not\nfind molecule '%s'. ",
00068       fullname, errpart);
00069     Tcl_SetResult(interp, errmsg, TCL_VOLATILE);
00070     delete [] errmsg;
00071   }
00072 
00073 public:
00074   IdList() {
00075     idList = 0;
00076     selectedMols = -1;
00077   }
00078   int find(Tcl_Interp *, VMDApp *app, const char *txt, int *allmolsflag = NULL); // return num()
00079   ~IdList() {
00080     delete [] idList;
00081   }
00082   int num() const { return selectedMols; }
00083   int operator[](int i) const { return idList[i]; }
00084 };
00085 
00086 int IdList::find(Tcl_Interp *interp, VMDApp *app, const char *givenName, int *allmolsflag) {
00087   char name[512];      
00088   int i, numMols;
00089 
00090   if (interp == NULL || app == NULL || givenName == NULL) {
00091     Tcl_SetResult(interp, (char *) "ERROR) IdList::find() bad parameters", TCL_STATIC);
00092     return -1;
00093   }
00094 
00095   numMols = app->num_molecules();
00096   if (!numMols) {
00097     Tcl_SetResult(interp, (char *) "ERROR) No molecules loaded.", TCL_STATIC);
00098     return -1;
00099   }
00100 
00101   idList = new int[numMols];
00102   for (i=0; i<numMols; i++) idList[i] = 0;
00103 
00104   // start to tokenize the string, then
00105   // scan the string and look for molecule specifiers
00106   strcpy(name, givenName);
00107   char *tok = strtok(name, "|/:");
00108   while(tok) {
00109     // look for what kind of name this is
00110     if(isdigit(*tok)) {     // check if it is a molid 
00111       int n = atoi(tok);
00112       if (!app->molecule_valid_id(n)) {
00113         molname_error(interp, givenName, tok);
00114         return -1;
00115       }
00116       for (i=0; i<numMols; i++) {
00117         if (app->molecule_id(i) == n) {
00118           idList[i] = TRUE;
00119         }
00120       }
00121     } else if(!strupncmp(tok, "all", CMDLEN)) {     // check if "all"
00122       // tell caller that _all_ molecules were selected, to allow more
00123       // efficient processing where possible.
00124       if (allmolsflag != NULL) {
00125         *allmolsflag = 1; 
00126       }
00127       for(i=0; i < numMols; i++)
00128         idList[i] = TRUE;
00129     } else if(!strupncmp(tok, "none", CMDLEN)) {    // "none"
00130       for(i=0; i < numMols; i++)
00131         idList[i] = FALSE;
00132     } else if(!strupncmp(tok, "top", CMDLEN)) {     // "top"
00133       int top = app->molecule_top();
00134       for(i=0; i < numMols; i++)
00135         if (app->molecule_id(i) == top)
00136           idList[i] = 1;
00137     } else if(!strupncmp(tok, "active", CMDLEN)) {  // check if "active"
00138       for(i=0; i < numMols; i++)
00139         if (app->molecule_is_active(app->molecule_id(i))) 
00140           idList[i] = 1;
00141     } else if(!strupncmp(tok, "inactive", CMDLEN)) {    // check if "inactive"
00142       for(i=0; i < numMols; i++)
00143         if (!app->molecule_is_active(app->molecule_id(i)))
00144           idList[i] = 1;
00145     } else if(!strupncmp(tok, "displayed", CMDLEN) ||
00146     !strupncmp(tok, "on", CMDLEN)) {        // "displayed" or "on"
00147       for(i=0; i < numMols; i++)
00148         if (app->molecule_is_displayed(app->molecule_id(i)))
00149           idList[i] = 1;
00150     } else if(!strupncmp(tok, "off", CMDLEN)) { // check if "off"
00151       for(i=0; i < numMols; i++)
00152         if (!app->molecule_is_displayed(app->molecule_id(i)))
00153           idList[i] = 1;
00154     } else if(!strupncmp(tok, "fixed", CMDLEN)) {   // check if "fixed"
00155       for(i=0; i < numMols; i++)
00156         if (app->molecule_is_fixed(app->molecule_id(i)))
00157           idList[i] = 1;
00158     } else if(!strupncmp(tok, "free", CMDLEN) ||
00159     !strupncmp(tok, "unfix", CMDLEN)) {         // "free" or "unfix"
00160       for(i=0; i < numMols; i++)
00161         if (!app->molecule_is_fixed(app->molecule_id(i)))
00162           idList[i] = 1;
00163     } else {
00164       // bad molecule name; print error and return
00165       molname_error(interp, givenName, tok);
00166       return -1;
00167     }
00168     tok = strtok(NULL,"|/:");
00169   }
00170 
00171   // found the names; now convert the flag array to a list of id's.  
00172   selectedMols = 0;
00173   for(i=0; i < numMols; i++) {
00174     if(idList[i])
00175       idList[selectedMols++] = app->molecule_id(i);
00176   }
00177   return selectedMols;
00178 }
00179 
00180 static void print_mol_summary(Tcl_Interp *interp, VMDApp *app, int molid) {
00181   if (!app->molecule_valid_id(molid)) return;
00182   // everything except molecule name is bounded in size
00183   char *buf = new char[strlen(app->molecule_name(molid))+50];
00184   sprintf(buf, "%s  Atoms:%d  Frames (C): %d(%d)  Status:%c%c%c%c\n",
00185           app->molecule_name(molid), app->molecule_numatoms(molid),
00186           app->molecule_numframes(molid), app->molecule_frame(molid),
00187           (app->molecule_is_active(molid) ? 'A' : 'a'),
00188           (app->molecule_is_displayed(molid) ? 'D' : 'd'),
00189           (app->molecule_is_fixed(molid) ? 'F' : 'f'),
00190           (molid == app->molecule_top() ? 'T' : 't'));
00191   Tcl_AppendResult(interp, buf, NULL);
00192   delete [] buf;
00193 }
00194 
00195 static void print_arep_summary(Tcl_Interp *interp, VMDApp *app, int molid, 
00196                                int i) {
00197   if (!app->molecule_valid_id(molid)) return;
00198   if (i < 0 || i >= app->num_molreps(molid)) return;
00199   char buf[100];
00200   sprintf(buf, "%d: %s, %d atoms selected.\n", 
00201           i, (app->molecule_is_displayed(molid) ? " on" : "off"), 
00202           app->molrep_numselected(molid, i));
00203   Tcl_AppendResult(interp, buf, NULL);
00204   Tcl_AppendResult(interp, "  Coloring method: ", 
00205                    app->molrep_get_color(molid, i), "\n", NULL);
00206   Tcl_AppendResult(interp, "   Representation: ", 
00207                    app->molrep_get_style(molid, i), "\n", NULL);
00208   Tcl_AppendResult(interp, "        Selection: ", 
00209                    app->molrep_get_selection(molid, i), "\n", NULL);
00210 }
00211 
00212 static void cmd_mol_list(Tcl_Interp *interp, VMDApp *app, const char *moltxt) {
00213   IdList idList;
00214   if (idList.find(interp, app, moltxt) > 1) {
00215     Tcl_AppendResult(interp, "Molecule Status Overview:\n", NULL);
00216     Tcl_AppendResult(interp, "-------------------------\n", NULL);
00217     for (int i=0; i < idList.num(); i++)
00218       print_mol_summary(interp, app, idList[i]);
00219   } else if (idList.num() == 1) {
00220     Tcl_AppendResult(interp, "Status of molecule ", 
00221                      app->molecule_name(idList[0]), ":\n", NULL);
00222     print_mol_summary(interp, app, idList[0]);
00223     char buf[50];
00224     sprintf(buf, "Atom representations: %d\n", app->num_molreps(idList[0]));
00225     Tcl_AppendResult(interp, buf, NULL); 
00226     for (int i=0; i < app->num_molreps(idList[0]); i++)
00227       print_arep_summary(interp, app, idList[0], i);
00228   }
00229 }
00230 
00231 static void cmd_mol_usage(Tcl_Interp *interp) {
00232     Tcl_AppendResult(interp, "usage: mol <command> [args...]\n",
00233     "\nMolecules and Data:\n",
00234     "  new [file name] [options...]       -- load file into a new molecule\n",
00235     "  new atoms <natoms>                 -- generate a new molecule with 'empty' atoms\n",
00236     "  addfile <file name> [options...]   -- load files into existing molecule\n",
00237     "    options: type, first, last, step, waitfor, volsets, filebonds, autobonds, \n",
00238     "             <molid> (addfile only)\n",
00239     "  load <file type> <file name>       -- load molecule (obsolescent)\n" ,
00240     "  urlload <file type> <URL>          -- load molecule from URL\n" ,
00241     "  pdbload <four letter accession id> -- download molecule from the PDB\n",
00242     "  cancel <molid>                     -- cancel load/save of trajectory\n",  
00243     "  delete <molid>                     -- delete given molecule\n" , 
00244     "  rename <molid> <name>              -- Rename the specified molecule\n",     
00245     "  dataflag <molid> [set | unset] <flagname> -- Set/unset data output flags\n",
00246     "  list [all|<molid>]                 -- displays info about molecules\n",
00247     "\nMolecule GUI Properties:\n",
00248     "  top <molid>                        -- make that molecule 'top'\n",
00249     "  on <molid>                         -- make molecule visible\n" ,
00250     "  off <molid>                        -- make molecule invisible\n" ,
00251     "  fix <molid>                        -- don't apply mouse motions\n" ,
00252     "  free <molid>                       -- let mouse move molecules\n" ,
00253     "  active <molid>                     -- make molecule active\n" ,
00254     "  inactive <molid>                   -- make molecule inactive\n" ,
00255     "\nGraphical Representations:\n",
00256     "  addrep <molid>                     -- add a new representation\n" ,
00257     "  delrep <repid> <molid>             -- delete rep\n" ,
00258     "  default [color | style | selection | material] <value>\n",
00259     "  representation|rep <style>         -- set the drawing style for new reps\n" ,
00260     "  selection <selection>              -- set the selection for new reps\n" ,
00261     "  color <color>                      -- set the color for new reps\n" ,
00262     "  material <material>                -- set the material for new reps\n" ,
00263     "  modstyle <repid> <molid> <style>   -- change the drawing style for a rep\n" ,
00264     "  modselect <repid> <molid> <selection>  -- change the selection for a rep\n" ,
00265     "  modcolor <repid> <molid> <color>   -- change the color for a rep\n" ,
00266     "  modmaterial <repid> <molid> <material> -- change the material for a rep\n" ,
00267     "  repname <molid> <repid>            -- Get the name of a rep\n",
00268     "  repindex <molid> <repname>         -- Get the repid of a rep from its name\n",
00269     "  reanalyze <molid>                  -- Re-analyze structure after changes\n",
00270     "  bondsrecalc <molid>                -- Recalculate bonds, current timestep\n",
00271     "  ssrecalc <molid>                   -- Recalculate secondary structure (Cartoon)\n",
00272     "  selupdate <repid> <molid> [on|off] -- Get/Set auto recalc of rep selection\n",
00273     "  colupdate <repid> <molid> [on|off] -- Get/Set auto recalc of rep color\n",
00274     "  scaleminmax <molid> <repid> [<min> <max>|auto] -- Get/set colorscale minmax\n",
00275     "  drawframes <molid> <repid> [<framespec>|now] -- Get/Set drawn frame range\n", 
00276     "  smoothrep <molid> <repid> [smooth] -- Get or set trajectory smoothing value\n",
00277     "  showperiodic <molid> <repid> [flags] -- Get or set periodic image display\n",
00278     "  numperiodic <molid> <repid> <n>    -- Get or set number of periodic images\n",
00279     "  showrep <molid> <repid> [on|off]   -- Turn selected rep on or off\n",
00280 
00281     "  volaxes   <molid> <volID> <Xaxis> <Yaxis> <Zaxis> -- set vol axes\n",
00282     "  voldelete <molid> <volID>          -- delete volumetric data\n",
00283     "  volmove   <molid> <volID> <matrix> -- transform volumetric data\n",
00284     "  volorigin <molid> <volID> <vector> -- set origin\n",
00285     "  volscale  <molid> <volID> <vector> -- scale volume\n",
00286     "\nClipping Planes:\n",
00287     "  clipplane center <clipid> <repid> <molid> [<vector>]\n",
00288     "  clipplane color  <clipid> <repid> <molid> [<vector>]\n",
00289     "  clipplane normal <clipid> <repid> <molid> [<vector>]\n",
00290     "  clipplane status <clipid> <repid> <molid> [<mode>]\n",
00291     "  clipplane num\n",
00292     "\n",
00293     "See also the molinfo command\n",
00294     NULL);
00295 }
00296 
00297 
00298 int text_cmd_mol(ClientData cd, Tcl_Interp *interp, int argc,
00299                             const char *argv[]) {
00300 
00301   VMDApp *app = (VMDApp *)cd;
00302 
00303   if (argc == 1) {
00304     cmd_mol_usage(interp);
00305     return TCL_ERROR;
00306   }
00307   if ((argc == 4 || argc == 6) && !strupncmp(argv[1], "load", CMDLEN)) {
00308     // load a new molecule
00309   
00310     // Special-case graphics molecules to load as "blank" molecules
00311     if (argc == 4 && !strupncmp(argv[2], "graphics", CMDLEN)) {
00312       int rc = app->molecule_new(argv[3], 0);
00313       Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
00314       return TCL_OK;
00315     }
00316     FileSpec spec;
00317     spec.waitfor = FileSpec::WAIT_ALL;
00318     int newmolid = app->molecule_load(-1, argv[3], argv[2], &spec);
00319     if (newmolid < 0) {
00320       Tcl_AppendResult(interp, "Unable to load structure file ",argv[3], NULL);
00321       return TCL_ERROR;
00322     }
00323     if (argc == 6) {
00324       if (app->molecule_load(newmolid, argv[5], argv[4], &spec) < 0) {
00325         Tcl_AppendResult(interp, "Unable to load coordinate file ", argv[5], 
00326                          NULL);
00327         return TCL_ERROR;
00328       }
00329     }
00330     Tcl_SetObjResult(interp, Tcl_NewIntObj(newmolid));
00331 
00332   } else if(argc < 4 && !strupncmp(argv[1], "list", CMDLEN)) {
00333     if(argc == 2)
00334       cmd_mol_list(interp, app, "all");
00335     else
00336       cmd_mol_list(interp, app, argv[2]);
00337   
00338   } else if (argc < 4 && !strupncmp(argv[1], "cancel", CMDLEN)) {
00339     IdList idList;
00340     if (argc == 2) {
00341       idList.find(interp, app, "all");
00342     } else {
00343       idList.find(interp, app, argv[2]);
00344     }
00345     for (int i=0; i<idList.num(); i++) app->molecule_cancel_io(idList[i]);
00346   
00347   } else if(!strupncmp(argv[1],"selection",CMDLEN)) {
00348     char *molstr = combine_arguments(argc, argv, 2);
00349     if (molstr) {
00350       app->molecule_set_selection(molstr);
00351       delete [] molstr;
00352     }
00353   } else if(!strupncmp(argv[1],"representation",CMDLEN) ||
00354             !strupncmp(argv[1],"rep",CMDLEN) ) {
00355     char *molstr = combine_arguments(argc, argv, 2);
00356     if (molstr) {
00357       app->molecule_set_style(molstr);
00358       delete [] molstr;
00359     }
00360 
00361   } else if(!strupncmp(argv[1],"color",CMDLEN)) {
00362     char *molstr = combine_arguments(argc, argv, 2);
00363     if (molstr) {
00364       app->molecule_set_color(molstr);
00365       delete [] molstr;
00366     }
00367 
00368   } else if(!strupncmp(argv[1],"material",CMDLEN)) {
00369     char *molstr = combine_arguments(argc, argv, 2);
00370     if (molstr) {
00371       app->molecule_set_material(molstr);
00372       delete [] molstr;
00373     }
00374 
00375   } else if(argc > 4 && (!strupncmp(argv[1],"modcolor",CMDLEN) ||
00376             !strupncmp(argv[1],"modstyle",CMDLEN) ||
00377             !strupncmp(argv[1],"modselect",CMDLEN) ||  
00378             !strupncmp(argv[1],"modmaterial",CMDLEN))) {
00379     IdList idList;
00380     if (idList.find(interp, app, argv[3]) != 1) {
00381       Tcl_AppendResult(interp, argv[0], " operates on one molecule only.", NULL);
00382       return TCL_ERROR;
00383     }
00384     int molid = idList[0]; 
00385     char *molstr = combine_arguments(argc, argv, 4);
00386     if(molstr) {
00387       if(!strupncmp(argv[1],"modcolor",CMDLEN))
00388         app->molrep_set_color(molid, atoi(argv[2]), molstr);
00389       else if(!strupncmp(argv[1],"modstyle",CMDLEN))
00390         app->molrep_set_style(molid, atoi(argv[2]), molstr);
00391       else if(!strupncmp(argv[1],"modselect",CMDLEN))
00392         app->molrep_set_selection(molid, atoi(argv[2]), molstr);
00393       else if(!strupncmp(argv[1],"modmaterial",CMDLEN))
00394         app->molrep_set_material(molid, atoi(argv[2]), molstr);
00395       delete [] molstr;
00396     }
00397   
00398   } else if(argc == 3 && !strupncmp(argv[1],"addrep",CMDLEN)) {
00399     IdList idList;
00400     if (idList.find(interp, app, argv[2]) > 1) {
00401       
00402       Tcl_AppendResult(interp, "mol addrep operates on one molecule only.", NULL);
00403       return TCL_ERROR;
00404     }
00405     if (idList.num() < 1) return TCL_ERROR;
00406     if (!app->molecule_addrep(idList[0])) {
00407       Tcl_AppendResult(interp, "addrep: Unable to add rep to molecule ", 
00408                        argv[2], NULL);
00409       return TCL_ERROR;
00410     }
00411   } else if(argc == 4 && !strupncmp(argv[1],"delrep",CMDLEN)) {
00412     IdList idList;
00413     if (idList.find(interp, app, argv[3]) != 1) {
00414       Tcl_AppendResult(interp, argv[0], " operates on one molecule only.", NULL);
00415       return TCL_ERROR;
00416     }
00417     app->molrep_delete(idList[0], atoi(argv[2]));
00418   } else if(argc == 4 && !strupncmp(argv[1],"modrep",CMDLEN)) {
00419     // XXX This is freakin' lame - deprecate this, please!
00420     IdList idList;
00421     if (idList.find(interp, app, argv[3]) != 1) {
00422       Tcl_AppendResult(interp, argv[0], " operates on one molecule only.", NULL);
00423       return TCL_ERROR;
00424     }
00425     int molid = idList[0];
00426     int repid = atoi(argv[2]);
00427     app->molrep_set_style(molid, repid, app->molecule_get_style());
00428     app->molrep_set_color(molid, repid, app->molecule_get_color());
00429     app->molrep_set_selection(molid, repid, app->molecule_get_selection());
00430     app->molrep_set_material(molid, repid, app->molecule_get_material());
00431   } else if(argc == 3 && !strupncmp(argv[1],"delete",CMDLEN)) {
00432     IdList idList;
00433     int allmolsflag=0;
00434     idList.find(interp, app, argv[2], &allmolsflag);
00435 
00436     if (allmolsflag) {
00437       // use most efficient molecule deletion code path
00438       app->molecule_delete_all();
00439     } else {
00440       // delete molecules piecemeal
00441       for (int i=0; i<idList.num(); i++) {
00442         app->molecule_delete(idList[i]);
00443       }
00444     }
00445   } else if(argc == 3 && (!strupncmp(argv[1],"active",CMDLEN) ||
00446             !strupncmp(argv[1],"inactive",CMDLEN))) {
00447     IdList idList;
00448     idList.find(interp, app, argv[2]);
00449     for (int i=0; i<idList.num(); i++) {
00450       app->molecule_activate(idList[i], !strupncmp(argv[1],"active",CMDLEN));
00451     }
00452   } else if(argc == 3 && (!strupncmp(argv[1],"on",CMDLEN) ||
00453             !strupncmp(argv[1],"off",CMDLEN))) {
00454     IdList idList;
00455     idList.find(interp, app, argv[2]);
00456     for (int i=0; i<idList.num(); i++) {
00457       app->molecule_display(idList[i], !strupncmp(argv[1],"on",CMDLEN));
00458     }
00459   } else if(argc == 3 && (!strupncmp(argv[1],"fix",CMDLEN) ||
00460             !strupncmp(argv[1],"free",CMDLEN))) {
00461     IdList idList;
00462     idList.find(interp, app, argv[2]);
00463     for (int i=0; i<idList.num(); i++) {
00464       app->molecule_fix(idList[i], !strupncmp(argv[1],"fix",CMDLEN));
00465     }
00466 
00467   } else if(argc == 3 && !strupncmp(argv[1],"top",CMDLEN)) {
00468     IdList idList;
00469     if (idList.find(interp,app, argv[2]) != 1) {
00470       Tcl_AppendResult(interp, argv[0], " operates on one molecule only.", NULL);
00471       return TCL_ERROR;
00472     }
00473     app->molecule_make_top(idList[0]);
00474   } else if (argc == 4 && !strupncmp(argv[1], "urlload", CMDLEN)) {
00475     // load a file from a URL
00476     //   "mol urlload xyz http://www.umn.edu/test/me/out.xyz
00477     // vmd_mol_urlload url localfile 
00478     char *localfile = vmd_tempfile("urlload");
00479     char *buf = new char[strlen(localfile)+strlen(argv[3])+100];
00480     sprintf(buf, "vmd_mol_urlload %s %s", argv[3], localfile);
00481     int rc = Tcl_Eval(interp, buf);
00482     delete [] buf;
00483     if (rc != TCL_OK) {
00484       Tcl_AppendResult(interp, "vmd_mol_urllload failed.", NULL);
00485       delete [] localfile;
00486       return TCL_ERROR;
00487     }
00488     FileSpec spec;
00489     spec.waitfor = FileSpec::WAIT_ALL;
00490     int molid = app->molecule_load(-1, localfile, argv[2], &spec);
00491     delete [] localfile;
00492     if (molid < 0) {
00493       Tcl_AppendResult(interp, "urlload failed: unable to load downloaded file '", localfile, "' as file type ", argv[2], NULL);
00494       return TCL_ERROR;
00495     }
00496     Tcl_SetObjResult(interp, Tcl_NewIntObj(molid));
00497   } else if (argc == 3 && !strupncmp(argv[1], "pdbload", CMDLEN)) {
00498     // alias to "mol load webpdb ..."
00499     FileSpec spec;
00500     spec.waitfor = FileSpec::WAIT_ALL; 
00501     int rc = app->molecule_load(-1, argv[2], "webpdb", &spec);
00502     if (rc < 0) {
00503       Tcl_AppendResult(interp, "pdbload of '", argv[2], "' failed.", NULL);
00504       return TCL_ERROR;
00505     }
00506     Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
00507   } else if (argc == 5 && !strupncmp(argv[1], "dataflag", CMDLEN)) {
00508     IdList idList;
00509     idList.find(interp, app, argv[2]);
00510     int setval;
00511 
00512     if (!strcmp("set", argv[3])) {
00513       setval = 1;
00514     } else if  (!strcmp("unset", argv[3])) {
00515       setval = 0;
00516     } else {
00517       Tcl_AppendResult(interp, argv[1], " subcommand unrecognized", NULL);
00518       return TCL_ERROR;
00519     }
00520 
00521     for (int i=0; i<idList.num(); i++) {
00522       if (!app->molecule_set_dataset_flag(idList[i], argv[4], setval)) {
00523         Tcl_AppendResult(interp, " error setting dataset flag ", argv[4], NULL);
00524         return TCL_ERROR;
00525       }
00526     }
00527   } else if (argc == 3 && !strupncmp(argv[1], "reanalyze", CMDLEN)) {
00528     IdList idList;
00529     idList.find(interp, app, argv[2]);
00530     for (int i=0; i<idList.num(); i++) {
00531       app->molecule_reanalyze(idList[i]);
00532     }
00533 
00534   } else if (argc == 3 && !strupncmp(argv[1], "bondsrecalc", CMDLEN)) {
00535     IdList idList;
00536     idList.find(interp, app, argv[2]);
00537     for (int i=0; i<idList.num(); i++) {
00538       app->molecule_bondsrecalc(idList[i]);
00539     }
00540 
00541   } else if (argc == 3 && !strupncmp(argv[1], "ssrecalc", CMDLEN)) {
00542     IdList idList;
00543     idList.find(interp, app, argv[2]);
00544     for (int i=0; i<idList.num(); i++) {
00545       app->molecule_ssrecalc(idList[i]);
00546     }
00547 
00548   } else if (argc == 12 && !strupncmp(argv[1], "volume", CMDLEN)) {
00549     float origin[3], xaxis[3], yaxis[3], zaxis[3];
00550     int xsize, ysize, zsize;
00551     float *data;  // new'ed here; passed to molecule
00552 
00553     IdList idList;
00554     if (idList.find(interp, app, argv[2]) != 1) {
00555       Tcl_AppendResult(interp, argv[0], " operates on one molecule only.", NULL);
00556       return TCL_ERROR;
00557     }
00558     int molid = idList[0];
00559    
00560     if (tcl_get_vector(argv[4], origin, interp) != TCL_OK ||
00561         tcl_get_vector(argv[5], xaxis, interp) != TCL_OK ||
00562         tcl_get_vector(argv[6], yaxis, interp) != TCL_OK ||
00563         tcl_get_vector(argv[7], zaxis, interp) != TCL_OK) {
00564       return TCL_ERROR;
00565     }
00566     if (Tcl_GetInt(interp, argv[8], &xsize) != TCL_OK ||
00567         Tcl_GetInt(interp, argv[9], &ysize) != TCL_OK ||
00568         Tcl_GetInt(interp, argv[10], &zsize) != TCL_OK) {
00569       return TCL_ERROR;
00570     }
00571     long size = xsize*ysize*zsize;
00572     data = new float[size];
00573    
00574     int ndata;
00575     const char **dataAsString;
00576     if (Tcl_SplitList(interp, argv[11], &ndata, &dataAsString) != TCL_OK) {
00577       Tcl_SetResult(interp, (char *) "mol volume: invalid data block", TCL_STATIC);
00578       delete [] data;
00579       return TCL_ERROR;
00580     }
00581     if (ndata != size) {
00582       Tcl_SetResult(interp, (char *) "mol volume: size of data does not match specified sizes", TCL_STATIC);
00583       Tcl_Free((char *)dataAsString);
00584       delete [] data;
00585       return TCL_ERROR;
00586     }
00587     for (int i=0; i<ndata; i++) {
00588       double tmp;
00589       if (Tcl_GetDouble(interp, dataAsString[i], &tmp) != TCL_OK) {
00590         Tcl_SetResult(interp, (char *) "graphics: volume: non-numeric found in data block", TCL_STATIC);
00591         Tcl_Free((char *)dataAsString);
00592         delete [] data;
00593         return TCL_ERROR;
00594       }
00595       data[i] = (float)tmp;
00596     }
00597     app->molecule_add_volumetric(molid, argv[3], origin, xaxis, yaxis, zaxis,
00598                                  xsize, ysize, zsize, data);
00599     Tcl_Free((char *)dataAsString);
00600 
00601   } else if ((argc == 4 || argc == 5) && !strupncmp(argv[1], "selupdate", CMDLEN)) {
00602     IdList idList;
00603     if (idList.find(interp, app, argv[3]) != 1) {
00604       Tcl_AppendResult(interp, argv[0], " operates on one molecule only.", NULL);
00605       return TCL_ERROR;
00606     }
00607     int molid = idList[0];
00608     int repid = atoi(argv[2]);
00609     if (argc == 4) {
00610       char tmpstring[64];
00611       sprintf(tmpstring, "%d", app->molrep_get_selupdate(molid, repid));
00612       Tcl_SetResult(interp, tmpstring, TCL_VOLATILE);
00613     } else {
00614       int onoff;
00615       if (Tcl_GetBoolean(interp, argv[4], &onoff) != TCL_OK)
00616         return TCL_ERROR; // GetBoolean sets error message.
00617       if (!app->molrep_set_selupdate(molid, repid, onoff)) {
00618         Tcl_AppendResult(interp, "Could not set auto update", NULL);
00619         return TCL_ERROR;
00620       }
00621     }
00622   } else if ((argc == 4 || argc == 5) && !strupncmp(argv[1], "colupdate", CMDLEN)) {
00623     IdList idList;
00624     if (idList.find(interp, app, argv[3]) != 1) {
00625       Tcl_AppendResult(interp, argv[0], " operates on one molecule only.", NULL);
00626       return TCL_ERROR;
00627     }
00628     int molid = idList[0];
00629     int repid = atoi(argv[2]);
00630     if (argc == 4) {
00631       char tmpstring[64];
00632       sprintf(tmpstring, "%d", app->molrep_get_colorupdate(molid, repid));
00633       Tcl_SetResult(interp, tmpstring, TCL_VOLATILE);
00634     } else {
00635       int onoff;
00636       if (Tcl_GetBoolean(interp, argv[4], &onoff) != TCL_OK)
00637         return TCL_ERROR; // GetBoolean sets error message.
00638       if (!app->molrep_set_colorupdate(molid, repid, onoff)) {
00639         Tcl_AppendResult(interp, "Could not set auto color update", NULL);
00640         return TCL_ERROR;
00641       }
00642     }
00643 
00644   // Clipping plane functions:
00645   // mol clipplane center <clipid> <repid> <molid> [<vector>]
00646   //   set/get the clipplane center
00647   // mol clipplane color <clipid> <repid> <molid> [<vector>]
00648   //   set/get the clipplane color 
00649   // mol clipplane normal <clipid> <repid> <molid> [<vector>]
00650   //   set/get the clipplane normal 
00651   // mol clipplane status <clipid> <repid> <molid> [<mode>]
00652   // mol clipplane num
00653   } else if (argc >= 2 && !strupncmp(argv[1], "clipplane", CMDLEN)) {
00654     if (argc == 3 && !strupncmp(argv[1], "clipplane", CMDLEN) &&
00655         !strupncmp(argv[2], "num", CMDLEN)) {
00656       Tcl_SetObjResult(interp, Tcl_NewIntObj(app->num_clipplanes()));
00657       return TCL_OK;
00658     } else if (argc >= 6 && !strupncmp(argv[1], "clipplane", CMDLEN)) {
00659       int clipid = atoi(argv[3]);
00660       int repid = atoi(argv[4]);
00661 
00662       // int molid = atoi(argv[5]);  // XXX should use IDList
00663       IdList idList;
00664       if (idList.find(interp, app, argv[5]) != 1) {
00665         Tcl_AppendResult(interp, argv[0], " operates on one molecule only.", NULL);
00666         return TCL_ERROR;
00667       }
00668       int molid = idList[0];
00669 
00670       if (clipid < 0 || clipid >= app->num_clipplanes()) {
00671         Tcl_AppendResult(interp, "Invalid clip plane id specified: ", 
00672                          argv[3], NULL);
00673         return TCL_ERROR;
00674       }
00675       if (!app->molecule_valid_id(molid)) {
00676         Tcl_AppendResult(interp, "Invalid molid specified:", argv[5], NULL);
00677         return TCL_ERROR;
00678       }
00679       if (repid < 0 || repid >= app->num_molreps(molid)) {
00680         Tcl_AppendResult(interp, "Invalid repid specified:", argv[4], NULL);
00681         return TCL_ERROR;
00682       }
00683 
00684       float center[3], normal[3], color[3];
00685       int status;
00686       if (argc == 6) {
00687         if (!app->molrep_get_clipplane(molid, repid, clipid, center, normal, color, &status)) {
00688           Tcl_AppendResult(interp, "Unable to get clip plane information", NULL);
00689           return TCL_ERROR;
00690         }
00691         if (!strupncmp(argv[2], "center", CMDLEN)) {
00692           // return center
00693           Tcl_Obj *result = Tcl_NewListObj(0, NULL);
00694           for (int i=0; i<3; i++) {
00695             Tcl_ListObjAppendElement(interp, result, 
00696               Tcl_NewDoubleObj(center[i]));
00697           }
00698           Tcl_SetObjResult(interp, result);
00699           return TCL_OK;
00700         } else if (!strupncmp(argv[2], "normal", CMDLEN)) { 
00701           // return normal
00702           Tcl_Obj *result = Tcl_NewListObj(0, NULL);
00703           for (int i=0; i<3; i++) {
00704             Tcl_ListObjAppendElement(interp, result, 
00705               Tcl_NewDoubleObj(normal[i]));
00706           }
00707           Tcl_SetObjResult(interp, result);
00708           return TCL_OK;
00709         } else if (!strupncmp(argv[2], "color", CMDLEN)) { 
00710           // return color 
00711           Tcl_Obj *result = Tcl_NewListObj(0, NULL);
00712           for (int i=0; i<3; i++) {
00713             Tcl_ListObjAppendElement(interp, result, 
00714               Tcl_NewDoubleObj(color[i]));
00715           }
00716           Tcl_SetObjResult(interp, result);
00717           return TCL_OK;
00718         } else if (!strupncmp(argv[2], "status", CMDLEN)) { 
00719           // return status 
00720           Tcl_SetObjResult(interp, Tcl_NewIntObj(status));
00721           return TCL_OK; 
00722         }
00723       } else if (argc == 7) {
00724         if (!strupncmp(argv[2], "center", CMDLEN)) {
00725           // set center
00726           if (tcl_get_vector(argv[6], center, interp) != TCL_OK) {
00727             return TCL_ERROR;
00728           }
00729           if (!app->molrep_set_clipcenter(molid, repid, clipid, center)) {
00730             Tcl_AppendResult(interp, "Unable to set clip center\n", NULL);
00731             return TCL_ERROR;
00732           }
00733         } else if (!strupncmp(argv[2], "normal", CMDLEN)) { 
00734           // set normal
00735           if (tcl_get_vector(argv[6], normal, interp) != TCL_OK) {
00736             return TCL_ERROR;
00737           }
00738           if (!app->molrep_set_clipnormal(molid, repid, clipid, normal)) {
00739             Tcl_AppendResult(interp, "Unable to set clip normal\n", NULL);
00740             return TCL_ERROR;
00741           }
00742         } else if (!strupncmp(argv[2], "color", CMDLEN)) { 
00743           // set color
00744           if (tcl_get_vector(argv[6], color, interp) != TCL_OK) {
00745             return TCL_ERROR;
00746           }
00747           if (!app->molrep_set_clipcolor(molid, repid, clipid, color)) {
00748             Tcl_AppendResult(interp, "Unable to set clip color\n", NULL);
00749             return TCL_ERROR;
00750           }
00751         } else if (!strupncmp(argv[2], "status", CMDLEN)) { 
00752           // set status 
00753           if (Tcl_GetInt(interp, argv[6], &status) != TCL_OK) {
00754             return TCL_ERROR;
00755           }
00756           if (!app->molrep_set_clipstatus(molid, repid, clipid, status)) {
00757             Tcl_AppendResult(interp, "Unable to set clip status\n", NULL);
00758             return TCL_ERROR;
00759           }
00760         }
00761         return TCL_OK;
00762       }
00763     } 
00764     Tcl_AppendResult(interp, "Usage: \n",
00765       "mol clipplane center <clipid> <repid> <molid> [<vector>]\n",
00766       "mol clipplane normal <clipid> <repid> <molid> [<vector>]\n",
00767       "mol clipplane color  <clipid> <repid> <molid> [<vector>]\n",
00768       "mol clipplane status <clipid> <repid> <molid> [<mode>]\n",
00769       "mol clipplane num\n",
00770       NULL);
00771     return TCL_ERROR;
00772   } else if (argc == 4 && !strupncmp(argv[1], "rename", CMDLEN)) {
00773     IdList idList;
00774     if (idList.find(interp, app, argv[2]) != 1) {
00775       Tcl_AppendResult(interp, argv[0], " operates on one molecule only.", NULL);
00776       return TCL_ERROR;
00777     }
00778     int molid = idList[0];
00779     if (!app->molecule_rename(molid, argv[3])) {
00780       Tcl_AppendResult(interp, "Unable to rename molecule.", NULL);
00781       return TCL_ERROR;
00782     }
00783   } else if (argc==4 && !strupncmp(argv[1], "repname", CMDLEN)) {
00784     IdList idList;
00785     if (idList.find(interp, app, argv[2]) != 1) {
00786       Tcl_AppendResult(interp, argv[0], argv[1], 
00787                        " operates on one molecule only", NULL);
00788       return TCL_ERROR;
00789     }
00790     int repid = atoi(argv[3]);
00791     const char *name = app->molrep_get_name(idList[0], repid);
00792     if (!name) {
00793       Tcl_AppendResult(interp, "mol repname: invalid repid ", argv[3], NULL);
00794       return TCL_ERROR;
00795     }
00796     Tcl_SetObjResult(interp, Tcl_NewStringObj(name, -1));
00797   } else if (argc == 4 && !strupncmp(argv[1], "repindex", CMDLEN)) {
00798     IdList idList;
00799     if (idList.find(interp, app, argv[2]) > 1) {
00800       Tcl_AppendResult(interp, argv[0], " ", argv[1], 
00801                        " operates on one molecule only", NULL);
00802       return TCL_ERROR;
00803     }
00804     int repid = -1;
00805     if (idList.num() == 1)
00806       repid = app->molrep_get_by_name(idList[0], argv[3]);
00807     Tcl_SetObjResult(interp, Tcl_NewIntObj(repid));
00808 // mol fromsels <selection list>
00809   } else if (argc >= 2 && !strupncmp(argv[1], "fromsels", CMDLEN)) {
00810     int newmolid = -1;
00811     if (argc == 3) {
00812       // build selection list
00813       int numsels=0;
00814 
00815       Tcl_Obj **sel_list = NULL;
00816       Tcl_Obj *selparms = Tcl_NewStringObj(argv[2], -1);
00817 #if 1
00818       if (Tcl_ListObjGetElements(interp, selparms, &numsels, &sel_list) != TCL_OK) {
00819         Tcl_AppendResult(interp, "mol fromsels: bad selection list", NULL);
00820         return TCL_ERROR;
00821       }
00822 #endif
00823 
00824 // printf("mol fromsels: numsels %d\n", numsels);
00825       AtomSel **asels = (AtomSel **) calloc(1, numsels * sizeof(AtomSel *));
00826       int s;
00827       for (s=0; s<numsels; s++) {
00828         asels[s] = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(sel_list[s], NULL));
00829         if (!asels[s]) {
00830 // printf("mol fromsels: invalid selection[%d]\n", s);
00831           Tcl_AppendResult(interp, "mol fromsels: invalid atom selection list element", NULL);
00832           return TCL_ERROR;
00833         }
00834       }
00835 
00836       newmolid = app->molecule_from_selection_list(NULL, 0, numsels, asels);
00837       free(asels);
00838 
00839       if (newmolid < 0) {
00840         Tcl_AppendResult(interp, "Unable to create new molecule.", NULL);
00841         return TCL_ERROR;
00842       }
00843     } else {
00844       Tcl_AppendResult(interp, "Atom selection list missing.", NULL);
00845       return TCL_ERROR;
00846     } 
00847 
00848     Tcl_SetObjResult(interp, Tcl_NewIntObj(newmolid));
00849 
00850 
00851 // mol new [filename] [options...]
00852 // mol addfile <filename> [options...]
00853 // options: 
00854 //   atoms <numatoms> (for "mol new" only and when no filename is given)
00855 //   type <filetype> 
00856 //   filebonds <onoff> 
00857 //   autobonds <onoff> 
00858 //   first <firstframe> 
00859 //   last <lastframe>
00860 //   step <frame stride>
00861 //   waitfor <all | number>
00862 //   volsets <list of set ids>
00863 //   molid   (for addfile only; must be the last item)
00864   } else if ((argc >= 2 && !strupncmp(argv[1], "new", CMDLEN)) ||
00865              (argc >= 3 && !strupncmp(argv[1], "addfile", CMDLEN))) {
00866     int molid = -1;
00867     const char *type = NULL;
00868     if (argc == 2) {
00869       molid = app->molecule_new(NULL, 0);
00870       if (molid < 0) {
00871         Tcl_AppendResult(interp, "Unable to create new molecule.", NULL);
00872         return TCL_ERROR;
00873       }
00874     } else if ((argc == 4) && (!strupncmp(argv[2], "atoms", CMDLEN))) {
00875       int natoms;
00876       Tcl_GetInt(interp, argv[3], &natoms);
00877       molid = app->molecule_new(NULL, natoms);
00878       if (molid < 0) {
00879         Tcl_AppendResult(interp, "Unable to create new molecule.", NULL);
00880         return TCL_ERROR;
00881       }
00882     } else if (argc >= 3) {
00883       if (!strupncmp(argv[1], "addfile", CMDLEN)) {
00884         molid = app->molecule_top();
00885       } // otherwise just -1
00886       // Check for optional parameters
00887       FileSpec spec;
00888       int a;
00889       for (a=3; a<argc; a+=2) {
00890         if (!strupncmp(argv[a], "type", CMDLEN)) {
00891           if ((a+1) < argc) {
00892             type = argv[a+1];
00893           } else {
00894             Tcl_AppendResult(interp, "Error, missing type parameter", NULL);
00895             return TCL_ERROR;
00896           }
00897         } else if (!strupncmp(argv[a], "autobonds", CMDLEN)) {
00898           if (((a+1) >= argc) || (Tcl_GetBoolean(interp, argv[a+1], &spec.autobonds) != TCL_OK)) {
00899             Tcl_AppendResult(interp, "Error, missing/bad autobonds parameter", NULL);
00900             return TCL_ERROR;
00901           }
00902         } else if (!strupncmp(argv[a], "filebonds", CMDLEN)) {
00903           if (((a+1) >= argc) || (Tcl_GetBoolean(interp, argv[a+1], &spec.filebonds) != TCL_OK)) {
00904             Tcl_AppendResult(interp, "Error, missing/bad filebonds parameter", NULL);
00905             return TCL_ERROR;
00906           }
00907         } else if (!strupncmp(argv[a], "first", CMDLEN)) {
00908           if (((a+1) >= argc) || (Tcl_GetInt(interp, argv[a+1], &spec.first) != TCL_OK)) {
00909             Tcl_AppendResult(interp, "Error, missing/bad first parameter", NULL);
00910             return TCL_ERROR;
00911           }
00912         } else if (!strupncmp(argv[a], "last", CMDLEN)) {
00913           if (((a+1) >= argc) || (Tcl_GetInt(interp, argv[a+1], &spec.last) != TCL_OK)) {
00914             Tcl_AppendResult(interp, "Error, missing/bad first parameter", NULL);
00915             return TCL_ERROR;
00916           }
00917         } else if (!strupncmp(argv[a], "step", CMDLEN)) {
00918           if (((a+1) >= argc) || (Tcl_GetInt(interp, argv[a+1], &spec.stride) != TCL_OK)) {
00919             Tcl_AppendResult(interp, "Error, missing/bad step parameter", NULL);
00920             return TCL_ERROR;
00921           }
00922         } else if (!strupncmp(argv[a], "waitfor", CMDLEN)) {
00923           if ((a+1) < argc) {
00924             if (!strupncmp(argv[a+1], "all", CMDLEN)) {
00925               spec.waitfor = FileSpec::WAIT_ALL;
00926             } else {
00927               if (Tcl_GetInt(interp, argv[a+1], &spec.waitfor) != TCL_OK)
00928                 return TCL_ERROR;
00929             }
00930           } else {
00931             Tcl_AppendResult(interp, "Error, missing waitfor parameter", NULL);
00932             return TCL_ERROR;
00933           }
00934         } else if (!strupncmp(argv[a], "volsets", CMDLEN)) {
00935           int nsets;
00936           const char **sets;
00937 
00938           if ((a+1) >= argc) {
00939             Tcl_AppendResult(interp, "Error, missing volsets parameters", NULL);
00940             return TCL_ERROR;
00941           }
00942           if (Tcl_SplitList(interp, argv[a+1], &nsets, &sets) != TCL_OK) {
00943             Tcl_AppendResult(interp, "Cannot parse list of volsets.", NULL);
00944             return TCL_ERROR;
00945           }
00946           if (nsets > 0) {
00947             spec.nvolsets = nsets;
00948             spec.setids = new int[nsets];
00949             for (int i=0; i<nsets; i++) {
00950               if (Tcl_GetInt(interp, sets[i], spec.setids+i) != TCL_OK) {
00951                 return TCL_ERROR;
00952               }
00953             }
00954           }
00955           Tcl_Free((char *)sets);
00956         }
00957       }
00958       if (!type) {
00959         type = app->guess_filetype(argv[2]);
00960         if (!type) {
00961           Tcl_AppendResult(interp, "Could not determine file type for file '",
00962                            argv[2], "' from its extension.", NULL);
00963           return TCL_ERROR;
00964         }
00965       }
00966       if (a == argc+1) {
00967         IdList idList;
00968         if (idList.find(interp, app, argv[argc-1]) != 1) {
00969           Tcl_AppendResult(interp, argv[0], " ", argv[1], 
00970                            " operates on one molecule only", NULL);
00971           return TCL_ERROR;
00972         }
00973         molid = idList[0];
00974       }
00975       molid = app->molecule_load(molid, argv[2], type, &spec);
00976       if (molid < 0) {
00977         Tcl_AppendResult(interp, "Unable to load file '", argv[2], "' using file type '", type, "'.", NULL);
00978         return TCL_ERROR;
00979       }
00980     }
00981     Tcl_SetObjResult(interp, Tcl_NewIntObj(molid));
00982     return TCL_OK;
00983   } else if ( (argc == 4 || argc == 5) && !strupncmp(argv[1], "smoothrep", CMDLEN)) {
00984     // smoothrep <molid> <repid> [<smoothness>]
00985     IdList idList;
00986     if (idList.find(interp, app, argv[2]) != 1) {
00987       Tcl_AppendResult(interp, argv[0], " ", argv[1],
00988                        " operates on one molecule only", NULL);
00989       return TCL_ERROR;
00990     }
00991     int repid;
00992     if (Tcl_GetInt(interp, argv[3], &repid) != TCL_OK) return TCL_ERROR;
00993     if (argc == 4) {
00994       int smooth = app->molrep_get_smoothing(idList[0], repid);
00995       if (smooth < 0) {
00996         Tcl_AppendResult(interp, "mol smoothrep: invalid rep", NULL);
00997         return TCL_ERROR;
00998       }
00999       Tcl_SetObjResult(interp, Tcl_NewIntObj(smooth));
01000     } else {
01001       int smooth;
01002       if (Tcl_GetInt(interp, argv[4], &smooth) != TCL_OK) return TCL_ERROR;
01003       if (smooth < 0) {
01004         Tcl_AppendResult(interp, "mol smoothrep: smoothness must be nonnegative", NULL);
01005         return TCL_ERROR;
01006       }
01007       if (!app->molrep_set_smoothing(idList[0], repid, smooth)) {
01008         Tcl_AppendResult(interp, "mol smoothrep: Unable to set smoothing for this rep", NULL);
01009         return TCL_ERROR;
01010       }
01011     }
01012     return TCL_OK;
01013 
01014     // mol showperiodic <molid> <repid> <string>
01015     // where string is x, y, z, xy, xz, yz, or xyz
01016   } else if ((argc == 4 || argc == 5) && !strupncmp(argv[1], "showperiodic", CMDLEN)) {
01017     IdList idList;
01018     if (idList.find(interp, app, argv[2]) != 1) {
01019       Tcl_AppendResult(interp, argv[0], " ", argv[1],
01020                        (char *)" operates on one molecule only", NULL);
01021       return TCL_ERROR;
01022     }
01023     int repid;
01024     if (Tcl_GetInt(interp, argv[3], &repid) != TCL_OK) return TCL_ERROR;
01025     if (argc == 5) {
01026       int pbc = PBC_NONE;  // defaults to PBC_NONE if no 5th argument is given
01027       if (strchr(argv[4], 'x')) pbc |= PBC_X;
01028       if (strchr(argv[4], 'y')) pbc |= PBC_Y;
01029       if (strchr(argv[4], 'z')) pbc |= PBC_Z;
01030       if (strchr(argv[4], 'X')) pbc |= PBC_OPX;
01031       if (strchr(argv[4], 'Y')) pbc |= PBC_OPY;
01032       if (strchr(argv[4], 'Z')) pbc |= PBC_OPZ;
01033       if (strchr(argv[4], 'n')) pbc |= PBC_NOSELF;
01034       if (!app->molrep_set_pbc(idList[0], repid, pbc)) {
01035         Tcl_AppendResult(interp, "mol setpbc: Unable to set periodic images for this rep", NULL);
01036         return TCL_ERROR;
01037       }
01038     } else {
01039       int pbc = app->molrep_get_pbc(idList[0], repid);
01040       if (pbc < 0) {
01041         Tcl_AppendResult(interp, "mol showperiodic: Unable to get periodic info for this rep", NULL);
01042         return TCL_ERROR;
01043       }
01044       char buf[10];
01045       buf[0] = '\0';
01046       if (pbc & PBC_X) strcat(buf, "x");
01047       if (pbc & PBC_Y) strcat(buf, "y");
01048       if (pbc & PBC_Z) strcat(buf, "z");
01049       if (pbc & PBC_OPX) strcat(buf, "X");
01050       if (pbc & PBC_OPY) strcat(buf, "Y");
01051       if (pbc & PBC_OPZ) strcat(buf, "Z");
01052       if (pbc & PBC_NOSELF) strcat(buf, "n");
01053       Tcl_SetResult(interp, buf, TCL_VOLATILE);
01054     }
01055   } else if ((argc == 4 || argc == 5) && !strupncmp(argv[1], "numperiodic", CMDLEN)) {
01056     IdList idList;
01057     if (idList.find(interp, app, argv[2]) != 1) {
01058       Tcl_AppendResult(interp, argv[0], " ", argv[1],
01059           (char *)" operates on one molecule only", NULL);
01060       return TCL_ERROR;
01061     }
01062     int repid;
01063     if (Tcl_GetInt(interp, argv[3], &repid) != TCL_OK) return TCL_ERROR;
01064     if (argc == 5) {
01065       int npbc;
01066       if (Tcl_GetInt(interp, argv[4], &npbc) != TCL_OK) return TCL_ERROR;
01067       if (!app->molrep_set_pbc_images(idList[0], repid, npbc)) {
01068         Tcl_AppendResult(interp, "mol numperiodic: Unable to set number of replicas for this rep", NULL);
01069         return TCL_ERROR;
01070       }
01071     } else {
01072       int npbc = app->molrep_get_pbc_images(idList[0], repid);
01073       if (npbc < 0) {
01074         Tcl_AppendResult(interp, "mol numperiodic: Unable to get number of replicas for this rep", NULL);
01075         return TCL_ERROR;
01076       }
01077       Tcl_SetObjResult(interp, Tcl_NewIntObj(npbc));
01078     }
01079 
01080     // mol instances 
01081   } else if (argc >= 2 && !strupncmp(argv[1], "instances", CMDLEN)) {
01082     IdList idList;
01083     if (idList.find(interp, app, argv[2]) != 1) {
01084       Tcl_AppendResult(interp, argv[0], " operates on one molecule only.", NULL);
01085       return TCL_ERROR;
01086     }
01087     int molid = idList[0];
01088     // 'mol instances x' query, return number of instances
01089     if (argc == 3) {
01090       int ninstances = app->molecule_num_instances(molid); 
01091       if (ninstances < 0) {
01092         Tcl_AppendResult(interp, "mol instances: Unable to get number of replicas for specified molecule", NULL);
01093         return TCL_ERROR;
01094       }
01095       Tcl_SetObjResult(interp, Tcl_NewIntObj(ninstances));
01096     } 
01097 
01098     // mol addinstance xform
01099   } else if (argc >= 2 && !strupncmp(argv[1], "addinstance", CMDLEN)) {
01100     IdList idList;
01101     if (idList.find(interp, app, argv[2]) != 1) {
01102       Tcl_AppendResult(interp, argv[0], " operates on one molecule only.", NULL);
01103       return TCL_ERROR;
01104     }
01105     int molid = idList[0];
01106 
01107     Matrix4 mat;
01108     Tcl_Obj *matobj = Tcl_NewStringObj(argv[3], -1);
01109     int mrc=tcl_get_matrix("mol addinstance:", interp, matobj , mat.mat);
01110     Tcl_DecrRefCount(matobj);
01111     if (mrc != TCL_OK)
01112       return TCL_ERROR;
01113 
01114     if (!app->molecule_add_instance(molid, mat)) {
01115       Tcl_AppendResult(interp, argv[0], " ", argv[1], (char *)" failed to add instance", NULL);
01116       return TCL_ERROR;
01117     }
01118 
01119     // mol showinstances <molid> <repid> <string>
01120     // where string is none, all, noself
01121   } else if ((argc == 4 || argc == 5) && !strupncmp(argv[1], "showinstances", CMDLEN)) {
01122     IdList idList;
01123     if (idList.find(interp, app, argv[2]) != 1) {
01124       Tcl_AppendResult(interp, argv[0], " ", argv[1],
01125                        (char *)" operates on one molecule only", NULL);
01126       return TCL_ERROR;
01127     }
01128     int repid;
01129     if (Tcl_GetInt(interp, argv[3], &repid) != TCL_OK) return TCL_ERROR;
01130     if (argc == 5) {
01131       // defaults to INSTANCE_NONE if no 5th argument is given
01132       int instances = INSTANCE_NONE;
01133 
01134       if (!strcmp(argv[4], "all")) 
01135         instances |= INSTANCE_ALL;
01136 
01137       if (!strcmp(argv[4], "noself")) 
01138         instances |= INSTANCE_ALL | INSTANCE_NOSELF;
01139 
01140       if (!app->molrep_set_instances(idList[0], repid, instances)) {
01141         Tcl_AppendResult(interp, "mol setinstances: Unable to set instances for this rep", NULL);
01142         return TCL_ERROR;
01143       }
01144     } else {
01145       int instances = app->molrep_get_instances(idList[0], repid);
01146       if (instances < 0) {
01147         Tcl_AppendResult(interp, "mol showinstances: Unable to get instance info for this rep", NULL);
01148         return TCL_ERROR;
01149       }
01150       if (instances & INSTANCE_NONE) Tcl_AppendResult(interp, "none", NULL);
01151       else if (instances & INSTANCE_ALL) Tcl_AppendResult(interp, "all", NULL);
01152       else if (instances & INSTANCE_NOSELF) Tcl_AppendResult(interp, "noself", NULL);
01153     }
01154 
01155   } else if ((argc >= 4 && argc <= 6) && !strupncmp(argv[1], "scaleminmax", CMDLEN)) {
01156     IdList idList;
01157     if (idList.find(interp, app, argv[2]) != 1) {
01158       Tcl_AppendResult(interp, argv[0], " ", argv[1],
01159                        (char *)" operates on one molecule only", NULL);
01160       return TCL_ERROR;
01161     }
01162     int repid;
01163     if (Tcl_GetInt(interp, argv[3], &repid) != TCL_OK) return TCL_ERROR;
01164     if (argc == 4) {
01165       float min, max;
01166       if (!app->molrep_get_scaleminmax(idList[0], repid, &min, &max)) {
01167         Tcl_AppendResult(interp, "mol scaleminmax: Unable to get color range for this rep", NULL);
01168         return TCL_ERROR;
01169       }
01170 
01171       char tmpstring[128] = { 0 };
01172       sprintf(tmpstring, "%f %f", min, max);
01173       Tcl_SetResult(interp, tmpstring, TCL_VOLATILE);
01174     } else if (argc == 5 && !strupncmp(argv[4], "auto", CMDLEN)) {
01175       if (!app->molrep_reset_scaleminmax(idList[0], repid)) {
01176         Tcl_AppendResult(interp, "mol scaleminmax: Unable to reset color range for this rep", NULL);
01177         return TCL_ERROR;
01178       }
01179     } else {
01180       double min, max;
01181       if (Tcl_GetDouble(interp, argv[4], &min) != TCL_OK ||
01182           Tcl_GetDouble(interp, argv[5], &max) != TCL_OK)
01183         return TCL_ERROR;
01184       if (!app->molrep_set_scaleminmax(idList[0],repid,(float)min,(float)max)) {
01185         Tcl_AppendResult(interp, "mol scaleminmax: Unable to set color range for this rep", NULL);
01186         return TCL_ERROR;
01187       }
01188     }
01189     // mol showrep <molid> <repid> [<onoff>]
01190   } else if ((argc == 4 || argc == 5) && !strupncmp(argv[1], "showrep", CMDLEN)) {
01191     IdList idList;
01192     if (idList.find(interp, app, argv[2]) != 1) {
01193       Tcl_AppendResult(interp, argv[0], " ", argv[1],
01194                        (char *)" operates on one molecule only", NULL);
01195       return TCL_ERROR;
01196     }
01197     int repid;
01198     if (Tcl_GetInt(interp, argv[3], &repid) != TCL_OK) return TCL_ERROR;
01199     if (argc == 4) {
01200       Tcl_SetObjResult(interp, Tcl_NewIntObj(app->molrep_is_shown(idList[0], repid)));
01201     } else {
01202       int onoff;
01203       if (Tcl_GetBoolean(interp, argv[4], &onoff) != TCL_OK) return TCL_ERROR;
01204       if (!app->molrep_show(idList[0], repid, onoff)) {
01205         Tcl_AppendResult(interp, "Unable to show/hide this rep", NULL);
01206         return TCL_ERROR;
01207       }
01208     }
01209   } else if ((argc == 4 || argc == 5) && !strupncmp(argv[1], "drawframes", CMDLEN)) {
01210     IdList idList;
01211     if (idList.find(interp, app, argv[2]) != 1) {
01212       Tcl_AppendResult(interp, argv[0], " ", argv[1],
01213                        (char *)" operates on one molecule only", NULL);
01214       return TCL_ERROR;
01215     }
01216     int repid;
01217     if (Tcl_GetInt(interp, argv[3], &repid) != TCL_OK) return TCL_ERROR;
01218 
01219     if (argc == 4) {
01220       Tcl_SetObjResult(interp, Tcl_NewStringObj(app->molrep_get_drawframes(idList[0], repid), -1));
01221     } else {
01222       if (!app->molrep_set_drawframes(idList[0], repid, argv[4])) {
01223         Tcl_AppendResult(interp, "Set drawframes failed.", NULL);
01224         return TCL_ERROR;
01225       }
01226     }
01227     // mol orblocalize <molid> <waveid>
01228   } else if (argc == 4 && !strupncmp(argv[1], "orblocalize", CMDLEN)) {
01229     IdList idList;
01230     if (idList.find(interp, app, argv[2]) != 1) {
01231       Tcl_AppendResult(interp, argv[0], " operates on one molecule only.", NULL);
01232       return TCL_ERROR;
01233     }
01234     int molid = idList[0];
01235     int waveid;
01236     if (Tcl_GetInt(interp, argv[3], &waveid) != TCL_OK) return TCL_ERROR;
01237     if (!app->molecule_orblocalize(molid, waveid)) {
01238       Tcl_AppendResult(interp, "Unable to localize orbitals.", NULL);
01239       return TCL_ERROR;
01240     }
01241   } else if ((argc == 3 || argc == 4) && !strupncmp(argv[1], "default", CMDLEN)) {
01242     if (argc == 3) {
01243       if (!strupncmp(argv[2], "color", CMDLEN)) {
01244         Tcl_SetResult(interp, (char *)app->moleculeList->default_color(), TCL_VOLATILE);
01245       } else if (!strupncmp(argv[2], "style", CMDLEN) || !strupncmp(argv[2], "representation", CMDLEN)) {
01246 
01247         Tcl_SetResult(interp, (char *)app->moleculeList->default_representation(), TCL_VOLATILE);
01248       } else if (!strupncmp(argv[2], "selection", CMDLEN)) {
01249         Tcl_SetResult(interp, (char *)app->moleculeList->default_selection(), TCL_VOLATILE);
01250       } else if (!strupncmp(argv[2], "material", CMDLEN)) {
01251         Tcl_SetResult(interp, (char *)app->moleculeList->default_material(), TCL_VOLATILE);
01252       } else {
01253         Tcl_SetResult(interp, (char *) "Usage: mol default [color | style | selection | material]", TCL_STATIC);
01254         return TCL_ERROR;
01255       }
01256       return TCL_OK;
01257     } else {
01258       if (!strupncmp(argv[2], "color", CMDLEN)) {
01259         if (!app->moleculeList->set_default_color(argv[3])) {
01260           Tcl_AppendResult(interp, "Could not set default color to ", argv[3], NULL);
01261           return TCL_ERROR;
01262         }
01263       } else if (!strupncmp(argv[2], "style", CMDLEN) || !strupncmp(argv[2], "representation", CMDLEN)) {
01264         if (!app->moleculeList->set_default_representation(argv[3])) {
01265           Tcl_AppendResult(interp, "Could not set default style to ", argv[3], NULL);
01266           return TCL_ERROR;
01267         }
01268       } else if (!strupncmp(argv[2], "selection", CMDLEN)) {
01269         if (!app->moleculeList->set_default_selection(argv[3])) {
01270           Tcl_AppendResult(interp, "Could not set default selection to ", argv[3], NULL);
01271           return TCL_ERROR;
01272         }
01273       } else if (!strupncmp(argv[2], "material", CMDLEN)) {
01274         if (!app->moleculeList->set_default_material(argv[3])) {
01275           Tcl_AppendResult(interp, "Could not set default material to ", argv[3], NULL);
01276           return TCL_ERROR;
01277         }
01278       } else {
01279         Tcl_SetResult(interp, (char *) "Usage: mol default [color | style | selection | material] <value>", TCL_STATIC);
01280         return TCL_ERROR;
01281       }
01282       return TCL_OK;
01283     }
01284 
01286   } else if (argc == 7 && !strupncmp(argv[1], "volaxes", CMDLEN)) {
01287     // volaxes <molid> <volidx> <Xaxis> <Yaxis> <Zaxis>
01288     int volset = 0;
01289     IdList idList;
01290     if (idList.find(interp, app, argv[2]) != 1) {
01291       Tcl_AppendResult(interp, argv[0], " operates on one molecule only.", NULL);
01292       return TCL_ERROR;
01293     }
01294     int molid = idList[0];
01295     Molecule *mol = app->moleculeList->mol_from_id(molid);
01296     if (!mol) {
01297       Tcl_SetResult(interp, (char *) "mol volaxes: molecule was deleted", TCL_STATIC);
01298       return TCL_ERROR;
01299     }
01300 
01301     if (Tcl_GetInt(interp, argv[3], &volset) != TCL_OK)
01302       return TCL_ERROR;
01303     if (volset >= mol->num_volume_data() || volset < 0) {
01304       char tmpstring[128] = { 0 };
01305       sprintf(tmpstring, "mol volaxes: no volume set %d", volset);
01306       Tcl_SetResult(interp, tmpstring, TCL_VOLATILE);
01307       return TCL_ERROR;
01308     }
01309     VolumetricData *v = mol->modify_volume_data(volset);
01310 
01311     float xax[3], yax[3], zax[3];
01312     if (tcl_get_vector(argv[4], xax,  interp) != TCL_OK)
01313       return TCL_ERROR;
01314     if (tcl_get_vector(argv[5], yax,  interp) != TCL_OK)
01315       return TCL_ERROR;
01316     if (tcl_get_vector(argv[6], zax,  interp) != TCL_OK)
01317       return TCL_ERROR;
01318 
01319     v->set_volume_axes(xax, yax, zax);
01320     mol->force_recalc(DrawMolItem::COL_REGEN);
01321     return TCL_OK;
01322 
01324   } else if ((argc == 4) && !strupncmp(argv[1], "voldelete", CMDLEN)) {
01325     int volset = 0;
01326     IdList idList;
01327     if (idList.find(interp, app, argv[2]) != 1) {
01328       Tcl_AppendResult(interp, argv[0], " operates on one molecule only.", NULL);
01329       return TCL_ERROR;
01330     }
01331     int molid = idList[0];
01332     Molecule *mol = app->moleculeList->mol_from_id(molid);
01333     if (!mol) {
01334       Tcl_SetResult(interp, (char *) "mol voldelete: molecule was deleted", TCL_STATIC);
01335       return TCL_ERROR;
01336     }
01337     if (Tcl_GetInt(interp, argv[3], &volset) != TCL_OK)
01338       return TCL_ERROR;
01339     if (volset >= mol->num_volume_data() || volset < 0) {
01340       char tmpstring[128] = { 0 };
01341       sprintf(tmpstring, "mol voldelete: no volume set %d", volset);
01342       Tcl_SetResult(interp, tmpstring, TCL_VOLATILE);
01343       return TCL_ERROR;
01344     }
01345     mol->remove_volume_data(volset); 
01346     return TCL_OK;
01347 
01349   } else if (argc == 7 && !strupncmp(argv[1], "volaxes", CMDLEN)) {
01350     // volorigin <molid> <volidx> <origin>
01351     int volset = 0;
01352     IdList idList;
01353     if (idList.find(interp, app, argv[2]) != 1) {
01354       Tcl_AppendResult(interp, argv[0], " operates on one molecule only.", NULL);
01355       return TCL_ERROR;
01356     }
01357     int molid = idList[0];
01358     Molecule *mol = app->moleculeList->mol_from_id(molid);
01359     if (!mol) {
01360       Tcl_SetResult(interp, (char *) "mol volorigin: molecule was deleted", TCL_STATIC);
01361       return TCL_ERROR;
01362     }
01363 
01364     if (Tcl_GetInt(interp, argv[3], &volset) != TCL_OK)
01365       return TCL_ERROR;
01366     if (volset >= mol->num_volume_data() || volset < 0) {
01367       char tmpstring[128] = { 0 };
01368       sprintf(tmpstring, "mol volorigin: no volume set %d", volset);
01369       Tcl_SetResult(interp, tmpstring, TCL_VOLATILE);
01370       return TCL_ERROR;
01371     }
01372     VolumetricData *v = mol->modify_volume_data(volset);
01373 
01374     float org[3];
01375     if (tcl_get_vector(argv[4], org,  interp) != TCL_OK)
01376       return TCL_ERROR;
01377 
01378     v->set_volume_origin(org);
01379     mol->force_recalc(DrawMolItem::COL_REGEN);
01380     return TCL_OK;
01381  
01384   } else if (argc == 5 && !strupncmp(argv[1], "volmove", CMDLEN)) {
01385     // volmove <molid> <volidx> <4x4 matrix, e.g., from trans*> 
01386     int volset = 0;
01387     IdList idList;
01388     if (idList.find(interp, app, argv[2]) != 1) {
01389       Tcl_AppendResult(interp, argv[0], " operates on one molecule only.", NULL);
01390       return TCL_ERROR;
01391     }
01392     int molid = idList[0];
01393     Molecule *mol = app->moleculeList->mol_from_id(molid);
01394     if (!mol) {
01395       Tcl_SetResult(interp, (char *) "mol volmove: molecule was deleted", TCL_STATIC);
01396       return TCL_ERROR;
01397     }
01398     if (Tcl_GetInt(interp, argv[3], &volset) != TCL_OK)
01399       return TCL_ERROR;
01400     if (volset >= mol->num_volume_data() || volset < 0) {
01401       char tmpstring[128] = { 0 };
01402       sprintf(tmpstring, "mol volmove: no volume set %d", volset);
01403       Tcl_SetResult(interp, tmpstring, TCL_VOLATILE);
01404       return TCL_ERROR;
01405     }
01406     VolumetricData *v = mol->modify_volume_data(volset);
01407     Matrix4 mat;
01408     Tcl_Obj *matobj = Tcl_NewStringObj(argv[4], -1);
01409     if (tcl_get_matrix("mol volmove:", interp, matobj , mat.mat) != TCL_OK) {
01410       Tcl_DecrRefCount(matobj); 
01411       return TCL_ERROR;
01412     }
01413     Tcl_DecrRefCount(matobj); 
01414     float tmp[4];
01415     float input[4];
01416     int idx;
01417     input[3] = 0;
01418     for (idx = 0; idx < 3; idx++) {
01419       input[idx] = float(v->origin[idx]);
01420     }
01421     //printf("Orig. orign: %.3f %.3f %.3f\n", v->origin[0], v->origin[1],v->origin[2]);
01422     mat.multpoint3d(&input[0], &tmp[0]);
01423     for (idx = 0; idx < 3; idx++) {
01424       v->origin[idx] = double(tmp[idx]);
01425       input[idx] = float(v->xaxis[idx]);
01426     }
01427     //printf("Final orign: %.3f %.3f %.3f\n", v->origin[0], v->origin[1],v->origin[2]);
01428     //printf("Orig. xaxis: %.3f %.3f %.3f\n", v->xaxis[0], v->xaxis[1],v->xaxis[2]);
01429     mat.multpoint4d(&input[0], &tmp[0]);
01430     for (idx = 0; idx < 3; idx++) {
01431       v->xaxis[idx] = double(tmp[idx]);
01432       input[idx] = float(v->yaxis[idx]);
01433     }
01434     //printf("Final xaxis: %.3f %.3f %.3f\n", v->xaxis[0], v->xaxis[1],v->xaxis[2]);
01435     mat.multpoint4d(&input[0], &tmp[0]);
01436     //printf("Orig. yaxis: %.3f %.3f %.3f\n", v->yaxis[0], v->yaxis[1],v->yaxis[2]);
01437     for (idx = 0; idx < 3; idx++) {
01438       v->yaxis[idx] = double(tmp[idx]);
01439       input[idx] = float(v->zaxis[idx]);
01440     }
01441     //printf("Final yaxis: %.3f %.3f %.3f\n", v->yaxis[0], v->yaxis[1],v->yaxis[2]);
01442     mat.multpoint4d(&input[0], &tmp[0]);
01443     //printf("Orig. zaxis: %.3f %.3f %.3f\n", v->zaxis[0], v->zaxis[1],v->zaxis[2]);
01444     for (idx = 0; idx < 3; idx++) {
01445       v->zaxis[idx] = double(tmp[idx]);
01446     }
01447     //printf("Final zaxis: %.3f %.3f %.3f\n", v->zaxis[0], v->zaxis[1],v->zaxis[2]);
01448     mol->force_recalc(DrawMolItem::COL_REGEN);
01449     return TCL_OK;
01450 
01452   } else if (argc == 5 && !strupncmp(argv[1], "volscale", CMDLEN)) {
01453     // volscale <molid> <volidx> <xscale, yscale, zscale>
01454     int volset = 0;
01455     IdList idList;
01456     if (idList.find(interp, app, argv[2]) != 1) {
01457       Tcl_AppendResult(interp, argv[0], " operates on one molecule only.", NULL);
01458       return TCL_ERROR;
01459     }
01460     int molid = idList[0];
01461     Molecule *mol = app->moleculeList->mol_from_id(molid);
01462     if (!mol) {
01463       Tcl_SetResult(interp, (char *) "mol volscale: molecule was deleted", TCL_STATIC);
01464       return TCL_ERROR;
01465     }
01466     if (Tcl_GetInt(interp, argv[3], &volset) != TCL_OK)
01467       return TCL_ERROR;
01468     if (volset >= mol->num_volume_data() || volset < 0) {
01469       char tmpstring[128] = { 0 };
01470       sprintf(tmpstring, "mol volscale: no volume set %d", volset);
01471       Tcl_SetResult(interp, tmpstring, TCL_VOLATILE);
01472       return TCL_ERROR;
01473     }
01474     VolumetricData *v = mol->modify_volume_data(volset);
01475 
01476     float vals[3];
01477     if (tcl_get_vector(argv[4], vals,  interp) != TCL_OK) {
01478       return TCL_ERROR;
01479     }
01480 
01481     v->scale_volume(vals[0], vals[1], vals[2]);
01482     mol->force_recalc(DrawMolItem::COL_REGEN);
01483     return TCL_OK;
01484 
01486   } else {
01487     cmd_mol_usage(interp);
01488     return TCL_ERROR;
01489   }
01490   return TCL_OK;
01491 }
01492 
01493 

Generated on Thu Mar 28 02:42:36 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002