GZigZag spec

$Id: zzspec.wml,v 1.23 2000/09/13 14:54:51 tjl Exp $
Written by
Tuomas J. Lukka
Benjamin Fallenstein
Antti-Juhani Kaijanaho
(add your name here if you do any significant modification)
  1. GZigZag spec
    1. Introduction
    2. The role of ZigZag in the overall scheme of things
    3. Cells, dimensions and connections
      1. Dimension-oriented view
      2. Subspaces, closed cell sets, closures
    4. Key structural mechanisms
      1. Cursors
      2. Inheritable parameter lists
      3. Paths
      4. Selectors
    5. Views
      1. Visible Dimensions
      2. Dimension lists
      3. Raster definition
        1. Vanishing raster
        2. Simple Flob Raster
    6. Primitive operations
      1. Connect
      2. Insert (XXX rename)
      3. Mono-chug
    7. Bindings
      1. Default bindings for the orthogonal rasters
      2. Text edit mode
      3. Curseling (Cursor selection)
    8. Compound spaces
      1. Trivial, kludgy
    9. Notification, events and synchronization
      1. Updating views
      2. Internal triggers
      3. Cursor triggers
    10. Cell storage mechanism
      1. Transient cells
      2. Slices
      3. Versioning
    11. Stable media streams
    12. Blobs
      1. Variables and constants
      2. Dimensions
      3. The structure of a blobview description
      4. A high-level example description of a blobview
    13. ZObs
    14. Email applitude, v1
    15. Interactions
    16. Summary of special dimensions
    17. File format
      1. Runs
        1. Dimension change run
        2. Content change run
        3. Character scroll
      2. Run synchonization
      3. Stream set

Note that this document contains some formatting that is best rendered using a true CSS1 standard-compliant browser such as Mozilla; however, it should work reasonably well with any browser that can at least ignore CSS that it doesn't understand. Unfortunately, Netscape Navigator 4.7, for example, doesn't. Well, that's life...

A non-CSS version exists: you can try by compiling this document from its WML version with some switches.. (if you came here through the WWW, there should be an alternate link on the referring page. However, I like the pretty rendering by Mozilla so much that that's still the default.

Introduction

The purpose of this document is to be a living specification of the features in the GZigZag system. The GZigZag system is an implementation of the ZigZag structure, invented by Ted Nelson. Much of this document is simply a somewhat more verbose version of discussions with him but other places go into more technical detail.

Some parts of this specification are not yet correctly implemented by the current version, but in these cases, this document is correct (or it should be ;-) and the implementation wrong.

Some parts of this spec are at the moment just general ramblings about a topic - once we have the pole editor, I will definitely rearrange it completely. The idea is to try to make them more and more like a true spec as time goes by.

The parts marked with the dreaded triple-X symbol (XXX) are as yet incomplete and should be taken with a not only a grain but a mountain of salt. They mostly contain just a few loose sentences setting the topic.

If you see anything suspicious, feel free to ask me at lukka@iki.fi.

The role of ZigZag in the overall scheme of things

ZigZag is a delightfully simple way of operating structures. As such, it has its own uses simply as a personal information manager for people who like multidimensionality,

In addition to stand-alone use ZigZag is related to Ted Nelson's Xanadu system; a newer version of Xanadu is being designed to make use of ZigZag as a platform. As a brief description of Xanadu, it has

Stable media streams (permascrolls)
A stable media stream is an invariant, addressable stream of data, e.g.~text, video or audio.
Documents
In Xanadu, documents are simply lists of spans from the stable media streams.
Content links
The linking model is fundamentally different from anything else hitherto seen. All links are handled on the lowest level, i.e. as links between lists of spans of stable media streams.
Finding by content
There are fast ways to find out in which documents a particular point in a stable media stream is included. All content copied via cut&paste can be tracked.

ZigZag can also work as a platform for other types of applications --- or preferably applitudes, meaning that they should also expose the other possibilities of ZigZag at the same time as being normal applications. This is so that the interconnectivity provided by ZigZag can be used to make the whole of two applitudes greater than the sum of the parts.

Cells, dimensions and connections

A cell is the fundamental container of data. A cell can "physically" contain either a text string or a single, contiguous span (which is an address, and references a permascroll).

Cells may be connected to each other along dimensions, so that each cell can be connected to another cell in two directions (negative and positive) on each dimension. The more global structure is not constrained: any two cells can be neighbours on any dimension, but some of these connections are used for interpreting the structure into views and actions (see below).

It is not yet clear whether dimensions are strings or whether they are cells. The various slice and compound space implementations will probably affect and depend on this. If dimensions are cells, then several uniqueness problems are quickly solved, but their being strings may be easier on the users.

One important point is that of headcells: on non-circular ranks, the headcell is the cell at the negative end of the rank. Ted specifies that all ranks should have a headcell and that there should be a way to specify the headcell of a circular rank. The exact mechanisms here are as of yet unclear.

Dimension-oriented view

An important way to describe the space is to take dimensions to be "objects": the dimensions are invertible mappings between cells. This is opposed to the immediate way of thinking "cell and connections", and there is a difference.

This view is important because here it is easy to discuss special dimensions that have interesting properties.

Subspaces, closed cell sets, closures

The following terms may prove useful from time to time:

Closed set of cells
A set of cells C is closed with respect to a set of dimensions D if and only if all neighbours of the cells in the set C along the dimensions in D are also in the set C.
Semiclosed set of cells
A set of cell C is semiclosed with respect to a set of dimension-direction pairs D if and only if all neighbours of the cells in the set C along the dimensions and their associated directions in D are also in the set C.
Closure
Let us have a set of cells C and a set of dimensions D. A set C' is a closure of C with respect to D if and only if it is a minimal closed (with respect to D) set containing all the elements of C.
Semiclosure
Let us have a set of cells C and a set of dimension-direction pairs D. A set C' is a semiclosure of C with respect to D if and only if it is a minimal semiclosed (with respect to D) set containing all the elements of C.
Subspace
A subset C of the set of cells in a ZigZag space Z is a subspace of Z with respect to a set of dimensions D, if and only if C is closed with respect to D in Z.
Proper subspace
A subspace C of a ZigZag space Z is a proper subspace if it is closed with respect to the set of dimensions D which contains every dimension of Z except d.cellcreation.
Semisubspace
A subset C of the set of cells in a ZigZag space Z is a semisubspace of Z with respect to a set of dimension-direction pairs D, if and only if C is semiclosed with respect to D in Z.
Generated subspace
A set of cells C in a ZigZag space Z and a set of dimensions D are said to generate a subspace C', which is the closure of C with respect to D in Z.

XXX: are these definitions OK?

Key structural mechanisms

Cursors

The path from the viewcell viewspx to the cell the cursor of the view points to A via the main cursor cell C which may or may not be the same as viewspx. C is at the negend of d.cursor-cargo from viewspx and the accursed cell A is at the negend of d.cursor.

The viewcell points to a particular cell where its cursor lies. The idea of cursors is not restricted to cursors of views but, as we shall see below, anything where selecting a single cell is important. This makes it possible to create a new view to select that cell on the fly (see below).

In the structure, a relcell is used so that several cursors can be maintained pointing to the same cell. The path to find the cell the view is pointing to is start at the viewcell, go to the posend on d.mycursor and then to the posend on d.cursor.

In order not to disturb other cursors, the insert operation should be used to move the relcell to a new d.cursor rank. This operation will leave the original and the new rank otherwise intact. It is possible that any other operation on d.cursor will be declared illegal.

Inheritable parameter lists

NOTE: this is liable to change. It is only documented here for understanding.

An example of the inherited parameter traveral to find a parameter value. Starting from start, we go poswards on d.2 until we reach a cell with a negward connection on d.3. We include that list and return to the main list. The parameters that have values store them on d.1 or as cursors starting on the parameter cell.

This section defines a way to inherit parameter lists based on the structure.

Paths

Paths are a precursor to Clang, and allow the user to express abstract paths in the structure. XXX See the docs for ZZPath.java.

Selectors

Selectors are a generalization of paths: where paths are like zeroth-order logic, selectors are first-order logic, allowing quantifiers ("every cell in this rank") but not quantification over quantifiers, or anything terribly general.

The point is to be able to easily describe in the structure the operation "show also all replies to this email", where the replies are generally connected to the original by some route.

One interesting idea that may or may not see the light of day is using inverse paths for selectors. This has certain aesthetic appeal.

Views

A view is represented by one maincell in the structure, called the viewcell. This cell can contain text which will be interpreted as the ``title'' of the view, but this is not mandatory.

XXX Since some views which contain more than one cursor are planned, it is possible that something will change below.

Visible Dimensions

The path from the viewcell to the cell specifying the Y dimension shown. First, we go two steps on d.dims, then use the same method as in the previous figure for getting to the accursed cell from there. Note that both the viewspx cell and the X have cursors similarly attached to them.

Dimensions that are currently visible are listed on d.dims from the viewcell, in order X, Y, Z (and possibly others, in case of complicated view rasters). The dimension cells are treated as cursors, i.e. the cell representing the dimension is found by going to the posend on d.mycursor and then to the posend on d.cursor from the dimension cell.

The point of this odd-seeming arrangement is, as alluded to in the Cursors section above, is that we can very simply create a new view that is bound to a dimension cell of another view.

Dimension lists

In order to change dimensions shown, the views provide an operation ``move the X/Y/Z-dimension-selector-cursor one step pos/negwards on d.2''. The usual plain-vanilla dimension lists are thus simply lists of cells on d.2 which contain the dimension name as a string (possibly by cloning). Most often these lists are cyclic but this is not mandatory: trying to move past the end/beginning of a list simply does nothing.

This is just the default arrangement - the user is free to create other dimlist operators and use them to change the dimensions taking advantage of the structure in a different way. One example of an operation we may want to provide at some point is "change dimension but not to one already being shown".

To select the dimension list for a particular dimension of a particular view, the user can simply create a new view for the dimension cursor, using the cursor-cargo mechanism. To set all the dimensions to the same list, the user can set the X dimension and then invoke a special operation that sets Y to the d.1 poswards neighbour of X, Z to the neighbour of Y and so on, on the same list.

Raster definition

Vanishing raster

XXX

Getting to the raster-defining cell R from the view specs. Note that the cursor-traversing operation is abbreviated to the curvy arrow. Also note that the inheriting mechanism defined previously is allowed.

The raster to use is obtained similar to the dimensions to use; only the first motion is different: down on d.2 until the text FlobRaster is found.

A sample specification of a vanishing raster, specifying values for two parameters. Here, the vanishing cell would stand in for the R cell in the previous image.

The raster itself is specified using a corner list. An incomplete list of parameters follows:

shrink
2 floats; the numbers to multiply the width and height of the cells with.
gap
2 ints: the number of pixels of space to leave between cells
depth
1 int: The number of cell "layers" to draw.
dimorder
2.. ints. The precedence of dimensions.
initmul
1 float. If the default size of cell will be multiplied by a number for the center cell (it is usually good to make the center cell larger

There are currently some undocumented interactions to provide for hard rasters; see the source.

Simple Flob Raster

The simple flob raster displays flobs extracted from the structure, on dimensions given by the structure. The dimensions are given by attaching paths to the cells in the dimlist.

Primitive operations

Connect

Insert (XXX rename)

Mono-chug

This operation changes one connection. It takes two directions and one cell as parameters. XXX image.

Bindings

Keybindings offer a nice way of seeing how flexible the ZigZag structure is for programming.

Most fundamentally, the names of the keys (e.g. Ctrl-k) are on cells connected along d.2. The action for each key is the poscell on d.1 from those cells - this way several keys can be bound to the same action quite easily.

However, this is not yet sufficient: there may be several input states, e.g. with the vi editor there is the insert mode and the command mode, and inside the command mode there is the special mode of waiting for a motion command. So in addition to the command, there needs to be a way to specify the next state. Likewise, some states are similar to each other so states should be able to inherit commands from each other in various ways.

GZigZag uses blank cells to represent inheritance: when the routine that searches for a key is going down along d.2, it will go to the poscell from that cell and check all the bindings on that dimension before returning to continue the search along the original rank.

The cursor mechanism is useful for keybindings as well: the current state can easily be maintaned by a cursor as shown above, allowing the user to easily set the cursor to a different state. However, care has to be taken here as moving the cursor in question can render keybindings unusable, so it is better to use an interface where the cursor can be immediately transported to the right place (such as clicking with the mouse).

The actual structure is currently such that the bindings cursor is the posend on d.bind of the view cell. This cursor points to the place where the inheritable parameter search for the next binding is begun. The cursor is set, if the inheritable parameter's value (on d.1) has a negward connection on d.3 -- it is set to the negend.

Additional problems arise when the same view can show different rasters. A different visualization of a structure often makes different means of navigation necessary, or different operations desirable. To provide for this, it is possible to assign a raster a list of modifications to a bindings mode; when the mode is selected, the raster's modifications are searched first, and the standard bindings for the mode are searched when the binding is not found in the modifications list.

A raster can be assigned two groups of modification lists: one to be applied when the raster is selected in the left (control) view, and one to be applied when the raster is selected in the right (data) view. These groups are obtained from the same corner list as the parameters given to the raster (see above); the text searched for is ctrlbindings and databindings, respective.

From that cell, an intersection on d.1 and d.clone with the current bindings mode is searched. That means that a mode which is intended to be modified is cloned, and attatched to the raster's bindings cell on d.1. From this cell, a definition for the binding is searched on d.2; if none is found, the mode's default bindings are invoked. For any of these searches, the standard parameter inheritance (see above) is allowed.

This method is practical because it "feels" very much like the definition of the modes themselves, as the modes are commonly listed on a d.1 rank from the Bindings cell on the system list. On the other hand, it's somewhat different structurally.

Default bindings for the orthogonal rasters

$Id: keybindings.wml,v 1.3 2000/10/26 13:08:11 ajk Exp $

These are still being discussed and are not yet frozen.

Key(s) Binding
Ctrl-S Commit the current changes to disk.
ijl,kK Up-left-right-down-Z+-Z- in view 1.
esfcdD Up-left-right-down-Z+-Z- in view 0.
n dir Create a new cell in given direction
b dir Break a connection in given direction
h dir Hop the accursed cell in the given direction. Hopping means simply switching the places of the accursed and the indicated cells in that rank, no other ranks are affected by the operation.
xyz Show next dimension on list on X/Y/Z in view 1
Alt-xyz Show previous dimension on list on X/Y/Z in view 1
XYZ Show next dimension on list on X/Y/Z in view 0
Alt-Shift-XYZ Show previous dimension on list on X/Y/Z in view 0
/ dir Connect the center cells of the right and left views in the given direction, if no connections will be broken by this.
~ Exchange the cursor positions of the two views (no other view parameters are changed).
Delete Delete the center cell of view 1 and move the cursor. Cursor move tries following directions in order: X-, X+, Y-, Y+, Z-, Z+ and finally goes to home cell.
m Mark or unmark the cell in view 1
Enter Execute cell in view 0, with the cell in view 1 as parameter
v Change raster in view 1.
V Change raster in view 0.
Alt-v Change raster in view 1 backwards.
Alt-V Change raster in view 0 backwards.
Home Go home: move view 1 cursor to homecell.
Esc Move both views to home and reset dimensions to first three dimensions on first dimlist.
0123456789 Insert the given number into the number insert buffer for cell IDs.
g Move view 1 to cell whose ID number was in buffer
G Move view 0 to cell whose ID number was in buffer
Backspace Remove one number from the number insert buffer
t dir Clone the view 1 cursor to given direction (may be in either view).
T dir Clone the view 0 cursor to given direction (may be in either view).
% Exchange the X and Y connections of the two accursed cells with each other.
o Go to original (rootclone, cell from which accursed cell was cloned) in view 1.
O Go to original (rootclone, cell from which accursed cell was cloned) in view 0.
End dir Move to te end of the rank in the given direction.
< Set the cursor of the left-hand-view to the cell the right-hand view is pointing to.
> Set the cursor of the right-hand-view to the cell the left-hand view is pointing to.
- dir Connect the current view1 cursor into marked cells in given direction. Direction must be in view 1.
Alt-c Switch into "curseling" (cursor selection) mode (see below).
a dir dir Monochug: change one connection. See above.

Text edit mode

Key(s) Binding
Esc or Tab Switch off text edit mode
Delete Delete one character after cursor
Backspace Delete one character before cursor
Left, Right Move the cursor within the current cell
Home Move the cursor to the beginning of the text in the current cell
End Move the cursor to the end of the text in the current cell
Ctrl-A Move the cursor to the beginning of the current line in the text of the current cell
Ctrl-E Move the cursor to the end of the current line in the text of the current cell
Enter Insert a line separator in the text before the cursor
any key producing a printable character Insert the character in the text before the cursor

Curseling (Cursor selection)

As an intermediate for multiple cursors, there is a key binding mode for "curseling:" cursor selection. In the standard keybindings, Alt-c is used to go into this mode, which by default supports the following key bindings:

Key(s) Binding
Tab, Spacebar, Alt-c or Esc Select this cursor, quit curseling mode.
Left, Right, jl Select next/last cursor in system cursor list in view 1.
Up, Down, i, Select next/last cursor positioned on the same cell in view 1.
sfec Like Left/Right/Up/Down, operating on view 0.

Note that you can create four additional cursors through executing the CreateCursors command, found in the action list, by centering the left view on it and hitting Enter.

Compound spaces

A compound space is simply a way of taking one or more existing spaces and creating a new space that is a view of these spaces combined according to some rule.

Trivial, kludgy

Notification, events and synchronization

XXX

There are many situations where one may want to be informed about changes to the structure, either before it happens (with the possibility of vetoing it), or after (e.g.~to reraster a window).

Updating views

Out of an email from Ted,

There are several issues here.  One is just the mechanics
 of a clean method of synchronization.  The other is
 the problem of A FEELING OF FAST RESPONSE--
 which means, very importantly, PREVENTING the
 non-current windows from refreshing in order to have
 truly INSTANTANEOUS response to each user action.
 Anyway, as much as possible.

In order to ensure a speedy response, we have to consider the numbers. There are thousands of cells. Each view shows some fraction of them. At each time, there are probably 1-10 views open and changes to cells will reflect in several of them.

Therefore, it is probably unnecessarily slow to store the information about which cells are seen by which views (except if it is naturally stored by the view itself). Rather, for views, there should just be a global list which gives the priorities with which the views get to refresh themselves.

Now, it makes no sense to start updating at each change to the structure - internally there has to be some method to freeze and thaw the global update queue.

One interesting problem here is finding which view is really the current view: for instance, in the two-part view Also, displaying only the central portion of the views whose cursor changes first could make a big difference. Or the rank along which the cursor moves plus some small number of cells.

Internal triggers

However, this is not the whole story: views are not the only things that need to be informed when something changes. It should be possible to define per-cell triggers as well.

This is possible in the Java code by passing an extra parameter, a ZZObs to a routine that returns some structural information, such as a neighbour, a headcell or the contents. The ZZObs will then be called once after any of the items it is observing changes, i.e. the return value of the function the ZZObs was passed to has changed.

The callback is not necessarily instantaneous; rather, all the callbacks are grouped and run after the activity that caused the trigger has finished.

Cursor triggers

Eventually, it should be possible to define these triggers in the structure as well, but the best mechanism for that is not yet known. However, for some applications these can't wait. Especially important are cursor triggers, which do something whenever a cursor changes value.

A cursor trigger is placed by placing the action (XXX In what form) on d..cursor-trigger of the cursor-cargo cell. These actions are queued to be called sometime after the cursor is changed (usually before the next screen update).

Cell storage mechanism

Transient cells

Most of the structure is persistent but some parts should be transient in order to save space and time. For example, if the information about the rastered representation of a part of the space (coordinates on the 2-D display) is stored in the space, this would waste an enormous amount of space each time the cursor moved.

The transiency is specified at the time of the cell creation on the Java level. How this figures in the space is yet to be decided.

The transient cells are not trivial: because of design considerations, they can't simply override connections and have all their connections appear deleted in the persistent space. Instead, the persistent space should appear as if the cells had been truly deleted using the delete operation, which causes the cells on opposite sides on a dimension from the cell being deleted to be connected to each other. In other words, if we have the rank ABCDE and the cell D is a transient cell, then this should correspond to a rank ABCE in the persistent space.

Slices

The slice design is what Ted ultimately wants but because it's somewhat more complicated to implement, it's postponed until some other parts of the system clear up (most importantly synchronization) and the existence of other types of subspaces and their interaction.

Versioning

A key mechanism for versioning is timestamps, which specify moments in the past. The full state of the ZZ space at each timestamp can be accessed through the file formats.

The past versions of cell structures are shown in the structure as virtual, non-modifiable cells, except for the one allowed source of modification: d.cursor. The dimension d.cursor is a source of much headache in versioning because of its nature but the current solution is to move past versions of d.cursor to d..cursor-past.

The past versions of a cell can be accessed on d.version, and the past versions where the cell's content or connections have changed is on d.cell-version, and the past versions where the cell's content has changed are on d.content-version. So d.cell-version skips on the cells of d.version, and d.content-version skips on the cells of d.cell-version. The skipped-to cells are the first cells with the new, changed property.

XXX Can we do d.cell-version efficiently???

Stable media streams

Referencing stable media streams is an important part of the overall design. For the Dominica project, we need a subset of the features.

A cell may contain either its text directly or a reference to a stable media stream - either an address or a span between two addresses. For now, we distinguish between the two types by having the references to stable media connected to themselves along d.stableref (this mechanism {\em will} change later, and is encapsulated in the ZZCell class as the contenttype routines).

Temporarily, we use the address format AAnumber where the number is simply the byte offset into the invariant media stream. Later on, the addresses will be converted into tumblers.

Given a space, it is possible to obtain a list of cells that overlap with a given list of spans. These can be used in various ways to display parts of texts that have links in different ways etc.

Later on, an enfiladic (tree-like) structure will be used to perform the cross-matching of the cell lists.

Blobs

Blobs are a stop en route to full hyperFlobs. Blobs are basically objects whose coordinates and appearance in 2D come somehow from the ZZ space, according to user-given instructions, which are themselves stored in the ZZ structure.

A blob has two separate aspects: location and appearance. The location is composed of multiple dimensions, specified in some way by the structure, of which the user will select a subset of two or three (or some more if using e.g. linear combinations). The appearance can also be selected from multiple possibilities, with different visual aspects showing different aspects of the entity the blob represents.

Throughout this section, I will use email as the recurring example. Email is a good application for blobs since it makes it possible to see the usefulness of blobs in a practical setting. Everybody gets too much email. Current email programs are not able to handle the load - first of all, they are too slow, reading the entire mailbox every time the program is started and the mailbox is opened. The obvious solution of splitting your mail into several folders is not nice either --- it makes it much more difficult to find anything. This problem is well solved by the stable media streams in the previous section: instead of different files as folders, folders are just sets of pointers to the original mailbox file. The algorithmically great thing is that the whole mailbox need not be reread at any point, only the new messages have to be inserted into the structure. After that, the structure is a good way of accessing the contents of the mailbox. But I digress - back to blobs.

In the world of blobs, each email would be represented as one blob. Likewise each person and subject line (modulus Re).

Variables and constants

Each ``statement'' or ``expression' in the ZZ space will have some parameters. For instance, an expression of ``headcell'' will need a dimension and a direction.

For maximum flexibility and ease, we want to be able to store the dimension parameter in two different ways: first, as a direct cell or clone of a cell, e.g. d.1, and second, as a pointer.

For design considerations, the first thing to note about pointers is that it would be quite powerful if we could bind a number of pointers to point to the same cell --- just like cursors above. So why not equate pointer$=$cursor, so that a cell is interpreted as itself if there's no d.mycursor poswards and otherwise as a cursor.

Dimensions

The whole concept of blobs (and flobs) is based on being able to grab visualizable dimensions from various user-defined places in the structure and throw the blobs on the screen at those coordinates.

Dimensions can be defined by the blobs themselves or by proxy (e.g. an email can have as one of its dimensions one of the dimensions of the sender of the email).

Eventually, it should be possible to edit some dimensions by just clicking and dragging. Some dimensions, like the date of an email, should be read-only but you should be able to drag email on an urgency dimension or some dimensions of your own (to arrange them in a pleasing way in space).

Note that dimensions do not need to have numerical values. An ordering can be quite sufficient and useful. For example, a time dimension to email may be more useful if it is not represented linearly but rather nonlinearly, based on the message density, expanding dense places and possibly (like in billowing) places that are near the cursor.

The structure of a blobview description

When the blobview is described in the structure, there will be one or many sets of blobs to render, as well as their connections. Each set of blobs is described by

All of these can be given directly or as (cursorial) references to other places. In the future, they will be able to pass parameters to each other, so that it would be possible to implement the perspective view through cells as blobs.

The connections between blobs will currently be described simply by giving paths from the maincell to other maincells that may be shown on the screen and if it is shown, a line is drawn.

A high-level example description of a blobview

I warned you that email would be the predominant example of this section. First, let's see how we describe emails in the ZZ structure for this simple example.

First of all, there is the handle for each email. This is just a cell that is used to designate the whole email. As emails contain the Message-ID field which is guaranteed to be unique, the handle cell will contain that string. Poswards on d.handle from the handle cell are the header, the body and the attachments.

The header is a simple d.2 and d.1 job for the field type and contents. However, both the email address cells, the subject cell and the references (message ids) are connected structurally: all of them point on d.ref to the handle of the corresponding structure. It may be that the structure that these cells point to is not loaded, in which case they just form a rank on d.ref without the handle cell at the end.

ZObs

It is going to be fairly common for a Java class to get its parameters from the structure. The ZOb mechanism is useful for easily creating such Java classes that read their parameters in a standard way. Basically, a ZOb is a Java class for which the instance variables are defined inside a STRUCTPARAMS {} block. There is some syntax support for specifying the number of elements required in arrays etc.

The point of the mechanism is to allow more latitude with the parameters later: for example, inserting them into the structure with descriptions, or caching the ZOb parameters read from the structure for larger ZOb systems to speed up the process.

Email applitude, v1

This is a specification for the first version of the flob-supporting email applitude. The relevant structure is shown in the figure. XXX email1 The handle cell is connected along d.handle to the most important header fields and the cell containing the actual content of the message. The rest of the headers are stored in the structure but are not relevant here. The message IDs connect replies together: the In-Reply-To: and Message-Id fields: the message ids on the reply-to fields are clones of the original message's message-id field. This makes it easy to track threads using only the structure.

The flob dimension specification is an interesting part of this problem: it should be compatible with the other rasters but store extra information for each dimension about where that dimension is to be found and whether it's user-modifiable (by clicking and dragging). Since each dimension is special, it doesn't make sense to have the same dimension lists for flob dimensions and normal dimensions but the operation of advancing a dimension can remain the same, i.e. advancing a cursor on d.2. In the flob coordinates, the cell on that rank gives the name and is connected on d.1 to the actual instructions on how to obtain the correct cell and label.

The fourth dimension is used for finding the flobs to show, i.e. to select the rank of references to show.

Interactions

This section deals with the interactions between the various planned features. Unfortunately, this is one part that is not yet fully specced but at least we're speccing what the problems are. (XXX todo)

  Clones Cursors Versioning (access to old versions) Slices Content links I18N
Clones            
Cursors            
Versioning (access to old versions)            
Slices            
Content links            
I18N            

Summary of special dimensions

d.clone
The clone dimension. All cells on a clone rank are clones of each other, meaning that their contents are enforced to be the same and changes to the contents of one are reflected to the others. For example, clones could be used to represent the same email address on a number of email headers, so that all those instances of the same email addresses would be linked to each other through d.clone.
d.cursor, d.cursor-list and d.cursor-cargo.
A set of pointing dimensions. This mechanism is used for instance by the views to point to the cursor which is at the center of the view. Moving the cursor is equivalent to inserting the maincell of the view poswards on d.cursor from the new position of the cursor (the accursed cell). d.cursor-cargo provides a mechanism for locking several cursors together.

File format

This section describes the GZigZag file formats that store the low-level structure. This is separate from the space description which describes e.g. the system list: the file format is lower-level still.

The file format is arranged as several layers, in order to make it more flexible in the future.

Runs

Runs are the lowest level of the file: they specify a sequence of changes to the structure, moving forwards in time.

The run formats given are version 0 of the run format.

Dimension change run

A dimension change run is a sequence of instructions telling how one dimension changed between two specific times. It contains records specifying connecting and disconnecting cells. The structure is that of a simple hash: disconnecting only disconnects in one direction.

The records are:

Connect record: connect cell id 1 to cell id 2 poswards.
nbytes content
1 'c' (99). Record identifier.
2..65537 Java UTF string. Cell id 1.
2..65537 Java UTF string. Cell id 2.
Disconnect record: disconnect cell id 1 in given direction.
nbytes content
1 'd' (100). Record identifier.
1 '+' (43) or '-' (45). Positive or negative direction.
2..65537 Java UTF string. Cell id.

These records are concatenated with no record identifier in between.

Content change run

This is the corresponding sequence for cell content changes.

New string content for a cell.
nbytes content
1 's' (115). Record identifier.
2..65537 Java UTF string. Cell id.
2..65537 Java UTF string. Text content.
New span content for a cell.
nbytes content
1 'S' (83). Record identifier.
2..65537 Java UTF string. Cell id.
2..65537 Java UTF string. Content, as a string representation of a span.

Character scroll

The character scroll for text is simply a sequence of 16-bit unicode characters, addressable by offsets.

Run synchonization

The dimensions and content (but not scrolls), are stored in streams that contain synchronization markers between runs of changes.

Header, identifying the file type, the content type and content version.
nbytes content
4 ASCII "GZZ0". Magic "number".
4 Java int: wrapper version number.
4 Java int: content type.
42 = dimension
43 = content
4 Java int: content version.

After the header, the actual data starts. The data is given in runs:

Run: A single run between timestamps.
nbytes content
1 't' (114). Record identifier.
4 Java int: timestamp number.
4 Java int: number of bytes to follow.
0..2147483647 The run.

Only the last timestamp before which changes occurred is stored: empty runs are not necessarily stored except for the content file. The time the save was done could be saved in a cell with the ID 'savetime' to facilitate backup recovery by time.

Stream set

A stream set, then, is a container for all of the above things, with streams named by unicode strings.

Currently, this is implemented simply as a directory, which means that using non-ascii characters, or anything that's not alphanumeric or dots or slashes is a really bad idea.

Later, it will probably be a single stream that encapsulates the other streams; it may even be that runsynch and streamset will be combined later on.