skip to main content NIST Center for Neutron Research NIST Center for Neutron Research National Institute of Standards and Technology
Home Live Data Instruments CHRNS Proposals

Details of the BROWSECIF Routines

This web page documents the routines found in the browsecif.tcl file that are used in EXPGUI, CIFEDIT and pdCIFplot.

Utility Routines

The MyMessageBox routine is used as an alternate to the usual Tk dialog boxes as it has more versatility.

The pleasewait and donewait routines are used to put a temporary message ("Please wait while...") and then remove this message from the screen. The optional first argument to pleasewait is a message to be displayed and the optional second argument is a the name of a global variable that will be displayed on the bottom of the message to show the status of the program.

The FixBigOptionMenu routine is used to create tk_optionMenu widgets that have too many items to fit on the screen. The AddSpecialEnumOpts routine adds the two specially defined placeholders, "?" and "." to tk_optionMenu widgets.

CIF Parsing Routines

The ParseCIF routine optionally reads a file and loads the contents into a text widget (variable txt). The contents of the text widget is then parsed. The routine uses some commands that are not present in Tcl/Tk versions before 8.2, so an error message is generated if an older version of Tcl/Tk is used.

Several variables are initialized before the CIF parsing is started:

defines a pointer to how far the file has been parsed. The initial value, 1.0, means the 0th (first) character in the 1st line.
defines the block number for the current block. It is incremented every time that a "data_" prefix is encountered. This means that if any CIF data times preceed a data_ line, they are placed in block #0.
the name of the currentlt processed CIF data name (if any). This variable serves as a state variable to indicate if a data name has been read and now a value is expected.
The value in each CIF data time is assigned a identifier to locate and change the value. The variable CIF(markcount) store the number that was last used.
is a state variable used to define what region of the CIF is being parsed with respect to loops. When the "loop_" keyword is encountered, loopflag is set to 0, to indicate that the data names in a loop header are being processed and if loopflag is set >0 then the values in the loop are being processed.
is a counter for the number of loops that have been encoutered. This is reset each time a new block is read.
is the maximum number of CIF data values that can be read and is set from variable CIF(maxvalues) if defined. If not, the default value, 0, means do not set a maximum number of data values.

The parsing loop is then started. Note that a considerable amount of error checking is performed in this loop This is well commented and will not be described further here. The pos variable is advanced to the first non-blank token from the current position. If there are none pos is set to blank and the loop terminates. The routine then returns a list of the block number that were read.

If the non-blank character is a "#" then the remainder of the line is a comment, so the pos variable is advanced to the beginning of the next line. Otherwise, the next non-blank character is located and variable token is set to the string. If the string starts with "data_" (with any combination of upper or lowercase letters) this indicates the beginning of a data block. If the string starts with an underscore (_), then the string is a CIF data name. If the string starts with "loop_" then this indicates the start of a loop. If anything else is found, this indicates the beginning of a data value and the various quoting schemes are checked. A semicolon at the start of a line requires the parser to scan forward for a matching semicolon. A string starting by a single quote (') or a double quote (") then the parser scans forward for a matching quote before the end of the line. Note that CIF does not treat a quote followed by a non-blank character ("A quote"d string") as a close quote. CIF v1.1 will support square bracket ("[" and "]") as quotes, so this is also parsed. If no quotes are found, then the data value is delimited by non-blank characters. Each data value is assigned an item number [CIF(markcount)] where marks $CIF(markcount).l and $CIF(markcount).r define the beginning and end of the value.

Note the use of state variables loopflag and dataname. When a dataname is read, the name is saved in variable dataname. When the associated value is read, variable blockn($dataname) is defined as a pointer [$CIF(markcount)] to the location for the value. When a loop_ is encountered, then variable loopflag is set to 0 and then all following data names are read and are appended to variable looplist until a value is found, which indicates that the loop header is complete, so loopflag is incremented. The data names in the list are saved as blockn(loop_m) and variable blockn($dataname) is assigned a list of pointers to all the data items in the list. Encountering a data name while loopflag is >0 indicates that the loop has ended.

The BrowseCIF routine creates a CIF browser/editor window and fills the window using the CIFOpenBrowser and CIFBrowser routines. The CIFOpenBrowser routine creates the browser window using a BWidget paned window and by inserting scrolled frames on each side. The CIFBrowser routine creates a hierarchical representation of the data names and loops in the CIF in the left-hand side of the panel. Clicking on a entry invokes routine showCIFbyTreeID. Note that each item in the tree has a name and a data value. The first entry in the name is the data name for the entry, or name for the loop. The pointer indicates the block where the data item is found, as well as either "loop" for a loop reference or the data name, for a loop name for the data names in loops.

The showCIFbyTreeID routine first calls CheckForCIFEdits to see if the values in the widgets have been edited, using routine CheckChanges, which also ensures edited values are valid with respect to the requirements of the CIF dictionary using routine ValidateCIFItem, which in turn calls the ParseSU routine to parse numbers, and if present uncertainty values. When changes are valid, the SaveCIFedits routine is used to insert the changed values into the in-memory copy of the CIF. The ReplaceMarkedText routine is called by SaveCIFedits to save the information to be changed in the undo list [CIF(undolist)] and then makes the change.

The showCIFbyTreeID routine looks up the information about the selected CIF data item or loop and then highlights the entry in red to show that it has been selected. The showCIFbyDataname routine is then called to display the contents of the selected item(s). The RepeatLastshowCIFvalue routine is used to redisplay the last set selected set of entries. This is used, for example, when the editing mode is switched.

The showCIFbyDataname routine calls a number of other routines. Routine DisplayCIFvalue displays the actual values. The way the information is displayed depend on the current editing mode [CIF(editmode), where true = edit, false = browse]. The ShowLoopVar routine is used to select which "row" of a table is displayed when an entire loop is selected. The ShowDictionaryDefinition routine displays the dictionary definition (or definitions, in the case where a loop is displayed) in the "CIF Definition Window." The GetCIFDefinitions routine is used to compile the definitions and the ReadCIFDefinition routine is used to obtain the definition from the CIF dictionary. Note that the definition(s) are obtained even if the definition window is currently hidden so that the appropriate definition(s) are present even whenever the window is revealed. The StripQuotes routine is used to remove quotes, if present from strings before they are displayed.

When an entire loop is open for editing, two buttons are available for modifying the loop contents. The AddToCIFloop routine will add a new "row" at the end of the loop. The values for the data items are set to '?'. Likewise, the DeleteCIFRow routine will confirm that the currently displayed row should be deleted and if confirmed will delete the row.

The UndoChanges routine is used to reverse edits made to the CIF. If edits are "undone" with UndoChanges, they can be restored with the RedoChanges routine.

The ValueFromCIF routine routine is used to look up a CIF data item in a specified block and strip quotes, if used. If a data item is not present a blank value is returned. Note that numbers may still need to be parsed using the ParseSU routine.

The MarkGotoLine routine is used within the CIF contents display to display a particular line in the display. This is useful for finding the locations of errors reported by the CIF parser.

Comments, corrections or questions:
Last modified 25-July-2003 by website owner: NCNR (attn: ) $Revision: 1.1 $ $Date: 2003/01/06 17:16:21 $