From 5e9875c6792b7a0b213a1dee990a745fbae45bcd Mon Sep 17 00:00:00 2001 From: Gregor Schneider Date: Thu, 16 Apr 2009 17:49:22 +0000 Subject: [PATCH] - Sync riched20 with Wine 1.1.19 - Fixes a problem where the richedit control forwarded messages to itself through user32, also known as the Winrar installation stack overflow, bug #4197 svn path=/trunk/; revision=40545 --- reactos/dll/win32/riched20/caret.c | 242 +++++++-------- reactos/dll/win32/riched20/context.c | 6 +- reactos/dll/win32/riched20/editor.c | 431 +++++++++++++-------------- reactos/dll/win32/riched20/editor.h | 20 +- reactos/dll/win32/riched20/editstr.h | 17 +- reactos/dll/win32/riched20/list.c | 10 - reactos/dll/win32/riched20/paint.c | 60 ++-- reactos/dll/win32/riched20/para.c | 70 +++-- reactos/dll/win32/riched20/reader.c | 5 + reactos/dll/win32/riched20/richole.c | 222 +++++++------- reactos/dll/win32/riched20/row.c | 66 +--- reactos/dll/win32/riched20/run.c | 148 +++++---- reactos/dll/win32/riched20/string.c | 192 +++--------- reactos/dll/win32/riched20/style.c | 6 - reactos/dll/win32/riched20/table.c | 27 +- reactos/dll/win32/riched20/txthost.c | 13 +- reactos/dll/win32/riched20/txtsrv.c | 4 +- reactos/dll/win32/riched20/undo.c | 4 +- reactos/dll/win32/riched20/wrap.c | 35 +-- reactos/dll/win32/riched20/writer.c | 18 +- 20 files changed, 711 insertions(+), 885 deletions(-) diff --git a/reactos/dll/win32/riched20/caret.c b/reactos/dll/win32/riched20/caret.c index cdd8f798415..2151e435e35 100644 --- a/reactos/dll/win32/riched20/caret.c +++ b/reactos/dll/win32/riched20/caret.c @@ -42,7 +42,9 @@ void ME_GetSelection(ME_TextEditor *editor, int *from, int *to) int ME_GetTextLength(ME_TextEditor *editor) { - return ME_CharOfsFromRunOfs(editor, ME_FindItemBack(editor->pBuffer->pLast, diRun), 0); + ME_DisplayItem *pLast = editor->pBuffer->pLast; + return ME_CharOfsFromRunOfs(editor, pLast->member.para.prev_para, + ME_FindItemBack(pLast, diRun), 0); } @@ -93,9 +95,11 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to) /* select all */ if (from == 0 && to == -1) { - editor->pCursors[1].pRun = ME_FindItemFwd(editor->pBuffer->pFirst, diRun); - editor->pCursors[1].nOffset = 0; - editor->pCursors[0].pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun); + editor->pCursors[1].pPara = editor->pBuffer->pFirst->member.para.next_para; + editor->pCursors[1].pRun = ME_FindItemFwd(editor->pCursors[1].pPara, diRun); + editor->pCursors[1].nOffset = 0; + editor->pCursors[0].pPara = editor->pBuffer->pLast->member.para.prev_para; + editor->pCursors[0].pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun); editor->pCursors[0].nOffset = 0; ME_InvalidateSelection(editor); ME_ClearTempStyle(editor); @@ -144,8 +148,10 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to) if (selectionEnd) { - editor->pCursors[1].pRun = editor->pCursors[0].pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun); - editor->pCursors[1].nOffset = editor->pCursors[0].nOffset = 0; + editor->pCursors[0].pPara = editor->pBuffer->pLast->member.para.prev_para; + editor->pCursors[0].pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun); + editor->pCursors[0].nOffset = 0; + editor->pCursors[1] = editor->pCursors[0]; ME_InvalidateSelection(editor); ME_ClearTempStyle(editor); return len; @@ -166,69 +172,58 @@ void ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor, int *x, int *y, int *height) { - ME_DisplayItem *pCursorRun = pCursor->pRun; - ME_DisplayItem *pSizeRun = pCursor->pRun; + ME_DisplayItem *row; + ME_DisplayItem *run = pCursor->pRun; + ME_DisplayItem *para = pCursor->pPara; + ME_DisplayItem *pSizeRun = run; + ME_Context c; + SIZE sz = {0, 0}; assert(height && x && y); - assert(!(ME_GetParagraph(pCursorRun)->member.para.nFlags & MEPF_REWRAP)); - assert(pCursor->pRun); - assert(pCursor->pRun->type == diRun); + assert(~para->member.para.nFlags & MEPF_REWRAP); + assert(run && run->type == diRun); + assert(para && para->type == diParagraph); - if (pCursorRun->type == diRun) { - ME_DisplayItem *row = ME_FindItemBack(pCursorRun, diStartRowOrParagraph); + row = ME_FindItemBack(run, diStartRowOrParagraph); + assert(row && row->type == diStartRow); - if (row) { - HDC hDC = ITextHost_TxGetDC(editor->texthost); - ME_Context c; - ME_DisplayItem *run = pCursorRun; - ME_DisplayItem *para = NULL; - SIZE sz = {0, 0}; + ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost)); - ME_InitContext(&c, editor, hDC); - - if (!pCursor->nOffset) - { - ME_DisplayItem *prev = ME_FindItemBack(pCursorRun, diRunOrParagraph); - assert(prev); - if (prev->type == diRun) - pSizeRun = prev; - } - assert(row->type == diStartRow); /* paragraph -> run without start row ?*/ - para = ME_FindItemBack(row, diParagraph); - assert(para); - assert(para->type == diParagraph); - if (editor->bCaretAtEnd && !pCursor->nOffset && - run == ME_FindItemFwd(row, diRun)) - { - ME_DisplayItem *tmp = ME_FindItemBack(row, diRunOrParagraph); - assert(tmp); - if (tmp->type == diRun) - { - row = ME_FindItemBack(tmp, diStartRow); - pSizeRun = run = tmp; - assert(run); - assert(run->type == diRun); - sz = ME_GetRunSize(&c, ¶->member.para, - &run->member.run, ME_StrLen(run->member.run.strText), - row->member.row.nLMargin); - } - } - if (pCursor->nOffset) { - sz = ME_GetRunSize(&c, ¶->member.para, &run->member.run, pCursor->nOffset, - row->member.row.nLMargin); - } - - *height = pSizeRun->member.run.nAscent + pSizeRun->member.run.nDescent; - *x = c.rcView.left + run->member.run.pt.x + sz.cx - editor->horz_si.nPos; - *y = c.rcView.top + para->member.para.pt.y + row->member.row.nBaseline - + run->member.run.pt.y - pSizeRun->member.run.nAscent - editor->vert_si.nPos; - ME_DestroyContext(&c); - return; + if (!pCursor->nOffset) + { + ME_DisplayItem *prev = ME_FindItemBack(run, diRunOrParagraph); + assert(prev); + if (prev->type == diRun) + pSizeRun = prev; + } + if (editor->bCaretAtEnd && !pCursor->nOffset && + run == ME_FindItemFwd(row, diRun)) + { + ME_DisplayItem *tmp = ME_FindItemBack(row, diRunOrParagraph); + assert(tmp); + if (tmp->type == diRun) + { + row = ME_FindItemBack(tmp, diStartRow); + pSizeRun = run = tmp; + assert(run); + assert(run->type == diRun); + sz = ME_GetRunSize(&c, ¶->member.para, + &run->member.run, run->member.run.strText->nLen, + row->member.row.nLMargin); } } - *height = 10; /* FIXME use global font */ - *x = 0; - *y = 0; + if (pCursor->nOffset) { + sz = ME_GetRunSize(&c, ¶->member.para, &run->member.run, + pCursor->nOffset, row->member.row.nLMargin); + } + + *height = pSizeRun->member.run.nAscent + pSizeRun->member.run.nDescent; + *x = c.rcView.left + run->member.run.pt.x + sz.cx - editor->horz_si.nPos; + *y = c.rcView.top + para->member.para.pt.y + row->member.row.nBaseline + + run->member.run.pt.y - pSizeRun->member.run.nAscent + - editor->vert_si.nPos; + ME_DestroyContext(&c); + return; } @@ -237,8 +232,6 @@ ME_MoveCaret(ME_TextEditor *editor) { int x, y, height; - if (ME_WrapMarkedParagraphs(editor)) - ME_UpdateScrollBar(editor); ME_GetCursorCoordinates(editor, &editor->pCursors[0], &x, &y, &height); if(editor->bHaveFocus && !ME_IsSelection(editor)) { @@ -273,17 +266,11 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars, int totalChars = nChars; ME_DisplayItem *start_para; - { - /* Prevent deletion past last end of paragraph run. */ - ME_DisplayItem *pTextEnd = editor->pBuffer->pLast; - int nMaxChars = pTextEnd->member.para.prev_para->member.para.nCharOfs; - nMaxChars += ME_FindItemBack(pTextEnd, diRun)->member.run.nCharOfs; - nMaxChars -= nOfs; - nChars = min(nChars, nMaxChars); - } + /* Prevent deletion past last end of paragraph run. */ + nChars = min(nChars, ME_GetTextLength(editor) - nOfs); ME_CursorFromCharOfs(editor, nOfs, &c); - start_para = ME_GetParagraph(c.pRun); + start_para = c.pPara; if (!bForce) { @@ -298,11 +285,12 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars, ME_CursorFromCharOfs(editor, nOfs+nChars, &c); if (!c.nOffset && nOfs+nChars == (c.pRun->member.run.nCharOfs - + ME_GetParagraph(c.pRun)->member.para.nCharOfs)) + + c.pPara->member.para.nCharOfs)) { /* We aren't deleting anything in this run, so we will go back to the * last run we are deleting text in. */ c.pRun = ME_FindItemBack(c.pRun, diRun); + c.pPara = ME_GetParagraph(c.pRun); c.nOffset = c.pRun->member.run.strText->nLen; } run = &c.pRun->member.run; @@ -338,7 +326,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars, keepFirstParaFormat = TRUE; } } - ME_JoinParagraphs(editor, ME_GetParagraph(c.pRun), keepFirstParaFormat); + ME_JoinParagraphs(editor, c.pPara, keepFirstParaFormat); /* ME_SkipAndPropagateCharOffset(p->pRun, shift); */ ME_CheckCharOffsets(editor); nChars -= (eollen < nChars) ? eollen : nChars; @@ -364,7 +352,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars, nCharsToDelete, nChars, c.nOffset, debugstr_w(run->strText->szData), run->strText->nLen); - if (!c.nOffset && ME_StrVLen(run->strText) == nCharsToDelete) + if (!c.nOffset && run->strText->nLen == nCharsToDelete) { /* undo = reinsert whole run */ /* nOfs is a character offset (from the start of the document @@ -386,10 +374,10 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars, TRACE("Post deletion string: %s (%d)\n", debugstr_w(run->strText->szData), run->strText->nLen); TRACE("Shift value: %d\n", shift); ME_StrDeleteV(run->strText, c.nOffset, nCharsToDelete); - + /* update cursors (including c) */ for (i=-1; inCursors; i++) { - ME_Cursor *pThisCur = editor->pCursors + i; + ME_Cursor *pThisCur = editor->pCursors + i; if (i == -1) pThisCur = &c; if (pThisCur->pRun == cursor.pRun) { if (pThisCur->nOffset > cursor.nOffset) { @@ -398,9 +386,9 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars, else pThisCur->nOffset -= nCharsToDelete; assert(pThisCur->nOffset >= 0); - assert(pThisCur->nOffset <= ME_StrVLen(run->strText)); + assert(pThisCur->nOffset <= run->strText->nLen); } - if (pThisCur->nOffset == ME_StrVLen(run->strText)) + if (pThisCur->nOffset == run->strText->nLen) { pThisCur->pRun = ME_FindItemFwd(pThisCur->pRun, diRunOrParagraphOrEnd); assert(pThisCur->pRun->type == diRun); @@ -408,21 +396,21 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars, } } } - + /* c = updated data now */ - + if (c.pRun == cursor.pRun) ME_SkipAndPropagateCharOffset(c.pRun, shift); else ME_PropagateCharOffset(c.pRun, shift); - if (!ME_StrVLen(cursor.pRun->member.run.strText)) + if (!cursor.pRun->member.run.strText->nLen) { TRACE("Removing useless run\n"); ME_Remove(cursor.pRun); ME_DestroyDisplayItem(cursor.pRun); } - + shift = 0; /* ME_CheckCharOffsets(editor); @@ -577,6 +565,7 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, /* ME_SplitParagraph increases style refcount */ tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, eol_str, 0); p->pRun = ME_FindItemFwd(tp, diRun); + p->pPara = ME_GetParagraph(p->pRun); end_run = ME_FindItemBack(tp, diRun); ME_ReleaseStyle(end_run->member.run.style); end_run->member.run.style = tmp_style; @@ -593,11 +582,12 @@ static BOOL ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs) { ME_DisplayItem *pRun = pCursor->pRun; - + if (nRelOfs == -1) { if (!pCursor->nOffset) { + ME_DisplayItem *pPara = pCursor->pPara; do { pRun = ME_FindItemBack(pRun, diRunOrParagraph); assert(pRun); @@ -606,9 +596,11 @@ ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs) case diRun: break; case diParagraph: - if (pRun->member.para.prev_para->type == diTextStart) + pPara = pRun; + if (pPara->member.para.prev_para->type == diTextStart) return FALSE; - pRun = ME_FindItemBack(pRun, diRunOrParagraph); + pRun = ME_FindItemBack(pPara, diRunOrParagraph); + pPara = pPara->member.para.prev_para; /* every paragraph ought to have at least one run */ assert(pRun && pRun->type == diRun); assert(pRun->member.run.nFlags & MERF_ENDPARA); @@ -619,23 +611,24 @@ ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs) } } while (RUN_IS_HIDDEN(&pRun->member.run) || pRun->member.run.nFlags & MERF_HIDDEN); + pCursor->pPara = pPara; pCursor->pRun = pRun; if (pRun->member.run.nFlags & MERF_ENDPARA) pCursor->nOffset = 0; else pCursor->nOffset = pRun->member.run.strText->nLen; } - + if (pCursor->nOffset) - pCursor->nOffset = ME_StrRelPos2(pCursor->pRun->member.run.strText, pCursor->nOffset, nRelOfs); + pCursor->nOffset = pCursor->nOffset + nRelOfs; return TRUE; } else { if (!(pRun->member.run.nFlags & MERF_ENDPARA)) { - int new_ofs = ME_StrRelPos2(pRun->member.run.strText, pCursor->nOffset, nRelOfs); - + int new_ofs = pCursor->nOffset + nRelOfs; + if (new_ofs < pRun->member.run.strText->nLen) { pCursor->nOffset = new_ofs; @@ -648,6 +641,7 @@ ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs) pRun->member.run.nFlags & MERF_HIDDEN)); if (pRun) { + pCursor->pPara = ME_GetParagraph(pRun); pCursor->pRun = pRun; pCursor->nOffset = 0; return TRUE; @@ -670,7 +664,7 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) { nOffset = ME_CallWordBreakProc(editor, pRun->member.run.strText, nOffset, WB_MOVEWORDLEFT); - if (nOffset) + if (nOffset) break; pOtherRun = ME_FindItemBack(pRun, diRunOrParagraph); if (pOtherRun->type == diRun) @@ -697,7 +691,7 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) if (pOtherRun->member.para.prev_para->type == diTextStart) return FALSE; - pRun = ME_FindItemBack(pOtherRun, diRunOrParagraph); + pRun = ME_FindItemBack(pOtherRun, diRun); } break; } @@ -743,6 +737,7 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) } } } + cursor->pPara = ME_GetParagraph(pRun); cursor->pRun = pRun; cursor->nOffset = nOffset; return TRUE; @@ -786,18 +781,22 @@ ME_SelectByType(ME_TextEditor *editor, ME_SelectionType selectionType) editor->pCursors[0].pRun = ME_FindItemBack(pItem, diRun); else editor->pCursors[0].pRun = ME_FindItemFwd(pItem, diRun); + editor->pCursors[0].pPara = ME_GetParagraph(editor->pCursors[0].pRun); editor->pCursors[0].nOffset = 0; pItem = ME_FindItemBack(pItem, backSearchType); editor->pCursors[1].pRun = ME_FindItemFwd(pItem, diRun); + editor->pCursors[1].pPara = ME_GetParagraph(editor->pCursors[1].pRun); editor->pCursors[1].nOffset = 0; break; } case stDocument: /* Select everything with cursor anchored from the start of the text */ editor->nSelectionType = stDocument; - editor->pCursors[1].pRun = ME_FindItemFwd(editor->pBuffer->pFirst, diRun); + editor->pCursors[1].pPara = editor->pBuffer->pFirst->member.para.next_para; + editor->pCursors[1].pRun = ME_FindItemFwd(editor->pCursors[1].pPara, diRun); editor->pCursors[1].nOffset = 0; + editor->pCursors[0].pPara = editor->pBuffer->pLast->member.para.prev_para; editor->pCursors[0].pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun); editor->pCursors[0].nOffset = 0; break; @@ -811,8 +810,8 @@ ME_SelectByType(ME_TextEditor *editor, ME_SelectionType selectionType) int ME_GetCursorOfs(ME_TextEditor *editor, int nCursor) { ME_Cursor *pCursor = &editor->pCursors[nCursor]; - return ME_GetParagraph(pCursor->pRun)->member.para.nCharOfs - + pCursor->pRun->member.run.nCharOfs + pCursor->nOffset; + return pCursor->pPara->member.para.nCharOfs + + pCursor->pRun->member.run.nCharOfs + pCursor->nOffset; } /* Helper function for ME_FindPixelPos to find paragraph within tables */ @@ -868,6 +867,7 @@ static BOOL ME_ReturnFoundPos(ME_TextEditor *editor, ME_DisplayItem *found, result->pRun = ME_FindItemFwd(editor->pCursors[0].pRun, diRun); result->nOffset = 0; } + result->pPara = ME_GetParagraph(result->pRun); return isExact; } @@ -968,6 +968,7 @@ static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y, last = p; } result->pRun = ME_FindItemBack(p, diRun); + result->pPara = ME_GetParagraph(result->pRun); result->nOffset = 0; assert(result->pRun->member.run.nFlags & MERF_ENDPARA); return FALSE; @@ -996,8 +997,8 @@ int ME_CharFromPos(ME_TextEditor *editor, int x, int y, BOOL *isExact) y += editor->vert_si.nPos; bResult = ME_FindPixelPos(editor, x, y, &cursor, NULL); if (isExact) *isExact = bResult; - return (ME_GetParagraph(cursor.pRun)->member.para.nCharOfs - + cursor.pRun->member.run.nCharOfs + cursor.nOffset); + return cursor.pPara->member.para.nCharOfs + + cursor.pRun->member.run.nCharOfs + cursor.nOffset; } @@ -1038,6 +1039,7 @@ static void ME_ExtendAnchorSelection(ME_TextEditor *editor) diStartRowOrParagraph:diParagraph); pItem = ME_FindItemBack(editor->pCursors[1].pRun, searchType); editor->pCursors[1].pRun = ME_FindItemFwd(pItem, diRun); + editor->pCursors[1].pPara = ME_GetParagraph(editor->pCursors[1].pRun); editor->pCursors[1].nOffset = 0; } } @@ -1057,6 +1059,7 @@ static void ME_ExtendAnchorSelection(ME_TextEditor *editor) editor->pCursors[0].pRun = ME_FindItemBack(pItem, diRun); else editor->pCursors[0].pRun = ME_FindItemFwd(pItem, diRun); + editor->pCursors[0].pPara = ME_GetParagraph(editor->pCursors[0].pRun); editor->pCursors[0].nOffset = 0; } } @@ -1272,8 +1275,6 @@ ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs) pItem = ME_FindItemFwd(pRun, diStartRow); if (!pItem) return; /* row not found - ignore */ - /* FIXME If diParagraph is before diStartRow, wrap the next paragraph? - */ pNewPara = ME_GetParagraph(pItem); if (pOldPara->member.para.nFlags & MEPF_ROWSTART || (pOldPara->member.para.pCell && @@ -1301,6 +1302,7 @@ ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs) return; } pCursor->pRun = ME_FindRunInRow(editor, pItem, x, &pCursor->nOffset, &editor->bCaretAtEnd); + pCursor->pPara = ME_GetParagraph(pCursor->pRun); assert(pCursor->pRun); assert(pCursor->pRun->type == diRun); } @@ -1311,7 +1313,8 @@ static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor) if (editor->vert_si.nPos < p->member.row.nHeight) { - pCursor->pRun = ME_FindItemFwd(editor->pBuffer->pFirst, diRun); + pCursor->pPara = editor->pBuffer->pFirst->member.para.next_para; + pCursor->pRun = ME_FindItemFwd(pCursor->pPara, diRun); pCursor->nOffset = 0; editor->bCaretAtEnd = FALSE; /* Native clears seems to clear this x value on page up at the top @@ -1357,6 +1360,7 @@ static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor) pCursor->pRun = ME_FindRunInRow(editor, pLast, x, &pCursor->nOffset, &editor->bCaretAtEnd); + pCursor->pPara = ME_GetParagraph(pCursor->pRun); } assert(pCursor->pRun); assert(pCursor->pRun->type == diRun); @@ -1376,6 +1380,7 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor) if (editor->vert_si.nPos >= y - editor->sizeWindow.cy) { + pCursor->pPara = editor->pBuffer->pLast->member.para.prev_para; pCursor->pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun); pCursor->nOffset = 0; editor->bCaretAtEnd = FALSE; @@ -1418,6 +1423,7 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor) pCursor->pRun = ME_FindRunInRow(editor, pLast, x, &pCursor->nOffset, &editor->bCaretAtEnd); + pCursor->pPara = ME_GetParagraph(pCursor->pRun); } assert(pCursor->pRun); assert(pCursor->pRun->type == diRun); @@ -1426,7 +1432,6 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor) static void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_DisplayItem *pRow = ME_FindItemBack(pCursor->pRun, diStartRow); - ME_WrapMarkedParagraphs(editor); if (pRow) { ME_DisplayItem *pRun; if (editor->bCaretAtEnd && !pCursor->nOffset) { @@ -1437,6 +1442,7 @@ static void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor) pRun = ME_FindItemFwd(pRow, diRun); if (pRun) { pCursor->pRun = pRun; + assert(pCursor->pPara == ME_GetParagraph(pRun)); pCursor->nOffset = 0; } } @@ -1445,48 +1451,42 @@ static void ME_ArrowHome(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) { - ME_DisplayItem *pRun = ME_FindItemFwd(pRow, diRun); - if (pRun) { - pCursor->pRun = pRun; - pCursor->nOffset = 0; - } - } + pCursor->pPara = editor->pBuffer->pFirst->member.para.next_para; + pCursor->pRun = ME_FindItemFwd(pCursor->pPara, diRun); + pCursor->nOffset = 0; + editor->bCaretAtEnd = FALSE; } static void ME_ArrowEnd(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_DisplayItem *pRow; - + if (editor->bCaretAtEnd && !pCursor->nOffset) return; - + pRow = ME_FindItemFwd(pCursor->pRun, diStartRowOrParagraphOrEnd); assert(pRow); if (pRow->type == diStartRow) { - /* FIXME WTF was I thinking about here ? */ ME_DisplayItem *pRun = ME_FindItemFwd(pRow, diRun); assert(pRun); pCursor->pRun = pRun; + assert(pCursor->pPara == ME_GetParagraph(pCursor->pRun)); pCursor->nOffset = 0; - editor->bCaretAtEnd = 1; + editor->bCaretAtEnd = TRUE; return; } pCursor->pRun = ME_FindItemBack(pRow, diRun); assert(pCursor->pRun && pCursor->pRun->member.run.nFlags & MERF_ENDPARA); + assert(pCursor->pPara == ME_GetParagraph(pCursor->pRun)); pCursor->nOffset = 0; editor->bCaretAtEnd = FALSE; } - + static void ME_ArrowCtrlEnd(ME_TextEditor *editor, ME_Cursor *pCursor) { - ME_DisplayItem *p = ME_FindItemFwd(pCursor->pRun, diTextEnd); - assert(p); - p = ME_FindItemBack(p, diRun); - assert(p); - assert(p->member.run.nFlags & MERF_ENDPARA); - pCursor->pRun = p; + pCursor->pPara = editor->pBuffer->pLast->member.para.prev_para; + pCursor->pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun); + assert(pCursor->pRun->member.run.nFlags & MERF_ENDPARA); pCursor->nOffset = 0; editor->bCaretAtEnd = FALSE; } diff --git a/reactos/dll/win32/riched20/context.c b/reactos/dll/win32/riched20/context.c index 6d4a2a93580..93d5caaed69 100644 --- a/reactos/dll/win32/riched20/context.c +++ b/reactos/dll/win32/riched20/context.c @@ -22,7 +22,7 @@ void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC) { - c->nSequence = editor->nSequence++; + c->nSequence = editor->nSequence++; c->hDC = hDC; c->editor = editor; c->pt.x = 0; @@ -35,6 +35,10 @@ void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC) } else { c->dpi.cx = c->dpi.cy = 96; } + if (editor->nAvailWidth) + c->nAvailWidth = ME_twips2pointsX(c, editor->nAvailWidth); + else + c->nAvailWidth = c->rcView.right - c->rcView.left; } void ME_DestroyContext(ME_Context *c) diff --git a/reactos/dll/win32/riched20/editor.c b/reactos/dll/win32/riched20/editor.c index 574118aede4..00fc38e21ca 100644 --- a/reactos/dll/win32/riched20/editor.c +++ b/reactos/dll/win32/riched20/editor.c @@ -69,7 +69,7 @@ ! - EM_GETTHUMB + EM_GETTEXTEX 2.0 + EM_GETTEXTLENGTHEX (GTL_PRECISE unimplemented) - - EM_GETTEXTMODE 2.0 + + EM_GETTEXTMODE 2.0 ? + EM_GETTEXTRANGE (ANSI&Unicode) - EM_GETTYPOGRAPHYOPTIONS 3.0 - EM_GETUNDONAME @@ -507,7 +507,7 @@ void ME_RTFParAttrHook(RTF_Info *info) /* We are just after a table row. */ RTFFlushOutputBuffer(info); cursor = info->editor->pCursors[0]; - para = ME_GetParagraph(cursor.pRun); + para = cursor.pPara; if (para == info->tableDef->tableRowStart->member.para.next_para && !cursor.nOffset && !cursor.pRun->member.run.nCharOfs) { @@ -860,7 +860,7 @@ void ME_RTFTblAttrHook(RTF_Info *info) if (cellNum < MAX_TAB_STOPS) { /* Tab stops were used to store cell positions before v4.1 but v4.1 * still seems to set the tabstops without using them. */ - ME_DisplayItem *para = ME_GetParagraph(info->editor->pCursors[0].pRun); + ME_DisplayItem *para = info->editor->pCursors[0].pPara; PARAFORMAT2 *pFmt = para->member.para.pFmt; pFmt->rgxTabs[cellNum] &= ~0x00FFFFFF; pFmt->rgxTabs[cellNum] = 0x00FFFFFF & info->rtfParam; @@ -931,7 +931,7 @@ void ME_RTFSpecialCharHook(RTF_Info *info) ME_InsertTableCellFromCursor(info->editor); } } else { /* v1.0 - v3.0 */ - ME_DisplayItem *para = ME_GetParagraph(info->editor->pCursors[0].pRun); + ME_DisplayItem *para = info->editor->pCursors[0].pPara; PARAFORMAT2 *pFmt = para->member.para.pFmt; if (pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE && tableDef->numCellsInserted < tableDef->numCellsDefined) @@ -1009,6 +1009,7 @@ void ME_RTFSpecialCharHook(RTF_Info *info) int nOfs, nChars; /* Delete inserted cells that aren't defined. */ info->editor->pCursors[1].pRun = run; + info->editor->pCursors[1].pPara = ME_GetParagraph(run); info->editor->pCursors[1].nOffset = 0; nOfs = ME_GetCursorOfs(info->editor, 1); nChars = ME_GetCursorOfs(info->editor, 0) - nOfs; @@ -1038,12 +1039,11 @@ void ME_RTFSpecialCharHook(RTF_Info *info) } } else { /* v1.0 - v3.0 */ WCHAR endl = '\r'; - ME_DisplayItem *para = ME_GetParagraph(info->editor->pCursors[0].pRun); + ME_DisplayItem *para = info->editor->pCursors[0].pPara; PARAFORMAT2 *pFmt = para->member.para.pFmt; pFmt->dxOffset = info->tableDef->gapH; pFmt->dxStartIndent = info->tableDef->leftEdge; - para = ME_GetParagraph(info->editor->pCursors[0].pRun); ME_ApplyBorderProperties(info, ¶->member.para.border, tableDef->border); while (tableDef->numCellsInserted < tableDef->numCellsDefined) @@ -1066,7 +1066,7 @@ void ME_RTFSpecialCharHook(RTF_Info *info) ME_DisplayItem *para; PARAFORMAT2 *pFmt; RTFFlushOutputBuffer(info); - para = ME_GetParagraph(info->editor->pCursors[0].pRun); + para = info->editor->pCursors[0].pPara; pFmt = para->member.para.pFmt; if (pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) { @@ -1404,16 +1404,18 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre /* Don't insert text at the end of the table row */ if (!editor->bEmulateVersion10) { /* v4.1 */ - ME_DisplayItem *para = ME_GetParagraph(editor->pCursors->pRun); + ME_DisplayItem *para = editor->pCursors->pPara; if (para->member.para.nFlags & MEPF_ROWEND) { para = para->member.para.next_para; + editor->pCursors[0].pPara = para; editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); editor->pCursors[0].nOffset = 0; } if (para->member.para.nFlags & MEPF_ROWSTART) { para = para->member.para.next_para; + editor->pCursors[0].pPara = para; editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); editor->pCursors[0].nOffset = 0; } @@ -1425,16 +1427,13 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre } } else { - ME_DisplayItem *para_item; style = editor->pBuffer->pDefaultStyle; ME_AddRefStyle(style); ME_SetSelection(editor, 0, 0); ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor), FALSE); from = to = 0; ME_ClearTempStyle(editor); - - para_item = ME_GetParagraph(editor->pCursors[0].pRun); - ME_SetDefaultParaFormat(para_item->member.para.pFmt); + ME_SetDefaultParaFormat(editor->pCursors[0].pPara->member.para.pFmt); } @@ -1517,6 +1516,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre } pCell = para->member.para.pCell; + editor->pCursors[1].pPara = para; editor->pCursors[1].pRun = ME_FindItemFwd(para, diRun); editor->pCursors[1].nOffset = 0; nOfs = ME_GetCursorOfs(editor, 1); @@ -1637,7 +1637,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH TRACE("flags==0x%08x, chrg->cpMin==%d, chrg->cpMax==%d text==%s\n", flags, chrg->cpMin, chrg->cpMax, debugstr_w(text)); - + if (flags & ~(FR_DOWN | FR_MATCHCASE | FR_WHOLEWORD)) FIXME("Flags 0x%08x not implemented\n", flags & ~(FR_DOWN | FR_MATCHCASE | FR_WHOLEWORD)); @@ -1647,7 +1647,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH nMax = nTextLen; else nMax = chrg->cpMax > nTextLen ? nTextLen : chrg->cpMax; - + /* In 1.0 emulation, if cpMax reaches end of text, add the FR_DOWN flag */ if (editor->bEmulateVersion10 && nMax == nTextLen) { @@ -1687,33 +1687,18 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH chrgText->cpMin = chrgText->cpMax = -1; return -1; } - + if (flags & FR_DOWN) /* Forward search */ { /* If possible, find the character before where the search starts */ if ((flags & FR_WHOLEWORD) && nMin) { - nStart = nMin - 1; - ME_RunOfsFromCharOfs(editor, nStart, &item, &nStart); - if (!item) - { - if (chrgText) - chrgText->cpMin = chrgText->cpMax = -1; - return -1; - } + ME_RunOfsFromCharOfs(editor, nMin - 1, NULL, &item, &nStart); wLastChar = item->member.run.strText->szData[nStart]; } - nStart = nMin; - ME_RunOfsFromCharOfs(editor, nStart, &item, &nStart); - if (!item) - { - if (chrgText) - chrgText->cpMin = chrgText->cpMax = -1; - return -1; - } + ME_RunOfsFromCharOfs(editor, nMin, ¶, &item, &nStart); - para = ME_GetParagraph(item); while (item && para->member.para.nCharOfs + item->member.run.nCharOfs + nStart + nLen <= nMax) { @@ -1736,7 +1721,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH /* Check to see if next character is a whitespace */ if (flags & FR_WHOLEWORD) { - if (nCurStart + nMatched == ME_StrLen(pCurItem->member.run.strText)) + if (nCurStart + nMatched == pCurItem->member.run.strText->nLen) { pNextItem = ME_FindItemFwd(pCurItem, diRun); nNextStart = -nMatched; @@ -1760,10 +1745,9 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH TRACE("found at %d-%d\n", nStart, nStart + nLen); return nStart; } - if (nCurStart + nMatched == ME_StrLen(pCurItem->member.run.strText)) + if (nCurStart + nMatched == pCurItem->member.run.strText->nLen) { pCurItem = ME_FindItemFwd(pCurItem, diRun); - para = ME_GetParagraph(pCurItem); nCurStart = -nMatched; } } @@ -1773,7 +1757,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH wLastChar = ' '; nStart++; - if (nStart == ME_StrLen(item->member.run.strText)) + if (nStart == item->member.run.strText->nLen) { item = ME_FindItemFwd(item, diRun); para = ME_GetParagraph(item); @@ -1786,42 +1770,25 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH /* If possible, find the character after where the search ends */ if ((flags & FR_WHOLEWORD) && nMax < nTextLen - 1) { - nEnd = nMax + 1; - ME_RunOfsFromCharOfs(editor, nEnd, &item, &nEnd); - if (!item) - { - if (chrgText) - chrgText->cpMin = chrgText->cpMax = -1; - return -1; - } + ME_RunOfsFromCharOfs(editor, nMax + 1, NULL, &item, &nEnd); wLastChar = item->member.run.strText->szData[nEnd]; } - nEnd = nMax; - ME_RunOfsFromCharOfs(editor, nEnd, &item, &nEnd); - if (!item) - { - if (chrgText) - chrgText->cpMin = chrgText->cpMax = -1; - return -1; - } - - para = ME_GetParagraph(item); - + ME_RunOfsFromCharOfs(editor, nMax, ¶, &item, &nEnd); + while (item && para->member.para.nCharOfs + item->member.run.nCharOfs + nEnd - nLen >= nMin) { ME_DisplayItem *pCurItem = item; int nCurEnd = nEnd; int nMatched = 0; - - if (nCurEnd - nMatched == 0) + + if (nCurEnd == 0) { pCurItem = ME_FindItemBack(pCurItem, diRun); - para = ME_GetParagraph(pCurItem); - nCurEnd = ME_StrLen(pCurItem->member.run.strText) + nMatched; + nCurEnd = pCurItem->member.run.strText->nLen + nMatched; } - + while (pCurItem && ME_CharCompare(pCurItem->member.run.strText->szData[nCurEnd - nMatched - 1], text[nLen - nMatched - 1], (flags & FR_MATCHCASE))) { if ((flags & FR_WHOLEWORD) && isalnumW(wLastChar)) @@ -1841,7 +1808,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH { pPrevItem = ME_FindItemBack(pCurItem, diRun); if (pPrevItem) - nPrevEnd = ME_StrLen(pPrevItem->member.run.strText) + nMatched; + nPrevEnd = pPrevItem->member.run.strText->nLen + nMatched; } if (pPrevItem) @@ -1853,7 +1820,8 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH break; } - nStart = para->member.para.nCharOfs + pCurItem->member.run.nCharOfs + nCurEnd - nMatched; + nStart = ME_GetParagraph(pCurItem)->member.para.nCharOfs + + pCurItem->member.run.nCharOfs + nCurEnd - nMatched; if (chrgText) { chrgText->cpMin = nStart; @@ -1867,8 +1835,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH pCurItem = ME_FindItemBack(pCurItem, diRun); /* Don't care about pCurItem becoming NULL here; it's already taken * care of in the exterior loop condition */ - para = ME_GetParagraph(pCurItem); - nCurEnd = ME_StrLen(pCurItem->member.run.strText) + nMatched; + nCurEnd = pCurItem->member.run.strText->nLen + nMatched; } } if (pCurItem) @@ -1881,7 +1848,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH { item = ME_FindItemBack(item, diRun); para = ME_GetParagraph(item); - nEnd = ME_StrLen(item->member.run.strText); + nEnd = item->member.run.strText->nLen; } } } @@ -1939,20 +1906,16 @@ static int ME_GetTextEx(ME_TextEditor *editor, GETTEXTEX *ex, LPARAM pText) } } -static int ME_GetTextRange(ME_TextEditor *editor, TEXTRANGEW *rng, BOOL unicode) +static int ME_GetTextRange(ME_TextEditor *editor, WCHAR *strText, + int start, int nLen, BOOL unicode) { - if (unicode) - return ME_GetTextW(editor, rng->lpstrText, rng->chrg.cpMin, - rng->chrg.cpMax-rng->chrg.cpMin, 0); - else - { - int nLen = rng->chrg.cpMax-rng->chrg.cpMin; + if (unicode) { + return ME_GetTextW(editor, strText, start, nLen, 0); + } else { WCHAR *p = ALLOC_N_OBJ(WCHAR, nLen+1); - int nChars = ME_GetTextW(editor, p, rng->chrg.cpMin, nLen, 0); - /* FIXME this is a potential security hole (buffer overrun) - if you know more about wchar->mbyte conversion please explain - */ - WideCharToMultiByte(CP_ACP, 0, p, nChars+1, (char *)rng->lpstrText, nLen+1, NULL, NULL); + int nChars = ME_GetTextW(editor, p, start, nLen, 0); + WideCharToMultiByte(CP_ACP, 0, p, nChars+1, (char *)strText, + nLen+1, NULL, NULL); FREE_OBJ(p); return nChars; } @@ -2051,11 +2014,14 @@ ME_FilterEvent(ME_TextEditor *editor, UINT msg, WPARAM* wParam, LPARAM* lParam) { MSGFILTER msgf; + if (!editor->hWnd) return FALSE; + msgf.nmhdr.hwndFrom = editor->hWnd; + msgf.nmhdr.idFrom = GetWindowLongW(editor->hWnd, GWLP_ID); msgf.nmhdr.code = EN_MSGFILTER; msgf.msg = msg; msgf.wParam = *wParam; msgf.lParam = *lParam; - if (ITextHost_TxNotify(editor->texthost, msgf.nmhdr.code, &msgf) == S_OK) + if (SendMessageW(GetParent(editor->hWnd), WM_NOTIFY, msgf.nmhdr.idFrom, (LPARAM)&msgf)) return FALSE; *wParam = msgf.wParam; *lParam = msgf.lParam; @@ -2066,40 +2032,26 @@ ME_FilterEvent(ME_TextEditor *editor, UINT msg, WPARAM* wParam, LPARAM* lParam) static void ME_UpdateSelectionLinkAttribute(ME_TextEditor *editor) { - ME_DisplayItem * startPara, * endPara; - ME_DisplayItem * item; - ME_Cursor cursor; + ME_DisplayItem *startPara, *endPara; + ME_DisplayItem *prev_para; int from, to; + if (!editor->AutoURLDetect_bEnable) return; + ME_GetSelection(editor, &from, &to); - if (from > to) from ^= to, to ^=from, from ^= to; - startPara = NULL; endPara = NULL; /* Find paragraph previous to the one that contains start cursor */ - ME_CursorFromCharOfs(editor, from, &cursor); - item = cursor.pRun; - if (item) { - startPara = ME_FindItemBack(item, diParagraph); - item = startPara->member.para.prev_para; - if (item && item->type == diParagraph) startPara = item; - } + ME_RunOfsFromCharOfs(editor, from, &startPara, NULL, NULL); + prev_para = startPara->member.para.prev_para; + if (prev_para->type == diParagraph) startPara = prev_para; /* Find paragraph that contains end cursor */ - ME_CursorFromCharOfs(editor, to, &cursor); - item = cursor.pRun; - if (item) { - endPara = ME_FindItemFwd(item, diParagraph); - } + ME_RunOfsFromCharOfs(editor, to, &endPara, NULL, NULL); + endPara = endPara->member.para.next_para; - if (startPara && endPara) { - ME_UpdateLinkAttribute(editor, - startPara->member.para.nCharOfs, - endPara->member.para.nCharOfs); - } else if (startPara) { - ME_UpdateLinkAttribute(editor, - startPara->member.para.nCharOfs, - -1); - } + ME_UpdateLinkAttribute(editor, + startPara->member.para.nCharOfs, + endPara->member.para.nCharOfs); } static BOOL @@ -2171,7 +2123,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) if (editor->styleFlags & ES_MULTILINE) { ME_Cursor cursor = editor->pCursors[0]; - ME_DisplayItem *para = ME_GetParagraph(cursor.pRun); + ME_DisplayItem *para = cursor.pPara; int from, to; const WCHAR endl = '\r'; ME_Style *style; @@ -2189,6 +2141,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) /* Add a new table row after this row. */ para = ME_AppendTableRow(editor, para); para = para->member.para.next_para; + editor->pCursors[0].pPara = para; editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; @@ -2197,7 +2150,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) ME_UpdateRepaint(editor); return TRUE; } - else if (para == ME_GetParagraph(editor->pCursors[1].pRun) && + else if (para == editor->pCursors[1].pPara && cursor.nOffset + cursor.pRun->member.run.nCharOfs == 0 && para->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART && !para->member.para.prev_para->member.para.nCharOfs) @@ -2205,6 +2158,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) /* Insert a newline before the table. */ para = para->member.para.prev_para; para->member.para.nFlags &= ~MEPF_ROWSTART; + editor->pCursors[0].pPara = para; editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); editor->pCursors[1] = editor->pCursors[0]; ME_InsertTextFromCursor(editor, 0, &endl, 1, @@ -2212,6 +2166,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) para = editor->pBuffer->pFirst->member.para.next_para; ME_SetDefaultParaFormat(para->member.para.pFmt); para->member.para.nFlags = MEPF_REWRAP; + editor->pCursors[0].pPara = para; editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); editor->pCursors[1] = editor->pCursors[0]; para->member.para.next_para->member.para.nFlags |= MEPF_ROWSTART; @@ -2221,7 +2176,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) return TRUE; } } else { /* v1.0 - 3.0 */ - ME_DisplayItem *para = ME_GetParagraph(cursor.pRun); + ME_DisplayItem *para = cursor.pPara; if (ME_IsInTable(para)) { if (cursor.pRun->member.run.nFlags & MERF_ENDPARA) @@ -2229,6 +2184,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) if (from == to) { ME_ContinueCoalescingTransaction(editor); para = ME_AppendTableRow(editor, para); + editor->pCursors[0].pPara = para; editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; @@ -2243,8 +2199,10 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) { /* Insert newline before table */ cursor.pRun = ME_FindItemBack(para, diRun); - if (cursor.pRun) + if (cursor.pRun) { editor->pCursors[0].pRun = cursor.pRun; + editor->pCursors[0].pPara = para->member.para.prev_para; + } editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; ME_InsertTextFromCursor(editor, 0, &endl, 1, @@ -2252,6 +2210,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) } else { editor->pCursors[1] = editor->pCursors[0]; para = ME_AppendTableRow(editor, para); + editor->pCursors[0].pPara = para; editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; @@ -2274,9 +2233,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) ME_CommitCoalescingUndo(editor); SetCursor(NULL); - if (editor->AutoURLDetect_bEnable) - ME_UpdateSelectionLinkAttribute(editor); - + ME_UpdateSelectionLinkAttribute(editor); ME_UpdateRepaint(editor); } return TRUE; @@ -2374,7 +2331,7 @@ static LRESULT ME_Char(ME_TextEditor *editor, WPARAM charCode, if ((unsigned)wstr >= ' ' || wstr == '\t') { ME_Cursor cursor = editor->pCursors[0]; - ME_DisplayItem *para = ME_GetParagraph(cursor.pRun); + ME_DisplayItem *para = cursor.pPara; int from, to; BOOL ctrl_is_down = GetKeyState(VK_CONTROL) & 0x8000; ME_GetSelection(editor, &from, &to); @@ -2385,7 +2342,7 @@ static LRESULT ME_Char(ME_TextEditor *editor, WPARAM charCode, ME_DisplayItem *para; BOOL bSelectedRow = FALSE; - para = ME_GetParagraph(cursor.pRun); + para = cursor.pPara; if (ME_IsSelection(editor) && cursor.pRun->member.run.nCharOfs + cursor.nOffset == 0 && to == ME_GetCursorOfs(editor, 0) && @@ -2406,6 +2363,7 @@ static LRESULT ME_Char(ME_TextEditor *editor, WPARAM charCode, para = para->member.para.next_para; if (para->member.para.nFlags & MEPF_ROWSTART) para = para->member.para.next_para; + editor->pCursors[0].pPara = para; editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; @@ -2434,8 +2392,7 @@ static LRESULT ME_Char(ME_TextEditor *editor, WPARAM charCode, ITextHost_TxSetCursor(editor->texthost, NULL, FALSE); } - if (editor->AutoURLDetect_bEnable) ME_UpdateSelectionLinkAttribute(editor); - + ME_UpdateSelectionLinkAttribute(editor); ME_UpdateRepaint(editor); } return 0; @@ -2556,22 +2513,20 @@ static BOOL ME_SetCursor(ME_TextEditor *editor) offset = ME_CharFromPos(editor, pt.x, pt.y, &isExact); if (isExact) { - if (editor->AutoURLDetect_bEnable) + ME_Cursor cursor; + ME_Run *run; + + ME_CursorFromCharOfs(editor, offset, &cursor); + run = &cursor.pRun->member.run; + if (run->style->fmt.dwMask & CFM_LINK && + run->style->fmt.dwEffects & CFE_LINK) { - ME_Cursor cursor; - ME_Run *run; - ME_CursorFromCharOfs(editor, offset, &cursor); - run = &cursor.pRun->member.run; - if (editor->AutoURLDetect_bEnable && - run->style->fmt.dwMask & CFM_LINK && - run->style->fmt.dwEffects & CFE_LINK) - { - ITextHost_TxSetCursor(editor->texthost, - LoadCursorW(NULL, (WCHAR*)IDC_HAND), - FALSE); - return TRUE; - } + ITextHost_TxSetCursor(editor->texthost, + LoadCursorW(NULL, (WCHAR*)IDC_HAND), + FALSE); + return TRUE; } + if (ME_IsSelection(editor)) { int selStart, selEnd; @@ -2653,10 +2608,10 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) */ ed->nCursors = 4; ed->pCursors = ALLOC_N_OBJ(ME_Cursor, ed->nCursors); - ed->pCursors[0].pRun = ME_FindItemFwd(ed->pBuffer->pFirst, diRun); + ed->pCursors[0].pPara = ed->pBuffer->pFirst->member.para.next_para; + ed->pCursors[0].pRun = ME_FindItemFwd(ed->pCursors[0].pPara, diRun); ed->pCursors[0].nOffset = 0; - ed->pCursors[1].pRun = ME_FindItemFwd(ed->pBuffer->pFirst, diRun); - ed->pCursors[1].nOffset = 0; + ed->pCursors[1] = ed->pCursors[0]; ed->pCursors[2] = ed->pCursors[0]; ed->pCursors[3] = ed->pCursors[1]; ed->nLastTotalLength = ed->nTotalLength = 0; @@ -2676,11 +2631,11 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) ed->nParagraphs = 1; ed->nLastSelStart = ed->nLastSelEnd = 0; ed->pLastSelStartPara = ed->pLastSelEndPara = ME_FindItemFwd(ed->pBuffer->pFirst, diParagraph); - ed->bWordWrap = (props & TXTBIT_WORDWRAP) != 0; + ed->nAvailWidth = 0; /* wrap to client area */ ed->bHideSelection = FALSE; ed->pfnWordBreak = NULL; ed->lpOleCallback = NULL; - ed->mode = TM_RICHTEXT | TM_MULTILEVELUNDO | TM_MULTICODEPAGE; + ed->mode = TM_MULTILEVELUNDO | TM_MULTICODEPAGE; ed->mode |= (props & TXTBIT_RICHTEXT) ? TM_RICHTEXT : TM_PLAINTEXT; ed->AutoURLDetect_bEnable = FALSE; ed->bHaveFocus = FALSE; @@ -2695,8 +2650,13 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) ME_CheckCharOffsets(ed); ed->bDefaultFormatRect = TRUE; ITextHost_TxGetSelectionBarWidth(ed->texthost, &selbarwidth); - /* FIXME: Convert selbarwidth from HIMETRIC to pixels */ - ed->selofs = selbarwidth ? SELECTIONBAR_WIDTH : 0; + if (selbarwidth) { + /* FIXME: Convert selbarwidth from HIMETRIC to pixels */ + ed->selofs = SELECTIONBAR_WIDTH; + ed->styleFlags |= ES_SELECTIONBAR; + } else { + ed->selofs = 0; + } ed->nSelectionType = stPosition; ed->cPasswordMask = 0; @@ -2705,8 +2665,12 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10) if (props & TXTBIT_AUTOWORDSEL) ed->styleFlags |= ECO_AUTOWORDSELECTION; - if (props & TXTBIT_MULTILINE) + if (props & TXTBIT_MULTILINE) { ed->styleFlags |= ES_MULTILINE; + ed->bWordWrap = (props & TXTBIT_WORDWRAP) != 0; + } else { + ed->bWordWrap = FALSE; + } if (props & TXTBIT_READONLY) ed->styleFlags |= ES_READONLY; if (!(props & TXTBIT_HIDESELECTION)) @@ -2940,23 +2904,20 @@ get_msg_name(UINT msg) void ME_LinkNotify(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM lParam) { int x,y; - ME_Cursor tmpCursor; + ME_DisplayItem *para, *run; BOOL isExact; int nCharOfs; /* The start of the clicked text. Absolute character offset */ - ME_Run *tmpRun; - ENLINK info; x = (short)LOWORD(lParam); y = (short)HIWORD(lParam); nCharOfs = ME_CharFromPos(editor, x, y, &isExact); if (!isExact) return; - ME_CursorFromCharOfs(editor, nCharOfs, &tmpCursor); - tmpRun = &tmpCursor.pRun->member.run; + ME_RunOfsFromCharOfs(editor, nCharOfs, ¶, &run, NULL); - if ((tmpRun->style->fmt.dwMask & CFM_LINK) - && (tmpRun->style->fmt.dwEffects & CFE_LINK)) + if ((run->member.run.style->fmt.dwMask & CFM_LINK) + && (run->member.run.style->fmt.dwEffects & CFE_LINK)) { /* The clicked run has CFE_LINK set */ info.nmhdr.hwndFrom = editor->hWnd; info.nmhdr.idFrom = GetWindowLongW(editor->hWnd, GWLP_ID); @@ -2964,8 +2925,8 @@ void ME_LinkNotify(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM lParam info.msg = msg; info.wParam = wParam; info.lParam = lParam; - info.chrg.cpMin = ME_CharOfsFromRunOfs(editor,tmpCursor.pRun,0); - info.chrg.cpMax = info.chrg.cpMin + ME_StrVLen(tmpRun->strText); + info.chrg.cpMin = ME_CharOfsFromRunOfs(editor, para, run, 0); + info.chrg.cpMax = info.chrg.cpMin + run->member.run.strText->nLen; SendMessageW(GetParent(editor->hWnd), WM_NOTIFY,info.nmhdr.idFrom, (LPARAM)&info); } } @@ -2999,7 +2960,6 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, UNSUPPORTED_MSG(EM_SETIMESTATUS) UNSUPPORTED_MSG(EM_GETLANGOPTIONS) UNSUPPORTED_MSG(EM_GETREDONAME) - UNSUPPORTED_MSG(EM_GETTEXTMODE) UNSUPPORTED_MSG(EM_GETTYPOGRAPHYOPTIONS) UNSUPPORTED_MSG(EM_GETUNDONAME) UNSUPPORTED_MSG(EM_GETWORDBREAKPROCEX) @@ -3108,31 +3068,36 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } changedSettings = oldSettings ^ settings; - if (oldSettings ^ settings) { + if (changedSettings) { editor->styleFlags = (editor->styleFlags & ~mask) | (settings & mask); - if (settings & ECO_SELECTIONBAR) { - editor->selofs = SELECTIONBAR_WIDTH; - editor->rcFormat.left += SELECTIONBAR_WIDTH; - } else { - editor->selofs = 0; - editor->rcFormat.left -= SELECTIONBAR_WIDTH; + if (changedSettings & ECO_SELECTIONBAR) + { + ITextHost_TxInvalidateRect(editor->texthost, &editor->rcFormat, TRUE); + if (settings & ECO_SELECTIONBAR) { + assert(!editor->selofs); + editor->selofs = SELECTIONBAR_WIDTH; + editor->rcFormat.left += editor->selofs; + } else { + editor->rcFormat.left -= editor->selofs; + editor->selofs = 0; + } + ME_RewrapRepaint(editor); } - ME_WrapMarkedParagraphs(editor); - } - if (settings & ECO_VERTICAL) - FIXME("ECO_VERTICAL not implemented yet!\n"); - if (settings & ECO_AUTOHSCROLL) - FIXME("ECO_AUTOHSCROLL not implemented yet!\n"); - if (settings & ECO_AUTOVSCROLL) - FIXME("ECO_AUTOVSCROLL not implemented yet!\n"); - if (settings & ECO_NOHIDESEL) - FIXME("ECO_NOHIDESEL not implemented yet!\n"); - if (settings & ECO_WANTRETURN) - FIXME("ECO_WANTRETURN not implemented yet!\n"); - if (settings & ECO_AUTOWORDSELECTION) - FIXME("ECO_AUTOWORDSELECTION not implemented yet!\n"); + if (changedSettings & settings & ECO_VERTICAL) + FIXME("ECO_VERTICAL not implemented yet!\n"); + if (changedSettings & settings & ECO_AUTOHSCROLL) + FIXME("ECO_AUTOHSCROLL not implemented yet!\n"); + if (changedSettings & settings & ECO_AUTOVSCROLL) + FIXME("ECO_AUTOVSCROLL not implemented yet!\n"); + if (changedSettings & settings & ECO_NOHIDESEL) + FIXME("ECO_NOHIDESEL not implemented yet!\n"); + if (changedSettings & settings & ECO_WANTRETURN) + FIXME("ECO_WANTRETURN not implemented yet!\n"); + if (changedSettings & settings & ECO_AUTOWORDSELECTION) + FIXME("ECO_AUTOWORDSELECTION not implemented yet!\n"); + } return settings; } @@ -3200,12 +3165,18 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, return 0; } - if (lParam) + if (lParam) { editor->styleFlags |= flags; - else - editor->styleFlags &= flags; - - ITextHost_TxShowScrollBar(editor->texthost, wParam, lParam); + if (flags & WS_HSCROLL) + ITextHost_TxShowScrollBar(editor->texthost, SB_HORZ, + editor->nTotalWidth > editor->sizeWindow.cx); + if (flags & WS_VSCROLL) + ITextHost_TxShowScrollBar(editor->texthost, SB_VERT, + editor->nTotalLength > editor->sizeWindow.cy); + } else { + editor->styleFlags &= ~flags; + ITextHost_TxShowScrollBar(editor->texthost, wParam, FALSE); + } return 0; } case EM_SETTEXTEX: @@ -3256,12 +3227,10 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, if (bSelection) { ME_ReleaseStyle(style); - if (editor->AutoURLDetect_bEnable) - ME_UpdateSelectionLinkAttribute(editor); + ME_UpdateSelectionLinkAttribute(editor); } else { len = 1; - if (editor->AutoURLDetect_bEnable) - ME_UpdateLinkAttribute(editor, 0, -1); + ME_UpdateLinkAttribute(editor, 0, -1); } ME_CommitUndo(editor); if (!(pStruct->flags & ST_KEEPUNDO)) @@ -3419,8 +3388,10 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } case EM_LINESCROLL: { + if (!(editor->styleFlags & ES_MULTILINE)) + return FALSE; ME_ScrollDown(editor, lParam * 8); /* FIXME follow the original */ - return TRUE; /* Should return false if a single line richedit control */ + return TRUE; } case WM_CLEAR: { @@ -3453,7 +3424,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, ME_ClearTempStyle(editor); ME_EndToUnicode(unicode, wszText); ME_CommitUndo(editor); - if (editor->AutoURLDetect_bEnable) ME_UpdateSelectionLinkAttribute(editor); + ME_UpdateSelectionLinkAttribute(editor); if (!wParam) ME_EmptyUndoStack(editor); ME_UpdateRepaint(editor); @@ -3468,7 +3439,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, CHARFORMAT2W fmt; HDC hDC; BOOL bRepaint = LOWORD(lParam); - + if (!wParam) wParam = (WPARAM)GetStockObject(SYSTEM_FONT); GetObjectW((HGDIOBJ)wParam, sizeof(LOGFONTW), &lf); @@ -3479,8 +3450,11 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, ME_SetDefaultCharFormat(editor, &fmt); ME_CommitUndo(editor); + ME_MarkAllForWrapping(editor); + ME_WrapMarkedParagraphs(editor); + ME_UpdateScrollBar(editor); if (bRepaint) - ME_RewrapRepaint(editor); + ME_Repaint(editor); return 0; } case WM_SETTEXT: @@ -3518,10 +3492,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, } else TRACE("WM_SETTEXT - NULL\n"); - if (editor->AutoURLDetect_bEnable) - { - ME_UpdateLinkAttribute(editor, 0, -1); - } + ME_UpdateLinkAttribute(editor, 0, -1); ME_SetSelection(editor, 0, 0); editor->nModifyStep = 0; ME_CommitUndo(editor); @@ -3605,12 +3576,9 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case EM_GETSELTEXT: { int from, to; - TEXTRANGEW tr; /* W and A differ only by rng->lpstrText */ ME_GetSelection(editor, &from, &to); - tr.chrg.cpMin = from; - tr.chrg.cpMax = to; - tr.lpstrText = (WCHAR *)lParam; - return ME_GetTextRange(editor, &tr, unicode); + return ME_GetTextRange(editor, (WCHAR *)lParam, from, + to - from, unicode); } case EM_GETSCROLLPOS: { @@ -3622,10 +3590,17 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case EM_GETTEXTRANGE: { TEXTRANGEW *rng = (TEXTRANGEW *)lParam; + int start = rng->chrg.cpMin; + int end = rng->chrg.cpMax; + int textlength = ME_GetTextLength(editor); TRACE("EM_GETTEXTRANGE min=%d max=%d unicode=%d emul1.0=%d length=%d\n", rng->chrg.cpMin, rng->chrg.cpMax, unicode, editor->bEmulateVersion10, ME_GetTextLength(editor)); - return ME_GetTextRange(editor, rng, unicode); + if (start < 0) return 0; + if ((start == 0 && end == -1) || end > textlength) + end = textlength; + if (start >= end) return 0; + return ME_GetTextRange(editor, rng->lpstrText, start, end - start, unicode); } case EM_GETLINE: { @@ -3743,7 +3718,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, { ME_DisplayItem *item, *item_end; int nChars = 0, nThisLineOfs = 0, nNextLineOfs = 0; - ME_Cursor cursor; + ME_DisplayItem *para, *run; if (wParam > ME_GetTextLength(editor)) return 0; @@ -3752,23 +3727,16 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, FIXME("EM_LINELENGTH: returning number of unselected characters on lines with selection unsupported.\n"); return 0; } - ME_CursorFromCharOfs(editor, wParam, &cursor); - item = ME_RowStart(cursor.pRun); - nThisLineOfs = ME_CharOfsFromRunOfs(editor, ME_FindItemFwd(item, diRun), 0); + ME_RunOfsFromCharOfs(editor, wParam, ¶, &run, NULL); + item = ME_RowStart(run); + nThisLineOfs = ME_CharOfsFromRunOfs(editor, para, ME_FindItemFwd(item, diRun), 0); item_end = ME_FindItemFwd(item, diStartRowOrParagraphOrEnd); - if (item_end->type == diStartRow) - nNextLineOfs = ME_CharOfsFromRunOfs(editor, ME_FindItemFwd(item_end, diRun), 0); - else - { - ME_DisplayItem *endPara; - - nNextLineOfs = ME_FindItemFwd(item, diParagraphOrEnd)->member.para.nCharOfs; - endPara = ME_FindItemFwd(item, diParagraphOrEnd); - endPara = ME_FindItemBack(endPara, diRun); - assert(endPara); - assert(endPara->type == diRun); - assert(endPara->member.run.nFlags & MERF_ENDPARA); - nNextLineOfs -= endPara->member.run.strText->nLen; + if (item_end->type == diStartRow) { + nNextLineOfs = ME_CharOfsFromRunOfs(editor, para, ME_FindItemFwd(item_end, diRun), 0); + } else { + ME_DisplayItem *endRun = ME_FindItemBack(item_end, diRun); + assert(endRun && endRun->member.run.nFlags & MERF_ENDPARA); + nNextLineOfs = item_end->member.para.nCharOfs - endRun->member.run.strText->nLen; } nChars = nNextLineOfs - nThisLineOfs; TRACE("EM_LINELENGTH(%ld)==%d\n",wParam, nChars); @@ -3844,7 +3812,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, return ME_CharFromPos(editor, ((POINTL *)lParam)->x, ((POINTL *)lParam)->y, NULL); case EM_POSFROMCHAR: { - ME_DisplayItem *pRun; + ME_DisplayItem *pPara, *pRun; int nCharOfs, nOffset, nLength; POINTL pt = {0,0}; @@ -3856,11 +3824,11 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, nCharOfs = min(nCharOfs, nLength); nCharOfs = max(nCharOfs, 0); - ME_RunOfsFromCharOfs(editor, nCharOfs, &pRun, &nOffset); + ME_RunOfsFromCharOfs(editor, nCharOfs, &pPara, &pRun, &nOffset); assert(pRun->type == diRun); pt.y = pRun->member.run.pt.y; pt.x = pRun->member.run.pt.x + ME_PointFromChar(editor, &pRun->member.run, nOffset); - pt.y += ME_GetParagraph(pRun)->member.para.pt.y + editor->rcFormat.top; + pt.y += pPara->member.para.pt.y + editor->rcFormat.top; pt.x += editor->rcFormat.left; pt.x -= editor->horz_si.nPos; @@ -4183,8 +4151,11 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, ME_SetDefaultFormatRect(editor); editor->bDefaultFormatRect = TRUE; } + ME_MarkAllForWrapping(editor); + ME_WrapMarkedParagraphs(editor); + ME_UpdateScrollBar(editor); if (msg != EM_SETRECTNP) - ME_RewrapRepaint(editor); + ME_Repaint(editor); return 0; } case EM_REQUESTRESIZE: @@ -4290,6 +4261,8 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, editor->pfnWordBreak = (EDITWORDBREAKPROCW)lParam; return (LRESULT)pfnOld; } + case EM_GETTEXTMODE: + return editor->mode; case EM_SETTEXTMODE: { LRESULT ret; @@ -4331,15 +4304,25 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam, case EM_SETTARGETDEVICE: if (wParam == 0) { - BOOL new = (lParam == 0); - if (editor->bWordWrap != new) + BOOL new = (lParam == 0 && (editor->styleFlags & ES_MULTILINE)); + if (editor->nAvailWidth || editor->bWordWrap != new) { editor->bWordWrap = new; + editor->nAvailWidth = 0; /* wrap to client area */ ME_RewrapRepaint(editor); } + } else { + int width = max(0, lParam); + if ((editor->styleFlags & ES_MULTILINE) && + (!editor->bWordWrap || editor->nAvailWidth != width)) + { + editor->nAvailWidth = width; + editor->bWordWrap = TRUE; + ME_RewrapRepaint(editor); + } + FIXME("EM_SETTARGETDEVICE doesn't use non-NULL target devices\n"); } - else FIXME("Unsupported yet non NULL device in EM_SETTARGETDEVICE\n"); - break; + return TRUE; default: do_default: *phresult = S_FALSE; @@ -4532,7 +4515,7 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nOffset, nWritten = 0; WCHAR *pStart = buffer; - ME_RunOfsFromCharOfs(editor, nStart, &pRun, &nOffset); + ME_RunOfsFromCharOfs(editor, nStart, NULL, &pRun, &nOffset); /* bCRLF flag is only honored in 2.0 and up. 1.0 must always return text verbatim */ if (editor->bEmulateVersion10) bCRLF = 0; @@ -4720,10 +4703,8 @@ static BOOL ME_FindNextURLCandidate(ME_TextEditor *editor, int sel_min, int sel_ TRACE("sel_min = %d sel_max = %d\n", sel_min, sel_max); *candidate_min = *candidate_max = -1; - ME_RunOfsFromCharOfs(editor, sel_min, &item, &nStart); - if (!item) return FALSE; + ME_RunOfsFromCharOfs(editor, sel_min, ¶, &item, &nStart); TRACE("nStart = %d\n", nStart); - para = ME_GetParagraph(item); if (sel_max == -1) sel_max = ME_GetTextLength(editor); while (item && para->member.para.nCharOfs + item->member.run.nCharOfs + nStart < sel_max) { @@ -4732,12 +4713,12 @@ static BOOL ME_FindNextURLCandidate(ME_TextEditor *editor, int sel_min, int sel_ if (!(item->member.run.nFlags & MERF_ENDPARA)) { /* Find start of candidate */ if (*candidate_min == -1) { - while (nStart < ME_StrLen(item->member.run.strText) && + while (nStart < item->member.run.strText->nLen && !(isalnumW(item->member.run.strText->szData[nStart]) || isurlspecial(item->member.run.strText->szData[nStart]))) { nStart++; } - if (nStart < ME_StrLen(item->member.run.strText) && + if (nStart < item->member.run.strText->nLen && (isalnumW(item->member.run.strText->szData[nStart]) || isurlspecial(item->member.run.strText->szData[nStart]))) { *candidate_min = para->member.para.nCharOfs + item->member.run.nCharOfs + nStart; @@ -4748,7 +4729,7 @@ static BOOL ME_FindNextURLCandidate(ME_TextEditor *editor, int sel_min, int sel_ /* Find end of candidate */ if (*candidate_min >= 0) { - while (nStart < ME_StrLen(item->member.run.strText) && + while (nStart < item->member.run.strText->nLen && (isalnumW(item->member.run.strText->szData[nStart]) || isurlspecial(item->member.run.strText->szData[nStart]) || (!foundColon && item->member.run.strText->szData[nStart] == ':') )) { @@ -4756,7 +4737,7 @@ static BOOL ME_FindNextURLCandidate(ME_TextEditor *editor, int sel_min, int sel_ lastAcceptedChar = item->member.run.strText->szData[nStart]; nStart++; } - if (nStart < ME_StrLen(item->member.run.strText) && + if (nStart < item->member.run.strText->nLen && !(isalnumW(item->member.run.strText->szData[nStart]) || isurlspecial(item->member.run.strText->szData[nStart]) )) { *candidate_max = para->member.para.nCharOfs + item->member.run.nCharOfs + nStart; @@ -4861,6 +4842,8 @@ static BOOL ME_UpdateLinkAttribute(ME_TextEditor *editor, int sel_min, int sel_m BOOL modified = FALSE; int cMin, cMax; + if (!editor->AutoURLDetect_bEnable) return FALSE; + if (sel_max == -1) sel_max = ME_GetTextLength(editor); do { diff --git a/reactos/dll/win32/riched20/editor.h b/reactos/dll/win32/riched20/editor.h index a412389a369..77b33d248c7 100644 --- a/reactos/dll/win32/riched20/editor.h +++ b/reactos/dll/win32/riched20/editor.h @@ -70,7 +70,6 @@ void ME_ClearTempStyle(ME_TextEditor *editor); void ME_DumpStyleToBuf(CHARFORMAT2W *pFmt, char buf[2048]); void ME_DumpStyle(ME_Style *s); CHARFORMAT2W *ME_ToCF2W(CHARFORMAT2W *to, CHARFORMAT2W *from); -void ME_CopyToCF2W(CHARFORMAT2W *to, CHARFORMAT2W *from); void ME_CopyToCFAny(CHARFORMAT2W *to, CHARFORMAT2W *from); void ME_CopyCharFormat(CHARFORMAT2W *pDest, const CHARFORMAT2W *pSrc); /* only works with 2W structs */ void ME_CharFormatFromLogFont(HDC hDC, const LOGFONTW *lf, CHARFORMAT2W *fmt); /* ditto */ @@ -81,7 +80,6 @@ void ME_Remove(ME_DisplayItem *diWhere); ME_DisplayItem *ME_FindItemBack(ME_DisplayItem *di, ME_DIType nTypeOrClass); ME_DisplayItem *ME_FindItemFwd(ME_DisplayItem *di, ME_DIType nTypeOrClass); ME_DisplayItem *ME_FindItemBackOrHere(ME_DisplayItem *di, ME_DIType nTypeOrClass); -ME_DisplayItem *ME_FindItemFwdOrHere(ME_DisplayItem *di, ME_DIType nTypeOrClass); ME_DisplayItem *ME_MakeDI(ME_DIType type); void ME_DestroyDisplayItem(ME_DisplayItem *item); void ME_DumpDocument(ME_TextBuffer *buffer); @@ -91,26 +89,15 @@ const char *ME_GetDITypeName(ME_DIType type); ME_String *ME_MakeString(LPCWSTR szText); ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars); ME_String *ME_MakeStringR(WCHAR cRepeat, int nMaxChars); -ME_String *ME_MakeStringB(int nMaxChars); ME_String *ME_StrDup(const ME_String *s); void ME_DestroyString(ME_String *s); void ME_AppendString(ME_String *s1, const ME_String *s2); -ME_String *ME_ConcatString(const ME_String *s1, const ME_String *s2); ME_String *ME_VSplitString(ME_String *orig, int nVPos); int ME_IsWhitespaces(const ME_String *s); int ME_IsSplitable(const ME_String *s); -/* int ME_CalcSkipChars(ME_String *s); */ -int ME_StrLen(const ME_String *s); -int ME_StrVLen(const ME_String *s); int ME_FindNonWhitespaceV(const ME_String *s, int nVChar); int ME_FindWhitespaceV(ME_String *s, int nVChar); int ME_CallWordBreakProc(ME_TextEditor *editor, ME_String *str, INT start, INT code); -int ME_GetCharFwd(const ME_String *s, int nPos); /* get char starting from start */ -int ME_GetCharBack(const ME_String *s, int nPos); /* get char starting from \0 */ -int ME_StrRelPos(const ME_String *s, int nVChar, int *pRelChars); -int ME_StrRelPos2(const ME_String *s, int nVChar, int nRelChars); -int ME_VPosToPos(ME_String *s, int nVPos); -int ME_PosToVPos(const ME_String *s, int nPos); void ME_StrDeleteV(ME_String *s, int nVChar, int nChars); /* smart helpers for A<->W conversions, they reserve/free memory and call MultiByte<->WideChar functions */ LPWSTR ME_ToUnicode(BOOL unicode, LPVOID psz); @@ -132,7 +119,6 @@ int ME_ReverseFindNonWhitespaceV(const ME_String *s, int nVChar); int ME_ReverseFindWhitespaceV(const ME_String *s, int nVChar); /* row.c */ -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 */ @@ -162,8 +148,8 @@ ME_DisplayItem *ME_SplitFurther(ME_TextEditor *editor, ME_DisplayItem *run); void ME_CalcRunExtent(ME_Context *c, const ME_Paragraph *para, int startx, ME_Run *run); SIZE ME_GetRunSize(ME_Context *c, const ME_Paragraph *para, ME_Run *run, int nLen, int startx); void ME_CursorFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_Cursor *pCursor); -void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem **ppRun, int *pOfs); -int ME_CharOfsFromRunOfs(ME_TextEditor *editor, ME_DisplayItem *pRun, int nOfs); +void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem **ppPara, ME_DisplayItem **ppRun, int *pOfs); +int ME_CharOfsFromRunOfs(ME_TextEditor *editor, const ME_DisplayItem *pPara, const ME_DisplayItem *pRun, int nOfs); void ME_SkipAndPropagateCharOffset(ME_DisplayItem *p, int shift); void ME_SetCharFormat(ME_TextEditor *editor, int nFrom, int nLen, CHARFORMAT2W *pFmt); void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt); @@ -211,7 +197,7 @@ void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor); void ME_SendRequestResize(ME_TextEditor *editor, BOOL force); /* para.c */ -ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *run); +ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *run); void ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end); void ME_MakeFirstParagraph(ME_TextEditor *editor); ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *rp, ME_Style *style, ME_String *eol_str, int paraFlags); diff --git a/reactos/dll/win32/riched20/editstr.h b/reactos/dll/win32/riched20/editstr.h index a6450753712..a4af8fe9c0c 100644 --- a/reactos/dll/win32/riched20/editstr.h +++ b/reactos/dll/win32/riched20/editstr.h @@ -164,12 +164,6 @@ typedef struct tagME_Run REOBJECT *ole_obj; /* FIXME: should be a union with strText (at least) */ } ME_Run; -typedef struct tagME_Document { - struct tagME_DisplayItem *def_char_style; - struct tagME_DisplayItem *def_para_style; - int last_wrapped_line; -} ME_Document; - typedef struct tagME_Border { int width; @@ -197,7 +191,7 @@ typedef struct tagME_Paragraph int nHeight, nWidth; int nLastPaintYPos, nLastPaintHeight; int nRows; - struct tagME_DisplayItem *prev_para, *next_para, *document; + struct tagME_DisplayItem *prev_para, *next_para; } ME_Paragraph; typedef struct tagME_Cell /* v4.1 */ @@ -242,7 +236,6 @@ typedef struct tagME_DisplayItem ME_Row row; ME_Cell cell; ME_Paragraph para; - ME_Document doc; /* not used */ ME_Style *ustyle; /* used by diUndoSetCharFormat */ } member; } ME_DisplayItem; @@ -263,6 +256,7 @@ typedef struct tagME_TextBuffer typedef struct tagME_Cursor { + ME_DisplayItem *pPara; ME_DisplayItem *pRun; int nOffset; } ME_Cursor; @@ -342,6 +336,7 @@ typedef struct tagME_TextEditor SIZE sizeWindow; int nTotalLength, nLastTotalLength; int nTotalWidth, nLastTotalWidth; + int nAvailWidth; /* 0 = wrap to client area, else wrap width in twips */ int nUDArrowX; int nSequence; COLORREF rgbBackColor; @@ -396,6 +391,7 @@ typedef struct tagME_Context RECT rcView; HBRUSH hbrMargin; SIZE dpi; + int nAvailWidth; /* those are valid inside ME_WrapTextParagraph and related */ POINT ptFirstRun; @@ -412,10 +408,11 @@ typedef struct tagME_WrapContext int nRow; POINT pt; BOOL bOverflown, bWordWrap; + ME_DisplayItem *pPara; ME_DisplayItem *pRowStart; - + ME_DisplayItem *pLastSplittableRun; POINT ptLastSplittableRun; -} ME_WrapContext; +} ME_WrapContext; #endif diff --git a/reactos/dll/win32/riched20/list.c b/reactos/dll/win32/riched20/list.c index f9a903205b9..d3d9463c04b 100644 --- a/reactos/dll/win32/riched20/list.c +++ b/reactos/dll/win32/riched20/list.c @@ -98,16 +98,6 @@ ME_DisplayItem *ME_FindItemFwd(ME_DisplayItem *di, ME_DIType nTypeOrClass) return NULL; } -ME_DisplayItem *ME_FindItemFwdOrHere(ME_DisplayItem *di, ME_DIType nTypeOrClass) -{ - while(di!=NULL) { - if (ME_DITypesEqual(di->type, nTypeOrClass)) - return di; - di = di->next; - } - return NULL; -} - void ME_DestroyDisplayItem(ME_DisplayItem *item) { /* TRACE("type=%s\n", ME_GetDITypeName(item->type)); */ if (item->type==diParagraph || item->type == diUndoSetParagraphFormat) { diff --git a/reactos/dll/win32/riched20/paint.c b/reactos/dll/win32/riched20/paint.c index 30548feaabb..620ac69160c 100644 --- a/reactos/dll/win32/riched20/paint.c +++ b/reactos/dll/win32/riched20/paint.c @@ -44,7 +44,7 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT * editor->nSequence++; ME_InitContext(&c, editor, hDC); SetBkMode(hDC, TRANSPARENT); - ME_MoveCaret(editor); /* Calls ME_WrapMarkedParagraphs */ + ME_MoveCaret(editor); item = editor->pBuffer->pFirst->next; /* This context point is an offset for the paragraph positions stored * during wrapping. It shouldn't be modified during painting. */ @@ -137,7 +137,6 @@ void ME_Repaint(ME_TextEditor *editor) void ME_UpdateRepaint(ME_TextEditor *editor) { /* Should be called whenever the contents of the control have changed */ - ME_Cursor *pCursor; BOOL wrappedParagraphs; wrappedParagraphs = ME_WrapMarkedParagraphs(editor); @@ -145,8 +144,7 @@ void ME_UpdateRepaint(ME_TextEditor *editor) ME_UpdateScrollBar(editor); /* Ensure that the cursor is visible */ - pCursor = &editor->pCursors[0]; - ME_EnsureVisible(editor, pCursor); + ME_EnsureVisible(editor, &editor->pCursors[0]); /* send EN_CHANGE if the event mask asks for it */ if(editor->nEventMask & ENM_CHANGE) @@ -446,9 +444,9 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa { if (c->editor->cPasswordMask) { - ME_String *szMasked = ME_MakeStringR(c->editor->cPasswordMask,ME_StrVLen(run->strText)); + ME_String *szMasked = ME_MakeStringR(c->editor->cPasswordMask, run->strText->nLen); ME_DrawTextWithStyle(c, x, y, - szMasked->szData, ME_StrVLen(szMasked), run->style, run->nWidth, + szMasked->szData, szMasked->nLen, run->style, run->nWidth, nSelFrom-runofs,nSelTo-runofs, c->pt.y + para->pt.y + start->member.row.pt.y, start->member.row.nHeight); @@ -456,7 +454,7 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa } else ME_DrawTextWithStyle(c, x, y, - run->strText->szData, ME_StrVLen(run->strText), run->style, run->nWidth, + run->strText->szData, run->strText->nLen, run->style, run->nWidth, nSelFrom-runofs,nSelTo-runofs, c->pt.y + para->pt.y + start->member.row.pt.y, start->member.row.nHeight); @@ -1073,7 +1071,8 @@ void ME_ScrollAbs(ME_TextEditor *editor, int x, int y) bScrollBarIsVisible = (winStyle & WS_VSCROLL) != 0; bScrollBarWillBeVisible = (editor->nTotalLength > editor->sizeWindow.cy - && (editor->styleFlags & WS_VSCROLL)) + && (editor->styleFlags & WS_VSCROLL) + && (editor->styleFlags & ES_MULTILINE)) || (editor->styleFlags & ES_DISABLENOSCROLL); if (bScrollBarIsVisible != bScrollBarWillBeVisible) ITextHost_TxShowScrollBar(editor->texthost, SB_VERT, @@ -1112,6 +1111,18 @@ void ME_ScrollRight(ME_TextEditor *editor, int cx) ME_HScrollAbs(editor, editor->horz_si.nPos + cx); } +/* Calculates the visiblity after a call to SetScrollRange or + * SetScrollInfo with SIF_RANGE. */ +static BOOL ME_PostSetScrollRangeVisibility(SCROLLINFO *si) +{ + if (si->fMask & SIF_DISABLENOSCROLL) + return TRUE; + + /* This must match the check in SetScrollInfo to determine whether + * to show or hide the scrollbars. */ + return si->nMin < si->nMax - max(si->nPage - 1, 0); +} + void ME_UpdateScrollBar(ME_TextEditor *editor) { /* Note that this is the only function that should ever call @@ -1159,15 +1170,14 @@ void ME_UpdateScrollBar(ME_TextEditor *editor) ITextHost_TxSetScrollRange(editor->texthost, SB_HORZ, si.nMin, si.nMax, FALSE); ITextHost_TxSetScrollPos(editor->texthost, SB_HORZ, si.nPos, TRUE); } + /* SetScrollInfo or SetScrollRange change scrollbar visibility. */ + bScrollBarWasVisible = ME_PostSetScrollRangeVisibility(&si); } } if (si.fMask & SIF_DISABLENOSCROLL) { bScrollBarWillBeVisible = TRUE; } else if (!(editor->styleFlags & WS_HSCROLL)) { - /* SetScrollInfo or SetScrollRange may cause the scrollbar to be - * shown, so hide the scrollbar if necessary. */ - bScrollBarWasVisible = bScrollBarWillBeVisible; bScrollBarWillBeVisible = FALSE; } @@ -1176,7 +1186,8 @@ void ME_UpdateScrollBar(ME_TextEditor *editor) /* Update vertical scrollbar */ bScrollBarWasVisible = editor->vert_si.nMax > editor->vert_si.nPage; - bScrollBarWillBeVisible = editor->nTotalLength > editor->sizeWindow.cy; + bScrollBarWillBeVisible = editor->nTotalLength > editor->sizeWindow.cy && + (editor->styleFlags & ES_MULTILINE); if (editor->vert_si.nPos && !bScrollBarWillBeVisible) { @@ -1205,15 +1216,14 @@ void ME_UpdateScrollBar(ME_TextEditor *editor) ITextHost_TxSetScrollRange(editor->texthost, SB_VERT, si.nMin, si.nMax, FALSE); ITextHost_TxSetScrollPos(editor->texthost, SB_VERT, si.nPos, TRUE); } + /* SetScrollInfo or SetScrollRange change scrollbar visibility. */ + bScrollBarWasVisible = ME_PostSetScrollRangeVisibility(&si); } } if (si.fMask & SIF_DISABLENOSCROLL) { bScrollBarWillBeVisible = TRUE; } else if (!(editor->styleFlags & WS_VSCROLL)) { - /* SetScrollInfo or SetScrollRange may cause the scrollbar to be - * shown, so hide the scrollbar if necessary. */ - bScrollBarWasVisible = bScrollBarWillBeVisible; bScrollBarWillBeVisible = FALSE; } @@ -1226,7 +1236,7 @@ void ME_EnsureVisible(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_Run *pRun = &pCursor->pRun->member.run; ME_DisplayItem *pRow = ME_FindItemBack(pCursor->pRun, diStartRow); - ME_DisplayItem *pPara = ME_FindItemBack(pCursor->pRun, diParagraph); + ME_DisplayItem *pPara = pCursor->pPara; int x, y, yheight; assert(pRow); @@ -1267,26 +1277,24 @@ ME_InvalidateSelection(ME_TextEditor *editor) assert(para1->type == diParagraph); assert(para2->type == diParagraph); /* last selection markers aren't always updated, which means - they can point past the end of the document */ + * they can point past the end of the document */ if (editor->nLastSelStart > len || editor->nLastSelEnd > len) { ME_MarkForPainting(editor, ME_FindItemFwd(editor->pBuffer->pFirst, diParagraph), - ME_FindItemFwd(editor->pBuffer->pFirst, diTextEnd)); + editor->pBuffer->pLast); } else { /* if the start part of selection is being expanded or contracted... */ if (nStart < editor->nLastSelStart) { - ME_MarkForPainting(editor, para1, ME_FindItemFwd(editor->pLastSelStartPara, diParagraphOrEnd)); - } else - if (nStart > editor->nLastSelStart) { - ME_MarkForPainting(editor, editor->pLastSelStartPara, ME_FindItemFwd(para1, diParagraphOrEnd)); + ME_MarkForPainting(editor, para1, editor->pLastSelStartPara->member.para.next_para); + } else if (nStart > editor->nLastSelStart) { + ME_MarkForPainting(editor, editor->pLastSelStartPara, para1->member.para.next_para); } /* if the end part of selection is being contracted or expanded... */ if (nEnd < editor->nLastSelEnd) { - ME_MarkForPainting(editor, para2, ME_FindItemFwd(editor->pLastSelEndPara, diParagraphOrEnd)); - } else - if (nEnd > editor->nLastSelEnd) { - ME_MarkForPainting(editor, editor->pLastSelEndPara, ME_FindItemFwd(para2, diParagraphOrEnd)); + ME_MarkForPainting(editor, para2, editor->pLastSelEndPara->member.para.next_para); + } else if (nEnd > editor->nLastSelEnd) { + ME_MarkForPainting(editor, editor->pLastSelEndPara, para2->member.para.next_para); } } diff --git a/reactos/dll/win32/riched20/para.c b/reactos/dll/win32/riched20/para.c index a4a9adb1b29..94ef7ae709f 100644 --- a/reactos/dll/win32/riched20/para.c +++ b/reactos/dll/win32/riched20/para.c @@ -208,7 +208,7 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, ME_DisplayItem *new_para = ME_MakeDI(diParagraph); ME_DisplayItem *end_run; ME_UndoItem *undo = NULL; - int ofs; + int ofs, i; ME_DisplayItem *pp; int run_flags = MERF_ENDPARA; @@ -236,14 +236,23 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, undo = ME_AddUndoItem(editor, diUndoJoinParagraphs, NULL); if (undo) undo->nStart = run_para->member.para.nCharOfs + ofs; - + + /* Update selection cursors to point to the correct paragraph. */ + for (i = 0; i < editor->nCursors; i++) { + if (editor->pCursors[i].pPara == run_para && + run->member.run.nCharOfs <= editor->pCursors[i].pRun->member.run.nCharOfs) + { + editor->pCursors[i].pPara = new_para; + } + } + /* the new paragraph will have a different starting offset, so let's update its runs */ pp = run; while(pp->type == diRun) { pp->member.run.nCharOfs -= ofs; pp = ME_FindItemFwd(pp, diRunOrParagraphOrEnd); } - new_para->member.para.nCharOfs = ME_GetParagraph(run)->member.para.nCharOfs+ofs; + new_para->member.para.nCharOfs = run_para->member.para.nCharOfs + ofs; new_para->member.para.nCharOfs += eol_str->nLen; new_para->member.para.nFlags = MEPF_REWRAP; @@ -309,11 +318,11 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, /* force rewrap of the */ run_para->member.para.prev_para->member.para.nFlags |= MEPF_REWRAP; 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, eol_str->nLen); editor->nParagraphs++; - + return new_para; } @@ -330,9 +339,9 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp, assert(tp->type == diParagraph); assert(tp->member.para.next_para); assert(tp->member.para.next_para->type == diParagraph); - + pNext = tp->member.para.next_para; - + /* Need to locate end-of-paragraph run here, in order to know end_len */ pRun = ME_FindItemBack(pNext, diRunOrParagraph); @@ -397,19 +406,21 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp, pTmp = pTmp->next; } } - + shift = pNext->member.para.nCharOfs - tp->member.para.nCharOfs - end_len; - + pFirstRunInNext = ME_FindItemFwd(pNext, diRunOrParagraph); assert(pFirstRunInNext->type == diRun); - - /* if some cursor points at end of paragraph, make it point to the first - run of the next joined paragraph */ - for (i=0; inCursors; i++) { + + /* Update selection cursors so they don't point to the removed end + * paragraph run, and point to the correct paragraph. */ + for (i=0; i < editor->nCursors; i++) { if (editor->pCursors[i].pRun == pRun) { editor->pCursors[i].pRun = pFirstRunInNext; editor->pCursors[i].nOffset = 0; + } else if (editor->pCursors[i].pPara == pNext) { + editor->pCursors[i].pPara = tp; } } @@ -421,7 +432,7 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp, TRACE("shifting \"%s\" by %d (previous %d)\n", debugstr_w(pTmp->member.run.strText->szData), shift, pTmp->member.run.nCharOfs); pTmp->member.run.nCharOfs += shift; } while(1); - + ME_Remove(pRun); ME_DestroyDisplayItem(pRun); @@ -429,16 +440,16 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp, editor->pLastSelStartPara = tp; if (editor->pLastSelEndPara == pNext) editor->pLastSelEndPara = tp; - + tp->member.para.next_para = pNext->member.para.next_para; pNext->member.para.next_para->member.para.prev_para = tp; ME_Remove(pNext); ME_DestroyDisplayItem(pNext); ME_PropagateCharOffset(tp->member.para.next_para, -end_len); - + ME_CheckCharOffsets(editor); - + editor->nParagraphs--; tp->member.para.nFlags |= MEPF_REWRAP; return tp; @@ -515,9 +526,12 @@ void ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end) { ME_Cursor *pEndCursor = &editor->pCursors[1]; - - *para = ME_GetParagraph(editor->pCursors[0].pRun); - *para_end = ME_GetParagraph(editor->pCursors[1].pRun); + + *para = editor->pCursors[0].pPara; + *para_end = editor->pCursors[1].pPara; + if (*para == *para_end) + return; + if ((*para_end)->member.para.nCharOfs < (*para)->member.para.nCharOfs) { ME_DisplayItem *tmp = *para; @@ -525,22 +539,20 @@ ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayIte *para_end = tmp; pEndCursor = &editor->pCursors[0]; } - - /* selection consists of chars from nFrom up to nTo-1 */ - if ((*para_end)->member.para.nCharOfs > (*para)->member.para.nCharOfs) { - if (!pEndCursor->nOffset) { - *para_end = ME_GetParagraph(ME_FindItemBack(pEndCursor->pRun, diRun)); - } - } + + /* The paragraph at the end of a non-empty selection isn't included + * if the selection ends at the start of the paragraph. */ + if (!pEndCursor->pRun->member.run.nCharOfs && !pEndCursor->nOffset) + *para_end = (*para_end)->member.para.prev_para; } BOOL ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt) { ME_DisplayItem *para, *para_end; - + ME_GetSelectionParas(editor, ¶, ¶_end); - + do { ME_SetParaFormat(editor, para, pFmt); if (para == para_end) diff --git a/reactos/dll/win32/riched20/reader.c b/reactos/dll/win32/riched20/reader.c index 3df7109a0f9..fa1ef79c9f0 100644 --- a/reactos/dll/win32/riched20/reader.c +++ b/reactos/dll/win32/riched20/reader.c @@ -475,6 +475,11 @@ static void RTFUngetToken(RTF_Info *info) info->pushedMinor = info->rtfMinor; info->pushedParam = info->rtfParam; lstrcpyA (info->pushedTextBuf, info->rtfTextBuf); + /* The read hook decrements stackTop on rtfEndGroup, so + * increment the value to compensate for it being decremented + * twice due to the RTFUngetToken. */ + if(RTFCheckCM (info, rtfGroup, rtfEndGroup)) + info->stackTop++; } diff --git a/reactos/dll/win32/riched20/richole.c b/reactos/dll/win32/riched20/richole.c index ee8ea600a68..326ecc537d5 100644 --- a/reactos/dll/win32/riched20/richole.c +++ b/reactos/dll/win32/riched20/richole.c @@ -524,7 +524,7 @@ ITextDocument_fnGetSelection(ITextDocument* me, ITextSelection** ppSel) } static HRESULT WINAPI -ITextDocument_fnGetStoryCount(ITextDocument* me, long* pCount) +ITextDocument_fnGetStoryCount(ITextDocument* me, LONG* pCount) { IRichEditOleImpl *This = impl_from_ITextDocument(me); FIXME("stub %p\n",This); @@ -541,7 +541,7 @@ ITextDocument_fnGetStoryRanges(ITextDocument* me, } static HRESULT WINAPI -ITextDocument_fnGetSaved(ITextDocument* me, long* pValue) +ITextDocument_fnGetSaved(ITextDocument* me, LONG* pValue) { IRichEditOleImpl *This = impl_from_ITextDocument(me); FIXME("stub %p\n",This); @@ -549,7 +549,7 @@ ITextDocument_fnGetSaved(ITextDocument* me, long* pValue) } static HRESULT WINAPI -ITextDocument_fnSetSaved(ITextDocument* me, long Value) +ITextDocument_fnSetSaved(ITextDocument* me, LONG Value) { IRichEditOleImpl *This = impl_from_ITextDocument(me); FIXME("stub %p\n",This); @@ -581,8 +581,8 @@ ITextDocument_fnNew(ITextDocument* me) } static HRESULT WINAPI -ITextDocument_fnOpen(ITextDocument* me, VARIANT* pVar, long Flags, - long CodePage) +ITextDocument_fnOpen(ITextDocument* me, VARIANT* pVar, LONG Flags, + LONG CodePage) { IRichEditOleImpl *This = impl_from_ITextDocument(me); FIXME("stub %p\n",This); @@ -590,8 +590,8 @@ ITextDocument_fnOpen(ITextDocument* me, VARIANT* pVar, long Flags, } static HRESULT WINAPI -ITextDocument_fnSave(ITextDocument* me, VARIANT* pVar, long Flags, - long CodePage) +ITextDocument_fnSave(ITextDocument* me, VARIANT* pVar, LONG Flags, + LONG CodePage) { IRichEditOleImpl *This = impl_from_ITextDocument(me); FIXME("stub %p\n",This); @@ -599,7 +599,7 @@ ITextDocument_fnSave(ITextDocument* me, VARIANT* pVar, long Flags, } static HRESULT WINAPI -ITextDocument_fnFreeze(ITextDocument* me, long* pCount) +ITextDocument_fnFreeze(ITextDocument* me, LONG* pCount) { IRichEditOleImpl *This = impl_from_ITextDocument(me); FIXME("stub %p\n",This); @@ -607,7 +607,7 @@ ITextDocument_fnFreeze(ITextDocument* me, long* pCount) } static HRESULT WINAPI -ITextDocument_fnUnfreeze(ITextDocument* me, long* pCount) +ITextDocument_fnUnfreeze(ITextDocument* me, LONG* pCount) { IRichEditOleImpl *This = impl_from_ITextDocument(me); FIXME("stub %p\n",This); @@ -631,7 +631,7 @@ ITextDocument_fnEndEditCollection(ITextDocument* me) } static HRESULT WINAPI -ITextDocument_fnUndo(ITextDocument* me, long Count, long* prop) +ITextDocument_fnUndo(ITextDocument* me, LONG Count, LONG* prop) { IRichEditOleImpl *This = impl_from_ITextDocument(me); FIXME("stub %p\n",This); @@ -639,7 +639,7 @@ ITextDocument_fnUndo(ITextDocument* me, long Count, long* prop) } static HRESULT WINAPI -ITextDocument_fnRedo(ITextDocument* me, long Count, long* prop) +ITextDocument_fnRedo(ITextDocument* me, LONG Count, LONG* prop) { IRichEditOleImpl *This = impl_from_ITextDocument(me); FIXME("stub %p\n",This); @@ -647,7 +647,7 @@ ITextDocument_fnRedo(ITextDocument* me, long Count, long* prop) } static HRESULT WINAPI -ITextDocument_fnRange(ITextDocument* me, long cp1, long cp2, +ITextDocument_fnRange(ITextDocument* me, LONG cp1, LONG cp2, ITextRange** ppRange) { IRichEditOleImpl *This = impl_from_ITextDocument(me); @@ -656,7 +656,7 @@ ITextDocument_fnRange(ITextDocument* me, long cp1, long cp2, } static HRESULT WINAPI -ITextDocument_fnRangeFromPoint(ITextDocument* me, long x, long y, +ITextDocument_fnRangeFromPoint(ITextDocument* me, LONG x, LONG y, ITextRange** ppRange) { IRichEditOleImpl *This = impl_from_ITextDocument(me); @@ -813,7 +813,7 @@ static HRESULT WINAPI ITextSelection_fnSetText( static HRESULT WINAPI ITextSelection_fnGetChar( ITextSelection *me, - long *pch) + LONG *pch) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -825,7 +825,7 @@ static HRESULT WINAPI ITextSelection_fnGetChar( static HRESULT WINAPI ITextSelection_fnSetChar( ITextSelection *me, - long ch) + LONG ch) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -873,7 +873,7 @@ static HRESULT WINAPI ITextSelection_fnSetFormattedText( static HRESULT WINAPI ITextSelection_fnGetStart( ITextSelection *me, - long *pcpFirst) + LONG *pcpFirst) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -885,7 +885,7 @@ static HRESULT WINAPI ITextSelection_fnGetStart( static HRESULT WINAPI ITextSelection_fnSetStart( ITextSelection *me, - long cpFirst) + LONG cpFirst) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -897,7 +897,7 @@ static HRESULT WINAPI ITextSelection_fnSetStart( static HRESULT WINAPI ITextSelection_fnGetEnd( ITextSelection *me, - long *pcpLim) + LONG *pcpLim) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -909,7 +909,7 @@ static HRESULT WINAPI ITextSelection_fnGetEnd( static HRESULT WINAPI ITextSelection_fnSetEnd( ITextSelection *me, - long cpLim) + LONG cpLim) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -969,7 +969,7 @@ static HRESULT WINAPI ITextSelection_fnSetPara( static HRESULT WINAPI ITextSelection_fnGetStoryLength( ITextSelection *me, - long *pcch) + LONG *pcch) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -981,7 +981,7 @@ static HRESULT WINAPI ITextSelection_fnGetStoryLength( static HRESULT WINAPI ITextSelection_fnGetStoryType( ITextSelection *me, - long *pValue) + LONG *pValue) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -993,7 +993,7 @@ static HRESULT WINAPI ITextSelection_fnGetStoryType( static HRESULT WINAPI ITextSelection_fnCollapse( ITextSelection *me, - long bStart) + LONG bStart) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1005,8 +1005,8 @@ static HRESULT WINAPI ITextSelection_fnCollapse( static HRESULT WINAPI ITextSelection_fnExpand( ITextSelection *me, - long Unit, - long *pDelta) + LONG Unit, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1018,8 +1018,8 @@ static HRESULT WINAPI ITextSelection_fnExpand( static HRESULT WINAPI ITextSelection_fnGetIndex( ITextSelection *me, - long Unit, - long *pIndex) + LONG Unit, + LONG *pIndex) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1031,9 +1031,9 @@ static HRESULT WINAPI ITextSelection_fnGetIndex( static HRESULT WINAPI ITextSelection_fnSetIndex( ITextSelection *me, - long Unit, - long Index, - long Extend) + LONG Unit, + LONG Index, + LONG Extend) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1045,8 +1045,8 @@ static HRESULT WINAPI ITextSelection_fnSetIndex( static HRESULT WINAPI ITextSelection_fnSetRange( ITextSelection *me, - long cpActive, - long cpOther) + LONG cpActive, + LONG cpOther) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1059,7 +1059,7 @@ static HRESULT WINAPI ITextSelection_fnSetRange( static HRESULT WINAPI ITextSelection_fnInRange( ITextSelection *me, ITextRange *pRange, - long *pb) + LONG *pb) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1072,7 +1072,7 @@ static HRESULT WINAPI ITextSelection_fnInRange( static HRESULT WINAPI ITextSelection_fnInStory( ITextSelection *me, ITextRange *pRange, - long *pb) + LONG *pb) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1085,7 +1085,7 @@ static HRESULT WINAPI ITextSelection_fnInStory( static HRESULT WINAPI ITextSelection_fnIsEqual( ITextSelection *me, ITextRange *pRange, - long *pb) + LONG *pb) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1108,9 +1108,9 @@ static HRESULT WINAPI ITextSelection_fnSelect( static HRESULT WINAPI ITextSelection_fnStartOf( ITextSelection *me, - long Unit, - long Extend, - long *pDelta) + LONG Unit, + LONG Extend, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1122,9 +1122,9 @@ static HRESULT WINAPI ITextSelection_fnStartOf( static HRESULT WINAPI ITextSelection_fnEndOf( ITextSelection *me, - long Unit, - long Extend, - long *pDelta) + LONG Unit, + LONG Extend, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1136,9 +1136,9 @@ static HRESULT WINAPI ITextSelection_fnEndOf( static HRESULT WINAPI ITextSelection_fnMove( ITextSelection *me, - long Unit, - long Count, - long *pDelta) + LONG Unit, + LONG Count, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1150,9 +1150,9 @@ static HRESULT WINAPI ITextSelection_fnMove( static HRESULT WINAPI ITextSelection_fnMoveStart( ITextSelection *me, - long Unit, - long Count, - long *pDelta) + LONG Unit, + LONG Count, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1164,9 +1164,9 @@ static HRESULT WINAPI ITextSelection_fnMoveStart( static HRESULT WINAPI ITextSelection_fnMoveEnd( ITextSelection *me, - long Unit, - long Count, - long *pDelta) + LONG Unit, + LONG Count, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1179,8 +1179,8 @@ static HRESULT WINAPI ITextSelection_fnMoveEnd( static HRESULT WINAPI ITextSelection_fnMoveWhile( ITextSelection *me, VARIANT *Cset, - long Count, - long *pDelta) + LONG Count, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1193,8 +1193,8 @@ static HRESULT WINAPI ITextSelection_fnMoveWhile( static HRESULT WINAPI ITextSelection_fnMoveStartWhile( ITextSelection *me, VARIANT *Cset, - long Count, - long *pDelta) + LONG Count, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1207,8 +1207,8 @@ static HRESULT WINAPI ITextSelection_fnMoveStartWhile( static HRESULT WINAPI ITextSelection_fnMoveEndWhile( ITextSelection *me, VARIANT *Cset, - long Count, - long *pDelta) + LONG Count, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1221,8 +1221,8 @@ static HRESULT WINAPI ITextSelection_fnMoveEndWhile( static HRESULT WINAPI ITextSelection_fnMoveUntil( ITextSelection *me, VARIANT *Cset, - long Count, - long *pDelta) + LONG Count, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1235,8 +1235,8 @@ static HRESULT WINAPI ITextSelection_fnMoveUntil( static HRESULT WINAPI ITextSelection_fnMoveStartUntil( ITextSelection *me, VARIANT *Cset, - long Count, - long *pDelta) + LONG Count, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1249,8 +1249,8 @@ static HRESULT WINAPI ITextSelection_fnMoveStartUntil( static HRESULT WINAPI ITextSelection_fnMoveEndUntil( ITextSelection *me, VARIANT *Cset, - long Count, - long *pDelta) + LONG Count, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1263,9 +1263,9 @@ static HRESULT WINAPI ITextSelection_fnMoveEndUntil( static HRESULT WINAPI ITextSelection_fnFindText( ITextSelection *me, BSTR bstr, - long cch, - long Flags, - long *pLength) + LONG cch, + LONG Flags, + LONG *pLength) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1278,9 +1278,9 @@ static HRESULT WINAPI ITextSelection_fnFindText( static HRESULT WINAPI ITextSelection_fnFindTextStart( ITextSelection *me, BSTR bstr, - long cch, - long Flags, - long *pLength) + LONG cch, + LONG Flags, + LONG *pLength) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1293,9 +1293,9 @@ static HRESULT WINAPI ITextSelection_fnFindTextStart( static HRESULT WINAPI ITextSelection_fnFindTextEnd( ITextSelection *me, BSTR bstr, - long cch, - long Flags, - long *pLength) + LONG cch, + LONG Flags, + LONG *pLength) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1307,9 +1307,9 @@ static HRESULT WINAPI ITextSelection_fnFindTextEnd( static HRESULT WINAPI ITextSelection_fnDelete( ITextSelection *me, - long Unit, - long Count, - long *pDelta) + LONG Unit, + LONG Count, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1346,7 +1346,7 @@ static HRESULT WINAPI ITextSelection_fnCopy( static HRESULT WINAPI ITextSelection_fnPaste( ITextSelection *me, VARIANT *pVar, - long Format) + LONG Format) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1359,8 +1359,8 @@ static HRESULT WINAPI ITextSelection_fnPaste( static HRESULT WINAPI ITextSelection_fnCanPaste( ITextSelection *me, VARIANT *pVar, - long Format, - long *pb) + LONG Format, + LONG *pb) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1372,7 +1372,7 @@ static HRESULT WINAPI ITextSelection_fnCanPaste( static HRESULT WINAPI ITextSelection_fnCanEdit( ITextSelection *me, - long *pb) + LONG *pb) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1384,7 +1384,7 @@ static HRESULT WINAPI ITextSelection_fnCanEdit( static HRESULT WINAPI ITextSelection_fnChangeCase( ITextSelection *me, - long Type) + LONG Type) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1396,9 +1396,9 @@ static HRESULT WINAPI ITextSelection_fnChangeCase( static HRESULT WINAPI ITextSelection_fnGetPoint( ITextSelection *me, - long Type, - long *cx, - long *cy) + LONG Type, + LONG *cx, + LONG *cy) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1410,10 +1410,10 @@ static HRESULT WINAPI ITextSelection_fnGetPoint( static HRESULT WINAPI ITextSelection_fnSetPoint( ITextSelection *me, - long x, - long y, - long Type, - long Extend) + LONG x, + LONG y, + LONG Type, + LONG Extend) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1425,7 +1425,7 @@ static HRESULT WINAPI ITextSelection_fnSetPoint( static HRESULT WINAPI ITextSelection_fnScrollIntoView( ITextSelection *me, - long Value) + LONG Value) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1450,7 +1450,7 @@ static HRESULT WINAPI ITextSelection_fnGetEmbeddedObject( /*** ITextSelection methods ***/ static HRESULT WINAPI ITextSelection_fnGetFlags( ITextSelection *me, - long *pFlags) + LONG *pFlags) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1462,7 +1462,7 @@ static HRESULT WINAPI ITextSelection_fnGetFlags( static HRESULT WINAPI ITextSelection_fnSetFlags( ITextSelection *me, - long Flags) + LONG Flags) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1474,7 +1474,7 @@ static HRESULT WINAPI ITextSelection_fnSetFlags( static HRESULT WINAPI ITextSelection_fnGetType( ITextSelection *me, - long *pType) + LONG *pType) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1486,10 +1486,10 @@ static HRESULT WINAPI ITextSelection_fnGetType( static HRESULT WINAPI ITextSelection_fnMoveLeft( ITextSelection *me, - long Unit, - long Count, - long Extend, - long *pDelta) + LONG Unit, + LONG Count, + LONG Extend, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1501,10 +1501,10 @@ static HRESULT WINAPI ITextSelection_fnMoveLeft( static HRESULT WINAPI ITextSelection_fnMoveRight( ITextSelection *me, - long Unit, - long Count, - long Extend, - long *pDelta) + LONG Unit, + LONG Count, + LONG Extend, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1516,10 +1516,10 @@ static HRESULT WINAPI ITextSelection_fnMoveRight( static HRESULT WINAPI ITextSelection_fnMoveUp( ITextSelection *me, - long Unit, - long Count, - long Extend, - long *pDelta) + LONG Unit, + LONG Count, + LONG Extend, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1531,10 +1531,10 @@ static HRESULT WINAPI ITextSelection_fnMoveUp( static HRESULT WINAPI ITextSelection_fnMoveDown( ITextSelection *me, - long Unit, - long Count, - long Extend, - long *pDelta) + LONG Unit, + LONG Count, + LONG Extend, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1546,9 +1546,9 @@ static HRESULT WINAPI ITextSelection_fnMoveDown( static HRESULT WINAPI ITextSelection_fnHomeKey( ITextSelection *me, - long Unit, - long Extend, - long *pDelta) + LONG Unit, + LONG Extend, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) @@ -1560,9 +1560,9 @@ static HRESULT WINAPI ITextSelection_fnHomeKey( static HRESULT WINAPI ITextSelection_fnEndKey( ITextSelection *me, - long Unit, - long Extend, - long *pDelta) + LONG Unit, + LONG Extend, + LONG *pDelta) { ITextSelectionImpl *This = (ITextSelectionImpl *) me; if (!This->reOle) diff --git a/reactos/dll/win32/riched20/row.c b/reactos/dll/win32/riched20/row.c index 3abff5f7a51..1bf153f6ca9 100644 --- a/reactos/dll/win32/riched20/row.c +++ b/reactos/dll/win32/riched20/row.c @@ -24,50 +24,6 @@ #include "editor.h" -ME_DisplayItem *ME_FindRowStart(ME_Context *c, ME_DisplayItem *item, - int nRelPos) { - ME_DisplayItem *para = ME_GetParagraph(item); - ME_MustBeWrapped(c, para); - if(nRelPos<=0) { /* if this or preceding row */ - do { - ME_DisplayItem *item2 = ME_FindItemBack(item, diStartRowOrParagraph); - if (item2->type == diParagraph) - { - if (item2->member.para.prev_para == NULL) - return item; - /* if skipping to the preceding paragraph, ensure it's wrapped */ - ME_MustBeWrapped(c, item2->member.para.prev_para); - item = item2; - continue; - } - else if (item2->type == diStartRow) - { - nRelPos++; - if (nRelPos>0) - return item; - item = item2; - continue; - } - assert(0 == "bug in FindItemBack(item, diStartRowOrParagraph)"); - item = item2; - } while(1); - } - while(nRelPos>0) { /* if one of the next rows */ - ME_DisplayItem *item2 = ME_FindItemFwd(item, diStartRowOrParagraph); - if (!item2) - return item; - if (item2->type == diParagraph) - { - if (item2->member.para.next_para == NULL) - return item; - continue; - } - item = item2; - nRelPos--; - } - return item; -} - /* I'm sure these functions would simplify some code in caret ops etc, * I just didn't remember them when I wrote that code */ @@ -89,14 +45,15 @@ 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) + + while (item->type == diParagraph && + nCount + item->member.para.nRows <= nRow) { nCount += item->member.para.nRows; - item = ME_FindItemFwd(item, diParagraph); + item = item->member.para.next_para; } - if (!item) - return item; + if (item->type != diParagraph) + return NULL; for (item = ME_FindItemFwd(item, diStartRow); item && nCount < nRow; nCount++) item = ME_FindItemFwd(item, diStartRow); return item; @@ -106,18 +63,19 @@ ME_FindRowWithNumber(ME_TextEditor *editor, int nRow) int ME_RowNumberFromCharOfs(ME_TextEditor *editor, int nOfs) { - ME_DisplayItem *item = editor->pBuffer->pFirst->next; + ME_DisplayItem *item = ME_FindItemFwd(editor->pBuffer->pFirst, diParagraph); int nRow = 0; - while (item && item->member.para.next_para->member.para.nCharOfs <= nOfs) + while (item->type == diParagraph && + item->member.para.next_para->member.para.nCharOfs <= nOfs) { nRow += item->member.para.nRows; - item = ME_FindItemFwd(item, diParagraph); + item = item->member.para.next_para; } - if (item) + if (item->type == diParagraph) { ME_DisplayItem *next_para = item->member.para.next_para; - + nOfs -= item->member.para.nCharOfs; item = ME_FindItemFwd(item, diRun); while ((item = ME_FindItemFwd(item, diStartRowOrParagraph)) != NULL) diff --git a/reactos/dll/win32/riched20/run.c b/reactos/dll/win32/riched20/run.c index 1f8cc1837c4..9778ea95baf 100644 --- a/reactos/dll/win32/riched20/run.c +++ b/reactos/dll/win32/riched20/run.c @@ -141,35 +141,30 @@ void ME_CheckCharOffsets(ME_TextEditor *editor) /****************************************************************************** * ME_CharOfsFromRunOfs - * + * * Converts a character position relative to the start of the run, to a * character position relative to the start of the document. - * Kind of a "local to global" offset conversion. - */ -int ME_CharOfsFromRunOfs(ME_TextEditor *editor, ME_DisplayItem *pRun, int nOfs) + * Kind of a "local to global" offset conversion. + */ +int ME_CharOfsFromRunOfs(ME_TextEditor *editor, const ME_DisplayItem *pPara, + const ME_DisplayItem *pRun, int nOfs) { - ME_DisplayItem *pPara; - - assert(pRun->type == diRun); - assert(pRun->member.run.nCharOfs != -1); - - pPara = ME_FindItemBack(pRun, diParagraph); - assert(pPara); - assert(pPara->type==diParagraph); - return pPara->member.para.nCharOfs + pRun->member.run.nCharOfs - + ME_VPosToPos(pRun->member.run.strText, nOfs); + assert(pRun && pRun->type == diRun); + assert(pPara && pPara->type == diParagraph); + return pPara->member.para.nCharOfs + pRun->member.run.nCharOfs + nOfs; } /****************************************************************************** * ME_CursorFromCharOfs * * Converts a character offset (relative to the start of the document) to - * a cursor structure (which contains a run and a position relative to that + * a cursor structure (which contains a run and a position relative to that * run). */ void ME_CursorFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_Cursor *pCursor) { - ME_RunOfsFromCharOfs(editor, nCharOfs, &pCursor->pRun, &pCursor->nOffset); + ME_RunOfsFromCharOfs(editor, nCharOfs, &pCursor->pPara, + &pCursor->pRun, &pCursor->nOffset); } /****************************************************************************** @@ -179,13 +174,14 @@ void ME_CursorFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_Cursor *pCurso * (absolute offset being an offset relative to the start of the document). * Kind of a "global to local" offset conversion. */ -void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem **ppRun, int *pOfs) +void ME_RunOfsFromCharOfs(ME_TextEditor *editor, + int nCharOfs, + ME_DisplayItem **ppPara, + ME_DisplayItem **ppRun, + int *pOfs) { ME_DisplayItem *item, *next_item; - assert(ppRun); - assert(pOfs); - nCharOfs = max(nCharOfs, 0); nCharOfs = min(nCharOfs, ME_GetTextLength(editor)); @@ -197,6 +193,7 @@ void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem ** } while (next_item->member.para.nCharOfs <= nCharOfs); assert(item->type == diParagraph); nCharOfs -= item->member.para.nCharOfs; + if (ppPara) *ppPara = item; /* Find the run at the offset. */ next_item = ME_FindItemFwd(item, diRun); @@ -208,8 +205,8 @@ void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem ** assert(item->type == diRun); nCharOfs -= item->member.run.nCharOfs; - *ppRun = item; - *pOfs = nCharOfs; + if (ppRun) *ppRun = item; + if (pOfs) *pOfs = nCharOfs; } /****************************************************************************** @@ -229,7 +226,7 @@ void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p) for (i=0; inCursors; i++) { if (editor->pCursors[i].pRun == pNext) { editor->pCursors[i].pRun = p; - editor->pCursors[i].nOffset += ME_StrVLen(p->member.run.strText); + editor->pCursors[i].nOffset += p->member.run.strText->nLen; } } @@ -247,10 +244,10 @@ void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p) /****************************************************************************** * ME_SplitRun - * + * * Splits a run into two in a given place. It also updates the screen position - * and size (extent) of the newly generated runs. - */ + * and size (extent) of the newly generated runs. + */ ME_DisplayItem *ME_SplitRun(ME_WrapContext *wc, ME_DisplayItem *item, int nVChar) { ME_TextEditor *editor = wc->context->editor; @@ -306,7 +303,7 @@ ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_DisplayItem *item, i ME_DisplayItem *item2; ME_Run *run2; int i; - assert(nVChar > 0 && nVChar < ME_StrVLen(run->strText)); + assert(nVChar > 0 && nVChar < run->strText->nLen); assert(item->type == diRun); assert(!(item->member.run.nFlags & MERF_NONTEXT)); assert(item->member.run.nCharOfs != -1); @@ -314,8 +311,7 @@ ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_DisplayItem *item, i item2 = ME_MakeRun(run->style, ME_VSplitString(run->strText, nVChar), run->nFlags&MERF_SPLITMASK); - item2->member.run.nCharOfs = item->member.run.nCharOfs+ - ME_VPosToPos(item->member.run.strText, nVChar); + item2->member.run.nCharOfs = item->member.run.nCharOfs + nVChar; run2 = &item2->member.run; ME_InsertBefore(item->next, item2); @@ -374,75 +370,76 @@ ME_DisplayItem *ME_InsertRun(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem /****************************************************************************** * ME_InsertRunAtCursor - * + * * Inserts a new run with given style, flags and content at a given position, * which is passed as a cursor structure (which consists of a run and - * a run-relative character offset). - */ + * a run-relative character offset). + */ ME_DisplayItem * ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style, const WCHAR *str, int len, int flags) { ME_DisplayItem *pDI; ME_UndoItem *pUI; - + if (cursor->nOffset) { /* We're inserting at the middle of the existing run, which means that * that run must be split. It isn't always necessary, but */ cursor->pRun = ME_SplitRunSimple(editor, cursor->pRun, cursor->nOffset); cursor->nOffset = 0; } - + pUI = ME_AddUndoItem(editor, diUndoDeleteRun, NULL); if (pUI) { - pUI->nStart = (ME_GetParagraph(cursor->pRun)->member.para.nCharOfs - + cursor->pRun->member.run.nCharOfs); + pUI->nStart = cursor->pPara->member.para.nCharOfs + + cursor->pRun->member.run.nCharOfs; pUI->nLen = len; } - + pDI = ME_MakeRun(style, ME_MakeStringN(str, len), flags); pDI->member.run.nCharOfs = cursor->pRun->member.run.nCharOfs; ME_InsertBefore(cursor->pRun, pDI); TRACE("Shift length:%d\n", len); ME_PropagateCharOffset(cursor->pRun, len); - ME_GetParagraph(cursor->pRun)->member.para.nFlags |= MEPF_REWRAP; + cursor->pPara->member.para.nFlags |= MEPF_REWRAP; return pDI; } /****************************************************************************** * ME_UpdateRunFlags - * + * * Determine some of run attributes given its content (style, text content). - * Some flags cannot be determined by this function (MERF_GRAPHICS, - * MERF_ENDPARA) - */ + * Some flags cannot be determined by this function (MERF_GRAPHICS, + * MERF_ENDPARA) + */ void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run) { - assert(run->nCharOfs != -1); + ME_String *strText = run->strText; + assert(run->nCharOfs >= 0); if (RUN_IS_HIDDEN(run) || run->nFlags & MERF_TABLESTART) run->nFlags |= MERF_HIDDEN; else run->nFlags &= ~MERF_HIDDEN; - if (ME_IsSplitable(run->strText)) + if (ME_IsSplitable(strText)) run->nFlags |= MERF_SPLITTABLE; else run->nFlags &= ~MERF_SPLITTABLE; if (!(run->nFlags & MERF_NOTEXT)) { - if (ME_IsWhitespaces(run->strText)) + if (ME_IsWhitespaces(strText)) run->nFlags |= MERF_WHITESPACE | MERF_STARTWHITE | MERF_ENDWHITE; else { run->nFlags &= ~MERF_WHITESPACE; - if (ME_IsWSpace(ME_GetCharFwd(run->strText,0))) + if (ME_IsWSpace(strText->szData[0])) run->nFlags |= MERF_STARTWHITE; else run->nFlags &= ~MERF_STARTWHITE; - if (ME_IsWSpace(ME_GetCharBack(run->strText,0))) + if (ME_IsWSpace(strText->szData[strText->nLen - 1])) run->nFlags |= MERF_ENDWHITE; else run->nFlags &= ~MERF_ENDWHITE; @@ -486,7 +483,7 @@ int ME_CharFromPoint(ME_Context *c, int cx, ME_Run *run) if (c->editor->cPasswordMask) { - ME_String *strMasked = ME_MakeStringR(c->editor->cPasswordMask,ME_StrVLen(run->strText)); + ME_String *strMasked = ME_MakeStringR(c->editor->cPasswordMask, run->strText->nLen); GetTextExtentExPointW(c->hDC, strMasked->szData, run->strText->nLen, cx, &fit, NULL, &sz); ME_DestroyString(strMasked); @@ -504,21 +501,21 @@ int ME_CharFromPoint(ME_Context *c, int cx, ME_Run *run) /****************************************************************************** * ME_CharFromPointCursor - * + * * Returns a character position inside the run given a run-relative - * pixel horizontal position. This version rounds to the nearest character edge - * (ie. if the second character is at pixel position 8, then for cx=0..3 + * pixel horizontal position. This version rounds to the nearest character edge + * (ie. if the second character is at pixel position 8, then for cx=0..3 * it returns 0, and for cx=4..7 it returns 1). - * + * * It is used for mouse click handling, for better usability (and compatibility - * with the native control). - */ + * with the native control). + */ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run) { ME_String *strRunText; /* This could point to either the run's real text, or it's masked form in a password control */ - - int fit = 0, fit1 = 0; + + int fit = 0; ME_Context c; HGDIOBJ hOldFont; SIZE sz, sz2, sz3; @@ -543,7 +540,7 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run) } if (editor->cPasswordMask) - strRunText = ME_MakeStringR(editor->cPasswordMask,ME_StrVLen(run->strText)); + strRunText = ME_MakeStringR(editor->cPasswordMask, run->strText->nLen); else strRunText = run->strText; @@ -552,18 +549,15 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run) cx, &fit, NULL, &sz); if (fit != strRunText->nLen) { - int chars = 1; - GetTextExtentPoint32W(c.hDC, strRunText->szData, fit, &sz2); - fit1 = ME_StrRelPos(strRunText, fit, &chars); - GetTextExtentPoint32W(c.hDC, strRunText->szData, fit1, &sz3); + GetTextExtentPoint32W(c.hDC, strRunText->szData, fit + 1, &sz3); if (cx >= (sz2.cx+sz3.cx)/2) - fit = fit1; + fit = fit + 1; } - + if (editor->cPasswordMask) ME_DestroyString(strRunText); - + ME_UnselectStyleFont(&c, run->style, hOldFont); ME_DestroyContext(&c); return fit; @@ -584,10 +578,10 @@ static void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style /****************************************************************************** * ME_PointFromChar - * + * * Returns a run-relative pixel position given a run-relative character * position (character offset) - */ + */ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset) { SIZE size; @@ -600,19 +594,19 @@ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset) { if (nOffset) ME_GetOLEObjectSize(&c, pRun, &size); - ITextHost_TxReleaseDC(editor->texthost, c.hDC); + ME_DestroyContext(&c); return nOffset != 0; } else if (pRun->nFlags & MERF_ENDPARA) { nOffset = 0; } if (editor->cPasswordMask) - strRunText = ME_MakeStringR(editor->cPasswordMask,ME_StrVLen(pRun->strText)); + strRunText = ME_MakeStringR(editor->cPasswordMask, pRun->strText->nLen); else strRunText = pRun->strText; ME_GetTextExtent(&c, strRunText->szData, nOffset, pRun->style, &size); - ITextHost_TxReleaseDC(editor->texthost, c.hDC); + ME_DestroyContext(&c); if (editor->cPasswordMask) ME_DestroyString(strRunText); return size.cx; @@ -628,7 +622,7 @@ static SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run int startx, int *pAscent, int *pDescent) { SIZE size; - int nMaxLen = ME_StrVLen(run->strText); + int nMaxLen = run->strText->nLen; if (nLen>nMaxLen) nLen = nMaxLen; @@ -721,7 +715,7 @@ void ME_CalcRunExtent(ME_Context *c, const ME_Paragraph *para, int startx, ME_Ru run->nWidth = 0; else { - int nEnd = ME_StrVLen(run->strText); + int nEnd = run->strText->nLen; SIZE size = ME_GetRunSizeCommon(c, para, run, nEnd, startx, &run->nAscent, &run->nDescent); run->nWidth = size.cx; @@ -783,7 +777,7 @@ void ME_SetCharFormat(ME_TextEditor *editor, int nOfs, int nChars, CHARFORMAT2W if (tmp2.nOffset) tmp2.pRun = ME_SplitRunSimple(editor, tmp2.pRun, tmp2.nOffset); - para = ME_GetParagraph(tmp.pRun); + para = tmp.pPara; para->member.para.nFlags |= MEPF_REWRAP; while(tmp.pRun != tmp2.pRun) @@ -878,17 +872,17 @@ void ME_GetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt) /****************************************************************************** * ME_GetCharFormat - * + * * Returns the style consisting of those attributes which are consistently set - * in the whole character range. - */ + * in the whole character range. + */ void ME_GetCharFormat(ME_TextEditor *editor, int nFrom, int nTo, CHARFORMAT2W *pFmt) { ME_DisplayItem *run, *run_end; int nOffset, nOffset2; CHARFORMAT2W tmp; - ME_RunOfsFromCharOfs(editor, nFrom, &run, &nOffset); + ME_RunOfsFromCharOfs(editor, nFrom, NULL, &run, &nOffset); if (nFrom == nTo) /* special case - if selection is empty, take previous char's formatting */ { if (!nOffset) @@ -905,7 +899,7 @@ void ME_GetCharFormat(ME_TextEditor *editor, int nFrom, int nTo, CHARFORMAT2W *p if (nTo>nFrom) /* selection consists of chars from nFrom up to nTo-1 */ nTo--; - ME_RunOfsFromCharOfs(editor, nTo, &run_end, &nOffset2); + ME_RunOfsFromCharOfs(editor, nTo, NULL, &run_end, &nOffset2); ME_GetRunCharFormat(editor, run, pFmt); diff --git a/reactos/dll/win32/riched20/string.c b/reactos/dll/win32/riched20/string.c index 0bd751ce66f..128e3c2ea7c 100644 --- a/reactos/dll/win32/riched20/string.c +++ b/reactos/dll/win32/riched20/string.c @@ -18,61 +18,49 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "editor.h" +#include "editor.h" WINE_DEFAULT_DEBUG_CHANNEL(richedit); static int ME_GetOptimalBuffer(int nLen) { - return ((2*nLen+1)+128)&~63; + /* FIXME: This seems wasteful for tabs and end of lines strings, + * since they have a small fixed length. */ + return ((sizeof(WCHAR) * nLen) + 128) & ~63; } -ME_String *ME_MakeString(LPCWSTR szText) +/* Create a buffer (uninitialized string) of size nMaxChars */ +static ME_String *ME_MakeStringB(int nMaxChars) { ME_String *s = ALLOC_OBJ(ME_String); - s->nLen = lstrlenW(szText); - s->nBuffer = ME_GetOptimalBuffer(s->nLen+1); + + s->nLen = nMaxChars; + s->nBuffer = ME_GetOptimalBuffer(s->nLen + 1); s->szData = ALLOC_N_OBJ(WCHAR, s->nBuffer); - lstrcpyW(s->szData, szText); + s->szData[s->nLen] = 0; return s; } ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars) { - ME_String *s = ALLOC_OBJ(ME_String); - - s->nLen = nMaxChars; - s->nBuffer = ME_GetOptimalBuffer(s->nLen+1); - s->szData = ALLOC_N_OBJ(WCHAR, s->nBuffer); - /* Native allows NUL chars */ - memmove(s->szData, szText, s->nLen * sizeof(WCHAR)); - s->szData[s->nLen] = 0; + ME_String *s = ME_MakeStringB(nMaxChars); + /* Native allows NULL chars */ + memcpy(s->szData, szText, s->nLen * sizeof(WCHAR)); return s; } +ME_String *ME_MakeString(LPCWSTR szText) +{ + return ME_MakeStringN(szText, lstrlenW(szText)); +} + +/* Make a string by repeating a char nMaxChars times */ ME_String *ME_MakeStringR(WCHAR cRepeat, int nMaxChars) -{ /* Make a string by repeating a char nMaxChars times */ +{ int i; - ME_String *s = ALLOC_OBJ(ME_String); - - s->nLen = nMaxChars; - s->nBuffer = ME_GetOptimalBuffer(s->nLen+1); - s->szData = ALLOC_N_OBJ(WCHAR, s->nBuffer); - - for (i = 0;iszData[i] = cRepeat; - s->szData[s->nLen] = 0; - return s; -} - -ME_String *ME_MakeStringB(int nMaxChars) -{ /* Create a buffer (uninitialized string) of size nMaxChars */ - ME_String *s = ALLOC_OBJ(ME_String); - - s->nLen = nMaxChars; - s->nBuffer = ME_GetOptimalBuffer(s->nLen+1); - s->szData = ALLOC_N_OBJ(WCHAR, s->nBuffer); - s->szData[s->nLen] = 0; return s; } @@ -90,35 +78,25 @@ void ME_DestroyString(ME_String *s) void ME_AppendString(ME_String *s1, const ME_String *s2) { - if (s1->nLen+s2->nLen+1 <= s1->nBuffer) { - lstrcpyW(s1->szData+s1->nLen, s2->szData); - s1->nLen += s2->nLen; - } - else + if (s1->nLen+s2->nLen+1 <= s1->nBuffer) { + memcpy(s1->szData + s1->nLen, s2->szData, s2->nLen * sizeof(WCHAR)); + s1->nLen += s2->nLen; + s1->szData[s1->nLen] = 0; + } else { WCHAR *buf; s1->nBuffer = ME_GetOptimalBuffer(s1->nLen+s2->nLen+1); - buf = ALLOC_N_OBJ(WCHAR, s1->nBuffer); - lstrcpyW(buf, s1->szData); - lstrcpyW(buf+s1->nLen, s2->szData); + buf = ALLOC_N_OBJ(WCHAR, s1->nBuffer); + memcpy(buf, s1->szData, s1->nLen * sizeof(WCHAR)); + memcpy(buf + s1->nLen, s2->szData, s2->nLen * sizeof(WCHAR)); FREE_OBJ(s1->szData); s1->szData = buf; s1->nLen += s2->nLen; + s1->szData[s1->nLen] = 0; } } -ME_String *ME_ConcatString(const ME_String *s1, const ME_String *s2) -{ - ME_String *s = ALLOC_OBJ(ME_String); - s->nLen = s1->nLen+s2->nLen; - s->nBuffer = ME_GetOptimalBuffer(s1->nLen+s2->nLen+1); - s->szData = ALLOC_N_OBJ(WCHAR, s->nBuffer); - lstrcpyW(s->szData, s1->szData); - lstrcpyW(s->szData+s1->nLen, s2->szData); - return s; -} - ME_String *ME_VSplitString(ME_String *orig, int charidx) { ME_String *s; @@ -163,113 +141,17 @@ int ME_IsSplitable(const ME_String *s) return 0; } -/* FIXME multibyte */ -/* -int ME_CalcSkipChars(ME_String *s) -{ - int cnt = 0; - while(cnt < s->nLen && s->szData[s->nLen-1-cnt]==' ') - cnt++; - return cnt; -} -*/ - -int ME_StrLen(const ME_String *s) { - return s->nLen; -} - -int ME_StrVLen(const ME_String *s) { - return s->nLen; -} - -int ME_StrRelPos(const ME_String *s, int nVChar, int *pRelChars) -{ - int nRelChars = *pRelChars; - - TRACE("%s,%d,&%d\n", debugstr_w(s->szData), nVChar, *pRelChars); - - assert(*pRelChars); - if (!nRelChars) - return nVChar; - - if (nRelChars>0) - nRelChars = min(*pRelChars, s->nLen - nVChar); - else - nRelChars = max(*pRelChars, -nVChar); - nVChar += nRelChars; - *pRelChars -= nRelChars; - return nVChar; -} - -int ME_StrRelPos2(const ME_String *s, int nVChar, int nRelChars) -{ - return ME_StrRelPos(s, nVChar, &nRelChars); -} - -int ME_VPosToPos(ME_String *s, int nVPos) -{ - return nVPos; - /* - int i = 0, len = 0; - if (!nVPos) - return 0; - while (i < s->nLen) - { - if (i == nVPos) - return len; - if (s->szData[i]=='\\') i++; - i++; - len++; - } - return len; - */ -} - -int ME_PosToVPos(const ME_String *s, int nPos) -{ - if (!nPos) - return 0; - return ME_StrRelPos2(s, 0, nPos); -} - void ME_StrDeleteV(ME_String *s, int nVChar, int nChars) { - int end_ofs; - - assert(nVChar >=0 && nVChar <= s->nLen); + int end_ofs = nVChar + nChars; + assert(nChars >= 0); - assert(nVChar+nChars <= s->nLen); - - end_ofs = ME_StrRelPos2(s, nVChar, nChars); + assert(nVChar >= 0); assert(end_ofs <= s->nLen); - memmove(s->szData+nVChar, s->szData+end_ofs, 2*(s->nLen+1-end_ofs)); - s->nLen -= (end_ofs - nVChar); -} -int ME_GetCharFwd(const ME_String *s, int nPos) -{ - int nVPos = 0; - - assert(nPos < ME_StrLen(s)); - if (nPos) - nVPos = ME_StrRelPos2(s, nVPos, nPos); - - if (nVPos < s->nLen) - return s->szData[nVPos]; - return -1; -} - -int ME_GetCharBack(const ME_String *s, int nPos) -{ - int nVPos = ME_StrVLen(s); - - assert(nPos < ME_StrLen(s)); - if (nPos) - nVPos = ME_StrRelPos2(s, nVPos, -nPos); - - if (nVPos < s->nLen) - return s->szData[nVPos]; - return -1; + memmove(s->szData + nVChar, s->szData + end_ofs, + (s->nLen - end_ofs + 1) * sizeof(WCHAR)); + s->nLen -= nChars; } int ME_FindNonWhitespaceV(const ME_String *s, int nVChar) { diff --git a/reactos/dll/win32/riched20/style.c b/reactos/dll/win32/riched20/style.c index 3980400fb65..a3b532ebd43 100644 --- a/reactos/dll/win32/riched20/style.c +++ b/reactos/dll/win32/riched20/style.c @@ -71,12 +71,6 @@ CHARFORMAT2W *ME_ToCF2W(CHARFORMAT2W *to, CHARFORMAT2W *from) return (from->cbSize >= sizeof(CHARFORMAT2W)) ? from : NULL; } -void ME_CopyToCF2W(CHARFORMAT2W *to, CHARFORMAT2W *from) -{ - if (ME_ToCF2W(to, from) == from) - *to = *from; -} - static CHARFORMAT2W *ME_ToCFAny(CHARFORMAT2W *to, CHARFORMAT2W *from) { assert(from->cbSize == sizeof(CHARFORMAT2W)); diff --git a/reactos/dll/win32/riched20/table.c b/reactos/dll/win32/riched20/table.c index e7eca244426..6c8ca76c4e7 100644 --- a/reactos/dll/win32/riched20/table.c +++ b/reactos/dll/win32/riched20/table.c @@ -70,6 +70,7 @@ static ME_DisplayItem* ME_InsertEndParaFromCursor(ME_TextEditor *editor, } tp = ME_SplitParagraph(editor, cursor->pRun, pStyle, eol_str, paraFlags); + cursor->pPara = tp; cursor->pRun = ME_FindItemFwd(tp, diRun); return tp; } @@ -89,6 +90,7 @@ ME_DisplayItem* ME_InsertTableRowStartAtParagraph(ME_TextEditor *editor, ME_DisplayItem *prev_para, *end_para; ME_Cursor savedCursor = editor->pCursors[0]; ME_DisplayItem *startRowPara; + editor->pCursors[0].pPara = para; editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; @@ -96,7 +98,7 @@ ME_DisplayItem* ME_InsertTableRowStartAtParagraph(ME_TextEditor *editor, editor->pCursors[0] = savedCursor; editor->pCursors[1] = editor->pCursors[0]; - end_para = ME_GetParagraph(editor->pCursors[0].pRun)->member.para.next_para; + end_para = editor->pCursors[0].pPara->member.para.next_para; prev_para = startRowPara->member.para.next_para; para = prev_para->member.para.next_para; while (para != end_para) @@ -276,9 +278,9 @@ void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, int nOfs,int *nChars) ME_Cursor c, c2; ME_DisplayItem *this_para, *end_para; ME_CursorFromCharOfs(editor, nOfs, &c); - this_para = ME_GetParagraph(c.pRun); + this_para = c.pPara; ME_CursorFromCharOfs(editor, nOfs + *nChars, &c2); - end_para = ME_GetParagraph(c2.pRun); + end_para = c2.pPara; if (c2.pRun->member.run.nFlags & MERF_ENDPARA) { /* End offset might be in the middle of the end paragraph run. * If this is the case, then we need to use the next paragraph as the last @@ -399,14 +401,15 @@ ME_DisplayItem* ME_AppendTableRow(ME_TextEditor *editor, ME_DisplayItem *insertedCell, *para, *cell, *prevTableEnd; cell = ME_FindItemFwd(ME_GetTableRowStart(table_row), diCell); prevTableEnd = ME_GetTableRowEnd(table_row); - run = prevTableEnd->member.para.next_para; - run = ME_FindItemFwd(run, diRun); + para = prevTableEnd->member.para.next_para; + run = ME_FindItemFwd(para, diRun); + editor->pCursors[0].pPara = para; editor->pCursors[0].pRun = run; editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; para = ME_InsertTableRowStartFromCursor(editor); insertedCell = ME_FindItemFwd(para, diCell); - /* Copy cell properties */ + /* Copy cell properties */ insertedCell->member.cell.nRightBoundary = cell->member.cell.nRightBoundary; insertedCell->member.cell.border = cell->member.cell.border; while (cell->member.cell.next_cell) { @@ -425,6 +428,7 @@ ME_DisplayItem* ME_AppendTableRow(ME_TextEditor *editor, run = ME_FindItemBack(table_row->member.para.next_para, diRun); pFmt = table_row->member.para.pFmt; assert(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE); + editor->pCursors[0].pPara = table_row; editor->pCursors[0].pRun = run; editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; @@ -474,6 +478,7 @@ static void ME_SelectOrInsertNextCell(ME_TextEditor *editor, para = ME_AppendTableRow(editor, ME_GetTableRowStart(para)); /* Put cursor at the start of the new table row */ para = para->member.para.next_para; + editor->pCursors[0].pPara = para; editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; @@ -483,10 +488,12 @@ static void ME_SelectOrInsertNextCell(ME_TextEditor *editor, } /* Select cell */ editor->pCursors[1].pRun = ME_FindItemFwd(cell, diRun); + editor->pCursors[1].pPara = ME_GetParagraph(editor->pCursors[1].pRun); editor->pCursors[1].nOffset = 0; assert(editor->pCursors[0].pRun); cell = cell->member.cell.next_cell; editor->pCursors[0].pRun = ME_FindItemBack(cell, diRun); + editor->pCursors[0].pPara = ME_GetParagraph(editor->pCursors[0].pRun); editor->pCursors[0].nOffset = 0; assert(editor->pCursors[1].pRun); } else { /* v1.0 - 3.0 */ @@ -508,6 +515,7 @@ static void ME_SelectOrInsertNextCell(ME_TextEditor *editor, { run = ME_FindItemFwd(para, diRun); assert(run); + editor->pCursors[0].pPara = para; editor->pCursors[0].pRun = run; editor->pCursors[0].nOffset = 0; i = 1; @@ -515,6 +523,7 @@ static void ME_SelectOrInsertNextCell(ME_TextEditor *editor, /* Insert table row */ para = ME_AppendTableRow(editor, para->member.para.prev_para); /* Put cursor at the start of the new table row */ + editor->pCursors[0].pPara = para; editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; @@ -526,6 +535,7 @@ static void ME_SelectOrInsertNextCell(ME_TextEditor *editor, if (i == 0) run = ME_FindItemFwd(run, diRun); editor->pCursors[i].pRun = run; + editor->pCursors[i].pPara = ME_GetParagraph(run); editor->pCursors[i].nOffset = 0; } } @@ -595,12 +605,13 @@ void ME_TabPressedInTable(ME_TextEditor *editor, BOOL bSelectedRow) * without a selection. */ void ME_MoveCursorFromTableRowStartParagraph(ME_TextEditor *editor) { - ME_DisplayItem *para = ME_GetParagraph(editor->pCursors[0].pRun); - if (para == ME_GetParagraph(editor->pCursors[1].pRun) && + ME_DisplayItem *para = editor->pCursors[0].pPara; + if (para == editor->pCursors[1].pPara && para->member.para.nFlags & MEPF_ROWSTART) { /* The cursors should not be at the hidden start row paragraph without * a selection, so the cursor is moved into the first cell. */ para = para->member.para.next_para; + editor->pCursors[0].pPara = para; editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun); editor->pCursors[0].nOffset = 0; editor->pCursors[1] = editor->pCursors[0]; diff --git a/reactos/dll/win32/riched20/txthost.c b/reactos/dll/win32/riched20/txthost.c index 5b52b9f84cc..8fabd8388d1 100644 --- a/reactos/dll/win32/riched20/txthost.c +++ b/reactos/dll/win32/riched20/txthost.c @@ -59,7 +59,7 @@ ITextHost *ME_CreateTextHost(HWND hwnd, BOOL bEmulateVersion10) editor = ME_MakeEditor((ITextHost*)texthost, bEmulateVersion10); editor->exStyleFlags = GetWindowLongW(hwnd, GWL_EXSTYLE); - editor->hWnd = hwnd; /* FIXME: Remove editor's dependance on hWnd */ + editor->hWnd = hwnd; /* FIXME: Remove editor's dependence on hWnd */ SetWindowLongPtrW(hwnd, 0, (LONG_PTR)editor); } @@ -258,14 +258,14 @@ HRESULT WINAPI ITextHostImpl_TxActivate(ITextHost *iface, LONG *plOldState) { ITextHostImpl *This = (ITextHostImpl *)iface; - *plOldState = (LONG)SetActiveWindow(This->hWnd); + *plOldState = HandleToLong(SetActiveWindow(This->hWnd)); return (*plOldState ? S_OK : E_FAIL); } HRESULT WINAPI ITextHostImpl_TxDeactivate(ITextHost *iface, LONG lNewState) { - HWND ret = SetActiveWindow((HWND)lNewState); + HWND ret = SetActiveWindow(LongToHandle(lNewState)); return (ret ? S_OK : E_FAIL); } @@ -323,7 +323,7 @@ HRESULT WINAPI ITextHostImpl_TxGetScrollBars(ITextHost *iface, DWORD *pdwScrollBar) { ITextHostImpl *This = (ITextHostImpl *)iface; - ME_TextEditor *editor = (ME_TextEditor*)GetWindowLongW(This->hWnd, 0); + ME_TextEditor *editor = (ME_TextEditor*)GetWindowLongPtrW(This->hWnd, 0); const DWORD mask = WS_VSCROLL| WS_HSCROLL| ES_AUTOVSCROLL| @@ -452,8 +452,6 @@ HRESULT WINAPI ITextHostImpl_TxNotify(ITextHost *iface, HWND parent = GetParent(hwnd); UINT id = GetWindowLongW(hwnd, GWLP_ID); - /* Note: EN_MSGFILTER is documented as not being sent to TxNotify */ - switch (iNotify) { case EN_DROPFILES: @@ -492,6 +490,9 @@ HRESULT WINAPI ITextHostImpl_TxNotify(ITextHost *iface, SendMessageW(parent, WM_COMMAND, MAKEWPARAM(id, iNotify), (LPARAM)hwnd); break; + case EN_MSGFILTER: + FIXME("EN_MSGFILTER is documented as not being sent to TxNotify\n"); + /* fall through */ default: return E_FAIL; } diff --git a/reactos/dll/win32/riched20/txtsrv.c b/reactos/dll/win32/riched20/txtsrv.c index d7b915cc1c9..a6d81703528 100644 --- a/reactos/dll/win32/riched20/txtsrv.c +++ b/reactos/dll/win32/riched20/txtsrv.c @@ -156,8 +156,10 @@ HRESULT WINAPI fnTextSrv_TxSendMessage(ITextServices *iface, { ICOM_THIS_MULTI(ITextServicesImpl, lpVtbl, iface); HRESULT hresult; + LRESULT lresult; - *plresult = ME_HandleMessage(This->editor, msg, wparam, lparam, TRUE, &hresult); + lresult = ME_HandleMessage(This->editor, msg, wparam, lparam, TRUE, &hresult); + if (plresult) *plresult = lresult; return hresult; } diff --git a/reactos/dll/win32/riched20/undo.c b/reactos/dll/win32/riched20/undo.c index 423a6d463e7..c2f7125b621 100644 --- a/reactos/dll/win32/riched20/undo.c +++ b/reactos/dll/win32/riched20/undo.c @@ -316,7 +316,7 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem) ME_Cursor tmp; ME_CursorFromCharOfs(editor, pUItem->nStart, &tmp); /* the only thing that's needed is paragraph offset, so no need to split runs */ - ME_JoinParagraphs(editor, ME_GetParagraph(tmp.pRun), TRUE); + ME_JoinParagraphs(editor, tmp.pPara, TRUE); break; } case diUndoSplitParagraph: @@ -329,7 +329,7 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem) if (tmp.nOffset) tmp.pRun = ME_SplitRunSimple(editor, tmp.pRun, tmp.nOffset); assert(pUItem->eol_str); - this_para = ME_GetParagraph(tmp.pRun); + this_para = tmp.pPara; bFixRowStart = this_para->member.para.nFlags & MEPF_ROWSTART; if (bFixRowStart) { diff --git a/reactos/dll/win32/riched20/wrap.c b/reactos/dll/win32/riched20/wrap.c index 4edbbb2d849..579f33ae19f 100644 --- a/reactos/dll/win32/riched20/wrap.c +++ b/reactos/dll/win32/riched20/wrap.c @@ -42,10 +42,11 @@ static ME_DisplayItem *ME_MakeRow(int height, int baseline, int width) return item; } -static void ME_BeginRow(ME_WrapContext *wc, ME_DisplayItem *para) +static void ME_BeginRow(ME_WrapContext *wc) { PARAFORMAT2 *pFmt; - assert(para && para->type == diParagraph); + ME_DisplayItem *para = wc->pPara; + pFmt = para->member.para.pFmt; wc->pRowStart = NULL; wc->bOverflown = FALSE; @@ -77,7 +78,7 @@ static void ME_BeginRow(ME_WrapContext *wc, ME_DisplayItem *para) - (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin; wc->bWordWrap = TRUE; } else { - wc->nAvailWidth = wc->context->rcView.right - wc->context->rcView.left + wc->nAvailWidth = wc->context->nAvailWidth - (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin; } wc->pt.x = wc->context->pt.x; @@ -94,7 +95,7 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) int ascent = 0, descent = 0, width=0, shift = 0, align = 0; PARAFORMAT2 *pFmt; /* wrap text */ - para = ME_GetParagraph(wc->pRowStart); + para = wc->pPara; pFmt = para->member.para.pFmt; for (p = pEnd->prev; p!=wc->pRowStart->prev; p = p->prev) @@ -114,7 +115,8 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) WCHAR *text = p->member.run.strText->szData + len - 1; assert (len); - while (len && *(text--) == ' ') + if (~p->member.run.nFlags & MERF_GRAPHICS) + while (len && *(text--) == ' ') len--; if (len) { @@ -162,12 +164,12 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) ME_InsertBefore(wc->pRowStart, row); wc->nRow++; wc->pt.y += row->member.row.nHeight; - ME_BeginRow(wc, para); + ME_BeginRow(wc); } static void ME_WrapEndParagraph(ME_WrapContext *wc, ME_DisplayItem *p) { - ME_DisplayItem *para = p->member.para.prev_para; + ME_DisplayItem *para = wc->pPara; PARAFORMAT2 *pFmt = para->member.para.pFmt; if (wc->pRowStart) ME_InsertRowStart(wc, p); @@ -180,7 +182,7 @@ static void ME_WrapEndParagraph(ME_WrapContext *wc, ME_DisplayItem *p) } /* - p = p->member.para.prev_para->next; + p = para->next; while(p) { if (p->type == diParagraph || p->type == diTextEnd) return; @@ -200,7 +202,7 @@ static void ME_WrapSizeRun(ME_WrapContext *wc, ME_DisplayItem *p) ME_UpdateRunFlags(wc->context->editor, &p->member.run); - ME_CalcRunExtent(wc->context, &ME_GetParagraph(p)->member.para, + ME_CalcRunExtent(wc->context, &wc->pPara->member.para, wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, &p->member.run); } @@ -253,7 +255,7 @@ static ME_DisplayItem *ME_SplitByBacktracking(ME_WrapContext *wc, ME_DisplayItem ME_Run *run = &p->member.run; idesp = i = ME_CharFromPoint(wc->context, loc, run); - len = ME_StrVLen(run->strText); + len = run->strText->nLen; assert(len>0); assert(ipLastSplittableRun; run = &piter->member.run; - len = ME_StrVLen(run->strText); + len = run->strText->nLen; /* don't split words */ i = ME_ReverseFindWhitespaceV(run->strText, len); if (i == len) @@ -315,11 +317,9 @@ static ME_DisplayItem *ME_SplitByBacktracking(ME_WrapContext *wc, ME_DisplayItem else { /* split point inside first character - no choice but split after that char */ - int chars = 1; - int pos2 = ME_StrRelPos(run->strText, 0, &chars); - if (pos2 != len) { + if (len != 1) { /* the run is more than 1 char, so we may split */ - return ME_SplitRun(wc, piter, pos2); + return ME_SplitRun(wc, piter, 1); } /* the run is one char, can't split it */ return piter; @@ -339,7 +339,7 @@ static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p) run->pt.x = wc->pt.x; run->pt.y = wc->pt.y; ME_WrapSizeRun(wc, p); - len = ME_StrVLen(run->strText); + len = run->strText->nLen; if (wc->bOverflown) /* just skipping final whitespaces */ { @@ -473,6 +473,7 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) { pFmt = tp->member.para.pFmt; wc.context = c; + wc.pPara = tp; /* wc.para_style = tp->member.para.style; */ wc.style = NULL; if (tp->member.para.nFlags & MEPF_ROWEND) { @@ -511,7 +512,7 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) { linespace = ME_GetParaLineSpace(c, &tp->member.para); - ME_BeginRow(&wc, tp); + ME_BeginRow(&wc); for (p = tp->next; p!=tp->member.para.next_para; ) { assert(p->type != diStartRow); if (p->type == diRun) { diff --git a/reactos/dll/win32/riched20/writer.c b/reactos/dll/win32/riched20/writer.c index 5a5135e986f..d1d99902761 100644 --- a/reactos/dll/win32/riched20/writer.c +++ b/reactos/dll/win32/riched20/writer.c @@ -766,13 +766,11 @@ static BOOL ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nChars, int dwFormat) { ME_DisplayItem *p, *pEnd, *pPara; - int nOffset, nEndLen; - - ME_RunOfsFromCharOfs(editor, nStart, &p, &nOffset); - ME_RunOfsFromCharOfs(editor, nStart+nChars, &pEnd, &nEndLen); - - pPara = ME_GetParagraph(p); - + int nOffset, nEndLen; + + ME_RunOfsFromCharOfs(editor, nStart, &pPara, &p, &nOffset); + ME_RunOfsFromCharOfs(editor, nStart+nChars, NULL, &pEnd, &nEndLen); + if (!ME_StreamOutRTFHeader(pStream, dwFormat)) return FALSE; @@ -891,7 +889,7 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC if (!ME_StreamOutRTFCharProps(pStream, &p->member.run.style->fmt)) return FALSE; - nEnd = (p == pEnd) ? nEndLen : ME_StrLen(p->member.run.strText); + nEnd = (p == pEnd) ? nEndLen : p->member.run.strText->nLen; if (!ME_StreamOutRTFText(pStream, p->member.run.strText->szData + nOffset, nEnd - nOffset)) return FALSE; nOffset = 0; @@ -922,7 +920,7 @@ ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int n int nBufLen = 0; BOOL success = TRUE; - ME_RunOfsFromCharOfs(editor, nStart, &item, &nStart); + ME_RunOfsFromCharOfs(editor, nStart, NULL, &item, &nStart); if (!item) return FALSE; @@ -933,7 +931,7 @@ ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int n /* TODO: Handle SF_TEXTIZED */ while (success && nChars && item) { - nLen = min(nChars, ME_StrLen(item->member.run.strText) - nStart); + nLen = min(nChars, item->member.run.strText->nLen - nStart); if (!editor->bEmulateVersion10 && item->member.run.nFlags & MERF_ENDPARA) {