-*-Mode:bolio; Package:zwei-*-
.chapter Fundamental Data Structures

.section The Tick
.cindex ticks
.setq tick section-page

Has a line changed since it was displayed on the screen in a certain window?
Has a buffer changed since it was saved in a file?
ZWEI arranges to answer these questions, and many similar ones, by
keeping a single counter called 3zwei:*tick** which is incremented
whenever any significant operation takes place, and labeling each
text line, window line and buffer with the tick at which it was
last updated.  A text line's tick is updated when the line is changed.
A window line's tick is updated when the window line's contents are drawn on the screen.
Therefore, if the tick of the window line's text line is greater than the
tick of the window line itself, the window line must be redrawn on the screen.
Other such questions are answered in similar ways.

.defvar zwei:*tick*
The tick counter.
.end_defvar

.defun zwei:tick
Increments the tick counter and returns the new tick.
.end_defun

.section Text
.cindex lines
.setq lines section-page

.lisp
1.. you might grow up to be a string.*
1  The string is a data type that's simple, it's true,*
1  But slow for what editors must do.*
1     It's quick to access, till you must insert.*
1     Then that's the time you really you lose your shirt.*
1  So if you want to write a slow and clunky thing*
1  Just store the text as one big string!*
.end_lisp

The string is a data type conceptually suitable for representing
text being edited, but it has the practical deficiency that inserting
or deleting from the middle of it is slow.  ZWEI uses a complicated
data format which can be thought of as a different implementation of
the abstraction called "strings", designed to make ZWEI's operations more
efficient.

Text in ZWEI is divided into 2lines*, each line represented in a separate array.
Each line points to the following line and to the previous line.
Thus lines are grouped into a sequence.  The sequence has a first line,
whose previous line is 3nil*, and a last line, whose next line is 3nil*.

No line ever contains a 3Return* character; a 3Return* is considered
to be present implicitly at the boundary between two successive lines.
There is no implicit 3Return* before the first line or after the last
line.  If the text ends with a 3Return* character, as it often does,
then the last line is empty.

Deletion of a 3Return* character coalesces two lines into one;
insertion of one splits a line into two.  The line structure is changed
by linking in the additional line or unlinking the extraneous one.

A line is an array of type 3art-string* or 3art-fat-string*;
its elements are the characters in the line.
The line also has these array leader slots:
.ftable 3
.item zwei:line-length
The fill pointer.
.item zwei:line-next
The following line, or 3nil*.
.item zwei:line-previous
The previous line, or 3nil*.
.item zwei:line-bp-list
A list of all the relocatable buffer pointers that point into this line.
This list is used in order to relocate them.
.item zwei:line-tick
The tick at which the most recent modification of this line took place
(see (tick)).
.item zwei:line-node
The innermost node containing this line.  See (nodes).
.item zwei:line-plist
A property list for data associated with the line itself.
For example, 3DIRED* uses this to hold information
on the file represented by the line.  Even though 3DIRED*
modifies the line to insert or remove a D in the first column,
this property list does not go away.
.item zwei:line-contents-plist
A property list for information about the contents of the line.
Any change to the line's contents sets this slot to 3nil*.

A property in this slot are used by the commands for parsing
Lisp expressions to record derived from parsing the line.
As long as the line does not change, the property will still
be present and can enable parsing to go faster.  If the line
is edited, the property disappears, which will cause the line
to be reparsed.
.end_table

An 3art-fat-string* line is used whenever there is a character
in the line whose font number is not zero.  Inserting such a
character into a line will cause its array type to change automatically.

There is no way to find a line in a sequence of lines except
to trace through 3zwei:line-next* and 3zwei:line-previous*
pointers until it is found or not found.  This structure makes
insertion of lines efficient, but makes it hard to tell which
of two places in the sequence comes earlier.

.section Buffer Pointers
.cindex buffer pointer
.cindex bp (buffer pointer)
.cindex temporary buffer pointer
.cindex relocating buffer pointer
.setq buffer-pointers section-page

A 2buffer pointer* ("bp") is an object that identifies a certain spot
within some text.  It should be thought of as pointing between two
characters rather than at one character.  When an editing command decides
to "move forward two lines", the place it "moves from" must be specified
with a buffer pointer, and the place "moved to" is returned as another
buffer pointer.  Point and Mark are both represented internally by
buffer pointers.

If you use *Control-X S* to store a pointer to a place in the text,
you will find that it stays between the same pair of characters when you
insert or delete earlier text, even on the same line.  This is called
automatic relocation.  ZWEI programs can create any number of buffer
pointers that will relocate automatically; Point and Mark are examples
of such.  These pointers must be explicitly released when they are no
longer needed.  Programs can also create non-relocating pointers, known
as "temporary" pointers, which are cheaper to use, and sufficient for
use within bounded contexts.

A buffer pointer is actually a list of length two or three.
A temporary buffer pointer has two elements:
.lisp
(2line* 2index*)
.end_lisp
where 2index* is the number of a character position within 2line*.
If 2index* is zero, the pointer points to the beginning of the line.
If 2index* equals the length of the line, the pointer points to the
end of the line, just before the implicit 3Return* (present unless
this line is the last line).

.defun zwei:bp-line bp
The line which 2bp* points into.
.end_defun

.defun zwei:bp-index bp
The index at which 2bp* points, within its line.
.end_defun

Relocating buffer pointers have three elements:
.lisp
(2line* 2index* 2status*)
.end_lisp
The first two elements give the current position of the buffer pointer;
they are interpreted the same for all types of pointers.
The third element 2status*, by being non-3nil*, indicates that this
is a relocating buffer pointer.

There are two possible values of 2status*, which are 3:normal* and
3:moves*.  These specify how to relocate the pointer when text is
inserted right where it points.  A 3:normal* buffer pointer is
left unchanged, but a 3:moves* pointer is relocated to point after
the inserted text.  The 3:normal* pointer can be thought of as
attached to the previous character, while the 3:moves* pointer
is attached to the following character.

.defun zwei:bp-status bp
The status of 2bp*: 3nil*, 3normal* or 3:moves*.
.end_defun

All relocating buffer pointers for a given 2line* are elements of
that line's 3zwei:line-bp-list*.  When text is inserted or deleted
in 2line*, that list is used to find all the buffer pointers that
might need to be relocated.

.defun zwei:create-bp line index &optional status
Creates and returns a buffer pointer to character 2index* within 2line*.
2index* should be between zero and the length of 2line*, inclusive.
2status* says which kind of relocation should be done;
it must be 3nil*, 3:normal* or 3:moves*.
.end_defun

.defun zwei:copy-bp bp &optional status
Creates and returns a buffer pointer of relocation type 2status* which points
where 2bp* points.
.end_defun

.defun zwei:move-bp bp &optional bp-or-line index
Makes the existing buffer pointer 3bp* point to a different place.
This is the same as rplac'ing the elements of 2bp* only if 2bp*
is a temporary bp; for relocating ones, additional work is done to
ensure correct relocation of the new position.

The new position can be specified either with a single argument,
another buffer pointer whose position is copied, or with two arguments,
a line and an index.
.end_defun

.defun zwei:flush-bp bp
Releases the relocating buffer pointer 2bp*.  It will no longer be
relocated, and may be garbage collected.  The main gain is that the
editor no longer incurs the overhead of thinking about 2bp*.
.end_defun

.defun zwei:bp-= bp1 bp2
Returns 3t* if the two arguments point to the same place.
Their relocation types do not enter into the comparison.
.end_defun

.defun zwei:bp-< bp1 bp2
Returns 2t* if 2bp1* points to a place before where 2bp2* points.
The value is 3nil* if they point to the same place.

It is the caller's responsibility to make sure that the two buffer pointers
point into the same sequence of lines (that is, in Zmacs, the same buffer).
Otherwise, the function may take a long time and will return an
unpredictable value.
.end_defun

.defun zwei:bp-in-interval-p bp interval-or-bp1 &optional bp2 in-order-p
The last three arguments specify an interval (see (intervals)); the
function returns 3t* if 3bp* points anywhere within that interval.
This includes either end of the interval.  The caller's responsibility
is as for 3zwei:bp-<*.
.end_defun

.defun zwei:bps-far-apart bp1 bp2 nlines
Returns 3t* if 2bp1* and 2bp2* are more than 2nlines* lines
apart.  This can be calculated in time proportional to 2nlines*
regardless of where the arguments point.
.end_defun

.defun zwei:bp-char bp
Returns the character that follows where 2bp* points,
or 3nil* if 2bp* points at the end of the buffer.
.end_defun

.defun zwei:bp-char-before bp
Returns the character that precedes where 2bp* points,
or 3nil* if 2bp* points at the end of the buffer.
.end_defun

.defun zwei:looking-at bp string
Returns 3t* if the text following where 2bp* points matches 2string*,
not considering case.  2string* must not contain any 3Return* characters.
.end_defun

.defun zwei:looking-at-backward bp string
Returns 3t* if the text preceding where 2bp* points matches 2string*,
not considering case.  2string* must not contain any 3Return* characters.
.end_defun

.defun zwei:bp-looking-at-list bp list
2list* should be a list of characters or strings; returns 3t*
if the text following where 2bp* points matches any element of 2list*.
Case is ignored in comparisons.
.end_defun

Many other functions that return buffer pointers are described
in (motion-functions).

.section Intervals
.cindex intervals
.setq intervals section-page

An 2interval* is a range of text, described by two buffer pointers.
An interval can also mean a object which is an instance of the flavor
3zwei:interval*; these contain two buffer pointers which specify a
range of text.

All functions in ZWEI that operate on a range of text expect the
caller to specify an interval.  This can be done by passing two
buffer pointers separately, or by passing just one object, an interval.

.subsection Intervals as Objects

.defflavor zwei:interval
An interval represents a range of text.
It has two instance variables, which hold buffer pointers
to the beginning and the end of the text.
.ftable 3
.item zwei:interval-first-bp
The buffer pointer to the beginning of the text in the interval.
.item zwei:interval-last-bp
The buffer pointer to the end of the text in the interval.
.end_table
.end_defflavor

.definstvar zwei:interval zwei:first-bp
.definstvar1 zwei:interval zwei:last-bp
These hold the interval's two buffer pointers.
.end_definstvar

Instances of 3zwei:interval* are used to represent ranges of text;
also, other more complicated flavors which include this flavor are used
for other purposes.  For example, buffers are a kind of interval.

.defun zwei:make-interval &optional first-bp last-bp
Creates and returns an interval containing the two specified buffer pointers.
This is very fast, as it avoids going through the flavor system;
it creates an instance with precisely specified instance variables.
.end_defun

.subsection Intervals as Arguments

Functions which expect to be passed an interval actually accept up
to three arguments.  Here is a fictitious example, 3zwei:confuse-interval*.

.defun-no-index zwei:confuse-interval interval-or-start &optional end in-order-p
Call with a single argument, an interval,
or with two arguments, both buffer pointers.
If you know which of the buffer pointers is the earlier of the two,
pass it as the first argument, and supply 3t* for 2in-order-p*.
Otherwise, this function will compare the two buffer pointers itself
to determine which one is the beginning of the interval and which the end.
This comparison takes time, so it is better for the caller to specify the order
if it can.
.end_defun

If the function takes additional arguments beyond those that specify the interval,
and you wish to pass them, you must use a full three arguments for the interval.
Use 3nil* for any of the three that you would have omitted.

.defun zwei:copy-interval interval-or-from-bp &optional to-bp in-order-p into-interval
Copies the text of the interval specified by the first three arguments
into a new interval.  The new interval is actually a node (see below).
If 2into-interval* is non-3nil*, the text is copied into that interval instead.
.end_defun

.defun zwei:string-interval  interval-or-from-bp &optional to-bp in-order-p remove-fonts-p
Copies the text of the interval specified by the first three arguments
into a string, which is returned.  If 2remove-fonts-p* is non-3nil*,
all characters have their font information removed.  Otherwise, the string
returned is made a fat string if necessary so that all the characters in the
interval can have their font information preserved.
.end_defun

.subsection The Current Interval; Nodes

The text that the editor is operating on is represented by an interval,
the value of 3zwei:*interval*.  All editor functions ought to detect
the "beginning" or "end" of the text by comparison with the buffer pointers
in this interval rather than checking only for a line with no predecessor
or no successor.

.defmetainstvar "editor windows" zwei:*interval*
The interval whose contents are the text "being edited".
The editor window flavors actually used all expect this to be
more than just an interval.
.end_defmetainstvar

.cindex nodes
.setq nodes page

.defflavor zwei:node (3zwei:interval* 3si:property-list-mixin*)
An interval which is capable of being the current interval of
an editor window.
The current interval of a window must be a 2node*.
The first-bp of the node must be a relocating buffer pointer of type
3:normal* so that any text inserted at the beginning of the node's
contents will appear to be "inside" the node.  For a similar reason,
the last-bp must be of type 3:moves*.
.end_defflavor

.definstvar zwei:node zwei:tick
The tick of the most recent change to any text in this node.
.end_definstvar

.definstvar zwei:node zwei:read-only-p
Non-3nil* if this node is 2read-only*; that is, editing commands to
change its text are not normally allowed.  This flag exists in all nodes
but is only checked in the top-level node.
.end_definstvar

.definstvar zwei:node zwei:undo-status
In a top-level node, records all changes made to the text of the node
so that they can be undone by the 3Undo* command.
It can also be 3:none* to indicate that undo information should
not be recorded, or 3nil* which means that a suitable undo-status
data structure should be created as soon as there is something to record.
See (undo-status) for more details.
.end_definstvar

.definstvar zwei:node si:property-list
A property list, created by 3si:propery-list-mixin*.
3get* and 3putprop* can be used on nodes.
.end_definstvar

.defun zwei:node-tick node
.defun1 zwei:node-read-only-p node
.defun1 zwei:node-undo-status node
.defun1 zwei:node-property-list node
Accessor defsubsts for the above four instance variables of 2node*.
.end_defun

.defun zwei:make-node &optional first-bp last-bp tick next previous superior inferiors undo-status read-only-p plist
Creates and returns a node, all of whose instance variables come from the arguments specified
(or 3nil* for omitted arguments).  The four instance variables not described
so far pertain to the node hierarchy and are described in the following section.

This is used by certain editor primitives in which speed is essential.
It avoids nearly all of the flavor system, including the 3:init* operation.
.end_defun

.subsection Node Hierarchy
.cindex node hierarchy

Nodes are arranged in a hierarchy; the text of any one node
must be contained within the text of its superior node.
Nodes without superiors are called 2top-level* nodes.
3Every line of text
in the editor belongs to one and only one top-level node.*
Inferior nodes of a common superior can overlap, however.

The inferior nodes of any single node are arranged in an order;
the beginnings of these inferiors must appear in the text in that order.
(One or more successive inferior nodes may begin at the same place,
but a later inferior may not begin before an earlier inferior).
The ends of the inferior nodes must satisfy the same sort of constraint.

.definstvar zwei:node zwei:inferiors
The list of inferior nodes of this node,
in their correct order.
.end_definstvar

.definstvar zwei:node zwei:superior
The superior node of this node, or 3nil* if this is a top level node.
.end_definstvar

.definstvar zwei:node zwei:next
.definstvar1 zwei:node zwei:previous
The next and previous nodes, among the inferiors of this node's superior.
.end_definstvar

.defun zwei:node-superior node
.defun1 zwei:node-inferiors node
.defun1 zwei:node-next node
.defun1 zwei:node-previous node
Accessor defsubsts for the above four instance variables of 2node*.
.end_defun

.defun zwei:node-top-level-node node
Returns the ultimate superior of 2node*.  This ultimate superior
has 3nil* as its 3zwei:node-superior*.
.end_defun

.setq line-node page
Each line contains a pointer to the smallest (most inferior) node
that contains it.  (It can happen that nodes overlap and more than
one node at that level contains the line, but the line still
claims to belong to only one.)  This pointer is in the line's
3zwei:line-node* slot (see (zwei:line-node-fun)).

.defun zwei:line-top-level-node line
The top-level node containing 2line*.  There can only be one.
.end_defun

.defun zwei:bp-node bp
.defun1 zwei:bp-top-level-node bp
Find the lowest level node or the top-level node of the line
which 2bp* points to.
.end_defun

.defflavor zwei:section-node
.end_defflavor

.defun zwei:get-section-node-name section-node
Returns a string saying what 2section-node* contains.
Uses the name defined in the DEFUN line, or else uses the section name.
The value may be a string or a function spec.
.end_defun

.section Buffers
.cindex buffers
.setq buffers section-page

A 2buffer* is a sophisticated kind of node intended for use as
the current interval in certain well-extended editors such as Zmacs
and ZMail.

.defflavor zwei:named-buffer (3zwei:node*)
Like a node, but has a 2name*.
.end_defflavor

.definstvar zwei:named-buffer zwei:name
The name of the buffer.  It should be a string.
.end_definstvar

.defflavor zwei:file-buffer (3zwei:named-buffer*)
A kind of buffer which is associated with a file.
It can record the file's name and when the file was read or written.
.end_defflavor

.defun zwei:buffer-pathname buffer
Accessor defsubst for the slot in 2buffer* that stores
the name of the file associated with 2buffer*.
It can also be 3nil* if 2buffer* does not happen to be associated
with a file.  A file buffer does not have to be associated with a file;
it merely has the capacity to be.
.end_defun

.defun zwei:buffer-generic-pathname buffer
Accessor defsubst for the generic pathname of the file associated with 2buffer*,
or 3nil* if none.
.end_defun
.c Actually, it is a dummy-pathname.  But that should be changed!!

.defun zwei:buffer-file-id buffer
Accessor defsubst for the slot that
records information about the particular version of 2buffer*'s associated file
that was last read or written.  The information is
the value returned by the 3:info* operation on the stream
that was used to read or write the file.  It is usually a list
containing elements that describe the exact file name including
the version number, and the creation date.

The file-id is used to check, before saving the file, whether it has been changed
by something other than this editor buffer.

The file-id is 3t* in a buffer that associated with a file which has
never been read or saved.  This is the situation if 3M-X Set Visited
Filename* is done on a buffer such as 3*Buffer-1*.

The file-id is 3nil* in a buffer not associated with a file.
.end_defun

.defun zwei:buffer-file-read-tick buffer
Accessor defsubst for
the tick as of the last time that 2buffer*'s text was read from its file.
If 2buffer* is not associated with the file, this is the tick of the time
it was created.
.end_defun

.defun zwei:buffer-file-tick buffer
.defun zwei:buffer-tick buffer
Accessor defsubst for
the tick as of the last time that 2buffer*'s text was either read from its file
or saved in the file.
If 2buffer* is not associated with the file, this is the tick of the time
it was created.

These two names are synonymous.
.end_defun

.defun zwei:buffer-version-string buffer
Accessor defsubst for a slot in 2buffer* that holds
a string which is a printed representation of the version number
of the last file version read or saved.  Strictly for the mode line.
The value is 3nil* if the file has no version number or there is no file.
.end_defun

.definstvar zwei:file-buffer zwei:pathname
.definstvar1 zwei:file-buffer zwei:generic-pathname
.definstvar1 zwei:file-buffer zwei:file-id
.definstvar1 zwei:file-buffer zwei:file-read-tick
.definstvar1 zwei:file-buffer zwei:file-tick
.definstvar1 zwei:file-buffer zwei:version-string
The instance variables accessed by the preceding defsubsts.
.end_definstvar

.subsection Zmacs Buffers
.cindex Zmacs buffers
.setq zmacs-buffers section-page

A Zmacs buffer must have additional features to enable
a Zmacs window to switch between different buffers, maintaining modes,
point and mark separately for each buffer.

.defflavor zwei:zmacs-buffer (3zwei:file-buffer*)
The flavor used for all Zmacs buffers.
.end_defflavor

.defun zwei:buffer-saved-point buffer
Accessor defsubst for 2buffer*'s saved Point.
This is a buffer pointer which, when 2buffer* is not current,
points to where Point was the last time 2buffer* was current.
When 2buffer* is selected again, Point is moved to that spot.
If 2buffer* is selected in more than one window at the same time,
the interactions between the Points of the various windows and this
variable are slightly unpredictable.
.end_defun

.defun zwei:buffer-saved-mark buffer
Like the previous, but for the Mark rather than for Point.
.end_defun

.defun zwei:buffer-saved-window-start-bp buffer
Like the previous, for the spot which is displayed at the top of the window.
This is so that if you switch away from the buffer and back,
it displays with the same alignment in the window as it did before.
.end_defun

.defun zwei:buffer-saved-major-mode buffer
Like the previous, for the buffer's major mode.
The value is a symbol such as 3zwei:lisp-mode*,
copied into this slot when the buffer is deselected
and examined when the buffer is selected.

Paradoxical interactions between windows are rare in
practise because normally the major mode of any one buffer
never changes.
.end_defun

.defun zwei:buffer-saved-mode-list buffer
Like the previous, for the value of 3zwei:*mode-list*
which records the selected minor modes.
.end_defun

.defun zwei:buffer-saved-package buffer
.defun1 zwei:buffer-package buffer
Like the previous, for the package to use when evaluating or compiling
anything while this buffer is selected.
The value is an actual package object.
.end_defun

.defun zwei:buffer-saved-font-alist buffer
Like the previous, for the list of fonts to use while editing this buffer.
.end_defun

.definstvar zwei:zmacs-buffer zwei:saved-point
.definstvar1 zwei:zmacs-buffer zwei:saved-mark
.definstvar1 zwei:zmacs-buffer zwei:saved-window-start-bp
.definstvar1 zwei:zmacs-buffer zwei:saved-major-mode
.definstvar1 zwei:zmacs-buffer zwei:saved-mode-list
.definstvar1 zwei:zmacs-buffer zwei:saved-package
.definstvar1 zwei:zmacs-buffer zwei:saved-font-alist
The instance variables accessed by the above defsubsts.
.end_definstvar

The property list of a Zmacs buffer (which it inherits from the flavor
3zwei:node*) is used to store the file attributes (Mode, Package,
Base, Lowercase, Patch-file, etc.) that pertain to the text in the
buffer.  The property names used are 3:mode*, 3:package*, 3:base*,
etc.  See (buffer-attributes).

Certain other properties also have standard meanings:
.table 3
.xitem :killed "buffer property"
Non-3nil* indicates a buffer that has been killed by the user
and should not be used.  Pointers to a killed buffer are not all
eliminated when the buffer is killed; any time you salt away a
pointer to a buffer, you must check each time you use that pointer
that the buffer is not killed.

.xitem :special-type "buffer property"
The special-type of a buffer is used to identify buffers
used for special purposes such as 3DIRED*, 3BDIRED*, 3M-X Mail*
and 3M-X Edit Buffers*.  The value is a keyword; currently
the defined keywords are 3:dired*, 3:bdired*, 3:edit-buffers*
and 3:mail*.
.kindex :dired "buffer special type"
.kindex :bdired "buffer special type"
.kindex :mail "buffer special type"
.kindex :edit-buffers "buffer special type"
.c possibilities?  warnings?

The special-type is used to control how 3M-X Revert Buffer*
operates on the buffer; this is how reverting a DIRED buffer knows
to reread the directory listing.  It is also sometimes used for finding
buffers to reuse.  Finally, buffers with non-3nil* special-types
do not get offered automatically for saving.

.xitem :dont-sectionize "buffer property"
A non-3nil* value for this property says that sectionization should
not be done unless the user explicitly requests it.
3M-X Find File No Sectionize* puts on this property.
See (sectionization).
.end_table

.defun zwei:node-special-type zmacs-buffer
Returns the value of 2zmacs-buffer*'s 3:special-type* property.
This is defined on nodes, but in practice is interesting only on Zmacs buffers.
.end_defun

.section Windows

.chapter Text Primitives

.section Position Predicates

.defun zwei:beg-line-p bp
.defun1 zwei:end-line-p bp
3t* if 2bp* points to the beginning of a line (or, the end of a line).
The beginning of the current interval is always considered the beginning of a line.
.end_defun

.section Motion Functions
.cindex motion functions
.cindex cursor motion
.setq motion-functions section-page

The functions in ZWEI
for moving across characters, lines, words, etc. do not really perform
any sort of 2motion*.  What they really do is return a pointer to
a place which is a certain number of characters, lines or words away
from another, specified place.  
"Cursor motion" is done by calling 3zwei:move-bp* with
3(zwei:point)* as the buffer pointer to move.
For example, moving Point forward by three words is done by
.lisp
zwei:(move-bp (point) (forward-word (point) 3 t))
.end_lisp
3zwei:forward-word* returns a temporary buffer pointer to
the place three words away from 3(zwei:point)*; then Point is moved
to that position.

3Do not to setq Point!  You will ruin the editor window.*

.subsection Standard Motion Functions

There is a standard calling sequence used by many motion functions.
Consider this fictitious function:

.defun-no-index zwei:forward-syllable bp &optional (times 31*) fixup-p
"Moves" 2times* syllables from 2bp*.

This means that the function returns a buffer pointer to a spot
which is 2times* syllables after where 2bp* points, if 2times*
is positive, or -2times* syllables before where 2bp* points
if 2times* is negative.  If 2times* is zero, 2bp* itself
is returned.

If the beginning or end of the current interval is reached before one can go that
many syllables away from 2bp*, the value returned depends on
2fixup-p*.  If 2fixup-p* is non-3nil*, the value is the
beginning or end of the current interval.  If 2fixup-p* is 3nil*,
the value is 3nil*.
.end_defun

A 2fixup-p* value of 3nil* is useful if the caller wants to
know if the specified syntactic units cannot be found, strictly speaking.
A 2fixup-p* value of 3t* is useful for avoiding errors, in situations
which are less strict.

.defun zwei:forward-char bp &optional (times 31*) fixup-p
"Moves" 2times* characters from 2bp*.
.end_defun

.defun zwei:forward-its-char bp &optional (times 31*) fixup-p
"Moves" from 2bp* the equivalent of 2times* characters in a PDP-10 file
(such as, one on ITS).  This is just like 3zwei:forward-char* except that
it counts a 3Return* character (which is present implicitly, or course)
as two characters rather than one.
.end_defun

.defun zwei:forward-line bp &optional (times 31*) fixup-p
"Moves" 2times* lines from 2bp*.  The position returned
is always at the beginning of a line, unless it is at the end of
the buffer because the buffer was exhausted and 2fixup-p* was non-3nil*.

If 2times* is zero, you get the front of the line 2bp* is on.
For -1, you get the front of the previous line.  For 1, you get
the start of the following line.
.end_defun

.defun zwei:beg-line bp &optional (times 30*) fixup-p
"Moves" to the beginning of the line 2times* lines down from
2bp*.  The default for 2times* is 0; this value for 2times*
specifies the beginning of the line 2bp* is on.
.end_defun

.defun zwei:beg-line bp &optional (times 30*) fixup-p
"Moves" to the end of the line 2times* lines down from
2bp*.  The default for 2times* is 0; this value for 2times*
specifies the beginning of the line 2bp* is on.
.end_defun

.defun zwei:forward-word bp &optional (times 31*) fixup-p
"Moves" 2times* words from 2bp*.  This
moves forward or backward across the requisite number of words
and stops at the end of a word when going forward or at the beginning
of a word when going backward.
.end_defun

.defun zwei:forward-to-word bp &optional (times 31*) fixup-p
"Moves" 2times* word-separations from 2bp*.
This moves across the requisite number of words except that
it stops short of moving across the last one; thus it stops at
the beginning of a word when moving forward or at the end of one
when moving backward.  It does not move quite as far as
3zwei:forward-word* would move with the same arguments.
.end_defun

.defun zwei:forward-sentence bp &optional (times 31*) fixup-p
"Moves" 2times* sentences from 2bp*.  Moving forward goes to the
next sentence-ending; moving backward goes back to a sentence-beginning.

Every paragraph beginning or end is also a sentence beginning or end.
Also, a sentence break within a paragraph is the end of one sentence
and the beginning of another.  A sentence break is defined to occur
whenever there is a period, question mark or exclamation mark followed
by either a 3Return* or two spaces.  Close parentheses, brackets or quotes
may be present between the sentence punctuation mark and the 3Return*
or spaces.
.end_defun

.defun zwei:forward-paragraph bp &optional (times 31*) fixup-p
"Moves" 2times* paragraphs from 2bp*.

Moving forward stops at the end of a paragraph; moving backward stops at
the beginning.  If 2bp* is within a paragraph, either part of that one
counts as the first one moved over.  The beginning of a paragraph is always
at the beginning of a line; so is the end of a paragraph.
.end_defun

Text is divided into paragraphs based on two kinds of boundary elements:
paragraph separator lines and paragraph initiator lines.  The criteria
for these two types of lines depend on whether a fill prefix is in
effect.

A pararaph separator line is not part of any paragraph.  Any number of
these lines, in a row, can separate two paragraphs.  Blank lines and
diagram lines are always paragraph separators.  If there is a fill
prefix, these are the only ones.  Otherwise, page boundary lines are
paragraph separator lines, and text justifier command lines are
typically defined as separator lines.

A paragraph initiator line is the beginning of a paragraph, and is part of
that paragraph.  A line starting with a space or a tab is (by default)
a paragraph initiator line.  When there is a fill prefix, any line which
does not start with the fill prefix, or which starts with the fill prefix
followed by a space or tab, is a paragraph initiator line.

Modification: a single blank line before a paragraph is considered part
of the paragraph.  This is true even if the first nonblank line of the
paragraph is a paragraph initiator line.  If there are multiple blank lines
before the paragraph, only the last one is considered part of the paragraph;
the remainder are still separators.

The beginning of a paragraph is the beginning of the first line in the
paragraph.  The end of a paragraph is the beginning of the first line
after the paragraph (that is, no longer in the paragraph).  The end
of one paragraph may be the beginning of the next, but this is not so
if there is a non-blank paragraph separator line.

.c rename
.defun zwei:bp-at-paragraph-starter bp &optional fill-prefix-p
Returns 3t* if 2bp* is on a line that is a paragraph initiator.
If 2fill-prefix-p* is non-3nil*, the determination is done on
the basis of assuming that there is a fill prefix in effect.
2fill-prefix-p* defaults to be 3t* if there really is a fill
prefix in effect.  See (fill-prefix).
.end_defun

.c rename
.defun zwei:bp-at-paragraph-delimiter bp &optional fill-prefix-p
Returns 3t* if 2bp* is on a line which separates paragraphs (and is
not part of one).  The considerations for 2fill-prefix-p* are the same
as above.
.end_defun

.defun zwei:bp-at-paragraph-terminator bp &optional fill-prefix-p
Returns 3t* if 2bp* is on a line that ends any preceding paragraph:
either a paragraph separator or a paragraph initiator line.
The considerations for 2fill-prefix-p* are the same as above.
.end_defun

.defvar zwei:*paragraph-delimiter-list*
A list of characters and strings, the presence of any of which at the front of a line
makes that line a paragraph initiator or a paragraph separator.
.end_defvar

.defvar zwei:*text-justifier-escape-list*
When a line is recognized as being either a paragraph initiator or a paragraph separator
according to 3zwei:*paragraph-delimiter-list**, this variable determines which one it is.
If the line's first character is found in this list, the line is a separator;
otherwise, it is an initiator.
.end_defvar

.defun zwei:forward-sexp bp &optional (times 31*) fixup-p (level 30*) stop-bp (move-over-singlequotes-p 3t*) no-up-p
"Moves" 2times* Lisp expressions (sexps) from 2bp*.
Comments are entirely ignored except sometimes when 2bp* is within a comment.

2stop-bp*, if not 3nil*, is a buffer pointer to a place beyond which
this function should not move.  Another way of phrasing this is that
2stop-bp* is used in place of the actual beginning or end of the
current interval as a place to stop the scan.  2fixup-p* controls the
value returned in that case; it is either 3nil* or 2stop-bp*.

If 2move-over-singlequotes-p* is non-3nil*, as it is by default,
then motion continues past any singlequote-syntax characters
before or after the last sexp moved over.  For example, moving backward
one sexp from the end of 3" 'foo "* would move back over the 7"'"* as
well as the 3"foo"*.  If this argument is 3nil*, motion in that case
would stop between the 7"'"* and the 3"f"*.

2level* nonzero means move up that many levels of list structure.
A nonzero 2level* is used in implementing the 3C-M-U* command.
You can move up in levels regardless of whether you are moving forward or backward.

If 2no-up-p* is non-3nil*, it means you do not wish to accept a
motion that goes up and then down.  For example, moving forward over
3") (foo"* would not be considered an acceptable way of moving forward
over one sexp (3"foo"*).  If a situation like this arises when
2no-up-p* is non-3nil*, the value of 3zwei:forward-sexp* is
3nil* regardless of 2fixup-p*.  (2fixup-p* applies only to the
problem of running out of characters to scan.)
.end_defun

.defun zwei:forward-sexp-no-up bp &optional (times 31*) fixup-p
Like 3zwei:forward-sexp* with 2no-up-p* automatically non-3nil*.
Thus it moves over Lisp expressions but returns 3nil* if it attempts to move past
an unmatched close parenthesis while going forward or an unmatched
open parenthesis while going backward.
.end_defun

.defun zwei:forward-up-list-or-string bp &optional (times 31*) fixup-p (single-quotes-p 3t*)
"Moves" forward or backward from 2bp* out of one level of list structure
or out of a string if 2bp* is inside one.
2times* should be 1 to move forward or -1 to move back;
other values do not necessarily work.
If 2single-quotes-p* is non-3nil* (as it is by default) then motion
continues over any characters whose Lisp syntax is 7'*, past the parenthesis
or double quote which bounded the list or string.
.end_defun

.defun zwei:forward-atom bp &optional (times 31*) fixup-p
"Moves" 2times* Lisp atoms from 2bp*.  Parentheses are ignored.
.end_defun

.defun zwei:forward-list bp &optional (times 31*) fixup-p (level 30*) downp no-up-p
"Moves" 2times* lists from 2bp*.
This is like moving by sexps except that atoms at top level are ignored;
only sexps which are lists are counted.  Also, when moving backwards,
list motion does not move back over singlequote-like characters before
the final list.

2level* nonzero means move up that many levels of list structure.
A nonzero 2level* is used in implementing the 3C-M-U* command.
You can move up in levels regardless of whether you are moving forward or backward.

You can also move down in levels; this is used in implementing the
3C-M-D* command.  When you do this, you should also specify
a non-3nil* value for 3downp*.

If 2no-up-p* is non-3nil*, it means you do not wish to accept a
motion that goes up and then down.  For example, moving forward over
3") ((foo)"* would not be considered an acceptable way of moving
forward one list (3"(foo)"*).  If a situation like this arises when
2no-up-p* is non-3nil*, the value of 3zwei:forward-list* is
3nil* regardless of 2fixup-p*.  (2fixup-p* applies only to the
problem of reaching an extremity of the buffer.)
.end_defun

.defun zwei:forward-defun bp &optional (times 31*) fixup-p
"Moves" 2times* defuns from 2bp*.  A "defun" is any top-level
list in a file of Lisp code; however, the editor does not strictly
check that a list is top-level, since the only way to do this is to
count all parentheses between that list and the beginning of the buffer.
Instead, an open parentheses that appears at the beginning of a line
is assumed to be at top level, and the beginning of a defun.
Ends of defuns are found by balancing parentheses from beginnings
found by the above convention.

Moving forward a defun stops at the end of one; moving backward stops at
the beginning of one.  If 2bp* is within a defun, that partial defun
counts as the first one moved over.
.end_defun

.defun zwei:forward-page bp &optional (times 31*) fixup-p
"Moves" 2times* page boundaries from 2bp*.  If 2bp* is within a
page, moving by one goes to the beginning or end of that page.
If 2bp* is at a page boundary, then moving by one goes to a different
page boundary.

A page boundary is any line which begins with a page delimiter character.
.end_defun

.defvar zwei:*page-delimiter-list*
A string which specifies the set of page delimiters.
Every character found in the string is a page delimiter.
By default, the value is a string containing one character, 3Page*.
.end_defvar

.defun zwei:forward-interval bp &optional (times 31*) fixup-p
"Moves" 2times* extremities of the current interval from 2bp*.
Moving forward one extremity of the current interval means
returning the end of the interval.  Moving backward one extremity
means returning the beginning of the interval.  2bp* and 2fixup-p*
are ignored; they are accepted just so that the standard calling
sequence will work.  Only the sign of 2times* matters.
.end_defun

.defun zwei:forward-over-matching-delimiters bp &optional (times 31*) fixup-p (level 30*) open close
"Moves" over 2times* sets of matching delimiters from 2bp*.
Alteratively, if 2level* is nonzero, moves up that many levels
of delimiter structure.

The delimiters to use may be specified as the arguments 2open* and
2close*, or allowed to be deduced from the text.  In the former case,
2open* and 2close* should be the left and right delimiter
characters.  They may be the same character; in that case, nesting of
delimiter sets is no allowed.  In the latter case, the first opening
delimiter character encountered going forward (or the first closing
delimiter encountered going backward) is used, together with its
standard partner as described in the table
3zwei:*matching-delimiter-list**.
.end_defun

.defvar zwei:*matching-delimiter-list*
Alist of matching opening and closing delimiters.
Typical elements are 3(#/[ #/] forward-sexp)* and
3(#/| #/| forward-sexp)*; in the second case, the delimiter
matches itself and pairs cannot be nested.
.end_defvar

.subsection Object Bounding Functions

There is a series of functions which find the beginning and the end
of some sort of textual object, and return an interval which contains
the object.

.defun zwei:defun-interval bp &optional (times 31*) fixup-p (comments-p 3t*) top-blank-p
Returns an interval containing the DEFUN that surrounds or follows
2bp* (if 2times* is 1), or some other DEFUN (if 2times* is not 1).
See 3zwei:forward-defun* ((zwei:forward-defun-fun)) for a definition of DEFUNs.

2times*, compared with 1, determines how many DEFUNs forward or back to
move before picking one.  Thus, if 2times* is 2, the DEFUN following the one
containing or following 2bp* is used.  If 2times* is 0, the DEFUN preceding
2bp* or preceding the one containing 2bp* is used.

Normally any comment lines preceding the DEFUN are included in the interval returned,
and so are any blank lines among the comment lines.
If 2comments-p* is 3nil*, these are all excluded.

If 2top-blank-p* is non-3nil*,
 one blank line (if there is one) is included, before the first
comment line or the actual beginning of the DEFUN.
.end_defun

.subsection Scanning By Characters

It is frequently useful to write a loop that scans characters of text
sequentially forward or backward.  Many of the standard motion functions do this.
The macros 3zwei:charmap* and 3zwei:rcharmap* are provided to make this easy.

.defmac zwei:charmap (from-bp to-bp return-forms...) body...
Executes the 2body* once for each character between 2from-bp* and 2to-bp*;
then executes the 2return-forms* and returns the value(s) of the last of them.

2body* can access the character pointed at, or get a buffer pointer to the
current scanning point, using the macros 3zwei:charmap-char-after*,
3zwei:charmap-bp* and others.  These macros are necessary because the
information is actually kept by 3zwei:charmap* in an internal form
optimized for speed of scanning.

Using 3zwei:charmap* generates code that works somewhat like
.lisp
(let ((bp1 2from-bp*)
      (bp2 2to-bp*)
  (do-forever
    (when (bp-= bp1 bp2)
      (return (progn 2return-forms*...)))
    (setq bp1 (zwei:forward-char bp1 1))
    (progn 2body*...)))
.end_lisp
but the generated code works differently and does not have variables
like 3bp1* or 3bp2* under any name.
.end_defmac

.defmac zwei:charmap-per-line from-bp to-bp return-forms...) (line-forms...) body...
Like 3zwei:charmap* but in addition executes the 2line-forms* once for
each line the scan moves through.  They are executed once at the start of the scan,
and executed again each time the scan begins a new line (just after 2body*
is executed for the implicit 3Return* character before that line).
The 2line-forms* will not be executed if no more characters remain
to be scanned (that is, if the scan ends at the beginning of the next line).
.end_defmac

.defmac zwei:charmap-char
Within the body of a 3zwei:charmap*, this macro can be used to access
the character that the scan has reached.
.end_defmac

.defmac zwei:charmap-ch-char
The same as 3(ldb %%ch-char (zwei:charmap-char))*.
.end_defmac

.defmac zwei:charmap-set-char new-char
Within the body of a 3zwei:charmap*, this macro can be used to alter
the character that the scan has reached.  The value 2new-char* is stored.
.end_defmac

.defmac zwei:charmap-bp-before
Within the body of a 3zwei:charmap*, this macro can be used to access
a temporary buffer pointer that points just before the character that
the scan has reached.

The buffer pointer is consed afresh by 3zwei:charmap-bp-before*, since
3zwei:charmap* does not actually use a buffer pointer for the scanning.
.end_defmac

.defmac zwei:charmap-bp-after
Similar, but the buffer pointer points just after the character that
the scan has reached.
.end_defmac

.defmac zwei:charmap-line
Within the body of a 3zwei:charmap*, this macro can be used to access
the line being scanned.  An implicit 3Return* character is considered
part of the line before it.
.end_defmac

.defmac zwei:charmap-increment
Advances the scan forward one character.  After this is done, 3zwei:charmap-char*
and 3zwei:charmap-bp-before* and so on will deal with the new character thus reached.

The increment at the end of the 3zwei:charmap* loop will happen as usual,
so the character reached by an explicit 3zwei:charmap-increment* will
not be considered by a pass through the loop.
.end_defmac

.defmac zwei:charmap-return body...
Executes 2body* and returns from the containing 3zwei:charmap*.
The values of the last form in 2body* become the values of the 3zwei:charmap*.
.end_defmac

.defmap zwei:rcharmap (from-bp to-bp return-forms...) body
Like 3zwei:charmap* but scans backwards.  Scan still starts at 2from-bp*
and ends at 2to-bp*, so 2to-bp* should point to an earlier place in the text.
.end_defmac

.defmac zwei:rcharmap-per-line (from-bp to-bp return-forms...) (line-forms...) body
Like 3zwei:charmap-per-line* but scans backwards.
The 2line-forms* are executed at the beginning of the scan,
and then executed again just before scanning each implicit 3Return* character;
but if 2from-bp* points to the beginning of a line, the 2line-forms*
are executed only once, not twice in a row, at the start.
.end_defmac

.defmac zwei:rcharmap-char
.defmac1 zwei:rcharmap-ch-char
.defmac1 zwei:rcharmap-set-char new-char
Within the body of a 3zwei:rcharmap*, access or set the character that the scan has reached.
.end_defmac

.defmac zwei:rcharmap-char-before
.defmac1 zwei:rcharmap-ch-char-before
Within the body of a 3zwei:rcharmap*, access the character 2before*
(in the buffer) the character that the scan has reached.  This is the character
that would be scanned on the next iteration.
.end_defmac

.defmac zwei:rcharmap-bp-before
.defmac1 zwei:rcharmap-bp-after
Within the body of a 3zwei:rcharmap*, return buffer pointers to before
or after the character that the scan has reached.
.end_defmac

.defmac zwei:rcharmap-line
Within the body of a 3zwei:rcharmap*, returns the line being scanned.
.end_defmac

.defmac zwei:rcharmap-decrement
Advances the scan backward one character.  After this is done, 3zwei:rcharmap-char*
and 3zwei:rcharmap-bp-before* and so on will deal with the new character thus reached.
.end_defmac

.defmac zwei:rcharmap-return body...
Executes 2body* and returns from the containing 3zwei:rcharmap*.
The values of the last form in 2body* become the values of the 3zwei:rcharmap*.
.end_defmac

.subsection Other Motion Functions

.defun zwei:backward-over-comment-lines bp &optional (top-blank-p 3t*) (up-p 3t*)
"Moves" back from 2bp* across any comment lines (including any intervening
blank lines), plus one more blank line before the first comment line
unless 2top-blank-p* is 3nil*.

In addition, unless 2up-p* is 3nil*, any list structure that
begins before 2bp* but is not closed until after 2bp* is moved over
(as well as comments preceding it).

In this example, if 2bp* points to just before the 3setq*,
the value returned will point to the blank line just after 3(test 1)*
if 2up-p* is 3t*, or to the beginning of the 3;;Do it* line
if 2up-p* is 3nil*.

.lisp
(test 1)

;; This is a hack.

;; It is very hairy.
(eval-when (compile)
;;Do it
 (setq foo 5))
.end_lisp
.end_defun

.defun zwei:forward-over character-list bp &optional limit-bp
"Moves" forward from 2bp* across all characters which match elements of
2character-list*, but not going beyond 2limit-bp*.
2limit-bp* defaults to the end of the current interval.
.end_defun

.defun zwei:backward-over character-list bp &optional limit-bp
Similar, but "Moves" backward from 2bp*.
.end_defun

.defvar zwei:*blanks*
A list of character codes for the characters that count as blanks:
3Space*, 3Tab* and 3Backspace*.
This constant is useful as the first argument to 3zwei:forward-over*
and similar functions.
.end_defvar

.defvar zwei:*whitespace-chars*
A list of character codes for the characters that count as whitespace:
3Return*, 3Space*, 3Tab* and 3Backspace*.
.end_defvar

.defun zwei:ibp bp &optional fixup-p
"Increments" the buffer pointer 2bp* by moving it one character
forward; then returns 2bp* (whose elements are now different).  If
2bp* was already at the end of the current interval, the action
depends on 2fixup-p*: if it is 2nil*, 2nil* is returned;
otherwise, 2bp* is returned unchanged.
.end_defun

.defun zwei:dpb bp
Like 3zwei:ibp* but moves 2bp* back one character rather than forward.
.end_defun

.section Insertion

The insertion primitives do not require that 2bp* point anywhere inside
the current interval.  For example, other buffers can be inserted into
without making them current.

.defun zwei:insert bp string &optional (start 30*) end
Inserts 2string* (or the portion of 2string* specified by indices 2start*
and 2end*) into the text that 2bp* points at.
Normally, 2bp* continues to point at the same index within its line,
which implies that it points at the beginning of the inserted text.
But if 2bp* is relocatable of type 3:moves*, it is relocated
automatically to point at the end of the inserted text.  (Other such relocatable
buffer pointers pointing at the same spot are relocated the same way.)

The value returned is a temporary buffer pointer pointing to the end of
the inserted text.

2string* can be a character instead of a string.
.end_defun

.defun zwei:insert-moving bp string
Inserts 2string* into the text that 2bp* points to
and modifies 2bp* to point at the end of the inserted text.

The value is a temporary buffer pointer distinct from 2bp* but
pointing to the same place.

2string* can be a character instead of a string.

It is often useful in simple commands to supply 3(point)* as the
2bp* argument.
.end_defun

.defun zwei:insert-interval at-bp interval-or-from-bp &optional to-bp in-order-p
Inserts a copy of the text of the interval specified by the last three
arguments at the place 2at-bp* points to.  Either
2interval-or-from-bp* should be an interval object, or it and
2to-bp* should be buffer pointers delimiting an interval.

Normally 2at-bp* continues to point at the same index, which implies
that it will point at the beginning of the inserted text.  But if it is
a relocatable buffer pointer of type 3:moves*, it is relocated
automatically to point at the end of the inserted text.

The value returned is a temporary buffer pointer pointing to the end of
the inserted text.
.end_defun

.defun zwei:insert-interval-moving at-bp interval-or-from-bp &optional to-bp in-order-p
Like 3zwei:insert-interval* except that it always modifies 2at-bp*
to point to the end of the inserted text.  The returned value also points there,
but it is never 3eq* to 2at-bp*.
.end_defun

.defun zwei:insert-thing bp thing
Performs 3zwei:insert* if 2thing* is a string or character;
performs 3zwei:insert-interval* if 2thing* is an interval.
.end_defun

.defun zwei:insert-chars bp char n
Inserts 2n* copies of the character 2char* at 2bp*.
If 2n* is zero or negative, nothing is inserted.
Like 3zwei:insert* except for how you specify what is inserted.
.end_defun

.section Deletion

Deletion primitives do not save anything on the kill ring.
That is a separate operation.  However, they all do make records
for the 3Undo* command.

.defun zwei:delete-interval interval-or-from-bp &optional to-bp in-order-p
The three arguments specify an interval; that interval is deleted (from whatever
text it is a part of).

If you pass an actual interval as an argument, the text of that interval is deleted.
Nothing happens to that interval itself.  For example, if you pass a Zmacs buffer
to this function, all the text of the buffer will be deleted, but the buffer itself
will not be affected except for its text.

If you pass two buffer pointers, you had better make sure that they point to
the same piece of text.
.end_defun

.defun zwei:delete-over character-list bp
Deletes all the characters following 2bp* that match elements of 2character-list*.
3zwei:*blanks** and 3zwei:*whitespace-characters** (see (zwei:*blanks*-var))
are good values to use for 2character-list*.
.end_defun

.defun zwei:delete-backward-over character-list bp
Deletes all the characters preceding 2bp* that match elements of 2character-list*.
.end_defun

.defun zwei:delete-around character-list bp
Deletes all the characters preceding or following 2bp* that match
elements of 2character-list*.
.end_defun

.chapter Random things

.defun zwei:exchange-subr function numeric-arg
Performs an "exchange" of syntactic units of text near point.
This subroutine is used by the 3C-T*, 3M-T*, and 3C-M-T* commands.
2function* should be a standard motion function which moves over
the type of unit to be exchanged (thus, the 3M-T* command supplies
3zwei:forward-word* as the 2function*).  2numeric-arg* is the argument
which the user supplied.
.end_defun

.defun zwei:reverse-subr function numeric-arg
Performs a "reverse" of syntactic units of text near point.
2function* should be a standard motion function which moves over the
type of unit to be reversed (thus, 3zwei:forward-word* to reverse
words).  2numeric-arg* is the argument which the user supplied.  That
many syntactic units, following point (or preceding point if the
argument is negative), are reversed in order.
.end_defun

.defun zwei:kill-command-internal function numeric-arg
Performs a "kill" of syntactic units of text near point.
2function* should be a standard motion function which moves over the
type of unit to be killed (thus, 3zwei:forward-word* to kill
words).  2numeric-arg* is the argument which the user supplied.  That
many syntactic units, following point (or preceding point if the
argument is negative), are killed.
.end_defun

.defun zwei:assure-string object
Coerces 2object* into a string, or a fat string if necessary (such as,
for an argument which is a character or number that will not fit in an
ordinary string).
.end_defun

.defun zwei:interval-real-tick bp1 &optional bp2 in-order-p
Returns the latest tick at which any line in the specified interval was modified.
.end_defun

.chapter Comments

.defun zwei:indent-for-comment bp &optional (times 31*) create-p move-to-next-p beg-line-not-special
Indents the comment on the line 2bp* points to.
If there is no comment, one is created if 2create-p* is non-3nil*.
Returns a buffer pointer that is a copy of the original one, but relocated for the insertion
so that it points to the same text now as 2bp* pointed to before.

2move-to-next-p* if non-3nil* says return instead a pointer to
the beginning of the following line.  In this case, more than one line
can be processed if 2times* is not 1.  Then the value will point to
the line following the ones processed.

The rules for indentation of comments are:
.table 1
.item starting at the beginning of the line
A comment starting at the beginning of the line
is exempt from relocation if 2beg-line-not-special* is nil.
.item one semicolon
Relocate to start at the comment column.
.item two semicolons
Relocate to start at the same place a line of code would start.
.item three semicolons
Do not ever relocate.
.end_table
.end_defun

.defvar zwei:*comment-column*
The 2comment column*: the horizontal position in pixels at which
single-semicolon comments should start.
.end_defvar

.defvar zwei:*comment-round-function*
A function used to compute the column to relocate a comment to
when it is impossible to put it at the comment column because
previous text on the line extends past there.
This function is called with a single argument, which is the first
free horizontal position at which the comment might start,
and the value it returns is the place to actually put the comment.
Both are measured in pixels.
.end_defvar

.defvar zwei:*comment-start*
A string or a symbol, used to recognize existing comments.
If it is a string, it is searched for.  If it is a symbol, it is called
and should be a function to search in an appropriate fashion.
The value can also be 3nil*, which specifies no way to recognize
a comment.  Then, for some purposes, comments will still be recognized
by searching for the 3zwei:*comment-begin** string, but for other
purposes, there are considered not to be any comments.
In Lisp mode, the value is 3zwei:lisp-find-comment-start-and-end*.
.end_defvar

.defvar zwei:*comment-begin*
A string, inserted in order to create a new comment.
In Lisp mode, this string is 3";"*.
.end_defvar

.defvar zwei:*comment-end*
A string, inserted at the end of an automatically created comment.
3zwei:indent-for-comment* does not insert the comment terminator string,
but continuation of comments and certain other operations do so.
.end_defvar

.defun zwei:round-for-comment start-pos
This function is the default value of 3zwei:*comment-round-function**.
It rounds up to the next position which is a multiple of 8 spaces past
the comment column.
.end_defun

.defun zwei:find-comment-start line &optional begin-also
Returns a description of where on 2line* a comment starts, if anywhere.
The value of 3zwei:*comment-start** determines how a comment is recognized.
If it is a string, that precise string is searched for.  If it is a symbol,
it is called as a function, and its values are returned.
If it is 3nil*, then this function also returns 3nil* unless
2begin-also* is non-3nil*, in which case the value of 3zwei:*comment-begin**
is used to recognize a comment.

2begin-also* should be non-3nil* whenever the user has specifically
asked to operate on a comment on a particular line: "I say there is a
comment there, so do your best to find it."  A value of 3nil* for
3zwei:*comment-start** is used in text mode, so that various commands
whose main purpose is unrelated to comments but which do notice comments
and treat them specially will not notice any.

Three values are returned:
.table 2
.item start-start-index
The index in 2line* of the start of the comment-starting string, or 3nil*
if there is no comment.
.item start-end-index
The index in 2line* of the end of the comment-starting string, or 3nil*
if there is no comment.  Note that more than one comment-starting string
may be valid in a given language; for example, in Lisp, any number of semicolons
followed by any number of spaces make up the comment-starting string.
The 2start-end-index* will be that of the first non-space following the
semicolons.
.item in-string
Non-3nil* if the entire line is within a string.  In this case,
most callers should decide to treat the line as not containing a comment
regardless of the first two values.
.end_table
.end-defun

.defun zwei:kill-comment line
Kill any comment on 2line*.
.end_defun

.defun zwei:report-column-setting name npixels
Print a message on 3query-io* reporting that a column variable
(such as the comment column) has been set.
2npixels* should be the value it has been set to,
either a horizontal position in pixels or 3nil*.
2name* is a string used only for printing the message.
.end_defun

.chapter Compilation and Evaluation

.defun compile-defun-internal compile-p mode-name echo-name &optional use-typeout defvar-hack (compiler-processing-mode 3'compiler:macro-compile*)
Compiles or evaluates a part of the current buffer.
If there is a region, it is used; otherwise the current or following defun is used.
The other arguments are passed along to 3zwei:compile-print-interval*,
except that 2defvar-hack* is always passed as 3t* if there is no region.
The 2defvar-hack* argument to this function is used only when there is a region.
.end_defun

.defun zwei:compile-buffer compile-p mode-name echo-name &optional (compiler-processing-mode 3'compiler:macro-compile*)
Compiles or evaluates the entire current buffer.
The arguments are passed along to 3zwei:compile-print-interval*.
.end_defun

.defun zwei:compile-buffer-changed-functions buffer ask-p &optional (compile-p 3t*) (names 3'("Compile" "Compiling" "compiled.")*)
Recompiles (or reevaluates) all sections in 2buffer* that have changed since the previous
compilation or evaluation.

2compile-p* is 3t* to compile, 3nil* to eval, or else a function
to be called to evaluate and print each form.

2ask-p* if non-3nil* means query the user for each section to be
processed.

2names* contains three strings used for printing messages for the
user.  They should be analogous syntactically and in capitalization to
the three elements of the default value.
.end_defun

.defun compile-print-interval bp1 bp2 in-order-p compile-p region-name mode-name echo-name &optional use-typeout defvar-hack compiler-processing-mode entire-file-flag already-resectionized-flag
Compiles or evaluates the interval specified in the standard manner
by 2bp1*, 2bp2* and 2in-order-p*.

2compile-p* is 3t* to compile, 3nil* to eval, or else a function to be used to evaluate and print each form.

If 2defvar-hack* is non-3nil*, any 3defvar*s that are processed will always
reinitialize the variable, even if it is already bound.  Normally a 3defvar* sets
the variable only if it is unbound.

2use-typeout* is a flag that controls what is done about printing information about
the progress of processing and results of evaluation if any.
The possible values are:
.table 3
.item t
Progress reports and evaluation results are printed on 3standard-output*.
.item nil
Progress reports and evaluation results on 3query-io*.
.item :prompt
Evaluation results on 3query-io*, progress reports on the mode line.
.end_table

2compiler-processing-mode* is relevant only if 2compile-p* is 3t*.
It should be 3compiler:macro-compile* or 3compiler:micro-compile*.
The latter value causes compilation into microcode.

2mode-name* should be a string containing a capitalized present
participle, such as 3"Compiling"*.  2echo-name* should be a string
containing a lowecase past participle and period (3"compiled."*).
These are used for printing messages.  2region-name* is a string to
print as the name for what is being compiled (such as 3"region"* or
3"buffer"*) or 3nil* to mention each object's name.

Normally the buffer is resectioized so that the proper
sections can be marked as compiled.  If 2already-resectionized-flag* is non-3nil*,
resectionization is not done.  This is used to avoid duplicate work in
3Compile Changed Sections*.

2entire-file-flag* should be non-3nil* if the whole buffer is being processed.
This is so that any old warnings for this file can be discarded.
.end_defun

.defun zwei:update-interval-compile-tick bp1 &optional bp2 in-order-p
Updates the tick-of-last-compilation for all sections contained
entirely or partially in the specified interval.
.end_defun

.chapter Other Lisp Parsing Functions
.setq lisp-parsing-functions section-page

.defun zwei:lisp-bp-syntactic-context bp &optional (start-bp 3(forward-defun bp -1 t)*)
Describes the syntactic context of the spot where 2bp* points,
returning three values:
.table 2
.item string-flag
The first value is non-3nil* if that spot is in a string.
.item slash-flag
The second value is non-3nil* if that spot is slashified (preceded by a non-quoted slash).
.item comment-flag
The third value is non-3nil* if that spot is in a comment.
.end_table

The parsing to compute this information starts at 2start-bp*,
which if omitted defaults to be the start of the DEFUN containing 2bp*.

This function is what 3Electric Shift Lock* mode uses to tell whether
a character should be converted to upper case.
.end_defun

.c Mention the syntax table.

.defun zwei:lisp-parse-from-defun line &optional defun-beg
Returns an indication of whether 2line* begins inside a string.
This is done by parsing down from the beginning of the containing DEFUN.
If 2defun-beg* is non-3nil*, it is used as the parse starting point.
.end_defun

.defun zwei:lisp-find-comment-start line &optional beg-index end-index
Returns the index within 2line* at which the comment starts, or
3nil* if 2line* does not contain a comment.  This depends not only
on the contents of 2line* but on the preceding lines linked with 2line*.

2beg-index* and 2end-index* can be specified to restrict the part of
2line* to be scanned.  They are indices within 2line*.  They default
to be the entire contents of 2line*.

A second value is also returned.  It is non-3nil* if 2line* ends
inside a string.  This information is returned since it is a byproduct of
distinguishing semicolons inside strings from those which start comments.
.end_defun

.defun zwei:lisp-find-comment-start-and-end line
Returns the indices of the beginning and end of the starting delimiter
of the comment on 2line*, or 3nil* if there is no comment on 2line*.

If there is a comment, the first two values are the indices at which
the starting delimiter begins and ends.  The starting delimiter is
made up of the initial semicolon plus any other semicolons that follow it,
plus any spaces that follow them.  Thus, the end index of the starting
delimiter is where the actual text of the comment begins.

There is also a third value returned.  It is non-3nil* if 2line* ends
inside a string.
.end_defun

.defun zwei:backward-leading-single-quotes bp first-bp
"Moves" back from 2bp* over any characters whose Lisp syntax is 7'*,
but in any case does not move beyond 2first-bp*.
It also never moves past a slashified character;
thus, starting from just before the "f" in
.lisp
/''foo
.end_lisp
this function will move back only one character.
In
.lisp
//''foo
.end_lisp
it would move back two characters since neither 7'* is quoted.
.end_defun

.defun zwei:forward-up-string bp reverse-flag &optional (single-quotes-p 3t*)
Returns a temporary buffer pointer to the end or beginning of the string
which 2bp* is inside.  Motion is backward if 2reverse-flag* is non-3nil*.

If 2single-quotes-p* is non-3nil* (as it is by default) then motion
continues over any characters whose Lisp syntax is 7'*, past the parenthesis
or double quote which bounded the list or string.
.end_defun

.chapter Registers
.setq registers section-page
.cindex registers

Registers are named variables in which the user can store text or buffer
pointers during editing.

A user specifies a register with a single character.  The register
is represented within ZWEI by a symbol interned in the utility package
(see (utility-package)); its pname is the character (converted to upper case).
The text or pointer associated with the register are stored on properties
of the symbol:
.table 3
.item zwei:text
The value of this property is the text associated with the register, or 3nil*
if there is none.  The text is represented as an interval.
.item zwei:point
The value of this property is the position associated with the register, or 3nil*
if there is none.  The position is represented as a relocating buffer pointer.
.end_table

.defvar *q-reg-list*
A list of all register symbols used so far.
.end_defvar

.defun zwei:get-register-name prompt &optional purpose
Reads a register name from the keyboard and returns the symbol which
represents the specified register internally.  2prompt* is a string
to print out to prompt with.  It should not end with a space.

2purpose* is an additional string explaining what the register is going
to be used for.  It is printed, following the words "a ZWEI register", if
the user types 3Help*.  It should start with a space.
.end_defun

.defun zwei:view-register register-symbol
Prints on 3standard-output* a description of the text and/or position
stored in the specified register. 
.end_defun

.chapter Editor Variables

ZWEI uses many variables as parameters that the user can set to control
editing.  While these can be set with 3setq*, there are also ZWEI
commands to make it easy for the user to examine and set them.

.chapter The Mini-buffer
.setq mini-buffer section-page
.cindex mini-buffer

The mini-buffer is a general mechanism whereby editing commands can ask
for textual input from the user.  A small editor window is popped up in the
echo area and the user then types in the input, editing it as desired.
The input is usually terminated with 3Return* or 3End*; then the
mini-buffer window disappears and the mini-buffer functions return the
specified input string to the editing command that called them.

.section Input Without Completion

.defun zwei:typein-line-readline format-string &rest format-args
Reads input using the mini-buffer and returns the result as a string.
3Return* terminates input, so this function is used where multiple-line
input is not normally expected.

2format-string* and 2format-args* are passed to 3format* to create
a prompt string which is displayed in the mode line while the mini-buffer
is being used.
.end_defun

.defun zwei:typein-line-multi-line-readline format-string &optional format-args
Like 3zwei:typein-line-readline* except that only 3End* terminates the
input.  3Return* is self-inserting.  This is used where multi-line input
is considered likely or useful.

The prompt string should tell the user to use 3End* to end.
.end_defun

.defun zwei:typein-line-read format-string &optional format-args
.defun1 zwei:typein-line-multi-line-read format-string &optional format-args
Like 3zwei:typein-line-read* and 3zwei:typein-line-multi-line-read*
except that the specified input is converted into a Lisp object with
3read-from-string* and that Lisp object is returned.
.end_defun

.defun zwei:edit-in-mini-buffer &optional (comtab 3zwei:*mini-buffer-comtab**) initial-contents initial-char-pos mode-line-list
This is the actual primitive which invokes the mini-buffer.  It is used
by the preceding functions.

You get to specify the comtab to use for editing while in the
mini-buffer, and therefore can provide any commands you like for the user
to use while there.  The default comtab is the one that
3zwei:typein-line-readline* uses.

You can make the mini-buffer start out with text already in it by specifying
a string as the 2initial-contents* argument.  2initial-char-pos* specifies
the position at which the pointer start out; often one wants to pass
the length of 2initial-contents* for this argument.

2mode-line-list* is used to drive the display of the mode line while
inside the mini-buffer.  3zwei:typein-line-readline* creates a mode line list
from the string returned by 3format*.  See (mode-line), for more information.
.end_defun

.defvar zwei:*mini-buffer-window*
The editor window which serves as the mini-buffer.
This is a closure variable of some editor closures.
.end_defvar

.defvar zwei:*mini-buffer-comtab*
The usual comtab used in reading input in the mini-buffer.
It defines 3Return* to exit, and 3Abort* as a command to
abort from the caller of the mini-buffer.  It also defines
3End* and 3C-Return* to exit.
.end_defvar

.defvar zwei:*mini-buffer-multi-line-comtab*
Another comtab useful with the mini-buffer.  It does not redefine
3Return*, but does define 3End* and 3C-Return* to exit.
.end_defvar

.section Completion
.cindex completion
.cindex aarray
.setq completion section-page
.setq aarray section-page

Completion is made available in the mini-buffer by specifying the use of
a comtab in which certain characters are defined as completion commands.

.defun zwei:completing-read-from-mini-buffer prompt alist &optional impossible-is-ok-p initial-complete help-message documenter
Reads input in the mini-buffer with completion.
2alist* specifies the possible input strings and what they mean.
The car of each element of 2alist* is a possible completion string.
The rest of the element is not looked at by this function.

The value returned by 3zwei:completing-read-from-mini-buffer*
is an element of 2alist*, if the input corresponds to one of them.
If the input does not match an element of 2alist*, it is returned as a string.
The user is always allowed to specify no input, so all callers should be prepared
to handle the null string as a value (usually by substituting some default).
Other strings are possible values only when 2impossible-is-ok-p* has been
specified non-3nil*.

2alist* can also be an 2aarray*: an 3art-q-list* array whose contents are such
an alist.  In principle one can think of the array as being equivalent
to a list of the same elements; however, the array is kept sorted
and this makes completion among a large number of possibilities much faster
than with an ordinary alist.  The aarray must have at least two elements in
its leader; element 0 is the fill pointer, and element 1 is a flag which should
be set to 3nil* any time you change the contents of the array and do not sort it.
If 3zwei:completing-read-from-mini-buffer* sees that the flag is 3nil*,
it sorts the aarray and sets the flag to 3t*.

2prompt* is a string which is displayed in the mode line
while in the mini-buffer.

2impossible-is-ok-p* should be non-3nil* if it is legitimate
for the user to specify a string which is not one of the possibilities
in 2alist*.
.table 3
.item nil
The user cannot exit the mini-buffer (except by aborting) if the input text
does not match one of the elements of 2alist*.
.item t
The user can exit the mini-buffer regardless of what the input text is.
.item :maybe
The user may is asked for confirmation if the input text does not match one of
the elements of 2alist*.

He can exit with 3Return* or with 3C-Return*.  If he exits with
3C-Return*, no confirmation is needed; the input is accepted regardless.
3Return* exits if the input matches; otherwise, it just beeps, but the
user can type a second 3Return* to confirm the first and exit anyway.
.end_table

2initial-complete*, if non-3nil*, says that completion from the elements
of 2alist* should be done as soon as the mini-buffer is entered.
If 2initial-complete* is a string, it is inserted into the mini-buffer
and then completion is done.  2initial-complete* can also be 3t*,
in which case completion is done starting from the empty string.
(This may actually complete a few characters, if all the possibilities
in 2alist* start the same way.)

2help-message* is a string to be printed if the user types 3Help*.
This is in addition to the documentation of the mini-buffer and completion.
If it is 3nil*, only the mini-buffer and completion documentation are printed.

2documenter* is a function which, given an element of 2alist* as argument,
prints on 3standard-output* a description of what it would mean to
choose that possibility for this piece of input.  If 3Help* is typed and
the input completes unambiguously, this function (if specified) is used
to find additional information to print.
.end_defun

.c Get rid if the use of :zwei-window in this function.

.defun zwei:completing-read window alist &optional prompt impossible-is-ok-p initial-complete help-message documenter
Like the preceding function but does the editing of input using the specified
editor window 2window*.  2prompt* is displayed in the window's label
using the 3:set-label* operation.  2window* is expected to know
which comtab to use, so none is specified in this function.

This function returns whatever 3:edit* operation on 2window* returns.
The normal commands for exiting from mini-buffers all arrange for the
3:edit* operation to return the contents of the window.
.end_defun

.defvar zwei:*completing-reader-comtab*
The comtab used in the mini-buffer for 3zwei:completing-read-from-mini-buffer*.
.end_defvar

.defun zwei:complete-string string alist delims &optional dont-need-list char-pos trunc ignore-trailing-space
This function performs the matching and completion operation itself without
any I/O.  It can be called from outside the editor.

2string* is completed with reference to the alist or aarray 2alist*.
Case is not significant.
If 2alist* is an aarray, it is assumed to be sorted already.

2delims* should be a list of characters that count as word-delimiters
for the sake of completion; each word in 2string* is matched against one
word of a completion possibility from 2alist*.

If 2dont-need-list* is non-3nil*, it means that the caller only wants
to know whether there is any completion for 2string* and whether it is unique;
he does not need to know all the possible completions if there are several.
Completion can be done faster in this case.

If 2trunc* is non-3nil*, it means that completion should not add more
than one word (as delimited by the 2delims*) at the end, even if more
than a single word is determined uniquely by the contents of 2string*.

2ignore-trailing-space*, if non-3nil* means that a single trailing space
in 2string* can be ignored if that causes 2string* to match exactly
with an element of 2alist*.

2charpos* is used by editor commands in order to relocate point.
To use it, specify the index of some character in 2string*.
A value is returned which is the position of the corresponding
character in the completed string.

The values returned are:
.table 1
.item the completed string
2string* plus any additional characters that are uniquely determined
by 2string* (that is, present in all the possibilities in 2alist*
which match 2string*).

.item the matching list
a list of elements of 2alist* which match 2string*.
If this is 3nil*, there was no match.  If this is of length one,
there was a single match, and it contains the 2alist* element matched.
If it is of length greater than one, the match was not unique, and
the value contains all the 2alist* elements that match.

If 2dont-need-list* is non-3nil*, then the elements of the value are not meaningful
if there are more than one of them.  The mere fact that there are more than one
indicates that there was not a unique match, and that is all the caller can tell.
But most callers don't care to know any more in this case.

.item completion flag
a flag that is non-3nil* if any completion at all was done;
that is, if 2string* determined any additional characters.
The value is 3zwei:nospace* if 2string* already contains a
proper terminating delimiter at the end of it.

.item updated 2char-pos*
the character position, in the first value, of the character which
corrrsponds to the one at position 2char-pos* in 2string*.

.item first ambiguity index
the index (in the first value) of the earliest point at which the various possible
completions disagree.  If there is a unique completion, this will equal
the length of the first value.
.end_table
.end_defun

.defun zwei:sort-completion-aarray aarray
Sorts 2aarray* if it is not sorted already.
.end_defun

.defun zwei:merge-completion-aarray aarray additional-aarray
Merges new elements from 2additional-aarray* into 2aarray*.
If 2aarray* was sorted already, it remains sorted, and this
is faster than adding new elements at the end and sorting it.
2additional-aarray* is not changed.
.end_defun

.defun zwei:string-in-aarray-p string aarray
Returns 3t* if there is an element in 2aarray* whose car is
a string which matches 2string* (ignoring case).
2aarray* is assumed to be sorted.
.end_defun
