riched20: Added support for image reading from RTF stream.
This commit is contained in:
parent
1e62b0e3b0
commit
e5f91bab15
@ -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) {
|
static void ME_RTFReadHook(RTF_Info *info) {
|
||||||
switch(info->rtfClass)
|
switch(info->rtfClass)
|
||||||
{
|
{
|
||||||
@ -830,12 +987,15 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
|
|||||||
WriterInit(&parser);
|
WriterInit(&parser);
|
||||||
RTFInit(&parser);
|
RTFInit(&parser);
|
||||||
RTFSetReadHook(&parser, ME_RTFReadHook);
|
RTFSetReadHook(&parser, ME_RTFReadHook);
|
||||||
|
RTFSetDestinationCallback(&parser, rtfPict, ME_RTFReadPictGroup);
|
||||||
BeginFile(&parser);
|
BeginFile(&parser);
|
||||||
|
|
||||||
/* do the parsing */
|
/* do the parsing */
|
||||||
RTFRead(&parser);
|
RTFRead(&parser);
|
||||||
RTFFlushOutputBuffer(&parser);
|
RTFFlushOutputBuffer(&parser);
|
||||||
RTFDestroy(&parser);
|
RTFDestroy(&parser);
|
||||||
|
if (parser.lpRichEditOle)
|
||||||
|
IRichEditOle_Release(parser.lpRichEditOle);
|
||||||
|
|
||||||
style = parser.style;
|
style = parser.style;
|
||||||
}
|
}
|
||||||
|
@ -1103,6 +1103,7 @@ struct _RTF_Info {
|
|||||||
RTFState stack[maxStack];
|
RTFState stack[maxStack];
|
||||||
int stackTop;
|
int stackTop;
|
||||||
BOOL styleChanged;
|
BOOL styleChanged;
|
||||||
|
LPRICHEDITOLE lpRichEditOle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user