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

📄 ldte.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//
// 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	LDTE.C - RichEdit Light Data Transfer Engine |
 *
 *		This file contains data transfer code using IDataObject
 *
 *	Author: <nl>
 *		alexgo (4/25/95)
 *
 *	Revisions: <nl>
 *		murrays (7/6/95) auto-doc'd and added RTF support
 *
 *	FUTURE (AlexGo): <nl>
 *		Maybe merge this class with CTxtRange to make more efficient use of
 *		the this ptr.  All but two methods use a CTxtRange and one of these
 *		could be global.  The two are:
 *
 *		GetDropTarget( IDropTarget **ppDropTarget )
 *		GetDataObjectInfo(IDataObject *pdo, DWORD *pDOIFlags) // Can be global
 *
 *		In general, a range can spawn data objects, which need to have a clone
 *		of the range in case the range is moved around.  The contained range
 *		is used for delayed rendering.  A prenotification is sent to the data
 *		object just before the data object's data is to be changed.  The data
 *		object then renders the data in its contained range, whereupon the
 *		object becomes independent of the range and destroys the range.
 *
 *	@devnote
 *		We use the word ANSI in a general way to mean any multibyte character
 *		system as distinguished from 16-bit Unicode.  Technically, ANSI refers
 *		to a specific single-byte character system (SBCS).  We translate
 *		between "ANSI" and Unicode text using the Win32
 *		MultiByteToWideChar() and WideCharToMultiByte() APIs.
 *
 */

#include "_common.h"
#include "_range.h"
#include "_ldte.h"
#include "_m_undo.h"
#include "_antievt.h"
#include "_edit.h"
#include "_disp.h"
#include "_select.h"
#include "_dragdrp.h"
#include "_dxfrobj.h"
#include "_rtfwrit.h"
#include "_rtfread.h"
#include "_urlsup.h"

ASSERTDATA


//Local Prototypes
DWORD CALLBACK ReadHGlobal (DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb);
DWORD CALLBACK WriteHGlobal(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb);

#define	SFF_ADJUSTENDEOP	0x80000000
//
// LOCAL METHODS
//

/*
 *	void PasteSetupDBCFont ( )
 *
 *	@func
 *		This routine is to setup the DBC font by calling CheckChangeFont() with 
 *		the current system LCID.  This is used during pasting/inserting
 *		plain text.
 */
void PasteSetupDBCFont ( CTxtEdit *ped )
{
	WORD lcidSystem;
	CTxtSelection *psel;

	if (ped->_fSingleCodePage || !ped->IsRich())
		{
		goto leave;
		}

	psel = ped->GetSel();
	if(!psel)
		{
		goto leave;
		}

	if (psel->GetCch())
	{
		// for selection, we need to get the character format at cpMin+1
		CTxtRange rg( ped, psel->GetCpMin()+1, 0 );
		LONG	iFormat;

		iFormat = rg.Get_iCF ();
		psel->Set_iCF( iFormat );

		// release format that has been AddRef in Get_iCF()
		ReleaseFormats(iFormat, -1);		

		psel->SetUseiFormat( TRUE );
	}

	lcidSystem = GetSystemDefaultLCID();
	psel->CheckChangeFont( ped, FALSE, lcidSystem,
		ConvertLanguageIDtoCodePage(lcidSystem) );	
leave:
	return;
}

/*
 *	ReadHGlobal(dwCookie, pbBuff, cb, pcb)
 *
 *	@func
 *		EDITSTREAM callback for reading from an hglobal
 *
 *	@rdesc
 *		es.dwError
 */
DWORD CALLBACK ReadHGlobal(
	DWORD	dwCookie,			// @parm READHGLOBAL *
	LPBYTE	pbBuff,				// @parm Buffer to fill
	LONG	cb,					// @parm Buffer length
	LONG *	pcb)				// @parm Out parm for # bytes stored
{
	TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "ReadHGlobal");

	READHGLOBAL * const prhg = (READHGLOBAL *)dwCookie;

	cb = min(cb, prhg->cbLeft);
	CopyMemory(pbBuff, prhg->ptext, cb);
	prhg->cbLeft	-= cb;
	prhg->ptext		+= cb;
	if(pcb)
		*pcb = cb; 
	return NOERROR;	
}

/*
 *	WriteHGlobal(dwCookie, pbBuff, cb, pcb)
 *
 *	@func
 *		EDITSTREAM callback for writing ASCII to an hglobal
 *
 *	@rdesc
 *		error (E_OUTOFMEMORY or NOERROR)
 */
DWORD CALLBACK WriteHGlobal(
	DWORD	dwCookie,			// @parm WRITEHGLOBAL *
	LPBYTE	pbBuff,				// @parm Buffer to write from
	LONG	cb,					// @parm Buffer length
	LONG *	pcb)				// @parm Out parm for # bytes written
{
	TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "WriteHGlobal");

	WRITEHGLOBAL * const pwhg = (WRITEHGLOBAL *)dwCookie;
	HGLOBAL		hglobal = pwhg->hglobal;
	LPSTR		pstr;

	if (pwhg->cch < 0 || cb < 0 || pwhg->cch + cb < pwhg->cch)
		return (DWORD)E_OUTOFMEMORY;
	if(pwhg->cch + cb > pwhg->cb)			// Less than requested cb in
	{										//  current Alloc
		if (pwhg->cb < 0 || 2 * pwhg->cb < pwhg->cb)
			return (DWORD)E_OUTOFMEMORY;
		ULONG cbNewSize = GROW_BUFFER(pwhg->cb, cb);
		hglobal = GlobalReAlloc(hglobal, cbNewSize, GMEM_MOVEABLE);
		if(!hglobal)	
			return (DWORD)E_OUTOFMEMORY;
		pwhg->hglobal = hglobal;			// May be superfluous...
		pwhg->cb = cbNewSize;
	}
	pstr = (LPSTR)GlobalLock(hglobal);
	if(!pstr)
		return (DWORD)E_OUTOFMEMORY;
	CopyMemory(pstr + pwhg->cch, pbBuff, cb);
	GlobalUnlock(hglobal);
	pwhg->cch += cb;
	if(pcb)
		*pcb = cb; 
	return NOERROR;	
}


//
// PUBLIC METHODS
//

/*
 *	Cleanse(pchD, pchS, cchS)
 *
 *	@func
 *		"Cleanses" the source string pchS of length cch by copying it to the
 *		destination string pchD ignoring LFs and replacing Unicode paragraph
 *		(0x2029) and line (0x2028) separators by Word/TOM-compatible CR and
 *		VT, respectively. Returns resulting clensed string length.  Also
 *		replaces CRCRLFs (MLE soft line breaks) by blanks.
 *
 *	@rdesc
 *		Length of cleansed string.
 *
 *	@devnote
 *		Caller needs to be sure that destination string is as long as the
 *		source string, in case no LFs are encountered.  pchD can point to
 *		the same string as pchS, since the cleansed string cannot be longer
 *		than the input string.  However if pchS points at a buffer that
 *		doesn't contain the whole input string, then the caller has to deal
 *		with CRLF and CRCRLF combos that overlap buffers.
 */
LONG Cleanse(
	TCHAR *			pchD,	//@parm Source string
	const TCHAR *   pchS,	//@parm Destination string
	LONG			cchS)	//@parm Length of source string
{
	LONG	 cchD = 0;
	unsigned ch;			// Current character value
	LONG	 i = cchS;		// Loop counter

	while(i-- > 0)
	{
		ch = *pchS++;						// Examine next char
		if(IsASCIIEOP(ch))					// Handle CR and LF combos
		{
			if(ch == CR)
			{
				if(i > 1 && *pchS == CR && *(pchS+1) == LF)
				{
					ch = ' ';				// Translate CRCRLF to ' '
					pchS += 2;
					i -= 2;
				}
				else if(i && *pchS == LF)	// Bypass LF of CRLF
				{
					pchS++;
					i--;
				}
			}
			else if(ch == LF)				// Treat lone LFs as EOPs, i.e.,
				ch = CR;					//  be nice to Unix text files
		}
		else if((ch | 1) == PS)				// Translate Unicode para/line
			ch = (ch == PS) ? CR : VT;		//  separators into CR/VT

		*pchD++ = ch;
		cchD++;
	}

	return cchD;
}

/*
 *	CLightDTEngine::CLightDTEngine()
 *
 *	@mfunc
 *		Constructor for Light Data Transfer Engine
 */
CLightDTEngine::CLightDTEngine()
{
	TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CLightDTEngine::CLightDTEngine");

	_ped = NULL;
	_pdt = NULL;
	_pdo = NULL;
	_fUseLimit = FALSE;
	_fOleless = FALSE;
}

/*
 *	CLightDTEngine::~CLightDTEngine 
 *
 *	@mfunc
 *		Handles all necessary clean up for the object..
 */
CLightDTEngine::~CLightDTEngine()
{
	TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CLightDTEngine::~CLightDTEngine");

	if( _pdt )
	{
		_pdt->Zombie();
		_pdt->Release();
		_pdt = NULL;
	}
	Assert(_pdo == NULL);
}

/*
 *	CLightDTEngine::Destroy()
 *
 *	@mfunc
 *		Deletes this instance
 */
void CLightDTEngine::Destroy()
{
	TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CLightDTEngine::Destroy");

	delete this;
}

/*
 *	CLightDTEngine::CopyRangeToClipboard ( prg )
 *
 *	@mfunc
 *		Copy the text of the range prg to the clipboard using Win32 APIs
 *
 *	@rdesc
 *		HRESULT
 */
HRESULT CLightDTEngine::CopyRangeToClipboard(
	CTxtRange *prg )				// @parm range to copy to clipboard
{
	TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CLightDTEngine::CopyRangeToClipboard");

	HRESULT hresult = E_FAIL;
	IDataObject *pdo;
	IRichEditOleCallback * precall = _ped->GetRECallback();
	BOOL fSingleObject;
	CHARRANGE chrg;

	prg->GetRange(chrg.cpMin, chrg.cpMost);
	fSingleObject = chrg.cpMost - chrg.cpMin == 1 &&
		_ped->HasObjects() &&
		_ped->_pobjmgr->CountObjectsInRange(chrg.cpMin, chrg.cpMost);
	if(precall)
	{
		// give the callback a chance to give us it's own IDataObject
		hresult = precall->GetClipboardData(&chrg, RECO_COPY, &pdo);
	}

	// If we didn't get an IDataObject from the callback, build our own
	if(hresult != NOERROR)
	{
		// if the range is empty, don't bother creating it.  Just
		// leave the clipboard alone and return
		if( prg->GetCch() == 0 )
		{
			_ped->Sound();
			return NOERROR;
		}

		hresult = RangeToDataObject(prg, SF_TEXT | SF_RTF, &pdo);
	}

	// NB: it's important to check both hresult && pdo; it is legal for
	// our client to say "yep, I handled the copy, but there was nothing
	// to copy".
	if( hresult == NOERROR && pdo )
	{
		hresult = pOleSetClipboard(pdo);
		if( hresult != NOERROR )
		{
			HWND hwnd;
			_fOleless = TRUE;
			// Ole less clipboard support
			if (_ped->TxGetWindow(&hwnd) == NOERROR &&
				::OpenClipboard(hwnd) &&
				::EmptyClipboard()
			)
			{
				::SetClipboardData(CF_UNICODETEXT, NULL);
				::SetClipboardData(cf_RTF, NULL);
				::SetClipboardData(cf_RTFUTF8, NULL);
				if (fSingleObject)
					::SetClipboardData(CF_DIB, NULL);
				::CloseClipboard();
				hresult = NOERROR;				// To cause replace range to happen
			}
		}
        if (_pdo)
		{
			_pdo->Release();
		}
		_pdo = pdo;
	}
	return hresult;
}

/* 
 *	CLightDTEngine::CutRangeToClipboard( prg, publdr );
 *	
 *	@mfunc
 *		Cut text of the range prg to the clipboard
 *
 *	@devnote
 *		If publdr is non-NULL, anti-events for the cut operation should be
 *		stuffed into this collection
 *
 *	@rdesc
 *		HRESULT from CopyRangeToClipboard()
 *
 *	@devnote
 *		First copy the text to the clipboard, then delete it from the range
 */
HRESULT CLightDTEngine::CutRangeToClipboard(
	CTxtRange *prg,				// @parm range to cut to clipboard
	IUndoBuilder *publdr )		// @parm undo builder to receive antievents
{
	TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CLightDTEngine::CutRangeToClipboard");

	HRESULT hresult = E_ACCESSDENIED;

	Assert(!_ped->TxGetReadOnly());

	prg->AdjustEndEOP(NONEWCHARS);				// Don't include trailing EOP
												//  in some selection cases
	hresult = CopyRangeToClipboard(prg);

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

	if( hresult == NOERROR )
	{
		// Delete contents of range
		prg->ReplaceRange(0, NULL, publdr, SELRR_REMEMBERRANGE);	
	}

	return hresult;
}


/*
 *	CLightDTEngine::FlushClipboard()
 *
 *	@mfunc	flushes the clipboard (if needed).  Typically called during
 *			shutdown.
 *
 *	@rdesc	void
 */
void CLightDTEngine::FlushClipboard()
{
	TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CLightDTEngine::FlushClipboard");
	ENSAVECLIPBOARD ens;

	if( _pdo )
	{
		if( pOleIsCurrentClipboard(_pdo) == NOERROR )
		{
			CDataTransferObj *pdo = NULL;

			// check to see if we have to flush the clipboard.
			ZeroMemory(&ens, sizeof(ENSAVECLIPBOARD));

			// check to make sure the object is one of ours before accessing
			// the memory.  

			if( _pdo->QueryInterface(IID_IRichEditDO, (void **)&pdo ) 
				== NOERROR && pdo  )
			{
				ens.cObjectCount = pdo->_cObjs;
				ens.cch = pdo->_cch;
				pdo->Release();
			}

			if( _ped->TxNotify(EN_SAVECLIPBOARD, &ens) == NOERROR )
			{
				pOleFlushClipboard();
			}
			else
			{
				pOleSetClipboard(NULL);
			}
		}
		_pdo->Release();

⌨️ 快捷键说明

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