From: Amine Khaldi Date: Mon, 6 Oct 2014 18:41:33 +0000 (+0000) Subject: [RICHED20] X-Git-Tag: backups/0.3.17@66124~178 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=c9eeedbc7bfa565745b8261a0a0830f21c1fc084 [RICHED20] * Sync with Wine 1.7.27. CORE-8540 svn path=/trunk/; revision=64571 --- diff --git a/reactos/dll/win32/riched20/caret.c b/reactos/dll/win32/riched20/caret.c index 90b30a2f576..043a32a0d64 100644 --- a/reactos/dll/win32/riched20/caret.c +++ b/reactos/dll/win32/riched20/caret.c @@ -139,6 +139,7 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to) { ME_SetCursorToStart(editor, &editor->pCursors[1]); ME_SetCursorToEnd(editor, &editor->pCursors[0]); + editor->pCursors[0].nOffset = editor->pCursors[0].pRun->member.run.len; ME_InvalidateSelection(editor); return len + 1; } @@ -159,6 +160,11 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to) ME_GetSelectionOfs(editor, &start, &end); if (start != end) { + if (end > len) + { + editor->pCursors[0].nOffset = 0; + end --; + } editor->pCursors[1] = editor->pCursors[0]; ME_Repaint(editor); } @@ -200,7 +206,12 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to) if (editor->pCursors[1].pRun->member.run.nFlags & MERF_ENDPARA) editor->pCursors[1].nOffset = 0; if (editor->pCursors[0].pRun->member.run.nFlags & MERF_ENDPARA) - editor->pCursors[0].nOffset = 0; + { + if (to > len) + editor->pCursors[0].nOffset = editor->pCursors[0].pRun->member.run.len; + else + editor->pCursors[0].nOffset = 0; + } return to; } diff --git a/reactos/dll/win32/riched20/clipboard.c b/reactos/dll/win32/riched20/clipboard.c index f7514a2ad85..250a233896a 100644 --- a/reactos/dll/win32/riched20/clipboard.c +++ b/reactos/dll/win32/riched20/clipboard.c @@ -352,7 +352,7 @@ static HGLOBAL get_unicode_text(ME_TextEditor *editor, const ME_Cursor *start, i ret = GlobalAlloc(GMEM_MOVEABLE, sizeof(WCHAR) * (nChars + pars + 1)); data = GlobalLock(ret); - ME_GetTextW(editor, data, nChars + pars, start, nChars, TRUE); + ME_GetTextW(editor, data, nChars + pars, start, nChars, TRUE, FALSE); GlobalUnlock(ret); return ret; } diff --git a/reactos/dll/win32/riched20/editor.c b/reactos/dll/win32/riched20/editor.c index 7ccdd494354..834f7102d76 100644 --- a/reactos/dll/win32/riched20/editor.c +++ b/reactos/dll/win32/riched20/editor.c @@ -1618,7 +1618,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre CR/LF counters, since RTF streaming presents only \para tokens, which are converted according to the standard rules: \r for 2.0, \r\n for 1.0 */ - if (stripLastCR) { + if (stripLastCR && !(format & SFF_SELECTION)) { int newto; ME_GetSelection(editor, &selStart, &selEnd); newto = ME_GetCursorOfs(selEnd); @@ -1628,7 +1628,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre ME_Cursor linebreakCursor = *selEnd; ME_MoveCursorChars(editor, &linebreakCursor, -linebreakSize); - ME_GetTextW(editor, lastchar, 2, &linebreakCursor, linebreakSize, FALSE); + ME_GetTextW(editor, lastchar, 2, &linebreakCursor, linebreakSize, FALSE, FALSE); if (lastchar[0] == '\r' && (lastchar[1] == '\n' || lastchar[1] == '\0')) { ME_InternalDeleteText(editor, &linebreakCursor, linebreakSize, FALSE); } @@ -1966,7 +1966,7 @@ static int ME_GetTextEx(ME_TextEditor *editor, GETTEXTEX *ex, LPARAM pText) if (ex->codepage == CP_UNICODE) { return ME_GetTextW(editor, (LPWSTR)pText, ex->cb / sizeof(WCHAR) - 1, - &start, nChars, ex->flags & GT_USECRLF); + &start, nChars, ex->flags & GT_USECRLF, FALSE); } else { @@ -1983,7 +1983,7 @@ static int ME_GetTextEx(ME_TextEditor *editor, GETTEXTEX *ex, LPARAM pText) buflen = min(crlfmul * nChars, ex->cb - 1); buffer = heap_alloc((buflen + 1) * sizeof(WCHAR)); - nChars = ME_GetTextW(editor, buffer, buflen, &start, nChars, ex->flags & GT_USECRLF); + nChars = ME_GetTextW(editor, buffer, buflen, &start, nChars, ex->flags & GT_USECRLF, FALSE); rc = WideCharToMultiByte(ex->codepage, 0, buffer, nChars + 1, (LPSTR)pText, ex->cb, ex->lpDefaultChar, ex->lpUsedDefChar); if (rc) rc--; /* do not count 0 terminator */ @@ -1998,12 +1998,12 @@ static int ME_GetTextRange(ME_TextEditor *editor, WCHAR *strText, { if (!strText) return 0; if (unicode) { - return ME_GetTextW(editor, strText, INT_MAX, start, nLen, FALSE); + return ME_GetTextW(editor, strText, INT_MAX, start, nLen, FALSE, FALSE); } else { int nChars; WCHAR *p = ALLOC_N_OBJ(WCHAR, nLen+1); if (!p) return 0; - nChars = ME_GetTextW(editor, p, nLen, start, nLen, FALSE); + nChars = ME_GetTextW(editor, p, nLen, start, nLen, FALSE, FALSE); WideCharToMultiByte(CP_ACP, 0, p, nChars+1, (char *)strText, nLen+1, NULL, NULL); FREE_OBJ(p); @@ -2742,6 +2742,7 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) ed->hwndParent = NULL; ed->sizeWindow.cx = ed->sizeWindow.cy = 0; ed->texthost = texthost; + ed->reOle = NULL; ed->bEmulateVersion10 = bEmulateVersion10; ed->styleFlags = 0; ITextHost_TxGetPropertyBits(texthost, @@ -2884,6 +2885,11 @@ static void ME_DestroyEditor(ME_TextEditor *editor) if(editor->lpOleCallback) IRichEditOleCallback_Release(editor->lpOleCallback); ITextHost_Release(editor->texthost); + if (editor->reOle) + { + IRichEditOle_Release(editor->reOle); + editor->reOle = NULL; + } OleUninitialize(); FREE_OBJ(editor->pBuffer); @@ -3091,6 +3097,8 @@ static void ME_LinkNotify(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM if (cursor.pRun->member.run.style->fmt.dwMask & CFM_LINK && cursor.pRun->member.run.style->fmt.dwEffects & CFE_LINK) { /* The clicked run has CFE_LINK set */ + ME_DisplayItem *di; + info.nmhdr.hwndFrom = NULL; info.nmhdr.idFrom = 0; info.nmhdr.code = EN_LINK; @@ -3098,8 +3106,25 @@ static void ME_LinkNotify(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM info.wParam = wParam; info.lParam = lParam; cursor.nOffset = 0; + + /* find the first contiguous run with CFE_LINK set */ info.chrg.cpMin = ME_GetCursorOfs(&cursor); - info.chrg.cpMax = info.chrg.cpMin + cursor.pRun->member.run.len; + 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; + } + + /* 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; + } + ITextHost_TxNotify(editor->texthost, info.nmhdr.code, &info); } } @@ -3452,7 +3477,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, editor->styleFlags |= ES_READONLY; else editor->styleFlags &= ~ES_READONLY; - return 0; + return 1; } case EM_SETEVENTMASK: { @@ -4446,8 +4471,12 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } case EM_GETOLEINTERFACE: { - LPVOID *ppvObj = (LPVOID*) lParam; - return CreateIRichEditOle(editor, ppvObj); + if (!editor->reOle) + if (!CreateIRichEditOle(editor, (LPVOID *)&editor->reOle)) + return 0; + *(LPVOID *)lParam = editor->reOle; + IRichEditOle_AddRef(editor->reOle); + return 1; } case EM_GETPASSWORDCHAR: { @@ -4716,7 +4745,8 @@ void ME_SendOldNotify(ME_TextEditor *editor, int nCode) * The written text is always NULL terminated. */ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, - const ME_Cursor *start, int srcChars, BOOL bCRLF) + const ME_Cursor *start, int srcChars, BOOL bCRLF, + BOOL bEOP) { ME_DisplayItem *pRun, *pNextRun; const WCHAR *pStart = buffer; @@ -4734,7 +4764,6 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, nLen = pRun->member.run.len - start->nOffset; str = get_text( &pRun->member.run, start->nOffset ); - /* No '\r' is appended to the last paragraph. */ while (srcChars && buflen && pNextRun) { int nFlags = pRun->member.run.nFlags; @@ -4766,6 +4795,12 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, nLen = pRun->member.run.len; str = get_text( &pRun->member.run, 0 ); } + /* append '\r' to the last paragraph. */ + if (pRun->next->type == diTextEnd && bEOP) + { + *buffer = '\r'; + buffer ++; + } *buffer = 0; return buffer - pStart; } @@ -5010,7 +5045,7 @@ static BOOL ME_IsCandidateAnURL(ME_TextEditor *editor, const ME_Cursor *start, i WCHAR bufferW[MAX_PREFIX_LEN + 1]; unsigned int i; - ME_GetTextW(editor, bufferW, MAX_PREFIX_LEN, start, nChars, FALSE); + ME_GetTextW(editor, bufferW, MAX_PREFIX_LEN, start, nChars, FALSE, FALSE); for (i = 0; i < sizeof(prefixes) / sizeof(*prefixes); i++) { if (nChars < prefixes[i].length) continue; diff --git a/reactos/dll/win32/riched20/editor.h b/reactos/dll/win32/riched20/editor.h index 4c19c49620e..f778381564b 100644 --- a/reactos/dll/win32/riched20/editor.h +++ b/reactos/dll/win32/riched20/editor.h @@ -286,7 +286,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode, HRESULT* phresult) DECLSPEC_HIDDEN; void ME_SendOldNotify(ME_TextEditor *editor, int nCode) DECLSPEC_HIDDEN; int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, - const ME_Cursor *start, int srcChars, BOOL bCRLF) DECLSPEC_HIDDEN; + const ME_Cursor *start, int srcChars, BOOL bCRLF, BOOL bEOP) DECLSPEC_HIDDEN; void ME_RTFCharAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN; void ME_RTFParAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN; void ME_RTFTblAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN; diff --git a/reactos/dll/win32/riched20/editstr.h b/reactos/dll/win32/riched20/editstr.h index 5356b0639bf..d9809db469d 100644 --- a/reactos/dll/win32/riched20/editstr.h +++ b/reactos/dll/win32/riched20/editstr.h @@ -357,6 +357,7 @@ typedef struct tagME_TextEditor { HWND hWnd, hwndParent; ITextHost *texthost; + IRichEditOle *reOle; BOOL bEmulateVersion10; ME_TextBuffer *pBuffer; ME_Cursor *pCursors; diff --git a/reactos/dll/win32/riched20/reader.c b/reactos/dll/win32/riched20/reader.c index 9e115b5514b..5e35d739391 100644 --- a/reactos/dll/win32/riched20/reader.c +++ b/reactos/dll/win32/riched20/reader.c @@ -699,7 +699,7 @@ static void _RTFGetToken2(RTF_Info *info) /* * Read the next character from the input. This handles setting the - * current line and position-within-line variables. Those variable are + * current line and position-within-line variables. Those variables are * set correctly whether lines end with CR, LF, or CRLF (the last being * the tricky case). * diff --git a/reactos/dll/win32/riched20/richole.c b/reactos/dll/win32/riched20/richole.c index e33bba5b201..eb7b1ded847 100644 --- a/reactos/dll/win32/riched20/richole.c +++ b/reactos/dll/win32/riched20/richole.c @@ -37,6 +37,7 @@ DEFINE_GUID(IID_ITextSelection, 0x8cc497c1, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0x typedef struct ITextSelectionImpl ITextSelectionImpl; typedef struct IOleClientSiteImpl IOleClientSiteImpl; +typedef struct ITextRangeImpl ITextRangeImpl; typedef struct IRichEditOleImpl { IRichEditOle IRichEditOle_iface; @@ -46,8 +47,18 @@ typedef struct IRichEditOleImpl { ME_TextEditor *editor; ITextSelectionImpl *txtSel; IOleClientSiteImpl *clientSite; + struct list rangelist; } IRichEditOleImpl; +struct ITextRangeImpl { + ITextRange ITextRange_iface; + LONG ref; + LONG start, end; + struct list entry; + + IRichEditOleImpl *reOle; +}; + struct ITextSelectionImpl { ITextSelection ITextSelection_iface; LONG ref; @@ -116,10 +127,13 @@ IRichEditOle_fnRelease(IRichEditOle *me) if (!ref) { + ITextRangeImpl *txtRge; TRACE ("Destroying %p\n", This); This->txtSel->reOle = NULL; ITextSelection_Release(&This->txtSel->ITextSelection_iface); IOleClientSite_Release(&This->clientSite->IOleClientSite_iface); + LIST_FOR_EACH_ENTRY(txtRge, &This->rangelist, ITextRangeImpl, entry) + txtRge->reOle = NULL; heap_free(This); } return ref; @@ -431,6 +445,722 @@ static const IRichEditOleVtbl revt = { IRichEditOle_fnImportDataObject }; +/* ITextRange interface */ +static inline ITextRangeImpl *impl_from_ITextRange(ITextRange *iface) +{ + return CONTAINING_RECORD(iface, ITextRangeImpl, ITextRange_iface); +} + +static HRESULT WINAPI ITextRange_fnQueryInterface(ITextRange *me, REFIID riid, void **ppvObj) +{ + *ppvObj = NULL; + if (IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_IDispatch) + || IsEqualGUID(riid, &IID_ITextRange)) + { + *ppvObj = me; + ITextRange_AddRef(me); + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG WINAPI ITextRange_fnAddRef(ITextRange *me) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI ITextRange_fnRelease(ITextRange *me) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE ("%p ref=%u\n", This, ref); + if (ref == 0) + { + if (This->reOle) + { + list_remove(&This->entry); + This->reOle = NULL; + } + heap_free(This); + } + return ref; +} + +static HRESULT WINAPI ITextRange_fnGetTypeInfoCount(ITextRange *me, UINT *pctinfo) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnGetTypeInfo(ITextRange *me, UINT iTInfo, LCID lcid, + ITypeInfo **ppTInfo) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnGetIDsOfNames(ITextRange *me, REFIID riid, LPOLESTR *rgszNames, + UINT cNames, LCID lcid, DISPID *rgDispId) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnInvoke(ITextRange *me, DISPID dispIdMember, REFIID riid, + LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, + VARIANT *pVarResult, EXCEPINFO *pExcepInfo, + UINT *puArgErr) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnGetText(ITextRange *me, BSTR *pbstr) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnSetText(ITextRange *me, BSTR bstr) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT range_GetChar(ME_TextEditor *editor, ME_Cursor *cursor, LONG *pch) +{ + WCHAR wch[2]; + + ME_GetTextW(editor, wch, 1, cursor, 1, FALSE, cursor->pRun->next->type == diTextEnd); + *pch = wch[0]; + + return S_OK; +} + +static HRESULT WINAPI ITextRange_fnGetChar(ITextRange *me, LONG *pch) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + ME_Cursor cursor; + + if (!This->reOle) + return CO_E_RELEASED; + TRACE("%p\n", pch); + if (!pch) + return E_INVALIDARG; + + ME_CursorFromCharOfs(This->reOle->editor, This->start, &cursor); + return range_GetChar(This->reOle->editor, &cursor, pch); +} + +static HRESULT WINAPI ITextRange_fnSetChar(ITextRange *me, LONG ch) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT CreateITextRange(IRichEditOleImpl *reOle, LONG start, LONG end, ITextRange** ppRange); + +static HRESULT WINAPI ITextRange_fnGetDuplicate(ITextRange *me, ITextRange **ppRange) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + TRACE("%p %p\n", This, ppRange); + if (!ppRange) + return E_INVALIDARG; + + return CreateITextRange(This->reOle, This->start, This->end, ppRange); +} + +static HRESULT WINAPI ITextRange_fnGetFormattedText(ITextRange *me, ITextRange **ppRange) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnSetFormattedText(ITextRange *me, ITextRange *pRange) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnGetStart(ITextRange *me, LONG *pcpFirst) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + if (!pcpFirst) + return E_INVALIDARG; + *pcpFirst = This->start; + TRACE("%d\n", *pcpFirst); + return S_OK; +} + +static HRESULT WINAPI ITextRange_fnSetStart(ITextRange *me, LONG cpFirst) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnGetEnd(ITextRange *me, LONG *pcpLim) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + if (!pcpLim) + return E_INVALIDARG; + *pcpLim = This->end; + TRACE("%d\n", *pcpLim); + return S_OK; +} + +static HRESULT WINAPI ITextRange_fnSetEnd(ITextRange *me, LONG cpLim) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnGetFont(ITextRange *me, ITextFont **pFont) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnSetFont(ITextRange *me, ITextFont *pFont) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnGetPara(ITextRange *me, ITextPara **ppPara) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnSetPara(ITextRange *me, ITextPara *pPara) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnGetStoryLength(ITextRange *me, LONG *pcch) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnGetStoryType(ITextRange *me, LONG *pValue) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT range_Collapse(LONG bStart, LONG *start, LONG *end) +{ + if (*end == *start) + return S_FALSE; + + if (bStart == tomEnd || bStart == tomFalse) + *start = *end; + else + *end = *start; + return S_OK; +} + +static HRESULT WINAPI ITextRange_fnCollapse(ITextRange *me, LONG bStart) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + return range_Collapse(bStart, &This->start, &This->end); +} + +static HRESULT WINAPI ITextRange_fnExpand(ITextRange *me, LONG Unit, LONG *pDelta) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnGetIndex(ITextRange *me, LONG Unit, LONG *pIndex) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnSetIndex(ITextRange *me, LONG Unit, LONG Index, + LONG Extend) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnSetRange(ITextRange *me, LONG cpActive, LONG cpOther) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnInRange(ITextRange *me, ITextRange *pRange, LONG *pb) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnInStory(ITextRange *me, ITextRange *pRange, LONG *pb) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnIsEqual(ITextRange *me, ITextRange *pRange, LONG *pb) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnSelect(ITextRange *me) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnStartOf(ITextRange *me, LONG Unit, LONG Extend, + LONG *pDelta) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnEndOf(ITextRange *me, LONG Unit, LONG Extend, + LONG *pDelta) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnMove(ITextRange *me, LONG Unit, LONG Count, LONG *pDelta) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnMoveStart(ITextRange *me, LONG Unit, LONG Count, + LONG *pDelta) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnMoveEnd(ITextRange *me, LONG Unit, LONG Count, + LONG *pDelta) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnMoveWhile(ITextRange *me, VARIANT *Cset, LONG Count, + LONG *pDelta) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnMoveStartWhile(ITextRange *me, VARIANT *Cset, LONG Count, + LONG *pDelta) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnMoveEndWhile(ITextRange *me, VARIANT *Cset, LONG Count, + LONG *pDelta) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnMoveUntil(ITextRange *me, VARIANT *Cset, LONG Count, + LONG *pDelta) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnMoveStartUntil(ITextRange *me, VARIANT *Cset, LONG Count, + LONG *pDelta) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnMoveEndUntil(ITextRange *me, VARIANT *Cset, LONG Count, + LONG *pDelta) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnFindText(ITextRange *me, BSTR bstr, LONG cch, LONG Flags, + LONG *pLength) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnFindTextStart(ITextRange *me, BSTR bstr, LONG cch, + LONG Flags, LONG *pLength) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnFindTextEnd(ITextRange *me, BSTR bstr, LONG cch, + LONG Flags, LONG *pLength) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnDelete(ITextRange *me, LONG Unit, LONG Count, + LONG *pDelta) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnCut(ITextRange *me, VARIANT *pVar) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnCopy(ITextRange *me, VARIANT *pVar) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnPaste(ITextRange *me, VARIANT *pVar, LONG Format) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnCanPaste(ITextRange *me, VARIANT *pVar, LONG Format, + LONG *pb) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnCanEdit(ITextRange *me, LONG *pb) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnChangeCase(ITextRange *me, LONG Type) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnGetPoint(ITextRange *me, LONG Type, LONG *cx, LONG *cy) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnSetPoint(ITextRange *me, LONG x, LONG y, LONG Type, + LONG Extend) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnScrollIntoView(ITextRange *me, LONG Value) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextRange_fnGetEmbeddedObject(ITextRange *me, IUnknown **ppv) +{ + ITextRangeImpl *This = impl_from_ITextRange(me); + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented %p\n", This); + return E_NOTIMPL; +} + +static const ITextRangeVtbl trvt = { + ITextRange_fnQueryInterface, + ITextRange_fnAddRef, + ITextRange_fnRelease, + ITextRange_fnGetTypeInfoCount, + ITextRange_fnGetTypeInfo, + ITextRange_fnGetIDsOfNames, + ITextRange_fnInvoke, + ITextRange_fnGetText, + ITextRange_fnSetText, + ITextRange_fnGetChar, + ITextRange_fnSetChar, + ITextRange_fnGetDuplicate, + ITextRange_fnGetFormattedText, + ITextRange_fnSetFormattedText, + ITextRange_fnGetStart, + ITextRange_fnSetStart, + ITextRange_fnGetEnd, + ITextRange_fnSetEnd, + ITextRange_fnGetFont, + ITextRange_fnSetFont, + ITextRange_fnGetPara, + ITextRange_fnSetPara, + ITextRange_fnGetStoryLength, + ITextRange_fnGetStoryType, + ITextRange_fnCollapse, + ITextRange_fnExpand, + ITextRange_fnGetIndex, + ITextRange_fnSetIndex, + ITextRange_fnSetRange, + ITextRange_fnInRange, + ITextRange_fnInStory, + ITextRange_fnIsEqual, + ITextRange_fnSelect, + ITextRange_fnStartOf, + ITextRange_fnEndOf, + ITextRange_fnMove, + ITextRange_fnMoveStart, + ITextRange_fnMoveEnd, + ITextRange_fnMoveWhile, + ITextRange_fnMoveStartWhile, + ITextRange_fnMoveEndWhile, + ITextRange_fnMoveUntil, + ITextRange_fnMoveStartUntil, + ITextRange_fnMoveEndUntil, + ITextRange_fnFindText, + ITextRange_fnFindTextStart, + ITextRange_fnFindTextEnd, + ITextRange_fnDelete, + ITextRange_fnCut, + ITextRange_fnCopy, + ITextRange_fnPaste, + ITextRange_fnCanPaste, + ITextRange_fnCanEdit, + ITextRange_fnChangeCase, + ITextRange_fnGetPoint, + ITextRange_fnSetPoint, + ITextRange_fnScrollIntoView, + ITextRange_fnGetEmbeddedObject +}; +/* ITextRange interface */ + static HRESULT WINAPI ITextDocument_fnQueryInterface(ITextDocument* me, REFIID riid, void** ppvObject) @@ -634,13 +1364,48 @@ ITextDocument_fnRedo(ITextDocument* me, LONG Count, LONG* prop) return E_NOTIMPL; } +static HRESULT CreateITextRange(IRichEditOleImpl *reOle, LONG start, LONG end, ITextRange** ppRange) +{ + ITextRangeImpl *txtRge = heap_alloc(sizeof(ITextRangeImpl)); + + if (!txtRge) + return E_OUTOFMEMORY; + txtRge->ITextRange_iface.lpVtbl = &trvt; + txtRge->ref = 1; + txtRge->reOle = reOle; + txtRge->start = start; + txtRge->end = end; + list_add_head(&reOle->rangelist, &txtRge->entry); + *ppRange = &txtRge->ITextRange_iface; + return S_OK; +} + static HRESULT WINAPI ITextDocument_fnRange(ITextDocument* me, LONG cp1, LONG cp2, ITextRange** ppRange) { IRichEditOleImpl *This = impl_from_ITextDocument(me); - FIXME("stub %p\n",This); - return E_NOTIMPL; + const int len = ME_GetTextLength(This->editor) + 1; + + TRACE("%p %p %d %d\n", This, ppRange, cp1, cp2); + if (!ppRange) + return E_INVALIDARG; + + cp1 = max(cp1, 0); + cp2 = max(cp2, 0); + cp1 = min(cp1, len); + cp2 = min(cp2, len); + if (cp1 > cp2) + { + LONG tmp; + tmp = cp1; + cp1 = cp2; + cp2 = tmp; + } + if (cp1 == len) + cp1 = cp2 = len - 1; + + return CreateITextRange(This, cp1, cp2, ppRange); } static HRESULT WINAPI @@ -771,11 +1536,34 @@ static HRESULT WINAPI ITextSelection_fnInvoke( static HRESULT WINAPI ITextSelection_fnGetText(ITextSelection *me, BSTR *pbstr) { ITextSelectionImpl *This = impl_from_ITextSelection(me); + ME_Cursor *start = NULL, *end = NULL; + int nChars, endOfs; + BOOL bEOP; + if (!This->reOle) return CO_E_RELEASED; + TRACE("%p\n", pbstr); + if (!pbstr) + return E_INVALIDARG; - FIXME("not implemented\n"); - return E_NOTIMPL; + ME_GetSelection(This->reOle->editor, &start, &end); + endOfs = ME_GetCursorOfs(end); + nChars = endOfs - ME_GetCursorOfs(start); + if (!nChars) + { + *pbstr = NULL; + return S_OK; + } + + *pbstr = SysAllocStringLen(NULL, nChars); + if (!*pbstr) + return E_OUTOFMEMORY; + + bEOP = (end->pRun->next->type == diTextEnd && endOfs > ME_GetTextLength(This->reOle->editor)); + ME_GetTextW(This->reOle->editor, *pbstr, nChars, start, nChars, FALSE, bEOP); + TRACE("%s\n", wine_dbgstr_w(*pbstr)); + + return S_OK; } static HRESULT WINAPI ITextSelection_fnSetText(ITextSelection *me, BSTR bstr) @@ -791,11 +1579,16 @@ static HRESULT WINAPI ITextSelection_fnSetText(ITextSelection *me, BSTR bstr) static HRESULT WINAPI ITextSelection_fnGetChar(ITextSelection *me, LONG *pch) { ITextSelectionImpl *This = impl_from_ITextSelection(me); + ME_Cursor *start = NULL, *end = NULL; + if (!This->reOle) return CO_E_RELEASED; + TRACE("%p\n", pch); + if (!pch) + return E_INVALIDARG; - FIXME("not implemented\n"); - return E_NOTIMPL; + ME_GetSelection(This->reOle->editor, &start, &end); + return range_GetChar(This->reOle->editor, start, pch); } static HRESULT WINAPI ITextSelection_fnSetChar(ITextSelection *me, LONG ch) @@ -841,11 +1634,15 @@ static HRESULT WINAPI ITextSelection_fnSetFormattedText(ITextSelection *me, ITex static HRESULT WINAPI ITextSelection_fnGetStart(ITextSelection *me, LONG *pcpFirst) { ITextSelectionImpl *This = impl_from_ITextSelection(me); + LONG lim; if (!This->reOle) return CO_E_RELEASED; - FIXME("not implemented\n"); - return E_NOTIMPL; + if (!pcpFirst) + return E_INVALIDARG; + ME_GetSelectionOfs(This->reOle->editor, pcpFirst, &lim); + TRACE("%d\n", *pcpFirst); + return S_OK; } static HRESULT WINAPI ITextSelection_fnSetStart(ITextSelection *me, LONG cpFirst) @@ -861,11 +1658,15 @@ static HRESULT WINAPI ITextSelection_fnSetStart(ITextSelection *me, LONG cpFirst static HRESULT WINAPI ITextSelection_fnGetEnd(ITextSelection *me, LONG *pcpLim) { ITextSelectionImpl *This = impl_from_ITextSelection(me); + LONG first; if (!This->reOle) return CO_E_RELEASED; - FIXME("not implemented\n"); - return E_NOTIMPL; + if (!pcpLim) + return E_INVALIDARG; + ME_GetSelectionOfs(This->reOle->editor, &first, pcpLim); + TRACE("%d\n", *pcpLim); + return S_OK; } static HRESULT WINAPI ITextSelection_fnSetEnd(ITextSelection *me, LONG cpLim) @@ -941,11 +1742,16 @@ static HRESULT WINAPI ITextSelection_fnGetStoryType(ITextSelection *me, LONG *pV static HRESULT WINAPI ITextSelection_fnCollapse(ITextSelection *me, LONG bStart) { ITextSelectionImpl *This = impl_from_ITextSelection(me); + LONG start, end; + HRESULT hres; if (!This->reOle) return CO_E_RELEASED; - FIXME("not implemented\n"); - return E_NOTIMPL; + ME_GetSelectionOfs(This->reOle->editor, &start, &end); + hres = range_Collapse(bStart, &start, &end); + if (SUCCEEDED(hres)) + ME_SetSelection(This->reOle->editor, start, end); + return hres; } static HRESULT WINAPI ITextSelection_fnExpand(ITextSelection *me, LONG Unit, LONG *pDelta) @@ -1513,6 +2319,7 @@ LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj) } TRACE("Created %p\n",reo); *ppObj = reo; + list_init(&reo->rangelist); return 1; } @@ -1551,7 +2358,12 @@ void ME_GetOLEObjectSize(const ME_Context *c, ME_Run *run, SIZE *pSize) return; } - IOleObject_QueryInterface(run->ole_obj->poleobj, &IID_IDataObject, (void**)&ido); + if (IOleObject_QueryInterface(run->ole_obj->poleobj, &IID_IDataObject, (void**)&ido) != S_OK) + { + FIXME("Query Interface IID_IDataObject failed!\n"); + pSize->cx = pSize->cy = 0; + return; + } fmt.cfFormat = CF_BITMAP; fmt.ptd = NULL; fmt.dwAspect = DVASPECT_CONTENT; diff --git a/reactos/dll/win32/riched20/string.c b/reactos/dll/win32/riched20/string.c index 12e4ad741ee..44726b35941 100644 --- a/reactos/dll/win32/riched20/string.c +++ b/reactos/dll/win32/riched20/string.c @@ -125,8 +125,7 @@ ME_WordBreakProc(LPWSTR s, INT start, INT len, INT code) /* FIXME: Native also knows about punctuation */ TRACE("s==%s, start==%d, len==%d, code==%d\n", debugstr_wn(s, len), start, len, code); - /* convert number of bytes to number of characters. */ - len /= sizeof(WCHAR); + switch (code) { case WB_ISDELIMITER: @@ -154,7 +153,7 @@ int ME_CallWordBreakProc(ME_TextEditor *editor, WCHAR *str, INT len, INT start, INT code) { if (!editor->pfnWordBreak) { - return ME_WordBreakProc(str, start, len * sizeof(WCHAR), code); + return ME_WordBreakProc(str, start, len, code); } else if (!editor->bEmulateVersion10) { /* MSDN lied about the third parameter for EditWordBreakProc being the number * of characters, it is actually the number of bytes of the string. */ diff --git a/reactos/dll/win32/riched20/txtsrv.c b/reactos/dll/win32/riched20/txtsrv.c index fe4bf34eb7f..8cf4eddddc3 100644 --- a/reactos/dll/win32/riched20/txtsrv.c +++ b/reactos/dll/win32/riched20/txtsrv.c @@ -250,7 +250,7 @@ DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetText(ITextServices *iface, BSTR *p return E_OUTOFMEMORY; ME_CursorFromCharOfs(This->editor, 0, &start); - ME_GetTextW(This->editor, bstr, length, &start, INT_MAX, FALSE); + ME_GetTextW(This->editor, bstr, length, &start, INT_MAX, FALSE, FALSE); *pbstrText = bstr; } else { *pbstrText = NULL; diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 92385540fec..b3575a68a07 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -169,7 +169,7 @@ reactos/dll/win32/qmgrprxy # Synced to Wine-1.7.17 reactos/dll/win32/query # Synced to Wine-1.7.17 reactos/dll/win32/rasapi32 # Synced to Wine-1.7.27 reactos/dll/win32/resutils # Synced to Wine-1.7.17 -reactos/dll/win32/riched20 # Synced to Wine-1.7.17 +reactos/dll/win32/riched20 # Synced to Wine-1.7.27 reactos/dll/win32/riched32 # Synced to Wine-1.7.17 reactos/dll/win32/rpcrt4 # Synced to Wine-1.7.17 reactos/dll/win32/rsabase # Synced to Wine-1.7.17