richedit: Created functions to move between runs and track paragraphs.
Plenty of places in the code find following or preceding runs, then afterwards find the paragraph from the run. This is inefficient because the same linked list is used for both runs and paragraphs, so changes in paragraphs can be detected while returning the next or previous run.
This commit is contained in:
parent
0362b1b087
commit
32dcd3bbe1
|
@ -305,8 +305,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars,
|
||||||
{
|
{
|
||||||
/* We aren't deleting anything in this run, so we will go back to the
|
/* We aren't deleting anything in this run, so we will go back to the
|
||||||
* last run we are deleting text in. */
|
* last run we are deleting text in. */
|
||||||
c.pRun = ME_FindItemBack(c.pRun, diRun);
|
ME_PrevRun(&c.pPara, &c.pRun);
|
||||||
c.pPara = ME_GetParagraph(c.pRun);
|
|
||||||
c.nOffset = c.pRun->member.run.strText->nLen;
|
c.nOffset = c.pRun->member.run.strText->nLen;
|
||||||
}
|
}
|
||||||
run = &c.pRun->member.run;
|
run = &c.pRun->member.run;
|
||||||
|
@ -581,7 +580,7 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
|
||||||
/* ME_SplitParagraph increases style refcount */
|
/* ME_SplitParagraph increases style refcount */
|
||||||
tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, eol_str, 0);
|
tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, eol_str, 0);
|
||||||
p->pRun = ME_FindItemFwd(tp, diRun);
|
p->pRun = ME_FindItemFwd(tp, diRun);
|
||||||
p->pPara = ME_GetParagraph(p->pRun);
|
p->pPara = tp;
|
||||||
end_run = ME_FindItemBack(tp, diRun);
|
end_run = ME_FindItemBack(tp, diRun);
|
||||||
ME_ReleaseStyle(end_run->member.run.style);
|
ME_ReleaseStyle(end_run->member.run.style);
|
||||||
end_run->member.run.style = tmp_style;
|
end_run->member.run.style = tmp_style;
|
||||||
|
@ -671,6 +670,7 @@ static BOOL
|
||||||
ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs)
|
ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs)
|
||||||
{
|
{
|
||||||
ME_DisplayItem *pRun = cursor->pRun, *pOtherRun;
|
ME_DisplayItem *pRun = cursor->pRun, *pOtherRun;
|
||||||
|
ME_DisplayItem *pPara = cursor->pPara;
|
||||||
int nOffset = cursor->nOffset;
|
int nOffset = cursor->nOffset;
|
||||||
|
|
||||||
if (nRelOfs == -1)
|
if (nRelOfs == -1)
|
||||||
|
@ -700,14 +700,15 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs)
|
||||||
{
|
{
|
||||||
if (cursor->pRun == pRun && cursor->nOffset == 0)
|
if (cursor->pRun == pRun && cursor->nOffset == 0)
|
||||||
{
|
{
|
||||||
|
pPara = pOtherRun;
|
||||||
/* Skip empty start of table row paragraph */
|
/* Skip empty start of table row paragraph */
|
||||||
if (pOtherRun->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART)
|
if (pPara->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART)
|
||||||
pOtherRun = pOtherRun->member.para.prev_para;
|
pPara = pPara->member.para.prev_para;
|
||||||
/* Paragraph breaks are treated as separate words */
|
/* Paragraph breaks are treated as separate words */
|
||||||
if (pOtherRun->member.para.prev_para->type == diTextStart)
|
if (pPara->member.para.prev_para->type == diTextStart)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
pRun = ME_FindItemBack(pOtherRun, diRun);
|
pRun = ME_FindItemBack(pPara, diRun);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -739,8 +740,10 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs)
|
||||||
{
|
{
|
||||||
if (pOtherRun->member.para.nFlags & MEPF_ROWSTART)
|
if (pOtherRun->member.para.nFlags & MEPF_ROWSTART)
|
||||||
pOtherRun = pOtherRun->member.para.next_para;
|
pOtherRun = pOtherRun->member.para.next_para;
|
||||||
if (cursor->pRun == pRun)
|
if (cursor->pRun == pRun) {
|
||||||
pRun = ME_FindItemFwd(pOtherRun, diRun);
|
pPara = pOtherRun;
|
||||||
|
pRun = ME_FindItemFwd(pPara, diRun);
|
||||||
|
}
|
||||||
nOffset = 0;
|
nOffset = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -753,7 +756,7 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cursor->pPara = ME_GetParagraph(pRun);
|
cursor->pPara = pPara;
|
||||||
cursor->pRun = pRun;
|
cursor->pRun = pRun;
|
||||||
cursor->nOffset = nOffset;
|
cursor->nOffset = nOffset;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -1246,14 +1249,14 @@ static void
|
||||||
ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs)
|
ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs)
|
||||||
{
|
{
|
||||||
ME_DisplayItem *pRun = pCursor->pRun;
|
ME_DisplayItem *pRun = pCursor->pRun;
|
||||||
ME_DisplayItem *pItem, *pOldPara, *pNewPara;
|
ME_DisplayItem *pOldPara = pCursor->pPara;
|
||||||
|
ME_DisplayItem *pItem, *pNewPara;
|
||||||
int x = ME_GetXForArrow(editor, pCursor);
|
int x = ME_GetXForArrow(editor, pCursor);
|
||||||
|
|
||||||
if (editor->bCaretAtEnd && !pCursor->nOffset)
|
if (editor->bCaretAtEnd && !pCursor->nOffset)
|
||||||
pRun = ME_FindItemBack(pRun, diRun);
|
if (!ME_PrevRun(&pOldPara, &pRun))
|
||||||
if (!pRun)
|
|
||||||
return;
|
return;
|
||||||
pOldPara = ME_GetParagraph(pRun);
|
|
||||||
if (nRelOfs == -1)
|
if (nRelOfs == -1)
|
||||||
{
|
{
|
||||||
/* start of this row */
|
/* start of this row */
|
||||||
|
|
|
@ -1765,8 +1765,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH
|
||||||
nStart++;
|
nStart++;
|
||||||
if (nStart == item->member.run.strText->nLen)
|
if (nStart == item->member.run.strText->nLen)
|
||||||
{
|
{
|
||||||
item = ME_FindItemFwd(item, diRun);
|
ME_NextRun(¶, &item);
|
||||||
para = ME_GetParagraph(item);
|
|
||||||
nStart = 0;
|
nStart = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1786,12 +1785,13 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH
|
||||||
&& para->member.para.nCharOfs + item->member.run.nCharOfs + nEnd - nLen >= nMin)
|
&& para->member.para.nCharOfs + item->member.run.nCharOfs + nEnd - nLen >= nMin)
|
||||||
{
|
{
|
||||||
ME_DisplayItem *pCurItem = item;
|
ME_DisplayItem *pCurItem = item;
|
||||||
|
ME_DisplayItem *pCurPara = para;
|
||||||
int nCurEnd = nEnd;
|
int nCurEnd = nEnd;
|
||||||
int nMatched = 0;
|
int nMatched = 0;
|
||||||
|
|
||||||
if (nCurEnd == 0)
|
if (nCurEnd == 0)
|
||||||
{
|
{
|
||||||
pCurItem = ME_FindItemBack(pCurItem, diRun);
|
ME_PrevRun(&pCurPara, &pCurItem);
|
||||||
nCurEnd = pCurItem->member.run.strText->nLen + nMatched;
|
nCurEnd = pCurItem->member.run.strText->nLen + nMatched;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1826,7 +1826,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
nStart = ME_GetParagraph(pCurItem)->member.para.nCharOfs
|
nStart = pCurPara->member.para.nCharOfs
|
||||||
+ pCurItem->member.run.nCharOfs + nCurEnd - nMatched;
|
+ pCurItem->member.run.nCharOfs + nCurEnd - nMatched;
|
||||||
if (chrgText)
|
if (chrgText)
|
||||||
{
|
{
|
||||||
|
@ -1838,7 +1838,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH
|
||||||
}
|
}
|
||||||
if (nCurEnd - nMatched == 0)
|
if (nCurEnd - nMatched == 0)
|
||||||
{
|
{
|
||||||
pCurItem = ME_FindItemBack(pCurItem, diRun);
|
ME_PrevRun(&pCurPara, &pCurItem);
|
||||||
/* Don't care about pCurItem becoming NULL here; it's already taken
|
/* Don't care about pCurItem becoming NULL here; it's already taken
|
||||||
* care of in the exterior loop condition */
|
* care of in the exterior loop condition */
|
||||||
nCurEnd = pCurItem->member.run.strText->nLen + nMatched;
|
nCurEnd = pCurItem->member.run.strText->nLen + nMatched;
|
||||||
|
@ -1852,8 +1852,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH
|
||||||
nEnd--;
|
nEnd--;
|
||||||
if (nEnd < 0)
|
if (nEnd < 0)
|
||||||
{
|
{
|
||||||
item = ME_FindItemBack(item, diRun);
|
ME_PrevRun(¶, &item);
|
||||||
para = ME_GetParagraph(item);
|
|
||||||
nEnd = item->member.run.strText->nLen;
|
nEnd = item->member.run.strText->nLen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4689,8 +4688,6 @@ static BOOL ME_FindNextURLCandidate(ME_TextEditor *editor, int sel_min, int sel_
|
||||||
if (sel_max == -1) sel_max = ME_GetTextLength(editor);
|
if (sel_max == -1) sel_max = ME_GetTextLength(editor);
|
||||||
while (item && para->member.para.nCharOfs + item->member.run.nCharOfs + nStart < sel_max)
|
while (item && para->member.para.nCharOfs + item->member.run.nCharOfs + nStart < sel_max)
|
||||||
{
|
{
|
||||||
ME_DisplayItem * next_item;
|
|
||||||
|
|
||||||
if (!(item->member.run.nFlags & MERF_ENDPARA)) {
|
if (!(item->member.run.nFlags & MERF_ENDPARA)) {
|
||||||
/* Find start of candidate */
|
/* Find start of candidate */
|
||||||
if (*candidate_min == -1) {
|
if (*candidate_min == -1) {
|
||||||
|
@ -4738,17 +4735,15 @@ static BOOL ME_FindNextURLCandidate(ME_TextEditor *editor, int sel_min, int sel_
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reaching this point means no span was found, so get next span */
|
/* Reaching this point means no span was found, so get next span */
|
||||||
next_item = ME_FindItemFwd(item, diRun);
|
if (!ME_NextRun(¶, &item)) {
|
||||||
if (!next_item) {
|
|
||||||
if (*candidate_min >= 0) {
|
if (*candidate_min >= 0) {
|
||||||
/* There are no further runs, so take end of text as end of candidate */
|
/* There are no further runs, so take end of text as end of candidate */
|
||||||
*candidate_max = para->member.para.nCharOfs + item->member.run.nCharOfs + nStart;
|
*candidate_max = para->member.para.nCharOfs + item->member.run.nCharOfs + nStart;
|
||||||
if (lastAcceptedChar == ':') (*candidate_max)--;
|
if (lastAcceptedChar == ':') (*candidate_max)--;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
item = next_item;
|
|
||||||
para = ME_GetParagraph(item);
|
|
||||||
nStart = 0;
|
nStart = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,8 @@ void ME_CharFormatFromLogFont(HDC hDC, const LOGFONTW *lf, CHARFORMAT2W *fmt); /
|
||||||
/* list.c */
|
/* list.c */
|
||||||
void ME_InsertBefore(ME_DisplayItem *diWhere, ME_DisplayItem *diWhat);
|
void ME_InsertBefore(ME_DisplayItem *diWhere, ME_DisplayItem *diWhat);
|
||||||
void ME_Remove(ME_DisplayItem *diWhere);
|
void ME_Remove(ME_DisplayItem *diWhere);
|
||||||
|
BOOL ME_NextRun(ME_DisplayItem **para, ME_DisplayItem **run);
|
||||||
|
BOOL ME_PrevRun(ME_DisplayItem **para, ME_DisplayItem **run);
|
||||||
ME_DisplayItem *ME_FindItemBack(ME_DisplayItem *di, ME_DIType nTypeOrClass);
|
ME_DisplayItem *ME_FindItemBack(ME_DisplayItem *di, ME_DIType nTypeOrClass);
|
||||||
ME_DisplayItem *ME_FindItemFwd(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_FindItemBackOrHere(ME_DisplayItem *di, ME_DIType nTypeOrClass);
|
||||||
|
|
|
@ -63,6 +63,47 @@ static BOOL ME_DITypesEqual(ME_DIType type, ME_DIType nTypeOrClass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Modifies run pointer to point to the next run, and modify the
|
||||||
|
* paragraph pointer if moving into the next paragraph.
|
||||||
|
*
|
||||||
|
* Returns TRUE if next run is found, otherwise returns FALSE. */
|
||||||
|
BOOL ME_NextRun(ME_DisplayItem **para, ME_DisplayItem **run)
|
||||||
|
{
|
||||||
|
ME_DisplayItem *p = (*run)->next;
|
||||||
|
while (p->type != diTextEnd)
|
||||||
|
{
|
||||||
|
if (p->type == diParagraph) {
|
||||||
|
*para = p;
|
||||||
|
} else if (p->type == diRun) {
|
||||||
|
*run = p;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modifies run pointer to point to the previous run, and modify the
|
||||||
|
* paragraph pointer if moving into the previous paragraph.
|
||||||
|
*
|
||||||
|
* Returns TRUE if previous run is found, otherwise returns FALSE. */
|
||||||
|
BOOL ME_PrevRun(ME_DisplayItem **para, ME_DisplayItem **run)
|
||||||
|
{
|
||||||
|
ME_DisplayItem *p = (*run)->prev;
|
||||||
|
while (p->type != diTextStart)
|
||||||
|
{
|
||||||
|
if (p->type == diParagraph) {
|
||||||
|
if (p->member.para.prev_para->type == diParagraph)
|
||||||
|
*para = p->member.para.prev_para;
|
||||||
|
} else if (p->type == diRun) {
|
||||||
|
*run = p;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
p = p->prev;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
ME_DisplayItem *ME_FindItemBack(ME_DisplayItem *di, ME_DIType nTypeOrClass)
|
ME_DisplayItem *ME_FindItemBack(ME_DisplayItem *di, ME_DIType nTypeOrClass)
|
||||||
{
|
{
|
||||||
if (!di)
|
if (!di)
|
||||||
|
|
|
@ -370,14 +370,19 @@ void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, int nOfs,int *nChars)
|
||||||
{
|
{
|
||||||
/* The deletion starts from before the row, so don't join it with
|
/* The deletion starts from before the row, so don't join it with
|
||||||
* previous non-empty paragraphs. */
|
* previous non-empty paragraphs. */
|
||||||
|
ME_DisplayItem *curPara;
|
||||||
pRun = NULL;
|
pRun = NULL;
|
||||||
if (nOfs > this_para->member.para.nCharOfs)
|
if (nOfs > this_para->member.para.nCharOfs) {
|
||||||
pRun = ME_FindItemBack(end_para, diRun);
|
pRun = ME_FindItemBack(end_para, diRun);
|
||||||
if (!pRun)
|
curPara = end_para->member.para.prev_para;
|
||||||
|
}
|
||||||
|
if (!pRun) {
|
||||||
pRun = ME_FindItemFwd(end_para, diRun);
|
pRun = ME_FindItemFwd(end_para, diRun);
|
||||||
|
curPara = end_para;
|
||||||
|
}
|
||||||
if (pRun)
|
if (pRun)
|
||||||
{
|
{
|
||||||
nCharsToBoundary = ME_GetParagraph(pRun)->member.para.nCharOfs
|
nCharsToBoundary = curPara->member.para.nCharOfs
|
||||||
+ pRun->member.run.nCharOfs
|
+ pRun->member.run.nCharOfs
|
||||||
- nOfs;
|
- nOfs;
|
||||||
if (nCharsToBoundary >= 0)
|
if (nCharsToBoundary >= 0)
|
||||||
|
|
|
@ -791,7 +791,7 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC
|
||||||
|
|
||||||
/* TODO: section formatting properties */
|
/* TODO: section formatting properties */
|
||||||
|
|
||||||
if (!ME_StreamOutRTFParaProps(editor, pStream, ME_GetParagraph(p)))
|
if (!ME_StreamOutRTFParaProps(editor, pStream, pPara))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
|
|
Loading…
Reference in New Issue