Led 3.0 Class Library Documentation

Module Marker

Classes and Global Functions Index

Module Description:

Marker positions are measured in units of Led_tChars - 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.

Class: 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.

Class: 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

Marker::AboutToUpdateText [public]

void Marker::AboutToUpdateText (const UpdateInfo& /*updateInfo*/)

Notification callback which is called by a TextStore when the text is updated. You override this if you want todo something special when the text marked by this particular marker is changed. You can throw from this method to prevent the update from actually taking place.

Marker::DidUpdateText [public]

void Marker::DidUpdateText (const UpdateInfo& /*updateInfo*/) throw ()

Notification callback which is called by a TextStore after the text is updated. You override this if you want todo something special when the text marked by this particular marker is changed. You cannot throw from this routine. Use Marker::AboutToUpdateText to preflight, and assure any DidUpdateText method calls will work without a hitch.

Marker::GetEnd [public]

size_t Marker::GetEnd () const

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 TextStore.

Marker::GetLength [public]

size_t Marker::GetLength () const

Return the length - in Led_tChars - of the marker span. This value can be zero. But if it ever goes to zero, Led will never re-inflate the marker. You must reset its bounds manually via Marker::SetRange ().

Marker::GetOwner [public]

MarkerOwner* Marker::GetOwner () const

Return the current marker owner. Unlike most Marker methods, this can be called when the marker hasn't yet been added to a TextStore. It just returns NULL in that case. Note, it can return NULL anyhow, as that is a valid value to specify in TextStore::AddMarker ().

Marker::GetRange [public]

void Marker::GetRange (size_t* start, size_t* end) const

Return the start and end position of the marker. You must set its bounds via Marker::SetRange ().

Marker::GetStart [public]

size_t Marker::GetStart () const

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 TextStore.

Class: 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.

Class: 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

MarkerMortuary < MARKER > ::AccumulateMarkerForDeletion [public]

template < class MARKER >

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 'MarkerMortuary::FinalizeMarkerDeletions ().

NB: It is illegal to accumulate a marker for deletion twice (detected error). And greatly discouraged using it afterwards.

MarkerMortuary < MARKER > ::FinalizeMarkerDeletions [public]

template < class MARKER >

Call anytime, but preferably after we've finished doing a bunch of marker deletions. See MarkerMortuary::AccumulateMarkerForDeletion for more information.

MarkerMortuary < MARKER > ::IsEmpty [public]

template < class MARKER >

Mostly used for assertions. Checks all accumulated markers have been finalized.

MarkerMortuary < MARKER > ::SafeAccumulateMarkerForDeletion [public]

template < class MARKER >

Like MarkerMortuary::AccumulateMarkerForDeletion, but its OK to add a marker more than once.

Class: 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

MarkerOwner::AboutToUpdateText [public]

void MarkerOwner::AboutToUpdateText (const UpdateInfo& /*updateInfo*/)

This method is called by a TextStore when text is being updated for all registered MarkerOwners (see TextStore::AddMarkerOwner). You can throw an exception to prevent text from being updated.

MarkerOwner::DidUpdateText [public]

void MarkerOwner::DidUpdateText (const UpdateInfo& /*updateInfo*/) throw ()

This method is called by a TextStore after a text update has taken place. You can use this to update some appropriate data structures based on the change. NB: an exception cannot be raised by this method, or any overrides of it.

MarkerOwner::EarlyDidUpdateText [public]

void MarkerOwner::EarlyDidUpdateText (const UpdateInfo& /*updateInfo*/) throw ()

This method is called by a TextStore justafter a text update has taken place (and before the DidUpdateText calls take place). You can use this call just to set private data in your objects - but make no calls out (til the DidUpdateText). This is just so that in some rare cases - you can tell if your getting a callback between your AboutToUpdate() call and your DidUpdateText () call - so you can tell if the text is truely updated yet.

MarkerOwner::GetTextStore [public]

TextStore& MarkerOwner::GetTextStore () const

This is a trivial wrapper on MarkerOwner::PeekAtTextStore which asserts that PeekAtTextStore () didn't return NULL, and then returns its result dereferences. Use this for clarity sake when you are sure the markerowner must have an associated TextStore.

MarkerOwner::PeekAtTextStore [public]

virtual TextStore* PeekAtTextStore () const = 0;

Returns the currently associated TextStore for this MarkerOwner. This method can return NULL only if owns no markers!

Class: 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.

Class: MarkerOwner::UpdateInfo [public]


A packaging up of information about an update, for MarkerOwner::AboutToUpdateText or MarkerOwner::DidUpdateText methods.

Class: TempMarker [public]

Base Classes: 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.

Class: 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.

Contains [public]

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

Return to Led Page Return to Led ClassLib Documentation Index Return to Led Reference Manual Index
Last Updated 2001-10-20