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

📄 text.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	{
		ptb = Elem(itb);
		AssertSz(cch < ptb->_cch, "last block too small");
		ptb->MoveGap(0);
		ptb->_cch -= cch;
#ifdef DEBUG
		((CTxtArray *)_prgRun)->Invariant();
#endif // DEBUG

	}
	((CTxtArray *)_prgRun)->CombineBlocks(_iRun);

	if(_iRun >= Count() || !Elem(_iRun)->_cch)
		BindToCp(_cp);					// Empty block: force tp rebind

	AssertSz (GetTextLength() == 
				((CTxtArray *)_prgRun)->GetCch(), 
				"CTxtPtr::DeleteRange(): _prgRun->_cchText messed up !");
}

/*
 *	CTxtPtr::FindText (cpMost, dwFlags, pch, cchToFind)
 *
 *	@mfunc
 *		Find the text string <p pch> of length <p cchToFind> starting at this
 *		text pointer. If found, move this text pointer to the end of the
 *		matched string and return the cp of the first character of the matched
 *		string.  If not found, return -1 and don't change this text ptr.
 *	
 *	@rdesc
 *		character position of first match
 *		<lt> 0 if no match
 */
LONG CTxtPtr::FindText (
	LONG		cpLimit, 	//@parm limit of search or <lt> 0 for end of text
	DWORD		dwFlags, 	//@parm FR_MATCHCASE	case must match <nl>
							//		FR_WHOLEWORD	match must be a whole word
	TCHAR const *pch, 		//@parm text to search for
	const DWORD cchToFind)	//@parm length of text to search for
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CTxtPtr::FindText");

	_TEST_INVARIANT_

	BOOL		bTemp;					// Used in find-first-char loops
	LONG		cch;
	const DWORD	cchAdjText	= _ped->GetAdjustedTextLength();
	LONG		cchChunk, cchChunkForward = 0;
	LONG		cchLeft;
	LONG		cchLimitFirst;			
	const DWORD	cchText		= GetTextLength();
	LONG		cchUnmatched;
	LONG		cchValid;
	TCHAR		chFirst;
	LONG		cpMatch;
	BOOL		fIgnoreCase		= !(FR_MATCHCASE & dwFlags);
	BOOL		fSearchForward	= FR_DOWN & dwFlags;
	BOOL		fWholeWord;
	const int	Direction = fSearchForward ? 1 : -1; // Which dir to step?
	const TCHAR *pchCurrent;
	const TCHAR *pchSave;
	const TCHAR *pchStart;				// ptr to start of new block search
	CTxtPtr		tp(*this);				// tp used to walk CTxtBlk chunks
	EDITWORDBREAKPROC pfnWB = _ped->_pfnWB;

	if( !cchToFind )
	{
		return -1;
	}

	if ( fSearchForward )
	{
		if((DWORD)cpLimit > cchText)			// NB: catches cpLimit < 0 too
			cpLimit = cchText;
		cch = cpLimit - _cp;
	}
	else
	{
		if((DWORD)cpLimit > _cp)				// NB: catches cpLimit < 0 too
			cpLimit = 0;
		cch = _cp - cpLimit;   
	}
	if((LONG)cchToFind > cch)
		return -1;

	chFirst = pch[0];
	if(fIgnoreCase)
	{
		// Read Win32 spec to understand the following strange casts
		chFirst = TCHAR (CharLower ((LPTSTR) chFirst));
	}

	cchLimitFirst = cch - (LONG)cchToFind + 1;				 
	if (! fSearchForward )	
	{
		 tp.AdvanceCp(-(LONG)cchToFind + 1);
	}

	while(cchLimitFirst > 0)
	{
		// Fetch how many characters are remaining for this pchCurrent. If
		// searching in reverse, fetch how many characters there are to the
		// start of pchCurrent.
		// NOTE: strings pointed to by pchCurrent are delineated by blocks
		//		 or block gaps.

		if ( fSearchForward )
		{
			pchCurrent = tp.GetPch(cchChunk);
			cchChunk = min(cchLimitFirst, cchChunk);
			tp.AdvanceCp(cchChunk);
			cchChunkForward = cchChunk;					// cch to tp.GetCp()
		}
		else
		{
			pchCurrent = tp.GetPchReverse(cchChunk, &cchChunkForward);
			pchCurrent--;
			cchChunkForward++;
			cchChunk = min(cchLimitFirst, cchChunk);
			tp.AdvanceCp(-cchChunk);
		}

		if( !pchCurrent )
		{
			return -1;
		}

		pchSave = pchStart = pchCurrent;				// Save starting ptr
		cchLimitFirst -= cchChunk;
		while(cchChunk > 0)
		{
			// Match first char
			if ( fIgnoreCase )
				do {
					bTemp = ( 2 == CompareString(LOCALE_USER_DEFAULT,
						NORM_IGNORECASE | NORM_IGNOREWIDTH, 
						pchCurrent, 1, &chFirst, 1) );
					pchCurrent += Direction;
				} while(!bTemp && --cchChunk > 0);
			else
				do {
					bTemp = TCHAR( *pchCurrent ) == chFirst;
					pchCurrent += Direction;
				} while(!bTemp && --cchChunk > 0);
			
			cchChunkForward += pchSave - pchCurrent;	// cch still valid
														//  for pchCurrent
			pchSave = pchCurrent;
			if(!fSearchForward)							// Setup is for
			{											//  forward match
				pchCurrent += 2;
				cchChunkForward -= 2;
			}						

			// Found first character; now find rest of string. Common routine
			// for forward and backward: in both cases, we match the rest of
			// the string going forward.

			if(cchChunk > 0)
			{
				cchChunk--;
				cchLeft = min((LONG)cchToFind - 1, cchChunkForward);

				if( fIgnoreCase )
				{
					if ( !cchLeft )
					{
						// nothing to compare, we find a match
						cchUnmatched = FALSE;
					}
					else
					{
						// Note: CompareString returns 2 if the two strings matched.
						cchUnmatched = !( 2 == CompareString( LOCALE_USER_DEFAULT, 
							NORM_IGNORECASE | NORM_IGNOREWIDTH, 
							&pch[1], cchLeft, pchCurrent, cchLeft) ) ;
					}
				}
				else
				{
					cchUnmatched = wcsncmp( &pch[1], pchCurrent, cchLeft);
				}

				if(!cchUnmatched)					
				{										
					// Matched whole (or partial) string. Calculate potential
					// match cpFirst
					cpMatch = tp.GetCp() + (fSearchForward ? 
								( -cchChunk - 1) : cchChunk );

					fWholeWord = (dwFlags & FR_WHOLEWORD) &&
								 ((DWORD)cpMatch + cchToFind <= cchAdjText);

					// Check for word delimiter before the match
					if((dwFlags & FR_WHOLEWORD) && cpMatch > 0)
					{
						CTxtPtr tpT(_ped, cpMatch - 1);

						if((pfnWB((LPTSTR)tpT.GetPch(cchValid), 0,
							sizeof(TCHAR), WB_CLASSIFY) & WBF_CLASS) == 0)
						{ goto no_match; }
					}

					// doesn't attempt to check next char if there isn't one

					if((LONG)cchToFind - 1 < cchChunkForward)
					{
						// pchCurrent is valid for one or more chars, so are
						// either done or can check for word delimeter

						// CTxtPtr tpT(_ped, cpMatch + cchToFind);
						// TCHAR* temptemp=tpT.GetPch();

						if (!fWholeWord || 
							(pfnWB((LPTSTR)(pchCurrent + cchLeft), 0,
								sizeof(TCHAR),WB_CLASSIFY) & WBF_CLASS) != 0)
						{ goto done; }
					}
					else	// Need to compare across chunks
						if(tp.MatchAcrossChunks(dwFlags, cchChunkForward,
								pch + 1, cchToFind - 1, fWholeWord, pfnWB))
					{ goto done; }
				}
no_match:
				pchCurrent = pchSave;
			}
		}
	}
	return -1;								// No match

done:
	if (cpMatch >= 0)
		SetCp(cpMatch + cchToFind);			// Match: set this tp just past
											//  match. When we have wildcard
	return cpMatch;							//  chars, we may need something
}											//  more general than cchToFind

/* 
 *	CTxtPtr::MatchAcrossChunks (dwFlags, cchChunkForward, pch, cchToMatch, 
 *								fWholeWord, pfnWB)
 *
 *	@mfunc		helper function for FindText
 *
 *	@rdesc		TRUE if match found
 *
 *	@comm		"*this" points to char to check against pch[cchMatched]
 */
#define __OPT_PLAT_FLAG (defined (ARMV4T))
#define __OPT_VER_OFF
#define	__OPT_BUGNUMSTRING	"26316"
#include <optimizer.h>

INLINE BOOL CTxtPtr::MatchAcrossChunks (
	DWORD		 dwFlags,			//@parm Search flags
	DWORD		 cchMatched,		//@parm Amount already matched
	const TCHAR *pch, 				//@parm String to match against
	DWORD		 cchToMatch,		//@parm Total cch to match 
	BOOL		 fWholeWord,		//@parm Match against whole word
	EDITWORDBREAKPROC pfnWB) const	//@parm Word break proc
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CTxtPtr::MatchAcrossChunks");

	_TEST_INVARIANT_

	LONG		 cchChunk;
	LONG		 cchValid;
	const TCHAR *pchCurrent;
	CTxtPtr		 tp(*this);			// tp already points to next 
									// chunk if searching forward.

	BOOL	fSearchForward	= (FR_DOWN & dwFlags) != 0;
	BOOL	fIgnoreCase		= (FR_MATCHCASE & dwFlags) == 0;

	if ( !fSearchForward )
	{
		// even though the overall search is in reverse, the compare is done
		// forward.
		tp.GetPch(cchValid);		// searching in reverse leaves _cp at previous chunk
		tp.AdvanceCp(cchValid);		// line it back up with searching forward.
	}

	pch += cchMatched;							// Bypass chars already matched
	cchToMatch -= cchMatched;
	if(!cchToMatch)
		pchCurrent = tp.GetPch(cchValid);

	while(cchToMatch > 0)
	{
		pchCurrent = tp.GetPch(cchChunk);
		if(cchChunk <= 0)
			return FALSE;
		cchChunk = min(cchChunk, (LONG)cchToMatch);
		tp.AdvanceCp(cchChunk);
		cchToMatch -= cchChunk;

		if ( fIgnoreCase )
		{
#ifdef PWD_JUPITER
			// GuyBark Jupiter 50123: fIgnoreCase means ignore width too. 
			// So take the same action as elsewhere when comparing strings.
			// Both pch and pchCurrent point to strings that are at least
			// cchChunk long.

			// Note: CompareString returns 2 if the two strings matched.
			if(CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_IGNOREWIDTH, 
			                 pchCurrent, cchChunk, pch, cchChunk) == 2)
			{
			    // Strings are close enough! Set things up as they would be set
			    // up using the ifdef'd out comparison test. Don't actually 
			    // need to set up pchCurrent here, but can't do any harm.

			    pch        += cchChunk;
			    pchCurrent += cchChunk;
			
			    cchChunk = 0;
			}

			// If the comparison failed, we don't need to mess with the pointers here,
			// as we're going to leave anyway below because cchChunk is still non-zero.
#else
			do {
				if ( TCHAR (CharLower ( (LPTSTR) *pchCurrent++ )) != TCHAR (CharLower ( (LPTSTR) *pch++ )) )
					break;
			} while( --cchChunk > 0);
#endif // PWD_JUPITER
		}
		else
		{
			do {
				if ( *pchCurrent++ != *pch++ )
					break;
			} while( --cchChunk > 0);
		}
				
		if(cchChunk > 0)
			return FALSE;
	}

	return !fWholeWord || (pfnWB((LPTSTR)tp.GetPch(cchValid), 0,
							sizeof(TCHAR), WB_CLASSIFY)	& WBF_CLASS);
}

#define __OPT_PLAT_FLAG (defined (ARMV4T))
#define __OPT_VER_RESTORE
#define	__OPT_BUGNUMSTRING	"26316"
#include <optimizer.h>

/*
 *	CTxtPtr::FindEOP(cchMax)
 *	
 *	@mfunc
 *		Find EOP mark in a range within cchMax chars from this text pointer
 *		and position *this after it.  If no EOP is found and cchMax is not
 *		enough to reach the start or end of the story, leave this text ptr
 *		alone and return 0.  If no EOP is found and cchMax is sufficient to
 *		reach the start or end of the story, position this text ptr at the
 *		beginning/end of document (BOD/EOD) for cchMax <lt>/<gt> 0,
 *		respectively, that is, BOD and EOD are treated as a BOP and an EOP,
 *		respectively.	
 *
 *	@rdesc
 *		Return cch this text ptr is moved
 *
 *	@devnote
 *		This function assumes that this text ptr isn't in middle of a CRLF
 *		or CRCRLF (found only in RichEdit 1.0 compatibility mode).  Changing
 *		the for loop could speed up ITextRange MoveUntil/While substantially.
 */
LONG CTxtPtr::FindEOP (
	LONG  cchMax,		//@parm Max signed count of chars to search
	LONG *pResults)		//@parm Flags saying if EOP and CELL are found
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CTxtPtr::FindEOP");

	LONG		cch = 0, cchStart;			// cch's for scans
	unsigned	ch;							// Current char
	DWORD		cpSave	= _cp;				// Save _cp for returning delta
	LONG		iDir	= 1;				// Default forward motion
	const TCHAR*pch;						// Used to walk text chunks
	LONG		Results = 0;				// Nothing found yet
	CTxtPtr		tp(*this);					// tp to search text with

	if(cchMax < 0)							// Backward search
	{
		iDir = -1;							// Backward motion
		cchMax = -cchMax;					// Make max count positive
		cch = tp.AdjustCpCRLF();			// If in middle of CRLF or
		if(!cch && IsAfterEOP())			//  CRCRLF, or follow any EOP,
			cch = tp.BackupCpCRLF();		//  backup before EOP
		cchMax += cch;
	}

	while(cchMax > 0)						// Scan until get out of search
	{										//  range or match an EOP
		pch = iDir > 0						// Point pch at contiguous text
			? tp.GetPch(cch)				//  chunk going forward or
			: tp.GetPchReverse(cch);		//  going backward

		if(!pch)							// No more text to search
			break;

		if(iDir < 0)						// Going backward, point at
			pch--;							//  previous char

		cch = min(cch, cchMax);				// Limit scan to cchMax chars
		for(cchStart = cch; cch; cch--)		// Scan chunk for EOP
		{
                    if (!pch)
                        break;
                     ch = *pch;
			if(ch == CELL)
				Results |= FEOP_CELL;		// Note that CELL was found

			if(IsEOP(ch))					// Note that EOP was found
			{								// Going forward, cch may = 0
				Results |= FEOP_EOP;		
				break;
			}
			pch += iDir;
		}
		cchStart -= cch;					// Get cch of chars passed by
		cchMax -= cchStart;					// Update cchMax
		tp.AdvanceCp(iDir*cchStart);		// Update tp
		if((Results & FEOP_EOP) || !(pch))				// Found an EOP
			break;
	}										// Continue with next chunk

	if(pResults)							// Report whether EOP and CELL
		*pResults = Results;				//  were found

	if(Results & FEOP_EOP || !tp.GetCp())	// Found EOP or cp is at beginning
	{										//  of story:
		SetCp(tp.GetCp());					//  set _cp = cp
		if(GetChar() == LF)					// In case there's a LF there,
			AdvanceCp(1);					//  bypass it
		else if(iDir > 0)					// Position this ptr just after
			AdvanceCpCRLF();				//  EOP
	}
	return _cp - cpSave;					// Return cch this tp moved
}

/*
 *	CTxtPtr::FindBOSentence(cch)
 *	
 *	@mfunc
 *		Find beginning of sentence in a range within cch chars from this text
 *		pointer and	position *this at it.  If no sentence beginning is found,
 *		position *this at beginning of document (BOD) for cch <lt> 0 and
 *		leave *this unchanged for cch >= 0.
 *
 *	@rdesc
 *		Count of chars moved *this moves
 *
 *	@comm 
 *		This routine defines a sentence as a character string that ends with
 *		period followed by at least one whitespace character or the EOD.  This
 *		should be replacable so that other kinds of sentence endings can be
 *		used.  This routine also matches initials like "M. " as sentences.
 *		We could eliminate those by requiring that sentences don't end with
 *		a word consisting of a single capital character.  Similarly, common
 *		abbreviations like "Mr." could be bypassed.  To allow a sentence to
 *		end with these "words", two blanks following a period could be used
 *		to mean an unconditi

⌨️ 快捷键说明

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