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

📄 rtext.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// 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 RTEXT.C - Rich-text ptr class |
 *
 *		This text ptr consists of a plain text ptr (_rpTX), a char-format
 *		run ptr (_rpCF), and a para-format run ptr (_rpPF). This module
 *		contains the methods to manipulate this combination of run ptrs
 *		consistently.
 *	
 *	Authors:<nl>
 *		Original RichEdit code: David R. Fulmer <nl>
 *		Main implementation: Murray Sargent <nl>
 *		Undo and notification implementations: Alex Gounares <nl>
 *
 */

#include "_common.h"
#include "_edit.h"
#include "_frunptr.h"
#include "_rtext.h"
#include "_disp.h"
#include "_select.h"
#include "_m_undo.h"
#include "_antievt.h"
#include "_objmgr.h"

ASSERTDATA

#define DEBUG_CLASSNAME CRchTxtPtr
#include "_invar.h"

#ifdef DEBUG
/*
 *	CRchTxtPtr::Invariant
 */
BOOL CRchTxtPtr::Invariant( void ) const
{
	unsigned ch;
	DWORD cch;
	DWORD cchLength = GetTextLength();
	LONG cp;

#ifdef EXTREME_CHECKING
	const TCHAR *pch;
	const TCHAR *pchReverse;
	LONG cchvalid;
#endif // EXTREME_CHECKING
	
	_rpTX.Invariant();
	_rpCF.Invariant();
	_rpPF.Invariant();

	if( _rpCF.IsValid() )
	{
		// BEGIN tone down of assert for IME Rich composition.
		CFormatRun *pRun = _rpCF.Elem(0);

		if ( !IsIMERich() || !pRun || pRun->_iFormat != -1 || _rpCF.Count() != 1 )
		// END tone down
		{
			Assert(GetCp()   == (cp  = _rpCF.GetCp()));
			Assert(cchLength == (cch = _rpCF.GetCch()));
		}
	}

	if( _rpPF.IsValid() )
	{
		Assert(GetCp()   == (cp  = _rpPF.GetCp()));
		Assert(cchLength == (cch = _rpPF.GetCch()));

		CTxtPtr	tp(_rpTX);

		tp.AdvanceCp(_rpPF.GetCchLeft() - 1);
		ch = tp.GetChar();
		if(!IsASCIIEOP(ch))
		{
			_rpTX.MoveGapToEndOfBlock();			// Make it easier to see
			AssertSz(FALSE,							//  what's going on
				"CRchTxtPtr::Invariant: PF run doesn't end with EOP");
		}

#ifdef EXTREME_CHECKING
		// we don't do this check normally as it is _extremely_ slow.
		// However, it's very useful for catching para-format run problems

		// now make sure that each para format run ends on a paragraph mark!
		CFormatRunPtr	rppf(_rpPF);

		rppf.BindToCp(0);
		tp.BindToCp(0);

		do
		{
			tp.SetCp(rppf.GetCp() + rppf.GetRun(0)->_cch);
			if( !tp.IsAfterEOP() )
			{
				cp = tp.GetCp();

				pch = tp.GetPch(cchvalid);
				pchReverse = tp.GetPchReverse(cchvalid);
				pchReverse -= cchvalid;
		
				AssertSz(0, "ParaFormat Run not aligned along paragraphs!");
			}
		} while( rppf.NextRun() );
#endif // EXTREME_CHECKING
	}

	return TRUE;
}

#endif  // DEBUG

//======================= CRchTxtPtr constructors ========================================

CRchTxtPtr::CRchTxtPtr(CTxtEdit *ped) :
	_rpTX(ped, 0), _rpCF(NULL),	_rpPF(NULL)
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::CRchTxtPtr");

	InitRunPtrs(0);
}

CRchTxtPtr::CRchTxtPtr(CTxtEdit *ped, DWORD cp) :
	_rpTX(ped, cp), _rpCF(NULL),	_rpPF(NULL)
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::CRchTxtPtr");

	InitRunPtrs(cp);
}

CRchTxtPtr::CRchTxtPtr (const CRchTxtPtr& rtp) :
	_rpTX(rtp._rpTX), _rpCF(NULL), _rpPF(NULL)
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::CRchTxtPtr");

	InitRunPtrs(rtp.GetCp());
}

CRchTxtPtr::CRchTxtPtr (const CDisplay * pdp) :
	_rpTX(pdp->GetED(), 0), _rpCF(NULL), _rpPF(NULL)
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::CRchTxtPtr");

	InitRunPtrs(0);
}

/*
 *	CRchTxtPtr::Advance(cch)
 *	
 *	@mfunc
 *		Move this rich-text ptr forward <p cch> characters.  If <p cch>
 *		<lt> 0, move backward by -<p cch> characters.
 *	
 *	@rdesc
 *		cch actually moved
 *
 */
LONG CRchTxtPtr::Advance(
	LONG cch)			// @parm count of characters to move - may be <lt> 0
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::Advance");

	if( cch != 0 )
	{
		cch = _rpTX.AdvanceCp(cch);
		_rpCF.AdvanceCp(cch);
		_rpPF.AdvanceCp(cch);
	}

	_TEST_INVARIANT_

	return cch;
}

/*
 *  CRchTxtPtr::AdvanceCRLF()
 *
 *  @mfunc
 *      Advance this text ptr one char, treating CRLF as a single char.
 *
 *  @rdesc
 *      cch actually moved
 */
LONG CRchTxtPtr::AdvanceCRLF()
{
    TRACEBEGIN(TRCSUBSYSRANG, TRCSCOPEINTERN, "CRchTxtPtr::AdvanceCRLF");

    LONG cch = _rpTX.AdvanceCpCRLF();
    _rpPF.AdvanceCp(cch);
    _rpCF.AdvanceCp(cch);
    return cch;
}

/*
 *  CRchTxtPtr::BackupCRLF()
 *
 *  @mfunc
 *      Backup this text ptr one char, treating CRLF as a single char.
 *
 *  @rdesc
 *      cch actually moved
 */
LONG CRchTxtPtr::BackupCRLF()
{
    TRACEBEGIN(TRCSUBSYSRANG, TRCSCOPEINTERN, "CRchTxtPtr::BackupCRLF");

    LONG cch = _rpTX.BackupCpCRLF();
    _rpPF.AdvanceCp(cch);
    _rpCF.AdvanceCp(cch);
    return cch;
}

/*
 * CRchTxtPtr::ValidateCp(&cp)
 *
 *	@mfunc
 *		If <p cp> <lt> 0, set it to 0; if it's <gt> text length, set it to
 *		text length.
 */
void CRchTxtPtr::ValidateCp(
	LONG &cp) const			// @parm new cp for this text ptr
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::ValidateCp");

	LONG cchT = GetTextLength();

	cp = min(cp, cchT);				// Be sure cp is valid
	cp = max(cp, 0);
}

/*
 * CRchTxtPtr::SetCp(cp)
 *
 *	@mfunc
 *		Set this rich text ptr's cp to cp
 */
DWORD CRchTxtPtr::SetCp(
	DWORD cp)			// @parm new cp for this text ptr
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::SetCp");

	CRchTxtPtr::Advance(cp - GetCp());
	return GetCp();
}

/*	CRchTxtPtr::GetIchRunXX() and CRchTxtPtr::GetCchRunXX()
 *
 *	@mfunc
 *		Text-run management to retrieve current text run cch and offset
 *
 *	@rdesc
 *		current run ich or cch
 *
 *	@devnote
 *		Use of queries like _rpCF.IsValid() instead of an inclusive fRich
 *		allows rich-text formatting to be applied per rich-text category,
 *		e.g., CHARFORMATs, but not necessarily PARAFORMATs.  If the rp isn't
 *		valid, _cp is used for ich and the document length is used for cch,
 *		i.e., the values for a document describable by a single plain-text run
 */
LONG CRchTxtPtr::GetIchRunCF()
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::GetIchRunCF");

	return _rpCF.IsValid() ? _rpCF.GetIch() : GetCp();
}

LONG CRchTxtPtr::GetCchRunCF() 
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::GetCchRunCF");

	return _rpCF.IsValid() ? _rpCF.GetRun(0)->_cch : GetTextLength();
}

/*	CRchTxtPtr::GetCchLeftRunCF() / GetCchLeftRunPF()
 *
 *	@mfunc
 *		Return cch left in run, i.e., cchRun - ich
 *
 *	@rdesc
 *		cch left in run
 */
LONG CRchTxtPtr::GetCchLeftRunCF() 
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::GetCchLeftRunCF");

	return _rpCF.IsValid()
		? _rpCF.GetCchLeft() : GetTextLength() - GetCp();
}

LONG CRchTxtPtr::GetCchLeftRunPF() 
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::GetCchLeftRunPF");

	return _rpPF.IsValid()
		? _rpPF.GetCchLeft() : GetTextLength() - GetCp();
}

/*
 *	CRchTxtPtr::FindText(cpMost, dwFlags, pch, cchToFind)
 *	
 *	@mfunc
 *		Find text in a range starting at this text pointer;
 *		if found, moves this text pointer to that position.
 *	
 *	@rdesc
 *		character position of first match
 *		<lt> 0 if no match
 *
 *	@devnote
 *		Would be easy to match a single format (like Word 6) provided
 *		cchToFind is nonzero.  Else need to search runs (also pretty easy).
 *		For format-sensitive searches, might be easier to search for matching
 *		format run first and then within that run search for text.
 */
LONG CRchTxtPtr::FindText (
	LONG		cpMost,		// @parm Limit of search; <lt> 0 for end of text
	DWORD		dwFlags,	// @parm FR_MATCHCASE	case must match
							//		 FR_WHOLEWORD	match must be a whole word
	TCHAR const *pch,		// @parm Text to search for
	LONG		cchToFind)	// @parm Length of text to search for
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::FindText");

	_TEST_INVARIANT_

	LONG cpSave = GetCp();
	LONG cpMatch = _rpTX.FindText(cpMost, dwFlags, pch, cchToFind);

	if(cpMatch >= 0)					// cpMatch = -1 means "not found"
		SetRunPtrs(GetCp(), cpSave);	
	
			// possible code for format-dependent Finds

	return cpMatch;
}

/*
 *	CRchTxtPtr::GetCF()/GetPF()
 *	
 *	@mfunc
 *		Return ptr to CCharFormat/CParaFormat at this text ptr. If no CF/PF runs
 *		are allocated, then return ptr to default format
 *	
 *	@rdesc
 *		Ptr to CCharFormat/CParaFormat at this text ptr
 */
const CCharFormat* CRchTxtPtr::GetCF() const
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::GetCF");

	return GetPed()->GetCharFormat(_rpCF.GetFormat());
}

const CParaFormat* CRchTxtPtr::GetPF() const
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::GetPF");

	return GetPed()->GetParaFormat(_rpPF.GetFormat());
}

/*
 *	CRchTxtPtr::ReplaceRange(cchOld, cchNew, *pch, pcpFirstRecalc, publdr,
 *							 iFormat)
 *	@mfunc
 *		Replace a range of text at this text pointer using CCharFormat iFormat
 *		and updating other text runs as needed
 *	
 *	@rdesc
 *		Count of new characters added
 *	
 *	@devnote
 *		Moves this text pointer to end of replaced text.
 *		May move text block and formatting arrays.
 */
LONG CRchTxtPtr::ReplaceRange(
	LONG		cchOld,		// @parm length of range to replace
							//		(<lt> 0 means to end of text)
	LONG		cchNew,		// @parm length of replacement text
	TCHAR const *pch,		// @parm replacement text
	IUndoBuilder *publdr,	// @parm CCharFormat iFormat to use for cchNew
	LONG		iFormat)
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CRchTxtPtr::ReplaceRange");

	LONG		  cch;
	LONG		  cchEndEOP = 0;				// Default 0 final EOP fixup
	LONG		  cchMove = 0;					// Default nothing to move
	LONG		  cchNextEOP = cchOld;			// cch to next EOP
	LONG		  cchPrevEOP = 0;				// cch back to previous EOP
	LONG		  cpFR;							//  between PF runs
	LONG 		  cpSave = GetCp();
	LONG		  cpFormatMin = cpSave;			// Used for notifications
	LONG		  cpFormat = cpSave;			// Will add cchOld, maybe cchMove
	IAntiEvent *  paeCF = NULL;
	IAntiEvent *  paePF = NULL;
	CNotifyMgr *  pnm;
	CObjectMgr *  pobjmgr;

 	_TEST_INVARIANT_

	LONG cchEnd = GetTextLength() - GetCp();
	if(cchOld < 0)
		cchOld = cchEnd;

  	if(IsRich() && cchOld == cchEnd)			// Attempting to delete up
	{											//  thru final EOP
		cchEndEOP = (GetPed()->Get10Mode())		// Calc cch of final EOP
				  ? CCH_EOD_10 : CCH_EOD_20;

		if(cchEndEOP <= cchOld)					// Don't delete it unless
			cchOld -= cchEndEOP;				//  converting from 2.0
	}
	else if(_rpPF.IsValid() && cchOld)			// If PARAFORMATs are enabled,
	{											//  get tp and rp at end of 
		CFormatRunPtr rp(_rpPF);				//  range. Need bounding para
		CTxtPtr 	  tp(_rpTX);				//  counts to save valid PF
		BOOL		  fIsAtBOP;					//  for undo

		tp.AdvanceCp(cchOld);
		rp.AdvanceCp(cchOld);

		cch = 0;
		if(tp.IsAfterEOP())						// Range ends with an EOP:
		{										//  get EOP length by
			cch = -tp.BackupCpCRLF();			//  backing up over it
			tp.AdvanceCp(cch);					// Advance past EOP
		}
		cchNextEOP = tp.FindEOP(tomForward);	// Get cch up to next EOP

⌨️ 快捷键说明

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