227 lines
7.1 KiB
C++
227 lines
7.1 KiB
C++
/*
|
|
* @doc INTERNAL
|
|
*
|
|
* @module _RUNPTR.H -- Text run and run pointer class defintion |
|
|
*
|
|
* Original Author: <nl>
|
|
* Christian Fortini
|
|
*
|
|
* History: <nl>
|
|
* 6/25/95 alexgo Commenting and Cleanup
|
|
*
|
|
* Copyright (c) 1995-1997 Microsoft Corporation. All rights reserved.
|
|
*/
|
|
|
|
#ifndef _RUNPTR_H
|
|
#define _RUNPTR_H
|
|
|
|
#include "_array.h"
|
|
#include "_doc.h"
|
|
|
|
typedef CArray<CTxtRun> CRunArray;
|
|
|
|
/*
|
|
* CRunPtrBase
|
|
*
|
|
* @class Base run pointer functionality. Keeps a position within an array
|
|
* of text runs.
|
|
*
|
|
* @devnote Run pointers go through three different possible states :
|
|
*
|
|
* NULL: there is no data and no array (frequently a startup condition) <nl>
|
|
* <mf CRunPtrBase::SetRunArray> will transition from this state to
|
|
* the Empty state. It is typically up to the derived class to
|
|
* define when that method should be called. IsValid() fails. <nl>
|
|
*
|
|
* <md CRunPtrBase::_pRuns> == NULL <nl>
|
|
* <md CRunPtrBase::_iRun> == 0 <nl>
|
|
* <md CRunPtrBase::_ich> == 0 <nl>
|
|
*
|
|
* Empty: an array class exists, but there is no data (can happen if all
|
|
* of the elements in the array are deleted). IsValid() fails.<nl>
|
|
* <md CRunPtrBase::_pRuns> != NULL <nl>
|
|
* <md CRunPtrBase::_iRun> == 0 <nl>
|
|
* <md CRunPtrBase::_ich> <gt>= 0 <nl>
|
|
* <md CRunPtrBase::_pRuns-<gt>Count()> == 0 <nl>
|
|
*
|
|
* Normal: the array class exists and has data; IsValid() succeeds and
|
|
* <md CRunPtrBase::_pRuns-<gt>Elem[] is defined <nl>
|
|
* <md CRunPtrBase::_pRuns> != NULL <nl>
|
|
* <md CRunPtrBase::_iRun> >= 0 <nl>
|
|
* <md CRunPtrBase::_ich> >= 0 <nl>
|
|
* <md _pRuns>-<gt>Count() > 0 <nl>
|
|
*
|
|
* Note that in order to support the empty and normal states, the actual
|
|
* array element at <md CRunPtrBase::_iRun> must be explicitly fetched in
|
|
* any method that may need it.
|
|
*
|
|
* Currently, there is no way to transition to the NULL state from any of
|
|
* the other states. If we needed to, we could support that by explicitly
|
|
* fetching the array from the document on demand.
|
|
*
|
|
* Note that only <md CRunPtrBase::_iRun> is kept. We could also keep
|
|
* a pointer to the actual run (i.e. _pRun). Earlier versions of this
|
|
* engine did in fact do this. I've opted to not do this for several
|
|
* reasons: <nl>
|
|
* 1. If IsValid(), _pRun is *always* available by calling Elem(_iRun).
|
|
* Therefore, there is nominally no need to keep both _iRun and _pRun.<nl>
|
|
* 2. Run pointers are typically used to either just move around
|
|
* and then fetch data or move and fetch data every time (like during
|
|
* a measuring loop). In the former case, there is no need to always
|
|
* bind _pRun; you can just do it on demand. In the latter case, the
|
|
* two models are equivalent.
|
|
*/
|
|
|
|
class CRunPtrBase
|
|
{
|
|
friend class CDisplayML;
|
|
friend class CDisplaySL;
|
|
|
|
//@access Public methods
|
|
public:
|
|
|
|
#ifdef DEBUG
|
|
BOOL Invariant() const; //@cmember Invariant tests
|
|
void ValidatePtr(void *pRun) const; //@cmember Validate <p pRun>
|
|
LONG CalcTextLength() const; //@cmember Get total cch in runs
|
|
#define VALIDATE_PTR(pRun) ValidatePtr(pRun)
|
|
|
|
#else
|
|
#define VALIDATE_PTR(pRun)
|
|
#endif // DEBUG
|
|
|
|
CRunPtrBase(CRunArray *pRuns); //@cmember Constructor
|
|
CRunPtrBase(CRunPtrBase& rp); //@cmember Constructor
|
|
|
|
// Run Control
|
|
void SetRunArray(CRunArray *pRuns) //@cmember Set run array for this
|
|
{ // run ptr
|
|
_pRuns = pRuns;
|
|
}
|
|
BOOL SetRun(LONG iRun, LONG ich); //@cmember Set this runptr to run
|
|
// <p iRun> & char offset <p ich>
|
|
BOOL NextRun(); //@cmember Advance to next run
|
|
BOOL PrevRun(); //@cmember Go back to prev run
|
|
BOOL ChgRun(LONG cRun) //@cmember Move <p cRun> runs
|
|
{ // returning TRUE if successful
|
|
return SetRun(_iRun + cRun, 0);
|
|
}
|
|
//@cmember Count <p cRun> runs
|
|
LONG CountRuns(LONG &cRun, // returning cch counted and
|
|
LONG cchMax, // updating <p cRun>
|
|
LONG cp,
|
|
LONG cchText) const;
|
|
//@cmember Find run range limits
|
|
void FindRun (LONG *pcpMin,
|
|
LONG *pcpMost, LONG cpMin, LONG cch, LONG cchText) const;
|
|
|
|
CTxtRun * GetRun(LONG cRun) const; //@cmember Retrieve run element at
|
|
// offset <p cRun> from this run
|
|
LONG Count() const //@cmember Get count of runs
|
|
{
|
|
return _pRuns->Count();
|
|
}
|
|
BOOL SameRuns(CRunPtrBase *prp) //@cmember Return TRUE iff same runs
|
|
{
|
|
return _pRuns == prp->_pRuns;
|
|
}
|
|
BOOL SameRun(CRunPtrBase *prp)
|
|
{
|
|
return SameRuns(prp) && _iRun == prp->_iRun;
|
|
}
|
|
|
|
// Character position control
|
|
LONG BindToCp(LONG cp); //@cmember Set cp for this run ptr = <p cp>
|
|
LONG CalculateCp() const;//@cmember Add _cch's up to _iRun, _ich
|
|
LONG AdvanceCp(LONG cch);//@cmember Advance cp by <p cch> chars
|
|
|
|
void AdjustBackward(); //@cmember If on the edge of two runs,
|
|
// adjust to end of left (previous) run
|
|
void AdjustForward(); //@cmember If at the edge of two runs,
|
|
// adjust to start of right (next) run
|
|
LONG GetIch() const //@cmember Return <md CRunPtrBase::_ich>
|
|
{Assert(IsValid()); return _ich;}
|
|
LONG GetCchLeft() const; //@cmember Return GetRun(0)->_cch - GetIch()
|
|
BOOL IsValid() const; //@cmember Return FALSE if run ptr is in
|
|
// empty or NULL states. TRUE otherwise
|
|
void SetToNull(); //@cmember Clears data from run pointer
|
|
|
|
//@access Protected Data
|
|
protected:
|
|
CRunArray * _pRuns; //@cmember Pointer to CTxtRun array
|
|
LONG _iRun; //@cmember Index of current run in array
|
|
LONG _ich; //@cmember Char offset inside current run
|
|
};
|
|
|
|
|
|
/*
|
|
* CRunPtr (template)
|
|
*
|
|
* @class a template over CRunPtrBase allowing for type-safe versions of
|
|
* run pointers
|
|
*
|
|
* @tcarg class | CElem | run array class to be used
|
|
*
|
|
* @base public | CRunPtrBase
|
|
*/
|
|
template <class CElem>
|
|
class CRunPtr : public CRunPtrBase
|
|
{
|
|
public:
|
|
CRunPtr (void) //@cmember Constructor
|
|
: CRunPtrBase (0) {}
|
|
CRunPtr (CRunArray *pRuns) //@cmember Constructor
|
|
: CRunPtrBase (pRuns) {}
|
|
CRunPtr (CRunPtrBase& rp) //@cmember Constructor
|
|
: CRunPtrBase (rp) {}
|
|
|
|
// Array management
|
|
|
|
CElem * Add (LONG cRun, LONG *pielIns) //@cmember Add <p cRun>
|
|
{ // elements at end of array
|
|
return (CElem *)_pRuns->Add(cRun, pielIns);
|
|
}
|
|
|
|
CElem * Insert (LONG cRun) //@cmember Insert <p cRun>
|
|
{ // elements at current pos
|
|
return (CElem *)_pRuns->Insert(_iRun, cRun);
|
|
}
|
|
|
|
void Remove (LONG cRun) //@cmember Remove <p cRun>
|
|
{ // elements at current pos
|
|
_pRuns->Remove (_iRun, cRun);
|
|
}
|
|
//@cmember Replace <p cRun> elements
|
|
// at current position with those
|
|
// from <p parRun>
|
|
BOOL Replace (LONG cRun, CArrayBase *parRun)
|
|
{
|
|
return _pRuns->Replace(_iRun, cRun, parRun);
|
|
}
|
|
|
|
CElem * Elem(LONG iRun) const //@cmember Get ptr to run <p iRun>
|
|
{
|
|
return (CElem *)_pRuns->Elem(iRun);
|
|
}
|
|
|
|
CElem * GetRun(LONG cRun) const //@cmember Get ptr <p cRun> runs
|
|
{ // away from current run
|
|
return Elem(_iRun + cRun);
|
|
}
|
|
|
|
void IncPtr(CElem *&pRun) const //@cmember Increment ptr <p pRun>
|
|
{
|
|
VALIDATE_PTR(pRun); // Allow invalid ptr after ++ for
|
|
pRun++; // for loops
|
|
}
|
|
|
|
CElem * GetPtr(CElem *pRun, LONG cRun) const//@cmember Get ptr <p cRun>
|
|
{ // runs away from ptr <p pRun>
|
|
VALIDATE_PTR(pRun + cRun);
|
|
return pRun + cRun;
|
|
}
|
|
};
|
|
|
|
#endif
|
|
|