@setfilename ../info/buttons
@node Buttons, Events, Screens, top
@chapter Buttons

@menu
* Button Basics::		Button Basics
* Button Primitives::		Button Primitives
* Deleting Buttons::		Deleting Buttons
* Style Primitives::		Stype Primitives
* Button Plotting::		Button Plotting
* Attribute Allocation::	Attribute Allocation
* Read-only Buttons::		Read-only Buttons
@end menu

@node Button Basics, Button Primitives, Buttons, Buttons
@section Button Basics

@cindex buttons
@cindex button object
Epoch supports the notion of @dfn{buttons}, which are regions that are
displayed in a different @dfn{styles}. Two new data types are used for this: 
@code{button} and @code{style}.
@table @code
@item button
Each button has the following characteristics:
@table @var
@item start
The start of the button. A marker.
@item end
The end of the button. A marker. The button covers all characters
between @var{start} and @var{end}.
@item attribute
An index into a table of @code{styles}. Currently a number from 0..255.
Value 0 is special, and always indicates the normal screen display
style.
@item read-only
If set to non-nil, the text of the button cannot be directly edited. 
Attempts to insert or delete any character in the button will generate 
an error. (@xref{Read-only Buttons})
@item data
Not used internally. This field can be any Elisp object, and is provided
for the programmer to use to attach data to a button for later
retrieval.
@end table
@c ---
@item style
A style is an object that describes how to display characters. It has the following fields:
@table @var
@item foreground
The text foreground color.
@item background
The text background color.
@item cursor-foreground
The character foreground color when the text cursor is on the character.
@item cursor-background
The character background color when the text cursor is on the character.
@item stipple
The stipple pattern to use for the text.
@item cursor-stipple
The stipple to use when the cursor is on the text.
@item background-stipple
The stipple to use for the background. Bits that are set in the stipple
are displayed in the screen background color. Cleared bits are displayed
in the style background color.
@item underline
The color to use for underlining. If not set, no underlining is done.
@end table
@end table

@cindex hypertext
Buttons were intended as a way of providing ``hotbutton'' capabilities in
hypertext-like applications using Epoch as a front-end.  In these cases
the data field will hold information for the hotbutton.  Buttons can also
be used for many other applications, of course.

Each button is attached to a buffer.  All buffer arguments in the Epoch
primitives default to the current buffer.  Arguments of type button must
button objects.

Functions exist to access and change a buttons start/end
position or even the button's buffer, while maintaining the correct
position in the button list.  @b{NOTE:} Elisp code that alters buttons
by changing the vectors directly will no longer work correctly.  See
the file @file{fix-3.2.el} for a function which will convert such code.

@node Button Primitives, Deleting Buttons, Button Basics, Buttons
@section Button Primitives

@defun epoch::make-button
@cindex button creation
Used to create a new button.  Returns a button pointing nowhere, in no
buffer.
@end defun

@defun epoch::buttonp object
Returns @code{t} if object is a button, otherwise @code{nil}
@end defun

@defun epoch::button-buffer button
Returns the buffer a button is currently in, or @code{nil}.
@end defun

@defun epoch::button-start button
Returns the button's @var{starting} position as an integer.
@end defun

@defun epoch::button-end button
Returns the button's @var{end} position as an integer
@end defun

@defun epoch::move-button &optional button start end buffer
Moves the specified button to a new position indicated by @var{start}
and @var{end} in @var{buffer}.  If either paramter is @code{nil}, it
will remain unchanged. The button start and end will be swapped, if
necessary, so that the start comes before the end. Moving buttons will
cause the respective buffer(s) to redisplay, but will @b{not} mark the
buffer as modified unless @code{epoch::buttons-modify-buffer} is
@code{t}.  Returns the updated button.

@var{start} and @var{end} may be markers, but only the marker position
is used.
@c epoch::move-button should be called epoch::set-button since it sets
@c the buffer as well, analogous to set-marker.
@end defun

@defun epoch::add-button start end attribute &optional data buffer
Add a button to @var{buffer}. @var{start} and @var{end} must be markers or
integers.  @var{attribute} is a number. @var{data} is programmer defined,
and not used internally, and so can be anything. Returns the new button, or
@code{nil} on failure.  (This function is provided for compatibility with the
Epoch 3.2 release.)
@end defun

@defun epoch::button-at &optional position buffer
Returns the button in @var{buffer} that contains @var{position}, or
@code{nil}.  If @var{position} is @code{nil}, point is used. 
@end defun

@defun epoch::buttons-at &optional position buffer
Returns a list of buttons in @var{buffer} that contain @var{position},
or @code{nil}.  If @var{position} is @code{nil}, point is used.  The buttons
are ordered by starting position.
@end defun

@defun epoch::button-list &optional buffer
Returns the list of buttons for @var{buffer}. The list contains the
actual buttons, not copies.  The buttons are ordered by starting position.
@end defun

@defun epoch::button-attribute button
Returns the button's current @var{attribute} value.
@end defun

@defun epoch::set-button-attribute button value
Sets the button's @var{attribute} to @var{value}.  Note that @var{value} 
must be a number less than 255.
@end defun

@defun epoch::button-data button
Returns the button's current @var{data} value.
@end defun

@defun epoch::set-button-data button value
Sets the button's @var{data} to @var{value}.
@end defun

@defun button-text &optional button
Returns a string that is the text contained in @var{button}. If
@var{button} is omitted, the @code{button-at} point is used, if any.
Returns the empty string for an empty button or no button.
@end defun

@defvar epoch::buttons-modify-buffer
If non-@code{nil}, changing any buttons with Epoch primitives will cause
the associated buffer to be marked as changed.  Useful if you want
@code{write-file-hooks} that save button information.
@end defvar


@node Deleting Buttons, Style Primitives, Button Primitives, Buttons
@section Deleting Buttons


@cindex deleting buttons
@defun epoch::delete-button button &optional buffer
Removes the @var{button} from @var{buffer}. The argument must be the
actual button itself, not a copy. This can be obtained by saving the
result from @code{epoch::make-button} or other button returning
primitives.  Returns the button if successful, @code{nil} otherwise.
@end defun

@defun epoch::delete-button-at position &optional buffer
Removes the button (if any) that contains @var{position} in @var{buffer}.
Returns the button if successful, @code{nil} otherwise.  Equivalent to
@code{(epoch::delete-button (epoch::button-at position buffer) buffer)}.
@end defun

@defun epoch::clear-buttons &optional buffer
Removes all buttons from @var{buffer}. Returns @code{t} if succesful,
@code{nil} otherwise.
@end defun

@node Style Primitives, Button Plotting, Deleting Buttons, Buttons
@section Style Primitives

Styles are used for display through attribute tables. Each screen has an
attribute table, each entry of which is either @code{nil} or a style.
When a button is displayed, the attribute value of the button is used to
look up the style to use. If there is no style, it is displayed in the
inverse of the screen foreground / background colors. The same style
object can be used in multiple attribute table entries. If a style is
changed, then all buttons that use that style will be displayed in the
new style values. There is also a global attribute table, not attached
to any screen, which serves as a default for attributes. If no screen
local style is available, the global style will be used. Note that this
is a complete substitution - style values that are not present in a
screen local style will not default to the values in a global style.

@cindex Style Primitives
@cindex styles
@cindex button display

A @dfn{style} is an Elisp object that describes how to display
characters. Each button has an attribute value, which is an index into a
style table. Each screen has its own style table. In addition, there is
a global style table. When a button is displayed, the local table is
searched first. If there is no style for that attribute, the global
table is used. If neither table has a style, then the button is
displayed in the inverse of the normal screen colors.

Each style has a number of different fields. The foreground and
background colors control how normal characters are displayed in the
style. The cursor foreground and background indicate how a character in
the text cursor is to be displayed. If the cursor colors are not set,
but the text colors, the cursor will use the inverse of the normal text
colors. The underline color controls if the characters are underlined.
If set to a color, a line of that color is drawn under the characters,
else if set to @code{nil} no line is drawn. The characters can also be
stippled. 
The characters, background, and cursor can all be stippled
independently. A stipple pattern must be a X-bitmap resource
(@xref{X Objects}). For text, the on bits in the stipple are displayed
in the text foreground, and the off bits in the text background. The
character background is either solid background color (if no stipple),
or the on bits are displayed in the screen background color, and the off
bits in the text background. For the cursor, the cursor colors are used,
and the cursor stipple (if any) is used in place of the background
stipple for the cursor background. If the cursor stipple is not set, and
the background stipple is, the cursor background is not stippled.

@defun epoch::make-style
Create a style object. Initially all fields are set to @code{nil}.
@end defun

@defun epoch::style-foreground style
Returns the foreground color of @var{style}.
@end defun

@defun epoch::set-style-foreground style color
Sets the @var{style} to foreground @var{color}.
@end defun

@defun epoch::style-background style
Returns the background color of @var{style}.
@end defun

@defun epoch::set-style-background style color
Set the @var{style} to background @var{color}.
@end defun

@defun epoch::style-cursor-foreground style
Returns the cursor foreground color of @var{style}.
@end defun

@defun epoch::set-style-cursor-foreground style color
Sets the @var{style} to cursor foreground @var{color}.
@end defun

@defun epoch::style-cursor-background style
Returns the background cursor color of @var{style}.
@end defun

@defun epoch::set-style-cursor-background style color
Set the @var{style} to cursor background @var{color}.
@end defun

@defun epoch::style-underline style
Return the underline color.
@end defun

@defun epoch::set-style-underline style color
Set the @var{style} underline to @var{color}.
@end defun

@defun epoch::style-stipple style
Return the text stipple for the @var{style}.
@end defun

@defun epoch::set-style-stipple style stipple
Set the text stipple pattern for @var{style} to @var{stipple}.
@end defun

@defun epoch::style-background-stipple style
Return the background stipple for @var{style}.
@end defun

@defun epoch::set-style-background-stipple style stipple
Set the background stipple pattern for @var{style} to @var{stipple}.
@end defun

@defun epoch::style-cursor-stipple style
Return the stipple pattern for the cursor for @var{style}.
@end defun

@defun epoch::set-style-cursor-stipple style stipple
Set the cursor stipple pattern for @var{style} to @var{stipple}.
@end defun

@defun epoch::style-font style
Return the font associated with @var{style}, or @code{nil} if none is specified.
@end defun

@defun epoch::set-style-font style font
Set the font for @var{style} to be @var{font}.
@end defun

@defun epoch::set-attribute-style attribute style &optional screen
Set @var{attribute} to display using @var{style}.  If @var{screen} is 
present, then @var{attribute} is set local to that screen.
@end defun

@defun epoch::set-attribute-local number fore back &optional c-fore c-back screen
Similar to @code{set-attribute-global}, except the screen local style
table is used.
@end defun

@defun set-attribute-global number fore back &optional c-fore c-back
Sets the fields in the style for attribute @var{number} in the global
table.  The foreground and background colors are set to @var{fore} and
@var{back} respectively. If @var{c-fore} is present, the cursor
foreground color is set to that, and similarly for @var{c-back} and the
cursor background color. If there is no style entry for attribute
@var{number} in the global table, one is created.  This is useful for 
installing styles in attribute tables.  
@end defun

@defun epoch::local-buttons-p &optional screen
OBSOLETE - no longer exists.
@end defun

@defun epoch::set-local-buttons flag &optional screen
OBSOLETE - no longer exists. The effect can be achieved by using
@code{set-attribute-style}.
@end defun

@defvar motion::attribute
This attribute is designated as the attribute used for displaying text 
which has been dragged.
@end defvar

@defvar motion::style
This style, which defaults to underlining, is the style used by Epoch mouse
dragging code found in @file{motion.el}.  It's value is set at runtime, and
may be superceded by values in the file @file{.emacs}.
@end defvar

The following code is used to set up the default style for mouse dragging,
and demonstrates the use of Epoch attribute and style primitives.
@example
(defvar motion::attribute (reserve-attribute))
(setq motion::style (make-style))
(set-style-foreground motion::style (foreground))
(set-style-background motion::style (background))
(set-style-underline motion::style (foreground))
(set-attribute-style motion::attribute motion::style)
@end example

@node Button Plotting, Attribute Allocation, Style Primitives, Buttons
@section Button Plotting
@cindex button plotting
@cindex overlapping buttons

When a buffer is plotted, buttons are extracted from the buffer button
list and used to change the colors of the text and cursor. If the
buttons are disjoint, then which button to use for a character is
unambiguous. Overlapping buttons are more complex; the algorithm for
deciding which attributes are used when buttons overlap is described
next.

The button plotter assumes that the button list is sorted by starting
position.  If buttons overlap, the button with the largest starting position 
takes precedence. This allows buttons to nest, so that if one button is 
entirely inside another, both buttons are visible. If two buttons overlap 
without containment, the second button will be entirely visible, and the first
truncated. Whenever there is a reference to the button ``at'' a location,
that means the button that was plotted at that location.

@cindex zero button attributes
A button with a non-zero attribute always has precedence over a button with
zero attribute. This means that if a button with an attribute of zero follows
and overlaps a button of non-zero attribute, the preceeding button will be
plotted in the overlap region. Zero attributes are intended for hidden or
non-user buttons (such as for tagging a region of text with data), and this
rule prevents them from interfering with visible buttons.

@node Attribute Allocation, Read-only Buttons, Button Plotting, Buttons
@section Attribute Allocation

In order to use buttons, specific attributes must be set by the button
code. To avoid collisions between different packages, an attribute
allocator is provided in @file{button.el}. This allows packages to
reserve attributes for their own use, and if desired release them to be
reused. It is strongly recommended that if you write a package that uses
buttons, you use the attribute allocator.

@defun reserve-attribute
Returns a number, the index of the allocated attribute.  Returns @code{nil}
if no attributes are available.
@end defun

@defun reserve-attributes count &optional noerror
Reserves @var{count} attributes, and returns the list of corresponding
attribute indices. If @var{noerror} is non-@code{nil}, and not enough
attributes are available, a short list is returned, otherwise an error
is signaled and no attributes are marked reserved.  If @var{count} is
omitted, is as assumed to be 1.
@end defun

@defun release-attribute attr
Mark @var{attr} (which should be an attribute index) as available.
@end defun

@defun release-attributes attr-list
Mark all attributes in @var{attr-list} as available. @var{attr-list}
should be a list of attribute indices.
@end defun

@node Read-only Buttons,  , Attribute Allocation, Buttons
@section Read-only Buttons

@cindex read-only buttons
In the case of a @dfn{read-only button}, (the @var{read-only} field is
@code{t}), most attempts to change text within the button will result
in an error analogous to changing a read-only buffer.  Two
exceptions to this rule exist at button boundaries.

@enumerate
@item
Attempted changes on the first character of the button will be allowed, but 
will be diverted to the left of the button itself, so the button is not 
extended.
@item
Attempted changes to the immediate right of the button will be permitted,
but the button will not be extended.  This is really a change outside of the
button.
@end enumerate

Essentially, this implies that the size of a read-only button will only change
because of explicit commands to change the button boundaries; @b{not} by 
inserting or deleting text within the button.  Changing the location of a 
read-only button by altering text previous to the button is permitted; this 
is even possible with adjoining read-only buttons (unless they explicitly 
overlap).

@defun add-read-only-button start end attribute &optional data buffer
@findex epoch::add-button
The same as @code{epoch::add-button} except that the button is set to be
read-only immediately after being created.
@end defun

@defun epoch::read-only-region-p start end &optional buffer
Given a region delimited by @var{start} and @var{end} in @var{buffer},
check for read-only buttons.  Returns @code{nil} if region contains no 
read-only buttons; otherwise it returns the button.  In cases of overlapping 
buttons, the display rule discussed earlier is obeyed 
(@xref{Button Plotting}).  

@b{NOTE:} When checking for insert operation, use the insertion point for
both start and end arguments. If this would normally be inside the button, but
because of insertion rules would be deflected to the side of the button,
this function will not return the button.
@end defun

@defun epoch::button-read-only button
Return's the button's current @var{read-only} value.
@end defun

@defun epoch::set-button-read-only button flag
Sets the button's @var{read-only} flag to @var{flag}, which must be either 
@code{t} or @code{nil}.
@end defun

