|
|
/*
* rtfread2.cpp * * Description: * This file contains the object functions for RichEdit RTF reader * * Original RichEdit 1.0 RTF converter: Anthony Francisco * Conversion to C++ and RichEdit 2.0: Murray Sargent * * * NOTE: * * All sz's in the RTF*.? files refer to a LPSTRs, not LPTSTRs, unless * * noted as a szW. * * Copyright (c) 1995-2000, Microsoft Corporation. All rights reserved. */
#include "_common.h"
#include "_rtfread.h"
#include "_coleobj.h"
//#include "_nlsprcs.h"
#include "_disp.h"
#include "_dxfrobj.h"
const char szFontsel[]="\\f";
ASSERTDATA
/*
* CRTFRead::HandleFieldInstruction() * * @mfunc * Handle field instruction * * @rdesc * EC The error code */ extern WCHAR pchStartField[]; EC CRTFRead::HandleFieldInstruction() { TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::HandleFieldInstruction"); BYTE *pch, *pch1;
for(pch1 = _szText; *pch1 == ' '; pch1++) // Bypass any leading blanks
; for(pch = pch1; *pch && *pch != ' '; pch++) ;
if(W32->ASCIICompareI(pch1, (BYTE *) "SYMBOL", 6)) { //Remove the start field character added when we saw the \fldinst
CTxtRange rg(*_prg);
rg.Move(-2, TRUE); Assert(rg.CRchTxtPtr::GetChar() == STARTFIELD); rg.Delete(0, SELRR_IGNORE);
BYTE szSymbol[2] = {0,0}; HandleFieldSymbolInstruction(pch, szSymbol); // SYMBOL
HandleText(szSymbol, CONTAINS_NONASCII);
_fSymbolField = TRUE; } else HandleText(pch1, CONTAINS_NONASCII);
TRACEERRSZSC("HandleFieldInstruction()", - _ecParseError); return _ecParseError; }
/*
* CRTFRead::HandleFieldSymbolInstruction(pch) * * @mfunc * Handle specific symbol field * * @rdesc * EC The error code * * @devnote * FUTURE: the two whiles below can be combined into one fairly easily; * Look at the definitions of IsXDigit() and IsDigit() and introduce * a variable flag as well as a variable base multiplier (= 10 or 16). * There were comments saying that we should parse font and font size from * fldrslt, but I don't know why. Field instruction seems to and should contain * all relevant data. */ EC CRTFRead::HandleFieldSymbolInstruction( BYTE *pch, //@parm Pointer to SYMBOL field instruction
BYTE *szSymbol) { TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::HandleFieldInstruction");
BYTE ch; BYTE chSymbol = 0; const char *pchFontsel = szFontsel;
while (*pch == ' ') // Eat spaces
++pch; // Collect symbol char's code
if (*pch == '0' && // which may be in decimal
(*++pch | ' ') == 'x') // or hex
{ // It's in hex
ch = *++pch; while (ch && IsXDigit(ch)) { chSymbol <<= 4; chSymbol += (ch <= '9') ? ch - '0' : (ch & 0x4f) - 'A' + 10; ch = *pch++; } } else // Decimal
{ ch = *pch; while (ch && IsDigit(ch)) { chSymbol *= 10; chSymbol += ch - '0' ; ch = *++pch; } }
szSymbol[0] = chSymbol;
// now check for the \\f "Facename" construct
// and deal with it
while (*pch == ' ') // Eat spaces
++pch;
while (*pch && *pch == *pchFontsel) // Make sure *pch is a \f
{ ++pch; ++pchFontsel; } if (! (*pchFontsel) ) { _ecParseError = HandleFieldSymbolFont(pch); // \\f "Facename"
}
TRACEERRSZSC("HandleFieldInstruction()", - _ecParseError); return _ecParseError; }
/*
* CRTFRead::HandleFieldSymbolFont(pch) * * @mfunc * Handle the \\f "Facename" instruction in the SYMBOL field * * @rdesc * EC The error code * * @devnote WARNING: may change _szText */ EC CRTFRead::HandleFieldSymbolFont( BYTE *pch) //@parm Ptr to symbol field
{ SHORT iFont = _fonts.Count(); TEXTFONT tf; TEXTFONT *ptf = &tf;
_pstateStackTop->ptf = &tf; // ReadFontName tries to append
tf.szName[0] = '\0';
// skip the initial blanks and quotes
while (*pch && (*pch == ' ' || *pch == '\"')) ++pch;
// DONT WORRY, we'll get it back to normal
// ReadFontName depends on _szText, so we need to alter it and then restore
// it's just too bad we have to do it ...
BYTE* szTextBAK = _szText; BOOL fAllAscii = TRUE;
_szText = pch;
// transform the trailing quote into ';'
while (*pch) { if (*pch == '\"') { *pch = ';'; break; }
if(*pch > 0x7f) fAllAscii = FALSE;
++pch; }
// NOW we can read the font name!!
ReadFontName(_pstateStackTop, fAllAscii ? ALL_ASCII : CONTAINS_NONASCII);
// Try to find this face name in the font table
BOOL fFontFound = FALSE; for (SHORT i = 0; i < iFont; ++i) { TEXTFONT *ptfTab = _fonts.Elem(i); if (0 == wcscmp(ptf->szName, ptfTab->szName)) { fFontFound = TRUE; i = ptfTab->sHandle; break; } }
// did we find the face name?
if (!fFontFound) { Assert(i == iFont); i+= RESERVED_FONT_HANDLES;
// Make room in font table for
// font to be inserted
if (!(ptf =_fonts.Add(1,NULL))) { _ped->GetCallMgr()->SetOutOfMemory(); _ecParseError = ecNoMemory; goto exit; }
// repeating inits from tokenFontSelect
ptf->sHandle = i; // Save handle
wcscpy(ptf->szName, tf.szName); ptf->bPitchAndFamily = 0; ptf->fNameIsDBCS = FALSE; ptf->sCodePage = (SHORT)_nCodePage; ptf->iCharRep = DEFAULT_INDEX; // SYMBOL_INDEX ??
}
SelectCurrentFont(i); exit: // needs to go back to normal
_szText = szTextBAK;
return _ecParseError; }
/*
* CRTFRead::ReadData(pbBuffer, cbBuffer) * * @mfunc * Read in object data. This must be called only after all initial * object header info has been read. * * @rdesc * LONG count of bytes read in */ LONG CRTFRead::ReadData( BYTE * pbBuffer, //@parm Ptr to buffer where to put data
LONG cbBuffer) //@parm How many bytes to read in
{ TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::ReadData");
BYTE bChar0, bChar1; LONG cbLeft = cbBuffer;
while (cbLeft && (bChar0 = GetHexSkipCRLF()) < 16 && (bChar1 = GetHexSkipCRLF()) < 16 && _ecParseError == ecNoError) { *pbBuffer++ = bChar0 << 4 | bChar1; cbLeft--; } return cbBuffer - cbLeft ; }
/*
* CRTFRead::ReadBinaryData(pbBuffer, cbBuffer) * * @mfunc * Read cbBuffer bytes into pbBuffer * * @rdesc * Count of bytes read in */ LONG CRTFRead::ReadBinaryData( BYTE * pbBuffer, //@parm Ptr to buffer where to put data
LONG cbBuffer) //@parm How many bytes to read in
{ TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::ReadBinaryData");
LONG cbLeft = min(_cbBinLeft, cbBuffer);
cbBuffer = cbLeft;
for (; cbLeft > 0 && _ecParseError == ecNoError ; cbLeft--) *pbBuffer++ = GetChar();
_cbBinLeft -= cbBuffer;
return cbBuffer ; }
/*
* CRTFRead::SkipBinaryData(cbSkip) * * @mfunc * Skip cbSkip bytes in input streamd * * @rdesc * LONG count of bytes skipped */ LONG CRTFRead::SkipBinaryData( LONG cbSkip) //@parm Count of bytes to skip
{ BYTE rgb[1024];
_cbBinLeft = cbSkip;
while(ReadBinaryData(rgb, sizeof(rgb)) > 0 && _ecParseError == ecNoError) ; return cbSkip; }
/*
* CRTFRead::ReadRawText(pszRawText) * * @mfunc * Read in raw text until }. A buffer is allocated to save the text. * The caller is responsible to free the buffer later. * * @rdesc * LONG count of bytes read */ LONG CRTFRead::ReadRawText( char **pszRawText) //@parm Address of the buffer containing the raw text
{ LONG cch=0; char *szRawTextStart = NULL; char *szRawText = NULL; char chLast=0; char ch; short cRBrace=0; LONG cchBuffer = 0; bool fNeedBuffer = (pszRawText != NULL);
if (fNeedBuffer) { *pszRawText = NULL; cchBuffer = 128; szRawText = szRawTextStart = (char *)PvAlloc(128, GMEM_ZEROINIT);
if(!szRawTextStart) { _ecParseError = ecNoMemory; return 0; } }
while (_ecParseError == ecNoError) { ch = GetChar(); if (ch == 0) break; // error case
if (ch == LF || ch == CR) continue; // Ignore noise characters
if (ch == '}' && chLast != '\\') { if (!cRBrace) { // Done
UngetChar();
if (fNeedBuffer) *szRawText = '\0';
break; } cRBrace--; // count the RBrace so we will ignore the matching pair of LBrace
}
if (ch == '{' && chLast != '\\') cRBrace++;
chLast = ch; cch++;
if (fNeedBuffer) { *szRawText = ch; if (cch == cchBuffer) { // Re-alloc a bigger buffer
char *pNewBuff = (char *)PvReAlloc(szRawTextStart, cchBuffer + 64); if (!pNewBuff) { _ecParseError = ecNoMemory; break; } cchBuffer += 64; szRawTextStart = pNewBuff; szRawText = szRawTextStart + cch; } else szRawText++; } } if (fNeedBuffer) { if (_ecParseError == ecNoError) *pszRawText = szRawTextStart; else FreePv(szRawTextStart); } return cch; }
/*
* CRTFRead::StrAlloc(ppsz, sz) * * @mfunc * Set up a pointer to a newly allocated space to hold a string * * @rdesc * EC The error code */ EC CRTFRead::StrAlloc( WCHAR ** ppsz, //@parm Ptr to ptr to string that needs allocation
BYTE * sz) //@parm String to be copied into allocated space
{ TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::StrAlloc");
int Length = strlen((CHAR *)sz)+1 ;
*ppsz = (WCHAR *) PvAlloc((Length + 1)*sizeof(WCHAR), GMEM_ZEROINIT); if (!*ppsz) { _ped->GetCallMgr()->SetOutOfMemory(); _ecParseError = ecNoMemory; goto Quit; } MultiByteToWideChar(CP_ACP,0,(char *)sz,-1,*ppsz,Length) ;
Quit: return _ecParseError; }
/*
* CRTFRead::FreeRtfObject() * * @mfunc * Cleans up memory used by prtfobject */ void CRTFRead::FreeRtfObject() { TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::FreeRtfObject");
if (_prtfObject) { FreePv(_prtfObject->szClass); FreePv(_prtfObject->szName); FreePv(_prtfObject); _prtfObject = NULL; } }
/*
* CRTFRead::ObjectReadSiteFlags(preobj) * * @mfunc * Read dwFlags and dwUser bytes from a container specific stream * * @rdesc * BOOL TRUE if successfully read the bytes */ BOOL CRTFRead::ObjectReadSiteFlags( REOBJECT * preobj) //@parm REOBJ from where to copy flags. This preobj is
// then later put out in a site
{ return (::ObjectReadSiteFlags(preobj) == NOERROR); }
/*
* ObjectReadEBookImageInfoFromEditStream() * * @mfunc * Reads in information about the EBook Image * At this point we don't read in the actual data * We just get info about the dimensions of the data * * Added * VikramM - esp. for e-books * * @rdesc * BOOL TRUE on success, FALSE on failure. */ BOOL CRTFRead::ObjectReadEBookImageInfoFromEditStream() { HRESULT hr = E_FAIL; BOOL fRet = FALSE; REOBJECT reobj = { 0 }; COleObject * pObj = NULL; LPARAM EBookID = 0; SIZE size; DWORD dwFlags;
CObjectMgr *ObjectMgr = _ped->GetObjectMgr(); if (! ObjectMgr) goto Cleanup;
if(!_prtfObject->szName) goto Cleanup;
// eBooks implies advanced layout, ensure the bit is on
_ped->OnSetTypographyOptions(TO_ADVANCEDLAYOUT, TO_ADVANCEDLAYOUT);
reobj.cbStruct = sizeof(REOBJECT); reobj.cp = _prg->GetCp();
// Read the object size from here. The size is in Device Units
if(!_ped->fInHost2() || (_ped->GetHost())->TxEBookLoadImage(_prtfObject->szName, &EBookID, &size,&dwFlags) != S_OK ) goto Cleanup;
// For objects, xExt and yExt need to be in Twips ..
_prtfObject->xExt = size.cx; _prtfObject->yExt = size.cy; { CRchTxtPtr rtp(_ped, 0); CDisplay * pdp = _ped->_pdp; reobj.sizel.cx = pdp->DUtoHimetricU(_prtfObject->xExt) * _prtfObject->xScale / 100; reobj.sizel.cy = pdp->DVtoHimetricV(_prtfObject->yExt) * _prtfObject->yScale / 100; } // what does this do ??
reobj.dvaspect = DVASPECT_CONTENT; // OLE 1 forces DVASPECT_CONTENT
reobj.dwFlags &= ~REO_BLANK; reobj.dwFlags |= dwFlags; //Ebook Float Flags
pObj = new COleObject(_ped); if(!pObj) goto Cleanup;
pObj->SetEBookImageID(EBookID); pObj->IsEbookImage(TRUE); pObj->SetEBookImageSizeDP(size); reobj.polesite = pObj;
#ifndef NOINKOBJECT
if(IsEqualCLSID(reobj.clsid, CLSID_Ink)) Apply_CF(); else #endif
_prg->Set_iCF(-1); if(hr = ObjectMgr->InsertObject(_prg, &reobj, NULL)) goto Cleanup;
fRet = TRUE;
Cleanup: // InsertObject AddRefs the object, so we need to release it
SafeReleaseAndNULL((IUnknown**)&pObj); return fRet; }
/*
* CRTFRead::ObjectReadFromStream() * * @mfunc * Reads an OLE object from the RTF output stream. * * @rdesc * BOOL TRUE on success, FALSE on failure. */ BOOL CRTFRead::ObjectReadFromEditStream() { BOOL fRet = FALSE; HRESULT hr; CObjectMgr * pObjectMgr = _ped->GetObjectMgr(); LPOLECACHE polecache = NULL; LPRICHEDITOLECALLBACK precall=NULL; LPENUMSTATDATA penumstatdata = NULL; REOBJECT reobj = { 0 }; STATDATA statdata;
if(!pObjectMgr) goto Cleanup; precall = pObjectMgr->GetRECallback();
// If no IRichEditOleCallback exists, then fail
if (!precall) goto Cleanup;
// AssertSz(_prtfObject->szClass,"ObFReadFromEditstream: reading unknown class");
if (_prtfObject->szClass) CLSIDFromProgID(_prtfObject->szClass, &reobj.clsid);
// Get storage for the object from the application
if (precall->GetNewStorage(&reobj.pstg)) goto Cleanup;
hr = OleConvertOLESTREAMToIStorage((LPOLESTREAM) &RTFReadOLEStream, reobj.pstg, NULL); if (FAILED(hr)) goto Cleanup;
// Create another object site for the new object
_ped->GetClientSite(&reobj.polesite) ; if(!reobj.polesite) goto Cleanup;
if(OleLoad(reobj.pstg, IID_IOleObject, reobj.polesite, (LPVOID *)&reobj.poleobj)) { if(!reobj.polesite->Release()) // OleLoad() may AddRef reobj.polesite
reobj.polesite = NULL; goto Cleanup; }
CLSID clsid;
// Get the actual clsid from the object
if (reobj.poleobj->GetUserClassID(&clsid) == NOERROR) reobj.clsid = clsid; reobj.cbStruct = sizeof(REOBJECT); reobj.cp = _prg->GetCp(); reobj.sizel.cx = HimetricFromTwips(_prtfObject->xExt) * _prtfObject->xScale / 100; reobj.sizel.cy = HimetricFromTwips(_prtfObject->yExt) * _prtfObject->yScale / 100;
// Read any container flags which may have been previously saved
if (!ObjectReadSiteFlags(&reobj)) reobj.dwFlags = REO_RESIZABLE; // If no flags, make best guess
reobj.dvaspect = DVASPECT_CONTENT; // OLE 1 forces DVASPECT_CONTENT
// Ask the cache if it knows what to display
if (!reobj.poleobj->QueryInterface(IID_IOleCache, (void**)&polecache) && !polecache->EnumCache(&penumstatdata)) { // Go look for the best cached presentation CF_METAFILEPICT
while (penumstatdata->Next(1, &statdata, NULL) == S_OK) { if (statdata.formatetc.cfFormat == CF_METAFILEPICT) { LPDATAOBJECT pdataobj = NULL; STGMEDIUM med; BOOL fUpdate;
ZeroMemory(&med, sizeof(STGMEDIUM)); if (!polecache->QueryInterface(IID_IDataObject, (void**)&pdataobj) && !pdataobj->GetData(&statdata.formatetc, &med)) { HANDLE hGlobal = med.hGlobal;
if( FIsIconMetafilePict(hGlobal) ) { OleStdSwitchDisplayAspect(reobj.poleobj, &reobj.dvaspect, DVASPECT_ICON, med.hGlobal, TRUE, FALSE, NULL, &fUpdate); } } ReleaseStgMedium(&med); if (pdataobj) pdataobj->Release(); break; } } polecache->Release(); penumstatdata->Release(); }
// EVIL HACK ALERT. This code is borrowed from RichEdit 1.0; Word generates
// bogus objects, so we need to compensate.
if( reobj.dvaspect == DVASPECT_CONTENT ) { IStream *pstm = NULL; BYTE bT; BOOL fUpdate;
if (!reobj.pstg->OpenStream(OLESTR("\3ObjInfo"), 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pstm) && !pstm->Read(&bT, sizeof(BYTE), NULL) && (bT & 0x40)) { _fNeedIcon = TRUE; _fNeedPres = TRUE; _pobj = (COleObject *)reobj.polesite; OleStdSwitchDisplayAspect(reobj.poleobj, &reobj.dvaspect, DVASPECT_ICON, NULL, TRUE, FALSE, NULL, &fUpdate); } if( pstm ) pstm->Release(); }
// Since we are loading an object, it shouldn't be blank
reobj.dwFlags &= ~REO_BLANK;
#ifndef NOINKOBJECT
if(IsEqualCLSID(reobj.clsid, CLSID_Ink)) Apply_CF(); else #endif
_prg->Set_iCF(-1); hr = pObjectMgr->InsertObject(_prg, &reobj, NULL); if(hr) goto Cleanup;
// EVIL HACK ALERT!! Word doesn't give us objects with presenation
// caches; as a result, we can't draw them! In order to get around this,
// we check to see if there is a presentation cache (via the same way
// RE 1.0 did) using a GetExtent call. If that fails, we'll just use
// the presentation stored in the RTF.
//
// COMPATIBILITY ISSUE: RE 1.0, instead of using the presentation stored
// in RTF, would instead call IOleObject::Update. There are two _big_
// drawbacks to this approach: 1. it's incredibly expensive (potentially,
// MANY SECONDS per object), and 2. it doesn't work if the object server
// is not installed on the machine.
SIZE sizeltemp;
if( reobj.poleobj->GetExtent(reobj.dvaspect, &sizeltemp) != NOERROR ) { _fNeedPres = TRUE; _pobj = (COleObject *)reobj.polesite; }
fRet = TRUE;
Cleanup: if (reobj.pstg) reobj.pstg->Release(); if (reobj.polesite) reobj.polesite->Release(); if (reobj.poleobj) reobj.poleobj->Release();
return fRet; }
/*
* ObHBuildMetafilePict(prtfobject, hBits) * * @func * Build a METAFILEPICT from RTFOBJECT and the raw data. * * @rdesc * HGLOBAL Handle to a METAFILEPICT */ HGLOBAL ObHBuildMetafilePict( RTFOBJECT * prtfobject, //@parm Details we picked up from RTF
HGLOBAL hBits) //@parm Handle to the raw data
{ #ifndef NOMETAFILES
ULONG cbBits; HGLOBAL hmfp = NULL; LPBYTE pbBits; LPMETAFILEPICT pmfp = NULL; SCODE sc = E_OUTOFMEMORY;
// Allocate the METAFILEPICT structure
hmfp = GlobalAlloc(GHND, sizeof(METAFILEPICT)); if (!hmfp) goto Cleanup;
// Lock it down
pmfp = (LPMETAFILEPICT) GlobalLock(hmfp); if (!pmfp) goto Cleanup;
// Put in the header information
pmfp->mm = prtfobject->sPictureType; pmfp->xExt = prtfobject->xExt; pmfp->yExt = prtfobject->yExt;
// Set the metafile bits
pbBits = (LPBYTE) GlobalLock(hBits); cbBits = GlobalSize(hBits); pmfp->hMF = SetMetaFileBitsEx(cbBits, pbBits); // We can throw away the data now since we don't need it anymore
GlobalUnlock(hBits); GlobalFree(hBits);
if (!pmfp->hMF) goto Cleanup; GlobalUnlock(hmfp); sc = S_OK;
Cleanup: if (sc && hmfp) { if (pmfp) { if (pmfp->hMF) ::DeleteMetaFile(pmfp->hMF); GlobalUnlock(hmfp); } GlobalFree(hmfp); hmfp = NULL; } TRACEERRSZSC("ObHBuildMetafilePict", sc); return hmfp; #else
return NULL; #endif
}
/*
* ObHBuildBitmap(prtfobject, hBits) * * @func * Build a BITMAP from RTFOBJECT and the raw data * * @rdesc * HGLOBAL Handle to a BITMAP */ HGLOBAL ObHBuildBitmap( RTFOBJECT * prtfobject, //@parm Details we picked up from RTF
HGLOBAL hBits) //@parm Handle to the raw data
{ HBITMAP hbm = NULL; LPVOID pvBits = GlobalLock(hBits);
if(pvBits) { hbm = CreateBitmap(prtfobject->xExt, prtfobject->yExt, prtfobject->cColorPlanes, prtfobject->cBitsPerPixel, pvBits); } GlobalUnlock(hBits); GlobalFree(hBits); return hbm; }
/*
* ObHBuildDib(prtfobject, hBits) * * @func * Build a DIB from RTFOBJECT and the raw data * * @rdesc * HGLOBAL Handle to a DIB */ HGLOBAL ObHBuildDib( RTFOBJECT * prtfobject, //@parm Details we picked up from RTF
HGLOBAL hBits) //@parm Handle to the raw data
{ // Apparently DIB's are just a binary dump
return hBits; }
/*
* CRTFRead::StaticObjectReadFromEditstream(cb) * * @mfunc * Reads a picture from the RTF output stream. * * @rdesc * BOOL TRUE on success, FALSE on failure. */ #define cbBufferMax 16384
#define cbBufferStep 1024
#define cbBufferMin 1024
BOOL CRTFRead::StaticObjectReadFromEditStream( int cb) //@parm Count of bytes to read
{ LONG cbBuffer; LONG cbRead; DWORD dwAdvf; DWORD dwConn; BOOL fBackground = _pstateStackTop && _pstateStackTop->fBackground; FORMATETC formatetc; BOOL fRet = FALSE; HGLOBAL hBits = NULL; HRESULT hr = E_FAIL; LPBYTE pbBuffer = NULL; CDocInfo * pDocInfo = _ped->GetDocInfoNC(); CObjectMgr *pObjectMgr = _ped->GetObjectMgr(); LPOLECACHE polecache = NULL; LPPERSISTSTORAGE pperstg = NULL; LPRICHEDITOLECALLBACK precall; LPSTREAM pstm = NULL; REOBJECT reobj = { 0 }; STGMEDIUM stgmedium; HGLOBAL (*pfnBuildPict)(RTFOBJECT *, HGLOBAL) = NULL;
if(!pObjectMgr) goto Cleanup; // precall may end up being null (e.g. Windows CE).
precall = pObjectMgr->GetRECallback();
// Initialize various data structures
formatetc.ptd = NULL; formatetc.dwAspect = DVASPECT_CONTENT; formatetc.lindex = -1; formatetc.tymed = TYMED_NULL; switch (_prtfObject->sType) { case ROT_Metafile: reobj.clsid = CLSID_StaticMetafile; formatetc.cfFormat = CF_METAFILEPICT; formatetc.tymed = TYMED_MFPICT; pfnBuildPict = ObHBuildMetafilePict; break;
case ROT_Bitmap: reobj.clsid = CLSID_StaticDib; formatetc.cfFormat = CF_BITMAP; formatetc.tymed = TYMED_GDI; pfnBuildPict = ObHBuildBitmap; break;
case ROT_DIB: reobj.clsid = CLSID_StaticDib; formatetc.cfFormat = CF_DIB; formatetc.tymed = TYMED_HGLOBAL; pfnBuildPict = ObHBuildDib; break;
case ROT_PNG: case ROT_JPEG: // We convert these types of pictures to a bitmap
reobj.clsid = CLSID_StaticDib; formatetc.cfFormat = CF_BITMAP; formatetc.tymed = TYMED_GDI; break; }
reobj.sizel.cx = (LONG) HimetricFromTwips(_prtfObject->xExtGoal) * _prtfObject->xScale / 100; reobj.sizel.cy = (LONG) HimetricFromTwips(_prtfObject->yExtGoal) * _prtfObject->yScale / 100; stgmedium.tymed = formatetc.tymed; stgmedium.pUnkForRelease = NULL;
if (precall) { if( !_fNeedPres ) { // Get storage for the object from the application
if (precall->GetNewStorage(&reobj.pstg)) goto Cleanup; } // Let's create a stream on HGLOBAL
if (hr = CreateStreamOnHGlobal(NULL, FALSE, &pstm)) goto Cleanup;
// Allocate a buffer, preferably a big one
for (cbBuffer = cbBufferMax; cbBuffer >= cbBufferMin; cbBuffer -= cbBufferStep) { pbBuffer = (unsigned char *)PvAlloc(cbBuffer, 0); if (pbBuffer) break; } } else { cbBuffer = cb; if(!cb) { // This means we didn't understand the picture type; so just
// skip it without failing.
fRet = TRUE; goto Cleanup; } hBits = GlobalAlloc(GMEM_FIXED, cb); pbBuffer = (BYTE *) GlobalLock(hBits); } if (!pbBuffer) goto Cleanup; // Copy the data from RTF into our HGLOBAL
while ((cbRead = RTFReadOLEStream.lpstbl->Get(&RTFReadOLEStream,pbBuffer,cbBuffer)) > 0) { if (_ecParseError != ecNoError) goto Cleanup;
if(pstm) { hr = pstm->Write(pbBuffer, cbRead, NULL); if(hr != NOERROR) { TRACEERRSZSC("ObFReadStaticFromEditstream: Write", GetScode(hr)); goto Cleanup; } } }
if (hBits) { Assert(!precall); GlobalUnlock(hBits); pbBuffer = NULL; // To avoid free below
}
if (pstm && (hr = GetHGlobalFromStream(pstm, &hBits))) { TRACEERRSZSC("ObFReadStaticFromEditstream: no hglobal from stm", GetScode(hr)); goto Cleanup; }
if(pDocInfo && fBackground) { pDocInfo->_bPicFormat = (BYTE)_prtfObject->sType; pDocInfo->_bPicFormatParm = (BYTE)_prtfObject->sPictureType; pDocInfo->_xExt = _prtfObject->xExt; pDocInfo->_yExt = _prtfObject->yExt; pDocInfo->_xScale = _prtfObject->xScale; pDocInfo->_yScale = _prtfObject->yScale; pDocInfo->_xExtGoal = _prtfObject->xExtGoal; pDocInfo->_yExtGoal = _prtfObject->yExtGoal; pDocInfo->_xExtPict = _prtfObject->xExtPict; pDocInfo->_yExtPict = _prtfObject->yExtPict; pDocInfo->_rcCrop = _prtfObject->rectCrop; pDocInfo->_hdata = hBits; }
// Build the picture
if(_prtfObject->sType == ROT_JPEG || _prtfObject->sType == ROT_PNG) { HBITMAP hbmp = W32->GetPictureBitmap(pstm); if (!hbmp) { hr = E_FAIL; goto Cleanup; } stgmedium.hGlobal = hbmp; } else if( pfnBuildPict ) stgmedium.hGlobal = pfnBuildPict(_prtfObject, hBits); else { // This means we didn't understand the picture type; so just
// skip it without failing.
fRet = TRUE; goto Cleanup; }
if( precall ) { if(!stgmedium.hGlobal) goto Cleanup;
if( !_fNeedPres ) { // Create the default handler
hr = OleCreateDefaultHandler(reobj.clsid, NULL, IID_IOleObject, (void **)&reobj.poleobj); if (hr) { TRACEERRSZSC("ObFReadStaticFromEditstream: no def handler", GetScode(hr)); goto Cleanup; }
// Get the IPersistStorage and initialize it
if ((hr = reobj.poleobj->QueryInterface(IID_IPersistStorage,(void **)&pperstg)) || (hr = pperstg->InitNew(reobj.pstg))) { TRACEERRSZSC("ObFReadStaticFromEditstream: InitNew", GetScode(hr)); goto Cleanup; } dwAdvf = ADVF_PRIMEFIRST; } else { Assert(_pobj); _pobj->GetIUnknown()->QueryInterface(IID_IOleObject, (void **)&(reobj.poleobj)); dwAdvf = ADVF_NODATA; formatetc.dwAspect = _fNeedIcon ? DVASPECT_ICON : DVASPECT_CONTENT; }
// Get the IOleCache and put the picture data there
if (hr = reobj.poleobj->QueryInterface(IID_IOleCache,(void **)&polecache)) { TRACEERRSZSC("ObFReadStaticFromEditstream: QI: IOleCache", GetScode(hr)); goto Cleanup; }
if (FAILED(hr = polecache->Cache(&formatetc, dwAdvf, &dwConn))) { TRACEERRSZSC("ObFReadStaticFromEditstream: Cache", GetScode(hr)); goto Cleanup; }
if (hr = polecache->SetData(&formatetc, &stgmedium, TRUE)) { TRACEERRSZSC("ObFReadStaticFromEditstream: SetData", GetScode(hr)); goto Cleanup; } }
if( !_fNeedPres ) { // Create another object site for the new object
_ped->GetClientSite(&reobj.polesite); if (!reobj.polesite ) goto Cleanup;
// Set the client site
if (reobj.poleobj && (hr = reobj.poleobj->SetClientSite(reobj.polesite))) { TRACEERRSZSC("ObFReadStaticFromEditstream: SetClientSite", GetScode(hr)); goto Cleanup; } else if (!reobj.poleobj) { if(_prtfObject->sType == ROT_DIB) { // Windows CE static object Save the data and mark it.
COleObject *pobj = (COleObject *)reobj.polesite; COleObject::ImageInfo *pimageinfo = new COleObject::ImageInfo; pobj->SetHdata(hBits); pimageinfo->xScale = _prtfObject->xScale; pimageinfo->yScale = _prtfObject->yScale; pimageinfo->xExtGoal = _prtfObject->xExtGoal; pimageinfo->yExtGoal = _prtfObject->yExtGoal; pimageinfo->cBytesPerLine = _prtfObject->cBytesPerLine; pobj->SetImageInfo(pimageinfo); } else goto Cleanup; // There has been a mistake
}
// Put object into the edit control
reobj.cbStruct = sizeof(REOBJECT); reobj.cp = _prg->GetCp(); reobj.dvaspect = DVASPECT_CONTENT; reobj.dwFlags = fBackground ? REO_RESIZABLE | REO_USEASBACKGROUND : REO_RESIZABLE; // Since we are loading an object, it shouldn't be blank
reobj.dwFlags &= ~REO_BLANK; if(_pstateStackTop->fShape && _ped->fUseObjectWrapping()) reobj.dwFlags |= _dwFlagsShape;
#ifndef NOINKOBJECT
if(IsEqualCLSID(reobj.clsid, CLSID_Ink)) Apply_CF(); else #endif
_prg->Set_iCF(-1); hr = pObjectMgr->InsertObject(_prg, &reobj, NULL); if(hr) goto Cleanup; } else { // The new presentation may have a different idea about how big the
// object is supposed to be. Make sure the object stays the correct
// size.
_pobj->ResetSize((SIZEUV&)reobj.sizel); } fRet = TRUE;
Cleanup: // Do not display backgrounds.
if(pDocInfo && fBackground) pDocInfo->_nFillType=-1;
if (polecache) polecache->Release() ; if (reobj.pstg) reobj.pstg->Release(); if (reobj.polesite) reobj.polesite->Release(); if (reobj.poleobj) reobj.poleobj->Release(); if (pperstg) pperstg->Release(); if (pstm) pstm->Release(); FreePv(pbBuffer);
_fNeedIcon = FALSE; _fNeedPres = FALSE; _pobj = NULL;
return fRet; }
/*
* CRTFRead::HandleSTextFlow(mode) * * @mfunc * Handle STextFlow setting. */ void CRTFRead::HandleSTextFlow( int mode) //@parm TextFlow mode
{ static BYTE bTFlow[9] = // Rotate @Font
{ 0, // 0 0
tflowSW | 0x80, // 270 1
tflowNE, // 90 0
tflowSW, // 270 0
0x80, // 0 1
0, // ?
tflowNE | 0x80, // 90 1
tflowWN | 0x80, // 180 1
tflowWN // 180 0
};
if (IN_RANGE(0, mode, 8)) { _ped->_fUseAtFont = bTFlow[mode] >> 7; _ped->_pdp->SetTflow(bTFlow[mode] & 0x03); } }
|