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

VMDApp.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  * RCS INFORMATION:
00010  *
00011  *      $RCSfile: VMDApp.C,v $
00012  *      $Author: johns $        $Locker:  $             $State: Exp $
00013  *      $Revision: 1.496 $      $Date: 2012/04/11 19:36:44 $
00014  *
00015  ***************************************************************************/
00016  
00017 #include <stdlib.h>
00018 #include <string.h>
00019 #include <signal.h>
00020 #include <sys/types.h>
00021 #include <sys/stat.h>
00022 #include <ctype.h> // for isalnum()
00023 
00024 #include "VMDDisplayList.h"
00025 #include "CoorPluginData.h"
00026 #include "PluginMgr.h"
00027 #include "MolFilePlugin.h"
00028 #include "Matrix4.h"
00029 #include "config.h"
00030 #include "Inform.h"
00031 #include "AtomSel.h"
00032 #include "VMDTitle.h"
00033 #include "DisplayDevice.h"
00034 #include "PickList.h"
00035 #include "PickModeList.h"
00036 #include "MaterialList.h"
00037 #include "Scene.h"
00038 #include "CommandQueue.h"
00039 #include "UIText.h"
00040 #include "Stage.h"
00041 #include "Axes.h"
00042 #include "DisplayRocker.h"
00043 #include "FPS.h"
00044 #include "MoleculeList.h"
00045 #include "Mouse.h"
00046 #include "MobileInterface.h"
00047 #include "Spaceball.h"
00048 #ifdef WIN32
00049 #include "Win32Joystick.h"
00050 #endif
00051 #include "GeometryList.h"
00052 #include "FileRenderer.h"
00053 #include "FileRenderList.h"
00054 #include "CmdAnimate.h"
00055 #include "CmdMol.h"
00056 #include "CmdMaterial.h"
00057 #include "CmdPlugin.h"
00058 #include "CmdRender.h"   // to log the render commands we execute
00059 #include "CmdTrans.h"
00060 #include "CmdDisplay.h"
00061 #include "CmdColor.h"
00062 #include "CmdLabel.h"
00063 #include "TextEvent.h"
00064 #include "CmdMenu.h"
00065 #include "P_UIVR.h"
00066 #include "P_CmdTool.h"
00067 #include "SymbolTable.h"
00068 #include "VMDCollab.h"
00069 #include "QMData.h"
00070 #include "Orbital.h"
00071 
00072 #include "CUDAAccel.h"
00073 #if defined(VMDOPENCL)
00074 #include "OpenCLUtils.h"
00075 #endif
00076 
00077 #if defined(VMDTHREADS) // System-specific threads code
00078 #include "WKFThreads.h"
00079 #endif
00080 
00081 #ifdef MACVMD
00082 #include "MacVMDDisplayDevice.h"
00083 #endif
00084 
00085 #ifdef VMDOPENGL        // OpenGL-specific files
00086 #if defined(VMDFLTKOPENGL)
00087 #include "FltkOpenGLDisplayDevice.h"
00088 #else
00089 #ifndef MACVMD
00090 #include "OpenGLDisplayDevice.h"
00091 #endif
00092 #endif
00093 
00094 #ifdef VMDCAVE          // CAVE-specific files
00095 #include "cave_ogl.h"
00096 #include "CaveDisplayDevice.h"
00097 #include "CaveRoutines.h"
00098 #include "CaveScene.h"
00099 #endif // VMDCAVE
00100 #endif // VMDOPENGL
00101 
00102 #include "VMDMenu.h"
00103 #ifdef VMDFLTK         // If using FORMS GUI include FORMS-specific objects
00104 #include "FL/forms.H"
00105 
00106 // New Fltk menus 
00107 #include "MainFltkMenu.h"
00108 #include "ColorFltkMenu.h"
00109 #include "MaterialFltkMenu.h"
00110 #include "DisplayFltkMenu.h"
00111 #include "FileChooserFltkMenu.h"
00112 #include "SaveTrajectoryFltkMenu.h"
00113 #include "GeometryFltkMenu.h"
00114 #include "GraphicsFltkMenu.h"
00115 #include "RenderFltkMenu.h"
00116 #include "ToolFltkMenu.h"
00117 
00118 #endif // VMDFLTK
00119 
00120 #ifdef VMDIMD
00121 #include "IMDMgr.h"
00122 #include "CmdIMD.h"
00123 #endif
00124 
00125 // FreeVR conflicts with the FLTK include files, so include it _after_ FLTK.
00126 #ifdef VMDFREEVR     // FreeVR-specific files
00127 #include "freevr.h"
00128 #include "FreeVRDisplayDevice.h"
00129 #include "FreeVRRoutines.h"
00130 #include "FreeVRScene.h"
00131 #endif
00132 
00133 #if defined(VMDTKCON)
00134 #include "vmdconsole.h"
00135 #endif
00136 
00137 #ifdef VMDMPI
00138 #include "VMDMPI.h" 
00139 #endif
00140 
00141 #include "VMDApp.h"
00142 
00143 // default atom selection
00144 #define DEFAULT_ATOMSEL "all"
00145 
00146 // XXX static data item
00147 static unsigned long repserialnum;
00148 static unsigned long texserialnum;
00149 
00150 // static initialization
00151 JString VMDApp::text_message;
00152 
00153 #if defined(VMDXPLOR)  
00154 VMDApp* VMDApp::obj = 0; 
00155 #endif
00156 
00157 VMDApp::VMDApp(int argc, char **argv) {
00158 #if defined(VMDXPLOR)  
00159   if (!obj) obj = this; 
00160 #endif
00161 
00162   // initialize ALL member variables
00163   argc_m = argc;
00164   argv_m = (const char **)argv;
00165   menulist = NULL;
00166   nextMolID = 0; 
00167   stride_firsttime = 1;
00168   eofexit = 0;
00169   mouse = NULL;
00170   spaceball = NULL;
00171 #ifdef WIN32
00172   win32joystick = NULL;
00173 #endif
00174   vmdTitle = NULL; 
00175   fileRenderList = NULL;
00176   pluginMgr = NULL;
00177   uiText = NULL;
00178   uivr = NULL;
00179 #ifdef VMDIMD
00180   imdMgr = NULL;
00181 #endif
00182   display = NULL;
00183   scene = NULL;
00184   pickList = NULL;
00185   pickModeList = NULL;
00186   materialList = NULL;
00187   stage = NULL;
00188   axes = NULL;
00189   fps = NULL;
00190   commandQueue = NULL;
00191   moleculeList = NULL;
00192   geometryList = NULL;
00193   atomSelParser = NULL;
00194   anim = NULL;
00195   vmdcollab = NULL;
00196   cuda = NULL;
00197   strcpy(nodename, "");
00198   noderank  = 0; // init with MPI values later
00199   nodecount = 1; // init with MPI values later
00200 
00201   UpdateDisplay = TRUE;
00202   exitFlag = TRUE;
00203   ResetViewPending = FALSE;
00204 
00205   background_processing_clear();
00206 
00207   highlighted_molid  = highlighted_rep = -1;
00208 }
00209 
00210 // initialization routine for the library globals
00211 int VMDApp::VMDinit(int argc, char **argv, const char *displaytype, 
00212                     int *displayLoc, int *displaySize) {
00213 #if defined(VMDCUDA)
00214   // register all usable CUDA GPU accelerator devices
00215   cuda = new CUDAAccel();
00216 #endif
00217 
00218 #if defined(VMDMPI)
00219   // initialize MPI node info and print output here
00220   vmd_mpi_nodescan(&noderank, &nodecount, 
00221                    nodename, sizeof(nodename), 
00222                    (cuda != NULL) ? cuda->num_devices() : 0);
00223 #endif
00224 
00225   // only emit detailed GPU enumeration data if we're running on a single node
00226   if (nodecount == 1) {
00227 #if defined(VMDCUDA)
00228     cuda->print_cuda_devices();
00229 #endif
00230 #if defined(VMDOPENCL)
00231     vmd_cl_print_platform_info();
00232 #endif
00233   }
00234 
00235   //
00236   // create commandQueue before all UIObjects!
00237   //
00238   commandQueue = new CommandQueue(); 
00239 
00240   // XXX This is currently only used for 64-bit MacOS X builds using Cocoa...
00241   // XXX Francois-Xavier Coudert has noted that this code path also corrected
00242   //     startup crashes he had been having with 32-bit builds using MacOS X
00243   //     10.7.x using FLTK 1.3.0.  It remains to be seen how stable the GUI is
00244   //     for the 32-bit build when the Cocoa workaround is active.  It has not
00245   //     been very stable for 64-bit builds thus far.
00246 #if defined(ARCH_MACOSXX86_64)
00247   // Tcl/Tk _must_ be initialized before FLTK due to low-level implementation
00248   // details of Cocoa-based Tk and FLTK code required for 64-bit MacOS X.
00249   uiText = new UIText(this, strcmp(displaytype, "TEXT") != 0); // text user interface
00250 #endif
00251 
00252   // initialize the display
00253   int *dloc = (displayLoc[0]  > 0 ? displayLoc  : (int *) NULL);
00254 
00255   int dsiz[2] = { 512, 512 };
00256   if (displaySize && displaySize[0] > 0 && displaySize[1] > 0) {
00257     dsiz[0] = displaySize[0];
00258     dsiz[1] = displaySize[1];
00259   }
00260 
00261   // initialize static data items
00262   repserialnum = 0; // initialize the display list serial number
00263   texserialnum = 0; // initialize the texture list serial number
00264 
00265 #ifdef MACVMD
00266   display = new MacVMDDisplayDevice(this, dsiz);
00267 #endif
00268 
00269   // check for a standard monitor display
00270   if (!strcmp(displaytype, "WIN") || !strcmp(displaytype, "OPENGL")) {
00271 #if defined(VMDOPENGL)
00272 #if defined(VMDFLTKOPENGL)
00273     display = new FltkOpenGLDisplayDevice(argc, argv, this, dsiz, dloc);
00274 #else
00275     display = new OpenGLDisplayDevice;
00276     if (!display->init(argc, argv, this, dsiz, dloc)) {
00277       VMDexit("Unable to create OpenGL window.", 1, 7);
00278       return FALSE;
00279     } 
00280 #endif
00281 #endif
00282   }
00283 
00284 #ifdef VMDCAVE
00285   if (!strcmp(displaytype, "CAVE") || !strcmp(displaytype, "CAVEFORMS")) {
00286     // The CAVE scene is allocated from shared memory and can be 
00287     // accessed by all of the rendering processes by virtue of its
00288     // class-specific operator new.
00289     scene = new CaveScene(this);
00290     msgInfo << "Cave shared memory scene created." << sendmsg;
00291 
00292     // the CAVE display device is created in process-private memory
00293     display = new CaveDisplayDevice;
00294 
00295     // set up pointers for cave_renderer, needs to be done before forking.
00296     set_cave_pointers(scene, display);
00297 
00298     // XXX this may cure a problem with specular highlights in CAVElib
00299     // by default CAVElib messes with the OpenGL modelview matrix, this
00300     // option prevents it from doing so, which should allow specular 
00301     // highlights to look right on multiple walls, but it breaks depth cueing.
00302     // CAVESetOption(CAVE_PROJ_USEMODELVIEW, 0);
00303     CAVESetOption(CAVE_GL_SAMPLES, 8); // enable multisample antialiasing
00304     CAVEInit();                        // fork off the rendering processes
00305     CAVEDisplay(cave_renderer, 0);     // set the fctn ptr for the renderers
00306     display->renderer_process = 0;     // this proc is the master process
00307     vmd_set_cave_is_initialized();     // flag successfull CAVE init
00308     msgInfo << "CAVE Initialized" << sendmsg;
00309   }
00310 #endif
00311 
00312 #ifdef VMDFREEVR
00313   if (!strcmp(displaytype, "FREEVR") || !strcmp(displaytype, "FREEVRFORMS")) {
00314     // The FreeVR scene is allocated from shared memory and can be 
00315     // accessed by all of the rendering processes by virtue of its
00316     // class-specific operator new.
00317     scene = new FreeVRScene(this);
00318     msgInfo << "FreeVR shared memory scene created." << sendmsg;
00319 
00320     // the FreeVR display device is created in process-private memory
00321     display = new FreeVRDisplayDevice;
00322 
00323     // set up pointers for freevr_renderer, needs to be done before forking.
00324     set_freevr_pointers(scene, display);
00325 
00326     // set the function pointer for the per-screen renderers
00327     vrFunctionSetCallback(VRFUNC_ALL_DISPLAY, vrCallbackCreate(freevr_renderer, 1, &display));  
00328     vrStart();                         // fork off the rendering processes
00329     display->renderer_process = 0;     // this proc is the master process
00330     msgInfo << "FreeVR Initialized" << sendmsg;
00331   }
00332 #endif
00333 
00334   // If no scene object has been created yet (e.g. CAVE/FreeVR), create one.
00335   if (!scene) {
00336     scene = new Scene;
00337   }
00338 
00339   // If a real display doesn't exist, create a stub display that eats commands
00340   if (!display) {
00341     display = new DisplayDevice("Default Display");
00342     display->resize_window(dsiz[0], dsiz[1]);
00343   }
00344 
00345   // print any useful informational messages now that the display is setup
00346   if (display->get_num_processes() > 1) {
00347     msgInfo << "Started " << display->get_num_processes() 
00348             << " slave rendering processes." << sendmsg;
00349   }
00350 
00351   //
00352   // create other global objects for the program
00353   //
00354 
00355   rocker = new DisplayRocker(&(scene->root));
00356 
00357   pluginMgr = new PluginMgr;
00358 
00359   atomSelParser = new SymbolTable;
00360   atomSelParser_init(atomSelParser);
00361 
00362   pickModeList = new PickModeList(this);
00363   pickList = new PickList(this);
00364 
00365   // create material list
00366   materialList = new MaterialList(&scene->root);
00367 
00368   // create other useful graphics objects
00369   axes = new Axes(display, &(scene->root));
00370   pickList->add_pickable(axes);
00371   
00372   fps = new FPS(display, &(scene->root));
00373   fps->off();
00374 
00375   // create the list of molecules (initially empty)
00376   moleculeList = new MoleculeList(this, scene);
00377 
00378   anim = new Animation(this);
00379   anim->On();
00380 
00381   // create the list of geometry monitors (initially empty)
00382   geometryList = new GeometryList(this, &(scene->root));
00383 
00384   menulist = new NameList<VMDMenu *>;
00385 
00386   // If the text UI hasn't already been initialized then initialize it here.
00387   // Cocoa-based FLTK/Tk builds of VMD for 64-bit MacOS X must 
00388   // initialize Tcl/Tk first, so that FLTK works correctly.
00389   if (uiText == NULL)
00390     uiText = new UIText(this, display->supports_gui()); // text user interface
00391   uiText->On();
00392 
00393   mouse = new Mouse(this); // mouse user interface
00394   mouse->On();
00395 
00396   mobile = new Mobile(this); // Smartphone/tablet network input device
00397   mobile->On();
00398 
00399   spaceball = new Spaceball(this); // Spaceball 6DOF input device
00400   spaceball->On();
00401 
00402 #ifdef WIN32
00403   win32joystick = new Win32Joystick(this); // Win32 Joystick devices
00404   win32joystick->On();
00405 #endif
00406 
00407 #ifdef VMDIMD
00408   imdMgr = new IMDMgr(this);
00409   imdMgr->On();
00410 #endif
00411 
00412   stage = new Stage(&(scene->root));
00413   pickList->add_pickable(stage);
00414 
00415   vmdcollab = new VMDCollab(this);
00416   vmdcollab->On();
00417 
00418   // make the classes which can render scenes to different file formats
00419   fileRenderList = new FileRenderList(this);
00420 
00421   display->queue_events(); // begin accepting UI events in graphics window
00422 
00423   // Create the menus; XXX currently this must be done _before_ calling
00424   // uiText->read_init() because otherwise the new menus created by the 
00425   // plugins loaded by the iit script won't be added to the main menu.
00426   activate_menus();
00427   
00428   // XXX loading static plugins should be controlled by a startup option
00429   pluginMgr->load_static_plugins();
00430 
00431   // plugin_update must take place _after_ creation of uiText.
00432   plugin_update();
00433 
00434   VMDupdate(VMD_IGNORE_EVENTS); // flush cmd queue, prepare to enter event loop
00435 
00436   // Read the initialization code for the text interpreter.
00437   // We wait to do it now since that script might contain commands that use 
00438   // the event queue
00439   uiText->read_init();
00440 
00441   // If there's no text interpreter, show the main menu
00442 #ifndef VMDTCL
00443 #ifndef VMDPYTHON
00444   menu_show("main", 1);
00445 #endif
00446 #endif
00447   
00448   // successful initialization.  Turn off the exit flag return success
00449   exitFlag = FALSE;
00450   return TRUE;
00451 }
00452 
00453 int VMDApp::num_menus() { return menulist->num(); }
00454 
00455 int VMDApp::add_menu(VMDMenu *m) {
00456   if (menulist->typecode(m->get_name()) != -1) {
00457     msgErr << "Menu " << m->get_name() << " already exists." << sendmsg;
00458     return 0;  
00459   }
00460   menulist->add_name(m->get_name(), m);
00461   return 1;
00462 }
00463  
00464 int VMDApp::remove_menu(const char *name) {
00465   int id = menulist->typecode(name);
00466   if (id == -1) {
00467     msgErr << "Menu " << name << " does not exist." << sendmsg;
00468     return 0;  
00469   }
00470   NameList<VMDMenu *> *newmenulist = new NameList<VMDMenu *>;
00471   for (int i=0; i<menulist->num(); i++) {
00472     VMDMenu *menu = menulist->data(i);
00473     if (i == id) {
00474       delete menu;
00475     } else {
00476       newmenulist->add_name(menu->get_name(), menu);
00477     }
00478   }
00479   delete menulist;
00480   menulist = newmenulist;
00481   return 1;
00482 }
00483  
00484 void VMDApp::menu_add_extension(const char *shortname, const char *menu_path) {
00485   commandQueue->runcommand(new CmdMenuExtensionAdd(shortname,menu_path));
00486 }
00487 
00488 void VMDApp::menu_remove_extension(const char *shortname) {
00489   commandQueue->runcommand(new CmdMenuExtensionRemove(shortname));
00490 }
00491 
00492 const char *VMDApp::menu_name(int i) { return menulist->name(i); }
00493 
00494 int VMDApp::menu_status(const char *name) {
00495   int id = menulist->typecode(name);
00496   if (id == -1) return 0;
00497   return menulist->data(id)->active();
00498 }
00499 
00500 int VMDApp::menu_location(const char *name, int &x, int &y) {
00501   int id = menulist->typecode(name);
00502   if (id == -1) return 0;
00503   menulist->data(id)->where(x, y);
00504   return 1;
00505 }
00506 
00507 int VMDApp::menu_show(const char *name, int on) {
00508   int id = menulist->typecode(name);
00509   if (id == -1) return 0;
00510   VMDMenu *obj = menulist->data(name);
00511   if (on)
00512     obj->On();
00513   else
00514     obj->Off();
00515   commandQueue->runcommand(new CmdMenuShow(name, on));
00516   return 1;
00517 }
00518 
00519 int VMDApp::menu_move(const char *name, int x, int y) {
00520   int id = menulist->typecode(name);
00521   if (id == -1) return 0;
00522   menulist->data(id)->move(x, y);
00523   return 1;
00524 }
00525 
00526 
00527 int VMDApp::menu_select_mol(const char *name, int molno) {
00528   int id = menulist->typecode(name);
00529   if (id == -1) return 0;
00530   return menulist->data(id)->selectmol(molno);
00531 }
00532 
00533 
00534 // redraw the screen and update all things that need updating
00535 int VMDApp::VMDupdate(int check_for_events) {
00536   // clear background processing flag
00537   background_processing_clear();
00538 
00539   // see if there are any pending events; if so, get them
00540   if (check_for_events) {
00541     commandQueue->check_events();
00542 #ifdef VMDGUI
00543 #ifdef VMDFLTK
00544     // if we are using the FLTK library ...
00545     if (display->supports_gui()) {
00546 #if defined(ARCH_MACOSX) && defined(VMDTCL)
00547       // don't call wait(0) since this causes Tcl/Tk to mishandle events
00548       Fl::flush();
00549 #elif (defined(ARCH_MACOSXX86) || defined(ARCH_MACOSXX86_64)) && defined(VMDTCL)
00550       // starting with more recent revs of FLTK and Tcl/Tk, we should no
00551       // longer need to drop events
00552       Fl::wait(0);
00553 #else
00554       Fl::wait(0);
00555 #endif
00556     }
00557 #endif
00558 #endif
00559   } 
00560   
00561   // check if the user has requested to exit the program.
00562   if (exitFlag) 
00563     return FALSE;
00564  
00565   commandQueue->execute_all(); // execute commands still in the queue
00566 
00567   int needupdate = 0;
00568 #if 1
00569   // Only prepare objects if display update is enabled
00570   // XXX avoid N^2 behavior when loading thousdands of molecules, 
00571   // don't prepare for drawing unless we have to.
00572   if (UpdateDisplay) {
00573     // If a resetview is pending, take care of it now before drawing
00574     if (ResetViewPending) 
00575       scene_resetview_newmoldata();
00576 
00577     needupdate = scene->prepare(); // prepare all objects for drawing
00578   } else {
00579     // XXX this has to be done currently to force trajectories to continue
00580     //     loading frames since they don't have their own UIObject yet.
00581     int molnum = moleculeList->num();
00582     int i;
00583     for (i=0; i<molnum; i++) {
00584       Molecule *mol = moleculeList->molecule(i);
00585       if (mol != NULL) {
00586         if (mol->get_new_frames()) {
00587           needupdate = 1; // need to update if any new frames were loaded
00588         }
00589       }
00590     }
00591   }
00592 #else
00593   // XXX this has to be done currently to force trajectories to continue
00594   //     loading frames since they don't have their own UIObject yet.
00595   needupdate = scene->prepare(); // prepare all objects for drawing
00596 #endif
00597 
00598   // turn off the spinning vmd when molecules are loaded
00599   if (vmdTitle && moleculeList->num() > 0) {
00600     delete vmdTitle;
00601     vmdTitle = NULL;
00602   }
00603   
00604   // Update the display (or sleep a tiny bit).
00605   if (UpdateDisplay && (needupdate || display->needRedraw())) {
00606     scene->draw(display);   // make the display redraw if necessary
00607     scene->draw_finished(); // perform any necessary post-drawing cleanup
00608   } else {
00609     // if not updating the display or doing background I/O, 
00610     // we sleep so we don't hog CPU.
00611     if (!needupdate && !background_processing())
00612       vmd_msleep(1); // sleep for 1 millisecond or more
00613   }
00614 
00615   // XXX A hack to decrease CPU utilization on machines that have
00616   //     problems keeping up with the 3-D draw rate at full speed.
00617   if (getenv("VMDMSECDELAYHACK") != NULL) {
00618     // Delay the whole program for a user-specified number of milliseconds.  
00619     vmd_msleep(atoi(getenv("VMDMSECDELAYHACK"))); 
00620   }
00621 
00622   return TRUE;
00623 }
00624 
00625 
00626 // exit the program normally; first delete all the necessary objects
00627 void VMDApp::VMDexit(const char *exitmsg, int exitcode, int pauseseconds) {
00628 
00629 #if defined(VMDTKCON)
00630   // switch to text mode and flush all pending messages to the screen.
00631   vmdcon_use_text((void *)uiText->get_tcl_interp());
00632   vmdcon_purge();
00633 #endif
00634 
00635 #if defined(VMDMPI)
00636   fflush(stdout);
00637   vmd_mpi_barrier(); // wait for peers before printing final messages
00638   if (noderank == 0)
00639     vmd_msleep(250); // give peer output time to percolate to the console...
00640 #endif
00641 
00642   // only print exit status output on the first exit call
00643   if (exitFlag == 0 || (exitmsg != NULL && strlen(exitmsg))) {
00644     msgInfo << VERSION_MSG << sendmsg; 
00645     if (exitmsg && strlen(exitmsg)) {
00646       msgInfo << exitmsg << sendmsg;
00647     } else {
00648       msgInfo << "Exiting normally." << sendmsg;
00649     }
00650   }
00651 
00652   vmd_sleep(pauseseconds);  // sleep for requested number of seconds
00653 
00654   // make the VMDupdate event loop return FALSE.
00655   exitFlag = 1;
00656 }
00657 
00658 VMDApp::~VMDApp() {
00659   int i;
00660 
00661   // delete all objects we created during initialization
00662   if (fileRenderList) delete fileRenderList;
00663   if (mouse)          delete mouse;
00664   if (mobile)         delete mobile;
00665   if (spaceball)      delete spaceball;
00666 
00667 #ifdef WIN32
00668   if (win32joystick)  delete win32joystick;
00669 #endif
00670 
00671   if (uivr)           delete uivr;
00672   if (geometryList)   delete geometryList;
00673 
00674 #ifdef VMDIMD
00675   if (imdMgr)         delete imdMgr;
00676   imdMgr = NULL;      // prevent free mem reads at moleculeList deletion
00677 #endif
00678 
00679   if (vmdTitle)       delete vmdTitle;
00680   if (stage)          delete stage;
00681   if (axes)           delete axes;
00682   if (fps)            delete fps;
00683   if (pickModeList)   delete pickModeList;
00684   if (materialList)   delete materialList;
00685   if (pluginMgr)      delete pluginMgr;
00686   if (cuda)           delete cuda;
00687   delete vmdcollab;
00688 
00689   // delete all of the Forms;
00690   if (menulist) {
00691     for (i=0; i<menulist->num(); i++)
00692       delete menulist->data(i);
00693     delete menulist;
00694   }
00695 
00696 #ifdef VMDGUI
00697   // Close all GUI windows
00698 #ifdef VMDFLTK
00699   if (display->supports_gui()) {
00700     Fl::wait(0); // Give Fltk a chance to close the menu windows.  
00701   }
00702 #endif
00703 #endif
00704 
00705   // Tcl/Python interpreters can only be deleted after Tk forms are shutdown
00706   if (uiText)         delete uiText;
00707 
00708   // delete the list of user keys and descriptions 
00709   for (i=0; i<userKeys.num(); i++)
00710     delete [] userKeys.data(i);
00711 
00712   for (i=0; i<userKeyDesc.num(); i++)
00713     delete [] userKeyDesc.data(i);
00714 
00715   delete atomSelParser;
00716   delete anim;
00717 
00718   // delete commandQueue _after_ all UIObjects have been deleted; otherwise
00719   // they will try to unRegister with a deleted CommandQueue.
00720   delete commandQueue;
00721 
00722   // (these dependencies really suck) delete moleculelist after uiText
00723   // because text interfaces might use commands that require moleculeList to
00724   // be there.
00725   delete moleculeList;
00726 
00727   // picklist can't be deleted until the molecule is deleted, since
00728   // the DrawMolecule destructor needs it.
00729   delete pickList;
00730  
00731   delete display;
00732   delete scene;
00733 }
00734 
00735 unsigned long VMDApp::get_repserialnum(void) {
00736   // first serial number returned will be 1, never return 0.
00737   repserialnum++;
00738   return repserialnum;
00739 }
00740 
00741 unsigned long VMDApp::get_texserialnum(void) {
00742   // first serial number returned will be 1, never return 0.
00743   texserialnum++;
00744   return texserialnum;
00745 }
00746 
00747 void VMDApp::show_stride_message() {
00748   if (stride_firsttime) {
00749     stride_firsttime = 0;
00750     msgInfo <<
00751      "In any publication of scientific results based in part or\n"
00752      "completely on the use of the program STRIDE, please reference:\n"
00753      " Frishman,D & Argos,P. (1995) Knowledge-based secondary structure\n"
00754      " assignment. Proteins: structure, function and genetics, 23, 566-579." 
00755       << "\n" << sendmsg;
00756   }
00757 }
00758 
00759 // this is a nasty hack until we get around to returning values from scripts
00760 // properly.
00761 
00762 #ifdef VMDTK
00763 #include <tcl.h> 
00764 #endif
00765 
00766 char *VMDApp::vmd_choose_file(const char *title,
00767         const char *extension, 
00768         const char *extension_label, int do_save) {
00769   
00770  char *chooser = getenv("VMDFILECHOOSER");
00771  if (!chooser || !strupcmp(chooser, "TK")) {
00772     
00773 #ifdef VMDTK
00774   JString t = title;
00775   JString ext = extension;
00776   JString label = extension_label;
00777   char *cmd = new char[300 + t.length() +ext.length() + label.length()];
00778   // no default extension for for saves/loads , because otherwise it 
00779   // automatically adds the file extension whether you specify it or not, and 
00780   // when the extension is * it won't let you save/load a file without an 
00781   // extension!
00782   if (do_save) {
00783     sprintf(cmd, "tk_getSaveFile -title {%s} -filetypes {{{%s} {%s}} {{All files} {*}}}", (const char *)t, (const char *)extension_label, (const char *)extension);
00784   } else {
00785     sprintf(cmd, "tk_getOpenFile -title {%s} -filetypes {{{%s} {%s}} {{All files} {*}}}", (const char *)t, (const char *)extension_label, (const char *)extension);
00786   }
00787   Tcl_Interp *interp = uiText->get_tcl_interp();
00788   if (interp) {
00789     int retval = Tcl_Eval(interp, cmd);
00790     delete [] cmd;
00791     if (retval == TCL_OK) {
00792       const char *result = Tcl_GetStringResult(interp);
00793       if (result == NULL || strlen(result) == 0) {
00794         return NULL;
00795       } else {
00796         return stringdup(result);
00797       }
00798     }
00799   }
00800   // fall through to next level on failure
00801 #endif
00802 
00803  } 
00804 
00805 #ifdef VMDFLTK
00806   return stringdup(fl_file_chooser(title, extension, NULL));
00807 #endif
00808 
00809   char *result = new char[256];
00810   fgets(result, 256, stdin);
00811   return result;
00812 }
00813  
00814 // file renderer API
00815 int VMDApp::filerender_num() {
00816   return fileRenderList->num();
00817 }
00818 const char *VMDApp::filerender_name(int n) {
00819   return fileRenderList->name(n);
00820 }
00821 const char *VMDApp::filerender_prettyname(int n) {
00822   return fileRenderList->pretty_name(n);
00823 }
00824 int VMDApp::filerender_valid(const char *method) {
00825   return (fileRenderList->find(method) != NULL);
00826 }
00827 // Find short renderer name from the "pretty" GUI renderer name
00828 const char *VMDApp::filerender_shortname_from_prettyname(const char *pretty) {
00829   return fileRenderList->find_short_name_from_pretty_name(pretty);
00830 }
00831 int VMDApp::filerender_has_antialiasing(const char *method) {
00832   return (fileRenderList->has_antialiasing(method));
00833 }
00834 int VMDApp::filerender_aasamples(const char *method, int aasamples) {
00835   return fileRenderList->aasamples(method, aasamples);
00836 }
00837 int VMDApp::filerender_aosamples(const char *method, int aosamples) {
00838   return fileRenderList->aosamples(method, aosamples);
00839 }
00840 int VMDApp::filerender_imagesize(const char *method, int *w, int *h) {
00841   if (!w || !h) return FALSE;
00842   return fileRenderList->imagesize(method, w, h); 
00843 }
00844 int VMDApp::filerender_has_imagesize(const char *method) {
00845   return fileRenderList->has_imagesize(method);
00846 }
00847 int VMDApp::filerender_aspectratio(const char *method, float *aspect) {
00848   if (!aspect) return FALSE;
00849   return fileRenderList->aspectratio(method, aspect);
00850 }
00851 int VMDApp::filerender_numformats(const char *method) {
00852   return fileRenderList->numformats(method);
00853 }
00854 const char *VMDApp::filerender_get_format(const char *method, int i) {
00855   return fileRenderList->format(method, i);
00856 }
00857 const char *VMDApp::filerender_cur_format(const char *method) {
00858   return fileRenderList->format(method);
00859 }
00860 int VMDApp::filerender_set_format(const char *m, const char *fmt) {
00861   return fileRenderList->set_format(m, fmt);
00862 }
00863 
00864 int VMDApp::filerender_render(const char *m, const char *f, const char *e) {
00865   int retval = fileRenderList->render(f, m, e);
00866   if (retval) {
00867     commandQueue->runcommand(new CmdRender(f, m, e));
00868   }
00869   return retval;
00870 }
00871 const char *VMDApp::filerender_option(const char *m, const char *o) {
00872   FileRenderer *ren = fileRenderList->find(m);
00873   if (!ren) {
00874     return NULL;
00875   }
00876   if (o) {
00877     ren->set_exec_string(o);
00878     commandQueue->runcommand(new CmdRenderOption(m, o));
00879   }
00880   return ren->saved_exec_string();
00881 }
00882 
00883 // XXX The Scene doesn't return error codes, so I don't know if the commands
00884 // worked or not.  I do what error checking I can here and hope that it works.
00885 int VMDApp::scene_rotate_by(float angle, char ax, float incr) {
00886   if (ax < 'x' || ax > 'z') return FALSE;  // failed
00887   rocker->stop_rocking();
00888   if (incr) {
00889     int nsteps = (int)(fabs(angle / incr) + 0.5);
00890     incr = (float) (angle < 0.0f ? -fabs(incr) : fabs(incr));
00891     rocker->start_rocking(incr, ax, nsteps, TRUE);
00892     commandQueue->runcommand(new CmdRotate(angle, ax, CmdRotate::BY, incr)); 
00893   } else {
00894     scene->root.add_rot(angle, ax);
00895     commandQueue->runcommand(new CmdRotate(angle, ax, CmdRotate::BY));
00896   }
00897   return TRUE;
00898 }
00899 int VMDApp::scene_rotate_to(float angle, char ax) {
00900   if (ax < 'x' || ax > 'z') return FALSE;  // failed
00901   rocker->stop_rocking();
00902   scene->root.set_rot(angle, ax);
00903   commandQueue->runcommand(new CmdRotate(angle, ax, CmdRotate::TO));
00904   return TRUE;
00905 }
00906 int VMDApp::scene_rotate_by(const float *m) {
00907   Matrix4 mat(m);
00908   scene->root.add_rot(mat);
00909   commandQueue->runcommand(new CmdRotMat(mat, CmdRotMat::BY));
00910   return TRUE;
00911 }
00912 int VMDApp::scene_rotate_to(const float *m) {
00913   Matrix4 mat(m);
00914   scene->root.set_rot(mat);
00915   commandQueue->runcommand(new CmdRotMat(mat, CmdRotMat::TO));
00916   return TRUE;
00917 }
00918 int VMDApp::scene_translate_by(float x, float y, float z) {
00919   scene->root.add_glob_trans(x, y, z);
00920   commandQueue->runcommand(new CmdTranslate(x,y,z,CmdTranslate::BY));
00921   return TRUE;
00922 }
00923 int VMDApp::scene_translate_to(float x, float y, float z) {
00924   scene->root.set_glob_trans(x, y, z);
00925   commandQueue->runcommand(new CmdTranslate(x,y,z,CmdTranslate::TO));
00926   return TRUE;
00927 }
00928 int VMDApp::scene_scale_by(float s) {
00929   if (s <= 0) return FALSE; 
00930   scene->root.mult_scale(s);
00931   commandQueue->runcommand(new CmdScale(s, CmdScale::BY));
00932   return TRUE;
00933 }
00934 int VMDApp::scene_scale_to(float s) {
00935   if (s <= 0) return FALSE; 
00936   scene->root.set_scale(s);
00937   commandQueue->runcommand(new CmdScale(s, CmdScale::TO));
00938   return TRUE;
00939 }
00940 void VMDApp::scene_resetview_newmoldata() {
00941 #if 1
00942   // XXX avoid N^2 behavior when loading thousands of molecules
00943   // we should only be resetting the view when necessary
00944   if (UpdateDisplay) {
00945     int nodisrupt = 0;
00946 
00947     if (getenv("VMDNODISRUPTHACK"))
00948       nodisrupt=1;
00949 
00950     if (nodisrupt && (moleculeList->num() > 1)) {
00951       moleculeList->center_top_molecule(); // new/top mol inherits current view
00952     } else {
00953       scene_resetview(); // reset all molecules to the newly loaded structure
00954     }
00955     ResetViewPending = FALSE;
00956   } else {
00957     ResetViewPending = TRUE;
00958   }
00959 #else
00960   scene_resetview(); // reset all molecules to the newly loaded structure
00961 #endif
00962 }
00963 void VMDApp::scene_resetview() {
00964   scene->root.reset_transformation();
00965   // center the view based on the displayed representations
00966   moleculeList->center_from_top_molecule_reps();
00967   moleculeList->center_all_molecules();
00968   commandQueue->runcommand(new CmdResetView);
00969 }
00970 int VMDApp::scene_rock(char ax, float step, int nsteps) {
00971   if (ax < 'x' || ax > 'z') return FALSE;  // failed
00972   rocker->start_rocking(step, ax, nsteps);
00973   commandQueue->runcommand(new CmdRockOn(step, ax, nsteps));
00974   return TRUE;
00975 }
00976 int VMDApp::scene_rockoff() {
00977   rocker->stop_rocking();
00978   commandQueue->runcommand(new CmdRockOff);
00979   return TRUE;
00980 } 
00981 int VMDApp::scene_stoprotation() {
00982   rocker->stop_rocking();
00983   mouse->stop_rotation();
00984   return TRUE;
00985 }
00986 
00987 int VMDApp::animation_num_dirs() {
00988   return Animation::ANIM_TOTAL_DIRS;
00989 }
00990 
00991 const char *VMDApp::animation_dir_name(int i) {
00992   if (i < 0 || i >= Animation::ANIM_TOTAL_DIRS) return NULL;
00993   return animationDirName[i]; 
00994 }
00995    
00996 int VMDApp::animation_set_dir(int d) {
00997   Animation::AnimDir dir = (Animation::AnimDir)d;
00998   anim->anim_dir(dir);
00999   commandQueue->runcommand(new CmdAnimDir(dir));
01000   return 1;
01001 }
01002 
01003 int VMDApp::animation_num_styles() {
01004   return Animation::ANIM_TOTAL_STYLES;
01005 }
01006 
01007 const char *VMDApp::animation_style_name(int i) {
01008   if (i < 0 || i >= Animation::ANIM_TOTAL_STYLES) return NULL;
01009   return animationStyleName[i];
01010 }
01011 
01012 int VMDApp::animation_set_style(int s) {
01013   Animation::AnimStyle style = (Animation::AnimStyle)s;
01014   anim->anim_style(style);
01015   commandQueue->runcommand(new CmdAnimStyle(style));
01016   return 1;
01017 }
01018 
01019 int VMDApp::animation_set_frame(int frame) {
01020     anim->goto_frame(frame);
01021     anim->anim_dir(Animation::ANIM_PAUSE);
01022     commandQueue->runcommand(new CmdAnimJump(frame));
01023     return 1;
01024 }
01025 
01026 int VMDApp::animation_set_stride(int stride) {
01027     anim->skip(stride);
01028     commandQueue->runcommand(new CmdAnimSkip(stride));
01029     return 1;
01030 }
01031 
01032 int VMDApp::animation_set_speed(float speed) {
01033     anim->speed(speed);
01034     commandQueue->runcommand(new CmdAnimSpeed(speed));
01035     return 1;
01036 }
01037 
01038 const char *VMDApp::filerender_default_option(const char *m) {
01039   FileRenderer *ren = fileRenderList->find(m);
01040   if (!ren) {
01041     return NULL;
01042   }
01043   return ren->default_exec_string();
01044 }
01045 const char *VMDApp::filerender_default_filename(const char *m) {
01046   FileRenderer *ren = fileRenderList->find(m);
01047   if (!ren) {
01048     return NULL;
01049   }
01050   return ren->default_filename();
01051 }
01052  
01053 
01054 // plugin stuff 
01055 
01056 vmdplugin_t *VMDApp::get_plugin(const char *type, const char *name) {
01057   if (!pluginMgr) return NULL;
01058   if (!type || !name) return NULL;
01059   PluginList p;
01060   vmdplugin_t *plugin = NULL;
01061   if (pluginMgr->plugins(p, type, name)) {
01062     plugin = p[0];
01063 
01064     // loop over plugins and select the highest version number for a 
01065     // given plugin type/name combo.
01066     for (int i=1; i<p.num(); i++) {
01067       vmdplugin_t *curplugin = p[i];
01068       if (curplugin->majorv > plugin->majorv || 
01069           (curplugin->majorv == plugin->majorv && curplugin->minorv > plugin->minorv))
01070         plugin = curplugin;
01071     }
01072   } 
01073   return plugin;
01074 }
01075 
01076 int VMDApp::list_plugins(PluginList &p, const char *type) {
01077   if (!pluginMgr) return 0;
01078   return pluginMgr->plugins(p, type);
01079 }
01080 
01081 int VMDApp::plugin_dlopen(const char *filename) {
01082   if (!pluginMgr) {
01083     msgErr << "scan_plugins: no plugin manager available" << sendmsg;
01084     return -1;
01085   }
01086   if (!filename) return -1;
01087   return pluginMgr->load_sharedlibrary_plugins(filename);
01088 }
01089 
01090 void VMDApp::plugin_update() {
01091   commandQueue->runcommand(new CmdPluginUpdate);
01092 }
01093 
01094 void VMDApp::display_update_on(int ison) {
01095   UpdateDisplay = ison;
01096 }
01097 
01098 int VMDApp::display_update_status() {
01099   return (UpdateDisplay != 0);
01100 }
01101 
01102 void VMDApp::display_update() {
01103   int prevUpdateFlag = UpdateDisplay;
01104   UpdateDisplay = 1;
01105   VMDupdate(VMD_IGNORE_EVENTS);
01106   UpdateDisplay = prevUpdateFlag;
01107 }
01108 
01109 void VMDApp::display_update_ui() {
01110   VMDupdate(VMD_CHECK_EVENTS);
01111 }
01112 
01113 int VMDApp::num_color_categories() {
01114   return scene->num_categories();
01115 }
01116 const char *VMDApp::color_category(int n) {
01117   return scene->category_name(n);
01118 }
01119 
01120 int VMDApp::color_add_item(const char *cat, const char *name, const char *defcolor) {
01121   int init_color = scene->color_index(defcolor);
01122   if (init_color < 0) {
01123     msgErr << "Cannot add color item: invalid color name '" << defcolor << "'" << sendmsg;
01124     return FALSE;
01125   }
01126   int ind = scene->category_index(cat);
01127   if (ind < 0) {
01128     ind = scene->add_color_category(cat);
01129   }
01130   if (scene->add_color_item(ind, name, init_color) < 0) {
01131     return FALSE;
01132   }
01133   commandQueue->runcommand(new CmdColorItem(cat, name, defcolor));
01134   return TRUE;
01135 }
01136 
01137 int VMDApp::num_color_category_items(const char *category) {
01138   int colCatIndex = scene->category_index(category);
01139   if (colCatIndex < 0) return 0;
01140   return scene->num_category_items(colCatIndex);
01141 }
01142 const char *VMDApp::color_category_item(const char *category, int n) {
01143   int colCatIndex = scene->category_index(category);
01144   if (colCatIndex < 0) return 0;
01145   return scene->category_item_name(colCatIndex, n); // XXX check valid n
01146 }
01147 int VMDApp::num_colors() {
01148   return MAXCOLORS;
01149 }
01150 int VMDApp::num_regular_colors() {
01151   return REGCLRS;
01152 }
01153 const char *VMDApp::color_name(int n) {
01154   return scene->color_name(n);
01155 }
01156 int VMDApp::color_index(const char *color) {
01157   if (!color) return -1;
01158   // If it's a number in the valid range, return the number; otherwise return
01159   // -1.
01160   int i;
01161   if (sscanf(color, "%d", &i)) {
01162     if (i >= 0 && i < MAXCOLORS)
01163       return i;
01164     else
01165       return -1;
01166   }
01167   // look up the color by name.
01168   return scene->color_index(color);
01169 } 
01170 int VMDApp::color_value(const char *colorname, float *r, float *g, float *b) {
01171   int colIndex = color_index(colorname);
01172   if (colIndex < 0) return 0;
01173   const float *col = scene->color_value(colIndex);
01174   *r = col[0];
01175   *g = col[1];
01176   *b = col[2];
01177   return 1;
01178 }
01179 int VMDApp::color_default_value(const char *colorname, float *r, float *g, float *b) {
01180   int colIndex = color_index(colorname);
01181   if (colIndex < 0) return 0;
01182   const float *col = scene->color_default_value(colIndex);
01183   *r = col[0];
01184   *g = col[1];
01185   *b = col[2];
01186   return 1;
01187 }
01188 const char *VMDApp::color_mapping(const char *category, const char *item) {
01189   
01190   int colCatIndex = scene->category_index(category);
01191   if (colCatIndex < 0) return 0;
01192 
01193   int colNameIndex = scene->category_item_index(colCatIndex, item);
01194   if (colNameIndex < 0) return 0;
01195   
01196   int ind = scene->category_item_value(colCatIndex, colNameIndex);
01197   return scene->color_name(ind);
01198 }
01199 
01200 const char *VMDApp::color_get_restype(const char *resname) {
01201   int id = moleculeList->resTypes.typecode(resname);
01202   if (id < 0) return NULL;
01203   return moleculeList->resTypes.data(id);
01204 }
01205 
01206 int VMDApp::color_set_restype(const char *resname, const char *restype) {
01207   int cat = moleculeList->colorCatIndex[MLCAT_RESTYPES];
01208   int ind = scene->category_item_index(cat, restype);
01209   if (ind < 0) return FALSE;  // nonexistent restype category
01210 
01211   // Use the string stored in Scene rather than the one passed to this
01212   // function, since then we don't have to worry about copying it and
01213   // freeing it later.
01214   const char *stable_restype_name = scene->category_item_name(cat, ind);
01215 
01216   // if the resname doesn't have an entry yet, create one.
01217   int resname_id = moleculeList->resTypes.add_name(resname, restype);
01218   moleculeList->resTypes.set_data(resname_id, stable_restype_name);
01219   scene->root.color_changed(cat);
01220   return TRUE;
01221 }
01222 
01223 int VMDApp::colorscale_info(float *mid, float *min, float *max) {
01224   scene->colorscale_value(mid, min, max);
01225   return 1;
01226 }
01227 int VMDApp::num_colorscale_methods() {
01228   return scene->num_colorscale_methods();
01229 }
01230 int VMDApp::colorscale_method_current() {
01231   return scene->colorscale_method();
01232 }
01233 const char *VMDApp::colorscale_method_name(int n) {
01234   if (n < 0 || n >= scene->num_colorscale_methods()) return NULL;
01235   return scene->colorscale_method_name(n);
01236 }
01237 int VMDApp::colorscale_method_index(const char *method) {
01238   for (int i=0; i<scene->num_colorscale_methods(); i++) {
01239     if (!strupncmp(method, scene->colorscale_method_name(i),CMDLEN)) {
01240       return i;
01241     }
01242   }
01243   return -1;
01244 }  
01245 
01246 int VMDApp::get_colorscale_colors(int whichScale, 
01247       float min[3], float mid[3], float max[3]) {
01248   return scene->get_colorscale_colors(whichScale, min, mid, max);
01249 }
01250 
01251 int VMDApp::set_colorscale_colors(int whichScale, 
01252       const float min[3], const float mid[3], const float max[3]) {
01253   if (scene->set_colorscale_colors(whichScale, min, mid, max)) {
01254     commandQueue->runcommand(new CmdColorScaleColors(
01255           scene->colorscale_method_name(whichScale), mid, min, max));
01256     return TRUE;
01257   }
01258   return FALSE;
01259 }
01260 
01261 int VMDApp::color_changename(const char *category, const char *colorname, 
01262                      const char *color) {
01263 
01264   if (!category || !colorname || !color) return 0;
01265 
01266   int colCatIndex = scene->category_index(category);
01267   if (colCatIndex < 0) return 0;
01268   
01269   int colNameIndex = scene->category_item_index(colCatIndex, colorname);
01270   if (colNameIndex < 0) return 0;
01271 
01272   int newIndex = color_index(color);
01273   if (newIndex < 0) return 0;
01274  
01275   // all systems go...
01276   scene->set_category_item(colCatIndex, colNameIndex, newIndex);
01277   
01278   // tell the rest of the world
01279   commandQueue->runcommand(new CmdColorName(category, colorname, color));
01280   return 1;
01281 }
01282 
01283 int VMDApp::color_get_from_name(const char *category, const char *colorname, 
01284                      const char **color) {
01285 
01286   if (!category || !colorname) return 0;
01287 
01288   int colCatIndex = scene->category_index(category);
01289   if (colCatIndex < 0) return 0;
01290   
01291   int colNameIndex = scene->category_item_index(colCatIndex, colorname);
01292   if (colNameIndex < 0) return 0;
01293  
01294   // all systems go...
01295   int colIndex = scene->get_category_item(colCatIndex, colNameIndex);
01296   if (colIndex < 0) return 0;
01297   
01298   *color = color_name(colIndex);
01299       
01300   return 1;
01301 }
01302 
01303 
01304 int VMDApp::color_changevalue(const char *color, float r, float g, float b) {
01305   int ind = color_index(color);
01306   if (ind < 0) return 0;
01307   float rgb[3] = {r, g, b};
01308   scene->set_color_value(ind, rgb);
01309   commandQueue->runcommand(new CmdColorChange(color, r, g, b));
01310   return 1;
01311 }
01312   
01313 int VMDApp::colorscale_setvalues(float mid, float min, float max) {
01314   scene->set_colorscale_value(min, mid, max);
01315   commandQueue->runcommand(new CmdColorScaleSettings(mid, min, max));
01316   return 1;
01317 }
01318 
01319 int VMDApp::colorscale_setmethod(int method) {
01320   if (method < 0 || method >= scene->num_colorscale_methods()) return 0;
01321   scene->set_colorscale_method(method);
01322   commandQueue->runcommand(new CmdColorScaleMethod(
01323         scene->colorscale_method_name(method)));
01324   return 1;
01325 }
01326   
01327   
01328 int VMDApp::logfile_read(const char *path) {
01329   uiText->read_from_file(path);
01330   return 1;
01331 }
01332 
01333 int VMDApp::save_state() {
01334   char *file = vmd_choose_file(
01335     "Enter filename to save current VMD state:",  // Title
01336     "*.vmd",                                      // extension
01337     "VMD files",                                  // label
01338     1                                             // do_save
01339   );
01340   if (!file)
01341     return 1;
01342   int retval = uiText->save_state(file);
01343   delete [] file;
01344   return retval;
01345 }
01346  
01347 int VMDApp::num_molecules() {
01348   return moleculeList->num();
01349 }
01350 
01351 
01352 // This creates a blank molecule, for use by "mol new atoms" and the like...
01353 int VMDApp::molecule_new(const char *name, int natoms, int docallbacks) {
01354   // if we aren't given a name for the molecule, use a temp name
01355   Molecule *newmol = new Molecule((name == NULL) ? "molecule" : name,
01356                                   this, &(scene->root));
01357   moleculeList->add_molecule(newmol);
01358   int molid = newmol->id();
01359 
01360   // If we aren't given a name for the molecule, we auto-generate one
01361   // from the assigned molid.
01362   if (name == NULL) {
01363     char buf[30];
01364     sprintf(buf, "molecule%d", molid);
01365 #if 1
01366     // We rename the molecule for ourselves without calling molecule_rename()
01367     // in order to avoid triggering extra callbacks that cause expensive 
01368     // GUI redraws.
01369     newmol->rename(buf);
01370 
01371     // Add item to Molecule color category; default color should be the same as
01372     // the original molecule.  
01373     int ind = moleculeList->colorCatIndex[MLCAT_MOLECULES];
01374     scene->add_color_item(ind, buf, molid % VISCLRS);
01375 #else
01376     molecule_rename(molid, buf);
01377 #endif
01378   }
01379 
01380   if (natoms > 0) {
01381     int i;
01382     newmol->init_atoms(natoms);
01383 
01384     float *charge = newmol->charge();
01385     float defcharge = newmol->default_charge("X");
01386     for (i=0; i<natoms; i++)
01387       charge[i] = defcharge;
01388 
01389     float *mass = newmol->mass();
01390     float defmass = newmol->default_mass("X");
01391     for (i=0; i<natoms; i++)
01392       mass[i] = defmass;
01393 
01394     float *radius = newmol->radius();
01395     float defradius = newmol->default_radius("X");
01396     for (i=0; i<natoms; i++)
01397       radius[i] = defradius;
01398 
01399     float *beta = newmol->beta();
01400     float defbeta = newmol->default_beta();
01401     for (i=0; i<natoms; i++)
01402       beta[i] = defbeta;
01403 
01404     float *occupancy = newmol->occupancy();
01405     float defoccupancy = newmol->default_occup();
01406     for (i=0; i<natoms; i++)
01407       occupancy[i] = defoccupancy;
01408 
01409     for (i=0; i<natoms; i++) {
01410       if (0 > newmol->add_atom("X", "X", 0, "UNK", 0, "", "", " ", "")) {
01411         // if an error occured while adding an atom, we should delete
01412         // the offending molecule since the data is presumably inconsistent,
01413         // or at least not representative of what we tried to load
01414         msgErr << "VMDApp::molecule_new: molecule creation aborted" << sendmsg;
01415         return -1; // signal failure
01416       }
01417     }
01418   }
01419 
01420   if (docallbacks) {
01421     commandQueue->runcommand(new CmdMolNew);
01422     commandQueue->runcommand(new MoleculeEvent(molid, MoleculeEvent::MOL_NEW));
01423     commandQueue->runcommand(new InitializeStructureEvent(molid, 1));
01424   }
01425 
01426   return molid; 
01427 } 
01428 
01429 
01430 const char *VMDApp::guess_filetype(const char *filename) {
01431   const char *ext = strrchr(filename, '.');
01432   if (!ext) {
01433     // check for webpdb
01434     if (strlen(filename) == 4) {
01435       return "webpdb";
01436     }
01437     msgWarn << "Unable to ascertain filetype from filename '"
01438             << filename << "'; assuming pdb." << sendmsg;
01439     return "pdb";
01440   }
01441   ext++;
01442   char *s = strdup(ext);
01443   char *c = s;
01444   while (*c) { *c = tolower(*c); c++; }
01445   PluginList plugins;
01446   pluginMgr->plugins(plugins, "mol file reader", NULL);
01447   pluginMgr->plugins(plugins, "mol file converter", NULL);
01448   const char *bestname = NULL;
01449   int bestrank = 9999;
01450   for (int i=0; i<plugins.num(); i++) {
01451     // check against comma separated list of filename extensions, 
01452     // no spaces, as in: "pdb,ent,foo,bar,baz,ban"
01453     // Also keep track of the place in the list that the extension was
01454     // found - thus a plugin that lists the extension first can override
01455     // a plugin that comes earlier in the plugin list but lists the
01456     // extension later in its filename_extension string.
01457     MolFilePlugin p(plugins[i]);
01458     char *extbuf = strdup(p.extension());
01459     int extlen = strlen(extbuf);
01460     char *extcur = extbuf;
01461     char *extnext = NULL; 
01462     int currank = 1;
01463     while ((extcur - extbuf) < extlen) { 
01464       extnext = strchr(extcur, ','); // find next extension string
01465       if (extnext) {
01466         *extnext = '\0'; // NUL terminate this extension string
01467         extnext++;       // step to beginning of next extension string
01468       } else {
01469         extnext = extbuf + extlen; // no more extensions, last time through
01470       }
01471       if (!strcmp(s, extcur)) {
01472         if (!bestname || currank < bestrank) {
01473           bestname = p.name();
01474           bestrank = currank;
01475         }
01476       }
01477       extcur = extnext;
01478       ++currank;
01479     }
01480     free(extbuf);
01481   }
01482   free(s);
01483   return bestname;
01484 }
01485 
01486 int VMDApp::molecule_load(int molid, const char *filename, 
01487                           const char *filetype, const FileSpec *spec) {
01488   int original_molid = molid;
01489 
01490   // Call BaseMolecule::analyze() only once, when structure is first created.
01491   int first_structure = 0;
01492 
01493   // check for valid timestep parameters
01494   if (spec->last != -1 && spec->last < spec->first) {
01495     msgErr << "Invalid last frame: " << spec->last << sendmsg;
01496     return -1;
01497   }
01498   if (spec->stride < 1) {
01499     msgErr << "Invalid stride: " << spec->stride << sendmsg;
01500     return -1;
01501   }
01502 
01503   // if no filetype was given, try to obtain it from the filename.
01504   if (!filetype) {
01505     filetype = guess_filetype(filename);
01506     if (!filetype) {
01507       msgErr << "Could not determine filetype of file '" << filename 
01508              << "' from its name." << sendmsg;
01509       return -1;
01510     }
01511   }
01512 
01513   int waitfor = spec->waitfor;
01514   if (waitfor == 0 && molid == -1) {
01515     // It's not ok to load zero frames for a new molecule because coordinates
01516     // might be needed to determine bonds from atom distances.
01517     waitfor = 1;
01518     msgWarn << "Will load one coordinate frame for new molecule." << sendmsg;
01519   }
01520   
01521   // Prefer to use a direct reader plugin over a translator, if one
01522   // is available.  If not, then attempt to use a translator.
01523   vmdplugin_t *p = get_plugin("mol file reader", filetype);
01524   if (!p) p = get_plugin("mol file converter", filetype);
01525   if (!p) {
01526     msgErr << "Cannot read file of type " << filetype << sendmsg;
01527     return -1;
01528   }
01529   MolFilePlugin *plugin = new MolFilePlugin(p);
01530   if (plugin->init_read(filename)) {
01531     msgErr << "Could not read file " << filename << sendmsg;
01532     delete plugin;
01533     return -1;
01534   }
01535 
01536   Molecule *newmol = NULL;
01537   if (molid == -1) {
01538 #if 1
01539     // don't trigger callbacks for MOL_NEW etc yet, as we will be triggering
01540     // more of them below, and we wish to prevent the GUIs from exhibiting
01541     // quadratic behavior -- they regen their molecule choosers from scratch
01542     // in any case where the count of molecules doesn't change (e.g. when
01543     // getting redundant molecule new events from the same load event)
01544     molid = molecule_new(filename, 0, 0);
01545 #else
01546     molid = molecule_new(filename, 0);
01547 #endif
01548   }
01549   newmol = moleculeList->mol_from_id(molid);
01550   if (!newmol) {
01551     msgErr << "Invalid molecule " << molid << sendmsg;
01552     delete plugin;
01553     return -1;
01554   }
01555 
01556   // We've committed to loading as much as we can from the file, so go ahead
01557   // and record it.  This needs to be done before the InitializeStructure
01558   // event is triggered so that the list of filenames for the molecule is
01559   // complete and the filename can be used by Tcl/Python scripts that want
01560   // to process the filename when the InitializeStructure even occurs.
01561   char specstr[8192];
01562   sprintf(specstr, "first %d last %d step %d filebonds %d autobonds %d",
01563           spec->first, spec->last, spec->stride, 
01564           spec->autobonds, spec->filebonds);
01565   newmol->record_file(filename, filetype, specstr);
01566 
01567   //
01568   // Molecule file metadata
01569   // 
01570   if (plugin->can_read_metadata()) {
01571     if (plugin->read_metadata(newmol)) {
01572       msgErr << "Error reading metadata." << sendmsg;
01573     } 
01574   } else {
01575     // each file must have something, even if blank 
01576     newmol->record_database("", "");
01577     newmol->record_remarks("");
01578   }
01579  
01580   // 
01581   // Atomic structure and coordinate data
01582   //
01583   if (plugin->can_read_structure()) {
01584     if (!newmol->has_structure()) {
01585       msgInfo << "Using plugin " << filetype << " for structure file " 
01586               << filename << sendmsg;
01587 
01588       int rc = plugin->read_structure(newmol, spec->filebonds, spec->autobonds);
01589 
01590       // it's not an error to get no structure data from formats that
01591       // don't always contain it, so only report an error when we 
01592       // expected to get structure data and got an error instead.
01593       if (rc != MOLFILE_SUCCESS && rc != MOLFILE_NOSTRUCTUREDATA) {
01594         // tell the user something went wrong, but keep going and try to
01595         // read other information in the file.  Perhaps it's better to
01596         // stop immediately and create no molecule if something goes wrong
01597         // at this stage?
01598         msgErr << "molecule_structure: Unable to read structure for molecule "
01599                << molid << sendmsg;
01600         if (rc == MOLFILE_ERROR) {
01601           msgErr << "molecule_structure: severe error indicated by plugin "
01602                  << "aborting loading of molecule " << molid << sendmsg;
01603           delete plugin;
01604           return -1;
01605         }
01606       }
01607 
01608       // initialize structure if we loaded with no errors
01609       if (rc == MOLFILE_SUCCESS) {
01610         first_structure = 1;
01611         commandQueue->runcommand(new InitializeStructureEvent(molid, 1));
01612       }
01613     } else {
01614       int rc = plugin->read_optional_structure(newmol, spec->filebonds);
01615       if (rc != MOLFILE_SUCCESS && rc != MOLFILE_NOSTRUCTUREDATA) {
01616         msgErr << 
01617           "Error reading optional structure information from coordinate file "
01618           << filename << sendmsg;
01619         msgErr << "Will ignore structure information in this file." << sendmsg;
01620       }
01621     }
01622   } else {
01623     // Can't read structure, but some plugins (e.g. dcd) can initialize the
01624     // atom number.  Do this if possible
01625     if (plugin->natoms() > 0) {
01626       if (!newmol->init_atoms(plugin->natoms())) {
01627         msgErr << "Invalid number of atoms in file: " << plugin->natoms()
01628                << sendmsg;
01629       }
01630     }
01631   }
01632 
01633 
01634   //
01635   // Read QM metadata and the actual data in one swoop
01636   // for now. We might have to separate these later.
01637   // 
01638   if (plugin->can_read_qm()) {
01639     if (plugin->read_qm_data(newmol)) {
01640       msgErr << "Error reading metadata." << sendmsg;
01641     } 
01642   }
01643   
01644 
01645   //
01646   // Volumetric data
01647   //
01648   if (plugin->can_read_volumetric()) {
01649     if (plugin->read_volumetric(newmol, spec->nvolsets, spec->setids)) {
01650       msgErr << "Error reading volumetric data." << sendmsg;
01651     } else {
01652       scene_resetview_newmoldata(); // reset the view so we can see the dataset.
01653       commandQueue->runcommand(new CmdMolVolume(molid));
01654     }
01655   }
01656 
01657 
01658   // 
01659   // Raw graphics
01660   // 
01661   if (plugin->can_read_graphics()) {
01662     if (plugin->read_rawgraphics(newmol, scene)) {
01663       msgErr << "Reading raw graphics failed." << sendmsg;
01664     } else {
01665       scene_resetview_newmoldata(); // reset the view so we can see the dataset.
01666     }
01667   }
01668 
01669   // Timesteps
01670   if (plugin->can_read_timesteps() || plugin->can_read_qm_timestep()) {
01671     msgInfo << "Using plugin " << filetype << " for coordinates from file " 
01672             << filename << sendmsg;
01673     if (!newmol->nAtoms) {
01674       msgErr << "Some frames from file '" << filename << "' could not be loaded"
01675         << sendmsg;
01676       msgErr << "because the number of atoms could not be determined.  Load a"
01677         << sendmsg;
01678       msgErr << "structure file first, then try loading this file again." << sendmsg;
01679     } else {
01680 
01681       CoorPluginData *data = new CoorPluginData(
01682           filename, newmol, plugin, 1, spec->first, spec->stride, spec->last);
01683       newmol->add_coor_file(data);
01684       if (waitfor < 0) {
01685         // drain the I/O queue of all frames, even those that didn't necessarily
01686         // come from this file.
01687         while (newmol->next_frame());
01688       } else {
01689         // read waitfor frames.
01690         for (int i=0; i<waitfor; i++)
01691           if (!newmol->next_frame()) break;
01692       }
01693     }
01694   } else {
01695     // Delete the plugin unless timesteps were loaded, in which case the 
01696     // plugin will be deleted by the CoorPluginData object.
01697     delete plugin;
01698     plugin = NULL;
01699   }
01700 
01701   // Now go back and analyze structure, since we may have had to load
01702   // timesteps first.
01703   if (first_structure) {
01704     // build structure information for this molecule
01705     newmol->analyze(); 
01706 
01707     // Must add color names here because atom names and such aren't defined
01708     // until there's a molecular structure.
01709     moleculeList->add_color_names(moleculeList->mol_index_from_id(molid));
01710 
01711     // force all colors and reps to be recalculated, since this may be 
01712     // loaded into a molecule that didn't previously contain atomic data
01713     newmol->force_recalc(DrawMolItem::COL_REGEN | DrawMolItem::SEL_REGEN);
01714 
01715     // since atom color definitions are now established, create a new 
01716     // representation using the default parameters.
01717     moleculeList->set_color((char *)moleculeList->default_color());
01718     moleculeList->set_representation((char *)moleculeList->default_representation());
01719     moleculeList->set_selection(moleculeList->default_selection());
01720     moleculeList->set_material((char *)moleculeList->default_material());
01721     molecule_addrep(newmol->id());
01722     scene_resetview_newmoldata(); // reset the view so we can see the dataset.
01723   }
01724 
01725   // If the molecule doesn't have any reps yet and we have volume data,
01726   // add a new Isosurface rep.
01727   if (!newmol->components() && newmol->num_volume_data()) {
01728     molecule_set_style("Isosurface");
01729     molecule_addrep(newmol->id());
01730   }
01731 
01732   commandQueue->runcommand(new CmdMolLoad(original_molid, filename, filetype, 
01733                            spec));
01734   return molid;
01735 }
01736 
01737 
01738 int VMDApp::molecule_savetrajectory(int molid, const char *fname, 
01739                                     const char *type, const FileSpec *spec) {
01740   Molecule *newmol = moleculeList->mol_from_id(molid);
01741   if (!newmol) {
01742     msgErr << "Invalid molecule id " << molid << sendmsg;
01743     return -1;
01744   }
01745   if (fname == NULL) {
01746     msgErr << "Invalid NULL filename string" << sendmsg;
01747     return -1;
01748   }
01749 
01750   int first = spec->first;
01751   int last = spec->last;
01752   int stride = spec->stride;
01753   int waitfor = spec->waitfor;
01754   int nframes = 0;
01755   int natoms = 0;
01756   const int *selection = spec->selection;
01757   CoorData *data = NULL;
01758   int savevoldata = (newmol->num_volume_data() > 0) && (spec->nvolsets != 0);
01759 
01760   // Determine number of atoms to write.
01761   natoms = newmol->nAtoms;
01762   if (selection) {
01763     natoms=0;
01764     // the selection cannot change as the trajectory is written out,
01765     // so this is a safe way to count selected atoms
01766     for (int i=0; i<newmol->nAtoms; i++)
01767       natoms += selection[i] ? 1 : 0;
01768   }
01769 
01770   // validate timesteps if we actually have atomic coordinates to write
01771   if (natoms > 0) {
01772     if (last == -1)
01773       last = newmol->numframes() - 1;
01774 
01775     if (last < first && last >= 0) {
01776       msgErr << "Invalid last frame: " << last << sendmsg;
01777       return -1;
01778     }
01779     
01780     if (stride == -1 || stride == 0)
01781       stride = 1; // save all frames 
01782 
01783     if (stride < 1) {
01784       msgErr << "Invalid stride: " << stride << sendmsg;
01785       return -1;
01786     }
01787 
01788     nframes = (last-first)/stride + 1;
01789     if (nframes < 1 && !savevoldata) {
01790       msgInfo << "Save Trajectory: 0 frames specified; no coordinates written."
01791               << sendmsg;
01792       return 0;
01793     }
01794 
01795     if (natoms < 1 && !savevoldata) {
01796       msgInfo << "Save Trajectory: 0 atoms in molecule or selection; no coordinates written."
01797               << sendmsg;
01798       return -1;
01799     }
01800   }
01801 
01802   // Prefer to use a direct reader plugin over a translator, if one
01803   // is available.  If not, then attempt to use a translator.
01804   vmdplugin_t *p = get_plugin("mol file reader", type);
01805   if (!p) p = get_plugin("mol file converter", type);
01806   MolFilePlugin *plugin = NULL;
01807   if (p) {
01808     plugin = new MolFilePlugin(p);
01809     if (plugin->init_write(fname, natoms)) {
01810       msgErr << "Unable to open file " << fname << " of type " << type
01811              << " for writing frames." << sendmsg;
01812       delete plugin;
01813       return -1;
01814     }
01815     data = new CoorPluginData(fname, newmol, plugin, 0, first, stride, last,
01816                               selection);
01817   } else {
01818     msgErr << "Unknown coordinate file type " << type << sendmsg;
01819     return -1;
01820   }
01821   if (data == NULL) {
01822     msgErr << "NULL data returned by plugin " << sendmsg;
01823     return -1;
01824   }    
01825   msgInfo << "Opened coordinate file " << fname << " for writing.";
01826   msgInfo << sendmsg;
01827 
01828   // XXX if writing volume sets was requested, do it here, since CoorPluginData 
01829   // doesn't know about that type of data.  CoorPluginData should be using
01830   // a FileSpec struct.
01831   if (savevoldata) {
01832 #if vmdplugin_ABIVERSION > 9
01833     if (plugin->can_write_volumetric()) {
01834       for (int i=0; i<spec->nvolsets; i++) {
01835         if (plugin->write_volumetric(newmol, spec->setids[i]) != 
01836             MOLFILE_SUCCESS) {
01837           msgErr << "Failed to write volume set " << spec->setids[i]
01838                  << sendmsg;
01839         }
01840       }
01841     } else {
01842       msgErr << "Cannot write volsets to files of type " << type << sendmsg;
01843     }
01844 #else
01845     msgInfo << "Writing of volume data not supported by current plugin ABI." << sendmsg;
01846 #endif
01847   }
01848   
01849   // write waitfor frames before adding to the Molecule's queue.
01850   int numwritten = 0;
01851   if (waitfor < 0) {
01852     while (data->next(newmol) == CoorData::NOTDONE)
01853       numwritten++;
01854   
01855     // Don't add to the I/O queue, just complete the I/O transaction 
01856     // synchronously and trigger any necessary callbacks.
01857     // This prevents analysis scripts that don't return control to the
01858     // main loop from queueing up large amounts of I/Os that only needed
01859     // file closures and memory frees to be completed.
01860     newmol->close_coor_file(data);
01861   } else if (waitfor > 0) {
01862     for (int i=0; i<waitfor; i++) {
01863       if (data->next(newmol) == CoorData::DONE) break;
01864         numwritten++;
01865     }
01866 
01867     // Add the I/O to the asynchronous queue and let it continue 
01868     // with subsequent main loop event polling/updates.
01869     newmol->add_coor_file(data);
01870   }
01871 
01872   commandQueue->runcommand(new CmdAnimWriteFile(molid, fname, type,
01873                            first, last, stride));
01874   return numwritten;
01875 }
01876  
01877 
01878 int VMDApp::molecule_deleteframes(int molid, int first, int last, 
01879                                    int stride) {
01880   Molecule *mol = moleculeList->mol_from_id(molid);
01881   if (!mol) {
01882     msgErr << "Invalid molecule id " << molid << sendmsg;
01883     return 0;
01884   }
01885   if (!mol->numframes()) return TRUE;
01886 
01887   if (last == -1)
01888     last = mol->numframes()-1;
01889   if (last < first) {
01890     msgErr << "Invalid last frame: " << last << sendmsg;
01891     return 0;
01892   }
01893   
01894   if (stride==-1) stride=0; //delete all frames in range
01895   if (stride < 0) {
01896     msgErr << "Invalid stride: " << stride << sendmsg;
01897     return 0;
01898   }
01899   
01900   // keep every stride frame btw first and last
01901   int indexshift = first; // as frames are deleted, indices are shifted
01902   for (int i=0; i<=last-first; i++) {
01903     if (!stride || i%stride) {
01904       mol->delete_frame(indexshift+i);
01905       indexshift--;
01906     }
01907   }
01908 
01909   commandQueue->runcommand(new CmdAnimDelete(molid, first, last, stride));
01910   return 1;
01911 }
01912 
01913 int VMDApp::molecule_index_from_id(int id) {
01914   if (id < 0) return -1;
01915   return moleculeList->mol_index_from_id(id);
01916 }
01917 int VMDApp::molecule_id(int i) {
01918   if (i < 0 || i >= num_molecules()) return -1;
01919   Molecule *m = moleculeList->molecule(i);
01920   if (m == NULL)
01921     return -1;
01922   return m->id();
01923 }
01924 int VMDApp::molecule_valid_id(int molid) {
01925   return (moleculeList->mol_from_id(molid) != NULL);
01926 }
01927 int VMDApp::molecule_cancel_io(int molid) {
01928   Molecule *m = moleculeList->mol_from_id(molid);
01929   if (!m) return 0;
01930   m->cancel();
01931   commandQueue->runcommand(new CmdMolCancel(molid));
01932   return 1;
01933 }
01934 
01935 int VMDApp::molecule_delete(int molid) {
01936   if (moleculeList->del_molecule(molid)) {
01937     commandQueue->runcommand(new CmdMolDelete(molid));
01938     commandQueue->runcommand(new InitializeStructureEvent(molid, 0));
01939     commandQueue->runcommand(new MoleculeEvent(molid, MoleculeEvent::MOL_DELETE));
01940     // XXX this has the side effect of altering the 'top' molecule.
01941     // At present the GUI is checking for MOL_DEL in addition to MOL_TOP,
01942     // but really it'd be nicer if we generated appropriate events for 
01943     // side effect cases like this.
01944     return 1;
01945   }
01946   return 0; 
01947 }
01948 
01949 int VMDApp::molecule_delete_all(void) {
01950   int i, nummols, rc;
01951   int *molidlist;
01952 
01953   rc = 0;
01954   nummols = num_molecules();
01955   molidlist = new int[nummols];
01956  
01957   // save molid translation list before we delete them all
01958   for (i=0; i<nummols; i++) {
01959     molidlist[i] = moleculeList->molecule(i)->id();
01960   }
01961 
01962   // delete all molecules and process molecule event callbacks
01963   if (moleculeList->del_all_molecules()) {
01964     for (i=0; i<nummols; i++) {
01965       int molid = molidlist[i];
01966       commandQueue->runcommand(new CmdMolDelete(molid));
01967       commandQueue->runcommand(new InitializeStructureEvent(molid, 0));
01968       commandQueue->runcommand(new MoleculeEvent(molid, MoleculeEvent::MOL_DELETE));
01969     }
01970 
01971     // XXX this has the side effect of altering the 'top' molecule.
01972     // At present the GUI is checking for MOL_DEL in addition to MOL_TOP,
01973     // but really it'd be nicer if we generated appropriate events for 
01974     // side effect cases like this.
01975     rc=1;
01976   }
01977 
01978   delete [] molidlist;
01979 
01980   return rc; 
01981 }
01982 
01983 int VMDApp::molecule_activate(int molid, int onoff) {
01984   int ind = moleculeList->mol_index_from_id(molid);
01985   if (ind < 0) return 0;
01986   if (onoff)
01987     moleculeList->activate(ind);
01988   else
01989     moleculeList->inactivate(ind);
01990   commandQueue->runcommand(new CmdMolActive(molid, onoff));
01991   return 1;
01992 }
01993 int VMDApp::molecule_is_active(int molid) {
01994   int ind = moleculeList->mol_index_from_id(molid);
01995   if (ind < 0) return 0;
01996   return moleculeList->active(ind);
01997 }
01998 int VMDApp::molecule_fix(int molid, int onoff) {
01999   int ind = moleculeList->mol_index_from_id(molid);
02000   if (ind < 0) return 0;
02001   if (onoff)
02002     moleculeList->fix(ind);
02003   else
02004     moleculeList->unfix(ind);
02005   commandQueue->runcommand(new CmdMolFix(molid, onoff));
02006   return 1;
02007 }
02008 int VMDApp::molecule_is_fixed(int molid) {
02009   int ind = moleculeList->mol_index_from_id(molid);
02010   if (ind < 0) return 0;
02011   return moleculeList->fixed(ind);
02012 }
02013 int VMDApp::molecule_display(int molid, int onoff) {
02014   int ind = moleculeList->mol_index_from_id(molid);
02015   if (ind < 0) return 0;
02016   if (onoff)
02017     moleculeList->show(ind);
02018   else
02019     moleculeList->hide(ind);
02020   commandQueue->runcommand(new CmdMolOn(molid, onoff));
02021   return 1;
02022 }
02023 int VMDApp::molecule_is_displayed(int molid) {
02024   int ind = moleculeList->mol_index_from_id(molid);
02025   if (ind < 0) return 0;
02026   return moleculeList->displayed(ind);
02027 }
02028 int VMDApp::molecule_make_top(int molid) {
02029   int ind = moleculeList->mol_index_from_id(molid);
02030   if (ind < 0) return 0;
02031   moleculeList->make_top(ind);
02032   commandQueue->runcommand(new CmdMolTop(molid));
02033   return 1;
02034 }
02035 int VMDApp::molecule_top() {
02036   Molecule *m = moleculeList->top();
02037   if (!m) return -1;
02038   return m->id();
02039 }
02040 int VMDApp::num_molreps(int molid) {
02041   Molecule *m = moleculeList->mol_from_id(molid);
02042   if (!m) return 0;
02043   return m->components();
02044 }
02045 const char *VMDApp::molrep_get_style(int molid, int repid) {
02046   if (repid < 0 || repid >= num_molreps(molid)) return NULL;
02047   DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02048   if (item == NULL)
02049     return NULL;
02050   return item->atomRep->cmdStr;
02051 }
02052 int VMDApp::molrep_set_style(int molid, int repid, const char *style) {
02053   int ind = moleculeList->mol_index_from_id(molid);
02054   if (ind < 0) return 0;
02055   if (!moleculeList->change_repmethod(repid, ind, (char *)style)) return 0;
02056   commandQueue->runcommand(
02057     new CmdMolChangeRepItem(repid, molid, CmdMolChangeRepItem::REP, style));
02058   return 1;
02059 }
02060 const char *VMDApp::molrep_get_color(int molid, int repid) {
02061   if (repid < 0 || repid >= num_molreps(molid)) return NULL;
02062   DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02063   if (item == NULL)
02064     return NULL;
02065   return item->atomColor->cmdStr;
02066 }
02067 int VMDApp::molrep_set_color(int molid, int repid, const char *color) {
02068   int ind = moleculeList->mol_index_from_id(molid);
02069   if (ind < 0) return 0;
02070   if (!moleculeList->change_repcolor(repid, ind, (char *)color)) return 0;
02071   commandQueue->runcommand(
02072     new CmdMolChangeRepItem(repid, molid, CmdMolChangeRepItem::COLOR, color));
02073   return 1;
02074 }
02075 const char *VMDApp::molrep_get_selection(int molid, int repid) {
02076   if (repid < 0 || repid >= num_molreps(molid)) return NULL;
02077   DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02078   if (item == NULL)
02079     return NULL;
02080   return item->atomSel->cmdStr;
02081 }
02082 int VMDApp::molrep_set_selection(int molid, int repid, const char *selection) {
02083   int ind = moleculeList->mol_index_from_id(molid);
02084   if (ind < 0) return FALSE;
02085   if (!moleculeList->change_repsel(repid, ind, selection)) 
02086       return FALSE;
02087   commandQueue->runcommand(
02088     new CmdMolChangeRepItem(repid, molid, CmdMolChangeRepItem::SEL, selection));
02089   return TRUE;
02090 }
02091 int VMDApp::molrep_numselected(int molid, int repid) {
02092   if (repid >= num_molreps(molid)) return  -1;
02093   DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02094   if (item == NULL)
02095     return -1;
02096   return item->atomSel->selected;
02097 }
02098 const char *VMDApp::molrep_get_material(int molid, int repid) {
02099   if (repid >= num_molreps(molid)) return NULL;
02100   DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02101   if (item == NULL)
02102     return NULL;
02103   return materialList->material_name(item->curr_material());
02104 }
02105 int VMDApp::molrep_set_material(int molid, int repid, const char *material) {
02106   int ind = moleculeList->mol_index_from_id(molid);
02107   if (ind < 0) return 0;
02108   if (!moleculeList->change_repmat(repid, ind, (char *)material)) return 0;
02109   commandQueue->runcommand(
02110     new CmdMolChangeRepItem(repid, molid, CmdMolChangeRepItem::MAT, material));
02111   return 1;
02112 }
02113 const char *VMDApp::molecule_get_style() {
02114   return moleculeList->representation();
02115 }
02116 int VMDApp::molecule_set_style(const char *style) {
02117   if (!moleculeList->set_representation((char *)style))
02118     return 0;
02119   commandQueue->runcommand(new CmdMolRep(style));
02120   return 1;
02121 }
02122 const char *VMDApp::molecule_get_color() {
02123   return moleculeList->color();
02124 }
02125 int VMDApp::molecule_set_color(const char *color) {
02126   if (!moleculeList->set_color((char *)color)) 
02127     return 0;
02128   commandQueue->runcommand(new CmdMolColor(color));
02129   return 1;
02130 }
02131 const char *VMDApp::molecule_get_selection() {
02132   return moleculeList->selection();
02133 }
02134 int VMDApp::molecule_set_selection(const char *selection) {
02135   if (!moleculeList->set_selection(selection))
02136     return FALSE;
02137   commandQueue->runcommand(new CmdMolSelect(selection));
02138   return TRUE;
02139 }
02140 const char *VMDApp::molecule_get_material() {
02141   return moleculeList->material();
02142 }
02143 int VMDApp::molecule_set_material(const char *material) {
02144   if (!moleculeList->set_material((char *)material))
02145     return 0;
02146   commandQueue->runcommand(new CmdMolMaterial(material));
02147   return 1;
02148 }
02149 int VMDApp::molecule_addrep(int molid) {
02150   int ind = moleculeList->mol_index_from_id(molid);
02151   if (ind < 0) return 0;
02152   if (!moleculeList->add_rep(ind)) return 0;
02153   commandQueue->runcommand(new CmdMolAddRep(molid));
02154   return 1;
02155 }
02156 int VMDApp::molecule_modrep(int molid, int repid) {
02157   int ind = moleculeList->mol_index_from_id(molid);
02158   if (ind < 0) return 0;
02159   if (!moleculeList->change_rep(repid, ind)) return 0;
02160   commandQueue->runcommand(new CmdMolChangeRep(molid, repid));
02161   return 1;
02162 } 
02163 int VMDApp::molrep_delete(int molid, int repid) {
02164   int ind = moleculeList->mol_index_from_id(molid);
02165   if (ind < 0) return 0;
02166   if (!moleculeList->del_rep(repid, ind)) return 0;
02167   commandQueue->runcommand(new CmdMolDeleteRep(repid, molid));
02168   return 1;
02169 }
02170 
02171 int VMDApp::molrep_get_selupdate(int molid, int repid) {
02172   if (repid >= num_molreps(molid)) return 0;
02173   DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02174   if (item == NULL || item->atomSel == NULL)
02175     return 0;
02176   return item->atomSel->do_update; 
02177 } 
02178 int VMDApp::molrep_set_selupdate(int molid, int repid, int onoff) {
02179   if (repid >= num_molreps(molid)) return 0;
02180   DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02181   if (item == NULL || item->atomSel == NULL)
02182     return 0;
02183   item->atomSel->do_update = onoff;
02184   commandQueue->runcommand(new CmdMolRepSelUpdate(repid, molid, onoff));
02185   return 1;
02186 } 
02187 
02188 int VMDApp::molrep_set_colorupdate(int molid, int repid, int onoff) {
02189   if (repid >= num_molreps(molid)) return 0;
02190   DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02191   if (item == NULL || item->atomColor == NULL)
02192     return 0;
02193   item->atomColor->do_update = onoff;
02194   if (onoff) item->force_recalc(DrawMolItem::COL_REGEN);
02195   commandQueue->runcommand(new CmdMolRepColorUpdate(repid, molid, onoff));
02196   return 1;
02197 } 
02198 int VMDApp::molrep_get_colorupdate(int molid, int repid) {
02199   if (repid >= num_molreps(molid)) return 0;
02200   DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02201   if (item == NULL || item->atomColor == NULL)
02202     return 0;
02203   return item->atomColor->do_update;
02204 }
02205 
02206 int VMDApp::molrep_set_smoothing(int molid, int repid, int n) {
02207   if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
02208   DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02209   if (item->get_smoothing() == n) return TRUE;
02210   if (item->set_smoothing(n)) {
02211     item->force_recalc(DrawMolItem::MOL_REGEN);
02212     commandQueue->runcommand(new CmdMolSmoothRep(molid, repid, n));
02213     return TRUE;
02214   }
02215   return FALSE;
02216 }
02217 int VMDApp::molrep_get_smoothing(int molid, int repid) {
02218   if (repid < 0 || repid >= num_molreps(molid)) return -1;
02219   DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02220   return item->get_smoothing();
02221 }
02222 
02223 int VMDApp::molrep_set_pbc(int molid, int repid, int pbc) {
02224   if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
02225   DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02226   item->set_pbc(pbc);
02227   commandQueue->runcommand(new CmdMolShowPeriodic(molid, repid, pbc));
02228   return TRUE;
02229 }
02230 int VMDApp::molrep_get_pbc(int molid, int repid) {
02231   if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
02232   const DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02233   return item->get_pbc();
02234 }
02235 
02236 int VMDApp::molrep_set_pbc_images(int molid, int repid, int n) {
02237   if (n < 1) return FALSE;
02238   if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
02239   DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02240   item->set_pbc_images(n);
02241   commandQueue->runcommand(new CmdMolNumPeriodic(molid, repid, n));
02242   return TRUE;
02243 }
02244 int VMDApp::molrep_get_pbc_images(int molid, int repid) {
02245   if (repid < 0 || repid >= num_molreps(molid)) return -1;
02246   const DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02247   return item->get_pbc_images();
02248 }
02249 
02250 
02251 int VMDApp::molecule_set_dataset_flag(int molid, const char *dataflagstr,
02252                                       int setval) {
02253   int dataflag=BaseMolecule::NODATA;
02254   Molecule *m = moleculeList->mol_from_id(molid);
02255   if (!m) return 0;
02256 
02257   // which flag to set/clear
02258   if (!strcmp("insertion", dataflagstr)) {
02259     dataflag=BaseMolecule::INSERTION;
02260   } else if (!strcmp("occupancy", dataflagstr)) {
02261     dataflag=BaseMolecule::OCCUPANCY;
02262   } else if (!strcmp("beta", dataflagstr)) {
02263     dataflag=BaseMolecule::BFACTOR;
02264   } else if (!strcmp("mass", dataflagstr)) {
02265     dataflag=BaseMolecule::MASS;
02266   } else if (!strcmp("charge", dataflagstr)) {
02267     dataflag=BaseMolecule::CHARGE;
02268   } else if (!strcmp("radius", dataflagstr)) {
02269     dataflag=BaseMolecule::RADIUS;
02270   } else if (!strcmp("altloc", dataflagstr)) {
02271     dataflag=BaseMolecule::ALTLOC;
02272   } else if (!strcmp("atomicnumber", dataflagstr)) {
02273     dataflag=BaseMolecule::ATOMICNUMBER;
02274   } else if (!strcmp("bonds", dataflagstr)) {
02275     dataflag=BaseMolecule::BONDS;
02276   } else if (!strcmp("bondorders", dataflagstr)) {
02277     dataflag=BaseMolecule::BONDORDERS;
02278   } else if (!strcmp("bondtypes", dataflagstr)) {
02279     dataflag=BaseMolecule::BONDTYPES;
02280   } else if (!strcmp("angles", dataflagstr)) {
02281     dataflag=BaseMolecule::ANGLES;
02282   } else if (!strcmp("angletypes", dataflagstr)) {
02283     dataflag=BaseMolecule::ANGLETYPES;
02284   } else if (!strcmp("cterms", dataflagstr)) {
02285     dataflag=BaseMolecule::CTERMS;
02286   } else if (!strcmp("all", dataflagstr)) {
02287     dataflag=
02288       BaseMolecule::INSERTION    |
02289       BaseMolecule::OCCUPANCY    |
02290       BaseMolecule::BFACTOR      |
02291       BaseMolecule::MASS         |
02292       BaseMolecule::CHARGE       |
02293       BaseMolecule::RADIUS       |
02294       BaseMolecule::ALTLOC       |
02295       BaseMolecule::ATOMICNUMBER |
02296       BaseMolecule::BONDS        |
02297       BaseMolecule::BONDORDERS   |
02298       BaseMolecule::BONDTYPES    |
02299       BaseMolecule::ANGLES       |
02300       BaseMolecule::ANGLETYPES   |
02301       BaseMolecule::CTERMS;
02302   }
02303 
02304   // return an error if the flag string is unknown
02305   if (dataflag == BaseMolecule::NODATA)
02306     return 0;
02307 
02308   // set/unset the flag if we recognized it
02309   if (setval)
02310     m->set_dataset_flag(dataflag); 
02311   else
02312     m->unset_dataset_flag(dataflag); 
02313 
02314   return 1;
02315 }
02316 
02317 
02318 int VMDApp::molecule_reanalyze(int molid) {
02319   Molecule *m = moleculeList->mol_from_id(molid);
02320   if (!m) return 0;
02321 
02322   // (re)analyze the molecular structure, since bonds may have been changed
02323   m->analyze();
02324 
02325   // force all reps and selections to be recalculated
02326   m->force_recalc(DrawMolItem::COL_REGEN | 
02327                   DrawMolItem::MOL_REGEN |
02328                   DrawMolItem::SEL_REGEN);
02329 
02330   // regen secondary structure as well
02331   m->invalidate_ss();
02332 
02333   // log the command
02334   commandQueue->runcommand(new CmdMolReanalyze(molid));
02335   commandQueue->runcommand(new MoleculeEvent(molid, MoleculeEvent::MOL_REGEN));
02336   return TRUE;
02337 }
02338 int VMDApp::molecule_bondsrecalc(int molid) {
02339   Molecule *m = moleculeList->mol_from_id(molid);
02340   if (!m) return 0;
02341   if (m->recalc_bonds()) return 0;
02342   commandQueue->runcommand(new CmdMolBondsRecalc(molid));
02343   commandQueue->runcommand(new MoleculeEvent(molid, MoleculeEvent::MOL_REGEN));
02344   return 1;
02345 }
02346 int VMDApp::molecule_ssrecalc(int molid) {
02347   Molecule *m = moleculeList->mol_from_id(molid);
02348   if (!m) return FALSE;
02349   if (!m->recalc_ss()) return FALSE;
02350   commandQueue->runcommand(new CmdMolSSRecalc(molid));
02351   return TRUE;
02352 }
02353 int VMDApp::molecule_numatoms(int molid) {
02354   Molecule *m = moleculeList->mol_from_id(molid);
02355   if (!m) return -1;
02356   return m->nAtoms;
02357 }
02358 int VMDApp::molecule_numframes(int molid) {
02359   Molecule *m = moleculeList->mol_from_id(molid);
02360   if (!m) return -1;
02361   return m->numframes();
02362 } 
02363 int VMDApp::molecule_frame(int molid) {
02364   Molecule *m = moleculeList->mol_from_id(molid);
02365   if (!m) return -1;
02366   return m->frame();
02367 } 
02368 int VMDApp::molecule_dupframe(int molid, int frame) {
02369   Molecule *m = moleculeList->mol_from_id(molid);
02370   if (!m) {
02371     msgErr << "molecule_dupframe: invalid molecule" << sendmsg;
02372     return FALSE;
02373   }
02374   if (frame >= m->numframes()) {
02375     msgErr << "molecule_dupframe: frame out of range" << sendmsg;
02376     return FALSE;
02377   }
02378   if (frame == -1) {
02379     m->duplicate_frame(m->current());
02380   } else {
02381     m->duplicate_frame(m->get_frame(frame));
02382   }
02383   commandQueue->runcommand(new CmdAnimDup(frame, molid));
02384   return TRUE;
02385 }
02386 
02387 const char *VMDApp::molecule_name(int molid) {
02388   Molecule *m = moleculeList->mol_from_id(molid);
02389   if (!m) return NULL;
02390   return m->molname();
02391 } 
02392 int VMDApp::molecule_rename(int molid, const char *newname) {
02393   Molecule *m = moleculeList->mol_from_id(molid);
02394   if (!m) return 0;
02395   if (!newname) return 0;
02396   if (!m->rename(newname)) return 0;
02397   
02398   // Add item to Molecule color category; default color should be the same as
02399   // the original molecule.  
02400   int ind = moleculeList->colorCatIndex[MLCAT_MOLECULES];
02401   scene->add_color_item(ind, newname, m->id() % VISCLRS);
02402   
02403   commandQueue->runcommand(new CmdMolRename(molid, newname));
02404   commandQueue->runcommand(new MoleculeEvent(molid, MoleculeEvent::MOL_RENAME));
02405   return 1;
02406 }
02407 
02410 int VMDApp::molecule_orblocalize(int molid, int waveid) {
02411   Molecule *m = moleculeList->mol_from_id(molid);
02412   if (!m) return 0;
02413 
02414   float *expandedbasis = NULL;
02415   int *numprims = NULL;
02416   m->qm_data->expand_basis_array(expandedbasis, numprims);
02417 
02418   int i;
02419   for (i=0; i<m->numframes(); i++) {
02420     msgInfo << "Localizing orbitals for wavefunction " << waveid
02421             << " in frame " << i << sendmsg;
02422     m->qm_data->orblocalize(m->get_frame(i), waveid, expandedbasis, numprims);
02423   }
02424 
02425   delete [] expandedbasis;
02426   delete [] numprims;
02427   // XXX need to add commandQueue->runcommand()
02428   return 1;
02429 }
02430 
02431 int VMDApp::molecule_add_volumetric(int molid, const char *dataname, 
02432     const float origin[3], const float xaxis[3], const float yaxis[3],
02433     const float zaxis[3], int xsize, int ysize, int zsize, float *datablock) {
02434   
02435   Molecule *m = moleculeList->mol_from_id(molid);
02436   if (!m) return 0;
02437   m->add_volume_data(dataname, origin, xaxis, yaxis, zaxis, xsize, ysize, 
02438     zsize, datablock);
02439 
02440   scene_resetview_newmoldata(); // reset the view so we can see the dataset.
02441   commandQueue->runcommand(new CmdMolVolume(molid));
02442   return 1;
02443 }
02444 
02445 void VMDApp::set_mouse_callbacks(int on) {
02446   mouse->set_callbacks(on);
02447 }
02448 
02449 void VMDApp::set_mouse_rocking(int on) {
02450   mouse->set_rocking(on);
02451 }
02452 
02453 int VMDApp::num_clipplanes() {
02454   return VMD_MAX_CLIP_PLANE;
02455 }
02456 int VMDApp::molrep_get_clipplane(int molid, int repid, int clipid,
02457                         float *center, float *normal, float *color, int *mode) {
02458   Molecule *mol = moleculeList->mol_from_id(molid);
02459   if (!mol) return 0;
02460   Displayable *d = mol->component(repid);
02461   if (!d) return 0;
02462   const VMDClipPlane *c = d->clipplane(clipid);
02463   if (!c) return 0;
02464   memcpy(center, c->center, 3*sizeof(float));
02465   memcpy(normal, c->normal, 3*sizeof(float));
02466   memcpy(color, c->color, 3*sizeof(float));
02467   *mode = c->mode;
02468   return 1;
02469 }
02470 int VMDApp::molrep_set_clipcenter(int molid, int repid, int clipid,
02471                                  const float *center) {
02472   Molecule *mol = moleculeList->mol_from_id(molid);
02473   if (!mol) return 0;
02474   Displayable *d = mol->component(repid);
02475   if (!d) return 0;
02476   return d->set_clip_center(clipid, center);
02477 }
02478 int VMDApp::molrep_set_clipnormal(int molid, int repid, int clipid,
02479                                  const float *normal) {
02480   Molecule *mol = moleculeList->mol_from_id(molid);
02481   if (!mol) return 0;
02482   Displayable *d = mol->component(repid);
02483   if (!d) return 0;
02484   return d->set_clip_normal(clipid, normal);
02485 }
02486 int VMDApp::molrep_set_clipcolor(int molid, int repid, int clipid,
02487                                  const float *color) {
02488   Molecule *mol = moleculeList->mol_from_id(molid);
02489   if (!mol) return 0;
02490   Displayable *d = mol->component(repid);
02491   if (!d) return 0;
02492   return d->set_clip_color(clipid, color);
02493 }
02494 int VMDApp::molrep_set_clipstatus(int molid, int repid, int clipid, int mode) {
02495   Molecule *mol = moleculeList->mol_from_id(molid);
02496   if (!mol) return 0;
02497   Displayable *d = mol->component(repid);
02498   if (!d) return 0;
02499   return d->set_clip_status(clipid, mode);
02500 }
02501  
02502 const char *VMDApp::molrep_get_name(int molid, int repid) {
02503   Molecule *mol = moleculeList->mol_from_id(molid);  
02504   if (!mol) return NULL;
02505   return mol->get_component_name(repid);
02506 }
02507 
02508 int VMDApp::molrep_get_by_name(int molid, const char *name) {
02509   Molecule *mol = moleculeList->mol_from_id(molid);  
02510   if (!mol) return -1;
02511   return mol->get_component_by_name(name);
02512 }
02513 
02514 int VMDApp::molrep_get_scaleminmax(int molid, int repid, float *min, float *max) {
02515   if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
02516   const DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02517 #if 0
02518   // XXX Axel's color data range auto scale patch to fix the "two clicks"
02519   // problem he discovered with some volumetric datasets.  Needs closer
02520   // examination when I have a few minutes, but this will get him by for
02521   // the CPMD tutorial.
02522   Molecule *mol = moleculeList->mol_from_id(molid);
02523   item->atomColor->rescale_colorscale_minmax();
02524   item->atomColor->find(mol);
02525 #endif
02526   item->atomColor->get_colorscale_minmax(min, max);
02527   return TRUE;
02528 }
02529 int VMDApp::molrep_set_scaleminmax(int molid, int repid, float min, float max) {
02530   if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
02531   DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02532   if (item->atomColor->set_colorscale_minmax(min, max)) {
02533     item->force_recalc(DrawMolItem::COL_REGEN);
02534     commandQueue->runcommand(new CmdMolScaleMinmax(molid, repid, min, max));
02535     return TRUE;
02536   }
02537   return FALSE;
02538 }
02539 int VMDApp::molrep_reset_scaleminmax(int molid, int repid) {
02540   if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
02541   DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02542   item->atomColor->rescale_colorscale_minmax();
02543   item->force_recalc(DrawMolItem::COL_REGEN);
02544   commandQueue->runcommand(new CmdMolScaleMinmax(molid, repid, 0, 0, 1));
02545   return TRUE;
02546 }
02547 
02548 int VMDApp::molrep_set_drawframes(int molid, int repid, const char *framesel) {
02549   if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
02550   if (!framesel) {
02551     msgErr << "molrep_set_drawframes: Error, framesel is NULL!" << sendmsg;
02552     return FALSE;
02553   }
02554   DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02555   item->set_drawframes(framesel);
02556   commandQueue->runcommand(new CmdMolDrawFrames(molid, repid, framesel));
02557   return TRUE;
02558 }
02559 
02560 const char *VMDApp::molrep_get_drawframes(int molid, int repid) {
02561   if (repid < 0 || repid >= num_molreps(molid)) return NULL;
02562   const DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02563   return item->get_drawframes();
02564 }
02565 
02566 int VMDApp::molrep_show(int molid, int repid, int onoff) {
02567   if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
02568   moleculeList->mol_from_id(molid)->show_rep(repid, onoff);
02569   commandQueue->runcommand(new CmdMolShowRep(molid, repid, onoff));
02570   return TRUE;
02571 }
02572 
02573 int VMDApp::molrep_is_shown(int molid, int repid) {
02574   if (repid < 0 || repid >= num_molreps(molid)) return FALSE;
02575   DrawMolItem *item = moleculeList->mol_from_id(molid)->component(repid);
02576   return item->displayed();
02577 }
02578 
02579 
02580 //
02581 // IMD methods
02582 //
02583 int VMDApp::imd_connect(int molid, const char *host, int port) {
02584 #ifdef VMDIMD 
02585   Molecule *mol = moleculeList->mol_from_id(molid);  
02586   if (!mol) return 0;
02587   if (!imdMgr) return 0;
02588   if (imdMgr->connect(mol, host, port)) {
02589     // tell the world
02590     commandQueue->runcommand(new CmdIMDConnect(molid,host, port));
02591     return 1;
02592   }
02593 #endif
02594   return 0;
02595 }
02596 
02597 int VMDApp::imd_connected(int molid) {
02598 #ifdef VMDIMD
02599   if (!imdMgr) return 0;
02600   Molecule *mol = imdMgr->get_imdmol();
02601   if (mol) {
02602     return (mol->id() == molid);
02603   }
02604 #endif
02605   return 0;
02606 }
02607 
02608 int VMDApp::imd_sendforces(int num, const int *ind, const float *forces) {
02609 #ifdef VMDIMD
02610   if (!imdMgr) return 0;
02611   return imdMgr->send_forces(num, ind, forces);
02612 #endif
02613   return 0;
02614 }
02615 
02616 int VMDApp::imd_disconnect(int molid) {
02617 #ifdef VMDIMD
02618   if (!imdMgr) return FALSE;
02619   Molecule *mol  = imdMgr->get_imdmol();
02620   if (mol && mol->id() == molid) {
02621     imdMgr->detach();
02622     return TRUE;
02623   }
02624 #endif
02625   return FALSE;
02626 }
02627 
02628 void VMDApp::display_set_screen_height(float ht) {
02629   if (!display) return;
02630   display->screen_height(ht);
02631   commandQueue->runcommand(new CmdDisplayScreenHeight(ht));
02632 }
02633 float VMDApp::display_get_screen_height() {
02634   if (!display) return 0.0f;
02635   return display->screen_height();
02636 }
02637 void VMDApp::display_set_screen_distance(float d) {
02638   if (!display) return;
02639   display->distance_to_screen(d);
02640   commandQueue->runcommand(new CmdDisplayScreenDistance(d));
02641 }
02642 float VMDApp::display_get_screen_distance() {
02643   if (!display) return 0.0f;
02644   return display->distance_to_screen();
02645 }
02646 void VMDApp::display_set_position(int x, int y) {
02647   if (display)
02648     display->reposition_window(x, y);
02649 }
02650 #if 0
02651 void VMDApp::display_get_position(int *x, int *y) {
02652   if (display) {
02653     display->window_position(x, y);
02654   }
02655 }
02656 #endif
02657 void VMDApp::display_set_size(int w, int h) {
02658   if (display) {
02659     display->resize_window(w, h);
02660     // do an update so that the new size of the window becomes immediately
02661     // available.  
02662     display_update_ui();
02663   }
02664 }
02665 void VMDApp::display_get_size(int *w, int *h) {
02666   if (display) {
02667     *w = display->xSize;
02668     *h = display->ySize;
02669   }
02670 }
02671 void VMDApp::display_titlescreen() {
02672   if (display && display->supports_gui()) {
02673     delete vmdTitle;
02674     vmdTitle = new VMDTitle(display, &(scene->root));
02675   }
02676 }
02677 
02678 int VMDApp::display_set_stereo(const char *mode) {
02679   if (!mode) 
02680     return FALSE;
02681 
02682   int i, j;
02683   for (i=0; i<display->num_stereo_modes(); i++) {
02684     if (!strcmp(mode, display->stereo_name(i))) {
02685       display->set_stereo_mode(i);
02686       commandQueue->runcommand(new CmdDisplayStereo(mode));
02687       return TRUE;
02688     }
02689   }
02690 
02691   // Backwards compatibility with old scripts...
02692   const char *OldStereoNames[] = { 
02693     "CrystalEyes", "CrystalEyesReversed", "CrossEyes" 
02694   };
02695   const char *NewStereoNames[] = {
02696     "QuadBuffered", "QuadBuffered", "SideBySide" 
02697   };
02698   for (j=0; j<3; j++) {
02699     if (!strcmp(mode, OldStereoNames[j])) {
02700       for (i=0; i<display->num_stereo_modes(); i++) {
02701         if (!strcmp(NewStereoNames[j], display->stereo_name(i))) {
02702           display->set_stereo_mode(i);
02703           commandQueue->runcommand(new CmdDisplayStereo(NewStereoNames[j]));
02704 
02705           // preserve the swapped eye behavior of the old stereo mode names
02706           if (!strcmp(mode, "CrystalEyesReversed") ||
02707               !strcmp(mode, "CrossEyes")) {
02708             display_set_stereo_swap(1); 
02709           } 
02710           return TRUE;
02711         }
02712       }
02713     }
02714   }
02715 
02716   msgErr << "Illegal stereo mode: " << mode << sendmsg;
02717   return FALSE;
02718 }
02719 
02720 int VMDApp::display_set_stereo_swap(int onoff) {
02721   if (!onoff) {
02722     display->set_stereo_swap(0);
02723     commandQueue->runcommand(new CmdDisplayStereoSwap(0));
02724     return TRUE;
02725   }
02726 
02727   display->set_stereo_swap(1);
02728   commandQueue->runcommand(new CmdDisplayStereoSwap(1));
02729   return TRUE;
02730 }
02731 
02732 int VMDApp::display_set_cachemode(const char *mode) {
02733   if (!mode) return FALSE;
02734   for (int i=0; i<display->num_cache_modes(); i++) {
02735     if (!strcmp(mode, display->cache_name(i))) {
02736       display->set_cache_mode(i);
02737       commandQueue->runcommand(new CmdDisplayCacheMode(mode));
02738       return TRUE;
02739     }
02740   }
02741   msgErr << "Illegal cache mode: " << mode << sendmsg;
02742   return FALSE;
02743 }
02744 
02745 int VMDApp::display_set_rendermode(const char *mode) {
02746   if (!mode) return FALSE;
02747   for (int i=0; i<display->num_render_modes(); i++) {
02748     if (!strcmp(mode, display->render_name(i))) {
02749       display->set_render_mode(i);
02750       commandQueue->runcommand(new CmdDisplayRenderMode(mode));
02751       return TRUE;
02752     }
02753   }
02754   msgErr << "Illegal rendering mode: " << mode << sendmsg;
02755   return FALSE;
02756 }
02757 
02758 int VMDApp::display_set_eyesep(float sep) {
02759   if (sep < 0) return FALSE;
02760   display->set_eyesep(sep);
02761   commandQueue->runcommand(new CmdDisplayEyesep(sep));
02762   return TRUE;
02763 }
02764 
02765 int VMDApp::display_set_focallen(float flen) {
02766   if (!display->set_eye_dist(flen)) return FALSE;
02767   commandQueue->runcommand(new CmdDisplayFocallen(flen));
02768   return TRUE;
02769 }
02770 
02771 int VMDApp::display_set_projection(const char *proj) {
02772   if (!display->set_projection(proj)) return FALSE;
02773   commandQueue->runcommand(new CmdDisplayProj(proj));
02774   return TRUE;
02775 }
02776 
02777 int VMDApp::display_projection_is_perspective(void) {
02778   if (display->projection() == DisplayDevice::ORTHOGRAPHIC)
02779     return FALSE;
02780 
02781   return TRUE;
02782 }
02783 
02784 int VMDApp::display_set_aa(int onoff) {
02785   if (!display->aa_available()) return FALSE;
02786   if (onoff) display->aa_on(); else display->aa_off();
02787   commandQueue->runcommand(new CmdDisplayAAOn(onoff));
02788   return TRUE;
02789 }
02790 
02791 int VMDApp::display_set_depthcue(int onoff) {
02792   if (!display->cueing_available()) return FALSE;
02793   if (onoff) display->cueing_on(); else display->cueing_off();
02794   commandQueue->runcommand(new CmdDisplayDepthcueOn(onoff));
02795   return TRUE;
02796 }
02797 
02798 int VMDApp::display_set_culling(int onoff) {
02799   if (!display->culling_available()) return FALSE;
02800   if (onoff) display->culling_on(); else display->culling_off();
02801   commandQueue->runcommand(new CmdDisplayCullingOn(onoff));
02802   return TRUE;
02803 }
02804 
02805 int VMDApp::display_set_fps(int onoff) {
02806   if (onoff) fps->on(); else fps->off();
02807   commandQueue->runcommand(new CmdDisplayFPSOn(onoff));
02808   return TRUE;
02809 }
02810 
02811 int VMDApp::display_set_background_mode(int mode) {
02812   scene->set_background_mode(mode);
02813   commandQueue->runcommand(new CmdDisplayBackgroundGradientOn(mode));
02814   return TRUE;
02815 }
02816 
02817 int VMDApp::display_set_nearclip(float amt, int isdelta) {
02818   if (isdelta) {
02819     display->addto_near_clip(amt); 
02820     commandQueue->runcommand(new CmdDisplayClipNearRel(amt));
02821   } else {
02822     // prevent illegal near clipping plane values from causing problems
02823     if (amt <= 0.0)
02824       amt = 0.001f;
02825     display->set_near_clip(amt);
02826     commandQueue->runcommand(new CmdDisplayClipNear(amt));
02827   }
02828   return TRUE;
02829 }
02830 
02831 int VMDApp::display_set_farclip(float amt, int isdelta) {
02832   if (isdelta) {
02833     display->addto_far_clip(amt); 
02834     commandQueue->runcommand(new CmdDisplayClipFarRel(amt));
02835   } else {
02836     display->set_far_clip(amt);
02837     commandQueue->runcommand(new CmdDisplayClipFar(amt));
02838   }
02839   return TRUE;
02840 }
02841 
02842 int VMDApp::stage_set_location (const char *pos) {
02843   if (!pos) return FALSE;
02844   for (int i=0; i<stage->locations(); i++) {
02845     if (!strupcmp(pos, stage->loc_description(i))) {
02846       stage->location(i);
02847       commandQueue->runcommand(new CmdDisplayStageLocation(pos));
02848       return TRUE;
02849     }
02850   }
02851   return FALSE;
02852 }
02853 
02854 int VMDApp::stage_set_numpanels(int num) {
02855   if (!stage->panels(num)) return FALSE;
02856   commandQueue->runcommand(new CmdDisplayStagePanels(num));
02857   return TRUE;
02858 }
02859 
02860 int VMDApp::stage_set_size(float sz) {
02861   if (!stage->size(sz)) return FALSE;
02862   commandQueue->runcommand(new CmdDisplayStageSize(sz));
02863   return TRUE;
02864 }
02865 
02866 int VMDApp::axes_set_location (const char *pos) {
02867   if (!pos) return FALSE;
02868   for (int i=0; i<axes->locations(); i++) {
02869     if (!strupcmp(pos, axes->loc_description(i))) {
02870       axes->location(i);
02871       commandQueue->runcommand(new CmdDisplayAxes(pos));
02872       return TRUE;
02873     }
02874   }
02875   return FALSE;
02876 }
02877 
02878 int VMDApp::light_on(int n, int onoff) {
02879   if (n<0 || n >= DISP_LIGHTS) return FALSE;
02880   scene->activate_light(n, onoff);
02881   commandQueue->runcommand(new CmdDisplayLightOn(n, onoff));
02882   return TRUE;
02883 }
02884 int VMDApp::light_highlight(int n, int onoff) {
02885   if (n<0 || n >= DISP_LIGHTS) return FALSE;
02886   scene->highlight_light(n, onoff);
02887   commandQueue->runcommand(new CmdDisplayLightHL(n, onoff));
02888   return TRUE;
02889 }
02890 
02891 int VMDApp::light_rotate(int n, float amt, char axis) {
02892   if (n<0 || n >= DISP_LIGHTS) return FALSE;
02893   scene->rotate_light(n, amt, axis);
02894   commandQueue->runcommand(new CmdDisplayLightRot(n, amt, axis));
02895   return TRUE;
02896 }
02897 
02898 int VMDApp::light_move(int n, const float *newpos) {
02899   if (n<0 || n >= DISP_LIGHTS) return FALSE;
02900   scene->move_light(n, newpos);
02901   commandQueue->runcommand(new CmdDisplayLightMove(n, newpos));
02902   return TRUE;
02903 }
02904 
02905 int VMDApp::depthcue_set_mode(const char *mode) {
02906   if (!display->set_cue_mode(mode)) return FALSE;
02907   commandQueue->runcommand(new CmdDisplayCueMode(mode));
02908   return TRUE;
02909 }
02910 
02911 int VMDApp::depthcue_set_start(float val) {
02912   if (!display->set_cue_start(val)) return FALSE;
02913   commandQueue->runcommand(new CmdDisplayCueStart(val));
02914   return TRUE;
02915 }
02916 
02917 int VMDApp::depthcue_set_end(float val) {
02918   if (!display->set_cue_end(val)) return FALSE;
02919   commandQueue->runcommand(new CmdDisplayCueEnd(val));
02920   return TRUE;
02921 }
02922 
02923 int VMDApp::depthcue_set_density(float val) {
02924   if (!display->set_cue_density(val)) return FALSE;
02925   commandQueue->runcommand(new CmdDisplayCueDensity(val));
02926   return TRUE;
02927 }
02928 
02929 int VMDApp::display_set_shadows(int onoff) {
02930   if (!display->set_shadow_mode(onoff)) return FALSE;
02931   commandQueue->runcommand(new CmdDisplayShadowOn(onoff));
02932   return TRUE;
02933 } 
02934 
02935 int VMDApp::display_set_ao(int onoff) {
02936   if (!display->set_ao_mode(onoff)) return FALSE;
02937   commandQueue->runcommand(new CmdDisplayAOOn(onoff));
02938   return TRUE;
02939 } 
02940 
02941 int VMDApp::display_set_ao_ambient(float val) {
02942   if (!display->set_ao_ambient(val)) return FALSE;
02943   commandQueue->runcommand(new CmdDisplayAOAmbient(val));
02944   return TRUE;
02945 }
02946 
02947 int VMDApp::display_set_ao_direct(float val) {
02948   if (!display->set_ao_direct(val)) return FALSE;
02949   commandQueue->runcommand(new CmdDisplayAODirect(val));
02950   return TRUE;
02951 }
02952 
02953 void VMDApp::deactivate_uitext_stdin() {
02954   if (uiText)
02955     uiText->Off();
02956 }
02957 
02958 int VMDApp::activate_menus() {
02959   // XXX This should control Tk menus as well; at present Tk menus are 
02960   // available whenever the display supports GUI's.
02961 
02962 #ifdef VMDGUI
02963   if(display->supports_gui()) {
02964 
02965     delete uivr;
02966     uivr = new UIVR(this);
02967     uivr->On();
02968 
02969     // if we are using the FLTK library ...
02970 #ifdef VMDFLTK
02971   VMDMenu *obj;
02972   obj = new MainFltkMenu(this);
02973   menulist->add_name(obj->get_name(), obj);
02974   obj = new ColorFltkMenu(this);
02975   menulist->add_name(obj->get_name(), obj);
02976   obj = new MaterialFltkMenu(this);
02977   menulist->add_name(obj->get_name(), obj);
02978   obj = new DisplayFltkMenu(this);
02979   menulist->add_name(obj->get_name(), obj);
02980   obj = new FileChooserFltkMenu(this);
02981   menulist->add_name(obj->get_name(), obj);
02982   obj = new GeometryFltkMenu(this);
02983   menulist->add_name(obj->get_name(), obj);
02984   obj = new GraphicsFltkMenu(this);
02985   menulist->add_name(obj->get_name(), obj);
02986   obj = new RenderFltkMenu(this);
02987   menulist->add_name(obj->get_name(), obj);
02988   obj = new SaveTrajectoryFltkMenu(this);
02989   menulist->add_name(obj->get_name(), obj);
02990   obj = new ToolFltkMenu(this);
02991   menulist->add_name(obj->get_name(), obj);
02992 #endif /*VMDFLTK*/
02993   }
02994   return TRUE;
02995 #endif /*VMDGUI*/
02996   
02997   // no menus available
02998   return FALSE;
02999 }
03000 
03001 int VMDApp::label_add(const char *category, int n, const int *molids, 
03002     const int *atomids, const int *cells, float k, int toggle) {
03003   if (!category || !molids || !atomids) return -1;
03004   int rc = geometryList->add_geometry(category, molids, atomids, cells, k, 
03005       toggle);
03006   if (rc >= 0) {
03007     if (!strcmp(category, "Springs"))
03008       commandQueue->runcommand(new CmdLabelAddspring(molids[0], atomids[0],
03009           atomids[1], k));
03010     else 
03011       commandQueue->runcommand(new CmdLabelAdd(category, n, (int *)molids, (int *)atomids));
03012   }
03013   return rc;
03014 }
03015 
03016 int VMDApp::label_show (const char *category, int n, int onoff) {
03017   if (!category) return FALSE;
03018   if (geometryList->show_geometry(category, n, onoff)) {
03019     commandQueue->runcommand(new CmdLabelShow(category, n, onoff));
03020     return TRUE;
03021   }
03022   return FALSE;
03023 }
03024 
03025 float VMDApp::label_get_text_size() const {
03026   return geometryList->getTextSize();
03027 }
03028 
03029 int VMDApp::label_set_text_size(float newsize) {
03030   if (geometryList->setTextSize(newsize)) {
03031     commandQueue->runcommand(new CmdLabelTextSize(newsize));
03032     return TRUE;
03033   }
03034   return FALSE;
03035 }
03036 
03037 float VMDApp::label_get_text_thickness() const {
03038   return geometryList->getTextThickness();
03039 }
03040 
03041 int VMDApp::label_set_text_thickness(float newthick) {
03042   if (geometryList->setTextThickness(newthick)) {
03043     commandQueue->runcommand(new CmdLabelTextThickness(newthick));
03044     return TRUE;
03045   }
03046   return FALSE;
03047 }
03048 
03049 int VMDApp::label_set_textoffset(const char *nm, int n, float x, float y) {
03050   float delta[2] = { x, y };
03051   if (geometryList->setTextOffset(nm, n, delta)) {
03052     commandQueue->runcommand(new CmdLabelTextOffset(nm, n, x, y));
03053     return TRUE;
03054   }
03055   return FALSE;
03056 }
03057 
03058 int VMDApp::label_set_textformat(const char *nm, int n, const char *format) {
03059   if (geometryList->setTextFormat(nm, n, format)) {
03060     commandQueue->runcommand(new CmdLabelTextFormat(nm, n, format));
03061     return TRUE;
03062   }
03063   return FALSE;
03064 }
03065 
03066 int VMDApp::label_delete(const char *category, int n) {
03067   if (!category) return FALSE;
03068   if (geometryList->del_geometry(category, n)) {
03069     commandQueue->runcommand(new CmdLabelDelete(category, n));
03070     return TRUE;
03071   }
03072   return FALSE;
03073 }
03074 
03075 int VMDApp::tool_create(const char *type, int argc, const char **argv) {
03076   if (!uivr) return FALSE;
03077   if (!uivr->add_tool_with_USL(type, argc, argv)) return FALSE;
03078   commandQueue->runcommand(new CmdToolCreate(type, argc, argv));
03079   return TRUE;
03080 }
03081 
03082 int VMDApp::tool_change_type(int toolnum, const char *type) {
03083   if (!uivr) return FALSE;
03084   if (!uivr->change_type(toolnum, type)) return FALSE;
03085   commandQueue->runcommand(new CmdToolChange(type, toolnum));
03086   return TRUE;
03087 }
03088 
03089 int VMDApp::tool_delete(int toolnum) {
03090   if (!uivr) return FALSE;
03091   if (!uivr->remove_tool(toolnum)) return FALSE;
03092   commandQueue->runcommand(new CmdToolDelete(toolnum));
03093   // XXXX fix this for multiple tools
03094   commandQueue->runcommand(new PickAtomCallbackEvent(-1,-1,"uivr"));
03095   return TRUE;
03096 }
03097 
03098 int VMDApp::tool_set_position_scale(int toolnum, float newval) {
03099   if (!uivr) return FALSE;
03100   if (uivr->set_position_scale(toolnum, newval)) {
03101     commandQueue->runcommand(new CmdToolScale(newval, toolnum));
03102     return TRUE;
03103   }
03104   return FALSE;
03105 }
03106 
03107 int VMDApp::tool_set_force_scale(int toolnum, float newval) {
03108   if (!uivr) return FALSE;
03109   if (uivr->set_force_scale(toolnum, newval)) {
03110     commandQueue->runcommand(new CmdToolScaleForce(newval, toolnum));
03111     return TRUE;
03112   }
03113   return FALSE;
03114 }
03115 
03116 int VMDApp::tool_set_spring_scale(int toolnum, float newval) {
03117   if (!uivr) return FALSE;
03118   if (uivr->set_spring_scale(toolnum, newval)) {
03119     commandQueue->runcommand(new CmdToolScaleSpring(newval, toolnum));
03120     return TRUE;
03121   }
03122   return FALSE;
03123 }
03124 
03125 const char *VMDApp::material_add(const char *name, const char *copy) {
03126   const char *newname = materialList->add_material(name, copy);
03127   if (newname) {
03128     commandQueue->runcommand(new CmdMaterialAdd(name, copy));
03129   }
03130   return newname;
03131 }
03132 
03133 int VMDApp::material_delete(const char *name) {
03134   char * strname = stringdup(name);
03135   int ind = materialList->material_index(strname);
03136   if (materialList->delete_material(ind)) {
03137     commandQueue->runcommand(new CmdMaterialDelete(strname));
03138     delete [] strname;
03139     return TRUE;
03140   }
03141   delete [] strname;
03142   return FALSE;
03143 }
03144 
03145 int VMDApp::material_rename(const char *prevname, const char *newname) {
03146   char * oldname = stringdup(prevname);
03147   int ind = materialList->material_index(oldname);
03148   if (ind < 0) {
03149     msgErr << "material rename: '" << oldname << "' does not exist."   
03150            << sendmsg;
03151     delete [] oldname;
03152     return FALSE;
03153   }
03154   int n = strlen(newname);
03155   if (!n) return FALSE;
03156   for (size_t i=0; i<strlen(newname); i++) {
03157     if (!isalnum(newname[i])) {
03158       msgErr << "material rename: new name contains non-alphanumeric character"
03159              << sendmsg;
03160       delete [] oldname;
03161       return FALSE;
03162     }
03163   }
03164   if (materialList->material_index(newname) >= 0) {
03165     msgErr << "material rename: '" << newname << "' already exists." 
03166            << sendmsg;
03167     delete [] oldname;
03168     return FALSE;
03169   }
03170   materialList->set_name(ind, newname);
03171   commandQueue->runcommand(new CmdMaterialRename(oldname, newname));
03172   delete [] oldname;
03173   return TRUE;
03174 }
03175 
03176 int VMDApp::material_change(const char *name, int property, float val) {
03177   int ind = materialList->material_index(name);
03178   if (ind < 0) return FALSE;
03179   switch (property) {
03180     case MAT_AMBIENT: materialList->set_ambient(ind, val); break;
03181     case MAT_SPECULAR: materialList->set_specular(ind, val); break;
03182     case MAT_DIFFUSE: materialList->set_diffuse(ind, val); break;
03183     case MAT_SHININESS: materialList->set_shininess(ind, val); break;
03184     case MAT_OPACITY: materialList->set_opacity(ind, val); break;
03185     case MAT_OUTLINE: materialList->set_outline(ind, val); break;
03186     case MAT_OUTLINEWIDTH: materialList->set_outlinewidth(ind, val); break;
03187     case MAT_TRANSMODE: materialList->set_transmode(ind, val); break;
03188   }
03189   commandQueue->runcommand(new CmdMaterialChange(name, property, val));
03190   return TRUE;
03191 }
03192 
03193 int VMDApp::material_restore_default(int ind) {
03194   if (materialList->restore_default(ind)) {
03195     commandQueue->runcommand(new CmdMaterialDefault(ind));
03196     return TRUE;
03197   }
03198   return FALSE;
03199 }
03200 
03201 int VMDApp::mouse_set_mode(int mm, int ms) {
03202   if (!mouse->move_mode((Mouse::MoveMode)mm, ms)) {
03203     msgErr << "Illegal mouse mode: " << mm << " " << ms << sendmsg;
03204     return FALSE;
03205   }
03206   
03207   // If mouse mode is a picking mode, set it here
03208   switch (mm) {
03209     case Mouse::PICK:        pickModeList->set_pick_mode(PickModeList::PICK); break;
03210     case Mouse::QUERY:       pickModeList->set_pick_mode(PickModeList::QUERY); break;
03211     case Mouse::CENTER:      pickModeList->set_pick_mode(PickModeList::CENTER); break;
03212     case Mouse::LABELATOM:   pickModeList->set_pick_mode(PickModeList::LABELATOM); break;
03213     case Mouse::LABELBOND:   pickModeList->set_pick_mode(PickModeList::LABELBOND); break;
03214     case Mouse::LABELANGLE:  pickModeList->set_pick_mode(PickModeList::LABELANGLE); break;
03215     case Mouse::LABELDIHEDRAL:  pickModeList->set_pick_mode(PickModeList::LABELDIHEDRAL); break;
03216     case Mouse::MOVEATOM:    pickModeList->set_pick_mode(PickModeList::MOVEATOM); break;
03217     case Mouse::MOVERES:     pickModeList->set_pick_mode(PickModeList::MOVERES); break;
03218     case Mouse::MOVEFRAG:    pickModeList->set_pick_mode(PickModeList::MOVEFRAG); break;
03219     case Mouse::MOVEMOL:     pickModeList->set_pick_mode(PickModeList::MOVEMOL); break;
03220     case Mouse::FORCEATOM:   pickModeList->set_pick_mode(PickModeList::FORCEATOM); break;
03221     case Mouse::FORCERES:    pickModeList->set_pick_mode(PickModeList::FORCERES); break;
03222     case Mouse::FORCEFRAG:   pickModeList->set_pick_mode(PickModeList::FORCEFRAG); break;
03223     case Mouse::MOVEREP:     pickModeList->set_pick_mode(PickModeList::MOVEREP); break;
03224     case Mouse::ADDBOND:     pickModeList->set_pick_mode(PickModeList::ADDBOND); break;
03225     default: break;
03226   }
03227   
03228   commandQueue->runcommand(new CmdMouseMode(mm, ms));
03229   return TRUE;
03230 }
03231 
03232 
03233 int VMDApp::mobile_set_mode(int mm) {
03234   if (!mobile->move_mode((Mobile::MoveMode) mm)) {
03235     msgErr << "Illegal mobile mode: " << mm << " " << sendmsg;
03236     return FALSE;
03237   }
03238   commandQueue->runcommand(new CmdMobileMode(mm));
03239   return TRUE;
03240 }
03241 
03242 int VMDApp::mobile_get_mode() {
03243   return mobile->get_move_mode();
03244 }
03245 
03246 void VMDApp::mobile_get_client_list(ResizeArray <JString*>* &nick, 
03247                          ResizeArray <JString*>* &ip, ResizeArray <bool>* &active) 
03248 {
03249   mobile->get_client_list(nick, ip, active);
03250 }
03251 
03252 int VMDApp::mobile_network_port(int port) {
03253   mobile->network_port(port);
03254   //  commandQueue->runcommand(new CmdMobileNetworkPort(port));
03255   return TRUE;
03256 }
03257 
03258 int VMDApp::mobile_get_network_port() {
03259   return mobile->get_port();
03260 }
03261 
03262 int VMDApp::mobile_get_APIsupported() {
03263   return mobile->get_APIsupported();
03264 }
03265 
03267 int VMDApp::mobile_set_activeClient(const char *nick, const char *ip) {
03268   return mobile->set_activeClient(nick, ip);
03269 }
03270 
03272 int VMDApp::mobile_sendMsg(const char *nick, const char *ip, 
03273                            const char *msgType, const char *msg) {
03274   return mobile->sendMsgToClient(nick, ip, msgType, msg);
03275 }
03276 
03277 
03280 void VMDApp::mobile_get_tracker_status(float &tx, float &ty, float &tz,
03281                                        float &rx, float &ry, float &rz,
03282                                        int &buttons) {
03283   if (mobile != NULL) {
03284     mobile->get_tracker_status(tx, ty, tz, rx, ry, rz, buttons);
03285   } else {
03286     tx=ty=tz=rx=ry=rz=0.0f;
03287     buttons=0;
03288   }
03289 }
03290 
03291 
03292 int VMDApp::spaceball_set_mode(int mm) {
03293   if (!spaceball->move_mode((Spaceball::MoveMode) mm)) {
03294     msgErr << "Illegal spaceball mode: " << mm << " " << sendmsg;
03295     return FALSE;
03296   }
03297   commandQueue->runcommand(new CmdSpaceballMode(mm));
03298   return TRUE;
03299 }
03300 
03301 
03302 int VMDApp::spaceball_set_sensitivity(float s) {
03303   spaceball->set_sensitivity(s);
03304   //  commandQueue->runcommand(new CmdSpaceballSensitivity(s));
03305   return TRUE;
03306 }
03307 
03308 
03309 int VMDApp::spaceball_set_null_region(int nr) {
03310   spaceball->set_null_region(nr);
03311   //  commandQueue->runcommand(new CmdSpaceballNullRegion(s));
03312   return TRUE;
03313 }
03314 
03315 
03318 void VMDApp::spaceball_get_tracker_status(float &tx, float &ty, float &tz,
03319                                           float &rx, float &ry, float &rz,
03320                                           int &buttons) {
03321   if (spaceball != NULL) {
03322     spaceball->get_tracker_status(tx, ty, tz, rx, ry, rz, buttons);
03323   } else {
03324     tx=ty=tz=rx=ry=rz=0.0f;
03325     buttons=0;
03326   }
03327 }
03328 
03329 
03330 int VMDApp::textinterp_change(const char *name) {
03331   return uiText->change_interp(name);
03332 }
03333 
03334 //
03335 // MPI related routines
03336 //
03337 void VMDApp::par_barrier() {
03338 #if defined(VMDMPI)
03339   vmd_mpi_barrier();
03340 #endif
03341 }
03342 

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