[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1 Extents

An extent is a region of text (a start position and an end position) that is displayed in a particular face and can have certain other properties such as being read-only. Extents can overlap each other. XEmacs efficiently handles buffers with large numbers of extents in them.

Function: extentp object

This returns t if object is an extent.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.1 Introduction to Extents

An extent is a region of text within a buffer that has certain properties associated with it. The properties of an extent primarily affect the way the text contained in the extent is displayed. Extents can freely overlap each other in a buffer. Extents are invisible to functions that merely examine the text of a buffer.

An extent is logically a Lisp object consisting of a start position, an end position, a buffer to which these positions refer, and a property list. As text is inserted into the buffer, the start and end positions of the extent are automatically adjusted as necessary to keep the extent referring to the same text in the buffer. If text is inserted at the boundary of an extent, the extent’s start-open and end-open properties control whether the text is included as part of the extent. If the text bounded by an extent is deleted, the extent becomes detached; its start and end positions are no longer meaningful, but it maintains all its other properties and can later be reinserted into a buffer.

Each extent has a face associated with it, which controls the way in which the text bounded by the extent is displayed . If an extent’s face is nil or its properties are partially undefined, the corresponding properties from the default face for the frame is used. If two or more extents overlap, the corresponding faces are merged to determine the text’s displayed properties. Every extent has a priority that determines which face takes precedence if the faces conflict. (If two extents have the same priority, the one that comes later in the display order takes precedence. See section display order.) Higher-numbered priority values correspond to a higher priority, and priority values can be negative. Every extent is created with a priority of 0, but this can be changed with set-extent-priority.

Extents can be set to respond specially to key and mouse events within the extent. An extent’s keymap property controls the effect of key and mouse strokes within the extent’s text, and the highlight property controls whether the extent is highlighted when the mouse moves over it. See section Interaction of Extents with Keyboard and Mouse Events.

An extent can optionally have a start-glyph or end-glyph (but not both at one time) associated with it. A start-glyph or end-glyph is a pixmap or string that will be displayed either at the start or end of an extent or in the margin of the line that the start or end of the extent lies in, depending on the extent’s layout policy. Start-glyphs and end-glyphs are used to implement annotations, and you should use the annotation API functions in preference to the lower-level extent functions. For more information, @xref{Annotations}.

If an extent has its detachable property set, it will become detached (i.e. no longer in the buffer) when all its text its deleted. Otherwise, it will simply shrink down to zero-length and sit it the same place in the buffer. By default, the detachable property is set on newly-created extents. See section Detached Extents.

If an extent has its duplicable property set, it will be remembered when a string is created from text bounded by the extent. When the string is re-inserted into a buffer, the extent will also be re-inserted. This mechanism is used in the kill, yank, and undo commands. See section Duplicable Extents.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.2 Creating and Modifying Extents

Function: make-extent from to &optional buffer

This function makes an extent for the range [from, to) in buffer. buffer defaults to the current buffer. Insertions at point to will be outside of the extent; insertions at from will be inside the extent, causing the extent to grow (see section Extent Endpoints). This is the same way that markers behave. The extent is initially detached if both from and to are nil, and in this case buffer defaults to nil, meaning the extent is in no buffer (see section Detached Extents).

Function: delete-extent extent

This function removes extent from its buffer and destroys it. This does not modify the buffer’s text, only its display properties. The extent cannot be used thereafter. To remove an extent in such a way that it can be re-inserted later, use detach-extent. See section Detached Extents.

Function: extent-buffer extent

This function returns the buffer of extent. If the return value is nil, this means that the extent is detached; however, a detached extent will not necessarily return a value of nil.

Function: extent-live-p extent

This function returns nil if extent is deleted, and t otherwise.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.3 Extent Endpoints

Every extent has a start position and an end position, and logically affects the characters between those positions. Normally the start and end positions must both be valid positions in the extent’s buffer. However, both endpoints can be nil, meaning the extent is detached. See section Detached Extents.

Whether the extent overlaps its endpoints is governed by its start-open and end-open properties. Insertion of a character at a closed endpoint will expand the extent to include that character; insertion at an open endpoint will not. Similarly, functions such as extent-at that scan over all extents overlapping a particular position will include extents with a closed endpoint at that position, but not extents with an open endpoint.

Note that the start-closed and end-closed properties are equivalent to start-open and end-open with the opposite sense.

Both endpoints can be equal, in which case the extent includes no characters but still exists in the buffer. Zero-length extents are used to represent annotations (@pxref{Annotations}) and can be used as a more powerful form of a marker. Deletion of all the characters in an extent may or may not result in a zero-length extent; this depends on the detachable property (see section Detached Extents). Insertion at the position of a zero-length extent expands the extent if both endpoints are closed; goes before the extent if it has the start-open property; and goes after the extent if it has the end-open property. Zero-length extents with both the start-open and end-open properties are not allowed to exist because there is no sensible way to define their properties. (If all the text in an extent with both properties set is deleted and the extent is not detachable, the start-open property is removed from the extent.) Deletion of a character on a side of a zero-length extent whose corresponding endpoint is closed causes the extent to be detached if its detachable property is set; if the corresponding endpoint is open, the extent remains in the buffer, moving as necessary.

Extents are ordered within a buffer by increasing start position, and then by decreasing end position (this is called the display order).

Function: extent-start-position extent

This function returns the start position of extent.

Function: extent-end-position extent

This function returns the end position of extent.

Function: extent-length extent

This function returns the length of extent in characters. If the extent is detached, this returns 0. If the extent is not detached, this is equivalent to

(- (extent-end-position extent) (extent-start-position extent))
Function: set-extent-endpoints extent start end

This function sets the start and end position of extent to start and end. If both are nil, this is equivalent to detach-extent.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.4 Finding Extents

The following functions allow for scanning over the extents in a buffer or searching for extents in a particular range of a buffer. Keep in mind the way that extents are ordered in a buffer (see section Extent Endpoints).

Function: next-extent extent

Given an extent extent, this function returns the next extent in the buffer’s display order. If extent is a buffer, this returns the first extent in the buffer.

Function: previous-extent extent

Given an extent extent, this function returns the previous extent in the buffer’s display order. If extent is a buffer, this returns the last extent in the buffer.

If you want to map over all extents that meet a certain criterion, use map-extents – it is much faster than a loop involving next-extent.

Function: extent-at pos &optional buffer property before

This function finds the “smallest” extent (i.e., the last one in the display order) at (i.e., overlapping) pos in buffer having property set. buffer defaults to the current buffer. property defaults to nil, meaning that any extent will do. Returns nil if there is no matching extent at pos. If the fourth argument before is not nil, it must be an extent; any returned extent will precede that extent. This feature allows extent-at to be used by a loop over extents.

Function: map-extents function &optional buffer from to maparg closed-end

This function maps function over the extents which overlap the region ‘[from, to)’ (or ‘[from, to]’ if closed-end is non-nil) in buffer. function is called with the arguments (extent, maparg). The arguments from, to, maparg, and buffer default to the beginning of buffer, the end of buffer, nil, and (current-buffer), respectively. map-extents returns the first non-nil result produced by function, and no more calls to function are made after that. If buffer is an extent, from and to default to the extent’s endpoints, and the mapping omits that extent and its predecessors. This feature supports restarting a loop based on map-extents.

The effect of closed-end is that, if an extent and the map region overlap only at a start and end position, the extent is visited by map-extents only if both positions are closed.

Function: map-extent-children function &optional buffer from to maparg closed-end

This function is similar to map-extents, but differs in that:

Thus, this function may be used to walk a tree of extents in a buffer:

(defun walk-extents (buffer &optional ignore)
  (map-extent-children 'walk-extents buffer))
Function: extent-in-region-p extent &optional from to closed-end

This function returns t if map-extents would visit extent if called with the given arguments.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.5 Properties of Extents

Each extent has a property list associating property names with values. Some property names have predefined meanings, and can usually only assume particular values. Assigning other values to such a property either cause the value to be converted into a legal value (e.g., assigning anything but nil to a Boolean property will cause the value of t to be assigned to the property) or will cause an error. Property names without predefined meanings can be assigned any value. An undefined property is equivalent to a property with a value of nil, or with a particular default value in the case of properties with predefined meanings. Note that, when an extent is created, the end-open and detachable properties are set on it.

Function: extent-property extent property

This function returns the value of property in extent. If property is undefined, nil is returned.

Function: extent-properties extent

This function returns a list of all of extent’s properties that do not have the value of nil (or the default value, for properties with predefined meanings).

Function: set-extent-property extent property value

This function sets property to value in extent. (If property has a predefined meaning, only certain values are allowed, and some values may be converted to others before being stored.)

The following table lists the properties with predefined meanings, along with their allowable values.

detached

(Boolean) Whether the extent is detached. Setting this is the same as calling detach-extent. See section Detached Extents.

destroyed

(Boolean) Whether the extent has been deleted. Setting this is the same as calling delete-extent.

priority

(integer) The extent’s redisplay priority. Defaults to 0. See section priority. This property can also be set with set-extent-priority and accessed with extent-priority.

start-open

(Boolean) Whether the start position of the extent is open, meaning that characters inserted at that position go outside of the extent. See section Extent Endpoints.

start-closed

(Boolean) Same as start-open but with the opposite sense. Setting this property clears start-open and vice-versa.

end-open

(Boolean) Whether the end position of the extent is open, meaning that characters inserted at that position go outside of the extent. This is t by default. See section Extent Endpoints.

end-closed

(Boolean) Same as end-open but with the opposite sense. Setting this property clears end-open and vice-versa.

read-only

(Boolean) Whether text within this extent will be unmodifiable.

face

(face, face name, or nil) The face in which to display the extent’s text. This property can also be set with set-extent-face and accessed with extent-face.

highlight

(Boolean) Whether to highlight the extent when the mouse moves over it. See section Interaction of Extents with Keyboard and Mouse Events.

detachable

(Boolean) Whether this extent becomes detached when all of the text it covers is deleted. This is t by default. See section Detached Extents.

duplicable

(Boolean) Whether this extent should be copied into strings, so that kill, yank, and undo commands will restore or copy it. See section Duplicable Extents.

unique

(Boolean) Meaningful only in conjunction with duplicable. When this is set, there may be only one instance of this extent attached at a time. See section Duplicable Extents.

invisible

(Boolean) If t, text under this extent will not be displayed – it will look as if the text is not there at all.

keymap

(keymap or nil) This keymap is consulted for mouse clicks on this extent or keypresses made while point is within the extent. See section Interaction of Extents with Keyboard and Mouse Events.

copy-function

This is a hook that is run when a duplicable extent is about to be copied from a buffer to a string (or the kill ring). See section Duplicable Extents.

paste-function

This is a hook that is run when a duplicable extent is about to be copied from a string (or the kill ring) into a buffer. See section Duplicable Extents.

glyph-layout

(’text, ’whitespace, ’inside-margin, or ’outside-margin) The layout policy for this extent’s glyph. Defaults to text. @xref{Annotations}.

begin-glyph

(pixmap, string, or nil) This extent’s begin-glyph. Cannot be non-nil at the same time as end-glyph. @xref{Annotations}.

end-glyph

(pixmap, string, or nil) This extent’s end-glyph. Cannot be non-nil at the same time as begin-glyph. @xref{Annotations}.

The following convenience functions are provided for accessing particular properties of an extent.

Function: extent-priority extent

This function returns the priority property of extent.

Function: extent-face extent

This function returns the face property of extent.

Function: extent-layout extent

This function returns the glyph-layout property of extent.

Function: extent-glyph extent

This function returns the glyph associated with extent. This is the value of the begin-glyph or end-glyph property, if either one is non-nil. (It is not possible for both to be non-nil at the same time.)

The following convenience functions are provided for setting particular properties of an extent.

Function: set-extent-priority extent pri

This function sets the priority property of extent to pri.

Function: set-extent-face extent face

This function sets the face property of extent to face.

Function: set-extent-layout extent layout

This function sets the glyph-layout property of extent to layout.

Function: set-extent-begin-glyph extent begin-glyph &optional layout

This function sets the begin-glyph and glyph-layout properties of extent to begin-glyph and layout, respectively. (layout defaults to text if not specified.) This function will fail if extent already has an end-glyph property.

Function: set-extent-end-glyph extent end-glyph &optional layout

This function sets the end-glyph and glyph-layout properties of extent to end-glyph and layout, respectively. (layout defaults to text if not specified.) This function will fail if extent already has a begin-glyph property.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.6 Detached Extents

A detached extent is an extent that is not attached to a buffer but can be re-inserted. Detached extents have a start position and end position of nil. Extents can be explicitly detached using detach-extent. An extent is also detached when all of its characters are all killed by a deletion, if its detachable property is set; if this property is not set, the extent becomes a zero-length extent. (Zero-length extents with the detachable property set behave specially. See section zero-length extents.)

Function: detach-extent extent

This function detaches extent from its buffer. If extent has the duplicable property, its detachment is tracked by the undo mechanism. See section Duplicable Extents.

Function: extent-detached-p extent

This function returns nil if extent is detached, and t otherwise.

Function: copy-extent extent &optional buffer

This function makes a copy of extent. It is initially detached. Optional argument buffer defaults to extent’s buffer.

Function: insert-extent extent &optional start end no-hooks

This function inserts extent from start to end in the current buffer. If extent is detached from a different buffer, or in most cases when extent is already attached, the extent will first be copied as if with copy-extent. This function operates the same as if insert were called on a string whose extent data calls for extent to be inserted, except that if no-hooks is non-nil, extent’s paste-function will not be invoked. See section Duplicable Extents.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.7 Duplicable Extents

If an extent has the duplicable property, it will be copied into strings, so that kill, yank, and undo commands will restore or copy it. Note that the extent is not actually copied; rather, a pointer to it is stored, along with the start and end positions of the extent. (This combination is called an extent replica.) This means that, e.g., if you copy a duplicable extent into the kill ring, then change the properties of the extent, then paste the kill-ring text back into the buffer, the newly-inserted extent will have the property changes you just made to the original extent, and not the property values at the time the text was copied into the kill ring.

Specifically:


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.8 Extent Replicas

The following primitives for manipulating extent replicas are available. An extent replica is used to store extent data in a string and is a primitive data type encapsulating an extent and start and end positions within the string. New extent replicas can be created but there are no mutator functions for modifying existing extent replicas. See section Duplicable Extents.

Note: Lisp-visible extent replicas may disappear in the future (replaced by allowing map-extents to take a string argument). Avoid using the following functions if at all possible.

Function: extent-replica-p object

This function returns non-nil if object is an extent replica.

Function: extent-replica-live-p object

This function returns non-nil if object is an extent replica that has not been deleted.

Function: string-extent-data string

This function returns the extent data stored along with string. The value returned is a list of extent replica objects.

Function: set-string-extent-data string data

This function sets the extent data stored along with a string. data should be nil or a list of extent replicas.

Function: make-extent-replica extent start end

This function makes an extent replica for extent in the range from start to end.

Function: extent-replica-extent dup

This function returns the extent to which extent replica dup refers.

Function: extent-replica-start dup

This function returns the start position of extent replica dup.

Function: extent-replica-end dup

This function returns the end position of extent replica dup.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.9 Interaction of Extents with Keyboard and Mouse Events

If an extent has the highlight property set, it will be highlighted when the mouse passes over it. Highlighting is accomplished by merging the extent’s face with the highlight face. The effect is as if a pseudo-extent with the highlight face were inserted after the extent in the display order (see section Extent Endpoints, display order).

Variable: mouse-highlight-priority

This variable holds the priority to use when merging in the highlighting pseudo-extent. The default is 1000. This is purposely set very high so that the highlighting pseudo-extent shows up even if there are other extents with various priorities at the same location.

You can also explicitly cause an extent to be highlighted. Only one extent at a time can be highlighted in this fashion, and any other highlighted extent will be de-highlighted.

Function: highlight-extent extent &optional highlight-p

This function highlights (if highlight-p is non-nil) or de-highlights (if highlight-p is nil) extent, if extent has the highlight property. (Nothing happens if extent does not have the highlight property.)

Function: force-highlight-extent extent &optional highlight-p

This function is similar to highlight-extent but highlights or de-highlights the extent regardless of whether it has the highlight property.

If an extent has a keymap property, this keymap will be consulted for mouse clicks on the extent and keypresses made while point is within the extent. The behavior of mouse clicks and keystrokes not defined in the keymap is as normal for the buffer.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.10 Atomic Extents

If the Lisp file ‘atomic-extents’ is loaded, then the atomic extent facility is available. An atomic extent is an extent for which point cannot be positioned anywhere within it. This ensures that when selecting text, either all or none of the extent is selected.

To make an extent atomic, set its atomic property.


[Top] [Contents] [Index] [ ? ]

About This Document

This document was generated on December 6, 2024 using texi2html 5.0.

The buttons in the navigation panels have the following meaning:

Button Name Go to From 1.2.3 go to
[ << ] FastBack Beginning of this chapter or previous chapter 1
[ < ] Back Previous section in reading order 1.2.2
[ Up ] Up Up section 1.2
[ > ] Forward Next section in reading order 1.2.4
[ >> ] FastForward Next chapter 2
[Top] Top Cover (top) of document  
[Contents] Contents Table of contents  
[Index] Index Index  
[ ? ] About About (help)  

where the Example assumes that the current position is at Subsubsection One-Two-Three of a document of the following structure:


This document was generated on December 6, 2024 using texi2html 5.0.