Source code of Windows XP (NT5)
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.

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