Lugaru's Epsilon
Programmer's
Editor

Context:
Epsilon User's Manual and Reference
   Primitives and EEL Subroutines
      Buffer Primitives
         . . .
         Moving Text Between Buffers
         Getting Text from a Buffer
         Spots
         Narrowing
         Undo Primitives
         . . .
      Display Primitives
         Creating & Destroying Windows
         Window Resizing Primitives
         Preserving Window Arrangements
         . . .
         Colors
      . . .

Previous   Up    Next
Getting Text from a Buffer  Primitives and EEL Subroutines   Narrowing


Epsilon User's Manual and Reference > Primitives and EEL Subroutines > Buffer Primitives >

Spots

spot alloc_spot(?int left_ins)
free_spot(spot sp)
int spot_to_buffer(spot sp)

A place in the buffer is usually recorded and saved for later use as a count of the characters before that place: this is a position, as described in Changing Buffer Contents. Sometimes it is important for the stored location to remain between the same pair of characters even if many changes are made to other parts of the buffer (affecting the number of characters before the saved location).

Epsilon provides a type of variable called a spot for this situation. The declaration

        spot sp;

says that sp can refer to a spot. It doesn't create a new spot itself, though.

The alloc_spot( ) primitive creates a new spot and returns it, and the free_spot( ) primitive takes a spot and discards it. The spot that alloc_spot( ) returns is initially set to point, and is associated with the current buffer. Deleting a buffer frees all spots associated with it. If you try to free a spot whose buffer has already been deleted, Epsilon will ignore the request, and will not signal an error.

The spot_to_buffer( ) primitive takes a spot and returns the buffer number it was created for, or -1 if the buffer no longer exists, or -2 if the buffer exists, but that particular spot has since been deleted.

If the left_ins parameter to alloc_spot( ) is nonzero, a left-inserting spot is created. If the left_ins parameter is 0, or is omitted, a right-inserting spot is created. The only difference between the two types of spots is what they do when characters are inserted right where the spot is. A left-inserting spot stays after such inserted characters, while a right-inserting spot stays before them. For example, imagine an empty buffer, with all spots at 0. After five characters are inserted, any left-inserting spots will be at the end of the buffer, while right-inserting spots will remain at the beginning.

A spot as returned by alloc_spot( ) behaves a little like a pointer to an int, in that you must dereference it by writing *sp to obtain the position it currently refers to. For example:

fill_all()      /* fill paragraphs, leave point alone */
{
spot oldpos = alloc_spot(), oldmark = alloc_spot();

*oldpos = point;
*oldmark = mark;        /* save old values */
point = 0;              /* make region be whole buffer */
mark = size();
fill_region();          /* fill paragraphs in region */
mark = *oldmark;        /* restore values */
point = *oldpos;
free_spot(oldmark);     /* free saving places */
free_spot(oldpos);
}

A simpler way to write the above subroutine uses EEL's save_spot keyword. The save_spot keyword takes care of allocating spots, saving the original values, and restoring those values when the subroutine exits. See Save_var Statements for more on save_spot.

fill_all()      /* fill paragraphs, leave point alone */
{               /* uses save_spot */
save_spot point = 0;    /* make region be whole buffer */
save_spot mark = size();
fill_region();          /* fill paragraphs in region */
}

Like a pointer, a spot variable can contain zero, and alloc_spot( ) is guaranteed never to return this value. Epsilon signals an error if you try to dereference a spot which has been freed, or whose buffer no longer exists.

buffer spot point_spot;
buffer spot mark_spot;
#define point   *point_spot
#define mark    *mark_spot
/* These variables are actually defined
   differently.  See below. */

Each new buffer begins with two spots, point_spot and mark_spot, set to the beginning of the buffer. Point_spot is a left-inserting spot, while mark_spot is a right-inserting spot. These spots are created automatically with each new buffer, and you cannot free them. You can think of the built-in variables point and mark as simply macros that yield *point_spot and *mark_spot, respectively. That's why you don't need to put a * before each reference to point.

user buffer int point;       /* True definitions */
user buffer int mark;
spot get_spot(int which)
#define point_spot      get_spot(0)
#define mark_spot       get_spot(1)

Actually, while point and mark could be defined as macros, as above, they're not. Epsilon recognizes them as built-in primitives for speed. On the other hand, point_spot and mark_spot actually are macros! They use the get_spot( ) primitive, which has no function other than to return these two values.

do_set_mark(int val)

The do_set_mark( ) subroutine sets the current buffer's mark to the specified value. It also records the current virtual column (which, typically, should match the mark). The rectangle commands retrieve this, so that in virtual mode you can copy rectangles that end in virtual space.

set_spot(spot *s, int pos)

The set_spot( ) subroutine sets a spot so it refers to the position pos in the current buffer. Pass it the address of a spot variable. If the spot is zero or refers to a different buffer, the subroutine will create a new right-inserting spot in the current buffer, freeing the old spot.



Previous   Up    Next
Getting Text from a Buffer  Primitives and EEL Subroutines   Narrowing


Lugaru Copyright (C) 1984, 2012 Lugaru Software Ltd. All Rights Reserved.