📄 dispsl.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*
* @doc INTERNAL
*
* @module dispsl.cpp -- CDisplaySL class |
*
* This is the Single-line display engine. See disp.c for the base class
* methods and dispml.c for the Multi-line display engine.
*
* Owner:<nl>
* Original RichEdit code: David R. Fulmer
* Christian Fortini
* Murray Sargent
*/
#include "_common.h"
#include "_dispsl.h"
#include "_measure.h"
#include "_select.h"
#include "_render.h"
#include "_font.h"
#include "_dfreeze.h"
ASSERTDATA
const LONG CALC_XSCROLL_FROM_FIRST_VISIBLE = -2;
/*
* CDisplaySL::CDisplaySL
*
* Purpose
* Constructor
*/
CDisplaySL::CDisplaySL ( CTxtEdit* ped )
: CDisplay( ped )
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::CDisplaySL");
}
/*
* CDisplaySL::Init()
*
* Purpose
* Init this display for the screen
*/
BOOL CDisplaySL::Init()
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::Init");
// Initialize our base class
if (CDisplay::Init())
{
return FALSE;
}
SetWordWrap(FALSE);
return TRUE;
}
/*
* CDisplaySL::InitVars()
*
*/
void CDisplaySL::InitVars()
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::InitVars");
_xScroll = 0;
SetCpFirstVisible(0);
}
/*
* CDisplaySL::RecalcView()
*
* @mfunc
* Recalc all lines breaks and update first visible line
*
* @rdesc
* TRUE if success
*/
BOOL CDisplaySL::RecalcView(
BOOL fUpdateScrollBars //@param TRUE - update scroll bars
)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::RecalcView");
LONG xWidthOld = _xWidth + _xLineOverhang;
if (!RecalcLine())
{
return FALSE;
}
if (_fViewChanged)
{
if (IsActive() || _xWidth + _xLineOverhang <= GetViewWidth())
{
_xScroll = 0;
SetCpFirstVisible(0);
}
else if (CALC_XSCROLL_FROM_FIRST_VISIBLE == _xScroll)
{
// In this case we want to set our xScroll by a visible. The
// only way to get here is if the active view has been cloned
// for displaying an inactive view.
// Assume that the first visible is 0
_xScroll = 0;
// Check the first visible
if (GetFirstVisibleCp() != 0)
{
// Start at cp 0
CMeasurer me(this);
// And measure from there to where we are
me.NewLine(*this);
// Scroll is the length to character
_xScroll = me.MeasureText(GetFirstVisibleCp());
}
}
if (fUpdateScrollBars)
{
UpdateScrollBar( SB_HORZ, TRUE );
}
_fViewChanged = FALSE;
}
// We will only resize if the width of the single line control has changed.
if ( (_xWidth + _xLineOverhang) != xWidthOld)
{
if(FAILED(RequestResize()))
{
_ped->GetCallMgr()->SetOutOfMemory();
}
}
return TRUE;
}
/*
* CDisplaySL::RecalcLine()
*
* @mfunc
* Recalculate a line
*
* @rdesc
* TRUE if success <nl>
* FALSE if failure <nl>
*/
BOOL CDisplaySL::RecalcLine()
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::RecalcLine");
BOOL measured;
LONG xWidthOld;
Assert( _ped );
// Create a measurer starting at cp = 0
CMeasurer me(this);
xWidthOld = CLine::_xWidth + CLine::_xLineOverhang;
measured = CLine::Measure( me, -1, MEASURE_FIRSTINPARA );
Assert( measured );
if (!measured)
{
InitVars();
return FALSE;
}
_fNeedRecalc = FALSE;
_fRecalcDone = TRUE;
if (_fViewChanged || xWidthOld != (CLine::_xWidth + CLine::_xLineOverhang))
{
_fViewChanged = TRUE;
}
_fLineRecalcErr = FALSE;
return measured;
}
/*
* CDisplaySL::Render(rcView, rcRender)
*
* Purpose
* Searches paragraph boundaries around a range
*/
void CDisplaySL::Render(
const RECT &rcView, //@parm View RECT
const RECT &rcRender) //@parm RECT to render (must be contained in
// client rect)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::Render");
POINT pt;
LONG yHeightBitmap = 0;
_fRectInvalid = FALSE;
CRenderer re(this);
if (!IsMetafile()
&& !_ped->_fTransparent && (_bFlags & fliUseOffScreenDC))
{
yHeightBitmap = _yHeight;
if (rcView.top > rcRender.top)
{
// Bit map for first line needs to be big enough to take into account
// the area above the first line so, add the difference between view
// and render start into the bitmap size.
yHeightBitmap += (rcView.top - rcRender.top);
}
}
if (!re.StartRender(rcView, rcRender, yHeightBitmap))
return;
// Set renderer at top/left of view rect
pt.x = rcView.left - _xScroll;
pt.y = rcView.top;
re.SetCurPoint(pt);
// Renderer is set at cp==0 at the moment
re.RenderLine(*this, TRUE);
if ((_bFlags & fliOffScreenOnce) != 0)
{
_bFlags &= ~(fliUseOffScreenDC | fliOffScreenOnce);
}
// If our line metrics are not yet up to date,
// get them from the renderer
if(_xWidth == -1)
{
_xWidth = re._xWidth;
_xLineOverhang = re._xLineOverhang;
_yHeight = re._yHeight;
_yDescent = re._yDescent;
}
re.EndRender();
}
/*
* CDisplaySL::WaitForRecalcIli(ili)
*
* @mfunc
* Wait until line array is recalculated up to line <p ili>
*
* @rdesc
* Returns TRUE if lines were recalc'd up to ili (TRUE if ili == 0)
*/
BOOL CDisplaySL::WaitForRecalcIli (
LONG ili) //@parm Line index to recalculate line array up to
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::WaitForRecalcIli");
return ili == 0;
}
/*
* CDisplaySL::GetScrollRange(nBar)
*
* @mfunc
* Returns the max part of a scrollbar range for scrollbar <p nBar>
*
* @rdesc
* LONG max part of scrollbar range
*/
LONG CDisplaySL::GetScrollRange(
INT nBar) const //@parm Scroll bar to interrogate (SB_VERT or SB_HORZ)
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::GetScrollRange");
Assert( IsMain() );
LONG lRange = 0;
if ((nBar != SB_VERT) && _fHScrollEnabled)
{
if(_ped->TxGetScrollBars() & WS_HSCROLL)
{
lRange = max(0, _xWidth + dxCaret);
lRange = min(lRange, _UI16_MAX);
}
}
return lRange;
}
/*
* CDisplaySL::UpdateScrollBar(nBar, fUpdateRange)
*
* @mfunc
* Update either the horizontal or vertial scroll bar
* Also figure whether the scroll bar should be visible or not
*
* @rdesc
* BOOL
*/
BOOL CDisplaySL::UpdateScrollBar (
INT nBar, //@parm Which scroll bar : SB_HORZ, SB_VERT
BOOL fUpdateRange) //@parm Should the range be recomputed and updated
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::UpdateScrollBar");
// Note: In the old days we didn't allow autosize & scroll bars, so to keep
// forms working, we need this special logic with respect to autosize.
if (!IsActive() || (SB_VERT == nBar)
|| (!_ped->fInOurHost() && _ped->TxGetAutoSize()))
{
// Scroll bars are only updated on active views.
return FALSE;
}
const DWORD dwScrollBars = _ped->TxGetScrollBars();
const BOOL fHide = !(dwScrollBars & ES_DISABLENOSCROLL);
BOOL fReturn = FALSE;
BOOL fEnabled = TRUE;
BOOL fEnabledOld = FALSE;
LONG lScroll = 0;
CTxtSelection *psel = _ped->GetSelNC();
// Get scrolling position
if(nBar == SB_HORZ)
{
if(!(dwScrollBars & WS_HSCROLL))
{
// even if we don't have scrollbars, we may allow horizontal
// scrolling.
if( !_fHScrollEnabled )
{
_fHScrollEnabled = !!(dwScrollBars & ES_AUTOHSCROLL);
}
return FALSE;
}
fEnabledOld = _fHScrollEnabled;
lScroll = ConvertXPosToScrollPos(_xScroll);
if(_xWidth <= _xWidthView)
fEnabled = FALSE;
}
// !s beforehand because all true values aren't necessarily equal
if(!fEnabled != !fEnabledOld)
{
if(_fDeferUpdateScrollBar)
_fUpdateScrollBarDeferred = TRUE;
else
{
if (nBar == SB_HORZ)
_fHScrollEnabled = fEnabled;
else
_fVScrollEnabled = fEnabled;
}
if(!_fDeferUpdateScrollBar)
{
if(!fHide) // Don't hide scrollbar, just disable
_ped->TxEnableScrollBar(nBar, fEnabled ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH);
else
{
fReturn = TRUE;
// Make sure to hide caret before showing scrollbar
if(psel)
psel->ShowCaret(FALSE);
// Hide or show scroll bar
_ped->TxShowScrollBar(nBar, fEnabled);
if(psel)
psel->ShowCaret(TRUE);
}
}
}
// Set scrollbar range and thumb position
if(fEnabled)
{
if (fUpdateRange)
{
if(!_fDeferUpdateScrollBar)
_ped->TxSetScrollRange(nBar, 0, GetScrollRange(nBar), FALSE);
}
if(_fDeferUpdateScrollBar)
_fUpdateScrollBarDeferred = TRUE;
else
_ped->TxSetScrollPos(nBar, lScroll, TRUE);
}
else if (!_fDeferUpdateScrollBar)
{
// This turns off the scroll bar and only needs to happen when a change
// occurs so we can count on the change in state check above to set
// _fUpdateScrollBarDeferred.
if (!fEnabled && fEnabledOld)
{
_ped->TxSetScrollRange(nBar, 0, 0, FALSE);
}
}
return fReturn;
}
BOOL CDisplaySL::IsMain() const
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::IsMain");
return TRUE;
}
LONG CDisplaySL::GetMaxWidth() const
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::GetMaxWidth");
return 0;
}
LONG CDisplaySL::GetMaxPixelWidth() const
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::GetMaxPixelWidth");
return GetViewWidth();
}
LONG CDisplaySL::GetMaxHeight() const
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::GetMaxHeight");
return 0;
}
LONG CDisplaySL::GetWidth() const
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::GetWidth");
return CLine::_xWidth + CLine::_xLineOverhang;
}
LONG CDisplaySL::GetHeight() const
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::GetHeight");
return CLine::_yHeight;
}
LONG CDisplaySL::GetResizeHeight() const
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::GetResizeHeight");
return CLine::_yHeight;
}
LONG CDisplaySL::LineCount() const
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::LineCount");
return 1;
}
/*
* CDisplaySL::GetCliVisible()
*
* @mfunc
* Get count of visible lines and update GetCp()MostVisible for PageDown()
*
* @rdesc
* count of visible lines
*/
LONG CDisplaySL::GetCliVisible (
LONG* pcpMostVisible, //@parm Returns cpMostVisible
BOOL fLastCharOfLastVisible) const //@parm Want cp of last visible char
// (ignored here).
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::GetCliVisible");
if (pcpMostVisible)
*pcpMostVisible = CLine::_cch;
return 1;
}
LONG CDisplaySL::GetFirstVisibleLine() const
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::GetFirstVisibleLine");
return 0;
}
/*
* CDisplaySL::GetLineText(ili, pchBuff, cchMost)
*
* @mfunc
* Copy given line of this display into a character buffer
*
* @rdesc
* number of character copied
*/
LONG CDisplaySL::GetLineText (
LONG ili, //@parm Line to get text of
TCHAR *pchBuff, //@parm Buffer to stuff text into
LONG cchMost) //@parm Length of buffer
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::GetLineText");
if (ili == 0)
{
cchMost = min( cchMost, (LONG)_ped->GetTextLength());
if (cchMost > 0)
{
CTxtPtr tp(_ped, 0);
return tp.GetText( cchMost, pchBuff );
}
}
return 0;
}
/*
* CDisplaySL::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; here always 0
*/
LONG CDisplaySL::CpFromLine (
LONG ili, //@parm Line we're interested in (if <lt> 0 means caret line)
LONG *pyLine) //@parm Returns top of line relative to display
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::CpFromLine");
// (NULL if don't want that info)
Assert( ili == 0 );
if (pyLine)
*pyLine = 0;
return 0;
}
/*
* CDisplaySL::LineFromCp(cp, fAtEnd)
*
* @mfunc
* Computes line containing given cp.
*
* @rdesc
* index of line found; here returns 0 always
*/
LONG CDisplaySL::LineFromCp(
LONG cp, //@parm cp to look for
BOOL fAtEnd) //@parm If true, return previous line for ambiguous cp
{
TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplaySL::LineFromCp");
return 0;
}
/*
* CDisplaySL::CpFromPoint(pt, ptp, prp, fAllowEOL)
*
* @mfunc
* Determine cp at given point
*
* @devnote
* --- Use when in-place active only ---
*
* @rdesc
* Computed cp, -1 if failed
*/
LONG CDisplaySL::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, "CDisplaySL::CpFromPoint");
LONG cch;
LONG dx = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -