From 8552a1297ecc90d71c8e922abf31e215c8f465cc Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sat, 26 Apr 2014 16:54:06 +0000 Subject: [PATCH] [RICHED20] * Sync with Wine 1.7.17. CORE-8080 svn path=/trunk/; revision=62982 --- reactos/dll/win32/riched20/CMakeLists.txt | 2 +- reactos/dll/win32/riched20/caret.c | 81 +++++-- reactos/dll/win32/riched20/editor.c | 240 +++++++++++++------ reactos/dll/win32/riched20/editor.h | 12 +- reactos/dll/win32/riched20/editstr.h | 12 + reactos/dll/win32/riched20/list.c | 34 +-- reactos/dll/win32/riched20/msvc-thiscall.c | 2 +- reactos/dll/win32/riched20/msvc.h | 2 +- reactos/dll/win32/riched20/paint.c | 7 +- reactos/dll/win32/riched20/reader.c | 18 +- reactos/dll/win32/riched20/richole.c | 5 +- reactos/dll/win32/riched20/row.c | 1 + reactos/dll/win32/riched20/rtf.h | 2 +- reactos/dll/win32/riched20/run.c | 137 +++++++---- reactos/dll/win32/riched20/string.c | 21 +- reactos/dll/win32/riched20/style.c | 2 + reactos/dll/win32/riched20/table.c | 2 +- reactos/dll/win32/riched20/txtsrv.c | 6 +- reactos/dll/win32/riched20/wrap.c | 255 ++++++++++++++++++++- reactos/dll/win32/riched20/writer.c | 1 + reactos/media/doc/README.WINE | 2 +- 21 files changed, 661 insertions(+), 183 deletions(-) diff --git a/reactos/dll/win32/riched20/CMakeLists.txt b/reactos/dll/win32/riched20/CMakeLists.txt index 339445459ec..8491fdc1d07 100644 --- a/reactos/dll/win32/riched20/CMakeLists.txt +++ b/reactos/dll/win32/riched20/CMakeLists.txt @@ -40,6 +40,6 @@ list(APPEND ADDITIONAL_SOURCE add_library(riched20 SHARED ${SOURCE} ${ADDITIONAL_SOURCE}) set_module_type(riched20 win32dll) target_link_libraries(riched20 wine uuid) -add_importlibs(riched20 ole32 oleaut32 imm32 user32 gdi32 msvcrt kernel32 ntdll) +add_importlibs(riched20 ole32 oleaut32 usp10 imm32 user32 gdi32 msvcrt kernel32 ntdll) add_pch(riched20 editor.h SOURCE) add_cd_file(TARGET riched20 DESTINATION reactos/system32 FOR all) diff --git a/reactos/dll/win32/riched20/caret.c b/reactos/dll/win32/riched20/caret.c index 07e042b8378..90b30a2f576 100644 --- a/reactos/dll/win32/riched20/caret.c +++ b/reactos/dll/win32/riched20/caret.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ + #include "editor.h" WINE_DEFAULT_DEBUG_CHANNEL(richedit); @@ -55,7 +56,19 @@ int ME_GetSelectionOfs(ME_TextEditor *editor, int *from, int *to) int ME_GetSelection(ME_TextEditor *editor, ME_Cursor **from, ME_Cursor **to) { - if (ME_GetCursorOfs(&editor->pCursors[0]) < ME_GetCursorOfs(&editor->pCursors[1])) + int from_ofs = ME_GetCursorOfs( &editor->pCursors[0] ); + int to_ofs = ME_GetCursorOfs( &editor->pCursors[1] ); + BOOL swap = (from_ofs > to_ofs); + + if (from_ofs == to_ofs) + { + /* If cursor[0] is at the beginning of a run and cursor[1] at the end + of the prev run then we need to swap. */ + if (editor->pCursors[0].nOffset < editor->pCursors[1].nOffset) + swap = TRUE; + } + + if (!swap) { *from = &editor->pCursors[0]; *to = &editor->pCursors[1]; @@ -127,7 +140,6 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to) ME_SetCursorToStart(editor, &editor->pCursors[1]); ME_SetCursorToEnd(editor, &editor->pCursors[0]); ME_InvalidateSelection(editor); - ME_ClearTempStyle(editor); return len + 1; } @@ -150,7 +162,6 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to) editor->pCursors[1] = editor->pCursors[0]; ME_Repaint(editor); } - ME_ClearTempStyle(editor); return end; } @@ -179,7 +190,6 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to) ME_SetCursorToEnd(editor, &editor->pCursors[0]); editor->pCursors[1] = editor->pCursors[0]; ME_InvalidateSelection(editor); - ME_ClearTempStyle(editor); return len; } @@ -283,13 +293,15 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, int nChars, BOOL bForce) { ME_Cursor c = *start; - int nOfs = ME_GetCursorOfs(start); + int nOfs = ME_GetCursorOfs(start), text_len = ME_GetTextLength( editor ); int shift = 0; int totalChars = nChars; ME_DisplayItem *start_para; + BOOL delete_all = FALSE; /* Prevent deletion past last end of paragraph run. */ - nChars = min(nChars, ME_GetTextLength(editor) - nOfs); + nChars = min(nChars, text_len - nOfs); + if (nChars == text_len) delete_all = TRUE; start_para = c.pPara; if (!bForce) @@ -423,6 +435,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, continue; } } + if (delete_all) ME_SetDefaultParaFormat( start_para->member.para.pFmt ); return TRUE; } @@ -526,7 +539,7 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, ME_InternalInsertTextFromCursor(editor, nCursor, &tab, 1, style, MERF_TAB); pos++; } else { /* handle EOLs */ - ME_DisplayItem *tp, *end_run; + ME_DisplayItem *tp, *end_run, *run, *prev; ME_Style *tmp_style; int eol_len = 0; @@ -560,17 +573,43 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, } p = &editor->pCursors[nCursor]; - if (p->nOffset) - ME_SplitRunSimple(editor, p); + + if (p->nOffset == p->pRun->member.run.len) + { + run = ME_FindItemFwd( p->pRun, diRun ); + if (!run) run = p->pRun; + } + else + { + if (p->nOffset) ME_SplitRunSimple(editor, p); + run = p->pRun; + } + tmp_style = ME_GetInsertStyle(editor, nCursor); /* ME_SplitParagraph increases style refcount */ - tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, eol_str, eol_len, 0); - p->pRun = ME_FindItemFwd(tp, diRun); - p->pPara = tp; + tp = ME_SplitParagraph(editor, run, run->member.run.style, eol_str, eol_len, 0); + end_run = ME_FindItemBack(tp, diRun); ME_ReleaseStyle(end_run->member.run.style); end_run->member.run.style = tmp_style; - p->nOffset = 0; + + /* Move any cursors that were at the end of the previous run to the beginning of the new para */ + prev = ME_FindItemBack( end_run, diRun ); + if (prev) + { + int i; + for (i = 0; i < editor->nCursors; i++) + { + if (editor->pCursors[i].pRun == prev && + editor->pCursors[i].nOffset == prev->member.run.len) + { + editor->pCursors[i].pPara = tp; + editor->pCursors[i].pRun = run; + editor->pCursors[i].nOffset = 0; + } + } + } + } } len -= pos - str; @@ -865,7 +904,7 @@ static ME_DisplayItem* ME_FindPixelPosInTableRow(int x, int y, } static BOOL ME_FindRunInRow(ME_TextEditor *editor, ME_DisplayItem *pRow, - int x, ME_Cursor *cursor, int *pbCaretAtEnd) + int x, ME_Cursor *cursor, BOOL *pbCaretAtEnd) { ME_DisplayItem *pNext, *pLastRun; ME_Row *row = &pRow->member.row; @@ -925,7 +964,7 @@ static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y, y -= editor->rcFormat.top; if (is_eol) - *is_eol = 0; + *is_eol = FALSE; /* find paragraph */ for (; p != editor->pBuffer->pLast; p = p->member.para.next_para) @@ -1070,8 +1109,7 @@ static void ME_ExtendAnchorSelection(ME_TextEditor *editor) void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum) { ME_Cursor tmp_cursor; - int is_selection = 0; - BOOL is_shift; + BOOL is_selection = FALSE, is_shift; editor->nUDArrowX = -1; @@ -1128,7 +1166,6 @@ void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum) ME_InvalidateSelection(editor); ITextHost_TxShowCaret(editor->texthost, FALSE); ME_ShowCaret(editor); - ME_ClearTempStyle(editor); ME_SendSelChange(editor); } @@ -1447,7 +1484,9 @@ void ME_DeleteSelection(ME_TextEditor *editor) { int from, to; int nStartCursor = ME_GetSelectionOfs(editor, &from, &to); + int nEndCursor = nStartCursor ^ 1; ME_DeleteTextAtCursor(editor, nStartCursor, to - from); + editor->pCursors[nEndCursor] = editor->pCursors[nStartCursor]; } ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor) @@ -1495,14 +1534,14 @@ ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl) ME_CheckCharOffsets(editor); switch(nVKey) { case VK_LEFT: - editor->bCaretAtEnd = 0; + editor->bCaretAtEnd = FALSE; if (ctrl) success = ME_MoveCursorWords(editor, &tmp_curs, -1); else success = ME_MoveCursorChars(editor, &tmp_curs, -1); break; case VK_RIGHT: - editor->bCaretAtEnd = 0; + editor->bCaretAtEnd = FALSE; if (ctrl) success = ME_MoveCursorWords(editor, &tmp_curs, +1); else @@ -1525,7 +1564,7 @@ ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl) ME_ArrowCtrlHome(editor, &tmp_curs); else ME_ArrowHome(editor, &tmp_curs); - editor->bCaretAtEnd = 0; + editor->bCaretAtEnd = FALSE; break; } case VK_END: diff --git a/reactos/dll/win32/riched20/editor.c b/reactos/dll/win32/riched20/editor.c index e63b92877a5..7ccdd494354 100644 --- a/reactos/dll/win32/riched20/editor.c +++ b/reactos/dll/win32/riched20/editor.c @@ -245,13 +245,13 @@ static const WCHAR REListBox20W[] = {'R','E','L','i','s','t','B','o','x','2','0' static const WCHAR REComboBox20W[] = {'R','E','C','o','m','b','o','B','o','x','2','0','W', 0}; static HCURSOR hLeft; -int me_debug = 0; +BOOL me_debug = FALSE; HANDLE me_heap = NULL; static BOOL ME_ListBoxRegistered = FALSE; static BOOL ME_ComboBoxRegistered = FALSE; -static inline int is_version_nt(void) +static inline BOOL is_version_nt(void) { return !(GetVersion() & 0x80000000); } @@ -284,6 +284,9 @@ static LRESULT ME_StreamInText(ME_TextEditor *editor, DWORD dwFormat, ME_InStrea WCHAR *pText; LRESULT total_bytes_read = 0; BOOL is_read = FALSE; + DWORD cp = CP_ACP, copy = 0; + char conv_buf[4 + STREAMIN_BUFFER_SIZE]; /* up to 4 additional UTF-8 bytes */ + static const char bom_utf8[] = {0xEF, 0xBB, 0xBF}; TRACE("%08x %p\n", dwFormat, stream); @@ -305,8 +308,7 @@ static LRESULT ME_StreamInText(ME_TextEditor *editor, DWORD dwFormat, ME_InStrea if (!(dwFormat & SF_UNICODE)) { char * buf = stream->buffer; - DWORD size = stream->dwSize; - DWORD cp = CP_ACP; + DWORD size = stream->dwSize, end; if (!is_read) { @@ -319,8 +321,56 @@ static LRESULT ME_StreamInText(ME_TextEditor *editor, DWORD dwFormat, ME_InStrea } } - nWideChars = MultiByteToWideChar(cp, 0, buf, size, wszText, STREAMIN_BUFFER_SIZE); + if (cp == CP_UTF8) + { + if (copy) + { + memcpy(conv_buf + copy, buf, size); + buf = conv_buf; + size += copy; + } + end = size; + while ((buf[end-1] & 0xC0) == 0x80) + { + --end; + --total_bytes_read; /* strange, but seems to match windows */ + } + if (buf[end-1] & 0x80) + { + DWORD need = 0; + if ((buf[end-1] & 0xE0) == 0xC0) + need = 1; + if ((buf[end-1] & 0xF0) == 0xE0) + need = 2; + if ((buf[end-1] & 0xF8) == 0xF0) + need = 3; + + if (size - end >= need) + { + /* we have enough bytes for this sequence */ + end = size; + } + else + { + /* need more bytes, so don't transcode this sequence */ + --end; + } + } + } + else + end = size; + + nWideChars = MultiByteToWideChar(cp, 0, buf, end, wszText, STREAMIN_BUFFER_SIZE); pText = wszText; + + if (cp == CP_UTF8) + { + if (end != size) + { + memcpy(conv_buf, buf + end, size - end); + copy = size - end; + } + } } else { @@ -1146,11 +1196,8 @@ static BOOL ME_RTFInsertOleObject(RTF_Info *info, HENHMETAFILE hemf, HBITMAP hbm } 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 && @@ -1581,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, 0); + ME_GetTextW(editor, lastchar, 2, &linebreakCursor, linebreakSize, FALSE); if (lastchar[0] == '\r' && (lastchar[1] == '\n' || lastchar[1] == '\0')) { ME_InternalDeleteText(editor, &linebreakCursor, linebreakSize, FALSE); } @@ -1916,7 +1963,7 @@ static int ME_GetTextEx(ME_TextEditor *editor, GETTEXTEX *ex, LPARAM pText) ME_SetCursorToStart(editor, &start); nChars = INT_MAX; } - if (ex->codepage == 1200) + if (ex->codepage == CP_UNICODE) { return ME_GetTextW(editor, (LPWSTR)pText, ex->cb / sizeof(WCHAR) - 1, &start, nChars, ex->flags & GT_USECRLF); @@ -1951,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, 0); + return ME_GetTextW(editor, strText, INT_MAX, start, nLen, FALSE); } else { int nChars; WCHAR *p = ALLOC_N_OBJ(WCHAR, nLen+1); if (!p) return 0; - nChars = ME_GetTextW(editor, p, nLen, start, nLen, 0); + nChars = ME_GetTextW(editor, p, nLen, start, nLen, FALSE); WideCharToMultiByte(CP_ACP, 0, p, nChars+1, (char *)strText, nLen+1, NULL, NULL); FREE_OBJ(p); @@ -1964,6 +2011,22 @@ static int ME_GetTextRange(ME_TextEditor *editor, WCHAR *strText, } } +static int handle_EM_EXSETSEL( ME_TextEditor *editor, int to, int from ) +{ + int end; + + TRACE("%d - %d\n", to, from ); + + ME_InvalidateSelection( editor ); + end = ME_SetSelection( editor, to, from ); + ME_InvalidateSelection( editor ); + ITextHost_TxShowCaret( editor->texthost, FALSE ); + ME_ShowCaret( editor ); + ME_SendSelChange( editor ); + + return end; +} + typedef struct tagME_GlobalDestStruct { HGLOBAL hData; @@ -2331,7 +2394,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) case 'A': if (ctrl_is_down) { - ME_SetSelection(editor, 0, -1); + handle_EM_EXSETSEL( editor, 0, -1 ); return TRUE; } break; @@ -2790,6 +2853,8 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) ed->horz_si.nPage = 0; ed->horz_si.nPos = 0; + ed->wheel_remain = 0; + OleInitialize(NULL); return ed; @@ -2857,6 +2922,23 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) return TRUE; } +static inline int get_default_line_height( ME_TextEditor *editor ) +{ + int height = 0; + + if (editor->pBuffer && editor->pBuffer->pDefaultStyle) + height = editor->pBuffer->pDefaultStyle->tm.tmHeight; + if (height <= 0) height = 24; + + return height; +} + +static inline int calc_wheel_change( int *remain, int amount_per_click ) +{ + int change = amount_per_click * (float)*remain / WHEEL_DELTA; + *remain -= WHEEL_DELTA * change / amount_per_click; + return change; +} static const char * const edit_messages[] = { "EM_GETSEL", @@ -3074,11 +3156,14 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, return ME_StreamOut(editor, wParam, (EDITSTREAM *)lParam); case WM_GETDLGCODE: { - UINT code = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS|DLGC_HASSETSEL; + UINT code = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS; + if (lParam) editor->bDialogMode = TRUE; if (editor->styleFlags & ES_MULTILINE) code |= DLGC_WANTMESSAGE; + if (!(editor->styleFlags & ES_SAVESEL)) + code |= DLGC_HASSETSEL; return code; } case EM_EMPTYUNDOBUFFER: @@ -3194,12 +3279,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } case EM_SETSEL: { - ME_InvalidateSelection(editor); - ME_SetSelection(editor, wParam, lParam); - ME_InvalidateSelection(editor); - ITextHost_TxShowCaret(editor->texthost, FALSE); - ME_ShowCaret(editor); - ME_SendSelChange(editor); + handle_EM_EXSETSEL( editor, wParam, lParam ); return 0; } case EM_SETSCROLLPOS: @@ -3223,19 +3303,9 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } case EM_EXSETSEL: { - int end; CHARRANGE range = *(CHARRANGE *)lParam; - TRACE("EM_EXSETSEL (%d,%d)\n", range.cpMin, range.cpMax); - - ME_InvalidateSelection(editor); - end = ME_SetSelection(editor, range.cpMin, range.cpMax); - ME_InvalidateSelection(editor); - ITextHost_TxShowCaret(editor->texthost, FALSE); - ME_ShowCaret(editor); - ME_SendSelChange(editor); - - return end; + return handle_EM_EXSETSEL( editor, range.cpMin, range.cpMax ); } case EM_SHOWSCROLLBAR: { @@ -3274,11 +3344,11 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, { LPWSTR wszText; SETTEXTEX *pStruct = (SETTEXTEX *)wParam; - size_t len = 0; - int from, to; + int from, to, len; ME_Style *style; - BOOL bRtf, bUnicode, bSelection; + BOOL bRtf, bUnicode, bSelection, bUTF8; int oldModify = editor->nModifyStep; + static const char utf8_bom[] = {0xef, 0xbb, 0xbf}; if (!pStruct) return 0; @@ -3286,7 +3356,8 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, * we know it isn't unicode. */ bRtf = (lParam && (!strncmp((char *)lParam, "{\\rtf", 5) || !strncmp((char *)lParam, "{\\urtf", 6))); - bUnicode = !bRtf && pStruct->codepage == 1200; + bUnicode = !bRtf && pStruct->codepage == CP_UNICODE; + bUTF8 = (lParam && (!strncmp((char *)lParam, utf8_bom, 3))); TRACE("EM_SETTEXTEX - %s, flags %d, cp %d\n", bUnicode ? debugstr_w((LPCWSTR)lParam) : debugstr_a((LPCSTR)lParam), @@ -3312,11 +3383,15 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, len = lParam ? strlen((char *)lParam) : 0; } } else { - /* FIXME: make use of pStruct->codepage in the to unicode translation */ - wszText = lParam ? ME_ToUnicode(bUnicode, (void *)lParam) : NULL; - len = wszText ? lstrlenW(wszText) : 0; - ME_InsertTextFromCursor(editor, 0, wszText, len, style); - ME_EndToUnicode(bUnicode, wszText); + if (bUTF8 && !bUnicode) { + wszText = ME_ToUnicode(CP_UTF8, (void *)(lParam+3), &len); + ME_InsertTextFromCursor(editor, 0, wszText, len, style); + ME_EndToUnicode(CP_UTF8, wszText); + } else { + wszText = ME_ToUnicode(pStruct->codepage, (void *)lParam, &len); + ME_InsertTextFromCursor(editor, 0, wszText, len, style); + ME_EndToUnicode(pStruct->codepage, wszText); + } } if (bSelection) { @@ -3487,7 +3562,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, { if (!(editor->styleFlags & ES_MULTILINE)) return FALSE; - ME_ScrollDown(editor, lParam * 8); /* FIXME follow the original */ + ME_ScrollDown( editor, lParam * get_default_line_height( editor ) ); return TRUE; } case WM_CLEAR: @@ -3503,8 +3578,9 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, { int from, to, nStartCursor; ME_Style *style; - LPWSTR wszText = lParam ? ME_ToUnicode(unicode, (void *)lParam) : NULL; - size_t len = wszText ? lstrlenW(wszText) : 0; + int len = 0; + LONG codepage = unicode ? CP_UNICODE : CP_ACP; + LPWSTR wszText = ME_ToUnicode(codepage, (void *)lParam, &len); TRACE("EM_REPLACESEL - %s\n", debugstr_w(wszText)); nStartCursor = ME_GetSelectionOfs(editor, &from, &to); @@ -3519,7 +3595,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, */ if (len>0 && wszText[len-1] == '\n') ME_ClearTempStyle(editor); - ME_EndToUnicode(unicode, wszText); + ME_EndToUnicode(codepage, wszText); ME_CommitUndo(editor); ME_UpdateSelectionLinkAttribute(editor); if (!wParam) @@ -3574,9 +3650,11 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } else { - LPWSTR wszText = ME_ToUnicode(unicode, (void *)lParam); + int textLen; + LONG codepage = unicode ? CP_UNICODE : CP_ACP; + LPWSTR wszText = ME_ToUnicode(codepage, (void *)lParam, &textLen); TRACE("WM_SETTEXT - %s\n", debugstr_w(wszText)); /* debugstr_w() */ - if (lstrlenW(wszText) > 0) + if (textLen > 0) { int len = -1; @@ -3591,7 +3669,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } ME_InsertTextFromCursor(editor, 0, wszText, len, editor->pBuffer->pDefaultStyle); } - ME_EndToUnicode(unicode, wszText); + ME_EndToUnicode(codepage, wszText); } } else @@ -3639,7 +3717,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, /* CR/LF conversion required in 2.0 mode, verbatim in 1.0 mode */ how.flags = GTL_CLOSE | (editor->bEmulateVersion10 ? 0 : GTL_USECRLF) | GTL_NUMCHARS; - how.codepage = unicode ? 1200 : CP_ACP; + how.codepage = unicode ? CP_UNICODE : CP_ACP; return ME_GetTextLengthEx(editor, &how); } case EM_GETTEXTLENGTHEX: @@ -3649,7 +3727,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, GETTEXTEX ex; ex.cb = wParam * (unicode ? sizeof(WCHAR) : sizeof(CHAR)); ex.flags = GT_USECRLF; - ex.codepage = unicode ? 1200 : CP_ACP; + ex.codepage = unicode ? CP_UNICODE : CP_ACP; ex.lpDefaultChar = NULL; ex.lpUsedDefChar = NULL; return ME_GetTextEx(editor, &ex, lParam); @@ -3948,6 +4026,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } case WM_CREATE: { + void *text = NULL; INT max; ME_SetDefaultFormatRect(editor); @@ -3973,6 +4052,29 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } } + if (lParam) + { + text = (unicode ? (void*)((CREATESTRUCTW*)lParam)->lpszName + : (void*)((CREATESTRUCTA*)lParam)->lpszName); + } + if (text) + { + WCHAR *textW; + int len; + LONG codepage = unicode ? CP_UNICODE : CP_ACP; + textW = ME_ToUnicode(codepage, text, &len); + if (!(editor->styleFlags & ES_MULTILINE)) + { + len = 0; + while(textW[len] != '\0' && textW[len] != '\r' && textW[len] != '\n') + len++; + } + ME_InsertTextFromCursor(editor, 0, textW, len, editor->pBuffer->pDefaultStyle); + ME_EndToUnicode(codepage, textW); + ME_SetCursorToStart(editor, &editor->pCursors[0]); + ME_SetCursorToStart(editor, &editor->pCursors[1]); + } + ME_CommitUndo(editor); ME_WrapMarkedParagraphs(editor); ME_MoveCaret(editor); @@ -4047,6 +4149,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case WM_KILLFOCUS: ME_CommitUndo(editor); /* End coalesced undos for typed characters */ editor->bHaveFocus = FALSE; + editor->wheel_remain = 0; ME_HideCaret(editor); ME_SendOldNotify(editor, EN_KILLFOCUS); return 0; @@ -4133,14 +4236,9 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case WM_VSCROLL: { int origNPos; - int lineHeight; + int lineHeight = get_default_line_height( editor ); origNPos = editor->vert_si.nPos; - lineHeight = 24; - - if (editor->pBuffer && editor->pBuffer->pDefaultStyle) - lineHeight = editor->pBuffer->pDefaultStyle->tm.tmHeight; - if (lineHeight <= 0) lineHeight = 24; switch(LOWORD(wParam)) { @@ -4180,8 +4278,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } case WM_MOUSEWHEEL: { - int gcWheelDelta; - UINT pulScrollLines; + int delta; BOOL ctrl_is_down; if ((editor->nEventMask & ENM_MOUSEEVENTS) && @@ -4190,9 +4287,16 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, ctrl_is_down = GetKeyState(VK_CONTROL) & 0x8000; - gcWheelDelta = GET_WHEEL_DELTA_WPARAM(wParam); + delta = GET_WHEEL_DELTA_WPARAM(wParam); + + /* if scrolling changes direction, ignore left overs */ + if ((delta < 0 && editor->wheel_remain < 0) || + (delta > 0 && editor->wheel_remain > 0)) + editor->wheel_remain += delta; + else + editor->wheel_remain = delta; - if (abs(gcWheelDelta) >= WHEEL_DELTA) + if (editor->wheel_remain) { if (ctrl_is_down) { int numerator; @@ -4202,14 +4306,18 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } else { numerator = editor->nZoomNumerator * 100 / editor->nZoomDenominator; } - numerator = numerator + (gcWheelDelta / WHEEL_DELTA) * 10; + numerator += calc_wheel_change( &editor->wheel_remain, 10 ); if (numerator >= 10 && numerator <= 500) ME_SetZoom(editor, numerator, 100); } else { - SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0); - /* FIXME follow the original */ - if (pulScrollLines) - ME_ScrollDown(editor,pulScrollLines * (-gcWheelDelta / WHEEL_DELTA) * 8); + UINT max_lines = 3; + int lines = 0; + + SystemParametersInfoW( SPI_GETWHEELSCROLLLINES, 0, &max_lines, 0 ); + if (max_lines) + lines = calc_wheel_change( &editor->wheel_remain, (int)max_lines ); + if (lines) + ME_ScrollDown( editor, -lines * get_default_line_height( editor ) ); } } break; @@ -4617,7 +4725,7 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen, int nLen; /* bCRLF flag is only honored in 2.0 and up. 1.0 must always return text verbatim */ - if (editor->bEmulateVersion10) bCRLF = 0; + if (editor->bEmulateVersion10) bCRLF = FALSE; pRun = start->pRun; assert(pRun); @@ -4902,7 +5010,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, 0); + ME_GetTextW(editor, bufferW, MAX_PREFIX_LEN, start, nChars, 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 0521522035e..4c19c49620e 100644 --- a/reactos/dll/win32/riched20/editor.h +++ b/reactos/dll/win32/riched20/editor.h @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -128,7 +129,6 @@ ME_DisplayItem *ME_FindItemBackOrHere(ME_DisplayItem *di, ME_DIType nTypeOrClass ME_DisplayItem *ME_MakeDI(ME_DIType type) DECLSPEC_HIDDEN; void ME_DestroyDisplayItem(ME_DisplayItem *item) DECLSPEC_HIDDEN; void ME_DumpDocument(ME_TextBuffer *buffer) DECLSPEC_HIDDEN; -const char *ME_GetDITypeName(ME_DIType type) DECLSPEC_HIDDEN; /* string.c */ ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars) DECLSPEC_HIDDEN; @@ -141,9 +141,11 @@ int ME_CallWordBreakProc(ME_TextEditor *editor, WCHAR *str, INT len, INT start, void ME_StrDeleteV(ME_String *s, int nVChar, int nChars) DECLSPEC_HIDDEN; BOOL ME_InsertString(ME_String *s, int ofs, const WCHAR *insert, int len) DECLSPEC_HIDDEN; +#define CP_UNICODE 1200 + /* smart helpers for A<->W conversions, they reserve/free memory and call MultiByte<->WideChar functions */ -LPWSTR ME_ToUnicode(BOOL unicode, LPVOID psz) DECLSPEC_HIDDEN; -void ME_EndToUnicode(BOOL unicode, LPVOID psz) DECLSPEC_HIDDEN; +LPWSTR ME_ToUnicode(LONG codepage, LPVOID psz, INT *len) DECLSPEC_HIDDEN; +void ME_EndToUnicode(LONG codepage, LPVOID psz) DECLSPEC_HIDDEN; static inline int ME_IsWSpace(WCHAR ch) { @@ -177,7 +179,7 @@ int ME_CharFromPointContext(ME_Context *c, int cx, ME_Run *run, BOOL closest, BO int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run, BOOL closest, BOOL visual_order) DECLSPEC_HIDDEN; int ME_PointFromCharContext(ME_Context *c, ME_Run *pRun, int nOffset, BOOL visual_order) DECLSPEC_HIDDEN; int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset, BOOL visual_order) DECLSPEC_HIDDEN; -int ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2) DECLSPEC_HIDDEN; +BOOL ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2) DECLSPEC_HIDDEN; void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p) DECLSPEC_HIDDEN; ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_Cursor *cursor) DECLSPEC_HIDDEN; void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run) DECLSPEC_HIDDEN; @@ -290,7 +292,7 @@ void ME_RTFParAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN; void ME_RTFTblAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN; void ME_RTFSpecialCharHook(struct _RTF_Info *info) DECLSPEC_HIDDEN; void ME_StreamInFill(ME_InStream *stream) DECLSPEC_HIDDEN; -extern int me_debug DECLSPEC_HIDDEN; +extern BOOL me_debug DECLSPEC_HIDDEN; /* table.c */ BOOL ME_IsInTable(ME_DisplayItem *pItem) DECLSPEC_HIDDEN; diff --git a/reactos/dll/win32/riched20/editstr.h b/reactos/dll/win32/riched20/editstr.h index 3d696822973..5356b0639bf 100644 --- a/reactos/dll/win32/riched20/editstr.h +++ b/reactos/dll/win32/riched20/editstr.h @@ -38,6 +38,7 @@ typedef struct tagME_Style HFONT hFont; /* cached font for the style */ TEXTMETRICW tm; /* cached font metrics for the style */ int nRefs; /* reference count */ + SCRIPT_CACHE script_cache; } ME_Style; typedef enum { @@ -104,6 +105,7 @@ typedef enum { #define MEPF_CELL 0x04 /* The paragraph is nested in a cell */ #define MEPF_ROWSTART 0x08 /* Hidden empty paragraph at the start of the row */ #define MEPF_ROWEND 0x10 /* Visible empty paragraph at the end of the row */ +#define MEPF_COMPLEX 0x20 /* Use uniscribe */ /******************************** structures *************************/ @@ -120,6 +122,15 @@ typedef struct tagME_Run int nAscent, nDescent; /* pixels above/below baseline */ POINT pt; /* relative to para's position */ REOBJECT *ole_obj; /* FIXME: should be a union with strText (at least) */ + + SCRIPT_ANALYSIS script_analysis; + int num_glyphs, max_glyphs; + WORD *glyphs; + SCRIPT_VISATTR *vis_attrs; + int *advances; + GOFFSET *offsets; + int max_clusters; + WORD *clusters; } ME_Run; typedef struct tagME_Border @@ -401,6 +412,7 @@ typedef struct tagME_TextEditor SCROLLINFO vert_si, horz_si; BOOL bMouseCaptured; + int wheel_remain; } ME_TextEditor; typedef struct tagME_Context diff --git a/reactos/dll/win32/riched20/list.c b/reactos/dll/win32/riched20/list.c index f71318a137f..10732e523dd 100644 --- a/reactos/dll/win32/riched20/list.c +++ b/reactos/dll/win32/riched20/list.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ + #include "editor.h" WINE_DEFAULT_DEBUG_CHANNEL(richedit_lists); @@ -138,9 +139,24 @@ ME_DisplayItem *ME_FindItemFwd(ME_DisplayItem *di, ME_DIType nTypeOrClass) return NULL; } +static const char *ME_GetDITypeName(ME_DIType type) +{ + switch(type) + { + case diParagraph: return "diParagraph"; + case diRun: return "diRun"; + case diCell: return "diCell"; + case diTextStart: return "diTextStart"; + case diTextEnd: return "diTextEnd"; + case diStartRow: return "diStartRow"; + default: return "?"; + } +} + void ME_DestroyDisplayItem(ME_DisplayItem *item) { -/* TRACE("type=%s\n", ME_GetDITypeName(item->type)); */ + if (0) + TRACE("type=%s\n", ME_GetDITypeName(item->type)); if (item->type==diParagraph) { FREE_OBJ(item->member.para.pFmt); @@ -150,6 +166,8 @@ void ME_DestroyDisplayItem(ME_DisplayItem *item) if (item->type==diRun) { if (item->member.run.ole_obj) ME_DeleteReObject(item->member.run.ole_obj); + heap_free( item->member.run.glyphs ); + heap_free( item->member.run.clusters ); ME_ReleaseStyle(item->member.run.style); } FREE_OBJ(item); @@ -171,20 +189,6 @@ ME_DisplayItem *ME_MakeDI(ME_DIType type) return item; } -const char *ME_GetDITypeName(ME_DIType type) -{ - switch(type) - { - case diParagraph: return "diParagraph"; - case diRun: return "diRun"; - case diCell: return "diCell"; - case diTextStart: return "diTextStart"; - case diTextEnd: return "diTextEnd"; - case diStartRow: return "diStartRow"; - default: return "?"; - } -} - void ME_DumpDocument(ME_TextBuffer *buffer) { /* FIXME this is useless, */ diff --git a/reactos/dll/win32/riched20/msvc-thiscall.c b/reactos/dll/win32/riched20/msvc-thiscall.c index 80f34595727..ca96c94b547 100644 --- a/reactos/dll/win32/riched20/msvc-thiscall.c +++ b/reactos/dll/win32/riched20/msvc-thiscall.c @@ -113,7 +113,7 @@ DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIActivate,4) DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate,4) DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText,8) DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText,8) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurrentTargetX,8) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurTargetX,8) DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos,8) DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize,36) DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget,8) diff --git a/reactos/dll/win32/riched20/msvc.h b/reactos/dll/win32/riched20/msvc.h index 0e44d43f48a..bcc603b1034 100644 --- a/reactos/dll/win32/riched20/msvc.h +++ b/reactos/dll/win32/riched20/msvc.h @@ -101,7 +101,7 @@ typedef HRESULT (WINAPI typeof(fnTextSrv_OnTxUIActivate))(ITextServices *iface); typedef HRESULT (WINAPI typeof(fnTextSrv_OnTxUIDeactivate))(ITextServices *iface); typedef HRESULT (WINAPI typeof(fnTextSrv_TxGetText))(ITextServices *iface,BSTR* pbstrText); typedef HRESULT (WINAPI typeof(fnTextSrv_TxSetText))(ITextServices *iface,LPCWSTR pszText); -typedef HRESULT (WINAPI typeof(fnTextSrv_TxGetCurrentTargetX))(ITextServices *iface,LONG* x); +typedef HRESULT (WINAPI typeof(fnTextSrv_TxGetCurTargetX))(ITextServices *iface,LONG* x); typedef HRESULT (WINAPI typeof(fnTextSrv_TxGetBaseLinePos))(ITextServices *iface,LONG* x); typedef HRESULT (WINAPI typeof(fnTextSrv_TxGetNaturalSize))(ITextServices *iface,DWORD dwAspect,HDC hdcDraw,HDC hicTargetDev,DVTARGETDEVICE* ptd,DWORD dwMode,const SIZEL* psizelExtent,LONG* pwidth,LONG* pheight); typedef HRESULT (WINAPI typeof(fnTextSrv_TxGetDropTarget))(ITextServices *iface,struct IDropTarget** ppDropTarget); diff --git a/reactos/dll/win32/riched20/paint.c b/reactos/dll/win32/riched20/paint.c index e728b47432a..f89306113b5 100644 --- a/reactos/dll/win32/riched20/paint.c +++ b/reactos/dll/win32/riched20/paint.c @@ -331,7 +331,12 @@ static void draw_text( ME_Context *c, ME_Run *run, int x, int y, BOOL selected, old_text = SetTextColor( c->hDC, text_color ); if (selected) old_back = SetBkColor( c->hDC, back_color ); - ExtTextOutW( c->hDC, x, y, selected ? ETO_OPAQUE : 0, sel_rect, text, run->len, NULL ); + if (run->para->nFlags & MEPF_COMPLEX) + ScriptTextOut( c->hDC, &run->style->script_cache, x, y, selected ? ETO_OPAQUE : 0, sel_rect, + &run->script_analysis, NULL, 0, run->glyphs, run->num_glyphs, run->advances, + NULL, run->offsets ); + else + ExtTextOutW( c->hDC, x, y, selected ? ETO_OPAQUE : 0, sel_rect, text, run->len, NULL ); if (selected) SetBkColor( c->hDC, old_back ); SetTextColor( c->hDC, old_text ); diff --git a/reactos/dll/win32/riched20/reader.c b/reactos/dll/win32/riched20/reader.c index f082a30c9a1..9e115b5514b 100644 --- a/reactos/dll/win32/riched20/reader.c +++ b/reactos/dll/win32/riched20/reader.c @@ -41,8 +41,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit); -extern HANDLE me_heap; - static int _RTFGetChar(RTF_Info *); static void _RTFGetToken (RTF_Info *); static void _RTFGetToken2 (RTF_Info *); @@ -247,7 +245,7 @@ void RTFInit(RTF_Info *info) info->rtfLineNum = 0; info->rtfLinePos = 0; info->prevChar = EOF; - info->bumpLine = 0; + info->bumpLine = FALSE; info->dwCPOutputCount = 0; if (!info->cpOutputBuffer) @@ -713,7 +711,7 @@ static void _RTFGetToken2(RTF_Info *info) static int GetChar(RTF_Info *info) { int c; - int oldBumpLine; + BOOL oldBumpLine; if ((c = _RTFGetChar(info)) != EOF) { @@ -721,16 +719,16 @@ static int GetChar(RTF_Info *info) info->rtfTextBuf[info->rtfTextLen] = '\0'; } if (info->prevChar == EOF) - info->bumpLine = 1; - oldBumpLine = info->bumpLine; /* non-zero if prev char was line ending */ - info->bumpLine = 0; + info->bumpLine = TRUE; + oldBumpLine = info->bumpLine; /* TRUE if prev char was line ending */ + info->bumpLine = FALSE; if (c == '\r') - info->bumpLine = 1; + info->bumpLine = TRUE; else if (c == '\n') { - info->bumpLine = 1; + info->bumpLine = TRUE; if (info->prevChar == '\r') /* oops, previous \r wasn't */ - oldBumpLine = 0; /* really a line ending */ + oldBumpLine = FALSE; /* really a line ending */ } ++info->rtfLinePos; if (oldBumpLine) /* were we supposed to increment the */ diff --git a/reactos/dll/win32/riched20/richole.c b/reactos/dll/win32/riched20/richole.c index b9e7699f864..e33bba5b201 100644 --- a/reactos/dll/win32/riched20/richole.c +++ b/reactos/dll/win32/riched20/richole.c @@ -503,6 +503,9 @@ ITextDocument_fnGetSelection(ITextDocument* me, ITextSelection** ppSel) { IRichEditOleImpl *This = impl_from_ITextDocument(me); TRACE("(%p)\n", me); + + if(!ppSel) + return E_INVALIDARG; *ppSel = &This->txtSel->ITextSelection_iface; ITextSelection_AddRef(*ppSel); return S_OK; @@ -1502,7 +1505,7 @@ LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj) return 0; } reo->clientSite = CreateOleClientSite(reo); - if (!reo->txtSel) + if (!reo->clientSite) { ITextSelection_Release(&reo->txtSel->ITextSelection_iface); heap_free(reo); diff --git a/reactos/dll/win32/riched20/row.c b/reactos/dll/win32/riched20/row.c index 7f48d4a4bab..1bf153f6ca9 100644 --- a/reactos/dll/win32/riched20/row.c +++ b/reactos/dll/win32/riched20/row.c @@ -21,6 +21,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ + #include "editor.h" /* I'm sure these functions would simplify some code in caret ops etc, diff --git a/reactos/dll/win32/riched20/rtf.h b/reactos/dll/win32/riched20/rtf.h index 766a8b3b4ec..4b10744b8ef 100644 --- a/reactos/dll/win32/riched20/rtf.h +++ b/reactos/dll/win32/riched20/rtf.h @@ -1129,7 +1129,7 @@ struct _RTF_Info { char *pushedTextBuf; int prevChar; - int bumpLine; + BOOL bumpLine; /* Document-wide attributes */ RTFFont *fontList; /* these lists MUST be */ diff --git a/reactos/dll/win32/riched20/run.c b/reactos/dll/win32/riched20/run.c index 8929fc536cb..38d027003fb 100644 --- a/reactos/dll/win32/riched20/run.c +++ b/reactos/dll/win32/riched20/run.c @@ -30,17 +30,17 @@ WINE_DECLARE_DEBUG_CHANNEL(richedit_lists); /****************************************************************************** * ME_CanJoinRuns * - * Returns 1 if two runs can be safely merged into one, 0 otherwise. - */ -int ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2) + * Returns TRUE if two runs can be safely merged into one, FALSE otherwise. + */ +BOOL ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2) { if ((run1->nFlags | run2->nFlags) & MERF_NOJOIN) - return 0; + return FALSE; if (run1->style != run2->style) - return 0; + return FALSE; if ((run1->nFlags & MERF_STYLEFLAGS) != (run2->nFlags & MERF_STYLEFLAGS)) - return 0; - return 1; + return FALSE; + return TRUE; } void ME_SkipAndPropagateCharOffset(ME_DisplayItem *p, int shift) @@ -295,6 +295,14 @@ ME_DisplayItem *ME_MakeRun(ME_Style *s, int nFlags) item->member.run.nCharOfs = -1; item->member.run.len = 0; item->member.run.para = NULL; + item->member.run.num_glyphs = 0; + item->member.run.max_glyphs = 0; + item->member.run.glyphs = NULL; + item->member.run.vis_attrs = NULL; + item->member.run.advances = NULL; + item->member.run.offsets = NULL; + item->member.run.max_clusters = 0; + item->member.run.clusters = NULL; ME_AddRefStyle(s); return item; } @@ -310,23 +318,52 @@ ME_DisplayItem * ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style, const WCHAR *str, int len, int flags) { - ME_DisplayItem *pDI; + ME_DisplayItem *pDI, *insert_before = cursor->pRun, *prev; if (cursor->nOffset) - ME_SplitRunSimple(editor, cursor); + { + if (cursor->nOffset == cursor->pRun->member.run.len) + { + insert_before = ME_FindItemFwd( cursor->pRun, diRun ); + if (!insert_before) insert_before = cursor->pRun; /* Always insert before the final eop run */ + } + else + { + ME_SplitRunSimple( editor, cursor ); + insert_before = cursor->pRun; + } + } - add_undo_delete_run( editor, cursor->pPara->member.para.nCharOfs + - cursor->pRun->member.run.nCharOfs, len ); + add_undo_delete_run( editor, insert_before->member.run.para->nCharOfs + + insert_before->member.run.nCharOfs, len ); pDI = ME_MakeRun(style, flags); - pDI->member.run.nCharOfs = cursor->pRun->member.run.nCharOfs; + pDI->member.run.nCharOfs = insert_before->member.run.nCharOfs; pDI->member.run.len = len; - pDI->member.run.para = cursor->pRun->member.run.para; + pDI->member.run.para = insert_before->member.run.para; ME_InsertString( pDI->member.run.para->text, pDI->member.run.nCharOfs, str, len ); - ME_InsertBefore(cursor->pRun, pDI); + ME_InsertBefore( insert_before, pDI ); TRACE("Shift length:%d\n", len); - ME_PropagateCharOffset(cursor->pRun, len); - cursor->pPara->member.para.nFlags |= MEPF_REWRAP; + ME_PropagateCharOffset( insert_before, len ); + insert_before->member.run.para->nFlags |= MEPF_REWRAP; + + /* Move any cursors that were at the end of the previous run to the end of the inserted run */ + prev = ME_FindItemBack( pDI, diRun ); + if (prev) + { + int i; + + for (i = 0; i < editor->nCursors; i++) + { + if (editor->pCursors[i].pRun == prev && + editor->pCursors[i].nOffset == prev->member.run.len) + { + editor->pCursors[i].pRun = pDI; + editor->pCursors[i].nOffset = len; + } + } + } + return pDI; } @@ -439,6 +476,18 @@ int ME_CharFromPointContext(ME_Context *c, int cx, ME_Run *run, BOOL closest, BO return 1; } + if (run->para->nFlags & MEPF_COMPLEX) + { + int cp, trailing; + if (visual_order && run->script_analysis.fRTL) cx = run->nWidth - cx - 1; + + ScriptXtoCP( cx, run->len, run->num_glyphs, run->clusters, run->vis_attrs, run->advances, &run->script_analysis, + &cp, &trailing ); + TRACE("x %d cp %d trailing %d (run width %d) rtl %d log order %d\n", cx, cp, trailing, run->nWidth, + run->script_analysis.fRTL, run->script_analysis.fLogicalOrder); + return closest ? cp + trailing : cp; + } + if (c->editor->cPasswordMask) { mask_text = ME_MakeStringR( c->editor->cPasswordMask, run->len ); @@ -514,6 +563,14 @@ int ME_PointFromCharContext(ME_Context *c, ME_Run *pRun, int nOffset, BOOL visua nOffset = 0; } + if (pRun->para->nFlags & MEPF_COMPLEX) + { + int x; + ScriptCPtoX( nOffset, FALSE, pRun->len, pRun->num_glyphs, pRun->clusters, + pRun->vis_attrs, pRun->advances, &pRun->script_analysis, &x ); + if (visual_order && pRun->script_analysis.fRTL) x = pRun->nWidth - x - 1; + return x; + } if (c->editor->cPasswordMask) { mask_text = ME_MakeStringR(c->editor->cPasswordMask, pRun->len); @@ -563,8 +620,12 @@ SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run *run, i * this is wasteful for MERF_NONTEXT runs, but that shouldn't matter * in practice */ - - if (c->editor->cPasswordMask) + + if (para->nFlags & MEPF_COMPLEX) + { + size.cx = run->nWidth; + } + else if (c->editor->cPasswordMask) { ME_String *szMasked = ME_MakeStringR(c->editor->cPasswordMask,nLen); ME_GetTextExtent(c, szMasked->szData, nLen,run->style, &size); @@ -658,19 +719,20 @@ void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) */ void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, CHARFORMAT2W *pFmt) { - ME_DisplayItem *para; - ME_DisplayItem *run; - ME_DisplayItem *end_run = NULL; + ME_DisplayItem *run, *start_run = start->pRun, *end_run = NULL; if (end && start->pRun == end->pRun && start->nOffset == end->nOffset) return; - if (start->nOffset) + if (start->nOffset == start->pRun->member.run.len) + start_run = ME_FindItemFwd( start->pRun, diRun ); + else if (start->nOffset) { /* SplitRunSimple may or may not update the cursors, depending on whether they * are selection cursors, but we need to make sure they are valid. */ int split_offset = start->nOffset; ME_DisplayItem *split_run = ME_SplitRunSimple(editor, start); + start_run = start->pRun; if (end && end->pRun == split_run) { end->pRun = start->pRun; @@ -678,31 +740,26 @@ void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, C } } - if (end && end->nOffset) - ME_SplitRunSimple(editor, end); - end_run = end ? end->pRun : NULL; - - run = start->pRun; - para = start->pPara; - para->member.para.nFlags |= MEPF_REWRAP; + if (end) + { + if (end->nOffset == end->pRun->member.run.len) + end_run = ME_FindItemFwd( end->pRun, diRun ); + else + { + if (end->nOffset) ME_SplitRunSimple(editor, end); + end_run = end->pRun; + } + } - while(run != end_run) + for (run = start_run; run != end_run; run = ME_FindItemFwd( run, diRun )) { ME_Style *new_style = ME_ApplyStyle(run->member.run.style, pFmt); - /* ME_DumpStyle(new_style); */ - add_undo_set_char_fmt( editor, para->member.para.nCharOfs + run->member.run.nCharOfs, + add_undo_set_char_fmt( editor, run->member.run.para->nCharOfs + run->member.run.nCharOfs, run->member.run.len, &run->member.run.style->fmt ); ME_ReleaseStyle(run->member.run.style); run->member.run.style = new_style; - run = ME_FindItemFwd(run, diRunOrParagraph); - if (run && run->type == diParagraph) - { - para = run; - run = ME_FindItemFwd(run, diRun); - if (run != end_run) - para->member.para.nFlags |= MEPF_REWRAP; - } + run->member.run.para->nFlags |= MEPF_REWRAP; } } diff --git a/reactos/dll/win32/riched20/string.c b/reactos/dll/win32/riched20/string.c index 6d7d222bde8..12e4ad741ee 100644 --- a/reactos/dll/win32/riched20/string.c +++ b/reactos/dll/win32/riched20/string.c @@ -172,23 +172,30 @@ ME_CallWordBreakProc(ME_TextEditor *editor, WCHAR *str, INT len, INT start, INT } } -LPWSTR ME_ToUnicode(BOOL unicode, LPVOID psz) +LPWSTR ME_ToUnicode(LONG codepage, LPVOID psz, INT *len) { - assert(psz != NULL); + *len = 0; + if (!psz) return NULL; - if (unicode) + if (codepage == CP_UNICODE) + { + *len = lstrlenW(psz); return psz; + } else { WCHAR *tmp; - int nChars = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0); + int nChars = MultiByteToWideChar(codepage, 0, psz, -1, NULL, 0); + + if(!nChars) return NULL; + if((tmp = ALLOC_N_OBJ(WCHAR, nChars)) != NULL) - MultiByteToWideChar(CP_ACP, 0, psz, -1, tmp, nChars); + *len = MultiByteToWideChar(codepage, 0, psz, -1, tmp, nChars) - 1; return tmp; } } -void ME_EndToUnicode(BOOL unicode, LPVOID psz) +void ME_EndToUnicode(LONG codepage, LPVOID psz) { - if (!unicode) + if (codepage != CP_UNICODE) FREE_OBJ(psz); } diff --git a/reactos/dll/win32/riched20/style.c b/reactos/dll/win32/riched20/style.c index 62927149074..0817ea80004 100644 --- a/reactos/dll/win32/riched20/style.c +++ b/reactos/dll/win32/riched20/style.c @@ -149,6 +149,7 @@ ME_Style *ME_MakeStyle(CHARFORMAT2W *style) s->hFont = NULL; memset(&s->tm, 0, sizeof(s->tm)); s->tm.tmAscent = -1; + s->script_cache = NULL; all_refs++; TRACE_(richedit_style)("ME_MakeStyle %p, total refs=%d\n", s, all_refs); return s; @@ -435,6 +436,7 @@ static void ME_DestroyStyle(ME_Style *s) { DeleteObject(s->hFont); s->hFont = NULL; } + ScriptFreeCache( &s->script_cache ); FREE_OBJ(s); } diff --git a/reactos/dll/win32/riched20/table.c b/reactos/dll/win32/riched20/table.c index d5fbfcbd450..e78a1df20aa 100644 --- a/reactos/dll/win32/riched20/table.c +++ b/reactos/dll/win32/riched20/table.c @@ -34,7 +34,7 @@ * * Richedit version 4.1: * Tables are implemented such that cells can contain multiple paragraphs, - * each with it's own paragraph format, and cells may even contain tables + * each with its own paragraph format, and cells may even contain tables * nested within the cell. * * There is also a paragraph at the start of each table row that contains diff --git a/reactos/dll/win32/riched20/txtsrv.c b/reactos/dll/win32/riched20/txtsrv.c index 613919da4aa..fe4bf34eb7f 100644 --- a/reactos/dll/win32/riched20/txtsrv.c +++ b/reactos/dll/win32/riched20/txtsrv.c @@ -278,7 +278,7 @@ DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxSetText(ITextServices *iface, LPCWSTR return S_OK; } -DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetCurrentTargetX(ITextServices *iface, LONG *x) +DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetCurTargetX(ITextServices *iface, LONG *x) { ITextServicesImpl *This = impl_from_ITextServices(iface); @@ -340,7 +340,7 @@ DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIActivate,4) DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate,4) DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText,8) DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText,8) -DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurrentTargetX,8) +DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurTargetX,8) DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos,8) DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize,36) DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget,8) @@ -364,7 +364,7 @@ static const ITextServicesVtbl textservices_vtbl = THISCALL(fnTextSrv_OnTxUIDeactivate), THISCALL(fnTextSrv_TxGetText), THISCALL(fnTextSrv_TxSetText), - THISCALL(fnTextSrv_TxGetCurrentTargetX), + THISCALL(fnTextSrv_TxGetCurTargetX), THISCALL(fnTextSrv_TxGetBaseLinePos), THISCALL(fnTextSrv_TxGetNaturalSize), THISCALL(fnTextSrv_TxGetDropTarget), diff --git a/reactos/dll/win32/riched20/wrap.c b/reactos/dll/win32/riched20/wrap.c index 4509a54b955..6c9f2e3d5dd 100644 --- a/reactos/dll/win32/riched20/wrap.c +++ b/reactos/dll/win32/riched20/wrap.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ + #include "editor.h" WINE_DEFAULT_DEBUG_CHANNEL(richedit); @@ -31,6 +32,66 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit); * - no tabs */ + +static BOOL get_run_glyph_buffers( ME_Run *run ) +{ + heap_free( run->glyphs ); + run->glyphs = heap_alloc( run->max_glyphs * (sizeof(WORD) + sizeof(SCRIPT_VISATTR) + sizeof(int) + sizeof(GOFFSET)) ); + if (!run->glyphs) return FALSE; + + run->vis_attrs = (SCRIPT_VISATTR*)((char*)run->glyphs + run->max_glyphs * sizeof(WORD)); + run->advances = (int*)((char*)run->glyphs + run->max_glyphs * (sizeof(WORD) + sizeof(SCRIPT_VISATTR))); + run->offsets = (GOFFSET*)((char*)run->glyphs + run->max_glyphs * (sizeof(WORD) + sizeof(SCRIPT_VISATTR) + sizeof(int))); + + return TRUE; +} + +static HRESULT shape_run( ME_Context *c, ME_Run *run ) +{ + HRESULT hr; + HFONT old_font; + int i; + + if (!run->glyphs) + { + run->max_glyphs = 1.5 * run->len + 16; /* This is suggested in the uniscribe documentation */ + run->max_glyphs = (run->max_glyphs + 7) & ~7; /* Keep alignment simple */ + get_run_glyph_buffers( run ); + } + + if (run->max_clusters < run->len) + { + heap_free( run->clusters ); + run->max_clusters = run->len * 2; + run->clusters = heap_alloc( run->max_clusters * sizeof(WORD) ); + } + + old_font = ME_SelectStyleFont( c, run->style ); + while (1) + { + hr = ScriptShape( c->hDC, &run->style->script_cache, get_text( run, 0 ), run->len, run->max_glyphs, + &run->script_analysis, run->glyphs, run->clusters, run->vis_attrs, &run->num_glyphs ); + if (hr != E_OUTOFMEMORY) break; + if (run->max_glyphs > 10 * run->len) break; /* something has clearly gone wrong */ + run->max_glyphs *= 2; + get_run_glyph_buffers( run ); + } + + if (SUCCEEDED(hr)) + hr = ScriptPlace( c->hDC, &run->style->script_cache, run->glyphs, run->num_glyphs, run->vis_attrs, + &run->script_analysis, run->advances, run->offsets, NULL ); + + if (SUCCEEDED(hr)) + { + for (i = 0, run->nWidth = 0; i < run->num_glyphs; i++) + run->nWidth += run->advances[i]; + } + + ME_UnselectStyleFont( c, run->style, old_font ); + + return hr; +} + /****************************************************************************** * calc_run_extent * @@ -77,7 +138,10 @@ static ME_DisplayItem *split_run_extents(ME_WrapContext *wc, ME_DisplayItem *ite ME_SplitRunSimple(editor, &cursor); run2 = &cursor.pRun->member.run; + run2->script_analysis = run->script_analysis; + shape_run( wc->context, run ); + shape_run( wc->context, run2 ); calc_run_extent(wc->context, para, wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, run); run2->pt.x = run->pt.x+run->nWidth; @@ -165,15 +229,73 @@ static void ME_BeginRow(ME_WrapContext *wc) wc->pt.y++; } +static void layout_row( ME_DisplayItem *start, const ME_DisplayItem *end ) +{ + ME_DisplayItem *p; + int i, num_runs = 0; + int buf[16 * 5]; /* 5 arrays - 4 of int & 1 of BYTE, alloc space for 5 of ints */ + int *vis_to_log = buf, *log_to_vis, *widths, *pos; + BYTE *levels; + BOOL found_black = FALSE; + + for (p = end->prev; p != start->prev; p = p->prev) + { + if (p->type == diRun) + { + if (!found_black) found_black = !(p->member.run.nFlags & (MERF_WHITESPACE | MERF_ENDPARA)); + if (found_black) num_runs++; + } + } + + TRACE("%d runs\n", num_runs); + if (!num_runs) return; + + if (num_runs > sizeof(buf) / (sizeof(buf[0]) * 5)) + vis_to_log = heap_alloc( num_runs * sizeof(int) * 5 ); + + log_to_vis = vis_to_log + num_runs; + widths = vis_to_log + 2 * num_runs; + pos = vis_to_log + 3 * num_runs; + levels = (BYTE*)(vis_to_log + 4 * num_runs); + + for (i = 0, p = start; i < num_runs; p = p->next) + { + if (p->type == diRun) + { + levels[i] = p->member.run.script_analysis.s.uBidiLevel; + widths[i] = p->member.run.nWidth; + TRACE( "%d: level %d width %d\n", i, levels[i], widths[i] ); + i++; + } + } + + ScriptLayout( num_runs, levels, vis_to_log, log_to_vis ); + + pos[0] = start->member.run.para->pt.x; + for (i = 1; i < num_runs; i++) + pos[i] = pos[i - 1] + widths[ vis_to_log[ i - 1 ] ]; + + for (i = 0, p = start; i < num_runs; p = p->next) + { + if (p->type == diRun) + { + p->member.run.pt.x = pos[ log_to_vis[ i ] ]; + TRACE( "%d: x = %d\n", i, p->member.run.pt.x ); + i++; + } + } + + if (vis_to_log != buf) heap_free( vis_to_log ); +} + static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) { - ME_DisplayItem *p, *row, *para; + ME_DisplayItem *p, *row; + ME_Paragraph *para = &wc->pPara->member.para; BOOL bSkippingSpaces = TRUE; int ascent = 0, descent = 0, width=0, shift = 0, align = 0; - PARAFORMAT2 *pFmt; + /* wrap text */ - para = wc->pPara; - pFmt = para->member.para.pFmt; for (p = pEnd->prev; p!=wc->pRowStart->prev; p = p->prev) { @@ -207,10 +329,10 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) } } - para->member.para.nWidth = max(para->member.para.nWidth, width); + para->nWidth = max(para->nWidth, width); row = ME_MakeRow(ascent+descent, ascent, width); if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */ - pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) + (para->pFmt->dwMask & PFM_TABLE) && (para->pFmt->wEffects & PFE_TABLE)) { /* The text was shifted down in ME_BeginRow so move the wrap context * back to where it should be. */ @@ -221,12 +343,15 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) row->member.row.pt = wc->pt; row->member.row.nLMargin = (!wc->nRow ? wc->nFirstMargin : wc->nLeftMargin); row->member.row.nRMargin = wc->nRightMargin; - assert(para->member.para.pFmt->dwMask & PFM_ALIGNMENT); - align = para->member.para.pFmt->wAlignment; + assert(para->pFmt->dwMask & PFM_ALIGNMENT); + align = para->pFmt->wAlignment; if (align == PFA_CENTER) shift = max((wc->nAvailWidth-width)/2, 0); if (align == PFA_RIGHT) shift = max(wc->nAvailWidth-width, 0); + + if (para->nFlags & MEPF_COMPLEX) layout_row( wc->pRowStart, pEnd ); + row->member.row.pt.x = row->member.row.nLMargin + shift; for (p = wc->pRowStart; p!=pEnd; p = p->next) { @@ -613,6 +738,111 @@ static void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp) { } } +static HRESULT itemize_para( ME_Context *c, ME_DisplayItem *p ) +{ + ME_Paragraph *para = &p->member.para; + ME_Run *run; + ME_DisplayItem *di; + SCRIPT_ITEM buf[16], *items = buf; + int items_passed = sizeof( buf ) / sizeof( buf[0] ), num_items, cur_item; + SCRIPT_CONTROL control = { LANG_USER_DEFAULT, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + FALSE, FALSE, 0 }; + SCRIPT_STATE state = { 0, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0 }; + HRESULT hr; + + assert( p->type == diParagraph ); + + while (1) + { + hr = ScriptItemize( para->text->szData, para->text->nLen, items_passed, &control, + &state, items, &num_items ); + if (hr != E_OUTOFMEMORY) break; /* may not be enough items if hr == E_OUTOFMEMORY */ + if (items_passed > para->text->nLen + 1) break; /* something else has gone wrong */ + items_passed *= 2; + if (items == buf) + items = heap_alloc( items_passed * sizeof( *items ) ); + else + items = heap_realloc( items, items_passed * sizeof( *items ) ); + if (!items) break; + } + if (FAILED( hr )) goto end; + + if (TRACE_ON( richedit )) + { + TRACE( "got items:\n" ); + for (cur_item = 0; cur_item < num_items; cur_item++) + { + TRACE( "\t%d - %d RTL %d bidi level %d\n", items[cur_item].iCharPos, items[cur_item+1].iCharPos - 1, + items[cur_item].a.fRTL, items[cur_item].a.s.uBidiLevel ); + } + + TRACE( "before splitting runs into ranges\n" ); + for (di = p->next; di != p->member.para.next_para; di = di->next) + { + if (di->type != diRun) continue; + TRACE( "\t%d: %s\n", di->member.run.nCharOfs, debugstr_run( &di->member.run ) ); + } + } + + /* split runs into ranges at item boundaries */ + for (di = p->next, cur_item = 0; di != p->member.para.next_para; di = di->next) + { + if (di->type != diRun) continue; + run = &di->member.run; + + if (run->nCharOfs == items[cur_item+1].iCharPos) cur_item++; + + items[cur_item].a.fLogicalOrder = TRUE; + run->script_analysis = items[cur_item].a; + + if (run->nFlags & MERF_ENDPARA) break; /* don't split eop runs */ + + if (run->nCharOfs + run->len > items[cur_item+1].iCharPos) + { + ME_Cursor cursor = {p, di, items[cur_item+1].iCharPos - run->nCharOfs}; + ME_SplitRunSimple( c->editor, &cursor ); + } + } + + if (TRACE_ON( richedit )) + { + TRACE( "after splitting into ranges\n" ); + for (di = p->next; di != p->member.para.next_para; di = di->next) + { + if (di->type != diRun) continue; + TRACE( "\t%d: %s\n", di->member.run.nCharOfs, debugstr_run( &di->member.run ) ); + } + } + + para->nFlags |= MEPF_COMPLEX; + +end: + if (items != buf) heap_free( items ); + return hr; +} + + +static HRESULT shape_para( ME_Context *c, ME_DisplayItem *p ) +{ + ME_DisplayItem *di; + ME_Run *run; + HRESULT hr; + + for (di = p->next; di != p->member.para.next_para; di = di->next) + { + if (di->type != diRun) continue; + run = &di->member.run; + + hr = shape_run( c, run ); + if (FAILED( hr )) + { + run->para->nFlags &= ~MEPF_COMPLEX; + return hr; + } + } + return hr; +} + static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) { ME_DisplayItem *p; ME_WrapContext wc; @@ -625,6 +855,15 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) { return; } ME_PrepareParagraphForWrapping(c, tp); + + /* For now treating all non-password text as complex for better testing */ + if (!c->editor->cPasswordMask /* && + ScriptIsComplex( tp->member.para.text->szData, tp->member.para.text->nLen, SIC_COMPLEX ) == S_OK */) + { + if (SUCCEEDED( itemize_para( c, tp ) )) + shape_para( c, tp ); + } + pFmt = tp->member.para.pFmt; wc.context = c; diff --git a/reactos/dll/win32/riched20/writer.c b/reactos/dll/win32/riched20/writer.c index c67d1921da5..9a2c3c7f87a 100644 --- a/reactos/dll/win32/riched20/writer.c +++ b/reactos/dll/win32/riched20/writer.c @@ -23,6 +23,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit); + static BOOL ME_StreamOutRTFText(ME_OutStream *pStream, const WCHAR *text, LONG nChars); diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index c7dbee7116e..b92752616f5 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -164,7 +164,7 @@ reactos/dll/win32/qmgrprxy # Synced to Wine-1.7.1 reactos/dll/win32/query # Synced to Wine-1.7.1 reactos/dll/win32/rasapi32 # Synced to Wine-1.7.1 reactos/dll/win32/resutils # Synced to Wine-1.7.1 -reactos/dll/win32/riched20 # Synced to Wine-1.7.1 +reactos/dll/win32/riched20 # Synced to Wine-1.7.17 reactos/dll/win32/riched32 # Synced to Wine-1.7.1 reactos/dll/win32/rpcrt4 # Synced to Wine-1.7.1 reactos/dll/win32/rsabase # Synced to Wine-1.7.1 -- 2.17.1