diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c index 2337107172b..3f0604eb7e7 100644 --- a/dlls/riched20/caret.c +++ b/dlls/riched20/caret.c @@ -393,18 +393,20 @@ ME_InternalInsertTextFromCursor(ME_TextEditor *editor, int nCursor, } -/* FIXME this is temporary, just to have something to test how bad graphics handler is */ -void ME_InsertGraphicsFromCursor(ME_TextEditor *editor, int nCursor) +void ME_InsertOLEFromCursor(ME_TextEditor *editor, const REOBJECT* reo, int nCursor) { - ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor); - WCHAR space = ' '; + ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor); + ME_DisplayItem *di; + WCHAR space = ' '; /* FIXME no no no */ if (ME_IsSelection(editor)) ME_DeleteSelection(editor); - ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, pStyle, - MERF_GRAPHICS); + di = ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, pStyle, + MERF_GRAPHICS); + di->member.run.ole_obj = ALLOC_OBJ(*reo); + ME_CopyReObject(di->member.run.ole_obj, reo); ME_SendSelChange(editor); } diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index 145dc912d3e..dde2efc9d73 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -149,7 +149,6 @@ ME_DisplayItem *ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style, const WCHAR *str, int len, int flags); void ME_CheckCharOffsets(ME_TextEditor *editor); void ME_PropagateCharOffset(ME_DisplayItem *p, int shift); -void ME_GetGraphicsSize(ME_TextEditor *editor, ME_Run *run, SIZE *pSize); int ME_CharFromPoint(ME_Context *c, int cx, ME_Run *run); /* this one accounts for 1/2 char tolerance */ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run); @@ -201,7 +200,7 @@ int ME_CountParagraphsBetween(ME_TextEditor *editor, int from, int to); BOOL ME_IsSelection(ME_TextEditor *editor); void ME_DeleteSelection(ME_TextEditor *editor); void ME_SendSelChange(ME_TextEditor *editor); -void ME_InsertGraphicsFromCursor(ME_TextEditor *editor, int nCursor); +void ME_InsertOLEFromCursor(ME_TextEditor *editor, const REOBJECT* reo, int nCursor); void ME_InsertTableCellFromCursor(ME_TextEditor *editor, int nCursor); void ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars); int ME_GetTextLength(ME_TextEditor *editor); @@ -259,7 +258,11 @@ int ME_GetParaBorderWidth(ME_TextEditor *editor, int); int ME_GetParaLineSpace(ME_Context *c, ME_Paragraph*); /* richole.c */ -extern LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *); +LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *); +void ME_DrawOLE(ME_Context *c, int x, int y, ME_Run* run, ME_Paragraph *para, BOOL selected); +void ME_GetOLEObjectSize(ME_TextEditor *editor, ME_Run *run, SIZE *pSize); +void ME_CopyReObject(REOBJECT* dst, const REOBJECT* src); +void ME_DeleteReObject(REOBJECT* reo); /* wintest.c */ diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h index aa7fd6b2ba0..92dbab4742b 100644 --- a/dlls/riched20/editstr.h +++ b/dlls/riched20/editstr.h @@ -145,6 +145,7 @@ typedef struct tagME_Run int nAscent, nDescent; /* pixels above/below baseline */ POINT pt; /* relative to para's position */ struct tagME_TableCell *pCell; /* for MERF_CELL: points to respective cell in ME_Paragraph */ + REOBJECT *ole_obj; /* FIXME: should be a union with strText (at least) */ } ME_Run; typedef struct tagME_Document { diff --git a/dlls/riched20/list.c b/dlls/riched20/list.c index ad7b4b659e4..14f9b178a40 100644 --- a/dlls/riched20/list.c +++ b/dlls/riched20/list.c @@ -115,6 +115,7 @@ void ME_DestroyDisplayItem(ME_DisplayItem *item) { ME_DestroyTableCellList(item); } if (item->type==diRun || item->type == diUndoInsertRun) { + if (item->member.run.ole_obj) ME_DeleteReObject(item->member.run.ole_obj); ME_ReleaseStyle(item->member.run.style); ME_DestroyString(item->member.run.strText); } diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c index 03a588c2aae..86876444669 100644 --- a/dlls/riched20/paint.c +++ b/dlls/riched20/paint.c @@ -246,34 +246,6 @@ static void ME_DebugWrite(HDC hDC, const POINT *pt, LPCWSTR szText) { SetTextColor(hDC, color); } -static void ME_DrawGraphics(ME_Context *c, int x, int y, ME_Run *run, - ME_Paragraph *para, BOOL selected) { - SIZE sz; - int xs, ys, xe, ye, h, ym, width, eyes; - ME_GetGraphicsSize(c->editor, run, &sz); - xs = run->pt.x; - ys = y-sz.cy; - xe = xs+sz.cx; - ye = y; - h = ye-ys; - ym = ys+h/4; - width = sz.cx; - eyes = width/8; - /* draw a smiling face :) */ - Ellipse(c->hDC, xs, ys, xe, ye); - Ellipse(c->hDC, xs+width/8, ym, x+width/8+eyes, ym+eyes); - Ellipse(c->hDC, xs+7*width/8-eyes, ym, xs+7*width/8, ym+eyes); - MoveToEx(c->hDC, xs+width/8, ys+3*h/4-eyes, NULL); - LineTo(c->hDC, xs+width/8, ys+3*h/4); - LineTo(c->hDC, xs+7*width/8, ys+3*h/4); - LineTo(c->hDC, xs+7*width/8, ys+3*h/4-eyes); - if (selected) - { - /* descent is usually (always?) 0 for graphics */ - PatBlt(c->hDC, x, y-run->nAscent, sz.cx, run->nAscent+run->nDescent, DSTINVERT); - } -} - static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Paragraph *para) { ME_Run *run = &rundi->member.run; @@ -299,7 +271,7 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa return; if (run->nFlags & MERF_GRAPHICS) - ME_DrawGraphics(c, x, y, run, para, (runofs >= nSelFrom) && (runofs < nSelTo)); + ME_DrawOLE(c, x, y, run, para, (runofs >= nSelFrom) && (runofs < nSelTo)); else { if (c->editor->cPasswordMask) diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c index 742323e0224..3bc9b8d4b15 100644 --- a/dlls/riched20/richole.c +++ b/dlls/riched20/richole.c @@ -218,11 +218,18 @@ IRichEditOle_fnInPlaceDeactivate(IRichEditOle *me) } static HRESULT WINAPI -IRichEditOle_fnInsertObject(IRichEditOle *me, REOBJECT *lpreobject) +IRichEditOle_fnInsertObject(IRichEditOle *me, REOBJECT *reo) { IRichEditOleImpl *This = impl_from_IRichEditOle(me); - FIXME("stub %p\n",This); - return E_NOTIMPL; + TRACE("(%p,%p)\n", This, reo); + + if (reo->cbStruct < sizeof(*reo)) return STG_E_INVALIDPARAMETER; + if (reo->poleobj) IOleObject_AddRef(reo->poleobj); + if (reo->pstg) IStorage_AddRef(reo->pstg); + if (reo->polesite) IOleClientSite_AddRef(reo->polesite); + + ME_InsertOLEFromCursor(This->editor, reo, 0); + return S_OK; } static HRESULT WINAPI IRichEditOle_fnSaveCompleted(IRichEditOle *me, LONG iob, @@ -542,3 +549,135 @@ LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj) return 1; } + +/****************************************************************************** + * ME_GetOLEObjectSize + * + * Sets run extent for OLE objects. + */ +void ME_GetOLEObjectSize(ME_TextEditor *editor, ME_Run *run, SIZE *pSize) +{ + IDataObject* ido; + FORMATETC fmt; + STGMEDIUM stgm; + DIBSECTION dibsect; + ENHMETAHEADER emh; + + assert(run->nFlags & MERF_GRAPHICS); + assert(run->ole_obj); + IOleObject_QueryInterface(run->ole_obj->poleobj, &IID_IDataObject, (void**)&ido); + fmt.cfFormat = CF_BITMAP; + fmt.ptd = NULL; + fmt.dwAspect = DVASPECT_CONTENT; + fmt.lindex = -1; + fmt.tymed = TYMED_GDI; + if (IDataObject_GetData(ido, &fmt, &stgm) != S_OK) + { + fmt.cfFormat = CF_ENHMETAFILE; + fmt.tymed = TYMED_ENHMF; + if (IDataObject_GetData(ido, &fmt, &stgm) != S_OK) + { + FIXME("unsupported format\n"); + pSize->cx = pSize->cy = 0; + IDataObject_Release(ido); + return; + } + } + + switch (stgm.tymed) + { + case TYMED_GDI: + GetObjectW(stgm.u.hBitmap, sizeof(dibsect), &dibsect); + pSize->cx = dibsect.dsBm.bmWidth; + pSize->cy = dibsect.dsBm.bmHeight; + if (!stgm.pUnkForRelease) DeleteObject(stgm.u.hBitmap); + break; + case TYMED_ENHMF: + GetEnhMetaFileHeader(stgm.u.hEnhMetaFile, sizeof(emh), &emh); + pSize->cx = emh.rclBounds.right - emh.rclBounds.left; + pSize->cy = emh.rclBounds.bottom - emh.rclBounds.top; + if (!stgm.pUnkForRelease) DeleteEnhMetaFile(stgm.u.hEnhMetaFile); + break; + default: + FIXME("Unsupported tymed %d\n", stgm.tymed); + break; + } + IDataObject_Release(ido); +} + +void ME_DrawOLE(ME_Context *c, int x, int y, ME_Run *run, + ME_Paragraph *para, BOOL selected) +{ + IDataObject* ido; + FORMATETC fmt; + STGMEDIUM stgm; + DIBSECTION dibsect; + ENHMETAHEADER emh; + HDC hMemDC; + RECT rc; + + assert(run->nFlags & MERF_GRAPHICS); + assert(run->ole_obj); + if (IOleObject_QueryInterface(run->ole_obj->poleobj, &IID_IDataObject, (void**)&ido) != S_OK) + { + FIXME("Couldn't get interface\n"); + return; + } + fmt.cfFormat = CF_BITMAP; + fmt.ptd = NULL; + fmt.dwAspect = DVASPECT_CONTENT; + fmt.lindex = -1; + fmt.tymed = TYMED_GDI; + if (IDataObject_GetData(ido, &fmt, &stgm) != S_OK) + { + fmt.cfFormat = CF_ENHMETAFILE; + fmt.tymed = TYMED_ENHMF; + if (IDataObject_GetData(ido, &fmt, &stgm) != S_OK) + { + FIXME("Couldn't get storage medium\n"); + IDataObject_Release(ido); + return; + } + } + switch (stgm.tymed) + { + case TYMED_GDI: + GetObjectW(stgm.u.hBitmap, sizeof(dibsect), &dibsect); + hMemDC = CreateCompatibleDC(c->hDC); + SelectObject(hMemDC, stgm.u.hBitmap); + BitBlt(c->hDC, x, y - dibsect.dsBm.bmHeight, dibsect.dsBm.bmWidth, dibsect.dsBm.bmHeight, hMemDC, 0, 0, SRCCOPY); + DeleteDC(hMemDC); + if (!stgm.pUnkForRelease) DeleteObject(stgm.u.hBitmap); + break; + case TYMED_ENHMF: + GetEnhMetaFileHeader(stgm.u.hEnhMetaFile, sizeof(emh), &emh); + rc.left = x; + rc.top = y - (emh.rclBounds.bottom - emh.rclBounds.top); + rc.right = x + emh.rclBounds.right - emh.rclBounds.left; + rc.bottom = y; + PlayEnhMetaFile(c->hDC, stgm.u.hEnhMetaFile, &rc); + if (!stgm.pUnkForRelease) DeleteEnhMetaFile(stgm.u.hEnhMetaFile); + break; + default: + FIXME("Unsupported tymed %d\n", stgm.tymed); + break; + } + IDataObject_Release(ido); +} + +void ME_DeleteReObject(REOBJECT* reo) +{ + if (reo->poleobj) IOleObject_Release(reo->poleobj); + if (reo->pstg) IStorage_Release(reo->pstg); + if (reo->polesite) IOleClientSite_Release(reo->polesite); + FREE_OBJ(reo); +} + +void ME_CopyReObject(REOBJECT* dst, const REOBJECT* src) +{ + *dst = *src; + + if (dst->poleobj) IOleObject_AddRef(dst->poleobj); + if (dst->pstg) IStorage_AddRef(dst->pstg); + if (dst->polesite) IOleClientSite_AddRef(dst->polesite); +} diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c index 2da891e7851..99286404408 100644 --- a/dlls/riched20/run.c +++ b/dlls/riched20/run.c @@ -359,6 +359,7 @@ ME_DisplayItem *ME_MakeRun(ME_Style *s, ME_String *strData, int nFlags) { ME_DisplayItem *item = ME_MakeDI(diRun); item->member.run.style = s; + item->member.run.ole_obj = NULL; item->member.run.strText = strData; item->member.run.nFlags = nFlags; item->member.run.nCharOfs = -1; @@ -467,19 +468,6 @@ void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run) run->nFlags &= ~(MERF_WHITESPACE | MERF_STARTWHITE | MERF_ENDWHITE); } -/****************************************************************************** - * ME_GetGraphicsSize - * - * Sets run extent for graphics runs. This functionality is just a placeholder - * for future OLE object support, and will be removed. - */ -void ME_GetGraphicsSize(ME_TextEditor *editor, ME_Run *run, SIZE *pSize) -{ - assert(run->nFlags & MERF_GRAPHICS); - pSize->cx = 64; - pSize->cy = 64; -} - /****************************************************************************** * ME_CharFromPoint * @@ -504,7 +492,7 @@ int ME_CharFromPoint(ME_Context *c, int cx, ME_Run *run) if (run->nFlags & MERF_GRAPHICS) { SIZE sz; - ME_GetGraphicsSize(c->editor, run, &sz); + ME_GetOLEObjectSize(c->editor, run, &sz); if (cx < sz.cx) return 0; return 1; @@ -561,7 +549,7 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run) if (run->nFlags & MERF_GRAPHICS) { SIZE sz; - ME_GetGraphicsSize(editor, run, &sz); + ME_GetOLEObjectSize(editor, run, &sz); if (cx < sz.cx/2) return 0; return 1; @@ -624,7 +612,7 @@ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset) if (pRun->nFlags & MERF_GRAPHICS) { if (!nOffset) return 0; - ME_GetGraphicsSize(editor, pRun, &size); + ME_GetOLEObjectSize(editor, pRun, &size); return 1; } @@ -701,7 +689,7 @@ static SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run } if (run->nFlags & MERF_GRAPHICS) { - ME_GetGraphicsSize(c->editor, run, &size); + ME_GetOLEObjectSize(c->editor, run, &size); if (size.cy > *pAscent) *pAscent = size.cy; /* descent is unchanged */ diff --git a/dlls/riched20/undo.c b/dlls/riched20/undo.c index d277e262192..12c8d30ba74 100644 --- a/dlls/riched20/undo.c +++ b/dlls/riched20/undo.c @@ -71,6 +71,12 @@ ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_Disp CopyMemory(&pItem->member.run, &pdi->member.run, sizeof(ME_Run)); pItem->member.run.strText = ME_StrDup(pItem->member.run.strText); ME_AddRefStyle(pItem->member.run.style); + if (pdi->member.run.ole_obj) + { + pItem->member.run.ole_obj = ALLOC_OBJ(*pItem->member.run.ole_obj); + ME_CopyReObject(pItem->member.run.ole_obj, pdi->member.run.ole_obj); + } + else pItem->member.run.ole_obj = NULL; break; case diUndoSetCharFormat: case diUndoSetDefaultCharFormat: