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

vmd.C

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

Generated on Sat May 26 01:48:33 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002