Revision: 21292
          http://sourceforge.net/p/jmol/code/21292
Author:   hansonr
Date:     2016-12-01 15:04:17 +0000 (Thu, 01 Dec 2016)
Log Message:
-----------
Jmol.___JmolVersion="14.7.4_2016.12.01"

new feature: fully implemented CIF 2.0 reader

new feature: CIF reader allows for [ .... ] array notation
 -- returned as an unaltered string for CIF 1.x 
 

Modified Paths:
--------------
    trunk/Jmol/src/javajs/util/CifDataParser.java
    trunk/Jmol/src/org/jmol/adapter/readers/cif/Cif2DataParser.java
    trunk/Jmol/src/org/jmol/adapter/readers/cif/Cif2Reader.java
    trunk/Jmol/src/org/jmol/adapter/readers/cif/CifReader.java
    trunk/Jmol/src/org/jmol/adapter/smarter/Resolver.java
    trunk/Jmol/src/org/jmol/viewer/Jmol.properties

Modified: trunk/Jmol/src/javajs/util/CifDataParser.java
===================================================================
--- trunk/Jmol/src/javajs/util/CifDataParser.java       2016-11-29 05:02:30 UTC 
(rev 21291)
+++ trunk/Jmol/src/javajs/util/CifDataParser.java       2016-12-01 15:04:17 UTC 
(rev 21292)
@@ -82,11 +82,11 @@
   private GenericLineReader reader;
   private BufferedReader br;
 
-  private String line;  
-  private String str;
-  private int ich;
-  private int cch;
-  private boolean wasUnQuoted;
+  protected String line;  
+  protected String str;
+  protected int ich;
+  protected int cch;
+  protected boolean wasUnquoted;
   private String strPeeked;
   private int ichPeeked;
   private int columnCount;
@@ -94,11 +94,13 @@
   private String[] columnData = new String[KEY_MAX];
   private boolean isLoop;
   private boolean haveData;
+  protected String nullString = "\0";
 
   private SB fileHeader = new SB();
   private boolean isHeader = true;
-  private String nullString = "\0";
 
+  protected char cterm = '\0';
+
   /**
    * Set the string value of what is returned for "." and "?"
    * 
@@ -195,6 +197,10 @@
           getAllCifLoopData(data);
           continue;
         }
+        if (key.startsWith("save_")) {
+          System.out.println("CIF reader ignoring save_");
+          continue;
+        }
         if (key.charAt(0) != '_') {
           System.out.println("CIF ERROR ? should be an underscore: " + key);
         } else {
@@ -320,12 +326,14 @@
    */
   @Override
   public String getNextToken() throws Exception {
-    while (!strHasMoreTokens())
-      if (setStringNextLine() == null)
-        return null;
-    return nextStrToken();
+    wasUnquoted = true;
+    return getNextTokenProtected();
   }
 
+  protected String getNextTokenProtected() throws Exception {
+    return (getNextLine() ? nextStrToken() : null);
+  }
+
   /**
    * 
    * first checks to see if the next token is an unquoted
@@ -339,7 +347,7 @@
     String str = peekToken();
     if (str == null)
       return null;
-    if (wasUnQuoted)
+    if (wasUnquoted)
       if (str.charAt(0) == '_' || str.startsWith("loop_")
           || str.startsWith("data_")
           || str.startsWith("stop_")
@@ -357,9 +365,8 @@
    */
   @Override
   public String peekToken() throws Exception {
-    while (!strHasMoreTokens())
-      if (setStringNextLine() == null)
-        return null;
+    if (!getNextLine())
+      return null;
     int ich = this.ich;
     strPeeked = nextStrToken();
     ichPeeked= this.ich;
@@ -367,6 +374,13 @@
     return strPeeked;
   }
   
+  private boolean getNextLine() throws Exception {
+    while (!strHasMoreTokens())
+      if (prepareNextLine() == null)
+        return false;
+    return true;
+  }
+
   /**
    * 
    * @return the token last acquired; may be null
@@ -545,14 +559,18 @@
   
   
   /**
-   * sets a string to be parsed from the beginning
+   * sets global str and line to be parsed from the beginning
    * 
-   * @param str
+   * \1 .... \1  indicates an embedded fully escaped data object
+   * 
+   * @param str new data string
+   * @return str
    */
-  private void setString(String str) {
+  protected String setString(String str) {
     this.str = line = str;
     cch = (str == null ? 0 : str.length());
     ich = 0;
+    return str;
   }
 
   /*
@@ -617,15 +635,36 @@
    * @return  the next line or null if EOF
    * @throws Exception
    */
-  protected String setStringNextLine() throws Exception {
+  protected String prepareNextLine() throws Exception {
     setString(readLine());
     if (line == null || line.length() == 0)
       return line;
-    if (line.charAt(0) != ';') {
-      if (str.startsWith("###non-st#"))
+    if (doPreProcess(line.charAt(0)))
+      return preprocessString();
+    if (str.startsWith("###non-st#"))
         ich = 10;
-      return line;
-    }
+    return line;
+ }
+
+  protected boolean doPreProcess(char ch) {
+    return ch == ';';
+  }
+
+  /**
+   * preprocess the string to produce a string with a \1 ... \1 segment
+   * that will be picked up next, probably from multiline data 
+   * @return escaped part with attached extra data
+   */
+  protected String preprocessString() throws Exception {
+    return setString(preprocessSemiString());
+  }
+
+  /**
+   * encapsulate a multi-line ; .... ;  string with \1 ... \1
+   * 
+   * @return ecapsulated string
+   */
+  protected String preprocessSemiString() throws Exception {
     ich = 1;
     String str = '\1' + line.substring(1) + '\n';
     while (readLine() != null) {
@@ -637,7 +676,6 @@
       }
       str += line + '\n';
     }
-    setString(str);
     return str;
   }
 
@@ -655,30 +693,62 @@
   }
 
   /**
-   * assume that hasMoreTokens() has been called and that
-   * ich is pointing at a non-white character. Also sets
-   * boolean wasUnQuoted, because we need to know if we should 
-   * be checking for a control keyword. 'loop_' is different from just 
-   * loop_ without the quotes.
-   *
-   * @return null if no more tokens, "\0" if '.' or '?', or next token 
+   * assume that hasMoreTokens() has been called and that ich is pointing at a
+   * non-white character. Also sets boolean wasUnQuoted, because we need to 
know
+   * if we should be checking for a control keyword. 'loop_' is different from
+   * just loop_ without the quotes.
+   * 
+   * @return null if no more tokens, "\0" if '.' or '?', or next token
    */
   protected String nextStrToken() {
     if (ich == cch)
       return null;
+    char ch = str.charAt(ich);
+    if (isQuote(ch)) {
+      wasUnquoted = false;
+      return (String) getQuotedStringOrObject(ch);
+    }
     int ichStart = ich;
-    char ch = str.charAt(ichStart);
-    if (ch != '\'' && ch != '"' && ch != '\1') {// && ch != '[') {
-      wasUnQuoted = true;
-      while (ich < cch && (ch = str.charAt(ich)) != ' ' && ch != '\t')
-        ++ich;
-      if (ich == ichStart + 1)
-        if (nullString != null && (str.charAt(ichStart) == '.' || 
str.charAt(ichStart) == '?'))
-          return nullString;
-      String s = str.substring(ichStart, ich);
-      return s;
+    wasUnquoted = true;
+    while (ich < cch && !isTerminator(ch = str.charAt(ich)))
+      ++ich;
+    if (ich == ichStart + 1)
+      if (nullString != null
+          && (str.charAt(ichStart) == '.' || str.charAt(ichStart) == '?'))
+        return nullString;
+    String s = str.substring(ichStart, ich);
+    return unquoted(s);
+  }
+
+  protected String unquoted(String s) {
+    return s;
+  }
+
+  protected boolean isTerminator(char c) {
+    return  c == ' ' || c == '\t' || c == cterm ;
+  }
+
+  protected boolean isQuote(char ch) {
+    switch (ch) {
+    case '\'':
+    case '\"':
+    case '\1':
+    case '[':
+      return  true;
     }
-    wasUnQuoted = false;
+    return false;
+  }
+
+  /**
+   * CIF 1.1 only, with addition of SIMPLE arrays due to the fact that 
+   * the MagCIF format includes one data value of that type even though it is 
not a CIF 2.0 file.
+   * 
+   * @param ichStart
+   * @param ch
+   * @return a String data object
+   */
+  protected Object getQuotedStringOrObject(char ch) {
+    int ichStart = ich;
     boolean isArray = (ch  == '[');
     char chClosingQuote = (isArray ? ']' : ch);
     boolean previousCharacterWasQuote = false;

Modified: trunk/Jmol/src/org/jmol/adapter/readers/cif/Cif2DataParser.java
===================================================================
--- trunk/Jmol/src/org/jmol/adapter/readers/cif/Cif2DataParser.java     
2016-11-29 05:02:30 UTC (rev 21291)
+++ trunk/Jmol/src/org/jmol/adapter/readers/cif/Cif2DataParser.java     
2016-12-01 15:04:17 UTC (rev 21292)
@@ -1,26 +1,412 @@
 package org.jmol.adapter.readers.cif;
 
 import javajs.util.CifDataParser;
+import javajs.util.PT;
 
 /**
+ * 
+ * Fully implemented 2016.12.1
+ * 
  * see http://journals.iucr.org/j/issues/2016/01/00/aj5269/index.html
  * 
+ * @author Bob Hanson hans...@stolaf.edu 
  */
 public class Cif2DataParser extends CifDataParser {
 
+//  3.1. Character set and encoding
+//
+//       - UTF-8
+//       CIF 2.0 files are permitted to begin with a Unicode byte-order mark 
(character U+FEFF)
+//
+//       - 0xEF,0xBB,0xBF
+//
+// - Implemented
+//  - See org.jmol.adapter.smarter.Resolver; BOM is taken care of in the 
reader  
+//
+//
+//  3.2. Whitespace and line termination
+//  
+//  Specifically, CIF 2.0 recognizes and attributes identical meaning as line 
termination to 
+//  three distinct character sequences: \n, \r, or \r\n. CIF 2.0 processors 
are required to 
+//  behave as if each appearance of any of the three equivalent forms of CIF 
2.0 line termination 
+//  in their inputs had been converted to a line feed prior to analysis.
+//  
+//  CIF keywords, data block headers, save frame headers, data names and data 
values all 
+//  must be separated from each other by whitespace (an in-line whitespace 
character or a 
+//  line terminator, followed by an arbitrary number of CIF comments, 
additional in-line 
+//  whitespace characters and line terminators). The line terminator 
immediately prior to
+//  a text-field opening delimiter serves both to separate the preceding data 
name or data
+//  value from the text field and to indicate the start of the text field; 
additional whitespace 
+//  prior to that line terminator is not required. Otherwise, whitespace is 
optional in CIF 2.0 in these positions:
+//
+//    (a) between the enclosing square brackets ([,]) of a List value (see 
§3.8[link]) and the 
+//           values within, and between the brackets of an empty List;
+//
+//    (b) between the enclosing braces ({,}) of a Table value (see §3.9[link]) 
and the entries 
+//           within, and between the braces of an empty Table; and
+//
+//    (c) between a Table key and its associated value.  
+//
+// - Implemented
+//  - GenericLineReader will take care of this automatically.
+//
+//
+//  3.3 version #\#CIF_2.0
+//
+// - Implemented
+//  - Jmol looks for #\#CIF_2 only, figuring that perhaps this will be 
augmented  
+//  - note that this can be preceded by the UTF-8 byte-order-mark, but that 
will not be seen by the reader anyway.
+//
+//
+//  3.4. Data names, block codes and frame codes  
+//
+//  CIF 2.0 defines data name, block code and frame code uniqueness in terms 
+//  of the Unicode canonical caseless matching algorithm (The Unicode 
Consortium, 
+//  2014b[The Unicode Consortium (2014b). The Unicode Standard, Version 7.0.0, 
+//  ch. 3, §3.13. Mountain View: The Unicode Consortium. 
http://www.unicode.org/versions/Unicode7.0.0/ .]): 
+//  no two data blocks in any CIF may have names that are canonical caseless 
matches 
+//  of each other, no two save frames in any data block may have names that 
are canonical caseless 
+//  matches of each other, and no two data names belonging directly to the 
same block or 
+//  frame may be canonical caseless matches of each other.
+//
+// - Implemented
+//  - A Jmol limitation: No critical keys read by Jmol should be unicode 
characters. 
+//  - JSmol in particular does not implement the very complex code necessary 
to accomplish Unicode case checking.
+//    
+//  3.5. Quoted and whitespace-delimited strings
+//
+//  CIF 2.0 ... does not permit quoted data values to embed their delimiter 
under any circumstance.
+//  CIF 2.0 excludes these four characters (',",[, and ]) from appearing 
anywhere in whitespace-delimited data values.
+//
+// - Implemented
+//
+//
+//  3.6. Triple-quoted strings
+//
+//  CIF 2.0 provides a new way to express single- and multi-line data values: 
triple-quoted strings. 
+//  A triple-quoted string begins with a delimiter consisting of three 
apostrophes (''') or three 
+//  quotation marks ("""), and ends with the next subsequent appearance of its 
opening delimiter.
+//
+// - Implemented
+//
+//
+//  3.7. Text fields
+//
+// [CIF 2.0 adopts] a text prefixing protocol (see §5.2[link]) and 
[incorporates] a version of the CIF 1.1 line-folding protocol
+// for text fields into the CIF 2.0 specification proper.
+//
+// [and 5.2]
+//  A `prefix' consists of a sequence of one or more characters that are 
permitted in a text field, 
+//  except for backslash (\) or a CIF line terminator, and it does not begin 
with a semicolon. The text prefix protocol 
+//  applies to text fields whose physical content begins with a prefix, 
followed by either one or two backslashes, any 
+//  number of in-line whitespace characters (including none), and a line 
terminator or the end of the field, and 
+//  whose subsequent lines each begin with the same prefix. The line 
containing the terminating semicolon is not 
+//  accounted part of the content for this purpose. Such a text field is 
called a `prefixed text field', 
+//  and the logical (`un-prefixed') content of such a field is derived from 
its physical content by the following procedure:
+//
+// (1) Remove the prefix from each line, including the first.
+// (2) If the remaining part of the first line starts with two backslashes 
then remove the first of them; 
+//     otherwise remove the whole first line.                                  
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                  
+//
+// - Implemented
+//
+//
+//  3.8. List data type
+//
+//  The new `List' data type provided by CIF 2.0 represents, as a single 
(compound) value, an ordered sequence of 
+//  values of any type or types. Syntactically, a List value takes the form of 
a whitespace-separated sequence of 
+//  data values enclosed in square brackets.
+//
+// - Implemented
+//  - Delivers proper JSON strings for lists. 
+//  - Numerical values are converted to integer or float type.
+//  - Trailing uncertainties (nn) removed.
+//
+//
+//  3.9. Table data type
+//
+//  The new `Table' data type provided by CIF 2.0 represents, as a single 
(compound) value, an unordered collection of 
+//  entries representing associations between string keys and data values of 
any type. This sort of data structure is 
+//  also known variously as a `map', `dictionary' or `associative array', 
among other names. Syntactically, a Table value 
+//  takes the form of a whitespace-separated sequence of key–value pairs, 
enclosed in braces. The values may be any CIF data 
+//  value. The keys take the form of quoted or triple-quoted strings as 
described above, with a colon appended immediately 
+//  after the closing delimiter. Keys may be separated from their values by an 
arbitrary amount of whitespace, including none. 
+//
+// - Implemented
+//  - Delivers proper JSON strings after converting keys and data values
+//
+// 
+
   
   /**
+   * Includes all possible operator tokens
+   */
+  @Override
+  protected boolean isQuote(char ch) {
+    switch (ch) {
+    case '\1': // CIF 1.1 encoded multi-line semicolon-encoded string
+    case '\'':
+    case '\"':
+    case '[':
+    case ']':
+    case '{':
+    case '}':
+    case ';':
+      return  true;
+    }
+    return false;
+  }
+
+  /**
+   * preprocess all operators
    * 
-   * @return the next token of any kind, or null
-   * @throws Exception
    */
   @Override
-  public String getNextToken() throws Exception {
-    while (!strHasMoreTokens())
-      if (setStringNextLine() == null)
-        return null;
-    return nextStrToken();
+  protected boolean doPreProcess(char ch) {
+    switch (ch) {
+    case '\1': // CIF 1.1 encoded multi-line semicolon-encoded string
+    case ';':
+      return  true;
+    default:
+      return false;
+    }
   }
 
+  /**
+   * final get for quoted object
+   */
+  @Override
+  protected Object getQuotedStringOrObject(char ch) {
+    return processQuotedString(false);
+  }
 
+  /**
+   * initial processing; returns to string.
+   */
+  @Override
+  protected String preprocessString() {
+    return processQuotedString(true);
+  }
+  
+  private String processQuotedString(boolean isPreprocessing) {
+    String str = null;
+    char quoteChar = this.str.charAt(ich);
+    String tripleChar = null;
+    try {
+      switch (quoteChar) {
+      case '\1':
+        str = this.str.substring(1, (ich = this.str.indexOf("\1", ich + 1)));
+        if (cterm != '\0')
+          str = PT.esc(str);
+        ich++;
+        break;
+      case ';':
+        line = (ich == 0 ? this.str : this.str.substring(ich));
+        str = processSemiString();
+        return setString(str);
+      case '[':
+        str = readListAsJSON(ich + 1);
+        break;
+      case ']':
+        str = "]";
+        ich++;
+        break;
+      case '{':
+        str = readTableAsJSON(ich + 1);
+        break;
+      case '}':
+        str = "}";
+        ich++;
+        break;
+      case '\'':
+      case '"':
+        line = this.str.substring(ich);
+        if (line.indexOf("'''") == 0)
+          tripleChar = "'''";
+        else if (line.indexOf("\"\"\"") == 0)
+          tripleChar = "\"\"\"";
+        int nchar = (tripleChar == null ? 1 : 3);
+        int pt = nchar;
+        int pt1 = 0;
+        str = "";
+        while (line != null
+            && (pt1 = (tripleChar == null ? line.indexOf(quoteChar, pt) : line
+                .indexOf(tripleChar, pt))) < 0) {
+          str += "\n" + line.substring(pt);
+          readLine();
+          pt = 0;
+        }
+        str += (line == null ? "" : line.substring(pt, pt1));
+        setString(line.substring(pt1 + nchar));
+        if (cterm != '\0')
+          str = PT.esc(str);
+        break;
+      }
+    } catch (Exception e) {
+      System.out.println("exception in Cif2DataParser ; " + e);
+    }
+    return str;
+  }
+
+  /**
+   * sets a multiline semicolon-eclipsed string to be parsed from the 
beginning, allowing for
+   * CIF 2.0-type prefixed text lines and removing line folding.
+   * 
+   * ;xxxx\comments here
+   * 
+   * xxxx
+   * 
+   * xxxx
+   * 
+   * xxxx
+   * 
+   * ;
+   * 
+   * @return \1....\1 string
+   * @throws Exception 
+   */
+  protected String processSemiString() throws Exception {
+    int pt1, pt2;
+    String str = preprocessSemiString();
+    // note that this string is already escaped with \1...\1 
+    if (str.indexOf(';') != 1 // "...and it does not begin with a semicolon" 
+        &&(pt1 = str.indexOf('\\')) > 1 && ((pt2 = str.indexOf('\n')) > pt1 || 
pt2 < 0)) {
+      String prefix = str.substring(1, pt1);
+      // remove just the next \ if it is there, or the first full line
+      str = PT.rep(str,  "\n" + prefix, "\n");
+      str = "\1" + str.substring(str.charAt(pt1 + 1) == '\\' ? pt1 + 1 : pt2 < 
0 ? str.length() - 1 : pt2 + 1);
+      // Note: Jmol's CIF 1.0 CifReader does not already recognize "\\\n" as a 
line folding indicator. 
+    }
+    ich = 0;
+    return fixLineFolding(str);
+  }
+
+  public String readListAsJSON(int ichStart) throws Exception {
+    String str = "";
+    ich = ichStart;
+    int n = 0;
+    char cterm0 = cterm;
+    cterm = ']';
+    nullString = null;
+    while (true) {
+      String s = getNextToken();
+      if (s == null || s.equals("]"))
+        break;
+      if (n++ > 0)
+        str += ",";
+      str += s;
+    }
+    cterm = cterm0;
+    str = "[" + str + "]";
+//    if (cterm == '\0')
+//      System.out.println("CIF2 list: " + str);
+    nullString = "\0";
+    return str;
+  }
+
+  public String readTableAsJSON(int ichStart) throws Exception {
+    String str = "";
+    int n = 0;
+    ich = ichStart;
+    char cterm0 = cterm;
+    cterm = '}';
+    nullString = null;
+    while (true) {
+      String key = getNextToken();
+      if (key == null || key.equals("}")) 
+        break;
+      while (isSpaceOrColon(ich))
+        ich++;
+      String value = getNextToken();
+      if (n++ > 0)
+        str += ",";
+      str += key + ":" + value;
+    }
+    cterm = cterm0;
+    str = "{" + str + "}";
+    nullString = "\0";
+//    if (cterm == '\0')
+//      System.out.println("CIF2 table: " + str);
+    return str;
+  }
+    
+
+  private boolean isSpaceOrColon(int ich) {
+    if (ich < cch)
+      switch (line.charAt(ich)) {
+      case ' ':
+      case '\t':
+      case '\n':
+      case ':':
+        return true;
+      }
+    return false;
+  }
+
+  @Override
+  protected String unquoted(String s) {
+    if (cterm == '\0')
+      return s;
+    int n = s.length();
+    if (n > 0) {
+      char c = s.charAt(0);
+      if (PT.isDigit(c) || c == '-' || c == '.' && n > 1) {
+        int pt = s.indexOf('(');
+        // trim off (10)  in 1.345(10)
+        boolean isFloat = (s.indexOf(".") >= 0);
+        if (n > 1 && pt > 0 && s.indexOf(')', pt + 1) == n - 1)
+          s = s.substring(0, pt);
+        try {
+          if (isFloat) {
+            s = "" + Float.parseFloat(s);
+            if (s.indexOf(".") < 0 && s.indexOf("E") < 0)
+              s += ".0";
+            return s;
+          }
+          return "" + Integer.parseInt(s);
+        } catch (Throwable e) {
+          // ignore
+        }
+      }
+    }
+    return PT.esc(s);
+  }
+
+
+  /**
+   * allow white space between \ and \n
+   * @param str
+   * @return fixed line
+   */
+  private String fixLineFolding(String str) {
+    if (str.indexOf('\\') < 0)
+        return str;
+    int n = str.length();
+    if (str.endsWith("\\\1"))
+      str = str.substring(0, n - 1) + "\n\1";
+    int pt = 0;
+    while ((pt = str.indexOf('\\', pt + 1)) >= 0) {
+      int eol = str.indexOf('\n', pt);
+      if (eol < 0)
+        break;
+      for (int i = eol; --i > pt;) {
+        char ch = str.charAt(i);
+        if (!PT.isWhitespace(ch)) {
+          if (ch == '\\') {
+            pt = i;
+            break;
+          }
+          pt = eol;
+          break;
+        }
+      }
+      if (pt < eol)
+        str = str.substring(0, pt) + str.substring(eol + 1);
+    }
+    //System.out.println("fixed: >>" + str + "<<");
+    return str;
+  }
+
+
+
 }

Modified: trunk/Jmol/src/org/jmol/adapter/readers/cif/Cif2Reader.java
===================================================================
--- trunk/Jmol/src/org/jmol/adapter/readers/cif/Cif2Reader.java 2016-11-29 
05:02:30 UTC (rev 21291)
+++ trunk/Jmol/src/org/jmol/adapter/readers/cif/Cif2Reader.java 2016-12-01 
15:04:17 UTC (rev 21292)
@@ -23,28 +23,9 @@
  */
 package org.jmol.adapter.readers.cif;
 
-import java.util.Hashtable;
-import java.util.Map;
-
 import javajs.api.GenericCifDataParser;
-import javajs.util.CifDataParser;
-import javajs.util.Lst;
-import javajs.util.M4;
-import javajs.util.P3;
-import javajs.util.PT;
-import javajs.util.SB;
 
-import org.jmol.adapter.smarter.Atom;
-import org.jmol.adapter.smarter.AtomSetCollectionReader;
-import org.jmol.adapter.smarter.Structure;
-import org.jmol.api.JmolAdapter;
-import org.jmol.c.STR;
-import org.jmol.java.BS;
-import org.jmol.util.BSUtil;
-import org.jmol.util.Logger;
-import org.jmol.util.SimpleUnitCell;
 
-
 /**
  * 
  * Preliminary Cif2 reader. Just a shell. 

Modified: trunk/Jmol/src/org/jmol/adapter/readers/cif/CifReader.java
===================================================================
--- trunk/Jmol/src/org/jmol/adapter/readers/cif/CifReader.java  2016-11-29 
05:02:30 UTC (rev 21291)
+++ trunk/Jmol/src/org/jmol/adapter/readers/cif/CifReader.java  2016-12-01 
15:04:17 UTC (rev 21292)
@@ -233,7 +233,8 @@
      * tokenizer.getTokenPeeked(); continue; }
      */
     if (key.indexOf("_") != 0) {
-      Logger.warn("CIF ERROR ? should be an underscore: " + key);
+      Logger.warn(key.startsWith("save_") ? 
+          "CIF reader ignoring save_" : "CIF ERROR ? should be an underscore: 
" + key);
       parser.getTokenPeeked();
     } else if (!getData()) {
       return true;
@@ -733,7 +734,7 @@
     key = parser.getTokenPeeked();
     data = parser.getNextToken();
     //if (debugging && data != null && data.charAt(0) != '\0')
-    //Logger.debug(key  + " " + data);
+    Logger.debug(">> " + key  + " " + data);
     if (data == null) {
       Logger.warn("CIF ERROR ? end of file; data missing: " + key);
       return false;

Modified: trunk/Jmol/src/org/jmol/adapter/smarter/Resolver.java
===================================================================
--- trunk/Jmol/src/org/jmol/adapter/smarter/Resolver.java       2016-11-29 
05:02:30 UTC (rev 21291)
+++ trunk/Jmol/src/org/jmol/adapter/smarter/Resolver.java       2016-12-01 
15:04:17 UTC (rev 21292)
@@ -385,7 +385,7 @@
   { "P2n", "REMARK   1 P2N" };
   
   private final static String[] cif2StartRecords = 
-  { "Cif2", "#\\#CIF_2.0" };
+  { "Cif2", "#\\#CIF_2" };
   
 
   private final static String[] xmlStartRecords = 

Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2016-11-29 05:02:30 UTC 
(rev 21291)
+++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2016-12-01 15:04:17 UTC 
(rev 21292)
@@ -47,8 +47,15 @@
  -- sets the echo offset to a specific screen pixel offset
  -- TODO not saved in state
 
-Jmol.___JmolVersion="14.7.4_2016.11.28"
+Jmol.___JmolVersion="14.7.4_2016.12.01"
 
+new feature: fully implemented CIF 2.0 reader
+
+new feature: CIF reader allows for [ .... ] array notation
+ -- returned as an unaltered string for CIF 1.x 
+ 
+JmolVersion="14.7.4_2016.11.28"
+
 new feature: MagCIF reader upgraded to new IUCR standard 
  -- see http://comcifs.github.io/magCIF.dic.html
  -- only required these two key changes:
@@ -59,13 +66,6 @@
     // old: _magnetic_space_group.transform_to_standard_Pp_abc
     // new: _space_group_magn.transform_BNS_Pp_abc
       
-new feature: CIF reader allows for [ .... ] array notation
- -- still returned as a string since it can contain error bars:  [0.24(05) 
0.34(10)]
-
-new feature: CIF 2.0 reader
- -- just a class extension for now
- -- no difference from CIF 1.1 yet
- 
 JmolVersion="14.7.4_2016.11.22"
 
 new feature: adds MagCIF reader based on 
http://comcifs.github.io/magCIF.dic.html

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
_______________________________________________
Jmol-commits mailing list
Jmol-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jmol-commits

Reply via email to