static void ME_LogFontFromStyle(ME_Context* c, LOGFONTW *lf, const ME_Style *s) { ZeroMemory(lf, sizeof(LOGFONTW)); lstrcpyW(lf->lfFaceName, s->fmt.szFaceName); lf->lfHeight = ME_twips2pointsY(c, -s->fmt.yHeight); lf->lfWeight = FW_NORMAL; if (s->fmt.dwEffects & s->fmt.dwMask & CFM_BOLD) lf->lfWeight = FW_BOLD; if (s->fmt.dwMask & CFM_WEIGHT) 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) lf->lfUnderline = 1; if (s->fmt.dwEffects & s->fmt.dwMask & CFM_STRIKEOUT) lf->lfStrikeOut = 1; if (s->fmt.dwEffects & s->fmt.dwMask & (CFM_SUBSCRIPT|CFM_SUPERSCRIPT)) lf->lfHeight = (lf->lfHeight*2)/3; /*lf.lfQuality = PROOF_QUALITY; */ if (s->fmt.dwMask & CFM_FACE) lf->lfPitchAndFamily = s->fmt.bPitchAndFamily; if (s->fmt.dwMask & CFM_CHARSET) lf->lfCharSet = s->fmt.bCharSet; }
static int ME_GetParaLineSpace(ME_Context* c, ME_Paragraph* para) { int sp = 0, ls = 0; if (!(para->pFmt->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) { 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); } if (c->editor->nZoomNumerator == 0) return sp; else return sp * c->editor->nZoomNumerator / c->editor->nZoomDenominator; }
BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) { ME_DisplayItem *item; ME_Context c; int totalWidth = 0; ME_DisplayItem *repaint_start = NULL, *repaint_end = NULL; ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost)); c.pt.x = 0; item = editor->pBuffer->pFirst->next; while(item != editor->pBuffer->pLast) { BOOL bRedraw = FALSE; assert(item->type == diParagraph); if ((item->member.para.nFlags & MEPF_REWRAP) || (item->member.para.pt.y != c.pt.y)) bRedraw = TRUE; item->member.para.pt = c.pt; ME_WrapTextParagraph(&c, item); if (bRedraw) ME_MarkRepaintEnd(item, &repaint_start, &repaint_end); if (item->member.para.nFlags & MEPF_ROWSTART) { ME_DisplayItem *cell = ME_FindItemFwd(item, diCell); ME_DisplayItem *endRowPara; int borderWidth = 0; cell->member.cell.pt = c.pt; /* Offset the text by the largest top border width. */ while (cell->member.cell.next_cell) { borderWidth = max(borderWidth, cell->member.cell.border.top.width); cell = cell->member.cell.next_cell; } endRowPara = ME_FindItemFwd(cell, diParagraph); assert(endRowPara->member.para.nFlags & MEPF_ROWEND); if (borderWidth > 0) { borderWidth = max(ME_twips2pointsY(&c, borderWidth), 1); while (cell) { cell->member.cell.yTextOffset = borderWidth; cell = cell->member.cell.prev_cell; } c.pt.y += borderWidth; } if (endRowPara->member.para.pFmt->dxStartIndent > 0) { int dxStartIndent = endRowPara->member.para.pFmt->dxStartIndent; cell = ME_FindItemFwd(item, diCell); cell->member.cell.pt.x += ME_twips2pointsX(&c, dxStartIndent); c.pt.x = cell->member.cell.pt.x; } } else if (item->member.para.nFlags & MEPF_ROWEND) { /* Set all the cells to the height of the largest cell */ ME_DisplayItem *startRowPara; int prevHeight, nHeight, bottomBorder = 0; ME_DisplayItem *cell = ME_FindItemBack(item, diCell); item->member.para.nWidth = cell->member.cell.pt.x + cell->member.cell.nWidth; if (!(item->member.para.next_para->member.para.nFlags & MEPF_ROWSTART)) { /* Last row, the bottom border is added to the height. */ cell = cell->member.cell.prev_cell; while (cell) { bottomBorder = max(bottomBorder, cell->member.cell.border.bottom.width); cell = cell->member.cell.prev_cell; } bottomBorder = ME_twips2pointsY(&c, bottomBorder); cell = ME_FindItemBack(item, diCell); } prevHeight = cell->member.cell.nHeight; nHeight = cell->member.cell.prev_cell->member.cell.nHeight + bottomBorder; cell->member.cell.nHeight = nHeight; item->member.para.nHeight = nHeight; cell = cell->member.cell.prev_cell; cell->member.cell.nHeight = nHeight; while (cell->member.cell.prev_cell) { cell = cell->member.cell.prev_cell; cell->member.cell.nHeight = nHeight; } /* Also set the height of the start row paragraph */ startRowPara = ME_FindItemBack(cell, diParagraph); startRowPara->member.para.nHeight = nHeight; c.pt.x = startRowPara->member.para.pt.x; c.pt.y = cell->member.cell.pt.y + nHeight; if (prevHeight < nHeight) { /* The height of the cells has grown, so invalidate the bottom of * the cells. */ ME_MarkRepaintEnd(item, &repaint_start, &repaint_end); cell = ME_FindItemBack(item, diCell); while (cell) { ME_MarkRepaintEnd(ME_FindItemBack(cell, diParagraph), &repaint_start, &repaint_end); cell = cell->member.cell.prev_cell; } } } else if (item->member.para.pCell && item->member.para.pCell != item->member.para.next_para->member.para.pCell) { /* The next paragraph is in the next cell in the table row. */ ME_Cell *cell = &item->member.para.pCell->member.cell; cell->nHeight = c.pt.y + item->member.para.nHeight - cell->pt.y; /* Propagate the largest height to the end so that it can be easily * sent back to all the cells at the end of the row. */ if (cell->prev_cell) cell->nHeight = max(cell->nHeight, cell->prev_cell->member.cell.nHeight); c.pt.x = cell->pt.x + cell->nWidth; c.pt.y = cell->pt.y; cell->next_cell->member.cell.pt = c.pt; if (!(item->member.para.next_para->member.para.nFlags & MEPF_ROWEND)) c.pt.y += cell->yTextOffset; } else { if (item->member.para.pCell) { /* Next paragraph in the same cell. */ c.pt.x = item->member.para.pCell->member.cell.pt.x; } else { /* Normal paragraph */ c.pt.x = 0; } c.pt.y += item->member.para.nHeight; } totalWidth = max(totalWidth, item->member.para.nWidth); item = item->member.para.next_para; } editor->sizeWindow.cx = c.rcView.right-c.rcView.left; editor->sizeWindow.cy = c.rcView.bottom-c.rcView.top; editor->nTotalLength = c.pt.y; editor->nTotalWidth = totalWidth; editor->pBuffer->pLast->member.para.pt.x = 0; editor->pBuffer->pLast->member.para.pt.y = c.pt.y; ME_DestroyContext(&c); if (repaint_start || editor->nTotalLength < editor->nLastTotalLength) ME_InvalidateParagraphRange(editor, repaint_start, repaint_end); return !!repaint_start; }
static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) { ME_DisplayItem *p; ME_WrapContext wc; int border = 0; int linespace = 0; PARAFORMAT2 *pFmt; assert(tp->type == diParagraph); if (!(tp->member.para.nFlags & MEPF_REWRAP)) { return; } ME_PrepareParagraphForWrapping(c, tp); /* 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 */) { if (SUCCEEDED( itemize_para( c, tp ) )) shape_para( c, tp ); } pFmt = tp->member.para.pFmt; wc.context = c; wc.pPara = tp; /* wc.para_style = tp->member.para.style; */ wc.style = NULL; 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; } wc.nFirstMargin = ME_twips2pointsX(c, dxStartIndent); wc.nLeftMargin = wc.nFirstMargin + ME_twips2pointsX(c, pFmt->dxOffset); wc.nRightMargin = ME_twips2pointsX(c, pFmt->dxRightIndent); } if (c->editor->bEmulateVersion10 && /* v1.0 - 3.0 */ pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) { wc.nFirstMargin += ME_twips2pointsX(c, pFmt->dxOffset * 2); } wc.nRow = 0; wc.pt.y = 0; if (pFmt->dwMask & PFM_SPACEBEFORE) wc.pt.y += ME_twips2pointsY(c, pFmt->dySpaceBefore); if (!(pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE) && pFmt->dwMask & PFM_BORDER) { border = ME_GetParaBorderWidth(c, tp->member.para.pFmt->wBorders); if (pFmt->wBorders & 1) { wc.nFirstMargin += border; wc.nLeftMargin += border; } if (pFmt->wBorders & 2) wc.nRightMargin -= border; if (pFmt->wBorders & 4) wc.pt.y += border; } linespace = ME_GetParaLineSpace(c, &tp->member.para); ME_BeginRow(&wc); for (p = tp->next; p!=tp->member.para.next_para; ) { assert(p->type != diStartRow); if (p->type == diRun) { p = ME_WrapHandleRun(&wc, p); } else p = p->next; if (wc.nRow && p == wc.pRowStart) wc.pt.y += linespace; } ME_WrapEndParagraph(&wc, p); 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) wc.pt.y += ME_twips2pointsY(c, pFmt->dySpaceAfter); tp->member.para.nFlags &= ~MEPF_REWRAP; tp->member.para.nHeight = wc.pt.y; tp->member.para.nRows = wc.nRow; }
static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp, DWORD beginofs) { ME_DisplayItem *p; ME_WrapContext wc; int border = 0; int linespace = 0; assert(tp->type == diParagraph); if (!(tp->member.para.nFlags & MEPF_REWRAP)) { return; } ME_PrepareParagraphForWrapping(c, tp); wc.context = c; /* wc.para_style = tp->member.para.style; */ wc.style = NULL; wc.nFirstMargin = ME_twips2pointsX(c, tp->member.para.pFmt->dxStartIndent) + beginofs; wc.nLeftMargin = wc.nFirstMargin + ME_twips2pointsX(c, tp->member.para.pFmt->dxOffset); wc.nRightMargin = ME_twips2pointsX(c, tp->member.para.pFmt->dxRightIndent); wc.nRow = 0; wc.pt.x = 0; wc.pt.y = 0; if (tp->member.para.pFmt->dwMask & PFM_SPACEBEFORE) wc.pt.y += ME_twips2pointsY(c, tp->member.para.pFmt->dySpaceBefore); if (tp->member.para.pFmt->dwMask & PFM_BORDER) { border = ME_GetParaBorderWidth(c->editor, tp->member.para.pFmt->wBorders); if (tp->member.para.pFmt->wBorders & 1) { wc.nFirstMargin += border; wc.nLeftMargin += border; } if (tp->member.para.pFmt->wBorders & 2) wc.nRightMargin -= border; if (tp->member.para.pFmt->wBorders & 4) wc.pt.y += border; } if (c->editor->bWordWrap) wc.nAvailWidth = c->rcView.right - c->rcView.left - wc.nFirstMargin - wc.nRightMargin; else wc.nAvailWidth = ~0u >> 1; wc.pRowStart = NULL; linespace = ME_GetParaLineSpace(c, &tp->member.para); ME_BeginRow(&wc); for (p = tp->next; p!=tp->member.para.next_para; ) { assert(p->type != diStartRow); if (p->type == diRun) { p = ME_WrapHandleRun(&wc, p); } else p = p->next; if (wc.nRow && p == wc.pRowStart) wc.pt.y += linespace; } ME_WrapEndParagraph(&wc, p); if ((tp->member.para.pFmt->dwMask & PFM_BORDER) && (tp->member.para.pFmt->wBorders & 8)) wc.pt.y += border; if (tp->member.para.pFmt->dwMask & PFM_SPACEAFTER) wc.pt.y += ME_twips2pointsY(c, tp->member.para.pFmt->dySpaceAfter); tp->member.para.nFlags &= ~MEPF_REWRAP; tp->member.para.nHeight = wc.pt.y; tp->member.para.nRows = wc.nRow; }