diff --git a/dlls/riched20/clipboard.c b/dlls/riched20/clipboard.c index cf4fe4b37a9..d573369cc67 100644 --- a/dlls/riched20/clipboard.c +++ b/dlls/riched20/clipboard.c @@ -328,16 +328,24 @@ static const IDataObjectVtbl VT_DataObjectImpl = static HGLOBAL get_unicode_text(ME_TextEditor *editor, const CHARRANGE *lpchrg) { - int pars, len; + int pars = 0; + int len; WCHAR *data; HANDLE ret; + ME_Cursor start; + ME_DisplayItem *para; + + ME_CursorFromCharOfs(editor, lpchrg->cpMin, &start); + /* count paragraphs in range */ + para = start.pPara; + while((para = para->member.para.next_para) && + para->member.para.nCharOfs <= lpchrg->cpMax) + pars++; - pars = ME_CountParagraphsBetween(editor, lpchrg->cpMin, lpchrg->cpMax); len = lpchrg->cpMax-lpchrg->cpMin; ret = GlobalAlloc(GMEM_MOVEABLE, sizeof(WCHAR)*(len+pars+1)); data = GlobalLock(ret); - len = ME_GetTextW(editor, data, lpchrg->cpMin, len, TRUE); - data[len] = 0; + len = ME_GetTextW(editor, data, len+pars, &start, len, TRUE); GlobalUnlock(ret); return ret; } diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index d3ebdb18e76..79f6be20472 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -1549,8 +1549,10 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre if (newto > to + (editor->bEmulateVersion10 ? 1 : 0)) { WCHAR lastchar[3] = {'\0', '\0'}; int linebreakSize = editor->bEmulateVersion10 ? 2 : 1; + ME_Cursor linebreakCursor; - ME_GetTextW(editor, lastchar, newto - linebreakSize, linebreakSize, 0); + ME_CursorFromCharOfs(editor, newto - linebreakSize, &linebreakCursor); + ME_GetTextW(editor, lastchar, 2, &linebreakCursor, linebreakSize, 0); if (lastchar[0] == '\r' && (lastchar[1] == '\n' || lastchar[1] == '\0')) { ME_InternalDeleteText(editor, newto - linebreakSize, linebreakSize, FALSE); } @@ -1864,7 +1866,8 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH static int ME_GetTextEx(ME_TextEditor *editor, GETTEXTEX *ex, LPARAM pText) { - int nStart, nCount; /* in chars */ + int nChars; + ME_Cursor start; if (!ex->cb || !pText) return 0; @@ -1873,18 +1876,20 @@ static int ME_GetTextEx(ME_TextEditor *editor, GETTEXTEX *ex, LPARAM pText) if (ex->flags & GT_SELECTION) { - ME_GetSelectionOfs(editor, &nStart, &nCount); - nCount -= nStart; + int from, to; + int nStartCur = ME_GetSelectionOfs(editor, &from, &to); + start = editor->pCursors[nStartCur]; + nChars = to - from; } else { - nStart = 0; - nCount = 0x7fffffff; + ME_CursorFromCharOfs(editor, 0, &start); + nChars = INT_MAX; } if (ex->codepage == 1200) { - nCount = min(nCount, ex->cb / sizeof(WCHAR) - 1); - return ME_GetTextW(editor, (LPWSTR)pText, nStart, nCount, ex->flags & GT_USECRLF); + return ME_GetTextW(editor, (LPWSTR)pText, ex->cb / sizeof(WCHAR) - 1, + &start, nChars, ex->flags & GT_USECRLF); } else { @@ -1894,16 +1899,15 @@ static int ME_GetTextEx(ME_TextEditor *editor, GETTEXTEX *ex, LPARAM pText) occurs only in richedit 2.0 mode, in which line breaks have only one CR */ int crlfmul = (ex->flags & GT_USECRLF) ? 2 : 1; + DWORD buflen; LPWSTR buffer; - DWORD buflen = ex->cb; LRESULT rc; - DWORD flags = 0; - nCount = min(nCount, ex->cb - 1); - buffer = heap_alloc((crlfmul*nCount + 1) * sizeof(WCHAR)); + buflen = min(crlfmul * nChars, ex->cb - 1); + buffer = heap_alloc((buflen + 1) * sizeof(WCHAR)); - buflen = ME_GetTextW(editor, buffer, nStart, nCount, ex->flags & GT_USECRLF); - rc = WideCharToMultiByte(ex->codepage, flags, buffer, buflen+1, + nChars = ME_GetTextW(editor, buffer, buflen, &start, nChars, ex->flags & GT_USECRLF); + rc = WideCharToMultiByte(ex->codepage, 0, buffer, nChars + 1, (LPSTR)pText, ex->cb, ex->lpDefaultChar, ex->lpUsedDefChar); if (rc) rc--; /* do not count 0 terminator */ @@ -1913,13 +1917,18 @@ static int ME_GetTextEx(ME_TextEditor *editor, GETTEXTEX *ex, LPARAM pText) } static int ME_GetTextRange(ME_TextEditor *editor, WCHAR *strText, - int start, int nLen, BOOL unicode) + int nStart, int nLen, BOOL unicode) { + ME_Cursor start; + if (!strText) return 0; + ME_CursorFromCharOfs(editor, nStart, &start); if (unicode) { - return ME_GetTextW(editor, strText, start, nLen, 0); + return ME_GetTextW(editor, strText, INT_MAX, &start, nLen, 0); } else { + int nChars; WCHAR *p = ALLOC_N_OBJ(WCHAR, nLen+1); - int nChars = ME_GetTextW(editor, p, start, nLen, 0); + if (!p) return 0; + nChars = ME_GetTextW(editor, p, nLen, &start, nLen, 0); WideCharToMultiByte(CP_ACP, 0, p, nChars+1, (char *)strText, nLen+1, NULL, NULL); FREE_OBJ(p); @@ -4473,81 +4482,71 @@ void ME_SendOldNotify(ME_TextEditor *editor, int nCode) ITextHost_TxNotify(editor->texthost, nCode, NULL); } -int ME_CountParagraphsBetween(ME_TextEditor *editor, int from, int to) +/* Fill buffer with srcChars unicode characters from the start cursor. + * + * buffer: destination buffer + * buflen: length of buffer in characters excluding the NULL terminator. + * start: start of editor text to copy into buffer. + * srcChars: Number of characters to use from the editor text. + * bCRLF: if true, replaces all end of lines with \r\n pairs. + * + * returns the number of characters written excluding the NULL terminator. + * + * 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) { - ME_DisplayItem *item = ME_FindItemFwd(editor->pBuffer->pFirst, diParagraph); - int i = 0; - - while(item && item->member.para.next_para->member.para.nCharOfs <= from) - item = item->member.para.next_para; - if (!item) - return 0; - while(item && item->member.para.next_para->member.para.nCharOfs <= to) { - item = item->member.para.next_para; - i++; - } - return i; -} - - -int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, - int nChars, int bCRLF) -{ - ME_DisplayItem *pRun; - int nOffset, nWritten = 0; - WCHAR *pStart = buffer; - - ME_RunOfsFromCharOfs(editor, nStart, NULL, &pRun, &nOffset); + ME_DisplayItem *pRun, *pNextRun; + const WCHAR *pStart = buffer; + const WCHAR cr_lf[] = {'\r', '\n', 0}; + const WCHAR *str; + int nLen; /* bCRLF flag is only honored in 2.0 and up. 1.0 must always return text verbatim */ if (editor->bEmulateVersion10) bCRLF = 0; - while (nChars && pRun) + pRun = start->pRun; + assert(pRun); + pNextRun = ME_FindItemFwd(pRun, diRun); + + nLen = pRun->member.run.strText->nLen - start->nOffset; + str = pRun->member.run.strText->szData + start->nOffset; + + /* No '\r' is appended to the last paragraph. */ + while (srcChars && buflen && pNextRun) { - int nLen; + int nFlags = pRun->member.run.nFlags; - if (pRun->member.run.nFlags & MERF_ENDCELL && - pRun->member.run.nFlags & MERF_ENDPARA) + if (bCRLF && nFlags & MERF_ENDPARA && ~nFlags & MERF_ENDCELL) { - *buffer = '\t'; - nLen = 1; - } else if (pRun->member.run.nFlags & MERF_ENDPARA) { - if (!ME_FindItemFwd(pRun, diRun)) { - /* No '\r' is appended to the last paragraph. */ - nLen = 0; - } else if (bCRLF && nChars == 1) { - nLen = 0; - nChars = 0; - } else { - WCHAR cr_lf[] = {'\r', '\n', 0}; - WCHAR *szData; - - if (bCRLF) - { - nLen = 2; - szData = cr_lf; - } else { - nLen = pRun->member.run.strText->nLen; - szData = pRun->member.run.strText->szData; - } - nLen = min(nChars, nLen - nOffset); - CopyMemory(buffer, szData + nOffset, sizeof(WCHAR) * nLen); - } + if (buflen == 1) break; + /* FIXME: native fails to reduce srcChars here for WM_GETTEXT or + * EM_GETTEXTEX, however, this is done for copying text which + * also uses this function. */ + srcChars -= min(nLen, srcChars); + nLen = 2; + str = cr_lf; } else { - nLen = min(nChars, pRun->member.run.strText->nLen - nOffset); - CopyMemory(buffer, pRun->member.run.strText->szData + nOffset, - sizeof(WCHAR) * nLen); + nLen = min(nLen, srcChars); + srcChars -= nLen; } - nChars -= nLen; - nWritten += nLen; - buffer += nLen; - nOffset = 0; - pRun = ME_FindItemFwd(pRun, diRun); + nLen = min(nLen, buflen); + buflen -= nLen; + + CopyMemory(buffer, str, sizeof(WCHAR) * nLen); + + buffer += nLen; + + pRun = pNextRun; + pNextRun = ME_FindItemFwd(pRun, diRun); + + nLen = pRun->member.run.strText->nLen; + str = pRun->member.run.strText->szData; } *buffer = 0; - TRACE("nWritten=%d, actual=%d\n", nWritten, buffer-pStart); - return nWritten; + return buffer - pStart; } static BOOL ME_RegisterEditorClass(HINSTANCE hInstance) @@ -4790,7 +4789,9 @@ static BOOL ME_IsCandidateAnURL(ME_TextEditor *editor, int sel_min, int sel_max) LPWSTR bufferW = NULL; WCHAR bufW[32]; unsigned int i; + ME_Cursor sel_start; + ME_CursorFromCharOfs(editor, sel_min, &sel_start); if (sel_max == -1) sel_max = ME_GetTextLength(editor); assert(sel_min <= sel_max); for (i = 0; i < sizeof(prefixes) / sizeof(struct prefix_s); i++) @@ -4799,7 +4800,8 @@ static BOOL ME_IsCandidateAnURL(ME_TextEditor *editor, int sel_min, int sel_max) if (bufferW == NULL) { bufferW = heap_alloc((sel_max - sel_min + 1) * sizeof(WCHAR)); } - ME_GetTextW(editor, bufferW, sel_min, min(sel_max - sel_min, lstrlenA(prefixes[i].text)), 0); + ME_GetTextW(editor, bufferW, sel_max - sel_min, &sel_start, + lstrlenA(prefixes[i].text), 0); MultiByteToWideChar(CP_ACP, 0, prefixes[i].text, -1, bufW, 32); if (!lstrcmpW(bufW, bufferW)) { diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index c0752a3c224..aa8bacd6cd9 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -169,7 +169,6 @@ BOOL ME_ArrowKey(ME_TextEditor *ed, int nVKey, BOOL extend, BOOL ctrl); int ME_GetCursorOfs(const ME_Cursor *cursor); int ME_GetSelectionOfs(ME_TextEditor *editor, int *from, int *to); int ME_GetSelection(ME_TextEditor *editor, ME_Cursor **from, ME_Cursor **to); -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); @@ -242,7 +241,8 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10); LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode, HRESULT* phresult); void ME_SendOldNotify(ME_TextEditor *editor, int nCode); -int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, BOOL bCRLF); +int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, + const ME_Cursor *start, int srcChars, BOOL bCRLF); void ME_RTFCharAttrHook(struct _RTF_Info *info); void ME_RTFParAttrHook(struct _RTF_Info *info); void ME_RTFTblAttrHook(struct _RTF_Info *info); diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h index a4af8fe9c0c..c3f59b9ec9b 100644 --- a/dlls/riched20/editstr.h +++ b/dlls/riched20/editstr.h @@ -29,6 +29,7 @@ #include #include #include +#include #define COBJMACROS #define NONAMELESSUNION diff --git a/dlls/riched20/table.c b/dlls/riched20/table.c index 10e276a92d6..de5de6cafb0 100644 --- a/dlls/riched20/table.c +++ b/dlls/riched20/table.c @@ -123,8 +123,8 @@ ME_DisplayItem* ME_InsertTableRowStartAtParagraph(ME_TextEditor *editor, ME_DisplayItem* ME_InsertTableCellFromCursor(ME_TextEditor *editor) { ME_DisplayItem *para; - WCHAR cr = '\r'; - ME_String *eol_str = ME_MakeStringN(&cr, 1); + WCHAR tab = '\t'; + ME_String *eol_str = ME_MakeStringN(&tab, 1); para = ME_InsertEndParaFromCursor(editor, 0, eol_str, MEPF_CELL); return para; } diff --git a/dlls/riched20/txtsrv.c b/dlls/riched20/txtsrv.c index 1df9d02639a..605d38d1a95 100644 --- a/dlls/riched20/txtsrv.c +++ b/dlls/riched20/txtsrv.c @@ -292,12 +292,14 @@ HRESULT WINAPI fnTextSrv_TxGetText(ITextServices *iface, length = ME_GetTextLength(This->editor); if (length) { + ME_Cursor start; BSTR bstr; bstr = SysAllocStringByteLen(NULL, length * sizeof(WCHAR)); if (bstr == NULL) return E_OUTOFMEMORY; - ME_GetTextW(This->editor, bstr , 0, length, FALSE); + ME_CursorFromCharOfs(This->editor, 0, &start); + ME_GetTextW(This->editor, bstr, length, &start, INT_MAX, FALSE); *pbstrText = bstr; } else { *pbstrText = NULL;