LessThan < MARKER >
Marker
Marker::HookData
MarkerMortuary < MARKER >
MarkerOwner
MarkerOwner::HookData
MarkerOwner::UpdateInfo
TempMarker
TemporaryMarkerSlideDown < MARKER >
Contains
Marker positions are measured in units of Led_tChar
s - which don't
necessarily correspond exactly to bytes or characters.
A TextStore contains an array of character (Led_tChar) cells numbered from 0..n-1, where n is the length of the buffer. But we will rarely refer to these, and more often refer to Marker positions.
A Marker is an abstract entity which is used to keep track of portions of the text. It maintains "pointers" just before, and just after character (Led_tChar) cells.
It is IMPORTANT not to confuse Marker positions with character (Led_tChar) positions. They are closely related, but not identical. Marker positions are numbered from 0..n, where n is the length of the buffer. The marker position ALPHA, comes just before the character (Led_tChar) position ALPHA. In other words, the character ALPHA lies between marker positions ALPHA, and ALPHA+1.
(Marker m)
/ |
0 1 2 3 4 5 6 7.... (marker positions)
|H|E|L|L|O| |W|O|R|L|D|
0 1 2 3 4 5 6 7.... (character positions)
In this example, Marker m extends from marker positions 0..4, and has a length of 4-0=4, and bounds the characters "HELL" (which were at character (Led_tChar) positions 0..3).
Since there is the potential for confusion between charater positions and marker positions, we will opt to ALWAYS refer to Marker positions - and NEVER refer to character positions. This will make things much clearer (I hope).
So our insert routines will, for example insert not AT a particular location, but just AFTER a particular marker. Similarly for deletes, etc. When you ask for text to be copied out of the editor into a 'C' array of characters, you will specify the marker position just before the first character (Led_tChar) you want copied out - and so on.
The main point of markers is to keep track of particular bits of text, and to attatch logical attributes to them. Some of these attributes might be visible (e.g. Bolding) and some may not (say a hyperlink, or dictionary source marker). But these markers are intended to be ATTACHED to particular words (or sequences of bytes) in the text, and NOT to positions in the text buffer. Therefore, it is one of the principle functions of a marker to adjust its position values so that it can keep track of a particular bit of text.
Here is how we define the behavior of markers and their tracking of text in the presence of edit operations. If text is simply changed within a marker, the marker doesn't move (though notification methods are called). If text is inserted to the left (before) a given marker, its left and right sides are adjusted by the same amount to the right. If text is removed from the left (before) the marker, then the left and right sides are adjusted the same amount to the left. If the modification - addition or removal - takes place to the right (after) the right side of the marker, it has no effect. If an insertion or removal takes place INSIDE the bounds of the left and right sides of the marker, the left side remains unchanged, and the right side is incremented by the size of the insertion or decremented by the size of the removal. Note: this specification counts heavily on our definition that the text changes must happen before or after marker positions - and cannot happen AT those positions. A markers size can never collapse below zero.
One implication of this definition of marker updating is that once a markers size becomes zero, it will never be automatically increased. Once they contain no text, the marker can only increase in size through programatic intervention. For this reason (at least partly) it is likely that many classes of markers will destroy themselves when their size decreses to zero.
Markers can also be used to do things other than mark particular bits of text. They can be used to insert other sorts of graphix into the flow of the text. One particular marker subclass might display a picture. Since this marker really has nothing todo with any text, it might be a zero-length marker. Even zero length markers CAN end up being displayed. They participate in the TextImager layout, and display. But, more typically, it would be a marker of length 1 (with a sentinal character in the character position marked by that marker), so that cursoring in the editor the image is treated as a single item (like a character of text).
It is for this reason (and others) that we care about the ordering of markers with zero length.
Markers have a natural ordering. They are ordered by their left hand sides start positions. This ordering could be further refined to take into account the markers right-hand sides - but that ordering would still not be a well-ordering (we can easily built two markers with the same left and right sides).
Since we care for display purposes about the relative ordering of markers - even those with zero length - we require a further constraint on the ordering of markers to make them well-ordered. We call this the "marker sub-position order". Each marker within the buffer which starts at a particular location has a sub-position index from 0..m-1, where m is the number of other markers which start at the same position. This sub-position order defines precedence at display time when markers overlap, and compete in the TextLayout and imaging process described in the TextImager header file.
LessThan < MARKER > [public]
Use this class when you have a vector of some marker subclass and want to sort it.
As in:
vector<MyMarker*> markers = get_em ();
sort (markers.begin (), markers.end (), LessThan<MyMarker> ())
Note that as of Led 3.0d6, this allows for where two markers have the same start, and then measures less according to where they end.
Marker [public]
A basic building-block of Led. This class marks a region of text, and sticks to that text, even as text before or after is updated. Also, Markers can be notified when any attempted update happens within their bounds.
Member Details |
---|
Notification callback which is called by a |
Notification callback which is called by a |
Returns the marker position of the end (rhs) of the marker. It is illegal to call this
if the marker is not currently added to a |
Return the length - in |
Return the current marker owner. Unlike most Marker methods, this can be called when the
marker hasn't yet been added to a |
Return the start and end position of the marker. You must set its bounds via Marker::SetRange (). |
Returns the marker position of the start (lhs) of the marker. It is illegal to call this
if the marker is not currently added to a |
Marker::HookData [public]
An implementation detail of implementing a TextStore
. This class is used
as an abstract interface for the data that must be kept track of by a TextStore
about
a Marker
when it is added to that TextStore
.
This class should only be of interest to those implementing a new TextStore
subclass.
MarkerMortuary < MARKER > [public]
MarkerMortuary is a template used to help delete markers from a TextStore, in a situation where the markers might still be refered to someplace.
A typical use would be to accomulate them for deletion - marking them as uninteresting. Then calling FinalizeMarkerDeletions () when there are certain to be no more outstanding pointers.
NB: We require that the markers added to a MarkerMortuary all share a common TextStore.
Member Details | |||
---|---|---|---|
Since Led can remove large numbers of markers at a time much faster than it can remove a single one, we have this special interface to accumulate markers to be deleted, and delete them all at once. This doesn't ususally NEED to be used. But it sometimes does Need to be used to avoid the case where a marker is kept in a list (say back on the stack in some caller for example), and we decide it must be deleted, but we don't know for sure if it will be accessed from that stack-based list again. After a call to this routine, the marker is effectively dead and removed from OUR marker list, but it is not 'delete' d. And the call to RemoveMarker is postponed til 'MarkerMortuaryNB: It is illegal to accumulate a marker for deletion twice (detected error). And greatly discouraged using it afterwards.
|
Call anytime, but preferably after we've finished doing a bunch of marker deletions.
See
|
Mostly used for assertions. Checks all accumulated markers have been finalized.
|
Like |
MarkerOwner [public]
Object which owns Markers. You register this with a TextStore
. And then when those markers are changed
(contents within the marker), you are updated via the MarkerOwner::AboutToUpdateText
and MarkerOwner::DidUpdateText
.
methods.
Member Details |
---|
This method is called by a TextStore when text is being updated for all registered MarkerOwners
(see |
This method is called by a |
This method is called by a |
This is a trivial wrapper on |
Returns the currently associated TextStore for this |
MarkerOwner::HookData [public]
An implementation detail of implementing a TextStore
. This class is used
as an abstract interface for the data that must be kept track of by a TextStore
about
a Marker
when it is added to that TextStore
.
This class should only be of interest to those implementing a new TextStore
subclass.
MarkerOwner::UpdateInfo [public]
A packaging up of information about an update, for MarkerOwner::AboutToUpdateText
or
MarkerOwner::DidUpdateText
methods.
TempMarker [public]
MarkerOwner
A trivial helper class which can be used in a 'stack based' fasion to keep temporary track of a region of text, without all the bookkeeping of having to add/remove the marker and marker owner, etc.
TemporaryMarkerSlideDown < MARKER > [public]
A simple helper class to take a vector of markers, and slide them one way or the other, and then restore them. This can occasionally be helpful when you are about to do some operation which you don't want to affect these markers - you can slide them out of the way - so they don't get updated - and then slide them back.
bool Contains (const Marker& containedMarker, const Marker& containerMarker)
Four overloads. Basically this tests if the first marker is contained in the second.
Note that Led doesn't treat the beginning and ending of a marker symetrically. It is considered legitimate containment if the marker start positions are equal, but not if the marker end positions are equal