- removed trailing spaces from some files

- tab support
- indent support
oldstable
Krzysztof Foltman 2005-04-16 10:48:35 +00:00 committed by Alexandre Julliard
parent 1f7d6ccc2e
commit 13578c8602
9 changed files with 268 additions and 140 deletions

View File

@ -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, &para->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, &para->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;

View File

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

View File

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

View File

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

View File

@ -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);
}

View File

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

View File

@ -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; i<editor->nCursors; 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);
}

View File

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

View File

@ -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(i<len);
@ -182,7 +182,7 @@ ME_DisplayItem *ME_SplitByBacktracking(ME_WrapContext *wc, ME_DisplayItem *p, in
TRACE("Must backtrack to split at: %s\n", debugstr_w(p->member.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;