.ds HF 3 3 3 3 3
.ds HP +4 +2 +1
.nr Hb 7
.\"{{{}}}
.\"{{{  Title
.ND "May 20, 1995"
.TL
Teapot User guide
.AU "Michael Haardt (michael@cantor.informatik.rwth-aachen.de)"
.AS "" 0.5i
For ages, spread sheet programs have been closely associated with
financial calculations done by typical end-users.  But it has shown
that there is also hacker's work which can be done with them, like
calculate monitor timings for various resolutions, inventing new floppy
formats and produce convincing time statistics which justify the lack
of documentation or the need for a budget increase to your employer.
This first part of this user guide explains how the various functions
of teapot are used, whereas the second part gives an introduction to
spread sheets and explains the expression evaluator and its functions.
.AE
.MT 4 1
.\"}}}
.\"{{{  Copyright
.H 1 "Copyright and usage conditions"
teapot is copyright (c) by Michael Haardt, 1995.  You may use and
modify this program or derived works without charge for personal use
and at work under the condition that no copyright notices are removed or
changed.  Any commercial use like charging for copying or selling it or
derived works, alone or as part of a bigger product, needs to be
licensed by me.  The source code is available via anonymous ftp from
cantor.informatik.rwth-aachen.de, pub/linux/teapot.tz.
.P
I can be reached by:
.DS I
Snail mail:
Michael Haardt
Rütscherstraße 155/1703
52072 Aachen
Germany

Email:
michael@cantor.informatik.rwth-aachen.de
.DE
Disclaimer: I am in no way responsible for anything caused by using this
program, so if your computer or house blows up, that's your problem.  :)
.\"}}}
.\"{{{  Function keys and menues
.H 1 "Function keys and menues"
.P
Some terminals do not have certain function keys, which are needed to
move around or perform other functions.  For that and other reasons,
the following control keys are also recognised:
.TS H
center,allbox;
l l l.
Function	Function key	Control key(s)
.TH
Next line	Cursor down	^n
Previous line	Cursor up	^p
Backward character	Cursor left	^b
Forward character	Cursor right	^f
Cancel	Cancel key	^g, ^[ (ESCAPE)
Backspace	Backspace key	^h
Delete	Delete key	^? (dec. 127), ^d
Enter	Enter key	^j, ^m
Beginning	Begin key	^a
End	End key	^e
Insert	Ins key	^i
Kill line	Delete line key	^k
Transpose character	^t
Goto matching paren	-	^\e
.TE
.P
Note that for technical reasons, the ESCAPE key will have a slight
delay.  From now on, the keys will only be referred to by their names
and not by the alternate control codes.
.P
Most functions are used through menues.  You can either use the key
before the paren to select an item or move the highlighted bar: Cursor
right, tab and space go to the next menu item; cursor left or backspace
goes to the previous item; return selects the current item and cancel
does not select any item and aborts the function.
.\"}}}
.\"{{{  Introduction to spread sheets
.H 1 "Introduction to spread sheets"
.\"{{{  General introduction
.H 2 "General introduction"
A spread sheet consists of cells formed by rows and columns. 
Additionally, in many spread sheets you have a third dimension, which
you can imagine as various sheets laying on top of each other.  The
third dimension allows you to hide intermediate results, show you
additional results you do not want to appear in the ``official''
tables, keep sheets per time period (like 12 sheets for each month in a
year) while allowing you to make calculations over the entire time
interval and much more.  The figure below shows the three dimensions:
.\"{{{  picture
.DS CB
.PS 5i
cols=20
rows=10
layers=4
dist=0.6
[
  SHEET: box invis wid 4 ht 1
  for x=0 to cols do { line from x/cols <SHEET.nw,SHEET.ne> down SHEET.ht }
  for y=0 to rows do { line from y/rows <SHEET.nw,SHEET.sw> right SHEET.wid }
  for i=1 to layers do
  {
    for x=0 to cols-1 do
    {
      line from x/cols <last box.nw,last box.ne> + (i*dist*last box.wid/cols,i*dist*last box.ht/rows) to x/cols <last box.nw,last box.ne> + (i*dist * last box.wid/cols,(i-1)*dist*last box.ht/rows)
    }
    L: line from last box.ne + (i*dist*last box.wid/cols,i*dist*last box.ht/rows) to last box.se + (i*dist*last box.wid/cols,dist*i*last box.ht/rows)
    line from L.end left dist*last box.wid/cols
    line from L.start left last box.wid
    for y=0 to rows-1 do
    {
      line from y/rows <last box.ne,last box.se> + (i*dist*last box.wid/cols,i*dist*last box.ht/rows) to y/rows <last box.ne,last box.se> + ((i-1)*dist * last box.wid/cols,i*dist*last box.ht/rows)
    }  
  }
]
SHEET: last [].SHEET
S: last [].se + (0.3,SHEET.ht)
arrow from S right SHEET.wid
" x" ljust at last arrow.end
arrow from S down SHEET.ht
"y" below at last arrow.end
arrow from S to S +(layers*dist*SHEET.wid/cols,layers*dist*SHEET.ht/rows)
" z" ljust at last arrow.end
.PE
.DE
.\"}}}
You can think of cells as variables, which value is the value of an
associated expression.  The expression may be constant, like 1.23, or
it may be a function of other cell values.  The advantage compared to a
programmable calculator is that if you change a number, you directly
see all changes in other cells caused by that.  Often this allows you
to get a feeling how much you may change basic sizes with still getting
satisfying results without having to solve the problem analytically.
.P
Spread sheets offer many editing functions in order to modify, clear,
copy and move cells or blocks of cells.  Besides the usual mathematical
functions, there are functions which work on blocks of cells, like
calculating the sum of a block or counting all non-empty elements. 
Further there are functions working on character strings, because most
likely you also want text besides numbers.  The next section will
introduce you to some of these by examples.
.\"}}}
.P
.\"{{{  First steps
.H 2 "The first steps"
Now that you should have an idea, it is probably a good time to make
your first steps.  This section will show you how to create and save a
sheet which contains two numbers and their sum.  At first, start the
program without any arguments:
.DS I
$ \fBteapot\fP
.DE
You see an empty sheet with the cell cursor being at the upper left
corner.  Further, the status line tells you that this cell is really empty:
.DS I
@(0,0,0)=
.DE
The meaning of \fB@()\fP will be explained soon.  You are now in the
command mode of teapot.  Now type return to edit this cell.  A complete
list of command mode functions will be given later.  A prompt will
appear below the status line:
.DS I
Cell contents: 
.DE
Type \fB1\fP and return.  Now the cell at position 0,0,0 has the integer
constant 1.  The status line shows you the cell contents, whereas in the
sheet you see its value.  Since constants are identical with their values,
both are 1.  Now move the cell cursor down one row and edit that cell,
giving it the integer constant 41.
.P
Now that you have two numbers, move the cell cursor to cell 0,2,0 and
give that cell the following contents:
.DS I
Cell contents: @(0,0,0)+@(0,1,0)
.DE
If you were confused about the difference between contents and value of
a cell, it should become more clear now: The status line shows the contents,
which is the arithmetic expression to calculate the sum of two cells,
whereas in the sheet you see the value of that expression: 42, which
was to be expected.
.P
As the last step, save your work sheet to a file.  Use \fB/\fP (slash) in
command mode to get into the main menu.  Depending on your screen size, 
you may not see all of it.  In this case, move the highlighted block 
right (or left) to scroll through it and to see all items.  One of them 
will be \fBS)ave\fP.  The paren tells you, that you just typing \fBs\fP 
would be enough.  If you don't like that, move the highlighted bar on 
that item and type enter.  Either way, hopefully you will find your way 
to the save menu.  The native file format is XDR, so chose that.  Up to 
now, your sheet does not have a name, so you will be prompted for one:
.DS
Save sheet to XDR file:
.DE
Type ``first_step'' and enter.  Unless you see an error message after,
your sheet is written to a file.
.P
If you have come this far, quit (from the main menu) and you have
successfully completed your first steps on using teapot.\*F
.FS
It may be a good idea to make and enjoy some tea at this point.  :)
.FE
.\"}}}
.\"}}}
.\"{{{  The command mode
.H 1 "The command mode"
Right after starting teapot, you are in the command mode.  Many
functions from the command mode are also available from menues, but
using keys is faster and some things, like moving the cell cursor,
are only available through keys.  The command mode accepts:
.DS CB
.TS
allbox;
l l.
Next line	move cell cursor up
Previous line	move cell cursor down
Forward character	move cell cursor left
Backward character	move cell cursor right
Begin	move cell cursor to column 0
End	move cell cursor to last column
<	move cell cursor to line 0
>	move cell cursor to last line
\&_	move cell cursor to sheet 0
*	move cell cursor to last sheet
/, F10	main menu
F2	save menu
F3	load menu
\&.	mark blocks (see below)
Enter	Edit cell contents (see below)
q	Quit
.TE
.DE
Besides the regular line editor functions as explained previously, you
may use ^o to temporarily leave the editor in order to move around in
the sheet if you are editing cell contents.  Another ^o brings you back
to the line editor.  While moving around in the sheet, you can insert
the value (v) or position (p) at the cursor position in the edited
cell.
.P
\&.\& (dot) marks blocks: The first time it marks the beginning of a
block, which is then extended by moving the cell cursor.  The next time,
it marks the end of the block which lets you move the cell cursor after
without changing the block.  The third time, it removes the block marks
again.
.\"}}}
.\"{{{  Interactive functions
.H 1 "Interactive functions"
All interactive functions which modify the cell at the position of the
cell cursor will be applied a block of cells, if one is marked.  Such
functions will be marked with \(dg.
.\"{{{  Saving and loading sheets
.H 2 "Saving and loading sheets"
.\"{{{  Save and load in XDR format
.H 3 "Save and load in XDR format"
XDR (eXternal Data Representation) is a standard invented by Sun
Microsystems which defines a canonical way of storing/transporting data
on external media.  Its advantage is that it is widely available and
that it defines a portable floating point number format.  The native
teapot file format uses XDR so it is portable across different machine
architectures and operating systems.  The advantage of this over the
portable ASCII format is that due to the (usually) missing conversion
calculations any floating point constants will be saved/loaded exactly
without conversion errors.
.\"}}}
.\"{{{  Save and load in ASCII format
.H 3 "Save and load in ASCII format"
The ASCII file format allows easy generation/modification of saved
sheets by shell scripts.  Due to binary/ASCII conversion, there may
be conversion errors in floating point constants.
.\"}}}
.\"{{{  Save in formatted ASCII format
.H 3 "Save in formatted ASCII format"
The generated formatted ASCII files contain about what you see on the
screen.  If your sheet has more than one layer, then the various layers
will be saved seperated by form feeds.
.\"}}}
.\"{{{  Save in tbl format
.H 3 "Save in tbl format"
teapot generates \fItbl\fP(1) table bodies which are supposed to be used
like this:
.DS I
\&.TS
options;
\&.so file.tbl
\&.TE
.DE
You will have to use \fIsoelim\fP(1) to eliminate the \&.so request
before the tbl run.
.\"}}}
.\"}}}
.\"{{{  Copying or moving blocks of cells
.H 2 "Copying or moving blocks of cells"
To copy a block of cells, mark it, then move the cell cursor to where
the upper left corner of the copy should be and issue the copy command.
Moving works similar, just use the move command.  Of course you can mark
three-dimensional blocks and copy them anywhere in the
three-dimensional sheet, but doing so requires a good three-dimensional
imagination to get what you want.
.\"}}}
.\"{{{  Clear cells
.H 2 "Clearing cells \(dg"
Clearing means to delete the cell contents and set all attributes to
the default value.  If you want to preserve the attributes, just edit
the contents of a cell and delete them.
.\"}}}
.\"{{{  Insert cells
.H 2 "Insert cells \(dg"
Since work sheets can be three-dimensional, you can insert cells in all
three dimensional, too.  The inserted cells will be empty and their
attributes have the default values.  Cells will always be moved away
from the front upper left corner to make room for the inserted cells.
To insert a row row-wise, mark the entire row at the position where you
want to insert the new row, then use the insert command and chose
inserting in Y direction.
.\"}}}
.\"{{{  Delete cells
.H 2 "Delete cells \(dg"
Deleting works contrary to inserting.  The deleted cells will be filled
by moving neighbour cells to their positions.  You will be prompted for
the direction from where those cells will be taken.  Deleting an entire
column column-wise is done by marking the column, use the delete command
and chose X direction.
.\"}}}
.\"{{{  Setting the column width
.H 2 "Setting the column width"
The column width only affects the screen display, not the formatting of
the final output with the expection of saved formatted ASCII files.  It
is intended to let you make better usage of the screen for more
overview.  If the width is too small to display the cell value, stars
will be displayed.
.\"}}}
.\"}}}
.\"{{{  Cells
.H 1 "Cells"
In this chapter, \fBbold\fP marks literals which have to be entered
exactly as shown.  \fIItalic\fP mark place holders, they are not to be
taken literally.
.\"{{{  Attributes
.H 2 "Attributes"
.P
Each cell consists of an expression, the result of that expression and
several attributes:
.BL
.LI
A cell label, which is useful because it avoids to directly address
cells by their position.
.LI
The cell adjustment, which determines if the cell value is printed left
adjusted, right adjusted or centered.
.LI
The precision of printed floating point numbers.  This only changes
what is printed, teapot always uses the maximum precision for
calculations.  It only affects the output, if the cell value is a floating
point number.
.LI
If floating point numbers should be printed in scientific notation
(0.123e1) or as decimal number (1.23).  It only affects the output, if
the cell value is a floating point number.
.LI
If the cell is shadowed by its left neighbour.  This means that the
left neighbour cell additionally uses the room of the shadowed cell.
.LI
If the cell is locked which prevents to accidentally edit or clear it. 
Note that block operations override this attribute, because when you
deal with blocks, you usually know what you are doing.
.LE
.\"}}}
.\"{{{  Data Types
.H 2 "Data Types"
.P
In teapot, each value has an associated data type.  The following
data types exist:
.BL
.LI
empty.  Empty cells have this as value.
.LI
string.  A string is a sequence of characters enclosed by double
quotes: \fB"This is a string"\fP
.LI
floating point.  Floating point values are inexact, their precision and
range depends on the implementation of the C type double on your
system.  An example is: \fB42.0\fP
.LI
integer.  Integer values are exact, their range depends on the C type
long on your system.  An example is: \fB42\fP
.LI
location.  Cell labels and the \fB&()\fP function have this type, but
there are no location constant literals.
.LI
error.  Syntactical, semantical (type mismatch) errors cause this value,
as well as division by 0 and the function \fBerror()\fP.  An error
always has an assigned error message.  Functions and operators, when
applied to a value of the type error, evaluate to just that value.  That
way, the first error which was found deep inside a complicated
expression will be showed.
.LE
.\"}}}
.\"}}}
.\"{{{  Arithmetic expressions
.H 1 "Arithmetic expressions"
.\"{{{  Operators
.H 2 "Operators"
Unlike other spread sheets, the operators in teapot check the type
of the values they are applied to, which means the try to add a string
to a floating point number will result in an type error.  The following
operators are available:
.VL \n(Pi
.LI \fIx\fP\fB+\fP\fIy\fP
evaluates to the sum if \fIx\fP and \fIy\fP are numbers.  If \fIx\fP and
\fIy\fP are strings, the result is the concatenated string.  If \fIx\fP
or \fIy\fP is empty, the result is the other element.
.LI \fIx\fP\fB\-\fP\fIy\fP
evaluates to the difference if \fIx\fP and \fIy\fP are numbers.  If
\fIx\fP is empty, the result is \fB\-\fP\fIy\fP.  If \fIy\fP is empty, the
result is \fIx\fP.
.LI \fIx\fP\fB*\fP\fIy\fP
evaluates to the product if \fIx\fP and \fIy\fP are numbers.  If \fIx\fP
or \fIy\fP is empty, the result is 0.
.LI \fIx\fP\fB/\fP\fIy\fP
evaluates to the quotient if \fIx\fP and \fIy\fP are numbers.  If
\fIx\fP is empty, the result is 0.  If \fIy\fP is empty, the result is
the error ``division by 0''.
.LI \fB\-\fP\fIx\fP
evaluates to \fB\-\fP\fIx\fP if \fIx\fP is a number.  If \fIx\fP is
empty, the result will be empty, too.
.LI \fIx\fP\fB^\fP\fIy\fP
evaluates to \fIx\fP to the power of \fIy\fP.  If \fIx\fP or \fIy\fP are
empty, they will be considered to be the integer value 0.
.LI \fB(\fP\fIexpression\fP\fB)\fP
.br
evaluates to the expression.
.LI \fIlabel\fP
evaluates to the location it is set at.
.LI \fIfunction\fP\fB(\fP\fIargument\fP\fB,\fP...\fB)\fP
.br
evaluates to the value of the function applied to the values resulting
from evaluating the argument expressions.
.LE
.\"}}}
.\"{{{  Functions
.H 2 "Functions"
This section documents all functions available in expressions.
The functions are given in a C-like notation, so use \fB@(0,0,0)\fP
instead of \fB@(integer 0, integer 0, integer 0)\fP.  If no type is
given for the result of a function, it means the result type depends on
the arguments.  Brackets mark optional arguments.
.VL \n(Pi
.\"{{{  @
.LI "\fB@(\fPinteger \fIx\fP\fB,\fPinteger \fIy\fP[\fB,\fPinteger \fIz\fP]\fB)\fP"
.br
.sp -0.5
.LI "\fB@(\fPlocation \fIl\fP\fB)\fP" 1
.br
returns the value of the cell at position \fIx\fP, \fIy\fP, \fIz\fP.  If
\fIz\fP is omitted, the current \fIz\fP is used.
.\"}}}
.\"{{{  &
.LI "location \fB&(\fPinteger \fIx\fP\fB,\fP integer \fIy\fP[\fB,\fP integer \fIz\fP]\fB)\fP"
.br
returns a pointer to the cell at location \fIx\fP, \fIy\fP, \fIz\fP.  If
\fIz\fP is omitted, the \fIz\fP position of the evaluated expression is
used.
.\"}}}
.\"{{{  error
.LI "error \fBerror(\fPstring \fImessage\fP\fB)\fP"
.br
evalutes to an error with the specified message.
.\"}}}
.\"{{{  int
.LI "int \fBint(\fPfloat \fIx\fP\fB)\fP"
.br
converts \fIx\fP to an integer value by cutting off the fractional
part.
.\"}}}
.\"{{{  frac
.LI "float \fBfrac(\fPfloat \fIx\fP\fB)\fP"
.br
evaluates to the fractional part of \fIx\fP.
.\"}}}
.\"{{{  here.x, here.y, here.z
.LI "int \fBhere.x(\fP[location \fIl\fP]\fB)\fP"
.br
.sp -0.5
.LI "int \fBhere.y(\fP[location \fIl\fP]\fB)\fP"
.br
.sp -0.5
.LI "int \fBhere.z(\fP[location \fIl\fP]\fB)\fP"
.br
evaluate to the \fIx\fP, \fIy\fP and \fIz\fP position of the given
location, of the currently updated cell if none is given.  These
functions are usually used in combination with the \fB@\fP function for
relative relations to other cells.
.\"}}}
.\"{{{  ctos
.LI "string \fBctos(\fPinteger \fIx\fP\fB,\fP integer \fIy\fP[\fB,\fP integer \fIz\fP]\fB)\fP"
.br
.sp -0.5
.LI "string \fBctos(\fPlocation \fIl\fP\fB)\fP"
.br
evaluates to a string containing the current value of the given cell.
If \fIz\fP is omitted, the \fIz\fP position of the expression is used.
.\"}}}
.\"{{{  sum
.LI "\fBsum(\fPlocation \fIl1\fP\fB,\fP location \fIl2\fP\fB)\fP"
.br
evaluates to the sum of all values in the block marked by the corners
pointed to by \fIl1\fP and \fIl2\fP.
.\"}}}
.\"{{{  n
.LI "int \fBn(\fPlocation \fIl1\fP\fB,\fP location \fIl2\fP\fB)\fP"
.br
evaluates to the number of non-empty cells in the block marked by the
corners pointed to by \fIl1\fP and \fIl2\fP.
.\"}}}
.\"{{{  len
.LI "string \fBlen(\fPstring \fIs\fP\fB)\fP"
.br
evaluates to the length of \fIs\fP.
.\"}}}
.\"{{{  min
.LI "\fBmin(\fPlocation \fIl1\fP\fB,\fP location \fIl2\fP\fB)\fP"
.br
evaluates to the minimum of all values in the block marked by the corners
pointed to by \fIl1\fP and \fIl2\fP.  Note that the empty cell is the
smallest element possible in the less-or-equal relation, so if there is
an empty cell within the block, the minimum will be an empty value, too.
.\"}}}
.\"{{{  abs
.LI "float \fBabs(\fPfloat \fIx\fP\fB)\fP"
.br
.sp -0.5
.LI "int \fBabs(\fPint \fIx\fP\fB)\fP"
.br
evaluates to the absolute value of \fIx\fP.
.\"}}}
.LE
.\"}}}
.\"}}}
.\"{{{  Expression grammar
.H 1 "Expression grammar"
.TS
lfI c l.
digit	::=	\fB0\fP | .. | \fB9\fP
hex_digit	::=	\fB0\fP | .. | \fB9\fP | \fBa\fP | .. | \fBf\fP
octal_digit	::=	\fB0\fP | .. | \fB7\fP
decimal_integer	::=	\fIdigit\fP { \fIdigit\fP }
hex_integer	::=	\fB0x\fP \fIhex_digit\fP { \fIhexdigit\fP }
octal_integer	::=	\fB0\fP \fIoctal_digit\fP { \fIoctdigit\fP }
integer	::=	\fIdecimal_integer\fP | \fIhex_integer\fP | \fIoctal_integer\fP
float	::=	\fIdigit\fP { \fIdigit\fP } [ \fB.\fP ] { \fIdigit\fP } [ \fBe\fP | \fBE\fP [ \fB+\fP | \fB\-\fP ] \fIdigit\fP { \fIdigit\fP } ]
quoted_character	::=	\fB\e\fP \fIany_character\fP
character	::=	\fIany_character\fP | \fIquoted_character\fP
string	::=	\fB"\fP { \fIcharacter\fP } \fB"\fP
identifier_character	::=	\fB_\fP | \fB@\fP | \fB&\fP | \fB.\fP | \fIalpha_character\fP
identifier	::=	\fIidentifier_character\fP { \fIidentifier_character\fP | \fIdigit\fP }
function	::=	\fIidentifier\fP \fB(\fP [ \fIterm\fP { \fB,\fP \fIterm\fP } ] \fB)\fP
label	::=	\fIidentifier\fP
parenterm	::=	\fB(\fP \fIterm\fP \fB)\fP
negterm	::=	\fB\-\fP \fIterm\fP
primary	::=	\fIfunction\fP | \fIlabel\fP | \fIparenterm\fP | \fInegterm\fP
powterm	::=	\fIprimary\fP { \fB^\fP \fIprimary\fP }
mathterm	::=	\fIpowterm\fP { \fB/\fP | \fB*\fP \fIpowterm\fP }
factor	::=	\fImathterm\fP { \fB+\fP | \fB\-\fP \fImathterm\fP }
term	::=	\fIfactor\fP {\fB<\fP | \fB<=\fP | \fB>=\fP | \fB>\fP | \fB==\fP | \fB!=\fP \fImathterm\fP }
.TE
.\"}}}
