📄 ldte.cpp
字号:
LONG temp = cbRead - 1;
// IsDBCSLeadByte can return TRUE for some trail bytes
// esp. for GBX. So, we need to keep on checking until
// we hit a non-lead byte character. Then, based on
// how many bytes we went back, we can determine if the
// last byte is really a Lead byte.
while (temp && IsDBCSLeadByte((BYTE)szBuf[temp]))
temp--;
if (temp && ((cbRead-1-temp) & 1))
j = 1;
}
// we don't want to pass the Lead byte or partial UTF-7 to MultiByteToWideChar
// because it will return bad char.
cchConv = MultiByteToWideChar(uCpg, 0,
szBuf, cbRead - j, &wszBuf[2], READSIZE);
// Prefix warns here, but I don't think it can happen
// but the check doesn't hurt
if (cbRead < 0)
{
Assert(cbRead >= 0);
return 0;
}
// On FE System, check if we have DBC in the text
if (bCheckFont)
{
if (cchConv > 0 && cchConv < cbRead - j)
{
// Once we setup the DB Font, no need to do it again
// for future buffer.
bCheckFont = FALSE;
PasteSetupDBCFont ( ped );
}
}
szBuf[0] = szBuf[--cbRead]; // Copy last char read
// down to buffer start
if(bCopyTwo) // UTF-8. Handle breaks
{ // in middle of char
szBuf[1] = szBuf[0]; // So copy last two bytes
szBuf[0] = szBuf[cbRead-1]; // down to buf start
} // If last char in buffer
}
cbReadTotal += cbRead - j - prevChar;
// Cleanse (CRLFs -> CRs, etc.), limit, and insert the data. Have
// to handle CRLFs and CRCRLFs that overlap two successive buffers.
// This code is similar to CTxtRange::CleanseAndReplaceRange(), but
// deals with a series of stream chunks instead of a single string.
Assert(cCR <= 2);
pch = &wszBuf[2 - cCR]; // Include CRs from prev
if(!ped->TxGetMultiLine()) // Single-line control
{ // Truncate at 1st EOP to
for(cch = 0; cch < cchConv && // be compatible with RE
!IsASCIIEOP(*pch++); // 1.0 and user's SLE,
cch++) // and to give consistent
; // display behavior
if(cch < cchConv) // Stop reading stream if
fContinue = FALSE; // EOP encountered
cchConv = cch;
pch = &wszBuf[2]; // Restore pch
}
else if(!ped->Get10Mode()) // Unless RE 1.0 mode,
{ // convert to simple EOPs
wszBuf[0] = wszBuf[1] = CR; // Store CRs for cchCR > 0
cCRPrev = cCR; // Save prev cchCR
cCR = 0; // Default no CR this buf
Assert((LONG)(sizeof(wszBuf)/sizeof(WCHAR)) >= cchConv + 2);
// Need to +2 since we are moving data into wszBuf[2]
// GuyBark Jupiter 37651:
// If the text stream ended on a CR, (ie not CRLF), then we'd loop
// forever. This has been fixed in the newest RichEdit by adding
// cchConv to the checks below. So do the same thing here.
if(cchConv && wszBuf[cchConv + 2 - 1] == CR) // There's at least one
{ // Set it up for next buf
cCR++; // in case CR of CRLF
if((cchConv > 1) && wszBuf[cchConv + 2 - 2] == CR) // Got 2nd CR; might be
cCR++; // first CR of CRCRLF so
} // setup for next buffer
cchConv += cCRPrev - cCR; // Add in count from prev
cchConv = Cleanse(pch, pch, cchConv); // and sub that for next
}
Assert(!prg->GetCch()); // Range is IP
cch = cchConv;
if (fTestLimit)
{
// Have to adjust size because it is
// changed in this loop.
cchLen = ped->GetAdjustedTextLength();
if(cch && (DWORD)(cch + ped->GetAdjustedTextLength()) > cchMax) // DWORD takes care of
{ // "negative" cchMax's
cch = cchMax - cchLen; // which are considered
cch = max(cch, 0); // "infinite", i.e., if
ped->GetCallMgr()->SetMaxText(); // will fail with such
} // (Can't edit > 2G files)
}
if(prg->ReplaceRange(cch, pch, publdr, SELRR_REMEMBERRANGE) < cchConv)
{
// Out of memory or reached the max size of our text control.
// In either case, return STG_E_MEDIUMFULL (for compatibility
// with RichEdit 1.0)
pes->dwError = (DWORD)STG_E_MEDIUMFULL;
break;
}
}
return cbReadTotal;
}
/*
* CLightDTEngine::WritePlainText (prg, pes, fTextize)
*
* @mfunc
* Writes plain text from the range into the given edit stream
*
* @rdesc
* Count of bytes written
*/
LONG CLightDTEngine::WritePlainText(
CTxtRange * prg, // @parm range to write from
EDITSTREAM *pes, // @parm edit stream to write to
LONG lStreamFormat) // @parm Stream format
{
TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CLightDTEngine::WritePlainText");
LONG cbConverted; // Bytes for output stream
LONG cbWrite; // Incremental byte count
LONG cbWriteTotal = 0; // No chars written yet
LONG cpMin, cpMost;
LONG cch = prg->GetRange(cpMin, cpMost);
BOOL fTextize = lStreamFormat & SF_TEXTIZED;
LPBYTE pb; // Byte ptr to szBuf or wszBuf
COleObject *pobj; // Ptr to embedded object
CTxtPtr tp(_ped, cpMin); // tp to walk prg with
UINT uCpg = CP_ACP; // Default system Ansi code page
// DBCS has up to 2 times as many chars as WCHARs. UTF-8 has 3 BYTES for
// all codes above 0x7ff. UTF-7 has even more due to shift in/out codes.
// We don't support UTF-7, since can't use WCTMB with UTF-7 chunks
char szBuf[3*WRITESIZE]; // Factor of 2 works with DBCS, 3 with UTF-8
WCHAR wszBuf[WRITESIZE];
pes->dwError = NOERROR; // No error yet
if(lStreamFormat & SFF_UTF8)
uCpg = CP_UTF8;
else if(_ped->_pDocInfo &&
_ped->_pDocInfo->wCpg != tomInvalidCpg) // Update code page if
{ // defined
uCpg = _ped->_pDocInfo->wCpg;
}
pb = (uCpg == 1200) ? (BYTE *)wszBuf // Setup Unicode or MBCS
: (BYTE *)szBuf;
LONG cchText = _ped->GetAdjustedTextLength();
cpMost = min(cpMost, cchText); // Don't write final CR
while((LONG)tp.GetCp() < cpMost)
{
if (fTextize && tp.GetChar() == WCH_EMBEDDING)
{
Assert(_ped->GetObjectCount());
pobj = _ped->GetObjectMgr()->GetObjectFromCp(tp.GetCp());
tp.AdvanceCp(1); // Advance past object
if(pobj)
{
cbWriteTotal += pobj->WriteTextInfoToEditStream(pes);
continue; // If no object at cp,
} // just ignore char
}
cch = tp.GetPlainText(WRITESIZE, wszBuf, cpMost, fTextize);
if(!cch)
break; // No more to do
cbConverted = 2*cch; // Default Unicode byte ct
if(uCpg != 1200) // Multibyte of some kind
{
cbConverted = MbcsFromUnicode(szBuf, 3*WRITESIZE, wszBuf, cch, uCpg,
UN_CONVERT_WCH_EMBEDDING);
// FUTURE: report some kind of error if default char used,
// i.e., data lost in conversion
// Did the conversion completely fail? As a fallback, we might try
// the system code page, or just plain ANSI...
if (!cbConverted)
{
uCpg = GetLocaleCodePage();
cbConverted = MbcsFromUnicode(szBuf, 3*WRITESIZE, wszBuf, cch, uCpg,
UN_CONVERT_WCH_EMBEDDING);
}
if (!cbConverted)
{
uCpg = CP_ACP;
cbConverted = MbcsFromUnicode(szBuf, 3*WRITESIZE, wszBuf, cch, uCpg,
UN_CONVERT_WCH_EMBEDDING);
}
}
pes->dwError = (*pes->pfnCallback)(pes->dwCookie, pb,
cbConverted, &cbWrite);
if(!pes->dwError && cbConverted != cbWrite) // Error or ran out of
pes->dwError = (DWORD)STG_E_MEDIUMFULL; // target storage
if(pes->dwError)
break;
cbWriteTotal += cbWrite;
}
AssertSz((LONG)tp.GetCp() >= cpMost,
"CLightDTEngine::WritePlainText: not all text written");
return cbWriteTotal;
}
/*
* CLightDTEngine::CreateOleObjFromDataObj ( pdo, prg, rps, pubdlr )
*
* @mfunc
* Creates an ole object based on the data object pdo, and
* pastes the object into the range prg. Any text that already
* existed in the range is replaced.
*
* @rdesc
* HRESULT
*
*/
HRESULT CLightDTEngine::CreateOleObjFromDataObj(
IDataObject * pdo, // @parm Data object from which to create
CTxtRange * prg, // @parm Range in which to place
REPASTESPECIAL *rps, // @parm Special paste info
INT iformatetc, // @parm Index in g_rgFETC
IUndoBuilder * publdr) // @parm Undo builder to receive antievents
{
#ifndef PEGASUS
TRACEBEGIN(TRCSUBSYSDTE, TRCSCOPEINTERN, "CLightDTEngine::CreateOleObjFromDataObj");
HRESULT hr = NOERROR;
REOBJECT reobj;
SIZEL sizel;
FORMATETC formatetc;
DWORD dwDrawAspect = 0;
HGLOBAL hMetaPict = NULL;
LPRICHEDITOLECALLBACK const precall = _ped->GetRECallback();
LPOBJECTDESCRIPTOR lpod = NULL;
STGMEDIUM medObjDesc;
BOOL fStatic = (iformatetc == iMfPict || iformatetc == iDIB ||
iformatetc == iBitmap);
BOOL fFilename = (iformatetc == iFilename);
DUAL_FORMATETC tmpFormatEtc;
if(!precall)
{
return E_NOINTERFACE;
}
ZeroMemory(&medObjDesc, sizeof(STGMEDIUM));
ZeroMemory(&sizel, sizeof(SIZEL));
ZeroMemory(&reobj, sizeof(REOBJECT));
if(fStatic)
{
dwDrawAspect = DVASPECT_CONTENT;
}
if(fFilename)
{
dwDrawAspect = DVASPECT_ICON;
}
if(rps && !dwDrawAspect)
{
dwDrawAspect = rps->dwAspect;
if(rps->dwAspect == DVASPECT_ICON)
hMetaPict = (HGLOBAL)rps->dwParam;
}
// If no aspect was specified, pick up the object descriptor hints
if(!dwDrawAspect)
{
// Define ObjectDescriptor data
formatetc.cfFormat = cf_OBJECTDESCRIPTOR;
formatetc.ptd = NULL;
formatetc.dwAspect = DVASPECT_CONTENT;
formatetc.lindex = -1;
formatetc.tymed = TYMED_HGLOBAL;
if(pdo->GetData(&formatetc, &medObjDesc) == NOERROR)
{
HANDLE hGlobal;
hGlobal = medObjDesc.hGlobal;
lpod = (LPOBJECTDESCRIPTOR)GlobalLock(hGlobal);
if(lpod)
{
dwDrawAspect = lpod->dwDrawAspect;
}
GlobalUnlock(hGlobal);
pReleaseStgMedium(&medObjDesc);
}
}
if(!dwDrawAspect)
{
dwDrawAspect = DVASPECT_CONTENT;
}
if(fStatic)
{
reobj.clsid = ((iformatetc == iMfPict) ?
CLSID_StaticMetafile : CLSID_StaticDib);
}
// COMPATIBILITY ISSUE: Compatibility Issue from Richedit 1.0 - Raid 16456:
// Don't call GetData(CF_EMBEDSOURCE)
// on 32-bit Excel. Also clsidPictPub.
// if(iformatetc == iformatetcEmbSrc && (ObFIsExcel(&clsid) ||
// IsEqualCLSID(&clsid, &clsidPictPub)))
// else
// ObGetStgFromDataObj(pdataobj, &medEmbed, iformatetc);
// Get storage for the object from the application
hr = precall->GetNewStorage(&reobj.pstg);
if(hr)
{
TRACEERRORSZ("GetNewStorage() failed.");
goto err;
}
// Create an object site for the new object
_ped->GetClientSite(&reobj.polesite);
if(hr)
{
TRACEERRORSZ("GetClientSite() failed.");
goto err;
}
ZeroMemory(&tmpFormatEtc, sizeof(DUAL_FORMATETC));
tmpFormatEtc.ptd = NULL;
tmpFormatEtc.dwAspect = dwDrawAspect;
tmpFormatEtc.lindex = -1;
//Create the object
if(fStatic)
{
hr = pOleCreateStaticFromData(pdo, IID_IOleObject, OLERENDER_DRAW,
&tmpFormatEtc, NULL, reobj.pstg, (LPVOID*)&reobj.poleobj);
}
else if(iformatetc == iLnkSrc)
{
hr = pOleCreateLinkFromData(pdo, IID_IOleObject, OLERENDER_DRAW,
&tmpFormatEtc, NULL, reobj.pstg, (LPVOID*)&reobj.poleobj);
}
else
{
hr = pOleCreateFromData(pdo, IID_IOleObject, OLERENDER_DRAW,
&tmpFormatEtc, NULL, reobj.pstg, (LPVOID*)&reobj.poleobj);
}
if(hr)
{
TRACEERRORSZ("Failure creating object.");
goto err;
}
//Get the clsid of the object.
if(!fStatic)
{
hr = reobj.poleobj->GetUserClassID(&reobj.clsid);
if(hr)
{
TRACEERRORSZ("GetUserClassID() failed.");
goto err;
}
}
//Deal with iconic aspect if specified.
if(hMetaPict)
{
BOOL fUpdate;
hr = OleStdSwitchDisplayAspect(reobj.poleobj, &dwDrawAspect,
DVASPECT_ICON, hMetaPict, FALSE,
FALSE, NULL, &fUpdate);
if(hr)
{
TRACEERRORSZ("OleStdSwitchDisplayAspect() failed.");
goto err;
}
// If we successully changed the aspect, recompute the size.
hr = reobj.poleobj->GetExtent(dwDrawAspect, &sizel);
if(hr)
{
TRACEERRORSZ("GetExtent() failed.");
goto err;
}
}
// Try to retrieve the previous saved RichEdit site flags.
if( ObjectReadSiteFlags(&reobj) != NOERROR )
{
// Set default for site flags
reobj.dwFlags = REO_RESIZABLE;
}
// first, clear the range
prg->ReplaceRange(0, NULL, publdr, SELRR_REMEMBERRANGE);
reobj.cbStruct = sizeof(REOBJECT);
reobj.cp = prg->GetCp();
reobj.dvaspect = dwDrawAspect;
reobj.sizel = sizel;
//COMPATIBILITY ISSUE: from Richedit 1.0 - don't Set the Extent,
//instead Get the Extent below in ObFAddObjectSite
//hr = reobj.poleobj->SetExtent(dwDrawAspect, &sizel);
hr = reobj.poleobj->SetClientSite(reobj.polesite);
if(hr)
{
TRACEERRORSZ("SetClientSite() failed.");
goto err;
}
if(hr = _ped->InsertObject(&reobj))
{
TRACEERRORSZ("InsertObject() failed.");
}
err:
if(reobj.poleobj)
{
reobj.poleobj->Release();
}
if(reobj.polesite)
{
reobj.polesite->Release();
}
if(reobj.pstg)
{
reobj.pstg->Release();
}
return hr;
#else
return 0;
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -