📄 dispml.cpp
字号:
if (!_ped->IsRich() && (!cLine || // If plain text with no lines
Elem(cLine - 1)->_cchEOP)) // or last line ending with a CR,
{ // then inc line count
cLine++;
}
return cLine;
}
// ================================ Line info retrieval ====================================
/*
* CDisplayML::YposFromLine(ili)
*
* @mfunc
* Computes top of line position
*
* @rdesc
* top position of given line (relative to the first line)
*/
LONG CDisplayML::YposFromLine(
LONG ili) //@parm Line we're interested in
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::YposFromLine");
_TEST_INVARIANT_
if(!WaitForRecalcIli(ili)) // out of range, use last valid line
{
ili = Count() -1;
ili = (ili > 0) ? ili : 0;
}
LONG cli = ili - _iliFirstVisible;
CLine * pli = Elem(_iliFirstVisible);
LONG yPos = _yScroll + _dyFirstVisible;
while(cli > 0)
{
yPos += pli->GetHeight();
cli--;
pli++;
}
while(cli < 0)
{
pli--;
yPos -= pli->GetHeight();
cli++;
}
AssertSz(yPos >= 0, "CDisplayML::YposFromLine height less than 0");
return yPos;
}
/*
* CDisplayML::CpFromLine(ili, pyHeight)
*
* @mfunc
* Computes cp at start of given line
* (and top of line position relative to this display)
*
* @rdesc
* cp of given line
*/
#define __OPT_PLAT_FLAG (defined (ARMV4T))
#define __OPT_VER_OFF
#define __OPT_BUGNUMSTRING "26316"
#include <optimizer.h>
LONG CDisplayML::CpFromLine (
LONG ili, //@parm Line we're interested in (if <lt> 0 means caret line)
LONG *pyHeight) //@parm Returns top of line relative to display
// (NULL if don't want that info)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::CpFromLine");
_TEST_INVARIANT_
LONG cli;
LONG y = _yScroll + _dyFirstVisible;
LONG cp = _cpFirstVisible;
CLine *pli;
LONG iStart = _iliFirstVisible;
cli = ili - _iliFirstVisible;
if(cli < 0 && -cli >= ili)
{
// Closer to first line than to first visible line,
// so start at the first line
cli = ili;
y = 0;
cp = 0;
iStart = 0;
}
else if( cli <= 0 )
{
CheckView();
for(ili = _iliFirstVisible-1; cli < 0; cli++, ili--)
{
pli = Elem(ili);
y -= pli->GetHeight();
cp -= pli->_cch;
}
goto end;
}
for(ili = iStart; cli > 0; cli--, ili++)
{
pli = Elem(ili);
if(!IsMain() || !WaitForRecalcIli(ili))
break;
y += pli->GetHeight();
cp += pli->_cch;
}
end:
if(pyHeight)
*pyHeight = y;
return cp;
}
#define __OPT_PLAT_FLAG (defined (ARMV4T))
#define __OPT_VER_RESTORE
#define __OPT_BUGNUMSTRING "26316"
#include <optimizer.h>
/*
* CDisplayML::LineFromYPos(yPos, pyLine, pcpFirst)
*
* @mfunc
* Computes line at given y position. Returns top of line ypos
* cp at start of line cp, and line index.
*
* @rdesc
* index of line found
*/
LONG CDisplayML::LineFromYpos (
LONG yPos, //@parm Ypos to look for (relative to first line)
LONG *pyLine, //@parm Returns ypos at top of line /r first line (can be NULL)
LONG *pcpFirst) //@parm Returns cp at start of line (can be NULL)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::LineFromYpos");
_TEST_INVARIANT_
LONG cpLi;
LONG dy;
LONG ili = 0;
LONG yLi;
CLine *pli;
if(!WaitForRecalc(-1, _yScroll))
{
yLi = 0;
cpLi = 0;
goto done;
}
cpLi = _cpFirstVisible;
ili = _iliFirstVisible;
yLi = _yScroll + _dyFirstVisible;
dy = yPos - yLi;
if(dy < 0 && -dy <= _yScroll)
{
// closer to first visible line than to first line
// go backwards from the first visible line
while(yPos < yLi && ili > 0)
{
pli = Elem(--ili);
yLi -= pli->GetHeight();
cpLi -= pli->_cch;
}
}
else
{
if(dy < 0)
{
// closer to first line than to first visible line
// so start at the first line
cpLi = _cpMin;
yLi = 0;
ili = 0;
}
pli = Elem(ili);
while(yPos > yLi && ili < (LONG)Count()-1)
{
yLi += pli->GetHeight();
cpLi += pli->_cch;
ili++;
pli++;
}
if(yPos < yLi && ili > 0)
{
ili--;
pli--;
yLi -= pli->GetHeight();
cpLi -= pli->_cch;
}
}
done:
if(pyLine)
*pyLine = yLi;
if(pcpFirst)
*pcpFirst = cpLi;
return ili;
}
/*
* CDisplayML::LineFromCp(cp, fAtEnd)
*
* @mfunc
* Computes line containing given cp.
*
* @rdesc
* index of line found, -1 if no line at that cp.
*/
LONG CDisplayML::LineFromCp(
LONG cp, //@parm cp to look for
BOOL fAtEnd) //@parm If true, return previous line for ambiguous cp
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::LineFromCp");
_TEST_INVARIANT_
CLinePtr rp(this);
if(!WaitForRecalc(cp, -1) || !rp.RpSetCp(cp, fAtEnd))
return -1;
return (LONG)rp;
}
//============================== Point <-> cp conversion ==============================
/*
* CDisplayML::CpFromPoint(pt, prcClient, ptp, prp, fAllowEOL)
*
* @mfunc
* Determine cp at given point
*
* @devnote
* --- Use when in-place active only ---
*
* @rdesc
* Computed cp, -1 if failed
*/
LONG CDisplayML::CpFromPoint(
POINT pt, //@parm Point to compute cp at (client coords)
const RECT *prcClient, //@parm Client rectangle (can be NULL if active).
CRchTxtPtr * const ptp, //@parm Returns text pointer at cp (may be NULL)
CLinePtr * const prp, //@parm Returns line pointer at cp (may be NULL)
BOOL fAllowEOL, //@parm Click at EOL returns cp after CRLF
HITTEST * pHit) //@parm Out parm for hit-test value
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::CpFromPoint");
_TEST_INVARIANT_
LONG cp;
LONG cch = 0;
LONG dx = 0;
LONG ili;
CLine * pli;
LONG yLine;
RECT rcView;
if(pHit)
*pHit = HT_Nothing;
GetViewRect(rcView, prcClient);
// Get line under hit
ili = LineFromYpos(pt.y + _yScroll - rcView.top, &yLine, &cp);
if(ili < 0)
return -1;
yLine -= _yScroll;
pli = Elem(ili);
// Create measurer
CMeasurer me(this);
AssertSz((pli != NULL) || (ili == 0),
"CDisplayML::CpFromPoint invalid line pointer");
if (pli != NULL)
{
// Get character in the line
me.SetCp(cp);
cch = pli->CchFromXpos(me, pt.x + _xScroll - rcView.left, &dx, pHit);
if(pHit && (pt.x > rcView.right || pt.y > rcView.bottom))
*pHit = HT_Nothing;
// Don't allow click at EOL to select EOL marker and take into account
// single line edits as well
if(!fAllowEOL && cch == (LONG)pli->_cch && pli->_cchEOP)
{
// Adjust the position on the line by the amount backed up
cch += me._rpTX.BackupCpCRLF();
me._rpCF.BindToCp(me.GetCp());
me._rpPF.BindToCp(me.GetCp());
}
}
if(ptp)
*ptp = me;
if(prp)
prp->RpSet(ili, cch);
return me.GetCp();
}
/*
* CDisplayML::PointFromTp(tp, prcClient, fAtEnd, pt, prp, taMode)
*
* @mfunc
* Determine coordinates at given tp
*
* @devnote
* --- Use when in-place active only ---
*
* @rdesc
* line index at cp, -1 if error
*/
LONG CDisplayML::PointFromTp(
const CRchTxtPtr &tp, //@parm Text ptr to get coordinates at
const RECT *prcClient, //@parm Client rectangle (can be NULL if active).
BOOL fAtEnd, //@parm Return end of previous line for ambiguous cp
POINT &pt, //@parm Returns point at cp in client coords
CLinePtr * const prp, //@parm Returns line pointer at tp (may be null)
UINT taMode) //@parm Text Align mode: top, baseline, bottom
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::PointFromTp");
_TEST_INVARIANT_
CLinePtr rp(this);
RECT rcView;
if( !WaitForRecalc(tp.GetCp(), -1) )
{
return -1;
}
if(!rp.RpSetCp(tp.GetCp(), fAtEnd))
return -1;
AssertSz(_ped->_fInPlaceActive || (prcClient != NULL),
"CDisplayML::PointFromTp() called with invalid client rect");
GetViewRect(rcView, prcClient);
pt.y = YposFromLine(rp);
pt.x = rp.IsValid() ? rp->_xLeft : 0;
pt.x += rcView.left - _xScroll;
pt.y += rcView.top - _yScroll;
if (rp.RpGetIch())
{
CMeasurer me(this, tp);
// Backup to start of line
me.Advance(-rp.RpGetIch());
// And measure from there to where we are
me.NewLine(*rp);
LONG xCalc = me.MeasureText(rp.RpGetIch());
if ((pt.x + xCalc <= rcView.right) || !GetWordWrap())
{
// Width is in view or there is no wordwrap so just
// add the length to the point.
pt.x += xCalc;
}
else
{
// Remember we ignore trailing spaces at the end of the line
// in the width, therefore the x value that MeasureText finds can
// be greater than the width in the line so we truncate to the
// previously calculated width which will ignore the spaces.
pt.x += rp->_xWidth; // we *don't* worry about xLineOverhang here.
}
}
if (prp)
*prp = rp;
if(rp >= 0 && taMode != TA_TOP)
{
// Check for vertical calculation request
if (taMode & TA_BOTTOM)
{
const CLine *pli = Elem(rp);
if(pli && !pli->_fCollapsed)
{
pt.y += pli->_yHeight;
if((taMode & TA_BASELINE) == TA_BASELINE)
pt.y -= pli->_yDescent;
}
}
// Do any special horizontal calculation
if (taMode & TA_CENTER)
{
pt.x += ModeOffsetIntoChar(taMode, tp);
}
}
return rp;
}
//==================================== Rendering =======================================
/*
* CDisplayML::Render(rcView, rcRender)
*
* @mfunc
* Searches paragraph boundaries around a range
*/
void CDisplayML::Render (
const RECT &rcView, //@parm View RECT
const RECT &rcRender) //@parm RECT to render (must be container in
// client rect)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::Render");
_TEST_INVARIANT_
LONG cp;
BOOL fLinesToRender = TRUE;
LONG ili;
LONG lCount = Count();
CLine * pli;
CTxtSelection *psel = _ped->GetSelNC();
POINT pt;
LONG yBottomOfRender;
LONG yHeightForBitmap = 0;
LONG yHeightForLine;
LONG yLi = 0;
LONG yLine;
LONG yRenderHeight = rcRender.top + _yScroll - rcView.top;
if(psel)
psel->ClearCchPending();
// Fire event "updating"
if(IsMain())
_ped->TxNotify(EN_UPDATE, NULL);
// Calculate line and cp to start the diplay at
ili = LineFromYpos(rcRender.top + _yScroll - rcView.top, &yLine, &cp);
yLi = Elem(ili)->GetHeight();
yLi = max(yLi, 0);
if (yRenderHeight > yLine + yLi)
fLinesToRender = FALSE;
// Calculate the point where the text will start being displayed
pt.x = rcView.left - _xScroll;
pt.y = rcView.top - _yScroll + yLine;
// We only need check for whether we want to off screen render if the
// control is rich text and it is not transparent. Remember if the
// control is transparent, the rendering of mixed character formats
// will work because characters in adjoining runs are only truncated
// if ExtTextOut is trying to clear the display area at the same time.
if (!IsMetafile() && IsMain()
&& (_fUpdateOffScreen || (_ped->IsRich() && !_ped->_fTransparent)))
{
// This is rich text - we may want to use off screen rendering. We
// only decide to set up off screen rendering if some line in the
// set of displayed lines has mixed format runs. The measurer is
// the one that determines this.
// Make sure update flag is no longer set as it has done its job.
_fUpdateOffScreen = FALSE;
// Initialize height counter to first position to display
yLi = pt.y;
yBottomOfRender = BottomOfRender(rcView, rcRender);
// Loop through the visible lines until we have examined the entire
// line array or we have exceeded the visible height
for (LONG iliLoop = ili;
(iliLoop < lCount) && (yLi < yBottomOfRender); iliLoop++)
{
pli = Elem(iliLoop);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -