[PATCH 6/8] [RichEdit]: Added support for image reading from RTF stream

Eric Pouech eric.pouech at orange.fr
Sun Jan 27 12:02:21 CST 2008




A+
---

 dlls/riched20/editor.c |  162 ++++++++++++++++++++++++++++++++++++++++++++++++
 dlls/riched20/rtf.h    |    1 
 2 files changed, 162 insertions(+), 1 deletions(-)

diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index 2df5eb1..02d5ca8 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -692,6 +692,163 @@ static void ME_RTFTblAttrHook(RTF_Info *info)
   }
 }
 
+static BOOL ME_RTFInsertOleObject(RTF_Info *info, HENHMETAFILE h, const SIZEL* sz)
+{
+  LPOLEOBJECT         lpObject = NULL;
+  LPSTORAGE           lpStorage = NULL;
+  LPOLECLIENTSITE     lpClientSite = NULL;
+  LPDATAOBJECT        lpDataObject = NULL;
+  LPOLECACHE          lpOleCache = NULL;
+  STGMEDIUM           stgm;
+  FORMATETC           fm;
+  CLSID               clsid;
+  BOOL                ret = FALSE;
+  DWORD               conn;
+
+  stgm.tymed = TYMED_ENHMF;
+  stgm.u.hEnhMetaFile = h;
+  stgm.pUnkForRelease = NULL;
+
+  fm.cfFormat = CF_ENHMETAFILE;
+  fm.ptd = NULL;
+  fm.dwAspect = DVASPECT_CONTENT;
+  fm.lindex = -1;
+  fm.tymed = stgm.tymed;
+
+  if (!info->lpRichEditOle)
+  {
+    CreateIRichEditOle(info->editor, (VOID**)&info->lpRichEditOle);
+  }
+
+  if (OleCreateDefaultHandler(&CLSID_NULL, NULL, &IID_IOleObject, (void**)&lpObject) == S_OK &&
+#if 0
+      /* FIXME: enable it when rich-edit properly implements this method */
+      IRichEditOle_GetClientSite(info->lpRichEditOle, &lpClientSite) == S_OK &&
+      IOleObject_SetClientSite(lpObject, lpClientSite) == S_OK &&
+#endif
+      IOleObject_GetUserClassID(lpObject, &clsid) == S_OK &&
+      IOleObject_QueryInterface(lpObject, &IID_IOleCache, (void**)&lpOleCache) == S_OK &&
+      IOleCache_Cache(lpOleCache, &fm, 0, &conn) == S_OK &&
+      IOleObject_QueryInterface(lpObject, &IID_IDataObject, (void**)&lpDataObject) == S_OK &&
+      IDataObject_SetData(lpDataObject, &fm, &stgm, TRUE) == S_OK)
+  {
+    REOBJECT            reobject;
+
+    reobject.cbStruct = sizeof(reobject);
+    reobject.cp = REO_CP_SELECTION;
+    reobject.clsid = clsid;
+    reobject.poleobj = lpObject;
+    reobject.pstg = lpStorage;
+    reobject.polesite = lpClientSite;
+    /* convert from twips to .01 mm */
+    reobject.sizel.cx = MulDiv(sz->cx, 254, 144);
+    reobject.sizel.cy = MulDiv(sz->cy, 254, 144);
+    reobject.dvaspect = DVASPECT_CONTENT;
+    reobject.dwFlags = 0; /* FIXME */
+    reobject.dwUser = 0;
+
+    /* FIXME: could be simpler */
+    ret = IRichEditOle_InsertObject(info->lpRichEditOle, &reobject) == S_OK;
+  }
+
+  if (lpObject)       IOleObject_Release(lpObject);
+  if (lpClientSite)   IOleClientSite_Release(lpClientSite);
+  if (lpStorage)      IStorage_Release(lpStorage);
+  if (lpDataObject)   IDataObject_Release(lpDataObject);
+  if (lpOleCache)     IOleCache_Release(lpOleCache);
+
+  return ret;
+}
+
+static void ME_RTFReadPictGroup(RTF_Info *info)
+{
+  SIZEL         sz;
+  BYTE*         buffer = NULL;
+  unsigned      bufsz, bufidx;
+  BOOL          flip;
+  BYTE          val;
+  METAFILEPICT  mfp;
+  HENHMETAFILE  hemf;
+
+  RTFGetToken (info);
+  if (info->rtfClass == rtfEOF)
+    return;
+  mfp.mm = MM_TEXT;
+  /* fetch picture type */
+  if (RTFCheckMM (info, rtfPictAttr, rtfWinMetafile))
+  {
+    mfp.mm = info->rtfParam;
+  }
+  else
+  {
+    FIXME("%d %d\n", info->rtfMajor, info->rtfMinor);
+    goto skip_group;
+  }
+  sz.cx = sz.cy = 0;
+  /* fetch picture attributes */
+  for (;;)
+  {
+    RTFGetToken (info);
+    if (info->rtfClass == rtfEOF)
+      return;
+    if (info->rtfClass == rtfText)
+      break;
+    if (!RTFCheckCM (info, rtfControl, rtfPictAttr))
+    {
+      ERR("Expected picture attribute (%d %d)\n",
+        info->rtfClass, info->rtfMajor);
+      goto skip_group;
+    }
+    else if (RTFCheckMM (info, rtfPictAttr, rtfPicWid))
+      mfp.xExt = info->rtfParam;
+    else if (RTFCheckMM (info, rtfPictAttr, rtfPicHt))
+      mfp.yExt = info->rtfParam;
+    else if (RTFCheckMM (info, rtfPictAttr, rtfPicGoalWid))
+      sz.cx = info->rtfParam;
+    else if (RTFCheckMM (info, rtfPictAttr, rtfPicGoalHt))
+      sz.cy = info->rtfParam;
+    else
+      FIXME("Non supported attribute: %d %d %d\n", info->rtfClass, info->rtfMajor, info->rtfMinor);
+  }
+  /* fetch picture data */
+  bufsz = 1024;
+  bufidx = 0;
+  buffer = HeapAlloc(GetProcessHeap(), 0, bufsz);
+  val = info->rtfMajor;
+  for (flip = TRUE;; flip = !flip)
+  {
+    RTFGetToken (info);
+    if (info->rtfClass == rtfEOF)
+    {
+      HeapFree(GetProcessHeap(), 0, buffer);
+      return; /* Warn ?? */
+    }
+    if (RTFCheckCM(info, rtfGroup, rtfEndGroup))
+      break;
+    if (info->rtfClass != rtfText) goto skip_group;
+    if (flip)
+    {
+      if (bufidx >= bufsz &&
+          !(buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, bufsz += 1024)))
+        goto skip_group;
+      buffer[bufidx++] = RTFCharToHex(val) * 16 + RTFCharToHex(info->rtfMajor);
+    }
+    else
+      val = info->rtfMajor;
+  }
+  if (flip) FIXME("wrong hex string\n");
+
+  if ((hemf = SetWinMetaFileBits(bufidx, buffer, NULL, &mfp)))
+    ME_RTFInsertOleObject(info, hemf, &sz);
+  HeapFree(GetProcessHeap(), 0, buffer);
+  RTFRouteToken (info);	/* feed "}" back to router */
+  return;
+skip_group:
+  HeapFree(GetProcessHeap(), 0, buffer);
+  RTFSkipGroup(info);
+  RTFRouteToken(info);	/* feed "}" back to router */
+}
+
 static void ME_RTFReadHook(RTF_Info *info) {
   switch(info->rtfClass)
   {
@@ -830,12 +987,15 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
       WriterInit(&parser);
       RTFInit(&parser);
       RTFSetReadHook(&parser, ME_RTFReadHook);
+      RTFSetDestinationCallback(&parser, rtfPict, ME_RTFReadPictGroup);
       BeginFile(&parser);
-  
+
       /* do the parsing */
       RTFRead(&parser);
       RTFFlushOutputBuffer(&parser);
       RTFDestroy(&parser);
+      if (parser.lpRichEditOle)
+        IRichEditOle_Release(parser.lpRichEditOle);
 
       style = parser.style;
     }
diff --git a/dlls/riched20/rtf.h b/dlls/riched20/rtf.h
index 5a12515..3a9c235 100644
--- a/dlls/riched20/rtf.h
+++ b/dlls/riched20/rtf.h
@@ -1103,6 +1103,7 @@ struct _RTF_Info {
     RTFState         stack[maxStack];
     int              stackTop;
     BOOL             styleChanged;
+    LPRICHEDITOLE       lpRichEditOle;
 };
 
 





More information about the wine-patches mailing list