⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dispml.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//
// 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	dispml.cpp -- CDisplayML class |
 *
 *		This is the Multi-line display engine.  See disp.c for the base class
 *		methods and dispsl.c for the single-line display engine.
 *	
 *	Owner:<nl>
 *		Original RichEdit code: David R. Fulmer
 *		Christian Fortini (initial conversion to C++)
 *		Murray Sargent
 *		Rick Sailor (for most of RE 2.0)
 */

#include "_common.h"
#include "_dispml.h"
#include "_edit.h"
#include "_font.h"
#include "_measure.h"
#include "_render.h"
#include "_select.h"
#include "_dfreeze.h"

ASSERTDATA

//
//	Invariant support
//
#define DEBUG_CLASSNAME	CDisplayML
#include "_invar.h"

// Timer tick counts for background task
#define cmsecBgndInterval 	300
#define cmsecBgndBusy 		100

// Lines ahead
const LONG cExtraBeforeLazy = 60;

// if we need to calc at least this many characters, then put up a wait
// cursor.  NB!  4096 is not a measured number; it just seemed like a good
// one.
#define NUMCHARFORWAITCURSOR	4096	

// define only if we want to disable the horizontal scroll bar
#define DISABLE_HORZ

#ifndef DEBUG
#define CheckView()
#define	CheckLineArray()
#endif
	
// V-GUYB: Add a local MulDiv to prevent wrapping during scroll calculations in long docs.
#define MulDivI64(nNumber, nNumerator, nDenominator) (int)((nDenominator) ? (((__int64)(nNumber) * (__int64)(nNumerator)) / (__int64)(nDenominator)) : -1)

// ===========================  CDisplayML  =====================================================

#ifdef DEBUG
/*
 *	CDisplayML::Invariant
 *
 *	@mfunc	Make sure the display is in a valid state
 *
 *	@rdesc	TRUE if the tests succeeded, FALSE otherwise
 */
BOOL CDisplayML::Invariant(void) const
{
	CDisplay::Invariant();

	if( _prgliNew )
	{
		Assert(_prgliNew->Invariant());
	}

	return TRUE;
}
#endif // DEBUG

/*
 *	CDisplayML::CalcScrollHeight()
 *
 *	@mfunc	
 *		Calculate the maximum Y scroll position.
 *
 *	@rdesc
 *		Maximum possible scrolling position
 *
 *	@devnote
 *		This routine exists because plain text controls do not have
 *		the auto-EOP and so the scroll height is different than
 *		the height of the control if the text ends in an EOP type
 *		character.
 *
 */
LONG CDisplayML::CalcScrollHeight(LONG yHeight) const
{
	// The max scroll height for plain text controls is calculated differently
	// because they don't have an automatic EOP character.
	if (!_ped->IsRich() && (Count() > 0))
	{
		// Get the last line in the array
		CLine *lp = Elem(Count() - 1);

		// Is the last character an EOP? - if so we need to bump the scroll
		// height.
		if (lp->_cchEOP)
			yHeight += lp->GetHeight();
	}
	return yHeight;
}

/*
 *	CDisplayML::GetMaxYScroll()
 *
 *	@mfunc	
 *		Calculate the maximum Y scroll position.
 *
 *	@rdesc
 *		Maximum possible scrolling position
 *
 *	@devnote
 *		This routine exists because we may have to come back and modify this 
 *		calculation for 1.0 compatibility. If we do, this routine only needs
 *		to be changed in one place rather than the three at which it is used.
 *
 */
INLINE LONG CDisplayML::GetMaxYScroll() const
{
	// The following code is turn off because we don't want to support 
	// 1.0 mode unless someone complained about it.  
#if 0		
 	if (_ped->Get10Mode())
	{
		// Ensure last line is always visible
		// (use dy as temp to calculate max scroll)
		yScroll = Elem(max(0, Count() - 1))->_yHeight;

		if(yScroll > _yHeightView)
			yScroll = _yHeightView;

		yScroll = _yHeight - yScroll;
	}
#endif //0

	return CalcScrollHeight(_yHeight);
}

/*
 *	CDisplayML::ConvertYPosToMax()
 *
 *	@mfunc	
 *		Calculate the real scroll position from the scroll position
 *
 *	@rdesc
 *		Y position from scroll
 *
 *	@devnote
 *		This routine exists because the thumb position messages
 *		are limited to 16-bits so we extrapolate when the Y position
 *		gets greater than that.
 *
 */
LONG CDisplayML::ConvertScrollToYPos(
	LONG yPos)		//@parm Scroll position 
{
	// Get the maximum scroll range
	LONG yRange = GetMaxYScroll();

	// Has the maximum scroll range exceeded 16-bits?
	if (yRange >= _UI16_MAX)
	{
		// Yes - Extrapolate to the "real" yPos		

#ifndef UNDER_CE
		yPos = MulDiv(yPos, yRange, _UI16_MAX);
#else
        // V-GUYB: 4 byte values can wrap in MulDiv, so use int64 here.
		yPos = MulDivI64(yPos, yRange, _UI16_MAX);
#endif
	}

	return yPos;
}

/*
 *	CDisplayML::ConvertYPosToScrollPos()
 *
 *	@mfunc	
 *		Calculate the scroll position from the Y position in the document.
 *
 *	@rdesc
 *		Scroll position from Y position
 *
 *	@devnote
 *		This routine exists because the thumb position messages
 *		are limited to 16-bits so we extrapolate when the Y position
 *		gets greater than that.
 *
 */
INLINE LONG CDisplayML::ConvertYPosToScrollPos(
	LONG yPos)		//@parm Y position in document
{
	// Get the maximum scroll range
	LONG yRange = GetMaxYScroll();

	// Has the maximum scroll range exceeded 16-bits?
	if (yRange >= _UI16_MAX)
	{
		// Yes - Extrapolate to the "real" yPos		

#ifndef UNDER_CE
		yPos = MulDiv(yPos, _UI16_MAX, yRange);
#else
        // V-GUYB: 4 byte values can wrap in MulDiv, so use int64 here if necessary.
        if(yPos < _UI16_MAX)
        {
            // yPos * _UI16_MAX won't wrap, so use 32 bit MulDiv.
            yPos = MulDiv(yPos, _UI16_MAX, yRange);
        }
        else
        {
            // yPos * _UI16_MAX will wrap, so use 64 bit MulDiv.
            yPos = MulDivI64(yPos, _UI16_MAX, yRange);
        }
#endif

	}
	return yPos;
}


CDisplayML::CDisplayML (CTxtEdit* ped)
  : CDisplay (ped), _pddTarget(NULL)
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::CDisplayML");

	_xWidthMax = 0;
	_yHeightMax = 0;
}

CDisplayML::~CDisplayML()
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::~CDisplayML");

	delete _prgliNew;

	delete _pddTarget;
}

/*
 *	CDisplayML::Init()
 *
 *	@mfunc	
 *		Init this display for the screen
 */
BOOL CDisplayML::Init()
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::Init");

	// Initialize our base class
	if (CDisplay::Init())
	{
		return FALSE;
	}

	DWORD dwScrollBars = _ped->TxGetScrollBars();
	int fnBarHorz = SB_HORZ;
	int fnBarVert = SB_VERT;

	AssertSz(_ped, "CDisplayML::Init(): _ped not initialized in display");
	Assert (_yCalcMax == 0);		// Verify allocation zeroed memory out
	Assert (_xWidth == 0);
	Assert (_yHeight == 0);
	Assert (_cpMin == 0);
	Assert (_fBgndRecalc == FALSE);
	Assert(!_fVScrollEnabled);
	Assert(!_fHScrollEnabled);

	// The printer view is not main, therefore we do this to make
	// sure scroll bars are not created for print views.
	if (IsMain())
	{
		if(dwScrollBars & WS_VSCROLL)
		{
			if(dwScrollBars & ES_DISABLENOSCROLL)
			{
				// This causes wlm to assert on the mac. something about the 
				// scrollbar being disabled
				_ped->TxSetScrollRange(fnBarVert, 0, 1, TRUE);

				_ped->TxEnableScrollBar(fnBarVert, ESB_DISABLE_BOTH);
			}
		}

		// Set horizontal scroll range and pos
		// ??? - CF need fixing for windowless case
		if(dwScrollBars & WS_HSCROLL)
		{
			if(dwScrollBars & ES_DISABLENOSCROLL)
			{
				_ped->TxSetScrollRange (fnBarHorz, 0, 1, TRUE);
				_ped->TxEnableScrollBar(fnBarHorz, ESB_DISABLE_BOTH);
			}
		}
	}

	SetWordWrap(_ped->TxGetWordWrap());

	_cpFirstVisible = _cpMin;
	
	Assert(_xScroll == 0);
	Assert(_yScroll == 0);
	Assert(_iliFirstVisible == 0);
	Assert(_cpFirstVisible == 0);
	Assert(_dyFirstVisible == 0);

    _TEST_INVARIANT_

	return TRUE;
}


//================================  Device drivers  ===================================
/*
 *	CDisplayML::SetMainTargetDC(hdc, xWidthMax)
 *
 *	@mfunc
 *		Sets a target device for this display and updates view 
 *
 *	@devnote
 *		Target device can't be a metafile (can get char width out of a 
 *		metafile)
 *
 *	@rdesc
 *		TRUE if success
 */
BOOL CDisplayML::SetMainTargetDC (
	HDC hdc,			//@parm Target DC, NULL for same as rendering device
	LONG xWidthMax)		//@parm Max line width (not used for screen)
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::SetMainTargetDC");

	BOOL	result = FALSE;

	if ( SetTargetDC( hdc ) )
	{
		// This is here because this is what RE 1.0 did. 
		SetWordWrap(!(!hdc && (xWidthMax != 0)));

		// if xWidthMax is greater than zero, then the caller is
		// trying to set the maximum width of the window (for measuring,
		// line breaking, etc.)  However,in order to make our measuring
		// algorithms more reasonable, we'll force the max size to
		// be *at least* as wide as the width of a character.
		// Note that xWidthMax = 0 means use the view rect width
		_xWidthMax = (xWidthMax <= 0) ? 0 : max(DXtoLX(GetXWidthSys()), 
												xWidthMax);

		// need to do a full recalc
		// if it fails, it fails, the lines are left in a reasonable state
		// no need to call WaitForRecalc() because UpdateView()
		// start at position zero and we're always calced up to there
		CDisplay::UpdateView();

		// caret/selection has most likely moved
		CTxtSelection *psel = _ped->GetSelNC();

		if ( psel ) 
		{
			psel->UpdateCaret(FALSE);
		}
		result = TRUE;
	}
	return result;
}

// Useful for both main and printing devices. jonmat 6/08/1995
BOOL CDisplayML::SetTargetDC( HDC hdc )
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::SetTargetDC");

	CDevDesc *pddTarget = NULL;

	// don't allow metafiles to be set as the target device
	if(hdc && GetDeviceCaps(hdc, TECHNOLOGY) == DT_METAFILE)
	{
		return FALSE;
	}

	if (hdc != NULL)
	{
		// Allocate the device first to see if we can. We 
		// don't want to change our state if this is going
		// to fail.
		pddTarget = new CDevDesc(_ped);

		if (NULL == pddTarget)
		{
			// We couldn't so we are done.
			return FALSE;
		}
	}

	// remove any cached information for the old target device
	if (_pddTarget != NULL)
	{
		delete _pddTarget;
		_pddTarget = NULL;
	}

	if(hdc != NULL)
	{
		// Update the device because we have one.
		_pddTarget = pddTarget;

		_pddTarget->SetDC(hdc);
	}
	return TRUE;
}

//=================================  Line recalc  ==============================
/*
 *	CDisplayML::RecalcScrollBars(void)
 *
 *	@mfunc
 *		Recalculate the scroll bars if the view has changed.
 *
 *
 *	@devnote	There is a possibility of recursion here, so we
 *				need to protect ourselves.
 *
 *	To visualize this, consider two types of characters, 'a' characters 
 *	which are small in height and 'A' 's which are really tall, but the same 
 *	width as an 'a'. So if I have
 *
 *	a a A						<nl>
 *	A							<nl>
 *
 *	I'll get a calced size that's basically 2 * heightof(A).
 *	With a scrollbar, this could wordwrap to 
 *
 *	a a							<nl>
 *	A A							<nl>
 *
 *	which is of calced size heightof(A) + heightof(a); this is
 *	obviously less than the height in the first case.
 */
void CDisplayML::RecalcScrollBars()
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::RecalcScrollBars");

	if(_fViewChanged)
	{
  		_fViewChanged = FALSE;

		UpdateScrollBar(SB_VERT, TRUE);
    	UpdateScrollBar(SB_HORZ, TRUE);
    }
}

/*
 *	CDisplayML::RecalcLines(fWait)
 *
 *	@mfunc
 *		Recalc all line breaks. 
 *		This method does a lazy calc after the last visible line
 *		except for a bottomless control
 *
 *	@rdesc
 *		TRUE if success
 */
BOOL CDisplayML::RecalcLines (
	BOOL fWait)		//@parm Recalc lines down to _cpWait/_yWait; then be lazy
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::RecalcLines");

	LONG		cliWait = cExtraBeforeLazy;			// Extra lines before being lazy
	BOOL		fDone = TRUE;
	BOOL		fFirstInPara = TRUE;
	CLine *		pliNew = NULL;
	LONG		xWidth;
	LONG		yHeight = 0;
    LONG        cchText = _ped->GetTextLength();
	BOOL		fWaitingForFirstVisible = TRUE;
	LONG		yHeightView = _yHeightView;
	LONG		yHeightScrollOld = GetMaxYScroll();
	LONG		yHeightScrollNew;

	Remove(0, -1, AF_KEEPMEM);					// Remove all old lines from *this

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -