Files
gzz-mirror/Documentation/Spec/zzspec.wml
2026-09-14 20:19:29 -04:00

1128 lines
39 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<!--
NOTE! This file uses WML 2.0.1
PLEASE PLEASE PLEASE don't edit .HTML. Edit .WML!!!! Actually,
it's more important for you since your changes will be LOST FOREVER
if you edit the .HTML files.
-->
<html>
<head>
<title>GZigZag spec</title>
#include '../wmlinc/article.wml'
#use wml::fmt::xtable
<!--
Make d.foo into <code>d.foo</code> so we don't have to explicitly
do it whenever we talk about dimensions.
-->
</head>
<body>
<substdims>
<H1>GZigZag spec</H1>
<pre>$Id: zzspec.wml,v 1.24 2001/02/13 18:54:28 ajk Exp $</pre>
Written by <br>
<b>Tuomas J. Lukka</b> <br>
<b>Benjamin Fallenstein</b> <br>
<b>Antti-Juhani Kaijanaho</b> <br>
(add your name here if you do any significant modification)
<toc>
<warn>
<h2>Introduction</h2>
<p>
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.
<p>
Some parts of this specification are not yet correctly implemented by
the current version, but in these cases, this document is correct (or
it <strong>should</strong> be ;-)
and the implementation wrong.
<p>
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.
<p>
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.
<p>
If you see anything suspicious, feel free to ask me at <code>lukka@iki.fi</code>.
<h2>The role of ZigZag in the overall scheme of things</h2>
<p>
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,
<p>
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
<dl>
<dt> Stable media streams (permascrolls)
<dd> A stable media stream is an invariant, addressable stream of
data, e.g.~text, video or audio.
<dt> Documents
<dd> In Xanadu, documents
are simply lists of spans from the stable
media streams.
<dt> Content links
<dd> 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.
<dt> Finding by content
<dd> 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.
</dl>
<p>
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 <em>at the same time</em> 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.
<h2>Cells, dimensions and connections</h2>
<p> 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).
<p>A cell has an ID, which is a string. Currently, if a cell ID
contains a colon (:), the cell belongs to a <em>space part</em>, where
the space part ID is everything from the beginning up to and excluding
the colon. If a cell ID contains an at sign (@), it is a <em>global
ID</em>; everything starting from and excluding the at sign to the end
of the ID is the ID of the cell's <em>creation space</em>. If the
creation space ID differs from the ID of the space the cell is in, the
cell is <em>foreign</em>, otherwise its <em>native</em>.
<p>
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).
<p>
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.
<p>
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.
<h3>Dimension-oriented view</h3>
<p>
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.
<p>
This view is important because here it is easy to discuss special dimensions
that have interesting properties.
<h3>Subspaces, closed cell sets, closures</h3>
<p>
The following terms may prove useful from time to time:
<p>
<dl>
<dt>Closed set of cells</dt>
<dd>
A set of cells C is <strong>closed</strong> 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.
</dd>
<dt>Semiclosed set of cells</dt>
<dd>
A set of cell C is <strong>semiclosed</strong> 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.
</dd>
<dt>Closure</dt>
<dd>
Let us have a set of cells C and a set of dimensions D. A
set C' is a <strong>closure</strong> 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.
</dd>
<dt>Semiclosure</dt>
<dd>
Let us have a set of cells C and a set of
dimension-direction pairs D. A set C' is a
<strong>semiclosure</strong> 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.
</dd>
<dt>Subspace</dt>
<dd>
A subset C of the set of cells in a ZigZag space Z is a
<strong>subspace</strong> of Z with respect to a set of
dimensions D, if and only if C is closed with respect to D
in Z.
</dd>
<dt>Proper subspace</dt>
<dd>
A subspace C of a ZigZag space Z is a <strong>proper
subspace</strong> if it is closed with respect to the set
of dimensions D which contains every dimension of Z except
<tt>d.cellcreation</tt>.
</dd>
<dt>Semisubspace</dt>
<dd>
A subset C of the set of cells in a ZigZag space Z is a
<strong>semisubspace</strong> 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.
</dd>
<dt>Generated subspace</dt>
<dd>
A set of cells C in a ZigZag space Z and a set of
dimensions D are said to <strong>generate</strong> a
subspace C', which is the closure of C with respect to D
in Z.
</dl>
<p>XXX: are these definitions OK?
<h2>Key structural mechanisms</h2>
<h3>Cursors</h3>
<figure img="cursor1.png" width="250px">
The path from the viewcell <code>viewspx</code>
to the cell the cursor of the view points to <code>A</code>
via the main cursor cell <code>C</code> which may or may not be the
same as <code>viewspx</code>.
<code>C</code> is at the negend of <code>d.cursor-cargo</code>
from <code>viewspx</code> and the accursed cell <code>A</code> is
at the negend of <code>d.cursor</code>.
</figure>
<p>
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).
<p>
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.
<p>
In order not to disturb other cursors, the insert operation should be
used to move the relcell to a new <code>d.cursor</code> rank. This operation
will leave the original and the new rank otherwise intact.
It is possible that any other operation on <code>d.cursor</code> will
be declared illegal.
<h3>Inheritable parameter lists</h3>
<p>
NOTE: this is liable to change. It is only documented here for
understanding.
<figure img="inheritparam.png" width="250px">
An example of the inherited parameter traveral to find a parameter
value. Starting from <code>start</code>, we go poswards on <code>d.2</code>
until we reach a cell with a negward connection on <code>d.3</code>.
We include that list and return to the main list. The parameters
that have values store them on <code>d.1</code> or as cursors starting
on the parameter cell.
</figure>
<p>
This section defines a way to inherit parameter lists based on the
structure.
<h3>Paths</h3>
<p>
Paths are a precursor to Clang, and allow the user to express abstract
paths in the structure. XXX See the docs for ZZPath.java.
<h3>Selectors</h3>
<p>
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.
<p>
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.
<p>
One interesting idea that may or may not see the light of day
is using inverse paths for selectors. This has certain aesthetic
appeal.
<h2>Views</h2>
<p>
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.
<p>
XXX Since some views which contain more than one cursor are planned,
it is possible that something will change below.
<h3>Visible Dimensions</h3>
<figure img="cursordim.png" width="250px">
The path from the viewcell to the cell specifying the Y dimension shown.
First, we go two steps on <code>d.dims</code>, then
use the same method as in the previous figure for getting to the accursed
cell from there.
Note that both the <code>viewspx</code> cell and the <code>X</code> have
cursors similarly attached to them.
</figure>
<p>
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.
<p>
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.
<h3>Dimension lists</h3>
<p>
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.
<p>
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".
<p>
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.
<h3>Raster definition</h3>
<h4>Vanishing raster</h4>
XXX
<figure img="canvasraster.png" width="250px">
Getting to the raster-defining cell <code>R</code> 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.
</figure>
<p>
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
<code>FlobRaster</code> is found.
<figure img="rasterspec.png" width="250px">
A sample specification of a vanishing
raster, specifying values for two parameters.
Here, the <code>vanishing</code> cell would stand in for the
<code>R</code> cell in the previous image.
</figure>
<p>
The raster itself is specified using a corner list.
An incomplete list of parameters follows:
<dl>
<dt>shrink
<dd>2 floats; the numbers to multiply the width and height
of the cells with.
<dt>gap
<dd>2 ints: the number of pixels of space to leave between cells
<dt>depth
<dd>1 int: The number of cell "layers" to draw.
<dt>dimorder
<dd>2.. ints. The precedence of dimensions.
<dt>initmul
<dd>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
</dl>
<p>
There are currently some undocumented interactions to provide for
hard rasters; see the source.
<h4>Simple Flob Raster</h4>
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.
<h2>Primitive operations</h2>
<h3>Connect</h3>
<h3>Insert (XXX rename)</h3>
<h3>Mono-chug</h3>
<p>
This operation changes one connection. It takes two directions
and one cell as parameters.
XXX image.
<h2>Bindings</h2>
<p>
Keybindings offer a nice way of seeing how flexible the
ZigZag structure is for programming.
<p>
Most fundamentally, the names of the keys
(e.g. <code>Ctrl-k</code>) 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.
<p>
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.
<p>
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.
<p>
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).
<p>
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.
<p>
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.
<p>
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 <code>ctrlbindings</code>
and <code>databindings</code>, respective.
<p>
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.
<p>
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 <code>Bindings</code>
cell on the system list. On the other hand, it's somewhat
different structurally.
#include '../keybindings.wml'
<h2>Compound spaces</h2>
<p>
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.
<h3>Trivial, kludgy</h3>
<h2>Notification, events and synchronization</h2>
<p>
XXX
<p>
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).
<h3>Updating views</h3>
<p>
Out of an email from Ted,
<pre>
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.
</pre>
<p>
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.
<p>
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.
<p>
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.
<p>
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.
<h3>Internal triggers</h3>
<p>
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.
<p>
This is possible in the Java code by passing an extra parameter, a
<code>ZZObs</code> to a routine that returns some structural information,
such as a neighbour, a headcell or the contents.
The ZZObs will then be called <em>once</em> after any of the items it is
observing changes, i.e. the return value of the function the <code>ZZObs</code>
was passed to has changed.
<p>
The callback is not necessarily instantaneous; rather, all the callbacks
are grouped and run after the activity that caused the trigger has finished.
<h3>Cursor triggers</h3>
<p>
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.
<p>
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 <em>before</em> the next screen update).
<h2>Cell storage mechanism</h2>
<h3>Transient cells</h3>
<p>
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.
<p>
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.
<p>
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.
<h3>Slices</h3>
<p>
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.
<h3>Versioning</h3>
<p>
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.
<p>
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.
<p>
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 <em>first</em> cells with
the new, changed property.
<p>
XXX Can we do d.cell-version efficiently???
<h2>Stable media streams</h2>
<p>
Referencing stable media streams is an important part of the
overall design. For the Dominica project, we need a subset of the
features.
<p>
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).
<p>
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.
<p>
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.
<p>
Later on, an enfiladic (tree-like) structure will be used to perform
the cross-matching of the cell lists.
<h2>Blobs</h2>
<p>
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.
<p>
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.
<p>
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.
<p>
In the world of blobs, each email would be represented as one blob.
Likewise each person and subject line (modulus <code>Re</code>).
<h3>Variables and constants</h3>
<p>
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.
<p>
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.
<p>
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.
<h3>Dimensions</h3>
<p>
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.
<p>
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).
<p>
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).
<p>
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.
<h3>The structure of a blobview description</h3>
<p>
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
<ul>
<li> a set of rules and paths to
find the maincells of the blobs to display, starting from the
cursor of the blobview,
<li> a set of rules to find the dimensions to show
for each blob
<li> a set of rules to show each blob on the screen
(e.g.~which cells' text to draw and how to arrange it).
</ul>
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.
<p>
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.
<h3>A high-level example description of a blobview</h3>
<p>
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.
<p>
First of all, there is the <em>handle</em> for each email. This is just
a cell that is used to designate the whole email.
As emails contain the <em>Message-ID</em> 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.
<p>
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.
<h2>ZObs</h2>
<p>
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 <code>STRUCTPARAMS {}</code> block. There is some
syntax support for specifying the number of elements required in arrays
etc.
<p>
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.
<h2>Email applitude, v1</h2>
<p>
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 <code>In-Reply-To:</code>
and <code>Message-Id</code> 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.
<p>
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
<code>d.2</code>.
In the flob coordinates, the cell on that rank gives the name and is
connected on <code>d.1</code> to the actual instructions on how to obtain
the correct cell and label.
<p>
The fourth dimension is used for finding the flobs to show, i.e. to
select the rank of references to show.
<h2>Interactions</h2>
<p>
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)
<xtable spacing=3 border=2>
((1, 2))
Clones
((1, 3))
Cursors
((1, 4))
Versioning (access to old versions)
((1, 5))
Slices
((1, 6))
Content links
((1, 7))
I18N
((2, 1))
Clones
((3, 1))
Cursors
((4, 1))
Versioning (access to old versions)
((5, 1))
Slices
((6, 1))
Content links
((7, 1))
I18N
</xtable>
<h2>Summary of special dimensions</h2>
<p>
<dl>
<dd>d.clone
<dt> 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.
<dd>d.cursor, d.cursor-list and d.cursor-cargo.
<dt> 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.
</dl>
<h2>File format</h2>
<p>
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.
<p>
The file format is arranged as several layers, in order to
make it more flexible in the future.
<h3>Runs</h3>
<p>
Runs are the lowest level of the file: they specify a sequence
of changes to the structure, moving forwards in time.
<p>
The run formats given are version 0 of the run format.
<h4>Dimension change run</h4>
<p>
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.
<p>The records are:
<grid spacing=3 layout=2x6 border=2>
<cell colspan = 2>
Connect record: connect cell id 1 to cell id 2 poswards.
</cell>
<cell> nbytes </cell> <cell> content </cell>
<cell> 1 </cell> <cell> 'c' (99). Record identifier. </cell>
<cell> 2..65537 </cell> <cell> Java UTF string. Cell id 1. </cell>
<cell> 2..65537 </cell> <cell> Java UTF string. Cell id 2. </cell>
</grid>
<grid spacing=3 layout=2x6 border=2>
<cell colspan = 2>
Disconnect record: disconnect cell id 1 in given direction.
</cell>
<cell> nbytes </cell> <cell> content </cell>
<cell> 1 </cell> <cell> 'd' (100). Record identifier. </cell>
<cell> 1 </cell> <cell> '+' (43) or '-' (45). Positive or negative direction. </cell>
<cell> 2..65537 </cell> <cell> Java UTF string. Cell id. </cell>
</grid>
<p>
These records are concatenated with no record identifier in
between.
<h4>Content change run</h4>
<p>This is the corresponding sequence for cell content
changes.
<grid spacing=3 layout=2x6 border=2>
<cell colspan = 2>
New string content for a cell.
</cell>
<cell> nbytes </cell> <cell> content </cell>
<cell> 1 </cell> <cell> 's' (115). Record identifier. </cell>
<cell> 2..65537 </cell> <cell> Java UTF string. Cell id. </cell>
<cell> 2..65537 </cell> <cell> Java UTF string. Text content. </cell>
</grid>
<grid spacing=3 layout=2x6 border=2>
<cell colspan = 2>
New span content for a cell.
</cell>
<cell> nbytes </cell> <cell> content </cell>
<cell> 1 </cell> <cell> 'S' (83). Record identifier. </cell>
<cell> 2..65537 </cell> <cell> Java UTF string. Cell id. </cell>
<cell> 2..65537 </cell> <cell> Java UTF string. Content,
as a string representation of a span. </cell>
</grid>
<h4>Character scroll</h4>
<p>The character scroll for text is simply a sequence of
16-bit unicode characters, addressable by offsets.
<h3>Run synchonization</h3>
<p>
The dimensions and content (but not scrolls), are stored in
streams that contain synchronization markers between runs
of changes.
<grid spacing=3 layout=2x10 border=2>
<cell colspan = 2>
Header, identifying the file type, the content type
and content version.
</cell>
<cell> nbytes </cell> <cell> content </cell>
<cell> 4 </cell> <cell> ASCII "GZZ0". Magic "number". </cell>
<cell> 4 </cell> <cell> Java int: wrapper version number. </cell>
<cell> 4 </cell> <cell> Java int: content type. </cell>
<cell></cell> <cell> 42 = dimension </cell>
<cell></cell> <cell> 43 = content </cell>
<cell> 4 </cell> <cell> Java int: content version. </cell>
</grid>
<p>
After the header, the actual data starts.
The data is given in runs:
<grid spacing=3 layout=2x8 border=2>
<cell colspan = 2>
Run: A single run between timestamps.
</cell>
<cell> nbytes </cell> <cell> content </cell>
<cell> 1 </cell> <cell> 't' (114). Record identifier. </cell>
<cell> 4 </cell> <cell> Java int: timestamp number. </cell>
<cell> 4 </cell> <cell> Java int: number of bytes to follow. </cell>
<cell> 0..2147483647 </cell>
<cell> The run. </cell>
</grid>
<p>
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.
<h3>Stream set</h3>
<p>A stream set, then, is a container for all of the above
things, with streams named by unicode strings.
<p>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.
<p>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.
</substdims>
</body>
<!--
vim: set syntax=html :
-->