From 13578c8602d2fd9916868e2b5e896949c2f066df Mon Sep 17 00:00:00 2001 From: Krzysztof Foltman Date: Sat, 16 Apr 2005 10:48:35 +0000 Subject: [PATCH] - removed trailing spaces from some files - tab support - indent support --- dlls/riched20/caret.c | 30 +++++- dlls/riched20/editor.c | 38 +++++++- dlls/riched20/editor.h | 6 +- dlls/riched20/editstr.h | 7 ++ dlls/riched20/paint.c | 10 +- dlls/riched20/para.c | 33 ++++++- dlls/riched20/run.c | 203 +++++++++++++++++++++++----------------- dlls/riched20/style.c | 1 + dlls/riched20/wrap.c | 80 ++++++++-------- 9 files changed, 268 insertions(+), 140 deletions(-) diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c index 2d2f6478615..8181f0a385f 100644 --- a/dlls/riched20/caret.c +++ b/dlls/riched20/caret.c @@ -104,11 +104,11 @@ void ME_MoveCaret(ME_TextEditor *editor) { row = ME_FindItemBack(tmp, diStartRow); pSizeRun = run = tmp; - sz = ME_GetRunSize(&c, &run->member.run, ME_StrLen(run->member.run.strText)); + sz = ME_GetRunSize(&c, ¶->member.para, &run->member.run, ME_StrLen(run->member.run.strText)); } } if (pCursor->nOffset && !(run->member.run.nFlags & MERF_SKIPPED)) { - sz = ME_GetRunSize(&c, &run->member.run, pCursor->nOffset); + sz = ME_GetRunSize(&c, ¶->member.para, &run->member.run, pCursor->nOffset); } CreateCaret(editor->hWnd, NULL, 0, pSizeRun->member.run.nAscent+pSizeRun->member.run.nDescent); SetCaretPos(run->member.run.pt.x+sz.cx, @@ -311,10 +311,30 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, len = lstrlenW(str); pos = str; /* FIXME this sucks - no respect for unicode (what else can be a line separator in unicode?) */ - while(pos-str < len && *pos != '\r' && *pos != '\n') + while(pos-str < len && *pos != '\r' && *pos != '\n' && *pos != '\t') pos++; - /* handle EOLs */ - if (pos-str < len) { + if (pos-str < len && *pos == '\t') { /* handle tabs */ + ME_DisplayItem *pNewRun = NULL; + WCHAR tab = '\t'; + + if (pos!=str) + ME_InsertTextFromCursor(editor, nCursor, str, pos-str, style); + + p = &editor->pCursors[nCursor]; + assert(style); + assert(p->pRun->type == diRun); + pNewRun = ME_MakeRun(style, ME_MakeStringN(&tab, 1), MERF_TAB); /* addrefs style */ + ME_InsertRun(editor, ME_CharOfsFromRunOfs(editor, p->pRun, p->nOffset), pNewRun); + ME_DestroyDisplayItem(pNewRun); + ME_ReleaseStyle(style); + + pos++; + if(pos-str < len) { + ME_InsertTextFromCursor(editor, nCursor, pos, len-(pos-str), style); + } + return; + } + if (pos-str < len) { /* handle EOLs */ ME_DisplayItem *tp, *end_run; ME_Paragraph *para; ME_Style *tmp_style; diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index c240fb652f9..33eb9ecde71 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -356,6 +356,8 @@ void ME_RTFCharAttrHook(RTF_Info *info) } } +/* FIXME this function doesn't get any information about context of the RTF tag, which is very bad, + the same tags mean different things in different contexts */ void ME_RTFParAttrHook(RTF_Info *info) { PARAFORMAT2 fmt; @@ -365,8 +367,30 @@ void ME_RTFParAttrHook(RTF_Info *info) switch(info->rtfMinor) { case rtfParDef: /* I'm not 100% sure what does it do, but I guess it restores default paragraph attributes */ - fmt.dwMask = PFM_ALIGNMENT; + fmt.dwMask = PFM_ALIGNMENT | PFM_TABSTOPS | PFM_OFFSET | PFM_STARTINDENT; fmt.wAlignment = PFA_LEFT; + fmt.cTabCount = 0; + fmt.dxOffset = fmt.dxStartIndent = 0; + break; + case rtfFirstIndent: + ME_GetSelectionParaFormat(info->editor, &fmt); + fmt.dwMask = PFM_STARTINDENT; + fmt.dxStartIndent = info->rtfParam + fmt.dxOffset; + break; + case rtfLeftIndent: + { + int first, left; + ME_GetSelectionParaFormat(info->editor, &fmt); + first = fmt.dxStartIndent; + left = info->rtfParam; + fmt.dwMask = PFM_STARTINDENT|PFM_OFFSET; + fmt.dxStartIndent = first + left; + fmt.dxOffset = -first; + break; + } + case rtfRightIndent: + fmt.dwMask = PFM_RIGHTINDENT; + fmt.dxRightIndent = info->rtfParam; break; case rtfQuadLeft: case rtfQuadJust: @@ -381,6 +405,16 @@ void ME_RTFParAttrHook(RTF_Info *info) fmt.dwMask = PFM_ALIGNMENT; fmt.wAlignment = PFA_CENTER; break; + case rtfTabPos: + ME_GetSelectionParaFormat(info->editor, &fmt); + if (!(fmt.dwMask & PFM_TABSTOPS)) + { + fmt.dwMask |= PFM_TABSTOPS; + fmt.cTabCount = 0; + } + if (fmt.cTabCount < MAX_TAB_STOPS) + fmt.rgxTabs[fmt.cTabCount++] = info->rtfParam; + break; } if (fmt.dwMask) { RTFFlushOutputBuffer(info); @@ -1160,7 +1194,7 @@ LRESULT WINAPI RichEditANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lP return 0; /* FIXME really 0 ? */ } wstr = LOWORD(wParam); - if (((unsigned)wstr)>=' ' || wstr=='\r') { + if (((unsigned)wstr)>=' ' || wstr=='\r' || wstr=='\t') { /* FIXME maybe it would make sense to call EM_REPLACESEL instead ? */ ME_Style *style = ME_GetInsertStyle(editor, 0); ME_SaveTempStyle(editor); diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index 010ccfda9f8..5cbcfbde224 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -108,7 +108,7 @@ ME_DisplayItem *ME_InsertRun(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem void ME_CheckCharOffsets(ME_TextEditor *editor); void ME_PropagateCharOffset(ME_DisplayItem *p, int shift); void ME_GetGraphicsSize(ME_TextEditor *editor, ME_Run *run, SIZE *pSize); -int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run); +int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Paragraph *para, ME_Run *run); /* this one accounts for 1/2 char tolerance */ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run); int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset); @@ -120,8 +120,8 @@ ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_DisplayItem *item, i int ME_FindSplitPoint(ME_Context *c, POINT *pt, ME_Run *run, int desperate); void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run); ME_DisplayItem *ME_SplitFurther(ME_TextEditor *editor, ME_DisplayItem *run); -void ME_CalcRunExtent(ME_Context *c, ME_Run *run); -SIZE ME_GetRunSize(ME_Context *c, ME_Run *run, int nLen); +void ME_CalcRunExtent(ME_Context *c, ME_Paragraph *para, ME_Run *run); +SIZE ME_GetRunSize(ME_Context *c, ME_Paragraph *para, ME_Run *run, int nLen); 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); diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h index 617ae6d0a2e..00329fb9628 100644 --- a/dlls/riched20/editstr.h +++ b/dlls/riched20/editstr.h @@ -86,6 +86,8 @@ typedef enum { #define MERF_STYLEFLAGS 0x0FFF /* run contains non-text content, which has its own rules for wrapping, sizing etc */ #define MERF_GRAPHICS 1 +/* run is a tab (or, in future, any kind of content whose size is dependent on run position) */ +#define MERF_TAB 2 /* run is splittable (contains white spaces in the middle or end) */ #define MERF_SPLITTABLE 0x001000 @@ -102,6 +104,11 @@ typedef enum { /* the "end of paragraph" run, contains 1 character */ #define MERF_ENDPARA 0x100000 +/* runs with any of these flags set cannot be joined */ +#define MERF_NOJOIN (MERF_GRAPHICS|MERF_TAB|MERF_ENDPARA) +/* runs that don't contain real text */ +#define MERF_NOTEXT (MERF_GRAPHICS|MERF_TAB|MERF_ENDPARA) + /* those flags are kept when the row is split */ #define MERF_SPLITMASK (~(0)) diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c index 67192bc35d5..7d5e387d20d 100644 --- a/dlls/riched20/paint.c +++ b/dlls/riched20/paint.c @@ -251,7 +251,7 @@ void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Paragraph int runofs = run->nCharOfs+para->nCharOfs; /* you can always comment it out if you need visible paragraph marks */ - if (run->nFlags & MERF_ENDPARA) + if (run->nFlags & (MERF_ENDPARA|MERF_TAB)) return; if (run->nFlags & MERF_GRAPHICS) { int blfrom, blto; @@ -311,19 +311,19 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) { visible = RectVisible(c->hDC, &rcPara); if (visible) { HBRUSH hbr; + hbr = CreateSolidBrush(ME_GetBackColor(c->editor)); /* left margin */ rc.left = c->rcView.left; rc.right = c->rcView.left+nMargWidth; rc.top = y; rc.bottom = y+p->member.row.nHeight; - FillRect(c->hDC, &rc, c->hbrMargin); + FillRect(c->hDC, &rc, hbr/* c->hbrMargin */); /* right margin */ rc.left = xe; rc.right = c->rcView.right; - FillRect(c->hDC, &rc, c->hbrMargin); - rc.left = c->rcView.left+para->nLeftMargin; + FillRect(c->hDC, &rc, hbr/* c->hbrMargin */); + rc.left = c->rcView.left+nMargWidth; rc.right = xe; - hbr = CreateSolidBrush(ME_GetBackColor(c->editor)); FillRect(c->hDC, &rc, hbr); DeleteObject(hbr); } diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c index 48ba176760c..4b1947ce797 100644 --- a/dlls/riched20/para.c +++ b/dlls/riched20/para.c @@ -57,7 +57,7 @@ void ME_MakeFirstParagraph(HDC hDC, ME_TextBuffer *text) ZeroMemory(&fmt, sizeof(fmt)); fmt.cbSize = sizeof(fmt); - fmt.dwMask = PFM_ALIGNMENT | PFM_OFFSET | PFM_STARTINDENT | PFM_RIGHTINDENT; + fmt.dwMask = PFM_ALIGNMENT | PFM_OFFSET | PFM_STARTINDENT | PFM_RIGHTINDENT | PFM_TABSTOPS; CopyMemory(para->member.para.pFmt, &fmt, sizeof(PARAFORMAT2)); @@ -282,6 +282,18 @@ void ME_SetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, PARAFORMAT2 * if (pFmt->dwMask & PFM_ALIGNMENT) para->member.para.pFmt->wAlignment = pFmt->wAlignment; + if (pFmt->dwMask & PFM_STARTINDENT) + para->member.para.pFmt->dxStartIndent = pFmt->dxStartIndent; + if (pFmt->dwMask & PFM_OFFSET) + para->member.para.pFmt->dxOffset = pFmt->dxOffset; + if (pFmt->dwMask & PFM_OFFSETINDENT) + para->member.para.pFmt->dxStartIndent += pFmt->dxStartIndent; + + if (pFmt->dwMask & PFM_TABSTOPS) + { + para->member.para.pFmt->cTabCount = pFmt->cTabCount; + memcpy(para->member.para.pFmt->rgxTabs, pFmt->rgxTabs, pFmt->cTabCount*sizeof(int)); + } /* FIXME to be continued (indents, bulleting and such) */ @@ -345,11 +357,28 @@ void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) ZeroMemory(&tmp, sizeof(tmp)); tmp.cbSize = sizeof(tmp); ME_GetParaFormat(editor, para, &tmp); - assert(tmp.dwMask & PFM_ALIGNMENT); + assert(tmp.dwMask & PFM_ALIGNMENT); if (pFmt->wAlignment != tmp.wAlignment) pFmt->dwMask &= ~PFM_ALIGNMENT; + assert(tmp.dwMask & PFM_STARTINDENT); + if (pFmt->dxStartIndent != tmp.dxStartIndent) + pFmt->dwMask &= ~PFM_STARTINDENT; + + assert(tmp.dwMask & PFM_OFFSET); + if (pFmt->dxOffset != tmp.dxOffset) + pFmt->dwMask &= ~PFM_OFFSET; + + assert(tmp.dwMask & PFM_TABSTOPS); + if (pFmt->dwMask & PFM_TABSTOPS) { + if (pFmt->cTabCount != tmp.cTabCount) + pFmt->dwMask &= ~PFM_TABSTOPS; + else + if (memcmp(pFmt->rgxTabs, tmp.rgxTabs, tmp.cTabCount*sizeof(int))) + pFmt->dwMask &= ~PFM_TABSTOPS; + } + if (para == para_end) return; para = para->member.para.next_para; diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c index 6440b6d37e6..533aae2a642 100644 --- a/dlls/riched20/run.c +++ b/dlls/riched20/run.c @@ -26,7 +26,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit); int ME_CanJoinRuns(ME_Run *run1, ME_Run *run2) { - if ((run1->nFlags | run2->nFlags) & (MERF_ENDPARA | MERF_GRAPHICS)) + if ((run1->nFlags | run2->nFlags) & MERF_NOJOIN) return 0; if (run1->style != run2->style) return 0; @@ -91,8 +91,8 @@ void ME_CheckCharOffsets(ME_TextEditor *editor) ofs = 0; break; case diRun: - TRACE("run, real ofs = %d (+ofsp = %d), counted = %d, len = %d, txt = \"%s\", flags=%08x, fx&mask = %08lx\n", - p->member.run.nCharOfs, p->member.run.nCharOfs+ofsp, ofsp+ofs, + TRACE("run, real ofs = %d (+ofsp = %d), counted = %d, len = %d, txt = \"%s\", flags=%08x, fx&mask = %08lx\n", + p->member.run.nCharOfs, p->member.run.nCharOfs+ofsp, ofsp+ofs, p->member.run.strText->nLen, debugstr_w(p->member.run.strText->szData), p->member.run.nFlags, p->member.run.style->fmt.dwMask & p->member.run.style->fmt.dwEffects); @@ -108,14 +108,14 @@ void ME_CheckCharOffsets(ME_TextEditor *editor) int ME_CharOfsFromRunOfs(ME_TextEditor *editor, 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 + return pPara->member.para.nCharOfs + pRun->member.run.nCharOfs + ME_VPosToPos(pRun->member.run.strText, nOfs); } @@ -128,7 +128,7 @@ void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem ** { ME_DisplayItem *pPara; int nParaOfs; - + pPara = editor->pBuffer->pFirst->member.para.next_para; assert(pPara); assert(ppRun); @@ -137,18 +137,18 @@ void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem ** { nParaOfs = pPara->member.para.nCharOfs; assert(nCharOfs >= nParaOfs); - + if (nCharOfs < pPara->member.para.next_para->member.para.nCharOfs) { *ppRun = ME_FindItemFwd(pPara, diRun); - assert(*ppRun); + assert(*ppRun); while (!((*ppRun)->member.run.nFlags & MERF_ENDPARA)) { ME_DisplayItem *pNext = ME_FindItemFwd(*ppRun, diRun); assert(pNext); assert(pNext->type == diRun); if (nCharOfs < nParaOfs + pNext->member.run.nCharOfs) { - *pOfs = ME_PosToVPos((*ppRun)->member.run.strText, + *pOfs = ME_PosToVPos((*ppRun)->member.run.strText, nCharOfs - nParaOfs - (*ppRun)->member.run.nCharOfs); return; } @@ -157,12 +157,12 @@ void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem ** if (nCharOfs == nParaOfs + (*ppRun)->member.run.nCharOfs) { *pOfs = 0; return; - } + } } pPara = pPara->member.para.next_para; } *ppRun = ME_FindItemBack(editor->pBuffer->pLast, diRun); - *pOfs = 0; + *pOfs = 0; assert((*ppRun)->member.run.nFlags & MERF_ENDPARA); } @@ -182,7 +182,7 @@ void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p) editor->pCursors[i].nOffset += ME_StrVLen(p->member.run.strText); } } - + ME_AppendString(p->member.run.strText, pNext->member.run.strText); ME_Remove(pNext); ME_DestroyDisplayItem(pNext); @@ -200,7 +200,8 @@ ME_DisplayItem *ME_SplitRun(ME_Context *c, ME_DisplayItem *item, int nVChar) ME_TextEditor *editor = c->editor; ME_DisplayItem *item2 = NULL; ME_Run *run, *run2; - + ME_Paragraph *para = &ME_GetParagraph(item)->member.para; + assert(item->member.run.nCharOfs != -1); if(TRACE_ON(richedit)) { @@ -215,28 +216,28 @@ ME_DisplayItem *ME_SplitRun(ME_Context *c, ME_DisplayItem *item, int nVChar) run->pt.x, run->pt.y); item2 = ME_SplitRunSimple(editor, item, nVChar); - + run2 = &item2->member.run; - - ME_CalcRunExtent(c, run); - ME_CalcRunExtent(c, run2); - + + ME_CalcRunExtent(c, para, run); + ME_CalcRunExtent(c, para, run2); + run2->pt.x = run->pt.x+run->nWidth; run2->pt.y = run->pt.y; - + if(TRACE_ON(richedit)) { TRACE("Before check after split\n"); ME_CheckCharOffsets(editor); TRACE("After check after split\n"); - TRACE("After split: %s(%ld, %ld), %s(%ld, %ld)\n", + TRACE("After split: %s(%ld, %ld), %s(%ld, %ld)\n", debugstr_w(run->strText->szData), run->pt.x, run->pt.y, debugstr_w(run2->strText->szData), run2->pt.x, run2->pt.y); } return item2; } - + /* split a run starting from voffset */ ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_DisplayItem *item, int nVChar) { @@ -246,22 +247,22 @@ ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_DisplayItem *item, i int i; assert(nVChar > 0 && nVChar < ME_StrVLen(run->strText)); assert(item->type == diRun); - assert(!(item->member.run.nFlags & MERF_GRAPHICS)); + assert(!(item->member.run.nFlags & (MERF_GRAPHICS | MERF_TAB))); assert(item->member.run.nCharOfs != -1); - item2 = ME_MakeRun(run->style, + 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); run2 = &item2->member.run; ME_InsertBefore(item->next, item2); - + ME_UpdateRunFlags(editor, run); ME_UpdateRunFlags(editor, run2); for (i=0; inCursors; i++) { - if (editor->pCursors[i].pRun == item && + if (editor->pCursors[i].pRun == item && editor->pCursors[i].nOffset >= nVChar) { assert(item2->type == diRun); editor->pCursors[i].pRun = item2; @@ -272,18 +273,6 @@ ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_DisplayItem *item, i return item2; } -/* split the start and final whitespace into separate runs */ -/* returns the last run added */ -/* -ME_DisplayItem *ME_SplitFurther(ME_TextEditor *editor, ME_DisplayItem *item) -{ - int i, nVLen, nChanged; - assert(item->type == diRun); - assert(!(item->member.run.nFlags & MERF_GRAPHICS)); - return item; -} -*/ - ME_DisplayItem *ME_MakeRun(ME_Style *s, ME_String *strData, int nFlags) { ME_DisplayItem *item = ME_MakeDI(diRun); @@ -300,9 +289,9 @@ ME_DisplayItem *ME_InsertRun(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem ME_Cursor tmp; ME_DisplayItem *pDI; ME_UndoItem *pUI; - + assert(pItem->type == diRun || pItem->type == diUndoInsertRun); - + pUI = ME_AddUndoItem(editor, diUndoDeleteRun, NULL); if (pUI) { pUI->nStart = nCharOfs; @@ -319,7 +308,7 @@ ME_DisplayItem *ME_InsertRun(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem TRACE("Shift length:%d\n", pDI->member.run.strText->nLen); ME_PropagateCharOffset(tmp.pRun, pDI->member.run.strText->nLen); ME_GetParagraph(tmp.pRun)->member.para.nFlags |= MEPF_REWRAP; - + return pDI; } @@ -330,19 +319,19 @@ void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run) run->nFlags |= MERF_SPLITTABLE; else run->nFlags &= ~MERF_SPLITTABLE; - - if (!(run->nFlags & MERF_GRAPHICS)) { + + if (!(run->nFlags & MERF_NOTEXT)) { if (ME_IsWhitespaces(run->strText)) run->nFlags |= MERF_WHITESPACE | MERF_STARTWHITE | MERF_ENDWHITE; else { run->nFlags &= ~MERF_WHITESPACE; - + if (ME_IsWSpace(ME_GetCharFwd(run->strText,0))) run->nFlags |= MERF_STARTWHITE; else run->nFlags &= ~MERF_STARTWHITE; - + if (ME_IsWSpace(ME_GetCharBack(run->strText,0))) run->nFlags |= MERF_ENDWHITE; else @@ -360,7 +349,7 @@ void ME_GetGraphicsSize(ME_TextEditor *editor, ME_Run *run, SIZE *pSize) pSize->cy = 64; } -int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run) +int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Paragraph *para, ME_Run *run) { int fit = 0; HGDIOBJ hOldFont; @@ -369,6 +358,12 @@ int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run) if (!run->strText->nLen) return 0; + if (run->nFlags & MERF_TAB) + { + if (cx < run->nWidth/2) + return 0; + return 1; + } if (run->nFlags & MERF_GRAPHICS) { SIZE sz; @@ -379,9 +374,9 @@ int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run) } hDC = GetDC(editor->hWnd); hOldFont = ME_SelectStyleFont(editor, hDC, run->style); - GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen, + GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen, cx, &fit, NULL, &sz); - ME_UnselectStyleFont(editor, hDC, run->style, hOldFont); + ME_UnselectStyleFont(editor, hDC, run->style, hOldFont); ReleaseDC(editor->hWnd, hDC); return fit; } @@ -395,6 +390,12 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run) if (!run->strText->nLen) return 0; + if (run->nFlags & MERF_TAB) + { + if (cx < run->nWidth/2) + return 0; + return 1; + } if (run->nFlags & MERF_GRAPHICS) { SIZE sz; @@ -406,19 +407,19 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run) hDC = GetDC(editor->hWnd); hOldFont = ME_SelectStyleFont(editor, hDC, run->style); - GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen, + GetTextExtentExPointW(hDC, run->strText->szData, run->strText->nLen, cx, &fit, NULL, &sz); if (fit != run->strText->nLen) { int chars = 1; - + GetTextExtentPoint32W(hDC, run->strText->szData, fit, &sz2); fit1 = ME_StrRelPos(run->strText, fit, &chars); GetTextExtentPoint32W(hDC, run->strText->szData, fit1, &sz3); if (cx >= (sz2.cx+sz3.cx)/2) fit = fit1; } - ME_UnselectStyleFont(editor, hDC, run->style, hOldFont); + ME_UnselectStyleFont(editor, hDC, run->style, hOldFont); ReleaseDC(editor->hWnd, hDC); return fit; } @@ -428,7 +429,7 @@ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset) SIZE size; HDC hDC = GetDC(editor->hWnd); HGDIOBJ hOldFont; - + if (pRun->nFlags & MERF_GRAPHICS) { if (!nOffset) return 0; @@ -437,56 +438,88 @@ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset) } hOldFont = ME_SelectStyleFont(editor, hDC, pRun->style); GetTextExtentPoint32W(hDC, pRun->strText->szData, nOffset, &size); - ME_UnselectStyleFont(editor, hDC, pRun->style, hOldFont); + ME_UnselectStyleFont(editor, hDC, pRun->style, hOldFont); ReleaseDC(editor->hWnd, hDC); return size.cx; } -void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s, +void ME_GetTextExtent(ME_Context *c, LPCWSTR szText, int nChars, ME_Style *s, SIZE *size) { HDC hDC = c->hDC; HGDIOBJ hOldFont; hOldFont = ME_SelectStyleFont(c->editor, hDC, s); GetTextExtentPoint32W(hDC, szText, nChars, size); - ME_UnselectStyleFont(c->editor, hDC, s, hOldFont); + ME_UnselectStyleFont(c->editor, hDC, s, hOldFont); } -SIZE ME_GetRunSize(ME_Context *c, ME_Run *run, int nLen) +SIZE ME_GetRunSizeCommon(ME_Context *c, ME_Paragraph *para, ME_Run *run, int nLen, int *pAscent, int *pDescent) { SIZE size; int nMaxLen = ME_StrVLen(run->strText); if (nLen>nMaxLen) nLen = nMaxLen; - + + /* FIXME the following call also ensures that TEXTMETRIC structure is filled + * this is wasteful for graphics and TAB runs, but that shouldn't matter + * in practice + */ + ME_GetTextExtent(c, run->strText->szData, nLen, run->style, &size); + assert(run->style->tm.tmAscent>0); + assert(run->style->tm.tmDescent>0); + *pAscent = run->style->tm.tmAscent; + *pDescent = run->style->tm.tmDescent; + size.cy = *pAscent + *pDescent; + + if (run->nFlags & MERF_TAB) + { + int pos = 0, i = 0, ppos; + int lpsx = GetDeviceCaps(c->hDC, LOGPIXELSX); + PARAFORMAT2 *pFmt = para->pFmt; + do { + if (i < pFmt->cTabCount) + { + pos = pFmt->rgxTabs[i]&0x00FFFFFF; + i++; + } + else + { + pos += 720-(pos%720); + } + ppos = pos*lpsx/1440; + if (ppos>run->pt.x) { + size.cx = ppos - run->pt.x; + break; + } + } while(1); + size.cy = *pAscent + *pDescent; + return size; + } if (run->nFlags & MERF_GRAPHICS) { ME_GetGraphicsSize(c->editor, run, &size); + if (size.cy > *pAscent) + *pAscent = size.cy; + /* descent is unchanged */ return size; } - ME_GetTextExtent(c, run->strText->szData, nLen, run->style, &size); - return size; } -void ME_CalcRunExtent(ME_Context *c, ME_Run *run) +SIZE ME_GetRunSize(ME_Context *c, ME_Paragraph *para, ME_Run *run, int nLen) +{ + int asc, desc; + return ME_GetRunSizeCommon(c, para, run, nLen, &asc, &desc); +} + +void ME_CalcRunExtent(ME_Context *c, ME_Paragraph *para, ME_Run *run) { - SIZE size; int nEnd = ME_StrVLen(run->strText); - - if (run->nFlags & MERF_GRAPHICS) { - ME_GetGraphicsSize(c->editor, run, &size); - run->nWidth = size.cx; - run->nAscent = size.cy; - run->nDescent = 0; - return; - } - ME_GetTextExtent(c, run->strText->szData, nEnd, run->style, &size); + SIZE size = ME_GetRunSizeCommon(c, para, run, nEnd, &run->nAscent, &run->nDescent); run->nWidth = size.cx; - run->nAscent = run->style->tm.tmAscent; - run->nDescent = run->style->tm.tmDescent; + assert(size.cx); } void ME_MustBeWrapped(ME_Context *c, ME_DisplayItem *para) @@ -516,7 +549,7 @@ void ME_SetCharFormat(ME_TextEditor *editor, int nOfs, int nChars, CHARFORMAT2W { ME_Cursor tmp, tmp2; ME_DisplayItem *para; - + ME_CursorFromCharOfs(editor, nOfs, &tmp); if (tmp.nOffset) tmp.pRun = ME_SplitRunSimple(editor, tmp.pRun, tmp.nOffset); @@ -527,7 +560,7 @@ void ME_SetCharFormat(ME_TextEditor *editor, int nOfs, int nChars, CHARFORMAT2W para = ME_GetParagraph(tmp.pRun); para->member.para.nFlags |= MEPF_REWRAP; - + while(tmp.pRun != tmp2.pRun) { ME_UndoItem *undo = NULL; @@ -558,9 +591,9 @@ void ME_SetCharFormat(ME_TextEditor *editor, int nOfs, int nChars, CHARFORMAT2W void ME_SetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *mod) { - ME_Style *style; + ME_Style *style; ME_UndoItem *undo; - + assert(mod->cbSize == sizeof(CHARFORMAT2W)); undo = ME_AddUndoItem(editor, diUndoSetDefaultCharFormat, NULL); if (undo) { @@ -606,10 +639,10 @@ void ME_GetCharFormat(ME_TextEditor *editor, int nFrom, int nTo, CHARFORMAT2W *p ME_DisplayItem *run, *run_end; int nOffset, nOffset2; CHARFORMAT2W tmp; - + if (nTo>nFrom) /* selection consists of chars from nFrom up to nTo-1 */ nTo--; - + ME_RunOfsFromCharOfs(editor, nFrom, &run, &nOffset); if (nFrom == nTo) /* special case - if selection is empty, take previous char's formatting */ { @@ -625,22 +658,22 @@ void ME_GetCharFormat(ME_TextEditor *editor, int nFrom, int nTo, CHARFORMAT2W *p return; } ME_RunOfsFromCharOfs(editor, nTo, &run_end, &nOffset2); - + ME_GetRunCharFormat(editor, run, pFmt); - + if (run == run_end) return; - + do { /* FIXME add more style feature comparisons */ int nAttribs = CFM_SIZE | CFM_FACE | CFM_COLOR; int nEffects = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE; run = ME_FindItemFwd(run, diRun); - + ZeroMemory(&tmp, sizeof(tmp)); tmp.cbSize = sizeof(tmp); ME_GetRunCharFormat(editor, run, &tmp); - + assert((tmp.dwMask & nAttribs) == nAttribs); assert((tmp.dwMask & nEffects) == nEffects); /* reset flags that differ */ @@ -664,8 +697,8 @@ void ME_GetCharFormat(ME_TextEditor *editor, int nFrom, int nTo, CHARFORMAT2W *p pFmt->dwMask &= ~CFM_COLOR; } } - + pFmt->dwMask &= ~((pFmt->dwEffects ^ tmp.dwEffects) & nEffects); - + } while(run != run_end); } diff --git a/dlls/riched20/style.c b/dlls/riched20/style.c index 1b5bc2f7c90..cbdd9327168 100644 --- a/dlls/riched20/style.c +++ b/dlls/riched20/style.c @@ -124,6 +124,7 @@ ME_Style *ME_MakeStyle(CHARFORMAT2W *style) { s->nSequence = -2; s->nRefs = 1; s->hFont = NULL; + s->tm.tmAscent = -1; all_refs++; return s; } diff --git a/dlls/riched20/wrap.c b/dlls/riched20/wrap.c index db92951dc79..d48da585942 100644 --- a/dlls/riched20/wrap.c +++ b/dlls/riched20/wrap.c @@ -26,16 +26,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit); /* * Unsolved problems: - * + * * - center and right align in WordPad omits all spaces at the start, we don't * - objects/images are not handled yet - * - no tabs - */ - + * - no tabs + */ + ME_DisplayItem *ME_MakeRow(int height, int baseline, int width) { ME_DisplayItem *item = ME_MakeDI(diStartRow); - + item->member.row.nHeight = height; item->member.row.nBaseline = baseline; item->member.row.nWidth = width; @@ -49,7 +49,7 @@ void ME_BeginRow(ME_WrapContext *wc) wc->pLastSplittableRun = NULL; wc->nAvailWidth = wc->nTotalWidth - (wc->nRow ? wc->nLeftMargin : wc->nFirstMargin) - wc->nRightMargin; wc->pt.x = 0; -} +} void ME_InsertRowStart(ME_WrapContext *wc, ME_DisplayItem *pEnd) { @@ -95,7 +95,7 @@ void ME_WrapEndParagraph(ME_WrapContext *wc, ME_DisplayItem *p) { if (wc->pRowStart) ME_InsertRowStart(wc, p->next); - + /* p = p->member.para.prev_para->next; while(p) { @@ -109,15 +109,15 @@ void ME_WrapEndParagraph(ME_WrapContext *wc, ME_DisplayItem *p) p = p->next; } */ -} +} void ME_WrapSizeRun(ME_WrapContext *wc, ME_DisplayItem *p) { /* FIXME compose style (out of character and paragraph styles) here */ - + ME_UpdateRunFlags(wc->context->editor, &p->member.run); - - ME_CalcRunExtent(wc->context, &p->member.run); + + ME_CalcRunExtent(wc->context, &ME_GetParagraph(p)->member.para, &p->member.run); } ME_DisplayItem *ME_MaximizeSplit(ME_WrapContext *wc, ME_DisplayItem *p, int i) @@ -139,7 +139,7 @@ ME_DisplayItem *ME_MaximizeSplit(ME_WrapContext *wc, ME_DisplayItem *p, int i) while(piter != wc->pRowStart) { piter = ME_FindItemBack(piter, diRun); - if (piter->member.run.nFlags & MERF_WHITESPACE) + if (piter->member.run.nFlags & MERF_WHITESPACE) { pp = piter; continue; @@ -167,8 +167,8 @@ ME_DisplayItem *ME_SplitByBacktracking(ME_WrapContext *wc, ME_DisplayItem *p, in ME_DisplayItem *piter = p, *pp; int i, idesp, len; ME_Run *run = &p->member.run; - - idesp = i = ME_CharFromPoint(wc->context->editor, loc, run); + + idesp = i = ME_CharFromPoint(wc->context->editor, loc, &ME_GetParagraph(p)->member.para, run); len = ME_StrVLen(run->strText); assert(len>0); assert(imember.run.strText->szData)); if (wc->pLastSplittableRun) { - if (wc->pLastSplittableRun->member.run.nFlags & MERF_GRAPHICS) + if (wc->pLastSplittableRun->member.run.nFlags & (MERF_GRAPHICS|MERF_TAB)) { wc->pt = wc->ptLastSplittableRun; return wc->pLastSplittableRun; @@ -193,7 +193,7 @@ ME_DisplayItem *ME_SplitByBacktracking(ME_WrapContext *wc, ME_DisplayItem *p, in they serve no other purpose */ ME_UpdateRunFlags(wc->context->editor, run); assert((wc->pLastSplittableRun->member.run.nFlags & MERF_SPLITTABLE)); - + piter = wc->pLastSplittableRun; run = &piter->member.run; len = ME_StrVLen(run->strText); @@ -201,7 +201,7 @@ ME_DisplayItem *ME_SplitByBacktracking(ME_WrapContext *wc, ME_DisplayItem *p, in i = ME_ReverseFindWhitespaceV(run->strText, len); if (i == len) i = ME_ReverseFindNonWhitespaceV(run->strText, len); - if (i) { + if (i) { ME_DisplayItem *piter2 = ME_SplitRun(wc->context, piter, i); wc->pt = piter2->member.run.pt; return piter2; @@ -239,7 +239,7 @@ ME_DisplayItem *ME_SplitByBacktracking(ME_WrapContext *wc, ME_DisplayItem *p, in } /* the run is one char, can't split it */ return piter; - } + } } ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p) @@ -248,24 +248,24 @@ ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p) ME_Run *run; int len; - assert(p->type == diRun); + assert(p->type == diRun); if (!wc->pRowStart) wc->pRowStart = p; - ME_WrapSizeRun(wc, p); run = &p->member.run; run->pt.x = wc->pt.x; run->pt.y = wc->pt.y; - len = ME_StrVLen(run->strText); - + ME_WrapSizeRun(wc, p); + len = ME_StrVLen(run->strText); + if (wc->bOverflown) /* just skipping final whitespaces */ - { - if (run->nFlags & MERF_WHITESPACE) { + { + if (run->nFlags & (MERF_WHITESPACE|MERF_TAB)) { p->member.run.nFlags |= MERF_SKIPPED; /* wc->pt.x += run->nWidth; */ /* skip runs consisting of only whitespaces */ return p->next; } - + if (run->nFlags & MERF_STARTWHITE) { /* try to split the run at the first non-white char */ int black; @@ -286,15 +286,15 @@ ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p) /* will current run fit? */ if (wc->pt.x + run->nWidth > wc->nAvailWidth) { - int loc = wc->nAvailWidth - wc->pt.x; + int loc = wc->nAvailWidth - wc->pt.x; /* total white run ? */ if (run->nFlags & MERF_WHITESPACE) { /* let the overflow logic handle it */ wc->bOverflown = TRUE; return p; } - /* graphics - we can split before */ - if (run->nFlags & MERF_GRAPHICS) { + /* graphics or TAB - we can split before */ + if (run->nFlags & (MERF_GRAPHICS|MERF_TAB)) { wc->bOverflown = TRUE; return p; } @@ -326,8 +326,8 @@ ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p) ERR("failure!\n"); /* not found anything - writing over margins is the only option left */ } - if ((run->nFlags & (MERF_SPLITTABLE | MERF_STARTWHITE)) - || ((run->nFlags & MERF_GRAPHICS) && (p != wc->pRowStart))) + if ((run->nFlags & (MERF_SPLITTABLE | MERF_STARTWHITE)) + || ((run->nFlags & (MERF_GRAPHICS|MERF_TAB)) && (p != wc->pRowStart))) { wc->pLastSplittableRun = p; wc->ptLastSplittableRun = wc->pt; @@ -335,20 +335,24 @@ ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p) wc->pt.x += run->nWidth; return p->next; } - + void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) { ME_DisplayItem *p; ME_WrapContext wc; + int dpi = GetDeviceCaps(c->hDC, LOGPIXELSX); - assert(tp->type == diParagraph); + assert(tp->type == diParagraph); if (!(tp->member.para.nFlags & MEPF_REWRAP)) { return; } ME_PrepareParagraphForWrapping(c, tp); - + wc.context = c; /* wc.para_style = tp->member.para.style; */ wc.style = NULL; + tp->member.para.nRightMargin = tp->member.para.pFmt->dxRightIndent*dpi/1440; + tp->member.para.nFirstMargin = tp->member.para.pFmt->dxStartIndent*dpi/1440; + tp->member.para.nLeftMargin = (tp->member.para.pFmt->dxStartIndent+tp->member.para.pFmt->dxOffset)*dpi/1440; wc.nFirstMargin = tp->member.para.nFirstMargin; wc.nLeftMargin = tp->member.para.nLeftMargin; wc.nRightMargin = tp->member.para.nRightMargin; @@ -358,7 +362,7 @@ void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) { wc.nTotalWidth = c->rcView.right - c->rcView.left; wc.nAvailWidth = wc.nTotalWidth - wc.nFirstMargin - wc.nRightMargin; wc.pRowStart = NULL; - + ME_BeginRow(&wc); for (p = tp->next; p!=tp->member.para.next_para; ) { assert(p->type != diStartRow); @@ -415,20 +419,20 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) { ME_DisplayItem *item; ME_Context c; BOOL bModified = FALSE; - + ME_InitContext(&c, editor, hDC); c.pt.x = 0; c.pt.y = 0; item = editor->pBuffer->pFirst->next; while(item != editor->pBuffer->pLast) { BOOL bRedraw = FALSE; - + assert(item->type == diParagraph); if ((item->member.para.nFlags & MEPF_REWRAP) || (item->member.para.nYPos != c.pt.y)) bRedraw = TRUE; item->member.para.nYPos = c.pt.y; - + ME_WrapTextParagraph(&c, item); if (bRedraw) @@ -442,7 +446,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) { editor->sizeWindow.cx = c.rcView.right-c.rcView.left; editor->sizeWindow.cy = c.rcView.bottom-c.rcView.top; editor->nTotalLength = c.pt.y; - + ME_DestroyContext(&c); ReleaseDC(hWnd, hDC); return bModified;