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

UIText.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2019 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: UIText.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.198 $      $Date: 2019/01/17 21:21:02 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *
00019  * This is the User Interface for text commands.  It reads characters from
00020  * the console, and executes the commands.
00021  *
00022  * This will use the Tcl library for general script interpretation, which
00023  * allows for general script capabilities such as variable substitution,
00024  * loops, etc.  If Tcl cannot be used, text commands will still be available
00025  * in the program, but the general script capabilities will be lost.
00026  ***************************************************************************/
00027 
00028 #ifdef VMDPYTHON
00029 #include "PythonTextInterp.h"
00030 #endif
00031 
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <ctype.h>
00035 
00036 #include "UIText.h"
00037 #include "TextEvent.h"
00038 #include "CommandQueue.h"
00039 #include "Inform.h"
00040 #include "config.h"
00041 #include "utilities.h"
00042 #include "PlainTextInterp.h"
00043 #include "VMDApp.h"
00044 #include "TclTextInterp.h"
00045 #include "Molecule.h"
00046 #include "MoleculeList.h"
00047 #include "SymbolTable.h"
00048 
00049 #if defined(VMDTKCON)
00050 #include "vmdconsole.h"
00051 #endif
00052 
00054 
00055 // constructor
00056 UIText::UIText(VMDApp *vmdapp, int guienabled, int mpienabled)
00057 #ifdef VMDVRJUGGLER
00058   : UIObject(vmdapp), _isInitialized(false) {
00059 #else
00060   : UIObject(vmdapp) {
00061 #endif
00062 
00063   // UIText logs all commands
00064   tclinterp = NULL;
00065   pythoninterp = NULL;
00066 
00067 #if defined(VMDTKCON)
00068   cmdbufstr = new Inform("", VMDCON_ALWAYS);
00069 #else
00070   cmdbufstr = new Inform("");
00071 #endif
00072 
00073   // UIText logs all commands
00074   for (int i=0; i<Command::TOTAL; i++) command_wanted(i);
00075 
00076   // Initialize the Tcl interpreter if enabled
00077 #ifdef VMDTCL
00078   tclinterp = new TclTextInterp(app, guienabled, mpienabled);
00079 #ifdef VMDTKCON
00080   // hook the default tcl interpreter into vmdcon as default.
00081   vmdcon_set_status(vmdcon_get_status(), ((TclTextInterp *)tclinterp)->get_interp());
00082 #endif
00083 #endif
00084 
00085   // The Python interpreter is initialized on first use.
00086   // However, if there's no Tcl interpreter, initialize the Python interpreter
00087   // right away.
00088 #ifdef VMDPYTHON
00089   if (!tclinterp)
00090     pythoninterp = new PythonTextInterp(app);
00091 #endif
00092 
00093   // start with the Tcl interpreter by default, if it exists.  If there is
00094   // no Tcl interpreter, go with Python.  Last resort: PlainTextInterpreter
00095   // (which has nothing to do with crypto, by the way).
00096   if (tclinterp)
00097     interp = tclinterp;
00098   else if (pythoninterp)
00099     interp = pythoninterp;
00100   else
00101     interp = new PlainTextInterp;
00102 
00103   reset();
00104 }
00105 
00106 // This is called in VMDApp::VMDinit just before reading the .vmdrc file.
00107 // It has to be done after the previous initialization because the
00108 // event look was not yet available.
00109 void UIText::read_init(void) {
00110   interp->doInit();
00111 #ifdef VMDVRJUGGLER
00112   _isInitialized = true;
00113 #endif
00114 }
00115 
00116 // destructor
00117 UIText::~UIText(void) {
00118   if (tclinterp) tclinterp->logfile_cb("exit");
00119 #ifdef VMDTCL
00120   delete tclinterp;
00121 #endif
00122 
00123 #ifdef VMDPYTHON
00124   delete pythoninterp;
00125 #endif
00126   delete cmdbufstr;
00127 }
00128 
00129 #ifdef VMDVRJUGGLER
00130 bool UIText::isInitialized(){
00131   // msgInfo  << "isInitialized()" << sendmsg;
00132   return _isInitialized;
00133 }
00134 #endif
00135 
00136 int UIText::save_state(const char *fname) {
00137   if (tclinterp) {
00138     JString cmd("save_state ");
00139     cmd += "{";
00140     cmd += fname;
00141     cmd += "}";
00142     return tclinterp->evalString((const char *)cmd);
00143   }
00144   return FALSE;
00145 }
00146 
00147 // specify new file to read commands from
00148 void UIText::read_from_file(const char *fname) {
00149 #ifdef VMDVRJUGGLER
00150   if (isInitialized()) {
00151     // msgInfo << "is Initialized" << sendmsg;
00152   } else {
00153     msgInfo << "is not Initialized" << sendmsg;
00154   }
00155 
00156   if (_isInitialized) {
00157     // && interp){   // prevent segfault when this is called during init 
00158     //    msgInfo  << "interp not null;" << sendmsg;
00159     interp->evalFile(fname);
00160   } else {
00161     msgInfo  << "not ready to read " << fname  << sendmsg;
00162   }
00163 #else
00164   interp->evalFile(fname);
00165 #endif
00166 }
00167 
00168 // check for an event; return TRUE if we found an event; FALSE otherwise
00169 int UIText::check_event(void) {
00170 
00171   // no tk event handling when building as a shared object 
00172   // for embedding in python.
00173 #if defined(VMD_SHARED)
00174   return FALSE;
00175 #endif
00176 
00177   // let the text interpreter have control for a while
00178   // If a Python interpreter has been initialized, let it do the Tk updates.
00179   // Python takes care of updating Tk; if we try to update Tk from within
00180   // Tcl when Tkinter widgets have been created, we crash and burn as Tk
00181   // is not thread safe.
00182   // If Python was not able to update Tk, possibly because Tkinter was not
00183   // found, then use the Tcl interpreter. 
00184   if (!pythoninterp || (pythoninterp && !pythoninterp->doTkUpdate())) {
00185     if (tclinterp) {
00186       tclinterp->doTkUpdate();
00187     } else {
00188       // last resort - use whatever interpreter we've got.
00189       interp->doTkUpdate();
00190     }
00191   }
00192   interp->doEvent();
00193   return TRUE; 
00194 }
00195 
00196 
00197 int UIText::act_on_command(int cmdtype, Command *cmd) {
00198   int action=1;
00199 
00200 #if defined(VMDNVTX)
00201   // log command in profiler, if possible
00202   int profile_pushed=0;
00203   if (cmd->has_text(cmdbufstr)) {
00204     profile_pushed=1;
00205     PROFILE_PUSH_RANGE(cmdbufstr->text(), 1); 
00206   }
00207 #endif
00208 
00209   if (tclinterp) {
00210     // log command, if possible
00211     if (cmd->has_text(cmdbufstr)) {
00212       tclinterp->logfile_cb(cmdbufstr->text());
00213 #ifdef VMDVRJUGGLER
00214       if (app->jugglerMode == VRJ_MASTER) {
00215         app->logfile_juggler(cmdbufstr->text());
00216       }
00217 #endif
00218       cmdbufstr->reset();
00219     }
00220   }
00221 
00222   if (cmdtype == Command::INTERP_EVENT) {
00223     // downcast to InterpEvent
00224     InterpEvent *event = (InterpEvent *)cmd;  
00225     if (tclinterp)
00226       event->do_callback(tclinterp);
00227     // ACK!  This used be "else if (pythoninterp)", which means python
00228     // callbacks never get called if you build with Tcl.  
00229     if (pythoninterp)
00230       event->do_callback(pythoninterp);
00231   } else {
00232     action=0;    // no action taken
00233   }
00234 
00235 #if defined(VMDNVTX)
00236   if (profile_pushed) {
00237     PROFILE_POP_RANGE(); // ensure we perform matching pop operation 
00238   }
00239 #endif
00240 
00241   return action; // return whether we used the command or not
00242 }
00243 
00244 
00245 int UIText::change_interp(const char *interpname) {
00246   if (!interpname) return FALSE;
00247   if (!strupcmp(interpname, "tcl")) {
00248     if (tclinterp) {
00249       msgInfo << "Text interpreter now Tcl" << sendmsg;
00250       interp = tclinterp;
00251       return TRUE;
00252     } else {
00253       msgErr << "Sorry, no Tcl text interpreter available" << sendmsg;
00254       // try for Python
00255       interpname = "python";
00256     }
00257   } 
00258   // fall through to Python if no Tcl interpreter is available
00259   if (!strupcmp(interpname, "python")) {
00260     if (pythoninterp) {
00261       msgInfo << "Text interpreter now Python" << sendmsg;
00262       interp = pythoninterp;
00263       // On MACOSX, when we change to the Python interpreter _after_ the
00264       // first time it's created (i.e. gopython, EOF, gopython), we get
00265       // kicked out right away because for some reason stdin has the EOF
00266       // flag set.  So, we clear the EOF flag here.
00267       clearerr(stdin);
00268       return TRUE;
00269     } else {
00270 #if defined(VMDPYTHON) 
00271       pythoninterp = new PythonTextInterp(app);
00272       if (pythoninterp) {
00273         msgInfo << "Text interpreter now Python" << sendmsg;
00274         interp = pythoninterp;
00275         return TRUE;
00276       } else {
00277         msgErr << "Sorry, unable to start Python text interpreter" << sendmsg;
00278       }
00279 #else
00280       msgErr << "Sorry, this version of VMD was compiled with Python support disabled" << sendmsg;
00281 #endif
00282     }
00283   } else {
00284     msgErr << "Unsupported text interpreter requested" << sendmsg;
00285   }
00286   return FALSE;
00287 }
00288 

Generated on Tue Apr 23 04:24:12 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002