Character Coloring

You can set the color of individual characters using the
set_character_color( ) primitive. At first glance, this feature
may seem similar to Epsilon's mechanism for defining highlighted
regions. Both let you specify a range of characters and a color to
display them with. But each has its own advantages.

Region highlighting can highlight the text in different ways: as a
rectangle, expanded to entire lines, and so forth, while character
coloring has no similar options. You can define a highlighted region
that moves around with the point, the mark, or any other spot.
Character coloring always remains with the characters.

But when there are many colored regions, using character coloring is
much faster than creating a corresponding set of highlighted regions.
If you define more than a few dozen highlighted regions, Epsilon's
screen refreshes will begin to slow down. Character coloring, on the
other hand, is designed to be very fast, even when there are
thousands of colored areas. Character coloring is also easier to use
for many tasks, since it doesn't require the programmer to allocate
spots to delimit the ends of the colored region, or delete them when
the region is no longer needed.

One more difference is the way you remove the coloring. For
highlighted regions, you can turn off the coloring temporarily by
calling modify_region( ), or eliminate the region entirely by
calling remove_region( ). To do either of these, you must supply
the region's handle, a value returned when the region was first
created. On the other hand, to remove character coloring, you can
simply set the desired range of characters to the special color
-1. A program using character coloring doesn't need to store a
series of handles to remove or modify the coloring.

Epsilon's code coloring functions are built on top of the character
coloring primitives described in this section. See the next section
for information on the higher-level functions that make code coloring
work.

set_character_color(int pos1, int pos2, int color)

The set_character_color( ) primitive
makes Epsilon display characters between pos1 and pos2
using the specified color class. Epsilon discards any previous color
settings of characters in that range.

A color class of -1 means the text will be "uncolored". To
display uncolored text, Epsilon uses the standard color class
text. When a buffer is first created, every character is
uncolored.

When you insert text in a buffer, it takes on the color of the
character immediately after it, or in the case of the last character
in the buffer, the character immediately before it. Characters
inserted in an empty buffer are initially uncolored. Copying text
from one buffer to another does not automatically transfer the color;
Epsilon treats the new characters the same as any other inserted
text. You can use the buf_xfer_colors( ) subroutine to copy
text from one buffer to another and retain its coloring. See Moving Text Between Buffers.

Epsilon maintains the character colors set by this primitive
independently of the highlighted regions created by
add_region( ). The modify_region( ) primitive will never
change what get_character_color( ) returns, and similarly the
set_character_color( ) primitive never changes the attributes of
a region you create with add_region( ). When Epsilon displays
text, it combines information from both sources to determine the
final color of each character.

When displaying a buffer, Epsilon uses the following procedure when
determining which color class to use for a character:

Make a list of all old-style highlighted regions that contain
the character, and the color classes used for each.

Add the character's color as set by set_character_color( )
to this list.

Remove color classes of -1 from the list.

Next, Epsilon chooses a color class from the list:

If the list of color classes is empty, use the text color class.

Otherwise, if the list contains the highlight color class,
use that.

Otherwise, use the color class from the old-style highlighted region
with the highest region number. If there are no old-style
highlighted regions in the list, the list must contain only one color
class, so use that.

Finally, if we wound up selecting the text color class, and
the text_color variable isn't equal to color_class text,
use the color class in the text_color variable instead of the
color_class text.

Notice that when a region using the highlight color class
overlaps another region, the highlight color class takes
precedence.

buf_set_character_color(int buf, int from, int to, int color)

The buf_set_character_color( ) subroutine is a convenience
function. It simply runs set_character_color( ) in the specified
buffer buf, passing it the remaining parameters.

short get_character_color(int pos, ?int *startp, ?int *endp)

The get_character_color( ) primitive returns the color class
for the character at the specified buffer position, as set by
set_character_color( ), or -1 if the character is uncolored,
and will be displayed using the window's default color class.

You can also use the primitive to determine the extent of a range of
characters all in the same color. If the optional pointer parameters
startp and endp are non-null, Epsilon fills in the locations they
point to with buffer positions. These specify the largest region of
the buffer containing characters the same color as the one at pos,
and including pos. For example, if the buffer contains a
five-character word that has been colored blue, the buffer is
otherwise uncolored, and pos refers to the second character in
the word, then Epsilon will set *startp to pos - 1 and
*endp to pos + 4.

The character coloring
primitives above are actually built from a more general facility that
allows you to associate a set of attributes with a buffer range.

Each set of attributes consists of a tag (a unique
string like "my-tag") and, for each character in the buffer, a number
that represents the attribute. Each buffer has its own set of tags, and each
tag has its own list of attributes, one for each character. (Epsilon stores
the numbers in a way that's efficient when many adjacent characters have the
same number, but nothing prevents each character from having a different
attribute.)

The set_tagged_region( ) primitive sets the attribute of the
characters in the range from to to, for the specified tag.

The get_tagged_region( ) primitive gets the attribute of the
character at position pos in the buffer. If you provide pointers
from and to, Epsilon will fill these in to indicate the largest range
of characters adjacent to pos that have the same attribute as
pos. Characters whose attributes have never been set for a given
tag will have the attribute -1.

Epsilon's character color primitives set_character_color( ) and
get_character_color( ) use a built-in tagged region with a tag name of
"colors".