C Programming Column
by Al Stevens
Listing One
// ---- Selection.h
#ifndef SELECTION_H
#define SELECTION_H
namespace DDJCProgrammingColumnSelection    {
//////////////////////////////////////////////////////////////////////
// P is a user-defined iterator type that indexes the item 
//     (char, e.g.) in the view
// P must support assignment and operator<
// P must support p(0) to initialize a P object to a null value 
//   which is the lowest relational value that a P object can have
// V is the view class, which must provide this function:
//   void InvertDisplayItems(P begin, P end);
//
template <class P, class V>
class Selection {
    V& view;        // reference to the document's view
    P anchor;       // the first event of a marked selection
    P terminal;     // the last event of a marked selection
    P saveanchor;   // for saving first event of marked selection
    P saveterminal; // for saving last event of marked selection
    bool marking;   // true when marking with mouse or keyboard
public:
    Selection(V& rV);
    bool IsSelectionMarked() const

       { return !(anchor == terminal); }
    bool IsMarking() const
        { return marking; }
    bool IsItemInSelection(P pos);
    void RestoreSelection();
    void SaveSelection();
    void GetSelectionMarkers(P& begin, P& end) const;
    void ExtendSelection(P pos);
    void UnmarkSelection();
    void SetMarking(P pos);
    void StopMarking();
};
template <class P, class V>
Selection<P, V>::Selection(V& rV) : 
    view(rV), anchor(0), terminal(0), marking(false)
{
}
template <class P, class V>
bool Selection<P, V>::IsItemInSelection(P pos)
{
    P begin, end;
    GetSelectionMarkers(begin, end);
    return !(pos < begin) && (pos < end);
}
template <class P, class V>
void Selection<P,V>::SaveSelection()
{
    saveanchor = anchor;
    saveterminal = terminal;
}
template <class P, class V>
void Selection<P,V>::RestoreSelection()
{
    anchor = saveanchor;
    terminal = saveterminal;
    P begin, end;
    GetSelectionMarkers(begin, end);
    view.InvertDisplayItems(begin, end);
}
template <class P, class V>
void Selection<P,V>::GetSelectionMarkers(P& begin, P& end) const
{
    begin = anchor;
    end = terminal;
    if (end < begin)    {
        P temp = begin;
        begin = end;
        end = temp;
    }
}
template <class P, class V>
void Selection<P,V>::ExtendSelection(P pos)
{
    if (pos < terminal) {
        view.InvertDisplayItems(pos, terminal);
    }
    else
        view.InvertDisplayItems(terminal, pos);
    terminal = pos;
}
template <class P, class V>
void Selection<P,V>::UnmarkSelection()
{
    if (IsSelectionMarked())    {
        P begin, end;
        GetSelectionMarkers(begin, end);
        view.InvertDisplayItems(begin, end);
        marking = false;
        anchor = terminal = 0;
    }
}
template <class P, class V>
void Selection<P,V>::SetMarking(P pos)
{
    if (!marking)   {
        UnmarkSelection();
        marking = true;
        terminal = anchor = pos;
    }
}
template <class P, class V>
void Selection<P,V>::StopMarking()
{
    marking = false;
}
}       // namespace DDJCProgrammingColumnSelection
#endif  // SELECTION_H

2


