From bacd0179ec3336674b02c69b3d9134eccce1b6c6 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Thu, 18 Aug 2016 10:40:37 +0000 Subject: [PATCH] [RICHED20] Sync with Wine Staging 1.9.16. CORE-11866 svn path=/trunk/; revision=72305 --- reactos/dll/win32/riched20/caret.c | 4 +- reactos/dll/win32/riched20/clipboard.c | 11 +- reactos/dll/win32/riched20/editor.c | 193 ++++++++++++++----------- reactos/dll/win32/riched20/editor.h | 4 +- reactos/dll/win32/riched20/list.c | 16 +- reactos/dll/win32/riched20/paint.c | 6 +- reactos/dll/win32/riched20/para.c | 2 +- reactos/dll/win32/riched20/richole.c | 38 ++--- reactos/dll/win32/riched20/writer.c | 94 +++++++++++- reactos/media/doc/README.WINE | 2 +- 10 files changed, 244 insertions(+), 126 deletions(-) diff --git a/reactos/dll/win32/riched20/caret.c b/reactos/dll/win32/riched20/caret.c index 177f3039033..170363a48f1 100644 --- a/reactos/dll/win32/riched20/caret.c +++ b/reactos/dll/win32/riched20/caret.c @@ -331,7 +331,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, { /* We aren't deleting anything in this run, so we will go back to the * last run we are deleting text in. */ - ME_PrevRun(&c.pPara, &c.pRun); + ME_PrevRun(&c.pPara, &c.pRun, TRUE); c.nOffset = c.pRun->member.run.len; } run = &c.pRun->member.run; @@ -1245,7 +1245,7 @@ ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs) int x = ME_GetXForArrow(editor, pCursor); if (editor->bCaretAtEnd && !pCursor->nOffset) - if (!ME_PrevRun(&pOldPara, &pRun)) + if (!ME_PrevRun(&pOldPara, &pRun, TRUE)) return; if (nRelOfs == -1) diff --git a/reactos/dll/win32/riched20/clipboard.c b/reactos/dll/win32/riched20/clipboard.c index 250a233896a..c7d850a30b2 100644 --- a/reactos/dll/win32/riched20/clipboard.c +++ b/reactos/dll/win32/riched20/clipboard.c @@ -157,7 +157,8 @@ static const IEnumFORMATETCVtbl VT_EnumFormatImpl = { EnumFormatImpl_Clone }; -static HRESULT EnumFormatImpl_Create(const FORMATETC *fmtetc, UINT fmtetc_cnt, IEnumFORMATETC **lplpformatetc) +static HRESULT EnumFormatImpl_Create(const FORMATETC *fmtetc, UINT fmtetc_cnt, + IEnumFORMATETC **formatetc) { EnumFormatImpl *ret; TRACE("\n"); @@ -169,7 +170,7 @@ static HRESULT EnumFormatImpl_Create(const FORMATETC *fmtetc, UINT fmtetc_cnt, I ret->fmtetc_cnt = fmtetc_cnt; ret->fmtetc = GlobalAlloc(GMEM_ZEROINIT, fmtetc_cnt*sizeof(FORMATETC)); memcpy(ret->fmtetc, fmtetc, fmtetc_cnt*sizeof(FORMATETC)); - *lplpformatetc = (LPENUMFORMATETC)ret; + *formatetc = &ret->IEnumFORMATETC_iface; return S_OK; } @@ -399,8 +400,8 @@ static HGLOBAL get_rtf_text(ME_TextEditor *editor, const ME_Cursor *start, int n return gds.hData; } -HRESULT ME_GetDataObject(ME_TextEditor *editor, const ME_Cursor *start, - int nChars, LPDATAOBJECT *lplpdataobj) +HRESULT ME_GetDataObject(ME_TextEditor *editor, const ME_Cursor *start, int nChars, + IDataObject **dataobj) { DataObjectImpl *obj; TRACE("(%p,%d,%d)\n", editor, ME_GetCursorOfs(start), nChars); @@ -424,6 +425,6 @@ HRESULT ME_GetDataObject(ME_TextEditor *editor, const ME_Cursor *start, InitFormatEtc(obj->fmtetc[1], cfRTF, TYMED_HGLOBAL); } - *lplpdataobj = (LPDATAOBJECT)obj; + *dataobj = &obj->IDataObject_iface; return S_OK; } diff --git a/reactos/dll/win32/riched20/editor.c b/reactos/dll/win32/riched20/editor.c index 648c3ef435d..e90dcb8c018 100644 --- a/reactos/dll/win32/riched20/editor.c +++ b/reactos/dll/win32/riched20/editor.c @@ -1860,7 +1860,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH cursor.nOffset++; if (cursor.nOffset == cursor.pRun->member.run.len) { - ME_NextRun(&cursor.pPara, &cursor.pRun); + ME_NextRun(&cursor.pPara, &cursor.pRun, TRUE); cursor.nOffset = 0; } } @@ -1886,7 +1886,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH if (nCurEnd == 0) { - ME_PrevRun(&pCurPara, &pCurItem); + ME_PrevRun(&pCurPara, &pCurItem, TRUE); nCurEnd = pCurItem->member.run.len; } @@ -1935,7 +1935,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH } if (nCurEnd - nMatched == 0) { - ME_PrevRun(&pCurPara, &pCurItem); + ME_PrevRun(&pCurPara, &pCurItem, TRUE); /* Don't care about pCurItem becoming NULL here; it's already taken * care of in the exterior loop condition */ nCurEnd = pCurItem->member.run.len + nMatched; @@ -1949,7 +1949,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH cursor.nOffset--; if (cursor.nOffset < 0) { - ME_PrevRun(&cursor.pPara, &cursor.pRun); + ME_PrevRun(&cursor.pPara, &cursor.pRun, TRUE); cursor.nOffset = cursor.pRun->member.run.len; } } @@ -2624,6 +2624,11 @@ static int ME_CalculateClickCount(ME_TextEditor *editor, UINT msg, WPARAM wParam return clickNum; } +static BOOL is_link( ME_Run *run ) +{ + return (run->style->fmt.dwMask & CFM_LINK) && (run->style->fmt.dwEffects & CFE_LINK); +} + static BOOL ME_SetCursor(ME_TextEditor *editor) { ME_Cursor cursor; @@ -2689,8 +2694,7 @@ static BOOL ME_SetCursor(ME_TextEditor *editor) ME_Run *run; run = &cursor.pRun->member.run; - if (run->style->fmt.dwMask & CFM_LINK && - run->style->fmt.dwEffects & CFE_LINK) + if (is_link( run )) { ITextHost_TxSetCursor(editor->texthost, LoadCursorW(NULL, (WCHAR*)IDC_HAND), @@ -3125,8 +3129,7 @@ static void ME_LinkNotify(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM ME_CharFromPos(editor, x, y, &cursor, &isExact); if (!isExact) return; - if (cursor.pRun->member.run.style->fmt.dwMask & CFM_LINK && - cursor.pRun->member.run.style->fmt.dwEffects & CFE_LINK) + if (is_link( &cursor.pRun->member.run )) { /* The clicked run has CFE_LINK set */ ME_DisplayItem *di; @@ -3140,21 +3143,15 @@ static void ME_LinkNotify(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM /* find the first contiguous run with CFE_LINK set */ info.chrg.cpMin = ME_GetCursorOfs(&cursor); - for (di = cursor.pRun->prev; - di && di->type == diRun && (di->member.run.style->fmt.dwMask & CFM_LINK) && (di->member.run.style->fmt.dwEffects & CFE_LINK); - di = di->prev) - { - info.chrg.cpMin -= di->member.run.len; - } + di = cursor.pRun; + while (ME_PrevRun( NULL, &di, FALSE ) && is_link( &di->member.run )) + info.chrg.cpMin -= di->member.run.len; /* find the last contiguous run with CFE_LINK set */ info.chrg.cpMax = ME_GetCursorOfs(&cursor) + cursor.pRun->member.run.len; - for (di = cursor.pRun->next; - di && di->type == diRun && (di->member.run.style->fmt.dwMask & CFM_LINK) && (di->member.run.style->fmt.dwEffects & CFE_LINK); - di = di->next) - { - info.chrg.cpMax += di->member.run.len; - } + di = cursor.pRun; + while (ME_NextRun( NULL, &di, FALSE ) && is_link( &di->member.run )) + info.chrg.cpMax += di->member.run.len; ITextHost_TxNotify(editor->texthost, info.nmhdr.code, &info); } @@ -3453,14 +3450,15 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, ME_RewrapRepaint(editor); } + if ((changedSettings & settings & ES_NOHIDESEL) && !editor->bHaveFocus) + ME_InvalidateSelection( editor ); + if (changedSettings & settings & ECO_VERTICAL) FIXME("ECO_VERTICAL not implemented yet!\n"); if (changedSettings & settings & ECO_AUTOHSCROLL) FIXME("ECO_AUTOHSCROLL not implemented yet!\n"); if (changedSettings & settings & ECO_AUTOVSCROLL) FIXME("ECO_AUTOVSCROLL not implemented yet!\n"); - if (changedSettings & settings & ECO_NOHIDESEL) - FIXME("ECO_NOHIDESEL not implemented yet!\n"); if (changedSettings & settings & ECO_WANTRETURN) FIXME("ECO_WANTRETURN not implemented yet!\n"); if (changedSettings & settings & ECO_AUTOWORDSELECTION) @@ -4257,6 +4255,8 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, editor->bHaveFocus = TRUE; ME_ShowCaret(editor); ME_SendOldNotify(editor, EN_SETFOCUS); + if (!editor->bHideSelection && !(editor->styleFlags & ES_NOHIDESEL)) + ME_InvalidateSelection( editor ); return 0; case WM_KILLFOCUS: ME_CommitUndo(editor); /* End coalesced undos for typed characters */ @@ -4264,6 +4264,8 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, editor->wheel_remain = 0; ME_HideCaret(editor); ME_SendOldNotify(editor, EN_KILLFOCUS); + if (!editor->bHideSelection && !(editor->styleFlags & ES_NOHIDESEL)) + ME_InvalidateSelection( editor ); return 0; case WM_COMMAND: TRACE("editor wnd command = %d\n", LOWORD(wParam)); @@ -5002,10 +5004,24 @@ LRESULT WINAPI REExtendedRegisterClass(void) return result; } -static BOOL isurlspecial(WCHAR c) +static int wchar_comp( const void *key, const void *elem ) { - static const WCHAR special_chars[] = {'.','/','%','@','*','|','\\','+','#',0}; - return strchrW( special_chars, c ) != NULL; + return *(const WCHAR *)key - *(const WCHAR *)elem; +} + +/* neutral characters end the url if the next non-neutral character is a space character, + otherwise they are included in the url. */ +static BOOL isurlneutral( WCHAR c ) +{ + /* NB this list is sorted */ + static const WCHAR neutral_chars[] = {'!','\"','\'','(',')',',','-','.',':',';','<','>','?','[',']','{','}'}; + + /* Some shortcuts */ + if (isalnum( c )) return FALSE; + if (c > neutral_chars[sizeof(neutral_chars) / sizeof(neutral_chars[0]) - 1]) return FALSE; + + return !!bsearch( &c, neutral_chars, sizeof(neutral_chars) / sizeof(neutral_chars[0]), + sizeof(c), wchar_comp ); } /** @@ -5021,87 +5037,90 @@ static BOOL ME_FindNextURLCandidate(ME_TextEditor *editor, ME_Cursor *candidate_min, ME_Cursor *candidate_max) { - ME_Cursor cursor = *start; - BOOL foundColon = FALSE; - BOOL candidateStarted = FALSE; - WCHAR lastAcceptedChar = '\0'; + ME_Cursor cursor = *start, neutral_end, space_end; + BOOL candidateStarted = FALSE, quoted = FALSE; + WCHAR c; while (nChars > 0) { - WCHAR *strStart = get_text( &cursor.pRun->member.run, 0 ); - WCHAR *str = strStart + cursor.nOffset; - int nLen = cursor.pRun->member.run.len - cursor.nOffset; - nChars -= nLen; + WCHAR *str = get_text( &cursor.pRun->member.run, 0 ); + int run_len = cursor.pRun->member.run.len; - if (~cursor.pRun->member.run.nFlags & MERF_ENDPARA) + nChars -= run_len - cursor.nOffset; + + /* Find start of candidate */ + if (!candidateStarted) { - /* Find start of candidate */ - if (!candidateStarted) + while (cursor.nOffset < run_len) { - while (nLen) + c = str[cursor.nOffset]; + if (!isspaceW( c ) && !isurlneutral( c )) { - nLen--; - if (isalnumW(*str) || isurlspecial(*str)) + *candidate_min = cursor; + candidateStarted = TRUE; + neutral_end.pPara = NULL; + space_end.pPara = NULL; + cursor.nOffset++; + break; + } + quoted = (c == '<'); + cursor.nOffset++; + } + } + + /* Find end of candidate */ + if (candidateStarted) + { + while (cursor.nOffset < run_len) + { + c = str[cursor.nOffset]; + if (isspaceW( c )) + { + if (quoted && c != '\r') { - cursor.nOffset = str - strStart; - *candidate_min = cursor; - candidateStarted = TRUE; - lastAcceptedChar = *str++; - break; + if (!space_end.pPara) + { + if (neutral_end.pPara) + space_end = neutral_end; + else + space_end = cursor; + } } - str++; + else + goto done; } - } - - /* Find end of candidate */ - if (candidateStarted) { - while (nLen) + else if (isurlneutral( c )) { - nLen--; - if (*str == ':' && !foundColon) { - foundColon = TRUE; - } else if (!isalnumW(*str) && !isurlspecial(*str)) { - cursor.nOffset = str - strStart; - if (lastAcceptedChar == ':') - ME_MoveCursorChars(editor, &cursor, -1); - *candidate_max = cursor; - return TRUE; + if (quoted && c == '>') + { + neutral_end.pPara = NULL; + space_end.pPara = NULL; + goto done; } - lastAcceptedChar = *str++; + if (!neutral_end.pPara) + neutral_end = cursor; } - } - } else { - /* End of paragraph: skip it if before candidate span, or terminates - current active span */ - if (candidateStarted) { - if (lastAcceptedChar == ':') - ME_MoveCursorChars(editor, &cursor, -1); - *candidate_max = cursor; - return TRUE; + else + neutral_end.pPara = NULL; + + cursor.nOffset++; } } - /* Reaching this point means no span was found, so get next span */ - if (!ME_NextRun(&cursor.pPara, &cursor.pRun)) { - if (candidateStarted) { - /* There are no further runs, so take end of text as end of candidate */ - cursor.nOffset = str - strStart; - if (lastAcceptedChar == ':') - ME_MoveCursorChars(editor, &cursor, -1); - *candidate_max = cursor; - return TRUE; - } - *candidate_max = *candidate_min = cursor; - return FALSE; - } cursor.nOffset = 0; + if (!ME_NextRun(&cursor.pPara, &cursor.pRun, TRUE)) + goto done; } - if (candidateStarted) { - /* There are no further runs, so take end of text as end of candidate */ - if (lastAcceptedChar == ':') - ME_MoveCursorChars(editor, &cursor, -1); - *candidate_max = cursor; +done: + if (candidateStarted) + { + if (space_end.pPara) + *candidate_max = space_end; + else if (neutral_end.pPara) + *candidate_max = neutral_end; + else + *candidate_max = cursor; return TRUE; } *candidate_max = *candidate_min = cursor; diff --git a/reactos/dll/win32/riched20/editor.h b/reactos/dll/win32/riched20/editor.h index 0c95cd39c47..1ea6ea6f427 100644 --- a/reactos/dll/win32/riched20/editor.h +++ b/reactos/dll/win32/riched20/editor.h @@ -123,8 +123,8 @@ void ME_CharFormatFromLogFont(HDC hDC, const LOGFONTW *lf, CHARFORMAT2W *fmt) DE /* list.c */ void ME_InsertBefore(ME_DisplayItem *diWhere, ME_DisplayItem *diWhat) DECLSPEC_HIDDEN; void ME_Remove(ME_DisplayItem *diWhere) DECLSPEC_HIDDEN; -BOOL ME_NextRun(ME_DisplayItem **para, ME_DisplayItem **run) DECLSPEC_HIDDEN; -BOOL ME_PrevRun(ME_DisplayItem **para, ME_DisplayItem **run) DECLSPEC_HIDDEN; +BOOL ME_NextRun(ME_DisplayItem **para, ME_DisplayItem **run, BOOL all_para) DECLSPEC_HIDDEN; +BOOL ME_PrevRun(ME_DisplayItem **para, ME_DisplayItem **run, BOOL all_para) DECLSPEC_HIDDEN; ME_DisplayItem *ME_FindItemBack(ME_DisplayItem *di, ME_DIType nTypeOrClass) DECLSPEC_HIDDEN; ME_DisplayItem *ME_FindItemFwd(ME_DisplayItem *di, ME_DIType nTypeOrClass) DECLSPEC_HIDDEN; ME_DisplayItem *ME_FindItemBackOrHere(ME_DisplayItem *di, ME_DIType nTypeOrClass) DECLSPEC_HIDDEN; diff --git a/reactos/dll/win32/riched20/list.c b/reactos/dll/win32/riched20/list.c index c57e5264f2e..ce21c59892e 100644 --- a/reactos/dll/win32/riched20/list.c +++ b/reactos/dll/win32/riched20/list.c @@ -63,16 +63,18 @@ static BOOL ME_DITypesEqual(ME_DIType type, ME_DIType nTypeOrClass) } } -/* Modifies run pointer to point to the next run, and modify the - * paragraph pointer if moving into the next paragraph. +/* Modifies run pointer to point to the next run. + * If all_para is FALSE constrain the search to the current para, + * otherwise modify the paragraph pointer if moving into the next paragraph. * * Returns TRUE if next run is found, otherwise returns FALSE. */ -BOOL ME_NextRun(ME_DisplayItem **para, ME_DisplayItem **run) +BOOL ME_NextRun(ME_DisplayItem **para, ME_DisplayItem **run, BOOL all_para) { ME_DisplayItem *p = (*run)->next; while (p->type != diTextEnd) { if (p->type == diParagraph) { + if (!all_para) return FALSE; *para = p; } else if (p->type == diRun) { *run = p; @@ -83,16 +85,18 @@ BOOL ME_NextRun(ME_DisplayItem **para, ME_DisplayItem **run) return FALSE; } -/* Modifies run pointer to point to the previous run, and modify the - * paragraph pointer if moving into the previous paragraph. +/* Modifies run pointer to point to the previous run. + * If all_para is FALSE constrain the search to the current para, + * otherwise modify the paragraph pointer if moving into the previous paragraph. * * Returns TRUE if previous run is found, otherwise returns FALSE. */ -BOOL ME_PrevRun(ME_DisplayItem **para, ME_DisplayItem **run) +BOOL ME_PrevRun(ME_DisplayItem **para, ME_DisplayItem **run, BOOL all_para) { ME_DisplayItem *p = (*run)->prev; while (p->type != diTextStart) { if (p->type == diParagraph) { + if (!all_para) return FALSE; if (p->member.para.prev_para->type == diParagraph) *para = p->member.para.prev_para; } else if (p->type == diRun) { diff --git a/reactos/dll/win32/riched20/paint.c b/reactos/dll/win32/riched20/paint.c index 85805398b6b..42434b9b470 100644 --- a/reactos/dll/win32/riched20/paint.c +++ b/reactos/dll/win32/riched20/paint.c @@ -261,7 +261,8 @@ static void draw_space( ME_Context *c, ME_Run *run, int x, int y, SetRect( &rect, x, ymin, x + run->nWidth, ymin + cy ); - if (c->editor->bHideSelection) selected = FALSE; + if (c->editor->bHideSelection || (!c->editor->bHaveFocus && + !(c->editor->styleFlags & ES_NOHIDESEL))) selected = FALSE; if (c->editor->bEmulateVersion10) { old_style_selected = selected; @@ -355,7 +356,8 @@ static void ME_DrawTextWithStyle(ME_Context *c, ME_Run *run, int x, int y, HGDIOBJ hOldFont; int yOffset = 0; BOOL selected = (nSelFrom < run->len && nSelTo >= 0 - && nSelFrom < nSelTo && !c->editor->bHideSelection); + && nSelFrom < nSelTo && !c->editor->bHideSelection && + (c->editor->bHaveFocus || (c->editor->styleFlags & ES_NOHIDESEL))); BOOL old_style_selected = FALSE; RECT sel_rect; HRGN clip = NULL, sel_rgn = NULL; diff --git a/reactos/dll/win32/riched20/para.c b/reactos/dll/win32/riched20/para.c index 67216982ad7..c762cf0c0fe 100644 --- a/reactos/dll/win32/riched20/para.c +++ b/reactos/dll/win32/riched20/para.c @@ -364,7 +364,7 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp, endCur.pRun = ME_FindItemFwd(pNext, diRun); endCur.nOffset = 0; startCur = endCur; - ME_PrevRun(&startCur.pPara, &startCur.pRun); + ME_PrevRun(&startCur.pPara, &startCur.pRun, TRUE); ME_SetCharFormat(editor, &startCur, &endCur, &fmt); if (!editor->bEmulateVersion10) { /* v4.1 */ diff --git a/reactos/dll/win32/riched20/richole.c b/reactos/dll/win32/riched20/richole.c index 784b85fe538..e38009dba8a 100644 --- a/reactos/dll/win32/riched20/richole.c +++ b/reactos/dll/win32/riched20/richole.c @@ -1597,7 +1597,7 @@ static HRESULT WINAPI ITextRange_fnGetIDsOfNames(ITextRange *me, REFIID riid, LP ITypeInfo *ti; HRESULT hr; - TRACE("(%p)->(%p,%p,%u,%d,%p)\n", This, riid, rgszNames, cNames, lcid, + TRACE("(%p)->(%s, %p, %u, %d, %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId); hr = get_typeinfo(ITextRange_tid, &ti); @@ -1615,8 +1615,8 @@ static HRESULT WINAPI ITextRange_fnInvoke(ITextRange *me, DISPID dispIdMember, R ITypeInfo *ti; HRESULT hr; - TRACE("(%p)->(%d,%p,%d,%u,%p,%p,%p,%p)\n", This, dispIdMember, riid, lcid, - wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + TRACE("(%p)->(%d, %s, %d, %u, %p, %p, %p, %p)\n", This, dispIdMember, debugstr_guid(riid), + lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); hr = get_typeinfo(ITextRange_tid, &ti); if (SUCCEEDED(hr)) @@ -1970,7 +1970,7 @@ static HRESULT range_Collapse(LONG bStart, LONG *start, LONG *end) if (*end == *start) return S_FALSE; - if (bStart == tomEnd || bStart == tomFalse) + if (bStart == tomEnd) *start = *end; else *end = *start; @@ -2618,8 +2618,8 @@ static HRESULT WINAPI TextFont_GetIDsOfNames(ITextFont *iface, REFIID riid, ITypeInfo *ti; HRESULT hr; - TRACE("(%p)->(%p,%p,%u,%d,%p)\n", This, riid, rgszNames, cNames, lcid, - rgDispId); + TRACE("(%p)->(%s, %p, %u, %d, %p)\n", This, debugstr_guid(riid), + rgszNames, cNames, lcid, rgDispId); hr = get_typeinfo(ITextFont_tid, &ti); if (SUCCEEDED(hr)) @@ -2642,8 +2642,8 @@ static HRESULT WINAPI TextFont_Invoke( ITypeInfo *ti; HRESULT hr; - TRACE("(%p)->(%d,%p,%d,%u,%p,%p,%p,%p)\n", This, dispIdMember, riid, lcid, - wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + TRACE("(%p)->(%d, %s, %d, %u, %p, %p, %p, %p)\n", This, dispIdMember, debugstr_guid(riid), + lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); hr = get_typeinfo(ITextFont_tid, &ti); if (SUCCEEDED(hr)) @@ -3430,8 +3430,8 @@ static HRESULT WINAPI TextPara_GetIDsOfNames(ITextPara *iface, REFIID riid, ITypeInfo *ti; HRESULT hr; - TRACE("(%p)->(%p,%p,%u,%d,%p)\n", This, riid, rgszNames, cNames, lcid, - rgDispId); + TRACE("(%p)->(%s, %p, %u, %d, %p)\n", This, debugstr_guid(riid), rgszNames, + cNames, lcid, rgDispId); hr = get_typeinfo(ITextPara_tid, &ti); if (SUCCEEDED(hr)) @@ -3454,8 +3454,9 @@ static HRESULT WINAPI TextPara_Invoke( ITypeInfo *ti; HRESULT hr; - TRACE("(%p)->(%d,%p,%d,%u,%p,%p,%p,%p)\n", This, dispIdMember, riid, lcid, - wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + TRACE("(%p)->(%d, %s, %d, %u, %p, %p, %p, %p)\n", This, dispIdMember, + debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, + pExcepInfo, puArgErr); hr = get_typeinfo(ITextPara_tid, &ti); if (SUCCEEDED(hr)) @@ -4125,8 +4126,8 @@ ITextDocument_fnGetIDsOfNames(ITextDocument* me, REFIID riid, ITypeInfo *ti; HRESULT hr; - TRACE("(%p)->(%p,%p,%u,%d,%p)\n", This, riid, rgszNames, cNames, lcid, - rgDispId); + TRACE("(%p)->(%s, %p, %u, %d, %p)\n", This, debugstr_guid(riid), + rgszNames, cNames, lcid, rgDispId); hr = get_typeinfo(ITextDocument_tid, &ti); if (SUCCEEDED(hr)) @@ -4143,8 +4144,9 @@ ITextDocument_fnInvoke(ITextDocument* me, DISPID dispIdMember, ITypeInfo *ti; HRESULT hr; - TRACE("(%p)->(%d,%p,%d,%u,%p,%p,%p,%p)\n", This, dispIdMember, riid, lcid, - wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + TRACE("(%p)->(%d, %s, %d, %u, %p, %p, %p, %p)\n", This, dispIdMember, + debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, + pExcepInfo, puArgErr); hr = get_typeinfo(ITextDocument_tid, &ti); if (SUCCEEDED(hr)) @@ -4445,7 +4447,7 @@ static HRESULT WINAPI ITextSelection_fnGetIDsOfNames(ITextSelection *me, REFIID ITypeInfo *ti; HRESULT hr; - TRACE("(%p)->(%p,%p,%u,%d,%p)\n", This, riid, rgszNames, cNames, lcid, + TRACE("(%p)->(%s, %p, %u, %d, %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId); hr = get_typeinfo(ITextSelection_tid, &ti); @@ -4469,7 +4471,7 @@ static HRESULT WINAPI ITextSelection_fnInvoke( ITypeInfo *ti; HRESULT hr; - TRACE("(%p)->(%d,%p,%d,%u,%p,%p,%p,%p)\n", This, dispIdMember, riid, lcid, + TRACE("(%p)->(%d, %s, %d, %u, %p, %p, %p, %p)\n", This, dispIdMember, debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); hr = get_typeinfo(ITextSelection_tid, &ti); diff --git a/reactos/dll/win32/riched20/writer.c b/reactos/dll/win32/riched20/writer.c index f38ea30c9c7..96b8a406859 100644 --- a/reactos/dll/win32/riched20/writer.c +++ b/reactos/dll/win32/riched20/writer.c @@ -112,6 +112,32 @@ ME_StreamOutPrint(ME_OutStream *pStream, const char *format, ...) return ME_StreamOutMove(pStream, string, len); } +#define HEX_BYTES_PER_LINE 40 + +static BOOL +ME_StreamOutHexData(ME_OutStream *stream, const BYTE *data, UINT len) +{ + + char line[HEX_BYTES_PER_LINE * 2 + 1]; + UINT size, i; + static const char hex[] = "0123456789abcdef"; + + while (len) + { + size = min( len, HEX_BYTES_PER_LINE ); + for (i = 0; i < size; i++) + { + line[i * 2] = hex[(*data >> 4) & 0xf]; + line[i * 2 + 1] = hex[*data & 0xf]; + data++; + } + line[size * 2] = '\n'; + if (!ME_StreamOutMove( stream, line, size * 2 + 1 )) + return FALSE; + len -= size; + } + return TRUE; +} static BOOL ME_StreamOutRTFHeader(ME_OutStream *pStream, int dwFormat) @@ -780,6 +806,69 @@ ME_StreamOutRTFText(ME_OutStream *pStream, const WCHAR *text, LONG nChars) return ME_StreamOutMove(pStream, buffer, pos); } +static BOOL stream_out_graphics( ME_TextEditor *editor, ME_OutStream *stream, + ME_Run *run ) +{ + IDataObject *data; + HRESULT hr; + FORMATETC fmt = { CF_ENHMETAFILE, NULL, DVASPECT_CONTENT, -1, TYMED_ENHMF }; + STGMEDIUM med = { TYMED_NULL }; + BOOL ret = FALSE; + ENHMETAHEADER *emf_bits = NULL; + UINT size; + SIZE goal, pic; + ME_Context c; + + hr = IOleObject_QueryInterface( run->ole_obj->poleobj, &IID_IDataObject, (void **)&data ); + if (FAILED(hr)) return FALSE; + + ME_InitContext( &c, editor, ITextHost_TxGetDC( editor->texthost ) ); + hr = IDataObject_QueryGetData( data, &fmt ); + if (hr != S_OK) goto done; + + hr = IDataObject_GetData( data, &fmt, &med ); + if (FAILED(hr)) goto done; + if (med.tymed != TYMED_ENHMF) goto done; + + size = GetEnhMetaFileBits( med.u.hEnhMetaFile, 0, NULL ); + if (size < FIELD_OFFSET(ENHMETAHEADER, cbPixelFormat)) goto done; + + emf_bits = HeapAlloc( GetProcessHeap(), 0, size ); + if (!emf_bits) goto done; + + size = GetEnhMetaFileBits( med.u.hEnhMetaFile, size, (BYTE *)emf_bits ); + if (size < FIELD_OFFSET(ENHMETAHEADER, cbPixelFormat)) goto done; + + /* size_in_pixels = (frame_size / 100) * szlDevice / szlMillimeters + pic = size_in_pixels * 2540 / dpi */ + pic.cx = MulDiv( emf_bits->rclFrame.right - emf_bits->rclFrame.left, emf_bits->szlDevice.cx * 254, + emf_bits->szlMillimeters.cx * c.dpi.cx * 10 ); + pic.cy = MulDiv( emf_bits->rclFrame.bottom - emf_bits->rclFrame.top, emf_bits->szlDevice.cy * 254, + emf_bits->szlMillimeters.cy * c.dpi.cy * 10 ); + + /* convert goal size to twips */ + goal.cx = MulDiv( run->ole_obj->sizel.cx, 144, 254 ); + goal.cy = MulDiv( run->ole_obj->sizel.cy, 144, 254 ); + + if (!ME_StreamOutPrint( stream, "{\\*\\shppict{\\pict\\emfblip\\picw%d\\pich%d\\picwgoal%d\\pichgoal%d\n", + pic.cx, pic.cy, goal.cx, goal.cy )) + goto done; + + if (!ME_StreamOutHexData( stream, (BYTE *)emf_bits, size )) + goto done; + + if (!ME_StreamOutPrint( stream, "}}\n" )) + goto done; + + ret = TRUE; + +done: + ME_DestroyContext( &c ); + HeapFree( GetProcessHeap(), 0, emf_bits ); + ReleaseStgMedium( &med ); + IDataObject_Release( data ); + return ret; +} static BOOL ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, const ME_Cursor *start, int nChars, int dwFormat) @@ -831,7 +920,8 @@ static BOOL ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, if (cursor.pPara->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND)) continue; if (cursor.pRun->member.run.nFlags & MERF_GRAPHICS) { - FIXME("embedded objects are not handled\n"); + if (!stream_out_graphics(editor, pStream, &cursor.pRun->member.run)) + return FALSE; } else if (cursor.pRun->member.run.nFlags & MERF_TAB) { if (editor->bEmulateVersion10 && /* v1.0 - 3.0 */ cursor.pPara->member.para.pFmt->dwMask & PFM_TABLE && @@ -886,7 +976,7 @@ static BOOL ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, if (!ME_StreamOutPrint(pStream, "}")) return FALSE; } - } while (cursor.pRun != endCur.pRun && ME_NextRun(&cursor.pPara, &cursor.pRun)); + } while (cursor.pRun != endCur.pRun && ME_NextRun(&cursor.pPara, &cursor.pRun, TRUE)); if (!ME_StreamOutMove(pStream, "}\0", 2)) return FALSE; diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 4f8cf85777b..57a81cd7e59 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -161,7 +161,7 @@ reactos/dll/win32/qmgrprxy # Synced to WineStaging-1.9.11 reactos/dll/win32/query # Synced to WineStaging-1.9.11 reactos/dll/win32/rasapi32 # Synced to WineStaging-1.9.11 reactos/dll/win32/resutils # Synced to WineStaging-1.9.11 -reactos/dll/win32/riched20 # Synced to WineStaging-1.9.11 +reactos/dll/win32/riched20 # Synced to WineStaging-1.9.16 reactos/dll/win32/riched32 # Synced to WineStaging-1.9.11 reactos/dll/win32/rpcrt4 # Synced to WineStaging-1.9.11 reactos/dll/win32/rsabase # Synced to WineStaging-1.9.11