Other Display Primitives ||
Primitives and EEL Subroutines ||
Epsilon User's Manual and Reference >
Primitives and EEL Subroutines >
Display Primitives >
Epsilon can display portions of a buffer in a different color than
the rest of the buffer. We call each such portion a region. The
most familiar region is the one between point and mark. Epsilon
defines this region automatically each time you create a new buffer.
(Also see the description of character coloring in Character Coloring.)
Epsilon can display a region in several ways. The most common method
corresponds to the one you see when you set the mark (by typing
Ctrl-@) and then move around: Epsilon highlights each of the
characters between point and mark. If you use the
mark-rectangle command on Ctrl-X # to define a rectangular
region, the highlighting appears on all columns between point and
mark, on all lines between point and mark. The pop-up windows of the
completion facility illustrate a third type of highlighting, where
complete lines appear highlighted. The header file codes.h defines
these types of regions as (respectively)
REGLINE. Epsilon won't do any
highlighting for a region that has type
A fourth type of highlighting,
REGINCL, is similar to
REGNORM, but includes an additional character at the end of the
region. If a REGNORM region runs between position 10 and
position 20 in the buffer, Epsilon would highlight the 10 characters
between the two positions. But if the region were a REGINCL
region, it would include 11 characters: the characters at positions
10 and 20, and all the characters between.
int add_region(spot from, spot to, int color,
int type, ?int handle)
int modify_region(int handle, int code, int val)
window char _highlight_control;
You can define new regions with add_region( ). It takes a
pair of spots, a color class expression such as
highlight, a region display type (as described above), and,
optionally, a numeric "handle". It returns a nonzero numeric
handle which you can use to refer to the region later. You can
provide the spots in either order, and you may give the same spot
twice (for example, in conjunction with REGLINE, to always
highlight a single line). See Setting Colors for basic
information on color classes, and Constants and Identifiers
for details on the syntax of color class expressions).
When you omit the
handle parameter to add_region( ) (or
handle of zero) add_region( ) assigns an unused
handle to the new region. You can also provide the handle of an
existing region, and add_region( ) will assign the same handle to
the new region. Any changes you make to one region by using
modify_region( ) will now apply to both, and a single
remove_region( ) call will remove both. You can link any
number of regions in the same buffer in this way. The special handle
1 refers to the region between point and mark that Epsilon
The remove_region( ) primitive takes a region handle, and
deletes all regions with that handle. The handle may belong to a
region in another buffer. Epsilon signals an error if the handle
doesn't refer to any region.
The modify_region( ) primitive retrieves or sets some of the
attributes of one or more regions. It takes a region handle, a modify
code (one of the
MR... codes below), and a new value. If you
provide a "new value" that's out of range (such as
-2, out of
range for all modify codes), Epsilon will not change that attribute of
the region, but will simply return its value. If you provide a valid
new value, Epsilon will set that attribute of the region, and will
return its previous value.
When several regions share the same handle, it's possible they will
have different attribute settings. In this case, which region's
attribute Epsilon returns is undefined. If you specify a new value
for an attribute, it will apply to all regions with that handle.
The modify code
MRCOLOR may be used to get or change a
region's color class. The modify code
MRTYPE may be used to
get or change a region's display type, such as REGRECT. The
MREND may be used to set the two
spots of a region; however, Epsilon will not return the spot
identifier for a region, but rather its current buffer position.
You can force a region's starting and ending positions to specific
columns using the modify codes
MRENDCOL. For example, if a region runs from point to mark,
and you set its MRSTARTCOL to 3, the region will start at column
3 of whatever line point is on. A column setting of
makes Epsilon use the actual column value of the spot; no column will
You can set up a region to be "controlled" by any numeric global
variable. Epsilon will display the region only if the variable is
nonzero. This is especially useful because the variable may be
window-specific. Since regions are associated with buffers, this is
needed so that a buffer displayed in two windows can have a region
that appears in only one of them.
The standard region between point and mark is controlled by the
window-specific character variable _highlight_control. By
default, other regions are not controlled by any variable. The
MRCONTROL may be used with modify_region( ) to
associate a controlling variable with a region. Provide the global
variable's name table index (obtainable through find_index( )) as
the value to set.
A region may be given an auto-delete property using the
MRAUTODEL macro. Pass a value of
1 to enable
0 to disable it. When you delete an auto-deleting
region, it automatically deletes the two spots assigned to it. By
default, no region is auto-deleting. The spots used for an
auto-deleting region should not be shared with other regions, or
system spots like point_spot or mark_spot.
set_region_type() /* disp.e */
int region_type() /* disp.e */
highlight_on() /* disp.e */
highlight_off() /* disp.e */
int is_highlight_on() /* disp.e */
Several subroutines let you conveniently control highlighting of the
standard region between point and mark. To set the type of the
region, call the subroutine set_region_type( ) with the
region type code, one of REGNORM, REGRECT, REGLINE,
or REGINCL. This doesn't automatically turn on highlighting.
Call highlight_on( ) to turn on highlighting, or
highlight_off( ) to turn it off.
The region_type( ) subroutine returns the type of the
current region, whether or not it's currently highlighted. The
is_highlight_on( ) subroutine returns the type of the
current region, but only if it's highlighted. It returns
highlighting is off.
There are several subroutines that help you write functions that work
with different types of regions. If you've written a function that
operates on the text of a normal Epsilon region, add the following
lines at the beginning of your function to make it work with
inclusive regions and line regions as well:
save_spot point, mark;
When the user has highlighted an inclusive or line region, the
fix_region( ) subroutine will reposition point and
mark to form a normal Epsilon region with the same characters.
(For example, in the case of a line region, Epsilon moves point to
the beginning of the line.) The function also swaps point and
mark so that point comes first (or equals mark, if the
region happens to be empty). This is often convenient.
This procedure assumes your function doesn't plan to modify
point or mark, just the characters between them, and it
makes sure that point and mark remain in the same place.
If your function needs to reposition the point or mark, try omitting
save_spot line. Your function will be responsible for
determining where the point and mark wind up.
A function needs to do more work to operate on rectangular regions.
If it's built to operate on all the characters in a region, without
regard to rectangles or columns, the simplest approach may be to
extract the rectangle into a temporary buffer, modify it there, and
then replace the rectangle in the original buffer. Several Epsilon
subroutines help you do this. For a concrete example, let's look at
the function fill_rectangle( ), defined in format.e. The
fill-region command calls this function when the current
region is rectangular.
// Fill paragraphs in rectangle between point and mark
// to marg columns (relative to rectangle's width if <=0).
int width, orig = bufnum, b = tmp_buf();
width = extract_rectangle(b, 0);
save_var bufnum = b;
mark = 0;
margin_right = marg + (marg <= 0 ? width : 0);
xfer_rectangle(orig, width, 1);
The function begins by allocating a temporary buffer using
tmp_buf( ). Then it calls the extract_rectangle( )
subroutine to copy the rectangle into the temporary buffer. This
function returns the width of the rectangle it copied. The call from
fill_rectangle( ) passes the destination buffer number as the
first parameter. Then fill_rectangle( ) switches to the
temporary buffer and reformats the text. Finally, the subroutine
copies the text back into its rectangle by calling
xfer_rectangle( ) and deletes the temporary buffer. If the
operation you want to perform on the text in the rectangle depends on
any buffer-specific variables, be sure to copy them to the temporary
Now let's look at the two rectangle-manipulating subroutines
fill_rectangle( ) calls in more detail.
extract_rectangle(int copybuf, int remove)
The extract_rectangle( ) subroutine operates on the region
between point and mark in the current buffer. It treats the region
as a rectangle, whether or not region_type( ) returns
REGRECT. It can perform several different actions, depending
upon its parameters. If
copybuf is nonzero, the subroutine
inserts a copy of the rectangle into the buffer with that buffer
number. The buffer must already exist.
1, the subroutine deletes the characters
inside the rectangle. If
2, the subroutine
replaces the characters with spaces. If
subroutine doesn't change the original rectangle.
The subroutine always leaves point at the upper left corner of the
rectangle and mark at the lower right. It return the width of the
xfer_rectangle(int dest, int width, int overwrite)
The xfer_rectangle( ) subroutine inserts the current buffer as
a rectangle of the given
width into buffer number
dest's current point. If
overwrite is nonzero,
the subroutine copies on top of any existing columns. Otherwise it
inserts new columns. In the destination buffer, it leaves point at
the top left corner of the new rectangle, and mark at the bottom
right. The point remains at the same position in the original buffer.
Functions that manipulate rectangles can sometimes use the
rectangle_standardize( ) subroutine to simplify their logic.
In a rectangular region, point may be at any one of the four corners
of the rectangle. This subroutine moves point and mark so they
indicate the same region, but with point at the lower right and mark
at the upper left. It's like the rectangular region equivalent of the
fix_region( ) subroutine.
Commands bound to cursor keys typically select
text when you hold down the shift key. They do this by calling
do_shift_selects( ) as they start. This routine looks at
the current state of the shift key and whether or not highlighting is
already on, and turns highlighting on or off as needed, possibly
make_line_highlight() /* complete.e */
remove_line_highlight() /* complete.e */
The make_line_highlight( ) subroutine uses the
add_region( ) primitive to create a region that highlights the
current line of the current buffer. When Epsilon puts up a menu of
options, it uses this function to keep the current line highlighted.
The remove_line_highlight( ) subroutine gets rid of such
Other Display Primitives ||
Primitives and EEL Subroutines ||
Copyright (C) 1984, 2020 by Lugaru Software Ltd. All rights reserved.