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

vmd.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: vmd.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.109 $      $Date: 2020/07/23 04:37:20 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *
00019  * Main program entry points.
00020  *
00021  ***************************************************************************/
00022 
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 
00026 #if defined(_MSC_VER)
00027 #include "win32vmdstart.h"
00028 #endif
00029 
00030 #if !defined(VMDNOMACBUNDLE) && defined(__APPLE__)
00031 #include "macosxvmdstart.h"
00032 #endif
00033 
00034 #include "vmd.h"
00035 #include "VMDApp.h"
00036 #include "utilities.h"  // for TRUE, and for string processing utilities
00037 #include "config.h"     // for compiled-in defaults
00038 #include "WKFThreads.h"
00039 #include "Inform.h"
00040 #include "CommandQueue.h"
00041 #include "TextEvent.h"
00042 #include "MaterialList.h" // for MAT_XXX definitions
00043 #include "SymbolTable.h"  // for processing atomselection macros
00044 
00045 #include "ProfileHooks.h" // NVTX profiling
00046 
00047 #if defined(VMDTKCON)
00048 #include "vmdconsole.h"
00049 #endif
00050 
00051 #ifdef VMDFLTK
00052 #include <FL/Fl.H>
00053 #endif
00054 
00055 #ifdef VMDOPENGL        // OpenGL-specific files
00056 #ifdef VMDCAVE          // CAVE-specific files
00057 #include "cave_ogl.h"
00058 #include "CaveRoutines.h"
00059 #endif
00060 #ifdef VMDFREEVR        // FreeVR-specific files
00061 #include "freevr.h"
00062 #include "FreeVRRoutines.h"
00063 #endif
00064 #endif
00065 
00066 #ifdef VMDMPI
00067 #include "VMDMPI.h"
00068 #endif
00069 
00070 #ifdef VMDTCL
00071 #include <tcl.h>
00072 #include <signal.h>
00073 
00074 //
00075 // set up signal handlers
00076 //
00077 static Tcl_AsyncHandler tclhandler;
00078 
00079 extern "C" {
00080   typedef void (*sighandler_t)(int);
00081 
00082   void VMDTclSigHandler(int) {
00083     Tcl_AsyncMark(tclhandler);
00084   }
00085 
00086   int VMDTclAsyncProc(ClientData, Tcl_Interp *, int) {
00087     signal(SIGINT, (sighandler_t) VMDTclSigHandler);
00088     return TCL_ERROR;
00089   }
00090 
00091 }
00092 #endif // VMDTCL
00093 
00094 
00097 static const char *vmd_initialize_tcl(const char *argv0) {
00098 #ifdef VMDTCL
00099 
00100 #if defined(_MSC_VER)
00101   static char buffer[MAX_PATH +1];
00102   char *p;
00103 
00104   // get full pathname to VMD executable
00105   GetModuleFileName(NULL, buffer, sizeof(buffer));
00106 
00107   // convert filename to Tcl-format
00108   for (p = buffer; *p != '\0'; p++) {
00109     if (*p == '\\') {
00110       *p = '/';
00111     }
00112   }
00113 
00114   Tcl_FindExecutable(buffer); 
00115   return buffer;
00116 #else
00117   if (argv0) {
00118     Tcl_FindExecutable(argv0);
00119   }
00120   return argv0;
00121 #endif
00122 
00123 #else  // no Tcl
00124   return "";
00125 #endif
00126 
00127 }
00128 
00131 static void vmd_finalize_tcl() {
00132 #ifdef VMDTCL
00133   Tcl_Finalize();
00134 #endif
00135 }
00136 
00137 
00138 extern "C" {
00139 
00140 // function pointer to shared memory allocator/deallocator
00141 void * (*vmd_alloc)(size_t);
00142 void (*vmd_dealloc)(void *);
00143 void * (*vmd_realloc)(void *, size_t);
00144 
00145 // function to resize allocations depending on whether or not the allocator
00146 // provides a realloc() function or not.
00147 void * vmd_resize_alloc(void *ptr, size_t oldsize, size_t newsize) {
00148   void *newptr=NULL;
00149 
00150   if (ptr == NULL) { 
00151     newptr = vmd_alloc(newsize);
00152     return newptr; 
00153   }
00154 
00155   if (vmd_realloc != NULL) {
00156     newptr = vmd_realloc(ptr, newsize);
00157   }
00158 
00159   if (newptr == NULL) {
00160     newptr = vmd_alloc(newsize);
00161     if (newptr != NULL) {
00162       memcpy(newptr, ptr, oldsize);
00163       vmd_dealloc(ptr);
00164     }
00165   }
00166 
00167   return newptr;
00168 }
00169 
00170 } // end of extern "C"
00171 
00172 extern void VMDupdateFltk() {
00173 #ifdef VMDFLTK
00174 #if (defined(__APPLE__)) && defined(VMDTCL)
00175   // don't call wait(0) since this causes Tcl/Tk to mishandle events
00176   Fl::flush();
00177 #else
00178   Fl::wait(0);
00179 #endif
00180 #endif
00181 }
00182 
00183 /***************************************************************************
00184  enumerates for different initial status variables, such as the type of
00185  display to use at startup
00186  ***************************************************************************/
00187   
00188 // display types at startup
00189 // For a complete case we should have:
00190 //   FLTK on? (or Tk? or MFC?)
00191 //   GL or OpenGL? (or other??)
00192 //   use the CAVE?
00193 // and be smart about choosing the GL/OpenGL CAVE options, etc.
00194 enum DisplayTypes { 
00195   DISPLAY_WIN,         // standard display in a window.
00196   DISPLAY_WINOGL,      // use OpenGL, if a valid option
00197   DISPLAY_OGLPBUFFER,  // use OpenGL off-screen rendering, if a valid option
00198   DISPLAY_CAVE,        // Display in the CAVE, no FLTK
00199   DISPLAY_TEXT,        // Don't use a graphics display
00200   DISPLAY_CAVEFORMS,   // Use the CAVE _and_ FLTK
00201   DISPLAY_FREEVR,      // Use the FREEVR, no FLTK
00202   DISPLAY_FREEVRFORMS, // Use the CAVE _and_ FLTK
00203   NUM_DISPLAY_TYPES
00204 };
00205 
00206 static const char *displayTypeNames[NUM_DISPLAY_TYPES] = {
00207   "WIN",  "OPENGL", "OPENGLPBUFFER", 
00208   "CAVE", "TEXT", "CAVEFORMS", "FREEVR", "FREEVRFORMS"
00209 };
00210 
00211 #define DISPLAY_USES_WINDOW(d) ((d) == DISPLAY_WIN || (d) == DISPLAY_WINOGL)
00212 #define DISPLAY_USES_CAVE(d) ((d) == DISPLAY_CAVE || (d) == DISPLAY_CAVEFORMS)
00213 #define DISPLAY_USES_FREEVR(d) ((d) == DISPLAY_FREEVR || (d) == DISPLAY_FREEVRFORMS)
00214 #define DISPLAY_USES_GUI(d) (DISPLAY_USES_WINDOW(d) || (d) == DISPLAY_CAVEFORMS || (d) == DISPLAY_FREEVRFORMS)
00215 
00216 // how to show the title
00217 enum TitleTypes { 
00218   TITLE_OFF, TITLE_ON, NUM_TITLE_TYPES 
00219 };
00220 
00221 static const char *titleTypeNames[NUM_TITLE_TYPES] = {
00222   "OFF", "ON"
00223 };
00224 
00225 // display options set at startup time
00226 static int   showTitle      = INIT_DEFTITLE;   
00227 static int   which_display  = INIT_DEFDISPLAY;     
00228 static float displayHeight  = INIT_DEFHEIGHT;
00229 static float displayDist    = INIT_DEFDIST;
00230 static int   displaySize[2] = { -1, -1 };
00231 static int   displayLoc[2]  = { -1, -1 };
00232 
00233 // filenames for init and startup files
00234 static const char *startupFileStr;
00235 static const char *beginCmdFile;
00236 
00237 // Change the text interpreter to Python before processing commands. 
00238 // (affects the "-e" file, not the .vmdrc or other files.
00239 static int cmdFileUsesPython;
00240 
00241 // Filename parsing on the command line works as follows.  The loadAsMolecules
00242 // flag is either on or off.  When on, each filename parsed will be loaded as
00243 // a separate molecule.  When off, all subsequent files will be loaded into
00244 // the same molecule.  The flag is turned on with "-m" and off with
00245 // "-f".  The default state is off.  "-m" and "-f" can be
00246 // specified multiple times on the command line.
00247 static int loadAsMolecules = 0;
00248 static int startNewMolecule = 1;
00249 static ResizeArray<int> startNewMoleculeFlags;
00250 static ResizeArray<const char *>initFilenames;
00251 static ResizeArray<const char *>initFiletypes;
00252 
00253 // Miscellaneous stuff
00254 static int eofexit  = 0;       
00255 static int just_print_help = 0;
00256 static ResizeArray<char *>customArgv;
00257 
00258 // forward declaration of startup processing routines
00259 static void VMDtitle();
00260 static void VMDGetOptions(int, char **, int mpienabled);
00261 
00262 
00263 int VMDinitialize(int *argc, char ***argv, int mpienabled) {
00264   int i;
00265 
00266   PROFILE_PUSH_RANGE("VMDinitialize()", 1);
00267 
00268 #if defined(VMDMPI)
00269   if (mpienabled) {
00270     // hack to fix up env vars if necessary
00271     for (i=0; i<(*argc); i++) {
00272       if(!strupcmp((*argv)[i], "-vmddir")) {
00273         if((*argc) > (i + 1)) {
00274           setenv("VMDDIR", (*argv)[++i], 1);
00275         } else {
00276           msgErr << "-vmddir must specify a fully qualified path." << sendmsg;
00277         }
00278       }
00279     }
00280 
00281     vmd_mpi_init(argc, argv);  // initialize MPI, fix up env vars, etc.
00282   }
00283 #endif
00284 
00285 #if defined(_MSC_VER) && !defined(VMDSEPARATESTARTUP)
00286   win32vmdstart(); // get registry info etc
00287 #endif
00288 
00289 #if !defined(VMDNOMACBUNDLE) && defined(__APPLE__)
00290   macosxvmdstart(*argc, *argv); // get env variables etc
00291 #endif
00292 
00293   // Tell Tcl where the executable is located
00294   const char *argv0 = vmd_initialize_tcl((*argv)[0]);
00295 
00296 #ifdef VMDTCL
00297   // register signal handler
00298   tclhandler = Tcl_AsyncCreate(VMDTclAsyncProc, (ClientData)NULL); 
00299   signal(SIGINT, (sighandler_t) VMDTclSigHandler);  
00300 #endif
00301 
00302   // Let people know who we are.
00303   VMDtitle();
00304 
00305   // Read environment variables and command line options.
00306   // Initialize customArgv with just argv0 to avoid problems with
00307   // Tcl extension.
00308   customArgv.append((char *)argv0);
00309   VMDGetOptions(*argc, *argv, mpienabled); 
00310 
00311 #if (!defined(__APPLE__) && !defined(_MSC_VER)) && (defined(VMDOPENGL) || defined(VMDFLTK))
00312   // If we're using X-windows, we autodetect if the DISPLAY environment
00313   // variable is unset, and automatically switch back to text mode without
00314   // requiring the user to pass the "-dispdev text" command line parameters
00315   if ((which_display == DISPLAY_WIN) && (getenv("DISPLAY") == NULL)) {
00316     which_display = DISPLAY_TEXT;
00317   }
00318 #endif
00319 
00320 #if defined(VMDTKCON)
00321   vmdcon_init();
00322   msgInfo << "Using VMD Console redirection interface." << sendmsg;
00323   // we default to a widget mode console, unless text mode is requested.
00324   // we don't have an tcl interpreter registered yet, so it is set to NULL.
00325   // flushing pending messages to the screen, is only in text mode possible.
00326   if ((which_display == DISPLAY_TEXT) || (which_display == DISPLAY_OGLPBUFFER) 
00327        || just_print_help) {
00328     vmdcon_use_text(NULL);
00329     vmdcon_purge();
00330   } else {
00331     vmdcon_use_widget(NULL);
00332   }
00333 #endif
00334 
00335 #ifdef VMDFLTK
00336   // Do various special FLTK initialization stuff here
00337   if ((which_display != DISPLAY_TEXT) && (which_display != DISPLAY_OGLPBUFFER)) {
00338     // Cause FLTK to to use 24-bit color for all windows if possible
00339     // This must be done before any FLTK windows are shown for the first time.
00340     if (!Fl::visual(FL_DOUBLE | FL_RGB8)) {
00341       if (!Fl::visual(FL_RGB8)) {
00342         Fl::visual(FL_RGB); 
00343       }
00344     }
00345 
00346     // Disable the use of the arrow keys for navigating buttons and other
00347     // non-text widgets, we'll try it out and see how it pans out
00348     Fl::visible_focus(0);
00349 
00350     // Disable Drag 'n Drop since the only text field in VMD is the
00351     // atomselection input and DND severely gets in the way there.
00352     Fl::dnd_text_ops(0);
00353   }
00354 #endif
00355 
00356   // Quit now if the user just wanted a list of command line options.
00357   if (just_print_help) {
00358     vmd_sleep(10);  // This is here so that the user can see the message 
00359                     // before the terminal/shell exits...
00360 
00361     PROFILE_POP_RANGE();
00362     return 0;
00363   }
00364 
00365   // Set up default allocators; these may be overridden by cave or freevr. 
00366   vmd_alloc   = malloc;  // system malloc() in the default case
00367   vmd_dealloc = free;    // system free() in the default case
00368   vmd_realloc = realloc; // system realloc(), set to NULL when not available 
00369 
00370   // check for a CAVE display
00371   if (DISPLAY_USES_CAVE(which_display)) {
00372 #ifdef VMDCAVE
00373     // allocate shared memory pool used to communicate with child renderers
00374     int megs = 2048;
00375     if (getenv("VMDCAVEMEM") != NULL) {
00376       megs = atoi(getenv("VMDCAVEMEM"));
00377     } 
00378     msgInfo << "Attempting to get " << megs << 
00379             "MB of CAVE Shared Memory" << sendmsg;
00380     grab_CAVE_memory(megs);
00381 
00382     CAVEConfigure(argc, *argv, NULL); // configure cave walls and memory use
00383 
00384     // point VMD shared memory allocators to CAVE routines
00385     vmd_alloc = malloc_from_CAVE_memory;
00386     vmd_dealloc = free_to_CAVE_memory;
00387     vmd_realloc = NULL; // no realloc() functionality is available presently
00388 #else
00389     msgErr << "Not compiled with the CAVE options set." << sendmsg;
00390     which_display = DISPLAY_WIN;    
00391 #endif
00392   }
00393 
00394   // check for a FreeVR display
00395   if (DISPLAY_USES_FREEVR(which_display)) {
00396 #ifdef VMDFREEVR
00397     int megs = 2048;
00398     if (getenv("VMDFREEVRMEM") != NULL) {
00399       megs = atoi(getenv("VMDFREEVRMEM"));
00400     } 
00401     msgInfo << "Attempting to get " << megs << 
00402             "MB of FreeVR Shared Memory" << sendmsg;
00403     grab_FreeVR_memory(megs); // have to do this *before* vrConfigure() if
00404                               // we want more than the default shared mem.
00405     vrConfigure(NULL, NULL, NULL); // configure FreeVR walls
00406 
00407     // point shared memory allocators to FreeVR routines
00408     vmd_alloc = malloc_from_FreeVR_memory;
00409     vmd_dealloc = free_to_FreeVR_memory;
00410     vmd_realloc = NULL; // no realloc() functionality is available presently
00411 #else
00412     msgErr << "Not compiled with the FREEVR options set." << sendmsg;
00413     which_display = DISPLAY_WIN;    
00414 #endif
00415   }
00416 
00417   // return custom argc/argv
00418   *argc = customArgv.num();
00419   for (i=0; i<customArgv.num(); i++) {
00420     (*argv)[i] = customArgv[i];
00421   }
00422 
00423   PROFILE_POP_RANGE();
00424 
00425   return 1; // successful startup
00426 }
00427 
00428 const char *VMDgetDisplayTypeName() {
00429   return displayTypeNames[which_display];
00430 }
00431 
00432 void VMDgetDisplayFrame(int *loc, int *size) {
00433   for (int i=0; i<2; i++) {
00434     loc[i] = displayLoc[i];
00435     size[i] = displaySize[i];
00436   }
00437 }
00438 
00439 void VMDshutdown(int mpienabled) {
00440   vmd_finalize_tcl();  // after all VMDApp instances are deleted
00441 
00442 #ifdef VMDCAVE
00443   if (DISPLAY_USES_CAVE(which_display)) {  // call the CAVE specific exit
00444     CAVEExit();
00445   }
00446 #endif
00447 #ifdef VMDFREEVR
00448   if (DISPLAY_USES_FREEVR(which_display)) {  // call the FreeVR specific exit
00449     vrExit();
00450   }
00451 #endif
00452 #ifdef VMDMPI
00453   if (mpienabled) {
00454     vmd_mpi_fini();
00455   }
00456 #endif
00457 }
00458 
00459 static void VMDtitle() {
00460   msgInfo << VERSION_MSG << "\n";
00461   msgInfo << "http://www.ks.uiuc.edu/Research/vmd/                         \n";
00462   msgInfo << "Email questions and bug reports to vmd@ks.uiuc.edu           \n";
00463   msgInfo << "Please include this reference in published work using VMD:   \n";
00464   msgInfo << "   Humphrey, W., Dalke, A. and Schulten, K., `VMD - Visual   \n";
00465   msgInfo << "   Molecular Dynamics', J. Molec. Graphics 1996, 14.1, 33-38.\n";
00466   msgInfo << "-------------------------------------------------------------\n";
00467   msgInfo << sendmsg;
00468 }
00469 
00471 
00472 // look for all environment variables VMD can use, and initialize the
00473 // proper variables.  If an env variable is not found, use a default value.
00474 // ENVIRONMENT VARIABLES USED BY VMD (default values set in config.h):
00475 //      VMDDIR          directory with VMD data files and utility programs
00476 //      VMDTMPDIR       directory in which to put temporary files (def: /tmp)
00477 static void VMDGetOptions(int argc, char **argv, int mpienabled) {
00478   char *envtxt;
00479 
00480   //
00481   // VMDDISPLAYDEVICE: which display device to use by default
00482   // 
00483   if((envtxt = getenv("VMDDISPLAYDEVICE"))) {
00484     for(int i=0; i < NUM_DISPLAY_TYPES; i++) {
00485       if(!strupcmp(envtxt, displayTypeNames[i])) {
00486         which_display = i;
00487         break;
00488       }
00489     }
00490   }
00491 
00492   // 
00493   // VMDTITLE: whether to enable the title screen
00494   //  
00495   if((envtxt = getenv("VMDTITLE"))) {
00496     for(int i=0; i < NUM_TITLE_TYPES; i++) {
00497       if(!strupcmp(envtxt, titleTypeNames[i])) {
00498         showTitle = i;
00499         break;
00500       }
00501     }
00502   }
00503 
00504   //
00505   // VMDSCRHEIGHT: height of the screen
00506   //
00507   if((envtxt = getenv("VMDSCRHEIGHT")))
00508     displayHeight = (float) atof(envtxt);
00509 
00510   //
00511   // VMDSCRDIST: distance to the screen
00512   //
00513   if((envtxt = getenv("VMDSCRDIST")))
00514     displayDist = (float) atof(envtxt); 
00515 
00516   // 
00517   // VMDSCRPOS: graphics window location
00518   //
00519   if((envtxt = getenv("VMDSCRPOS"))) {
00520     char * dispStr = NULL;
00521     char * dispArgv[64];
00522     int dispArgc;
00523 
00524     if((dispStr = str_tokenize(envtxt, &dispArgc, dispArgv)) != NULL
00525                 && dispArgc == 2) {
00526       displayLoc[0] = atoi(dispArgv[0]);
00527       displayLoc[1] = atoi(dispArgv[1]);
00528     } else {
00529       msgErr << "Illegal VMDSCRPOS environment variable setting '" 
00530              << envtxt << "'." << sendmsg;
00531     }
00532     if(dispStr)  delete [] dispStr;
00533   }
00534 
00535   // 
00536   // VMDSCRSIZE: graphics window size
00537   //
00538   if((envtxt = getenv("VMDSCRSIZE"))) {
00539     char * dispStr = NULL;
00540     char * dispArgv[64];
00541     int dispArgc;
00542     if((dispStr = str_tokenize(envtxt, &dispArgc, dispArgv)) != NULL
00543                 && dispArgc == 2) {
00544       displaySize[0] = atoi(dispArgv[0]);
00545       displaySize[1] = atoi(dispArgv[1]);
00546  
00547       // force users to do something that makes sense
00548       if (displaySize[0] < 100) 
00549         displaySize[0] = 100; // minimum sane width
00550       if (displaySize[1] < 100) 
00551         displaySize[1] = 100; // minimum sane height
00552 
00553     } else {
00554       msgErr << "Illegal VMDSCRSIZE environment variable setting '" 
00555              << envtxt << "'." << sendmsg;
00556     }
00557     if(dispStr)  delete [] dispStr;
00558   }
00559 
00560   // initialize variables which indicate how VMD starts up, and
00561   // parse the command-line options
00562 
00563   // go through the arguments
00564   int ev = 1;
00565   while(ev < argc) {
00566     if(!strupcmp(argv[ev], "-dist")) {
00567       if(argc > (ev + 1)) {
00568         displayDist = (float) atof(argv[++ev]);
00569       } else
00570         msgErr << "-dist must also specify a distance." << sendmsg;
00571 
00572     } else if(!strupcmp(argv[ev], "-e")) {
00573       if(argc > (ev + 1)) {
00574         beginCmdFile = argv[++ev];
00575       } else
00576         msgErr << "-e must also specify a filename." << sendmsg;
00577 
00578     } else if(!strupcmp(argv[ev], "-height")) {
00579       if(argc > (ev + 1)) {
00580         displayHeight = (float) atof(argv[++ev]);
00581       } else
00582         msgErr << "-height must also specify a distance." << sendmsg;
00583 
00584     } else if(!strupcmp(argv[ev], "-pos")) {
00585       if(argc > (ev + 2) && *(argv[ev+1]) != '-' && *(argv[ev+2]) != '-') {
00586         displayLoc[0] = atoi(argv[++ev]);
00587         displayLoc[1] = atoi(argv[++ev]);
00588       } else
00589         msgErr << "-pos must also specify an X Y pair." << sendmsg;
00590 
00591     } else if(!strupcmp(argv[ev], "-size")) {
00592       if(argc > (ev + 2) && *(argv[ev+1]) != '-' && *(argv[ev+2]) != '-') {
00593         displaySize[0] = atoi(argv[++ev]);
00594         displaySize[1] = atoi(argv[++ev]);
00595       } else
00596         msgErr << "-size must also specify an X Y pair." << sendmsg;
00597 
00598     } else if(!strupcmp(argv[ev], "-startup")) {
00599       // use next argument as startup config file name
00600       if(argc > (ev + 1))
00601         startupFileStr = argv[++ev];
00602       else
00603         msgErr << "-startup must also have a new file name specified."
00604                << sendmsg;
00605 
00606     } else if(!strupcmp(argv[ev], "-nt")) {
00607       // do not print out the program title
00608       showTitle = TITLE_OFF;
00609 
00610     } else if (!strupcmp(argv[ev], "-dispdev")) {  // startup Display
00611       ev++;
00612       if (argc > ev) {
00613         if (!strupcmp(argv[ev], "cave")) {  
00614           which_display = DISPLAY_CAVE;        // use the CAVE
00615         } else if (!strupcmp(argv[ev], "win")) {       
00616           which_display = DISPLAY_WIN;         // use OpenGL, the default
00617         } else if (!strupcmp(argv[ev], "opengl")) {  
00618           which_display = DISPLAY_WINOGL;      // use OpenGL if available
00619         } else if (!strupcmp(argv[ev], "openglpbuffer")) {  
00620           which_display = DISPLAY_OGLPBUFFER;  // use OpenGLPbuffer if available
00621         } else if (!strupcmp(argv[ev], "text")) {
00622           which_display = DISPLAY_TEXT;        // use text console only 
00623         } else if (!strupcmp(argv[ev], "caveforms")) {
00624           which_display = DISPLAY_CAVEFORMS;   // use CAVE+Forms
00625         } else if (!strupcmp(argv[ev], "freevr")) {
00626           which_display = DISPLAY_FREEVR;      // use FreeVR
00627         } else if (!strupcmp(argv[ev], "freevrforms")) {
00628           which_display = DISPLAY_FREEVRFORMS; // use FreeVR+Forms
00629         } else if (!strupcmp(argv[ev], "none")) {      
00630           which_display = DISPLAY_TEXT;        // use text console only
00631         } else {
00632           msgErr << "-dispdev options are 'win' 'opengl' (default), 'openglpbuffer', 'cave', 'caveforms', 'freevr', 'freevrforms', or 'text | none'" << sendmsg;
00633         }
00634       } else {
00635         msgErr << "-dispdev options are 'win' 'opengl' (default), 'openglpbuffer', 'cave', 'caveforms', 'freevr', 'freevrforms', or 'text | none'" << sendmsg;
00636       }
00637     } else if (!strupcmp(argv[ev], "-h") || !strupcmp(argv[ev], "--help")) {
00638       // print out command-line option summary
00639       msgInfo << "Available command-line options:" << sendmsg;
00640       msgInfo << "\t-dispdev <win | cave | text | none> Specify display device";
00641       msgInfo << sendmsg;
00642       msgInfo << "\t-dist <d>           Distance from origin to screen";
00643       msgInfo << sendmsg;
00644       msgInfo << "\t-e <filename>       Execute commands in <filename>\n";
00645       msgInfo << "\t-python             Use Python for -e file and subsequent text input\n";
00646       msgInfo << "\t-eofexit            Exit when end-of-file occurs on input\n";
00647       msgInfo << "\t-h | --help         Display this command-line summary\n";
00648       msgInfo << "\t-height <h>         Height of display screen";
00649       msgInfo << sendmsg;
00650       msgInfo << "\t-pos <X> <Y>        Lower-left corner position of display";
00651       msgInfo << sendmsg;
00652       msgInfo << "\t-nt                 No title display at start" << sendmsg;
00653       msgInfo << "\t-size <X> <Y>       Size of display" << sendmsg;
00654       msgInfo << "\t-startup <filename> Specify startup script file" << sendmsg;
00655       msgInfo << "\t-m                  Load subsequent files as separate molecules\n";
00656       msgInfo << "\t-f                  Load subsequent files into the same molecule\n";
00657       msgInfo << "\t<filename>          Load file using best-guess file type\n";
00658       msgInfo << "\t-<type> <filename>  Load file using specified file type\n";
00659       msgInfo << "\t-args               Pass subsequent arguments to text interpreter\n";
00660       msgInfo << sendmsg;
00661       just_print_help = 1;
00662     } else if (!strupcmp(argv[ev], "-eofexit")) {  // exit on EOF
00663       eofexit = 1;
00664     } else if (!strupcmp(argv[ev], "-node")) { 
00665       // start VMD process on a cluster node, next parm is node ID..
00666       ev++; // skip node ID parm
00667     } else if (!strupcmp(argv[ev], "-webhelper")) { 
00668       // Unix startup script doesn't run VMD in the background, so that
00669       // web browsers won't delete files out from under us until it really
00670       // exits.  We don't do anything special inside VMD itself presently
00671       // however.
00672     } else if (!strupcmp(argv[ev], "-python")) {
00673       cmdFileUsesPython = 1;
00674     } else if (!strupcmp(argv[ev], "-args")) {
00675       // pass the rest of the command line arguments, and only those, 
00676       // to the embedded text interpreters.
00677       while (++ev < argc)
00678         customArgv.append(argv[ev]);
00679 
00680     } else if (!strupcmp(argv[ev], "-m")) {
00681       loadAsMolecules = 1;
00682       startNewMolecule = 1;
00683     } else if (!strupcmp(argv[ev], "-f")) {
00684       loadAsMolecules = 0;
00685       startNewMolecule = 1;
00686 #ifdef VMDMPI
00687     } else if (mpienabled && !strupcmp(argv[ev], "-vmddir")) {
00688       ev++; // skip VMDDIR directory parm, since we already handled this
00689             // in MPI startup before we got to this loop...
00690 #endif
00691     } else {
00692       // any other argument is treated either as a filename or as a 
00693       // filetype/filename pair of the form -filetype filename.
00694       const char *filename, *filetype;
00695       if (argv[ev][0] == '-') {
00696         // must be filetype/filename pair
00697         if (argc > ev+1) {
00698           filetype = argv[ev]+1;
00699           filename = argv[ev+1];
00700           ev++;
00701         } else {
00702           msgErr << "filetype argument '" << argv[ev] << "' needs a filename."
00703             << sendmsg;
00704           ev++;  // because we skip past the ev++ at the bottom of the loop.
00705           continue; 
00706         }
00707       } else {
00708         // Given just a filename.  The filetype will have to be guessed.
00709         filename = argv[ev];
00710         filetype = NULL;
00711       }
00712       initFilenames.append(filename);
00713       initFiletypes.append(filetype);
00714       startNewMoleculeFlags.append(startNewMolecule);
00715       if (!loadAsMolecules) startNewMolecule = 0;
00716     }
00717     ev++;
00718   }
00719 
00720   // command-line options have been parsed ... any init status variables that
00721   // have been given initial values will have flags saying so, and their
00722   // values will not be changed when the init file(s) is parsed.
00723 }
00724 
00725 static int parseColorDefs(const char *path, VMDApp *app) {
00726   FILE *fd = fopen(path, "rt");
00727   char buf[256];
00728   memset(buf, 0, sizeof(buf));
00729 
00730   int success = TRUE;
00731 
00732   if (!fd) {
00733     msgErr << "Color definitions file '" << path << "' does not exist." << sendmsg;
00734     return FALSE;
00735   }
00736   while (fgets(buf, sizeof(buf), fd)) {
00737     if (buf[0] == '\0' || buf[0] == '#') continue;
00738     char first[128], second[128], third[128], fourth[128];
00739     memset(first, 0, sizeof(first));
00740     memset(second, 0, sizeof(second));
00741     memset(third, 0, sizeof(third));
00742     memset(fourth, 0, sizeof(fourth));
00743 
00744     // handle cases like "Structure {Alpha Helix} purple
00745     int rc = sscanf(buf, "%s { %s %s %s", first, second, third, fourth);
00746     if (rc == 4) {
00747       char *right = strchr(third, '}');
00748       if (right) *right = '\0';
00749       strcat(second, " ");
00750       strcat(second, third);
00751       if (!app->color_add_item(first, second, fourth)) {
00752         msgErr << "Failed to add color definition: '" << buf << "'" << sendmsg;
00753         success = FALSE;
00754       }
00755     } else if (sscanf(buf, "%s %s %s", first, second, third) == 3) {
00756       if (!app->color_add_item(first, second, third)) {
00757         msgErr << "Failed to add color definition: '" << buf << "'" << sendmsg;
00758         success = FALSE;
00759       }
00760     }
00761   }
00762   fclose(fd);
00763   return success;
00764 }
00765 
00766 static int parseMaterialDefs(const char *path, VMDApp *app) {
00767   FILE *fd = fopen(path, "rt");
00768   char buf[256] = { 0 };
00769   int success = TRUE;
00770 
00771   if (!fd) {
00772     msgErr << "Material definitions file '" << path << "' does not exist." << sendmsg;
00773     return FALSE;
00774   }
00775   while (fgets(buf, sizeof(buf), fd)) {
00776     if (buf[0] == '\0' || buf[0] == '#') continue;
00777     char name[100] = { 0 };
00778     float vals[10] = { 0 };
00779     int readcount;
00780 
00781     memset(vals, 0, sizeof(vals));
00782     readcount=sscanf(buf, "%s %f %f %f %f %f %f %f %f %f", 
00783                      name, vals, vals+1, vals+2, vals+3, vals+4, 
00784                      vals+5, vals+6, vals+7, vals+8);
00785     if ((readcount < 7) || (readcount > 10))
00786       continue; // skip bad material
00787 
00788     if (!app->material_add(name, NULL)) {
00789       msgErr << "Failed to add material '" << name << "'" << sendmsg;
00790       success = FALSE;
00791       continue;
00792     }
00793     app->material_change(name, MAT_AMBIENT, vals[0]);
00794     app->material_change(name, MAT_DIFFUSE, vals[1]);
00795     app->material_change(name, MAT_SPECULAR, vals[2]);
00796     app->material_change(name, MAT_SHININESS, vals[3]);
00797     app->material_change(name, MAT_MIRROR, vals[4]);
00798     app->material_change(name, MAT_OPACITY, vals[5]);
00799     app->material_change(name, MAT_OUTLINE, vals[6]);
00800     app->material_change(name, MAT_OUTLINEWIDTH, vals[7]);
00801     app->material_change(name, MAT_TRANSMODE, vals[8]);
00802   }
00803   fclose(fd);
00804   return success;
00805 }
00806 
00807 static int parseRestypes(const char *path, VMDApp *app) {
00808   FILE *fd = fopen(path, "rt");
00809   char buf[256];
00810   memset(buf, 0, sizeof(buf));
00811   int success = TRUE;
00812 
00813   if (!fd) {
00814     msgErr << "Residue types file '" << path << "' does not exist." << sendmsg;
00815     return FALSE;
00816   }
00817   while (fgets(buf, sizeof(buf), fd)) {
00818     if (buf[0] == '\0' || buf[0] == '#') continue;
00819     char name[64], type[64];
00820     memset(name, 0, sizeof(name));
00821     memset(type, 0, sizeof(type));
00822 
00823     if (sscanf(buf, "%s %s", name, type) != 2) continue;
00824 
00825     if (!app->color_set_restype(name, type)) {
00826       msgErr << "Failed to add residue type '" << buf << "'" << sendmsg;
00827       success = FALSE;
00828     }
00829   }
00830   fclose(fd);
00831   return success;
00832 }
00833 
00834 static int parseAtomselMacros(const char *path, VMDApp *app) {
00835   char buf[256];
00836   memset(buf, 0, sizeof(buf));
00837 
00838   FILE *fd = fopen(path, "rt");
00839   if (!fd) {
00840     msgErr << "Atomselection macro file '" << path << "' does not exist." << sendmsg;
00841     return FALSE;
00842   }
00843   int success= TRUE;
00844   while (fgets(buf, sizeof(buf), fd)) {
00845     if (buf[0] == '\0' || buf[0] == '#' || isspace(buf[0])) continue;
00846     char *macro = strchr(buf, ' ');
00847     if (!macro) continue;
00848     *macro = '\0';
00849     macro++;
00850 
00851     // Remove trailing newline characters
00852     macro[strcspn(macro, "\r\n")] = 0;
00853 
00854     if (!app->atomSelParser->add_custom_singleword(buf, macro)) {
00855       msgErr << "Failed to add macro '" << buf << "'" << sendmsg;
00856       success = FALSE;
00857     }
00858   }
00859   fclose(fd);
00860   return success;
00861 }
00862 
00863 // Read scripts in scripts/vmd
00864 void VMDreadInit(VMDApp *app) {
00865   char path[4096];
00866   
00867   const char *vmddir = getenv("VMDDIR"); 
00868   if (vmddir == NULL) {
00869     msgErr << "VMDDIR undefined, startup failure likely." << sendmsg;
00870 #if defined(_MSC_VER)
00871     vmddir = "c:/program files/university of illinois/vmd";
00872 #else
00873     vmddir = "/usr/local/lib/vmd";
00874 #endif
00875   } 
00876   sprintf(path, "%s/scripts/vmd/colordefs.dat", vmddir);
00877   if (!parseColorDefs(path, app)) {
00878     msgErr << "Parsing color definitions failed." << sendmsg;
00879   }
00880   sprintf(path, "%s/scripts/vmd/materials.dat", vmddir);
00881   if (!parseMaterialDefs(path, app)) {
00882     msgErr << "Parsing material definitions failed." << sendmsg;
00883   }
00884   sprintf(path, "%s/scripts/vmd/restypes.dat", vmddir);
00885   if (!parseRestypes(path, app)) {
00886     msgErr << "Parsing residue types failed." << sendmsg;
00887   }
00888   sprintf(path, "%s/scripts/vmd/atomselmacros.dat", vmddir);
00889   if (!parseAtomselMacros(path, app)) {
00890     msgErr << "Parsing atomselection macros failed." << sendmsg;
00891   }
00892 }
00893 
00894 // read in the startup script, execute it, and then execute any other commands
00895 // which might be necessary (i.e. to load any molecules at start)
00896 // This searches for the startup file in the following
00897 // places (and in this order), reading only the FIRST one found:
00898 //              1. Current directory
00899 //              2. Home directory
00900 //              3. 'Default' directory (here, /usr/local/vmd)
00901 // If a name was given in the -startup switch, that file is checked for ONLY.
00902 void VMDreadStartup(VMDApp *app) {
00903   char namebuf[512] = { 0 };
00904   char *envtxt;
00905   int found = FALSE;
00906   FILE * tfp;
00907   char *DataPath; // path of last resort to find a .vmdrc file
00908 
00909   // These options were set by environment variables or command line options
00910   app->display_set_screen_height(displayHeight);
00911   app->display_set_screen_distance(displayDist);
00912   app->set_eofexit(eofexit);
00913   if (showTitle == TITLE_ON && (which_display != DISPLAY_TEXT) && 
00914       (which_display != DISPLAY_OGLPBUFFER)) {
00915     app->display_titlescreen();
00916   }
00917 
00918   if ((envtxt = getenv("VMDDIR")) != NULL)
00919     DataPath = stringdup(envtxt);
00920   else
00921     DataPath = stringdup(DEF_VMDENVVAR);
00922   stripslashes(DataPath); // strip out ending '/' chars.
00923 
00924   // check if the file is available
00925   if (startupFileStr) { // name specified by -startup
00926     if ((tfp = fopen(startupFileStr, "rb")) != NULL) {
00927       found = TRUE;
00928       fclose(tfp);
00929       strcpy(namebuf, startupFileStr);
00930     }
00931   } else {      // search in different directories, for default file
00932     const char *def_startup = VMD_STARTUP;
00933     // first, look in current dir
00934     strcpy(namebuf, def_startup);
00935     if ((tfp = fopen(namebuf, "rb")) != NULL) {
00936       found = TRUE;
00937       fclose(tfp);
00938     } else {
00939       // not found in current dir; look in home dir
00940       if ((envtxt = getenv("HOME")) != NULL)
00941         strcpy(namebuf, envtxt);
00942       else
00943         strcpy(namebuf, ".");
00944       strcat(namebuf, "/");
00945       strcat(namebuf, def_startup);
00946       if ((tfp = fopen(namebuf, "rb")) != NULL) {
00947         found = TRUE;
00948         fclose(tfp);
00949       } else {
00950         // not found in home dir; look in default dir
00951         strcpy(namebuf, DataPath);
00952         strcat(namebuf, "/");
00953         strcat(namebuf, def_startup);
00954         if ((tfp = fopen(namebuf, "rb")) != NULL) {
00955           found = TRUE;
00956           fclose(tfp);
00957         }
00958       }
00959     }
00960   }
00961   delete [] DataPath; DataPath = NULL;
00962 
00963   //
00964   // execute any commands needed at start
00965   //
00966   
00967   PROFILE_PUSH_RANGE("VMDreadStartup(): process cmd args", 4);
00968 
00969   // read in molecules requested via command-line switches
00970   FileSpec spec;
00971   spec.waitfor = -1; // wait for all files to load before proceeding
00972   int molid = -1;    // set sentinel value to determine if files were loaded
00973 
00974   if (startNewMoleculeFlags.num() > 0) {
00975     msgInfo << "File loading in progress, please wait." << sendmsg;
00976   }
00977 
00978   for (int i=0; i<startNewMoleculeFlags.num(); i++) {
00979     const char *filename = initFilenames[i];
00980     const char *filetype = initFiletypes[i];
00981     if (!filetype) {
00982       filetype = app->guess_filetype(filename);
00983       if (!filetype) {
00984         // assume pdb 
00985         msgErr << "Unable to determine file type for file '"
00986           << filename << "'.  Assuming pdb." << sendmsg;
00987         filetype = "pdb";
00988       }
00989     }
00990     if (startNewMoleculeFlags[i]) {
00991       molid = app->molecule_load(-1, filename, filetype, &spec);
00992     } else {
00993       molid = app->molecule_load(molid, filename, filetype, &spec);
00994     }
00995     if (molid < 0) {
00996       msgErr  << "Loading of startup molecule files aborted." << sendmsg;
00997       break;
00998     }
00999   }
01000 
01001   PROFILE_POP_RANGE();
01002   PROFILE_PUSH_RANGE("VMDreadStartup(): process " VMD_STARTUP, 3);
01003 
01004   // if the startup file was found, read in the text commands there
01005   if (found) {
01006     app->logfile_read(namebuf);
01007   }
01008 
01009   PROFILE_POP_RANGE();
01010   PROFILE_PUSH_RANGE("VMDreadStartup(): load plugins", 5);
01011 
01012   // Load the extension packages here, _after_ reading the .vmdrc file,
01013   // so that the search path for extensions can be customized.
01014   app->commandQueue->runcommand(
01015     new TclEvalEvent("vmd_load_extension_packages"));   
01016   
01017   PROFILE_POP_RANGE();
01018   PROFILE_PUSH_RANGE("VMDreadStartup(): start Python", 1);
01019 
01020   // Switch to Python if requested, before reading beginCmdFile
01021   if (cmdFileUsesPython) {
01022     if (!app->textinterp_change("python")) {
01023       // bail out since Python scripts won't be readable by Tcl.
01024       msgErr << "Skipping startup script because Python could not be started." 
01025              << sendmsg;
01026       return;
01027     }
01028   }
01029 
01030   PROFILE_POP_RANGE();
01031   PROFILE_PUSH_RANGE("VMDreadStartup(): process cmd scripts", 1);
01032 
01033   // after reading in startup file and loading any molecule, the file
01034   // specified by the -e option is set up to be executed.  
01035   if (beginCmdFile) {
01036     app->logfile_read(beginCmdFile);
01037   } 
01038 
01039   PROFILE_POP_RANGE();
01040 }
01041 

Generated on Fri Oct 4 02:45:10 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002