diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c index 99ad947..754c75f 100644 --- a/dlls/riched20/caret.c +++ b/dlls/riched20/caret.c @@ -262,13 +262,20 @@ void ME_HideCaret(ME_TextEditor *ed) } } -void ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, - int nChars) +BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars, + BOOL bForce) { ME_Cursor c; int shift = 0; int totalChars = nChars; - + + if (!bForce) + { + ME_ProtectPartialTableDeletion(editor, nOfs, &nChars); + if (nChars == 0) + return FALSE; + } + while(nChars > 0) { ME_Run *run; @@ -280,7 +287,7 @@ void ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, if (!ME_FindItemFwd(c.pRun, diParagraph)) { - return; + return TRUE; } keepFirstParaFormat = (totalChars == nChars && nChars <= eollen && run->nCharOfs); @@ -377,15 +384,16 @@ void ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, continue; } } + return TRUE; } -void ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, - int nChars) +BOOL ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars) { assert(nCursor>=0 && nCursornCursors); /* text operations set modified state */ editor->nModifyStep = 1; - ME_InternalDeleteText(editor, ME_GetCursorOfs(editor, nCursor), nChars); + return ME_InternalDeleteText(editor, ME_GetCursorOfs(editor, nCursor), nChars, + FALSE); } static ME_DisplayItem * diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index 6754440..2528e94 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -1082,14 +1082,14 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre if ((format & SFF_SELECTION) && (editor->mode & TM_RICHTEXT)) { style = ME_GetSelectionInsertStyle(editor); - ME_InternalDeleteText(editor, from, to-from); + ME_InternalDeleteText(editor, from, to-from, FALSE); } else { ME_DisplayItem *para_item; style = editor->pBuffer->pDefaultStyle; ME_AddRefStyle(style); SendMessageA(editor->hWnd, EM_SETSEL, 0, 0); - ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor)); + ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor), FALSE); from = to = 0; ME_ClearTempStyle(editor); @@ -1165,7 +1165,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre ME_GetTextW(editor, lastchar, newto - linebreakSize, linebreakSize, 0); if (lastchar[0] == '\r' && (lastchar[1] == '\n' || lastchar[1] == '\0')) { - ME_InternalDeleteText(editor, newto - linebreakSize, linebreakSize); + ME_InternalDeleteText(editor, newto - linebreakSize, linebreakSize, FALSE); } } } @@ -2353,7 +2353,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, if (pStruct->flags & ST_SELECTION) { ME_GetSelection(editor, &from, &to); style = ME_GetSelectionInsertStyle(editor); - ME_InternalDeleteText(editor, from, to - from); + ME_InternalDeleteText(editor, from, to - from, FALSE); if (pStruct->codepage != 1200 && lParam && !strncmp((char *)lParam, "{\\rtf", 5)) ME_StreamInRTFString(editor, 1, (char *)lParam); else ME_InsertTextFromCursor(editor, 0, wszText, len, style); @@ -2362,7 +2362,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, if (editor->AutoURLDetect_bEnable) ME_UpdateSelectionLinkAttribute(editor); } else { - ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor)); + ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor), FALSE); if (pStruct->codepage != 1200 && lParam && !strncmp((char *)lParam, "{\\rtf", 5)) ME_StreamInRTFString(editor, 0, (char *)lParam); else ME_InsertTextFromCursor(editor, 0, wszText, len, editor->pBuffer->pDefaultStyle); @@ -2530,7 +2530,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, { int from, to; ME_GetSelection(editor, &from, &to); - ME_InternalDeleteText(editor, from, to-from); + ME_InternalDeleteText(editor, from, to-from, FALSE); ME_CommitUndo(editor); ME_UpdateRepaint(editor); return 0; @@ -2545,7 +2545,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, ME_GetSelection(editor, &from, &to); style = ME_GetSelectionInsertStyle(editor); - ME_InternalDeleteText(editor, from, to-from); + ME_InternalDeleteText(editor, from, to-from, FALSE); ME_InsertTextFromCursor(editor, 0, wszText, len, style); ME_ReleaseStyle(style); /* drop temporary style if line end */ @@ -2604,7 +2604,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, } case WM_SETTEXT: { - ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor)); + ME_InternalDeleteText(editor, 0, ME_GetTextLength(editor), FALSE); if (lParam) { TRACE("WM_SETTEXT lParam==%lx\n",lParam); @@ -2704,7 +2704,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, } if (SUCCEEDED(hr) && msg == WM_CUT) { - ME_InternalDeleteText(editor, range.cpMin, range.cpMax-range.cpMin); + ME_InternalDeleteText(editor, range.cpMin, range.cpMax-range.cpMin, FALSE); ME_CommitUndo(editor); ME_UpdateRepaint(editor); } diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index 869a2ce..ed0175f 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -182,7 +182,7 @@ void ME_MoveCaret(ME_TextEditor *ed); int ME_CharFromPos(ME_TextEditor *editor, int x, int y, BOOL *isExact); void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum); void ME_MouseMove(ME_TextEditor *editor, int x, int y); -void ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars); +BOOL ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars); void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, const WCHAR *str, int len, ME_Style *style); void ME_InsertEndRowFromCursor(ME_TextEditor *editor, int nCursor); @@ -198,7 +198,7 @@ BOOL ME_IsSelection(ME_TextEditor *editor); void ME_DeleteSelection(ME_TextEditor *editor); void ME_SendSelChange(ME_TextEditor *editor); void ME_InsertOLEFromCursor(ME_TextEditor *editor, const REOBJECT* reo, int nCursor); -void ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars); +BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars, BOOL bForce); int ME_GetTextLength(ME_TextEditor *editor); int ME_GetTextLengthEx(ME_TextEditor *editor, const GETTEXTLENGTHEX *how); ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor); @@ -287,6 +287,7 @@ void ME_UpdateSelectionLinkAttribute(ME_TextEditor *editor); /* table.c */ BOOL ME_IsInTable(ME_DisplayItem *pItem); +void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, int nOfs,int *nChars); void ME_TabPressedInTable(ME_TextEditor *editor, BOOL bSelectedRow); /* undo.c */ diff --git a/dlls/riched20/table.c b/dlls/riched20/table.c index ace36d0..78b38d4 100644 --- a/dlls/riched20/table.c +++ b/dlls/riched20/table.c @@ -47,6 +47,67 @@ BOOL ME_IsInTable(ME_DisplayItem *pItem) return pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE; } +/* Table rows should either be deleted completely or not at all. */ +void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, int nOfs,int *nChars) +{ + ME_Cursor c, c2; + ME_DisplayItem *this_para, *end_para; + ME_DisplayItem *pRun; + int nCharsToBoundary; + + ME_CursorFromCharOfs(editor, nOfs, &c); + this_para = ME_GetParagraph(c.pRun); + ME_CursorFromCharOfs(editor, nOfs + *nChars, &c2); + end_para = ME_GetParagraph(c2.pRun); + 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 + * paragraphs. + */ + int remaining = nOfs + *nChars - c2.pRun->member.run.nCharOfs + - end_para->member.para.nCharOfs; + if (remaining) + { + assert(remaining < c2.pRun->member.run.nCR + c2.pRun->member.run.nLF); + end_para = end_para->member.para.next_para; + } + } + + if ((this_para->member.para.nCharOfs != nOfs || this_para == end_para) && + this_para->member.para.pFmt->dwMask & PFM_TABLE && + this_para->member.para.pFmt->wEffects & PFE_TABLE) + { + pRun = c.pRun; + /* Find the next tab or end paragraph to use as a delete boundary */ + while (!(pRun->member.run.nFlags & (MERF_TAB|MERF_ENDPARA))) + pRun = ME_FindItemFwd(pRun, diRun); + nCharsToBoundary = pRun->member.run.nCharOfs + - c.pRun->member.run.nCharOfs + - c.nOffset; + *nChars = min(*nChars, nCharsToBoundary); + } else if (end_para->member.para.pFmt->dwMask & PFM_TABLE && + end_para->member.para.pFmt->wEffects & PFE_TABLE) + { + /* The deletion starts from before the row, so don't join it with + * previous non-empty paragraphs. */ + pRun = NULL; + if (nOfs > this_para->member.para.nCharOfs) + pRun = ME_FindItemBack(end_para, diRun); + if (!pRun) + pRun = ME_FindItemFwd(end_para, diRun); + if (pRun) + { + nCharsToBoundary = ME_GetParagraph(pRun)->member.para.nCharOfs + + pRun->member.run.nCharOfs + - nOfs; + if (nCharsToBoundary >= 0) + *nChars = min(*nChars, nCharsToBoundary); + } + } + if (*nChars < 0) + nChars = 0; +} + static ME_DisplayItem* ME_AppendTableRow(ME_TextEditor *editor, ME_DisplayItem *table_row) { diff --git a/dlls/riched20/undo.c b/dlls/riched20/undo.c index 9fcdc4b..d5e071c 100644 --- a/dlls/riched20/undo.c +++ b/dlls/riched20/undo.c @@ -300,7 +300,7 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem) } case diUndoDeleteRun: { - ME_InternalDeleteText(editor, pUItem->nStart, pUItem->nLen); + ME_InternalDeleteText(editor, pUItem->nStart, pUItem->nLen, TRUE); break; } case diUndoJoinParagraphs: