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 Mon Nov 17 02:47:20 2025 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002

AltStyle によって変換されたページ (->オリジナル) /