richedit: Store paragraph in cursors.

This prevents some needless searching for the start of the paragraph
from a run stored in a cursor.  Usually a pointer to the paragraph is
already available when the cursor is set anyway.
oldstable
Dylan Smith 2009-02-09 12:01:35 -05:00 committed by Alexandre Julliard
parent 2033312b43
commit ecb6c2169c
8 changed files with 156 additions and 96 deletions

View File

@ -95,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);
@ -146,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;
@ -170,7 +174,7 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor,
{
ME_DisplayItem *row;
ME_DisplayItem *run = pCursor->pRun;
ME_DisplayItem *para = ME_GetParagraph(run);
ME_DisplayItem *para = pCursor->pPara;
ME_DisplayItem *pSizeRun = run;
ME_Context c;
SIZE sz = {0, 0};
@ -266,7 +270,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars,
nChars = min(nChars, ME_GetTextLength(editor) - nOfs);
ME_CursorFromCharOfs(editor, nOfs, &c);
start_para = ME_GetParagraph(c.pRun);
start_para = c.pPara;
if (!bForce)
{
@ -281,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;
@ -321,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;
@ -369,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; i<editor->nCursors; 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) {
@ -391,9 +396,9 @@ 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
@ -405,7 +410,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars,
ME_Remove(cursor.pRun);
ME_DestroyDisplayItem(cursor.pRun);
}
shift = 0;
/*
ME_CheckCharOffsets(editor);
@ -560,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;
@ -581,6 +587,7 @@ ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs)
{
if (!pCursor->nOffset)
{
ME_DisplayItem *pPara = pCursor->pPara;
do {
pRun = ME_FindItemBack(pRun, diRunOrParagraph);
assert(pRun);
@ -589,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);
@ -602,6 +611,7 @@ 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;
@ -631,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;
@ -653,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)
@ -680,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;
}
@ -726,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;
@ -769,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;
@ -794,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 */
@ -851,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;
}
@ -951,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;
@ -979,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;
}
@ -1021,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;
}
}
@ -1040,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;
}
}
@ -1282,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);
}
@ -1292,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
@ -1338,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);
@ -1357,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;
@ -1399,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);
@ -1417,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;
}
}
@ -1425,7 +1451,8 @@ static void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor)
static void ME_ArrowCtrlHome(ME_TextEditor *editor, ME_Cursor *pCursor)
{
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;
}
@ -1443,18 +1470,21 @@ static void ME_ArrowEnd(ME_TextEditor *editor, ME_Cursor *pCursor)
ME_DisplayItem *pRun = ME_FindItemFwd(pRow, diRun);
assert(pRun);
pCursor->pRun = pRun;
assert(pCursor->pPara == ME_GetParagraph(pCursor->pRun));
pCursor->nOffset = 0;
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)
{
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;

View File

@ -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, &para->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)
{
@ -2122,7 +2122,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;
@ -2140,6 +2140,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];
@ -2148,7 +2149,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)
@ -2156,6 +2157,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,
@ -2163,6 +2165,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;
@ -2172,7 +2175,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)
@ -2180,6 +2183,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];
@ -2194,8 +2198,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,
@ -2203,6 +2209,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];
@ -2325,7 +2332,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);
@ -2336,7 +2343,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) &&
@ -2357,6 +2364,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];
@ -2604,10 +2612,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;

View File

@ -263,6 +263,7 @@ typedef struct tagME_TextBuffer
typedef struct tagME_Cursor
{
ME_DisplayItem *pPara;
ME_DisplayItem *pRun;
int nOffset;
} ME_Cursor;

View File

@ -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)
@ -1226,7 +1224,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);

View File

@ -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; i<editor->nCursors; 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;
@ -516,8 +527,8 @@ ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayIte
{
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;

View File

@ -163,7 +163,8 @@ int ME_CharOfsFromRunOfs(ME_TextEditor *editor, const ME_DisplayItem *pPara,
*/
void ME_CursorFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_Cursor *pCursor)
{
ME_RunOfsFromCharOfs(editor, nCharOfs, NULL, &pCursor->pRun, &pCursor->nOffset);
ME_RunOfsFromCharOfs(editor, nCharOfs, &pCursor->pPara,
&pCursor->pRun, &pCursor->nOffset);
}
/******************************************************************************
@ -243,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;
@ -369,38 +370,38 @@ 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;
}
@ -577,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;
@ -776,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)

View File

@ -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];

View File

@ -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)
{