From e5f91bab15607a990f664a136f90a77b83a65aa6 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Sun, 27 Jan 2008 19:02:21 +0100 Subject: [PATCH] riched20: Added support for image reading from RTF stream. --- dlls/riched20/editor.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++- dlls/riched20/rtf.h | 1 + 2 files changed, 162 insertions(+), 1 deletion(-) diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index 2df5eb14246..02d5ca8bf0c 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 5a1251533a3..3a9c235cd47 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; }; -- 2.11.4.GIT