📄 range.cpp
字号:
*/
LONG CTxtRange::CheckChange(
LONG cpSave) //@parm Original _cp for this range
{
LONG cchAdj = GetAdjustedTextLength();
LONG cchSave = _cch;
if(_fExtend) // Wants to be nondegenerate
{ // and maybe it is
LONG cp = GetCp();
_cch = cp - (cpSave - cchSave);
CheckIfSelHasEOP(cpSave, cchSave);
}
else
{
_cch = 0; // Insertion point
_fSelHasEOP = FALSE; // Selection doesn't contain
_fSelHasCell = FALSE; // any char, let alone a CR
} // or table cell
if(!_cch && GetCp() > cchAdj) // If still IP and active end
CRchTxtPtr::SetCp(cchAdj); // follows nondeletable EOP,
// backspace over that EOP
if(cpSave != GetCp() || cchSave != _cch)
{
Update_iFormat(-1);
if(_fSel)
GetPed()->GetCallMgr()->SetSelectionChanged();
_TEST_INVARIANT_
}
LONG cch = GetCp() - cpSave;
_fMoveBack = cch < 0;
return cch;
}
/*
* CTxtRange::CheckIfSelHasEOP(cpSave, cchSave)
*
* @mfunc
* Maintains _fSelHasEOP = TRUE iff selection contains one or more EOPs.
* When cpSave = -1, calculates _fSelHasEOP unconditionally and cchSave
* is ignored (it's only used for conditional execution). Else _fSelHasEOP
* is only calculated for cases that may change it, i.e., it's assumed
* be up to date before the change.
*
* @rdesc
* TRUE iff _fSel and _cch
*
* @devnote
* Call after updating range _cch
*/
BOOL CTxtRange::CheckIfSelHasEOP(
LONG cpSave, //@parm Previous active end cp or -1
LONG cchSave) //@parm Previous signed length if cpSave != -1
{
// _fSelHasEOP only maintained for the selection
if(!_fSel)
return FALSE;
if(!_cch)
{
_fSelHasEOP = FALSE; // Selection doesn't contain
_fSelHasCell = FALSE; // any char, let alone CR
return FALSE;
}
LONG cpMin, cpMost;
GetRange(cpMin, cpMost);
if(cpSave != -1) // Selection may have changed
{ // Set up to bypass text scan if
LONG cpMinPrev, cpMostPrev; // selection grew and _fSelHasEOP
// is already TRUE or got smaller
cpMinPrev = cpMostPrev = cpSave;// and _fSelHasEOP is FALSE.
if(cchSave > 0) // Calculate previous cpMin
cpMinPrev -= cchSave; // and cpMost
else
cpMostPrev -= cchSave;
// Note: _fSelHasCell shouldn't change while in a table, since
// Update() should always expand to a cell once _fSelHasCell has
// been deteted.
if (!_fSelHasEOP && cpMin >= cpMinPrev && cpMost <= cpMostPrev ||
_fSelHasEOP && cpMin <= cpMinPrev && cpMost >= cpMostPrev)
{
return TRUE; // _fSelHasEOP can't change
}
}
LONG FEOP_Results;
CTxtPtr tp(_rpTX); // Scan range for an EOP
tp.SetCp(cpMin);
tp.FindEOP(cpMost - cpMin, &FEOP_Results);
_fSelHasCell = (FEOP_Results & FEOP_CELL) != 0;
_fSelHasEOP = (FEOP_Results & FEOP_EOP) != 0;
return TRUE;
}
/*
* CTxtRange::GetRange(&cpMin, &cpMost)
*
* @mfunc
* set cpMin = this range cpMin
* set cpMost = this range cpMost
* return cpMost - cpMin, i.e. abs(_cch)
*
* @rdesc
* abs(_cch)
*/
LONG CTxtRange::GetRange (
LONG& cpMin, // @parm Pass-by-ref cpMin
LONG& cpMost) const // @parm Pass-by-ref cpMost
{
TRACEBEGIN(TRCSUBSYSRANG, TRCSCOPEINTERN, "CTxtRange::GetRange");
LONG cch = _cch;
if(cch >= 0)
{
cpMost = GetCp();
cpMin = cpMost - cch;
}
else
{
cch = -cch;
cpMin = GetCp();
cpMost = cpMin + cch;
}
return cch;
}
/*
* CTxtRange::GetCpMin()
*
* @mfunc
* return this range's cpMin
*
* @rdesc
* cpMin
*
* @devnote
* If you need cpMost and/or cpMost - cpMin, GetRange() is faster
*/
LONG CTxtRange::GetCpMin() const
{
TRACEBEGIN(TRCSUBSYSRANG, TRCSCOPEINTERN, "CTxtRange::GetCpMin");
LONG cp = GetCp();
return min(cp, cp - _cch);
}
/*
* CTxtRange::GetCpMost()
*
* @mfunc
* return this range's cpMost
*
* @rdesc
* cpMost
*
* @devnote
* If you need cpMin and/or cpMost - cpMin, GetRange() is faster
*/
LONG CTxtRange::GetCpMost() const
{
TRACEBEGIN(TRCSUBSYSRANG, TRCSCOPEINTERN, "CTxtRange::GetCpMost");
LONG cp = GetCp();
return max(cp, cp - _cch);
}
/*
* CTxtRange::Update(fScrollIntoView)
*
* @mfunc
* Virtual stub routine overruled by CTxtSelection::Update() when this
* text range is a text selection. The purpose is to update the screen
* display of the caret or selection to correspond to changed cp's.
*
* @rdesc
* TRUE
*/
BOOL CTxtRange::Update (
BOOL fScrollIntoView) //@parm TRUE if should scroll caret into view
{
TRACEBEGIN(TRCSUBSYSRANG, TRCSCOPEINTERN, "CTxtRange::Update");
return TRUE; // Simple range has no selection colors or
} // caret, so just return TRUE
/*
* CTxtRange::SetCp(cp)
*
* @mfunc
* Set active end of this range to cp. Leave other end where it is or
* collapse range depending on _fExtend (see CheckChange()).
*
* @rdesc
* cp at new active end (may differ from cp, since cp may be invalid).
*/
DWORD CTxtRange::SetCp(
DWORD cp) // @parm new cp for active end of this range
{
TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CTxtRange::SetCp");
LONG cpSave = GetCp();
CRchTxtPtr::SetCp(cp);
CheckChange(cpSave); // NB: this changes _cp if after
return GetCp(); // final CR and _cch = 0
}
/*
* CTxtRange::Set (cp, cch)
*
* @mfunc
* Set this range's active-end cp and signed cch
*/
BOOL CTxtRange::Set (
LONG cp, // @parm Desired active end cp
LONG cch) // @parm Desired signed count of chars
{
TRACEBEGIN(TRCSUBSYSRANG, TRCSCOPEINTERN, "CTxtRange::Set");
BOOL bRet = FALSE;
LONG cchSave = _cch; // Save entry _cp, _cch for change check
LONG cchText = GetAdjustedTextLength();
LONG cpSave = GetCp();
LONG cpOther = cp - cch; // Desired "other" end
ValidateCp(cp); // Be absolutely sure to validate
ValidateCp(cpOther); // both ends
if(cp == cpOther && cp > cchText) // IP cannot follow undeletable
cp = cpOther = cchText; // EOP at end of story
CRchTxtPtr::Advance(cp - GetCp());
AssertSz(cp == GetCp(),
"CTxtRange::Set: inconsistent cp");
_cch = cp - cpOther; // Validated _cch value
CheckIfSelHasEOP(cpSave, cchSave); // Maintain _fSelHasEOP in
// outline mode
if(cpSave != GetCp() || cchSave != _cch)
{
if(_fSel)
GetPed()->GetCallMgr()->SetSelectionChanged();
Update_iFormat(-1);
bRet = TRUE;
}
_fMoveBack = GetCp() < cpSave;
_TEST_INVARIANT_
return bRet;
}
/*
* CTxtRange::Advance(cch)
*
* @mfunc
* Advance active end of range by cch.
* Other end stays put iff _fExtend
*
* @rdesc
* cch actually moved
*/
LONG CTxtRange::Advance (
LONG cch) // @parm Signed char count to move active end
{
TRACEBEGIN(TRCSUBSYSRANG, TRCSCOPEINTERN, "CTxtRange::Advance");
LONG cpSave = GetCp(); // Save entry _cp for CheckChange()
CRchTxtPtr::Advance(cch);
return CheckChange(cpSave);
}
/*
* CTxtRange::AdvanceCRLF()
*
* @mfunc
* Advance active end of range one char, treating CRLF as a single char.
* Other end stays put iff _fExtend is nonzero.
*
* @rdesc
* cch actually moved
*/
LONG CTxtRange::AdvanceCRLF()
{
TRACEBEGIN(TRCSUBSYSRANG, TRCSCOPEINTERN, "CTxtRange::AdvanceCRLF");
LONG cpSave = GetCp(); // Save entry _cp for CheckChange()
CRchTxtPtr::AdvanceCRLF();
return CheckChange(cpSave);
}
/*
* CTxtRange::BackupCRLF()
*
* @mfunc
* Backup active end of range one char, treating CRLF as a single char.
* Other end stays put iff _fExtend
*
* @rdesc
* cch actually moved
*/
LONG CTxtRange::BackupCRLF()
{
TRACEBEGIN(TRCSUBSYSRANG, TRCSCOPEINTERN, "CTxtRange::BackupCRLF");
LONG cpSave = GetCp(); // Save entry _cp for CheckChange()
CRchTxtPtr::BackupCRLF();
return CheckChange(cpSave);
}
/*
* CTxtRange::FindWordBreak(action)
*
* @mfunc
* Move active end as determined by plain-text FindWordBreak().
* Other end stays put iff _fExtend
*
* @rdesc
* cch actually moved
*/
LONG CTxtRange::FindWordBreak (
INT action) // @parm action defined by CTxtPtr::FindWordBreak()
{
TRACEBEGIN(TRCSUBSYSRANG, TRCSCOPEINTERN, "CTxtPtr::FindWordBreak");
LONG cpSave = GetCp(); // Save entry _cp for CheckChange()
CRchTxtPtr::FindWordBreak(action);
return CheckChange(cpSave);
}
/*
* CTxtRange::FlipRange()
*
* @mfunc
* Flip active and non active ends
*/
void CTxtRange::FlipRange()
{
TRACEBEGIN(TRCSUBSYSRANG, TRCSCOPEINTERN, "CTxtRange::FlipRange");
_TEST_INVARIANT_
CRchTxtPtr::Advance(-_cch);
_cch = -_cch;
}
/*
* CTxtRange::CleanseAndReplaceRange(cch, *pch, fTestLimit, publdr)
*
* @mfunc
* Cleanse the string pch (replace CRLFs by CRs, etc.) and substitute
* the resulting string for the text in this range using the CCharFormat
* _iFormat and updating other text runs as needed. For single-line
* controls, truncate on the first EOP and substitute the truncated
* string. Also truncate if string would overflow the max text length.
*
* @rdesc
* Count of new characters added
*
* @devnote
* If we know somehow that pch comes from RichEdit, we shouldn't have to
* cleanse it. This could be tied into delayed IDataObject rendering.
* This code is similar to that in CLightDTEngine::ReadPlainText(), but
* deals with a single string instead of a series of stream buffers.
*/
LONG CTxtRange::CleanseAndReplaceRange (
LONG cch, // @parm Length of replacement text
const TCHAR * pch, // @parm Replacement text
BOOL fTestLimit, // @parm whether we need to do a limit test
IUndoBuilder * publdr) // @parm UndoBuilder to receive antievents
{
TRACEBEGIN(TRCSUBSYSRANG, TRCSCOPEINTERN, "CTxtRange::CleanseAndReplaceRange");
CTxtEdit * ped = GetPed();
LONG cchLen = CalcTextLenNotInRange();
DWORD cchMax = ped->TxGetMaxLength();
LONG cchT;
CTempWcharBuf twcb;
TCHAR * pchT;
if(!pch) // No text so no cleansing
cch = 0;
else if(!ped->TxGetMultiLine()) // Single-line control
{
if(cch < 0) // Calculate string length
cch = tomForward; // while looking for EOP
// Truncate at 1st EOP to be
for(cchT = 0; cchT < cch && // compatible with RE 1.0
*pch && !IsASCIIEOP(*pch); // and user's SLE and to
cchT++, pch++) // give consistent display
; // behavior
cch = cchT;
pch -= cchT; // Restore pch
}
else // Multiline control
{
if(cch < 0) // Calculate length
cch = wcslen(pch);
if(!GetPed()->Get10Mode() && cch) // Cleanse if not RE 1.0
{ // and some new chars
pchT = twcb.GetBuf(cch);
if (NULL == pchT)
{
// Could not allocate buffer so give up with no update.
return 0;
}
cch = Cleanse(pchT, pch, cch);
pch = pchT;
}
}
if(fTestLimit && cch && (DWORD)(cch + cchLen) > cchMax) // New plus old count exceeds
{ // max allowed, so truncate
cch = cchMax - cchLen; // down to what fits
cch = max(cch, 0); // Keep it positive
ped->GetCallMgr()->SetMaxText(); // Tell anyone who cares
}
LONG cchUpdate = ReplaceRange(cch, pch, publdr, SELRR_REMEMBERRANGE);
return cchUpdate;
}
/*
* CTxtRange::ReplaceRange(cchNew, *pch, publdr. selaemode)
*
* @mfunc
* Replace the text in this range by pch using CCharFormat _iFormat
* and updating other text runs as needed.
*
* @rdesc
* Count of new characters added
*
* @devnote
* moves this text pointer to end of replaced text and
* may move text block and formatting arrays
*/
LONG CTxtRange::ReplaceRange (
LONG cchNew, // @parm Length of replacement text
TCHAR const * pch, // @parm Replacement text
IUndoBuilder * publdr, // @parm UndoBuilder to receive antievents
SELRR selaemode) // @parm Controls how selection antievents
// are to be generated.
{
TRACEBEGIN(TRCSUBSYSRANG, TRCSCOPEINTERN, "CTxtRange::ReplaceRange");
LONG lRet;
LONG iFormat = _iFormat;
BOOL fReleaseFormat = FALSE;
ICharFormatCache * pcf;
_TEST_INVARIANT_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -