mirror of
https://github.com/reactos/reactos.git
synced 2025-04-06 05:34:22 +00:00
[RICHED20] Sync with Wine Staging 1.9.23. CORE-12409
svn path=/trunk/; revision=73288
This commit is contained in:
parent
757b0ecb88
commit
534805b248
17 changed files with 1109 additions and 541 deletions
|
@ -31,11 +31,11 @@ void ME_SetCursorToStart(ME_TextEditor *editor, ME_Cursor *cursor)
|
|||
cursor->nOffset = 0;
|
||||
}
|
||||
|
||||
static void ME_SetCursorToEnd(ME_TextEditor *editor, ME_Cursor *cursor)
|
||||
static void ME_SetCursorToEnd(ME_TextEditor *editor, ME_Cursor *cursor, BOOL final_eop)
|
||||
{
|
||||
cursor->pPara = editor->pBuffer->pLast->member.para.prev_para;
|
||||
cursor->pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun);
|
||||
cursor->nOffset = 0;
|
||||
cursor->nOffset = final_eop ? cursor->pRun->member.run.len : 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -83,7 +83,7 @@ int ME_GetSelection(ME_TextEditor *editor, ME_Cursor **from, ME_Cursor **to)
|
|||
int ME_GetTextLength(ME_TextEditor *editor)
|
||||
{
|
||||
ME_Cursor cursor;
|
||||
ME_SetCursorToEnd(editor, &cursor);
|
||||
ME_SetCursorToEnd(editor, &cursor, FALSE);
|
||||
return ME_GetCursorOfs(&cursor);
|
||||
}
|
||||
|
||||
|
@ -138,8 +138,7 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to)
|
|||
if (from == 0 && to == -1)
|
||||
{
|
||||
ME_SetCursorToStart(editor, &editor->pCursors[1]);
|
||||
ME_SetCursorToEnd(editor, &editor->pCursors[0]);
|
||||
editor->pCursors[0].nOffset = editor->pCursors[0].pRun->member.run.len;
|
||||
ME_SetCursorToEnd(editor, &editor->pCursors[0], TRUE);
|
||||
ME_InvalidateSelection(editor);
|
||||
return len + 1;
|
||||
}
|
||||
|
@ -193,7 +192,7 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to)
|
|||
|
||||
if (selectionEnd)
|
||||
{
|
||||
ME_SetCursorToEnd(editor, &editor->pCursors[0]);
|
||||
ME_SetCursorToEnd(editor, &editor->pCursors[0], FALSE);
|
||||
editor->pCursors[1] = editor->pCursors[0];
|
||||
ME_InvalidateSelection(editor);
|
||||
return len;
|
||||
|
@ -201,7 +200,7 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to)
|
|||
|
||||
ME_CursorFromCharOfs(editor, from, &editor->pCursors[1]);
|
||||
editor->pCursors[0] = editor->pCursors[1];
|
||||
ME_MoveCursorChars(editor, &editor->pCursors[0], to - from);
|
||||
ME_MoveCursorChars(editor, &editor->pCursors[0], to - from, FALSE);
|
||||
/* Selection is not allowed in the middle of an end paragraph run. */
|
||||
if (editor->pCursors[1].pRun->member.run.nFlags & MERF_ENDPARA)
|
||||
editor->pCursors[1].nOffset = 0;
|
||||
|
@ -445,7 +444,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start,
|
|||
continue;
|
||||
}
|
||||
}
|
||||
if (delete_all) ME_SetDefaultParaFormat( editor, start_para->member.para.pFmt );
|
||||
if (delete_all) ME_SetDefaultParaFormat( editor, &start_para->member.para.fmt );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -550,7 +549,6 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
|
|||
pos++;
|
||||
} else { /* handle EOLs */
|
||||
ME_DisplayItem *tp, *end_run, *run, *prev;
|
||||
ME_Style *tmp_style;
|
||||
int eol_len = 0;
|
||||
|
||||
/* Find number of CR and LF in end of paragraph run */
|
||||
|
@ -595,13 +593,9 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
|
|||
run = p->pRun;
|
||||
}
|
||||
|
||||
tmp_style = ME_GetInsertStyle(editor, nCursor);
|
||||
/* ME_SplitParagraph increases style refcount */
|
||||
tp = ME_SplitParagraph(editor, run, run->member.run.style, eol_str, eol_len, 0);
|
||||
tp = ME_SplitParagraph(editor, run, style, eol_str, eol_len, 0);
|
||||
|
||||
end_run = ME_FindItemBack(tp, diRun);
|
||||
ME_ReleaseStyle(end_run->member.run.style);
|
||||
end_run->member.run.style = tmp_style;
|
||||
|
||||
/* Move any cursors that were at the end of the previous run to the beginning of the new para */
|
||||
prev = ME_FindItemBack( end_run, diRun );
|
||||
|
@ -628,10 +622,11 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
|
|||
}
|
||||
|
||||
/* Move the cursor nRelOfs characters (either forwards or backwards)
|
||||
* If final_eop is TRUE, allow moving the cursor to the end of the final eop.
|
||||
*
|
||||
* returns the actual number of characters moved.
|
||||
**/
|
||||
int ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs)
|
||||
int ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs, BOOL final_eop)
|
||||
{
|
||||
cursor->nOffset += nRelOfs;
|
||||
if (cursor->nOffset < 0)
|
||||
|
@ -683,11 +678,11 @@ int ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs)
|
|||
return nRelOfs;
|
||||
}
|
||||
|
||||
if (new_offset >= ME_GetTextLength(editor))
|
||||
if (new_offset >= ME_GetTextLength(editor) + (final_eop ? 1 : 0))
|
||||
{
|
||||
/* new offset at the end of the text */
|
||||
ME_SetCursorToEnd(editor, cursor);
|
||||
nRelOfs -= new_offset - ME_GetTextLength(editor);
|
||||
ME_SetCursorToEnd(editor, cursor, final_eop);
|
||||
nRelOfs -= new_offset - (ME_GetTextLength(editor) + (final_eop ? 1 : 0));
|
||||
return nRelOfs;
|
||||
}
|
||||
|
||||
|
@ -859,7 +854,7 @@ ME_SelectByType(ME_TextEditor *editor, ME_SelectionType selectionType)
|
|||
/* Select everything with cursor anchored from the start of the text */
|
||||
editor->nSelectionType = stDocument;
|
||||
ME_SetCursorToStart(editor, &editor->pCursors[1]);
|
||||
ME_SetCursorToEnd(editor, &editor->pCursors[0]);
|
||||
ME_SetCursorToEnd(editor, &editor->pCursors[0], FALSE);
|
||||
break;
|
||||
default: assert(0);
|
||||
}
|
||||
|
@ -908,8 +903,8 @@ static ME_DisplayItem* ME_FindPixelPosInTableRow(int x, int y,
|
|||
/* Return table row delimiter */
|
||||
para = ME_FindItemFwd(cell, diParagraph);
|
||||
assert(para->member.para.nFlags & MEPF_ROWEND);
|
||||
assert(para->member.para.pFmt->dwMask & PFM_TABLEROWDELIMITER);
|
||||
assert(para->member.para.pFmt->wEffects & PFE_TABLEROWDELIMITER);
|
||||
assert(para->member.para.fmt.dwMask & PFM_TABLEROWDELIMITER);
|
||||
assert(para->member.para.fmt.wEffects & PFE_TABLEROWDELIMITER);
|
||||
return para;
|
||||
}
|
||||
|
||||
|
@ -961,11 +956,13 @@ static BOOL ME_FindRunInRow(ME_TextEditor *editor, ME_DisplayItem *pRow,
|
|||
* x & y are pixel positions in virtual coordinates into the rich edit control,
|
||||
* so client coordinates must first be adjusted by the scroll position.
|
||||
*
|
||||
* If final_eop is TRUE consider the final end-of-paragraph.
|
||||
*
|
||||
* returns TRUE if the result was exactly under the cursor, otherwise returns
|
||||
* FALSE, and result is set to the closest position to the coordinates.
|
||||
*/
|
||||
static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y,
|
||||
ME_Cursor *result, BOOL *is_eol)
|
||||
ME_Cursor *result, BOOL *is_eol, BOOL final_eop)
|
||||
{
|
||||
ME_DisplayItem *p = editor->pBuffer->pFirst->member.para.next_para;
|
||||
BOOL isExact = TRUE;
|
||||
|
@ -1001,7 +998,7 @@ static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y,
|
|||
if (!pp) break;
|
||||
p = pp;
|
||||
}
|
||||
if (p == editor->pBuffer->pLast)
|
||||
if (p == editor->pBuffer->pLast && !final_eop)
|
||||
{
|
||||
/* The position is below the last paragraph, so the last row will be used
|
||||
* rather than the end of the text, so the x position will be used to
|
||||
|
@ -1016,10 +1013,7 @@ static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y,
|
|||
if( p->type == diStartRow )
|
||||
return ME_FindRunInRow( editor, p, x, result, is_eol ) && isExact;
|
||||
|
||||
result->pRun = ME_FindItemBack(p, diRun);
|
||||
result->pPara = ME_GetParagraph(result->pRun);
|
||||
result->nOffset = 0;
|
||||
assert(result->pRun->member.run.nFlags & MERF_ENDPARA);
|
||||
ME_SetCursorToEnd(editor, result, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -1047,7 +1041,7 @@ BOOL ME_CharFromPos(ME_TextEditor *editor, int x, int y,
|
|||
}
|
||||
x += editor->horz_si.nPos;
|
||||
y += editor->vert_si.nPos;
|
||||
bResult = ME_FindPixelPos(editor, x, y, cursor, NULL);
|
||||
bResult = ME_FindPixelPos(editor, x, y, cursor, NULL, FALSE);
|
||||
if (isExact) *isExact = bResult;
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -1130,7 +1124,7 @@ void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum)
|
|||
is_selection = ME_IsSelection(editor);
|
||||
is_shift = GetKeyState(VK_SHIFT) < 0;
|
||||
|
||||
ME_FindPixelPos(editor, x, y, &editor->pCursors[0], &editor->bCaretAtEnd);
|
||||
ME_FindPixelPos(editor, x, y, &editor->pCursors[0], &editor->bCaretAtEnd, FALSE);
|
||||
|
||||
if (x >= editor->rcFormat.left || is_shift)
|
||||
{
|
||||
|
@ -1190,7 +1184,7 @@ void ME_MouseMove(ME_TextEditor *editor, int x, int y)
|
|||
|
||||
tmp_cursor = editor->pCursors[0];
|
||||
/* FIXME: do something with the return value of ME_FindPixelPos */
|
||||
ME_FindPixelPos(editor, x, y, &tmp_cursor, &editor->bCaretAtEnd);
|
||||
ME_FindPixelPos(editor, x, y, &tmp_cursor, &editor->bCaretAtEnd, TRUE);
|
||||
|
||||
ME_InvalidateSelection(editor);
|
||||
editor->pCursors[0] = tmp_cursor;
|
||||
|
@ -1237,7 +1231,7 @@ static int ME_GetXForArrow(ME_TextEditor *editor, ME_Cursor *pCursor)
|
|||
|
||||
|
||||
static void
|
||||
ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs)
|
||||
ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs, BOOL extend)
|
||||
{
|
||||
ME_DisplayItem *pRun = pCursor->pRun;
|
||||
ME_DisplayItem *pOldPara = pCursor->pPara;
|
||||
|
@ -1255,8 +1249,12 @@ ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs)
|
|||
assert(pItem);
|
||||
/* start of the previous row */
|
||||
pItem = ME_FindItemBack(pItem, diStartRow);
|
||||
if (!pItem)
|
||||
return; /* row not found - ignore */
|
||||
if (!pItem) /* row not found */
|
||||
{
|
||||
if (extend)
|
||||
ME_SetCursorToStart(editor, pCursor);
|
||||
return;
|
||||
}
|
||||
pNewPara = ME_GetParagraph(pItem);
|
||||
if (pOldPara->member.para.nFlags & MEPF_ROWEND ||
|
||||
(pOldPara->member.para.pCell &&
|
||||
|
@ -1282,8 +1280,12 @@ ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs)
|
|||
{
|
||||
/* start of the next row */
|
||||
pItem = ME_FindItemFwd(pRun, diStartRow);
|
||||
if (!pItem)
|
||||
return; /* row not found - ignore */
|
||||
if (!pItem) /* row not found */
|
||||
{
|
||||
if (extend)
|
||||
ME_SetCursorToEnd(editor, pCursor, TRUE);
|
||||
return;
|
||||
}
|
||||
pNewPara = ME_GetParagraph(pItem);
|
||||
if (pOldPara->member.para.nFlags & MEPF_ROWSTART ||
|
||||
(pOldPara->member.para.pCell &&
|
||||
|
@ -1383,7 +1385,7 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
|
|||
|
||||
if (editor->vert_si.nPos >= y - editor->sizeWindow.cy)
|
||||
{
|
||||
ME_SetCursorToEnd(editor, pCursor);
|
||||
ME_SetCursorToEnd(editor, pCursor, FALSE);
|
||||
editor->bCaretAtEnd = FALSE;
|
||||
} else {
|
||||
ME_DisplayItem *pRun = pCursor->pRun;
|
||||
|
@ -1480,7 +1482,7 @@ static void ME_ArrowEnd(ME_TextEditor *editor, ME_Cursor *pCursor)
|
|||
|
||||
static void ME_ArrowCtrlEnd(ME_TextEditor *editor, ME_Cursor *pCursor)
|
||||
{
|
||||
ME_SetCursorToEnd(editor, pCursor);
|
||||
ME_SetCursorToEnd(editor, pCursor, FALSE);
|
||||
editor->bCaretAtEnd = FALSE;
|
||||
}
|
||||
|
||||
|
@ -1508,9 +1510,6 @@ void ME_SendSelChange(ME_TextEditor *editor)
|
|||
{
|
||||
SELCHANGE sc;
|
||||
|
||||
if (!(editor->nEventMask & ENM_SELCHANGE))
|
||||
return;
|
||||
|
||||
sc.nmhdr.hwndFrom = NULL;
|
||||
sc.nmhdr.idFrom = 0;
|
||||
sc.nmhdr.code = EN_SELCHANGE;
|
||||
|
@ -1520,16 +1519,21 @@ void ME_SendSelChange(ME_TextEditor *editor)
|
|||
sc.seltyp |= SEL_TEXT;
|
||||
if (sc.chrg.cpMin < sc.chrg.cpMax+1) /* what were RICHEDIT authors thinking ? */
|
||||
sc.seltyp |= SEL_MULTICHAR;
|
||||
TRACE("cpMin=%d cpMax=%d seltyp=%d (%s %s)\n",
|
||||
sc.chrg.cpMin, sc.chrg.cpMax, sc.seltyp,
|
||||
(sc.seltyp & SEL_TEXT) ? "SEL_TEXT" : "",
|
||||
(sc.seltyp & SEL_MULTICHAR) ? "SEL_MULTICHAR" : "");
|
||||
|
||||
if (sc.chrg.cpMin != editor->notified_cr.cpMin || sc.chrg.cpMax != editor->notified_cr.cpMax)
|
||||
{
|
||||
ME_ClearTempStyle(editor);
|
||||
|
||||
editor->notified_cr = sc.chrg;
|
||||
ITextHost_TxNotify(editor->texthost, sc.nmhdr.code, &sc);
|
||||
|
||||
if (editor->nEventMask & ENM_SELCHANGE)
|
||||
{
|
||||
TRACE("cpMin=%d cpMax=%d seltyp=%d (%s %s)\n",
|
||||
sc.chrg.cpMin, sc.chrg.cpMax, sc.seltyp,
|
||||
(sc.seltyp & SEL_TEXT) ? "SEL_TEXT" : "",
|
||||
(sc.seltyp & SEL_MULTICHAR) ? "SEL_MULTICHAR" : "");
|
||||
ITextHost_TxNotify(editor->texthost, sc.nmhdr.code, &sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1548,20 +1552,20 @@ ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl)
|
|||
if (ctrl)
|
||||
success = ME_MoveCursorWords(editor, &tmp_curs, -1);
|
||||
else
|
||||
success = ME_MoveCursorChars(editor, &tmp_curs, -1);
|
||||
success = ME_MoveCursorChars(editor, &tmp_curs, -1, extend);
|
||||
break;
|
||||
case VK_RIGHT:
|
||||
editor->bCaretAtEnd = FALSE;
|
||||
if (ctrl)
|
||||
success = ME_MoveCursorWords(editor, &tmp_curs, +1);
|
||||
else
|
||||
success = ME_MoveCursorChars(editor, &tmp_curs, +1);
|
||||
success = ME_MoveCursorChars(editor, &tmp_curs, +1, extend);
|
||||
break;
|
||||
case VK_UP:
|
||||
ME_MoveCursorLines(editor, &tmp_curs, -1);
|
||||
ME_MoveCursorLines(editor, &tmp_curs, -1, extend);
|
||||
break;
|
||||
case VK_DOWN:
|
||||
ME_MoveCursorLines(editor, &tmp_curs, +1);
|
||||
ME_MoveCursorLines(editor, &tmp_curs, +1, extend);
|
||||
break;
|
||||
case VK_PRIOR:
|
||||
ME_ArrowPageUp(editor, &tmp_curs);
|
||||
|
|
|
@ -424,11 +424,12 @@ void ME_RTFCharAttrHook(RTF_Info *info)
|
|||
{
|
||||
case rtfPlain:
|
||||
/* FIXME add more flags once they're implemented */
|
||||
fmt.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINETYPE | CFM_STRIKEOUT | CFM_COLOR | CFM_BACKCOLOR | CFM_SIZE | CFM_WEIGHT;
|
||||
fmt.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_UNDERLINETYPE | CFM_STRIKEOUT |
|
||||
CFM_COLOR | CFM_BACKCOLOR | CFM_SIZE | CFM_WEIGHT;
|
||||
fmt.dwEffects = CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR;
|
||||
fmt.yHeight = 12*20; /* 12pt */
|
||||
fmt.wWeight = FW_NORMAL;
|
||||
fmt.bUnderlineType = CFU_UNDERLINENONE;
|
||||
fmt.bUnderlineType = CFU_UNDERLINE;
|
||||
break;
|
||||
case rtfBold:
|
||||
fmt.dwMask = CFM_BOLD | CFM_WEIGHT;
|
||||
|
@ -440,24 +441,28 @@ void ME_RTFCharAttrHook(RTF_Info *info)
|
|||
fmt.dwEffects = info->rtfParam ? fmt.dwMask : 0;
|
||||
break;
|
||||
case rtfUnderline:
|
||||
fmt.dwMask = CFM_UNDERLINETYPE;
|
||||
fmt.bUnderlineType = info->rtfParam ? CFU_CF1UNDERLINE : CFU_UNDERLINENONE;
|
||||
fmt.dwMask = CFM_UNDERLINETYPE | CFM_UNDERLINE;
|
||||
fmt.bUnderlineType = CFU_UNDERLINE;
|
||||
fmt.dwEffects = info->rtfParam ? CFE_UNDERLINE : 0;
|
||||
break;
|
||||
case rtfDotUnderline:
|
||||
fmt.dwMask = CFM_UNDERLINETYPE;
|
||||
fmt.bUnderlineType = info->rtfParam ? CFU_UNDERLINEDOTTED : CFU_UNDERLINENONE;
|
||||
fmt.dwMask = CFM_UNDERLINETYPE | CFM_UNDERLINE;
|
||||
fmt.bUnderlineType = CFU_UNDERLINEDOTTED;
|
||||
fmt.dwEffects = info->rtfParam ? CFE_UNDERLINE : 0;
|
||||
break;
|
||||
case rtfDbUnderline:
|
||||
fmt.dwMask = CFM_UNDERLINETYPE;
|
||||
fmt.bUnderlineType = info->rtfParam ? CFU_UNDERLINEDOUBLE : CFU_UNDERLINENONE;
|
||||
fmt.dwMask = CFM_UNDERLINETYPE | CFM_UNDERLINE;
|
||||
fmt.bUnderlineType = CFU_UNDERLINEDOUBLE;
|
||||
fmt.dwEffects = info->rtfParam ? CFE_UNDERLINE : 0;
|
||||
break;
|
||||
case rtfWordUnderline:
|
||||
fmt.dwMask = CFM_UNDERLINETYPE;
|
||||
fmt.bUnderlineType = info->rtfParam ? CFU_UNDERLINEWORD : CFU_UNDERLINENONE;
|
||||
fmt.dwMask = CFM_UNDERLINETYPE | CFM_UNDERLINE;
|
||||
fmt.bUnderlineType = CFU_UNDERLINEWORD;
|
||||
fmt.dwEffects = info->rtfParam ? CFE_UNDERLINE : 0;
|
||||
break;
|
||||
case rtfNoUnderline:
|
||||
fmt.dwMask = CFM_UNDERLINETYPE;
|
||||
fmt.bUnderlineType = CFU_UNDERLINENONE;
|
||||
fmt.dwMask = CFM_UNDERLINE;
|
||||
fmt.dwEffects = 0;
|
||||
break;
|
||||
case rtfStrikeThru:
|
||||
fmt.dwMask = CFM_STRIKEOUT;
|
||||
|
@ -486,7 +491,7 @@ void ME_RTFCharAttrHook(RTF_Info *info)
|
|||
{
|
||||
RTFColor *c = RTFGetColor(info, info->rtfParam);
|
||||
if (c && c->rtfCBlue >= 0)
|
||||
fmt.crTextColor = (c->rtfCBlue<<16)|(c->rtfCGreen<<8)|(c->rtfCRed);
|
||||
fmt.crBackColor = (c->rtfCBlue<<16)|(c->rtfCGreen<<8)|(c->rtfCRed);
|
||||
else
|
||||
fmt.dwEffects = CFE_AUTOBACKCOLOR;
|
||||
}
|
||||
|
@ -550,8 +555,9 @@ void ME_RTFParAttrHook(RTF_Info *info)
|
|||
info->borderType = RTFBorderParaTop;
|
||||
info->fmt.dwMask = PFM_ALIGNMENT | PFM_BORDER | PFM_LINESPACING | PFM_TABSTOPS |
|
||||
PFM_OFFSET | PFM_RIGHTINDENT | PFM_SPACEAFTER | PFM_SPACEBEFORE |
|
||||
PFM_STARTINDENT | PFM_RTLPARA;
|
||||
/* TODO: numbering, shading */
|
||||
PFM_STARTINDENT | PFM_RTLPARA | PFM_NUMBERING | PFM_NUMBERINGSTART |
|
||||
PFM_NUMBERINGSTYLE | PFM_NUMBERINGTAB;
|
||||
/* TODO: shading */
|
||||
info->fmt.wAlignment = PFA_LEFT;
|
||||
info->fmt.cTabCount = 0;
|
||||
info->fmt.dxOffset = info->fmt.dxStartIndent = info->fmt.dxRightIndent = 0;
|
||||
|
@ -561,6 +567,11 @@ void ME_RTFParAttrHook(RTF_Info *info)
|
|||
info->fmt.dySpaceBefore = info->fmt.dySpaceAfter = 0;
|
||||
info->fmt.dyLineSpacing = 0;
|
||||
info->fmt.wEffects &= ~PFE_RTLPARA;
|
||||
info->fmt.wNumbering = 0;
|
||||
info->fmt.wNumberingStart = 0;
|
||||
info->fmt.wNumberingStyle = 0;
|
||||
info->fmt.wNumberingTab = 0;
|
||||
|
||||
if (!info->editor->bEmulateVersion10) /* v4.1 */
|
||||
{
|
||||
if (info->tableDef && info->tableDef->tableRowStart &&
|
||||
|
@ -754,18 +765,6 @@ void ME_RTFParAttrHook(RTF_Info *info)
|
|||
info->fmt.dwMask |= PFM_NUMBERING;
|
||||
info->fmt.wNumbering = 2; /* FIXME: MSDN says it's not used ?? */
|
||||
break;
|
||||
case rtfParNumDecimal:
|
||||
info->fmt.dwMask |= PFM_NUMBERING;
|
||||
info->fmt.wNumbering = 2; /* FIXME: MSDN says it's not used ?? */
|
||||
break;
|
||||
case rtfParNumIndent:
|
||||
info->fmt.dwMask |= PFM_NUMBERINGTAB;
|
||||
info->fmt.wNumberingTab = info->rtfParam;
|
||||
break;
|
||||
case rtfParNumStartAt:
|
||||
info->fmt.dwMask |= PFM_NUMBERINGSTART;
|
||||
info->fmt.wNumberingStart = info->rtfParam;
|
||||
break;
|
||||
case rtfBorderLeft:
|
||||
info->borderType = RTFBorderParaLeft;
|
||||
info->fmt.wBorders |= 1;
|
||||
|
@ -861,7 +860,7 @@ void ME_RTFParAttrHook(RTF_Info *info)
|
|||
info->fmt.wEffects |= PFE_RTLPARA;
|
||||
break;
|
||||
case rtfLTRPar:
|
||||
info->fmt.dwMask = PFM_RTLPARA;
|
||||
info->fmt.dwMask |= PFM_RTLPARA;
|
||||
info->fmt.wEffects &= ~PFE_RTLPARA;
|
||||
break;
|
||||
}
|
||||
|
@ -899,7 +898,7 @@ void ME_RTFTblAttrHook(RTF_Info *info)
|
|||
/* 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 = info->editor->pCursors[0].pPara;
|
||||
PARAFORMAT2 *pFmt = para->member.para.pFmt;
|
||||
PARAFORMAT2 *pFmt = ¶->member.para.fmt;
|
||||
pFmt->rgxTabs[cellNum] &= ~0x00FFFFFF;
|
||||
pFmt->rgxTabs[cellNum] |= 0x00FFFFFF & info->rtfParam;
|
||||
}
|
||||
|
@ -970,7 +969,7 @@ void ME_RTFSpecialCharHook(RTF_Info *info)
|
|||
}
|
||||
} else { /* v1.0 - v3.0 */
|
||||
ME_DisplayItem *para = info->editor->pCursors[0].pPara;
|
||||
PARAFORMAT2 *pFmt = para->member.para.pFmt;
|
||||
PARAFORMAT2 *pFmt = ¶->member.para.fmt;
|
||||
if (pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE &&
|
||||
tableDef->numCellsInserted < tableDef->numCellsDefined)
|
||||
{
|
||||
|
@ -1056,8 +1055,8 @@ void ME_RTFSpecialCharHook(RTF_Info *info)
|
|||
}
|
||||
|
||||
para = ME_InsertTableRowEndFromCursor(info->editor);
|
||||
para->member.para.pFmt->dxOffset = abs(info->tableDef->gapH);
|
||||
para->member.para.pFmt->dxStartIndent = info->tableDef->leftEdge;
|
||||
para->member.para.fmt.dxOffset = abs(info->tableDef->gapH);
|
||||
para->member.para.fmt.dxStartIndent = info->tableDef->leftEdge;
|
||||
ME_ApplyBorderProperties(info, ¶->member.para.border,
|
||||
tableDef->border);
|
||||
info->nestingLevel--;
|
||||
|
@ -1079,7 +1078,7 @@ void ME_RTFSpecialCharHook(RTF_Info *info)
|
|||
} else { /* v1.0 - v3.0 */
|
||||
WCHAR endl = '\r';
|
||||
ME_DisplayItem *para = info->editor->pCursors[0].pPara;
|
||||
PARAFORMAT2 *pFmt = para->member.para.pFmt;
|
||||
PARAFORMAT2 *pFmt = ¶->member.para.fmt;
|
||||
pFmt->dxOffset = info->tableDef->gapH;
|
||||
pFmt->dxStartIndent = info->tableDef->leftEdge;
|
||||
|
||||
|
@ -1106,7 +1105,7 @@ void ME_RTFSpecialCharHook(RTF_Info *info)
|
|||
PARAFORMAT2 *pFmt;
|
||||
RTFFlushOutputBuffer(info);
|
||||
para = info->editor->pCursors[0].pPara;
|
||||
pFmt = para->member.para.pFmt;
|
||||
pFmt = ¶->member.para.fmt;
|
||||
if (pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE)
|
||||
{
|
||||
/* rtfPar is treated like a space within a table. */
|
||||
|
@ -1423,6 +1422,110 @@ static void ME_RTFReadObjectGroup(RTF_Info *info)
|
|||
RTFRouteToken(info); /* feed "}" back to router */
|
||||
}
|
||||
|
||||
static void ME_RTFReadParnumGroup( RTF_Info *info )
|
||||
{
|
||||
int level = 1, type = -1;
|
||||
WORD indent = 0, start = 1;
|
||||
WCHAR txt_before = 0, txt_after = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
RTFGetToken( info );
|
||||
|
||||
if (RTFCheckCMM( info, rtfControl, rtfDestination, rtfParNumTextBefore ) ||
|
||||
RTFCheckCMM( info, rtfControl, rtfDestination, rtfParNumTextAfter ))
|
||||
{
|
||||
int loc = info->rtfMinor;
|
||||
|
||||
RTFGetToken( info );
|
||||
if (info->rtfClass == rtfText)
|
||||
{
|
||||
if (loc == rtfParNumTextBefore)
|
||||
txt_before = info->rtfMajor;
|
||||
else
|
||||
txt_after = info->rtfMajor;
|
||||
continue;
|
||||
}
|
||||
/* falling through to catch EOFs and group level changes */
|
||||
}
|
||||
|
||||
if (info->rtfClass == rtfEOF)
|
||||
return;
|
||||
|
||||
if (RTFCheckCM( info, rtfGroup, rtfEndGroup ))
|
||||
{
|
||||
if (--level == 0) break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (RTFCheckCM( info, rtfGroup, rtfBeginGroup ))
|
||||
{
|
||||
level++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Ignore non para-attr */
|
||||
if (!RTFCheckCM( info, rtfControl, rtfParAttr ))
|
||||
continue;
|
||||
|
||||
switch (info->rtfMinor)
|
||||
{
|
||||
case rtfParLevel: /* Para level is ignored */
|
||||
case rtfParSimple:
|
||||
break;
|
||||
case rtfParBullet:
|
||||
type = PFN_BULLET;
|
||||
break;
|
||||
|
||||
case rtfParNumDecimal:
|
||||
type = PFN_ARABIC;
|
||||
break;
|
||||
case rtfParNumULetter:
|
||||
type = PFN_UCLETTER;
|
||||
break;
|
||||
case rtfParNumURoman:
|
||||
type = PFN_UCROMAN;
|
||||
break;
|
||||
case rtfParNumLLetter:
|
||||
type = PFN_LCLETTER;
|
||||
break;
|
||||
case rtfParNumLRoman:
|
||||
type = PFN_LCROMAN;
|
||||
break;
|
||||
|
||||
case rtfParNumIndent:
|
||||
indent = info->rtfParam;
|
||||
break;
|
||||
case rtfParNumStartAt:
|
||||
start = info->rtfParam;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (type != -1)
|
||||
{
|
||||
info->fmt.dwMask |= (PFM_NUMBERING | PFM_NUMBERINGSTART | PFM_NUMBERINGSTYLE | PFM_NUMBERINGTAB);
|
||||
info->fmt.wNumbering = type;
|
||||
info->fmt.wNumberingStart = start;
|
||||
info->fmt.wNumberingStyle = PFNS_PAREN;
|
||||
if (type != PFN_BULLET)
|
||||
{
|
||||
if (txt_before == 0 && txt_after == 0)
|
||||
info->fmt.wNumberingStyle = PFNS_PLAIN;
|
||||
else if (txt_after == '.')
|
||||
info->fmt.wNumberingStyle = PFNS_PERIOD;
|
||||
else if (txt_before == '(' && txt_after == ')')
|
||||
info->fmt.wNumberingStyle = PFNS_PARENS;
|
||||
}
|
||||
info->fmt.wNumberingTab = indent;
|
||||
}
|
||||
|
||||
TRACE("type %d indent %d start %d txt before %04x txt after %04x\n",
|
||||
type, indent, start, txt_before, txt_after);
|
||||
|
||||
RTFRouteToken( info ); /* feed "}" back to router */
|
||||
}
|
||||
|
||||
static void ME_RTFReadHook(RTF_Info *info)
|
||||
{
|
||||
switch(info->rtfClass)
|
||||
|
@ -1523,7 +1626,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
|
|||
ME_GetTextLength(editor), FALSE);
|
||||
from = to = 0;
|
||||
ME_ClearTempStyle(editor);
|
||||
ME_SetDefaultParaFormat(editor, editor->pCursors[0].pPara->member.para.pFmt);
|
||||
ME_SetDefaultParaFormat(editor, &editor->pCursors[0].pPara->member.para.fmt);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1556,8 +1659,9 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
|
|||
|
||||
if (!invalidRTF && !inStream.editstream->dwError)
|
||||
{
|
||||
ME_Cursor start;
|
||||
from = ME_GetCursorOfs(&editor->pCursors[0]);
|
||||
if (format & SF_RTF) {
|
||||
from = ME_GetCursorOfs(&editor->pCursors[0]);
|
||||
|
||||
/* setup the RTF parser */
|
||||
memset(&parser, 0, sizeof parser);
|
||||
|
@ -1571,6 +1675,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
|
|||
RTFSetDestinationCallback(&parser, rtfShpPict, ME_RTFReadShpPictGroup);
|
||||
RTFSetDestinationCallback(&parser, rtfPict, ME_RTFReadPictGroup);
|
||||
RTFSetDestinationCallback(&parser, rtfObject, ME_RTFReadObjectGroup);
|
||||
RTFSetDestinationCallback(&parser, rtfParNumbering, ME_RTFReadParnumGroup);
|
||||
if (!parser.editor->bEmulateVersion10) /* v4.1 */
|
||||
{
|
||||
RTFSetDestinationCallback(&parser, rtfNoNestTables, RTFSkipGroup);
|
||||
|
@ -1644,9 +1749,19 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
|
|||
if (newto > to + (editor->bEmulateVersion10 ? 1 : 0)) {
|
||||
WCHAR lastchar[3] = {'\0', '\0'};
|
||||
int linebreakSize = editor->bEmulateVersion10 ? 2 : 1;
|
||||
ME_Cursor linebreakCursor = *selEnd;
|
||||
ME_Cursor linebreakCursor = *selEnd, lastcharCursor = *selEnd;
|
||||
CHARFORMAT2W cf;
|
||||
|
||||
ME_MoveCursorChars(editor, &linebreakCursor, -linebreakSize);
|
||||
/* Set the final eop to the char fmt of the last char */
|
||||
cf.cbSize = sizeof(cf);
|
||||
cf.dwMask = CFM_ALL2;
|
||||
ME_MoveCursorChars(editor, &lastcharCursor, -1, FALSE);
|
||||
ME_GetCharFormat(editor, &lastcharCursor, &linebreakCursor, &cf);
|
||||
ME_SetSelection(editor, newto, -1);
|
||||
ME_SetSelectionCharFormat(editor, &cf);
|
||||
ME_SetSelection(editor, newto, newto);
|
||||
|
||||
ME_MoveCursorChars(editor, &linebreakCursor, -linebreakSize, FALSE);
|
||||
ME_GetTextW(editor, lastchar, 2, &linebreakCursor, linebreakSize, FALSE, FALSE);
|
||||
if (lastchar[0] == '\r' && (lastchar[1] == '\n' || lastchar[1] == '\0')) {
|
||||
ME_InternalDeleteText(editor, &linebreakCursor, linebreakSize, FALSE);
|
||||
|
@ -1659,12 +1774,17 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
|
|||
style = parser.style;
|
||||
}
|
||||
else if (format & SF_TEXT)
|
||||
{
|
||||
num_read = ME_StreamInText(editor, format, &inStream, style);
|
||||
to = ME_GetCursorOfs(&editor->pCursors[0]);
|
||||
}
|
||||
else
|
||||
ERR("EM_STREAMIN without SF_TEXT or SF_RTF\n");
|
||||
/* put the cursor at the top */
|
||||
if (!(format & SFF_SELECTION))
|
||||
ME_SetSelection(editor, 0, 0);
|
||||
ME_CursorFromCharOfs(editor, from, &start);
|
||||
ME_UpdateLinkAttribute(editor, &start, to - from);
|
||||
}
|
||||
|
||||
/* Restore saved undo mode */
|
||||
|
@ -1796,7 +1916,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH
|
|||
{
|
||||
ME_CursorFromCharOfs(editor, nMin - 1, &cursor);
|
||||
wLastChar = *get_text( &cursor.pRun->member.run, cursor.nOffset );
|
||||
ME_MoveCursorChars(editor, &cursor, 1);
|
||||
ME_MoveCursorChars(editor, &cursor, 1, FALSE);
|
||||
} else {
|
||||
ME_CursorFromCharOfs(editor, nMin, &cursor);
|
||||
}
|
||||
|
@ -1872,7 +1992,7 @@ ME_FindText(ME_TextEditor *editor, DWORD flags, const CHARRANGE *chrg, const WCH
|
|||
{
|
||||
ME_CursorFromCharOfs(editor, nMax + 1, &cursor);
|
||||
wLastChar = *get_text( &cursor.pRun->member.run, cursor.nOffset );
|
||||
ME_MoveCursorChars(editor, &cursor, -1);
|
||||
ME_MoveCursorChars(editor, &cursor, -1, FALSE);
|
||||
} else {
|
||||
ME_CursorFromCharOfs(editor, nMax, &cursor);
|
||||
}
|
||||
|
@ -2286,7 +2406,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
|
|||
int from, to;
|
||||
const WCHAR endl = '\r';
|
||||
const WCHAR endlv10[] = {'\r','\n'};
|
||||
ME_Style *style;
|
||||
ME_Style *style, *eop_style;
|
||||
|
||||
if (editor->styleFlags & ES_READONLY) {
|
||||
MessageBeep(MB_ICONERROR);
|
||||
|
@ -2324,7 +2444,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
|
|||
ME_InsertTextFromCursor(editor, 0, &endl, 1,
|
||||
editor->pCursors[0].pRun->member.run.style);
|
||||
para = editor->pBuffer->pFirst->member.para.next_para;
|
||||
ME_SetDefaultParaFormat(editor, para->member.para.pFmt);
|
||||
ME_SetDefaultParaFormat(editor, ¶->member.para.fmt);
|
||||
para->member.para.nFlags = MEPF_REWRAP;
|
||||
editor->pCursors[0].pPara = para;
|
||||
editor->pCursors[0].pRun = ME_FindItemFwd(para, diRun);
|
||||
|
@ -2383,21 +2503,29 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
|
|||
}
|
||||
|
||||
style = ME_GetInsertStyle(editor, 0);
|
||||
ME_SaveTempStyle(editor);
|
||||
|
||||
/* Normally the new eop style is the insert style, however in a list it is copied from the existing
|
||||
eop style (this prevents the list label style changing when the new eop is inserted).
|
||||
No extra ref is taken here on eop_style. */
|
||||
if (para->member.para.fmt.wNumbering)
|
||||
eop_style = para->member.para.eop_run->style;
|
||||
else
|
||||
eop_style = style;
|
||||
ME_ContinueCoalescingTransaction(editor);
|
||||
if (shift_is_down)
|
||||
ME_InsertEndRowFromCursor(editor, 0);
|
||||
else
|
||||
if (!editor->bEmulateVersion10)
|
||||
ME_InsertTextFromCursor(editor, 0, &endl, 1, style);
|
||||
ME_InsertTextFromCursor(editor, 0, &endl, 1, eop_style);
|
||||
else
|
||||
ME_InsertTextFromCursor(editor, 0, endlv10, 2, style);
|
||||
ME_ReleaseStyle(style);
|
||||
ME_InsertTextFromCursor(editor, 0, endlv10, 2, eop_style);
|
||||
ME_CommitCoalescingUndo(editor);
|
||||
SetCursor(NULL);
|
||||
|
||||
ME_UpdateSelectionLinkAttribute(editor);
|
||||
ME_UpdateRepaint(editor, FALSE);
|
||||
ME_SaveTempStyle(editor, style); /* set the temp insert style for the new para */
|
||||
ME_ReleaseStyle(style);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -2557,7 +2685,6 @@ static LRESULT ME_Char(ME_TextEditor *editor, WPARAM charCode,
|
|||
if(editor->nTextLimit > ME_GetTextLength(editor) - (to-from))
|
||||
{
|
||||
ME_Style *style = ME_GetInsertStyle(editor, 0);
|
||||
ME_SaveTempStyle(editor);
|
||||
ME_ContinueCoalescingTransaction(editor);
|
||||
ME_InsertTextFromCursor(editor, 0, &wstr, 1, style);
|
||||
ME_ReleaseStyle(style);
|
||||
|
@ -4529,7 +4656,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
|||
ME_Style *style = ME_GetInsertStyle(editor, 0);
|
||||
hIMC = ITextHost_TxImmGetContext(editor->texthost);
|
||||
ME_DeleteSelection(editor);
|
||||
ME_SaveTempStyle(editor);
|
||||
ME_SaveTempStyle(editor, style);
|
||||
if (lParam & (GCS_RESULTSTR|GCS_COMPSTR))
|
||||
{
|
||||
LPWSTR lpCompStr = NULL;
|
||||
|
|
|
@ -111,7 +111,7 @@ ME_Style *ME_ApplyStyle(ME_TextEditor *ed, ME_Style *sSrc, CHARFORMAT2W *style)
|
|||
HFONT ME_SelectStyleFont(ME_Context *c, ME_Style *s) DECLSPEC_HIDDEN;
|
||||
void ME_UnselectStyleFont(ME_Context *c, ME_Style *s, HFONT hOldFont) DECLSPEC_HIDDEN;
|
||||
void ME_InitCharFormat2W(CHARFORMAT2W *pFmt) DECLSPEC_HIDDEN;
|
||||
void ME_SaveTempStyle(ME_TextEditor *editor) DECLSPEC_HIDDEN;
|
||||
void ME_SaveTempStyle(ME_TextEditor *editor, ME_Style *style) DECLSPEC_HIDDEN;
|
||||
void ME_ClearTempStyle(ME_TextEditor *editor) DECLSPEC_HIDDEN;
|
||||
void ME_DumpStyleToBuf(CHARFORMAT2W *pFmt, char buf[2048]) DECLSPEC_HIDDEN;
|
||||
void ME_DumpStyle(ME_Style *s) DECLSPEC_HIDDEN;
|
||||
|
@ -135,6 +135,8 @@ void ME_DumpDocument(ME_TextBuffer *buffer) DECLSPEC_HIDDEN;
|
|||
/* string.c */
|
||||
ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars) DECLSPEC_HIDDEN;
|
||||
ME_String *ME_MakeStringR(WCHAR cRepeat, int nMaxChars) DECLSPEC_HIDDEN;
|
||||
ME_String *ME_MakeStringConst(const WCHAR *str, int len) DECLSPEC_HIDDEN;
|
||||
ME_String *ME_MakeStringEmpty(int len) DECLSPEC_HIDDEN;
|
||||
void ME_DestroyString(ME_String *s) DECLSPEC_HIDDEN;
|
||||
BOOL ME_AppendString(ME_String *s, const WCHAR *append, int len) DECLSPEC_HIDDEN;
|
||||
ME_String *ME_VSplitString(ME_String *orig, int nVPos) DECLSPEC_HIDDEN;
|
||||
|
@ -213,7 +215,7 @@ BOOL ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars) DECLS
|
|||
void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
|
||||
const WCHAR *str, int len, ME_Style *style) DECLSPEC_HIDDEN;
|
||||
void ME_InsertEndRowFromCursor(ME_TextEditor *editor, int nCursor) DECLSPEC_HIDDEN;
|
||||
int ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) DECLSPEC_HIDDEN;
|
||||
int ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs, BOOL final_eop) DECLSPEC_HIDDEN;
|
||||
BOOL ME_ArrowKey(ME_TextEditor *ed, int nVKey, BOOL extend, BOOL ctrl) DECLSPEC_HIDDEN;
|
||||
|
||||
int ME_GetCursorOfs(const ME_Cursor *cursor) DECLSPEC_HIDDEN;
|
||||
|
@ -251,6 +253,8 @@ BOOL ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt) D
|
|||
void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN;
|
||||
void ME_MarkAllForWrapping(ME_TextEditor *editor) DECLSPEC_HIDDEN;
|
||||
void ME_SetDefaultParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) DECLSPEC_HIDDEN;
|
||||
void para_num_init( ME_Context *c, ME_Paragraph *para ) DECLSPEC_HIDDEN;
|
||||
void para_num_clear( struct para_num *pn ) DECLSPEC_HIDDEN;
|
||||
|
||||
/* paint.c */
|
||||
void ME_PaintContent(ME_TextEditor *editor, HDC hDC, const RECT *rcUpdate) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -29,6 +29,7 @@ typedef struct tagME_String
|
|||
{
|
||||
WCHAR *szData;
|
||||
int nLen, nBuffer;
|
||||
void (*free)(struct tagME_String *);
|
||||
} ME_String;
|
||||
|
||||
typedef struct tagME_FontCacheItem
|
||||
|
@ -158,9 +159,17 @@ typedef struct tagME_BorderRect
|
|||
ME_Border right;
|
||||
} ME_BorderRect;
|
||||
|
||||
struct para_num
|
||||
{
|
||||
ME_Style *style;
|
||||
ME_String *text;
|
||||
INT width;
|
||||
POINT pt;
|
||||
};
|
||||
|
||||
typedef struct tagME_Paragraph
|
||||
{
|
||||
PARAFORMAT2 *pFmt;
|
||||
PARAFORMAT2 fmt;
|
||||
ME_String *text;
|
||||
|
||||
struct tagME_DisplayItem *pCell; /* v4.1 */
|
||||
|
@ -171,6 +180,8 @@ typedef struct tagME_Paragraph
|
|||
POINT pt;
|
||||
int nHeight, nWidth;
|
||||
int nRows;
|
||||
struct para_num para_num;
|
||||
ME_Run *eop_run; /* ptr to the end-of-para run */
|
||||
struct tagME_DisplayItem *prev_para, *next_para;
|
||||
} ME_Paragraph;
|
||||
|
||||
|
@ -333,27 +344,6 @@ struct tagME_InStream {
|
|||
};
|
||||
typedef struct tagME_InStream ME_InStream;
|
||||
|
||||
|
||||
#define STREAMOUT_BUFFER_SIZE 4096
|
||||
#define STREAMOUT_FONTTBL_SIZE 8192
|
||||
#define STREAMOUT_COLORTBL_SIZE 1024
|
||||
|
||||
typedef struct tagME_OutStream {
|
||||
EDITSTREAM *stream;
|
||||
char buffer[STREAMOUT_BUFFER_SIZE];
|
||||
UINT pos, written;
|
||||
UINT nCodePage;
|
||||
UINT nFontTblLen;
|
||||
ME_FontTableItem fonttbl[STREAMOUT_FONTTBL_SIZE];
|
||||
UINT nColorTblLen;
|
||||
COLORREF colortbl[STREAMOUT_COLORTBL_SIZE];
|
||||
UINT nDefaultFont;
|
||||
UINT nDefaultCodePage;
|
||||
/* nNestingLevel = 0 means we aren't in a cell, 1 means we are in a cell,
|
||||
* an greater numbers mean we are in a cell nested within a cell. */
|
||||
UINT nNestingLevel;
|
||||
} ME_OutStream;
|
||||
|
||||
typedef struct tagME_TextEditor
|
||||
{
|
||||
HWND hWnd, hwndParent;
|
||||
|
@ -431,19 +421,4 @@ typedef struct tagME_Context
|
|||
ME_TextEditor *editor;
|
||||
} ME_Context;
|
||||
|
||||
typedef struct tagME_WrapContext
|
||||
{
|
||||
ME_Style *style;
|
||||
ME_Context *context;
|
||||
int nLeftMargin, nRightMargin, nFirstMargin;
|
||||
int nAvailWidth;
|
||||
int nRow;
|
||||
POINT pt;
|
||||
BOOL bOverflown, bWordWrap;
|
||||
ME_DisplayItem *pPara;
|
||||
ME_DisplayItem *pRowStart;
|
||||
|
||||
ME_DisplayItem *pLastSplittableRun;
|
||||
} ME_WrapContext;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -163,8 +163,8 @@ void ME_DestroyDisplayItem(ME_DisplayItem *item)
|
|||
TRACE("type=%s\n", ME_GetDITypeName(item->type));
|
||||
if (item->type==diParagraph)
|
||||
{
|
||||
FREE_OBJ(item->member.para.pFmt);
|
||||
ME_DestroyString(item->member.para.text);
|
||||
para_num_clear( &item->member.para.para_num );
|
||||
}
|
||||
|
||||
if (item->type==diRun)
|
||||
|
|
|
@ -201,11 +201,26 @@ static COLORREF get_text_color( ME_Context *c, ME_Style *style, BOOL highlight )
|
|||
return color;
|
||||
}
|
||||
|
||||
static COLORREF get_back_color( ME_Context *c, ME_Style *style, BOOL highlight )
|
||||
{
|
||||
COLORREF color;
|
||||
|
||||
if (highlight)
|
||||
color = ITextHost_TxGetSysColor( c->editor->texthost, COLOR_HIGHLIGHT );
|
||||
else if ( (style->fmt.dwMask & CFM_BACKCOLOR)
|
||||
&& !(style->fmt.dwEffects & CFE_AUTOBACKCOLOR) )
|
||||
color = style->fmt.crBackColor;
|
||||
else
|
||||
color = ITextHost_TxGetSysColor( c->editor->texthost, COLOR_WINDOW );
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
static void get_underline_pen( ME_Style *style, COLORREF color, HPEN *pen )
|
||||
{
|
||||
*pen = NULL;
|
||||
/* Choose the pen type for underlining the text. */
|
||||
if (style->fmt.dwMask & CFM_UNDERLINETYPE)
|
||||
if (style->fmt.dwEffects & CFE_UNDERLINE)
|
||||
{
|
||||
switch (style->fmt.bUnderlineType)
|
||||
{
|
||||
|
@ -314,14 +329,17 @@ static void get_selection_rect( ME_Context *c, ME_Run *run, int from, int to, in
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
static void draw_text( ME_Context *c, ME_Run *run, int x, int y, BOOL selected, RECT *sel_rect )
|
||||
{
|
||||
COLORREF text_color = get_text_color( c, run->style, selected );
|
||||
COLORREF back_color = selected ? ITextHost_TxGetSysColor( c->editor->texthost, COLOR_HIGHLIGHT ) : 0;
|
||||
COLORREF back_color = get_back_color( c, run->style, selected );
|
||||
COLORREF old_text, old_back = 0;
|
||||
const WCHAR *text = get_text( run, 0 );
|
||||
ME_String *masked = NULL;
|
||||
const BOOL paint_bg = ( selected
|
||||
|| ( ( run->style->fmt.dwMask & CFM_BACKCOLOR )
|
||||
&& !(CFE_AUTOBACKCOLOR & run->style->fmt.dwEffects) )
|
||||
);
|
||||
|
||||
if (c->editor->cPasswordMask)
|
||||
{
|
||||
|
@ -330,16 +348,16 @@ static void draw_text( ME_Context *c, ME_Run *run, int x, int y, BOOL selected,
|
|||
}
|
||||
|
||||
old_text = SetTextColor( c->hDC, text_color );
|
||||
if (selected) old_back = SetBkColor( c->hDC, back_color );
|
||||
if (paint_bg) old_back = SetBkColor( c->hDC, back_color );
|
||||
|
||||
if (run->para->nFlags & MEPF_COMPLEX)
|
||||
ScriptTextOut( c->hDC, &run->style->script_cache, x, y, selected ? ETO_OPAQUE : 0, sel_rect,
|
||||
ScriptTextOut( c->hDC, &run->style->script_cache, x, y, paint_bg ? ETO_OPAQUE : 0, sel_rect,
|
||||
&run->script_analysis, NULL, 0, run->glyphs, run->num_glyphs, run->advances,
|
||||
NULL, run->offsets );
|
||||
else
|
||||
ExtTextOutW( c->hDC, x, y, selected ? ETO_OPAQUE : 0, sel_rect, text, run->len, NULL );
|
||||
ExtTextOutW( c->hDC, x, y, paint_bg ? ETO_OPAQUE : 0, sel_rect, text, run->len, NULL );
|
||||
|
||||
if (selected) SetBkColor( c->hDC, old_back );
|
||||
if (paint_bg) SetBkColor( c->hDC, old_back );
|
||||
SetTextColor( c->hDC, old_text );
|
||||
|
||||
draw_underline( c, run, x, y, text_color );
|
||||
|
@ -389,7 +407,18 @@ static void ME_DrawTextWithStyle(ME_Context *c, ME_Run *run, int x, int y,
|
|||
hOldFont = ME_SelectStyleFont( c, run->style );
|
||||
|
||||
if (sel_rgn) ExtSelectClipRgn( hDC, sel_rgn, RGN_DIFF );
|
||||
draw_text( c, run, x, y - yOffset, FALSE, NULL );
|
||||
|
||||
if (!(run->style->fmt.dwEffects & CFE_AUTOBACKCOLOR)
|
||||
&& (run->style->fmt.dwMask & CFM_BACKCOLOR) )
|
||||
{
|
||||
RECT tmp_rect;
|
||||
get_selection_rect( c, run, 0, run->len, cy, &tmp_rect );
|
||||
OffsetRect( &tmp_rect, x, ymin );
|
||||
draw_text( c, run, x, y - yOffset, FALSE, &tmp_rect );
|
||||
}
|
||||
else
|
||||
draw_text( c, run, x, y - yOffset, FALSE, NULL );
|
||||
|
||||
if (sel_rgn)
|
||||
{
|
||||
ExtSelectClipRgn( hDC, clip, RGN_COPY );
|
||||
|
@ -524,16 +553,16 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT
|
|||
BOOL hasParaBorder;
|
||||
|
||||
SetRectEmpty(bounds);
|
||||
if (!(para->pFmt->dwMask & (PFM_BORDER | PFM_SPACEBEFORE | PFM_SPACEAFTER))) return;
|
||||
if (!(para->fmt.dwMask & (PFM_BORDER | PFM_SPACEBEFORE | PFM_SPACEAFTER))) return;
|
||||
|
||||
border_width = top_border = bottom_border = 0;
|
||||
idx = (para->pFmt->wBorders >> 8) & 0xF;
|
||||
idx = (para->fmt.wBorders >> 8) & 0xF;
|
||||
hasParaBorder = (!(c->editor->bEmulateVersion10 &&
|
||||
para->pFmt->dwMask & PFM_TABLE &&
|
||||
para->pFmt->wEffects & PFE_TABLE) &&
|
||||
(para->pFmt->dwMask & PFM_BORDER) &&
|
||||
para->fmt.dwMask & PFM_TABLE &&
|
||||
para->fmt.wEffects & PFE_TABLE) &&
|
||||
(para->fmt.dwMask & PFM_BORDER) &&
|
||||
idx != 0 &&
|
||||
(para->pFmt->wBorders & 0xF));
|
||||
(para->fmt.wBorders & 0xF));
|
||||
if (hasParaBorder)
|
||||
{
|
||||
/* FIXME: wBorders is not stored as MSDN says in v1.0 - 4.1 of richedit
|
||||
|
@ -560,29 +589,29 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT
|
|||
* 0x0F00 bottom right
|
||||
* 0xF000 right bottom
|
||||
*/
|
||||
if (para->pFmt->wBorders & 0x00B0)
|
||||
FIXME("Unsupported border flags %x\n", para->pFmt->wBorders);
|
||||
border_width = ME_GetParaBorderWidth(c, para->pFmt->wBorders);
|
||||
if (para->pFmt->wBorders & 4) top_border = border_width;
|
||||
if (para->pFmt->wBorders & 8) bottom_border = border_width;
|
||||
if (para->fmt.wBorders & 0x00B0)
|
||||
FIXME("Unsupported border flags %x\n", para->fmt.wBorders);
|
||||
border_width = ME_GetParaBorderWidth(c, para->fmt.wBorders);
|
||||
if (para->fmt.wBorders & 4) top_border = border_width;
|
||||
if (para->fmt.wBorders & 8) bottom_border = border_width;
|
||||
}
|
||||
|
||||
if (para->pFmt->dwMask & PFM_SPACEBEFORE)
|
||||
if (para->fmt.dwMask & PFM_SPACEBEFORE)
|
||||
{
|
||||
rc.left = c->rcView.left;
|
||||
rc.right = c->rcView.right;
|
||||
rc.top = y;
|
||||
bounds->top = ME_twips2pointsY(c, para->pFmt->dySpaceBefore);
|
||||
bounds->top = ME_twips2pointsY(c, para->fmt.dySpaceBefore);
|
||||
rc.bottom = y + bounds->top + top_border;
|
||||
FillRect(c->hDC, &rc, c->editor->hbrBackground);
|
||||
}
|
||||
|
||||
if (para->pFmt->dwMask & PFM_SPACEAFTER)
|
||||
if (para->fmt.dwMask & PFM_SPACEAFTER)
|
||||
{
|
||||
rc.left = c->rcView.left;
|
||||
rc.right = c->rcView.right;
|
||||
rc.bottom = y + para->nHeight;
|
||||
bounds->bottom = ME_twips2pointsY(c, para->pFmt->dySpaceAfter);
|
||||
bounds->bottom = ME_twips2pointsY(c, para->fmt.dySpaceAfter);
|
||||
rc.top = rc.bottom - bounds->bottom - bottom_border;
|
||||
FillRect(c->hDC, &rc, c->editor->hbrBackground);
|
||||
}
|
||||
|
@ -595,11 +624,11 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT
|
|||
HPEN pen = NULL, oldpen = NULL;
|
||||
POINT pt;
|
||||
|
||||
if (para->pFmt->wBorders & 64) /* autocolor */
|
||||
if (para->fmt.wBorders & 64) /* autocolor */
|
||||
pencr = ITextHost_TxGetSysColor(c->editor->texthost,
|
||||
COLOR_WINDOWTEXT);
|
||||
else
|
||||
pencr = pen_colors[(para->pFmt->wBorders >> 12) & 0xF];
|
||||
pencr = pen_colors[(para->fmt.wBorders >> 12) & 0xF];
|
||||
|
||||
rightEdge = c->pt.x + max(c->editor->sizeWindow.cx,
|
||||
c->editor->nTotalWidth);
|
||||
|
@ -612,9 +641,9 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT
|
|||
/* before & after spaces are not included in border */
|
||||
|
||||
/* helper to draw the double lines in case of corner */
|
||||
#define DD(x) ((para->pFmt->wBorders & (x)) ? (pen_width + 1) : 0)
|
||||
#define DD(x) ((para->fmt.wBorders & (x)) ? (pen_width + 1) : 0)
|
||||
|
||||
if (para->pFmt->wBorders & 1)
|
||||
if (para->fmt.wBorders & 1)
|
||||
{
|
||||
MoveToEx(c->hDC, c->pt.x, y + bounds->top, NULL);
|
||||
LineTo(c->hDC, c->pt.x, y + para->nHeight - bounds->bottom);
|
||||
|
@ -629,7 +658,7 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT
|
|||
}
|
||||
bounds->left += border_width;
|
||||
}
|
||||
if (para->pFmt->wBorders & 2)
|
||||
if (para->fmt.wBorders & 2)
|
||||
{
|
||||
MoveToEx(c->hDC, rightEdge - 1, y + bounds->top, NULL);
|
||||
LineTo(c->hDC, rightEdge - 1, y + para->nHeight - bounds->bottom);
|
||||
|
@ -644,7 +673,7 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT
|
|||
}
|
||||
bounds->right += border_width;
|
||||
}
|
||||
if (para->pFmt->wBorders & 4)
|
||||
if (para->fmt.wBorders & 4)
|
||||
{
|
||||
MoveToEx(c->hDC, c->pt.x, y + bounds->top, NULL);
|
||||
LineTo(c->hDC, rightEdge, y + bounds->top);
|
||||
|
@ -654,7 +683,7 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT
|
|||
}
|
||||
bounds->top += border_width;
|
||||
}
|
||||
if (para->pFmt->wBorders & 8)
|
||||
if (para->fmt.wBorders & 8)
|
||||
{
|
||||
MoveToEx(c->hDC, c->pt.x, y + para->nHeight - bounds->bottom - 1, NULL);
|
||||
LineTo(c->hDC, rightEdge, y + para->nHeight - bounds->bottom - 1);
|
||||
|
@ -812,7 +841,7 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
|
|||
}
|
||||
} else { /* v1.0 - 3.0 */
|
||||
/* Draw simple table border */
|
||||
if (para->pFmt->dwMask & PFM_TABLE && para->pFmt->wEffects & PFE_TABLE) {
|
||||
if (para->fmt.dwMask & PFM_TABLE && para->fmt.wEffects & PFE_TABLE) {
|
||||
HPEN pen = NULL, oldpen = NULL;
|
||||
int i, firstX, startX, endX, rowY, rowBottom, nHeight;
|
||||
POINT oldPt;
|
||||
|
@ -824,21 +853,21 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
|
|||
/* Find the start relative to the text */
|
||||
firstX = c->pt.x + ME_FindItemFwd(paragraph, diRun)->member.run.pt.x;
|
||||
/* Go back by the horizontal gap, which is stored in dxOffset */
|
||||
firstX -= ME_twips2pointsX(c, para->pFmt->dxOffset);
|
||||
firstX -= ME_twips2pointsX(c, para->fmt.dxOffset);
|
||||
/* The left edge, stored in dxStartIndent affected just the first edge */
|
||||
startX = firstX - ME_twips2pointsX(c, para->pFmt->dxStartIndent);
|
||||
startX = firstX - ME_twips2pointsX(c, para->fmt.dxStartIndent);
|
||||
rowY = c->pt.y + para->pt.y;
|
||||
if (para->pFmt->dwMask & PFM_SPACEBEFORE)
|
||||
rowY += ME_twips2pointsY(c, para->pFmt->dySpaceBefore);
|
||||
if (para->fmt.dwMask & PFM_SPACEBEFORE)
|
||||
rowY += ME_twips2pointsY(c, para->fmt.dySpaceBefore);
|
||||
nHeight = ME_FindItemFwd(paragraph, diStartRow)->member.row.nHeight;
|
||||
rowBottom = rowY + nHeight;
|
||||
|
||||
/* Draw horizontal lines */
|
||||
MoveToEx(c->hDC, firstX, rowY, &oldPt);
|
||||
i = para->pFmt->cTabCount - 1;
|
||||
endX = startX + ME_twips2pointsX(c, para->pFmt->rgxTabs[i] & 0x00ffffff) + 1;
|
||||
i = para->fmt.cTabCount - 1;
|
||||
endX = startX + ME_twips2pointsX(c, para->fmt.rgxTabs[i] & 0x00ffffff) + 1;
|
||||
LineTo(c->hDC, endX, rowY);
|
||||
pNextFmt = para->next_para->member.para.pFmt;
|
||||
pNextFmt = ¶->next_para->member.para.fmt;
|
||||
/* The bottom of the row only needs to be drawn if the next row is
|
||||
* not a table. */
|
||||
if (!(pNextFmt && pNextFmt->dwMask & PFM_TABLE && pNextFmt->wEffects &&
|
||||
|
@ -854,9 +883,9 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
|
|||
/* Draw vertical lines */
|
||||
MoveToEx(c->hDC, firstX, rowY, NULL);
|
||||
LineTo(c->hDC, firstX, rowBottom);
|
||||
for (i = 0; i < para->pFmt->cTabCount; i++)
|
||||
for (i = 0; i < para->fmt.cTabCount; i++)
|
||||
{
|
||||
int rightBoundary = para->pFmt->rgxTabs[i] & 0x00ffffff;
|
||||
int rightBoundary = para->fmt.rgxTabs[i] & 0x00ffffff;
|
||||
endX = startX + ME_twips2pointsX(c, rightBoundary);
|
||||
MoveToEx(c->hDC, endX, rowY, NULL);
|
||||
LineTo(c->hDC, endX, rowBottom);
|
||||
|
@ -869,6 +898,28 @@ static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
|
|||
}
|
||||
}
|
||||
|
||||
static void draw_para_number( ME_Context *c, ME_DisplayItem *p )
|
||||
{
|
||||
ME_Paragraph *para = &p->member.para;
|
||||
HFONT old_font;
|
||||
int x, y;
|
||||
COLORREF old_text;
|
||||
|
||||
if (para->fmt.wNumbering)
|
||||
{
|
||||
old_font = ME_SelectStyleFont( c, para->para_num.style );
|
||||
old_text = SetTextColor( c->hDC, get_text_color( c, para->para_num.style, FALSE ) );
|
||||
|
||||
x = c->pt.x + para->para_num.pt.x;
|
||||
y = c->pt.y + para->pt.y + para->para_num.pt.y;
|
||||
|
||||
ExtTextOutW( c->hDC, x, y, 0, NULL, para->para_num.text->szData, para->para_num.text->nLen, NULL );
|
||||
|
||||
SetTextColor( c->hDC, old_text );
|
||||
ME_UnselectStyleFont( c, para->para_num.style, old_font );
|
||||
}
|
||||
}
|
||||
|
||||
static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph)
|
||||
{
|
||||
int align = SetTextAlign(c->hDC, TA_BASELINE);
|
||||
|
@ -994,6 +1045,7 @@ static void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph)
|
|||
}
|
||||
|
||||
ME_DrawTableBorders(c, paragraph);
|
||||
draw_para_number(c, paragraph);
|
||||
|
||||
SetTextAlign(c->hDC, align);
|
||||
}
|
||||
|
|
|
@ -27,8 +27,7 @@ static ME_DisplayItem *make_para(ME_TextEditor *editor)
|
|||
{
|
||||
ME_DisplayItem *item = ME_MakeDI(diParagraph);
|
||||
|
||||
item->member.para.pFmt = ALLOC_OBJ(PARAFORMAT2);
|
||||
ME_SetDefaultParaFormat(editor, item->member.para.pFmt);
|
||||
ME_SetDefaultParaFormat(editor, &item->member.para.fmt);
|
||||
item->member.para.nFlags = MEPF_REWRAP;
|
||||
return item;
|
||||
}
|
||||
|
@ -53,11 +52,12 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
|
|||
GetObjectW(hf, sizeof(LOGFONTW), &lf);
|
||||
ZeroMemory(&cf, sizeof(cf));
|
||||
cf.cbSize = sizeof(cf);
|
||||
cf.dwMask = CFM_BACKCOLOR|CFM_COLOR|CFM_FACE|CFM_SIZE|CFM_CHARSET;
|
||||
cf.dwMask = CFM_ANIMATION|CFM_BACKCOLOR|CFM_CHARSET|CFM_COLOR|CFM_FACE|CFM_KERNING|CFM_LCID|CFM_OFFSET;
|
||||
cf.dwMask |= CFM_REVAUTHOR|CFM_SIZE|CFM_SPACING|CFM_STYLE|CFM_UNDERLINETYPE|CFM_WEIGHT;
|
||||
cf.dwMask |= CFM_ALLCAPS|CFM_BOLD|CFM_DISABLED|CFM_EMBOSS|CFM_HIDDEN;
|
||||
cf.dwMask |= CFM_IMPRINT|CFM_ITALIC|CFM_LINK|CFM_OUTLINE|CFM_PROTECTED;
|
||||
cf.dwMask |= CFM_REVISED|CFM_SHADOW|CFM_SMALLCAPS|CFM_STRIKEOUT;
|
||||
cf.dwMask |= CFM_SUBSCRIPT|CFM_UNDERLINETYPE|CFM_WEIGHT;
|
||||
cf.dwMask |= CFM_SUBSCRIPT|CFM_UNDERLINE;
|
||||
|
||||
cf.dwEffects = CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR;
|
||||
lstrcpyW(cf.szFaceName, lf.lfFaceName);
|
||||
|
@ -66,10 +66,12 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
|
|||
if (lf.lfWeight > FW_NORMAL) cf.dwEffects |= CFE_BOLD;
|
||||
cf.wWeight = lf.lfWeight;
|
||||
if (lf.lfItalic) cf.dwEffects |= CFE_ITALIC;
|
||||
cf.bUnderlineType = (lf.lfUnderline) ? CFU_CF1UNDERLINE : CFU_UNDERLINENONE;
|
||||
if (lf.lfUnderline) cf.dwEffects |= CFE_UNDERLINE;
|
||||
cf.bUnderlineType = CFU_UNDERLINE;
|
||||
if (lf.lfStrikeOut) cf.dwEffects |= CFE_STRIKEOUT;
|
||||
cf.bPitchAndFamily = lf.lfPitchAndFamily;
|
||||
cf.bCharSet = lf.lfCharSet;
|
||||
cf.lcid = GetSystemDefaultLCID();
|
||||
|
||||
style = ME_MakeStyle(&cf);
|
||||
text->pDefaultStyle = style;
|
||||
|
@ -82,6 +84,8 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
|
|||
run->member.run.len = eol_len;
|
||||
run->member.run.para = ¶->member.para;
|
||||
|
||||
para->member.para.eop_run = &run->member.run;
|
||||
|
||||
ME_InsertBefore(text->pLast, para);
|
||||
ME_InsertBefore(text->pLast, run);
|
||||
para->member.para.prev_para = text->pFirst;
|
||||
|
@ -110,29 +114,234 @@ void ME_MarkAllForWrapping(ME_TextEditor *editor)
|
|||
|
||||
static void ME_UpdateTableFlags(ME_DisplayItem *para)
|
||||
{
|
||||
para->member.para.pFmt->dwMask |= PFM_TABLE|PFM_TABLEROWDELIMITER;
|
||||
para->member.para.fmt.dwMask |= PFM_TABLE|PFM_TABLEROWDELIMITER;
|
||||
if (para->member.para.pCell) {
|
||||
para->member.para.nFlags |= MEPF_CELL;
|
||||
} else {
|
||||
para->member.para.nFlags &= ~MEPF_CELL;
|
||||
}
|
||||
if (para->member.para.nFlags & MEPF_ROWEND) {
|
||||
para->member.para.pFmt->wEffects |= PFE_TABLEROWDELIMITER;
|
||||
para->member.para.fmt.wEffects |= PFE_TABLEROWDELIMITER;
|
||||
} else {
|
||||
para->member.para.pFmt->wEffects &= ~PFE_TABLEROWDELIMITER;
|
||||
para->member.para.fmt.wEffects &= ~PFE_TABLEROWDELIMITER;
|
||||
}
|
||||
if (para->member.para.nFlags & (MEPF_ROWSTART|MEPF_CELL|MEPF_ROWEND))
|
||||
para->member.para.pFmt->wEffects |= PFE_TABLE;
|
||||
para->member.para.fmt.wEffects |= PFE_TABLE;
|
||||
else
|
||||
para->member.para.pFmt->wEffects &= ~PFE_TABLE;
|
||||
para->member.para.fmt.wEffects &= ~PFE_TABLE;
|
||||
}
|
||||
|
||||
static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, const PARAFORMAT2 *pFmt)
|
||||
static inline BOOL para_num_same_list( const PARAFORMAT2 *item, const PARAFORMAT2 *base )
|
||||
{
|
||||
return item->wNumbering == base->wNumbering &&
|
||||
item->wNumberingStart == base->wNumberingStart &&
|
||||
item->wNumberingStyle == base->wNumberingStyle &&
|
||||
!(item->wNumberingStyle & PFNS_NEWNUMBER);
|
||||
}
|
||||
|
||||
static int para_num_get_num( ME_Paragraph *para )
|
||||
{
|
||||
ME_DisplayItem *prev;
|
||||
int num = para->fmt.wNumberingStart;
|
||||
|
||||
for (prev = para->prev_para; prev->type == diParagraph;
|
||||
para = &prev->member.para, prev = prev->member.para.prev_para, num++)
|
||||
{
|
||||
if (!para_num_same_list( &prev->member.para.fmt, ¶->fmt )) break;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
static ME_String *para_num_get_str( ME_Paragraph *para, WORD num )
|
||||
{
|
||||
/* max 4 Roman letters (representing '8') / decade + '(' + ')' */
|
||||
ME_String *str = ME_MakeStringEmpty( 20 + 2 );
|
||||
WCHAR *p;
|
||||
static const WCHAR fmtW[] = {'%', 'd', 0};
|
||||
static const WORD letter_base[] = { 1, 26, 26 * 26, 26 * 26 * 26 };
|
||||
/* roman_base should start on a '5' not a '1', otherwise the 'total' code will need adjusting.
|
||||
'N' and 'O' are what MS uses for 5000 and 10000, their version doesn't work well above 30000,
|
||||
but we'll use 'P' as the obvious extension, this gets us up to 2^16, which is all we care about. */
|
||||
static const struct
|
||||
{
|
||||
int base;
|
||||
char letter;
|
||||
}
|
||||
roman_base[] =
|
||||
{
|
||||
{50000, 'P'}, {10000, 'O'}, {5000, 'N'}, {1000, 'M'},
|
||||
{500, 'D'}, {100, 'C'}, {50, 'L'}, {10, 'X'}, {5, 'V'}, {1, 'I'}
|
||||
};
|
||||
int i, len;
|
||||
WORD letter, total, char_offset = 0;
|
||||
|
||||
if (!str) return NULL;
|
||||
|
||||
p = str->szData;
|
||||
|
||||
if ((para->fmt.wNumberingStyle & 0xf00) == PFNS_PARENS)
|
||||
*p++ = '(';
|
||||
|
||||
switch (para->fmt.wNumbering)
|
||||
{
|
||||
case PFN_ARABIC:
|
||||
default:
|
||||
p += sprintfW( p, fmtW, num );
|
||||
break;
|
||||
|
||||
case PFN_LCLETTER:
|
||||
char_offset = 'a' - 'A';
|
||||
/* fall through */
|
||||
case PFN_UCLETTER:
|
||||
if (!num) num = 1;
|
||||
|
||||
/* This is not base-26 (or 27) as zeros don't count unless they are leading zeros.
|
||||
It's simplest to start with the least significant letter, so first calculate how many letters are needed. */
|
||||
for (i = 0, total = 0; i < sizeof(letter_base) / sizeof(letter_base[0]); i++)
|
||||
{
|
||||
total += letter_base[i];
|
||||
if (num < total) break;
|
||||
}
|
||||
len = i;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
num -= letter_base[i];
|
||||
letter = (num / letter_base[i]) % 26;
|
||||
p[len - i - 1] = letter + 'A' + char_offset;
|
||||
}
|
||||
p += len;
|
||||
*p = 0;
|
||||
break;
|
||||
|
||||
case PFN_LCROMAN:
|
||||
char_offset = 'a' - 'A';
|
||||
/* fall through */
|
||||
case PFN_UCROMAN:
|
||||
if (!num) num = 1;
|
||||
|
||||
for (i = 0; i < sizeof(roman_base) / sizeof(roman_base[0]); i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
if (i % 2 == 0) /* eg 5000, check for 9000 */
|
||||
total = roman_base[i].base + 4 * roman_base[i + 1].base;
|
||||
else /* eg 1000, check for 4000 */
|
||||
total = 4 * roman_base[i].base;
|
||||
|
||||
if (num / total)
|
||||
{
|
||||
*p++ = roman_base[(i & ~1) + 1].letter + char_offset;
|
||||
*p++ = roman_base[i - 1].letter + char_offset;
|
||||
num -= total;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
len = num / roman_base[i].base;
|
||||
while (len--)
|
||||
{
|
||||
*p++ = roman_base[i].letter + char_offset;
|
||||
num -= roman_base[i].base;
|
||||
}
|
||||
}
|
||||
*p = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (para->fmt.wNumberingStyle & 0xf00)
|
||||
{
|
||||
case PFNS_PARENS:
|
||||
case PFNS_PAREN:
|
||||
*p++ = ')';
|
||||
*p = 0;
|
||||
break;
|
||||
|
||||
case PFNS_PERIOD:
|
||||
*p++ = '.';
|
||||
*p = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
str->nLen = p - str->szData;
|
||||
return str;
|
||||
}
|
||||
|
||||
void para_num_init( ME_Context *c, ME_Paragraph *para )
|
||||
{
|
||||
ME_Style *style;
|
||||
CHARFORMAT2W cf;
|
||||
static const WCHAR bullet_font[] = {'S','y','m','b','o','l',0};
|
||||
static const WCHAR bullet_str[] = {0xb7, 0};
|
||||
static const WCHAR spaceW[] = {' ', 0};
|
||||
HFONT old_font;
|
||||
SIZE sz;
|
||||
|
||||
if (para->para_num.style && para->para_num.text) return;
|
||||
|
||||
if (!para->para_num.style)
|
||||
{
|
||||
style = para->eop_run->style;
|
||||
|
||||
if (para->fmt.wNumbering == PFN_BULLET)
|
||||
{
|
||||
cf.cbSize = sizeof(cf);
|
||||
cf.dwMask = CFM_FACE | CFM_CHARSET;
|
||||
memcpy( cf.szFaceName, bullet_font, sizeof(bullet_font) );
|
||||
cf.bCharSet = SYMBOL_CHARSET;
|
||||
style = ME_ApplyStyle( c->editor, style, &cf );
|
||||
}
|
||||
else
|
||||
{
|
||||
ME_AddRefStyle( style );
|
||||
}
|
||||
|
||||
para->para_num.style = style;
|
||||
}
|
||||
|
||||
if (!para->para_num.text)
|
||||
{
|
||||
if (para->fmt.wNumbering != PFN_BULLET)
|
||||
para->para_num.text = para_num_get_str( para, para_num_get_num( para ) );
|
||||
else
|
||||
para->para_num.text = ME_MakeStringConst( bullet_str, 1 );
|
||||
}
|
||||
|
||||
old_font = ME_SelectStyleFont( c, para->para_num.style );
|
||||
GetTextExtentPointW( c->hDC, para->para_num.text->szData, para->para_num.text->nLen, &sz );
|
||||
para->para_num.width = sz.cx;
|
||||
GetTextExtentPointW( c->hDC, spaceW, 1, &sz );
|
||||
para->para_num.width += sz.cx;
|
||||
ME_UnselectStyleFont( c, para->para_num.style, old_font );
|
||||
}
|
||||
|
||||
void para_num_clear( struct para_num *pn )
|
||||
{
|
||||
if (pn->style)
|
||||
{
|
||||
ME_ReleaseStyle( pn->style );
|
||||
pn->style = NULL;
|
||||
}
|
||||
ME_DestroyString( pn->text );
|
||||
pn->text = NULL;
|
||||
}
|
||||
|
||||
static void para_num_clear_list( ME_Paragraph *para, const PARAFORMAT2 *orig_fmt )
|
||||
{
|
||||
do
|
||||
{
|
||||
para->nFlags |= MEPF_REWRAP;
|
||||
para_num_clear( ¶->para_num );
|
||||
if (para->next_para->type != diParagraph) break;
|
||||
para = ¶->next_para->member.para;
|
||||
} while (para_num_same_list( ¶->fmt, orig_fmt ));
|
||||
}
|
||||
|
||||
static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_Paragraph *para, const PARAFORMAT2 *pFmt)
|
||||
{
|
||||
PARAFORMAT2 copy;
|
||||
DWORD dwMask;
|
||||
|
||||
assert(para->member.para.pFmt->cbSize == sizeof(PARAFORMAT2));
|
||||
assert(para->fmt.cbSize == sizeof(PARAFORMAT2));
|
||||
dwMask = pFmt->dwMask;
|
||||
if (pFmt->cbSize < sizeof(PARAFORMAT))
|
||||
return FALSE;
|
||||
|
@ -141,27 +350,27 @@ static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, const
|
|||
else
|
||||
dwMask &= PFM_ALL2;
|
||||
|
||||
add_undo_set_para_fmt( editor, ¶->member.para );
|
||||
add_undo_set_para_fmt( editor, para );
|
||||
|
||||
copy = *para->member.para.pFmt;
|
||||
copy = para->fmt;
|
||||
|
||||
#define COPY_FIELD(m, f) \
|
||||
if (dwMask & (m)) { \
|
||||
para->member.para.pFmt->dwMask |= m; \
|
||||
para->member.para.pFmt->f = pFmt->f; \
|
||||
para->fmt.dwMask |= m; \
|
||||
para->fmt.f = pFmt->f; \
|
||||
}
|
||||
|
||||
COPY_FIELD(PFM_NUMBERING, wNumbering);
|
||||
COPY_FIELD(PFM_STARTINDENT, dxStartIndent);
|
||||
if (dwMask & PFM_OFFSETINDENT)
|
||||
para->member.para.pFmt->dxStartIndent += pFmt->dxStartIndent;
|
||||
para->fmt.dxStartIndent += pFmt->dxStartIndent;
|
||||
COPY_FIELD(PFM_RIGHTINDENT, dxRightIndent);
|
||||
COPY_FIELD(PFM_OFFSET, dxOffset);
|
||||
COPY_FIELD(PFM_ALIGNMENT, wAlignment);
|
||||
if (dwMask & PFM_TABSTOPS)
|
||||
{
|
||||
para->member.para.pFmt->cTabCount = pFmt->cTabCount;
|
||||
memcpy(para->member.para.pFmt->rgxTabs, pFmt->rgxTabs, pFmt->cTabCount*sizeof(LONG));
|
||||
para->fmt.cTabCount = pFmt->cTabCount;
|
||||
memcpy(para->fmt.rgxTabs, pFmt->rgxTabs, pFmt->cTabCount*sizeof(LONG));
|
||||
}
|
||||
|
||||
#define EFFECTS_MASK (PFM_RTLPARA|PFM_KEEP|PFM_KEEPNEXT|PFM_PAGEBREAKBEFORE| \
|
||||
|
@ -170,9 +379,9 @@ static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, const
|
|||
/* we take for granted that PFE_xxx is the hiword of the corresponding PFM_xxx */
|
||||
if (dwMask & EFFECTS_MASK)
|
||||
{
|
||||
para->member.para.pFmt->dwMask |= dwMask & EFFECTS_MASK;
|
||||
para->member.para.pFmt->wEffects &= ~HIWORD(dwMask);
|
||||
para->member.para.pFmt->wEffects |= pFmt->wEffects & HIWORD(dwMask);
|
||||
para->fmt.dwMask |= dwMask & EFFECTS_MASK;
|
||||
para->fmt.wEffects &= ~HIWORD(dwMask);
|
||||
para->fmt.wEffects |= pFmt->wEffects & HIWORD(dwMask);
|
||||
}
|
||||
#undef EFFECTS_MASK
|
||||
|
||||
|
@ -190,11 +399,19 @@ static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, const
|
|||
COPY_FIELD(PFM_BORDER, wBorderWidth);
|
||||
COPY_FIELD(PFM_BORDER, wBorders);
|
||||
|
||||
para->member.para.pFmt->dwMask |= dwMask;
|
||||
para->fmt.dwMask |= dwMask;
|
||||
#undef COPY_FIELD
|
||||
|
||||
if (memcmp(©, para->member.para.pFmt, sizeof(PARAFORMAT2)))
|
||||
para->member.para.nFlags |= MEPF_REWRAP;
|
||||
if (memcmp(©, ¶->fmt, sizeof(PARAFORMAT2)))
|
||||
{
|
||||
para->nFlags |= MEPF_REWRAP;
|
||||
if (((dwMask & PFM_NUMBERING) && (copy.wNumbering != para->fmt.wNumbering)) ||
|
||||
((dwMask & PFM_NUMBERINGSTART) && (copy.wNumberingStart != para->fmt.wNumberingStart)) ||
|
||||
((dwMask & PFM_NUMBERINGSTYLE) && (copy.wNumberingStyle != para->fmt.wNumberingStyle)))
|
||||
{
|
||||
para_num_clear_list( para, © );
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -225,7 +442,11 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
|
|||
}
|
||||
assert(run->type == diRun);
|
||||
run_para = ME_GetParagraph(run);
|
||||
assert(run_para->member.para.pFmt->cbSize == sizeof(PARAFORMAT2));
|
||||
assert(run_para->member.para.fmt.cbSize == sizeof(PARAFORMAT2));
|
||||
|
||||
/* Clear any cached para numbering following this paragraph */
|
||||
if (run_para->member.para.fmt.wNumbering)
|
||||
para_num_clear_list( &run_para->member.para, &run_para->member.para.fmt );
|
||||
|
||||
new_para->member.para.text = ME_VSplitString( run_para->member.para.text, run->member.run.nCharOfs );
|
||||
|
||||
|
@ -260,7 +481,7 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
|
|||
new_para->member.para.nFlags = MEPF_REWRAP;
|
||||
|
||||
/* FIXME initialize format style and call ME_SetParaFormat blah blah */
|
||||
*new_para->member.para.pFmt = *run_para->member.para.pFmt;
|
||||
new_para->member.para.fmt = run_para->member.para.fmt;
|
||||
new_para->member.para.border = run_para->member.para.border;
|
||||
|
||||
/* insert paragraph into paragraph double linked list */
|
||||
|
@ -273,6 +494,10 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
|
|||
ME_InsertBefore(run, new_para);
|
||||
ME_InsertBefore(new_para, end_run);
|
||||
|
||||
/* Fix up the paras' eop_run ptrs */
|
||||
new_para->member.para.eop_run = run_para->member.para.eop_run;
|
||||
run_para->member.para.eop_run = &end_run->member.run;
|
||||
|
||||
if (!editor->bEmulateVersion10) { /* v4.1 */
|
||||
if (paraFlags & (MEPF_ROWSTART|MEPF_CELL))
|
||||
{
|
||||
|
@ -345,6 +570,10 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
|
|||
assert(tp->member.para.next_para);
|
||||
assert(tp->member.para.next_para->type == diParagraph);
|
||||
|
||||
/* Clear any cached para numbering following this paragraph */
|
||||
if (tp->member.para.fmt.wNumbering)
|
||||
para_num_clear_list( &tp->member.para, &tp->member.para.fmt );
|
||||
|
||||
pNext = tp->member.para.next_para;
|
||||
|
||||
/* Need to locate end-of-paragraph run here, in order to know end_len */
|
||||
|
@ -399,7 +628,7 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
|
|||
if (!keepFirstParaFormat)
|
||||
{
|
||||
add_undo_set_para_fmt( editor, &tp->member.para );
|
||||
*tp->member.para.pFmt = *pNext->member.para.pFmt;
|
||||
tp->member.para.fmt = pNext->member.para.fmt;
|
||||
tp->member.para.border = pNext->member.para.border;
|
||||
}
|
||||
|
||||
|
@ -430,6 +659,9 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
|
|||
pTmp->member.run.para = &tp->member.para;
|
||||
} while(1);
|
||||
|
||||
/* Fix up the para's eop_run ptr */
|
||||
tp->member.para.eop_run = pNext->member.para.eop_run;
|
||||
|
||||
ME_Remove(pRun);
|
||||
ME_DestroyDisplayItem(pRun);
|
||||
|
||||
|
@ -551,7 +783,7 @@ BOOL ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt)
|
|||
ME_GetSelectionParas(editor, ¶, ¶_end);
|
||||
|
||||
do {
|
||||
ME_SetParaFormat(editor, para, pFmt);
|
||||
ME_SetParaFormat(editor, ¶->member.para, pFmt);
|
||||
if (para == para_end)
|
||||
break;
|
||||
para = para->member.para.next_para;
|
||||
|
@ -566,9 +798,9 @@ static void ME_GetParaFormat(ME_TextEditor *editor,
|
|||
{
|
||||
UINT cbSize = pFmt->cbSize;
|
||||
if (pFmt->cbSize >= sizeof(PARAFORMAT2)) {
|
||||
*pFmt = *para->member.para.pFmt;
|
||||
*pFmt = para->member.para.fmt;
|
||||
} else {
|
||||
CopyMemory(pFmt, para->member.para.pFmt, pFmt->cbSize);
|
||||
CopyMemory(pFmt, ¶->member.para.fmt, pFmt->cbSize);
|
||||
pFmt->dwMask &= PFM_ALL;
|
||||
}
|
||||
pFmt->cbSize = cbSize;
|
||||
|
@ -592,7 +824,7 @@ void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt)
|
|||
while (para != para_end)
|
||||
{
|
||||
para = para->member.para.next_para;
|
||||
curFmt = para->member.para.pFmt;
|
||||
curFmt = ¶->member.para.fmt;
|
||||
|
||||
#define CHECK_FIELD(m, f) \
|
||||
if (pFmt->f != curFmt->f) pFmt->dwMask &= ~(m);
|
||||
|
@ -603,7 +835,7 @@ void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt)
|
|||
CHECK_FIELD(PFM_OFFSET, dxOffset);
|
||||
CHECK_FIELD(PFM_ALIGNMENT, wAlignment);
|
||||
if (pFmt->dwMask & PFM_TABSTOPS) {
|
||||
if (pFmt->cTabCount != para->member.para.pFmt->cTabCount ||
|
||||
if (pFmt->cTabCount != para->member.para.fmt.cTabCount ||
|
||||
memcmp(pFmt->rgxTabs, curFmt->rgxTabs, curFmt->cTabCount*sizeof(int)))
|
||||
pFmt->dwMask &= ~PFM_TABSTOPS;
|
||||
}
|
||||
|
|
|
@ -1763,8 +1763,8 @@ static RTFKey rtfKey[] =
|
|||
{ rtfDestination, rtfFooterFirst, "footerf", 0 },
|
||||
{ rtfDestination, rtfParNumText, "pntext", 0 },
|
||||
{ rtfDestination, rtfParNumbering, "pn", 0 },
|
||||
{ rtfDestination, rtfParNumTextAfter, "pntexta", 0 },
|
||||
{ rtfDestination, rtfParNumTextBefore, "pntextb", 0 },
|
||||
{ rtfDestination, rtfParNumTextAfter, "pntxta", 0 },
|
||||
{ rtfDestination, rtfParNumTextBefore, "pntxtb", 0 },
|
||||
{ rtfDestination, rtfBookmarkStart, "bkmkstart", 0 },
|
||||
{ rtfDestination, rtfBookmarkEnd, "bkmkend", 0 },
|
||||
{ rtfDestination, rtfPict, "pict", 0 },
|
||||
|
|
|
@ -437,7 +437,7 @@ static HRESULT get_textfont_prop_for_pos(const IRichEditOleImpl *reole, int pos,
|
|||
|
||||
ME_CursorFromCharOfs(reole->editor, pos, &from);
|
||||
to = from;
|
||||
ME_MoveCursorChars(reole->editor, &to, 1);
|
||||
ME_MoveCursorChars(reole->editor, &to, 1, FALSE);
|
||||
ME_GetCharFormat(reole->editor, &from, &to, &fmt);
|
||||
|
||||
switch (propid)
|
||||
|
|
|
@ -616,17 +616,16 @@ SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run *run, i
|
|||
int startx, int *pAscent, int *pDescent)
|
||||
{
|
||||
SIZE size;
|
||||
int nMaxLen = run->len;
|
||||
WCHAR spaceW[] = {' ',0};
|
||||
|
||||
if (nLen>nMaxLen)
|
||||
nLen = nMaxLen;
|
||||
nLen = min( nLen, run->len );
|
||||
|
||||
/* FIXME the following call also ensures that TEXTMETRIC structure is filled
|
||||
* this is wasteful for MERF_NONTEXT runs, but that shouldn't matter
|
||||
* in practice
|
||||
*/
|
||||
|
||||
if (para->nFlags & MEPF_COMPLEX)
|
||||
if (run->nFlags & MERF_ENDPARA)
|
||||
{
|
||||
nLen = min( nLen, 1 );
|
||||
ME_GetTextExtent(c, spaceW, nLen, run->style, &size);
|
||||
}
|
||||
else if (para->nFlags & MEPF_COMPLEX)
|
||||
{
|
||||
size.cx = run->nWidth;
|
||||
}
|
||||
|
@ -647,7 +646,7 @@ SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run *run, i
|
|||
if (run->nFlags & MERF_TAB)
|
||||
{
|
||||
int pos = 0, i = 0, ppos, shift = 0;
|
||||
PARAFORMAT2 *pFmt = para->pFmt;
|
||||
const PARAFORMAT2 *pFmt = ¶->fmt;
|
||||
|
||||
if (c->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
|
||||
pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE)
|
||||
|
@ -759,28 +758,26 @@ void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, C
|
|||
for (run = start_run; run != end_run; run = ME_FindItemFwd( run, diRun ))
|
||||
{
|
||||
ME_Style *new_style = ME_ApplyStyle(editor, run->member.run.style, pFmt);
|
||||
ME_Paragraph *para = run->member.run.para;
|
||||
|
||||
add_undo_set_char_fmt( editor, run->member.run.para->nCharOfs + run->member.run.nCharOfs,
|
||||
run->member.run.len, &run->member.run.style->fmt );
|
||||
ME_ReleaseStyle(run->member.run.style);
|
||||
run->member.run.style = new_style;
|
||||
run->member.run.para->nFlags |= MEPF_REWRAP;
|
||||
|
||||
/* The para numbering style depends on the eop style */
|
||||
if ((run->member.run.nFlags & MERF_ENDPARA) && para->para_num.style)
|
||||
{
|
||||
ME_ReleaseStyle(para->para_num.style);
|
||||
para->para_num.style = NULL;
|
||||
}
|
||||
para->nFlags |= MEPF_REWRAP;
|
||||
}
|
||||
}
|
||||
|
||||
static void ME_GetRunCharFormat(ME_TextEditor *editor, ME_DisplayItem *run, CHARFORMAT2W *pFmt)
|
||||
{
|
||||
ME_CopyCharFormat(pFmt, &run->member.run.style->fmt);
|
||||
if ((pFmt->dwMask & CFM_UNDERLINETYPE) && (pFmt->bUnderlineType == CFU_CF1UNDERLINE))
|
||||
{
|
||||
pFmt->dwMask |= CFM_UNDERLINE;
|
||||
pFmt->dwEffects |= CFE_UNDERLINE;
|
||||
}
|
||||
if ((pFmt->dwMask & CFM_UNDERLINETYPE) && (pFmt->bUnderlineType == CFU_UNDERLINENONE))
|
||||
{
|
||||
pFmt->dwMask |= CFM_UNDERLINE;
|
||||
pFmt->dwEffects &= ~CFE_UNDERLINE;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
|
|
@ -24,27 +24,59 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
|||
|
||||
static int ME_GetOptimalBuffer(int nLen)
|
||||
{
|
||||
/* FIXME: This seems wasteful for tabs and end of lines strings,
|
||||
* since they have a small fixed length. */
|
||||
return ((sizeof(WCHAR) * nLen) + 128) & ~63;
|
||||
}
|
||||
|
||||
/* Create a buffer (uninitialized string) of size nMaxChars */
|
||||
static ME_String *ME_MakeStringB(int nMaxChars)
|
||||
static ME_String *make_string( void (*free)(ME_String *) )
|
||||
{
|
||||
ME_String *s = ALLOC_OBJ(ME_String);
|
||||
ME_String *s = heap_alloc( sizeof(*s) );
|
||||
|
||||
if (s) s->free = free;
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Create a ME_String using the const string provided.
|
||||
* str must exist for the lifetime of the returned ME_String.
|
||||
*/
|
||||
ME_String *ME_MakeStringConst(const WCHAR *str, int len)
|
||||
{
|
||||
ME_String *s = make_string( NULL );
|
||||
if (!s) return NULL;
|
||||
|
||||
s->szData = (WCHAR *)str;
|
||||
s->nLen = len;
|
||||
s->nBuffer = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
static void heap_string_free(ME_String *s)
|
||||
{
|
||||
heap_free( s->szData );
|
||||
}
|
||||
|
||||
/* Create a buffer (uninitialized string) of size nMaxChars */
|
||||
ME_String *ME_MakeStringEmpty(int nMaxChars)
|
||||
{
|
||||
ME_String *s = make_string( heap_string_free );
|
||||
|
||||
if (!s) return NULL;
|
||||
s->nLen = nMaxChars;
|
||||
s->nBuffer = ME_GetOptimalBuffer(s->nLen + 1);
|
||||
s->szData = ALLOC_N_OBJ(WCHAR, s->nBuffer);
|
||||
s->szData = heap_alloc( s->nBuffer * sizeof(WCHAR) );
|
||||
if (!s->szData)
|
||||
{
|
||||
heap_free( s );
|
||||
return NULL;
|
||||
}
|
||||
s->szData[s->nLen] = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars)
|
||||
{
|
||||
ME_String *s = ME_MakeStringB(nMaxChars);
|
||||
/* Native allows NULL chars */
|
||||
ME_String *s = ME_MakeStringEmpty(nMaxChars);
|
||||
|
||||
if (!s) return NULL;
|
||||
memcpy(s->szData, szText, s->nLen * sizeof(WCHAR));
|
||||
return s;
|
||||
}
|
||||
|
@ -53,7 +85,9 @@ ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars)
|
|||
ME_String *ME_MakeStringR(WCHAR cRepeat, int nMaxChars)
|
||||
{
|
||||
int i;
|
||||
ME_String *s = ME_MakeStringB(nMaxChars);
|
||||
ME_String *s = ME_MakeStringEmpty(nMaxChars);
|
||||
|
||||
if (!s) return NULL;
|
||||
for (i = 0; i < nMaxChars; i++)
|
||||
s->szData[i] = cRepeat;
|
||||
return s;
|
||||
|
@ -62,20 +96,24 @@ ME_String *ME_MakeStringR(WCHAR cRepeat, int nMaxChars)
|
|||
void ME_DestroyString(ME_String *s)
|
||||
{
|
||||
if (!s) return;
|
||||
FREE_OBJ(s->szData);
|
||||
FREE_OBJ(s);
|
||||
if (s->free) s->free( s );
|
||||
heap_free( s );
|
||||
}
|
||||
|
||||
BOOL ME_InsertString(ME_String *s, int ofs, const WCHAR *insert, int len)
|
||||
{
|
||||
DWORD new_len = s->nLen + len + 1;
|
||||
WCHAR *new;
|
||||
|
||||
assert( s->nBuffer ); /* Not a const string */
|
||||
assert( ofs <= s->nLen );
|
||||
|
||||
if( new_len > s->nBuffer )
|
||||
{
|
||||
s->nBuffer = ME_GetOptimalBuffer( new_len );
|
||||
s->szData = heap_realloc( s->szData, s->nBuffer * sizeof(WCHAR) );
|
||||
if (!s->szData) return FALSE;
|
||||
new = heap_realloc( s->szData, s->nBuffer * sizeof(WCHAR) );
|
||||
if (!new) return FALSE;
|
||||
s->szData = new;
|
||||
}
|
||||
|
||||
memmove( s->szData + ofs + len, s->szData + ofs, (s->nLen - ofs + 1) * sizeof(WCHAR) );
|
||||
|
@ -94,13 +132,13 @@ ME_String *ME_VSplitString(ME_String *orig, int charidx)
|
|||
{
|
||||
ME_String *s;
|
||||
|
||||
/*if (charidx<0) charidx = 0;
|
||||
if (charidx>orig->nLen) charidx = orig->nLen;
|
||||
*/
|
||||
assert(orig->nBuffer); /* Not a const string */
|
||||
assert(charidx>=0);
|
||||
assert(charidx<=orig->nLen);
|
||||
|
||||
s = ME_MakeStringN(orig->szData+charidx, orig->nLen-charidx);
|
||||
if (!s) return NULL;
|
||||
|
||||
orig->nLen = charidx;
|
||||
orig->szData[charidx] = '\0';
|
||||
return s;
|
||||
|
@ -110,6 +148,7 @@ void ME_StrDeleteV(ME_String *s, int nVChar, int nChars)
|
|||
{
|
||||
int end_ofs = nVChar + nChars;
|
||||
|
||||
assert(s->nBuffer); /* Not a const string */
|
||||
assert(nChars >= 0);
|
||||
assert(nVChar >= 0);
|
||||
assert(end_ofs <= s->nLen);
|
||||
|
@ -163,6 +202,7 @@ ME_CallWordBreakProc(ME_TextEditor *editor, WCHAR *str, INT len, INT start, INT
|
|||
int buffer_size = WideCharToMultiByte(CP_ACP, 0, str, len,
|
||||
NULL, 0, NULL, NULL);
|
||||
char *buffer = heap_alloc(buffer_size);
|
||||
if (!buffer) return 0;
|
||||
WideCharToMultiByte(CP_ACP, 0, str, len,
|
||||
buffer, buffer_size, NULL, NULL);
|
||||
result = editor->pfnWordBreak((WCHAR*)buffer, start, buffer_size, code);
|
||||
|
@ -187,7 +227,7 @@ LPWSTR ME_ToUnicode(LONG codepage, LPVOID psz, INT *len)
|
|||
|
||||
if(!nChars) return NULL;
|
||||
|
||||
if((tmp = ALLOC_N_OBJ(WCHAR, nChars)) != NULL)
|
||||
if((tmp = heap_alloc( nChars * sizeof(WCHAR) )) != NULL)
|
||||
*len = MultiByteToWideChar(codepage, 0, psz, -1, tmp, nChars) - 1;
|
||||
return tmp;
|
||||
}
|
||||
|
@ -196,5 +236,5 @@ LPWSTR ME_ToUnicode(LONG codepage, LPVOID psz, INT *len)
|
|||
void ME_EndToUnicode(LONG codepage, LPVOID psz)
|
||||
{
|
||||
if (codepage != CP_UNICODE)
|
||||
FREE_OBJ(psz);
|
||||
heap_free( psz );
|
||||
}
|
||||
|
|
|
@ -79,20 +79,6 @@ static CHARFORMAT2W *ME_ToCFAny(CHARFORMAT2W *to, CHARFORMAT2W *from)
|
|||
CHARFORMATA *t = (CHARFORMATA *)to;
|
||||
CopyMemory(t, from, FIELD_OFFSET(CHARFORMATA, szFaceName));
|
||||
WideCharToMultiByte(CP_ACP, 0, from->szFaceName, -1, t->szFaceName, sizeof(t->szFaceName), NULL, NULL);
|
||||
if (from->dwMask & CFM_UNDERLINETYPE)
|
||||
{
|
||||
switch (from->bUnderlineType)
|
||||
{
|
||||
case CFU_CF1UNDERLINE:
|
||||
to->dwMask |= CFM_UNDERLINE;
|
||||
to->dwEffects |= CFE_UNDERLINE;
|
||||
break;
|
||||
case CFU_UNDERLINENONE:
|
||||
to->dwMask |= CFM_UNDERLINE;
|
||||
to->dwEffects &= ~CFE_UNDERLINE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
t->cbSize = sizeof(*t); /* it was overwritten by CopyMemory */
|
||||
return to;
|
||||
}
|
||||
|
@ -100,20 +86,6 @@ static CHARFORMAT2W *ME_ToCFAny(CHARFORMAT2W *to, CHARFORMAT2W *from)
|
|||
{
|
||||
CHARFORMATW *t = (CHARFORMATW *)to;
|
||||
CopyMemory(t, from, sizeof(*t));
|
||||
if (from->dwMask & CFM_UNDERLINETYPE)
|
||||
{
|
||||
switch (from->bUnderlineType)
|
||||
{
|
||||
case CFU_CF1UNDERLINE:
|
||||
to->dwMask |= CFM_UNDERLINE;
|
||||
to->dwEffects |= CFE_UNDERLINE;
|
||||
break;
|
||||
case CFU_UNDERLINENONE:
|
||||
to->dwMask |= CFM_UNDERLINE;
|
||||
to->dwEffects &= ~CFE_UNDERLINE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
t->cbSize = sizeof(*t); /* it was overwritten by CopyMemory */
|
||||
return to;
|
||||
}
|
||||
|
@ -195,7 +167,6 @@ ME_Style *ME_ApplyStyle(ME_TextEditor *editor, ME_Style *sSrc, CHARFORMAT2W *mod
|
|||
}
|
||||
COPY_STYLE_ITEM(CFM_SPACING, sSpacing);
|
||||
COPY_STYLE_ITEM(CFM_STYLE, sStyle);
|
||||
COPY_STYLE_ITEM(CFM_UNDERLINETYPE, bUnderlineType);
|
||||
COPY_STYLE_ITEM(CFM_WEIGHT, wWeight);
|
||||
/* FIXME: this is not documented this way, but that's the more logical */
|
||||
COPY_STYLE_ITEM(CFM_FACE, bPitchAndFamily);
|
||||
|
@ -210,12 +181,18 @@ ME_Style *ME_ApplyStyle(ME_TextEditor *editor, ME_Style *sSrc, CHARFORMAT2W *mod
|
|||
else
|
||||
fmt.dwEffects &= ~CFE_AUTOCOLOR;
|
||||
}
|
||||
if (mod->dwMask & CFM_UNDERLINE)
|
||||
|
||||
COPY_STYLE_ITEM(CFM_UNDERLINETYPE, bUnderlineType);
|
||||
/* If the CFM_UNDERLINE effect is not specified set it appropiately */
|
||||
if ((mod->dwMask & CFM_UNDERLINETYPE) && !(mod->dwMask & CFM_UNDERLINE))
|
||||
{
|
||||
fmt.dwMask |= CFM_UNDERLINETYPE;
|
||||
fmt.bUnderlineType = (mod->dwEffects & CFM_UNDERLINE) ?
|
||||
CFU_CF1UNDERLINE : CFU_UNDERLINENONE;
|
||||
fmt.dwMask |= CFM_UNDERLINE;
|
||||
if (mod->bUnderlineType == CFU_UNDERLINENONE)
|
||||
fmt.dwEffects &= ~CFE_UNDERLINE;
|
||||
else
|
||||
fmt.dwEffects |= CFE_UNDERLINE;
|
||||
}
|
||||
|
||||
if (mod->dwMask & CFM_BOLD && !(mod->dwMask & CFM_WEIGHT))
|
||||
{
|
||||
fmt.wWeight = (mod->dwEffects & CFE_BOLD) ? FW_BOLD : FW_NORMAL;
|
||||
|
@ -329,9 +306,8 @@ ME_LogFontFromStyle(ME_Context* c, LOGFONTW *lf, const ME_Style *s)
|
|||
lf->lfWeight = s->fmt.wWeight;
|
||||
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_ITALIC)
|
||||
lf->lfItalic = 1;
|
||||
if (s->fmt.dwEffects & s->fmt.dwMask & (CFM_UNDERLINE | CFE_LINK))
|
||||
lf->lfUnderline = 1;
|
||||
if (s->fmt.dwMask & CFM_UNDERLINETYPE && s->fmt.bUnderlineType == CFU_CF1UNDERLINE)
|
||||
if ((s->fmt.dwEffects & s->fmt.dwMask & (CFM_UNDERLINE | CFE_LINK)) &&
|
||||
s->fmt.bUnderlineType == CFU_CF1UNDERLINE)
|
||||
lf->lfUnderline = 1;
|
||||
if (s->fmt.dwEffects & s->fmt.dwMask & CFM_STRIKEOUT)
|
||||
lf->lfStrikeOut = 1;
|
||||
|
@ -352,14 +328,13 @@ void ME_CharFormatFromLogFont(HDC hDC, const LOGFONTW *lf, CHARFORMAT2W *fmt)
|
|||
ry = GetDeviceCaps(hDC, LOGPIXELSY);
|
||||
lstrcpyW(fmt->szFaceName, lf->lfFaceName);
|
||||
fmt->dwEffects = 0;
|
||||
fmt->dwMask = CFM_WEIGHT|CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_STRIKEOUT|CFM_SIZE|CFM_FACE|CFM_CHARSET;
|
||||
fmt->dwMask = CFM_WEIGHT|CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_UNDERLINETYPE|CFM_STRIKEOUT|CFM_SIZE|CFM_FACE|CFM_CHARSET;
|
||||
fmt->wWeight = lf->lfWeight;
|
||||
fmt->yHeight = -lf->lfHeight*1440/ry;
|
||||
if (lf->lfWeight > FW_NORMAL) fmt->dwEffects |= CFM_BOLD;
|
||||
if (lf->lfItalic) fmt->dwEffects |= CFM_ITALIC;
|
||||
if (lf->lfUnderline) fmt->dwEffects |= CFM_UNDERLINE;
|
||||
/* notice that if a logfont was created with underline due to CFM_LINK, this
|
||||
would add an erroneous CFM_UNDERLINE. This isn't currently ever a problem. */
|
||||
fmt->bUnderlineType = CFU_UNDERLINE;
|
||||
if (lf->lfStrikeOut) fmt->dwEffects |= CFM_STRIKEOUT;
|
||||
fmt->bPitchAndFamily = lf->lfPitchAndFamily;
|
||||
fmt->bCharSet = lf->lfCharSet;
|
||||
|
@ -513,12 +488,13 @@ ME_Style *ME_GetInsertStyle(ME_TextEditor *editor, int nCursor)
|
|||
}
|
||||
}
|
||||
|
||||
void ME_SaveTempStyle(ME_TextEditor *editor)
|
||||
void ME_SaveTempStyle(ME_TextEditor *editor, ME_Style *style)
|
||||
{
|
||||
ME_Style *old_style = editor->pBuffer->pCharStyle;
|
||||
editor->pBuffer->pCharStyle = ME_GetInsertStyle(editor, 0);
|
||||
if (old_style)
|
||||
ME_ReleaseStyle(old_style);
|
||||
|
||||
if (style) ME_AddRefStyle( style );
|
||||
editor->pBuffer->pCharStyle = style;
|
||||
if (old_style) ME_ReleaseStyle( old_style );
|
||||
}
|
||||
|
||||
void ME_ClearTempStyle(ME_TextEditor *editor)
|
||||
|
|
|
@ -105,9 +105,9 @@ ME_DisplayItem* ME_InsertTableRowStartAtParagraph(ME_TextEditor *editor,
|
|||
para->member.para.pCell = prev_para->member.para.pCell;
|
||||
para->member.para.nFlags |= MEPF_CELL;
|
||||
para->member.para.nFlags &= ~(MEPF_ROWSTART|MEPF_ROWEND);
|
||||
para->member.para.pFmt->dwMask |= PFM_TABLE|PFM_TABLEROWDELIMITER;
|
||||
para->member.para.pFmt->wEffects |= PFE_TABLE;
|
||||
para->member.para.pFmt->wEffects &= ~PFE_TABLEROWDELIMITER;
|
||||
para->member.para.fmt.dwMask |= PFM_TABLE|PFM_TABLEROWDELIMITER;
|
||||
para->member.para.fmt.wEffects |= PFE_TABLE;
|
||||
para->member.para.fmt.wEffects &= ~PFE_TABLEROWDELIMITER;
|
||||
prev_para = para;
|
||||
para = para->member.para.next_para;
|
||||
}
|
||||
|
@ -205,12 +205,12 @@ void ME_CheckTablesForCorruption(ME_TextEditor *editor)
|
|||
{
|
||||
while (p->type == diParagraph)
|
||||
{
|
||||
assert(p->member.para.pFmt->dwMask & PFM_TABLE);
|
||||
assert(p->member.para.pFmt->dwMask & PFM_TABLEROWDELIMITER);
|
||||
assert(p->member.para.fmt.dwMask & PFM_TABLE);
|
||||
assert(p->member.para.fmt.dwMask & PFM_TABLEROWDELIMITER);
|
||||
if (p->member.para.pCell)
|
||||
{
|
||||
assert(p->member.para.nFlags & MEPF_CELL);
|
||||
assert(p->member.para.pFmt->wEffects & PFE_TABLE);
|
||||
assert(p->member.para.fmt.wEffects & PFE_TABLE);
|
||||
}
|
||||
if (p->member.para.pCell != pPrev->member.para.pCell)
|
||||
{
|
||||
|
@ -225,11 +225,11 @@ void ME_CheckTablesForCorruption(ME_TextEditor *editor)
|
|||
assert(pPrev->member.para.pCell);
|
||||
assert(p->member.para.pCell
|
||||
== pPrev->member.para.pCell->member.cell.parent_cell);
|
||||
assert(p->member.para.pFmt->wEffects & PFE_TABLEROWDELIMITER);
|
||||
assert(p->member.para.fmt.wEffects & PFE_TABLEROWDELIMITER);
|
||||
}
|
||||
else if (p->member.para.pCell)
|
||||
{
|
||||
assert(!(p->member.para.pFmt->wEffects & PFE_TABLEROWDELIMITER));
|
||||
assert(!(p->member.para.fmt.wEffects & PFE_TABLEROWDELIMITER));
|
||||
assert(pPrev->member.para.pCell ||
|
||||
pPrev->member.para.nFlags & MEPF_ROWSTART);
|
||||
if (pPrev->member.para.pCell &&
|
||||
|
@ -244,7 +244,7 @@ void ME_CheckTablesForCorruption(ME_TextEditor *editor)
|
|||
}
|
||||
else if (!(p->member.para.nFlags & MEPF_ROWSTART))
|
||||
{
|
||||
assert(!(p->member.para.pFmt->wEffects & PFE_TABLEROWDELIMITER));
|
||||
assert(!(p->member.para.fmt.wEffects & PFE_TABLEROWDELIMITER));
|
||||
/* ROWSTART must be followed by a cell. */
|
||||
assert(!(p->member.para.nFlags & MEPF_CELL));
|
||||
/* ROWSTART must be followed by a cell. */
|
||||
|
@ -257,8 +257,8 @@ void ME_CheckTablesForCorruption(ME_TextEditor *editor)
|
|||
while (p->type == diParagraph)
|
||||
{
|
||||
assert(!(p->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND|MEPF_CELL)));
|
||||
assert(p->member.para.pFmt->dwMask & PFM_TABLE);
|
||||
assert(!(p->member.para.pFmt->wEffects & PFE_TABLEROWDELIMITER));
|
||||
assert(p->member.para.fmt.dwMask & PFM_TABLE);
|
||||
assert(!(p->member.para.fmt.wEffects & PFE_TABLEROWDELIMITER));
|
||||
assert(!p->member.para.pCell);
|
||||
p = p->member.para.next_para;
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ BOOL ME_IsInTable(ME_DisplayItem *pItem)
|
|||
pItem = ME_GetParagraph(pItem);
|
||||
if (pItem->type != diParagraph)
|
||||
return FALSE;
|
||||
pFmt = pItem->member.para.pFmt;
|
||||
pFmt = &pItem->member.para.fmt;
|
||||
return pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE;
|
||||
}
|
||||
|
||||
|
@ -291,7 +291,7 @@ void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, ME_Cursor *c, int *nC
|
|||
ME_DisplayItem *this_para = c->pPara;
|
||||
ME_DisplayItem *end_para;
|
||||
|
||||
ME_MoveCursorChars(editor, &c2, *nChars);
|
||||
ME_MoveCursorChars(editor, &c2, *nChars, FALSE);
|
||||
end_para = c2.pPara;
|
||||
if (c2.pRun->member.run.nFlags & MERF_ENDPARA) {
|
||||
/* End offset might be in the middle of the end paragraph run.
|
||||
|
@ -364,8 +364,8 @@ void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, ME_Cursor *c, int *nC
|
|||
int nCharsToBoundary;
|
||||
|
||||
if ((this_para->member.para.nCharOfs != nOfs || this_para == end_para) &&
|
||||
this_para->member.para.pFmt->dwMask & PFM_TABLE &&
|
||||
this_para->member.para.pFmt->wEffects & PFE_TABLE)
|
||||
this_para->member.para.fmt.dwMask & PFM_TABLE &&
|
||||
this_para->member.para.fmt.wEffects & PFE_TABLE)
|
||||
{
|
||||
pRun = c->pRun;
|
||||
/* Find the next tab or end paragraph to use as a delete boundary */
|
||||
|
@ -375,8 +375,8 @@ void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, ME_Cursor *c, int *nC
|
|||
- c->pRun->member.run.nCharOfs
|
||||
- c->nOffset;
|
||||
*nChars = min(*nChars, nCharsToBoundary);
|
||||
} else if (end_para->member.para.pFmt->dwMask & PFM_TABLE &&
|
||||
end_para->member.para.pFmt->wEffects & PFE_TABLE)
|
||||
} else if (end_para->member.para.fmt.dwMask & PFM_TABLE &&
|
||||
end_para->member.para.fmt.wEffects & PFE_TABLE)
|
||||
{
|
||||
/* The deletion starts from before the row, so don't join it with
|
||||
* previous non-empty paragraphs. */
|
||||
|
@ -438,12 +438,12 @@ ME_DisplayItem* ME_AppendTableRow(ME_TextEditor *editor,
|
|||
insertedCell->member.cell.border = cell->member.cell.border;
|
||||
};
|
||||
para = ME_InsertTableRowEndFromCursor(editor);
|
||||
*para->member.para.pFmt = *prevTableEnd->member.para.pFmt;
|
||||
para->member.para.fmt = prevTableEnd->member.para.fmt;
|
||||
/* return the table row start for the inserted paragraph */
|
||||
return ME_FindItemFwd(cell, diParagraph)->member.para.next_para;
|
||||
} else { /* v1.0 - 3.0 */
|
||||
run = ME_FindItemBack(table_row->member.para.next_para, diRun);
|
||||
pFmt = table_row->member.para.pFmt;
|
||||
pFmt = &table_row->member.para.fmt;
|
||||
assert(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE);
|
||||
editor->pCursors[0].pPara = table_row;
|
||||
editor->pCursors[0].pRun = run;
|
||||
|
|
|
@ -155,7 +155,7 @@ BOOL add_undo_set_para_fmt( ME_TextEditor *editor, const ME_Paragraph *para )
|
|||
if (!undo) return FALSE;
|
||||
|
||||
undo->u.set_para_fmt.pos = para->nCharOfs;
|
||||
undo->u.set_para_fmt.fmt = *para->pFmt;
|
||||
undo->u.set_para_fmt.fmt = para->fmt;
|
||||
undo->u.set_para_fmt.border = para->border;
|
||||
|
||||
return TRUE;
|
||||
|
@ -189,7 +189,7 @@ BOOL add_undo_split_para( ME_TextEditor *editor, const ME_Paragraph *para, ME_St
|
|||
|
||||
undo->u.split_para.pos = para->nCharOfs - eol_str->nLen;
|
||||
undo->u.split_para.eol_str = eol_str;
|
||||
undo->u.split_para.fmt = *para->pFmt;
|
||||
undo->u.split_para.fmt = para->fmt;
|
||||
undo->u.split_para.border = para->border;
|
||||
undo->u.split_para.flags = para->prev_para->member.para.nFlags & ~MEPF_CELL;
|
||||
|
||||
|
@ -339,7 +339,7 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, struct undo_item *undo)
|
|||
ME_CursorFromCharOfs(editor, undo->u.set_para_fmt.pos, &tmp);
|
||||
para = ME_FindItemBack(tmp.pRun, diParagraph);
|
||||
add_undo_set_para_fmt( editor, ¶->member.para );
|
||||
*para->member.para.pFmt = undo->u.set_para_fmt.fmt;
|
||||
para->member.para.fmt = undo->u.set_para_fmt.fmt;
|
||||
para->member.para.border = undo->u.set_para_fmt.border;
|
||||
para->member.para.nFlags |= MEPF_REWRAP;
|
||||
break;
|
||||
|
@ -349,7 +349,7 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, struct undo_item *undo)
|
|||
ME_Cursor start, end;
|
||||
ME_CursorFromCharOfs(editor, undo->u.set_char_fmt.pos, &start);
|
||||
end = start;
|
||||
ME_MoveCursorChars(editor, &end, undo->u.set_char_fmt.len);
|
||||
ME_MoveCursorChars(editor, &end, undo->u.set_char_fmt.len, FALSE);
|
||||
ME_SetCharFormat(editor, &start, &end, &undo->u.set_char_fmt.fmt);
|
||||
break;
|
||||
}
|
||||
|
@ -398,7 +398,7 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, struct undo_item *undo)
|
|||
undo->u.split_para.eol_str->szData, undo->u.split_para.eol_str->nLen, paraFlags);
|
||||
if (bFixRowStart)
|
||||
new_para->member.para.nFlags |= MEPF_ROWSTART;
|
||||
*new_para->member.para.pFmt = undo->u.split_para.fmt;
|
||||
new_para->member.para.fmt = undo->u.split_para.fmt;
|
||||
new_para->member.para.border = undo->u.split_para.border;
|
||||
if (paraFlags)
|
||||
{
|
||||
|
|
|
@ -33,6 +33,22 @@ WINE_DECLARE_DEBUG_CHANNEL(richedit_check);
|
|||
* - no tabs
|
||||
*/
|
||||
|
||||
typedef struct tagME_WrapContext
|
||||
{
|
||||
ME_Style *style;
|
||||
ME_Context *context;
|
||||
int nLeftMargin, nRightMargin;
|
||||
int nFirstMargin; /* Offset to first line's text, always to the text itself even if a para number is present */
|
||||
int nParaNumOffset; /* Offset to the para number */
|
||||
int nAvailWidth; /* Width avail for text to wrap into. Does not include any para number text */
|
||||
int nRow;
|
||||
POINT pt;
|
||||
BOOL bOverflown, bWordWrap;
|
||||
ME_DisplayItem *pPara;
|
||||
ME_DisplayItem *pRowStart;
|
||||
|
||||
ME_DisplayItem *pLastSplittableRun;
|
||||
} ME_WrapContext;
|
||||
|
||||
static BOOL get_run_glyph_buffers( ME_Run *run )
|
||||
{
|
||||
|
@ -182,7 +198,7 @@ static void ME_BeginRow(ME_WrapContext *wc)
|
|||
PARAFORMAT2 *pFmt;
|
||||
ME_DisplayItem *para = wc->pPara;
|
||||
|
||||
pFmt = para->member.para.pFmt;
|
||||
pFmt = ¶->member.para.fmt;
|
||||
wc->pRowStart = NULL;
|
||||
wc->bOverflown = FALSE;
|
||||
wc->pLastSplittableRun = NULL;
|
||||
|
@ -204,7 +220,7 @@ static void ME_BeginRow(ME_WrapContext *wc)
|
|||
width -= cell->prev_cell->member.cell.nRightBoundary;
|
||||
if (!cell->prev_cell)
|
||||
{
|
||||
int rowIndent = ME_GetTableRowEnd(para)->member.para.pFmt->dxStartIndent;
|
||||
int rowIndent = ME_GetTableRowEnd(para)->member.para.fmt.dxStartIndent;
|
||||
width -= rowIndent;
|
||||
}
|
||||
cell->nWidth = max(ME_twips2pointsX(wc->context, width), 0);
|
||||
|
@ -289,7 +305,12 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
|
|||
BOOL bSkippingSpaces = TRUE;
|
||||
int ascent = 0, descent = 0, width=0, shift = 0, align = 0;
|
||||
|
||||
/* wrap text */
|
||||
/* Include height of para numbering label */
|
||||
if (wc->nRow == 0 && para->fmt.wNumbering)
|
||||
{
|
||||
ascent = para->para_num.style->tm.tmAscent;
|
||||
descent = para->para_num.style->tm.tmDescent;
|
||||
}
|
||||
|
||||
for (p = pEnd->prev; p!=wc->pRowStart->prev; p = p->prev)
|
||||
{
|
||||
|
@ -326,7 +347,7 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
|
|||
para->nWidth = max(para->nWidth, width);
|
||||
row = ME_MakeRow(ascent+descent, ascent, width);
|
||||
if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
|
||||
(para->pFmt->dwMask & PFM_TABLE) && (para->pFmt->wEffects & PFE_TABLE))
|
||||
(para->fmt.dwMask & PFM_TABLE) && (para->fmt.wEffects & PFE_TABLE))
|
||||
{
|
||||
/* The text was shifted down in ME_BeginRow so move the wrap context
|
||||
* back to where it should be. */
|
||||
|
@ -337,8 +358,8 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
|
|||
row->member.row.pt = wc->pt;
|
||||
row->member.row.nLMargin = (!wc->nRow ? wc->nFirstMargin : wc->nLeftMargin);
|
||||
row->member.row.nRMargin = wc->nRightMargin;
|
||||
assert(para->pFmt->dwMask & PFM_ALIGNMENT);
|
||||
align = para->pFmt->wAlignment;
|
||||
assert(para->fmt.dwMask & PFM_ALIGNMENT);
|
||||
align = para->fmt.wAlignment;
|
||||
if (align == PFA_CENTER)
|
||||
shift = max((wc->nAvailWidth-width)/2, 0);
|
||||
if (align == PFA_RIGHT)
|
||||
|
@ -353,6 +374,13 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
|
|||
p->member.run.pt.x += row->member.row.nLMargin+shift;
|
||||
}
|
||||
}
|
||||
|
||||
if (wc->nRow == 0 && para->fmt.wNumbering)
|
||||
{
|
||||
para->para_num.pt.x = wc->nParaNumOffset + shift;
|
||||
para->para_num.pt.y = wc->pt.y + row->member.row.nBaseline;
|
||||
}
|
||||
|
||||
ME_InsertBefore(wc->pRowStart, row);
|
||||
wc->nRow++;
|
||||
wc->pt.y += row->member.row.nHeight;
|
||||
|
@ -362,7 +390,7 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
|
|||
static void ME_WrapEndParagraph(ME_WrapContext *wc, ME_DisplayItem *p)
|
||||
{
|
||||
ME_DisplayItem *para = wc->pPara;
|
||||
PARAFORMAT2 *pFmt = para->member.para.pFmt;
|
||||
PARAFORMAT2 *pFmt = ¶->member.para.fmt;
|
||||
if (wc->pRowStart)
|
||||
ME_InsertRowStart(wc, p);
|
||||
if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
|
||||
|
@ -610,8 +638,8 @@ static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p)
|
|||
wc->pt.x + run->nWidth - wc->context->pt.x > wc->nAvailWidth)
|
||||
{
|
||||
int loc = wc->context->pt.x + wc->nAvailWidth - wc->pt.x;
|
||||
/* total white run ? */
|
||||
if (run->nFlags & MERF_WHITESPACE) {
|
||||
/* total white run or end para */
|
||||
if (run->nFlags & (MERF_WHITESPACE | MERF_ENDPARA)) {
|
||||
/* let the overflow logic handle it */
|
||||
wc->bOverflown = TRUE;
|
||||
return p;
|
||||
|
@ -685,19 +713,19 @@ static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p)
|
|||
static int ME_GetParaLineSpace(ME_Context* c, ME_Paragraph* para)
|
||||
{
|
||||
int sp = 0, ls = 0;
|
||||
if (!(para->pFmt->dwMask & PFM_LINESPACING)) return 0;
|
||||
if (!(para->fmt.dwMask & PFM_LINESPACING)) return 0;
|
||||
|
||||
/* FIXME: how to compute simply the line space in ls ??? */
|
||||
/* FIXME: does line spacing include the line itself ??? */
|
||||
switch (para->pFmt->bLineSpacingRule)
|
||||
switch (para->fmt.bLineSpacingRule)
|
||||
{
|
||||
case 0: sp = ls; break;
|
||||
case 1: sp = (3 * ls) / 2; break;
|
||||
case 2: sp = 2 * ls; break;
|
||||
case 3: sp = ME_twips2pointsY(c, para->pFmt->dyLineSpacing); if (sp < ls) sp = ls; break;
|
||||
case 4: sp = ME_twips2pointsY(c, para->pFmt->dyLineSpacing); break;
|
||||
case 5: sp = para->pFmt->dyLineSpacing / 20; break;
|
||||
default: FIXME("Unsupported spacing rule value %d\n", para->pFmt->bLineSpacingRule);
|
||||
case 3: sp = ME_twips2pointsY(c, para->fmt.dyLineSpacing); if (sp < ls) sp = ls; break;
|
||||
case 4: sp = ME_twips2pointsY(c, para->fmt.dyLineSpacing); break;
|
||||
case 5: sp = para->fmt.dyLineSpacing / 20; break;
|
||||
default: FIXME("Unsupported spacing rule value %d\n", para->fmt.bLineSpacingRule);
|
||||
}
|
||||
if (c->editor->nZoomNumerator == 0)
|
||||
return sp;
|
||||
|
@ -746,7 +774,7 @@ static HRESULT itemize_para( ME_Context *c, ME_DisplayItem *p )
|
|||
|
||||
assert( p->type == diParagraph );
|
||||
|
||||
if (para->pFmt->dwMask & PFM_RTLPARA && para->pFmt->wEffects & PFE_RTLPARA)
|
||||
if (para->fmt.dwMask & PFM_RTLPARA && para->fmt.wEffects & PFE_RTLPARA)
|
||||
state.uBidiLevel = 1;
|
||||
|
||||
TRACE( "Base embedding level %d\n", state.uBidiLevel );
|
||||
|
@ -855,6 +883,9 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
|
|||
}
|
||||
ME_PrepareParagraphForWrapping(c, tp);
|
||||
|
||||
/* Calculate paragraph numbering label */
|
||||
para_num_init( c, &tp->member.para );
|
||||
|
||||
/* For now treating all non-password text as complex for better testing */
|
||||
if (!c->editor->cPasswordMask /* &&
|
||||
ScriptIsComplex( tp->member.para.text->szData, tp->member.para.text->nLen, SIC_COMPLEX ) == S_OK */)
|
||||
|
@ -863,21 +894,29 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
|
|||
shape_para( c, tp );
|
||||
}
|
||||
|
||||
pFmt = tp->member.para.pFmt;
|
||||
pFmt = &tp->member.para.fmt;
|
||||
|
||||
wc.context = c;
|
||||
wc.pPara = tp;
|
||||
/* wc.para_style = tp->member.para.style; */
|
||||
wc.style = NULL;
|
||||
wc.nParaNumOffset = 0;
|
||||
if (tp->member.para.nFlags & MEPF_ROWEND) {
|
||||
wc.nFirstMargin = wc.nLeftMargin = wc.nRightMargin = 0;
|
||||
} else {
|
||||
int dxStartIndent = pFmt->dxStartIndent;
|
||||
if (tp->member.para.pCell) {
|
||||
dxStartIndent += ME_GetTableRowEnd(tp)->member.para.pFmt->dxOffset;
|
||||
dxStartIndent += ME_GetTableRowEnd(tp)->member.para.fmt.dxOffset;
|
||||
}
|
||||
wc.nLeftMargin = ME_twips2pointsX(c, dxStartIndent + pFmt->dxOffset);
|
||||
wc.nFirstMargin = ME_twips2pointsX(c, dxStartIndent);
|
||||
wc.nLeftMargin = wc.nFirstMargin + ME_twips2pointsX(c, pFmt->dxOffset);
|
||||
if (pFmt->wNumbering)
|
||||
{
|
||||
wc.nParaNumOffset = wc.nFirstMargin;
|
||||
dxStartIndent = max( ME_twips2pointsX(c, pFmt->wNumberingTab),
|
||||
tp->member.para.para_num.width );
|
||||
wc.nFirstMargin += dxStartIndent;
|
||||
}
|
||||
wc.nRightMargin = ME_twips2pointsX(c, pFmt->dxRightIndent);
|
||||
|
||||
if (wc.nFirstMargin < 0)
|
||||
|
@ -897,7 +936,7 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
|
|||
if (!(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) &&
|
||||
pFmt->dwMask & PFM_BORDER)
|
||||
{
|
||||
border = ME_GetParaBorderWidth(c, tp->member.para.pFmt->wBorders);
|
||||
border = ME_GetParaBorderWidth(c, tp->member.para.fmt.wBorders);
|
||||
if (pFmt->wBorders & 1) {
|
||||
wc.nFirstMargin += border;
|
||||
wc.nLeftMargin += border;
|
||||
|
@ -924,7 +963,7 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
|
|||
if (!(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) &&
|
||||
(pFmt->dwMask & PFM_BORDER) && (pFmt->wBorders & 8))
|
||||
wc.pt.y += border;
|
||||
if (tp->member.para.pFmt->dwMask & PFM_SPACEAFTER)
|
||||
if (tp->member.para.fmt.dwMask & PFM_SPACEAFTER)
|
||||
wc.pt.y += ME_twips2pointsY(c, pFmt->dySpaceAfter);
|
||||
|
||||
tp->member.para.nFlags &= ~MEPF_REWRAP;
|
||||
|
@ -987,9 +1026,9 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor)
|
|||
}
|
||||
c.pt.y += borderWidth;
|
||||
}
|
||||
if (endRowPara->member.para.pFmt->dxStartIndent > 0)
|
||||
if (endRowPara->member.para.fmt.dxStartIndent > 0)
|
||||
{
|
||||
int dxStartIndent = endRowPara->member.para.pFmt->dxStartIndent;
|
||||
int dxStartIndent = endRowPara->member.para.fmt.dxStartIndent;
|
||||
cell = ME_FindItemFwd(item, diCell);
|
||||
cell->member.cell.pt.x += ME_twips2pointsX(&c, dxStartIndent);
|
||||
c.pt.x = cell->member.cell.pt.x;
|
||||
|
|
|
@ -23,6 +23,27 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
||||
|
||||
#define STREAMOUT_BUFFER_SIZE 4096
|
||||
#define STREAMOUT_FONTTBL_SIZE 8192
|
||||
#define STREAMOUT_COLORTBL_SIZE 1024
|
||||
|
||||
typedef struct tagME_OutStream
|
||||
{
|
||||
EDITSTREAM *stream;
|
||||
char buffer[STREAMOUT_BUFFER_SIZE];
|
||||
UINT pos, written;
|
||||
UINT nCodePage;
|
||||
UINT nFontTblLen;
|
||||
ME_FontTableItem fonttbl[STREAMOUT_FONTTBL_SIZE];
|
||||
UINT nColorTblLen;
|
||||
COLORREF colortbl[STREAMOUT_COLORTBL_SIZE];
|
||||
UINT nDefaultFont;
|
||||
UINT nDefaultCodePage;
|
||||
/* nNestingLevel = 0 means we aren't in a cell, 1 means we are in a cell,
|
||||
* an greater numbers mean we are in a cell nested within a cell. */
|
||||
UINT nNestingLevel;
|
||||
CHARFORMAT2W cur_fmt; /* current character format */
|
||||
} ME_OutStream;
|
||||
|
||||
static BOOL
|
||||
ME_StreamOutRTFText(ME_OutStream *pStream, const WCHAR *text, LONG nChars);
|
||||
|
@ -39,6 +60,9 @@ ME_StreamOutInit(ME_TextEditor *editor, EDITSTREAM *stream)
|
|||
pStream->nFontTblLen = 0;
|
||||
pStream->nColorTblLen = 1;
|
||||
pStream->nNestingLevel = 0;
|
||||
memset(&pStream->cur_fmt, 0, sizeof(pStream->cur_fmt));
|
||||
pStream->cur_fmt.dwEffects = CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR;
|
||||
pStream->cur_fmt.bUnderlineType = CFU_UNDERLINE;
|
||||
return pStream;
|
||||
}
|
||||
|
||||
|
@ -208,6 +232,86 @@ ME_StreamOutRTFHeader(ME_OutStream *pStream, int dwFormat)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void add_font_to_fonttbl( ME_OutStream *stream, ME_Style *style )
|
||||
{
|
||||
ME_FontTableItem *table = stream->fonttbl;
|
||||
CHARFORMAT2W *fmt = &style->fmt;
|
||||
WCHAR *face = fmt->szFaceName;
|
||||
BYTE charset = (fmt->dwMask & CFM_CHARSET) ? fmt->bCharSet : DEFAULT_CHARSET;
|
||||
int i;
|
||||
|
||||
if (fmt->dwMask & CFM_FACE)
|
||||
{
|
||||
for (i = 0; i < stream->nFontTblLen; i++)
|
||||
if (table[i].bCharSet == charset
|
||||
&& (table[i].szFaceName == face || !lstrcmpW(table[i].szFaceName, face)))
|
||||
break;
|
||||
|
||||
if (i == stream->nFontTblLen && i < STREAMOUT_FONTTBL_SIZE)
|
||||
{
|
||||
table[i].bCharSet = charset;
|
||||
table[i].szFaceName = face;
|
||||
stream->nFontTblLen++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL find_font_in_fonttbl( ME_OutStream *stream, CHARFORMAT2W *fmt, unsigned int *idx )
|
||||
{
|
||||
WCHAR *facename;
|
||||
int i;
|
||||
|
||||
*idx = 0;
|
||||
if (fmt->dwMask & CFM_FACE)
|
||||
facename = fmt->szFaceName;
|
||||
else
|
||||
facename = stream->fonttbl[0].szFaceName;
|
||||
for (i = 0; i < stream->nFontTblLen; i++)
|
||||
{
|
||||
if (facename == stream->fonttbl[i].szFaceName
|
||||
|| !lstrcmpW(facename, stream->fonttbl[i].szFaceName))
|
||||
if (!(fmt->dwMask & CFM_CHARSET)
|
||||
|| fmt->bCharSet == stream->fonttbl[i].bCharSet)
|
||||
{
|
||||
*idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i < stream->nFontTblLen;
|
||||
}
|
||||
|
||||
static void add_color_to_colortbl( ME_OutStream *stream, COLORREF color )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < stream->nColorTblLen; i++)
|
||||
if (stream->colortbl[i] == color)
|
||||
break;
|
||||
|
||||
if (i == stream->nColorTblLen && i < STREAMOUT_COLORTBL_SIZE)
|
||||
{
|
||||
stream->colortbl[i] = color;
|
||||
stream->nColorTblLen++;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL find_color_in_colortbl( ME_OutStream *stream, COLORREF color, unsigned int *idx )
|
||||
{
|
||||
int i;
|
||||
|
||||
*idx = 0;
|
||||
for (i = 1; i < stream->nColorTblLen; i++)
|
||||
{
|
||||
if (stream->colortbl[i] == color)
|
||||
{
|
||||
*idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i < stream->nFontTblLen;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
ME_StreamOutRTFFontAndColorTbl(ME_OutStream *pStream, ME_DisplayItem *pFirstRun,
|
||||
|
@ -216,82 +320,44 @@ ME_StreamOutRTFFontAndColorTbl(ME_OutStream *pStream, ME_DisplayItem *pFirstRun,
|
|||
ME_DisplayItem *item = pFirstRun;
|
||||
ME_FontTableItem *table = pStream->fonttbl;
|
||||
unsigned int i;
|
||||
ME_DisplayItem *pLastPara = ME_GetParagraph(pLastRun);
|
||||
ME_DisplayItem *pCell = NULL;
|
||||
|
||||
ME_Paragraph *prev_para = NULL;
|
||||
|
||||
do {
|
||||
CHARFORMAT2W *fmt = &item->member.run.style->fmt;
|
||||
COLORREF crColor;
|
||||
|
||||
if (fmt->dwMask & CFM_FACE) {
|
||||
WCHAR *face = fmt->szFaceName;
|
||||
BYTE bCharSet = (fmt->dwMask & CFM_CHARSET) ? fmt->bCharSet : DEFAULT_CHARSET;
|
||||
|
||||
for (i = 0; i < pStream->nFontTblLen; i++)
|
||||
if (table[i].bCharSet == bCharSet
|
||||
&& (table[i].szFaceName == face || !lstrcmpW(table[i].szFaceName, face)))
|
||||
break;
|
||||
if (i == pStream->nFontTblLen && i < STREAMOUT_FONTTBL_SIZE) {
|
||||
table[i].bCharSet = bCharSet;
|
||||
table[i].szFaceName = face;
|
||||
pStream->nFontTblLen++;
|
||||
}
|
||||
}
|
||||
|
||||
if (fmt->dwMask & CFM_COLOR && !(fmt->dwEffects & CFE_AUTOCOLOR)) {
|
||||
crColor = fmt->crTextColor;
|
||||
for (i = 1; i < pStream->nColorTblLen; i++)
|
||||
if (pStream->colortbl[i] == crColor)
|
||||
break;
|
||||
if (i == pStream->nColorTblLen && i < STREAMOUT_COLORTBL_SIZE) {
|
||||
pStream->colortbl[i] = crColor;
|
||||
pStream->nColorTblLen++;
|
||||
}
|
||||
}
|
||||
if (fmt->dwMask & CFM_BACKCOLOR && !(fmt->dwEffects & CFE_AUTOBACKCOLOR)) {
|
||||
crColor = fmt->crBackColor;
|
||||
for (i = 1; i < pStream->nColorTblLen; i++)
|
||||
if (pStream->colortbl[i] == crColor)
|
||||
break;
|
||||
if (i == pStream->nColorTblLen && i < STREAMOUT_COLORTBL_SIZE) {
|
||||
pStream->colortbl[i] = crColor;
|
||||
pStream->nColorTblLen++;
|
||||
add_font_to_fonttbl( pStream, item->member.run.style );
|
||||
|
||||
if (fmt->dwMask & CFM_COLOR && !(fmt->dwEffects & CFE_AUTOCOLOR))
|
||||
add_color_to_colortbl( pStream, fmt->crTextColor );
|
||||
if (fmt->dwMask & CFM_BACKCOLOR && !(fmt->dwEffects & CFE_AUTOBACKCOLOR))
|
||||
add_color_to_colortbl( pStream, fmt->crBackColor );
|
||||
|
||||
if (item->member.run.para != prev_para)
|
||||
{
|
||||
/* check for any para numbering text */
|
||||
if (item->member.run.para->fmt.wNumbering)
|
||||
add_font_to_fonttbl( pStream, item->member.run.para->para_num.style );
|
||||
|
||||
if ((pCell = item->member.para.pCell))
|
||||
{
|
||||
ME_Border* borders[4] = { &pCell->member.cell.border.top,
|
||||
&pCell->member.cell.border.left,
|
||||
&pCell->member.cell.border.bottom,
|
||||
&pCell->member.cell.border.right };
|
||||
for (i = 0; i < 4; i++)
|
||||
if (borders[i]->width > 0)
|
||||
add_color_to_colortbl( pStream, borders[i]->colorRef );
|
||||
}
|
||||
|
||||
prev_para = item->member.run.para;
|
||||
}
|
||||
|
||||
if (item == pLastRun)
|
||||
break;
|
||||
item = ME_FindItemFwd(item, diRun);
|
||||
} while (item);
|
||||
item = ME_GetParagraph(pFirstRun);
|
||||
do {
|
||||
if ((pCell = item->member.para.pCell))
|
||||
{
|
||||
ME_Border* borders[4] = { &pCell->member.cell.border.top,
|
||||
&pCell->member.cell.border.left,
|
||||
&pCell->member.cell.border.bottom,
|
||||
&pCell->member.cell.border.right };
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (borders[i]->width > 0)
|
||||
{
|
||||
unsigned int j;
|
||||
COLORREF crColor = borders[i]->colorRef;
|
||||
for (j = 1; j < pStream->nColorTblLen; j++)
|
||||
if (pStream->colortbl[j] == crColor)
|
||||
break;
|
||||
if (j == pStream->nColorTblLen && j < STREAMOUT_COLORTBL_SIZE) {
|
||||
pStream->colortbl[j] = crColor;
|
||||
pStream->nColorTblLen++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (item == pLastPara)
|
||||
break;
|
||||
item = item->member.para.next_para;
|
||||
} while (item);
|
||||
|
||||
|
||||
if (!ME_StreamOutPrint(pStream, "{\\fonttbl"))
|
||||
return FALSE;
|
||||
|
||||
|
@ -344,7 +410,7 @@ ME_StreamOutRTFTableProps(ME_TextEditor *editor, ME_OutStream *pStream,
|
|||
if (!ME_StreamOutPrint(pStream, "\\trowd"))
|
||||
return FALSE;
|
||||
if (!editor->bEmulateVersion10) { /* v4.1 */
|
||||
PARAFORMAT2 *pFmt = ME_GetTableRowEnd(para)->member.para.pFmt;
|
||||
PARAFORMAT2 *pFmt = &ME_GetTableRowEnd(para)->member.para.fmt;
|
||||
para = ME_GetTableRowStart(para);
|
||||
cell = para->member.para.next_para->member.para.pCell;
|
||||
assert(cell);
|
||||
|
@ -361,17 +427,13 @@ ME_StreamOutRTFTableProps(ME_TextEditor *editor, ME_OutStream *pStream,
|
|||
{
|
||||
if (borders[i]->width)
|
||||
{
|
||||
unsigned int j;
|
||||
unsigned int idx;
|
||||
COLORREF crColor = borders[i]->colorRef;
|
||||
sprintf(props + strlen(props), "\\clbrdr%c", sideChar[i]);
|
||||
sprintf(props + strlen(props), "\\brdrs");
|
||||
sprintf(props + strlen(props), "\\brdrw%d", borders[i]->width);
|
||||
for (j = 1; j < pStream->nColorTblLen; j++) {
|
||||
if (pStream->colortbl[j] == crColor) {
|
||||
sprintf(props + strlen(props), "\\brdrcf%u", j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (find_color_in_colortbl( pStream, crColor, &idx ))
|
||||
sprintf(props + strlen(props), "\\brdrcf%u", idx);
|
||||
}
|
||||
}
|
||||
sprintf(props + strlen(props), "\\cellx%d", cell->member.cell.nRightBoundary);
|
||||
|
@ -382,7 +444,7 @@ ME_StreamOutRTFTableProps(ME_TextEditor *editor, ME_OutStream *pStream,
|
|||
¶->member.para.border.left,
|
||||
¶->member.para.border.bottom,
|
||||
¶->member.para.border.right };
|
||||
PARAFORMAT2 *pFmt = para->member.para.pFmt;
|
||||
PARAFORMAT2 *pFmt = ¶->member.para.fmt;
|
||||
|
||||
assert(!(para->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND|MEPF_CELL)));
|
||||
if (pFmt->dxOffset)
|
||||
|
@ -393,17 +455,13 @@ ME_StreamOutRTFTableProps(ME_TextEditor *editor, ME_OutStream *pStream,
|
|||
{
|
||||
if (borders[i]->width)
|
||||
{
|
||||
unsigned int j;
|
||||
unsigned int idx;
|
||||
COLORREF crColor = borders[i]->colorRef;
|
||||
sprintf(props + strlen(props), "\\trbrdr%c", sideChar[i]);
|
||||
sprintf(props + strlen(props), "\\brdrs");
|
||||
sprintf(props + strlen(props), "\\brdrw%d", borders[i]->width);
|
||||
for (j = 1; j < pStream->nColorTblLen; j++) {
|
||||
if (pStream->colortbl[j] == crColor) {
|
||||
sprintf(props + strlen(props), "\\brdrcf%u", j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (find_color_in_colortbl( pStream, crColor, &idx ))
|
||||
sprintf(props + strlen(props), "\\brdrcf%u", idx);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < pFmt->cTabCount; i++)
|
||||
|
@ -417,13 +475,87 @@ ME_StreamOutRTFTableProps(ME_TextEditor *editor, ME_OutStream *pStream,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL stream_out_para_num( ME_OutStream *stream, ME_Paragraph *para, BOOL pn_dest )
|
||||
{
|
||||
static const char fmt_label[] = "{\\*\\pn\\pnlvlbody\\pnf%u\\pnindent%d\\pnstart%d%s%s}";
|
||||
static const char fmt_bullet[] = "{\\*\\pn\\pnlvlblt\\pnf%u\\pnindent%d{\\pntxtb\\'b7}}";
|
||||
static const char dec[] = "\\pndec";
|
||||
static const char lcltr[] = "\\pnlcltr";
|
||||
static const char ucltr[] = "\\pnucltr";
|
||||
static const char lcrm[] = "\\pnlcrm";
|
||||
static const char ucrm[] = "\\pnucrm";
|
||||
static const char period[] = "{\\pntxta.}";
|
||||
static const char paren[] = "{\\pntxta)}";
|
||||
static const char parens[] = "{\\pntxtb(}{\\pntxta)}";
|
||||
const char *type, *style = "";
|
||||
unsigned int idx;
|
||||
|
||||
find_font_in_fonttbl( stream, ¶->para_num.style->fmt, &idx );
|
||||
|
||||
if (!ME_StreamOutPrint( stream, "{\\pntext\\f%u ", idx )) return FALSE;
|
||||
if (!ME_StreamOutRTFText( stream, para->para_num.text->szData, para->para_num.text->nLen ))
|
||||
return FALSE;
|
||||
if (!ME_StreamOutPrint( stream, "\\tab}" )) return FALSE;
|
||||
|
||||
if (!pn_dest) return TRUE;
|
||||
|
||||
if (para->fmt.wNumbering == PFN_BULLET)
|
||||
{
|
||||
if (!ME_StreamOutPrint( stream, fmt_bullet, idx, para->fmt.wNumberingTab ))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (para->fmt.wNumbering)
|
||||
{
|
||||
case PFN_ARABIC:
|
||||
default:
|
||||
type = dec;
|
||||
break;
|
||||
case PFN_LCLETTER:
|
||||
type = lcltr;
|
||||
break;
|
||||
case PFN_UCLETTER:
|
||||
type = ucltr;
|
||||
break;
|
||||
case PFN_LCROMAN:
|
||||
type = lcrm;
|
||||
break;
|
||||
case PFN_UCROMAN:
|
||||
type = ucrm;
|
||||
break;
|
||||
}
|
||||
switch (para->fmt.wNumberingStyle & 0xf00)
|
||||
{
|
||||
case PFNS_PERIOD:
|
||||
style = period;
|
||||
break;
|
||||
case PFNS_PAREN:
|
||||
style = paren;
|
||||
break;
|
||||
case PFNS_PARENS:
|
||||
style = parens;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ME_StreamOutPrint( stream, fmt_label, idx, para->fmt.wNumberingTab,
|
||||
para->fmt.wNumberingStart, type, style ))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream,
|
||||
ME_DisplayItem *para)
|
||||
{
|
||||
PARAFORMAT2 *fmt = para->member.para.pFmt;
|
||||
PARAFORMAT2 *fmt = ¶->member.para.fmt;
|
||||
char props[STREAMOUT_BUFFER_SIZE] = "";
|
||||
int i;
|
||||
ME_Paragraph *prev_para = NULL;
|
||||
|
||||
if (para->member.para.prev_para->type == diParagraph)
|
||||
prev_para = ¶->member.para.prev_para->member.para;
|
||||
|
||||
if (!editor->bEmulateVersion10) { /* v4.1 */
|
||||
if (para->member.para.nFlags & MEPF_ROWSTART) {
|
||||
|
@ -443,24 +575,33 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream,
|
|||
if (!ME_StreamOutPrint(pStream, "\\nestrow}{\\nonesttables\\par}\r\n"))
|
||||
return FALSE;
|
||||
} else {
|
||||
if (!ME_StreamOutPrint(pStream, "\\row \r\n"))
|
||||
if (!ME_StreamOutPrint(pStream, "\\row\r\n"))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
} else { /* v1.0 - 3.0 */
|
||||
if (para->member.para.pFmt->dwMask & PFM_TABLE &&
|
||||
para->member.para.pFmt->wEffects & PFE_TABLE)
|
||||
if (para->member.para.fmt.dwMask & PFM_TABLE &&
|
||||
para->member.para.fmt.wEffects & PFE_TABLE)
|
||||
{
|
||||
if (!ME_StreamOutRTFTableProps(editor, pStream, para))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Don't emit anything if the last PARAFORMAT2 is inherited */
|
||||
if (prev_para && !memcmp( fmt, &prev_para->fmt, sizeof(*fmt) ))
|
||||
{
|
||||
if (fmt->wNumbering)
|
||||
return stream_out_para_num( pStream, ¶->member.para, FALSE );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!ME_StreamOutPrint(pStream, "\\pard"))
|
||||
return FALSE;
|
||||
|
||||
if (fmt->wNumbering)
|
||||
if (!stream_out_para_num( pStream, ¶->member.para, TRUE )) return FALSE;
|
||||
|
||||
if (!editor->bEmulateVersion10) { /* v4.1 */
|
||||
if (pStream->nNestingLevel > 0)
|
||||
strcat(props, "\\intbl");
|
||||
|
@ -470,7 +611,7 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream,
|
|||
if (fmt->dwMask & PFM_TABLE && fmt->wEffects & PFE_TABLE)
|
||||
strcat(props, "\\intbl");
|
||||
}
|
||||
|
||||
|
||||
/* TODO: PFM_BORDER. M$ does not emit any keywords for these properties, and
|
||||
* when streaming border keywords in, PFM_BORDER is set, but wBorder field is
|
||||
* set very different from the documentation.
|
||||
|
@ -538,11 +679,11 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream,
|
|||
if (!(editor->bEmulateVersion10 && /* v1.0 - 3.0 */
|
||||
fmt->dwMask & PFM_TABLE && fmt->wEffects & PFE_TABLE))
|
||||
{
|
||||
if (fmt->dwMask & PFM_OFFSET)
|
||||
if (fmt->dxOffset)
|
||||
sprintf(props + strlen(props), "\\li%d", fmt->dxOffset);
|
||||
if (fmt->dwMask & PFM_OFFSETINDENT || fmt->dwMask & PFM_STARTINDENT)
|
||||
if (fmt->dxStartIndent)
|
||||
sprintf(props + strlen(props), "\\fi%d", fmt->dxStartIndent);
|
||||
if (fmt->dwMask & PFM_RIGHTINDENT)
|
||||
if (fmt->dxRightIndent)
|
||||
sprintf(props + strlen(props), "\\ri%d", fmt->dxRightIndent);
|
||||
if (fmt->dwMask & PFM_TABSTOPS) {
|
||||
static const char * const leader[6] = { "", "\\tldot", "\\tlhyph", "\\tlul", "\\tlth", "\\tleq" };
|
||||
|
@ -568,11 +709,11 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (fmt->dwMask & PFM_SPACEAFTER)
|
||||
if (fmt->dySpaceAfter)
|
||||
sprintf(props + strlen(props), "\\sa%d", fmt->dySpaceAfter);
|
||||
if (fmt->dwMask & PFM_SPACEBEFORE)
|
||||
if (fmt->dySpaceBefore)
|
||||
sprintf(props + strlen(props), "\\sb%d", fmt->dySpaceBefore);
|
||||
if (fmt->dwMask & PFM_STYLE)
|
||||
if (fmt->sStyle != -1)
|
||||
sprintf(props + strlen(props), "\\s%d", fmt->sStyle);
|
||||
|
||||
if (fmt->dwMask & PFM_SHADING) {
|
||||
|
@ -588,6 +729,8 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream,
|
|||
sprintf(props + strlen(props), "\\cfpat%d\\cbpat%d",
|
||||
(fmt->wShadingStyle >> 4) & 0xF, (fmt->wShadingStyle >> 8) & 0xF);
|
||||
}
|
||||
if (*props)
|
||||
strcat(props, " ");
|
||||
|
||||
if (*props && !ME_StreamOutPrint(pStream, props))
|
||||
return FALSE;
|
||||
|
@ -601,125 +744,114 @@ ME_StreamOutRTFCharProps(ME_OutStream *pStream, CHARFORMAT2W *fmt)
|
|||
{
|
||||
char props[STREAMOUT_BUFFER_SIZE] = "";
|
||||
unsigned int i;
|
||||
CHARFORMAT2W *old_fmt = &pStream->cur_fmt;
|
||||
static const struct
|
||||
{
|
||||
DWORD effect;
|
||||
const char *on, *off;
|
||||
} effects[] =
|
||||
{
|
||||
{ CFE_ALLCAPS, "\\caps", "\\caps0" },
|
||||
{ CFE_BOLD, "\\b", "\\b0" },
|
||||
{ CFE_DISABLED, "\\disabled", "\\disabled0" },
|
||||
{ CFE_EMBOSS, "\\embo", "\\embo0" },
|
||||
{ CFE_HIDDEN, "\\v", "\\v0" },
|
||||
{ CFE_IMPRINT, "\\impr", "\\impr0" },
|
||||
{ CFE_ITALIC, "\\i", "\\i0" },
|
||||
{ CFE_OUTLINE, "\\outl", "\\outl0" },
|
||||
{ CFE_PROTECTED, "\\protect", "\\protect0" },
|
||||
{ CFE_SHADOW, "\\shad", "\\shad0" },
|
||||
{ CFE_SMALLCAPS, "\\scaps", "\\scaps0" },
|
||||
{ CFE_STRIKEOUT, "\\strike", "\\strike0" },
|
||||
};
|
||||
|
||||
if (fmt->dwMask & CFM_ALLCAPS && fmt->dwEffects & CFE_ALLCAPS)
|
||||
strcat(props, "\\caps");
|
||||
if (fmt->dwMask & CFM_ANIMATION)
|
||||
for (i = 0; i < sizeof(effects) / sizeof(effects[0]); i++)
|
||||
{
|
||||
if ((old_fmt->dwEffects ^ fmt->dwEffects) & effects[i].effect)
|
||||
strcat( props, fmt->dwEffects & effects[i].effect ? effects[i].on : effects[i].off );
|
||||
}
|
||||
|
||||
if ((old_fmt->dwEffects ^ fmt->dwEffects) & CFE_AUTOBACKCOLOR ||
|
||||
old_fmt->crBackColor != fmt->crBackColor)
|
||||
{
|
||||
if (fmt->dwEffects & CFE_AUTOBACKCOLOR) i = 0;
|
||||
else find_color_in_colortbl( pStream, fmt->crBackColor, &i );
|
||||
sprintf(props + strlen(props), "\\cb%u", i);
|
||||
}
|
||||
if ((old_fmt->dwEffects ^ fmt->dwEffects) & CFE_AUTOCOLOR ||
|
||||
old_fmt->crTextColor != fmt->crTextColor)
|
||||
{
|
||||
if (fmt->dwEffects & CFE_AUTOCOLOR) i = 0;
|
||||
else find_color_in_colortbl( pStream, fmt->crTextColor, &i );
|
||||
sprintf(props + strlen(props), "\\cf%u", i);
|
||||
}
|
||||
|
||||
if (old_fmt->bAnimation != fmt->bAnimation)
|
||||
sprintf(props + strlen(props), "\\animtext%u", fmt->bAnimation);
|
||||
if (fmt->dwMask & CFM_BACKCOLOR) {
|
||||
if (!(fmt->dwEffects & CFE_AUTOBACKCOLOR)) {
|
||||
for (i = 1; i < pStream->nColorTblLen; i++)
|
||||
if (pStream->colortbl[i] == fmt->crBackColor) {
|
||||
sprintf(props + strlen(props), "\\cb%u", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fmt->dwMask & CFM_BOLD && fmt->dwEffects & CFE_BOLD)
|
||||
strcat(props, "\\b");
|
||||
if (fmt->dwMask & CFM_COLOR) {
|
||||
if (!(fmt->dwEffects & CFE_AUTOCOLOR)) {
|
||||
for (i = 1; i < pStream->nColorTblLen; i++)
|
||||
if (pStream->colortbl[i] == fmt->crTextColor) {
|
||||
sprintf(props + strlen(props), "\\cf%u", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* TODO: CFM_DISABLED */
|
||||
if (fmt->dwMask & CFM_EMBOSS && fmt->dwEffects & CFE_EMBOSS)
|
||||
strcat(props, "\\embo");
|
||||
if (fmt->dwMask & CFM_HIDDEN && fmt->dwEffects & CFE_HIDDEN)
|
||||
strcat(props, "\\v");
|
||||
if (fmt->dwMask & CFM_IMPRINT && fmt->dwEffects & CFE_IMPRINT)
|
||||
strcat(props, "\\impr");
|
||||
if (fmt->dwMask & CFM_ITALIC && fmt->dwEffects & CFE_ITALIC)
|
||||
strcat(props, "\\i");
|
||||
if (fmt->dwMask & CFM_KERNING)
|
||||
if (old_fmt->wKerning != fmt->wKerning)
|
||||
sprintf(props + strlen(props), "\\kerning%u", fmt->wKerning);
|
||||
if (fmt->dwMask & CFM_LCID) {
|
||||
|
||||
if (old_fmt->lcid != fmt->lcid)
|
||||
{
|
||||
/* TODO: handle SFF_PLAINRTF */
|
||||
if (LOWORD(fmt->lcid) == 1024)
|
||||
strcat(props, "\\noproof\\lang1024\\langnp1024\\langfe1024\\langfenp1024");
|
||||
else
|
||||
sprintf(props + strlen(props), "\\lang%u", LOWORD(fmt->lcid));
|
||||
}
|
||||
/* CFM_LINK is not streamed out by M$ */
|
||||
if (fmt->dwMask & CFM_OFFSET) {
|
||||
|
||||
if (old_fmt->yOffset != fmt->yOffset)
|
||||
{
|
||||
if (fmt->yOffset >= 0)
|
||||
sprintf(props + strlen(props), "\\up%d", fmt->yOffset);
|
||||
else
|
||||
sprintf(props + strlen(props), "\\dn%d", -fmt->yOffset);
|
||||
}
|
||||
if (fmt->dwMask & CFM_OUTLINE && fmt->dwEffects & CFE_OUTLINE)
|
||||
strcat(props, "\\outl");
|
||||
if (fmt->dwMask & CFM_PROTECTED && fmt->dwEffects & CFE_PROTECTED)
|
||||
strcat(props, "\\protect");
|
||||
/* TODO: CFM_REVISED CFM_REVAUTHOR - probably using rsidtbl? */
|
||||
if (fmt->dwMask & CFM_SHADOW && fmt->dwEffects & CFE_SHADOW)
|
||||
strcat(props, "\\shad");
|
||||
if (fmt->dwMask & CFM_SIZE)
|
||||
if (old_fmt->yHeight != fmt->yHeight)
|
||||
sprintf(props + strlen(props), "\\fs%d", fmt->yHeight / 10);
|
||||
if (fmt->dwMask & CFM_SMALLCAPS && fmt->dwEffects & CFE_SMALLCAPS)
|
||||
strcat(props, "\\scaps");
|
||||
if (fmt->dwMask & CFM_SPACING)
|
||||
if (old_fmt->sSpacing != fmt->sSpacing)
|
||||
sprintf(props + strlen(props), "\\expnd%u\\expndtw%u", fmt->sSpacing / 5, fmt->sSpacing);
|
||||
if (fmt->dwMask & CFM_STRIKEOUT && fmt->dwEffects & CFE_STRIKEOUT)
|
||||
strcat(props, "\\strike");
|
||||
if (fmt->dwMask & CFM_STYLE) {
|
||||
sprintf(props + strlen(props), "\\cs%u", fmt->sStyle);
|
||||
/* TODO: emit style contents here */
|
||||
}
|
||||
if (fmt->dwMask & (CFM_SUBSCRIPT | CFM_SUPERSCRIPT)) {
|
||||
if ((old_fmt->dwEffects ^ fmt->dwEffects) & (CFM_SUBSCRIPT | CFM_SUPERSCRIPT))
|
||||
{
|
||||
if (fmt->dwEffects & CFE_SUBSCRIPT)
|
||||
strcat(props, "\\sub");
|
||||
else if (fmt->dwEffects & CFE_SUPERSCRIPT)
|
||||
strcat(props, "\\super");
|
||||
else
|
||||
strcat(props, "\\nosupersub");
|
||||
}
|
||||
if (fmt->dwMask & CFM_UNDERLINE || fmt->dwMask & CFM_UNDERLINETYPE) {
|
||||
if (fmt->dwMask & CFM_UNDERLINETYPE)
|
||||
switch (fmt->bUnderlineType) {
|
||||
case CFU_CF1UNDERLINE:
|
||||
case CFU_UNDERLINE:
|
||||
if ((old_fmt->dwEffects ^ fmt->dwEffects) & CFE_UNDERLINE ||
|
||||
old_fmt->bUnderlineType != fmt->bUnderlineType)
|
||||
{
|
||||
BYTE type = (fmt->dwEffects & CFE_UNDERLINE) ? fmt->bUnderlineType : CFU_UNDERLINENONE;
|
||||
switch (type)
|
||||
{
|
||||
case CFU_UNDERLINE:
|
||||
strcat(props, "\\ul");
|
||||
break;
|
||||
case CFU_UNDERLINEDOTTED:
|
||||
case CFU_UNDERLINEDOTTED:
|
||||
strcat(props, "\\uld");
|
||||
break;
|
||||
case CFU_UNDERLINEDOUBLE:
|
||||
case CFU_UNDERLINEDOUBLE:
|
||||
strcat(props, "\\uldb");
|
||||
break;
|
||||
case CFU_UNDERLINEWORD:
|
||||
case CFU_UNDERLINEWORD:
|
||||
strcat(props, "\\ulw");
|
||||
break;
|
||||
case CFU_UNDERLINENONE:
|
||||
default:
|
||||
case CFU_CF1UNDERLINE:
|
||||
case CFU_UNDERLINENONE:
|
||||
default:
|
||||
strcat(props, "\\ulnone");
|
||||
break;
|
||||
}
|
||||
else if (fmt->dwEffects & CFE_UNDERLINE)
|
||||
strcat(props, "\\ul");
|
||||
}
|
||||
/* FIXME: How to emit CFM_WEIGHT? */
|
||||
|
||||
if (fmt->dwMask & CFM_FACE || fmt->dwMask & CFM_CHARSET) {
|
||||
WCHAR *szFaceName;
|
||||
|
||||
if (fmt->dwMask & CFM_FACE)
|
||||
szFaceName = fmt->szFaceName;
|
||||
else
|
||||
szFaceName = pStream->fonttbl[0].szFaceName;
|
||||
for (i = 0; i < pStream->nFontTblLen; i++) {
|
||||
if (szFaceName == pStream->fonttbl[i].szFaceName
|
||||
|| !lstrcmpW(szFaceName, pStream->fonttbl[i].szFaceName))
|
||||
if (!(fmt->dwMask & CFM_CHARSET)
|
||||
|| fmt->bCharSet == pStream->fonttbl[i].bCharSet)
|
||||
break;
|
||||
}
|
||||
if (i < pStream->nFontTblLen)
|
||||
if (strcmpW(old_fmt->szFaceName, fmt->szFaceName) ||
|
||||
old_fmt->bCharSet != fmt->bCharSet)
|
||||
{
|
||||
if (find_font_in_fonttbl( pStream, fmt, &i ))
|
||||
{
|
||||
if (i != pStream->nDefaultFont)
|
||||
sprintf(props + strlen(props), "\\f%u", i);
|
||||
sprintf(props + strlen(props), "\\f%u", i);
|
||||
|
||||
/* In UTF-8 mode, charsets/codepages are not used */
|
||||
if (pStream->nDefaultCodePage != CP_UTF8)
|
||||
|
@ -735,6 +867,7 @@ ME_StreamOutRTFCharProps(ME_OutStream *pStream, CHARFORMAT2W *fmt)
|
|||
strcat(props, " ");
|
||||
if (!ME_StreamOutPrint(pStream, props))
|
||||
return FALSE;
|
||||
*old_fmt = *fmt;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -874,13 +1007,10 @@ static BOOL ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream,
|
|||
const ME_Cursor *start, int nChars, int dwFormat)
|
||||
{
|
||||
ME_Cursor cursor = *start;
|
||||
ME_DisplayItem *prev_para = cursor.pPara;
|
||||
ME_DisplayItem *prev_para = NULL;
|
||||
ME_Cursor endCur = cursor;
|
||||
int actual_chars;
|
||||
|
||||
actual_chars = ME_MoveCursorChars(editor, &endCur, nChars);
|
||||
/* Include the final \r which MoveCursorChars will ignore. */
|
||||
if (actual_chars != nChars) endCur.nOffset++;
|
||||
ME_MoveCursorChars(editor, &endCur, nChars, TRUE);
|
||||
|
||||
if (!ME_StreamOutRTFHeader(pStream, dwFormat))
|
||||
return FALSE;
|
||||
|
@ -890,8 +1020,7 @@ static BOOL ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream,
|
|||
|
||||
/* TODO: stylesheet table */
|
||||
|
||||
/* FIXME: maybe emit something smarter for the generator? */
|
||||
if (!ME_StreamOutPrint(pStream, "{\\*\\generator Wine Riched20 2.0.????;}"))
|
||||
if (!ME_StreamOutPrint(pStream, "{\\*\\generator Wine Riched20 2.0;}"))
|
||||
return FALSE;
|
||||
|
||||
/* TODO: information group */
|
||||
|
@ -902,9 +1031,6 @@ static BOOL ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream,
|
|||
|
||||
/* TODO: section formatting properties */
|
||||
|
||||
if (!ME_StreamOutRTFParaProps(editor, pStream, cursor.pPara))
|
||||
return FALSE;
|
||||
|
||||
do {
|
||||
if (cursor.pPara != prev_para)
|
||||
{
|
||||
|
@ -924,8 +1050,8 @@ static BOOL ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream,
|
|||
return FALSE;
|
||||
} else if (cursor.pRun->member.run.nFlags & MERF_TAB) {
|
||||
if (editor->bEmulateVersion10 && /* v1.0 - 3.0 */
|
||||
cursor.pPara->member.para.pFmt->dwMask & PFM_TABLE &&
|
||||
cursor.pPara->member.para.pFmt->wEffects & PFE_TABLE)
|
||||
cursor.pPara->member.para.fmt.dwMask & PFM_TABLE &&
|
||||
cursor.pPara->member.para.fmt.wEffects & PFE_TABLE)
|
||||
{
|
||||
if (!ME_StreamOutPrint(pStream, "\\cell "))
|
||||
return FALSE;
|
||||
|
@ -943,27 +1069,25 @@ static BOOL ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream,
|
|||
}
|
||||
nChars--;
|
||||
} else if (cursor.pRun->member.run.nFlags & MERF_ENDPARA) {
|
||||
if (cursor.pPara->member.para.pFmt->dwMask & PFM_TABLE &&
|
||||
cursor.pPara->member.para.pFmt->wEffects & PFE_TABLE &&
|
||||
if (cursor.pPara->member.para.fmt.dwMask & PFM_TABLE &&
|
||||
cursor.pPara->member.para.fmt.wEffects & PFE_TABLE &&
|
||||
!(cursor.pPara->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND|MEPF_CELL)))
|
||||
{
|
||||
if (!ME_StreamOutPrint(pStream, "\\row \r\n"))
|
||||
if (!ME_StreamOutPrint(pStream, "\\row\r\n"))
|
||||
return FALSE;
|
||||
} else {
|
||||
if (!ME_StreamOutPrint(pStream, "\r\n\\par"))
|
||||
if (!ME_StreamOutPrint(pStream, "\\par\r\n"))
|
||||
return FALSE;
|
||||
}
|
||||
/* Skip as many characters as required by current line break */
|
||||
nChars = max(0, nChars - cursor.pRun->member.run.len);
|
||||
} else if (cursor.pRun->member.run.nFlags & MERF_ENDROW) {
|
||||
if (!ME_StreamOutPrint(pStream, "\\line \r\n"))
|
||||
if (!ME_StreamOutPrint(pStream, "\\line\r\n"))
|
||||
return FALSE;
|
||||
nChars--;
|
||||
} else {
|
||||
int nEnd;
|
||||
|
||||
if (!ME_StreamOutPrint(pStream, "{"))
|
||||
return FALSE;
|
||||
TRACE("style %p\n", cursor.pRun->member.run.style);
|
||||
if (!ME_StreamOutRTFCharProps(pStream, &cursor.pRun->member.run.style->fmt))
|
||||
return FALSE;
|
||||
|
@ -973,8 +1097,6 @@ static BOOL ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream,
|
|||
nEnd - cursor.nOffset))
|
||||
return FALSE;
|
||||
cursor.nOffset = 0;
|
||||
if (!ME_StreamOutPrint(pStream, "}"))
|
||||
return FALSE;
|
||||
}
|
||||
} while (cursor.pRun != endCur.pRun && ME_NextRun(&cursor.pPara, &cursor.pRun, TRUE));
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ reactos/dll/win32/qmgrprxy # Synced to WineStaging-1.9.11
|
|||
reactos/dll/win32/query # Synced to WineStaging-1.9.11
|
||||
reactos/dll/win32/rasapi32 # Synced to WineStaging-1.9.11
|
||||
reactos/dll/win32/resutils # Synced to WineStaging-1.9.11
|
||||
reactos/dll/win32/riched20 # Synced to WineStaging-1.9.16
|
||||
reactos/dll/win32/riched20 # Synced to WineStaging-1.9.23
|
||||
reactos/dll/win32/riched32 # Synced to WineStaging-1.9.11
|
||||
reactos/dll/win32/rpcrt4 # Synced to WineStaging-1.9.16
|
||||
reactos/dll/win32/rsabase # Synced to WineStaging-1.9.11
|
||||
|
|
Loading…
Reference in a new issue