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

📄 text.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CTxtPtr::AdjustCpCRLF");

	_TEST_INVARIANT_

	LONG	 cpSave = _cp;
	unsigned ch		= GetChar();

//	To support UTF-16, include the following code
//	if((ch & UTF16) == UTF16_TRAIL)
//		AdvanceCp(-1);

	if(!IsASCIIEOP(ch))							// Early out
		return 0;

	if(ch == LF && cpSave && PrevChar() != CR)	// Landed on LF not preceded
	{											//  by CR, so go back to LF
		AdvanceCp(1);							// Else on CR of CRLF or 
	}											//  second CR of CRCRLF

	if(GetChar() == CR)							// Land on a CR of CRLF or
	{											//  second CR of CRCRLF?
		CTxtPtr tp(*this);

		if(tp.NextChar() == LF)
		{
			tp.AdvanceCp(-2);					// First CR of CRCRLF ?
			if(tp.GetChar() == CR)				// Yes or CRLF is at start of
				AdvanceCp(-1);					//  story. Try to back up over
		}										//  CR (If at BOS, no effect)
	}
	return _cp - cpSave;
}

/*
 *	CTxtPtr::IsAtEOP()
 *	
 *	@mfunc
 *		Return TRUE iff this text pointer is at an end-of-paragraph mark
 *	
 *	@rdesc
 *		TRUE if at EOP
 *
 *	@devnote
 *		End of paragraph marks for RichEdit 1.0 and the MLE can be CRLF
 *		and CRCRLF.  For RichEdit 2.0, EOPs can also be CR, VT (0xb - Shift-
 *		Enter), and FF (0xc - page break).
 */
BOOL CTxtPtr::IsAtEOP()
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CTxtPtr::IsAtEOP");

	_TEST_INVARIANT_

	unsigned ch = GetChar();

	if(IsASCIIEOP(ch))							// See if LF <= ch <= CR
	{											// Clone tp in case
		CTxtPtr tp(*this);						//  AdjustCpCRLF moves
		return !tp.AdjustCpCRLF();				// Return TRUE unless in
	}											//  middle of CRLF or CRCRLF
	return (ch | 1) == PS;						// Allow Unicode 0x2028/9 also
}

/*
 *	CTxtPtr::IsAfterEOP()
 *	
 *	@mfunc
 *		Return TRUE iff this text pointer is just after an end-of-paragraph
 *		mark
 *	
 *	@rdesc
 *		TRUE iff text ptr follows an EOP mark
 */
BOOL CTxtPtr::IsAfterEOP()
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CTxtPtr::IsAfterEOP");

	_TEST_INVARIANT_

	CTxtPtr tp(*this);							// Clone to look around with
	TCHAR ch = GetChar();

	if(IsASCIIEOP(GetChar()) &&					// If in middle of CRLF
		tp.AdjustCpCRLF())						//  or CRCRLF, return FALSE
	{
		return FALSE;
	}

	return IsEOP(tp.PrevChar());				// After EOP if after Unicode
}								   				//  PS or LF, VT, FF, or CR

// needed for the routine below
#if cchGapInitial < 1
#error "cchGapInitial must be at least one"
#endif

/*
 *	CTxtPtr::FindWordBreak(action, cpMost)
 *	
 *	@mfunc
 *		Find a word break and move this text pointer to it.
 *
 *	@rdesc
 *		Offset from cp of the word break
 */
LONG CTxtPtr::FindWordBreak(
	INT		action,		//@parm See TxWordBreakProc header
	LONG	cpMost)		//@parm Limiting character position
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "CTxtPtr::FindWordBreak");

	_TEST_INVARIANT_

	const INT			breakBufSize = 16;
	LONG				bufferSize;
	LONG				cch;
	LONG				cchBuffer;
	LONG				cchChunk;
	DWORD				cchText = GetTextLength();
	TCHAR				ch = GetChar();
	TCHAR				chBreakBuf[breakBufSize];
	LONG				cpSave = _cp;				// For calculating break pt
	LONG				ichBreak;
	TCHAR *				pBuf;
	TCHAR const *		pch;
	EDITWORDBREAKPROC	pfnWB = _ped->_pfnWB;
	LONG				t;							// Temp for abs() macro

	if(action == WB_CLASSIFY || action == WB_ISDELIMITER)
	{
		return ch ? pfnWB(&ch, 0, CbOfCch(1), action) : 0;
	}

	if(action & 1)									// Searching forward
	{												// Easiest to handle EOPs			
		if(action == WB_MOVEWORDRIGHT && IsEOP(ch))	//  explicitly (spanning
		{											//  a class can go too
			AdjustCpCRLF();							//  far). Go to end of
			AdvanceCpCRLF();						//  EOP "word"
			goto done;
		}
													// Calc. max search
		if((DWORD)cpMost > cchText)					// Bounds check: get < 0
			cpMost = cchText;						//  as well as too big
		cch = cpMost - _cp;

		while(cch > 0)
		{											// The independent buffer
			cchBuffer = min(cch, breakBufSize - 1);	//  avoids gaps in BS
			cch -= bufferSize = cchBuffer;
			pBuf = chBreakBuf;						// Fill buffer forward

			// Grab the first character in reverse for fnWB that require 2
			// chars. Note, we play with _ich to get single char fnWB
			// to ignore this character.			 							
			pch = GetPchReverse(cchChunk);
			if ( !cchChunk ) pch = L" ";			// Any break char
			*pBuf++ = *pch;

			while ( cchBuffer )						// Finish filling
			{
				pch = GetPch(cchChunk);
				if (!cchChunk) { Assert(0); break; }

				cchChunk = min(cchBuffer, cchChunk);
				AdvanceCp(cchChunk);
				wcsncpy(pBuf, pch, cchChunk);
				pBuf += cchChunk;
				cchBuffer -= cchChunk;
			}
			ichBreak = pfnWB(chBreakBuf, 1,			// Find the break
						CbOfCch(bufferSize+1), action) - 1;

			// Apparently, some fnWBs return ambiguous results
			if(ichBreak >= 0 && ichBreak <= bufferSize)
			{
				// Ambiguous break pt?
				// Due to the imprecise nature of the word break proc spec,
				// we've reached an ambiguous condition where we don't know
				// if this is really a break, or just the end of the data.
				// By backing up or going forward by 2, we'll know for sure.
				// NOTE: we'll always be able to advance or go back by 2
				// because we guarantee that when !cch that we have
				// at least breakBufSize (16) characters in the data stream.
				if (ichBreak < bufferSize || !cch)
				{
					AdvanceCp( ichBreak - bufferSize );
					break;
				}

				// Need to recalc break pt to disambiguate
				t = AdvanceCp(ichBreak - bufferSize - 2);	// abs() is a
				cch += abs(t);						//  macro
			}
		}
	}
	else	// REVERSE - code dup based on EliK "streams" concept.
	{
		if(!_cp)									// Can't go anywhere
			return 0;

		if(action == WB_MOVEWORDLEFT)				// Easiest to handle EOPs			
		{											//  here
			if(IsASCIIEOP(ch) && AdjustCpCRLF())	// In middle of a CRLF or
				goto done;							//  CRCRLF "word"
			ch = PrevChar();						// Check if previous char
			if(IsEOP(ch))							//  is an EOP char
			{
				if(ch == LF)						// Backspace to start of
					AdjustCpCRLF();					//  CRLF and CRCRLF
				goto done;
			}
			AdvanceCp(1);							// Move back to start char
		}
													// Calc. max search
		if((DWORD)cpMost > _cp)						// Bounds check (also
			cpMost = _cp;							//  handles cpMost < 0)
		cch = cpMost;

		while(cch > 0)
		{											// The independent buffer
			cchBuffer = min(cch, breakBufSize - 1);	//  avoids gaps in BS
			cch -= bufferSize = cchBuffer;
			pBuf = chBreakBuf + cchBuffer;			// Fill from the end.

			// Grab the first character forward for fnWB that require 2 chars.
			// Note: we play with _ich to get single char fnWB to ignore this
			// character.
			pch = GetPch(cchChunk);
			if ( !cchChunk ) pch = L" ";			// Any break char
			*pBuf = *pch;

			while ( cchBuffer > 0 )					// Fill rest of buffer 
			{										//  before going in reverse
				pch = GetPchReverse(cchChunk );
				if (!cchChunk) { Assert(0); break; }

				cchChunk = min(cchBuffer, cchChunk);
				AdvanceCp(-cchChunk);
				pch -= cchChunk;
				pBuf -= cchChunk;
				wcsncpy(pBuf, pch, cchChunk);
				cchBuffer -= cchChunk;
			}
													// Get break left.
			ichBreak = pfnWB(chBreakBuf, bufferSize,
							 CbOfCch(bufferSize+1), action);
			
			// Apparently, some fnWBs return ambiguous results
			if(ichBreak >= 0 && ichBreak <= bufferSize)
			{										// Ambiguous break pt?
				// NOTE: when going in reverse, we have >= bufsize - 1
				//  because there is a break-after char (hyphen).
				if ( ichBreak > 0 || !cch )
				{
					AdvanceCp(ichBreak);			// Move _cp to break point.
					break;
				}													
				cch += AdvanceCp(2 + ichBreak);		// Need to recalc break pt
			}										//  to disambiguate.
		}
	}

done:
	return _cp - cpSave;							// Offset of where to break
}

/*
 *	INT CALLBACK TxWordBreakProc (pch, ich, cb, action)
 *	
 *	@func
 *		Default word break proc used in conjunction with FindWordBreak. ich
 *		is character offset (start position) in the buffer pch, which is cb
 *		bytes in length.  Possible action values are:
 *
 *	WB_CLASSIFY
 *		Returns char class and word break flags of char at start position.
 *
 *	WB_ISDELIMITER
 *		Returns TRUE iff char at start position is a delimeter.
 *
 *	WB_LEFT
 *		Finds nearest word beginning before start position using word breaks.
 *
 *	WB_LEFTBREAK
 *		Finds nearest word end before start position using word breaks.
 *		Used by CMeasurer::Measure()
 *
 *	WB_MOVEWORDLEFT
 *		Finds nearest word beginning before start position using class
 *		differences. This value is used during CTRL+LEFT key processing.
 *
 *	WB_MOVEWORDRIGHT
 *		Finds nearest word beginning after start position using class
 *		differences. This value is used during CTRL+RIGHT key processing.
 *
 *	WB_RIGHT
 *		Finds nearest word beginning after start position using word breaks.
 *		Used by CMeasurer::Measure()
 *
 *	WB_RIGHTBREAK
 *		Finds nearest word end after start position using word breaks.
 *	
 *	@rdesc
 *		Character offset from start of buffer (pch) of the word break
 */
INT CALLBACK TxWordBreakProc(
	TCHAR const *pch,	//@parm Char buffer
	INT			ich,	//@parm Char offset of _cp in buffer
	INT			cb,		//@parm Count of bytes in buffer
	INT			action)	//@parm Type of breaking action
{
	TRACEBEGIN(TRCSUBSYSBACK, TRCSCOPEINTERN, "TxWordBreakProc");

	LONG	cchBuff = CchOfCb(cb);
	LONG	cch = cchBuff - ich;
	TCHAR	ch;
	WORD	cType3[MAX_CLASSIFY_CHARS];
	INT		kinsokuClassifications[MAX_CLASSIFY_CHARS];
	WORD *	pcType3;
	INT  *	pKinsoku1, *pKinsoku2;
	WORD *	pwRes;
	WORD	startType3 = 0;
	WORD	wb = 0;
	WORD	wClassifyData[MAX_CLASSIFY_CHARS];	// For batch classifying

       if ((!(cchBuff < MAX_CLASSIFY_CHARS)) || (!(ich >= 0 && ich < cchBuff)))
        {
            Assert(0);
            return ich;
        }
	
	// Single character actions
	if ( action == WB_CLASSIFY )
		return ClassifyChar(pch[ich]);

	if ( action == WB_ISDELIMITER )
		return !!(ClassifyChar(pch[ich]) & WBF_BREAKLINE);

        if (!(cchBuff <= sizeof(wClassifyData)))
        {
            ASSERT(0);
            return ich;
        }

	// Batch classify buffer for whitespace and kinsoku classes
	ClassifyChars		(pch, cchBuff, wClassifyData);
	BatchKinsokuClassify(pch, cchBuff, cType3, kinsokuClassifications );

	// Setup pointers
	pKinsoku2 = kinsokuClassifications + ich; 		// Ptr to current  kinsoku
	pKinsoku1 = pKinsoku2 - 1;						// Ptr to previous kinsoku

	if(!(action & 1))								// WB_(MOVE)LEFTxxx
	{
		ich--;
		Assert(ich >= 0);
	}
	pwRes	 = &wClassifyData[ich];
	pcType3	 = &cType3[ich];						// for ideographics

	switch(action)
	{
	case WB_LEFT:
		for(; ich >= 0 && *pwRes & WBF_BREAKLINE;	// Skip preceding line
			ich--, pwRes--)							//  break chars
				;									// Empty loop. Then fall
													//  thru to WB_LEFTBREAK
	case WB_LEFTBREAK:
		for(; ich >= 0 && !CanBreak(*pKinsoku1, *pKinsoku2);
			ich--, pwRes--, pKinsoku1--, pKinsoku2--)
				;									// Empty loop
		if(action == WB_LEFTBREAK)					// Skip preceding line
		{											//  break chars
			for(; ich >= 0 && *pwRes & WBF_BREAKLINE;
				ich--, pwRes--)
					;								// Empty loop
		}
		return ich + 1;

	case WB_MOVEWORDLEFT:
		for(; ich >= 0 && (*pwRes & WBF_CLASS) == 2;// Skip preceding blank
			ich--, pwRes--, pcType3--)				//  chars
				;
		if(ich >= 0)								// Save starting wRes and
		{											//  startType3
			wb = *pwRes--;							// Really type1
			startType3 = *pcType3--;				// type3
			ich--;
		}
		// Skip to beginning of current word
		while(ich >= 0 && (*pwRes & WBF_CLASS) != 3 &&
			(IsSameClass(*pwRes, wb, *pcType3, startType3) ||
			!wb && ich && ((ch = pch[ich]) == '\'' || ch == RQUOTE)))
		{
			ich--, pwRes--, pcType3--;
		}
		return ich + 1;


	case WB_RIGHTBREAK:
		for(; cch > 0 && *pwRes & WBF_BREAKLINE;	// Skip any leading line
			cch--, pwRes++)							//  break chars
				;									// Empty loop
													// Fall thru to WB_RIGHT
	case WB_RIGHT:
		// Skip to end of current word
		for(; cch > 0 && !CanBreak(*pKinsoku1, *pKinsoku2);
			cch--, pKinsoku1++, pKinsoku2++, pwRes++)
				;
		if(action != WB_RIGHTBREAK)					// Skip trailing line
		{											//  break chars
			for(; cch > 0 && *pwRes & WBF_BREAKLINE;
				cch--, pwRes++)
					;
		}
		return cchBuff - cch;

	case WB_MOVEWORDRIGHT:
		if(cch <= 0)								// Nothing to do
			return ich;

		wb = *pwRes;								// Save start wRes
		startType3 = *pcType3;						//  and startType3

		// Skip to end of word
		if (startType3 & C3_IDEOGRAPH ||			// If ideographic or
			(*pwRes & WBF_CLASS) == 3)				//  tab/cell, just
		{
			cch--, pwRes++;							//  skip one char
		}
		else while(cch > 0 &&
			(IsSameClass(*pwRes, wb, *pcType3, startType3) || !wb &&
			 ((ch = pch[cchBuff - cch]) == '\'' || ch == RQUOTE)))
		{
			cch--, pwRes++, pcType3++;
		}

		for(; cch > 0 && (*pwRes & WBF_CLASS) == 2;	// Skip trailing blank
			cch--, pwRes++)							//  chars
					;
		return cchBuff - cch;
	}

	TRACEERRSZSC("TxWordBreakProc: unknown action", action);
	return ich;
}

/*
 *	CTxtPtr::ReplaceRange(cchOld, cchNew, *pch, pcpFirstRecalc)
 *	
 *	@mfunc
 *		replace a range of text at this text pointer.
 *	
 *	@rdesc
 *		count of new characters added
 *	
 *	@comm	SideEffects: <nl>
 *		moves this text pointer to end of replaced text <nl>
 *		moves text block array <nl>
 *
 */
DWORD CTxtPtr::ReplaceRange(
	LONG cchOld, 				//@parm length of range to replace 
								// (<lt> 0 means to end of text)
	DWORD cchNew, 				//@parm length of replacement text

⌨️ 快捷键说明

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