diff --git a/reactos/lib/riched20/caret.c b/reactos/lib/riched20/caret.c index 24b37589ca2..f1c87db24d0 100644 --- a/reactos/lib/riched20/caret.c +++ b/reactos/lib/riched20/caret.c @@ -192,6 +192,8 @@ void ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, /* ME_SkipAndPropagateCharOffset(p->pRun, shift); */ ME_CheckCharOffsets(editor); nChars--; + if (editor->bEmulateVersion10 && nChars) + nChars--; continue; } else @@ -413,7 +415,7 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, } } -BOOL ME_ArrowLeft(ME_TextEditor *editor, ME_Cursor *p) +static BOOL ME_ArrowLeft(ME_TextEditor *editor, ME_Cursor *p) { if (p->nOffset) { p->nOffset = ME_StrRelPos2(p->pRun->member.run.strText, p->nOffset, -1); @@ -453,21 +455,26 @@ BOOL ME_ArrowLeft(ME_TextEditor *editor, ME_Cursor *p) return FALSE; } -BOOL ME_ArrowRight(ME_TextEditor *editor, ME_Cursor *p) +static BOOL ME_ArrowRight(ME_TextEditor *editor, ME_Cursor *p) { - int new_ofs = ME_StrRelPos2(p->pRun->member.run.strText, p->nOffset, 1); - if (new_ofspRun->member.run.strText->nLen) { - p->nOffset = new_ofs; - } - else + ME_DisplayItem *pRun; + + if (!(p->pRun->member.run.nFlags & MERF_ENDPARA)) { - ME_DisplayItem *pRun = ME_FindItemFwd(p->pRun, diRun); - if (pRun) { - p->pRun = pRun; - assert(p->pRun->type == diRun); - p->nOffset = 0; + int new_ofs = ME_StrRelPos2(p->pRun->member.run.strText, p->nOffset, 1); + + if (new_ofspRun->member.run.strText->nLen) + { + p->nOffset = new_ofs; + return TRUE; } } + pRun = ME_FindItemFwd(p->pRun, diRun); + if (pRun) { + p->pRun = pRun; + assert(p->pRun->type == diRun); + p->nOffset = 0; + } return TRUE; } @@ -698,7 +705,7 @@ static int ME_GetXForArrow(ME_TextEditor *editor, ME_Cursor *pCursor) return x; } -void ME_ArrowUp(ME_TextEditor *editor, ME_Cursor *pCursor) +static void ME_ArrowUp(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_DisplayItem *pRun = pCursor->pRun; ME_DisplayItem *pItem, *pItem2; @@ -725,7 +732,7 @@ void ME_ArrowUp(ME_TextEditor *editor, ME_Cursor *pCursor) pCursor->pRun = ME_FindRunInRow(editor, pItem2, x, &pCursor->nOffset, &editor->bCaretAtEnd); } -void ME_ArrowDown(ME_TextEditor *editor, ME_Cursor *pCursor) +static void ME_ArrowDown(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_DisplayItem *pRun = pCursor->pRun; ME_DisplayItem *pItem; @@ -749,7 +756,7 @@ void ME_ArrowDown(ME_TextEditor *editor, ME_Cursor *pCursor) assert(pCursor->pRun->type == diRun); } -void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor) +static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_DisplayItem *pRun = pCursor->pRun; ME_DisplayItem *pLast, *p; @@ -804,7 +811,7 @@ void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor) In such a situation, clicking the scrollbar restores its position back to the normal range (ie. sets it to (doclength-screenheight)). */ -void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor) +static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_DisplayItem *pRun = pCursor->pRun; ME_DisplayItem *pLast, *p; @@ -852,7 +859,7 @@ void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor) assert(pCursor->pRun->type == diRun); } -void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor) +static void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_DisplayItem *pRow = ME_FindItemBack(pCursor->pRun, diStartRow); if (pRow) { @@ -871,7 +878,7 @@ void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor) editor->bCaretAtEnd = FALSE; } -void ME_ArrowCtrlHome(ME_TextEditor *editor, ME_Cursor *pCursor) +static void ME_ArrowCtrlHome(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_DisplayItem *pRow = ME_FindItemBack(pCursor->pRun, diTextStart); if (pRow) { @@ -883,7 +890,7 @@ void ME_ArrowCtrlHome(ME_TextEditor *editor, ME_Cursor *pCursor) } } -void ME_ArrowEnd(ME_TextEditor *editor, ME_Cursor *pCursor) +static void ME_ArrowEnd(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_DisplayItem *pRow; @@ -907,7 +914,7 @@ void ME_ArrowEnd(ME_TextEditor *editor, ME_Cursor *pCursor) editor->bCaretAtEnd = FALSE; } -void ME_ArrowCtrlEnd(ME_TextEditor *editor, ME_Cursor *pCursor) +static void ME_ArrowCtrlEnd(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_DisplayItem *p = ME_FindItemFwd(pCursor->pRun, diTextEnd); assert(p); @@ -924,7 +931,7 @@ BOOL ME_IsSelection(ME_TextEditor *editor) return memcmp(&editor->pCursors[0], &editor->pCursors[1], sizeof(ME_Cursor))!=0; } -int ME_GetSelCursor(ME_TextEditor *editor, int dir) +static int ME_GetSelCursor(ME_TextEditor *editor, int dir) { int cdir = ME_GetCursorOfs(editor, 0) - ME_GetCursorOfs(editor, 1); @@ -934,7 +941,7 @@ int ME_GetSelCursor(ME_TextEditor *editor, int dir) return 1; } -BOOL ME_CancelSelection(ME_TextEditor *editor, int dir) +static BOOL ME_CancelSelection(ME_TextEditor *editor, int dir) { int cdir; @@ -979,7 +986,7 @@ BOOL ME_UpdateSelection(ME_TextEditor *editor, ME_Cursor *pTempCursor) return TRUE; } -void ME_RepaintSelection(ME_TextEditor *editor, ME_Cursor *pTempCursor) +static void ME_RepaintSelection(ME_TextEditor *editor, ME_Cursor *pTempCursor) { if (ME_UpdateSelection(editor, pTempCursor)) { ME_EnsureVisible(editor, editor->pCursors[0].pRun); diff --git a/reactos/lib/riched20/editor.c b/reactos/lib/riched20/editor.c index 0e4d2b7a11a..8339b12e9c4 100644 --- a/reactos/lib/riched20/editor.c +++ b/reactos/lib/riched20/editor.c @@ -31,10 +31,10 @@ + EM_EMPTYUNDOBUFFER + EM_EXGETSEL - EM_EXLIMITTEXT - - EM_EXLINEFROMCHAR + + EM_EXLINEFROMCHAR + EM_EXSETSEL - - EM_FINDTEXT - - EM_FINDTEXTEX + + EM_FINDTEXT (only FR_DOWN flag implemented) + + EM_FINDTEXTEX (only FR_DOWN flag implemented) - EM_FINDWORDBREAK - EM_FMTLINES - EM_FORMATRANGE @@ -51,7 +51,7 @@ - EM_GETLANGOPTIONS 2.0 - EM_GETLIMITTEXT - EM_GETLINE - - EM_GETLINECOUNT returns number of rows, not of paragraphs + + EM_GETLINECOUNT returns number of rows, not of paragraphs + EM_GETMODIFY - EM_GETOLEINTERFACE - EM_GETOPTIONS @@ -73,12 +73,12 @@ - EM_GETWORDBREAKPROC - EM_GETWORDBREAKPROCEX - EM_GETWORDWRAPMODE 1.0asian - - EM_SETZOOM 3.0 + + EM_GETZOOM 3.0 - EM_HIDESELECTION - EM_LIMITTEXT - - EM_LINEFROMCHAR - - EM_LINEINDEX - - EM_LINELENGTH + + EM_LINEFROMCHAR + + EM_LINEINDEX + + EM_LINELENGTH + EM_LINESCROLL - EM_PASTESPECIAL - EM_POSFROMCHARS @@ -112,17 +112,17 @@ - EM_SETSCROLLPOS 3.0 - EM_SETTABSTOPS 3.0 - EM_SETTARGETDEVICE - - EM_SETTEXTEX 3.0 + + EM_SETTEXTEX 3.0 (unicode only, no rich text insertion handling, proper style?) - EM_SETTEXTMODE 2.0 - EM_SETTYPOGRAPHYOPTIONS 3.0 - EM_SETUNDOLIMIT 2.0 - EM_SETWORDBREAKPROC - EM_SETWORDBREAKPROCEX - EM_SETWORDWRAPMODE 1.0asian - - EM_SETZOOM 3.0 + + EM_SETZOOM 3.0 - EM_SHOWSCROLLBAR 2.0 - EM_STOPGROUPTYPING 2.0 - + EM_STREAMIN (can't fall back to text when the RTF isn't really RTF) + + EM_STREAMIN + EM_STREAMOUT + EM_UNDO + WM_CHAR @@ -205,6 +205,9 @@ * - when should EN_SELCHANGE be sent after text change ? (before/after EN_UPDATE?) * - WM_SETTEXT may use wrong style (but I'm 80% sure it's OK) * - EM_GETCHARFORMAT with SCF_SELECTION may not behave 100% like in original (but very close) + * - full justification + * - hyphenation + * - tables * * Bugs that are probably fixed, but not so easy to verify: * - EN_UPDATE/EN_CHANGE are handled very incorrectly (should be OK now) @@ -218,6 +221,7 @@ */ #include "editor.h" +#include "commdlg.h" #include "ole2.h" #include "richole.h" #include "winreg.h" @@ -231,7 +235,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit); int me_debug = 0; HANDLE me_heap = NULL; -ME_TextBuffer *ME_MakeText(void) { +static ME_TextBuffer *ME_MakeText(void) { ME_TextBuffer *buf = ALLOC_OBJ(ME_TextBuffer); @@ -295,7 +299,7 @@ static LRESULT ME_StreamInText(ME_TextEditor *editor, DWORD dwFormat, ME_InStrea return 0; } -void ME_RTFCharAttrHook(RTF_Info *info) +static void ME_RTFCharAttrHook(RTF_Info *info) { CHARFORMAT2W fmt; fmt.cbSize = sizeof(fmt); @@ -394,7 +398,7 @@ void ME_RTFCharAttrHook(RTF_Info *info) /* FIXME this function doesn't get any information about context of the RTF tag, which is very bad, the same tags mean different things in different contexts */ -void ME_RTFParAttrHook(RTF_Info *info) +static void ME_RTFParAttrHook(RTF_Info *info) { PARAFORMAT2 fmt; fmt.cbSize = sizeof(fmt); @@ -459,7 +463,7 @@ void ME_RTFParAttrHook(RTF_Info *info) } } -void ME_RTFReadHook(RTF_Info *info) { +static void ME_RTFReadHook(RTF_Info *info) { switch(info->rtfClass) { case rtfGroup: @@ -651,11 +655,75 @@ ME_FindItemAtOffset(ME_TextEditor *editor, ME_DIType nItemType, int nOffset, int } +static int +ME_FindText(ME_TextEditor *editor, DWORD flags, CHARRANGE *chrg, WCHAR *text, CHARRANGE *chrgText) +{ + int nStart = chrg->cpMin; + int nLen = lstrlenW(text); + ME_DisplayItem *item = ME_FindItemAtOffset(editor, diRun, nStart, &nStart); + ME_DisplayItem *para; + + if (!item) + return -1; + + if (!nLen) + { + if (chrgText) + chrgText->cpMin = chrgText->cpMax = chrg->cpMin; + return chrg->cpMin; + } + + if (!(flags & FR_DOWN)) + FIXME("Backward search not implemented\n"); + if (!(flags & FR_MATCHCASE)) + FIXME("Case-insensitive search not implemented\n"); + if (flags & ~(FR_DOWN | FR_MATCHCASE)) + FIXME("Flags 0x%08lx not implemented\n", flags & ~(FR_DOWN | FR_MATCHCASE)); + + para = ME_GetParagraph(item); + while (item && para->member.para.nCharOfs + item->member.run.nCharOfs + nStart + nLen < chrg->cpMax) + { + ME_DisplayItem *pCurItem = item; + int nCurStart = nStart; + int nMatched = 0; + + while (pCurItem->member.run.strText->szData[nCurStart + nMatched] == text[nMatched]) + { + nMatched++; + if (nMatched == nLen) + { + nStart += para->member.para.nCharOfs + item->member.run.nCharOfs; + if (chrgText) + { + chrgText->cpMin = nStart; + chrgText->cpMax = nStart + nLen; + } + return nStart; + } + if (nCurStart + nMatched == ME_StrLen(pCurItem->member.run.strText)) + { + pCurItem = ME_FindItemFwd(pCurItem, diRun); + nCurStart = -nMatched; + } + } + nStart++; + if (nStart == ME_StrLen(item->member.run.strText)) + { + item = ME_FindItemFwd(item, diRun); + para = ME_GetParagraph(item); + nStart = 0; + } + } + return -1; +} + + ME_TextEditor *ME_MakeEditor(HWND hWnd) { ME_TextEditor *ed = ALLOC_OBJ(ME_TextEditor); HDC hDC; int i; ed->hWnd = hWnd; + ed->bEmulateVersion10 = FALSE; ed->pBuffer = ME_MakeText(); hDC = GetDC(hWnd); ME_MakeFirstParagraph(hDC, ed->pBuffer); @@ -679,6 +747,7 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) { ed->nParagraphs = 1; ed->nLastSelStart = ed->nLastSelEnd = 0; ed->nScrollPosY = 0; + ed->nZoomNumerator = ed->nZoomDenominator = 0; for (i=0; ipFontCache[i].nRefs = 0; @@ -753,6 +822,7 @@ static DWORD CALLBACK ME_ReadFromHGLOBALRTF(DWORD_PTR dwCookie, LPBYTE lpBuff, L return 0; } + void ME_DestroyEditor(ME_TextEditor *editor) { ME_DisplayItem *pFirst = editor->pBuffer->pFirst; @@ -808,6 +878,140 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) FIXME(#e ": stub\n"); \ return DefWindowProcW(hWnd, msg, wParam, lParam); +static const char * const edit_messages[] = { + "EM_GETSEL", + "EM_SETSEL", + "EM_GETRECT", + "EM_SETRECT", + "EM_SETRECTNP", + "EM_SCROLL", + "EM_LINESCROLL", + "EM_SCROLLCARET", + "EM_GETMODIFY", + "EM_SETMODIFY", + "EM_GETLINECOUNT", + "EM_LINEINDEX", + "EM_SETHANDLE", + "EM_GETHANDLE", + "EM_GETTHUMB", + "EM_UNKNOWN_BF", + "EM_UNKNOWN_C0", + "EM_LINELENGTH", + "EM_REPLACESEL", + "EM_UNKNOWN_C3", + "EM_GETLINE", + "EM_LIMITTEXT", + "EM_CANUNDO", + "EM_UNDO", + "EM_FMTLINES", + "EM_LINEFROMCHAR", + "EM_UNKNOWN_CA", + "EM_SETTABSTOPS", + "EM_SETPASSWORDCHAR", + "EM_EMPTYUNDOBUFFER", + "EM_GETFIRSTVISIBLELINE", + "EM_SETREADONLY", + "EM_SETWORDBREAKPROC", + "EM_GETWORDBREAKPROC", + "EM_GETPASSWORDCHAR", + "EM_SETMARGINS", + "EM_GETMARGINS", + "EM_GETLIMITTEXT", + "EM_POSFROMCHAR", + "EM_CHARFROMPOS" +}; + +static const char * const richedit_messages[] = { + "EM_CANPASTE", + "EM_DISPLAYBAND", + "EM_EXGETSEL", + "EM_EXLIMITTEXT", + "EM_EXLINEFROMCHAR", + "EM_EXSETSEL", + "EM_FINDTEXT", + "EM_FORMATRANGE", + "EM_GETCHARFORMAT", + "EM_GETEVENTMASK", + "EM_GETOLEINTERFACE", + "EM_GETPARAFORMAT", + "EM_GETSELTEXT", + "EM_HIDESELECTION", + "EM_PASTESPECIAL", + "EM_REQUESTRESIZE", + "EM_SELECTIONTYPE", + "EM_SETBKGNDCOLOR", + "EM_SETCHARFORMAT", + "EM_SETEVENTMASK", + "EM_SETOLECALLBACK", + "EM_SETPARAFORMAT", + "EM_SETTARGETDEVICE", + "EM_STREAMIN", + "EM_STREAMOUT", + "EM_GETTEXTRANGE", + "EM_FINDWORDBREAK", + "EM_SETOPTIONS", + "EM_GETOPTIONS", + "EM_FINDTEXTEX", + "EM_GETWORDBREAKPROCEX", + "EM_SETWORDBREAKPROCEX", + "EM_SETUNDOLIMIT", + "EM_UNKNOWN_USER_83", + "EM_REDO", + "EM_CANREDO", + "EM_GETUNDONAME", + "EM_GETREDONAME", + "EM_STOPGROUPTYPING", + "EM_SETTEXTMODE", + "EM_GETTEXTMODE", + "EM_AUTOURLDETECT", + "EM_GETAUTOURLDETECT", + "EM_SETPALETTE", + "EM_GETTEXTEX", + "EM_GETTEXTLENGTHEX", + "EM_SHOWSCROLLBAR", + "EM_SETTEXTEX", + "EM_UNKNOWN_USER_98", + "EM_UNKNOWN_USER_99", + "EM_SETPUNCTUATION", + "EM_GETPUNCTUATION", + "EM_SETWORDWRAPMODE", + "EM_GETWORDWRAPMODE", + "EM_SETIMECOLOR", + "EM_GETIMECOLOR", + "EM_SETIMEOPTIONS", + "EM_GETIMEOPTIONS", + "EM_CONVPOSITION", + "EM_UNKNOWN_USER_109", + "EM_UNKNOWN_USER_110", + "EM_UNKNOWN_USER_111", + "EM_UNKNOWN_USER_112", + "EM_UNKNOWN_USER_113", + "EM_UNKNOWN_USER_114", + "EM_UNKNOWN_USER_115", + "EM_UNKNOWN_USER_116", + "EM_UNKNOWN_USER_117", + "EM_UNKNOWN_USER_118", + "EM_UNKNOWN_USER_119", + "EM_SETLANGOPTIONS", + "EM_GETLANGOPTIONS", + "EM_GETIMECOMPMODE", + "EM_FINDTEXTW", + "EM_FINDTEXTEXW", + "EM_RECONVERSION", + "EM_SETIMEMODEBIAS", + "EM_GETIMEMODEBIAS" +}; + +static const char * +get_msg_name(UINT msg) +{ + if (msg >= EM_GETSEL && msg <= EM_SETLIMITTEXT) + return edit_messages[msg - EM_GETSEL]; + if (msg >= EM_CANPASTE && msg <= EM_GETIMEMODEBIAS) + return richedit_messages[msg - EM_CANPASTE]; + return ""; +} + /****************************************************************** * RichEditANSIWndProc (RICHED20.10) */ @@ -816,16 +1020,15 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP PAINTSTRUCT ps; SCROLLINFO si; ME_TextEditor *editor = (ME_TextEditor *)GetWindowLongW(hWnd, 0); - TRACE("msg %d %08x %08lx\n", msg, wParam, lParam); + + TRACE("msg %d (%s) %08x %08lx\n", msg, get_msg_name(msg), wParam, lParam); + switch(msg) { UNSUPPORTED_MSG(EM_AUTOURLDETECT) UNSUPPORTED_MSG(EM_CHARFROMPOS) UNSUPPORTED_MSG(EM_DISPLAYBAND) UNSUPPORTED_MSG(EM_EXLIMITTEXT) - UNSUPPORTED_MSG(EM_EXLINEFROMCHAR) - UNSUPPORTED_MSG(EM_FINDTEXT) - UNSUPPORTED_MSG(EM_FINDTEXTEX) UNSUPPORTED_MSG(EM_FINDWORDBREAK) UNSUPPORTED_MSG(EM_FMTLINES) UNSUPPORTED_MSG(EM_FORMATRANGE) @@ -838,25 +1041,19 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP UNSUPPORTED_MSG(EM_GETLANGOPTIONS) UNSUPPORTED_MSG(EM_GETLIMITTEXT) UNSUPPORTED_MSG(EM_GETLINE) - UNSUPPORTED_MSG(EM_GETLINECOUNT) /* UNSUPPORTED_MSG(EM_GETOLEINTERFACE) separate stub */ UNSUPPORTED_MSG(EM_GETOPTIONS) UNSUPPORTED_MSG(EM_GETPASSWORDCHAR) UNSUPPORTED_MSG(EM_GETRECT) UNSUPPORTED_MSG(EM_GETREDONAME) UNSUPPORTED_MSG(EM_GETSCROLLPOS) - UNSUPPORTED_MSG(EM_GETTEXTEX) UNSUPPORTED_MSG(EM_GETTEXTMODE) UNSUPPORTED_MSG(EM_GETTYPOGRAPHYOPTIONS) UNSUPPORTED_MSG(EM_GETUNDONAME) UNSUPPORTED_MSG(EM_GETWORDBREAKPROC) UNSUPPORTED_MSG(EM_GETWORDBREAKPROCEX) - UNSUPPORTED_MSG(EM_GETZOOM) UNSUPPORTED_MSG(EM_HIDESELECTION) UNSUPPORTED_MSG(EM_LIMITTEXT) /* also known as EM_SETLIMITTEXT */ - UNSUPPORTED_MSG(EM_LINEFROMCHAR) - UNSUPPORTED_MSG(EM_LINEINDEX) - UNSUPPORTED_MSG(EM_LINELENGTH) UNSUPPORTED_MSG(EM_PASTESPECIAL) /* UNSUPPORTED_MSG(EM_POSFROMCHARS) missing in Wine headers */ UNSUPPORTED_MSG(EM_REQUESTRESIZE) @@ -876,14 +1073,12 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP UNSUPPORTED_MSG(EM_SETSCROLLPOS) UNSUPPORTED_MSG(EM_SETTABSTOPS) UNSUPPORTED_MSG(EM_SETTARGETDEVICE) - UNSUPPORTED_MSG(EM_SETTEXTEX) UNSUPPORTED_MSG(EM_SETTEXTMODE) UNSUPPORTED_MSG(EM_SETTYPOGRAPHYOPTIONS) UNSUPPORTED_MSG(EM_SETUNDOLIMIT) UNSUPPORTED_MSG(EM_SETWORDBREAKPROC) UNSUPPORTED_MSG(EM_SETWORDBREAKPROCEX) UNSUPPORTED_MSG(EM_SHOWSCROLLBAR) - UNSUPPORTED_MSG(EM_SETZOOM) UNSUPPORTED_MSG(WM_SETFONT) UNSUPPORTED_MSG(WM_STYLECHANGING) UNSUPPORTED_MSG(WM_STYLECHANGED) @@ -905,6 +1100,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP case WM_NCCREATE: { CREATESTRUCTW *pcs = (CREATESTRUCTW *)lParam; + TRACE("WM_NCCREATE: style 0x%08lx\n", pcs->style); editor = ME_MakeEditor(hWnd); SetWindowLongW(hWnd, 0, (long)editor); pcs = 0; /* ignore */ @@ -928,6 +1124,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP { CHARRANGE *pRange = (CHARRANGE *)lParam; ME_GetSelection(editor, (int *)&pRange->cpMin, (int *)&pRange->cpMax); + TRACE("EM_EXGETSEL = (%ld,%ld)\n", pRange->cpMin, pRange->cpMax); return 0; } case EM_CANUNDO: @@ -950,12 +1147,44 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP case EM_EXSETSEL: { CHARRANGE *pRange = (CHARRANGE *)lParam; + TRACE("EM_EXSETSEL (%ld,%ld)\n", pRange->cpMin, pRange->cpMax); ME_SetSelection(editor, pRange->cpMin, pRange->cpMax); /* FIXME optimize */ ME_Repaint(editor); ME_SendSelChange(editor); return 0; } + case EM_SETTEXTEX: + { + LPWSTR wszText = (LPWSTR)lParam; + SETTEXTEX *pStruct = (SETTEXTEX *)wParam; + size_t len = lstrlenW(wszText); + int from, to; + ME_Style *style; + TRACE("EM_SETTEXEX - %s, flags %d, cp %d\n", debugstr_w(wszText), (int)pStruct->flags, pStruct->codepage); + if (pStruct->codepage != 1200) { + FIXME("EM_SETTEXTEX only supports unicode right now!\n"); + return 0; + } + /* FIXME: this should support RTF strings too, according to MSDN */ + if (pStruct->flags & ST_SELECTION) { + ME_GetSelection(editor, &from, &to); + style = ME_GetSelectionInsertStyle(editor); + ME_InternalDeleteText(editor, from, to - from); + ME_InsertTextFromCursor(editor, 0, wszText, len, style); + ME_ReleaseStyle(style); + } + else { + ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor)); + ME_InsertTextFromCursor(editor, 0, wszText, -1, editor->pBuffer->pDefaultStyle); + len = 1; + } + ME_CommitUndo(editor); + if (!(pStruct->flags & ST_KEEPUNDO)) + ME_EmptyUndoStack(editor); + ME_UpdateRepaint(editor); + return len; + } case EM_SETBKGNDCOLOR: { LRESULT lColor = ME_GetBackColor(editor); @@ -1002,7 +1231,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP if (!wParam) ME_SetDefaultCharFormat(editor, p); else if (wParam == (SCF_WORD | SCF_SELECTION)) - FIXME("word selection not supported\n"); + FIXME("EM_SETCHARFORMAT: word selection not supported\n"); else if (wParam == SCF_ALL) ME_SetCharFormat(editor, 0, ME_GetTextLength(editor), p); else { @@ -1018,14 +1247,19 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP } case EM_GETCHARFORMAT: { - CHARFORMAT2W tmp; + CHARFORMAT2W tmp, *dst = (CHARFORMAT2W *)lParam; + if (dst->cbSize != sizeof(CHARFORMATA) && + dst->cbSize != sizeof(CHARFORMATW) && + dst->cbSize != sizeof(CHARFORMAT2A) && + dst->cbSize != sizeof(CHARFORMAT2W)) + return 0; tmp.cbSize = sizeof(tmp); if (!wParam) ME_GetDefaultCharFormat(editor, &tmp); else ME_GetSelectionCharFormat(editor, &tmp); - ME_CopyToCFAny((CHARFORMAT2W *)lParam, &tmp); - return 0; + ME_CopyToCFAny(dst, &tmp); + return tmp.dwMask; } case EM_SETPARAFORMAT: ME_SetSelectionParaFormat(editor, (PARAFORMAT2 *)lParam); @@ -1087,12 +1321,21 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP } case WM_SETTEXT: { - LPWSTR wszText = ME_ToUnicode(hWnd, (void *)lParam); - TRACE("WM_SETTEXT - %s\n", (char *)(wszText)); /* debugstr_w() */ ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor)); - /* uses default style! */ - ME_InsertTextFromCursor(editor, 0, wszText, -1, editor->pBuffer->pDefaultStyle); - ME_EndToUnicode(hWnd, wszText); + if (lParam) + { + LPWSTR wszText = ME_ToUnicode(hWnd, (void *)lParam); + TRACE("WM_SETTEXT lParam==%lx\n",lParam); + TRACE("WM_SETTEXT - %s\n", debugstr_w(wszText)); /* debugstr_w() */ + if (lstrlenW(wszText) > 0) + { + /* uses default style! */ + ME_InsertTextFromCursor(editor, 0, wszText, -1, editor->pBuffer->pDefaultStyle); + } + ME_EndToUnicode(hWnd, wszText); + } + else + TRACE("WM_SETTEXT - NULL\n"); ME_CommitUndo(editor); ME_EmptyUndoStack(editor); ME_UpdateRepaint(editor); @@ -1184,6 +1427,29 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP tr.lpstrText = (WCHAR *)lParam; return RichEditANSIWndProc(hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr); } + case EM_GETTEXTEX: + { + GETTEXTEX *ex = (GETTEXTEX*)wParam; + + if (ex->flags != 0) + FIXME("Unhandled EM_GETTEXTEX flags 0x%lx\n",ex->flags); + + if (IsWindowUnicode(hWnd)) + return ME_GetTextW(editor, (LPWSTR)lParam, 0, ex->cb, FALSE); + else + { + LPWSTR buffer = HeapAlloc(GetProcessHeap(),0,ex->cb*sizeof(WCHAR)); + DWORD buflen = ex->cb; + LRESULT rc; + DWORD flags = 0; + + buflen = ME_GetTextW(editor, buffer, 0, buflen, FALSE); + rc = WideCharToMultiByte(ex->codepage, flags, buffer, buflen, (LPSTR)lParam, ex->cb, ex->lpDefaultChar, ex->lpUsedDefaultChar); + + HeapFree(GetProcessHeap(),0,buffer); + return rc; + } + } case EM_GETSELTEXT: { int from, to; @@ -1213,6 +1479,114 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP } return ME_GetTextW(editor, rng->lpstrText, rng->chrg.cpMin, rng->chrg.cpMax-rng->chrg.cpMin, FALSE); } + case EM_GETLINECOUNT: + { + ME_DisplayItem *item = editor->pBuffer->pFirst->next; + int nRows = 0; + + while (item != editor->pBuffer->pLast) + { + assert(item->type == diParagraph); + nRows += item->member.para.nRows; + item = item->member.para.next_para; + } + TRACE("EM_GETLINECOUNT: nRows==%d\n", nRows); + return max(1, nRows); + } + case EM_LINEFROMCHAR: + { + if (wParam == -1) + return ME_RowNumberFromCharOfs(editor, ME_GetCursorOfs(editor, 1)); + else + return ME_RowNumberFromCharOfs(editor, wParam); + } + case EM_EXLINEFROMCHAR: + { + return ME_RowNumberFromCharOfs(editor, lParam); + } + case EM_LINEINDEX: + { + ME_DisplayItem *item, *para; + int nCharOfs; + + if (wParam == -1) + item = ME_FindItemBack(editor->pCursors[0].pRun, diStartRow); + else + item = ME_FindRowWithNumber(editor, wParam); + if (!item) + return -1; + para = ME_GetParagraph(item); + item = ME_FindItemFwd(item, diRun); + nCharOfs = para->member.para.nCharOfs + item->member.run.nCharOfs; + TRACE("EM_LINEINDEX: nCharOfs==%d\n", nCharOfs); + return nCharOfs; + } + case EM_LINELENGTH: + { + ME_DisplayItem *item, *item_end; + int nChars = 0; + + if (wParam > ME_GetTextLength(editor)) + return 0; + if (wParam == -1) + { + FIXME("EM_LINELENGTH: returning number of unselected characters on lines with selection unsupported.\n"); + return 0; + } + item = ME_FindItemAtOffset(editor, diRun, wParam, NULL); + item = ME_RowStart(item); + item_end = ME_RowEnd(item); + if (!item_end) + { + /* Empty buffer, no runs */ + nChars = 0; + } + else + { + nChars = ME_CharOfsFromRunOfs(editor, item_end, ME_StrLen(item_end->member.run.strText)); + nChars -= ME_CharOfsFromRunOfs(editor, item, 0); + } + TRACE("EM_LINELENGTH(%d)==%d\n",wParam, nChars); + return nChars; + } + case EM_FINDTEXT: + { + FINDTEXTA *ft = (FINDTEXTA *)lParam; + int nChars = MultiByteToWideChar(CP_ACP, 0, ft->lpstrText, -1, NULL, 0); + WCHAR *tmp; + + if ((tmp = ALLOC_N_OBJ(WCHAR, nChars)) != NULL) + MultiByteToWideChar(CP_ACP, 0, ft->lpstrText, -1, tmp, nChars); + return ME_FindText(editor, wParam, &ft->chrg, tmp, NULL); + } + case EM_FINDTEXTEX: + { + FINDTEXTEXA *ex = (FINDTEXTEXA *)lParam; + int nChars = MultiByteToWideChar(CP_ACP, 0, ex->lpstrText, -1, NULL, 0); + WCHAR *tmp; + + if ((tmp = ALLOC_N_OBJ(WCHAR, nChars)) != NULL) + MultiByteToWideChar(CP_ACP, 0, ex->lpstrText, -1, tmp, nChars); + return ME_FindText(editor, wParam, &ex->chrg, tmp, &ex->chrgText); + } + case EM_FINDTEXTW: + { + FINDTEXTW *ft = (FINDTEXTW *)lParam; + return ME_FindText(editor, wParam, &ft->chrg, ft->lpstrText, NULL); + } + case EM_FINDTEXTEXW: + { + FINDTEXTEXW *ex = (FINDTEXTEXW *)lParam; + return ME_FindText(editor, wParam, &ex->chrg, ex->lpstrText, &ex->chrgText); + } + case EM_GETZOOM: + if (!wParam || !lParam) + return FALSE; + *(int *)wParam = editor->nZoomNumerator; + *(int *)lParam = editor->nZoomDenominator; + return TRUE; + case EM_SETZOOM: + return ME_SetZoom(editor, wParam, lParam); case WM_CREATE: ME_CommitUndo(editor); ME_WrapMarkedParagraphs(editor); @@ -1369,10 +1743,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP } case WM_SIZE: { - ME_MarkAllForWrapping(editor); - ME_WrapMarkedParagraphs(editor); - ME_UpdateScrollBar(editor); - ME_Repaint(editor); + ME_RewrapRepaint(editor); return DefWindowProcW(hWnd, msg, wParam, lParam); } case EM_GETOLEINTERFACE: @@ -1388,13 +1759,24 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP return 0L; } + /****************************************************************** * RichEdit10ANSIWndProc (RICHED20.9) */ LRESULT WINAPI RichEdit10ANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { + LRESULT result; + /* FIXME: this is NOT the same as 2.0 version */ - return RichEditANSIWndProc(hWnd, msg, wParam, lParam); + result = RichEditANSIWndProc(hWnd, msg, wParam, lParam); + if (msg == WM_NCCREATE) + { + ME_TextEditor *editor = (ME_TextEditor *)GetWindowLongW(hWnd, 0); + + editor->bEmulateVersion10 = TRUE; + editor->pBuffer->pLast->member.para.nCharOfs = 2; + } + return result; } void ME_SendOldNotify(ME_TextEditor *editor, int nCode) diff --git a/reactos/lib/riched20/editor.h b/reactos/lib/riched20/editor.h index a0eab82c3c9..9f5f6bdd0ab 100644 --- a/reactos/lib/riched20/editor.h +++ b/reactos/lib/riched20/editor.h @@ -100,6 +100,8 @@ ME_DisplayItem *ME_FindRowStart(ME_Context *c, ME_DisplayItem *run, int nRelPos) ME_DisplayItem *ME_RowStart(ME_DisplayItem *item); ME_DisplayItem *ME_RowEnd(ME_DisplayItem *item); void ME_RenumberParagraphs(ME_DisplayItem *item); /* TODO */ +ME_DisplayItem *ME_FindRowWithNumber(ME_TextEditor *editor, int nRow); +int ME_RowNumberFromCharOfs(ME_TextEditor *editor, int nOfs); /* run.c */ ME_DisplayItem *ME_MakeRun(ME_Style *s, ME_String *strData, int nFlags); @@ -189,6 +191,7 @@ void ME_MarkAllForWrapping(ME_TextEditor *editor); /* paint.c */ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, RECT *rcUpdate); void ME_Repaint(ME_TextEditor *editor); +void ME_RewrapRepaint(ME_TextEditor *editor); void ME_UpdateRepaint(ME_TextEditor *editor); void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph); void ME_UpdateScrollBar(ME_TextEditor *editor); @@ -196,6 +199,7 @@ int ME_GetYScrollPos(ME_TextEditor *editor); void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun); COLORREF ME_GetBackColor(ME_TextEditor *editor); void ME_Scroll(ME_TextEditor *editor, int cx, int cy); +BOOL ME_SetZoom(ME_TextEditor *editor, int numerator, int denominator); /* richole.c */ extern LRESULT CreateIRichEditOle(LPVOID *); diff --git a/reactos/lib/riched20/editstr.h b/reactos/lib/riched20/editstr.h index 00329fb9628..b6df58774cd 100644 --- a/reactos/lib/riched20/editstr.h +++ b/reactos/lib/riched20/editstr.h @@ -147,6 +147,7 @@ typedef struct tagME_Paragraph int nFlags; int nYPos, nHeight; int nLastPaintYPos, nLastPaintHeight; + int nRows; struct tagME_DisplayItem *prev_para, *next_para, *document; } ME_Paragraph; @@ -246,6 +247,7 @@ typedef struct tagME_FontCacheItem typedef struct tagME_TextEditor { HWND hWnd; + BOOL bEmulateVersion10; BOOL bCaretShown; ME_TextBuffer *pBuffer; ME_Cursor *pCursors; @@ -267,6 +269,7 @@ typedef struct tagME_TextEditor ME_OutStream *pStream; BOOL bScrollX, bScrollY; int nScrollPosY; + int nZoomNumerator, nZoomDenominator; } ME_TextEditor; typedef struct tagME_Context diff --git a/reactos/lib/riched20/paint.c b/reactos/lib/riched20/paint.c index d02bd258308..7b734af1ef3 100644 --- a/reactos/lib/riched20/paint.c +++ b/reactos/lib/riched20/paint.c @@ -94,7 +94,7 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, RECT *rcUpda ME_DestroyContext(&c); } -void ME_MarkParagraphRange(ME_TextEditor *editor, ME_DisplayItem *p1, +static void ME_MarkParagraphRange(ME_TextEditor *editor, ME_DisplayItem *p1, ME_DisplayItem *p2, int nFlags) { ME_DisplayItem *p3; @@ -113,7 +113,7 @@ void ME_MarkParagraphRange(ME_TextEditor *editor, ME_DisplayItem *p1, } while (p1 != p2); } -void ME_MarkOffsetRange(ME_TextEditor *editor, int from, int to, int nFlags) +static void ME_MarkOffsetRange(ME_TextEditor *editor, int from, int to, int nFlags) { ME_Cursor c1, c2; ME_CursorFromCharOfs(editor, from, &c1); @@ -122,7 +122,7 @@ void ME_MarkOffsetRange(ME_TextEditor *editor, int from, int to, int nFlags) ME_MarkParagraphRange(editor, ME_GetParagraph(c1.pRun), ME_GetParagraph(c2.pRun), nFlags); } -void ME_MarkSelectionForRepaint(ME_TextEditor *editor) +static void ME_MarkSelectionForRepaint(ME_TextEditor *editor) { int from, to, from2, to2, end; @@ -173,7 +173,18 @@ void ME_UpdateRepaint(ME_TextEditor *editor) ME_SendSelChange(editor); } -void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, int nChars, + +void +ME_RewrapRepaint(ME_TextEditor *editor) +{ + ME_MarkAllForWrapping(editor); + ME_WrapMarkedParagraphs(editor); + ME_UpdateScrollBar(editor); + ME_Repaint(editor); +} + + +static void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, int nChars, ME_Style *s, int *width, int nSelFrom, int nSelTo, int ymin, int cy) { HDC hDC = c->hDC; HGDIOBJ hOldFont; @@ -193,7 +204,17 @@ void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, int nChar if (s->fmt.dwEffects & CFE_SUBSCRIPT) yTwipsOffset = -s->fmt.yHeight/12; } if (yTwipsOffset) - yOffset = yTwipsOffset*GetDeviceCaps(hDC, LOGPIXELSY)/1440; + { + int numerator = 1; + int denominator = 1; + + if (c->editor->nZoomNumerator) + { + numerator = c->editor->nZoomNumerator; + denominator = c->editor->nZoomDenominator; + } + yOffset = yTwipsOffset * GetDeviceCaps(hDC, LOGPIXELSY) * numerator / denominator / 1440; + } ExtTextOutW(hDC, x, y-yOffset, 0, NULL, szText, nChars, NULL); if (width) { SIZE sz; @@ -214,7 +235,7 @@ void ME_DrawTextWithStyle(ME_Context *c, int x, int y, LPCWSTR szText, int nChar ME_UnselectStyleFont(c->editor, hDC, s, hOldFont); } -void ME_DebugWrite(HDC hDC, POINT *pt, WCHAR *szText) { +static void ME_DebugWrite(HDC hDC, POINT *pt, WCHAR *szText) { int align = SetTextAlign(hDC, TA_LEFT|TA_TOP); HGDIOBJ hFont = SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT)); COLORREF color = SetTextColor(hDC, RGB(128,128,128)); @@ -252,7 +273,7 @@ void ME_DrawGraphics(ME_Context *c, int x, int y, ME_Run *run, } } -void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Paragraph *para) { +static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Paragraph *para) { ME_Run *run = &rundi->member.run; int runofs = run->nCharOfs+para->nCharOfs; @@ -484,3 +505,25 @@ void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun) UpdateWindow(hWnd); } } + + +BOOL +ME_SetZoom(ME_TextEditor *editor, int numerator, int denominator) +{ + /* TODO: Zoom images and objects */ + + if (numerator != 0) + { + if (denominator == 0) + return FALSE; + if (1.0 / 64.0 > (float)numerator / (float)denominator + || (float)numerator / (float)denominator > 64.0) + return FALSE; + } + + editor->nZoomNumerator = numerator; + editor->nZoomDenominator = denominator; + + ME_RewrapRepaint(editor); + return TRUE; +} diff --git a/reactos/lib/riched20/para.c b/reactos/lib/riched20/para.c index 4b1947ce797..a6a548f1e5c 100644 --- a/reactos/lib/riched20/para.c +++ b/reactos/lib/riched20/para.c @@ -101,6 +101,7 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, ME ME_UndoItem *undo = NULL; int ofs; ME_DisplayItem *pp; + int end_len = (editor->bEmulateVersion10 ? 2 : 1); assert(run->type == diRun); @@ -122,7 +123,7 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, ME pp = ME_FindItemFwd(pp, diRunOrParagraphOrEnd); } new_para->member.para.nCharOfs = ME_GetParagraph(run)->member.para.nCharOfs+ofs; - new_para->member.para.nCharOfs += 1; + new_para->member.para.nCharOfs += end_len; new_para->member.para.nFlags = MEPF_REWRAP; /* FIXME copy flags (if applicable) */ /* FIXME initialize format style and call ME_SetParaFormat blah blah */ @@ -148,7 +149,7 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, ME new_para->member.para.prev_para->member.para.nFlags |= MEPF_REWRAP; /* we've added the end run, so we need to modify nCharOfs in the next paragraphs */ - ME_PropagateCharOffset(next_para, 1); + ME_PropagateCharOffset(next_para, end_len); editor->nParagraphs++; return new_para; @@ -161,6 +162,7 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp) ME_DisplayItem *pNext, *pFirstRunInNext, *pRun, *pTmp; int i, shift; ME_UndoItem *undo = NULL; + int end_len = (editor->bEmulateVersion10 ? 2 : 1); assert(tp->type == diParagraph); assert(tp->member.para.next_para); @@ -172,17 +174,17 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp) /* null char format operation to store the original char format for the ENDPARA run */ CHARFORMAT2W fmt; ME_InitCharFormat2W(&fmt); - ME_SetCharFormat(editor, pNext->member.para.nCharOfs-1, 1, &fmt); + ME_SetCharFormat(editor, pNext->member.para.nCharOfs - end_len, end_len, &fmt); } undo = ME_AddUndoItem(editor, diUndoSplitParagraph, NULL); if (undo) { - undo->nStart = pNext->member.para.nCharOfs-1; + undo->nStart = pNext->member.para.nCharOfs - end_len; assert(pNext->member.para.pFmt->cbSize == sizeof(PARAFORMAT2)); CopyMemory(undo->di.member.para.pFmt, pNext->member.para.pFmt, sizeof(PARAFORMAT2)); } - shift = pNext->member.para.nCharOfs - tp->member.para.nCharOfs - 1; + shift = pNext->member.para.nCharOfs - tp->member.para.nCharOfs - end_len; pRun = ME_FindItemBack(pNext, diRunOrParagraph); pFirstRunInNext = ME_FindItemFwd(pNext, diRunOrParagraph); @@ -218,7 +220,7 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp) ME_Remove(pNext); ME_DestroyDisplayItem(pNext); - ME_PropagateCharOffset(tp->member.para.next_para, -1); + ME_PropagateCharOffset(tp->member.para.next_para, -end_len); ME_CheckCharOffsets(editor); diff --git a/reactos/lib/riched20/row.c b/reactos/lib/riched20/row.c index 1e4e208a97a..b803ed21302 100644 --- a/reactos/lib/riched20/row.c +++ b/reactos/lib/riched20/row.c @@ -82,3 +82,49 @@ ME_DisplayItem *ME_RowEnd(ME_DisplayItem *item) { if (!item2) return NULL; return ME_FindItemBack(item, diRun); } + + +ME_DisplayItem * +ME_FindRowWithNumber(ME_TextEditor *editor, int nRow) +{ + ME_DisplayItem *item = ME_FindItemFwd(editor->pBuffer->pFirst, diParagraph); + int nCount = 0; + + while (item && nCount + item->member.para.nRows <= nRow) + { + nCount += item->member.para.nRows; + item = ME_FindItemFwd(item, diParagraph); + } + if (!item) + return item; + for (item = ME_FindItemFwd(item, diStartRow); item && nCount < nRow; nCount++) + item = ME_FindItemFwd(item, diStartRow); + return item; +} + + +int +ME_RowNumberFromCharOfs(ME_TextEditor *editor, int nOfs) +{ + ME_DisplayItem *item = editor->pBuffer->pFirst->next; + int nRow = 0; + + while (item && item->member.para.next_para->member.para.nCharOfs <= nOfs) + { + nRow += item->member.para.nRows; + item = ME_FindItemFwd(item, diParagraph); + } + if (item) + { + nOfs -= item->member.para.nCharOfs; + item = ME_FindItemFwd(item, diRun); + while ((item = ME_FindItemFwd(item, diStartRowOrParagraph)) != NULL) + { + item = ME_FindItemFwd(item, diRun); + if (item->member.run.nCharOfs > nOfs) + break; + nRow++; + } + } + return nRow; +} diff --git a/reactos/lib/riched20/run.c b/reactos/lib/riched20/run.c index 2c8edb2b851..eab74012fe1 100644 --- a/reactos/lib/riched20/run.c +++ b/reactos/lib/riched20/run.c @@ -97,7 +97,10 @@ void ME_CheckCharOffsets(ME_TextEditor *editor) p->member.run.nFlags, p->member.run.style->fmt.dwMask & p->member.run.style->fmt.dwEffects); assert(ofs == p->member.run.nCharOfs); - ofs += ME_StrLen(p->member.run.strText); + if (p->member.run.nFlags & MERF_ENDPARA) + ofs += (editor->bEmulateVersion10 ? 2 : 1); + else + ofs += ME_StrLen(p->member.run.strText); break; default: assert(0); @@ -639,9 +642,6 @@ void ME_GetCharFormat(ME_TextEditor *editor, int nFrom, int nTo, CHARFORMAT2W *p int nOffset, nOffset2; CHARFORMAT2W tmp; - if (nTo>nFrom) /* selection consists of chars from nFrom up to nTo-1 */ - nTo--; - ME_RunOfsFromCharOfs(editor, nFrom, &run, &nOffset); if (nFrom == nTo) /* special case - if selection is empty, take previous char's formatting */ { @@ -656,6 +656,9 @@ void ME_GetCharFormat(ME_TextEditor *editor, int nFrom, int nTo, CHARFORMAT2W *p ME_GetRunCharFormat(editor, run, pFmt); return; } + + if (nTo>nFrom) /* selection consists of chars from nFrom up to nTo-1 */ + nTo--; ME_RunOfsFromCharOfs(editor, nTo, &run_end, &nOffset2); ME_GetRunCharFormat(editor, run, pFmt); diff --git a/reactos/lib/riched20/style.c b/reactos/lib/riched20/style.c index 3bc8b9e4173..3cc543a3b9e 100644 --- a/reactos/lib/riched20/style.c +++ b/reactos/lib/riched20/style.c @@ -249,14 +249,23 @@ void ME_DumpStyleToBuf(CHARFORMAT2W *pFmt, char buf[2048]) ME_DumpStyleEffect(&p, "Text protected:", pFmt, CFM_PROTECTED); } -void ME_LogFontFromStyle(HDC hDC, LOGFONTW *lf, ME_Style *s) + +static void +ME_LogFontFromStyle(HDC hDC, LOGFONTW *lf, ME_Style *s, int nZoomNumerator, int nZoomDenominator) { int rx, ry; rx = GetDeviceCaps(hDC, LOGPIXELSX); ry = GetDeviceCaps(hDC, LOGPIXELSY); ZeroMemory(lf, sizeof(LOGFONTW)); lstrcpyW(lf->lfFaceName, s->fmt.szFaceName); - lf->lfHeight = -s->fmt.yHeight*ry/1440; + + if (nZoomNumerator == 0) + { + nZoomNumerator = 1; + nZoomDenominator = 1; + } + lf->lfHeight = -s->fmt.yHeight*ry*nZoomNumerator/nZoomDenominator/1440; + lf->lfWeight = 400; if (s->fmt.dwEffects & s->fmt.dwMask & CFM_BOLD) lf->lfWeight = 700; @@ -294,7 +303,7 @@ HFONT ME_SelectStyleFont(ME_TextEditor *editor, HDC hDC, ME_Style *s) assert(hDC); assert(s); - ME_LogFontFromStyle(hDC, &lf, s); + ME_LogFontFromStyle(hDC, &lf, s, editor->nZoomNumerator, editor->nZoomDenominator); for (i=0; ipFontCache[i].nAge++; diff --git a/reactos/lib/riched20/wrap.c b/reactos/lib/riched20/wrap.c index d48da585942..2da74a17bcd 100644 --- a/reactos/lib/riched20/wrap.c +++ b/reactos/lib/riched20/wrap.c @@ -42,7 +42,7 @@ ME_DisplayItem *ME_MakeRow(int height, int baseline, int width) return item; } -void ME_BeginRow(ME_WrapContext *wc) +static void ME_BeginRow(ME_WrapContext *wc) { wc->pRowStart = NULL; wc->bOverflown = FALSE; @@ -91,7 +91,7 @@ void ME_InsertRowStart(ME_WrapContext *wc, ME_DisplayItem *pEnd) ME_BeginRow(wc); } -void ME_WrapEndParagraph(ME_WrapContext *wc, ME_DisplayItem *p) +static void ME_WrapEndParagraph(ME_WrapContext *wc, ME_DisplayItem *p) { if (wc->pRowStart) ME_InsertRowStart(wc, p->next); @@ -111,7 +111,7 @@ void ME_WrapEndParagraph(ME_WrapContext *wc, ME_DisplayItem *p) */ } -void ME_WrapSizeRun(ME_WrapContext *wc, ME_DisplayItem *p) +static void ME_WrapSizeRun(ME_WrapContext *wc, ME_DisplayItem *p) { /* FIXME compose style (out of character and paragraph styles) here */ @@ -120,7 +120,7 @@ void ME_WrapSizeRun(ME_WrapContext *wc, ME_DisplayItem *p) ME_CalcRunExtent(wc->context, &ME_GetParagraph(p)->member.para, &p->member.run); } -ME_DisplayItem *ME_MaximizeSplit(ME_WrapContext *wc, ME_DisplayItem *p, int i) +static ME_DisplayItem *ME_MaximizeSplit(ME_WrapContext *wc, ME_DisplayItem *p, int i) { ME_DisplayItem *pp, *piter = p; int j; @@ -162,7 +162,7 @@ ME_DisplayItem *ME_MaximizeSplit(ME_WrapContext *wc, ME_DisplayItem *p, int i) } } -ME_DisplayItem *ME_SplitByBacktracking(ME_WrapContext *wc, ME_DisplayItem *p, int loc) +static ME_DisplayItem *ME_SplitByBacktracking(ME_WrapContext *wc, ME_DisplayItem *p, int loc) { ME_DisplayItem *piter = p, *pp; int i, idesp, len; @@ -242,7 +242,7 @@ ME_DisplayItem *ME_SplitByBacktracking(ME_WrapContext *wc, ME_DisplayItem *p, in } } -ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p) +static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p) { ME_DisplayItem *pp; ME_Run *run; @@ -375,12 +375,15 @@ void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) { ME_WrapEndParagraph(&wc, p); tp->member.para.nFlags &= ~MEPF_REWRAP; tp->member.para.nHeight = wc.pt.y; + tp->member.para.nRows = wc.nRow; } void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp) { ME_DisplayItem *p; + /* remove all items that will be reinserted by paragraph wrapper anyway */ + tp->member.para.nRows = 0; for (p = tp->next; p!=tp->member.para.next_para; p = p->next) { switch(p->type) { case diStartRow: diff --git a/reactos/lib/riched20/writer.c b/reactos/lib/riched20/writer.c index 176c1619e79..a6aba952472 100644 --- a/reactos/lib/riched20/writer.c +++ b/reactos/lib/riched20/writer.c @@ -33,6 +33,7 @@ ME_StreamOutInit(ME_TextEditor *editor, EDITSTREAM *stream) { editor->pStream = ALLOC_OBJ(ME_OutStream); editor->pStream->stream = stream; + editor->pStream->stream->dwError = 0; editor->pStream->pos = 0; editor->pStream->written = 0; editor->pStream->nFontTblLen = 0; @@ -108,7 +109,7 @@ ME_StreamOutMove(ME_TextEditor *editor, BYTE *buffer, int len) static BOOL -ME_StreamOutPrint(ME_TextEditor *editor, char *format, ...) +ME_StreamOutPrint(ME_TextEditor *editor, const char *format, ...) { char string[STREAMOUT_BUFFER_SIZE]; /* This is going to be enough */ int len; @@ -125,7 +126,7 @@ ME_StreamOutPrint(ME_TextEditor *editor, char *format, ...) static BOOL ME_StreamOutRTFHeader(ME_TextEditor *editor, int dwFormat) { - char *cCharSet = NULL; + const char *cCharSet = NULL; UINT nCodePage; LANGID language; BOOL success; @@ -567,7 +568,7 @@ ME_StreamOutRTFText(ME_TextEditor *editor, WCHAR *text, LONG nChars) { char buffer[STREAMOUT_BUFFER_SIZE]; int pos = 0; - int fit, i; + int fit, nBytes, i; if (nChars == -1) nChars = lstrlenW(text); @@ -577,18 +578,18 @@ ME_StreamOutRTFText(ME_TextEditor *editor, WCHAR *text, LONG nChars) if (editor->pStream->nDefaultCodePage == CP_UTF8) { /* 6 is the maximum character length in UTF-8 */ fit = min(nChars, STREAMOUT_BUFFER_SIZE / 6); - WideCharToMultiByte(CP_UTF8, 0, text, fit, buffer, STREAMOUT_BUFFER_SIZE, - NULL, NULL); + nBytes = WideCharToMultiByte(CP_UTF8, 0, text, fit, buffer, + STREAMOUT_BUFFER_SIZE, NULL, NULL); nChars -= fit; text += fit; - for (i = 0; buffer[i]; i++) + for (i = 0; i < nBytes; i++) if (buffer[i] == '{' || buffer[i] == '}' || buffer[i] == '\\') { if (!ME_StreamOutPrint(editor, "%.*s\\", i - pos, buffer + pos)) return FALSE; pos = i; } if (!pos) - if (!ME_StreamOutPrint(editor, "%s", buffer + pos)) + if (!ME_StreamOutMove(editor, buffer + pos, nBytes - pos)) return FALSE; pos = 0; } else if (*text < 128) { @@ -599,7 +600,6 @@ ME_StreamOutRTFText(ME_TextEditor *editor, WCHAR *text, LONG nChars) } else { BOOL unknown = FALSE; BYTE letter[3]; - int nBytes, i; /* FIXME: In the MS docs for WideCharToMultiByte there is a big list of * codepages including CP_SYMBOL for which the last parameter must be set @@ -759,11 +759,13 @@ ME_StreamOutText(ME_TextEditor *editor, int nStart, int nChars, DWORD dwFormat) } WideCharToMultiByte(nCodePage, 0, item->member.run.strText->szData + nStart, nLen, buffer, nSize, NULL, NULL); - success = ME_StreamOutMove(editor, buffer, nSize - 1); + success = ME_StreamOutMove(editor, buffer, nSize); } } nChars -= nLen; + if (editor->bEmulateVersion10 && nChars && item->member.run.nFlags & MERF_ENDPARA) + nChars--; nStart = 0; item = ME_FindItemFwd(item, diRun); } @@ -791,7 +793,7 @@ ME_StreamOut(ME_TextEditor *editor, DWORD dwFormat, EDITSTREAM *stream) nTo = ME_GetTextLength(editor); TRACE("from %d to %d\n", nStart, nTo); - if (dwFormat & SF_RTF || dwFormat & SF_RTFNOOBJS) + if (dwFormat & SF_RTF) ME_StreamOutRTF(editor, nStart, nTo - nStart, dwFormat); else if (dwFormat & SF_TEXT || dwFormat & SF_TEXTIZED) ME_StreamOutText(editor, nStart, nTo - nStart, dwFormat); diff --git a/reactos/w32api/include/richedit.h b/reactos/w32api/include/richedit.h index 6d135a55ecf..5a1a5fe046c 100644 --- a/reactos/w32api/include/richedit.h +++ b/reactos/w32api/include/richedit.h @@ -139,6 +139,9 @@ extern "C" { #define SFF_PERSISTVIEWSCALE 0x2000 #define SFF_PLAINRTF 0x4000 #define SFF_SELECTION 0x8000 +#define ST_DEFAULT 0x00000000 +#define ST_KEEPUNDO 0x00000001 +#define ST_SELECTION 0x00000002 #define WB_CLASSIFY 3 #define WB_MOVEWORDLEFT 4 #define WB_MOVEWORDRIGHT 5 @@ -225,6 +228,8 @@ extern "C" { #define EM_FINDTEXTW (WM_USER + 123) #define EM_FINDTEXTEXW (WM_USER + 124) #define EM_RECONVERSION (WM_USER + 125) +#define EM_SETIMEMODEBIAS (WM_USER + 126) +#define EM_GETIMEMODEBIAS (WM_USER + 127) #define EM_SETBIDIOPTIONS (WM_USER + 200) #define EM_GETBIDIOPTIONS (WM_USER + 201) #define EM_SETTYPOGRAPHYOPTIONS (WM_USER+202) @@ -510,6 +515,10 @@ typedef struct _gettextex { LPCSTR lpDefaultChar; LPBOOL lpUsedDefaultChar; } GETTEXTEX; +typedef struct _settextex { + DWORD flags; + UINT codepage; +} SETTEXTEX; typedef LONG (*EDITWORDBREAKPROCEX)(char*,LONG,BYTE,INT); /* Defines for EM_SETTYPOGRAPHYOPTIONS */ #define TO_ADVANCEDTYPOGRAPHY 1