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

📄 ldte.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	LONG		lStreamFormat,	// @parm stream format to use for loading
	EDITSTREAM *pes,			// @parm edit stream to load from
	BOOL		fTestLimit,		// @parm Whether to test text limit
	IUndoBuilder *publdr)		// @parm undo builder to receive antievents
{
	TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CLightDTEngine::LoadFromEs");

#ifdef DEBUG
	// FUTURE: Currently freezing the display prior to loading text
	// is simply an optimization. This may become a requirement in the
	// future. If this does become a requirement then we'll want to
	// exit with an error.
	if( !_ped->_pdp->IsFrozen() )
	{
		TRACEWARNSZ("CLightDTEngine::LoadFromEs	display not frozen");
	}
#endif // DEBUG

	LONG		cch = 0;				// Default no chars read
	CTxtSelection *psel;
	IAntiEvent *pae = NULL;

	if( publdr )
	{
		publdr->StopGroupTyping();
	}

	_ped->CheckUnicode(lStreamFormat);			// If Unicode, set code page
												//  1200
	// other components, such as the display and backing store, will
	// be able to make optimizations if they know that we are streaming
	// in text or RTF data.

	_ped->SetStreaming(TRUE);

	if( lStreamFormat & SF_RTF )					// RTF case must precede
	{												//  TEXT case (see SF_x
		if( !_ped->IsRich() )						//  values)
		{
			Assert(cch == 0);
			goto Exit;
		}

		LONG cpMin, cpMost;

		// Here we do something a bit unusual for performance reasons.
		// instead of letting the rtf reader generate it's own undo actions,
		// we'll take care of it ourselves.  Instead of generating actions
		// for each little operation, we simply generate a "big" anti-event
		// for the whole shebang

		// There is a subtlty w.r.t. to paragraph format runs.  By inserting
		// text with para formatting, it's possible that we will modify the
		// para formatting of the _current_ paragraph.  Thus, it's necessary
		// to remember what the formatting currently is for undo.  Note that
		// it may actually not be changed; but we go ahead and generate an
		// anti-event anyways.  Note that we only need to do this if cpMin is
		// the middle of a paragraph
		
		CTxtPtr tp(prg->_rpTX);
		if(prg->GetCch() > 0)
			tp.AdvanceCp(-prg->GetCch());
		
		if( publdr && prg->_rpPF.IsValid() && !tp.IsAfterEOP() )
		{
			IParaFormatCache *ppfc;
			GetParaFormatCache(&ppfc);

			tp.FindEOP(tomBackward);
			cpMin = tp.GetCp();
			tp.FindEOP(tomForward);
			cpMost = tp.GetCp();
			
			// We must be in rich text mode, so we must be able to always
			// find a paragraph.
			Assert(cpMost > cpMin);

			CFormatRunPtr rpPF(prg->_rpPF);
			rpPF.AdvanceCp(cpMin - prg->GetCp());
			
			pae = gAEDispenser.CreateReplaceFormattingAE( _ped, rpPF, 
						cpMost - cpMin, ppfc, ParaFormat);
			if( pae )
				publdr->AddAntiEvent(pae);
		} 

		// First, clear the range
		if( prg->GetCch() )
			prg->ReplaceRange(0, NULL, publdr, SELRR_REMEMBERRANGE);

		Assert(prg->GetCch() == 0);

		cpMin = prg->GetCp();
		CRTFRead rtfRead(prg, pes, lStreamFormat);
	
		cch	= rtfRead.ReadRtf();

		if (lStreamFormat & SFF_ADJUSTENDEOP &&		// If range end EOP
			pes->dwError == NOERROR &&				//  wasn't deleted and
			prg->_rpTX.IsAfterEOP())	 			//  new text ends with
		{											//  an EOP,
			prg->SetExtend(TRUE);					//  select and delete
			prg->BackupCRLF();						//  the latter
			prg->ReplaceRange(0, NULL, NULL, SELRR_IGNORE);
		}

		cpMost = prg->GetCp();

		Assert(cpMost >= cpMin);

		// If nothing changed, get rid of any anti-events (like the formatting
		// one) that we may have "speculatively" added

		if( publdr && !_ped->GetCallMgr()->GetChangeEvent() )
		{
			publdr->Discard();
		}

		if( publdr && cpMost > cpMin )
		{
			// If some text was added, create an anti-event for
			// it and add it in.

			AssertSz(_ped->GetCallMgr()->GetChangeEvent(),
				"Something changed, but nobody set the change flag");
				
			pae = gAEDispenser.CreateReplaceRangeAE(_ped, cpMin, cpMost, 0, 
						NULL, NULL, NULL);

			HandleSelectionAEInfo(_ped, publdr, -1, -1, cpMost, 0, 
						SELAE_FORCEREPLACE);
			if( pae )
				publdr->AddAntiEvent(pae);
		}
	}
	else if( lStreamFormat & SF_TEXT )
	{
		cch = ReadPlainText( prg, pes, fTestLimit, publdr );
	}

	// Before updating the selection, try the auto-URL detect.  This makes
	// two cases better: 1. a long drag drop is now faster and 2. the
	// selection _iFormat will now be udpated correctly for cases of
	// copy/paste of a URL.

	if( _ped->GetDetectURL() )
	{
		_ped->GetDetectURL()->ScanAndUpdate(publdr);
	}

	// The caret belongs in one of two places:
	//		1. if we loaded into a selection, at the end of the new text
	//		2. otherwise, we loaded an entire document, set it to cp 0
	//
	// ReadPlainText() and ReadRtf() set prg to an insertion point
	// at the end, so if we loaded a whole document, reset it.

	if( (psel = _ped->GetSel()) )
	{
		if( !(lStreamFormat & SFF_SELECTION) )
		{
			psel->Set(0,0);
		}
		psel->Update_iFormat(-1);
	}

Exit:

	_ped->SetStreaming(FALSE);

	if (!fTestLimit)
	{
		// If we don't limit the text then we adjust the text limit
		// if we have exceeded it.
		_ped->TxSetMaxToMaxText();
	}

	return cch;
}

/*
 *	CLightDTEngine::SaveToEs (prg, lStreamFormat, pes)
 *
 *	@mfunc
 *		save data into the given stream
 *
 *	@rdesc
 *		LONG -- count of characters written
 */
LONG CLightDTEngine::SaveToEs(
	CTxtRange *	prg,			// @parm range to drag from
	LONG		lStreamFormat,	// @parm stream format to use for saving
	EDITSTREAM *pes )			// @parm edit stream to save to
{
	TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CLightDTEngine::SaveToEs");

	LONG cch = 0;								// Default no chars written

	_ped->CheckUnicode(lStreamFormat);			// If Unicode, set code page

	if( lStreamFormat & SF_RTF )				// Be sure to check for SF_RTF
	{											//  before checking for SF_TEXT
		CRTFWrite rtfWrite( prg, pes, lStreamFormat );
	
		cch = rtfWrite.WriteRtf();
	}
	else if(lStreamFormat & (SF_TEXT | SF_TEXTIZED))
	{
		cch = WritePlainText(prg, pes, lStreamFormat);
	}
	else
	{
		Assert(FALSE);
	}

	return cch;
}

/*
 *	CLightDTEngine::UnicodePlainTextFromRange (prg)
 *
 *	@mfunc
 *		fetch the plain text from a range and puts it in an hglobal
 *
 *	@rdesc
 *		an allocated HGLOBAL.
 *
 *	@devnote
 *		FUTURE: Export bullets as does Word for plain text
 */
HGLOBAL CLightDTEngine::UnicodePlainTextFromRange(
	CTxtRange *prg)				// @parm range to get text from
{
	TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CLightDTEngine::UnicodePlainTextFromRange");

	LONG	cpMin, cpMost;
	LONG	cch = prg->GetRange(cpMin, cpMost);
	LONG	cchT = 2*(cch + 1);
	HGLOBAL	hText;
	HGLOBAL	hTextNew;
	TCHAR *	pText;
	CTxtPtr tp(_ped, cpMin);

	hText = GlobalAlloc(GMEM_FIXED,						// Allocate 2* in
						cchT * sizeof(TCHAR) );			//  case all CRs
	if( !hText )
		return NULL;

	pText = (TCHAR *)GlobalLock(hText);
	if( !pText || 0 == GlobalSize(hText))
		return NULL;

	if( cch )
	{
		cch = tp.GetPlainText(cchT, pText, cpMost, FALSE);
		AssertSz(cch <= cchT,
			"CLightDTEngine::UnicodePlainTextFromRange: got too much text");
	}

	*(pText + cch) = '\0';

	// GuyBark Jupiter: Unlock before the realloc, (even though the lock 
	// didn't do anything anyway), and beware of oom.
	GlobalUnlock(hText);

	if(!(hTextNew = GlobalReAlloc(hText, 2*(cch + 1), GMEM_MOVEABLE)))
	{
	    GlobalFree(hText);
	}

	hText = hTextNew;

	return hText;
}

/*
 *	CLightDTEngine::AnsiPlainTextFromRange (prg)
 *
 *	@mfunc
 *		Retrieve an ANSI copy of the text in the range prg
 *
 *	@rdesc
 *		HRESULT
 */
HGLOBAL CLightDTEngine::AnsiPlainTextFromRange(
	CTxtRange *prg)				// @parm range to get text from
{
	TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CLightDTEngine::AnsiPlainTextFromRange");

	HGLOBAL hUnicode;
	HGLOBAL hAnsi;

	// FUTURE (alexgo): if we implement the option to store text as 8-bit
	// chars, then we can make this routine more efficient

	hUnicode = UnicodePlainTextFromRange(prg);
	hAnsi = TextHGlobalWtoA(hUnicode);

	GlobalFree(hUnicode);
	return hAnsi;
}

/*
 *	CLightDTEngine::RtfFromRange (prg, lStreamFormat)
 *
 *	@mfunc
 *		Fetch RTF text from a range and put it in an hglobal
 *
 *	@rdesc
 *		an allocated HGLOBAL.  
 */
HGLOBAL CLightDTEngine::RtfFromRange(
	CTxtRange *	prg,			// @parm Range to get RTF from
	LONG 		lStreamFormat)	// @parm stream format to use for loading
{
	TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CLightDTEngine::RtfFromRange");

	WRITEHGLOBAL whg;
	EDITSTREAM	 es = {(DWORD)&whg, NOERROR, WriteHGlobal};
	DWORD		 cb	= 2*abs(prg->GetCch()) + 100;	// Rough estimate
	HGLOBAL      hgNew;
 
	whg.cb			= cb;
	whg.hglobal		= GlobalAlloc(GMEM_FIXED, cb);
	if(!whg.hglobal)
		return NULL;		
	whg.cch			= 0;					// Nothing written yet
	SaveToEs(prg, lStreamFormat & ~SF_TEXT, &es);
	if(es.dwError)
	{
		GlobalFree(whg.hglobal);
		return NULL;
	}

	// GuyBark Jupiter: Don't leak here.

	if(!(hgNew = GlobalReAlloc(whg.hglobal, whg.cch, GMEM_MOVEABLE)))
	{
	    GlobalFree(whg.hglobal);
	}

	whg.hglobal = hgNew;

    return whg.hglobal;
}


//
// PROTECTED METHODS
//

#define READSIZE 	4096 - 2
#define WRITESIZE	2048

/*
 *	CLightDTEngine::ReadPlainText (prg, pes, publdr)
 *
 *	@mfunc
 *		Replaces contents of the range prg with the data given in the edit
 *		stream pes. Handles multibyte sequences that overlap stream buffers.
 *
 *	@rdesc
 *		Count of bytes read (to be compatible with RichEdit 1.0)
 *
 *	@devnote
 *		prg is modified; at the return of the call, it will be a degenerate
 *		range at the end of the read in text.
 *
 *		Three kinds of multibyte/char sequences can overlap stream buffers:
 *		DBCS, UTF-8, and CRLF/CRCRLF combinations. DBCS and UTF-8 streams are
 *		converted by MultiByteToWideChar(), which cannot convert a lead byte
 *		(DBCS and UTF-8) that occurs at the end of the buffer, since the
 *		corresponding trail byte(s) will be in the next buffer.  Similarly,
 *		in RichEdit 2.0 mode, we convert CRLFs to CRs and CRCRLFs to blanks,
 *		so one or two CRs at the end of the buffer require knowledge of the
 *		following char to determine if they are part of a CRLF or CRCRLF.
 *
 *		To handle these overlapped buffer cases, we move the ambiguous chars
 *		to the start of the next buffer, rather than keeping them as part of
 *		the current buffer.  At the start of the buffer, the extra char(s)
 *		needed for translation follow immediately.
 */
LONG CLightDTEngine::ReadPlainText(
	CTxtRange *	  prg, 			// @parm range to read to
	EDITSTREAM *  pes,			// @parm edit stream to read from
	BOOL		  fTestLimit,	// @parm whether limit testing is needed
	IUndoBuilder *publdr )		// @parm undo builder to receive antievents
{
	TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CLightDTEngine::ReadPlainText");

	CTxtEdit *ped = _ped;
	LONG	  cbRead;
	LONG 	  cbReadTotal = 0;	// No bytes read yet
	LONG	  cch;
	LONG	  cchConv;
	LONG	  cchLen;
	DWORD	  cchMax = ped->TxGetMaxLength();
	LONG	  cCR = 0;			// Count of CRs from preceding buffer
	LONG	  cCRPrev = 0;		// Count used while calc'ing new cCR
	BOOL	  fContinue = TRUE;	// Keep reading so long as TRUE
	BYTE *	  pb;				// Byte ptr to szBuf or wszBuf
	TCHAR *	  pch;				// Ptr to wszBuf
	UINT	  uCpg = CP_ACP;	// Default system Ansi code page
	BOOL	  bCheckFont = (OnWin95FE() || OnWinNTFE());		// check DB font on FE systems

	// just put a big buffer on the stack.  Thankfully, we only
	// run on 32bit OS's.  4K is a good read size for NT file caching.
	char 	szBuf[READSIZE];
	WCHAR	wszBuf[READSIZE+2];	// Allow for moving end CRs to start

	// first, empty the range
	if( prg->GetCch() )
	{
		// Delete text in range
		prg->ReplaceRange(0, NULL, publdr, SELRR_REMEMBERRANGE);			
	}

	if(ped->_pDocInfo && 
		ped->_pDocInfo->wCpg != tomInvalidCpg)		// Update code page if
	{												//  defined
		uCpg = ped->_pDocInfo->wCpg;
	}

	pb = (uCpg == 1200) ? (BYTE *)(wszBuf + 2)		// Setup Unicode or MBCS
						: (BYTE *)szBuf;
	LONG j = 0;										// Haven't read anything,
													//  so no lead byte left
	while(fContinue)								//  from previous read
	{
		LONG	prevChar = j;						// Save byte(s) left over
													//  from previous read
		pes->dwError = (*pes->pfnCallback)(			// Read next bufferful,
				pes->dwCookie, pb + j, 				//  bypassing any lead
				READSIZE - j, &cbRead);				//  bytes

		if(pes->dwError || !cbRead && !cCR)
			break;									// Error or done

		// adjust cbRead with previous leading byte(s)
		cbRead += j;

		j = 0;										
		
		cchConv = cbRead/2;							// Default Unicode cch
		if(uCpg != 1200 && cbRead)					// Multibyte of some kind
		{
			Assert(pb == (BYTE *)szBuf);			// Just in case...

			BOOL	bCopyTwo = FALSE;

			// check the last byte if it is a leading byte
			if (uCpg == CP_UTF8)
			{
				// Note: UTF-7 can be in the middle of a long sequence, so
				// it can't be converted effectively in chunks
				LONG	cbLocalRead = cbRead - 1;
				while((BYTE)szBuf[cbLocalRead -j] > 127)	// Find UTF-8 lead byte
				{
					j++;
					if((BYTE)szBuf[cbLocalRead -j] > 0xC0)
						break;						// Break on UTF-8 lead 
				}									//  byte
				if(j > 1)
				{
					if (j == 3 || (BYTE)			// Three-byte char or
						szBuf[cbLocalRead - 1] < 0xE0)	//  on second byte of 2
					{								//  byte char:
						j = 0;						// Finished full char
					}
					else							// Landed on first trail
					{								//  byte of 3-byte char
						bCopyTwo = TRUE;			// So copy last two bytes
					}								//  down to buf start
				}
			}
			else 
			{

⌨️ 快捷键说明

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