#

# Appendices

Python code in leo.py
Error messages
Future directions
Glossary
Sentinel lines
Transferring Leo files between Macintosh and PC
XML file format
XML file format 1
XML file format 2
An example Leo file
DTD

## Python code in leo.py

leo.py contains Python code that may be of interest to some Python programmers. The following paragraphs describe this code briefly.

#### c2py.py

This script does much of the grunt work of converting from C/C++ syntax to Python syntax. It was surprisingly effective in converting Leo from C++ to Python. These scripts don't need to be perfect to save a lot of work. And of course you can always add your own improvements...

As written, the script converts an entire Leo tree. It would be easy to write an entry that would convert plain text files, but it's probably best to import the files to be converted into Leo first. That way the slow algorithms in c2py.py will work on smaller pieces of text.

#### disStats.py

This code gathers and prints static statistics about Python bytecode.

#### Tkinter utilities

leoUtils.py contains the following Tkinter utilities:

`w,h,x,y = get_window_info(top)` returns the width, height, x and y positions of the Tkinter window top.

`center_dialog(top)` centers the Tkinter window top on the screen.

`w,f = create_labeled_frame(parent...)` creates a labeled Tkinter window as a child of parent. The caller packs widgets into f to create the frame.

leoUtils.py contains many other routines, including an Python version of the Sherlock tracing package.

#### Font dialog

leoFontPanel.py puts up a Font dialog. This dialog dispenses with the typical "sample" pane and instead changes text immediately directly on the screen. Comes with Ok, Cancel and Revert buttons.

#### Syntax coloring code

leoColor.py contains code to syntax color Tk.Text widgets for a variety of languages. Supporting a new language here is mostly a matter of adding another table of keywords.

#### Tree code

Leo supports powerful outlining features, including clones. Clones are challenging to implement, to say the least. The vnode and tnode classes, defined in leoNodes.py, represent the underlying data. vnodes represent nodes on the screen. vnodes may share text, the tnode class is the "unit of sharing" of such text. The leoTree class draws the tree and handles events, including dragging nodes around the screen. The Commands class calls the vnode, tnode and leoTree classes to handle menu commands. In Smalltalk's model/view/controller terminology, the vnode and tnode classes are model classes, the leoTree class is a view class, and the Commands class is a controller class.

## Error Messages

The Tangle commands write the following error messages to the log window.

    Can not reopen temp file.

> A file error occurred while trying to reopen the temporary file used during tangling

    Can not rename temporary file name.

> A file error occurred while trying to change the name of the temporary file used during tangling.

    @code expects the header: text of header to contain a section name.

> An `@code` directive appeared in body text whose header does not contain a section name. This warning is given only in @root trees. Unnamed nodes are valid in @file trees.

    @directive not valid here.

> An @directive was seen somewhere other than the start of a line.

    Code expected after section definition.

> A code section contained no text.

    Halting Tangle: too many errors.

> Tangle detected more than 20 errors.

    Invalid recursive reference of << section name >>.

>     called from << section name >>
>     called from << section name >>
>     ...

> A section was defined in terms of itself, either directly or indirectly. The trace shows the chain of section definitions that resulted in the illegal definition.

    Multiple parts not allowed for << section name >>.

> Sections can be defined in several parts in two ways:

> 1. Using << section name >>= in several places with the same section name.

> 2. Using several @code directives within the same body text.

> As a precaution against mistakenly defining a section in more than one place, it is invalid to use @code in different nodes to define multiple parts for the same section. In particular, this error may arise when using cloned nodes. This error may always be eliminated by using << section name >>= instead of @code.

    No file written because of errors.

> Tangle did not write a file because errors were found.

    Run on comment.

> A comment was not properly terminated.

    Run on file name in @root directive.

> The file name in an @root directive was not terminated with the proper delimiter.

    Run on section name.

> A section name was not properly terminated before the end of the line in which it started.

    Run on string.

> A string or character constant was not properly terminated.

    Section definition not valid here.

> Something that looks like a section definition was seen in the middle of a line.

    Sections nested too deeply.

> A section was defined using more than 100 levels of section definitions (!)

    The outline contains no roots.

> The selected outline contained no `@root` directive.

    Undefined section: << section name >>.

> A reference to an undefined section was encountered.

    Unexpected @directive while putting code.

> Tangle outputs 2-character WEB control code in a comment. This message is given if we find such comments in a code definition.

    Warning: possible duplicate definition of: << section name >>.

> (The text of the duplicate definition follows.)

    Warning: << section name >> has been defined but not used

> The indicated section name has been defined but not used.

## Future directions

#### Styled text and graphics

Except for syntax coloring, there is no way to style text in an outline. The ultimate would be for Leo to support arbitrary XML code in the body pane. Perhaps someday Tk's text panes will allow this.

## Glossary

@root node, @file node, @ignore node, @others node, etc.

> We often refer to outline nodes by the directives they contain. For example, an @root node is a node containing an @root directive, an @ignore node is a node containing an @ignore directive, and so on. Exception: an @file node is a node whose headline starts with @file.

@root tree, @file tree, @ignore tree, @others tree, etc.

> An @root tree is a tree whose is an @root node, @file trees are trees whose root is an @file node, and so on.

    Body pane

> The pane containing the body text of the currently selected headline in the outline pane.

    Body text

> The text in the body pane. Body text is always associated with a particular headline.

    Body text box

> A small box near the leader character of a headline that indicates that the node contains body text.

    Child

> A node directly contained by a node.

    Chunk

> Another name for a section or part.

    Clone

> A copy of a tree that changes whenever the original changes. The original and all clones are treated equally: no special status is given to the "original" node.

    Clone arrow

> A small arrow near the leader character of a headline that indicates that the node is a clone of another node.

    Code section

> A section containing code. Code sections start with `@c` or `@code` directives.

    CWEB

> A literate programming language invented by Donald Knuth and Silvio Levy. CWEB produces derived files for the C language. http://www-cs-faculty.stanford.edu/~knuth/cweb.html

    Demote

> To move left all following siblings of a node so that they become children of a node.

    Derived file

> The output file created as the result of tangling a node containing an `@root` directive. The file consists of the expansion of the text following the `@root` directive.

    Descendant

> An offspring of a node. That is, a child, grandchild, etc. of a node.

    Directive

> A line of body text that starts with `'@'` followed by whitespace or a newline, or `'@'` followed by the name of a directive. The valid directives are `@`, `@c`, `@code`, `@comment`, `@color`, `@delims`, `@doc`, `@ignore`, `@language`, `@nocolor,` `@root` and `@unit`.

> Note: we speak of @file nodes, and strictly speaking there is no @file directive. Rather, an @file node is a node whose headline starts with @file.

    Doc section

> A section containing only documentation. That is, a section that start with `@.` Doc sections are associated with the immediately following code section, if any.

    Edit box

> A box drawn around the currently selected headline in the outline pane. Only the currently selected headline text may be edited.

    Escape convention

> A convention for representing sequences of characters that would otherwise have special meaning. Leo has only one such convention: in @root trees, @@ in the leftmost column of a code part stands for a single @ character.

> Note: the markup language Leo uses in body pane is based on noweb. However, Leo does not support noweb's @<< and @>> escape conventions. If a line in a code part contains << followed by >>, then that line does contain a section name, regardless of context. If the << and >> characters should not, if fact, delimit a section name, then you must place the << and >> on separate lines.

> Eliminating noweb's escape conventions for << and >> characters solves some difficult problems when automatically untangling derived files. Moreover, it is typically easier to split source lines than to use @<< and @>>. Finally, Leo's Export and Import commands do support the @<< and @>> conventions.

    Grandchild

> The child of a child of a node.

    Headline

> The organizational unit of an outline. A node. Each headline contains headline text and body text, either of which may be empty.

    Leader character

> A plus or minus sign preceding headline text. A plus indicates that the node contains children. A minus indicates that the node contains no children. A small arrow indicates that the node is a clone of another node. A small box, like or , indicates that the node contains body text.

Leo, Leo1 and Leo2

> Leo stands for Literate Editor with Outlines. That is, Leo supports both literate programming and outlining.

> Leo1 denotes all versions of Leo that write version 1 .leo files, that is, all Windows version of Leo prior to version 2.0. The last version of Leo1, version 1.15, understands enough about Leo2 to issue a warning when opening version 2 files.

> Leo2 denotes all versions of Leo that write version 2 .leo files, that is, all versions of leo.py and all Windows versions with version number 2.0 and above. Only Leo2 can generate derived files from @file trees.

    Literate programming

> A style of programming invented by D. E. Knuth that aims at producing the highest quality program listings. Literate programming languages apply two fundamental operations to text: weaving and tangling. Leo supports two literate programming languages, CWEB and noweb. Knuth's book is a good introduction to literate programming.

    Marking

> Marking a node by placing a red mark near its leader character. Marks can be placed using the Mark command, as the result of Find and Change commands, or as the result of the Mark Changed Roots and Mark Changed Items command. The Tangle Marked command tangles only those subtrees that are marked.

    Named node

> Within an @file tree, a node that contain a section name, like <<x>>, at the start of its headline text. Within an @file tree, all nodes containing a section reference must have a descendent named node corresponding to the reference.
> Within an @root or @unit tree, an @code directive is an abbreviation for <<x>>=, where << x >> is found in the headline.

    Node

> The organizational unit of an outline. The combination of a headline and body text.

noweb

> A simple literate programming language invented by Norman Ramsey. noweb can produce derived files for any text-based programming language. http://www.eecs.harvard.edu/~nr/noweb/ Noweb forms the basis for the markup language used in Leo's body pane.

    Offspring

> The children, grandchildren, etc. of a node. The descendants of a node.

    Organizing node

> An unnamed node in an @tree that contains no body text. Such nodes may appear anywhere in an @file tree; they do not affect the derived file in any way. In particular, organizing nodes do not affect indentation in the derived file.

    Orphan node

> An unnamed node in an @file tree that can not be placed in the file derived from the @file node. This can happen for two reasons: the orphan node may not descend from any @others node, or a named node may intervene between the orphan node and an @others node.

> Orphan nodes prevent Leo from tangling or untangling @file trees. Leo issues a warning and saves the @file tree in the .leo file so that no information is lost.

    Outline

> 1. A visual representation of a hierarchy on the screen.
> 2. The data contained by the hierarchy.

> Outlines are composed of headlines representing data. The combination of a headline and its associated body text is called a node.

    Outline pane

> The pane containing a visual representation of outlines.

    Parent

> The node that directly contains a node.

    Part

> Another name for a section or chunk.

    .pdf file

> A file that can be read by Adobe Acrobat Reader. Leo's documentation files are best read with version 3.01 of Acrobat Reader.

    Promote

> To move all children of a node left in an outline so that they become siblings of the node.

    Root

> The node from which all the nodes of a subtree descend. For example, the root of an @file tree is an @file node. Note: both the Windows version of Leo and leo.py allow an outline to have multiple top-level nodes, so outlines may have multiple roots.

    Scope

> The portion of the outline in which a section definition is known. By default the scope of a section definition is the smallest subtree containing both the section and a node containing an `@root` directive. The `@unit` directive declares that the subtree containing the `@unit` directive is the scope for all sections defined in that tree.

    Section

> A fragment of code that can be incorporated into derived files. A syntactic unit of body text..

> There are two kinds of sections: code sections and doc sections. Sections are defined in slightly different ways in @file in @root trees (that's the difference between the two kinds of trees.)

> In @file trees
> Code sections start with the @c directive. The entire body text of a node is a code section by default, so the @c directive can be omitted if there are no doc sections in the body pane. Doc sections start with @ followed by a space at the start of a line. Doc sections continue until the end of body text or until the next @c or @(space) directive.

> In @root trees
> Code sections start with the @c directive or section definition lines of the form:

> > `<< section name >>=`

> Such lines begin named code sections. Other code sections are unnamed. Doc sections start with @ followed by a space at the start of a line. Doc sections continue until the end of body text or until the next @c or @(space) directive.

    Section name

> A name enclosed in << and >>. Section names may contain any characters except newlines and ">>".

    Section reference

> A section name appearing in a code part. Tangling replaces all references by their definitions.

    Sentinels, Sentinel lines

> Comment lines in files derived from @file nodes. Such lines start with an @ following the opening comment delimiter. Sentinels embed outline structure into derived files. Do not alter such lines! Doing so can corrupt the outline structure.

    Sibling

> Nodes with the same parent are siblings.

    Status Icon

> The icon that appears just to the left of headline text in the outline pane. This icon shows: a blue body text box if the node contains body text, a red clone arrow if the node is cloned, and a red marker bar if the node is marked. The icon is outlined in black if the node is dirty, that is, if the node has been changed since the file was last change.

    Tangling

> The process of creating derived files from @root or @file trees. Leo tangles @file automatically when writing a .leo file. The user must explicitly tangle @root trees using the Tangle command. Tangling expands all references in an @root node or @file node.\

    Target language

> The language used to syntax color text. This language determines the default comment delimiters used during tangling and untangling.

    Tree, subtree

> Another name for an outline. A subtree is another name for a node and all its descendants.

    Untangling

> The process of updating @root or @file trees an based on changes to derived files. Untangling allows changes to be propagated from derived files back to the outline. Leo untangles @file automatically when reading a .leo file. The user must explicitly untangle @root trees using the Untangle command.

    Weaving

> The process of creating typeset documentation from a noweb or CWEB source file. Weaving creates documentation. Tangling creates source code files known as derived files.

> Leo does not support weaving directly. If you want to weave a file you can create noweb or CWEB files using Leo's export commands, then use the noweb or CWEB systems to weave those files.

## Sentinel lines in @file trees

The following sections describe sentinel lines embedded in files derived from @file trees. Sentinel lines are also generated by the Tangle command in files derived from @root trees. Such sentinels have a different format and are discussed in the next section.

It is not necessary to understand this section in order to use @file trees. All you need to know is this:

1. Sentinel lines are comment lines whose first character (after the comment delimiter) is @.
2. Do not alter sentinel lines in derived files. Doing so will corrupt the outline structure!

#### @leo sentinel and comment delimiters

A file produced by an @file node begins with an @+leo sentinel. This sentinel has the form:

> `<opening_delim>@+leo<closing_delim>`

The last lines of the file should be the matching @-leo sentinel:

> `<opening_delim>@-leo<closing_delim>`

The comment delimiters that delimit all sentinels are specified by the first line of the file, that is, the @+leo sentinel.

<closing_delim> may be empty, in which case single-line comments are used. The Write code generates single-line comments if possible. Presently, the Save Command generates single line comments for all languages except HTML. Block comments can be specified using the @comment directive if so desired.

#### @node sentinel

Suppose the parent node of a node N is P and that P has n children. The sentinel

> `@+node:<child_index>:<status_fields>:<headline>`

begins the expansion of node N. The expansion continues until a matching sentinel:

> `@-node:<child_index>:<status_fields>:<headline>`

The <child_index> field is a number from 1 to n indicating the index of the node in the list of its parent's children.

The <status_field> field the cloneIndex field of the form: "C=nnn", where nnn is an immutable clone index.

The <headline> field contains headline text, not reference text.

The indentation of the expansion is increased by the extra indentation of preceding the reference. tree level never affects indentation level.

#### @body sentinel

If a node contains significant (non-whitespace) body text, @+body and @-body sentinels surround the text. These sentinels are nested within @node sentinels.

#### @at and @doc sentinels and the trailing whitespace convention

+doc and @-doc sentinels delimit doc parts within a node that start with @doc. These sentinels are nested within @body directives. Similarly, @+at and @-at sentinels delimit doc parts within a node that start with @<whitespace>.

Leo2 uses the following convention to determine where the Save command has inserted line breaks: A line in a doc part is followed by an inserted newline if and only if the newline is preceded by whitespace. To make this convention work, the Save command deletes the trailing whitespace of all lines that are followed by a "real" newline.

#### @others sentinel

@+others indicates the start of the expansion of an @+others directive, which continues until the matching @-others. @others sentinels are nested within @body sentinels; the expansion of the @others directive always occurs within the body text of some node N.

#### @@<text> sentinel

The @@<text> sentinel represents any line starting with @ in body text except @<whitespace>, @doc and @others. Examples:

> @@nocolor @@pagewidth 80 @@tabwidth 4 @@code

#### @verbatim sentinel

@verbatim indicates that the next line of the derived file is not a sentinel. This escape convention allows body text to contain lines that would otherwise be considered sentinel lines.

#### @<<section name>> sentinel

@<<section_name>> sentinel represents a section reference. (The angle brackets are part of this sentinel.) If the reference does not end the line, the sentinel line ending the expansion is followed by the remainder of the reference line. This allows the Open Command to recreate the reference line exactly.

## Sentinel lines in @root trees

The following paragraphs describe sentinel lines embedded in files derived from @root trees. Sentinel lines also appear in files derived from @root trees. Such sentinels have a different format and are discussed in the previous section.

It is not necessary to understand this section in order to use the Tangle and Untangle commands. All you need to know is this:

1. Sentinel lines are comment lines that contain a section name.
2. Do not alter sentinel lines in derived files. Doing so will make defeat the Untangle command.

The Tangle command indicates where sections begin and end using comment lines called sentinel lines. When outputting C code, the beginning sentinel line has the form:

    	/// <<section name>>

When outputting C code, the end sentinel line has the form:

    	/// --end-- <<section name>>

Other information may appear in a sentinel line after the `<<section name>>`. Sections that contain multiple parts in the outline have beginning sentinels of the following form:

    	/// <<section name>> (3 of 7)

Finally, an end sentinel line may end with (!newline), indicating that the section reference in the original outline did not end the line on which it appears. The (!newline) allows Untangle to end references to sections properly. For example, consider the code in an outline:

    	case '\n': <<handle a newline>> break ;

In the derived file, the expansion of `<<handle a newline>>` will appear, terminated by the following two lines:

    	/// --end-- <<handle a newline>> (!newline)
    	break ;

We can't end the end sentinel line with 'break;' because 'break;' would be part of the /// comment! So the (!newline) construct tells Untangle to place the line following the end sentinel on the previous line in the outline. Finally, the Tangle command inserts the whitespace that appears between >> and break ; in the outline after the (!newline). This allows Untangle to get the spacing correct when recreating the code in the outline.

Expansions may appear many times in the same derived file: there is no such thing as a "duplicate definition" of a section in a derived file. Some expansions may occur with (!newline) and some without. To repeat: the (!newline) property is associated with section references, not section definitions.

## Transferring Leo files between Macintosh and PC

1. Create a text file in MORE format.

On the Mac, simply copy an outline in Leo and paste into a text file. I use the Metrowerks IDE to create the text file because it handles newlines properly, but almost any text editor will do. Use the text editor to create the text file.

On the PC, use the Export More Text command, then paste the text into any text editor and use the text editor to create the file.

2. Transfer the text file to the other machine.

3. Create an outline using the text file created in step 1.

On the Mac, load the text file into a text editor. Select all the text and copy it to the clipboard. In Leo, choose the Copy Outline command to create the outline.

On the PC, load the text file into a text editor. Select all the text and copy it to the clipboard. In Leo, choose the Import More Text command to create the outline.

## XML file formats

The following sections describe the formats used by various versions of Leo.

### XML file format 1

This Appendix describes the first version of Leo's XML file format, used in Leo 1 (all Windows version of Leo prior to version 2.0). This technical information will be of use only to those wanting to process Leo files with special-purpose filters.

The following sections describe this format in detail. The last paragraphs gives an example, and it will be useful to refer to this example frequently. In the description below sss denotes a string with the XML escapes for the & < and > characters:

- & becomes &amp;
- < becomes &lt;
- > becomes &gt;

This translation is performed on any text that could contain the & < or > characters.

For those of you who grok DTD's a preliminary DTD for Leo's XML concludes this chapter. This DTD is under development and may contain syntax or semantics errors. It may also simply be inaccurate.

    <?xml ... ?>

Leo files start out with the following line declaring the format to be formatted as a type of XML.

    <?xml version="1.0" encoding="UTF-8"?>

<leo_file> ... </leo_file>

The <leo_file> tag opens an element that contains the entire file. The </leo_file> tag at the end of the file ends this element.

The following paragraphs describe the elements that may appear between the <leo_file> tag and the </leo_file> tag. These elements must appear in the order given. However, the clone_windows element is optional.

    <leo_header ... />

The file header element specifies information used to parse the file or to allocate data structures needed to read the file. The header starts with <leo_header and ends with /> In between are the following four required attribute fields.

> file_format="1" indicates the version number of the file format: 1, 2, 3, etc.

> tnodes="2" indicates the number of tnodes that appear in the file.

> max_tnode_index="2" indicates the largest tnode index.

> clone_windows="0" indicates the number of clone windows specified by the file.

I'll say more about tnodes later.

    <globals ... > ... </globals>

The globals element specifies information relating to the entire file. This element starts with the following the <globals body_outline_ratio="0.50"> tag and ends with </globals> tag.

The body_outline_ratio attribute specifies the ratio of the height of the body pane to the total height of the Leo window. It initializes the position of the splitter separating the outline pane from the body pane.

In between the <globals...> tag and the </globals tag> are the following two elements. These specify the position of the Leo window and Log window in global coordinates:

  `<global_window_position`
    `top="27" left="27" height="472" width="571"/>`
  `<global_log_window_position`
    `top="183" left="446" height="397" width="534"/>`

    <preferences ... > ... </preferences>

The preferences element specifies the preferences that the user can change using the Preferences command. It starts with the <preferences...> tag and ends with </preferences> tag.

The following three attributes may appear before the > that ends the <preferences...> tag.

  `allow_rich_text="1"`
  `tab_width="4"`
  `page_width="132"`

At present the "Allow Rich Text" option is non-functional.

Following the <preferences...> tag is the following element.

    <syntax_prefs>sss</syntax_prefs>

The sss string encodes the settings of the TSyntaxMemo component used for body text. This string is simply passed to and from TSyntaxMemo and is not used by Leo in any other way. Future version of TSyntaxMemo will allow more settings to be encoded, and those settings will appear between the <preferences...> and </preferences> tags.

    <find_panel_settings ... > ... </find_panel_settings>

The find_panel_settings element specifies the settings of the Find panel at the time the file was saved. This element starts with the <find_panel_settings...> tag and continues until the </find_panel_settings> tag.

Zero or more of the following attributes may appear before the > that terminates the <find_panel_settings...> tag. Leo writes these attributes in the order shown, but they may appear in any order.

  `whole_word="1"`
  `search_body="1"`
  `whole_word="1"`
  `ignore_case="1"`
  `pattern_match="1"`
  `search_headline="1"`
  `search_body="1"`
  `suboutline_only="1"`
  `mark_changes="1"`
  `mark_finds="1"`
  `reverse="1"`

The default for all attributes is "0" (unchecked check box) and an attribute is written only if is "1" (check check box).

The following elements appear after the <find_panel_settings> tag and before the </find_panel_settings> tag.

  `<find_string>sss</find_string>`
  `<change_string>sss</change_string>`

The sss strings indicate the find and change strings in the Find panel. Either sss string may be empty. Both sss strings are encoded with the usual XML escapes.

    <vnodes>...</vnodes>

The vnodes element specifies the list of so-called vnodes of an outline.

The vnodes element starts with <vnodes...> and ends with </vnodes>. In between these tags are one or more v elements.

    <v...> ... </v>

The v element represents a single vnode and has the following form:

>     <v...><vh>sss</vh> (zero or more nested v elements) </v>

The vh element specifies the headline text. As usual it starts at the <vh> tag and continues until the </vh> tag. sss is the headline text encoded with the usual XML escapes.

As shown above, a v element may contain nested v elements. Each vnode corresponds to a headline on the screen, and vnodes are written to the file in the order they would appear on the screen if all headlines were fully expanded.

The nesting relationship between vnodes gives the outline structure. v elements for child vnodes are nested within the v elements of parent vnodes. Therefore, the outline level of a v element is the number of unclosed v elements containing it.

Zero or more of the following three attributes may appear before the > that terminates the <v...> tag.

  `t="T23"`
  `vtag="V18"`
  `a="xxxx"`

The t="Tnnn" attribute specifies the tnode associated with this vnode. (See the section describing the <t> tag for more details.

The vtag="Vnnn" attributes specifies the vtag number for this node. This tag is specified only if a clone window exists for this vnode.

The a="xxxx" attribute specifies vnode attributes. The xxxx denotes one or more upper case letters whose meanings are as follows:

  C The vnode is a clone.
  E The vnode is expanded so its children are visible.
  M The vnode is marked.
  T The vnode is the top visible node.
  V The vnode is the current vnode.

For example, a="CEM" specifies that the vnode is a clone, is expanded and is marked.

    <tnodes> ... </tnodes>

The tnodes element specifies the list of tnodes of an outline. The tnodes element starts with <tnodes...> and ends with </tnodes>. In between these tags are zero or more t elements.

    <t...> ... </t>

The t element represents a single tnode. Each tnode represents body text. Because of cloning, a tnode may be shared among several vnodes. tnodes have the following form:

>     <t...><tb>sss</tb></t>

The tb element specifies the body text. As usual it starts at the <tb> tag and continues until the </tb> tag. sss is the headline text encoded with the usual XML escapes.

The tx="Tnnn" attribute must appear before the > that terminates the <t...> tag. It specifies the tnode index of the tnode. Vnodes refer to this index in their t="Tnnn" attribute.

The rtf="1" attribute may appear before the > that terminates the <t...>tag. If present it specifies that body text is encoded as Rich Text Format. This attribute is not used at present.

    <clone_windows> ... </clone_windows>

The clone_windows element is optional. If present it specifies the list of cloned windows of an outline.

The clone_windows element starts with <clone_windows> and ends with </clone_windows>. In between these tags are one or more clone_window elements.

    <clone_window ...> ... </clone_window>

The clone_window element specifies a single clone window to be opened when the file opens.

The clone_window element has the following form:

    	<clone_window vtag="Vnnn">
    		<global_window_position top="nnn" left="nnn" height="nnn" width="nnn" >
    	</clone_window>

All attributes and elements shown above are required.

The vtag attribute must match the vtag attribute in some vnode, and associates the clone window with the vnode.

The global_window_position element specifies the size and position of the clone window. The top and left attributes specify the position of the clone window in global coordinates. The height and width attributes specify the size of the clone window.

### XML file format 2

Version 2 of Leo's XML file format is used by Leo 2 (all versions of leo.py and all Windows versions of Leo with version number 2.0 and above). Version 2 exists to support @file trees. Versions 1 and 2 is almost identical. The only differences are:

1. The version number field in the header is 1 for version 1 files and 2 for version 2 files. This allows Leo1 to issue an important warning if a version 2 file is opened.
2. In version 2, vnodes contain a cloneIndex field, which records the immutable clone indices found in derived files.
3. In version 2, vnodes contain a new attribute byte, the "O" (orphan) attribute.

Leo1 can open Leo2 files, but Leo1 ignores all information unique to Leo2. However, Leo1 treats @file nodes as regular outline nodes: Leo1 neither reads derived files when outlines (.leo files) are loaded nor writes derived files when outlines are saved.

### An example Leo file

The following is the text of an actual leo file.

    <?xml version="1.0" encoding="UTF-8"?>
    <leo_file>
    <leo_header file_format="1" tnodes="4" max_tnode_index="4" clone_windows="0"/>
    <globals body_outline_ratio="0.499">
    	<global_window_position top="54" left="54" height="550" width="559"/>
    	<global_log_window_position top="2" left="630" height="397" width="336"/>
    </globals>
    <preferences allow_rich_text="0" tab_width="4" page_width="72" tangle_bat="0" untangle_bat="0">
    	<TSyntaxMemo_options>DBSoft6:OPT#8#67100656GWD#1#0GCL#11# 2147483633WRC#1#0IDS#1#1WRO#3#&gt;|:FON#11#Courier NewFOS#1#9STC#8#16777215STB#7#8388608TBC#0#TBD#1#4EFF#323#18,0,0,16777215,;3,0,16777215,;4,8421504,16777215,;5,0,16777215,;6,255,16777215,;10,16711680,16777215,;11,0,16777215,;12,16711680,16777215,;14,16711680,16777215,;15,255,16777215,;16,16711680,16777215,;17,255,16777215,;18,16711680,16777215,;19,32768,16777215,;30,255,16777215,;32,0,16777215,;33,255,16777215,;36,0,16777215,;GDF#1#0MDF#1#0SDF#1#0BDF#1#0FOC#1#0RMG#1#0LNN#13#MS Sans SerifLNS#1#8LNC#11# 2147483640LNT#1#1LNE#0##END#</TSyntaxMemo_options>
    </preferences>
    <find_panel_settings whole_word="1" search_body="1">
    	<find_string>error</find_string>
    	<change_string></change_string>
    </find_panel_settings>
    <vnodes>
    <v t="T1" a="TV"><vh>Headline 1</vh>
    <v t="T2" a="E"><vh>Headline 2</vh>
    <v><vh>Headline 3 ( No body text)</vh></v>
    </v>
    </v>
    <v t="T3" a="C"><vh>Headline 4 ( a clone )</vh>
    <v t="T4"><vh>Headline 5</vh></v>
    </v>
    <v t="T3" a="C"><vh>Headline 4 ( a clone )</vh>
    <v t="T4"><vh>Headline 5</vh></v>
    </v>
    </vnodes>
    <tnodes>
    <t tx="T1">Text of headline 1.</t>
    <t tx="T2">Text of headline 2.</t>
    <t tx="T3">Text of headline 4.</t>
    <t tx="T4">Text of headline 5.</t>
    </tnodes>
    </leo_file>

### DTD

Here is the DTD (Data Type Definition) for Leo's XML file format. This DTD has not been tested and it may contain errors.

    <!-- This is a comment -->
    <!-- Version 1 of Leo DTD -->

    <!DOCTYPE LeoOutlineDocumentType [

    <!-- A Leo file consists of the following parts (clone_windows is optional) -->
    <!ELEMENT leo_file (header, globals, prefs, find_settings, vnodes, tnodes, clone_windows?) >

    <!ELEMENT header EMPTY >
        <!ATTLIST header
            file_format     CDATA #REQUIRED  <!-- An integer version number -->
            tnodes          CDATA #REQUIRED  <!-- Unused at present -->
            max_tnode_index CDATA #REQUIRED  <!-- The size of the array used to resolve tnode indices -->
            clone_windows   CDATA 0 >  <!-- Number of clone windows -->

    <!ELEMENT globals (global_window_position? global_log_window_position?) >
        <!ATTLIST globals body_outline_ratio CDATA 0.5 >
        <!ELEMENT global_window_position EMPTY >
            <!ATTLIST global_window_position
                top     CDATA #REQUIRED
                left    CDATA #REQUIRED
                height  CDATA #REQUIRED
                width   CDATA #REQUIRED >
        <!ELEMENT global_log_window_position EMPTY >
            <!ATTLIST global_window_position
                top     CDATA #REQUIRED
                left    CDATA #REQUIRED
                height  CDATA #REQUIRED
                width   CDATA #REQUIRED >

    <!ELEMENT preferences ( syntax_options? ) >
        <!ATTLIST preferences
            <!-- The following specify defaults for preferences -->
    		allow_rich_text  CDATA 0
    		tab_width        CDATA 4
    		page_width       CDATA 132
    		font_name		CDATA "Courier New"
    		font_size		CDATA 9 >
        <!ELEMENT syntax_options (#PCDATA) >

    <!ELEMENT find_settings (find_string? change_string?) >
        <!ATTLIST find_settings
            <!-- The following specify defaults for the find/change panel -->
            batch            CDATA 0
            wrap_around      CDATA 0
            batch            CDATA 0
            whole_word       CDATA 1
            ignore_case      CDATA 0
            pattern_match    CDATA 0
            search_head_text CDATA 0
            search_body_text CDATA 1
            suboutline_only  CDATA 0
            mark_changes     CDATA 0
            mark_finds       CDATA 0
            reverse          CDATA 0 >
        <!ELEMENT find_string   (#PCDATA) >
        <!ELEMENT change_string (#PCDATA) >

    <!ELEMENT vnodes (v*) >
        <!ELEMENT v (vh, v*) >  <!-- The crucial change: vnode may contain other vnodes -->
            <!ATTLIST v
                vtag ID    #IMPLIED       <!-- for use by clone_windows section -->
                t    IDREF #IMPLIED       <!-- the tnode for this vnode, or none -->
                a    CDATA "" >    <!-- V=current, M=marked, C=cloned, E=expanded -->
        <!ELEMENT vh (#PCDATA) >

    <!ELEMENT tnodes (t*)>
        <!ELEMENT t (#PCDATA) >
            <!ATTLIST t
                tx  ID
                rtf CDATA 0 >      <!-- 1 if the #PCDATA is rtf format -->

    <!ELEMENT clone_windows (clone_window*) >
        <!ELEMENT clone_window (global_clone_window_position) >
            <!ATTLIST clone_window
                vref IDREF #REQUIRED >    <!-- the vtag of the vnode that owns this clone window -->
            <!ELEMENT global_clone_window_position EMPTY >
                <!ATTLIST global_clone_window_position
                    top     CDATA #REQUIRED
                    left    CDATA #REQUIRED
                    height  CDATA #REQUIRED
                    width   CDATA #REQUIRED >
    ]