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

Generated on Sat Aug 30 01:27:08 2008 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002