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

📄 dispml.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		}

		// Add a new line
		pliNew = _prgliNew->Add(1, NULL);
		if (!pliNew)
		{
			TRACEWARNSZ("CDisplayML::RecalcLines unable to alloc additional CLine in CLineArray");
			goto errspace;
		}

    	Tracef(TRCSEVINFO, "Measuring new line from cp = %d", me.GetCp());

		// Stuff some text into new line
		wNumber = me._wNumber;
		if (!pliNew->Measure(me, -1, MEASURE_BREAKATWORD | 
							(fFirstInPara ? MEASURE_FIRSTINPARA : 0)))
		{
			Assert(FALSE);
			goto err;
		}
		
		fFirstInPara = pliNew->_cchEOP;
		yHeight += pliNew->GetHeight();

		if(fBackground && GetTickCount() >= (DWORD)_dwBgndTickMax)
		{
			fDone = FALSE;			// Took too long, stop for now
			break;
		}

		if(fWait && yHeight > _yWait && (LONG) me.GetCp() > _cpWait
			&& cliWait-- <= 0)
		{							// Not really done, just past region we're
			fDone = FALSE;			//  waiting for so let background recalc
			break;					//  take it from here
		}
	}								// while(me < cchText) ...

no_match:
	// Didn't find match: whole line array from _iliFirst needs to be changed
	pled->_iliMatchOld	= Count(); 
	pled->_cpMatchOld	= cchText;
	pled->_yMatchNew	= yHeight;
	pled->_yMatchNewTop = yHeightPrev;
	pled->_yMatchOld	= _yHeight;
	_cpCalcMax			= me.GetCp();

	// Replace old lines by new ones
	rpOld = pled->_iliFirst;

	// We store the result from the replace because although it can fail the 
	// fields used for first visible must be set to something sensible whether 
	// the replace fails or not. Further, the setting up of the first visible 
	// fields must happen after the Replace because the lines could have 
	// changed in length which in turns means that the first visible position
	// has failed.

	fReplaceResult = rpOld.Replace(-1, _prgliNew);

	// _iliMatchNew & _cpMatchNew are used for first visible constants so we
	// need to set them to something reasonable. In particular the rendering
	// logic expects _cpMatchNew to be set to the first character of the first
	// visible line. rpOld is used because it is convenient.

	// Note we can't use RpBindToCp at this point because the first visible
	// information is screwed up because we may have changed the line that
	// the first visible cp is on. 
	rpOld.BindToCp(me.GetCp());
	pled->_iliMatchNew = rpOld.GetLineIndex();
	pled->_cpMatchNew = me.GetCp() - rpOld.RpGetIch();

	if (!fReplaceResult)
	{
		TRACEERRORSZ("CDisplayML::RecalcLines rpOld.Replace() failed");
		goto errspace;
	}

    // Adjust first affected line if this line is gone
    // after replacing by new lines
    
    if(pled->_iliFirst >= (LONG)Count() && Count() > 0)
    {
        Assert(pled->_iliFirst == (LONG)Count());
        pled->_iliFirst = Count() - 1;
		pliNew = Elem(pled->_iliFirst);
        pled->_yFirst -= pliNew->GetHeight();
		AssertSz(pled->_yFirst >= 0, "CDisplayML::RecalcLines _yFirst < 0");
        pled->_cpFirst -= pliNew->_cch;
    }
    
match:
	_fRecalcDone = fDone;
    _fNeedRecalc = FALSE;
	_yCalcMax = yHeight;

	Tracef(TRCSEVINFO, "CDisplayML::RecalcLine(tpFirst, ...) - Done. Recalced down to line #%d", Count() - 1);

	// Clear wait fields since we want caller's to set them up.
	_yWait = -1;
	_cpWait = -1;

	if(fDone && fBackground)
	{
		TRACEINFOSZ("Background line recalc done");
		_ped->TxKillTimer(RETID_BGND_RECALC);
		_fBgndRecalc = FALSE;
		_fRecalcDone = TRUE;
	}

	// Determine display height and update scrollbar
	yHeightScrollNew = CalcScrollHeight(yHeight);

	if (_fViewChanged ||
		fDone && (yHeight != _yHeight || yHeightScrollNew != yHeightScrollOld)
		|| yHeightScrollNew > yHeightScrollOld) 
	{
		_yHeight = yHeight;
   		UpdateScrollBar(SB_VERT, TRUE);
	}

	// Determine display width and update scrollbar
	xWidth = CalcDisplayWidth();
    if(_fViewChanged || (fDone && xWidth != _xWidth) || xWidth > _xWidth)
    {
        _xWidth = xWidth;
   		UpdateScrollBar(SB_HORZ, TRUE);
    }    

    _fViewChanged = FALSE;

	// If not done, do the rest in background
	if(!fDone && !fBackground)
		fDone = StartBackgroundRecalc();

	if(fDone)
	{
		CheckLineArray();
		_fLineRecalcErr = FALSE;
	}

#ifdef DEBUG
	if( 1 )
    {
		_TEST_INVARIANT_
	}
#endif // DEBUG

	return TRUE;

errspace:
	_ped->GetCallMgr()->SetOutOfMemory();
	_fNeedRecalc = TRUE;
	_cpCalcMax = _yCalcMax = 0;
	_fLineRecalcErr = TRUE;

err:
	if(!_fLineRecalcErr)
	{
		_cpCalcMax = me.GetCp();
		_yCalcMax = yHeight;
	}

	TRACEERRORSZ("CDisplayML::RecalcLines() failed");

	if(!_fLineRecalcErr)
	{
		_fLineRecalcErr = TRUE;
		_ped->GetCallMgr()->SetOutOfMemory();
		_fLineRecalcErr = FALSE;			//  fix up CArray & bail
	}
	pled->SetMax(this);

	return FALSE;
}

/*
 *	CDisplayML::CalcDisplayWidth()
 *
 *	@mfunc
 *		Computes and returns width of this display by walking line
 *		CArray and returning the widest line.  Used for
 *		horizontal scroll bar routines
 *
 */
LONG CDisplayML::CalcDisplayWidth ()
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::CalcDisplayWidth");

	LONG	ili = Count();
	CLine *	pli;
	LONG	xWidth = 0, lineWidth;

	if(ili)
	{
		// Note: pli++ breaks array encapsulation (pli = &(*this)[ili] doesn't)
		pli = Elem(0);
		for(xWidth = 0; ili--; pli++)
		{
			lineWidth = pli->_xLeft + pli->_xWidth + pli->_xLineOverhang;
			xWidth = max(xWidth, lineWidth);
		}
	}
    return xWidth;
}

/*
 *	CDisplayML::StartBackgroundRecalc()
 *
 *	@mfunc
 *		Starts background line recalc (at _cpCalcMax position)
 *
 */
BOOL CDisplayML::StartBackgroundRecalc()
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::StartBackgroundRecalc");

	if(_fBgndRecalc)
	{
		// Already in background recalc
		return FALSE;
	}

	AssertSz(_cpCalcMax <= (LONG)_ped->GetTextLength(),
		"CDisplayML::StartBackgroundRecalc _cpCalcMax > Text Length");

	if (_cpCalcMax == (LONG)_ped->GetTextLength())
	{
		// Enough characters are recalc'd.
		return TRUE;
	}

	if (!_ped->TxSetTimer(RETID_BGND_RECALC, cmsecBgndInterval))
	{
		// Could not instantiate a timer so wait for recalculation
		WaitForRecalc(_ped->GetTextLength(), -1);
		return TRUE;
	}

	_fRecalcDone = FALSE;
	_fBgndRecalc = TRUE;
	return FALSE;
}

/*
 *	CDisplayML::StepBackgroundRecalc()
 *
 *	@mfunc
 *		Steps background line recalc (at _cpCalcMax position)
 *		Called by timer proc
 *
 */
void CDisplayML::StepBackgroundRecalc()
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::StepBackgroundRecalc");

    _TEST_INVARIANT_

	if (!_fBgndRecalc)
	{
		// We aren't in a background recalc so we don't
		// do anything.
		return;
	}

	LONG cch = _ped->GetTextLength() - _cpCalcMax;

	// Don't try recalc when processing OOM or had an error doing recalc or
	// if we are asserting.
#ifdef DEBUG
	if(_fInBkgndRecalc || _fLineRecalcErr || fInAssert)
	{
		if(_fInBkgndRecalc)
			TRACEINFOSZ("avoiding reentrant background recalc");
		else
			TRACEINFOSZ("OOM: not stepping recalc");
		return;
	}
#else
	if(_fInBkgndRecalc || _fLineRecalcErr )
		return;
#endif

	_fInBkgndRecalc = TRUE;

	if (!IsActive())
	{
		// Background recalc is over if we are no longer active	because
		// we can no longer get the information we need for recalculating.
		// But, if we are half recalc'd we need to set ourselves up to 
		// recalc again when we go active.
		InvalidateRecalc();
		cch = 0;
	}

	// Background recalc is over if no more characters or we are no longer
	// active.
	if(cch <= 0)
	{
		TRACEINFOSZ("Background line recalc done");
		_ped->TxKillTimer(RETID_BGND_RECALC);
		_fBgndRecalc = FALSE;
		_fRecalcDone = TRUE;
		_fInBkgndRecalc = FALSE;
		CheckLineArray();
		return;
	}

	_dwBgndTickMax = GetTickCount() + cmsecBgndBusy;
	CRchTxtPtr tp(_ped, _cpCalcMax);
	RecalcLines(tp, cch, cch, TRUE, FALSE, NULL);

	_fInBkgndRecalc = FALSE;
}

/*
 *	CDisplayML::WaitForRecalc(cpMax, yMax)
 *
 *	@mfunc
 *		Ensures that lines are recalced until a specific character
 *		position or ypos.
 *
 *	@rdesc
 *		success
 */
BOOL CDisplayML::WaitForRecalc(
	LONG cpMax,		//@parm Position recalc up to (-1 to ignore)
	LONG yMax)		//@parm ypos to recalc up to (-1 to ignore)
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::WaitForRecalc");

    _TEST_INVARIANT_

	if (IsFrozen() || !_ped->fInplaceActive())
	{
		return TRUE;
	}

	BOOL fReturn = TRUE;
	LONG cch;

	if((yMax < 0 || yMax >= _yCalcMax) &&
	   (cpMax < 0 || cpMax >= _cpCalcMax))
    {
    	cch = _ped->GetTextLength() - _cpCalcMax;
    	if(cch > 0 || Count() == 0)
    	{
    		HCURSOR hcur = NULL;
			BOOL fSetCursor = (cch > NUMCHARFORWAITCURSOR);

    		_cpWait = cpMax;
    		_yWait = yMax;
		
			if( fSetCursor )
			{
    			hcur = SetCursor(LoadCursor(0, IDC_WAIT));
			}
    		TRACEINFOSZ("Lazy recalc");
		
    		if(!_cpCalcMax || _fNeedRecalc )
			{
    			fReturn = RecalcLines(TRUE);
				if( !fReturn )
				{
					InitVars();
				}
			}
    		else			
    		{
    			CRchTxtPtr tp(_ped, _cpCalcMax);
    			fReturn = RecalcLines(tp, cch, cch, FALSE, TRUE, NULL);
    		}

			if( fSetCursor )
			{
    			SetCursor(hcur);
			}
    	}
		else if( cch == 0 )
		{
			// if there was nothing else to calc, make sure that we think
			// recalc is done.
#ifdef DEBUG
			if( !_fRecalcDone )
			{
				TRACEWARNSZ("For some reason we didn't think background "
					"recalc was done, but it was!!");
			}
#endif // DEBUG
			_fRecalcDone = TRUE;
		}
    }

	// If the view rect changed, make sure to update the scrollbars
	RecalcScrollBars();

	return fReturn;
}

/*
 *	CDisplayML::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
 */
BOOL CDisplayML::WaitForRecalcIli (
	LONG ili)		//@parm Line index to recalculate line array up to
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::WaitForRecalcIli");

	LONG cchGuess;

	while(!_fRecalcDone && ili >= (LONG)Count())
	{
		// just go ahead and recalc everything.
		cchGuess = _ped->GetTextLength();
		if(!WaitForRecalc(cchGuess, -1))
			return FALSE;
	}
	return ili < (LONG)Count();
}

/*
 *	CDisplayML::WaitForRecalcView()
 *
 *	@mfunc
 *		Ensure visible lines are completly recalced
 *
 *	@rdesc TRUE iff successful
 */
BOOL CDisplayML::WaitForRecalcView()
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::WaitForRecalcView");

	return WaitForRecalc(-1, _yScroll + _yHeightView);
}

/*
 *	CDisplayML::InitLinePtr ( CLinePtr & plp )
 *
 *	@mfunc
 *		Initialize a CLinePtr properly
 */
void CDisplayML::InitLinePtr (
	CLinePtr & plp )		//@parm Ptr to line to initialize
{
	TRACEBEGIN(TRCSUBSYSDISP, TRCSCOPEINTERN, "CDisplayML::InitLinePtr");

    plp.Init( *this );
}

/*
 *	CDisplayML::GetLineText(ili, pchBuff, cchMost)
 *
 *	@mfunc
 *		Copy given line of this display into a character buffer
 *
 *	@rdesc
 *		number of character copied
 */
LONG CDisplayML::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, "CDisplayML::GetLineText");
    
	_TEST_INVARIANT_

	CTxtPtr tp (_ped, 0);

	// FUTURE (alexgo, ricksa): This is called from EM_GETLINE whose parameter
	// is a WPARAM which is unsigned we need to fix the type of ili.

	if(ili >= 0 && (ili < (LONG)Count() || WaitForRecalcIli(ili)))
	{
		cchMost = min(cchMost, (LONG)Elem(ili)->_cch);
		if(cchMost > 0)
		{
			tp.SetCp(CpFromLine(ili, NULL));
			return tp.GetText(cchMost, pchBuff);
		}
	}
	*pchBuff = TEXT('\0');
	return 0;
}

/*
 *	CDisplayML::LineCount
 *
 *	@mfunc	returns the number of lines in this control.  Note that for plain
 *			text mode, we will add on an extra line of the last character is
 *			a CR.  This is for compatibility with MLE
 *
 *	@rdesc	LONG
 */
LONG CDisplayML::LineCount() const
{
	LONG cLine = Count();

⌨️ 快捷键说明

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