Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1091 lines
26 KiB

  1. /*
  2. * rtfread2.cpp
  3. *
  4. * Description:
  5. * This file contains the object functions for RichEdit RTF reader
  6. *
  7. * Original RichEdit 1.0 RTF converter: Anthony Francisco
  8. * Conversion to C++ and RichEdit 2.0: Murray Sargent
  9. *
  10. * * NOTE:
  11. * * All sz's in the RTF*.? files refer to a LPSTRs, not LPTSTRs, unless
  12. * * noted as a szW.
  13. *
  14. * Copyright (c) 1995-1997, Microsoft Corporation. All rights reserved.
  15. */
  16. #include "_common.h"
  17. #include "_rtfread.h"
  18. #include "_coleobj.h"
  19. //#include "_nlsprcs.h"
  20. const char szFontsel[]="\\f";
  21. ASSERTDATA
  22. /*
  23. * CRTFRead::HandleFieldInstruction()
  24. *
  25. * @mfunc
  26. * Handle field instruction
  27. *
  28. * @rdesc
  29. * EC The error code
  30. */
  31. EC CRTFRead::HandleFieldInstruction()
  32. {
  33. TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::HandleFieldInstruction");
  34. //TODO rewrite this function for common case
  35. //FUTURE save field instruction
  36. BYTE *pch, *pch1;
  37. for(pch1 = _szText; *pch1 == ' '; pch1++) // Bypass any leading blanks
  38. ;
  39. for(pch = pch1; *pch && *pch != ' '; pch++)
  40. ;
  41. _fHyperlinkField = FALSE;
  42. if(W32->ASCIICompareI(pch1, (BYTE *) "SYMBOL", 6))
  43. HandleFieldSymbolInstruction(pch); // SYMBOL
  44. else if (W32->ASCIICompareI(pch1, (BYTE *) "HYPERLINK", 9))
  45. {
  46. _fHyperlinkField = TRUE;
  47. HandleFieldHyperlink(pch);
  48. }
  49. // save the current formatting for the field result
  50. _FieldCF = _CF;
  51. _ptfField = _pstateStackTop->ptf;
  52. _nFieldCodePage = _pstateStackTop->nCodePage;
  53. _dwMaskFieldCF = _dwMaskCF;
  54. _dwMaskFieldCF2 = _dwMaskCF2;
  55. TRACEERRSZSC("HandleFieldInstruction()", - _ecParseError);
  56. return _ecParseError;
  57. }
  58. /*
  59. * CRTFRead::HandleFieldSymbolInstruction(pch)
  60. *
  61. * @mfunc
  62. * Handle specific symbol field
  63. *
  64. * @rdesc
  65. * EC The error code
  66. *
  67. * @devnote
  68. * FUTURE: the two whiles below can be combined into one fairly easily;
  69. * Look at the definitions of IsXDigit() and IsDigit() and introduce
  70. * a variable flag as well as a variable base multiplier (= 10 or 16).
  71. */
  72. EC CRTFRead::HandleFieldSymbolInstruction(
  73. BYTE *pch ) //@parm Pointer to SYMBOL field instruction
  74. {
  75. TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::HandleFieldInstruction");
  76. BYTE ch;
  77. BYTE chSymbol = 0;
  78. const char *pchFontsel = szFontsel;
  79. while (*pch == ' ') // Eat spaces
  80. ++pch;
  81. // Collect symbol char's code
  82. if (*pch == '0' && // which may be in decimal
  83. (*++pch | ' ') == 'x') // or hex
  84. { // It's in hex
  85. ch = *++pch;
  86. while (ch && IsXDigit(ch))
  87. {
  88. chSymbol <<= 4;
  89. chSymbol += (ch <= '9') ? ch - '0' : (ch & 0x4f) - 'A' + 10;
  90. ch = *pch++;
  91. }
  92. }
  93. else // Decimal
  94. {
  95. ch = *pch;
  96. while (ch && IsDigit(ch))
  97. {
  98. chSymbol *= 10;
  99. chSymbol += ch - '0' ;
  100. ch = *++pch;
  101. }
  102. }
  103. _szSymbolFieldResult = (BYTE *)PvAlloc(2, GMEM_ZEROINIT);
  104. if (NULL == _szSymbolFieldResult)
  105. {
  106. _ecParseError = ecNoMemory;
  107. goto CleanUp;
  108. }
  109. _szSymbolFieldResult[0] = chSymbol;
  110. // now check for the \\f "Facename" construct
  111. // and deal with it
  112. while (*pch == ' ') // Eat spaces
  113. ++pch;
  114. while (*pch && *pch == *pchFontsel) // Make sure *pch is a \f
  115. {
  116. ++pch;
  117. ++pchFontsel;
  118. }
  119. if (! (*pchFontsel) )
  120. {
  121. _ecParseError = HandleFieldSymbolFont(pch); // \\f "Facename"
  122. }
  123. // ASSERTION font & font size will be in field result \flds
  124. // BUGBUG: A more robust implementation would parse the font
  125. // and font size from both \fldinst and \fldrslt (RE1.0 does this)
  126. CleanUp:
  127. TRACEERRSZSC("HandleFieldInstruction()", - _ecParseError);
  128. return _ecParseError;
  129. }
  130. /*
  131. * CRTFRead::HandleFieldSymbolFont(pch)
  132. *
  133. * @mfunc
  134. * Handle the \\f "Facename" instruction in the SYMBOL field
  135. *
  136. * @rdesc
  137. * EC The error code
  138. *
  139. * @devnote WARNING: may change _szText
  140. */
  141. EC CRTFRead::HandleFieldSymbolFont(
  142. BYTE *pch) //@parm Ptr to symbol field
  143. {
  144. SHORT iFont = _fonts.Count();
  145. TEXTFONT tf;
  146. TEXTFONT *ptf = &tf;
  147. _pstateStackTop->ptf = &tf;
  148. // ReadFontName tries to append
  149. tf.szName[0] = '\0';
  150. // skip the initial blanks and quotes
  151. while (*pch && (*pch == ' ' || *pch == '\"'))
  152. ++pch;
  153. // DONT WORRY, we'll get it back to normal
  154. // ReadFontName depends on _szText, so we need to alter it and then restore
  155. // it's just too bad we have to do it ...
  156. BYTE* szTextBAK = _szText;
  157. BOOL fAllAscii = TRUE;
  158. _szText = pch;
  159. // transform the trailing quote into ';'
  160. while (*pch)
  161. {
  162. if (*pch == '\"')
  163. {
  164. *pch = ';';
  165. break;
  166. }
  167. if(*pch > 0x7f)
  168. fAllAscii = FALSE;
  169. ++pch;
  170. }
  171. // NOW we can read the font name!!
  172. ReadFontName(_pstateStackTop, fAllAscii ? ALL_ASCII : CONTAINS_NONASCII);
  173. // Try to find this face name in the font table
  174. BOOL fFontFound = FALSE;
  175. for (SHORT i = 0; i < iFont; ++i)
  176. {
  177. TEXTFONT *ptfTab = _fonts.Elem(i);
  178. if (0 == wcscmp(ptf->szName, ptfTab->szName))
  179. {
  180. fFontFound = TRUE;
  181. i = ptfTab->sHandle;
  182. break;
  183. }
  184. }
  185. // did we find the face name?
  186. if (!fFontFound)
  187. {
  188. Assert(i == iFont);
  189. i+= RESERVED_FONT_HANDLES;
  190. // Make room in font table for
  191. // font to be inserted
  192. if (!(ptf =_fonts.Add(1,NULL)))
  193. {
  194. _ped->GetCallMgr()->SetOutOfMemory();
  195. _ecParseError = ecNoMemory;
  196. goto exit;
  197. }
  198. // repeating inits from tokenFontSelect
  199. ptf->sHandle = i; // Save handle
  200. wcscpy(ptf->szName, tf.szName);
  201. ptf->bPitchAndFamily = 0;
  202. ptf->fNameIsDBCS = FALSE;
  203. ptf->sCodePage = (SHORT)_nCodePage;
  204. ptf->bCharSet = DEFAULT_CHARSET; // SYMBOL_CHARSET ??
  205. }
  206. SelectCurrentFont(i);
  207. exit:
  208. // needs to go back to normal
  209. _szText = szTextBAK;
  210. return _ecParseError;
  211. }
  212. /*
  213. * CRTFRead::HandleFieldHyperlink(pch)
  214. *
  215. * @mfunc
  216. * Handle HYPERLINK field
  217. *
  218. * @rdesc
  219. * EC The error code
  220. */
  221. EC CRTFRead::HandleFieldHyperlink(
  222. BYTE *pch) //@parm Pointer to HYPERLINK field instruction
  223. {
  224. TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::HandleFieldHyperlink");
  225. BYTE *pBuffer;
  226. for( ; *pch == ' '; pch++) ; // Skip leading blanks
  227. // allocate the buffer and add the string to it
  228. _cchHyperlinkFldinst = MAX_PATH;
  229. _cchHyperlinkFldinstUsed = 1;
  230. pBuffer = (BYTE *)PvAlloc( MAX_PATH, GMEM_FIXED );
  231. if ( !pBuffer )
  232. return ( _ecParseError = ecNoMemory );
  233. pBuffer[0] = ' ';
  234. pBuffer[1] = '\0';
  235. _szHyperlinkFldinst = pBuffer;
  236. if ( *pch )
  237. {
  238. _ecParseError = AppendString( &_szHyperlinkFldinst, pch, &_cchHyperlinkFldinst, &_cchHyperlinkFldinstUsed );
  239. }
  240. return _ecParseError;
  241. }
  242. /*
  243. * CRTFRead::ReadData(pbBuffer, cbBuffer)
  244. *
  245. * @mfunc
  246. * Read in object data. This must be called only after all initial
  247. * object header info has been read.
  248. *
  249. * @rdesc
  250. * LONG count of bytes read in
  251. */
  252. LONG CRTFRead::ReadData(
  253. BYTE * pbBuffer, //@parm Ptr to buffer where to put data
  254. LONG cbBuffer) //@parm How many bytes to read in
  255. {
  256. TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::ReadData");
  257. BYTE bChar0, bChar1;
  258. LONG cbLeft = cbBuffer;
  259. while (cbLeft && (bChar0 = GetHexSkipCRLF()) < 16 &&
  260. (bChar1 = GetHexSkipCRLF()) < 16 &&
  261. _ecParseError == ecNoError)
  262. {
  263. *pbBuffer++ = bChar0 << 4 | bChar1;
  264. cbLeft--;
  265. }
  266. return cbBuffer - cbLeft ;
  267. }
  268. /*
  269. * CRTFRead::ReadBinaryData(pbBuffer, cbBuffer)
  270. *
  271. * @mfunc
  272. * Read cbBuffer bytes into pbBuffer
  273. *
  274. * @rdesc
  275. * Count of bytes read in
  276. */
  277. LONG CRTFRead::ReadBinaryData(
  278. BYTE * pbBuffer, //@parm Ptr to buffer where to put data
  279. LONG cbBuffer) //@parm How many bytes to read in
  280. {
  281. TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::ReadBinaryData");
  282. LONG cbLeft = min(_cbBinLeft, cbBuffer);
  283. cbBuffer = cbLeft;
  284. for (; cbLeft > 0 && _ecParseError == ecNoError ; cbLeft--)
  285. {
  286. *pbBuffer++ = GetChar();
  287. }
  288. _cbBinLeft -= cbBuffer - cbLeft;
  289. return cbBuffer - cbLeft ;
  290. }
  291. /*
  292. * CRTFRead::SkipBinaryData(cbSkip)
  293. *
  294. * @mfunc
  295. * Skip cbSkip bytes in input streamd
  296. *
  297. * @rdesc
  298. * LONG count of bytes skipped
  299. */
  300. LONG CRTFRead::SkipBinaryData(
  301. LONG cbSkip) //@parm Count of bytes to skip
  302. {
  303. BYTE rgb[1024];
  304. _cbBinLeft = cbSkip;
  305. while(ReadBinaryData(rgb, sizeof(rgb)) > 0 && _ecParseError == ecNoError)
  306. ;
  307. return cbSkip;
  308. }
  309. /*
  310. * CRTFRead::ReadRawText(pszRawText)
  311. *
  312. * @mfunc
  313. * Read in raw text until }. A buffer is allocated to save the text.
  314. * The caller is responsible to free the buffer later.
  315. *
  316. * @rdesc
  317. * LONG count of bytes read
  318. */
  319. LONG CRTFRead::ReadRawText(
  320. char **pszRawText) //@parm Address of the buffer containing the raw text
  321. {
  322. LONG cch=0;
  323. char *szRawTextStart = NULL;
  324. char *szRawText = NULL;
  325. char chLast=0;
  326. char ch;
  327. short cRBrace=0;
  328. LONG cchBuffer = 0;
  329. bool fNeedBuffer = (pszRawText != NULL);
  330. if (fNeedBuffer)
  331. {
  332. *pszRawText = NULL;
  333. cchBuffer = 128;
  334. szRawText = szRawTextStart = (char *)PvAlloc(128, GMEM_ZEROINIT);
  335. if(!szRawTextStart)
  336. {
  337. _ecParseError = ecNoMemory;
  338. return 0;
  339. }
  340. }
  341. while (_ecParseError == ecNoError)
  342. {
  343. ch = GetChar();
  344. if (ch == 0)
  345. break; // error case
  346. if (ch == LF || ch == CR)
  347. continue; // ignore noice characters
  348. if (ch == '}' && chLast != '\\')
  349. {
  350. if (!cRBrace)
  351. {
  352. // Done
  353. UngetChar();
  354. if (fNeedBuffer)
  355. *szRawText = '\0';
  356. break;
  357. }
  358. cRBrace--; // count the RBrace so we will ignore the matching pair of LBrace
  359. }
  360. if (ch == '{' && chLast != '\\')
  361. cRBrace++;
  362. chLast = ch;
  363. cch++;
  364. if (fNeedBuffer)
  365. {
  366. *szRawText = ch;
  367. if (cch == cchBuffer)
  368. {
  369. // Re-alloc a bigger buffer
  370. char *pNewBuff = (char *)PvReAlloc(szRawTextStart, cchBuffer + 64);
  371. if (!pNewBuff)
  372. {
  373. _ecParseError = ecNoMemory;
  374. break;
  375. }
  376. cchBuffer += 64;
  377. szRawTextStart = pNewBuff;
  378. szRawText = szRawTextStart + cch;
  379. }
  380. else
  381. szRawText++;
  382. }
  383. }
  384. if (fNeedBuffer)
  385. {
  386. if (_ecParseError == ecNoError)
  387. *pszRawText = szRawTextStart;
  388. else
  389. FreePv(szRawTextStart);
  390. }
  391. return cch;
  392. }
  393. /*
  394. * CRTFRead::StrAlloc(ppsz, sz)
  395. *
  396. * @mfunc
  397. * Set up a pointer to a newly allocated space to hold a string
  398. *
  399. * @rdesc
  400. * EC The error code
  401. */
  402. EC CRTFRead::StrAlloc(
  403. TCHAR ** ppsz, //@parm Ptr to ptr to string that needs allocation
  404. BYTE * sz) //@parm String to be copied into allocated space
  405. {
  406. TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::StrAlloc");
  407. int Length = strlen((CHAR *)sz)+1 ;
  408. *ppsz = (TCHAR *) PvAlloc((Length + 1)*sizeof(TCHAR), GMEM_ZEROINIT);
  409. if (!*ppsz)
  410. {
  411. _ped->GetCallMgr()->SetOutOfMemory();
  412. _ecParseError = ecNoMemory;
  413. goto Quit;
  414. }
  415. MultiByteToWideChar(CP_ACP,0,(char *)sz,-1,*ppsz,Length) ;
  416. Quit:
  417. return _ecParseError;
  418. }
  419. /*
  420. * CRTFRead::FreeRtfObject()
  421. *
  422. * @mfunc
  423. * Cleans up memory used by prtfobject
  424. */
  425. void CRTFRead::FreeRtfObject()
  426. {
  427. TRACEBEGIN(TRCSUBSYSRTFR, TRCSCOPEINTERN, "CRTFRead::FreeRtfObject");
  428. if (_prtfObject)
  429. {
  430. FreePv(_prtfObject->szClass);
  431. FreePv(_prtfObject->szName);
  432. FreePv(_prtfObject);
  433. _prtfObject = NULL;
  434. }
  435. }
  436. /*
  437. * CRTFRead::ObjectReadSiteFlags(preobj)
  438. *
  439. * @mfunc
  440. * Read dwFlags and dwUser bytes from a container specific stream
  441. *
  442. * @rdesc
  443. * BOOL TRUE if successfully read the bytes
  444. */
  445. BOOL CRTFRead::ObjectReadSiteFlags(
  446. REOBJECT * preobj) //@parm REOBJ from where to copy flags. This preobj is
  447. // then later put out in a site
  448. {
  449. return (::ObjectReadSiteFlags(preobj) == NOERROR);
  450. }
  451. /*
  452. * CRTFRead::ObjectReadFromStream()
  453. *
  454. * @mfunc
  455. * Reads an OLE object from the RTF output stream.
  456. *
  457. * @rdesc
  458. * BOOL TRUE on success, FALSE on failure.
  459. */
  460. BOOL CRTFRead::ObjectReadFromEditStream()
  461. {
  462. WCHAR ch = WCH_EMBEDDING;
  463. BOOL fRet = FALSE;
  464. HRESULT hr;
  465. CObjectMgr * pObjectMgr = _ped->GetObjectMgr();
  466. LPOLECACHE polecache = NULL;
  467. LPRICHEDITOLECALLBACK precall=NULL;
  468. LPENUMSTATDATA penumstatdata = NULL;
  469. REOBJECT reobj = { 0 };
  470. STATDATA statdata;
  471. if(!pObjectMgr)
  472. goto Cleanup;
  473. precall = pObjectMgr->GetRECallback();
  474. // If no IRichEditOleCallback exists, then fail
  475. if (!precall)
  476. goto Cleanup;
  477. // AssertSz(_prtfObject->szClass,"ObFReadFromEditstream: reading unknown class");
  478. if (_prtfObject->szClass)
  479. CLSIDFromProgID(_prtfObject->szClass, &reobj.clsid);
  480. // Get storage for the object from the application
  481. if (precall->GetNewStorage(&reobj.pstg))
  482. goto Cleanup;
  483. hr = OleConvertOLESTREAMToIStorage((LPOLESTREAM) &RTFReadOLEStream, reobj.pstg, NULL);
  484. if (FAILED(hr))
  485. goto Cleanup;
  486. // Create another object site for the new object
  487. _ped->GetClientSite(&reobj.polesite) ;
  488. if (!reobj.polesite ||
  489. OleLoad(reobj.pstg, IID_IOleObject, reobj.polesite,
  490. (LPVOID *) &reobj.poleobj))
  491. {
  492. goto Cleanup;
  493. }
  494. CLSID clsid;
  495. // Get the actual clsid from the object
  496. if (reobj.poleobj->GetUserClassID(&clsid) == NOERROR)
  497. reobj.clsid = clsid;
  498. reobj.cbStruct = sizeof(REOBJECT);
  499. reobj.cp = _prg->GetCp();
  500. reobj.sizel.cx = HimetricFromTwips(_prtfObject->xExt)
  501. * _prtfObject->xScale / 100;
  502. reobj.sizel.cy = HimetricFromTwips(_prtfObject->yExt)
  503. * _prtfObject->yScale / 100;
  504. // Read any container flags which may have been previously saved
  505. if (!ObjectReadSiteFlags(&reobj))
  506. reobj.dwFlags = REO_RESIZABLE; // If no flags, make best guess
  507. reobj.dvaspect = DVASPECT_CONTENT; // OLE 1 forces DVASPECT_CONTENT
  508. // Ask the cache if it knows what to display
  509. if (!reobj.poleobj->QueryInterface(IID_IOleCache, (void**)&polecache) &&
  510. !polecache->EnumCache(&penumstatdata))
  511. {
  512. // Go look for the best cached presentation CF_METAFILEPICT
  513. while (penumstatdata->Next(1, &statdata, NULL) == S_OK)
  514. {
  515. if (statdata.formatetc.cfFormat == CF_METAFILEPICT)
  516. {
  517. LPDATAOBJECT pdataobj = NULL;
  518. STGMEDIUM med;
  519. BOOL fUpdate;
  520. ZeroMemory(&med, sizeof(STGMEDIUM));
  521. if (!polecache->QueryInterface(IID_IDataObject, (void**)&pdataobj) &&
  522. !pdataobj->GetData(&statdata.formatetc, &med))
  523. {
  524. HANDLE hGlobal = med.hGlobal;
  525. if( FIsIconMetafilePict(hGlobal) )
  526. {
  527. OleStdSwitchDisplayAspect(reobj.poleobj, &reobj.dvaspect,
  528. DVASPECT_ICON, med.hGlobal, TRUE, FALSE, NULL, &fUpdate);
  529. }
  530. }
  531. ReleaseStgMedium(&med);
  532. if (pdataobj)
  533. pdataobj->Release();
  534. break;
  535. }
  536. }
  537. polecache->Release();
  538. penumstatdata->Release();
  539. }
  540. // EVIL HACK ALERT. This code is borrowed from RichEdit1.0; Word generates
  541. // bogus objects, so we need to compensate.
  542. if( reobj.dvaspect == DVASPECT_CONTENT )
  543. {
  544. IStream *pstm = NULL;
  545. BYTE bT;
  546. BOOL fUpdate;
  547. if (!reobj.pstg->OpenStream(OLESTR("\3ObjInfo"), 0, STGM_READ |
  548. STGM_SHARE_EXCLUSIVE, 0, &pstm) &&
  549. !pstm->Read(&bT, sizeof(BYTE), NULL) &&
  550. (bT & 0x40))
  551. {
  552. _fNeedIcon = TRUE;
  553. _fNeedPres = TRUE;
  554. _pobj = (COleObject *)reobj.polesite;
  555. OleStdSwitchDisplayAspect(reobj.poleobj, &reobj.dvaspect, DVASPECT_ICON,
  556. NULL, TRUE, FALSE, NULL, &fUpdate);
  557. }
  558. if( pstm )
  559. pstm->Release();
  560. }
  561. // Since we are loading an object, it shouldn't be blank
  562. reobj.dwFlags &= ~REO_BLANK;
  563. _prg->Set_iCF(-1);
  564. _prg->ReplaceRange(1, &ch, NULL, SELRR_IGNORE);
  565. hr = pObjectMgr->InsertObject(reobj.cp, &reobj, NULL);
  566. if(hr)
  567. goto Cleanup;
  568. // EVIL HACK ALERT!! Word doesn't give us objects with presenation
  569. // caches; as a result, we can't draw them! In order to get around this,
  570. // we check to see if there is a presentation cache (via the same way
  571. // RE1.0 did) using a GetExtent call. If that fails, we'll just use
  572. // the presentation stored in the RTF.
  573. //
  574. // COMPATIBILITY ISSUE: RE1.0, instead of using the presenation stored
  575. // in RTF, would instead call IOleObject::Update. There are two _big_
  576. // drawbacks to this approach: 1. it's incredibly expensive (potentially,
  577. // MANY SECONDS per object), and 2. it doesn't work if the object server
  578. // is not installed on the machine.
  579. SIZE sizeltemp;
  580. if( reobj.poleobj->GetExtent(reobj.dvaspect, &sizeltemp) != NOERROR )
  581. {
  582. _fNeedPres = TRUE;
  583. _pobj = (COleObject *)reobj.polesite;
  584. }
  585. fRet = TRUE;
  586. Cleanup:
  587. if (reobj.pstg) reobj.pstg->Release();
  588. if (reobj.polesite) reobj.polesite->Release();
  589. if (reobj.poleobj) reobj.poleobj->Release();
  590. return fRet;
  591. }
  592. /*
  593. * ObHBuildMetafilePict(prtfobject, hBits)
  594. *
  595. * @func
  596. * Build a METAFILEPICT from RTFOBJECT and the raw data.
  597. *
  598. * @rdesc
  599. * HGLOBAL Handle to a METAFILEPICT
  600. */
  601. HGLOBAL ObHBuildMetafilePict(
  602. RTFOBJECT * prtfobject, //@parm Details we picked up from RTF
  603. HGLOBAL hBits) //@parm Handle to the raw data
  604. {
  605. #ifndef NOMETAFILES
  606. ULONG cbBits;
  607. HGLOBAL hmfp = NULL;
  608. LPBYTE pbBits;
  609. LPMETAFILEPICT pmfp = NULL;
  610. SCODE sc = E_OUTOFMEMORY;
  611. // Allocate the METAFILEPICT structure
  612. hmfp = GlobalAlloc(GHND, sizeof(METAFILEPICT));
  613. if (!hmfp)
  614. goto Cleanup;
  615. // Lock it down
  616. pmfp = (LPMETAFILEPICT) GlobalLock(hmfp);
  617. if (!pmfp)
  618. goto Cleanup;
  619. // Put in the header information
  620. pmfp->mm = prtfobject->sPictureType;
  621. pmfp->xExt = prtfobject->xExt;
  622. pmfp->yExt = prtfobject->yExt;
  623. // Set the metafile bits
  624. pbBits = (LPBYTE) GlobalLock(hBits);
  625. cbBits = GlobalSize(hBits);
  626. pmfp->hMF = SetMetaFileBitsEx(cbBits, pbBits);
  627. // We can throw away the data now since we don't need it anymore
  628. GlobalUnlock(hBits);
  629. GlobalFree(hBits);
  630. if (!pmfp->hMF)
  631. goto Cleanup;
  632. GlobalUnlock(hmfp);
  633. sc = S_OK;
  634. Cleanup:
  635. if (sc && hmfp)
  636. {
  637. if (pmfp)
  638. {
  639. if (pmfp->hMF)
  640. ::DeleteMetaFile(pmfp->hMF);
  641. GlobalUnlock(hmfp);
  642. }
  643. GlobalFree(hmfp);
  644. hmfp = NULL;
  645. }
  646. TRACEERRSZSC("ObHBuildMetafilePict", sc);
  647. return hmfp;
  648. #else
  649. return NULL;
  650. #endif
  651. }
  652. /*
  653. * ObHBuildBitmap(prtfobject, hBits)
  654. *
  655. * @func
  656. * Build a BITMAP from RTFOBJECT and the raw data
  657. *
  658. * @rdesc
  659. * HGLOBAL Handle to a BITMAP
  660. */
  661. HGLOBAL ObHBuildBitmap(
  662. RTFOBJECT * prtfobject, //@parm Details we picked up from RTF
  663. HGLOBAL hBits) //@parm Handle to the raw data
  664. {
  665. HBITMAP hbm = NULL;
  666. LPVOID pvBits = GlobalLock(hBits);
  667. if(pvBits)
  668. {
  669. hbm = CreateBitmap(prtfobject->xExt, prtfobject->yExt,
  670. prtfobject->cColorPlanes, prtfobject->cBitsPerPixel,
  671. pvBits);
  672. }
  673. GlobalUnlock(hBits);
  674. GlobalFree(hBits);
  675. return hbm;
  676. }
  677. /*
  678. * ObHBuildDib(prtfobject, hBits)
  679. *
  680. * @func
  681. * Build a DIB from RTFOBJECT and the raw data
  682. *
  683. * @rdesc
  684. * HGLOBAL Handle to a DIB
  685. */
  686. HGLOBAL ObHBuildDib(
  687. RTFOBJECT * prtfobject, //@parm Details we picked up from RTF
  688. HGLOBAL hBits) //@parm Handle to the raw data
  689. {
  690. // Apparently DIB's are just a binary dump
  691. return hBits;
  692. }
  693. /*
  694. * CRTFRead::StaticObjectReadFromEditstream(cb)
  695. *
  696. * @mfunc
  697. * Reads a picture from the RTF output stream.
  698. *
  699. * @rdesc
  700. * BOOL TRUE on success, FALSE on failure.
  701. */
  702. #define cbBufferMax 16384
  703. #define cbBufferStep 1024
  704. #define cbBufferMin 1024
  705. BOOL CRTFRead::StaticObjectReadFromEditStream(
  706. int cb) //@parm Count of bytes to read
  707. {
  708. LONG cbBuffer;
  709. LONG cbRead;
  710. WCHAR ch = WCH_EMBEDDING;
  711. DWORD dwAdvf;
  712. DWORD dwConn;
  713. FORMATETC formatetc;
  714. BOOL fRet = FALSE;
  715. HGLOBAL hBits = NULL;
  716. HRESULT hr;
  717. CObjectMgr *pObjectMgr = _ped->GetObjectMgr();
  718. LPPERSISTSTORAGE pperstg = NULL;
  719. LPOLECACHE polecache = NULL;
  720. REOBJECT reobj = { 0 };
  721. LPBYTE pbBuffer = NULL;
  722. LPSTREAM pstm = NULL;
  723. STGMEDIUM stgmedium;
  724. HGLOBAL (*pfnBuildPict)(RTFOBJECT *, HGLOBAL) = NULL;
  725. LPRICHEDITOLECALLBACK precall ;
  726. if(!pObjectMgr)
  727. goto Cleanup;
  728. // precall may end up being null (e.g. Windows CE).
  729. precall = pObjectMgr->GetRECallback();
  730. // Initialize various data structures
  731. formatetc.ptd = NULL;
  732. formatetc.dwAspect = DVASPECT_CONTENT;
  733. formatetc.lindex = -1;
  734. formatetc.tymed = TYMED_NULL;
  735. switch (_prtfObject->sType)
  736. {
  737. case ROT_Metafile:
  738. reobj.clsid = CLSID_StaticMetafile;
  739. formatetc.cfFormat = CF_METAFILEPICT;
  740. formatetc.tymed = TYMED_MFPICT;
  741. pfnBuildPict = ObHBuildMetafilePict;
  742. break;
  743. case ROT_Bitmap:
  744. reobj.clsid = CLSID_StaticDib;
  745. formatetc.cfFormat = CF_BITMAP;
  746. formatetc.tymed = TYMED_GDI;
  747. pfnBuildPict = ObHBuildBitmap;
  748. break;
  749. case ROT_DIB:
  750. reobj.clsid = CLSID_StaticDib;
  751. formatetc.cfFormat = CF_DIB;
  752. formatetc.tymed = TYMED_HGLOBAL;
  753. pfnBuildPict = ObHBuildDib;
  754. break;
  755. }
  756. reobj.sizel.cx = (LONG) HimetricFromTwips(_prtfObject->xExtGoal)
  757. * _prtfObject->xScale / 100;
  758. reobj.sizel.cy = (LONG) HimetricFromTwips(_prtfObject->yExtGoal)
  759. * _prtfObject->yScale / 100;
  760. stgmedium.tymed = formatetc.tymed;
  761. stgmedium.pUnkForRelease = NULL;
  762. if (precall)
  763. {
  764. if( !_fNeedPres )
  765. {
  766. // Get storage for the object from the application
  767. if (precall->GetNewStorage(&reobj.pstg))
  768. goto Cleanup;
  769. }
  770. // Let's create a stream on HGLOBAL
  771. if (hr = CreateStreamOnHGlobal(NULL, FALSE, &pstm))
  772. goto Cleanup;
  773. // Allocate a buffer, preferably a big one
  774. for (cbBuffer = cbBufferMax;
  775. cbBuffer >= cbBufferMin;
  776. cbBuffer -= cbBufferStep)
  777. {
  778. pbBuffer = (unsigned char *)PvAlloc(cbBuffer, 0);
  779. if (pbBuffer)
  780. break;
  781. }
  782. }
  783. else
  784. {
  785. cbBuffer = cb;
  786. if (!cb)
  787. {
  788. // this means we didn't understand the picture type; so just
  789. // skip it without failing.
  790. fRet = TRUE;
  791. goto Cleanup;
  792. }
  793. hBits = GlobalAlloc(GMEM_FIXED, cb);
  794. pbBuffer = (BYTE *) GlobalLock(hBits);
  795. }
  796. if (!pbBuffer)
  797. goto Cleanup;
  798. // Copy the data from RTF into our HGLOBAL
  799. while ((cbRead = RTFReadOLEStream.lpstbl->Get(&RTFReadOLEStream,pbBuffer,cbBuffer)) > 0)
  800. {
  801. if (pstm && (hr = pstm->Write( pbBuffer, cbRead, NULL)))
  802. {
  803. TRACEERRSZSC("ObFReadStaticFromEditstream: Write", GetScode(hr));
  804. goto Cleanup;
  805. }
  806. }
  807. if (hBits)
  808. {
  809. Assert(!precall);
  810. GlobalUnlock(hBits);
  811. pbBuffer = NULL; // To avoid free below
  812. }
  813. if (pstm && (hr = GetHGlobalFromStream(pstm, &hBits)))
  814. {
  815. TRACEERRSZSC("ObFReadStaticFromEditstream: no hglobal from stm", GetScode(hr));
  816. goto Cleanup;
  817. }
  818. // Build the picture
  819. if( pfnBuildPict )
  820. {
  821. stgmedium.hGlobal = pfnBuildPict(_prtfObject, hBits);
  822. }
  823. else
  824. {
  825. // this means we didn't understand the picture type; so just
  826. // skip it without failing.
  827. fRet = TRUE;
  828. goto Cleanup;
  829. }
  830. if( precall && !stgmedium.hGlobal )
  831. goto Cleanup;
  832. if( precall )
  833. {
  834. if( !_fNeedPres )
  835. {
  836. // Create the default handler
  837. hr = OleCreateDefaultHandler(reobj.clsid, NULL, IID_IOleObject,(void **) &reobj.poleobj);
  838. if (hr)
  839. {
  840. TRACEERRSZSC("ObFReadStaticFromEditstream: no def handler", GetScode(hr));
  841. goto Cleanup;
  842. }
  843. // Get the IPersistStorage and initialize it
  844. if ((hr = reobj.poleobj->QueryInterface(IID_IPersistStorage,(void **)&pperstg)) ||
  845. (hr = pperstg->InitNew(reobj.pstg)))
  846. {
  847. TRACEERRSZSC("ObFReadStaticFromEditstream: InitNew", GetScode(hr));
  848. goto Cleanup;
  849. }
  850. dwAdvf = ADVF_PRIMEFIRST;
  851. }
  852. else
  853. {
  854. Assert(_pobj);
  855. _pobj->GetIUnknown()->QueryInterface(IID_IOleObject, (void **)&(reobj.poleobj));
  856. dwAdvf = ADVF_NODATA;
  857. formatetc.dwAspect = _fNeedIcon ? DVASPECT_ICON : DVASPECT_CONTENT;
  858. }
  859. // Get the IOleCache and put the picture data there
  860. if (hr = reobj.poleobj->QueryInterface(IID_IOleCache,(void **)&polecache))
  861. {
  862. TRACEERRSZSC("ObFReadStaticFromEditstream: QI: IOleCache", GetScode(hr));
  863. goto Cleanup;
  864. }
  865. if (FAILED(hr = polecache->Cache(&formatetc, dwAdvf,
  866. &dwConn)))
  867. {
  868. TRACEERRSZSC("ObFReadStaticFromEditstream: Cache", GetScode(hr));
  869. goto Cleanup;
  870. }
  871. if (hr = polecache->SetData(&formatetc, &stgmedium,
  872. TRUE))
  873. {
  874. TRACEERRSZSC("ObFReadStaticFromEditstream: SetData", GetScode(hr));
  875. goto Cleanup;
  876. }
  877. }
  878. if( !_fNeedPres )
  879. {
  880. // Create another object site for the new object
  881. _ped->GetClientSite(&reobj.polesite) ;
  882. if (!reobj.polesite )
  883. goto Cleanup;
  884. // Set the client site
  885. if (reobj.poleobj && (hr = reobj.poleobj->SetClientSite(reobj.polesite)))
  886. {
  887. TRACEERRSZSC("ObFReadStaticFromEditstream: SetClientSite", GetScode(hr));
  888. goto Cleanup;
  889. }
  890. else if (!reobj.poleobj)
  891. {
  892. if(_prtfObject->sType == ROT_DIB)
  893. {
  894. // Windows CE static object Save the data and mark it.
  895. COleObject *pobj = (COleObject *)reobj.polesite;
  896. COleObject::ImageInfo *pimageinfo = new COleObject::ImageInfo;
  897. pobj->SetHdata(hBits);
  898. pimageinfo->xScale = _prtfObject->xScale;
  899. pimageinfo->yScale = _prtfObject->yScale;
  900. pimageinfo->xExtGoal = _prtfObject->xExtGoal;
  901. pimageinfo->yExtGoal = _prtfObject->yExtGoal;
  902. pimageinfo->cBytesPerLine = _prtfObject->cBytesPerLine;
  903. pobj->SetImageInfo(pimageinfo);
  904. }
  905. else
  906. goto Cleanup; // There has been a mistake
  907. }
  908. // Put object into the edit control
  909. reobj.cbStruct = sizeof(REOBJECT);
  910. reobj.cp = _prg->GetCp();
  911. reobj.dvaspect = DVASPECT_CONTENT;
  912. reobj.dwFlags = REO_RESIZABLE;
  913. // Since we are loading an object, it shouldn't be blank
  914. reobj.dwFlags &= ~REO_BLANK;
  915. _prg->Set_iCF(-1);
  916. _prg->ReplaceRange(1, &ch, NULL, SELRR_IGNORE);
  917. hr = pObjectMgr->InsertObject(reobj.cp, &reobj, NULL);
  918. if (hr)
  919. goto Cleanup;
  920. }
  921. else
  922. {
  923. // the new presentation may have a different idea about how big the
  924. // object is supposed to be. Make sure the object stays the correct
  925. // size.
  926. _pobj->ResetSizel(reobj.sizel);
  927. }
  928. fRet = TRUE;
  929. Cleanup:
  930. if (polecache) polecache->Release() ;
  931. if (reobj.pstg) reobj.pstg->Release();
  932. if (reobj.polesite) reobj.polesite->Release();
  933. if (reobj.poleobj) reobj.poleobj->Release();
  934. if (pperstg) pperstg->Release();
  935. if (pstm) pstm->Release();
  936. FreePv(pbBuffer);
  937. _fNeedIcon = FALSE;
  938. _fNeedPres = FALSE;
  939. _pobj = NULL;
  940. return fRet;
  941. }