📄 tomrange.cpp
字号:
* story and an index of -1 refers to the last Unit in the story.
*
* @rdesc
* HRESULT = (invalid index) ? E_INVALIDARG :
* (Unit not supported) ? E_NOTIMPL :
* (change) ? NOERROR : S_FALSE
*
* @devnote
* Currently moves out <p Index> <p Unit>s from the start of the story.
* Might be faster to move from current position, but would need to know
* the current index.
*/
STDMETHODIMP CTxtRange::SetIndex (
long Unit, //@parm Unit to index
long Index, //@parm Index value to use
long Extend) //@parm if nonzero, set range to <p Unit>
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::SetIndex");
if(IsZombie())
return CO_E_RELEASED;
if(!Index)
return E_INVALIDARG;
CCallMgr callmgr(GetPed());
LONG cchText = GetTextLength();
CTxtRange rg(GetPed()); // Create IP at cp = 0
if(Index > 0) // Index going forward First
Index--; // Unit is at start of story
else // Index from end of story
rg.Set(cchText, cchText); // selecting whole story
LONG cUnit;
HRESULT hr = rg.Mover(Unit, Index, &cUnit, MOVE_END);
if(FAILED(hr))
return hr;
if(Index != cUnit || rg.GetCp() == cchText) // No such index in story
return E_INVALIDARG;
rg._cch = 0; // Collapse at active end
// namely at cpMost
LONG cpMin, cpMost;
if(Extend) // Select Index'th Unit
rg.Expander(Unit, TRUE, NULL, &cpMin, &cpMost);
if(Set(rg.GetCp(), rg._cch)) // Something changed
{
Update(TRUE);
return NOERROR;
}
return S_FALSE;
}
/*
* CTxtRange::SetPara (pPara)
*
* @mfunc
* Set this range's paragraph attributes to those given by <p pPara>
* This method is a "Paragraph format painter".
*
* @rdesc
* HRESULT = (!pPara) ? E_INVALIDARG :
* (if success) ? NOERROR :
* (protected) ? E_ACCESSDENIED : E_OUTOFMEMORY
*/
STDMETHODIMP CTxtRange::SetPara (
ITextPara * pPara) //@parm Paragraph object with desired paragraph
{ // formatting
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::SetPara");
if(!pPara)
return E_INVALIDARG;
if(IsZombie())
return CO_E_RELEASED;
ITextPara * pParaApply = (ITextPara *) new CTxtPara(this);
if(!pParaApply)
return E_OUTOFMEMORY;
HRESULT
hr = (*(LONG *)pParaApply == *(LONG *)pPara) // If same vtable, use
? ParaFormatSetter(&((CTxtPara *)pPara)->_PF) // its _PF; else copy
: pParaApply->SetDuplicate(pPara); // to clone and apply
pParaApply->Release();
return hr;
}
/*
* CTxtRange::SetPoint (x, y, Extend)
*
* @mfunc
* Select text at or up through (depending on <p Extend>) the point
* (<p x>, <p y>).
*
* @rdesc
* HRESULT = NOERROR
*/
STDMETHODIMP CTxtRange::SetPoint (
long x, //@parm Horizontal coord of point to select
long y, //@parm Vertical coord of point to select
long Type, //@parm Defines the end to extend if Extend != 0.
long Extend) //@parm Whether to extend selection to point
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::SetPoint");
if(IsZombie())
return CO_E_RELEASED;
// Copy the ped locally once to save some indirections
CTxtEdit *ped = GetPed();
CCallMgr callmgr(ped);
if ((Type != tomStart) && (Type != tomEnd))
{
return E_INVALIDARG;
}
if (!ped->fInplaceActive())
{
// If we aren't inplace active we can't get a DC to
// calculate the cp.
return OLE_E_NOT_INPLACEACTIVE;
}
LONG cchForSel = 0;
POINT pt = {x, y};
LONG cpSel;
LONG cpMin;
LONG cpMost;
// Convert x, y from screen coordinates to client coordinates
if (!ped->TxScreenToClient(&pt))
{
// It is unexpected for this to happen
return E_FAIL;
}
// Get the cp for the x,y
if ((cpSel =
ped->_pdp->CpFromPoint(pt, NULL, NULL, NULL, TRUE)) == -1)
{
// It is highly unexpected for this to fail.
return E_FAIL;
}
// Extend the range as requested.
if (Extend)
{
GetRange(cpMin, cpMost);
if (Type == tomStart)
{
cchForSel = cpSel - cpMin;
}
else
{
cchForSel = cpSel - cpMost;
}
}
// Update the range
Set(cpSel, cchForSel);
return S_OK;
}
/*
* CTxtRange::SetRange (cp1, cp2)
*
* @mfunc
* Set this range's ends
*
* @rdesc
* HRESULT = (cp1 > cp2) ? E_INVALIDARG
* : (if change) ? NOERROR : S_FALSE
*/
STDMETHODIMP CTxtRange::SetRange (
long cp1, //@parm Char position for Start end
long cp2) //@parm Char position for End end
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::SetRange");
if(IsZombie())
return CO_E_RELEASED;
CCallMgr callmgr(GetPed());
LONG cpMin, cpMost; // Save starting cp's for
// change determination
GetRange(cpMin, cpMost);
ValidateCp(cp1);
ValidateCp(cp2);
Set(cp2, cp2 - cp1);
GetRange(cp1, cp2); // See if either range end changed
if(cp1 != cpMin || cp2 != cpMost) // (independent of active end)
{
Update(TRUE); // Update selection
return NOERROR;
}
return S_FALSE;
}
/*
* CTxtRange::SetStart (cp)
*
* @mfunc
* Set this range's Start cp
*
* @rdesc
* HRESULT = (if change) ? NOERROR : S_FALSE
*
* @comm
* Note that setting this range's cpMin to <p cp> also sets cpMost to
* <p cp> if <p cp> > cpMost.
*/
STDMETHODIMP CTxtRange::SetStart (
long cp) //@parm Desired new Start cp
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::SetStart");
if(IsZombie())
return CO_E_RELEASED;
LONG cpMost = GetCpMost();
ValidateCp(cp);
return SetRange(max(cpMost, cp), cp); // Active end is Start
}
/*
* CTxtRange::SetText (bstr)
*
* @mfunc
* Replace text in this range by that given by <p bstr>. If <p bstr>
* is NULL, delete text in range.
*
* @rdesc
* HRESULT = (WriteAccessDenied) ? E_ACCESSDENIED :
* (if success) ? NOERROR : S_FALSE
*
*/
STDMETHODIMP CTxtRange::SetText (
BSTR bstr) //@parm Text to replace text in this range by
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::SetText");
if(IsZombie())
return CO_E_RELEASED;
CCallMgr callmgr(GetPed());
if( WriteAccessDenied())
return E_ACCESSDENIED;
LONG cchNew = bstr ? pSysStringLen(bstr) : 0;
_cch = Replacer(cchNew, (TCHAR *)bstr); // Select the new text
GetPed()->TxSetMaxToMaxText();
return _cch == cchNew ? NOERROR : S_FALSE;
}
/*
* CTxtRange::StartOf (Unit, Extend, pDelta)
*
* @mfunc
* Move this range end(s) to start of the first overlapping Unit in
* the range.
*
* @rdesc
* HRESULT = (if change) ? NOERROR :
* (if <p Unit> valid) ? S_FALSE : E_INVALIDARG
*/
STDMETHODIMP CTxtRange::StartOf (
long Unit, //@parm Unit to use
long Extend, //@parm If true, leave other end alone
long * pDelta) //@parm Out parm to get count of chars that
// StartOf moved
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::StartOf");
CCallMgr callmgr(GetPed());
LONG cpMin;
HRESULT hr = Expander (Unit, Extend, pDelta, &cpMin, NULL);
if(hr == NOERROR)
{
Update(TRUE); // Update selection
}
return hr;
}
//---------------------- CTxtRange ITextSelection stubs -----------------------------
// Dummy CTxtRange routines to simplify CTxtSelection inheritance hierarchy
STDMETHODIMP CTxtRange::GetFlags (long * pFlags)
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::GetFlags");
return E_NOTIMPL;
}
STDMETHODIMP CTxtRange::SetFlags (long Flags)
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::SetFlags");
return E_NOTIMPL;
}
STDMETHODIMP CTxtRange::GetType (long * pType)
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::GetType");
return E_NOTIMPL;
}
STDMETHODIMP CTxtRange::MoveLeft (long Unit, long Count, long Extend, long * pDelta)
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::Left");
return E_NOTIMPL;
}
STDMETHODIMP CTxtRange::MoveRight (long Unit, long Count, long Extend, long * pDelta)
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::Right");
return E_NOTIMPL;
}
STDMETHODIMP CTxtRange::MoveUp (long Unit, long Count, long Extend, long * pDelta)
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::Up");
return E_NOTIMPL;
}
STDMETHODIMP CTxtRange::MoveDown (long Unit, long Count, long Extend, long * pDelta)
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::Down");
return E_NOTIMPL;
}
STDMETHODIMP CTxtRange::HomeKey (long Unit, long Extend, long * pDelta)
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::HomeKey");
return E_NOTIMPL;
}
STDMETHODIMP CTxtRange::EndKey (long Unit, long Extend, long * pDelta)
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::EndKey");
return E_NOTIMPL;
}
STDMETHODIMP CTxtRange::TypeText (BSTR bstr)
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::TypeText");
return E_NOTIMPL;
}
//--------------------- ITextRange Private Helper Methods -----------------------------
/*
* @doc INTERNAL
*
* CTxtRange::Collapser (bStart)
*
* @mfunc
* Internal routine to collapse this range into a degenerate point
* either at the the start (<p bStart> is nonzero or the end
* (<p bStart> = 0)
*/
void CTxtRange::Collapser (
long bStart) //@parm Flag specifying end to collapse at
{
TRACEBEGIN(TRCSUBSYSRANG, TRCSCOPEEXTERN, "CTxtRange::Collapser");
if(bStart) // Collapse to Start
{
if(_cch > 0)
FlipRange(); // Move active end to range Start
}
else // Collapse to End
{
if(_cch < 0)
FlipRange(); // Move active end to range End
const LONG cchText = GetAdjustedTextLength();
if(GetCp() > cchText) // IP can't follow final CR
Set(cchText, 0); // so move it before
}
_cch = 0; // Collapse this range
if(_fSel) // Notify if selection changed
GetPed()->GetCallMgr()->SetSelectionChanged();
Update_iFormat(-1); // Make sure format is up to date
}
/*
* CTxtRange::Comparer(pRange)
*
* @mfunc
* helper function for CTxtRange::InRange() and IsEqual()
*
* @rdesc
* 0 if not same story or if this range isn't contained by <p pRange>;
* -1 if ranges are equal; 1 if this range wholely contained in
* <p pRange>.
*
* @comm
* Note that if this range is degenerate and *pRange is nondegenerate,
* this range is not included in *pRange if it's located at pRange's
* End position.
*/
LONG CTxtRange::Comparer (
ITextRange * pRange) //@parm ITextRange to compare with
{
TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEINTERN, "CTxtRange::Comparer");
LONG cpMin, cpMost;
LONG Start, End;
if(InStory(pRange, NULL) != NOERROR) // If this range doesn't point at
return 0; // same story as pRange's,
// return 0
GetRange(cpMin, cpMost); // Get this range's cp's
pRange->GetStart(&Start); // Get pRange's cp's
pRange->GetEnd(&End);
if(cpMin == Start && cpMost == End) // Exact match
return -1;
return cpMin >= Start && cpMost <= End && cpMin < End;
}
/*
* CTxtRange::Expander (Unit, fExtend, pDelta, pcpMin, pcpMost)
*
* @mfunc
* Helper function that expands this range so that partial Units it
* contains are completely contained according to the out parameters
* pcpMin and pcpMost. If pcpMin is not NULL, the range is expanded to
* the beginning of the Unit. Similarly, if pcpMost is not NULL, the
* range is expanded to the end of the Unit. <p pDelta> is an out
* parameter that receives the number of chars added to the range.
*
* @rdesc
* HRESULT = (if change) ? NOERROR :
* (if Unit valid) ? S_FALSE : E_INVALIDARG
*
* @devnote
* Used by ITextRange::Expand(), StartOf(), and EndOf(). Both pcpMin and
* pcpMost are nonNULL for Expand(). pcpMin is NULL for EndOf() and
* pcpMost is NULL for StartOf().
*
* @future
* Discontiguous Units. Expander should expand only to end of Unit,
* rather than to start of next Unit.
*/
HRESULT CTxtRange::Expander (
long Unit, //@parm Unit to expand range to
BOOL fExtend, //@parm Expand this range if TRUE
LONG * pDelta, //@parm Out parm that receives chars added
L
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -