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