1 /* $RCSfile$ 2 * $Author: hansonr $ 3 * $Date: 2021-12-31 18:52:23 -0600 (Fri, 31 Dec 2021) $ 4 * $Revision: 22287 $ 5 * 6 * Copyright (C) 2003-2006 Miguel, Jmol Development, www.jmol.org 7 * 8 * Contact: jmol-developers@lists.sf.net 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 23 */ 24 package org.jmol.script; 25 26 import java.util.Arrays; 27 import java.util.Hashtable; 28 import java.util.Map; 29 30 import org.jmol.api.Interface; 31 import org.jmol.api.JmolParallelProcessor; 32 import org.jmol.api.JmolScriptFunction; 33 import org.jmol.api.SymmetryInterface; 34 import org.jmol.atomdata.RadiusData; 35 import org.jmol.atomdata.RadiusData.EnumType; 36 import org.jmol.c.PAL; 37 import org.jmol.c.STR; 38 import org.jmol.c.VDW; 39 import org.jmol.i18n.GT; 40 import org.jmol.modelset.Atom; 41 import org.jmol.modelset.BondSet; 42 import org.jmol.modelset.Group; 43 import org.jmol.modelset.TickInfo; 44 import org.jmol.shape.MeshCollection; 45 import org.jmol.shape.Shape; 46 import org.jmol.thread.JmolThread; 47 import org.jmol.util.BSUtil; 48 import org.jmol.util.ColorEncoder; 49 import org.jmol.util.Edge; 50 import org.jmol.util.Elements; 51 import org.jmol.util.Escape; 52 import org.jmol.util.Font; 53 import org.jmol.util.Logger; 54 import org.jmol.util.Parser; 55 import org.jmol.util.SimpleUnitCell; 56 import org.jmol.util.Txt; 57 import org.jmol.viewer.ActionManager; 58 import org.jmol.viewer.FileManager; 59 import org.jmol.viewer.JC; 60 import org.jmol.viewer.ShapeManager; 61 import org.jmol.viewer.StateManager; 62 import org.jmol.viewer.TransformManager; 63 import org.jmol.viewer.Viewer; 64 65 import javajs.util.A4; 66 import javajs.util.AU; 67 import javajs.util.BArray; 68 import javajs.util.BS; 69 import javajs.util.Base64; 70 import javajs.util.Lst; 71 import javajs.util.M3; 72 import javajs.util.M4; 73 import javajs.util.Measure; 74 import javajs.util.OC; 75 import javajs.util.P3; 76 import javajs.util.P4; 77 import javajs.util.PT; 78 import javajs.util.Quat; 79 import javajs.util.SB; 80 import javajs.util.T3; 81 import javajs.util.V3; 82 83 public class ScriptEval extends ScriptExpr { 84 85 86 /* 87 * To make this a bit more manageable, I separated ScriptEvaluator into four parts: 88 * 89 * 90 * ScriptEval -- entry point and script command code 91 * 92 * extends ScriptExpr -- expression parsing 93 * 94 * extends ScriptParam -- parameter parsing 95 * 96 * extends ScriptError -- error handling 97 * 98 * scriptext.CmdExt -- optionally loaded, less-used commands 99 * scriptext.IsoExt -- optionally loaded, less-used commands 100 * scriptext.MathExt -- optionally loaded, less-used functions 101 * scriptext.SmilesExt -- optionally loaded methods for cmds and math 102 * 103 * 104 * 105 * This main class is subdivided into the following sections: 106 * 107 * global fields 108 * 109 * 110 * 111 * 112 * Bob Hanson, 2/27/2014 113 */ 114 115 /* 116 * 117 * The ScriptEvaluator class, the Viewer, the xxxxManagers, the Graphics3D 118 * rendering engine, the ModelSet and Shape classes, and the Adapter file 119 * reader classes form the core of the Jmol molecular visualization framework. 120 * 121 * An extension of this file is org.jmol.scriptext.ScriptExt . 122 * 123 * The ScriptEvaluator has just a few entry points, which you will find 124 * immediately following this comment. They include: 125 * 126 * public boolean compileScriptString(String script, boolean tQuiet) 127 * 128 * public boolean compileScriptFile(String filename, boolean tQuiet) 129 * 130 * public void evaluateCompiledScript(boolean isCmdLine_c_or_C_Option, boolean 131 * isCmdLine_C_Option, boolean historyDisabled, boolean listCommands) 132 * 133 * Essentially ANYTHING can be done using these three methods. A variety of 134 * other methods are available via Viewer, which is the the true portal to 135 * Jmol (via the JmolViewer interface) for application developers who want 136 * faster, more direct processing. 137 * 138 * A little Jmol history: 139 * 140 * General history notes can be found at our ConfChem paper, which can be 141 * found at 142 * http://chemapps.stolaf.edu/jmol/presentations/confchem2006/jmol-confchem 143 * .htm 144 * 145 * This ScriptEvaluator class was initially written by Michael (Miguel) Howard 146 * as Eval.java as an efficient means of reproducing the RasMol scripting 147 * language for Jmol. Key additions there included: 148 * 149 * - tokenization of commands via the Compiler class (now ScriptCompiler and 150 * ScriptCompilationTokenParser) - ScriptException error handling - a flexible 151 * yet structured command parameter syntax - implementations of RasMol 152 * secondary structure visualizations - isosurfaces, dots, labels, polyhedra, 153 * draw, stars, pmesh, more 154 * 155 * Other Miguel contributions include: 156 * 157 * - the structural bases of the Adapter, ModelSet, and ModelSetBio classes - 158 * creation of Manager classes - absolutely amazing raw pixel bitmap rendering 159 * code (org.jmol.g3d) - popup context menu - inline model loading 160 * 161 * Bob Hanson (St. Olaf College) found out about Jmol during the spring of 162 * 2004. After spending over a year working on developing online interactive 163 * documentation, he started actively writing code early in 2006. During the 164 * period 2006-2009 Bob completely reworked the script processor (and much of 165 * the rest of Jmol) to handle a much broader range of functionality. Notable 166 * improvements include: 167 * 168 * - display/hide commands - dipole, ellipsoid, geosurface, lcaoCartoon 169 * visualizations - quaternion and ramachandran commands - much expanded 170 * isosurface / draw commands - configuration, disorder, and biomolecule 171 * support - broadly 2D- and 3D-positionable echos - translateSelected and 172 * rotateSelected commands - getProperty command, providing access to more 173 * file information - data and write commands - writing of high-resolution 174 * JPG, PNG, and movie-sequence JPG - generalized export to Maya and PovRay 175 * formats 176 * 177 * - multiple file loading, including trajectories - minimization using the 178 * Universal Force Field (UFF) - atom/model deletion and addition - direct 179 * loading of properties such as partial charge or coordinates - several new 180 * file readers, including manifested zip file reading - default directory, CD 181 * command, and pop-up file open/save dialogs 182 * 183 * - "internal" molecular coordinate-based rotations - full support for 184 * crystallographic formats, including space groups, symmetry, unit cells, and 185 * fractional coordinates - support for point groups and molecular symmetry - 186 * navigation mode - antialiasing of display and imaging - save/restore/write 187 * exact Jmol state - JVXL file format for compressed rapid generation of 188 * isosurfaces 189 * 190 * - user-defined variables - addition of a Reverse Polish Notation (RPN) 191 * expression processor - extension of the RPN processor to user variables - 192 * user-defined functions - flow control commands if/else/endif, for, and 193 * while - JavaScript/Java-like brace syntax - key stroke-by-key stroke 194 * command syntax checking - integrated help command - user-definable popup 195 * menu - language switching 196 * 197 * - fully functional signed applet - applet-applet synchronization, including 198 * two-applet geoWall stereo rendering - JSON format for property delivery to 199 * JavaScript - jmolScriptWait, dual-threaded queued JavaScript scripting 200 * interface - extensive callback development - script editor panel (work in 201 * progress, June 2009) 202 * 203 * Several other people have contributed. Perhaps they will not be too shy to 204 * add their claim to victory here. Please add your contributions. 205 * 206 * - Jmol application (Egon Willighagen) - smiles support (Nico Vervelle) - 207 * readers (Rene Kanter, Egon, several others) - initial VRML export work 208 * (Nico Vervelle) - WebExport (Jonathan Gutow) - internationalization (Nico, 209 * Egon, Angel Herriez) - Jmol Wiki and user guide book (Angel Herriez) 210 * 211 * While this isn't necessarily the best place for such discussion, open 212 * source principles require proper credit given to those who have 213 * contributed. This core class seems to me a place to acknowledge this core 214 * work of the Jmol team. 215 * 216 * Bob Hanson, 6/2009 hansonr@stolaf.edu 217 */ 218 219 220 221 /////////////////// global fields /////////////////// 222 223 private final static String saveList = 224 "bonds? context? coordinates? orientation? rotation? selection? state? structure?"; 225 226 private static int iProcess; 227 228 public ShapeManager sm; 229 230 public boolean isJS; 231 232 private JmolThread scriptDelayThread, fileLoadThread; 233 234 private boolean allowJSThreads = true; 235 236 @Override getAllowJSThreads()237 public boolean getAllowJSThreads() { 238 return allowJSThreads; 239 } 240 setAllowJSThreads(boolean b)241 public void setAllowJSThreads(boolean b) { 242 allowJSThreads = b; 243 } 244 245 private boolean isFuncReturn; 246 247 // execution options: 248 249 public boolean historyDisabled; // set by ScriptExt.evaluateParallel 250 251 private boolean debugScript; 252 private boolean isCmdLine_C_Option; 253 private boolean isCmdLine_c_or_C_Option; 254 private boolean listCommands; 255 256 public boolean tQuiet; 257 doReport()258 public boolean doReport() { 259 return (!tQuiet && scriptLevel <= scriptReportingLevel); 260 } 261 262 private boolean executionStopped; 263 private boolean executionPaused; 264 private boolean executionStepping; 265 private boolean executing; 266 267 private long timeBeginExecution; 268 private long timeEndExecution; 269 270 private boolean mustResumeEval; // see resumeEval 271 272 //private static int evalID; 273 274 private Thread currentThread; 275 public ScriptCompiler compiler; 276 277 public SB outputBuffer; 278 279 private String contextPath = ""; 280 public String scriptFileName; 281 public String functionName; 282 283 public boolean isStateScript; 284 285 @Override isStateScript()286 public boolean isStateScript() { 287 return isStateScript; 288 } 289 290 public int scriptLevel; 291 public static final String CONTEXT_HOLD_QUEUE = "getEvalContextAndHoldQueue"; 292 public static final String CONTEXT_DELAY = "delay"; 293 294 private static final long DELAY_INTERRUPT_MS = 1000000; // testing! 295 296 private static final int EXEC_ASYNC = -1; 297 private static final int EXEC_ERR = 1; 298 private static final int EXEC_OK = 0; 299 300 public static int commandHistoryLevelMax = 0; 301 private static int contextDepthMax = 100; // mutable using set scriptLevelMax 302 private static int scriptReportingLevel = 0; 303 304 /** 305 * set a static variable, with checking for range 306 */ 307 @Override setStatic(int tok, int ival)308 public int setStatic(int tok, int ival) { 309 switch (tok) { 310 case T.contextdepthmax: 311 if (ival >= 10) 312 contextDepthMax = ival; 313 return contextDepthMax; 314 case T.historylevel: 315 if (ival >= 0) 316 commandHistoryLevelMax = ival; 317 return commandHistoryLevelMax; 318 case T.scriptreportinglevel: 319 if (ival >= 0) 320 scriptReportingLevel = ival; 321 return scriptReportingLevel; 322 } 323 return 0; 324 } 325 326 // created by Compiler: 327 328 public T[][] aatoken; 329 private short[] lineNumbers; 330 private int[][] lineIndices; 331 332 private String script; 333 private String scriptExtensions; 334 335 @Override getScript()336 public String getScript() { 337 return script; 338 } 339 340 // specific to current statement: 341 342 public int pc; // program counter 343 public String thisCommand; 344 public String fullCommand; 345 private int lineEnd; 346 private int pcEnd; 347 348 // for specific commmands: 349 350 private boolean forceNoAddHydrogens; 351 352 private boolean isEmbedded; 353 354 ScriptEval()355 public ScriptEval() { 356 // by reflection as well as directly 357 currentThread = Thread.currentThread(); 358 //evalID++; 359 } 360 361 @Override setViewer(Viewer vwr)362 public ScriptEval setViewer(Viewer vwr) { 363 this.vwr = vwr; 364 this.compiler = (compiler == null ? (ScriptCompiler) vwr.compiler 365 : compiler); 366 isJS = vwr.isSingleThreaded; 367 return this; 368 } 369 370 @Override setCompiler()371 public void setCompiler() { 372 vwr.compiler = compiler = new ScriptCompiler(vwr); 373 } 374 375 // //////////////// primary interfacing methods ////////////////// 376 377 /* 378 * see Viewer.evalStringWaitStatus for how these are implemented 379 */ 380 @Override compileScriptString(String script, boolean tQuiet)381 public boolean compileScriptString(String script, boolean tQuiet) { 382 clearState(tQuiet); 383 contextPath = "[script]"; 384 return compileScript(null, script, debugScript); 385 } 386 387 @Override compileScriptFile(String filename, boolean tQuiet)388 public boolean compileScriptFile(String filename, boolean tQuiet) { 389 clearState(tQuiet); 390 contextPath = filename; 391 String script = getScriptFileInternal(filename, null, null, null); 392 return (script != null && compileScript(filename, script, debugScript)); 393 } 394 395 @Override evaluateCompiledScript(boolean isCmdLine_c_or_C_Option, boolean isCmdLine_C_Option, boolean historyDisabled, boolean listCommands, SB outputBuffer, boolean allowThreads)396 public void evaluateCompiledScript(boolean isCmdLine_c_or_C_Option, 397 boolean isCmdLine_C_Option, 398 boolean historyDisabled, 399 boolean listCommands, SB outputBuffer, 400 boolean allowThreads) { 401 boolean tempOpen = this.isCmdLine_C_Option; 402 this.isCmdLine_C_Option = isCmdLine_C_Option; 403 chk = this.isCmdLine_c_or_C_Option = isCmdLine_c_or_C_Option; 404 this.historyDisabled = historyDisabled; 405 this.outputBuffer = outputBuffer; 406 privateFuncs = null; 407 currentThread = Thread.currentThread(); 408 setAllowJSThreads(allowThreads & !vwr.getBoolean(T.nodelay)); 409 this.listCommands = listCommands; 410 timeBeginExecution = System.currentTimeMillis(); 411 executionStopped = executionPaused = false; 412 executionStepping = false; 413 executing = true; 414 vwr.pushHoldRepaintWhy("runEval"); 415 setScriptExtensions(); 416 executeCommands(false, true); 417 this.isCmdLine_C_Option = tempOpen; 418 if(isStateScript) 419 ScriptManager.setStateScriptVersion(vwr, null); // set by compiler 420 } 421 useThreads()422 public boolean useThreads() { 423 return (!chk && !vwr.headless && !vwr.autoExit 424 && vwr.haveDisplay && outputBuffer == null && allowJSThreads); 425 } 426 executeCommands(boolean isTry, boolean reportCompletion)427 private int executeCommands(boolean isTry, boolean reportCompletion) { 428 boolean haveError = false; 429 try { 430 if (!dispatchCommands(false, false, isTry)) 431 return EXEC_ASYNC; 432 } catch (Error er) { 433 vwr.handleError(er, false); 434 setErrorMessage("" + er + " " + vwr.getShapeErrorState()); 435 errorMessageUntranslated = "" + er; 436 report(errorMessage, true); 437 haveError = true; 438 } catch (ScriptException e) { 439 if (e instanceof ScriptInterruption && (!isTry || !e.isError)) { 440 441 // ScriptInterruption will be called in Java or JavaScript 442 // by a THROW command, but in that case e.isError == true 443 444 // ScriptInterruption will be called in JavaScript to 445 // stop this thread and initiate a setTimeout sequence 446 // that is responsible for getting us back to the 447 // current point using resumeEval again. 448 // it's not a real exception, but it has that 449 // property so that it can be caught here. 450 451 return EXEC_ASYNC; 452 } 453 if (isTry) { 454 vwr.setStringProperty("_errormessage", "" + e); 455 return EXEC_ERR; 456 } 457 setErrorMessage(e.toString()); 458 errorMessageUntranslated = e.getErrorMessageUntranslated(); 459 report(errorMessage, true); 460 vwr 461 .notifyError( 462 (errorMessage != null 463 && errorMessage.indexOf("java.lang.OutOfMemoryError") >= 0 ? "Error" 464 : "ScriptException"), errorMessage, errorMessageUntranslated); 465 haveError = true; 466 } 467 if (haveError || !isJS || !allowJSThreads) { 468 vwr.setTainted(true); 469 vwr.popHoldRepaint("executeCommands" + " " 470 + (scriptLevel > 0 ? JC.REPAINT_IGNORE : "")); 471 } 472 timeEndExecution = System.currentTimeMillis(); 473 if (errorMessage == null && executionStopped) 474 setErrorMessage("execution interrupted"); 475 else if (!tQuiet && reportCompletion) 476 vwr.scriptStatus(JC.SCRIPT_COMPLETED); 477 executing = chk = this.isCmdLine_c_or_C_Option = this.historyDisabled = false; 478 String msg = getErrorMessageUntranslated(); 479 vwr.setErrorMessage(errorMessage, msg); 480 if (!tQuiet && reportCompletion) 481 vwr.setScriptStatus("Jmol script terminated", errorMessage, 482 1 + (int) (timeEndExecution - timeBeginExecution), msg); 483 return (haveError ? EXEC_ERR : EXEC_OK); 484 } 485 486 487 /** 488 * From dispatchCommands and JmolThread resumeEval. 489 * 490 * After throwing a ScriptInterruption, all statements following the current 491 * one are lost. When a JavaScript timeout returns from a DELAY, MOVE, MOVETO, 492 * or other sleep-requiring command, it is the ScriptContext that contains all 493 * have to worry about this, because the current thread is just put to sleep, 494 * not stopped, but in JavaScript, where we only have one thread, we need to 495 * manage this more carefully. 496 * 497 * We re-enter the halted script here, using a saved script context. The 498 * program counter is incremented to skip the initiating statement, and all 499 * parent contexts up the line are set with mustResumeEval = true. 500 * 501 * @param sco 502 */ 503 504 @Override resumeEval(Object sco)505 public void resumeEval(Object sco) { 506 507 ScriptContext sc = (ScriptContext) sco; 508 509 // 510 // 511 // | 512 // | 513 // INTERRUPT--- 514 // (1) | 515 // | | 516 // | | 517 // | INTERRUPT---------------- 518 // | (2) | 519 // | | | 520 // | | | 521 // | resumeEval-->(1) MOVETO_INIT 522 // (DONE) 523 // (new thread) 524 // MOVETO_FINISH 525 // | 526 // resumeEval-->(2) 527 // 528 // In Java, this is one overall thread that sleeps 529 // during the MOVETO. But in JavaScript, the setTimeout() 530 // starts a new thread and (1) and (2) are never executed. 531 // We must run resumeEval at the end of each dispatch loop. 532 // 533 // Thus, it is very important that nothing is ever executed 534 // after dispatchCommands. 535 // 536 // 537 // Functions are tricky, though. How do we restart them? 538 // 539 // main 540 // | 541 // ---------test() 542 // | 543 // | 544 // | 545 // -------------------zoomTo 546 // (2) | 547 // | | 548 // ---------return | 549 // | MOVETO_INIT 550 // (DONE) 551 // (new thread) 552 // MOVETO_FINISH 553 // | 554 // resumeEval-->(2) 555 // 556 // When the zoomTo is initiated, a ScriptInterrpt is thrown, which 557 // stops processing in test() and main. 558 // 559 // 560 setErrorMessage(null); 561 if (executionStopped || sc == null || !sc.mustResumeEval) { 562 resumeViewer("resumeEval"); 563 return; 564 } 565 thisContext = sc; 566 567 if (sc.scriptLevel > 0 && sc.why != CONTEXT_HOLD_QUEUE) 568 scriptLevel = sc.scriptLevel - 1; 569 if (sc.isTryCatch) { 570 postProcessTry(null); 571 pcResume = -1; 572 } else { 573 if (!executionPaused) 574 sc.pc++; 575 restoreScriptContext(sc, true, false, false); 576 pcResume = sc.pc; 577 } 578 switch (executeCommands(thisContext != null && thisContext.isTryCatch, 579 scriptLevel <= 0)) { 580 case EXEC_ASYNC: 581 break; 582 case EXEC_ERR: 583 case EXEC_OK: 584 postProcessTry(null); 585 if (executing) 586 executeCommands(true, false); 587 break; 588 } 589 pcResume = -1; 590 } 591 resumeViewer(String why)592 private void resumeViewer(String why) { 593 vwr.setTainted(true); 594 vwr.popHoldRepaint(why + (chk ? JC.REPAINT_IGNORE : "")); 595 vwr.queueOnHold = false; 596 } 597 598 @Override runScript(String script)599 public void runScript(String script) throws ScriptException { 600 if (!vwr.isPreviewOnly) 601 runScriptBuffer(script, outputBuffer, false); 602 } 603 604 /** 605 * runs a script immediately and sends selected output to a provided SB 606 * @param outputBuffer 607 * @param script 608 * 609 * @throws ScriptException 610 */ 611 @Override runScriptBuffer(String script, SB outputBuffer, boolean isFuncReturn)612 public void runScriptBuffer(String script, SB outputBuffer, boolean isFuncReturn) 613 throws ScriptException { 614 pushContext(null, "runScriptBuffer"); 615 contextPath += " >> script() "; 616 this.outputBuffer = outputBuffer; 617 setAllowJSThreads(false); 618 boolean fret = this.isFuncReturn; 619 this.isFuncReturn |= isFuncReturn; 620 if (compileScript(null, script + JC.SCRIPT_EDITOR_IGNORE 621 + JC.REPAINT_IGNORE, false)) 622 dispatchCommands(false, false, false); 623 popContext(false, false); 624 this.isFuncReturn = fret; 625 } 626 627 /** 628 * a method for just checking a script 629 * 630 * @param script 631 * @return a ScriptContext that indicates errors and provides a tokenized 632 * version of the script that has passed all syntax checking, both in 633 * the compiler and the evaluator 634 * 635 */ 636 @Override checkScriptSilent(String script)637 public ScriptContext checkScriptSilent(String script) { 638 ScriptContext sc = compiler.compile(null, script, false, true, false, true); 639 if (sc.errorType != null) 640 return sc; 641 restoreScriptContext(sc, false, false, false); 642 chk = true; 643 isCmdLine_c_or_C_Option = isCmdLine_C_Option = false; 644 pc = 0; 645 try { 646 dispatchCommands(false, false, false); 647 } catch (ScriptException e) { 648 setErrorMessage(e.toString()); 649 sc = getScriptContext("checkScriptSilent"); 650 } 651 chk = false; 652 return sc; 653 } 654 getContextTrace(Viewer vwr, ScriptContext sc, SB sb, boolean isTop)655 static SB getContextTrace(Viewer vwr, ScriptContext sc, SB sb, 656 boolean isTop) { 657 if (sb == null) 658 sb = new SB(); 659 int pc = Math.min(sc.pc, sc.lineNumbers[sc.lineNumbers.length - 1]); 660 sb.append(getErrorLineMessage(sc.functionName, sc.scriptFileName, 661 sc.lineNumbers[pc], pc, ScriptEval.statementAsString(vwr, 662 sc.statement, (isTop ? sc.iToken : 9999), false))); 663 if (sc.parentContext != null) 664 getContextTrace(vwr, sc.parentContext, sb, false); 665 return sb; 666 } 667 668 // //////////////////////// script execution ///////////////////// 669 670 @Override setDebugging()671 public void setDebugging() { 672 debugScript = vwr.getBoolean(T.debugscript); 673 debugHigh = (debugScript && Logger.debugging); 674 } 675 676 677 @Override haltExecution()678 public void haltExecution() { 679 if (isEmbedded) { 680 vwr.setBooleanProperty("allowEmbeddedScripts", true); 681 isEmbedded = false; 682 } 683 resumePausedExecution(); 684 executionStopped = true; 685 } 686 687 @Override pauseExecution(boolean withDelay)688 public void pauseExecution(boolean withDelay) { 689 if (chk || vwr.headless) 690 return; 691 if (withDelay && !isJS) 692 delayScript(-100); 693 vwr.popHoldRepaint("pauseExecution " + withDelay); 694 executionStepping = false; 695 executionPaused = true; 696 } 697 698 @Override stepPausedExecution()699 public void stepPausedExecution() { 700 executionStepping = true; 701 executionPaused = false; 702 // releases a paused thread but 703 // sets it to pause for the next command. 704 } 705 706 @Override resumePausedExecution()707 public void resumePausedExecution() { 708 executionPaused = false; 709 executionStepping = false; 710 } 711 712 @Override isExecuting()713 public boolean isExecuting() { 714 return executing && !executionStopped; 715 } 716 717 @Override isPaused()718 public boolean isPaused() { 719 return executionPaused; 720 } 721 722 @Override isStepping()723 public boolean isStepping() { 724 return executionStepping; 725 } 726 727 @Override isStopped()728 public boolean isStopped() { 729 return executionStopped || !isJS && currentThread != Thread.currentThread(); 730 } 731 732 /** 733 * when paused, indicates what statement will be next 734 * 735 * @return a string indicating the statement 736 */ 737 @Override getNextStatement()738 public String getNextStatement() { 739 return (pc < aatoken.length ? getErrorLineMessage(functionName, 740 scriptFileName, getLinenumber(null), pc, 741 statementAsString(vwr, aatoken[pc], -9999, debugHigh)) : ""); 742 } 743 744 /** 745 * used for recall of commands in the application console 746 * 747 * @param pc 748 * @param allThisLine 749 * @param addSemi 750 * @return a string representation of the command 751 */ getCommand(int pc, boolean allThisLine, boolean addSemi)752 private String getCommand(int pc, boolean allThisLine, boolean addSemi) { 753 if (pc >= lineIndices.length) 754 return ""; 755 if (allThisLine) { 756 int pt0 = -1; 757 int pt1 = script.length(); 758 for (int i = 0; i < lineNumbers.length; i++) 759 if (lineNumbers[i] == lineNumbers[pc]) { 760 if (pt0 < 0) 761 pt0 = lineIndices[i][0]; 762 pt1 = lineIndices[i][1]; 763 } else if (lineNumbers[i] == 0 || lineNumbers[i] > lineNumbers[pc]) { 764 break; 765 } 766 String s = script; 767 if (s.indexOf('\1') >= 0) 768 s = s.substring(0, s.indexOf('\1')); 769 if (pt1 == s.length() - 1 && s.endsWith("}")) 770 pt1++; 771 return (pt0 == s.length() || pt1 < pt0 ? "" : s.substring( 772 Math.max(pt0, 0), Math.min(s.length(), pt1))); 773 } 774 int ichBegin = lineIndices[pc][0]; 775 int ichEnd = lineIndices[pc][1]; 776 // (pc + 1 == lineIndices.length || lineIndices[pc + 1][0] == 0 ? script 777 // .length() 778 // : lineIndices[pc + 1]); 779 String s = ""; 780 if (ichBegin < 0 || ichEnd <= ichBegin || ichEnd > script.length()) 781 return ""; 782 try { 783 s = script.substring(ichBegin, ichEnd); 784 if (s.indexOf("\\\n") >= 0) 785 s = PT.rep(s, "\\\n", " "); 786 if (s.indexOf("\\\r") >= 0) 787 s = PT.rep(s, "\\\r", " "); 788 // int i; 789 // for (i = s.length(); --i >= 0 && !ScriptCompiler.eol(s.charAt(i), 0); 790 // ){ 791 // } 792 // s = s.substring(0, i + 1); 793 if (s.length() > 0 && !s.endsWith(";")/* 794 * && !s.endsWith("{") && 795 * !s.endsWith("}") 796 */) 797 s += ";"; 798 } catch (Exception e) { 799 Logger.error("darn problem in Eval getCommand: ichBegin=" + ichBegin 800 + " ichEnd=" + ichEnd + " len = " + script.length() + "\n" + e); 801 } 802 return s; 803 } 804 logDebugScript(T[] st, int ifLevel)805 private void logDebugScript(T[] st, int ifLevel) { 806 iToken = -9999; 807 if (debugHigh) { 808 if (st.length > 0) 809 Logger.debug(st[0].toString()); 810 for (int i = 1; i < st.length; ++i) 811 if (st[i] != null) 812 Logger.debug(st[i].toString()); 813 SB strbufLog = new SB(); 814 String s = (ifLevel > 0 ? " ".substring(0, 815 ifLevel * 2) : ""); 816 strbufLog.append(s).append( 817 statementAsString(vwr, st, iToken, debugHigh)); 818 vwr.scriptStatus(strbufLog.toString()); 819 } else { 820 String cmd = getCommand(pc, false, false); 821 if (cmd != "") 822 vwr.scriptStatus(cmd); 823 } 824 825 } 826 827 // /////////////// string-based evaluation support ///////////////////// 828 829 /** 830 * a general-use method to evaluate a "SET" type expression. 831 * @param asVariable 832 * @param expr 833 * 834 * @return an object of one of the following types: Boolean, Integer, Float, 835 * String, Point3f, BitSet 836 */ 837 838 839 @Override evaluateExpression(Object expr, boolean asVariable, boolean compileOnly)840 public Object evaluateExpression(Object expr, boolean asVariable, boolean compileOnly) { 841 // Text.formatText for MESSAGE and ECHO 842 // prior to 12.[2/3].32 was not thread-safe for compilation. 843 ScriptEval e = (new ScriptEval()).setViewer(vwr); 844 try { 845 // disallow end-of-script message and JavaScript script queuing 846 e.thisContext = thisContext; 847 e.contextVariables = contextVariables; 848 e.pushContext(null, "evalExp"); 849 e.setAllowJSThreads(false); 850 } catch (ScriptException e1) { 851 //ignore 852 } 853 boolean exec0 = executing; 854 Object o = (e.evaluate(expr, asVariable, compileOnly)); 855 executing = exec0; 856 return o; 857 } 858 859 860 runBufferedSafely(String script, SB outputBuffer)861 public void runBufferedSafely(String script, SB outputBuffer) { 862 if (outputBuffer == null) 863 outputBuffer = this.outputBuffer; 864 ScriptEval e = (new ScriptEval()).setViewer(vwr); 865 boolean exec0 = executing; 866 try { 867 e.runScriptBuffer(script, outputBuffer, false); 868 } catch (ScriptException e1) { 869 e1.printStackTrace(); 870 //ignore 871 } 872 executing = exec0; 873 } 874 875 876 877 runUserAction(String functionName, Object[] params, Viewer vwr)878 public static SV runUserAction(String functionName, Object[] params, Viewer vwr) { 879 ScriptEval ev = (new ScriptEval()).setViewer(vwr); 880 JmolScriptFunction func = vwr.getFunction(functionName.toLowerCase()); 881 if (func == null) 882 return null; 883 try { 884 Lst<SV> svparams = SV.getVariableAO(params).getList(); 885 ev.restoreFunction(func, svparams, null); 886 ev.dispatchCommands(false, true, false); 887 } catch (ScriptException e) { 888 return null; 889 } 890 SV ret = ev.getContextVariableAsVariable("_retval", false); 891 return (ret == null ? SV.vT : ret); 892 } 893 evaluate(Object expr, boolean asVariable, boolean compileOnly)894 private Object evaluate(Object expr, boolean asVariable, boolean compileOnly) { 895 try { 896 if (expr instanceof String) { 897 if (compileScript(null, "e_x_p_r_e_s_s_i_o_n = " + expr, false)) { 898 if (compileOnly) 899 return aatoken[0]; 900 setStatement(aatoken[0], 1); 901 return (asVariable ? parameterExpressionList(2, -1, false).get(0) 902 : parameterExpressionString(2, 0)); 903 } 904 } else if (expr instanceof T[]) { 905 BS bs = atomExpression((T[]) expr, 0, 0, true, false, null, false); 906 return (asVariable ? SV.newV(T.bitset, bs) : bs); 907 } else if (expr instanceof T[][]) { 908 setStatement(((T[][])expr)[0], 1); 909 return (asVariable ? parameterExpressionList(0, -1, false).get(0) 910 : parameterExpressionString(0, -1)); 911 } 912 } catch (Exception ex) { 913 Logger.error("Error evaluating: " + expr + "\n" + ex); 914 } 915 return (asVariable ? SV.getVariable("ERROR") : "ERROR"); 916 } 917 918 /** 919 * Check a map for a WHERE phrase 920 * 921 */ 922 @Override checkSelect(Map<String, SV> h, T[] where)923 public boolean checkSelect(Map<String, SV> h, T[] where) { 924 boolean ok = false; 925 try { 926 pushContext(null, "checkSelect"); 927 ok = parameterExpressionSelect(h, where); 928 } catch (Exception ex) { 929 Logger.error("checkSelect " + ex); 930 } 931 popContext(false, false); 932 return ok; 933 } 934 935 /** 936 * A general method to evaluate a string representing an atom set. 937 * Excepts one atom expression or one per line as "OR". 938 * Excepts "()" as "none". 939 * 940 * 941 * @param atomExpression 942 * @return is a bitset indicating the selected atoms 943 * 944 */ 945 @Override getAtomBitSet(Object atomExpression)946 public BS getAtomBitSet(Object atomExpression) { 947 948 // called by ScriptExpr and ScriptManager 949 950 if (atomExpression instanceof BS) 951 return (BS) atomExpression; 952 BS bs = new BS(); 953 boolean executing = this.executing; 954 try { 955 pushContext(null, "getAtomBitSet"); 956 String scr = "select (" + atomExpression + ")"; 957 scr = PT.replaceAllCharacters(scr, "\n\r", "),("); 958 scr = PT.rep(scr, "()", "(none)"); 959 if (compileScript(null, scr, false)) { 960 st = aatoken[0]; 961 setStatement(st, 0); 962 bs = atomExpression(st, 1, 0, false, false, null, true); 963 } 964 popContext(false, false); 965 } catch (Exception ex) { 966 Logger.error("getAtomBitSet " + atomExpression + "\n" + ex); 967 } 968 this.executing = executing; 969 return bs; 970 } 971 972 973 // ////////////////////// supporting methods for compilation and loading 974 compileScript(String filename, String strScript, boolean debugCompiler)975 public boolean compileScript(String filename, String strScript, 976 boolean debugCompiler) { 977 scriptFileName = filename; 978 strScript = fixScriptPath(strScript, filename); 979 ScriptContext sc = compiler.compile(filename, strScript, false, false, 980 debugCompiler && Logger.debugging, false); 981 addFunction(null); 982 Map<String, ScriptFunction> pf = privateFuncs; 983 restoreScriptContext(sc, false, false, false); 984 privateFuncs = null; 985 if (thisContext != null) 986 thisContext.privateFuncs = pf; 987 isStateScript = compiler.isStateScript; 988 forceNoAddHydrogens = (isStateScript && script.indexOf("pdbAddHydrogens") < 0); 989 String s = script; 990 pc = setScriptExtensions(); 991 if (!chk && vwr.scriptEditorVisible 992 && strScript.indexOf(JC.SCRIPT_EDITOR_IGNORE) < 0) 993 vwr.scriptStatus(""); 994 script = s; 995 return !error; 996 } 997 fixScriptPath(String strScript, String filename)998 private String fixScriptPath(String strScript, String filename) { 999 if (filename != null && strScript.indexOf("$SCRIPT_PATH$") >= 0) { 1000 String path = filename; 1001 // we first check for paths into ZIP files and adjust accordingly 1002 int pt = Math.max(filename.lastIndexOf("|"), filename.lastIndexOf("/")); 1003 path = path.substring(0, pt + 1); 1004 strScript = PT.rep(strScript, "$SCRIPT_PATH$/", path); 1005 // now replace the variable itself 1006 strScript = PT.rep(strScript, "$SCRIPT_PATH$", path); 1007 } 1008 return strScript; 1009 } 1010 setScriptExtensions()1011 private int setScriptExtensions() { 1012 String extensions = scriptExtensions; 1013 if (extensions == null) 1014 return 0; 1015 int pt = extensions.indexOf("##SCRIPT_STEP"); 1016 if (pt >= 0) { 1017 executionStepping = true; 1018 } 1019 pt = extensions.indexOf("##SCRIPT_START="); 1020 if (pt < 0) 1021 return 0; 1022 pt = PT.parseInt(extensions.substring(pt + 15)); 1023 if (pt == Integer.MIN_VALUE) 1024 return 0; 1025 for (pc = 0; pc < lineIndices.length; pc++) { 1026 if (lineIndices[pc][0] > pt || lineIndices[pc][1] >= pt) 1027 break; 1028 } 1029 if (pc > 0 && pc < lineIndices.length && lineIndices[pc][0] > pt) 1030 --pc; 1031 return pc; 1032 } 1033 1034 /** 1035 * Retrieve the uncompiled script or null if failed 1036 * @param filename 1037 * @param localPath 1038 * @param remotePath 1039 * @param scriptPath 1040 * @return Jmol script or null 1041 */ getScriptFileInternal(String filename, String localPath, String remotePath, String scriptPath)1042 private String getScriptFileInternal(String filename, String localPath, 1043 String remotePath, String scriptPath) { 1044 // from "script" command, with push/pop surrounding or vwr 1045 if (filename.toLowerCase().indexOf("javascript:") == 0) { 1046 return vwr.jsEval(filename.substring(11)); 1047 } 1048 String[] data = new String[2]; 1049 data[0] = filename; 1050 if (!vwr.fm.getFileDataAsString(data, -1, false, true, false)) { // first opening 1051 setErrorMessage("io error reading " + data[0] + ": " + data[1]); 1052 return null; 1053 } 1054 String movieScript = ""; 1055 if (("\n" + data[1]).indexOf("\nJmolManifest.txt\n") >= 0) { 1056 String path; 1057 if (filename.endsWith(".all.pngj") || filename.endsWith(".all.png")) { 1058 path = "|state.spt"; 1059 filename += "|"; 1060 } else { 1061 if (data[1].indexOf("movie.spt") >= 0) { 1062 data[0] = filename + "|movie.spt"; 1063 if (vwr.fm.getFileDataAsString(data, -1, false, true, false)) { // movie.spt 1064 movieScript = data[1]; 1065 } 1066 } 1067 filename += "|JmolManifest.txt"; 1068 data[0] = filename; 1069 if (!vwr.fm.getFileDataAsString(data, -1, false, true, false)) { // second entry 1070 setErrorMessage("io error reading " + data[0] + ": " + data[1]); 1071 return null; 1072 } 1073 path = FileManager.getManifestScriptPath(data[1]); 1074 } 1075 if (path != null && path.length() > 0) { 1076 data[0] = filename = filename.substring(0, filename.lastIndexOf("|")) 1077 + path; 1078 if (!vwr.fm.getFileDataAsString(data, -1, false, true, false)) { // third entry 1079 setErrorMessage("io error reading " + data[0] + ": " + data[1]); 1080 return null; 1081 } 1082 } 1083 if (filename.endsWith("|state.spt")) { 1084 vwr.g.setO("_pngjFile", filename.substring(0, filename.length() - 10) 1085 + "?"); 1086 } 1087 } 1088 scriptFileName = filename; 1089 data[1] = FileManager.getEmbeddedScript(data[1]); 1090 String script = fixScriptPath(data[1], data[0]); 1091 if (scriptPath == null) { 1092 scriptPath = vwr.fm.getFilePath(filename, false, false); 1093 scriptPath = scriptPath.substring(0, 1094 Math.max(scriptPath.lastIndexOf("|"), scriptPath.lastIndexOf("/"))); 1095 } 1096 return FileManager.setScriptFileReferences(script, localPath, remotePath, 1097 scriptPath) + movieScript; 1098 } 1099 1100 // ///////////// Jmol function support // /////////////// 1101 1102 private JmolParallelProcessor parallelProcessor; 1103 1104 public int pcResume = -1; 1105 1106 @Override 1107 @SuppressWarnings("unchecked") evalFunctionFloat(Object func, Object params, float[] values)1108 public float evalFunctionFloat(Object func, Object params, float[] values) { 1109 try { 1110 Lst<SV> p = (Lst<SV>) params; 1111 for (int i = 0; i < values.length; i++) 1112 p.get(i).value = Float.valueOf(values[i]); 1113 ScriptFunction f = (ScriptFunction) func; 1114 return SV.fValue(runFunctionAndRet(f, f.name, p, null, true, false, false)); 1115 } catch (Exception e) { 1116 return Float.NaN; 1117 } 1118 1119 } 1120 getUserFunctionResult(String name, Lst<SV> params, SV tokenAtom)1121 public SV getUserFunctionResult(String name, Lst<SV> params, SV tokenAtom) 1122 throws ScriptException { 1123 1124 // called by ScriptExpr(getBitsetProperty) and ScriptExt(evaluateUserFunction) 1125 // 1126 1127 return runFunctionAndRet(null, name, params, tokenAtom, true, true, false); 1128 } 1129 runFunctionAndRet(JmolScriptFunction function, String name, Lst<SV> params, SV tokenAtom, boolean getReturn, boolean setContextPath, boolean allowThreads)1130 private SV runFunctionAndRet(JmolScriptFunction function, String name, 1131 Lst<SV> params, SV tokenAtom, boolean getReturn, 1132 boolean setContextPath, boolean allowThreads) 1133 throws ScriptException { 1134 1135 // called by cmdFlow(TRY command), cmdFunc(user-defined command), 1136 // evalFunctionFloat (isosurface looking for a value), getFunctionRet 1137 // (above) 1138 // 1139 if (function == null) { 1140 // general function call 1141 name = name.toLowerCase(); 1142 function = getFunction(name); 1143 if (function == null) 1144 return null; 1145 if (setContextPath) 1146 contextPath += " >> function " + name; 1147 } else if (setContextPath) { 1148 // "try"; not from evalFunctionFloat 1149 contextPath += " >> " + name; 1150 } 1151 pushContext(null, "runFunctionAndRet "); 1152 if (allowJSThreads) 1153 setAllowJSThreads(allowThreads); 1154 boolean isTry = (function.getTok() == T.trycmd); 1155 thisContext.isTryCatch = isTry; 1156 thisContext.isFunction = !isTry; 1157 functionName = name; 1158 if (isTry) { 1159 resetError(); 1160 thisContext.displayLoadErrorsSave = vwr.displayLoadErrors; 1161 thisContext.tryPt = ++vwr.tryPt; 1162 vwr.displayLoadErrors = false; 1163 restoreFunction(function, params, tokenAtom); 1164 contextVariables.put("_breakval", SV.newI(Integer.MAX_VALUE)); 1165 contextVariables.put("_errorval", SV.newS("")); 1166 Map<String, SV> cv = contextVariables; 1167 switch(executeCommands(true, false)) { 1168 case EXEC_ASYNC: 1169 // do this later 1170 break; 1171 case EXEC_ERR: 1172 case EXEC_OK: 1173 //JavaScript will not return here after DELAY 1174 postProcessTry(cv); 1175 } 1176 return null; 1177 } else if (function instanceof JmolParallelProcessor) { 1178 synchronized (function) // can't do this -- too general 1179 { 1180 parallelProcessor = (JmolParallelProcessor) function; 1181 restoreFunction(function, params, tokenAtom); 1182 dispatchCommands(false, true, false); // to load the processes 1183 ((JmolParallelProcessor) function).runAllProcesses(vwr); 1184 } 1185 } else { 1186 restoreFunction(function, params, tokenAtom); 1187 dispatchCommands(false, true, false); 1188 //JavaScript will not return here after DELAY or after what??? 1189 } 1190 SV v = (getReturn ? getContextVariableAsVariable("_retval", false) : null); 1191 popContext(false, false); 1192 return v; 1193 } 1194 postProcessTry(Map<String, SV> cv)1195 private void postProcessTry(Map<String, SV> cv) { 1196 if (thisContext == null) 1197 return; 1198 while (thisContext.tryPt > vwr.tryPt) 1199 popContext(false, false); 1200 boolean isJSReturn = (cv == null); 1201 if (isJSReturn) { 1202 cv = contextVariables; 1203 } 1204 vwr.displayLoadErrors = thisContext.displayLoadErrorsSave; 1205 popContext(false, false); 1206 String err = (String) vwr.getP("_errormessage"); 1207 if (err.length() > 0) { 1208 cv.put("_errorval", SV.newS(err)); 1209 resetError(); 1210 } 1211 cv.put("_tryret", cv.get("_retval")); 1212 SV ret = cv.get("_tryret"); 1213 if (ret.value != null || ret.intValue != Integer.MAX_VALUE) { 1214 try { 1215 cmdReturn(ret); 1216 } catch (ScriptException e) { 1217 e.printStackTrace(); 1218 } 1219 return; 1220 } 1221 String errMsg = (String) (cv.get("_errorval")).value; 1222 if (errMsg.length() == 0) { 1223 int iBreak = (cv.get("_breakval")).intValue; 1224 if (iBreak != Integer.MAX_VALUE) { 1225 breakAt(pc - iBreak); 1226 return; 1227 } 1228 } 1229 // normal return will skip the catch 1230 if (pc + 1 < aatoken.length && aatoken[pc + 1][0].tok == T.catchcmd) { 1231 // set the intValue positive to indicate "not done" for the IF evaluation 1232 ContextToken ct = (ContextToken) aatoken[pc + 1][0]; 1233 if (ct.contextVariables != null && ct.name0 != null) 1234 ct.contextVariables.put(ct.name0, SV.newS(errMsg)); 1235 ct.intValue = (errMsg.length() > 0 ? 1 : -1) * Math.abs(ct.intValue); 1236 } 1237 if (isJSReturn) 1238 pc++; 1239 } 1240 breakAt(int pt)1241 private void breakAt(int pt) { 1242 if (pt < 0) { 1243 // if pt is a backward reference 1244 // this is a break within a try{...} block 1245 getContextVariableAsVariable("_breakval", false).intValue = -pt; 1246 pcEnd = pc; 1247 return; 1248 } 1249 // pt is to the FOR, WHILE, or SWITCH statement that is being exited 1250 int ptEnd = Math.abs(aatoken[pt][0].intValue); 1251 int tok = aatoken[pt][0].tok; 1252 if (tok == T.casecmd || tok == T.defaultcmd) { 1253 // breaking from SWITCH 1254 theToken = aatoken[ptEnd--][0]; 1255 int ptNext = Math.abs(theToken.intValue); 1256 if (theToken.tok != T.end) 1257 theToken.intValue = -ptNext; 1258 } else { 1259 // breaking from FOR or WHILE (or PROCESS?) 1260 pc = -1; 1261 while (pc != pt && thisContext != null) { 1262 while (thisContext != null 1263 && !ScriptCompiler.isBreakableContext(thisContext.token.tok)) 1264 popContext(true, false); 1265 pc = thisContext.pc; 1266 popContext(true, false); 1267 } 1268 } 1269 pc = ptEnd; 1270 } 1271 1272 /** 1273 * note that functions requiring motion cannot be run in JavaScript 1274 * 1275 * @param f 1276 * @param params 1277 * @param tokenAtom 1278 * @throws ScriptException 1279 */ restoreFunction(JmolScriptFunction f, Lst<SV> params, SV tokenAtom)1280 private void restoreFunction(JmolScriptFunction f, Lst<SV> params, 1281 SV tokenAtom) throws ScriptException { 1282 ScriptFunction function = (ScriptFunction) f; 1283 aatoken = function.aatoken; 1284 lineNumbers = function.lineNumbers; 1285 lineIndices = function.lineIndices; 1286 script = function.script; 1287 pc = 0; 1288 if (function.names != null) { 1289 contextVariables = new Hashtable<String, SV>(); 1290 function.setVariables(contextVariables, params); 1291 } 1292 if (tokenAtom != null) 1293 contextVariables.put("_x", tokenAtom); 1294 } 1295 1296 1297 ////////////////////////// defined atom sets //////////////////////// 1298 clearDefinedVariableAtomSets()1299 public void clearDefinedVariableAtomSets() { 1300 vwr.definedAtomSets.remove("# variable"); 1301 } 1302 1303 /** 1304 * support for @xxx or define xxx commands 1305 * 1306 */ defineSets()1307 private void defineSets() { 1308 if (!vwr.definedAtomSets.containsKey("# static")) { 1309 for (int i = 0; i < JC.predefinedStatic.length; i++) 1310 defineAtomSet(JC.predefinedStatic[i]); 1311 defineAtomSet("# static"); 1312 } 1313 if (vwr.definedAtomSets.containsKey("# variable")) 1314 return; 1315 for (int i = 0; i < JC.predefinedVariable.length; i++) 1316 defineAtomSet(JC.predefinedVariable[i]); 1317 // Now, define all the elements as predefined sets 1318 1319 // name ==> elemno=n for all standard elements, isotope-blind 1320 // _Xx ==> elemno=n for of all elements, isotope-blind 1321 for (int i = Elements.elementNumberMax; --i >= 0;) { 1322 String definition = " elemno=" + i; 1323 defineAtomSet("@" + Elements.elementNameFromNumber(i) + definition); 1324 defineAtomSet("@_" + Elements.elementSymbolFromNumber(i) + definition); 1325 } 1326 // name ==> _e=nn for each alternative element 1327 for (int i = Elements.firstIsotope; --i >= 0;) { 1328 String definition = "@" + Elements.altElementNameFromIndex(i) + " _e=" 1329 + Elements.altElementNumberFromIndex(i); 1330 defineAtomSet(definition); 1331 } 1332 // these variables _e, _x can't be more than two characters 1333 // name ==> _isotope=iinn for each isotope 1334 // _T ==> _isotope=iinn for each isotope 1335 // _3H ==> _isotope=iinn for each isotope 1336 for (int i = Elements.altElementMax; --i >= Elements.firstIsotope;) { 1337 int ei = Elements.altElementNumberFromIndex(i); 1338 String def = " _e=" + ei; 1339 String definition = "@_" + Elements.altElementSymbolFromIndex(i); 1340 defineAtomSet(definition + def); 1341 1342 definition = "@_" + Elements.altIsotopeSymbolFromIndex(i); 1343 defineAtomSet(definition + def); 1344 definition = "@_" + Elements.altIsotopeSymbolFromIndex2(i); 1345 defineAtomSet(definition + def); 1346 1347 definition = "@" + Elements.altElementNameFromIndex(i); 1348 if (definition.length() > 1) 1349 defineAtomSet(definition + def); 1350 1351 // @_12C _e=6 1352 // @_C12 _e=6 1353 int e = Elements.getElementNumber(ei); 1354 ei = Elements.getNaturalIsotope(e); 1355 if (ei > 0) { 1356 def = Elements.elementSymbolFromNumber(e); 1357 defineAtomSet("@_" + def + ei + " _e=" + e); 1358 defineAtomSet("@_" + ei + def + " _e=" + e); 1359 } 1360 } 1361 defineAtomSet("# variable"); 1362 } 1363 defineAtomSet(String script)1364 private void defineAtomSet(String script) { 1365 if (script.indexOf("#") == 0) { 1366 vwr.definedAtomSets.put(script, Boolean.TRUE); 1367 return; 1368 } 1369 ScriptContext sc = compiler.compile("#predefine", script, true, false, 1370 false, false); 1371 if (sc.errorType != null) { 1372 vwr 1373 .scriptStatus("JmolConstants.java ERROR: predefined set compile error:" 1374 + script + "\ncompile error:" + sc.errorMessageUntranslated); 1375 return; 1376 } 1377 1378 if (sc.getTokenCount() != 1) { 1379 vwr 1380 .scriptStatus("JmolConstants.java ERROR: predefinition does not have exactly 1 command:" 1381 + script); 1382 return; 1383 } 1384 T[] statement = sc.getToken(0); 1385 if (statement.length <= 2) { 1386 vwr.scriptStatus("JmolConstants.java ERROR: bad predefinition length:" 1387 + script); 1388 return; 1389 } 1390 int tok = statement[1].tok; 1391 if (!T.tokAttr(tok, T.identifier) && !T.tokAttr(tok, T.predefinedset)) { 1392 vwr.scriptStatus("JmolConstants.java ERROR: invalid variable name:" 1393 + script); 1394 return; 1395 } 1396 String name = ((String) statement[1].value).toLowerCase(); 1397 if (name.startsWith("dynamic_")) 1398 name = "!" + name.substring(8); 1399 vwr.definedAtomSets.put(name, statement); 1400 } 1401 lookupIdentifierValue(String identifier)1402 public BS lookupIdentifierValue(String identifier) throws ScriptException { 1403 1404 // called by ScriptExpr and ScriptExt 1405 1406 // all variables and possible residue names for PDB 1407 // or atom names for non-pdb atoms are processed here. 1408 1409 // priority is given to a defined variable. 1410 1411 BS bs = lookupValue(identifier, false); 1412 if (bs != null) 1413 return BSUtil.copy(bs); 1414 1415 // next we look for names of groups (PDB) or atoms (non-PDB) 1416 bs = getAtomBits(T.identifier, identifier); 1417 return (bs == null ? new BS() : bs); 1418 } 1419 lookupValue(String setName, boolean plurals)1420 private BS lookupValue(String setName, boolean plurals) 1421 throws ScriptException { 1422 if (chk) { 1423 return new BS(); 1424 } 1425 defineSets(); 1426 setName = setName.toLowerCase(); 1427 Object value = vwr.definedAtomSets.get(setName); 1428 boolean isDynamic = false; 1429 if (value == null) { 1430 value = vwr.definedAtomSets.get("!" + setName); 1431 isDynamic = (value != null); 1432 } 1433 if (value instanceof BS) 1434 return (BS) value; 1435 if (value instanceof T[]) { // j2s OK -- any Array here 1436 pushContext(null, "lookupValue"); 1437 BS bs = atomExpression((T[]) value, -2, 0, true, false, null, true); 1438 popContext(false, false); 1439 if (!isDynamic) 1440 vwr.definedAtomSets.put(setName, bs); 1441 return bs; 1442 } 1443 if (setName.equals("water")) { 1444 BS bs = vwr.ms.getAtoms(T.solvent, null); 1445 if (!isDynamic) 1446 vwr.definedAtomSets.put(setName, bs); 1447 return bs; 1448 } 1449 if (plurals) 1450 return null; 1451 int len = setName.length(); 1452 if (len < 5) // iron is the shortest 1453 return null; 1454 if (setName.charAt(len - 1) != 's') 1455 return null; 1456 if (setName.endsWith("ies")) 1457 setName = setName.substring(0, len - 3) + 'y'; 1458 else 1459 setName = setName.substring(0, len - 1); 1460 return lookupValue(setName, true); 1461 } 1462 1463 @Override deleteAtomsInVariables(BS bsDeleted)1464 public void deleteAtomsInVariables(BS bsDeleted) { 1465 for (Map.Entry<String, Object> entry : vwr.definedAtomSets.entrySet()) { 1466 Object value = entry.getValue(); 1467 if (value instanceof BS) { 1468 BSUtil.deleteBits((BS) value, bsDeleted); 1469 if (!entry.getKey().startsWith("!")) 1470 vwr 1471 .g.setUserVariable("@" + entry.getKey(), SV.newV(T.bitset, value)); 1472 } 1473 } 1474 } 1475 1476 1477 // ///////////////// Script context support ////////////////////// 1478 1479 @Override getThisContext()1480 public ScriptContext getThisContext() { 1481 return thisContext; 1482 } 1483 clearState(boolean tQuiet)1484 private void clearState(boolean tQuiet) { 1485 thisContext = null; 1486 scriptLevel = 0; 1487 setErrorMessage(null); 1488 contextPath = ""; 1489 this.tQuiet = tQuiet; 1490 } 1491 1492 @Override pushContextDown(String why)1493 public void pushContextDown(String why) { 1494 scriptLevel--; 1495 pushContext2(null, why); 1496 } 1497 pushContext(ContextToken token, String why)1498 private void pushContext(ContextToken token, String why) 1499 throws ScriptException { 1500 if (scriptLevel == contextDepthMax) 1501 error(ERROR_tooManyScriptLevels); 1502 pushContext2(token, why); 1503 } 1504 pushContext2(ContextToken token, String why)1505 private void pushContext2(ContextToken token, String why) { 1506 thisContext = getScriptContext(why); 1507 thisContext.token = token; 1508 if (token == null) { 1509 scriptLevel = ++thisContext.scriptLevel; 1510 } else { 1511 thisContext.scriptLevel = -1; 1512 contextVariables = new Hashtable<String, SV>(); 1513 if (token.contextVariables != null) 1514 for (String key : token.contextVariables.keySet()) 1515 ScriptCompiler.addContextVariable(contextVariables, key); 1516 } 1517 if (debugHigh || isCmdLine_c_or_C_Option) 1518 Logger.info("-->>----------------------".substring(0, 1519 Math.min(15, scriptLevel + 5)) 1520 + scriptLevel 1521 + " " 1522 + scriptFileName 1523 + " " 1524 + token 1525 + " " 1526 + thisContext.id + " " + why + " path=" + thisContext.contextPath); 1527 } 1528 1529 @Override getScriptContext(String why)1530 public ScriptContext getScriptContext(String why) { 1531 ScriptContext context = new ScriptContext(); 1532 if (debugHigh) 1533 Logger.info("creating context " + context.id + " for " + why + " path=" + contextPath); 1534 context.why = why; 1535 context.scriptLevel = scriptLevel; 1536 context.parentContext = thisContext; 1537 context.contextPath = contextPath; 1538 context.scriptFileName = scriptFileName; 1539 context.parallelProcessor = parallelProcessor; 1540 context.functionName = functionName; 1541 context.script = script; 1542 context.lineNumbers = lineNumbers; 1543 context.lineIndices = lineIndices; 1544 context.saveTokens(aatoken); 1545 context.statement = st; 1546 context.statementLength = slen; 1547 context.pc = context.pc0 = pc; 1548 context.lineEnd = lineEnd; 1549 context.pcEnd = pcEnd; 1550 context.iToken = iToken; 1551 context.theToken = theToken; 1552 context.theTok = theTok; 1553 context.outputBuffer = outputBuffer; 1554 context.vars = contextVariables; 1555 context.isStateScript = isStateScript; 1556 1557 context.errorMessage = errorMessage; 1558 context.errorType = errorType; 1559 context.iCommandError = iCommandError; 1560 context.chk = chk; 1561 context.executionStepping = executionStepping; 1562 context.executionPaused = executionPaused; 1563 context.scriptExtensions = scriptExtensions; 1564 1565 context.mustResumeEval = mustResumeEval; 1566 context.allowJSThreads = allowJSThreads; 1567 return context; 1568 } 1569 popContext(boolean isFlowCommand, boolean statementOnly)1570 void popContext(boolean isFlowCommand, boolean statementOnly) { 1571 if (thisContext == null) 1572 return; 1573 if (thisContext.scriptLevel > 0) 1574 scriptLevel = thisContext.scriptLevel - 1; 1575 // we must save (and thus NOT restore) the current statement 1576 // business when doing push/pop for commands like FOR and WHILE 1577 ScriptContext scTemp = (isFlowCommand ? getScriptContext("popFlow") : null); 1578 restoreScriptContext(thisContext, true, isFlowCommand, statementOnly); 1579 if (scTemp != null) 1580 restoreScriptContext(scTemp, true, false, true); 1581 if (debugHigh || isCmdLine_c_or_C_Option) 1582 Logger.info("--<<------------".substring(0, 1583 Math.min(15, scriptLevel + 5)) 1584 + (scriptLevel + 1) 1585 + " " 1586 + scriptFileName 1587 + " isFlow " 1588 + isFlowCommand 1589 + " thisContext=" 1590 + (thisContext == null ? "" : "" + thisContext.id) 1591 + " pc=" + pc + "-->" + pc + " path=" + (thisContext == null ? "" : thisContext.contextPath)); 1592 } 1593 restoreScriptContext(ScriptContext context, boolean isPopContext, boolean isFlowCommand, boolean statementOnly)1594 public void restoreScriptContext(ScriptContext context, boolean isPopContext, 1595 boolean isFlowCommand, boolean statementOnly) { 1596 1597 executing = !chk; 1598 if (context == null) 1599 return; 1600 if (!isFlowCommand) { 1601 st = context.statement; 1602 slen = context.statementLength; 1603 pc = context.pc; 1604 lineEnd = context.lineEnd; 1605 pcEnd = context.pcEnd; 1606 if (statementOnly) 1607 return; 1608 } 1609 if (context.privateFuncs != null) 1610 privateFuncs = context.privateFuncs; 1611 mustResumeEval = context.mustResumeEval; 1612 script = context.script; 1613 lineNumbers = context.lineNumbers; 1614 lineIndices = context.lineIndices; 1615 aatoken = context.restoreTokens(); 1616 contextVariables = context.vars; 1617 scriptExtensions = context.scriptExtensions; 1618 1619 if (isPopContext) { 1620 contextPath = context.contextPath; 1621 int pt = (contextPath == null ? -1 : contextPath.indexOf(" >> ")); 1622 if (pt >= 0) 1623 contextPath = contextPath.substring(0, pt); 1624 scriptFileName = context.scriptFileName; 1625 parallelProcessor = context.parallelProcessor; 1626 functionName = context.functionName; 1627 iToken = context.iToken; 1628 theToken = context.theToken; 1629 theTok = context.theTok; 1630 1631 outputBuffer = context.outputBuffer; 1632 isStateScript = context.isStateScript; 1633 thisContext = context.parentContext; 1634 allowJSThreads = context.allowJSThreads; 1635 if (debugHigh || isCmdLine_c_or_C_Option) 1636 Logger.info("--r------------".substring(0, 1637 Math.min(15, scriptLevel + 5)) 1638 + scriptLevel 1639 + " " 1640 + scriptFileName 1641 + " isPop " 1642 + isPopContext 1643 + " isFlow " 1644 + isFlowCommand 1645 + " context.id=" 1646 + context.id + " pc=" + pc + "-->" + context.pc + " " + contextPath); 1647 } else { 1648 error = (context.errorType != null); 1649 //isComplete = context.isComplete; 1650 errorMessage = context.errorMessage; 1651 errorMessageUntranslated = context.errorMessageUntranslated; 1652 iCommandError = context.iCommandError; 1653 errorType = context.errorType; 1654 } 1655 } 1656 1657 // /////////////// error message support ///////////////// 1658 setException(ScriptException sx, String msg, String untranslated)1659 public void setException(ScriptException sx, String msg, String untranslated) { 1660 // from ScriptException, while initializing 1661 sx.untranslated = (untranslated == null ? msg : untranslated); 1662 boolean isThrown = "!".equals(untranslated); 1663 errorType = msg; 1664 iCommandError = pc; 1665 if (sx.message == null) { 1666 sx.message = ""; 1667 return; 1668 } 1669 String s = ScriptEval.getContextTrace(vwr, 1670 getScriptContext("setException"), null, true).toString(); 1671 while (thisContext != null && !thisContext.isTryCatch) 1672 popContext(false, false); 1673 if (sx.message.indexOf(s) < 0) { 1674 sx.message += s; 1675 sx.untranslated += s; 1676 } 1677 resumeViewer(isThrown ? "throw context" : "scriptException"); 1678 if (isThrown || thisContext != null || chk 1679 || msg.indexOf(JC.NOTE_SCRIPT_FILE) >= 0) 1680 return; 1681 Logger.error("eval ERROR: " + s + "\n" + toString()); 1682 if (vwr.autoExit) 1683 vwr.exitJmol(); 1684 } 1685 1686 @SuppressWarnings("unchecked") statementAsString(Viewer vwr, T[] statement, int iTok, boolean doLogMessages)1687 public static String statementAsString(Viewer vwr, T[] statement, 1688 int iTok, boolean doLogMessages) { 1689 if (statement.length == 0) 1690 return ""; 1691 SB sb = new SB(); 1692 int tok = statement[0].tok; 1693 switch (tok) { 1694 case T.nada: 1695 return (String) statement[0].value; 1696 case T.end: 1697 if (statement.length == 2 1698 && (statement[1].tok == T.function || statement[1].tok == T.parallel)) 1699 return ((ScriptFunction) (statement[1].value)).toString(); 1700 } 1701 boolean useBraces = true;// (!Token.tokAttr(tok, 1702 // Token.atomExpressionCommand)); 1703 boolean inBrace = false; 1704 boolean inClauseDefine = false; 1705 boolean setEquals = (statement.length > 1 && tok == T.set 1706 && statement[0].value.equals("") 1707 && (statement[0].intValue == '=' || statement[0].intValue == '#') && statement[1].tok != T.expressionBegin); 1708 int len = statement.length; 1709 for (int i = 0; i < len; ++i) { 1710 T token = statement[i]; 1711 if (token == null) { 1712 len = i; 1713 break; 1714 } 1715 if (iTok == i - 1) 1716 sb.append(" <<"); 1717 if (i != 0) 1718 sb.appendC(' '); 1719 if (i == 2 && setEquals) { 1720 if ((setEquals = (token.tok != T.opEQ)) || statement[0].intValue == '#') { 1721 sb.append(setEquals ? "= " : "== "); 1722 if (!setEquals) 1723 continue; 1724 } 1725 } 1726 if (iTok == i && token.tok != T.expressionEnd) 1727 sb.append("<<<<"); 1728 switch (token.tok) { 1729 case T.expressionBegin: 1730 if (useBraces) 1731 sb.append("{"); 1732 continue; 1733 case T.expressionEnd: 1734 if (inClauseDefine && i == statement.length - 1) 1735 useBraces = false; 1736 if (useBraces) 1737 sb.append("}"); 1738 continue; 1739 case T.leftsquare: 1740 case T.rightsquare: 1741 break; 1742 case T.leftbrace: 1743 case T.rightbrace: 1744 inBrace = (token.tok == T.leftbrace); 1745 break; 1746 case T.define: 1747 if (i > 0 && ((String) token.value).equals("define")) { 1748 sb.append("@"); 1749 if (i + 1 < statement.length 1750 && statement[i + 1].tok == T.expressionBegin) { 1751 if (!useBraces) 1752 inClauseDefine = true; 1753 useBraces = true; 1754 } 1755 continue; 1756 } 1757 break; 1758 case T.on: 1759 sb.append("true"); 1760 continue; 1761 case T.off: 1762 sb.append("false"); 1763 continue; 1764 case T.select: 1765 break; 1766 case T.integer: 1767 sb.appendI(token.intValue); 1768 continue; 1769 case T.point3f: 1770 case T.point4f: 1771 case T.bitset: 1772 sb.append(SV.sValue(token)); // list 1773 continue; 1774 case T.hash: 1775 if (Boolean.TRUE == ((Map<String, Object>)token.value).get("$_BINARY_$")) { 1776 sb.append("<BINARY DATA>"); 1777 continue; 1778 } 1779 //$FALL-THROUGH$ 1780 case T.varray: 1781 sb.append(((SV) token).escape()); // list 1782 continue; 1783 case T.inscode: 1784 sb.appendC('^'); 1785 continue; 1786 case T.spec_seqcode_range: 1787 if (token.intValue != Integer.MAX_VALUE) 1788 sb.appendI(token.intValue); 1789 else 1790 sb.append(Group.getSeqcodeStringFor(getSeqCode(token))); 1791 token = statement[++i]; 1792 sb.appendC(' '); 1793 // if (token.intValue == Integer.MAX_VALUE) 1794 sb.append(inBrace ? "-" : "- "); 1795 //$FALL-THROUGH$ 1796 case T.spec_seqcode: 1797 if (token.intValue != Integer.MAX_VALUE) 1798 sb.appendI(token.intValue); 1799 else 1800 sb.append(Group.getSeqcodeStringFor(getSeqCode(token))); 1801 continue; 1802 case T.spec_chain: 1803 sb.append("*:"); 1804 sb.append(vwr.getChainIDStr(token.intValue)); 1805 continue; 1806 case T.spec_alternate: 1807 sb.append("*%"); 1808 if (token.value != null) 1809 sb.append(token.value.toString()); 1810 continue; 1811 case T.spec_model: 1812 sb.append("*/"); 1813 //$FALL-THROUGH$ 1814 case T.spec_model2: 1815 case T.decimal: 1816 if (token.intValue < Integer.MAX_VALUE) { 1817 sb.append(Escape.escapeModelFileNumber(token.intValue)); 1818 } else { 1819 sb.append("" + token.value); 1820 } 1821 continue; 1822 case T.spec_resid: 1823 sb.appendC('['); 1824 int ptr = token.intValue * 6 + 1; 1825 sb.append(Group.standardGroupList.substring(ptr, ptr + 3).trim()); 1826 sb.appendC(']'); 1827 continue; 1828 case T.spec_name_pattern: 1829 sb.appendC('['); 1830 sb.appendO(token.value); 1831 sb.appendC(']'); 1832 continue; 1833 case T.spec_atom: 1834 sb.append("*."); 1835 break; 1836 case T.cell: 1837 if (token.value instanceof P3) { 1838 P3 pt = (P3) token.value; 1839 sb.append("cell=").append(Escape.eP(pt)); 1840 continue; 1841 } 1842 break; 1843 case T.string: 1844 sb.append("\"").appendO(token.value).append("\""); 1845 continue; 1846 case T.opEQ: 1847 case T.opLE: 1848 case T.opGE: 1849 case T.opGT: 1850 case T.opLT: 1851 case T.opNE: 1852 // not quite right -- for "inmath" 1853 if (token.intValue == T.property) { 1854 sb.append((String) statement[++i].value).append(" "); 1855 } else if (token.intValue != Integer.MAX_VALUE) 1856 sb.append(T.nameOf(token.intValue)).append(" "); 1857 break; 1858 case T.trycmd: 1859 continue; 1860 case T.end: 1861 sb.append("end"); 1862 continue; 1863 default: 1864 if (T.tokAttr(token.tok, T.identifier) || !doLogMessages) 1865 break; 1866 sb.appendC('\n').append(token.toString()).appendC('\n'); 1867 continue; 1868 } 1869 if (token.value != null) 1870 sb.append(token.value.toString()); 1871 } 1872 // if (iTok >= len - 1 && iTok != 9999) 1873 // sb.append(" <<"); 1874 return sb.toString(); 1875 } 1876 1877 ///////////// shape get/set properties //////////////// 1878 1879 /** 1880 * called by Viewer in setting up a PyMOL scene. 1881 */ 1882 @Override setObjectPropSafe(String id, int tokCommand)1883 public String setObjectPropSafe(String id, int tokCommand) { 1884 try { 1885 return setObjectProp(id, tokCommand, -1); 1886 } catch (ScriptException e) { 1887 return null; 1888 } 1889 } 1890 setAtomProp(String prop, Object value, BS bs)1891 protected void setAtomProp(String prop, Object value, BS bs) { 1892 setShapePropertyBs(JC.SHAPE_BALLS, prop, value, bs); 1893 } 1894 restrictSelected(boolean isBond, boolean doInvert)1895 public void restrictSelected(boolean isBond, boolean doInvert) { 1896 1897 // called by ScriptParam 1898 1899 if (!chk) 1900 sm.restrictSelected(isBond, doInvert); 1901 } 1902 1903 //////////////////// showing strings ///////////////// 1904 showString(String str)1905 public void showString(String str) { 1906 // called by ScriptExt and ScriptError 1907 showStringPrint(str, false); 1908 } 1909 1910 @Override showStringPrint(String s, boolean mustDo)1911 public void showStringPrint(String s, boolean mustDo) { 1912 if (chk || s == null) 1913 return; 1914 if (outputBuffer == null) 1915 vwr.showString(s, mustDo); 1916 else 1917 appendBuffer(s, mustDo); 1918 } 1919 report(String s, boolean isError)1920 public void report(String s, boolean isError) { 1921 if (chk || isError && s.indexOf(" of try:") >= 0) 1922 return; 1923 if (outputBuffer == null) 1924 vwr.scriptStatus(s); 1925 else 1926 appendBuffer(s, isError); 1927 } 1928 appendBuffer(String str, boolean mustDo)1929 private void appendBuffer(String str, boolean mustDo) { 1930 if (mustDo || isFuncReturn || Logger.isActiveLevel(Logger.LEVEL_INFO)) 1931 outputBuffer.append(str).appendC('\n'); 1932 } 1933 1934 /* 1935 * **************************************************************** 1936 * =============== command processing checks =============================== 1937 */ 1938 addProcess(Lst<T[]> vProcess, int pc, int pt)1939 private void addProcess(Lst<T[]> vProcess, int pc, int pt) { 1940 if (parallelProcessor == null) 1941 return; 1942 T[][] statements = new T[pt][]; 1943 for (int i = 0; i < vProcess.size(); i++) 1944 statements[i + 1 - pc] = vProcess.get(i); 1945 ScriptContext context = getScriptContext("addProcess"); 1946 context.saveTokens(statements); 1947 context.pc = 1 - pc; 1948 context.pcEnd = pt; 1949 parallelProcessor.addProcess("p" + (++iProcess), context); 1950 } 1951 1952 /** 1953 * checks to see if there is a pause condition, during which commands can 1954 * still be issued, but with the ! first. 1955 * 1956 * @return false if there was a problem 1957 * @throws ScriptException 1958 */ checkContinue()1959 private boolean checkContinue() throws ScriptException { 1960 if (executionStopped) 1961 return false; 1962 if (executionStepping && isCommandDisplayable(pc)) { 1963 vwr.scriptStatusMsg("Next: " + getNextStatement(), 1964 "stepping -- type RESUME to continue"); 1965 executionPaused = true; 1966 } else if (!executionPaused) { 1967 return true; 1968 } 1969 if (Logger.debugging) { 1970 Logger.debug("script execution paused at command " + (pc + 1) + " level " 1971 + scriptLevel + ": " + thisCommand); 1972 } 1973 refresh(false); 1974 while (executionPaused) { 1975 vwr.popHoldRepaint("pause " + JC.REPAINT_IGNORE); 1976 // does not actually do a repaint 1977 // but clears the way for interaction 1978 String script = vwr.getInsertedCommand(); 1979 if (script.length() > 0) { 1980 resumePausedExecution(); 1981 setErrorMessage(null); 1982 ScriptContext scSave = getScriptContext("script insertion"); 1983 pc--; // in case there is an error, we point to the PAUSE command 1984 try { 1985 runScript(script); 1986 } catch (Exception e) { 1987 setErrorMessage("" + e); 1988 } catch (Error er) { 1989 setErrorMessage("" + er); 1990 } 1991 if (error) { 1992 report(errorMessage, true); 1993 setErrorMessage(null); 1994 } 1995 restoreScriptContext(scSave, true, false, false); 1996 pauseExecution(false); 1997 } 1998 doDelay(ScriptDelayThread.PAUSE_DELAY); 1999 // JavaScript will not reach this point, 2000 // but no need to pop anyway, because 2001 // we will be out of this thread. 2002 vwr.pushHoldRepaintWhy("pause"); 2003 } 2004 notifyResumeStatus(); 2005 // once more to trap quit during pause 2006 return !error && !executionStopped; 2007 } 2008 delayScript(int millis)2009 public void delayScript(int millis) { 2010 if (vwr.autoExit) 2011 return; 2012 stopScriptThreads(); 2013 if (vwr.captureParams != null && millis > 0) { 2014 vwr.captureParams.put("captureDelayMS", Integer.valueOf(millis)); 2015 } 2016 scriptDelayThread = new ScriptDelayThread(this, vwr, millis); 2017 if (isJS && allowJSThreads) { 2018 // abort this; wait for delay to come back. 2019 pc = aatoken.length; 2020 } 2021 scriptDelayThread.run(); 2022 } 2023 2024 /** 2025 * 2026 * @param millis 2027 * negative here bypasses max check 2028 * @throws ScriptException 2029 */ doDelay(int millis)2030 private void doDelay(int millis) throws ScriptException { 2031 if (!useThreads()) 2032 return; 2033 if (isJS) 2034 throw new ScriptInterruption(this, CONTEXT_DELAY, millis); 2035 delayScript(millis); 2036 } 2037 2038 @Override evalParallel(ScriptContext context, ShapeManager shapeManager)2039 public boolean evalParallel(ScriptContext context, 2040 ShapeManager shapeManager) { 2041 2042 // now in ScriptExt 2043 2044 return getCmdExt().evalParallel(context, shapeManager); 2045 } 2046 2047 /** 2048 * provides support for the script editor 2049 * 2050 * @param i 2051 * @return true if displayable 2052 */ isCommandDisplayable(int i)2053 private boolean isCommandDisplayable(int i) { 2054 if (i >= aatoken.length || i >= pcEnd || aatoken[i] == null) 2055 return false; 2056 return (lineIndices[i][1] > lineIndices[i][0]); 2057 } 2058 2059 /** 2060 * load a static file asynchronously 2061 */ 2062 @Override loadFileResourceAsync(String fileName)2063 public void loadFileResourceAsync(String fileName) throws ScriptException { 2064 loadFileAsync(null, fileName, -Math.abs(fileName.hashCode()), false); 2065 } 2066 2067 /** 2068 * Allows asynchronous file loading from the LOAD or SCRIPT command. Saves the 2069 * context, initiates a FileLoadThread instance. When the file loading 2070 * completes, the file data (sans filename) is saved in the FileManager cache 2071 * under cache://localLoad_xxxxx. Context is resumed at this command in the 2072 * script, and the file is then retrieved from the cache. Only run from 2073 * JSmol/HTML5 when vwr.isJS; 2074 * 2075 * Incompatibilities: 2076 * 2077 * LOAD and SCRIPT commands, load() function only; 2078 * 2079 * only one "?" per LOAD command 2080 * 2081 * @param prefix 2082 * @param filename 2083 * or null if end of LOAD command and now just clearing out cache 2084 * @param i 2085 * @param doClear 2086 * ensures only one file is in the cache for a given type 2087 * @return cached file name if it exists 2088 * @throws ScriptException 2089 */ loadFileAsync(String prefix, String filename, int i, boolean doClear)2090 public String loadFileAsync(String prefix, String filename, int i, 2091 boolean doClear) throws ScriptException { 2092 // note that we will never know the actual file name 2093 // so we construct one and point to it in the scriptContext 2094 // with a key to this point in the script. 2095 2096 if (vwr.fm.cacheGet(filename, false) != null) { 2097 cancelFileThread(); 2098 return filename; 2099 } 2100 if (prefix != null) 2101 prefix = "cache://local" + prefix; 2102 String key = pc + "_" + i + "_" + filename; 2103 String cacheName; 2104 if (thisContext == null) { 2105 // add temp context 2106 pushContext(null, "loadFileAsync"); 2107 } 2108 if (thisContext.htFileCache == null) { 2109 thisContext.htFileCache = new Hashtable<String, String>(); 2110 } 2111 cacheName = thisContext.htFileCache.get(key); 2112 if (cacheName != null && cacheName.length() > 0) { 2113 cancelFileThread(); 2114 //no, problems with isosurface "?" map "?": popContext(false, false); 2115 vwr.queueOnHold = false; 2116 if ("#CANCELED#".equals(cacheName) || "#CANCELED#".equals(vwr.fm.cacheGet(cacheName, false))) 2117 evalError("#CANCELED#", null); 2118 return cacheName; 2119 } 2120 thisContext.htFileCache.put(key, 2121 cacheName = prefix + System.currentTimeMillis()); 2122 // if (fileLoadThread != null && i >= 0) 2123 // evalError("#CANCELED#", null); 2124 if (doClear) 2125 vwr.cacheFileByName(prefix + "*", false); 2126 fileLoadThread = new FileLoadThread(this, vwr, filename, key, cacheName); 2127 if (vwr.testAsync) 2128 fileLoadThread.start(); 2129 else 2130 fileLoadThread.run(); 2131 if (i < 0) // no need to hang on to this - never "canceled" 2132 fileLoadThread = null; 2133 throw new ScriptInterruption(this, "load", 1); 2134 } 2135 cancelFileThread()2136 private void cancelFileThread() { 2137 // file has been loaded 2138 fileLoadThread = null; 2139 if (thisContext != null && thisContext.why == "loadFileAsync") { 2140 // remove temp context 2141 popContext(false, false); 2142 } 2143 } 2144 2145 @SuppressWarnings("unchecked") logLoadInfo(String msg, boolean isData)2146 private void logLoadInfo(String msg, boolean isData) { 2147 if (msg.length() > 0) 2148 Logger.info(msg); 2149 SB sb = new SB(); 2150 int modelCount = vwr.ms.mc; 2151 if (modelCount > 1 && !isData) 2152 sb.append((vwr.am.isMovie ? vwr.am.getFrameCount() + " frames" 2153 : modelCount + " models") + "\n"); 2154 for (int i = 0; i < modelCount; i++) { 2155 Map<String, Object> moData = (Map<String, Object>) vwr 2156 .ms.getInfo(i, "moData"); 2157 if (moData == null || !moData.containsKey("mos")) 2158 continue; 2159 sb.appendI(((Lst<Map<String, Object>>) moData.get("mos")).size()) 2160 .append(" molecular orbitals in model ") 2161 .append(vwr.getModelNumberDotted(i)).append("\n"); 2162 } 2163 if (sb.length() > 0) 2164 vwr.showString(sb.toString(), false); 2165 } 2166 2167 @Override notifyResumeStatus()2168 public void notifyResumeStatus() { 2169 if (!chk && !executionStopped && !executionStepping && !executionPaused) { 2170 vwr.scriptStatus("script execution " 2171 + (error || executionStopped ? "interrupted" : "resumed")); 2172 } 2173 if (Logger.debugging) 2174 Logger.debug("script execution resumed"); 2175 } 2176 2177 /** 2178 * Refresh the display NOW 2179 * @param doDelay 2180 * @throws ScriptException 2181 * 2182 */ refresh(boolean doDelay)2183 public void refresh(boolean doDelay) throws ScriptException { 2184 if (chk) 2185 return; 2186 vwr.setTainted(true); 2187 vwr.requestRepaintAndWait("refresh cmd"); 2188 if (isJS && doDelay) 2189 doDelay(10); // need this to update JavaScript display 2190 } 2191 2192 @Override stopScriptThreads()2193 public void stopScriptThreads() { 2194 if (scriptDelayThread != null) { 2195 scriptDelayThread.interrupt(); 2196 scriptDelayThread = null; 2197 } 2198 if (fileLoadThread != null) { 2199 fileLoadThread.interrupt(); 2200 fileLoadThread.resumeEval(); 2201 cancelFileThread(); 2202 } 2203 } 2204 2205 // from ScriptExt 2206 getErrorLineMessage2()2207 public String getErrorLineMessage2() { 2208 return getErrorLineMessage(functionName, scriptFileName, 2209 getLinenumber(null), pc, 2210 statementAsString(vwr, st, -9999, debugHigh)); 2211 } 2212 getLinenumber(ScriptContext c)2213 public int getLinenumber(ScriptContext c) { 2214 return (c == null ? lineNumbers[pc] : c.lineNumbers[c.pc]); 2215 } 2216 2217 2218 /////////////////////////////////////////////////////////////////////// 2219 ///////////////////////// Jmol script commands //////////////////////// 2220 /////////////////////////////////////////////////////////////////////// 2221 2222 /** 2223 * 2224 * @param isSpt 2225 * @param fromFunc 2226 * @param isTry 2227 * @return false only when still working through resumeEval 2228 * @throws ScriptException 2229 */ dispatchCommands(boolean isSpt, boolean fromFunc, boolean isTry)2230 public boolean dispatchCommands(boolean isSpt, boolean fromFunc, boolean isTry) 2231 throws ScriptException { 2232 if (sm == null) 2233 sm = vwr.shm; 2234 debugScript = debugHigh = false; 2235 if (!chk) 2236 setDebugging(); 2237 if (pcEnd == 0) 2238 pcEnd = Integer.MAX_VALUE; 2239 if (lineEnd == 0) 2240 lineEnd = Integer.MAX_VALUE; 2241 if (aatoken == null) 2242 return true; 2243 if (!tQuiet) { 2244 tQuiet = (vwr.getInt(T.showscript) < 0); 2245 } 2246 boolean allowJSInterrupt = ( 2247 isJS 2248 && !fromFunc 2249 && useThreads() 2250 && vwr.getInt(T.showscript) >= 0); 2251 commandLoop(allowJSInterrupt); 2252 if (chk) 2253 return true; 2254 String script = vwr.getInsertedCommand(); 2255 if (!"".equals(script)) 2256 runScriptBuffer(script, null, false); 2257 else if (isSpt && debugScript && vwr.getBoolean(T.messagestylechime)) 2258 vwr.getChimeMessenger().update(null); 2259 if (!mustResumeEval && !allowJSInterrupt || fromFunc) 2260 return true; 2261 if (!isTry && mustResumeEval || thisContext == null) { 2262 boolean done = (thisContext == null); 2263 resumeEval(thisContext); 2264 mustResumeEval = false; 2265 return done; 2266 } 2267 return true; 2268 } 2269 commandLoop(boolean allowJSInterrupt)2270 private void commandLoop(boolean allowJSInterrupt) throws ScriptException { 2271 String lastCommand = ""; 2272 boolean isForCheck = false; // indicates the stage of the for command loop 2273 Lst<T[]> vProcess = null; 2274 long lastTime = System.currentTimeMillis(); 2275 2276 if (debugScript && debugHigh && !chk) { 2277 for (int i = pc; i < aatoken.length && i < pcEnd; i++) { 2278 Logger.info("Command " + i); 2279 if (debugScript) 2280 logDebugScript(aatoken[i], 0); 2281 } 2282 Logger.info("-----"); 2283 } 2284 2285 for (; pc < aatoken.length && pc < pcEnd; pc++) { 2286 if (allowJSInterrupt) { 2287 // every 1 s check for interruptions 2288 if (!executionPaused && System.currentTimeMillis() - lastTime > DELAY_INTERRUPT_MS) { 2289 pc--; 2290 doDelay(-1); 2291 } 2292 lastTime = System.currentTimeMillis(); 2293 } 2294 if (!chk && !checkContinue()) 2295 break; 2296 if (pc >= lineNumbers.length || lineNumbers[pc] > lineEnd) 2297 break; 2298 if (debugHigh) { 2299 long timeBegin = 0; 2300 timeBegin = System.currentTimeMillis(); 2301 vwr.scriptStatus("Eval.dispatchCommands():" + timeBegin); 2302 vwr.scriptStatus(script); 2303 } 2304 2305 if (debugScript && !chk) 2306 Logger.info("Command " + pc 2307 + (thisContext == null ? "" : " path=" + thisContext.contextPath)); 2308 theToken = (aatoken[pc].length == 0 ? null : aatoken[pc][0]); 2309 // when checking scripts, we can't check statments 2310 // containing @{...} 2311 if (!historyDisabled && !chk && scriptLevel <= commandHistoryLevelMax 2312 && !tQuiet) { 2313 String cmdLine = getCommand(pc, true, true); 2314 if (theToken != null 2315 && cmdLine.length() > 0 2316 && !cmdLine.equals(lastCommand) 2317 && (theToken.tok == T.function || theToken.tok == T.parallel || !T 2318 .tokAttr(theToken.tok, T.flowCommand))) 2319 vwr.addCommand(lastCommand = cmdLine); 2320 } 2321 if (!chk && allowJSInterrupt) { 2322 String script = vwr.getInsertedCommand(); 2323 if (!"".equals(script)) 2324 runScript(script); 2325 } 2326 if (!setStatement(aatoken[pc], 1)) { 2327 Logger.info(getCommand(pc, true, false) 2328 + " -- STATEMENT CONTAINING @{} SKIPPED"); 2329 continue; 2330 } 2331 thisCommand = getCommand(pc, false, true); 2332 if (debugHigh || debugScript) 2333 Logger.info(thisCommand); 2334 String nextCommand = getCommand(pc + 1, false, true); 2335 fullCommand = thisCommand 2336 + (nextCommand.startsWith("#") ? nextCommand : ""); 2337 getToken(0); 2338 iToken = 0; 2339 if ((listCommands || !chk && scriptLevel > 0) && !isJS) { 2340 int milliSecDelay = vwr.getInt(T.showscript); 2341 if (listCommands || milliSecDelay > 0) { 2342 if (milliSecDelay > 0) 2343 delayScript(-milliSecDelay); 2344 vwr.scriptEcho("$[" + scriptLevel + "." + lineNumbers[pc] + "." 2345 + (pc + 1) + "] " + thisCommand); 2346 } 2347 } 2348 if (vProcess != null 2349 && (theTok != T.end || slen < 2 || st[1].tok != T.process)) { 2350 vProcess.addLast(st); 2351 continue; 2352 } 2353 if (chk) { 2354 if (isCmdLine_c_or_C_Option) 2355 Logger.info(thisCommand); 2356 if (slen == 1 && st[0].tok != T.function && st[0].tok != T.parallel) 2357 continue; 2358 } else { 2359 if (debugScript) 2360 logDebugScript(st, 0); 2361 if (scriptLevel == 0 && vwr.g.logCommands) 2362 vwr.log(thisCommand); 2363 if (debugHigh && theToken != null) 2364 Logger.debug(theToken.toString()); 2365 } 2366 if (theToken == null) 2367 continue; 2368 int tok = theToken.tok; 2369 switch (tok) { 2370 case T.set: 2371 cmdSet(); 2372 continue; 2373 case T.forcmd: 2374 isForCheck = cmdFor(tok, isForCheck); 2375 continue; 2376 case T.process: 2377 pushContext((ContextToken) theToken, "PROCESS"); 2378 if (parallelProcessor != null) 2379 vProcess = new Lst<T[]>(); 2380 continue; 2381 default: 2382 if (T.tokAttr(tok, T.flowCommand)) { 2383 isForCheck = cmdFlow(tok, isForCheck, vProcess); 2384 if (theTok == T.process) 2385 vProcess = null; // "end process" 2386 continue; 2387 } 2388 processCommand(tok); 2389 setCursorWait(false); 2390 if (executionStepping) { 2391 executionPaused = (isCommandDisplayable(pc + 1)); 2392 } 2393 } 2394 } 2395 } 2396 2397 // public void terminateAfterStep() { 2398 // pc = pcEnd; 2399 // } 2400 processCommand(int tok)2401 private void processCommand(int tok) throws ScriptException { 2402 if (T.tokAttr(theToken.tok, T.shapeCommand)) { 2403 processShapeCommand(tok); 2404 return; 2405 } 2406 switch (tok) { 2407 case T.nada: 2408 if (!chk && vwr.getBoolean(T.messagestylechime)) 2409 vwr.getChimeMessenger().showHash(outputBuffer, (String) theToken.value); 2410 break; 2411 case T.push: 2412 pushContext((ContextToken) theToken, "PUSH"); 2413 break; 2414 case T.pop: 2415 popContext(true, false); 2416 break; 2417 case T.colon: 2418 break; 2419 case T.animation: 2420 cmdAnimation(); 2421 break; 2422 case T.background: 2423 cmdBackground(1); 2424 break; 2425 case T.bind: 2426 cmdBind(); 2427 break; 2428 case T.bondorder: 2429 cmdBondorder(); 2430 break; 2431 case T.cd: 2432 cmdCD(); 2433 break; 2434 case T.center: 2435 cmdCenter(1); 2436 break; 2437 case T.color: 2438 cmdColor(); 2439 break; 2440 case T.define: 2441 cmdDefine(); 2442 break; 2443 case T.delay: 2444 cmdDelay(); 2445 break; 2446 case T.delete: 2447 cmdDelete(); 2448 break; 2449 case T.depth: 2450 cmdSlab(true); 2451 break; 2452 case T.display: 2453 cmdDisplay(true); 2454 break; 2455 case T.exit: // flush the queue and... 2456 case T.quit: // quit this only if it isn't the first command 2457 if (chk) 2458 break; 2459 if (pc > 0 && theToken.tok == T.exit && !vwr.autoExit) { 2460 vwr.clearScriptQueue(); 2461 } 2462 executionStopped = (pc > 0 || !vwr.g.useScriptQueue); 2463 break; 2464 case T.exitjmol: 2465 if (chk) 2466 return; 2467 if (outputBuffer != null) 2468 Logger.warn(outputBuffer.toString()); 2469 vwr.exitJmol(); 2470 break; 2471 case T.file: 2472 cmdFile(); 2473 break; 2474 case T.fixed: 2475 cmdFixed(); 2476 break; 2477 case T.font: 2478 cmdFont(-1, 0); 2479 break; 2480 case T.frame: 2481 case T.model: 2482 cmdModel(1); 2483 break; 2484 case T.identifier: 2485 cmdFunc(); // when a function is a command 2486 break; 2487 case T.getproperty: 2488 cmdGetProperty(); 2489 break; 2490 case T.gotocmd: // 2491 if (vwr.headless) 2492 break; 2493 cmdGoto(true); 2494 break; 2495 case T.help: 2496 cmdHelp(); 2497 break; 2498 case T.hide: 2499 cmdDisplay(false); 2500 break; 2501 case T.hbond: 2502 cmdHbond(); 2503 break; 2504 case T.history: 2505 cmdHistory(1); 2506 break; 2507 case T.hover: 2508 cmdHover(); 2509 break; 2510 case T.initialize: 2511 switch (slen) { 2512 case 1: 2513 if (!chk) 2514 vwr.initialize(!isStateScript, false); 2515 break; 2516 case 2: 2517 if (tokAt(1) == T.inchi) { 2518 vwr.getInchi(null, null, null); 2519 if (chk) { 2520 } else { 2521 if (Viewer.isJS) { 2522 vwr.showString("InChI module initialized", false); 2523 doDelay(1); 2524 } 2525 } 2526 break; 2527 } 2528 //$FALL-THROUGH$ 2529 default: 2530 bad(); 2531 } 2532 break; 2533 case T.javascript: 2534 cmdScript(T.javascript, null, null); 2535 break; 2536 case T.load: 2537 cmdLoad(); 2538 break; 2539 case T.log: 2540 cmdLog(); 2541 break; 2542 case T.loop: 2543 cmdLoop(); 2544 break; 2545 case T.message: 2546 cmdMessage(); 2547 break; 2548 case T.move: 2549 cmdMove(); 2550 break; 2551 case T.moveto: 2552 cmdMoveto(); 2553 break; 2554 case T.pause: // resume is done differently 2555 cmdPause(); 2556 break; 2557 case T.print: 2558 cmdPrint(); 2559 break; 2560 case T.prompt: 2561 cmdPrompt(); 2562 break; 2563 case T.redomove: 2564 case T.undomove: 2565 cmdUndoRedoMove(); 2566 break; 2567 case T.refresh: 2568 refresh(true); 2569 break; 2570 case T.reset: 2571 cmdReset(); 2572 break; 2573 case T.restrict: 2574 cmdRestrict(); 2575 break; 2576 case T.resume: 2577 if (slen == 0) { 2578 if (!chk) 2579 resumePausedExecution(); 2580 break; 2581 } 2582 //$FALL-THROUGH$ 2583 case T.restore: 2584 cmdRestore(); 2585 break; 2586 case T.returncmd: 2587 cmdReturn(null); 2588 break; 2589 case T.rotate: 2590 cmdRotate(false, false); 2591 break; 2592 case T.rotateSelected: 2593 cmdRotate(false, true); 2594 break; 2595 case T.save: 2596 cmdSave(); 2597 break; 2598 case T.script: 2599 cmdScript(T.script, null, null); 2600 break; 2601 case T.select: 2602 cmdSelect(1); 2603 break; 2604 case T.selectionhalos: 2605 cmdSelectionHalos(1); 2606 break; 2607 case T.slab: 2608 cmdSlab(false); 2609 break; 2610 //case Token.slice: 2611 // slice(); 2612 //break; 2613 case T.spin: 2614 cmdRotate(true, false); 2615 break; 2616 case T.ssbond: 2617 cmdSsbond(); 2618 break; 2619 case T.step: 2620 if (cmdPause()) 2621 stepPausedExecution(); 2622 break; 2623 case T.structure: 2624 cmdStructure(); 2625 break; 2626 case T.subset: 2627 cmdSubset(); 2628 break; 2629 case T.sync: 2630 cmdSync(); 2631 break; 2632 case T.throwcmd: 2633 cmdThrow(); 2634 break; 2635 case T.timeout: 2636 cmdTimeout(1); 2637 break; 2638 case T.translate: 2639 cmdTranslate(false); 2640 break; 2641 case T.translateSelected: 2642 cmdTranslate(true); 2643 break; 2644 case T.unbind: 2645 cmdUnbind(); 2646 break; 2647 case T.var: 2648 break; 2649 case T.vibration: 2650 cmdVibration(); 2651 break; 2652 case T.zap: 2653 cmdZap(true); 2654 break; 2655 case T.zoom: 2656 cmdZoom(false); 2657 break; 2658 case T.zoomTo: 2659 cmdZoom(true); 2660 break; 2661 default: 2662 checkExtension(theToken.tok); 2663 } 2664 } 2665 checkExtension(int tok)2666 private void checkExtension(int tok) throws ScriptException { 2667 switch (tok) { 2668 case T.assign: 2669 case T.cache: 2670 case T.calculate: 2671 case T.capture: 2672 case T.centerat: 2673 case T.compare: 2674 case T.configuration: 2675 case T.connect: 2676 case T.console: 2677 case T.hbond: // hbond connect 2678 case T.image: 2679 case T.invertSelected: 2680 case T.stereo: 2681 case T.macro: 2682 case T.mapproperty: 2683 case T.minimize: 2684 case T.modelkitmode: 2685 case T.modulation: 2686 case T.mutate: 2687 case T.data: 2688 case T.navigate: 2689 case T.plot: 2690 case T.quaternion: 2691 case T.ramachandran: 2692 case T.show: 2693 case T.write: 2694 getCmdExt().dispatch(tok, false, st); 2695 break; 2696 default: 2697 System.out.println(T.nameOf(tok) + " is not a command"); 2698 error(ERROR_unrecognizedCommand); 2699 } 2700 } 2701 processShapeCommand(int tok)2702 private void processShapeCommand(int tok) throws ScriptException { 2703 int iShape = 0; 2704 switch (tok) { 2705 case T.axes: 2706 iShape = JC.SHAPE_AXES; 2707 break; 2708 case T.backbone: 2709 iShape = JC.SHAPE_BACKBONE; 2710 break; 2711 case T.boundbox: 2712 iShape = JC.SHAPE_BBCAGE; 2713 break; 2714 case T.cartoon: 2715 iShape = JC.SHAPE_CARTOON; 2716 break; 2717 case T.cgo: 2718 iShape = JC.SHAPE_CGO; 2719 break; 2720 case T.contact: 2721 iShape = JC.SHAPE_CONTACT; 2722 break; 2723 case T.dipole: 2724 iShape = JC.SHAPE_DIPOLES; 2725 break; 2726 case T.dots: 2727 iShape = JC.SHAPE_DOTS; 2728 break; 2729 case T.draw: 2730 iShape = JC.SHAPE_DRAW; 2731 break; 2732 case T.echo: 2733 iShape = JC.SHAPE_ECHO; 2734 break; 2735 case T.ellipsoid: 2736 iShape = JC.SHAPE_ELLIPSOIDS; 2737 break; 2738 case T.frank: 2739 iShape = JC.SHAPE_FRANK; 2740 break; 2741 case T.geosurface: 2742 iShape = JC.SHAPE_GEOSURFACE; 2743 break; 2744 case T.halo: 2745 iShape = JC.SHAPE_HALOS; 2746 break; 2747 case T.isosurface: 2748 iShape = JC.SHAPE_ISOSURFACE; 2749 break; 2750 case T.label: 2751 iShape = JC.SHAPE_LABELS; 2752 break; 2753 case T.lcaocartoon: 2754 iShape = JC.SHAPE_LCAOCARTOON; 2755 break; 2756 case T.measurements: 2757 case T.measure: 2758 iShape = JC.SHAPE_MEASURES; 2759 break; 2760 case T.meshRibbon: 2761 iShape = JC.SHAPE_MESHRIBBON; 2762 break; 2763 case T.mo: 2764 iShape = JC.SHAPE_MO; 2765 break; 2766 case T.nbo: 2767 iShape = JC.SHAPE_NBO; 2768 break; 2769 case T.plot3d: 2770 iShape = JC.SHAPE_PLOT3D; 2771 break; 2772 case T.pmesh: 2773 iShape = JC.SHAPE_PMESH; 2774 break; 2775 case T.polyhedra: 2776 iShape = JC.SHAPE_POLYHEDRA; 2777 break; 2778 case T.ribbon: 2779 iShape = JC.SHAPE_RIBBONS; 2780 break; 2781 case T.rocket: 2782 iShape = JC.SHAPE_ROCKETS; 2783 break; 2784 case T.spacefill: // aka cpk 2785 iShape = JC.SHAPE_BALLS; 2786 break; 2787 case T.star: 2788 iShape = JC.SHAPE_STARS; 2789 break; 2790 case T.strands: 2791 iShape = JC.SHAPE_STRANDS; 2792 break; 2793 case T.struts: 2794 iShape = JC.SHAPE_STRUTS; 2795 break; 2796 case T.trace: 2797 iShape = JC.SHAPE_TRACE; 2798 break; 2799 case T.unitcell: 2800 iShape = JC.SHAPE_UCCAGE; 2801 break; 2802 case T.vector: 2803 iShape = JC.SHAPE_VECTORS; 2804 break; 2805 case T.wireframe: 2806 iShape = JC.SHAPE_STICKS; 2807 break; 2808 default: 2809 error(ERROR_unrecognizedCommand); 2810 } 2811 2812 // check for "OFF/delete/NONE" with no shape to avoid loading it at all 2813 if (sm.getShape(iShape) == null && slen == 2) { 2814 switch (st[1].tok) { 2815 case T.off: 2816 case T.delete: 2817 case T.none: 2818 return; 2819 } 2820 } 2821 2822 // atom objects: 2823 2824 switch (tok) { 2825 case T.backbone: 2826 case T.cartoon: 2827 case T.meshRibbon: 2828 case T.ribbon: 2829 case T.rocket: 2830 case T.strands: 2831 case T.trace: 2832 setSizeBio(iShape); 2833 return; 2834 case T.dots: 2835 case T.geosurface: 2836 cmdDots(iShape); 2837 return; 2838 case T.halo: 2839 case T.spacefill: // aka cpk 2840 case T.star: 2841 setSize(iShape, (tok == T.halo ? -1000f : 1f)); 2842 return; 2843 case T.label: 2844 cmdLabel(1, null); 2845 return; 2846 case T.vector: 2847 cmdVector(); 2848 return; 2849 case T.wireframe: 2850 cmdWireframe(); 2851 return; 2852 } 2853 2854 // other objects: 2855 2856 switch (tok) { 2857 case T.axes: 2858 cmdAxes(1); 2859 return; 2860 case T.boundbox: 2861 cmdBoundbox(1); 2862 return; 2863 case T.echo: 2864 cmdEcho(1); 2865 return; 2866 case T.frank: 2867 cmdFrank(1); 2868 return; 2869 case T.unitcell: 2870 cmdUnitcell(1); 2871 return; 2872 case T.ellipsoid: 2873 case T.measurements: 2874 case T.measure: 2875 case T.polyhedra: 2876 case T.struts: 2877 getCmdExt().dispatch(iShape, false, st); 2878 return; 2879 case T.cgo: 2880 case T.contact: 2881 case T.dipole: 2882 case T.draw: 2883 case T.isosurface: 2884 case T.lcaocartoon: 2885 case T.mo: 2886 case T.nbo: 2887 case T.plot3d: 2888 case T.pmesh: 2889 getIsoExt().dispatch(iShape, false, st); 2890 return; 2891 } 2892 } 2893 cmdAnimation()2894 private void cmdAnimation() throws ScriptException { 2895 boolean animate = false; 2896 switch (getToken(1).tok) { 2897 case T.on: 2898 animate = true; 2899 //$FALL-THROUGH$ 2900 case T.off: 2901 if (!chk) 2902 vwr.setAnimationOn(animate); 2903 break; 2904 case T.morph: 2905 int morphCount = (int) floatParameter(2); 2906 if (!chk) 2907 vwr.am.setMorphCount(Math.abs(morphCount)); 2908 break; 2909 case T.display: 2910 iToken = 2; 2911 BS bs = (tokAt(2) == T.all ? null : atomExpressionAt(2)); 2912 checkLength(iToken + 1); 2913 if (!chk) 2914 vwr.setAnimDisplay(bs); 2915 return; 2916 case T.frame: 2917 if (isArrayParameter(2)) 2918 setFrameSet(2); 2919 else 2920 cmdModel(2); 2921 break; 2922 case T.mode: 2923 float startDelay = 1, 2924 endDelay = 1; 2925 if (slen > 5) 2926 bad(); 2927 int animationMode = T.getTokFromName(paramAsStr(2)); 2928 switch (animationMode) { 2929 case T.once: 2930 startDelay = endDelay = 0; 2931 break; 2932 case T.loop: 2933 case T.palindrome: 2934 break; 2935 default: 2936 invArg(); 2937 } 2938 if (slen >= 4) { 2939 startDelay = endDelay = floatParameter(3); 2940 if (slen == 5) 2941 endDelay = floatParameter(4); 2942 } 2943 if (!chk) 2944 vwr.am.setAnimationReplayMode(animationMode, startDelay, endDelay); 2945 break; 2946 case T.direction: 2947 int i = 2; 2948 int direction = 0; 2949 switch (tokAt(i)) { 2950 case T.minus: 2951 direction = -intParameter(++i); 2952 break; 2953 case T.plus: 2954 direction = intParameter(++i); 2955 break; 2956 case T.integer: 2957 direction = intParameter(i); 2958 break; 2959 default: 2960 invArg(); 2961 } 2962 checkLength(++i); 2963 if (direction != 1 && direction != -1) 2964 errorStr2(ERROR_numberMustBe, "-1", "1"); 2965 if (!chk) 2966 vwr.am.setAnimationDirection(direction); 2967 break; 2968 case T.fps: 2969 setIntProperty("animationFps", intParameter(checkLast(2))); 2970 break; 2971 default: 2972 frameControl(1); 2973 } 2974 } 2975 setFrameSet(int i)2976 private void setFrameSet(int i) throws ScriptException { 2977 int[] frames = (int[]) expandFloatArray( 2978 floatParameterSet(i, 0, Integer.MAX_VALUE), 1, false); 2979 checkLength(iToken + 1); 2980 if (chk) 2981 return; 2982 Map<String, Object> movie = new Hashtable<String, Object>(); 2983 if (frames.length > 0) 2984 movie.put("frames", frames); 2985 movie.put("currentFrame", Integer.valueOf(0)); 2986 vwr.am.setMovie(movie); 2987 } 2988 cmdAxes(int index)2989 private void cmdAxes(int index) throws ScriptException { 2990 // axes (index==1) or set axes (index==2) 2991 TickInfo tickInfo = tickParamAsStr(index, true, true, false); 2992 index = iToken + 1; 2993 int tok = tokAt(index); 2994 String type = optParameterAsString(index).toLowerCase(); 2995 if (slen == index + 1 && PT.isOneOf(type, ";window;unitcell;molecular;")) { 2996 setBooleanProperty("axes" + type, true); 2997 return; 2998 } 2999 switch (tok) { 3000 case T.offset: 3001 setFloatProperty("axisOffset", floatParameter(++index)); 3002 checkLast(iToken); 3003 return; 3004 case T.center: 3005 setShapeProperty(JC.SHAPE_AXES, "origin", 3006 centerParameter(index + 1, null)); 3007 checkLast(iToken); 3008 return; 3009 case T.type: 3010 String s = stringParameter(index + 1); 3011 if (!PT.isOneOf(s, ";a;b;c;ab;ac;bc;abc;")) 3012 s = null; 3013 setShapeProperty(JC.SHAPE_AXES, "type", s); 3014 checkLast(iToken); 3015 return; 3016 case T.scale: 3017 setFloatProperty("axesScale", floatParameter(checkLast(++index))); 3018 return; 3019 case T.label: 3020 switch (tok = tokAt(index + 1)) { 3021 case T.off: 3022 case T.on: 3023 checkLength(index + 2); 3024 setShapeProperty(JC.SHAPE_AXES, 3025 "labels" + (tok == T.on ? "On" : "Off"), null); 3026 return; 3027 } 3028 String sOrigin = null; 3029 switch (slen - index) { 3030 case 7: 3031 // axes labels "X" "Y" "Z" "-X" "-Y" "-Z" 3032 setShapeProperty(JC.SHAPE_AXES, "labels", new String[] { 3033 paramAsStr(++index), paramAsStr(++index), paramAsStr(++index), 3034 paramAsStr(++index), paramAsStr(++index), paramAsStr(++index) }); 3035 break; 3036 case 5: 3037 sOrigin = paramAsStr(index + 4); 3038 //$FALL-THROUGH$ 3039 case 4: 3040 // axes labels "X" "Y" "Z" [origin] 3041 setShapeProperty(JC.SHAPE_AXES, "labels", new String[] { 3042 paramAsStr(++index), paramAsStr(++index), paramAsStr(++index), 3043 sOrigin }); 3044 break; 3045 default: 3046 bad(); 3047 } 3048 return; 3049 } 3050 // axes position [x y %] 3051 if (type.equals("position")) { 3052 P3 xyp; 3053 if (tokAt(++index) == T.off) { 3054 xyp = new P3(); 3055 } else { 3056 xyp = xypParameter(index); 3057 if (xyp == null) 3058 invArg(); 3059 index = iToken; 3060 } 3061 setShapeProperty(JC.SHAPE_AXES, "position", xyp); 3062 return; 3063 } 3064 int mad10 = getSetAxesTypeMad10(index); 3065 if (chk || mad10 == Integer.MAX_VALUE) 3066 return; 3067 setObjectMad10(JC.SHAPE_AXES, "axes", mad10); 3068 if (tickInfo != null) 3069 setShapeProperty(JC.SHAPE_AXES, "tickInfo", tickInfo); 3070 } 3071 cmdBackground(int i)3072 private void cmdBackground(int i) throws ScriptException { 3073 getToken(i); 3074 int argb; 3075 if (theTok == T.image) { 3076 // background IMAGE "xxxx.jpg" 3077 Object o = null; 3078 switch (tokAt(++i)) { 3079 case T.barray: 3080 case T.hash: 3081 o = getToken(i).value; 3082 break; 3083 default: 3084 String file = paramAsStr(checkLast(i)); 3085 if (chk) 3086 return; 3087 if (file.equalsIgnoreCase("none") || file.length() == 0) { 3088 vwr.setBackgroundImage(null, null); 3089 return; 3090 } 3091 o = (file.startsWith(";base64,") ? new BArray(Base64.decodeBase64(file)) : file); 3092 } 3093 if (vwr.fm.loadImage(o, null, !useThreads())) 3094 throw new ScriptInterruption(this,"backgroundImage", 1); 3095 return; 3096 } 3097 if (theTok == T.none || isColorParam(i)) { 3098 argb = getArgbParamLast(i, true); 3099 if (chk) 3100 return; 3101 setObjectArgb("background", argb); 3102 vwr.setBackgroundImage(null, null); 3103 return; 3104 } 3105 int iShape = getShapeType(theTok); 3106 colorShape(iShape, i + 1, true); 3107 } 3108 cmdBind()3109 private void cmdBind() throws ScriptException { 3110 /* 3111 * bind "MOUSE-ACTION" actionName bind "MOUSE-ACTION" "script" 3112 * not implemented: range [xyrange] [xyrange] 3113 */ 3114 String mouseAction = stringParameter(1); 3115 String name = paramAsStr(2); 3116 checkLength(3); 3117 if (!chk) 3118 vwr.bindAction(mouseAction, name); 3119 } 3120 cmdBondorder()3121 private void cmdBondorder() throws ScriptException { 3122 checkLength(-3); 3123 int order = 0; 3124 switch (getToken(1).tok) { 3125 case T.integer: 3126 case T.decimal: 3127 if ((order = Edge.getBondOrderFromFloat(floatParameter(1))) == Edge.BOND_ORDER_NULL) 3128 invArg(); 3129 break; 3130 default: 3131 if ((order = getBondOrderFromString(paramAsStr(1))) == Edge.BOND_ORDER_NULL) 3132 invArg(); 3133 // generic partial can be indicated by "partial n.m" 3134 if (order == Edge.BOND_PARTIAL01 && tokAt(2) == T.decimal) { 3135 order = getPartialBondOrderFromFloatEncodedInt(st[2].intValue); 3136 } 3137 } 3138 setShapeProperty(JC.SHAPE_STICKS, "bondOrder", Integer.valueOf(order)); 3139 } 3140 cmdBoundbox(int index)3141 private void cmdBoundbox(int index) throws ScriptException { 3142 TickInfo tickInfo = tickParamAsStr(index, false, true, false); 3143 index = iToken + 1; 3144 float scale = 1; 3145 if (tokAt(index) == T.scale) { 3146 scale = floatParameter(++index); 3147 if (!chk && scale == 0) 3148 invArg(); 3149 index++; 3150 if (index == slen) { 3151 if (!chk) 3152 vwr.ms.setBoundBox(null, null, true, scale); 3153 return; 3154 } 3155 } 3156 boolean byCorner = (tokAt(index) == T.corners); 3157 if (byCorner) 3158 index++; 3159 if (isCenterParameter(index)) { 3160 Object[] ret = new Object[1]; 3161 int index0 = index; 3162 P3 pt1 = centerParameter(index, ret); 3163 index = iToken + 1; 3164 if (byCorner || isCenterParameter(index)) { 3165 // boundbox CORNERS {expressionOrPoint1} {expressionOrPoint2} 3166 // boundbox {expressionOrPoint1} {vector} 3167 P3 pt2 = (byCorner ? centerParameter(index, ret) : getPoint3f(index, true, true)); 3168 index = iToken + 1; 3169 if (!chk) 3170 vwr.ms.setBoundBox(pt1, pt2, byCorner, scale); 3171 } else if (ret[0] != null && ret[0] instanceof BS) { 3172 // boundbox {expression} 3173 if (!chk) 3174 vwr.calcBoundBoxDimensions((BS) ret[0], scale); 3175 } else if (ret[0] == null && tokAt(index0) == T.dollarsign) { 3176 if (chk) 3177 return; 3178 P3[] bbox = getObjectBoundingBox(objectNameParameter(++index0)); 3179 if (bbox == null) 3180 invArg(); 3181 vwr.ms.setBoundBox(bbox[0], bbox[1], true, scale); 3182 index = iToken + 1; 3183 } else { 3184 invArg(); 3185 } 3186 if (index == slen) 3187 return; 3188 } 3189 int mad10 = getSetAxesTypeMad10(index); 3190 if (chk || mad10 == Integer.MAX_VALUE) 3191 return; 3192 if (tickInfo != null) 3193 setShapeProperty(JC.SHAPE_BBCAGE, "tickInfo", tickInfo); 3194 setObjectMad10(JC.SHAPE_BBCAGE, "boundbox", mad10); 3195 } 3196 cmdCD()3197 private void cmdCD() throws ScriptException { 3198 if (chk) 3199 return; 3200 String dir = (slen == 1 ? null : paramAsStr(1)); 3201 showString(vwr.cd(dir)); 3202 } 3203 cmdCenter(int i)3204 private void cmdCenter(int i) throws ScriptException { 3205 // from center (atom) or from zoomTo under conditions of not 3206 // windowCentered() 3207 if (slen == 1) { 3208 vwr.setNewRotationCenter(null); 3209 return; 3210 } 3211 P3 center = centerParameter(i, null); 3212 if (center == null) 3213 invArg(); 3214 if (!chk) 3215 vwr.setNewRotationCenter(center); 3216 } 3217 cmdColor()3218 private void cmdColor() throws ScriptException { 3219 int i = 1; 3220 String strColor = (tokAt(1) == T.string ? stringParameter(1) : null); 3221 if (isColorParam(1)) { 3222 theTok = T.atoms; 3223 } else { 3224 int argb = 0; 3225 i = 2; 3226 int tok = getToken(1).tok; 3227 if (tok == T.string) { 3228 tok = T.getTokFromName(strColor); 3229 if (tok == T.nada) 3230 tok = T.string; 3231 } 3232 switch (tok) { 3233 case T.dollarsign: 3234 setObjectProperty(); 3235 return; 3236 case T.altloc: 3237 case T.amino: 3238 case T.nucleic: 3239 case T.chain: 3240 case T.fixedtemp: 3241 case T.formalcharge: 3242 case T.group: 3243 case T.hydrophobicity: 3244 case T.insertion: 3245 case T.jmol: 3246 case T.molecule: 3247 case T.monomer: 3248 case T.none: 3249 case T.opaque: 3250 case T.partialcharge: 3251 case T.polymer: 3252 case T.property: 3253 case T.rasmol: 3254 case T.pymol: 3255 case T.spacefill: 3256 case T.shapely: 3257 case T.straightness: 3258 case T.structure: 3259 case T.surfacedistance: 3260 case T.temperature: 3261 case T.translucent: 3262 case T.user: 3263 case T.vanderwaals: 3264 theTok = T.atoms; 3265 i = 1; 3266 break; 3267 case T.string: 3268 i = 2; 3269 if (isArrayParameter(i)) { 3270 strColor = strColor += "=" 3271 + SV.sValue(SV.getVariableAS(stringParameterSet(i))).replace( 3272 '\n', ' '); 3273 i = iToken + 1; 3274 } 3275 boolean isTranslucent = (tokAt(i) == T.translucent); 3276 if (!chk) 3277 vwr.setPropertyColorScheme(strColor, isTranslucent, true); 3278 if (isTranslucent) 3279 ++i; 3280 if (tokAt(i) == T.range || tokAt(i) == T.absolute) { 3281 float min = floatParameter(++i); 3282 float max = floatParameter(++i); 3283 if (!chk) 3284 vwr.cm.setPropertyColorRange(min, max); 3285 } 3286 return; 3287 case T.range: 3288 case T.absolute: 3289 float min = floatParameter(2); 3290 float max = floatParameter(checkLast(3)); 3291 if (!chk) 3292 vwr.cm.setPropertyColorRange(min, max); 3293 return; 3294 case T.background: 3295 argb = getArgbParamLast(2, true); 3296 if (!chk) 3297 setObjectArgb("background", argb); 3298 return; 3299 case T.define: 3300 case T.bitset: 3301 case T.expressionBegin: 3302 i = -1; 3303 theTok = T.atoms; 3304 break; 3305 case T.rubberband: 3306 argb = getArgbParamLast(2, false); 3307 if (!chk) 3308 vwr.cm.setRubberbandArgb(argb); 3309 return; 3310 case T.highlight: 3311 case T.selectionhalos: 3312 i = 2; 3313 if (tokAt(2) == T.opaque) 3314 i++; 3315 argb = getArgbParamLast(i, true); 3316 if (chk) 3317 return; 3318 sm.loadShape(JC.SHAPE_HALOS); 3319 setShapeProperty(JC.SHAPE_HALOS, 3320 (tok == T.selectionhalos ? "argbSelection" : "argbHighlight"), 3321 Integer.valueOf(argb)); 3322 return; 3323 case T.axes: 3324 case T.boundbox: 3325 case T.unitcell: 3326 case T.identifier: 3327 case T.hydrogen: 3328 // color element 3329 String str = paramAsStr(1); 3330 if (checkToken(2)) { 3331 argb = getToken(2).tok; 3332 switch (argb) { 3333 case T.none: 3334 argb = T.jmol; 3335 break; 3336 case T.jmol: 3337 case T.rasmol: 3338 case T.pymol: 3339 break; 3340 default: 3341 argb = getArgbParam(2); 3342 } 3343 } 3344 if (argb == 0) 3345 error(ERROR_colorOrPaletteRequired); 3346 checkLast(iToken); 3347 if (str.equalsIgnoreCase("axes") 3348 || StateManager.getObjectIdFromName(str) >= 0) { 3349 setObjectArgb(str, argb); 3350 return; 3351 } 3352 if (setElementColor(str, argb)) 3353 return; 3354 invArg(); 3355 break; 3356 case T.isosurface: 3357 case T.contact: 3358 setShapeProperty(JC.shapeTokenIndex(tok), "thisID", 3359 MeshCollection.PREVIOUS_MESH_ID); 3360 break; 3361 } 3362 } 3363 colorShape(getShapeType(theTok), i, false); 3364 } 3365 cmdDefine()3366 private void cmdDefine() throws ScriptException { 3367 // note that the standard definition depends upon the 3368 // current state. Once defined, a setName is the set 3369 // of atoms that matches the definition at that time. 3370 // adding DYMAMIC_ to the beginning of the definition 3371 // allows one to create definitions that are recalculated 3372 // whenever they are used. When used, "DYNAMIC_" is dropped 3373 // so, for example: 3374 // define DYNAMIC_what selected and visible 3375 // and then 3376 // select what 3377 // will return different things at different times depending 3378 // upon what is selected and what is visible 3379 // but 3380 // define what selected and visible 3381 // will evaluate the moment it is defined and then represent 3382 // that set of atoms forever. 3383 3384 if (slen < 3 || !(getToken(1).value instanceof String)) 3385 invArg(); 3386 String setName = ((String) getToken(1).value).toLowerCase(); 3387 if (PT.parseInt(setName) != Integer.MIN_VALUE) 3388 invArg(); 3389 if (chk) 3390 return; 3391 boolean isSite = setName.startsWith("site_"); 3392 boolean isDynamic = (setName.indexOf("dynamic_") == 0); 3393 if (isDynamic || isSite) { 3394 T[] code = new T[slen]; 3395 for (int i = slen; --i >= 0;) 3396 code[i] = st[i]; 3397 vwr.definedAtomSets 3398 .put("!" + (isSite ? setName : setName.substring(8)), code); 3399 //if (!isSite) 3400 //vwr.addStateScript(thisCommand, false, true); removed for 12.1.16 3401 } else { 3402 BS bs = atomExpressionAt(2); 3403 vwr.definedAtomSets.put(setName, bs); 3404 if (!chk) 3405 vwr.g.setUserVariable("@" + setName, SV.newV(T.bitset, bs)); 3406 } 3407 } 3408 cmdDelay()3409 private void cmdDelay() throws ScriptException { 3410 int millis = 0; 3411 switch (getToken(1).tok) { 3412 case T.on: // this is auto-provided as a default 3413 millis = 1; 3414 break; 3415 case T.integer: 3416 millis = intParameter(1) * 1000; 3417 break; 3418 case T.decimal: 3419 millis = (int) (floatParameter(1) * 1000); 3420 break; 3421 default: 3422 error(ERROR_numberExpected); 3423 } 3424 refresh(false); 3425 doDelay(Math.abs(millis)); 3426 } 3427 cmdDelete()3428 private void cmdDelete() throws ScriptException { 3429 if (tokAt(1) == T.dollarsign) { 3430 if (slen == 4 && optParameterAsString(2).equals("saved") && slen == 4) { 3431 vwr.stm.deleteSaved(optParameterAsString(3)); 3432 if (doReport()) 3433 report(GT.o(GT.$("show saved: {0}"), vwr.stm.listSavedStates()), false); 3434 return; 3435 } 3436 setObjectProperty(); 3437 return; 3438 } 3439 BS bs = (slen == 1 ? null : atomExpression(st, 1, 0, true, false, null, 3440 false)); 3441 if (chk) 3442 return; 3443 if (bs == null) 3444 bs = vwr.getAllAtoms(); 3445 int nDeleted = vwr.deleteAtoms(bs, false); 3446 if (doReport()) 3447 report(GT.i(GT.$("{0} atoms deleted"), nDeleted), false); 3448 } 3449 cmdDisplay(boolean isDisplay)3450 private void cmdDisplay(boolean isDisplay) throws ScriptException { 3451 BS bs = null; 3452 int addRemove = 0; 3453 int i = 1; 3454 int tok; 3455 switch (tok = tokAt(1)) { 3456 case T.add: 3457 case T.remove: 3458 addRemove = tok; 3459 tok = tokAt(++i); 3460 break; 3461 } 3462 boolean isGroup = (tok == T.group); 3463 if (isGroup) 3464 tok = tokAt(++i); 3465 switch (tok) { 3466 case T.dollarsign: 3467 setObjectProperty(); 3468 return; 3469 case T.nada: 3470 break; 3471 default: 3472 if (slen == 4 && tokAt(2) == T.bonds) 3473 bs = BondSet.newBS(BSUtil.newBitSet2(0, vwr.ms.bondCount), null); 3474 else 3475 bs = atomExpressionAt(i); 3476 } 3477 if (chk) 3478 return; 3479 if (bs instanceof BondSet) { 3480 vwr.ms.displayBonds((BondSet) bs, isDisplay); 3481 return; 3482 } 3483 vwr.displayAtoms(bs, isDisplay, isGroup, addRemove, tQuiet); 3484 } 3485 cmdDots(int iShape)3486 private void cmdDots(int iShape) throws ScriptException { 3487 if (!chk) 3488 sm.loadShape(iShape); 3489 setShapeProperty(iShape, "init", null); 3490 float value = Float.NaN; 3491 EnumType type = EnumType.ABSOLUTE; 3492 int ipt = 1; 3493 boolean isOnly = false; 3494 while (true) { 3495 switch (getToken(ipt).tok) { 3496 case T.only: 3497 isOnly = true; 3498 //$FALL-THROUGH$ 3499 case T.on: 3500 value = 1; 3501 type = EnumType.FACTOR; 3502 break; 3503 case T.off: 3504 value = 0; 3505 break; 3506 case T.ignore: 3507 setShapeProperty(iShape, "ignore", atomExpressionAt(ipt + 1)); 3508 ipt = iToken + 1; 3509 continue; 3510 case T.decimal: 3511 isOnly = (tokAt(ipt + 1) == T.only || floatParameter(ipt) < 0); 3512 break; 3513 case T.integer: 3514 int dotsParam = intParameter(ipt); 3515 if (tokAt(ipt + 1) == T.radius) { 3516 ipt++; 3517 setShapeProperty(iShape, "atom", Integer.valueOf(dotsParam)); 3518 setShapeProperty(iShape, "radius", 3519 Float.valueOf(floatParameter(++ipt))); 3520 if (tokAt(++ipt) == T.color) { 3521 setShapeProperty(iShape, "colorRGB", 3522 Integer.valueOf(getArgbParam(++ipt))); 3523 ipt++; 3524 } 3525 if (getToken(ipt).tok != T.bitset) 3526 invArg(); 3527 setShapeProperty(iShape, "dots", st[ipt].value); 3528 return; 3529 } 3530 break; 3531 } 3532 break; 3533 } 3534 RadiusData rd = (Float.isNaN(value) ? encodeRadiusParameter(ipt, isOnly, 3535 true) : new RadiusData(null, value, type, VDW.AUTO)); 3536 if (rd == null) 3537 return; 3538 if (Float.isNaN(rd.value)) 3539 invArg(); 3540 if (isOnly) { 3541 restrictSelected(false, false); 3542 } 3543 setShapeSize(iShape, rd); 3544 } 3545 cmdEcho(int index)3546 private void cmdEcho(int index) 3547 throws ScriptException { 3548 if (chk) 3549 return; 3550 String text = optParameterAsString(index); 3551 boolean doRefresh = true; 3552 if (vwr.ms.getEchoStateActive()) { 3553 if (text.startsWith("\1")) { 3554 // no reporting, just screen echo, from mouseManager key press 3555 text = text.substring(1); 3556 doRefresh = false; 3557 } 3558 if (text != null) 3559 setShapeProperty(JC.SHAPE_ECHO, "text", text); 3560 } 3561 if (doRefresh && vwr.getRefreshing()) 3562 showString(Txt.formatText(vwr, text)); 3563 } 3564 cmdFile()3565 private void cmdFile() throws ScriptException { 3566 int file = intParameter(checkLast(1)); 3567 if (chk) 3568 return; 3569 int modelIndex = vwr.ms.getModelNumberIndex(file * 1000000 + 1, false, 3570 false); 3571 int modelIndex2 = -1; 3572 if (modelIndex >= 0) { 3573 modelIndex2 = vwr.ms.getModelNumberIndex((file + 1) * 1000000 + 1, false, 3574 false); 3575 if (modelIndex2 < 0) 3576 modelIndex2 = vwr.ms.mc; 3577 modelIndex2--; 3578 } 3579 vwr.setAnimationOn(false); 3580 vwr.am.setAnimationDirection(1); 3581 vwr.setAnimationRange(modelIndex, modelIndex2); 3582 vwr.setCurrentModelIndex(-1); 3583 } 3584 cmdFixed()3585 private void cmdFixed() throws ScriptException { 3586 BS bs = (slen == 1 ? null : atomExpressionAt(1)); 3587 if (chk) 3588 return; 3589 vwr.setMotionFixedAtoms(bs); 3590 } 3591 3592 @SuppressWarnings("unchecked") cmdFor(int tok, boolean isForCheck)3593 private boolean cmdFor(int tok, boolean isForCheck) throws ScriptException { 3594 ContextToken cmdToken = (ContextToken) theToken; 3595 int pt = st[0].intValue; 3596 SV[] forVars = cmdToken.forVars; 3597 int[] pts = new int[2]; 3598 Object bsOrList = null; 3599 SV forVal = null; 3600 SV forVar = null; 3601 int inTok = 0; 3602 boolean isOK = true; 3603 boolean isMinusMinus = false; 3604 int j = 0; 3605 String key = null; 3606 if (isForCheck && forVars != null) { 3607 3608 // for xx IN [...] or for xx FROM [...] 3609 3610 tok = T.in; 3611 // i in x, already initialized 3612 forVar = forVars[0]; 3613 forVal = forVars[1]; 3614 bsOrList = forVars[1].value; 3615 // nth time through 3616 j = ++forVal.intValue; 3617 if (forVal.tok == T.integer) { 3618 // values are stored in value as [i1 i2] 3619 isMinusMinus = (j < 0); 3620 int i1 = ((int[]) bsOrList)[0]; 3621 int i2 = ((int[]) bsOrList)[1]; 3622 isOK = (i1 != i2 && (i2 < i1) == isMinusMinus); 3623 if (isOK) 3624 forVar.intValue = ((int[]) bsOrList)[0] = i1 + (isMinusMinus ? -1 : 1); 3625 j = -1; 3626 } else if (forVal.tok == T.varray) { 3627 isOK = (j <= ((Lst<SV>) bsOrList).size()); 3628 if (isOK) 3629 forVar.setv(SV.selectItemVar(forVal)); 3630 j = -1; 3631 } else { 3632 isBondSet = bsOrList instanceof BondSet; 3633 j = ((BS) bsOrList).nextSetBit(j); 3634 isOK = (j >= 0); 3635 } 3636 } else { 3637 // for (i = 1; i < 3; i = i + 1); 3638 // for (i = 1; i < 3; i = i + 1); 3639 // for (var i = 1; i < 3; i = i + 1); 3640 // for (;;;); 3641 // for (var x in {...}) { xxxxx } 3642 // for (var x in y) { xxxx } 3643 boolean isLocal = false; 3644 for (int i = 1, nSkip = 0; i < slen && j < 2; i++) { 3645 switch (tok = tokAt(i)) { 3646 case T.var: 3647 isLocal = true; 3648 break; 3649 case T.semicolon: 3650 if (nSkip > 0) 3651 nSkip--; 3652 else 3653 pts[j++] = i; 3654 break; 3655 case T.in: 3656 case T.from: 3657 key = paramAsStr(i - 1); 3658 nSkip -= 2; 3659 if (isAtomExpression(++i)) { 3660 inTok = T.bitset; 3661 bsOrList = atomExpressionAt(i); 3662 if (isBondSet) 3663 bsOrList = BondSet.newBS((BS) bsOrList, null); 3664 isOK = (((BS) bsOrList).nextSetBit(0) >= 0); 3665 } else { 3666 Lst<SV> what = parameterExpressionList(-i, 1, false); 3667 if (what == null || what.size() < 1) 3668 invArg(); 3669 SV vl = what.get(0); 3670 switch (inTok = vl.tok) { 3671 case T.bitset: 3672 bsOrList = vl.value; 3673 isOK = !((BS) bsOrList).isEmpty(); 3674 break; 3675 case T.varray: 3676 Lst<SV> v = vl.getList(); 3677 j = v.size(); 3678 isOK = (j > 0); 3679 if (isOK && tok == T.from) { 3680 int[] i12 = new int[] {SV.iValue(v.get(0)), SV.iValue(v.get(j - 1)) }; 3681 isMinusMinus = (i12[1] < i12[0]); 3682 bsOrList = i12; 3683 tok = T.in; 3684 inTok = T.integer; 3685 } else { 3686 bsOrList = v; 3687 } 3688 break; 3689 case T.hash: 3690 Map<String, SV> m = vl.getMap(); 3691 int n = m.keySet().size(); 3692 isOK = (n > 0); 3693 if (isOK) { 3694 String[] keys = new String[n]; 3695 m.keySet().toArray(keys); 3696 Arrays.sort(keys); 3697 bsOrList = keys; 3698 } 3699 break; 3700 default: 3701 invArg(); 3702 } 3703 } 3704 i = iToken; 3705 break; 3706 case T.select: 3707 nSkip += 2; 3708 break; 3709 } 3710 } 3711 if (!isForCheck) { 3712 pushContext(cmdToken, "FOR"); 3713 thisContext.forVars = forVars; 3714 forVars = null; 3715 } 3716 if (key == null) { 3717 if (isForCheck) { 3718 j = (bsOrList == null ? pts[1] + 1 : 2); 3719 } else { 3720 j = 2; 3721 } 3722 if (tokAt(j) == T.var) 3723 j++; 3724 key = paramAsStr(j); 3725 isMinusMinus = key.equals("--") || key.equals("++"); 3726 if (isMinusMinus) 3727 key = paramAsStr(++j); 3728 } 3729 if (isOK) 3730 if (tok == T.in) { 3731 // start of FOR (i in x) block or FOR (i from x) 3732 forVar = getContextVariableAsVariable(key, isLocal); 3733 if (forVar == null && !isLocal) 3734 forVar = vwr.g.getAndSetNewVariable(key, false); 3735 if (forVar == null || forVar.myName == null) { 3736 if (key.startsWith("_")) 3737 invArg(); 3738 if (isLocal) 3739 contextVariables.put(key.toLowerCase(), forVar = SV.newI(0)); 3740 else 3741 forVar = vwr.g.getAndSetNewVariable(key, true); 3742 } 3743 if (inTok == T.integer) { 3744 // for (i from [0 31]) 3745 forVar.tok = T.integer; 3746 forVar.intValue = ((int[]) bsOrList)[0]; 3747 forVal = SV.newV(T.integer, bsOrList); 3748 forVal.intValue = (isMinusMinus ? Integer.MIN_VALUE : 0); 3749 j = -1; 3750 } else { 3751 forVal = SV.getVariable(bsOrList); 3752 if (inTok == T.bitset) { 3753 j = ((BS) bsOrList).nextSetBit(0); 3754 forVal.intValue = 0; 3755 } else { 3756 forVal.intValue = 1; 3757 forVar.setv(SV.selectItemVar(forVal)); 3758 j = -1; 3759 } 3760 } 3761 if (forVars == null) 3762 forVars = cmdToken.forVars = new SV[2]; 3763 forVars[0] = forVar; 3764 forVars[1] = forVal; 3765 } else { 3766 int vtok = tokAt(j); 3767 if (vtok != T.semicolon && (T.tokAttr(vtok, T.misc) 3768 || (forVal = getContextVariableAsVariable(key, false)) != null)) { 3769 if (!isMinusMinus && getToken(++j).tok != T.opEQ) 3770 invArg(); 3771 if (isMinusMinus) 3772 j -= 2; 3773 setVariable(++j, slen - 1, key, false); 3774 } 3775 isOK = (pts[0] + 1 == pts[1] || parameterExpressionBoolean(pts[0] + 1, pts[1])); 3776 } 3777 } 3778 if (isOK && tok == T.in && j >= 0) { 3779 forVal.intValue = j; 3780 forVar.tok = T.bitset; 3781 if (isBondSet) { 3782 forVar.value = new BondSet(); 3783 ((BondSet) forVar.value).set(j); 3784 } else { 3785 forVar.value = BSUtil.newAndSetBit(j); 3786 } 3787 } 3788 pt++; 3789 if (!isOK) { 3790 cmdToken.forVars = thisContext.forVars; 3791 popContext(true, false); 3792 } 3793 isForCheck = false; 3794 if (!isOK && !chk) 3795 pc = Math.abs(pt) - 1; 3796 return isForCheck; 3797 } 3798 cmdFlow(int tok, boolean isForCheck, Lst<T[]> vProcess)3799 private boolean cmdFlow(int tok, boolean isForCheck, Lst<T[]> vProcess) 3800 throws ScriptException { 3801 ContextToken ct; 3802 int pt = st[0].intValue; 3803 boolean isDone = (pt < 0 && !chk); 3804 boolean continuing = true; 3805 int ptNext = 0; 3806 switch (tok) { 3807 case T.function: 3808 case T.parallel: 3809 cmdFunc(); // when a function is a command 3810 return isForCheck; 3811 case T.trycmd: 3812 return isForCheck; 3813 case T.catchcmd: 3814 ct = (ContextToken) theToken; 3815 pushContext(ct, "CATCH"); 3816 if (!isDone && ct.name0 != null) 3817 contextVariables.put(ct.name0, ct.contextVariables.get(ct.name0)); 3818 continuing = !isDone; 3819 st[0].intValue = -Math.abs(pt); 3820 break; 3821 case T.switchcmd: 3822 case T.defaultcmd: 3823 case T.casecmd: 3824 ptNext = Math.abs(aatoken[Math.abs(pt)][0].intValue); 3825 switch (isDone ? 0 : cmdFlowSwitch((ContextToken) theToken, tok)) { 3826 case 0: 3827 // done 3828 ptNext = -ptNext; 3829 continuing = false; 3830 break; 3831 case -1: 3832 // skip this case 3833 continuing = false; 3834 break; 3835 case 1: 3836 // do this one 3837 } 3838 aatoken[pc][0].intValue = Math.abs(pt); 3839 theToken = aatoken[Math.abs(pt)][0]; 3840 if (theToken.tok != T.end) 3841 theToken.intValue = ptNext; 3842 break; 3843 case T.ifcmd: 3844 case T.elseif: 3845 continuing = (!isDone && parameterExpressionBoolean(1, 0)); 3846 if (chk) 3847 break; 3848 ptNext = Math.abs(aatoken[Math.abs(pt)][0].intValue); 3849 ptNext = (isDone || continuing ? -ptNext : ptNext); 3850 aatoken[Math.abs(pt)][0].intValue = ptNext; 3851 if (tok == T.catchcmd) 3852 aatoken[pc][0].intValue = -pt; // reset to "done" state 3853 break; 3854 case T.elsecmd: 3855 checkLength(1); 3856 if (pt < 0 && !chk) 3857 pc = -pt - 1; 3858 break; 3859 case T.endifcmd: 3860 checkLength(1); 3861 break; 3862 case T.whilecmd: 3863 if (!isForCheck) 3864 pushContext((ContextToken) theToken, "WHILE"); 3865 isForCheck = false; 3866 if (!parameterExpressionBoolean(1, 0) && !chk) { 3867 pc = pt; 3868 popContext(true, false); 3869 } 3870 break; 3871 case T.breakcmd: 3872 if (!chk) { 3873 breakAt(pt); 3874 break; 3875 } 3876 if (slen == 1) 3877 break; 3878 int n = intParameter(checkLast(1)); 3879 if (chk) 3880 break; 3881 for (int i = 0; i < n; i++) 3882 popContext(true, false); 3883 break; 3884 case T.continuecmd: 3885 isForCheck = true; 3886 if (!chk) 3887 pc = pt - 1; 3888 if (slen > 1) 3889 intParameter(checkLast(1)); 3890 break; 3891 case T.end: // function, if, for, while, catch, switch 3892 switch (getToken(checkLast(1)).tok) { 3893 case T.trycmd: 3894 ScriptFunction trycmd = (ScriptFunction) getToken(1).value; 3895 if (chk) 3896 return false; 3897 runFunctionAndRet(trycmd, "try", null, null, true, true, true); 3898 return false; 3899 case T.function: 3900 case T.parallel: 3901 addFunction((ScriptFunction) theToken.value); 3902 return isForCheck; 3903 case T.catchcmd: 3904 popContext(true, false); 3905 break; 3906 case T.process: 3907 addProcess(vProcess, pt, pc); 3908 popContext(true, false); 3909 break; 3910 case T.switchcmd: 3911 if (pt > 0 && cmdFlowSwitch((ContextToken) aatoken[pt][0], 0) == -1) { 3912 // check for the default position 3913 for (; pt < pc; pt++) 3914 if ((tok = aatoken[pt][0].tok) != T.defaultcmd && tok != T.casecmd) 3915 break; 3916 continuing = (pc == pt); 3917 } 3918 break; 3919 case T.ifcmd: 3920 break; 3921 case T.forcmd: 3922 case T.whilecmd: 3923 continuing = false; 3924 isForCheck = true; 3925 break; 3926 } 3927 break; 3928 } 3929 if (!continuing && !chk) 3930 pc = Math.abs(pt) - 1; 3931 return isForCheck; 3932 } 3933 cmdFlowSwitch(ContextToken c, int tok)3934 private int cmdFlowSwitch(ContextToken c, int tok) throws ScriptException { 3935 if (tok == T.switchcmd) 3936 c.addName("_var"); 3937 SV var = c.contextVariables.get("_var"); 3938 if (var == null) 3939 return 1; // OK, case found -- no more testing 3940 if (tok == 0) { 3941 // end: remove variable and do default 3942 // this causes all other cases to 3943 // skip 3944 c.contextVariables.remove("_var"); 3945 return -1; 3946 } 3947 if (tok == T.defaultcmd) // never do the default one directly 3948 return -1; 3949 SV v = parameterExpressionToken(1); 3950 if (tok == T.casecmd) { 3951 boolean isOK = SV.areEqual(var, v); 3952 if (isOK) 3953 c.contextVariables.remove("_var"); 3954 return isOK ? 1 : -1; 3955 } 3956 c.contextVariables.put("_var", v); 3957 return 1; 3958 } 3959 cmdFont(int shapeType, float fontsize)3960 private void cmdFont(int shapeType, float fontsize) throws ScriptException { 3961 String fontface = "SansSerif"; 3962 String fontstyle = "Plain"; 3963 int sizeAdjust = 0; 3964 float scaleAngstromsPerPixel = -1; 3965 switch (iToken = slen) { 3966 case 6: 3967 scaleAngstromsPerPixel = floatParameter(5); 3968 if (scaleAngstromsPerPixel >= 5) // actually a zoom value 3969 scaleAngstromsPerPixel = vwr.tm.getZoomSetting() 3970 / scaleAngstromsPerPixel / vwr.getScalePixelsPerAngstrom(false); 3971 //$FALL-THROUGH$ 3972 case 5: 3973 if (getToken(4).tok != T.identifier) 3974 invArg(); 3975 fontstyle = paramAsStr(4); 3976 //$FALL-THROUGH$ 3977 case 4: 3978 if (getToken(3).tok != T.identifier) 3979 invArg(); 3980 fontface = paramAsStr(3); 3981 if (!isFloatParameter(2)) 3982 error(ERROR_numberExpected); 3983 fontsize = floatParameter(2); 3984 shapeType = getShapeType(getToken(1).tok); 3985 break; 3986 case 3: 3987 if (!isFloatParameter(2)) 3988 error(ERROR_numberExpected); 3989 if (shapeType == -1) { 3990 shapeType = getShapeType(getToken(1).tok); 3991 fontsize = floatParameter(2); 3992 } else {// labels --- old set fontsize N 3993 if (fontsize >= 1) 3994 fontsize += (sizeAdjust = 5); 3995 } 3996 break; 3997 case 2: 3998 default: 3999 if (shapeType == JC.SHAPE_LABELS) { 4000 // set fontsize 4001 fontsize = JC.LABEL_DEFAULT_FONTSIZE; 4002 break; 4003 } 4004 bad(); 4005 } 4006 if (shapeType == JC.SHAPE_LABELS) { 4007 if (fontsize < 0 4008 || fontsize >= 1 4009 && (fontsize < JC.LABEL_MINIMUM_FONTSIZE || fontsize > JC.LABEL_MAXIMUM_FONTSIZE)) { 4010 integerOutOfRange(JC.LABEL_MINIMUM_FONTSIZE - sizeAdjust, 4011 JC.LABEL_MAXIMUM_FONTSIZE - sizeAdjust); 4012 return; 4013 } 4014 setShapeProperty(JC.SHAPE_LABELS, "setDefaults", vwr.slm.noneSelected); 4015 } 4016 if (chk) 4017 return; 4018 if (Font.getFontStyleID(fontface) >= 0) { 4019 fontstyle = fontface; 4020 fontface = "SansSerif"; 4021 } 4022 Font font3d = vwr.getFont3D(fontface, fontstyle, fontsize); 4023 sm.loadShape(shapeType); 4024 setShapeProperty(shapeType, "font", font3d); 4025 if (scaleAngstromsPerPixel >= 0) 4026 setShapeProperty(shapeType, "scalereference", 4027 Float.valueOf(scaleAngstromsPerPixel)); 4028 } 4029 cmdFrank(int i)4030 private void cmdFrank(int i) throws ScriptException { 4031 boolean b = true; 4032 if (slen > i) 4033 switch (getToken(checkLast(i)).tok) { 4034 case T.on: 4035 break; 4036 case T.off: 4037 b = false; 4038 break; 4039 default: 4040 error(ERROR_booleanExpected); 4041 } 4042 setBooleanProperty("frank", b); 4043 } 4044 cmdFunc()4045 private void cmdFunc() throws ScriptException { 4046 if (chk && !isCmdLine_c_or_C_Option) 4047 return; 4048 String name = ((String) getToken(0).value).toLowerCase(); 4049 if (tokAt(1) == T.opEQ && tokAt(2) == T.none) { 4050 vwr.removeFunction(name); 4051 return; 4052 } 4053 if (!isFunction(name)) 4054 error(ERROR_commandExpected); 4055 Lst<SV> params = (slen == 1 || slen == 3 && tokAt(1) == T.leftparen 4056 && tokAt(2) == T.rightparen ? null : parameterExpressionList(1, -1, 4057 false)); 4058 if (chk) 4059 return; 4060 runFunctionAndRet(null, name, params, null, false, true, true); 4061 } 4062 cmdGetProperty()4063 private void cmdGetProperty() throws ScriptException { 4064 if (chk) 4065 return; 4066 String retValue = ""; 4067 String property = optParameterAsString(1); 4068 String name = property; 4069 if (name.indexOf(".") >= 0) 4070 name = name.substring(0, name.indexOf(".")); 4071 if (name.indexOf("[") >= 0) 4072 name = name.substring(0, name.indexOf("[")); 4073 int propertyID = vwr.getPropertyNumber(name); 4074 Object param = ""; 4075 switch (tokAt(2)) { 4076 default: 4077 param = optParameterAsString(2); 4078 break; 4079 case T.define: 4080 case T.expressionBegin: 4081 case T.bitset: 4082 param = atomExpressionAt(2); 4083 if (property.equalsIgnoreCase("bondInfo") && isAtomExpression(++iToken)) 4084 param = new BS[] { (BS) param, atomExpressionAt(iToken) }; 4085 break; 4086 } 4087 if (property.length() > 0 && propertyID < 0) { 4088 // no such property 4089 property = ""; // produces a list from Property Manager 4090 param = ""; 4091 } else if (propertyID >= 0 && slen < 3) { 4092 if ((param = vwr.getDefaultPropertyParam(propertyID)).equals("(visible)")) 4093 param = vwr.ms.getVisibleSet(true); 4094 } else if (propertyID == vwr.getPropertyNumber("fileContents")) { 4095 String s = param.toString(); 4096 for (int i = 3; i < slen; i++) 4097 s += paramAsStr(i); 4098 param = s; 4099 } 4100 retValue = (String) vwr.getProperty("readable", property, param); 4101 showString(retValue); 4102 } 4103 cmdGoto(boolean isCmd)4104 private void cmdGoto(boolean isCmd) throws ScriptException { 4105 String strTo = (isCmd ? paramAsStr(checkLast(1)) : null); 4106 int pcTo = (strTo == null ? aatoken.length - 1 : -1); 4107 String s = null; 4108 for (int i = pcTo + 1; i < aatoken.length; i++) { 4109 T[] tokens = aatoken[i]; 4110 int tok = tokens[0].tok; 4111 switch (tok) { 4112 case T.message: 4113 case T.nada: 4114 s = (String) tokens[tokens.length - 1].value; 4115 if (tok == T.nada) 4116 s = s.substring(s.startsWith("#") ? 1 : 2); 4117 break; 4118 default: 4119 continue; 4120 } 4121 if (s.equalsIgnoreCase(strTo)) { 4122 pcTo = i; 4123 break; 4124 } 4125 } 4126 if (pcTo < 0) 4127 invArg(); 4128 if (strTo == null) 4129 pcTo = 0; 4130 int di = (pcTo < pc ? 1 : -1); 4131 int nPush = 0; 4132 for (int i = pcTo; i != pc; i += di) { 4133 switch (aatoken[i][0].tok) { 4134 case T.push: 4135 case T.process: 4136 case T.forcmd: 4137 case T.catchcmd: 4138 case T.whilecmd: 4139 nPush++; 4140 break; 4141 case T.pop: 4142 nPush--; 4143 break; 4144 case T.end: 4145 switch (aatoken[i][1].tok) { 4146 case T.process: 4147 case T.forcmd: 4148 case T.catchcmd: 4149 case T.whilecmd: 4150 nPush--; 4151 } 4152 break; 4153 } 4154 } 4155 if (strTo == null) { 4156 pcTo = Integer.MAX_VALUE; 4157 for (; nPush > 0; --nPush) 4158 popContext(false, false); 4159 } 4160 if (nPush != 0) 4161 invArg(); 4162 if (!chk) 4163 pc = pcTo - 1; // ... resetting the program counter 4164 } 4165 cmdHbond()4166 private void cmdHbond() throws ScriptException { 4167 if (slen == 2 && getToken(1).tok == T.calculate) { 4168 if (chk) 4169 return; 4170 int n = vwr.autoHbond(null, null, false); 4171 report(GT.i(GT.$("{0} hydrogen bonds"), Math.abs(n)), false); 4172 return; 4173 } 4174 if (slen == 2 && getToken(1).tok == T.delete) { 4175 if (chk) 4176 return; 4177 checkExtension(T.hbond); 4178 return; 4179 } 4180 int mad = getMadParameter(); 4181 if (mad == Integer.MAX_VALUE) 4182 return; 4183 setShapeProperty(JC.SHAPE_STICKS, "type", 4184 Integer.valueOf(Edge.BOND_HYDROGEN_MASK)); 4185 setShapeSizeBs(JC.SHAPE_STICKS, mad, null); 4186 setShapeProperty(JC.SHAPE_STICKS, "type", 4187 Integer.valueOf(Edge.BOND_COVALENT_MASK)); 4188 } 4189 cmdHelp()4190 private void cmdHelp() throws ScriptException { 4191 if (chk) 4192 return; 4193 String what = optParameterAsString(1).toLowerCase(); 4194 int pt = 0; 4195 if (what.startsWith("mouse") && (pt = what.indexOf(" ")) >= 0 4196 && pt == what.lastIndexOf(" ")) { 4197 showString(vwr.getBindingInfo(what.substring(pt + 1))); 4198 return; 4199 } 4200 if (T.tokAttr(T.getTokFromName(what), T.scriptCommand)) 4201 what = "?command=" + what; 4202 vwr.getHelp(what); 4203 } 4204 cmdHistory(int pt)4205 private void cmdHistory(int pt) throws ScriptException { 4206 // history or set history 4207 if (slen == 1) { 4208 // show it 4209 showString(vwr.getSetHistory(Integer.MAX_VALUE)); 4210 return; 4211 } 4212 if (pt == 2) { 4213 // set history n; n' = -2 - n; if n=0, then set history OFF 4214 int n = intParameter(checkLast(2)); 4215 if (n < 0) 4216 invArg(); 4217 if (!chk) 4218 vwr.getSetHistory(n == 0 ? 0 : -2 - n); 4219 return; 4220 } 4221 switch (getToken(checkLast(1)).tok) { 4222 // pt = 1 history ON/OFF/CLEAR 4223 case T.on: 4224 case T.clear: 4225 if (!chk) 4226 vwr.getSetHistory(Integer.MIN_VALUE); 4227 return; 4228 case T.off: 4229 if (!chk) 4230 vwr.getSetHistory(0); 4231 break; 4232 default: 4233 errorStr(ERROR_keywordExpected, "ON, OFF, CLEAR"); 4234 } 4235 } 4236 cmdHover()4237 private void cmdHover() throws ScriptException { 4238 if (chk) 4239 return; 4240 String strLabel = (slen == 1 ? "on" : paramAsStr(1)); 4241 if (strLabel.equalsIgnoreCase("on")) 4242 strLabel = "%U"; 4243 else if (strLabel.equalsIgnoreCase("off")) 4244 strLabel = null; 4245 vwr.setHoverLabel(strLabel); 4246 } 4247 cmdLabel(int index, BS bs)4248 private void cmdLabel(int index, BS bs) throws ScriptException { 4249 if (chk) 4250 return; 4251 sm.loadShape(JC.SHAPE_LABELS); 4252 Object strLabel = null; 4253 switch (getToken(index).tok) { 4254 case T.on: 4255 strLabel = vwr.getStandardLabelFormat(0); 4256 break; 4257 case T.off: 4258 break; 4259 case T.hide: 4260 case T.display: 4261 setShapeProperty(JC.SHAPE_LABELS, "display", 4262 theTok == T.display ? Boolean.TRUE : Boolean.FALSE); 4263 return; 4264 case T.varray: 4265 strLabel = theToken.value; 4266 break; 4267 default: 4268 strLabel = paramAsStr(index); 4269 } 4270 sm.setLabel(strLabel, bs == null ? vwr.bsA() : bs); 4271 } 4272 cmdLoad()4273 public void cmdLoad() throws ScriptException { 4274 boolean doLoadFiles = (!chk || isCmdLine_C_Option); 4275 boolean isAppend = false; 4276 boolean isInline = false; 4277 boolean isSmiles = false; 4278 boolean isMutate = false; 4279 boolean isData = false; 4280 boolean isAsync = vwr.async; 4281 boolean isConcat = false; 4282 boolean doOrient = false; 4283 boolean appendNew = vwr.getBoolean(T.appendnew); 4284 boolean isAudio = false; 4285 String filename = null; 4286 BS bsModels; 4287 int i = (tokAt(0) == T.data ? 0 : 1); 4288 String filter = null; 4289 int modelCount0 = vwr.ms.mc 4290 - (vwr.fm.getFileName().equals(JC.ZAP_TITLE) ? 1 : 0); 4291 int ac0 = vwr.ms.ac; 4292 SB loadScript = new SB().append("load"); 4293 int nFiles = 1; 4294 Map<String, Object> htParams = new Hashtable<String, Object>(); 4295 // ignore optional file format 4296 if (isStateScript) { 4297 htParams.put("isStateScript", Boolean.TRUE); 4298 if (forceNoAddHydrogens) 4299 htParams.put("doNotAddHydrogens", Boolean.TRUE); 4300 } 4301 String modelName = null; 4302 String[] filenames = null; 4303 String[] tempFileInfo = null; 4304 String errMsg = null; 4305 SB sOptions = new SB(); 4306 int tokType = 0; 4307 int tok; 4308 4309 // check for special parameters 4310 4311 if (slen == 1) { 4312 i = 0; 4313 } else { 4314 modelName = paramAsStr(i); 4315 if (slen == 2 && !chk) { 4316 // spt, png, and pngj files may be 4317 // run using the LOAD command, but 4318 // we transfer them to the script command 4319 // if it is just LOAD "xxxx.xxx" 4320 // so as to avoid the ZAP in case these 4321 // do not contain a full state script 4322 if (modelName.endsWith(".spt") || modelName.endsWith(".png") 4323 || modelName.endsWith(".pngj")) { 4324 cmdScript(0, modelName, null); 4325 return; 4326 } 4327 } 4328 4329 tok = tokAt(i); 4330 // load MENU 4331 // load DATA "xxx" ...(data here)...END "xxx" 4332 // load DATA "append_and/or_orientation xxx" ...(data here)...END "append_and/or_orientation xxx" 4333 // load DATA "@varName" 4334 // load APPEND (moves pointer forward) 4335 // load XYZ 4336 // load VXYZ 4337 // load VIBRATION 4338 // load TEMPERATURE 4339 // load OCCUPANCY 4340 // load PARTIALCHARGE 4341 // load HISTORY 4342 // load NBO 4343 switch (tok) { 4344 case T.var: 4345 String var = paramAsStr(++i); 4346 filename = "@" + var; 4347 Object o = getVarParameter(var, false); 4348 if (o instanceof Map<?, ?>) { 4349 checkLength(3); 4350 loadPNGJVar(filename, o, htParams); 4351 return; 4352 } 4353 break; 4354 case T.nbo: 4355 case T.history: 4356 case T.menu: 4357 String m = paramAsStr(checkLast(2)); 4358 if (!chk) { 4359 switch (tok) { 4360 case T.nbo: 4361 htParams.put("service", "nbo"); 4362 htParams.put("mode", Integer.valueOf(1)); // MODEL 4363 htParams.put("action", "load"); 4364 htParams.put("value", m); 4365 htParams.put("sync", Boolean.TRUE); 4366 vwr.sm.processService(htParams); 4367 runScript((String) htParams.get("ret")); 4368 break; 4369 case T.history: 4370 vwr.setHistory(m); 4371 break; 4372 case T.menu: 4373 vwr.setMenu(m, true); 4374 break; 4375 } 4376 } 4377 return; 4378 case T.mutate: 4379 isMutate = isAppend = true; 4380 appendNew = false; 4381 loadScript.append(" mutate"); 4382 modelName = optParameterAsString(++i); 4383 tok = T.getTokFromName(modelName); 4384 htParams.put("appendToModelIndex", Integer.valueOf(vwr.am.cmi)); 4385 break; 4386 case T.append: 4387 // we are looking out for state scripts after model 1.1 deletion. 4388 modelName = optParameterAsString(++i); 4389 int ami = PT.parseInt(modelName); 4390 isAppend = (!isStateScript || vwr.ms.mc > 0); 4391 if (isAppend) 4392 loadScript.append(" append"); 4393 if (ami >= 0) { 4394 modelName = optParameterAsString(++i); 4395 if (isAppend) { 4396 loadScript.append(" " + ami); 4397 appendNew = false; 4398 htParams.put("appendToModelIndex", Integer.valueOf(ami)); 4399 } 4400 } 4401 tok = T.getTokFromName(modelName); 4402 break; 4403 case T.orientation: 4404 doOrient = true; 4405 loadScript.append(" orientation"); 4406 vwr.stm.saveOrientation("preload", null); 4407 modelName = optParameterAsString(++i); 4408 tok = T.getTokFromName(modelName); 4409 break; 4410 case T.audio: 4411 isAudio = true; 4412 i++; 4413 break; 4414 case T.identifier: 4415 i++; 4416 loadScript.append(" " + modelName); 4417 tokType = (tok == T.identifier 4418 && PT.isOneOf(modelName.toLowerCase(), JC.LOAD_ATOM_DATA_TYPES) ? T 4419 .getTokFromName(modelName) : T.nada); 4420 if (tokType != T.nada) { 4421 // loading just some data here 4422 // xyz vxyz vibration temperature occupancy partialcharge 4423 htParams.put("atomDataOnly", Boolean.TRUE); 4424 htParams.put("modelNumber", Integer.valueOf(1)); 4425 if (tokType == T.vibration) 4426 tokType = T.vibxyz; 4427 tempFileInfo = vwr.fm.getFileInfo(); 4428 isAppend = true; 4429 } 4430 } 4431 // LOAD [[APPEND]] FILE 4432 // LOAD [[APPEND]] INLINE 4433 // LOAD [[APPEND]] SMILES 4434 // LOAD [[APPEND]] TRAJECTORY 4435 // LOAD [[APPEND]] MODEL 4436 // LOAD ASYNC (asynchronous -- flag for RecentFileDialog) 4437 // LOAD [[APPEND]] "fileNameInQuotes" 4438 4439 switch (tok) { 4440 case T.file: 4441 i++; 4442 loadScript.append(" " + modelName); 4443 if (optParameterAsString(i).equals("+")) { 4444 isConcat = true; 4445 i++; 4446 loadScript.append(" +"); 4447 } 4448 if (optParameterAsString(i).equals("-")) { 4449 isConcat = true; 4450 i++; 4451 loadScript.append(" -"); 4452 } 4453 if (tokAt(i) == T.varray) { 4454 filenames = stringParameterSet(i); 4455 i = iToken; 4456 if (i + 1 != slen) 4457 invArg(); 4458 if (filenames != null) 4459 nFiles = filenames.length; 4460 } 4461 break; 4462 case T.inline: 4463 isInline = true; 4464 i++; 4465 loadScript.append(" " + modelName); 4466 break; 4467 case T.smiles: 4468 isSmiles = true; 4469 i++; 4470 break; 4471 case T.async: 4472 isAsync = true; 4473 htParams.put("async", Boolean.TRUE); 4474 i++; 4475 break; 4476 case T.trajectory: 4477 case T.model: 4478 i++; 4479 loadScript.append(" " + modelName); 4480 if (tok == T.trajectory) 4481 htParams.put("isTrajectory", Boolean.TRUE); 4482 if (isPoint3f(i)) { 4483 P3 pt = getPoint3f(i, false, true); 4484 i = iToken + 1; 4485 // first last stride 4486 htParams.put("firstLastStep", new int[] { (int) pt.x, (int) pt.y, 4487 (int) pt.z }); 4488 loadScript.append(" " + Escape.eP(pt)); 4489 } else { 4490 switch (tokAt(i)) { 4491 case T.bitset: 4492 bsModels = (BS) getToken(i++).value; 4493 htParams.put("bsModels", bsModels); 4494 loadScript.append(" " + Escape.eBS(bsModels)); 4495 break; 4496 default: 4497 htParams.put("firstLastStep", new int[] { 0, -1, 1 }); 4498 } 4499 } 4500 break; 4501 case T.identifier: 4502 // i has been incremented; continue... 4503 break; 4504 case T.data: 4505 String key = stringParameter(++i).toLowerCase(); 4506 modelName = optParameterAsString(i + 1); 4507 isAppend = key.startsWith("append"); 4508 if (isAppend && key.startsWith("append modelindex=")) { 4509 int ami = PT.parseInt(key.substring(18)); 4510 if (ami >= 0) { 4511 appendNew = false; 4512 htParams.put("appendToModelIndex", Integer.valueOf(ami)); 4513 } 4514 } 4515 doOrient = (key.indexOf("orientation") >= 0); 4516 i = addLoadData(loadScript, key, htParams, i); 4517 isData = true; 4518 break; 4519 default: 4520 modelName = "fileset"; 4521 } 4522 if (filename == null && filenames == null && getToken(i).tok != T.string) 4523 error(ERROR_filenameExpected); 4524 } 4525 // long timeBegin = System.currentTimeMillis(); 4526 4527 // file name is next 4528 4529 // LOAD ... "xxxx" 4530 // LOAD ... "xxxx" AS "yyyy" 4531 4532 int filePt = i; 4533 int ptAs = i + 1; 4534 String localName = null; 4535 // String annotation = null; 4536 // if (tokAt(filePt + 1) == T.divide) { 4537 // annotation = optParameterAsString(filePt + 2); 4538 // ptAs += 2; 4539 // i += 2; 4540 // } 4541 if (tokAt(ptAs) == T.as) { 4542 localName = stringParameter(i = ptAs + 1); 4543 if (vwr.fm.getPathForAllFiles() != "") { 4544 // we use the LOCAL name when reading from a local path only (in the case of JMOL files) 4545 localName = null; 4546 filePt = i; 4547 } 4548 } 4549 4550 String appendedData = null; 4551 String appendedKey = null; 4552 4553 if (slen == i + 1) { 4554 // end-of-command options: 4555 // LOAD SMILES "xxxx" --> load "$xxxx" 4556 4557 if (filename == null 4558 && (i == 0 || filenames == null 4559 && (filename = paramAsStr(filePt)).length() == 0)) 4560 filename = getFullPathName(); 4561 if (filename == null && filenames == null) { 4562 cmdZap(false); 4563 return; 4564 } 4565 if (filenames == null && !isInline) { 4566 if (isSmiles) { 4567 filename = "$" + filename; 4568 } else { 4569 if (filename.equals("String[]")) 4570 return; 4571 if (filename.indexOf("[") == 0) { 4572 filenames = Escape.unescapeStringArray(filename); 4573 if (filenames != null) { 4574 if (i == 1) 4575 loadScript.append(" files"); 4576 nFiles = filenames.length; 4577 } 4578 } 4579 } 4580 } 4581 if (filenames != null) 4582 for (int j = 0; j < nFiles; j++) 4583 loadScript.append(" /*file*/").append(PT.esc(filenames[j])); 4584 } else if (isLoadOption(getToken(i + 1).tok)) { 4585 4586 // more complicated command options, in order 4587 // (checking the tokens after "....") 4588 4589 // LOAD "" --> prevous file 4590 4591 if (filename == null && (filename = paramAsStr(filePt)).length() == 0 4592 && (filename = getFullPathName()) == null) { 4593 // no previously loaded file 4594 cmdZap(false); 4595 return; 4596 } 4597 if (filePt == i || localName != null) 4598 i++; 4599 4600 // for whatever reason, we don't allow a filename with [] in it. 4601 if (filename.equals("String[]")) 4602 return; 4603 // MANIFEST "..." 4604 if ((tok = tokAt(i)) == T.manifest) { 4605 String manifest = stringParameter(++i); 4606 htParams.put("manifest", manifest); 4607 sOptions.append(" MANIFEST " + PT.esc(manifest)); 4608 tok = tokAt(++i); 4609 } 4610 // n >= 0: model number 4611 // n < 0: vibration number 4612 // [index1, index2, index3,...] 4613 4614 switch (tok) { 4615 case T.integer: 4616 case T.varray: 4617 case T.leftsquare: 4618 case T.spacebeforesquare: 4619 i = getLoadModelIndex(i, sOptions, htParams); 4620 break; 4621 } 4622 i = getCmdExt().getLoadSymmetryParams(i, sOptions, htParams); 4623 4624 // .... APPEND DATA "appendedData" .... end "appendedData" 4625 // option here to designate other than "appendedData" 4626 // .... APPEND "appendedData" @x .... 4627 4628 if (tokAt(i) == T.append) { 4629 // for CIF reader -- experimental 4630 if (tokAt(++i) == T.data) { 4631 i += 2; 4632 appendedData = (String) getToken(i++).value; 4633 appendedKey = stringParameter(++i); 4634 ++i; 4635 } else { 4636 appendedKey = stringParameter(i++); 4637 appendedData = stringParameter(i++); 4638 } 4639 htParams.put(appendedKey, appendedData); 4640 } 4641 if (tokAt(i) == T.filter) 4642 filter = stringParameter(++i); 4643 } else { 4644 Lst<String> fNames = new Lst<String>(); 4645 if (i == 1) { 4646 if (tokAt(i + 1) == T.plus || tokAt(i + 1) == T.minus) { 4647 modelName = "files"; 4648 } else { 4649 i++; 4650 } 4651 loadScript.append(" " + modelName); 4652 } 4653 if (tokAt(i + 1) == T.minus) // state from /val 4654 isConcat = true; 4655 filter = getLoadFilesList(i, loadScript, sOptions, htParams, fNames); 4656 filenames = fNames.toArray(new String[nFiles = fNames.size()]); 4657 if (!isConcat && loadScript.indexOf("/*concat*/") >= 0) 4658 isConcat = true; 4659 } 4660 4661 // end of parsing 4662 4663 if (!doLoadFiles) 4664 return; 4665 4666 if (filenames != null) 4667 filename = "fileSet"; 4668 4669 // get default filter if necessary 4670 4671 if (appendedData != null) { 4672 sOptions.append(" APPEND data \"" + appendedKey + "\"\n" + appendedData 4673 + (appendedData.endsWith("\n") ? "" : "\n") + "end \"" + appendedKey 4674 + "\""); 4675 } 4676 if (filter == null) 4677 filter = vwr.g.defaultLoadFilter; 4678 if (filter.length() > 0) { 4679 if (filter.toUpperCase().indexOf("DOCACHE") >= 0) { 4680 if (!isStateScript && !isAppend) 4681 vwr.cacheClear(); 4682 } 4683 htParams.put("filter", filter); 4684 if (filter.equalsIgnoreCase("2d")) // MOL file hack 4685 filter = "2D-noMin"; 4686 sOptions.append(" FILTER " + PT.esc(filter)); 4687 } 4688 4689 // store inline data or variable data in htParams 4690 4691 boolean isVariable = false; 4692 if (filenames == null) { 4693 if (filename.equals("string") && vwr.am.cmi >= 0) { 4694 filename = vwr.getCurrentFileAsString(null); 4695 loadScript = new SB().append("load inline "); 4696 isInline = true; 4697 } 4698 if (isInline) { 4699 htParams.put("fileData", filename); 4700 } else if (filename.startsWith("@") && filename.length() > 1) { 4701 Object o = getVarParameter(filename.substring(1), false); 4702 if (o instanceof Map<?, ?>) { 4703 checkLength(i + 1); 4704 loadPNGJVar(filename, o, htParams); 4705 return; 4706 } 4707 isVariable = true; 4708 o = "" + o; 4709 loadScript = new SB().append("{\n var ") 4710 .append(filename.substring(1)).append(" = ") 4711 .append(PT.esc((String) o)).append(";\n ").appendSB(loadScript); 4712 htParams.put("fileData", o); 4713 } else if (!isData && !((filename.startsWith("=") || filename.startsWith("*")) && filename.indexOf("/") > 0)) { 4714 // only for cases that can get filename changed to actual reference 4715 String type = ""; 4716 int pt = filename.indexOf("::"); 4717 if (pt > 0 && pt < 20) { // trying to avoid conflict with some sort of URL that has "::" in it. 4718 type = filename.substring(0, pt + 2); 4719 filename = filename.substring(pt + 2); 4720 } 4721 filename = type + checkFileExists("LOAD" + (isAppend ? "_APPEND_" : "_"), 4722 isAsync, filename, filePt, !isAppend && pc != pcResume); 4723 4724 if (filename.startsWith("cache://")) 4725 localName = null; 4726 // on first pass, a ScriptInterruption will be thrown; 4727 // on the second pass, we will have the file name, which will be cache://localLoad_n__m 4728 } 4729 } 4730 4731 // set up the output stream from AS keyword 4732 4733 OC out = null; 4734 String filecat = null; 4735 if (localName != null) { 4736 if (localName.equals(".")) 4737 localName = vwr.fm.getFilePath(filename, false, true); 4738 if (localName.length() == 0 4739 || vwr.fm.getFilePath(localName, false, false).equalsIgnoreCase( 4740 vwr.fm.getFilePath(filename, false, false))) 4741 invArg(); 4742 String[] fullPath = new String[] { localName }; 4743 out = vwr.getOutputChannel(localName, fullPath); 4744 if (out == null) 4745 Logger.error("Could not create output stream for " + fullPath[0]); 4746 else 4747 htParams.put("outputChannel", out); 4748 } 4749 4750 // check for single file or string 4751 4752 if (filenames == null && tokType == 0) { 4753 4754 // finalize the loadScript 4755 4756 loadScript.append(" "); 4757 if (isVariable || isInline) { 4758 loadScript.append(filename.indexOf('\n') >= 0 || isVariable ? PT 4759 .esc(filename) : filename); 4760 } else if (!isData) { 4761 if (localName != null) 4762 localName = vwr.fm.getFilePath(localName, false, false); 4763 if (!filename.equals("String[]")) 4764 loadScript.append("/*file*/").append( 4765 (localName != null ? PT.esc(localName) : "$FILENAME$")); 4766 } 4767 if (!isConcat && (filename.startsWith("=") || filename.startsWith("*")) 4768 && filename.indexOf("/") > 0) { 4769 4770 // EBI domains and validations, also rna3 and dssr 4771 4772 // load *1cbs/dom/xx/xx --> load *1cbs - *dom/xx/xx/1cbs 4773 // load *1cbs/val/xx/xx --> load *1cbs - *val/xx/xx/1cbs 4774 // load *1cbs/rna3d/loops --> load *1cbs - *rna3d/loops/downloads/1cbs 4775 // TODO load *1cbs/map/xx/xx --> load *1cbs - *map/xx/xx/1cbs (unimplemented electron density?) 4776 // load =1mys/dssr --> load =1mys + *dssr/1mys 4777 4778 isConcat = true; 4779 int pt = filename.indexOf("/"); 4780 String id; 4781 if (pt == 1 && (id = vwr.getPdbID()) != null) { 4782 filename = filename.substring(0, 1) + id + filename.substring(1); 4783 pt = filename.indexOf("/"); 4784 } else { 4785 id = filename.substring(1, pt); 4786 } 4787 String ext = filename.substring(pt + 1); 4788 filename = filename.substring(0, pt); 4789 if ((pt = filename.indexOf(".")) >= 0) 4790 filename = filename.substring(0, pt); 4791 if (JC.PDB_ANNOTATIONS.indexOf(";" + ext + ";") >= 0 4792 || ext.startsWith("dssr--")) { 4793 if (filename.startsWith("=")) 4794 filename += ".cif"; 4795 filenames = (ext.equals("all") ? new String[] { filename, 4796 "*dom/" + id, "*val/" + id } : new String[] { filename, 4797 "*" + ext + "/" + id }); 4798 filename = "fileSet"; 4799 loadScript = null; 4800 isVariable = false; 4801 filecat = "-"; 4802 //sOptions.setLength(0); 4803 } else { 4804 filename += "/" + ext; 4805 } 4806 } 4807 if (loadScript != null) { 4808 if (sOptions.length() > 0) 4809 loadScript.append(" /*options*/ ").append(sOptions.toString()); 4810 if (isVariable) 4811 loadScript.append("\n }"); 4812 htParams.put("loadScript", loadScript); 4813 } 4814 } 4815 4816 if (isAudio) { 4817 if (filename != null) 4818 htParams.put("audioFile", filename); 4819 addFilterAttribute(htParams, filter, "id"); 4820 addFilterAttribute(htParams, filter, "pause"); 4821 addFilterAttribute(htParams, filter, "play"); 4822 addFilterAttribute(htParams, filter, "ended"); 4823 addFilterAttribute(htParams, filter, "action"); 4824 vwr.sm.playAudio(htParams); 4825 return; 4826 } 4827 4828 // load model 4829 4830 setCursorWait(true); 4831 boolean timeMsg = vwr.getBoolean(T.showtiming); 4832 if (timeMsg) 4833 Logger.startTimer("load"); 4834 if (!isStateScript && !isAppend) 4835 vwr.setBooleanProperty("legacyJavaFloat", false); 4836 if (isMutate) 4837 htParams.put("isMutate", Boolean.TRUE); 4838 htParams.put("eval", this); 4839 errMsg = vwr.loadModelFromFile(null, filename, filenames, null, isAppend, 4840 htParams, loadScript, sOptions, tokType, filecat != null ? filecat 4841 : isConcat ? "+" : " "); 4842 if (timeMsg) 4843 showString(Logger.getTimerMsg("load", 0)); 4844 4845 // close output channel 4846 4847 if (out != null) { 4848 vwr.fm.setFileInfo(new String[] { localName }); 4849 Logger.info(GT.o(GT.$("file {0} created"), localName)); 4850 showString(vwr.fm.getFilePath(localName, false, false) + " created"); 4851 out.closeChannel(); 4852 } 4853 4854 // check for just loading an atom property 4855 4856 if (tokType > 0) { 4857 // reset the file info in FileManager, check for errors, and return 4858 vwr.fm.setFileInfo(tempFileInfo); 4859 if (errMsg != null && !isCmdLine_c_or_C_Option) 4860 evalError(errMsg, null); 4861 return; 4862 } 4863 4864 // check for an error 4865 4866 if (errMsg != null && !isCmdLine_c_or_C_Option) { 4867 // note that as ZAP will already have been issued here. 4868 if (errMsg.indexOf(JC.NOTE_SCRIPT_FILE) == 0) { 4869 filename = errMsg.substring(JC.NOTE_SCRIPT_FILE.length()).trim(); 4870 if (filename.indexOf("png|") >= 0 && filename.endsWith("pdb|state.spt")) { 4871 // fix for earlier version in JavaScript saving the full state instead of just the PDB file. 4872 filename = filename.substring(0, filename.lastIndexOf("|")); 4873 filename += filename.substring(filename.lastIndexOf("|")); 4874 runScript("load \"" + filename + "\""); 4875 return; 4876 } 4877 cmdScript(0, filename, null); 4878 return; 4879 } 4880 if (vwr.async && errMsg.startsWith(JC.READER_NOT_FOUND)) { 4881 //TODO: other errors can occur due to missing files 4882 //String rdrName = errMsg.substring(JC.READER_NOT_FOUND.length()); 4883 throw new ScriptInterruption(this, "async", 1); 4884 //errMsg = "asynchronous load for " + rdrName + " initiated"; 4885 } 4886 evalError(errMsg, null); 4887 } 4888 4889 if (debugHigh) 4890 report( 4891 "Successfully loaded:" 4892 + (filenames == null ? htParams.get("fullPathName") : modelName), 4893 false); 4894 4895 finalizeLoad(isAppend, appendNew, isConcat, doOrient, nFiles, ac0, 4896 modelCount0, isData); 4897 4898 } 4899 checkFileExists(String prefix, boolean isAsync, String filename, int i, boolean doClear)4900 public String checkFileExists(String prefix, boolean isAsync, String filename, int i, boolean doClear) throws ScriptException { 4901 if (chk || filename.startsWith("cache://")) 4902 return filename; 4903 if ((vwr.testAsync || Viewer.isJS) 4904 && (isAsync || filename.startsWith("?")) 4905 || vwr.apiPlatform.forceAsyncLoad(filename)) { 4906 filename = loadFileAsync(prefix, filename, i, doClear); 4907 // on first pass, a ScriptInterruption will be thrown; 4908 // on the second pass, we will have the file name, which will be cache://localLoad_n__m 4909 } 4910 4911 String[] fullPathNameOrError = vwr.getFullPathNameOrError(filename); 4912 filename = fullPathNameOrError[0]; 4913 if (fullPathNameOrError[1] != null) 4914 errorStr(ScriptError.ERROR_fileNotFoundException, filename 4915 + ":" + fullPathNameOrError[1]); 4916 return filename; 4917 } 4918 addFilterAttribute(Map<String, Object> htParams, String filter, String key)4919 private void addFilterAttribute(Map<String, Object> htParams, String filter, 4920 String key) { 4921 String val = PT.getQuotedOrUnquotedAttribute(filter, key); 4922 if (val != null && val.length() > 0) 4923 htParams.put(key, val); 4924 } 4925 addLoadData(SB loadScript, String key, Map<String, Object> htParams, int i)4926 private int addLoadData(SB loadScript, String key, Map<String, Object> htParams, int i) throws ScriptException { 4927 loadScript.append(" /*data*/ data"); 4928 int ptVar = key.indexOf("@"); 4929 if (ptVar >= 0) 4930 key = key.replace('@', '_'); 4931 loadScript.append(" ").append(PT.esc(key)); 4932 String strModel = (ptVar >= 0 ? "" 4933 + getParameter(key.substring(ptVar + 1), T.string, true) 4934 : paramAsStr(++i)); 4935 strModel = Viewer.fixInlineString(strModel, vwr.getInlineChar()); 4936 htParams.put("fileData", strModel); 4937 htParams.put("isData", Boolean.TRUE); 4938 //note: ScriptCompiler will remove an initial \n if present 4939 loadScript.appendC('\n').append(strModel).append(" end ") 4940 .append(PT.esc(key)); 4941 if (ptVar < 0) 4942 i += 2; // skip END "key" 4943 return i; 4944 } 4945 loadPNGJVar(String varName, Object o, Map<String, Object> htParams)4946 private void loadPNGJVar(String varName, Object o, Map<String, Object> htParams) throws ScriptException { 4947 SV[] av = new SV[] {SV.newV(T.hash, o)}; 4948 getCmdExt().dispatch(T.binary, false, av); 4949 htParams.put("imageData", av[0].value); 4950 OC out = vwr.getOutputChannel(null, null); 4951 htParams.put("outputChannel", out); 4952 vwr.createZip("", "BINARY", htParams); 4953 String modelName = "cache://VAR_" + varName; 4954 vwr.cacheFileByName("cache://VAR_*",false); 4955 vwr.cachePut(modelName, out.toByteArray()); 4956 cmdScript(0, modelName, null); 4957 } 4958 getLoadFilesList(int i, SB loadScript, SB sOptions, Map<String, Object> htParams, Lst<String> fNames)4959 private String getLoadFilesList(int i, SB loadScript, SB sOptions, 4960 Map<String, Object> htParams, Lst<String> fNames) throws ScriptException { 4961 // list of file names 4962 // or COORD {i j k} "fileName" 4963 // or COORD ({bitset}) "fileName" 4964 // or FILTER "xxxx" 4965 4966 Lst<Object> firstLastSteps = null; 4967 String filter = null; 4968 P3 pt = null; 4969 BS bs = null; 4970 while (i < slen) { 4971 switch (tokAt(i)) { 4972 case T.plus: 4973 loadScript.append("/*concat*/ +"); 4974 ++i; 4975 continue; 4976 case T.minus: 4977 // =xxxx/val split into two 4978 loadScript.append(" -"); 4979 ++i; 4980 continue; 4981 case T.integer: 4982 case T.varray: 4983 case T.leftsquare: 4984 case T.spacebeforesquare: 4985 i = getLoadModelIndex(i, sOptions, htParams); 4986 continue; 4987 case T.filter: 4988 filter = stringParameter(++i); 4989 ++i; 4990 continue; 4991 case T.coord: 4992 htParams.remove("isTrajectory"); 4993 if (firstLastSteps == null) { 4994 firstLastSteps = new Lst<Object>(); 4995 pt = P3.new3(0, -1, 1); 4996 } 4997 if (isPoint3f(++i)) { 4998 pt = getPoint3f(i, false, true); 4999 i = iToken + 1; 5000 } else if (tokAt(i) == T.bitset) { 5001 bs = (BS) getToken(i).value; 5002 pt = null; 5003 i = iToken + 1; 5004 } 5005 break; 5006 case T.identifier: 5007 invArg(); 5008 } 5009 fNames.addLast(paramAsStr(i++)); 5010 if (pt != null) { 5011 firstLastSteps 5012 .addLast(new int[] { (int) pt.x, (int) pt.y, (int) pt.z }); 5013 loadScript.append(" COORD " + Escape.eP(pt)); 5014 } else if (bs != null) { 5015 firstLastSteps.addLast(bs); 5016 loadScript.append(" COORD " + Escape.eBS(bs)); 5017 } 5018 loadScript.append(" /*file*/$FILENAME" + fNames.size() + "$"); 5019 } 5020 if (firstLastSteps != null) 5021 htParams.put("firstLastSteps", firstLastSteps); 5022 return filter; 5023 } 5024 isLoadOption(int tok)5025 private boolean isLoadOption(int tok) { 5026 switch (tok) { 5027 case T.manifest: 5028 // model/vibration index or list of model indices 5029 case T.integer: 5030 case T.varray: 5031 case T.leftsquare: 5032 case T.spacebeforesquare: 5033 // {i j k} (lattice) 5034 case T.leftbrace: 5035 case T.point3f: 5036 // PACKED/CENTROID, either order 5037 case T.packed: 5038 case T.centroid: 5039 // SUPERCELL {i j k} 5040 case T.supercell: 5041 // RANGE x.x or RANGE -x.x 5042 case T.fill: // new in Jmol 14.3.14 5043 // FILL BOUNDBOX 5044 // FILL UNITCELL 5045 case T.range: 5046 // SPACEGROUP "nameOrNumber" 5047 // or SPACEGROUP "IGNOREOPERATORS" 5048 // or SPACEGROUP "" (same as current) 5049 case T.spacegroup: 5050 // UNITCELL [a b c alpha beta gamma] 5051 // or UNITCELL [ax ay az bx by bz cx cy cz] 5052 // or UNITCELL "" (same as current) 5053 // UNITCELL "..." or UNITCELL "" 5054 case T.unitcell: 5055 // OFFSET {x y z} 5056 case T.offset: 5057 case T.data: 5058 // FILTER "..." 5059 case T.append: 5060 // Jmol 13.1.5 -- APPEND "data..." 5061 return true; 5062 case T.filter: 5063 case T.identifier: 5064 return (tokAt(iToken + 2) != T.coord); 5065 } 5066 return false; 5067 } 5068 getLoadModelIndex(int i, SB sOptions, Map<String, Object> htParams)5069 private int getLoadModelIndex(int i, SB sOptions, 5070 Map<String, Object> htParams) 5071 throws ScriptException { 5072 int n; 5073 switch (tokAt(i)) { 5074 case T.integer: 5075 htParams.remove("firstLastStep"); 5076 htParams.remove("bsModel"); 5077 htParams.put("useFileModelNumbers", Boolean.TRUE); 5078 n = intParameter(i); 5079 sOptions.append(" ").appendI(n); 5080 if (n < 0) 5081 htParams.put("vibrationNumber", Integer.valueOf(-n)); 5082 else 5083 htParams.put("modelNumber", Integer.valueOf(n)); 5084 break; 5085 case T.varray: 5086 case T.leftsquare: 5087 case T.spacebeforesquare: 5088 htParams.remove("firstLastStep"); 5089 float[] data = floatParameterSet(i, 1, Integer.MAX_VALUE); 5090 BS bs = new BS(); 5091 int[] iArray = new int[data.length]; 5092 for (int j = 0; j < data.length; j++) { 5093 n = (int) data[j]; 5094 if (data[j] >= 1 && data[j] == n) 5095 bs.set(n - 1); 5096 else 5097 invArg(); 5098 iArray[j] = n; 5099 } 5100 sOptions.append(" " + Escape.eAI(iArray)); 5101 htParams.put("bsModels", bs); 5102 htParams.put("useFileModelNumbers", Boolean.TRUE); 5103 break; 5104 } 5105 return iToken + 1; 5106 } 5107 finalizeLoad(boolean isAppend, boolean appendNew, boolean isConcat, boolean doOrient, int nFiles, int ac0, int modelCount0, boolean isData)5108 private void finalizeLoad(boolean isAppend, boolean appendNew, 5109 boolean isConcat, boolean doOrient, int nFiles, 5110 int ac0, int modelCount0, boolean isData) 5111 throws ScriptException { 5112 if (isAppend && (appendNew || nFiles > 1)) { 5113 vwr.setAnimationRange(-1, -1); 5114 vwr.setCurrentModelIndex(modelCount0); 5115 } 5116 String msg; 5117 if (scriptLevel == 0 && !isAppend && (isConcat || nFiles < 2) 5118 && (msg = (String) vwr.ms.getInfoM("modelLoadNote")) != null) 5119 vwr.showString(msg, false); 5120 Object centroid = vwr.ms.getInfoM("centroidMinMax"); 5121 if (AU.isAI(centroid) && vwr.ms.ac > 0) { 5122 BS bs = BSUtil.newBitSet2(isAppend ? ac0 : 0, vwr.ms.ac); 5123 vwr.ms.setCentroid(bs, (int[]) centroid); 5124 } 5125 String script = vwr.g.defaultLoadScript; 5126 msg = ""; 5127 if (script.length() > 0) 5128 msg += "\nUsing defaultLoadScript: " + script; 5129 String embeddedScript; 5130 Map<String, Object> info = vwr.ms.msInfo; 5131 if (info != null && vwr.allowEmbeddedScripts() 5132 && (embeddedScript = (String) info.remove("jmolscript")) != null 5133 && embeddedScript.length() > 0) { 5134 msg += "\nAdding embedded #jmolscript: " + embeddedScript; 5135 script += ";" + embeddedScript; 5136 setStringProperty("_loadScript", script); 5137 script = "allowEmbeddedScripts = false;try{" + script 5138 + "} allowEmbeddedScripts = true;"; 5139 isEmbedded = !isCmdLine_c_or_C_Option; 5140 } else { 5141 setStringProperty("_loadScript", ""); 5142 } 5143 logLoadInfo(msg, isData); 5144 5145 String siteScript = (info == null ? null 5146 : (String) info.remove("sitescript")); 5147 if (siteScript != null) 5148 script = siteScript + ";" + script; 5149 if (doOrient) 5150 script += ";restore orientation preload"; 5151 if (script.length() > 0 && !isCmdLine_c_or_C_Option) 5152 // NOT checking embedded scripts in some cases 5153 runScript(script); 5154 isEmbedded = false; 5155 } 5156 cmdLog()5157 private void cmdLog() throws ScriptException { 5158 if (slen == 1) 5159 bad(); 5160 if (chk) 5161 return; 5162 String s = parameterExpressionString(1, 0); 5163 if (tokAt(1) == T.off) 5164 setStringProperty("logFile", ""); 5165 else 5166 vwr.log(s); 5167 } 5168 cmdLoop()5169 private void cmdLoop() throws ScriptException { 5170 if (vwr.headless) 5171 return; 5172 // back to the beginning of this script 5173 if (!chk) 5174 pc = -1; 5175 cmdDelay(); 5176 // JavaScript will not get here 5177 } 5178 cmdMessage()5179 private void cmdMessage() throws ScriptException { 5180 String text = paramAsStr(checkLast(1)); 5181 if (chk) 5182 return; 5183 String s = Txt.formatText(vwr, text); 5184 if (outputBuffer == null && !vwr.isPrintOnly) 5185 Logger.warn(s); 5186 if (!s.startsWith("_")) 5187 report(s, false); 5188 } 5189 5190 /** 5191 * ONE difference between FRAME and MODEL: model 1 sets model NAMED one in the 5192 * case of PDB frame 1 always sets the first model 5193 * 5194 * @param offset 5195 * will be 2 for "anim frame ..." 5196 * @throws ScriptException 5197 */ cmdModel(int offset)5198 private void cmdModel(int offset) throws ScriptException { 5199 boolean isFrame = (theTok == T.frame || vwr.ms.mc > 1); 5200 int[] frameList = new int[] { -1, -1 }; 5201 int nFrames = 0; 5202 boolean useModelNumber = true; 5203 int modelIndex = -1; 5204 if (slen == 1 && offset == 1) { 5205 modelIndex = vwr.am.cmi; 5206 int m; 5207 if (!chk && modelIndex >= 0 5208 && (m = vwr.ms.getJmolDataSourceFrame(modelIndex)) >= 0) 5209 vwr.setCurrentModelIndex(m == modelIndex ? Integer.MIN_VALUE : m); 5210 return; 5211 } 5212 switch (tokAt(1)) { 5213 case T.mo: 5214 if (!chk && isFrame && slen == 2) { 5215 while (++modelIndex < vwr.ms.mc) { 5216 if (!vwr.ms.am[modelIndex].auxiliaryInfo.containsKey("moData")) 5217 continue; 5218 vwr.am.setFrame(modelIndex); 5219 showString("Frame set to " + (modelIndex + 1)); 5220 return; 5221 } 5222 showString("No molecular orbitals"); 5223 } 5224 return; 5225 case T.integer: 5226 if (isFrame && slen == 2) { 5227 // FRAME n 5228 if (!chk) 5229 vwr.am.setFrame(intParameter(1) - 1); 5230 return; 5231 } 5232 break; 5233 case T.expressionBegin: 5234 case T.bitset: 5235 modelIndex = atomExpressionAt(1).nextSetBit(0); 5236 if (chk || modelIndex < 0 || modelIndex >= vwr.ms.ac) 5237 return; 5238 modelIndex = vwr.ms.at[modelIndex].mi; 5239 if (iToken + 1 == slen) { 5240 vwr.setCurrentModelIndex(modelIndex); 5241 return; 5242 } 5243 frameList[nFrames++] = modelIndex; 5244 offset = iToken + 1; 5245 useModelNumber = false; 5246 break; 5247 case T.create: 5248 iToken = 1; 5249 int n = (tokAt(2) == T.integer ? intParameter(++iToken) : 1); 5250 checkLength(iToken + 1); 5251 if (!chk && n > 0) 5252 vwr.ms.createModels(n); 5253 return; 5254 case T.id: 5255 checkLength(3); 5256 String id = stringParameter(2); 5257 if (!chk) 5258 vwr.setCurrentModelID(id); 5259 return; 5260 case T.delay: 5261 long millis = 0; 5262 checkLength(3); 5263 switch (getToken(2).tok) { 5264 case T.integer: 5265 case T.decimal: 5266 millis = (long) (floatParameter(2) * 1000); 5267 break; 5268 default: 5269 error(ERROR_integerExpected); 5270 } 5271 if (!chk) 5272 vwr.setFrameDelayMs(millis); 5273 return; 5274 case T.title: 5275 if (checkLength23() > 0) 5276 if (!chk) 5277 vwr.setFrameTitleObj(slen == 2 ? "@{_modelName}" 5278 : (tokAt(2) == T.varray ? SV.strListValue(st[2]) : paramAsStr(2))); 5279 return; 5280 case T.orientation: 5281 if (tokAt(2) == T.decimal && tokAt(3) == T.matrix4f) { 5282 modelIndex = vwr.ms.getModelNumberIndex(getToken(2).intValue, false, 5283 false); 5284 M4 mat4 = (M4) getToken(3).value; 5285 if (modelIndex >= 0) 5286 vwr.ms.am[modelIndex].mat4 = mat4; 5287 return; 5288 } 5289 break; 5290 case T.align: 5291 boolean isNone = (tokAt(2) == T.none); 5292 BS bs = (slen == 2 || isNone ? null : atomExpressionAt(2)); 5293 if (isNone) 5294 iToken = 2; 5295 boolean isFixed = (tokAt(iToken + 1) == T.fixed); 5296 checkLength(iToken + (isFixed ? 2 : 1)); 5297 if (!chk) 5298 vwr.setFrameOffsets(bs, isFixed); 5299 return; 5300 } 5301 if (getToken(offset).tok == T.minus) { 5302 ++offset; 5303 if (getToken(checkLast(offset)).tok != T.integer 5304 || intParameter(offset) != 1) 5305 invArg(); 5306 if (!chk) 5307 vwr.setAnimation(T.prev); 5308 return; 5309 } 5310 boolean isPlay = false; 5311 boolean isRange = false; 5312 String propName = null; 5313 Object prop = null; 5314 boolean isAll = false; 5315 boolean isHyphen = false; 5316 float fFrame = 0; 5317 P3 frameAlign = null; 5318 boolean haveFileSet = vwr.haveFileSet(); 5319 if (isArrayParameter(1)) { 5320 setFrameSet(1); 5321 isAll = true; 5322 } else { 5323 for (int i = offset; i < slen; i++) { 5324 switch (getToken(i).tok) { 5325 case T.align: 5326 // model 2.3 align {0 0 0} // from state 5327 if (i != 2) 5328 invArg(); 5329 frameAlign = centerParameter(3, null); 5330 checkLength(i = iToken + 1); 5331 break; 5332 case T.all: 5333 case T.times: 5334 checkLength(offset + (isRange ? 2 : 1)); 5335 isAll = true; 5336 break; 5337 case T.minus: // ignore 5338 if (nFrames != 1) 5339 invArg(); 5340 isHyphen = true; 5341 break; 5342 case T.none: 5343 checkLength(offset + 1); 5344 break; 5345 case T.decimal: 5346 useModelNumber = false; 5347 if ((fFrame = floatParameter(i)) < 0) { 5348 checkLength(i + 1); 5349 if (!chk) 5350 vwr.am.morph(-fFrame); 5351 return; 5352 } 5353 //$FALL-THROUGH$ 5354 case T.integer: 5355 case T.string: 5356 if (nFrames == 2) 5357 invArg(); 5358 int iFrame = (theTok == T.string ? getFloatEncodedInt((String) theToken.value) 5359 : theToken.intValue); 5360 if (iFrame < 0 && nFrames == 1) { 5361 isHyphen = true; 5362 iFrame = -iFrame; 5363 if (haveFileSet && iFrame < 1000000) 5364 iFrame *= 1000000; 5365 } 5366 if (theTok == T.decimal && haveFileSet && fFrame == (int) fFrame) 5367 iFrame = (int) fFrame * 1000000; 5368 if (iFrame == Integer.MAX_VALUE) { 5369 useModelNumber = false; 5370 frameList[nFrames++] = (chk || i != 1 ? 0 : vwr 5371 .getModelIndexFromId(theToken.value.toString())); 5372 break; 5373 } 5374 if (iFrame == -1) { 5375 checkLength(offset + 1); 5376 if (!chk) 5377 vwr.setAnimation(T.prev); 5378 return; 5379 } 5380 if (iFrame >= 1000 && iFrame < 1000000 && haveFileSet) 5381 iFrame = (iFrame / 1000) * 1000000 + (iFrame % 1000); // initial way 5382 if (!useModelNumber && iFrame == 0 && nFrames == 0) 5383 isAll = true; // 0.0 means ALL; 0 means "all in this range 5384 if (iFrame >= 1000000) 5385 useModelNumber = false; 5386 frameList[nFrames++] = iFrame; 5387 break; 5388 case T.play: 5389 isPlay = true; 5390 break; 5391 case T.range: 5392 isRange = true; 5393 break; 5394 case T.property: 5395 if (modelIndex < 0 && (modelIndex = vwr.am.cmi) < 0) 5396 return; 5397 propName = paramAsStr(++i); 5398 SV sv = setVariable(++i, -1, "", false); 5399 if (sv != null && !chk) { 5400 if (propName.equalsIgnoreCase("DSSR")) { 5401 loadDssr(modelIndex, (String) sv.value); 5402 return; 5403 } 5404 prop = SV.oValue(sv); 5405 } 5406 if (!chk) 5407 vwr.ms.setInfo(modelIndex, propName, prop); 5408 return; 5409 default: 5410 frameControl(offset); 5411 return; 5412 } 5413 } 5414 } 5415 if (chk) 5416 return; 5417 if (isRange && nFrames == 0) 5418 isAll = true; 5419 if (isAll) { 5420 vwr.setAnimationOn(false); 5421 vwr.setAnimationRange(-1, -1); 5422 if (!isRange) 5423 vwr.setCurrentModelIndex(-1); 5424 return; 5425 } 5426 if (nFrames == 2 && !isRange) 5427 isHyphen = true; 5428 if (haveFileSet) 5429 useModelNumber = false; 5430 else if (useModelNumber) 5431 for (int i = 0; i < nFrames; i++) 5432 if (frameList[i] >= 0) 5433 frameList[i] %= 1000000; 5434 modelIndex = vwr.ms 5435 .getModelNumberIndex(frameList[0], useModelNumber, false); 5436 if (frameAlign != null) { 5437 if (modelIndex >= 0) { 5438 vwr.ms.translateModel(modelIndex, null); 5439 vwr.ms.translateModel(modelIndex, frameAlign); 5440 } 5441 return; 5442 } 5443 int modelIndex2 = -1; 5444 if (haveFileSet && modelIndex < 0 && frameList[0] != 0) { 5445 // may have frame 2.0 or frame 2 meaning the range of models in file 2 5446 // or frame 2.0 - 3.1 or frame 2.0 - 3.0 5447 if (frameList[0] < 1000000) 5448 frameList[0] *= 1000000; 5449 if (nFrames == 2 && frameList[1] < 1000000) 5450 frameList[1] *= 1000000; 5451 if (frameList[0] % 1000000 == 0) { 5452 frameList[0]++; 5453 modelIndex = vwr.ms.getModelNumberIndex(frameList[0], false, false); 5454 if (modelIndex >= 0) { 5455 int i2 = (nFrames == 1 ? frameList[0] + 1000000 5456 : frameList[1] == 0 ? -1 5457 : frameList[1] % 1000000 == 0 ? frameList[1] + 1000001 5458 : frameList[1] + 1); 5459 modelIndex2 = vwr.ms.getModelNumberIndex(i2, false, false); 5460 if (modelIndex2 < 0) 5461 modelIndex2 = vwr.ms.mc; 5462 modelIndex2--; 5463 if (isRange) 5464 nFrames = 2; 5465 else if (!isHyphen && modelIndex2 != modelIndex) 5466 isHyphen = true; 5467 isRange = isRange || modelIndex == modelIndex2;// (isRange || 5468 // !isHyphen && 5469 // modelIndex2 != 5470 // modelIndex); 5471 } 5472 } else { 5473 // must have been a bad frame number. Just return. 5474 return; 5475 } 5476 } 5477 5478 if (!isPlay && !isRange || modelIndex >= 0) 5479 vwr.setCurrentModelIndexClear(modelIndex, false); 5480 if (isPlay && nFrames == 2 || isRange || isHyphen) { 5481 if (modelIndex2 < 0) 5482 modelIndex2 = vwr.ms.getModelNumberIndex(frameList[1], useModelNumber, 5483 false); 5484 vwr.setAnimationOn(false); 5485 vwr.am.setAnimationDirection(1); 5486 vwr.setAnimationRange(modelIndex, modelIndex2); 5487 vwr.setCurrentModelIndexClear(isHyphen && !isRange ? -1 5488 : modelIndex >= 0 ? modelIndex : 0, false); 5489 } 5490 if (isPlay) 5491 vwr.setAnimation(T.resume); 5492 } 5493 loadDssr(int modelIndex, String data)5494 private void loadDssr(int modelIndex, String data) throws ScriptException { 5495 if (modelIndex < 0 && (modelIndex = vwr.am.cmi) < 0) 5496 errorStr(ScriptError.ERROR_multipleModelsDisplayedNotOK, "load <dssr file>"); 5497 if (!data.startsWith("{")) 5498 data = vwr.getFileAsString3(data, true, "script"); 5499 clearDefinedVariableAtomSets(); 5500 Map<String, Object> map = vwr.parseJSONMap(data); 5501 showString(vwr.getAnnotationParser(true).fixDSSRJSONMap(map)); 5502 vwr.ms.setInfo(modelIndex, "dssr", map); 5503 } 5504 cmdMove()5505 private void cmdMove() throws ScriptException { 5506 checkLength(-11); 5507 // rotx roty rotz zoom transx transy transz slab seconds fps 5508 V3 dRot = V3.new3(floatParameter(1), floatParameter(2), floatParameter(3)); 5509 float dZoom = floatParameter(4); 5510 V3 dTrans = V3.new3(intParameter(5), intParameter(6), intParameter(7)); 5511 float dSlab = floatParameter(8); 5512 float floatSecondsTotal = floatParameter(9); 5513 int fps = (slen == 11 ? intParameter(10) : 30); 5514 if (chk) 5515 return; 5516 refresh(false); 5517 if (!useThreads()) 5518 floatSecondsTotal = 0; 5519 vwr.move(this, dRot, dZoom, dTrans, dSlab, floatSecondsTotal, fps); 5520 if (floatSecondsTotal > 0 && isJS) 5521 throw new ScriptInterruption(this, "move", 1); 5522 } 5523 cmdMoveto()5524 private void cmdMoveto() throws ScriptException { 5525 // moveto time 5526 // moveto [time] { x y z deg} zoom xTrans yTrans (rotCenter) rotationRadius 5527 // (navCenter) xNav yNav navDepth 5528 // moveto [time] { x y z deg} 0 xTrans yTrans (rotCenter) [zoom factor] 5529 // (navCenter) xNav yNav navDepth 5530 // moveto [time] { x y z deg} (rotCenter) [zoom factor] (navCenter) xNav 5531 // yNav navDepth 5532 // where [zoom factor] is [0|n|+n|-n|*n|/n|IN|OUT] 5533 // moveto [time] front|back|left|right|top|bottom 5534 if (slen == 2 && tokAt(1) == T.stop) { 5535 if (!chk) 5536 vwr.tm.stopMotion(); 5537 return; 5538 } 5539 float floatSecondsTotal; 5540 if (slen == 2 && isFloatParameter(1)) { 5541 floatSecondsTotal = floatParameter(1); 5542 if (chk) 5543 return; 5544 if (!useThreads()) 5545 floatSecondsTotal = 0; 5546 if (floatSecondsTotal > 0) 5547 refresh(false); 5548 vwr.moveTo(this, floatSecondsTotal, null, JC.axisZ, 0, null, 100, 0, 0, 5549 0, null, Float.NaN, Float.NaN, Float.NaN, Float.NaN, Float.NaN, 5550 Float.NaN); 5551 if (isJS && floatSecondsTotal > 0 && vwr.g.waitForMoveTo) 5552 throw new ScriptInterruption(this, "moveTo", 1); 5553 return; 5554 } 5555 V3 axis = V3.new3(Float.NaN, 0, 0); 5556 P3 center = null; 5557 int i = 1; 5558 floatSecondsTotal = (isFloatParameter(i) ? floatParameter(i++) : 2.0f); 5559 float degrees = 90; 5560 BS bsCenter = null; 5561 boolean isChange = true; 5562 boolean isMolecular = false; 5563 float xTrans = 0; 5564 float yTrans = 0; 5565 float zoom = Float.NaN; 5566 float rotationRadius = Float.NaN; 5567 float zoom0 = vwr.tm.getZoomSetting(); 5568 P3 navCenter = null; 5569 float xNav = Float.NaN; 5570 float yNav = Float.NaN; 5571 float navDepth = Float.NaN; 5572 float cameraDepth = Float.NaN; 5573 float cameraX = Float.NaN; 5574 float cameraY = Float.NaN; 5575 float[] pymolView = null; 5576 Quat q = null; 5577 int tok = getToken(i).tok; 5578 switch (tok) { 5579 case T.pymol: 5580 // 18-element standard PyMOL view matrix 5581 // [0-8] are 3x3 rotation matrix (inverted) 5582 // [9,10] are x,y translations (y negative) 5583 // [11] is distance from camera to center (negative) 5584 // [12-14] are rotation center coords 5585 // [15-16] are slab and depth distance from camera (0 to ignore) 5586 // [17] is field of view; positive for orthographic projection 5587 // or 21-element extended matrix (PSE file reading) 5588 // [18,19] are boolean depth_cue and fog settings 5589 // [20] is fogStart (usually 0.45) 5590 pymolView = floatParameterSet(++i, 18, 21); 5591 i = iToken + 1; 5592 if (chk && checkLength(i) > 0) 5593 return; 5594 break; 5595 case T.quaternion: 5596 if (tokAt(++i) == T.molecular) { 5597 // see comment below 5598 isMolecular = true; 5599 i++; 5600 } 5601 if (isAtomExpression(i)) { 5602 isMolecular = true; 5603 Object[] ret = new Object[1]; 5604 center = centerParameter(i, ret); 5605 if (!(ret[0] instanceof BS)) 5606 invArg(); 5607 bsCenter = (BS) ret[0]; 5608 q = (chk ? new Quat() : vwr.ms.getQuaternion(bsCenter.nextSetBit(0), 5609 vwr.getQuaternionFrame())); 5610 } else { 5611 q = getQuaternionParameter(i, null, false); 5612 } 5613 i = iToken + 1; 5614 if (q == null) 5615 invArg(); 5616 break; 5617 case T.point4f: 5618 case T.point3f: 5619 case T.leftbrace: 5620 // {X, Y, Z} deg or {x y z deg} 5621 if (isPoint3f(i)) { 5622 axis.setT(getPoint3f(i, true, true)); 5623 i = iToken + 1; 5624 degrees = floatParameter(i++); 5625 } else { 5626 P4 pt4 = getPoint4f(i); 5627 i = iToken + 1; 5628 axis.set(pt4.x, pt4.y, pt4.z); 5629 degrees = (pt4.x == 0 && pt4.y == 0 && pt4.z == 0 ? Float.NaN : pt4.w); 5630 } 5631 break; 5632 case T.front: 5633 axis.set(1, 0, 0); 5634 degrees = 0f; 5635 checkLength(++i); 5636 break; 5637 case T.back: 5638 axis.set(0, 1, 0); 5639 degrees = 180f; 5640 checkLength(++i); 5641 break; 5642 case T.left: 5643 axis.set(0, 1, 0); 5644 checkLength(++i); 5645 break; 5646 case T.right: 5647 axis.set(0, -1, 0); 5648 checkLength(++i); 5649 break; 5650 case T.top: 5651 axis.set(1, 0, 0); 5652 checkLength(++i); 5653 break; 5654 case T.bottom: 5655 axis.set(-1, 0, 0); 5656 checkLength(++i); 5657 break; 5658 case T.axis: 5659 String abc = paramAsStr(++i); 5660 if (abc.equals("-")) 5661 abc += paramAsStr(++i); 5662 checkLength(++i); 5663 switch ("xyz".indexOf(abc)) { 5664 case 0: 5665 q = Quat.new4(0.5f,0.5f,0.5f,-0.5f); 5666 break; 5667 case 1: 5668 q = Quat.new4(0.5f,0.5f,0.5f,0.5f); 5669 break; 5670 case 2: 5671 q = Quat.new4(0, 0, 0, 1); 5672 break; 5673 default: 5674 // a b c 5675 SymmetryInterface uc; 5676 uc = vwr.getCurrentUnitCell(); 5677 if (uc == null) { 5678 uc = vwr.getSymTemp(); 5679 uc.setUnitCell(new float[] { 1, 1, 1, 90, 90, 90 }, false); 5680 } 5681 q = uc.getQuaternionRotation(abc); 5682 if (q == null) 5683 invArg(); 5684 } 5685 break; 5686 default: 5687 // X Y Z deg 5688 axis = V3.new3(floatParameter(i++), floatParameter(i++), 5689 floatParameter(i++)); 5690 degrees = floatParameter(i++); 5691 } 5692 if (q != null) { 5693 A4 aa; 5694 aa = q.toAxisAngle4f(); 5695 axis.set(aa.x, aa.y, aa.z); 5696 /* 5697 * The quaternion angle for an atom represents the angle by which the 5698 * reference frame must be rotated to match the frame defined for the 5699 * residue. 5700 * 5701 * However, to "moveTo" this frame as the REFERENCE frame, what we have to 5702 * do is take that quaternion frame and rotate it BACKWARD by that many 5703 * degrees. Then it will match the reference frame, which is ultimately 5704 * our window frame. 5705 * 5706 * We only apply this for molecular-type quaternions, because in general 5707 * the orientation quaternion refers to how the reference plane has been 5708 * changed (the orientation matrix) 5709 */ 5710 degrees = (isMolecular ? -1 : 1) * (float) (aa.angle * 180.0 / Math.PI); 5711 } 5712 if (Float.isNaN(axis.x) || Float.isNaN(axis.y) || Float.isNaN(axis.z)) 5713 axis.set(0, 0, 0); 5714 else if (axis.length() == 0 && degrees == 0) 5715 degrees = Float.NaN; 5716 isChange = (tok == T.quaternion || !vwr.tm.isInPosition(axis, degrees)); 5717 // optional zoom 5718 if (isFloatParameter(i)) 5719 zoom = floatParameter(i++); 5720 // optional xTrans yTrans 5721 if (isFloatParameter(i) && !isCenterParameter(i)) { 5722 xTrans = floatParameter(i++); 5723 yTrans = floatParameter(i++); 5724 if (!isChange && Math.abs(xTrans - vwr.tm.getTranslationXPercent()) >= 1) 5725 isChange = true; 5726 if (!isChange && Math.abs(yTrans - vwr.tm.getTranslationYPercent()) >= 1) 5727 isChange = true; 5728 } 5729 if (bsCenter == null && i != slen) { 5730 // if any more, required (center) 5731 Object[] ret = new Object[1]; 5732 center = centerParameter(i, ret); 5733 if (ret[0] instanceof BS) 5734 bsCenter = (BS) ret[0]; 5735 i = iToken + 1; 5736 } 5737 if (center != null) { 5738 if (!isChange && center.distance(vwr.tm.fixedRotationCenter) >= 0.1) 5739 isChange = true; 5740 // optional {center} rotationRadius 5741 if (isFloatParameter(i)) 5742 rotationRadius = floatParameter(i++); 5743 if (!isCenterParameter(i)) { 5744 if ((rotationRadius == 0 || Float.isNaN(rotationRadius)) 5745 && (zoom == 0 || Float.isNaN(zoom))) { 5746 // alternative (atom expression) 0 zoomFactor 5747 float newZoom = Math.abs(getZoom(0, i, bsCenter, (zoom == 0 ? 0 5748 : zoom0))); 5749 i = iToken + 1; 5750 zoom = newZoom; 5751 } else { 5752 if (!isChange 5753 && Math.abs(rotationRadius - vwr.getFloat(T.rotationradius)) >= 0.1) 5754 isChange = true; 5755 } 5756 } 5757 if (zoom == 0 || Float.isNaN(zoom)) 5758 zoom = 100; 5759 if (Float.isNaN(rotationRadius)) 5760 rotationRadius = 0; 5761 5762 if (!isChange && Math.abs(zoom - zoom0) >= 1) 5763 isChange = true; 5764 // (navCenter) xNav yNav navDepth 5765 5766 if (i != slen) { 5767 navCenter = centerParameter(i, null); 5768 i = iToken + 1; 5769 if (i != slen) { 5770 xNav = floatParameter(i++); 5771 yNav = floatParameter(i++); 5772 } 5773 if (i != slen) 5774 navDepth = floatParameter(i++); 5775 if (i != slen) { 5776 cameraDepth = floatParameter(i++); 5777 if (!isChange 5778 && Math.abs(cameraDepth - vwr.tm.getCameraDepth()) >= 0.01f) 5779 isChange = true; 5780 } 5781 if (i + 1 < slen) { 5782 cameraX = floatParameter(i++); 5783 cameraY = floatParameter(i++); 5784 if (!isChange && Math.abs(cameraX - vwr.tm.camera.x) >= 0.01f) 5785 isChange = true; 5786 if (!isChange && Math.abs(cameraY - vwr.tm.camera.y) >= 0.01f) 5787 isChange = true; 5788 } 5789 } 5790 } 5791 checkLength(i); 5792 if (chk) 5793 return; 5794 if (!isChange) 5795 floatSecondsTotal = 0; 5796 if (floatSecondsTotal > 0) 5797 refresh(false); 5798 if (!useThreads()) 5799 floatSecondsTotal = 0; 5800 if (cameraDepth == 0) { 5801 cameraDepth = cameraX = cameraY = Float.NaN; 5802 } 5803 if (pymolView != null) 5804 vwr.tm.moveToPyMOL(this, floatSecondsTotal, pymolView); 5805 else 5806 vwr.moveTo(this, floatSecondsTotal, center, axis, degrees, null, zoom, 5807 xTrans, yTrans, rotationRadius, navCenter, xNav, yNav, navDepth, 5808 cameraDepth, cameraX, cameraY); 5809 if (isJS && floatSecondsTotal > 0 && vwr.g.waitForMoveTo) 5810 throw new ScriptInterruption(this, "moveTo", 1); 5811 } 5812 isAtomExpression(int i)5813 public boolean isAtomExpression(int i) { 5814 switch(tokAt(i)) { 5815 case T.define: // added 5/13/17 5816 case T.bitset: 5817 case T.expressionBegin: 5818 return true; 5819 default: 5820 return false; 5821 } 5822 } 5823 cmdPause()5824 private boolean cmdPause() throws ScriptException { 5825 if (chk || isJS && !allowJSThreads) 5826 return false; 5827 String msg = optParameterAsString(1); 5828 if (!vwr.getBooleanProperty("_useCommandThread")) { 5829 // showString("Cannot pause thread when _useCommandThread = FALSE: " + 5830 // msg); 5831 // return; 5832 } 5833 if (vwr.autoExit || !vwr.haveDisplay && !Viewer.isWebGL) 5834 return false; 5835 if (scriptLevel == 0 && pc == aatoken.length - 1) { 5836 vwr.scriptStatus("nothing to pause: " + msg); 5837 return false; 5838 } 5839 msg = (msg.length() == 0 ? ": RESUME to continue." : ": " 5840 + Txt.formatText(vwr, msg)); 5841 pauseExecution(true); 5842 vwr.scriptStatusMsg("script execution paused" + msg, 5843 "script paused for RESUME"); 5844 return true; 5845 } 5846 cmdPrint()5847 private void cmdPrint() throws ScriptException { 5848 if (slen == 1) { 5849 if (!chk) 5850 showStringPrint("\0", true); 5851 return; 5852 } 5853 showStringPrint(parameterExpressionString(1, 0), true); 5854 } 5855 cmdPrompt()5856 private void cmdPrompt() throws ScriptException { 5857 String msg = null; 5858 if (slen == 1) { 5859 if (!chk) 5860 msg = getContextTrace(vwr, getScriptContext("prompt"), null, true) 5861 .toString(); 5862 } else { 5863 msg = parameterExpressionString(1, 0); 5864 } 5865 if (!chk) 5866 vwr.prompt(msg, null, null, true); 5867 } 5868 cmdReset()5869 private void cmdReset() throws ScriptException { 5870 if (slen == 3 && tokAt(1) == T.function) { 5871 if (!chk) 5872 vwr.removeFunction(stringParameter(2)); 5873 return; 5874 } 5875 checkLength(-2); 5876 if (chk) 5877 return; 5878 if (slen == 1) { 5879 vwr.reset(false); 5880 return; 5881 } 5882 // possibly "all" 5883 switch (tokAt(1)) { 5884 case T.print: 5885 if (!chk && outputBuffer != null) 5886 outputBuffer.setLength(0); 5887 return; 5888 case T.cache: 5889 vwr.cacheClear(); 5890 return; 5891 case T.error: 5892 resetError(); 5893 return; 5894 case T.lighting: 5895 vwr.stm.resetLighting(); 5896 return; 5897 case T.shape: 5898 vwr.resetShapes(true); 5899 return; 5900 case T.function: 5901 vwr.clearFunctions(); 5902 return; 5903 case T.structure: 5904 BS bsModified = new BS(); 5905 runScript(vwr.ms.getDefaultStructure(vwr.bsA(), bsModified)); 5906 vwr.shm.resetBioshapes(bsModified); 5907 return; 5908 case T.vanderwaals: 5909 vwr.setData("element_vdw", new Object[] { null, "" }, 0, 0, 0, 0, 0); 5910 return; 5911 case T.aromatic: 5912 vwr.ms.resetAromatic(); 5913 return; 5914 case T.spin: 5915 vwr.reset(true); 5916 return; 5917 } 5918 String var = paramAsStr(1); 5919 if (var.charAt(0) == '_') 5920 invArg(); 5921 vwr.unsetProperty(var); 5922 } 5923 resetError()5924 private void resetError() { 5925 vwr.g.removeParam("_errormessage"); 5926 } 5927 cmdRestrict()5928 private void cmdRestrict() throws ScriptException { 5929 boolean isBond = (tokAt(1) == T.bonds); 5930 cmdSelect(isBond ? 2 : 1); 5931 restrictSelected(isBond, true); 5932 } 5933 cmdReturn(SV tv)5934 private void cmdReturn(SV tv) throws ScriptException { 5935 if (chk) 5936 return; 5937 SV t = getContextVariableAsVariable("_retval", false); 5938 if (t != null) { 5939 SV v = (tv != null || slen == 1 ? null : parameterExpressionToken(1)); 5940 if (tv == null) 5941 tv = (v == null ? SV.newI(0) : v); 5942 t.value = tv.value; 5943 t.intValue = tv.intValue; 5944 t.tok = tv.tok; 5945 } 5946 cmdGoto(false); 5947 } 5948 cmdRotate(boolean isSpin, boolean isSelected)5949 public void cmdRotate(boolean isSpin, boolean isSelected) 5950 throws ScriptException { 5951 5952 // rotate is a full replacement for spin 5953 // spin is DEPRECATED 5954 5955 /* 5956 * The Chime spin method: 5957 * 5958 * set spin x 10;set spin y 30; set spin z 10; spin | spin ON spin OFF 5959 * 5960 * Jmol does these "first x, then y, then z" I don't know what Chime does. 5961 * 5962 * spin and rotate are now consolidated here. 5963 * 5964 * far simpler is 5965 * 5966 * spin x 10 spin y 10 5967 * 5968 * these are pure x or y spins or 5969 * 5970 * spin axisangle {1 1 0} 10 5971 * 5972 * this is the same as the old "spin x 10; spin y 10" -- or is it? anyway, 5973 * it's better! 5974 * 5975 * note that there are many defaults 5976 * 5977 * spin # defaults to spin y 10 5978 * spin 10 # defaults to spin y 10 5979 * spin x # defaults to spin x 10 5980 * 5981 * and several new options 5982 * 5983 * spin -x 5984 * spin axisangle {1 1 0} 10 5985 * spin 10 (atomno=1)(atomno=2) 5986 * spin 20 {0 0 0} {1 1 1} 5987 * 5988 * spin MOLECULAR {0 0 0} 20 5989 * 5990 * The MOLECULAR keyword indicates that spins or rotations are to be carried 5991 * out in the internal molecular coordinate frame, not the fixed room frame. 5992 * 5993 * In the case of rotateSelected, all rotations are molecular and the 5994 * absense of the MOLECULAR keyword indicates to rotate about the geometric 5995 * center of the molecule, not {0 0 0} 5996 * 5997 * Fractional coordinates may be indicated: 5998 * 5999 * spin 20 {0 0 0/} {1 1 1/} 6000 * 6001 * In association with this, TransformManager and associated functions are 6002 * TOTALLY REWRITTEN and consolideated. It is VERY clean now - just two 6003 * methods here -- one fixed and one molecular, two in Viewer, and two in 6004 * TransformManager. All the centering stuff has been carefully inspected 6005 * are reorganized as well. 6006 * 6007 * Bob Hanson 5/21/06 6008 */ 6009 6010 if (slen == 2) 6011 switch (getToken(1).tok) { 6012 case T.on: 6013 if (!chk) 6014 vwr.tm.setSpinOn(); 6015 return; 6016 case T.off: 6017 if (!chk) 6018 vwr.tm.setSpinOff(); 6019 return; 6020 } 6021 6022 BS bsAtoms = null, bsBest = null; 6023 float degreesPerSecond = PT.FLOAT_MIN_SAFE; 6024 int nPoints = 0; 6025 float endDegrees = Float.MAX_VALUE; 6026 boolean isMolecular = false; 6027 boolean haveRotation = false; 6028 float[] dihedralList = null; 6029 Lst<P3> ptsA = null; 6030 P3[] points = new P3[2]; 6031 V3 rotAxis = V3.new3(0, 1, 0); 6032 V3 translation = null; 6033 M4 m4 = null; 6034 M3 m3 = null; 6035 boolean is4x4 = false; 6036 int direction = 1; 6037 int tok; 6038 Quat q = null; 6039 boolean helicalPath = false; 6040 boolean isDegreesPerSecond = false; 6041 boolean isSeconds = false; 6042 Lst<P3> ptsB = null; 6043 BS bsCompare = null; 6044 P3 invPoint = null; 6045 P4 invPlane = null; 6046 boolean axesOrientationRasmol = vwr.getBoolean(T.axesorientationrasmol); 6047 for (int i = 1; i < slen; ++i) { 6048 switch (tok = getToken(i).tok) { 6049 case T.rotate: 6050 // from MODELKIT - ignore 6051 continue; 6052 case T.define: 6053 case T.bitset: 6054 case T.expressionBegin: 6055 bsBest = atomExpressionAt(i); 6056 if (translation != null || q != null || nPoints == 2) { 6057 bsAtoms = bsBest; 6058 ptsB = null; 6059 isSelected = true; 6060 break; 6061 } 6062 //$FALL-THROUGH$ 6063 case T.leftbrace: 6064 case T.point3f: 6065 case T.dollarsign: 6066 haveRotation = true; 6067 if (nPoints == 2) 6068 nPoints = 0; 6069 // {X, Y, Z} 6070 // $drawObject[n] 6071 P3 pt1 = centerParameterForModel(i, vwr.am.cmi, null); 6072 if (!chk && tok == T.dollarsign && tokAt(i + 2) != T.leftsquare) { 6073 // rotation about an axis such as $line1 6074 isMolecular = true; 6075 Object[] data = new Object[] { objectNameParameter(++i), 6076 Integer.valueOf(vwr.am.cmi), null }; 6077 rotAxis = (getShapePropertyData(JC.SHAPE_DRAW, "getSpinAxis", data) ? (V3) data[2] 6078 : null); 6079 } 6080 points[nPoints++] = pt1; 6081 break; 6082 case T.spin: 6083 isSpin = true; 6084 continue; 6085 case T.internal: 6086 case T.molecular: 6087 isMolecular = true; 6088 continue; 6089 case T.selected: 6090 isSelected = true; 6091 break; 6092 case T.comma: 6093 continue; 6094 case T.integer: 6095 case T.decimal: 6096 if (isSpin) { 6097 // rotate spin ... [degreesPerSecond] 6098 // rotate spin ... [endDegrees] [degreesPerSecond] 6099 // rotate spin BRANCH <DihedralList> [seconds] 6100 if (degreesPerSecond == PT.FLOAT_MIN_SAFE) { 6101 degreesPerSecond = floatParameter(i); 6102 } else if (endDegrees == Float.MAX_VALUE) { 6103 endDegrees = degreesPerSecond; 6104 degreesPerSecond = floatParameter(i); 6105 } else { 6106 invArg(); 6107 } 6108 } else { 6109 // rotate ... [endDegrees] 6110 // rotate ... [endDegrees] [degreesPerSecond] 6111 if (endDegrees == Float.MAX_VALUE) { 6112 endDegrees = floatParameter(i); 6113 } else if (degreesPerSecond == PT.FLOAT_MIN_SAFE) { 6114 degreesPerSecond = floatParameter(i); 6115 isSpin = true; 6116 } else { 6117 invArg(); 6118 } 6119 } 6120 if (i == slen - 2 && (tokAt(i + 1) == T.misc || tokAt(i + 1) == T.string)) { 6121 String s = paramAsStr(++i).toLowerCase(); 6122 if (s.equals("dps")) { 6123 isDegreesPerSecond = true; 6124 } else if (s.equals("sec")) { 6125 isSeconds = true; 6126 } 6127 } 6128 break; 6129 case T.minus: 6130 direction = -1; 6131 continue; 6132 case T.x: 6133 haveRotation = true; 6134 rotAxis.set(direction, 0, 0); 6135 continue; 6136 case T.y: 6137 haveRotation = true; 6138 rotAxis.set(0, direction, 0); 6139 continue; 6140 case T.z: 6141 haveRotation = true; 6142 rotAxis.set(0, 0, (axesOrientationRasmol && !isMolecular ? -direction 6143 : direction)); 6144 continue; 6145 6146 // 11.6 options 6147 6148 case T.point4f: 6149 case T.quaternion: 6150 case T.best: 6151 if (tok == T.quaternion) 6152 i++; 6153 haveRotation = true; 6154 if ((q = getQuaternionParameter(i, bsBest, tok == T.best)) != null) { 6155 if (q.q0 == 0) 6156 q.q0 = 1e-10f; 6157 rotAxis.setT(q.getNormal()); 6158 endDegrees = q.getTheta(); // returns [0-180] 6159 // System.out.println(q + " " + rotAxis + " " + endDegrees); 6160 // if (q.q0 < 0) { 6161 // greater than 180 degrees - we go the other way, in case this is a spin 6162 // endDegrees = -endDegrees; 6163 // } 6164 } 6165 break; 6166 case T.plane: 6167 // rotate plane @1 @2 @3 6168 // rotate plane picked 6169 P3[] pts; 6170 int n; 6171 if (paramAsStr(i + 1).equalsIgnoreCase("picked")) { 6172 i++; 6173 @SuppressWarnings("unchecked") 6174 Lst<SV> lst = (Lst<SV>) vwr.getPOrNull("pickedList"); 6175 n = lst.size(); 6176 if (n < 3) 6177 return; 6178 pts = new P3[3]; 6179 for (int j = 0; j < 3; j++) 6180 pts[j] = vwr.ms.getAtomSetCenter(SV.getBitSet(lst.get(n - 3 + j), 6181 false)); 6182 } else if (isArrayParameter(i + 1)) { 6183 pts = getPointArray(++i, -1, false); 6184 i = iToken; 6185 } else { 6186 pts = new P3[3]; 6187 for (int j = 0; j < 3; j++) { 6188 pts[j] = centerParameter(++i, null); 6189 i = iToken; 6190 } 6191 } 6192 n = pts.length; 6193 if (n < 3) 6194 return; 6195 q = Quat.getQuaternionFrame(pts[n - 3], pts[n - 2], pts[n - 1]); 6196 q = Quat.new4(1, 0, 0, 0).mulQ(q.inv().div(vwr.tm.getRotationQ())); 6197 rotAxis.setT(q.getNormal()); 6198 endDegrees = q.getTheta(); 6199 break; 6200 case T.axisangle: 6201 haveRotation = true; 6202 if (isPoint3f(++i)) { 6203 rotAxis.setT(centerParameter(i, null)); 6204 break; 6205 } 6206 P4 p4 = getPoint4f(i); 6207 rotAxis.set(p4.x, p4.y, p4.z); 6208 endDegrees = p4.w; 6209 q = Quat.newVA(rotAxis, endDegrees); 6210 break; 6211 case T.branch: 6212 isSelected = true; 6213 isMolecular = true; 6214 haveRotation = true; 6215 if (isArrayParameter(++i)) { 6216 dihedralList = floatParameterSet(i, 6, Integer.MAX_VALUE); 6217 i = iToken; 6218 } else { 6219 int iAtom1 = atomExpressionAt(i).nextSetBit(0); 6220 int iAtom2 = atomExpressionAt(++iToken).nextSetBit(0); 6221 if (iAtom1 < 0 || iAtom2 < 0) 6222 return; 6223 bsAtoms = vwr.getBranchBitSet(iAtom2, iAtom1, true); 6224 points[0] = vwr.ms.at[iAtom1]; 6225 points[1] = vwr.ms.at[iAtom2]; 6226 nPoints = 2; 6227 } 6228 break; 6229 6230 // 12.0 options 6231 6232 case T.translate: 6233 translation = V3.newV(centerParameter(++i, null)); 6234 isMolecular = isSelected = true; 6235 break; 6236 case T.helix: 6237 // screw motion, for quaternion-based operations 6238 helicalPath = true; 6239 continue; 6240 case T.symop: 6241 int symop = intParameter(++i); 6242 if (chk) 6243 continue; 6244 Map<String, Object> info = vwr.getSymTemp().getSpaceGroupInfo(vwr.ms, 6245 null, -1, false, null); 6246 Object[] op = (info == null ? null : (Object[]) info.get("operations")); 6247 if (symop == 0 || op == null || op.length < Math.abs(symop)) 6248 invArg(); 6249 op = (Object[]) op[Math.abs(symop) - 1]; 6250 translation = (V3) op[5]; 6251 invPoint = (P3) op[6]; 6252 points[0] = (P3) op[7]; 6253 if (op[8] != null) 6254 rotAxis = (V3) op[8]; 6255 endDegrees = ((Integer) op[9]).intValue(); 6256 if (symop < 0) { 6257 endDegrees = -endDegrees; 6258 if (translation != null) 6259 translation.scale(-1); 6260 } 6261 if (endDegrees == 0 && points[0] != null) { 6262 // glide plane 6263 rotAxis.normalize(); 6264 Measure.getPlaneThroughPoint(points[0], rotAxis, invPlane = new P4()); 6265 } 6266 q = Quat.newVA(rotAxis, endDegrees); 6267 nPoints = (points[0] == null ? 0 : 1); 6268 isMolecular = true; 6269 haveRotation = true; 6270 isSelected = true; 6271 continue; 6272 case T.compare: 6273 bsCompare = atomExpressionAt(++i); 6274 ptsA = vwr.ms.getAtomPointVector(bsCompare); 6275 if (ptsA == null) { 6276 iToken = i; 6277 invArg(); 6278 } 6279 i = iToken; 6280 ptsB = getPointVector(getToken(++i), i); 6281 if (ptsB == null || ptsA.size() != ptsB.size()) { 6282 iToken = i; 6283 invArg(); 6284 } 6285 m4 = new M4(); 6286 points[0] = new P3(); 6287 nPoints = 1; 6288 Interface.getInterface("javajs.util.Eigen", vwr, "script"); 6289 float stddev = (chk ? 0 : Measure.getTransformMatrix4(ptsA, ptsB, m4, 6290 points[0])); 6291 // if the standard deviation is very small, we leave ptsB 6292 // because it will be used to set the absolute final positions 6293 if (stddev > 0.001) 6294 ptsB = null; 6295 //$FALL-THROUGH$ 6296 case T.matrix4f: 6297 case T.matrix3f: 6298 haveRotation = true; 6299 m3 = new M3(); 6300 if (tok == T.matrix4f) { 6301 is4x4 = true; 6302 m4 = (M4) theToken.value; 6303 } 6304 if (m4 != null) { 6305 // translation and rotation are calculated 6306 translation = new V3(); 6307 m4.getTranslation(translation); 6308 m4.getRotationScale(m3); 6309 } else { 6310 m3 = (M3) theToken.value; 6311 } 6312 q = (chk ? new Quat() : Quat.newM(m3)); 6313 rotAxis.setT(q.getNormal()); 6314 endDegrees = q.getTheta(); 6315 isMolecular = true; 6316 break; 6317 default: 6318 invArg(); 6319 } 6320 i = iToken; 6321 } 6322 if (chk) 6323 return; 6324 6325 // process 6326 if (dihedralList != null) { 6327 if (endDegrees != Float.MAX_VALUE) { 6328 isSpin = true; 6329 degreesPerSecond = endDegrees; 6330 } 6331 } 6332 6333 if (isSelected && bsAtoms == null) 6334 bsAtoms = vwr.bsA(); 6335 if (bsCompare != null) { 6336 isSelected = true; 6337 if (bsAtoms == null) 6338 bsAtoms = bsCompare; 6339 } 6340 if (q != null && !isSeconds && !isDegreesPerSecond) { 6341 isDegreesPerSecond = (degreesPerSecond > 0); 6342 isSeconds = !isDegreesPerSecond; 6343 } 6344 float rate = (degreesPerSecond == PT.FLOAT_MIN_SAFE ? 10 6345 : endDegrees == Float.MAX_VALUE ? degreesPerSecond 6346 : isDegreesPerSecond ? degreesPerSecond 6347 : isSeconds ? (endDegrees < 0 ? -1 : 1) * Math.abs(endDegrees / degreesPerSecond) 6348 : (degreesPerSecond < 0) == (q == null ? endDegrees > 0 6349 : true) ? 6350 // -n means number of seconds, not degreesPerSecond 6351 -endDegrees / degreesPerSecond 6352 : degreesPerSecond); 6353 if (q == null && endDegrees < 0 && rate > 0) 6354 rate = -rate; 6355 if (dihedralList != null) { 6356 if (!isSpin) { 6357 vwr.setDihedrals(dihedralList, null, 1); 6358 return; 6359 } 6360 translation = null; 6361 } 6362 6363 if (q != null) { 6364 // only when there is a translation but not a 4x4 matrix) 6365 // do we set the rotation to be the center of the selected atoms or model 6366 if (nPoints == 0 && translation != null && !is4x4) 6367 points[0] = vwr.ms.getAtomSetCenter(bsAtoms != null ? bsAtoms 6368 : isSelected ? vwr.bsA() : vwr.getAllAtoms()); 6369 if (helicalPath && translation != null) { 6370 points[1] = P3.newP(points[0]); 6371 points[1].add(translation); 6372 T3[] ret = Measure.computeHelicalAxis(points[0], points[1], q); 6373 // new T3[] { pt_a_prime, n, r, P3.new3(theta, pitch, residuesPerTurn), pt_b_prime }; 6374 points[0] = (P3) ret[0]; 6375 float theta = ((P3) ret[3]).x; 6376 if (theta != 0) { 6377 translation = (V3) ret[1]; 6378 rotAxis = V3.newV(translation); 6379 if (theta < 0) 6380 rotAxis.scale(-1); 6381 } 6382 m4 = null; 6383 } 6384 if (isSpin && m4 == null) 6385 m4 = ScriptMathProcessor.getMatrix4f(q.getMatrix(), translation); 6386 if (points[0] != null) 6387 nPoints = 1; 6388 } 6389 if (invPoint != null) { 6390 vwr.invertAtomCoordPt(invPoint, bsAtoms); 6391 if (rotAxis == null) 6392 return; 6393 } 6394 if (invPlane != null) { 6395 vwr.invertAtomCoordPlane(invPlane, bsAtoms); 6396 if (rotAxis == null) 6397 return; 6398 } 6399 // a thread will be required if we are spinning 6400 // UNLESS we are headless, 6401 // in which case we just turn off the spin 6402 boolean requiresThread = (isSpin && (!vwr.headless || endDegrees == Float.MAX_VALUE)); 6403 // just turn this into a rotation if we cannot spin 6404 if (isSpin && !requiresThread) 6405 isSpin = false; 6406 if (nPoints < 2 && dihedralList == null) { 6407 if (!isMolecular) { 6408 // fixed-frame rotation 6409 // rotate x 10 # Chime-like 6410 // rotate axisangle {0 1 0} 10 6411 // rotate x 10 (atoms) # point-centered 6412 // rotate x 10 $object # point-centered 6413 if (requiresThread && bsAtoms == null && !useThreads()) { 6414 isSpin = false; 6415 if (endDegrees == Float.MAX_VALUE) 6416 return; 6417 } 6418 if (vwr.rotateAxisAngleAtCenter(this, points[0], rotAxis, rate, 6419 endDegrees, isSpin, bsAtoms)) { 6420 // bsAtoms can be non-null if we have a quaternion 6421 // rotate quaternion {2 3 4 4} {atomno<10} 6422 // a fixed quaternion rotation of a set of atoms 6423 // currently rotateAxisAngleAtCenter cannot return true 6424 // if isSpin is true. But that is what we are working on 6425 // TODO: not exactly clear here if this will work 6426 if (isJS && isSpin && bsAtoms == null && vwr.g.waitForMoveTo 6427 && endDegrees != Float.MAX_VALUE) 6428 throw new ScriptInterruption(this, "rotate", 1); 6429 } 6430 return; 6431 } 6432 6433 // must be an internal rotation 6434 6435 if (nPoints == 0) 6436 points[0] = new P3(); 6437 // rotate MOLECULAR 6438 // rotate MOLECULAR (atom1) 6439 // rotate MOLECULAR x 10 (atom1) 6440 // rotate axisangle MOLECULAR (atom1) 6441 points[1] = P3.newP(points[0]); 6442 points[1].add(rotAxis); 6443 nPoints = 2; 6444 } 6445 if (nPoints == 0) 6446 points[0] = new P3(); 6447 if (nPoints < 2 || points[0].distance(points[1]) == 0) { 6448 points[1] = P3.newP(points[0]); 6449 points[1].y += 1.0; 6450 } 6451 if (endDegrees == Float.MAX_VALUE) 6452 endDegrees = 0; 6453 if (endDegrees != 0 && translation != null && !haveRotation) 6454 translation.scale(endDegrees / translation.length()); 6455 if (isSpin && translation != null 6456 && (endDegrees == 0 || degreesPerSecond == 0)) { 6457 // need a token rotation 6458 endDegrees = 0.01f; 6459 rate = (degreesPerSecond == PT.FLOAT_MIN_SAFE ? 0.01f 6460 : degreesPerSecond < 0 ? 6461 // -n means number of seconds, not degreesPerSecond 6462 -endDegrees / degreesPerSecond 6463 : degreesPerSecond * 0.01f / translation.length()); 6464 degreesPerSecond = 0.01f; 6465 } 6466 if (bsAtoms != null && isSpin && ptsB == null && m4 != null) { 6467 ptsA = vwr.ms.getAtomPointVector(bsAtoms); 6468 // note that this m4 is NOT through 6469 ptsB = Measure.transformPoints(ptsA, m4, points[0]); 6470 } 6471 if (bsAtoms != null && !isSpin && ptsB != null) { 6472 vwr.setAtomCoords(bsAtoms, T.xyz, ptsB); 6473 } else { 6474 if (requiresThread && !useThreads()) 6475 return; 6476 if (vwr.rotateAboutPointsInternal(this, points[0], points[1], rate, 6477 endDegrees, isSpin, bsAtoms, translation, ptsB, dihedralList, 6478 is4x4 ? m4 : null) 6479 && isJS && isSpin) 6480 throw new ScriptInterruption(this, "rotate", 1); 6481 } 6482 } 6483 cmdRestore()6484 private void cmdRestore() throws ScriptException { 6485 // restore orientation name time 6486 if (slen > 1) { 6487 String saveName = optParameterAsString(2); 6488 int tok = tokAt(1); 6489 switch (tok) { 6490 case T.unitcell: 6491 if (!chk) 6492 setModelCagePts(-1, null, null); 6493 return; 6494 case T.orientation: 6495 case T.rotation: 6496 case T.scene: 6497 float floatSecondsTotal = (slen > 3 ? floatParameter(3) : 0); 6498 if (floatSecondsTotal < 0) 6499 invArg(); 6500 if (chk) 6501 return; 6502 String type = ""; 6503 switch (tok) { 6504 case T.orientation: 6505 type = "Orientation"; 6506 vwr.stm.restoreOrientation(saveName, floatSecondsTotal, true); 6507 break; 6508 case T.rotation: 6509 type = "Rotation"; 6510 vwr.stm.restoreOrientation(saveName, floatSecondsTotal, false); 6511 break; 6512 case T.scene: 6513 type = "Scene"; 6514 vwr.stm.restoreScene(saveName, floatSecondsTotal); 6515 break; 6516 } 6517 if (isJS && floatSecondsTotal > 0 && vwr.g.waitForMoveTo) 6518 throw new ScriptInterruption(this, "restore" + type, 1); 6519 return; 6520 } 6521 checkLength23(); 6522 switch (tok) { 6523 case T.bonds: 6524 if (!chk) 6525 vwr.stm.restoreBonds(saveName); 6526 return; 6527 case T.context: 6528 if (chk) 6529 return; 6530 ScriptContext sc = (ScriptContext) vwr.stm.getContext(saveName); 6531 if (sc != null) { 6532 restoreScriptContext(sc, true, false, false); 6533 if (thisContext != null) { 6534 thisContext.setMustResume(); 6535 mustResumeEval = true; 6536 tQuiet = true; 6537 } 6538 } 6539 return; 6540 case T.coord: 6541 if (chk) 6542 return; 6543 String script = vwr.stm.getSavedCoordinates(saveName); 6544 if (script == null) 6545 invArg(); 6546 runScript(script); 6547 vwr.checkCoordinatesChanged(); 6548 return; 6549 case T.selection: 6550 if (!chk) 6551 vwr.stm.restoreSelection(saveName); 6552 return; 6553 case T.state: 6554 if (chk) 6555 return; 6556 String state = vwr.stm.getSavedState(saveName); 6557 if (state == null) 6558 invArg(); 6559 runScript(state); 6560 return; 6561 case T.structure: 6562 if (chk) 6563 return; 6564 String shape = vwr.stm.getSavedStructure(saveName); 6565 if (shape == null) 6566 invArg(); 6567 runScript(shape); 6568 return; 6569 } 6570 } 6571 errorStr2(ERROR_what, "RESTORE", saveList); 6572 } 6573 cmdSave()6574 private void cmdSave() throws ScriptException { 6575 if (slen > 1) { 6576 String saveName = optParameterAsString(2); 6577 switch (tokAt(1)) { 6578 case T.bonds: 6579 if (!chk) 6580 vwr.stm.saveBonds(saveName); 6581 return; 6582 case T.context: 6583 if (!chk) 6584 saveContext(saveName); 6585 return; 6586 case T.coord: 6587 if (!chk) 6588 vwr.stm.saveCoordinates(saveName, vwr.bsA()); 6589 return; 6590 case T.orientation: 6591 case T.rotation: 6592 if (!chk) 6593 vwr.stm.saveOrientation(saveName, null); 6594 return; 6595 case T.selection: 6596 if (!chk) { 6597 vwr.stm.saveSelection(saveName, vwr.bsA()); 6598 vwr.stm.restoreSelection(saveName); // just to register the # of 6599 } 6600 return; 6601 case T.state: 6602 if (!chk) 6603 vwr.stm.saveState(saveName); 6604 return; 6605 case T.structure: 6606 if (!chk) 6607 vwr.stm.saveStructure(saveName); 6608 return; 6609 } 6610 } 6611 errorStr2(ERROR_what, "SAVE", saveList); 6612 } 6613 cmdScript(int tok, String filename, String theScript)6614 public void cmdScript(int tok, String filename, String theScript) 6615 throws ScriptException { 6616 if (tok == T.javascript) { 6617 checkLength(2); 6618 if (!chk) 6619 vwr.jsEval(paramAsStr(1)); 6620 return; 6621 } 6622 boolean loadCheck = true; 6623 boolean isCheck = false; 6624 boolean doStep = false; 6625 boolean isAsync = vwr.async; 6626 int lineNumber = 0; 6627 int pc = 0; 6628 int lineEnd = 0; 6629 int pcEnd = 0; 6630 int i = 1; 6631 String localPath = null; 6632 String remotePath = null; 6633 String scriptPath = null; 6634 Lst<SV> params = null; 6635 if (tok == T.macro) { 6636 i = -2; 6637 } 6638 if (filename == null && theScript == null) { 6639 tok = tokAt(i); 6640 if (tok != T.string) 6641 error(ERROR_filenameExpected); 6642 filename = paramAsStr(i); 6643 6644 if (filename.equalsIgnoreCase("async")) { 6645 isAsync = true; 6646 filename = paramAsStr(++i); 6647 } 6648 if (filename.equalsIgnoreCase("applet")) { 6649 filename = null; 6650 // script APPLET x "....." 6651 String appID = paramAsStr(++i); 6652 theScript = parameterExpressionString(++i, 0); // had _script variable?? 6653 checkLast(iToken); 6654 if (chk) 6655 return; 6656 if (appID.length() == 0 || appID.equals("all")) 6657 appID = "*"; 6658 if (!appID.equals(".")) { 6659 vwr.jsEval(appID + "\1" + theScript); 6660 if (!appID.equals("*")) 6661 return; 6662 } 6663 } else { 6664 tok = tokAt(slen - 1); 6665 doStep = (tok == T.step); 6666 if (filename.equalsIgnoreCase("inline")) { 6667 filename = null; 6668 theScript = parameterExpressionString(++i, (doStep ? slen - 1 : 0)); 6669 i = iToken; 6670 } else { 6671 while (filename.equalsIgnoreCase("localPath") 6672 || filename.equalsIgnoreCase("remotePath") 6673 || filename.equalsIgnoreCase("scriptPath")) { 6674 if (filename.equalsIgnoreCase("localPath")) 6675 localPath = paramAsStr(++i); 6676 else if (filename.equalsIgnoreCase("scriptPath")) 6677 scriptPath = paramAsStr(++i); 6678 else 6679 remotePath = paramAsStr(++i); 6680 filename = paramAsStr(++i); 6681 } 6682 if (filename.startsWith("spt::")) 6683 filename = filename.substring(5); 6684 filename = checkFileExists("SCRIPT_", isAsync, filename, i, true); 6685 } 6686 if ((tok = tokAt(++i)) == T.check) { 6687 isCheck = true; 6688 tok = tokAt(++i); 6689 } 6690 if (tok == T.noload) { 6691 loadCheck = false; 6692 tok = tokAt(++i); 6693 } 6694 if (tok == T.line || tok == T.lines) { 6695 i++; 6696 lineEnd = lineNumber = Math.max(intParameter(i++), 0); 6697 if (checkToken(i)) { 6698 if (getToken(i).tok == T.minus) 6699 lineEnd = (checkToken(++i) ? intParameter(i++) : 0); 6700 else 6701 lineEnd = -intParameter(i++); 6702 if (lineEnd <= 0) 6703 invArg(); 6704 } 6705 } else if (tok == T.command || tok == T.commands) { 6706 i++; 6707 pc = Math.max(intParameter(i++) - 1, 0); 6708 pcEnd = pc + 1; 6709 if (checkToken(i)) { 6710 if (getToken(i).tok == T.minus) 6711 pcEnd = (checkToken(++i) ? intParameter(i++) : 0); 6712 else 6713 pcEnd = -intParameter(i++); 6714 if (pcEnd <= 0) 6715 invArg(); 6716 } 6717 } 6718 i = -i; 6719 } 6720 } else if (filename != null && isAsync) { 6721 filename = checkFileExists("SCRIPT_", isAsync, filename, i, true); 6722 } 6723 if (i < 0) { 6724 if (tokAt(i = -i) == T.leftparen) { 6725 params = parameterExpressionList(i, -1, false); 6726 i = iToken + 1; 6727 } 6728 checkLength(doStep ? i + 1 : i); 6729 } 6730 6731 // processing 6732 6733 if (chk && !isCmdLine_c_or_C_Option) 6734 return; 6735 if (isCmdLine_c_or_C_Option) 6736 isCheck = true; 6737 boolean wasSyntaxCheck = chk; 6738 boolean wasScriptCheck = isCmdLine_c_or_C_Option; 6739 if (isCheck) 6740 chk = isCmdLine_c_or_C_Option = true; 6741 pushContext(null, "SCRIPT"); 6742 contextPath += " >> " + filename; 6743 if (theScript == null) 6744 theScript = getScriptFileInternal(filename, localPath, remotePath, scriptPath); 6745 if (compileScript(filename, theScript, filename != null && debugScript)) { 6746 this.pcEnd = pcEnd; 6747 this.lineEnd = lineEnd; 6748 while (pc < lineNumbers.length && lineNumbers[pc] < lineNumber) 6749 pc++; 6750 this.pc = pc; 6751 boolean saveLoadCheck = isCmdLine_C_Option; 6752 isCmdLine_C_Option &= loadCheck; 6753 executionStepping |= doStep; 6754 6755 if (contextVariables == null) 6756 contextVariables = new Hashtable<String, SV>(); 6757 contextVariables.put("_arguments", 6758 (params == null ? SV.getVariableAI(new int[] {}) 6759 : SV.getVariableList(params))); 6760 contextVariables.put("_argcount", 6761 SV.newI(params == null ? 0 : params.size())); 6762 6763 if (isCheck) 6764 listCommands = true; 6765 boolean timeMsg = vwr.getBoolean(T.showtiming); 6766 if (timeMsg) 6767 Logger.startTimer("script"); 6768 privateFuncs = null; 6769 dispatchCommands(false, false, false); 6770 if (isStateScript) 6771 ScriptManager.setStateScriptVersion(vwr, null); 6772 if (timeMsg) 6773 showString(Logger.getTimerMsg("script", 0)); 6774 isCmdLine_C_Option = saveLoadCheck; 6775 popContext(false, false); 6776 } else { 6777 Logger.error(GT.$("script ERROR: ") + errorMessage); 6778 popContext(false, false); 6779 if (wasScriptCheck) { 6780 setErrorMessage(null); 6781 } else { 6782 evalError(null, null); 6783 } 6784 } 6785 6786 chk = wasSyntaxCheck; 6787 isCmdLine_c_or_C_Option = wasScriptCheck; 6788 } 6789 cmdSelect(int i)6790 private void cmdSelect(int i) throws ScriptException { 6791 // NOTE this is called by restrict() 6792 if (slen == 1) { 6793 vwr.select(null, false, 0, !doReport()); 6794 return; 6795 } 6796 if (slen == 2 && tokAt(1) == T.only) 6797 return; // coming from "cartoon only" 6798 // select beginexpr none endexpr 6799 int tok = tokAt(2); 6800 vwr.slm.noneSelected = Boolean.valueOf(slen == 4 && tok == T.none); 6801 BS bs = null; 6802 switch (tok) { 6803 case T.bitset: 6804 // select beginexpr bonds ( {...} ) endex pr 6805 if (getToken(2).value instanceof BondSet || tokAt(2) == T.bonds 6806 && getToken(3).tok == T.bitset) { 6807 if (slen != iToken + 2) 6808 invArg(); 6809 if (!chk) 6810 vwr.selectBonds((BS) theToken.value); 6811 return; 6812 } 6813 break; 6814 case T.measure: 6815 case T.bonds: 6816 if (slen == 5 && tokAt(3) == T.bitset) { 6817 bs = (BS) getToken(3).value; 6818 iToken++; 6819 } else if (isArrayParameter(4)) { 6820 bs = new BS(); 6821 // 0-based here, to conform with getProperty measurementInfo.index 6822 int[] a = (int[]) expandFloatArray(floatParameterSet(4, 0, 6823 Integer.MAX_VALUE), 0, false); 6824 for (int ii = a.length; --ii >= 0;) 6825 if (a[ii] >= 0) 6826 bs.set(a[ii]); 6827 } 6828 checkLast(iToken); 6829 if (chk) 6830 return; 6831 if (bs == null) 6832 invArg(); 6833 if (tok == T.measure) 6834 setShapeProperty(JC.SHAPE_MEASURES, "select", bs); 6835 else 6836 vwr.selectBonds(bs); 6837 return; 6838 } 6839 6840 int addRemove = 0; 6841 boolean isGroup = false; 6842 if (getToken(1).intValue == 0 && theTok != T.off) { 6843 Object v = parameterExpressionToken(0).value; 6844 if (!(v instanceof BS)) 6845 invArg(); 6846 checkLast(iToken); 6847 bs = (BS) v; 6848 } else { 6849 tok = tokAt(i); 6850 switch (tok) { 6851 case T.on: 6852 case T.off: 6853 if (!chk) 6854 vwr.setSelectionHalosEnabled(tok == T.on); 6855 tok = tokAt(++i); 6856 if (tok == T.nada) 6857 return; 6858 break; 6859 } 6860 switch (tok) { 6861 case T.add: 6862 case T.remove: 6863 addRemove = tok; 6864 tok = tokAt(++i); 6865 } 6866 isGroup = (tok == T.group); 6867 if (isGroup) 6868 tok = tokAt(++i); 6869 bs = atomExpressionAt(i); 6870 } 6871 if (chk) 6872 return; 6873 if (isBondSet) { 6874 vwr.selectBonds(bs); 6875 } else { 6876 if (bs.length() > vwr.ms.ac) { 6877 BS bs1 = vwr.getAllAtoms(); 6878 bs1.and(bs); 6879 bs = bs1; 6880 } 6881 vwr.select(bs, isGroup, addRemove, !doReport()); 6882 } 6883 } 6884 cmdSelectionHalos(int pt)6885 private void cmdSelectionHalos(int pt) throws ScriptException { 6886 boolean showHalo = false; 6887 switch (pt == slen ? T.on : getToken(pt).tok) { 6888 case T.on: 6889 case T.selected: 6890 showHalo = true; 6891 //$FALL-THROUGH$ 6892 case T.off: 6893 case T.none: 6894 case T.normal: 6895 setBooleanProperty("selectionHalos", showHalo); 6896 break; 6897 default: 6898 invArg(); 6899 } 6900 } 6901 cmdSet()6902 private void cmdSet() throws ScriptException { 6903 /* 6904 * The SET command now allows only the following: 6905 * 6906 * SET SET xxx? SET [valid Jmol Token.setparam keyword] SET labelxxxx SET 6907 * xxxxCallback 6908 * 6909 * All other variables must be assigned using 6910 * 6911 * x = .... 6912 * 6913 * The processing goes as follows: 6914 * 6915 * check for SET check for SET xx? check for SET xxxx where xxxx is a 6916 * command --- deprecated (all other settings may alternatively start with x 6917 * = y) check for SET xxxx where xxxx requires special checking (all other 6918 * settings may alternatively start with x = (math expression) check for 6919 * context variables var x = ... check for deprecated SET words such as 6920 * "radius" 6921 */ 6922 if (slen == 1) { 6923 showString(vwr.getAllSettings(null)); 6924 return; 6925 } 6926 boolean isJmolSet = (paramAsStr(0).equals("set")); 6927 String key = optParameterAsString(1); 6928 if (isJmolSet && slen == 2 && key.indexOf("?") >= 0) { 6929 showString(vwr.getAllSettings(key.substring(0, key.indexOf("?")))); 6930 return; 6931 } 6932 int tok = getToken(1).tok; 6933 6934 int newTok = 0; 6935 String sval; 6936 int ival = Integer.MAX_VALUE; 6937 boolean b; 6938 P3 pt; 6939 6940 boolean showing = (!chk && doReport() 6941 && !((String) st[0].value).equals("var")); 6942 6943 // THESE FIRST ARE DEPRECATED AND HAVE THEIR OWN COMMAND 6944 // anything in this block MUST RETURN 6945 6946 switch (tok) { 6947 case T.historylevel: 6948 case T.iskiosk: 6949 case T.saveproteinstructurestate: 6950 case T.showkeystrokes: 6951 case T.testflag1: 6952 case T.testflag2: 6953 case T.testflag3: 6954 case T.testflag4: 6955 case T.useminimizationthread: 6956 // these might be set in older state scripts, but they should not have been there 6957 if (isStateScript) 6958 return; 6959 break; 6960 case T.axes: 6961 cmdAxes(2); 6962 return; 6963 case T.background: 6964 cmdBackground(2); 6965 return; 6966 case T.boundbox: 6967 cmdBoundbox(2); 6968 return; 6969 case T.frank: 6970 cmdFrank(2); 6971 return; 6972 case T.history: 6973 cmdHistory(2); 6974 return; 6975 case T.label: 6976 cmdLabel(2, null); 6977 return; 6978 case T.unitcell: 6979 cmdUnitcell(2); 6980 return; 6981 case T.highlight: 6982 sm.loadShape(JC.SHAPE_HALOS); 6983 setShapeProperty(JC.SHAPE_HALOS, "highlight", 6984 (tokAt(2) == T.off ? null : atomExpressionAt(2))); 6985 return; 6986 case T.display:// deprecated 6987 case T.selectionhalos: 6988 cmdSelectionHalos(2); 6989 return; 6990 case T.timeout: 6991 cmdTimeout(2); 6992 return; 6993 6994 // THESE HAVE MULTIPLE CONTEXTS AND 6995 // SO DO NOT ALLOW CALCULATIONS xxx = a + b... 6996 // and are thus "setparam" only 6997 // anything in this block MUST RETURN 6998 case T.window: 6999 Object o = (isArrayParameter(2) ? floatParameterSet(2, 2, 2) 7000 : tokAt(2) == T.integer 7001 ? new float[] { intParameter(2), intParameter(3) } 7002 : stringParameter(2)); 7003 checkLast(iToken); 7004 if (chk) 7005 return; 7006 if (o instanceof String) { 7007 if (vwr.fm.loadImage(o, "\0windowImage", !useThreads())) 7008 throw new ScriptInterruption(this, "windowImage", 1); 7009 } else { 7010 vwr.setWindowDimensions((float[]) o); 7011 } 7012 return; 7013 case T.structure: 7014 STR type = STR.getProteinStructureType(paramAsStr(2)); 7015 if (type == STR.NOT) 7016 invArg(); 7017 float[] data = floatParameterSet(3, 0, Integer.MAX_VALUE); 7018 if (data.length % 4 != 0) 7019 invArg(); 7020 vwr.setStructureList(data, type); 7021 checkLast(iToken); 7022 return; 7023 case T.axescolor: 7024 ival = getArgbParam(2); 7025 if (!chk) 7026 setObjectArgb("axes", ival); 7027 return; 7028 case T.bondmode: 7029 b = false; 7030 switch (getToken(checkLast(2)).tok) { 7031 case T.opAnd: 7032 break; 7033 case T.opOr: 7034 b = true; 7035 break; 7036 default: 7037 invArg(); 7038 } 7039 setBooleanProperty("bondModeOr", b); 7040 return; 7041 case T.debug: 7042 case T.debughigh: 7043 if (chk) 7044 return; 7045 int iLevel = (tokAt(2) == T.off 7046 || tokAt(2) == T.integer && intParameter(2) == 0 ? 4 7047 : (tok == T.debughigh ? 6 : 5)); 7048 Logger.setLogLevel(iLevel); 7049 setIntProperty("logLevel", iLevel); 7050 if (iLevel == 4) { 7051 vwr.setDebugScript(false); 7052 if (showing) 7053 vwr.showParameter("debugScript", true, 80); 7054 } 7055 setDebugging(); 7056 if (showing) 7057 vwr.showParameter("logLevel", true, 80); 7058 return; 7059 case T.echo: 7060 cmdSetEcho(); 7061 return; 7062 case T.fontsize: 7063 cmdFont(JC.SHAPE_LABELS, checkLength23() == 2 ? 0 : floatParameter(2)); 7064 return; 7065 case T.hbond: 7066 boolean bool = false; 7067 switch (tokAt(checkLast(2))) { 7068 case T.backbone: 7069 bool = true; 7070 //$FALL-THROUGH$ 7071 case T.sidechain: 7072 setBooleanProperty("hbondsBackbone", bool); 7073 break; 7074 case T.solid: 7075 bool = true; 7076 //$FALL-THROUGH$ 7077 case T.dotted: 7078 setBooleanProperty("hbondsSolid", bool); 7079 break; 7080 default: 7081 invArg(); 7082 } 7083 return; 7084 case T.measure: 7085 case T.measurements: 7086 // on off here incompatible with "monitor on/off" so this is just a SET 7087 // option. 7088 switch (tok = tokAt(checkLast(2))) { 7089 case T.on: 7090 case T.off: 7091 setBooleanProperty("measurementlabels", tok == T.on); 7092 return; 7093 case T.dotted: 7094 case T.integer: 7095 case T.decimal: 7096 vwr.shm.loadShape(JC.SHAPE_MEASURES); 7097 int mad10 = getSetAxesTypeMad10(2); 7098 if (mad10 != Integer.MAX_VALUE) 7099 setShapeSizeBs(JC.SHAPE_MEASURES, 7100 tok == T.decimal ? mad10 / 10 : mad10, null); 7101 return; 7102 } 7103 setUnits(paramAsStr(2), T.measurementunits); 7104 return; 7105 case T.ssbond: // ssBondsBackbone 7106 b = false; 7107 // shapeManager.loadShape(JmolConstants.SHAPE_SSSTICKS); 7108 switch (tokAt(checkLast(2))) { 7109 case T.backbone: 7110 b = true; 7111 break; 7112 case T.sidechain: 7113 break; 7114 default: 7115 invArg(); 7116 } 7117 setBooleanProperty("ssbondsBackbone", b); 7118 return; 7119 case T.togglelabel: 7120 cmdSetLabel("toggle"); 7121 return; 7122 case T.usercolorscheme: 7123 Lst<Integer> v = new Lst<Integer>(); 7124 for (int i = 2; i < slen; i++) { 7125 int argb = getArgbParam(i); 7126 v.addLast(Integer.valueOf(argb)); 7127 i = iToken; 7128 } 7129 if (chk) 7130 return; 7131 int n = v.size(); 7132 int[] scale = new int[n]; 7133 for (int i = n; --i >= 0;) 7134 scale[i] = v.get(i).intValue(); 7135 vwr.cm.ce.setUserScale(scale); 7136 return; 7137 case T.zslab: 7138 // sets zSlab either based on a percent value or an atom position 7139 if (isFloatParameter(2)) { 7140 checkLength(3); 7141 setIntProperty("zSlab", (int) floatParameter(2)); 7142 pt = null; 7143 } else { 7144 if (!isCenterParameter(2)) 7145 invArg(); 7146 pt = centerParameter(2, null); 7147 checkLength(iToken + 1); 7148 } 7149 if (!chk) 7150 vwr.tm.zSlabPoint = (pt == null ? null : P3.newP(pt)); 7151 return; 7152 } 7153 7154 boolean justShow = true; 7155 7156 // these next may just report a value 7157 // require special checks 7158 // math expressions are allowed in most cases using xxxSetting(...) 7159 7160 switch (tok) { 7161 case T.backgroundmodel: 7162 if (slen > 2) { 7163 String modelDotted = getSettingStr(2, false); 7164 int modelNumber; 7165 boolean useModelNumber = false; 7166 if (modelDotted.indexOf(".") < 0) { 7167 modelNumber = PT.parseInt(modelDotted); 7168 useModelNumber = true; 7169 } else { 7170 modelNumber = getFloatEncodedInt(modelDotted); 7171 } 7172 if (chk) 7173 return; 7174 int modelIndex = vwr.ms.getModelNumberIndex(modelNumber, useModelNumber, 7175 true); 7176 vwr.setBackgroundModelIndex(modelIndex); 7177 return; 7178 } 7179 break; 7180 case T.vanderwaals: 7181 if (chk) 7182 return; 7183 vwr.setAtomProperty(vwr.getAllAtoms(), T.vanderwaals, -1, Float.NaN, null, 7184 null, null); 7185 if (slen > 2 && "probe".equalsIgnoreCase(getSettingStr(2, false))) { 7186 runScript(Elements.VdwPROBE); 7187 return; 7188 } 7189 newTok = T.defaultvdw; 7190 //$FALL-THROUGH$ 7191 case T.defaultvdw: 7192 // allows unquoted string for known vdw type 7193 if (slen > 2) { 7194 sval = paramAsStr(2); 7195 if (slen == 3 && VDW.getVdwType(sval) == null 7196 && VDW.getVdwType(sval = getSettingStr(2, false)) == null) 7197 invArg(); 7198 setStringProperty(key, sval); 7199 } 7200 break; 7201 case T.defaultlattice: 7202 // in very early versions of Jmol we might 7203 // have accepted string "{1.0,2.0,3.0}" here, 7204 // but that is at least before 11.8. 7205 // shouldn't be saving this in the state anyway. 7206 7207 if (slen > 2) { 7208 SV var = parameterExpressionToken(2); 7209 if (var.tok == T.point3f) 7210 pt = (P3) var.value; 7211 else { 7212 pt = new P3(); 7213 int ijk = var.asInt(); 7214 if (ijk >= 100) 7215 SimpleUnitCell.ijkToPoint3f(ijk, pt, -1, 0); 7216 } 7217 if (!chk) 7218 vwr.setDefaultLattice(pt); 7219 } 7220 break; 7221 case T.defaults: 7222 case T.defaultcolorscheme: 7223 // allows unquoted "jmol" or "rasmol" 7224 if (slen > 2) { 7225 if ((theTok = tokAt(2)) == T.jmol || theTok == T.rasmol) { 7226 sval = paramAsStr(checkLast(2)); 7227 } else { 7228 sval = getSettingStr(2, false); 7229 } 7230 setStringProperty(key, sval); 7231 } 7232 break; 7233 case T.formalcharge: 7234 ival = getSettingInt(2); 7235 if (ival == Integer.MIN_VALUE) 7236 invArg(); 7237 if (!chk) 7238 vwr.ms.setFormalCharges(vwr.bsA(), ival); 7239 return; 7240 case T.language: 7241 // language can be used without quotes in a SET context 7242 // set language en 7243 if (slen > 2) 7244 setStringProperty(key, getSettingStr(2, isJmolSet)); 7245 break; 7246 case T.measurementunits: 7247 case T.energyunits: 7248 if (slen > 2) 7249 setUnits(getSettingStr(2, isJmolSet), tok); 7250 break; 7251 case T.picking: 7252 if (!chk) 7253 vwr.setPicked(-1, false); 7254 if (slen > 2) { 7255 cmdSetPicking(); 7256 return; 7257 } 7258 break; 7259 case T.pickingstyle: 7260 if (slen > 2) { 7261 cmdSetPickingStyle(); 7262 return; 7263 } 7264 break; 7265 case T.property: // compiler may give different values to this token 7266 // set property_xxxx will be handled in setVariable 7267 break; 7268 case T.specular: 7269 ival = getSettingInt(2); 7270 if (ival == Integer.MIN_VALUE || ival == 0 || ival == 1) { 7271 justShow = false; 7272 break; 7273 } 7274 tok = T.specularpercent; 7275 key = "specularPercent"; 7276 setIntProperty(key, ival); 7277 break; 7278 case T.strands: 7279 tok = T.strandcount; 7280 key = "strandCount"; 7281 setIntProperty(key, getSettingInt(2)); 7282 break; 7283 default: 7284 justShow = false; 7285 } 7286 7287 if (justShow && !showing) 7288 return; 7289 7290 // var xxxx = xxx can supercede set xxxx 7291 7292 boolean isContextVariable = (!justShow && !isJmolSet 7293 && getContextVariableAsVariable(key, false) != null); 7294 7295 if (!justShow && !isContextVariable) { 7296 7297 // THESE NEXT are deprecated: 7298 7299 switch (tok) { 7300 case T.bonds: 7301 newTok = T.showmultiplebonds; 7302 break; 7303 case T.hetero: 7304 newTok = T.selecthetero; 7305 break; 7306 case T.hydrogen: 7307 newTok = T.selecthydrogen; 7308 break; 7309 case T.measurementnumbers: 7310 newTok = T.measurementlabels; 7311 break; 7312 case T.radius: 7313 newTok = T.solventproberadius; 7314 setFloatProperty("solventProbeRadius", getSettingFloat(2)); 7315 justShow = true; 7316 break; 7317 case T.scale3d: 7318 newTok = T.scaleangstromsperinch; 7319 break; 7320 case T.solvent: 7321 newTok = T.solventprobe; 7322 break; 7323 case T.color: 7324 newTok = T.defaultcolorscheme; 7325 break; 7326 case T.spin: 7327 sval = paramAsStr(2).toLowerCase(); 7328 switch ("x;y;z;fps;".indexOf(sval + ";")) { 7329 case 0: 7330 newTok = T.spinx; 7331 break; 7332 case 2: 7333 newTok = T.spiny; 7334 break; 7335 case 4: 7336 newTok = T.spinz; 7337 break; 7338 case 6: 7339 newTok = T.spinfps; 7340 break; 7341 default: 7342 errorStr2(ERROR_unrecognizedParameter, "set SPIN ", sval); 7343 } 7344 if (!chk) 7345 vwr.setSpin(sval, (int) floatParameter(checkLast(3))); 7346 justShow = true; 7347 break; 7348 } 7349 } 7350 7351 if (newTok != 0) { 7352 key = T.nameOf(tok = newTok); 7353 } else if (!justShow && !isContextVariable) { 7354 // special cases must be checked 7355 if (key.length() == 0 || key.charAt(0) == '_' && tokAt(2) != T.leftsquare) // these cannot be set by user 7356 error(ERROR_cannotSet); 7357 7358 // these next are not reported and do not allow calculation xxxx = a + b 7359 7360 String lckey = key.toLowerCase(); 7361 if (lckey.indexOf("label") == 0 && PT.isOneOf(lckey.substring(5), 7362 ";front;group;atom;offset;offsetexact;offsetabsolute;pointer;alignment;toggle;scalereference;for;")) { 7363 if (cmdSetLabel(lckey.substring(5))) 7364 return; 7365 } 7366 if (isJmolSet && lckey.indexOf("shift_") == 0) { 7367 float f = floatParameter(2); 7368 checkLength(3); 7369 if (!chk) 7370 vwr.getNMRCalculation().setChemicalShiftReference(lckey.substring(6), 7371 f); 7372 return; 7373 } 7374 if (lckey.endsWith("callback")) 7375 tok = T.setparam; 7376 } 7377 if (isJmolSet && !T.tokAttr(tok, T.setparam)) { 7378 iToken = 1; 7379 if (!isStateScript) 7380 errorStr2(ERROR_unrecognizedParameter, "SET", key); 7381 warning(ERROR_unrecognizedParameterWarning, "SET", key); 7382 } 7383 7384 if (!justShow && isJmolSet) { 7385 // simple cases 7386 switch (slen) { 7387 case 2: 7388 // set XXXX; 7389 // too bad we allow this... 7390 setBooleanProperty(key, true); 7391 justShow = true; 7392 break; 7393 case 3: 7394 // set XXXX val; 7395 // check for int and NONE just in case 7396 if (ival != Integer.MAX_VALUE) { 7397 // keep it simple 7398 setIntProperty(key, ival); 7399 justShow = true; 7400 } 7401 break; 7402 } 7403 } 7404 7405 if (!justShow && !isJmolSet && tokAt(2) == T.none) { 7406 if (!chk) 7407 vwr.removeUserVariable(key.toLowerCase()); 7408 justShow = true; 7409 } 7410 if (!justShow) { 7411 setVariable(1, 0, key, true); 7412 if (!isJmolSet) 7413 return; 7414 } 7415 if (showing) 7416 vwr.showParameter(key, true, 80); 7417 } 7418 cmdSetEcho()7419 private void cmdSetEcho() throws ScriptException { 7420 String propertyName = null; 7421 Object propertyValue = null; 7422 String id = null; 7423 boolean echoShapeActive = true; 7424 // set echo xxx 7425 int pt = 2; 7426 7427 // check for ID name or just name 7428 // also check simple OFF, NONE 7429 switch (getToken(2).tok) { 7430 case T.off: 7431 id = propertyName = "allOff"; 7432 checkLength(++pt); 7433 break; 7434 case T.none: 7435 echoShapeActive = false; 7436 //$FALL-THROUGH$ 7437 case T.all: 7438 // all and none get NO additional parameters; 7439 id = paramAsStr(2); 7440 checkLength(++pt); 7441 break; 7442 case T.left: 7443 case T.center: 7444 case T.right: 7445 case T.top: 7446 case T.middle: 7447 case T.bottom: 7448 case T.identifier: 7449 case T.string: 7450 case T.id: 7451 if (theTok == T.id) 7452 pt++; 7453 id = paramAsStr(pt++); 7454 break; 7455 } 7456 7457 if (!chk) { 7458 vwr.ms.setEchoStateActive(echoShapeActive); 7459 sm.loadShape(JC.SHAPE_ECHO); 7460 if (id != null) 7461 setShapeProperty(JC.SHAPE_ECHO, propertyName == null ? "target" 7462 : propertyName, id); 7463 } 7464 7465 if (pt < slen) { 7466 // set echo name xxx 7467 // pt is usually 3, but could be 4 if ID used 7468 switch (getToken(pt++).tok) { 7469 case T.align: 7470 propertyName = "align"; 7471 switch (getToken(pt).tok) { 7472 case T.left: 7473 case T.right: 7474 case T.center: 7475 propertyValue = paramAsStr(pt++); 7476 break; 7477 default: 7478 invArg(); 7479 } 7480 break; 7481 case T.center: 7482 case T.left: 7483 case T.right: 7484 propertyName = "align"; 7485 propertyValue = paramAsStr(pt - 1); 7486 break; 7487 case T.depth: 7488 propertyName = "%zpos"; 7489 propertyValue = Integer.valueOf((int) floatParameter(pt++)); 7490 break; 7491 case T.display: 7492 case T.displayed: 7493 case T.on: 7494 propertyName = "hidden"; 7495 propertyValue = Boolean.FALSE; 7496 break; 7497 case T.hide: 7498 case T.hidden: 7499 propertyName = "hidden"; 7500 propertyValue = Boolean.TRUE; 7501 break; 7502 case T.model: 7503 int modelIndex = (chk ? 0 : modelNumberParameter(pt++)); 7504 if (modelIndex >= vwr.ms.mc) 7505 invArg(); 7506 propertyName = "model"; 7507 propertyValue = Integer.valueOf(modelIndex); 7508 break; 7509 case T.leftsquare: 7510 case T.spacebeforesquare: 7511 // [ x y ] with or without % 7512 propertyName = "xypos"; 7513 propertyValue = xypParameter(--pt); 7514 if (propertyValue == null) 7515 invArg(); 7516 pt = iToken + 1; 7517 break; 7518 case T.integer: 7519 // x y without brackets 7520 int posx = intParameter(pt - 1); 7521 String namex = "xpos"; 7522 if (tokAt(pt) == T.percent) { 7523 namex = "%xpos"; 7524 pt++; 7525 } 7526 propertyName = "ypos"; 7527 propertyValue = Integer.valueOf(intParameter(pt++)); 7528 if (tokAt(pt) == T.percent) { 7529 propertyName = "%ypos"; 7530 pt++; 7531 } 7532 checkLength(pt); 7533 setShapeProperty(JC.SHAPE_ECHO, namex, Integer.valueOf(posx)); 7534 break; 7535 case T.offset: 7536 propertyName = "offset"; 7537 if (isPoint3f(pt)) { 7538 P3 pt3 = getPoint3f(pt, false, true); 7539 // minus 1 here means from Jmol, not from PyMOL 7540 propertyValue = new float[] { -1, pt3.x, pt3.y, pt3.z, 0, 0, 0 }; 7541 pt = iToken + 1; 7542 } else if (isArrayParameter(pt)) { 7543 // PyMOL offsets -- [1, scrx, scry, scrz, molx, moly, molz] in angstroms 7544 propertyValue = floatParameterSet(pt, 7, 7); 7545 pt = iToken + 1; 7546 } 7547 break; 7548 case T.off: 7549 propertyName = "off"; 7550 break; 7551 case T.scale: 7552 propertyName = "scale"; 7553 propertyValue = Float.valueOf(floatParameter(pt++)); 7554 break; 7555 case T.script: 7556 propertyName = "script"; 7557 propertyValue = paramAsStr(pt++); 7558 break; 7559 case T.image: 7560 pt++; 7561 //$FALL-THROUGH$ 7562 case T.string: 7563 boolean isImage = (theTok != T.string); 7564 checkLength(pt--); 7565 if (isImage) { 7566 if (id == null) { 7567 String[] data = new String[1]; 7568 getShapePropertyData(JC.SHAPE_ECHO, "currentTarget", data); 7569 id = data[0]; 7570 } 7571 if (!chk && vwr.ms.getEchoStateActive() 7572 && vwr.fm.loadImage(getToken(pt).value, id, !useThreads())) 7573 throw new ScriptInterruption(this, "setEchoImage", 1); 7574 return; 7575 } 7576 cmdEcho(pt); 7577 return; 7578 case T.point: 7579 propertyName = "point"; 7580 propertyValue = (isCenterParameter(pt) ? centerParameter(pt, null) 7581 : null); 7582 pt = iToken + 1; 7583 break; 7584 default: 7585 if (isCenterParameter(pt - 1)) { 7586 propertyName = "xyz"; 7587 propertyValue = centerParameter(pt - 1, null); 7588 pt = iToken + 1; 7589 break; 7590 } 7591 invArg(); 7592 } 7593 } 7594 checkLength(pt); 7595 if (!chk && propertyName != null) 7596 setShapeProperty(JC.SHAPE_ECHO, propertyName, propertyValue); 7597 } 7598 cmdSetLabel(String str)7599 private boolean cmdSetLabel(String str) throws ScriptException { 7600 sm.loadShape(JC.SHAPE_LABELS); 7601 Object propertyValue = null; 7602 setShapeProperty(JC.SHAPE_LABELS, "setDefaults", vwr.slm.noneSelected); 7603 while (true) { 7604 if (str.equals("for")) { 7605 BS bs = atomExpressionAt(2); 7606 cmdLabel(iToken + 1, bs); 7607 return true; 7608 } 7609 if (str.equals("scalereference")) { 7610 float scaleAngstromsPerPixel = floatParameter(2); 7611 if (scaleAngstromsPerPixel >= 5) // actually a zoom value 7612 scaleAngstromsPerPixel = vwr.tm.getZoomSetting() 7613 / scaleAngstromsPerPixel / vwr.getScalePixelsPerAngstrom(false); 7614 propertyValue = Float.valueOf(scaleAngstromsPerPixel); 7615 break; 7616 } 7617 boolean isAbsolute = false; 7618 if (str.equals("offset") || (isAbsolute = (str.equals("offsetabsolute") || str.equals("offsetexact")))) { 7619 str = "offset"; 7620 if (isPoint3f(2)) { 7621 // PyMOL offsets -- {x, y, z} in angstroms 7622 P3 pt = getPoint3f(2, false, true); 7623 // minus 1 here means from Jmol, not from PyMOL 7624 propertyValue = new float[] { -1, pt.x, pt.y, pt.z, 0, 0, 0 }; 7625 } else if (isArrayParameter(2)) { 7626 // PyMOL offsets -- [1, scrx, scry, scrz, molx, moly, molz] in angstroms 7627 propertyValue = floatParameterSet(2, 7, 7); 7628 } else { 7629 int xOffset = intParameterRange(2, -JC.LABEL_OFFSET_MAX, JC.LABEL_OFFSET_MAX); 7630 int yOffset = intParameterRange(3, -JC.LABEL_OFFSET_MAX, JC.LABEL_OFFSET_MAX); 7631 if (xOffset == Integer.MAX_VALUE || yOffset == Integer.MAX_VALUE) 7632 return true; 7633 propertyValue = Integer.valueOf(JC.getOffset(xOffset, yOffset, isAbsolute)); 7634 } 7635 break; 7636 } 7637 if (str.equals("alignment")) { 7638 switch (getToken(2).tok) { 7639 case T.left: 7640 case T.right: 7641 case T.center: 7642 str = "align"; 7643 propertyValue = theToken.value; 7644 break; 7645 default: 7646 invArg(); 7647 } 7648 break; 7649 } 7650 if (str.equals("pointer")) { 7651 int flags = JC.LABEL_POINTER_NONE; 7652 switch (getToken(2).tok) { 7653 case T.off: 7654 case T.none: 7655 break; 7656 case T.background: 7657 flags |= JC.LABEL_POINTER_BACKGROUND; 7658 //$FALL-THROUGH$ 7659 case T.on: 7660 flags |= JC.LABEL_POINTER_ON; 7661 break; 7662 default: 7663 invArg(); 7664 } 7665 propertyValue = Integer.valueOf(flags); 7666 break; 7667 } 7668 if (str.equals("toggle")) { 7669 iToken = 1; 7670 BS bs = (slen == 2 ? vwr.bsA() : atomExpressionAt(2)); 7671 checkLast(iToken); 7672 if (chk) 7673 return true; 7674 vwr.shm.loadShape(JC.SHAPE_LABELS); 7675 vwr.shm.setShapePropertyBs(JC.SHAPE_LABELS, "toggleLabel", null, bs); 7676 return true; 7677 } 7678 iToken = 1; 7679 boolean TF = (slen == 2 || getToken(2).tok == T.on); 7680 if (str.equals("front") || str.equals("group")) { 7681 if (!TF && tokAt(2) != T.off) 7682 invArg(); 7683 if (!TF) 7684 str = "front"; 7685 propertyValue = (TF ? Boolean.TRUE : Boolean.FALSE); 7686 break; 7687 } 7688 if (str.equals("atom")) { 7689 if (!TF && tokAt(2) != T.off) 7690 invArg(); 7691 str = "front"; 7692 propertyValue = (TF ? Boolean.FALSE : Boolean.TRUE); 7693 break; 7694 } 7695 return false; 7696 } 7697 BS bs = (iToken + 1 < slen ? atomExpressionAt(++iToken) : null); 7698 checkLast(iToken); 7699 if (chk) 7700 return true; 7701 if (bs == null) 7702 setShapeProperty(JC.SHAPE_LABELS, str, propertyValue); 7703 else 7704 setShapePropertyBs(JC.SHAPE_LABELS, str, propertyValue, bs); 7705 return true; 7706 } 7707 cmdSetPicking()7708 private void cmdSetPicking() throws ScriptException { 7709 // set picking 7710 if (slen == 2) { 7711 setStringProperty("picking", "identify"); 7712 return; 7713 } 7714 // set picking @{"xxx"} or some large length, ignored 7715 if (slen > 4 || tokAt(2) == T.string) { 7716 setStringProperty("picking", getSettingStr(2, false)); 7717 return; 7718 } 7719 int i = 2; 7720 // set picking select ATOM|CHAIN|GROUP|MOLECULE|MODEL|SITE 7721 // set picking measure ANGLE|DISTANCE|TORSION 7722 // set picking spin fps 7723 String type = "SELECT"; 7724 switch (getToken(2).tok) { 7725 case T.select: 7726 case T.measure: 7727 case T.spin: 7728 if (checkLength34() == 4) { 7729 type = paramAsStr(2).toUpperCase(); 7730 if (type.equals("SPIN")) 7731 setIntProperty("pickingSpinRate", intParameter(3)); 7732 else 7733 i = 3; 7734 } 7735 break; 7736 case T.delete: 7737 break; 7738 default: 7739 checkLength(3); 7740 } 7741 7742 // set picking on 7743 // set picking normal 7744 // set picking identify 7745 // set picking off 7746 // set picking select 7747 // set picking bonds 7748 // set picking dragmolecule 7749 // set picking dragmodel 7750 // set picking dragselected 7751 7752 String str = paramAsStr(i); 7753 switch (getToken(i).tok) { 7754 case T.on: 7755 case T.normal: 7756 str = "identify"; 7757 break; 7758 case T.off: 7759 case T.none: 7760 str = "off"; 7761 break; 7762 case T.select: 7763 str = "atom"; 7764 break; 7765 case T.label: 7766 str = "label"; 7767 break; 7768 case T.bonds: // not implemented 7769 str = "bond"; 7770 break; 7771 case T.delete: 7772 checkLength(4); 7773 if (tokAt(3) != T.bonds) 7774 invArg(); 7775 str = "deleteBond"; 7776 break; 7777 } 7778 int mode = ((mode = str.indexOf("_")) >= 0 ? mode : str.length()); 7779 mode = ActionManager.getPickingMode(str.substring(0, mode)); 7780 if (mode < 0) 7781 errorStr2(ERROR_unrecognizedParameter, "SET PICKING " + type, str); 7782 setStringProperty("picking", str); 7783 } 7784 cmdSetPickingStyle()7785 private void cmdSetPickingStyle() throws ScriptException { 7786 if (slen > 4 || tokAt(2) == T.string) { 7787 setStringProperty("pickingStyle", getSettingStr(2, false)); 7788 return; 7789 } 7790 int i = 2; 7791 boolean isMeasure = false; 7792 String type = "SELECT"; 7793 switch (getToken(2).tok) { 7794 case T.measure: 7795 isMeasure = true; 7796 type = "MEASURE"; 7797 //$FALL-THROUGH$ 7798 case T.select: 7799 if (checkLength34() == 4) 7800 i = 3; 7801 break; 7802 default: 7803 checkLength(3); 7804 } 7805 String str = paramAsStr(i); 7806 switch (getToken(i).tok) { 7807 case T.none: 7808 case T.off: 7809 str = (isMeasure ? "measureoff" : "toggle"); 7810 break; 7811 case T.on: 7812 if (isMeasure) 7813 str = "measure"; 7814 break; 7815 } 7816 if (ActionManager.getPickingStyleIndex(str) < 0) 7817 errorStr2(ERROR_unrecognizedParameter, "SET PICKINGSTYLE " + type, str); 7818 setStringProperty("pickingStyle", str); 7819 } 7820 cmdSlab(boolean isDepth)7821 private void cmdSlab(boolean isDepth) throws ScriptException { 7822 boolean TF = false; 7823 P4 plane = null; 7824 String str; 7825 if (isCenterParameter(1) || tokAt(1) == T.point4f) 7826 plane = planeParameter(1); 7827 else 7828 switch (getToken(1).tok) { 7829 case T.integer: 7830 int percent = intParameter(checkLast(1)); 7831 if (!chk) 7832 if (isDepth) 7833 vwr.tm.depthToPercent(percent); 7834 else 7835 vwr.tm.slabToPercent(percent); 7836 return; 7837 case T.on: 7838 TF = true; 7839 //$FALL-THROUGH$ 7840 case T.off: 7841 checkLength(2); 7842 setBooleanProperty("slabEnabled", TF); 7843 return; 7844 case T.reset: 7845 checkLength(2); 7846 if (chk) 7847 return; 7848 vwr.tm.slabReset(); 7849 setBooleanProperty("slabEnabled", true); 7850 return; 7851 case T.set: 7852 checkLength(2); 7853 if (!chk) 7854 vwr.tm.setSlabDepthInternal(isDepth); 7855 return; 7856 case T.minus: 7857 str = paramAsStr(2); 7858 if (str.equalsIgnoreCase("hkl")) 7859 plane = hklParameter(3, false); 7860 else if (str.equalsIgnoreCase("plane")) 7861 plane = planeParameter(2); 7862 if (plane == null) 7863 invArg(); 7864 plane.scale4(-1); 7865 break; 7866 case T.plane: 7867 switch (getToken(2).tok) { 7868 case T.none: 7869 break; 7870 default: 7871 plane = planeParameter(1); 7872 } 7873 break; 7874 case T.hkl: 7875 plane = (getToken(2).tok == T.none ? null : hklParameter(2, false)); 7876 break; 7877 case T.reference: 7878 // only in 11.2; deprecated 7879 return; 7880 default: 7881 invArg(); 7882 } 7883 if (!chk) 7884 vwr.tm.slabInternal(plane, isDepth); 7885 } 7886 7887 /* 7888 private void slice() throws ScriptException{ 7889 if(!chk && vwr.slicer==null){ 7890 vwr.createSlicer(); 7891 } 7892 int tok1 = getToken(1).tok; 7893 if(tok1==Token.left||tok1==Token.right){ 7894 switch (getToken(2).tok){ 7895 case Token.on: 7896 if(chk) return; 7897 vwr.slicer.drawSlicePlane(tok1, true); 7898 return; 7899 case Token.off: 7900 if(chk) return; 7901 vwr.slicer.drawSlicePlane(tok1, false); 7902 return; 7903 default: 7904 invArg(); 7905 break; 7906 } 7907 }else{//command to slice object, not show slice planes 7908 String name = (String)getToken(1).value; 7909 //TODO - should accept "all" for now "all" will fail silently. 7910 // Should check it is a valid isosurface name 7911 //Should be followed by two angles, and two percents (float values) 7912 float[] param = new float[4]; 7913 for (int i=2;i<6;++i){ 7914 if(getToken(i).tok == Token.decimal){ 7915 param[i-2]=floatParameter(i); 7916 } else{ 7917 invArg(); 7918 } 7919 } 7920 if(!chk){ 7921 vwr.slicer.setSlice(param[0], param[1], param[2], param[3]); 7922 vwr.slicer.sliceObject(name); 7923 } 7924 return; 7925 } 7926 } 7927 7928 */ 7929 cmdSsbond()7930 private void cmdSsbond() throws ScriptException { 7931 int mad = getMadParameter(); 7932 if (mad == Integer.MAX_VALUE) 7933 return; 7934 setShapeProperty(JC.SHAPE_STICKS, "type", 7935 Integer.valueOf(Edge.BOND_SULFUR_MASK)); 7936 setShapeSizeBs(JC.SHAPE_STICKS, mad, null); 7937 setShapeProperty(JC.SHAPE_STICKS, "type", 7938 Integer.valueOf(Edge.BOND_COVALENT_MASK)); 7939 } 7940 cmdStructure()7941 private void cmdStructure() throws ScriptException { 7942 STR type = STR 7943 .getProteinStructureType(paramAsStr(1)); 7944 if (type == STR.NOT) 7945 invArg(); 7946 BS bs = null; 7947 switch (tokAt(2)) { 7948 case T.define: 7949 case T.bitset: 7950 case T.expressionBegin: 7951 bs = atomExpressionAt(2); 7952 checkLast(iToken); 7953 break; 7954 default: 7955 checkLength(2); 7956 } 7957 if (chk) 7958 return; 7959 clearDefinedVariableAtomSets(); 7960 vwr.setProteinType(type, bs); 7961 } 7962 cmdSubset()7963 private void cmdSubset() throws ScriptException { 7964 BS bs = null; 7965 if (!chk) 7966 vwr.slm.setSelectionSubset(null); 7967 // hover none --> subset exprbeg "off" exprend 7968 if (slen != 1 && (slen != 4 || !getToken(2).value.equals("off"))) 7969 bs = atomExpressionAt(1); 7970 if (!chk) 7971 vwr.slm.setSelectionSubset(bs); 7972 } 7973 cmdSync()7974 private void cmdSync() throws ScriptException { 7975 // new 11.3.9 7976 String text = ""; 7977 String applet = ""; 7978 int port = PT.parseInt(optParameterAsString(1)); 7979 if (port == Integer.MIN_VALUE) { 7980 checkLength(-3); 7981 port = 0; 7982 switch (slen) { 7983 case 1: 7984 // sync 7985 applet = "*"; 7986 text = "ON"; 7987 break; 7988 case 2: 7989 // sync (*) text 7990 applet = paramAsStr(1); 7991 if (applet.indexOf("jmolApplet") == 0 7992 || PT.isOneOf(applet, ";*;.;^;")) { 7993 text = "ON"; 7994 if (!chk) 7995 vwr.syncScript(text, applet, 0); 7996 applet = "."; 7997 break; 7998 } 7999 text = applet; 8000 applet = "*"; 8001 break; 8002 case 3: 8003 // sync applet text 8004 // sync applet STEREO 8005 applet = paramAsStr(1); 8006 text = (tokAt(2) == T.stereo ? Viewer.SYNC_GRAPHICS_MESSAGE 8007 : paramAsStr(2)); 8008 break; 8009 } 8010 } else { 8011 SV v = null; 8012 if (slen > 2 && (v = setVariable(2, -1, "", false)) == null) 8013 return; 8014 text = (slen == 2 ? null : v.tok == T.hash ? v.toJSON() : v.asString()); 8015 applet = null; 8016 } 8017 if (chk) 8018 return; 8019 vwr.syncScript(text, applet, port); 8020 } 8021 cmdThrow()8022 private void cmdThrow() throws ScriptException { 8023 if (chk) 8024 return; 8025 int pt = (tokAt(1) == T.context ? 2 : 1); 8026 SV v = (pt == 1 ? setVariable(1, slen, "thrown_value", false) 8027 : vwr.g.setUserVariable("thrown_value", SV.newS(optParameterAsString(2)))); 8028 String info = v.asString(); 8029 if (info.length() == 0 && (info = optParameterAsString(1)).length() == 0) 8030 info = "context"; 8031 if (pt == 2) { 8032 saveContext(info); 8033 if (doReport()) 8034 report(GT.o(GT.$("to resume, enter: &{0}"), info), false); 8035 throw new ScriptInterruption(this, info, Integer.MIN_VALUE); 8036 } 8037 evalError(info, null); 8038 } 8039 saveContext(String saveName)8040 private ScriptContext saveContext(String saveName) { 8041 ScriptContext sc = getScriptContext("Context_" + saveName); 8042 vwr.stm.saveContext(saveName, sc); 8043 vwr.g.setUserVariable(saveName, SV.newV(T.context, sc)); 8044 return sc; 8045 } 8046 cmdTimeout(int index)8047 private void cmdTimeout(int index) throws ScriptException { 8048 // timeout ID "mytimeout" mSec "script" 8049 // msec < 0 --> repeat indefinitely 8050 // timeout ID "mytimeout" 1000 // milliseconds 8051 // timeout ID "mytimeout" 0.1 // seconds 8052 // timeout ID "mytimeout" OFF 8053 // timeout ID "mytimeout" // flag to trigger waiting timeout repeat 8054 // timeout OFF 8055 String name = null; 8056 String script = null; 8057 int mSec = 0; 8058 if (slen == index) { 8059 showString(vwr.showTimeout(null)); 8060 return; 8061 } 8062 for (int i = index; i < slen; i++) 8063 switch (getToken(i).tok) { 8064 case T.id: 8065 name = paramAsStr(++i); 8066 if (slen == 3) { 8067 if (!chk) 8068 vwr.triggerTimeout(name); 8069 return; 8070 } 8071 break; 8072 case T.off: 8073 break; 8074 case T.integer: 8075 mSec = intParameter(i); 8076 break; 8077 case T.decimal: 8078 mSec = Math.round(floatParameter(i) * 1000); 8079 break; 8080 default: 8081 if (name == null) 8082 name = paramAsStr(i); 8083 else if (script == null) 8084 script = paramAsStr(i); 8085 else 8086 invArg(); 8087 break; 8088 } 8089 if (!chk) 8090 vwr.setTimeout(name, mSec, script); 8091 } 8092 cmdTranslate(boolean isSelected)8093 private void cmdTranslate(boolean isSelected) throws ScriptException { 8094 // translate [selected] X|Y|Z x.x [NM|ANGSTROMS] 8095 // translate [selected] X|Y x.x% 8096 // translate [selected] {x y z} [{atomExpression}] 8097 BS bs = null; 8098 int i = 1; 8099 int i0 = 0; 8100 if (tokAt(1) == T.selected) { 8101 isSelected = true; 8102 i0 = 1; 8103 i = 2; 8104 } 8105 if (isPoint3f(i)) { 8106 P3 pt = getPoint3f(i, true, true); 8107 bs = (iToken + 1 < slen ? atomExpressionAt(++iToken) 8108 : null); 8109 checkLast(iToken); 8110 if (!chk) 8111 vwr.setAtomCoordsRelative(pt, bs); 8112 return; 8113 } 8114 char xyz = (paramAsStr(i).toLowerCase() + " ").charAt(0); 8115 if ("xyz".indexOf(xyz) < 0) 8116 error(ERROR_axisExpected); 8117 float amount = floatParameter(++i); 8118 char type; 8119 switch (tokAt(++i)) { 8120 case T.nada: 8121 case T.define: 8122 case T.bitset: 8123 case T.expressionBegin: 8124 type = '\0'; 8125 break; 8126 default: 8127 type = (optParameterAsString(i).toLowerCase() + '\0').charAt(0); 8128 } 8129 if (amount == 0 && type != '\0') 8130 return; 8131 iToken = i0 + (type == '\0' ? 2 : 3); 8132 bs = (isSelected ? vwr.bsA() 8133 : iToken + 1 < slen ? atomExpressionAt(++iToken) : null); 8134 checkLast(iToken); 8135 if (!chk) { 8136 vwr.translate(xyz, amount, type, bs); 8137 refresh(false); 8138 } 8139 } 8140 cmdUnbind()8141 private void cmdUnbind() throws ScriptException { 8142 /* 8143 * unbind "MOUSE-ACTION"|all ["...script..."|actionName|all] 8144 */ 8145 if (slen != 1) 8146 checkLength23(); 8147 String mouseAction = optParameterAsString(1); 8148 String name = optParameterAsString(2); 8149 if (mouseAction.length() == 0 || tokAt(1) == T.all) 8150 mouseAction = null; 8151 if (name.length() == 0 || tokAt(2) == T.all) 8152 name = null; 8153 if (name == null && mouseAction != null 8154 && ActionManager.getActionFromName(mouseAction) >= 0) { 8155 name = mouseAction; 8156 mouseAction = null; 8157 } 8158 if (!chk) 8159 vwr.unBindAction(mouseAction, name); 8160 } 8161 cmdUndoRedoMove()8162 private void cmdUndoRedoMove() throws ScriptException { 8163 // Jmol 12.1.46 8164 int n = 1; 8165 int len = 2; 8166 switch (tokAt(1)) { 8167 case T.nada: 8168 len = 1; 8169 break; 8170 case T.all: 8171 n = 0; 8172 break; 8173 case T.integer: 8174 n = intParameter(1); 8175 break; 8176 default: 8177 invArg(); 8178 } 8179 checkLength(len); 8180 if (!chk) 8181 vwr.undoMoveAction(tokAt(0), n); 8182 } 8183 setModelCagePts(int iModel, T3[] originABC, String name)8184 public void setModelCagePts(int iModel, T3[] originABC, String name) { 8185 if (iModel < 0) 8186 iModel = vwr.am.cmi; 8187 SymmetryInterface sym = Interface.getSymmetry(vwr, "eval"); 8188 if (sym == null && vwr.async) 8189 throw new NullPointerException(); 8190 try { 8191 vwr.ms.setModelCage(iModel, 8192 originABC == null ? null : sym.getUnitCell(originABC, false, name)); 8193 } catch (Exception e) { 8194 // 8195 } 8196 } 8197 cmdUnitcell(int i)8198 private void cmdUnitcell(int i) throws ScriptException { 8199 getCmdExt().dispatch(T.unitcell, i == 2, null); 8200 } 8201 cmdVector()8202 private void cmdVector() throws ScriptException { 8203 EnumType type = EnumType.SCREEN; 8204 float value = 1; 8205 checkLength(-3); 8206 switch (iToken = slen) { 8207 case 1: 8208 break; 8209 case 2: 8210 switch (getToken(1).tok) { 8211 case T.on: 8212 break; 8213 case T.off: 8214 value = 0; 8215 break; 8216 case T.integer: 8217 // diameter Pixels 8218 int d = intParameterRange(1, 0, 19); 8219 if (d == Integer.MAX_VALUE) 8220 return; 8221 value = d; 8222 break; 8223 case T.decimal: 8224 // radius angstroms 8225 type = EnumType.ABSOLUTE; 8226 if (Float.isNaN(value = floatParameterRange(1, 0, 3))) 8227 return; 8228 break; 8229 default: 8230 error(ERROR_booleanOrNumberExpected); 8231 } 8232 break; 8233 case 3: 8234 switch (tokAt(1)) { 8235 case T.trace: 8236 setIntProperty("vectorTrace", intParameterRange(2, 0, 20)); 8237 return; 8238 case T.scale: 8239 if (!Float.isNaN(value = floatParameterRange(2, -100, 100))) 8240 setFloatProperty("vectorScale", value); 8241 return; 8242 case T.max: 8243 float max = floatParameter(2); 8244 if (!chk) 8245 vwr.ms.scaleVectorsToMax(max); 8246 return; 8247 } 8248 break; 8249 } 8250 setShapeSize(JC.SHAPE_VECTORS, new RadiusData(null, value, type, null)); 8251 } 8252 cmdVibration()8253 private void cmdVibration() throws ScriptException { 8254 checkLength(-3); 8255 float period = 0; 8256 switch (getToken(1).tok) { 8257 case T.on: 8258 checkLength(2); 8259 period = vwr.getFloat(T.vibrationperiod); 8260 break; 8261 case T.off: 8262 checkLength(2); 8263 period = 0; 8264 break; 8265 case T.integer: 8266 case T.decimal: 8267 checkLength(2); 8268 period = floatParameter(1); 8269 break; 8270 case T.scale: 8271 if (!Float.isNaN(period = floatParameterRange(2, -100, 100))) 8272 setFloatProperty("vibrationScale", period); 8273 return; 8274 case T.max: 8275 float max = floatParameter(2); 8276 if (!chk) 8277 vwr.ms.scaleVectorsToMax(max); 8278 break; 8279 case T.period: 8280 setFloatProperty("vibrationPeriod", floatParameter(2)); 8281 return; 8282 case T.identifier: 8283 invArg(); 8284 break; 8285 default: 8286 period = -1; 8287 } 8288 if (period < 0) 8289 invArg(); 8290 if (chk) 8291 return; 8292 if (period == 0) { 8293 vwr.tm.setVibrationPeriod(0); 8294 return; 8295 } 8296 vwr.setVibrationPeriod(-period); 8297 } 8298 cmdWireframe()8299 private void cmdWireframe() throws ScriptException { 8300 int mad = Integer.MIN_VALUE; 8301 if (tokAt(1) == T.reset) 8302 checkLast(1); 8303 else 8304 mad = getMadParameter(); 8305 if (chk || mad == Integer.MAX_VALUE) 8306 return; 8307 setShapeProperty(JC.SHAPE_STICKS, "type", 8308 Integer.valueOf(Edge.BOND_COVALENT_MASK)); 8309 setShapeSizeBs(JC.SHAPE_STICKS, 8310 mad == Integer.MIN_VALUE ? 2 * JC.DEFAULT_BOND_MILLIANGSTROM_RADIUS 8311 : mad, null); 8312 } 8313 cmdZap(boolean isZapCommand)8314 private void cmdZap(boolean isZapCommand) throws ScriptException { 8315 if (slen == 1 || !isZapCommand) { 8316 boolean doAll = (isZapCommand && !isStateScript); 8317 if (doAll) 8318 vwr.cacheFileByName(null, false); 8319 vwr.zap(true, doAll, true); 8320 refresh(false); 8321 return; 8322 } 8323 BS bs = atomExpressionAt(1); 8324 if (chk) 8325 return; 8326 if (bs.nextSetBit(0) < 0 && slen == 4 && tokAt(2) == T.spec_model2) { 8327 int iModel = vwr.ms.getModelNumberIndex(getToken(2).intValue, false, true); 8328 if (iModel >= 0) 8329 vwr.deleteModels(iModel, null); 8330 return; 8331 } 8332 int nDeleted = vwr.deleteAtoms(bs, true); 8333 boolean isQuiet = !doReport(); 8334 if (!isQuiet) 8335 report(GT.i(GT.$("{0} atoms deleted"), nDeleted), false); 8336 vwr.select(null, false, 0, isQuiet); 8337 } 8338 cmdZoom(boolean isZoomTo)8339 private void cmdZoom(boolean isZoomTo) throws ScriptException { 8340 if (!isZoomTo) { 8341 // zoom 8342 // zoom on|off 8343 int tok = (slen > 1 ? getToken(1).tok : T.on); 8344 switch (tok) { 8345 case T.in: 8346 case T.out: 8347 break; 8348 case T.on: 8349 case T.off: 8350 if (slen > 2) 8351 bad(); 8352 if (!chk) 8353 setBooleanProperty("zoomEnabled", tok == T.on); 8354 return; 8355 } 8356 } 8357 P3 center = null; 8358 //Point3f currentCenter = vwr.getRotationCenter(); 8359 int i = 1; 8360 // zoomTo time-sec 8361 float floatSecondsTotal = (isZoomTo ? (isFloatParameter(i) ? floatParameter(i++) 8362 : 1f) 8363 : 0f); 8364 if (floatSecondsTotal < 0) { 8365 // zoom -10 8366 i--; 8367 floatSecondsTotal = 0; 8368 } 8369 // zoom {x y z} or (atomno=3) 8370 int ptCenter = 0; 8371 BS bsCenter = null; 8372 if (isCenterParameter(i)) { 8373 ptCenter = i; 8374 Object[] ret = new Object[1]; 8375 center = centerParameter(i, ret); 8376 if (ret[0] instanceof BS) 8377 bsCenter = (BS) ret[0]; 8378 i = iToken + 1; 8379 } else if (tokAt(i) == T.integer && getToken(i).intValue == 0) { 8380 bsCenter = vwr.getAtomBitSet("visible"); 8381 center = vwr.ms.getAtomSetCenter(bsCenter); 8382 } 8383 8384 // disabled sameAtom stuff -- just too weird 8385 boolean isSameAtom = false;// && (center != null && currentCenter.distance(center) < 0.1); 8386 // zoom/zoomTo [0|n|+n|-n|*n|/n|IN|OUT] 8387 // zoom/zoomTo percent|-factor|+factor|*factor|/factor | 0 8388 float zoom = vwr.tm.getZoomSetting(); 8389 8390 float newZoom = getZoom(ptCenter, i, bsCenter, zoom); 8391 i = iToken + 1; 8392 float xTrans = Float.NaN; 8393 float yTrans = Float.NaN; 8394 if (i != slen) { 8395 xTrans = floatParameter(i++); 8396 yTrans = floatParameter(i++); 8397 } 8398 if (i != slen) 8399 invArg(); 8400 if (newZoom < 0) { 8401 newZoom = -newZoom; // currentFactor 8402 if (isZoomTo) { 8403 // undocumented! 8404 // no factor -- check for no center (zoom out) or same center (zoom in) 8405 if (slen == 1 || isSameAtom) 8406 newZoom *= 2; 8407 else if (center == null) 8408 newZoom /= 2; 8409 } 8410 } 8411 float max = TransformManager.MAXIMUM_ZOOM_PERCENTAGE; 8412 if (newZoom < 5 || newZoom > max) 8413 numberOutOfRange(5, max); 8414 if (!vwr.tm.isWindowCentered()) { 8415 // do a smooth zoom only if not windowCentered 8416 if (center != null) { 8417 BS bs = atomExpressionAt(ptCenter); 8418 if (!chk) 8419 vwr.setCenterBitSet(bs, false); 8420 } 8421 center = vwr.tm.fixedRotationCenter; 8422 if (Float.isNaN(xTrans)) 8423 xTrans = vwr.tm.getTranslationXPercent(); 8424 if (Float.isNaN(yTrans)) 8425 yTrans = vwr.tm.getTranslationYPercent(); 8426 } 8427 if (chk) 8428 return; 8429 if (Float.isNaN(xTrans)) 8430 xTrans = 0; 8431 if (Float.isNaN(yTrans)) 8432 yTrans = 0; 8433 if (isSameAtom && Math.abs(zoom - newZoom) < 1 || !useThreads()) 8434 floatSecondsTotal = 0; 8435 vwr.moveTo(this, floatSecondsTotal, center, JC.center, Float.NaN, null, 8436 newZoom, xTrans, yTrans, Float.NaN, null, Float.NaN, Float.NaN, 8437 Float.NaN, Float.NaN, Float.NaN, Float.NaN); 8438 if (isJS && floatSecondsTotal > 0 && vwr.g.waitForMoveTo) 8439 throw new ScriptInterruption(this, "zoomTo", 1); 8440 8441 } 8442 8443 /////////////////////////////// methods used just by cmdXXXXX methods 8444 colorShape(int shapeType, int index, boolean isBackground)8445 private void colorShape(int shapeType, int index, boolean isBackground) 8446 throws ScriptException { 8447 String translucency = null; 8448 Object colorvalue = null; 8449 Object colorvalue1 = null; 8450 BS bs = null; 8451 String prefix = (index == 2 && tokAt(1) == T.balls ? "ball" : ""); 8452 boolean isColor = false; 8453 boolean isIsosurface = (shapeType == JC.SHAPE_ISOSURFACE || shapeType == JC.SHAPE_CONTACT); 8454 int typeMask = 0; 8455 boolean doClearBondSet = false; 8456 float translucentLevel = Float.MAX_VALUE; 8457 if (index < 0) { 8458 bs = atomExpressionAt(-index); 8459 index = iToken + 1; 8460 if (isBondSet) { 8461 doClearBondSet = true; 8462 shapeType = JC.SHAPE_STICKS; 8463 } 8464 } 8465 int tok = getToken(index).tok; 8466 if (isBackground) 8467 getToken(index); 8468 else if ((isBackground = (tok == T.background)) == true) 8469 getToken(++index); 8470 if (isBackground) 8471 prefix = "bg"; 8472 else if (isIsosurface) { 8473 switch (theTok) { 8474 case T.mesh: 8475 getToken(++index); 8476 prefix = "mesh"; 8477 break; 8478 case T.phase: 8479 int argb = getArgbParamOrNone(++index, false); 8480 colorvalue1 = (argb == 0 ? null : Integer.valueOf(argb)); 8481 getToken(index = iToken + 1); 8482 break; 8483 case T.define: 8484 case T.bitset: 8485 case T.expressionBegin: 8486 if (theToken.value instanceof BondSet) { 8487 bs = (BondSet) theToken.value; 8488 prefix = "vertex"; 8489 } else { 8490 bs = atomExpressionAt(index); 8491 prefix = "atom"; 8492 } 8493 // don't allow isosurface partial translucency (yet) 8494 //translucentLevel = Parser.FLOAT_MIN_SAFE; 8495 getToken(index = iToken + 1); 8496 break; 8497 } 8498 } 8499 if (!chk && (shapeType == JC.SHAPE_MO || shapeType == JC.SHAPE_NBO) 8500 && getIsoExt().dispatch(shapeType, true, st) != null) 8501 return; 8502 boolean isTranslucent = (theTok == T.translucent); 8503 if (isTranslucent || theTok == T.opaque) { 8504 if (translucentLevel == PT.FLOAT_MIN_SAFE) 8505 invArg(); 8506 translucency = paramAsStr(index++); 8507 if (isTranslucent && isFloatParameter(index)) 8508 translucentLevel = getTranslucentLevel(index++); 8509 } 8510 tok = 0; 8511 if (index < slen && tokAt(index) != T.on && tokAt(index) != T.off) { 8512 isColor = true; 8513 tok = getToken(index).tok; 8514 if ((!isIsosurface || tokAt(index + 1) != T.to) && isColorParam(index)) { 8515 int argb = getArgbParamOrNone(index, false); 8516 colorvalue = (argb == 0 ? null : Integer.valueOf(argb)); 8517 if (tokAt(index = iToken + 1) != T.nada && translucency == null) { 8518 getToken(index); 8519 isTranslucent = (theTok == T.translucent); 8520 if (isTranslucent || theTok == T.opaque) { 8521 translucency = paramAsStr(index++); 8522 if (isTranslucent && isFloatParameter(index)) 8523 translucentLevel = getTranslucentLevel(index++); 8524 } 8525 } 8526 if (isColorParam(index)) { 8527 argb = getArgbParamOrNone(index, false); 8528 colorvalue1 = (argb == 0 ? null : Integer.valueOf(argb)); 8529 index = iToken + 1; 8530 } 8531 checkLength(index); 8532 } else if (shapeType == JC.SHAPE_LCAOCARTOON) { 8533 iToken--; // back up one 8534 } else { 8535 // must not be a color, but rather a color SCHEME 8536 // this could be a problem for properties, which can't be 8537 // checked later -- they must be turned into a color NOW. 8538 8539 // "cpk" value would be "spacefill" 8540 String name = paramAsStr(index).toLowerCase(); 8541 boolean isByElement = (name.indexOf(ColorEncoder.BYELEMENT_PREFIX) == 0); 8542 boolean isColorIndex = (isByElement || name 8543 .indexOf(ColorEncoder.BYRESIDUE_PREFIX) == 0); 8544 PAL pal = (isColorIndex || isIsosurface ? PAL.PROPERTY 8545 : tok == T.spacefill ? PAL.CPK : PAL.getPalette(name)); 8546 // color atoms "cpkScheme" 8547 if (pal == PAL.UNKNOWN || (pal == PAL.TYPE || pal == PAL.ENERGY) 8548 && shapeType != JC.SHAPE_HSTICKS) 8549 invArg(); 8550 Object data = null; 8551 BS bsSelected = (pal != PAL.PROPERTY && pal != PAL.VARIABLE 8552 || !vwr.g.rangeSelected ? null : vwr.bsA()); 8553 if (pal == PAL.PROPERTY) { 8554 if (isColorIndex) { 8555 if (!chk) { 8556 data = getCmdExt().getBitsetPropertyFloat(bsSelected, (isByElement ? T.elemno 8557 : T.groupid) | T.allfloat, null, Float.NaN, Float.NaN); 8558 } 8559 } else { 8560 boolean isPropertyExplicit = name.equals("property"); 8561 // problem here with color $isosurface1 "rwb" 8562 if (isPropertyExplicit 8563 && T.tokAttr((tok = getToken(++index).tok), T.atomproperty) 8564 && !T.tokAttr(tok, T.strproperty)) { 8565 tok = getToken(index).tok; 8566 String type = (tok == T.dssr ? getToken(++index).value.toString() : null); 8567 if (!chk) { 8568 data = getCmdExt().getBitsetPropertyFloat(bsSelected, tok 8569 | T.allfloat, type, Float.NaN, Float.NaN); 8570 } 8571 index++; 8572 } else if (!isPropertyExplicit && !isIsosurface) { 8573 index++; 8574 } 8575 // index points to item after property 8576 } 8577 } else if (pal == PAL.VARIABLE) { 8578 index++; 8579 name = paramAsStr(index++); 8580 data = new float[vwr.ms.ac]; 8581 Parser.parseStringInfestedFloatArray( 8582 "" + getParameter(name, T.string, true), null, (float[]) data); 8583 pal = PAL.PROPERTY; 8584 } 8585 // index here points to NEXT item 8586 if (pal == PAL.PROPERTY) { 8587 String scheme = null; 8588 if (tokAt(index) == T.string) { 8589 scheme = paramAsStr(index++).toLowerCase(); 8590 if (isArrayParameter(index)) { 8591 scheme += "=" 8592 + SV.sValue(SV.getVariableAS(stringParameterSet(index))) 8593 .replace('\n', ' '); 8594 index = iToken + 1; 8595 } 8596 } else if (isIsosurface && isColorParam(index)) { 8597 scheme = getColorRange(index); 8598 index = iToken + 1; 8599 } 8600 if (scheme != null && !isIsosurface) { 8601 setStringProperty("propertyColorScheme", (isTranslucent 8602 && translucentLevel == Float.MAX_VALUE ? "translucent " : "") 8603 + scheme); 8604 isColorIndex = (scheme.indexOf(ColorEncoder.BYELEMENT_PREFIX) == 0 || scheme 8605 .indexOf(ColorEncoder.BYRESIDUE_PREFIX) == 0); 8606 } 8607 float min = 0; 8608 float max = Float.MAX_VALUE; 8609 if (!isColorIndex 8610 && (tokAt(index) == T.absolute || tokAt(index) == T.range)) { 8611 min = floatParameter(index + 1); 8612 max = floatParameter(index + 2); 8613 index += 3; 8614 if (min == max && isIsosurface) { 8615 float[] range = (float[]) getShapeProperty(shapeType, "dataRange"); 8616 if (range != null) { 8617 min = range[0]; 8618 max = range[1]; 8619 } 8620 } else if (min == max) { 8621 max = Float.MAX_VALUE; 8622 } 8623 } 8624 if (isIsosurface) { 8625 } else if (data == null) { 8626 if (!chk) 8627 vwr.setCurrentColorRange(name); 8628 } else { 8629 if (!chk) 8630 vwr.cm.setPropertyColorRangeData((float[]) data, bsSelected); 8631 } 8632 if (isIsosurface) { 8633 checkLength(index); 8634 if (chk) 8635 return; 8636 isColor = false; 8637 ColorEncoder ce = (scheme == null ? (ColorEncoder) getShapeProperty(shapeType, "colorEncoder") : null); 8638 if (ce == null && (ce = vwr.cm.getColorEncoder(scheme)) == null) 8639 return; 8640 ce.isTranslucent = (isTranslucent && translucentLevel == Float.MAX_VALUE); 8641 ce.setRange(min, max, min > max); 8642 if (max == Float.MAX_VALUE) 8643 ce.hi = max; 8644 setShapeProperty(shapeType, "remapColor", ce); 8645 showString(((String) getShapeProperty(shapeType, "dataRangeStr")) 8646 .replace('\n', ' ')); 8647 if (translucentLevel == Float.MAX_VALUE) 8648 return; 8649 } else if (max != Float.MAX_VALUE) { 8650 vwr.cm.setPropertyColorRange(min, max); 8651 } 8652 } else { 8653 index++; 8654 } 8655 checkLength(index); 8656 colorvalue = pal; 8657 } 8658 } 8659 if (chk || shapeType < 0) 8660 return; 8661 switch (shapeType) { 8662 case JC.SHAPE_STRUTS: 8663 typeMask = Edge.BOND_STRUT; 8664 break; 8665 case JC.SHAPE_HSTICKS: 8666 typeMask = Edge.BOND_HYDROGEN_MASK; 8667 break; 8668 case JC.SHAPE_SSSTICKS: 8669 typeMask = Edge.BOND_SULFUR_MASK; 8670 break; 8671 case JC.SHAPE_STICKS: 8672 typeMask = Edge.BOND_COVALENT_MASK; 8673 break; 8674 default: 8675 typeMask = 0; 8676 } 8677 if (typeMask == 0) { 8678 sm.loadShape(shapeType); 8679 if (shapeType == JC.SHAPE_LABELS) 8680 setShapeProperty(JC.SHAPE_LABELS, "setDefaults", vwr.slm.noneSelected); 8681 } else { 8682 if (bs != null) { 8683 vwr.selectBonds(bs); 8684 bs = null; 8685 } 8686 shapeType = JC.SHAPE_STICKS; 8687 setShapeProperty(shapeType, "type", Integer.valueOf(typeMask)); 8688 } 8689 if (isColor) { 8690 // ok, the following options require precalculation. 8691 // the state must not save them as paletteIDs, only as pure 8692 // color values. 8693 switch (tok) { 8694 case T.partialcharge: 8695 getPartialCharges(bs); 8696 break; 8697 case T.surfacedistance: 8698 case T.straightness: 8699 vwr.autoCalculate(tok, null); 8700 break; 8701 case T.temperature: 8702 if (vwr.g.rangeSelected) 8703 vwr.ms.clearBfactorRange(); 8704 break; 8705 case T.group: 8706 vwr.ms.calcSelectedGroupsCount(); 8707 break; 8708 case T.polymer: 8709 case T.monomer: 8710 vwr.ms.calcSelectedMonomersCount(); 8711 break; 8712 case T.molecule: 8713 vwr.ms.calcSelectedMoleculesCount(); 8714 break; 8715 } 8716 if (colorvalue1 != null 8717 && (isIsosurface || shapeType == JC.SHAPE_CARTOON 8718 || shapeType == JC.SHAPE_RIBBONS || shapeType == JC.SHAPE_POLYHEDRA)) 8719 setShapeProperty(shapeType, "colorPhase", new Object[] { colorvalue1, 8720 colorvalue }); 8721 else if (bs == null) 8722 setShapeProperty(shapeType, prefix + "color", colorvalue); 8723 else 8724 setShapePropertyBs(shapeType, prefix + "color", colorvalue, bs); 8725 } 8726 if (translucency != null) 8727 setShapeTranslucency(shapeType, prefix, translucency, translucentLevel, 8728 bs); 8729 if (typeMask != 0) 8730 setShapeProperty(JC.SHAPE_STICKS, "type", 8731 Integer.valueOf(Edge.BOND_COVALENT_MASK)); 8732 if (doClearBondSet) 8733 vwr.selectBonds(null); 8734 if (shapeType == JC.SHAPE_BALLS) 8735 vwr.shm.checkInheritedShapes(); 8736 } 8737 8738 /* 8739 * Based on the form of the parameters, returns and encoded radius as follows: 8740 * 8741 * script meaning range 8742 * 8743 * +1.2 offset [0 - 10] 8744 * -1.2 offset 0) 8745 * 1.2 absolute (0 - 10] 8746 * -30% 70% (-100 - 0) 8747 * +30% 130% (0 8748 * 80% percent (0 8749 */ 8750 getPartialCharges(BS bs)8751 public void getPartialCharges(BS bs) throws ScriptException { 8752 try { 8753 vwr.getOrCalcPartialCharges(bs, null); 8754 } catch (Exception e) { 8755 throw new ScriptInterruption(this, "partialcharge", 1); 8756 } 8757 } 8758 encodeRadiusParameter(int index, boolean isOnly, boolean allowAbsolute)8759 public RadiusData encodeRadiusParameter(int index, boolean isOnly, 8760 boolean allowAbsolute) 8761 throws ScriptException { 8762 8763 float value = Float.NaN; 8764 EnumType factorType = EnumType.ABSOLUTE; 8765 VDW vdwType = null; 8766 8767 int tok = (index == -1 ? T.vanderwaals : getToken(index).tok); 8768 switch (tok) { 8769 case T.adpmax: 8770 case T.adpmin: 8771 case T.bondingradius: 8772 case T.hydrophobicity: 8773 case T.temperature: 8774 case T.vanderwaals: 8775 value = 1; 8776 factorType = EnumType.FACTOR; 8777 vdwType = (tok == T.vanderwaals ? null : VDW.getVdwType2(T 8778 .nameOf(tok))); 8779 tok = tokAt(++index); 8780 break; 8781 } 8782 switch (tok) { 8783 case T.reset: 8784 return vwr.rd; 8785 case T.auto: 8786 case T.rasmol: 8787 case T.babel: 8788 case T.babel21: 8789 case T.jmol: 8790 value = 1; 8791 factorType = EnumType.FACTOR; 8792 iToken = index - 1; 8793 break; 8794 case T.plus: 8795 case T.integer: 8796 case T.decimal: 8797 if (tok == T.plus) { 8798 index++; 8799 } else if (tokAt(index + 1) == T.percent) { 8800 value = Math.round(floatParameter(index)); 8801 iToken = ++index; 8802 factorType = EnumType.FACTOR; 8803 if (value < 0 || value > 200) { 8804 integerOutOfRange(0, 200); 8805 return null; 8806 } 8807 value /= 100; 8808 break; 8809 } else if (tok == T.integer) { 8810 value = intParameter(index); 8811 // rasmol 250-scale if positive or percent (again), if negative 8812 // (deprecated) 8813 if (value > 749 || value < -200) { 8814 integerOutOfRange(-200, 749); 8815 return null; 8816 8817 } 8818 if (value > 0) { 8819 value /= 250; 8820 factorType = EnumType.ABSOLUTE; 8821 } else { 8822 value /= -100; 8823 factorType = EnumType.FACTOR; 8824 } 8825 break; 8826 } 8827 float max; 8828 if (tok == T.plus || !allowAbsolute) { 8829 factorType = EnumType.OFFSET; 8830 max = Atom.RADIUS_MAX; 8831 } else { 8832 factorType = EnumType.ABSOLUTE; 8833 vdwType = VDW.NADA; 8834 max = 100; 8835 } 8836 value = floatParameterRange(index, (isOnly || !allowAbsolute ? -max : 0), 8837 max); 8838 if (Float.isNaN(value)) 8839 return null; 8840 if (isOnly) 8841 value = -value; 8842 if (value > Atom.RADIUS_MAX) 8843 value = Atom.RADIUS_GLOBAL; 8844 break; 8845 default: 8846 if (value == 1) 8847 index--; 8848 } 8849 if (vdwType == null) { 8850 vdwType = VDW.getVdwType(optParameterAsString(++iToken)); 8851 if (vdwType == null) { 8852 iToken = index; 8853 vdwType = VDW.AUTO; 8854 } 8855 } 8856 return new RadiusData(null, value, factorType, vdwType); 8857 } 8858 8859 /** 8860 * Accepts a float array and expands [1 -3] to [1 2 3], for example. 8861 * 8862 * @param a 8863 * @param min 8864 * @param asBS 8865 * @return float[] or BS 8866 * @throws ScriptException 8867 */ expandFloatArray(float[] a, int min, boolean asBS)8868 public Object expandFloatArray(float[] a, int min, boolean asBS) throws ScriptException { 8869 int n = a.length; 8870 boolean haveNeg = false; 8871 BS bs = (asBS ? new BS() : null); 8872 try { 8873 for (int i = 0; i < a.length; i++) 8874 if (a[i] < 0) { 8875 n += Math.abs(a[i - 1] + a[i]) - 1; // 100 - 102 or 11 - 3 8876 haveNeg = true; 8877 } 8878 if (haveNeg) { 8879 float[] b = (asBS ? null : new float[n]); 8880 for (int pt = 0, i = 0; i < a.length; i++) { 8881 n = (int) a[i]; 8882 if (n >= 0) { 8883 if (n < min) 8884 invArg(); 8885 if (asBS) 8886 bs.set(n - 1); 8887 else 8888 b[pt++] = n; 8889 } else { 8890 int j = (int) a[i - 1]; 8891 int dir = (j <= -n ? 1 : -1); 8892 for (int j2 = -n; j != j2; j += dir, pt++) 8893 if (!asBS) 8894 b[pt] = j + dir; 8895 else 8896 bs.set(j); 8897 } 8898 } 8899 a = b; 8900 if (!asBS) 8901 n = a.length; 8902 } 8903 if (asBS) { 8904 for (int i = n; --i >= 0;) 8905 bs.set((int) a[i] - 1); 8906 return bs; 8907 } 8908 int[] ia = new int[n]; 8909 for (int i = n; --i >= 0;) 8910 ia[i] = (int) a[i]; 8911 return ia; 8912 } catch (Exception e) { 8913 invArg(); 8914 return null; 8915 } 8916 } 8917 frameControl(int i)8918 private void frameControl(int i) throws ScriptException { 8919 switch (getToken(checkLast(i)).tok) { 8920 case T.playrev: 8921 case T.play: 8922 case T.resume: 8923 case T.pause: 8924 case T.next: 8925 case T.prev: 8926 case T.rewind: 8927 case T.first: 8928 case T.last: 8929 if (!chk) 8930 vwr.setAnimation(theTok); 8931 return; 8932 } 8933 invArg(); 8934 } 8935 getColorRange(int i)8936 public String getColorRange(int i) throws ScriptException { 8937 int color1 = getArgbParam(i); 8938 if (tokAt(++iToken) != T.to) 8939 invArg(); 8940 int color2 = getArgbParam(++iToken); 8941 int nColors = (tokAt(iToken + 1) == T.integer ? intParameter(++iToken) : 0); 8942 return ColorEncoder.getColorSchemeList(ColorEncoder.getPaletteAtoB(color1, 8943 color2, nColors)); 8944 } 8945 getFullPathName()8946 public String getFullPathName() throws ScriptException { 8947 String filename = (!chk || isCmdLine_C_Option ? vwr 8948 .fm.getFullPathName(true) : "test.xyz"); 8949 if (filename == null) 8950 invArg(); 8951 return filename; 8952 } 8953 getObjectBoundingBox(String id)8954 private P3[] getObjectBoundingBox(String id) { 8955 Object[] data = new Object[] { id, null, null }; 8956 return (getShapePropertyData(JC.SHAPE_ISOSURFACE, "getBoundingBox", data) 8957 || getShapePropertyData(JC.SHAPE_PMESH, "getBoundingBox", data) 8958 || getShapePropertyData(JC.SHAPE_CONTACT, "getBoundingBox", data) 8959 || getShapePropertyData(JC.SHAPE_NBO, "getBoundingBox", data) 8960 || getShapePropertyData(JC.SHAPE_MO, "getBoundingBox", data) ? (P3[]) data[2] 8961 : null); 8962 } 8963 getObjectCenter(String axisID, int index, int modelIndex)8964 protected P3 getObjectCenter(String axisID, int index, int modelIndex) { 8965 8966 // called by ScriptParam 8967 8968 Object[] data = new Object[] { axisID, Integer.valueOf(index), 8969 Integer.valueOf(modelIndex) }; 8970 return (getShapePropertyData(JC.SHAPE_DRAW, "getCenter", data) 8971 || getShapePropertyData(JC.SHAPE_ISOSURFACE, "getCenter", data) 8972 || getShapePropertyData(JC.SHAPE_PMESH, "getCenter", data) 8973 || getShapePropertyData(JC.SHAPE_CONTACT, "getCenter", data) 8974 || getShapePropertyData(JC.SHAPE_NBO, "getCenter", data) 8975 || getShapePropertyData(JC.SHAPE_MO, "getCenter", data) ? (P3) data[2] 8976 : null); 8977 } 8978 getPlaneForObject(String id, V3 vAB)8979 protected P4 getPlaneForObject(String id, V3 vAB) { 8980 8981 // called by ScriptParam 8982 8983 int shapeType = sm.getShapeIdFromObjectName(id); 8984 switch (shapeType) { 8985 case JC.SHAPE_DRAW: 8986 setShapeProperty(JC.SHAPE_DRAW, "thisID", id); 8987 T3[] points = (T3[]) getShapeProperty(JC.SHAPE_DRAW, "vertices"); 8988 if (points == null || points.length < 3 || points[0] == null 8989 || points[1] == null || points[2] == null) 8990 break; 8991 return Measure.getPlaneThroughPoints(points[0], points[1], points[2], 8992 new V3(), vAB, new P4()); 8993 case JC.SHAPE_ISOSURFACE: 8994 setShapeProperty(JC.SHAPE_ISOSURFACE, "thisID", id); 8995 return (P4) getShapeProperty(JC.SHAPE_ISOSURFACE, "plane"); 8996 } 8997 return null; 8998 } 8999 9000 @SuppressWarnings("unchecked") getQuaternionArray(Object quaternionOrSVData, int itype)9001 public Quat[] getQuaternionArray(Object quaternionOrSVData, int itype) { 9002 Quat[] data; 9003 switch (itype) { 9004 case T.quaternion: 9005 data = (Quat[]) quaternionOrSVData; 9006 break; 9007 case T.point4f: 9008 P4[] pts = (P4[]) quaternionOrSVData; 9009 data = new Quat[pts.length]; 9010 for (int i = 0; i < pts.length; i++) 9011 data[i] = Quat.newP4(pts[i]); 9012 break; 9013 case T.list: 9014 Lst<SV> sv = (Lst<SV>) quaternionOrSVData; 9015 data = new Quat[sv.size()]; 9016 for (int i = 0; i < sv.size(); i++) { 9017 P4 pt = SV.pt4Value(sv.get(i)); 9018 if (pt == null) 9019 return null; 9020 data[i] = Quat.newP4(pt); 9021 } 9022 break; 9023 default: 9024 return null; 9025 } 9026 return data; 9027 } 9028 getSetAxesTypeMad10(int index)9029 public int getSetAxesTypeMad10(int index) throws ScriptException { 9030 if (index == slen) 9031 return 1; 9032 switch (getToken(checkLast(index)).tok) { 9033 case T.on: 9034 return 1; 9035 case T.off: 9036 return 0; 9037 case T.dotted: 9038 return -1; 9039 case T.integer: 9040 return intParameterRange(index, -1, 19); 9041 case T.decimal: 9042 float angstroms = floatParameterRange(index, 0, 2); 9043 return (Float.isNaN(angstroms) ? Integer.MAX_VALUE : (int) Math.floor(angstroms * 10000 * 2)); 9044 } 9045 if (!chk) 9046 errorStr(ERROR_booleanOrWhateverExpected, "\"DOTTED\""); 9047 return 0; 9048 } 9049 getSettingFloat(int pt)9050 private float getSettingFloat(int pt) throws ScriptException { 9051 return (pt >= slen ? Float.NaN : SV.fValue(parameterExpressionToken(pt))); 9052 } 9053 getSettingInt(int pt)9054 private int getSettingInt(int pt) throws ScriptException { 9055 return (pt >= slen ? Integer.MIN_VALUE : parameterExpressionToken(pt) 9056 .asInt()); 9057 } 9058 9059 /** 9060 * Accept an unquoted string if there is just one parameter regardless of its 9061 * type. In other words, these commands cannot accept a variable name by 9062 * itself. 9063 * 9064 * @param pt 9065 * @param isJmolSet 9066 * @return string parameter 9067 * @throws ScriptException 9068 */ getSettingStr(int pt, boolean isJmolSet)9069 private String getSettingStr(int pt, boolean isJmolSet) 9070 throws ScriptException { 9071 return (isJmolSet && slen == pt + 1 ? paramAsStr(pt) 9072 : parameterExpressionToken(pt).asString()); 9073 } 9074 getShapeProperty(int shapeType, String propertyName)9075 public Object getShapeProperty(int shapeType, String propertyName) { 9076 return sm.getShapePropertyIndex(shapeType, propertyName, Integer.MIN_VALUE); 9077 } 9078 getShapePropertyData(int shapeType, String propertyName, Object[] data)9079 public boolean getShapePropertyData(int shapeType, String propertyName, 9080 Object[] data) { 9081 return sm.getShapePropertyData(shapeType, propertyName, data); 9082 } 9083 getShapeType(int tok)9084 private int getShapeType(int tok) throws ScriptException { 9085 int iShape = JC.shapeTokenIndex(tok); 9086 if (iShape < 0) 9087 error(ERROR_unrecognizedObject); 9088 return iShape; 9089 } 9090 getTranslucentLevel(int i)9091 public float getTranslucentLevel(int i) throws ScriptException { 9092 float f = floatParameter(i); 9093 return (theTok == T.integer && f > 0 && f < 9 ? f + 1 : f); 9094 } 9095 getZoom(int ptCenter, int i, BS bs, float currentZoom)9096 private float getZoom(int ptCenter, int i, BS bs, float currentZoom) 9097 throws ScriptException { 9098 // where [zoom factor] is [0|n|+n|-n|*n|/n|IN|OUT] 9099 9100 float zoom = (isFloatParameter(i) ? floatParameter(i++) : Float.NaN); 9101 if (zoom == 0 || currentZoom == 0) { 9102 // moveTo/zoom/zoomTo {center} 0 9103 float r = Float.NaN; 9104 if (bs == null) { 9105 if (tokAt(ptCenter) == T.dollarsign) { 9106 P3[] bbox = getObjectBoundingBox(objectNameParameter(ptCenter + 1)); 9107 if (bbox == null || (r = bbox[0].distance(bbox[1]) / 2) == 0) 9108 invArg(); 9109 } 9110 } else { 9111 r = vwr.ms.calcRotationRadiusBs(bs); 9112 } 9113 if (Float.isNaN(r)) 9114 invArg(); 9115 currentZoom = vwr.getFloat(T.rotationradius) / r * 100; 9116 zoom = Float.NaN; 9117 } 9118 if (zoom < 0) { 9119 // moveTo/zoom/zoomTo -factor 9120 zoom += currentZoom; 9121 } else if (Float.isNaN(zoom)) { 9122 // moveTo/zoom/zoomTo [optional {center}] percent|+factor|*factor|/factor 9123 // moveTo/zoom/zoomTo {center} 0 [optional 9124 // -factor|+factor|*factor|/factor] 9125 int tok = tokAt(i); 9126 switch (tok) { 9127 case T.out: 9128 case T.in: 9129 zoom = currentZoom * (tok == T.out ? 0.5f : 2f); 9130 i++; 9131 break; 9132 case T.divide: 9133 case T.times: 9134 case T.plus: 9135 float value = floatParameter(++i); 9136 i++; 9137 switch (tok) { 9138 case T.divide: 9139 zoom = currentZoom / value; 9140 break; 9141 case T.times: 9142 zoom = currentZoom * value; 9143 break; 9144 case T.plus: 9145 zoom = currentZoom + value; 9146 break; 9147 } 9148 break; 9149 default: 9150 // indicate no factor indicated 9151 zoom = (bs == null ? -currentZoom : currentZoom); 9152 } 9153 } 9154 iToken = i - 1; 9155 return zoom; 9156 } 9157 setElementColor(String str, int argb)9158 private boolean setElementColor(String str, int argb) { 9159 for (int i = Elements.elementNumberMax; --i >= 0;) { 9160 if (str.equalsIgnoreCase(Elements.elementNameFromNumber(i))) { 9161 if (!chk) 9162 vwr.setElementArgb(i, argb); 9163 return true; 9164 } 9165 } 9166 for (int i = Elements.altElementMax; --i >= 0;) { 9167 if (str.equalsIgnoreCase(Elements.altElementNameFromIndex(i))) { 9168 if (!chk) 9169 vwr.setElementArgb(Elements.altElementNumberFromIndex(i), argb); 9170 return true; 9171 } 9172 } 9173 if (str.charAt(0) != '_') 9174 return false; 9175 for (int i = Elements.elementNumberMax; --i >= 0;) { 9176 if (str.equalsIgnoreCase("_" + Elements.elementSymbolFromNumber(i))) { 9177 if (!chk) 9178 vwr.setElementArgb(i, argb); 9179 return true; 9180 } 9181 } 9182 for (int i = Elements.altElementMax; --i >= Elements.firstIsotope;) { 9183 if (str.equalsIgnoreCase("_" + Elements.altElementSymbolFromIndex(i))) { 9184 if (!chk) 9185 vwr.setElementArgb(Elements.altElementNumberFromIndex(i), argb); 9186 return true; 9187 } 9188 if (str.equalsIgnoreCase("_" + Elements.altIsotopeSymbolFromIndex(i))) { 9189 if (!chk) 9190 vwr.setElementArgb(Elements.altElementNumberFromIndex(i), argb); 9191 return true; 9192 } 9193 } 9194 return false; 9195 } 9196 9197 /** 9198 * @param shape 9199 * @param i 9200 * @param tok 9201 * @return true if successful 9202 * @throws ScriptException 9203 */ setMeshDisplayProperty(int shape, int i, int tok)9204 public boolean setMeshDisplayProperty(int shape, int i, int tok) 9205 throws ScriptException { 9206 String propertyName = null; 9207 Object propertyValue = null; 9208 boolean allowCOLOR = (shape == JC.SHAPE_CONTACT); 9209 boolean checkOnly = (i == 0); 9210 // these properties are all processed in MeshCollection.java 9211 if (!checkOnly) 9212 tok = getToken(i).tok; 9213 switch (tok) { 9214 case T.color: 9215 if (allowCOLOR) 9216 iToken++; 9217 else 9218 break; 9219 //$FALL-THROUGH$ 9220 case T.opaque: 9221 case T.translucent: 9222 if (!checkOnly) 9223 colorShape(shape, iToken, false); 9224 return true; 9225 case T.nada: 9226 case T.delete: 9227 case T.on: 9228 case T.off: 9229 case T.hide: 9230 case T.hidden: 9231 case T.display: 9232 case T.displayed: 9233 if (iToken == 1 && shape >= 0 && tokAt(2) == T.nada) 9234 setShapeProperty(shape, "thisID", null); 9235 if (tok == T.nada) 9236 return (iToken == 1); 9237 if (checkOnly) 9238 return true; 9239 switch (tok) { 9240 case T.delete: 9241 setShapeProperty(shape, "delete", null); 9242 return true; 9243 case T.hidden: 9244 case T.hide: 9245 tok = T.off; 9246 break; 9247 case T.displayed: 9248 tok = T.on; 9249 break; 9250 case T.display: 9251 if (i + 1 == slen) 9252 tok = T.on; 9253 break; 9254 } 9255 //$FALL-THROUGH$ for on/off/display 9256 case T.frontlit: 9257 case T.backlit: 9258 case T.fullylit: 9259 case T.contourlines: 9260 case T.nocontourlines: 9261 case T.dots: 9262 case T.nodots: 9263 case T.mesh: 9264 case T.nomesh: 9265 case T.fill: 9266 case T.nofill: 9267 case T.backshell: 9268 case T.nobackshell: 9269 case T.triangles: 9270 case T.notriangles: 9271 case T.frontonly: 9272 case T.notfrontonly: 9273 propertyName = "token"; 9274 propertyValue = Integer.valueOf(tok); 9275 break; 9276 } 9277 if (propertyName == null) 9278 return false; 9279 if (checkOnly) 9280 return true; 9281 setShapeProperty(shape, propertyName, propertyValue); 9282 if ((tokAt(iToken + 1)) != T.nada) { 9283 if (!setMeshDisplayProperty(shape, ++iToken, 0)) 9284 --iToken; 9285 } 9286 return true; 9287 } 9288 setObjectArgb(String str, int argb)9289 private void setObjectArgb(String str, int argb) { 9290 if (chk) 9291 return; 9292 vwr.setObjectArgb(str, argb); 9293 } 9294 setObjectMad10(int iShape, String name, int mad10)9295 public void setObjectMad10(int iShape, String name, int mad10) { 9296 if (!chk) 9297 vwr.setObjectMad10(iShape, name, mad10); 9298 } 9299 setObjectProp(String id, int tokCommand, int ptColor)9300 private String setObjectProp(String id, int tokCommand, int ptColor) 9301 throws ScriptException { 9302 Object[] data = new Object[] { id, null }; 9303 String s = ""; 9304 boolean isWild = PT.isWild(id); 9305 for (int iShape = JC.SHAPE_DIPOLES;;) { 9306 if (getShapePropertyData(iShape, "checkID", data)) { 9307 setShapeProperty(iShape, "thisID", id); 9308 switch (tokCommand) { 9309 case T.delete: 9310 setShapeProperty(iShape, "delete", null); 9311 break; 9312 case T.hide: 9313 case T.display: 9314 setShapeProperty(iShape, "hidden", 9315 tokCommand == T.display ? Boolean.FALSE : Boolean.TRUE); 9316 break; 9317 case T.show: 9318 //if (iShape == JmolConstants.SHAPE_ISOSURFACE && !isWild) 9319 //return getIsosurfaceJvxl(false, JmolConstants.SHAPE_ISOSURFACE); 9320 //else if (iShape == JmolConstants.SHAPE_PMESH && !isWild) 9321 //return getIsosurfaceJvxl(true, JmolConstants.SHAPE_PMESH); 9322 s += (String) getShapeProperty(iShape, "command") + "\n"; 9323 break; 9324 case T.color: 9325 if (ptColor >= 0) 9326 colorShape(iShape, ptColor + 1, false); 9327 break; 9328 } 9329 if (!isWild) 9330 break; 9331 } 9332 switch (iShape) { 9333 case JC.SHAPE_DIPOLES: 9334 iShape = JC.SHAPE_ELLIPSOIDS; 9335 continue; 9336 case JC.SHAPE_ELLIPSOIDS: 9337 iShape = JC.SHAPE_MAX_HAS_ID; 9338 } 9339 switch (--iShape) { 9340 // skip MO and NBO? 9341 case JC.SHAPE_MO: 9342 iShape--; 9343 break; 9344 case JC.SHAPE_NBO: 9345 iShape -= 2; 9346 break; 9347 } 9348 if (iShape < JC.SHAPE_MIN_HAS_ID) 9349 break; 9350 } 9351 return s; 9352 } 9353 setObjectProperty()9354 public String setObjectProperty() throws ScriptException { 9355 // also called by show command, in ScriptExt 9356 String id = setShapeNameParameter(2); 9357 return (chk ? "" : setObjectProp(id, tokAt(0), iToken)); 9358 } 9359 setShapeNameParameter(int i)9360 public String setShapeNameParameter(int i) throws ScriptException { 9361 String id = paramAsStr(i); 9362 boolean isWild = id.equals("*"); 9363 if (id.length() == 0) 9364 invArg(); 9365 if (isWild) { 9366 switch (tokAt(i + 1)) { 9367 case T.nada: 9368 case T.on: 9369 case T.off: 9370 case T.displayed: 9371 case T.hidden: 9372 case T.color: 9373 case T.delete: 9374 break; 9375 default: 9376 if (setMeshDisplayProperty(-1, 0, tokAt(i + 1))) 9377 break; 9378 id += optParameterAsString(++i); 9379 } 9380 } 9381 if (tokAt(i + 1) == T.times) 9382 id += paramAsStr(++i); 9383 iToken = i; 9384 return id; 9385 } 9386 setShapeProperty(int shapeType, String propertyName, Object propertyValue)9387 public void setShapeProperty(int shapeType, String propertyName, 9388 Object propertyValue) { 9389 if (!chk) 9390 sm.setShapePropertyBs(shapeType, propertyName, propertyValue, null); 9391 } 9392 setShapePropertyBs(int iShape, String propertyName, Object propertyValue, BS bs)9393 public void setShapePropertyBs(int iShape, String propertyName, 9394 Object propertyValue, BS bs) { 9395 if (!chk) 9396 sm.setShapePropertyBs(iShape, propertyName, propertyValue, bs); 9397 } 9398 setShapeSize(int shapeType, RadiusData rd)9399 private void setShapeSize(int shapeType, RadiusData rd) { 9400 if (!chk) 9401 sm.setShapeSizeBs(shapeType, 0, rd, null); 9402 } 9403 setShapeSizeBs(int shapeType, int size, BS bs)9404 public void setShapeSizeBs(int shapeType, int size, BS bs) { 9405 // stars, halos, balls only 9406 if (!chk) 9407 sm.setShapeSizeBs(shapeType, size, null, bs); 9408 } 9409 setShapeTranslucency(int shapeType, String prefix, String translucency, float translucentLevel, BS bs)9410 public void setShapeTranslucency(int shapeType, String prefix, 9411 String translucency, float translucentLevel, 9412 BS bs) { 9413 if (translucentLevel == Float.MAX_VALUE) 9414 translucentLevel = vwr.getFloat(T.defaulttranslucent); 9415 setShapeProperty(shapeType, "translucentLevel", 9416 Float.valueOf(translucentLevel)); 9417 if (prefix == null) 9418 return; 9419 if (bs == null) 9420 setShapeProperty(shapeType, prefix + "translucency", translucency); 9421 else if (!chk) 9422 setShapePropertyBs(shapeType, prefix + "translucency", translucency, bs); 9423 } 9424 setSize(int shape, float scale)9425 private void setSize(int shape, float scale) throws ScriptException { 9426 // halo star spacefill 9427 RadiusData rd = null; 9428 int tok = tokAt(1); 9429 boolean isOnly = false; 9430 switch (tok) { 9431 case T.only: 9432 restrictSelected(false, false); 9433 //$FALL-THROUGH$ 9434 case T.on: 9435 break; 9436 case T.off: 9437 scale = 0; 9438 break; 9439 case T.decimal: 9440 isOnly = (floatParameter(1) < 0); 9441 //$FALL-THROUGH$ 9442 case T.integer: 9443 default: 9444 rd = encodeRadiusParameter(1, isOnly, true); 9445 if (rd == null) 9446 return; 9447 if (Float.isNaN(rd.value)) 9448 invArg(); 9449 } 9450 if (rd == null) 9451 rd = new RadiusData(null, scale, EnumType.FACTOR, VDW.AUTO); 9452 if (isOnly) 9453 restrictSelected(false, false); 9454 setShapeSize(shape, rd); 9455 } 9456 setSizeBio(int iShape)9457 private void setSizeBio(int iShape) throws ScriptException { 9458 int mad = 0; 9459 // token has ondefault1 9460 switch (getToken(1).tok) { 9461 case T.only: 9462 restrictSelected(false, false); 9463 //$FALL-THROUGH$ 9464 case T.on: 9465 mad = -1; // means take default 9466 break; 9467 case T.off: 9468 break; 9469 case T.structure: 9470 mad = -2; 9471 break; 9472 case T.temperature: 9473 case T.displacement: 9474 mad = -4; 9475 break; 9476 case T.integer: 9477 if ((mad = (intParameterRange(1, 0, 1000) * 8)) == Integer.MAX_VALUE) 9478 return; 9479 break; 9480 case T.decimal: 9481 mad = Math.round(floatParameterRange(1, -Shape.RADIUS_MAX, 9482 Shape.RADIUS_MAX) * 2000); 9483 if (mad == Integer.MAX_VALUE) 9484 return; 9485 if (mad < 0) { 9486 restrictSelected(false, false); 9487 mad = -mad; 9488 } 9489 break; 9490 case T.bitset: 9491 if (!chk) 9492 sm.loadShape(iShape); 9493 setShapeProperty(iShape, "bitset", theToken.value); 9494 return; 9495 default: 9496 error(ERROR_booleanOrNumberExpected); 9497 } 9498 setShapeSizeBs(iShape, mad, null); 9499 } 9500 setUnits(String units, int tok)9501 private boolean setUnits(String units, int tok) throws ScriptException { 9502 if (tok == T.measurementunits 9503 && (units.toLowerCase().endsWith("hz") || PT.isOneOf(units.toLowerCase(), 9504 ";angstroms;au;bohr;nanometers;nm;picometers;pm;vanderwaals;vdw;"))) { 9505 if (!chk) 9506 vwr.setUnits(units, true); 9507 } else if (tok == T.energyunits 9508 && PT.isOneOf(units.toLowerCase(), ";kcal;kj;")) { 9509 if (!chk) 9510 vwr.setUnits(units, false); 9511 } else { 9512 errorStr2(ERROR_unrecognizedParameter, "set " + T.nameOf(tok), units); 9513 } 9514 return true; 9515 } 9516 9517 9518 9519 @Override toString()9520 public String toString() { 9521 SB str = new SB(); 9522 str.append("Eval\n pc:"); 9523 str.appendI(pc); 9524 str.append("\n"); 9525 str.appendI(aatoken.length); 9526 str.append(" statements\n"); 9527 for (int i = 0; i < aatoken.length; ++i) { 9528 str.append("----\n"); 9529 T[] atoken = aatoken[i]; 9530 for (int j = 0; j < atoken.length; ++j) { 9531 str.appendO(atoken[j]); 9532 str.appendC('\n'); 9533 } 9534 str.appendC('\n'); 9535 } 9536 str.append("END\n"); 9537 return str.toString(); 9538 } 9539 9540 } 9541