BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) { ME_DisplayItem *item; ME_Context c; BOOL bModified = FALSE; int yStart = -1; ME_InitContext(&c, editor, GetDC(editor->hWnd)); editor->nHeight = 0; item = editor->pBuffer->pFirst->next; while(item != editor->pBuffer->pLast) { BOOL bRedraw = FALSE; assert(item->type == diParagraph); editor->nHeight = max(editor->nHeight, item->member.para.nYPos); if ((item->member.para.nFlags & MEPF_REWRAP) || (item->member.para.nYPos != c.pt.y)) bRedraw = TRUE; item->member.para.nYPos = c.pt.y; ME_WrapTextParagraph(&c, item, editor->selofs); if (bRedraw) { item->member.para.nFlags |= MEPF_REPAINT; if (yStart == -1) yStart = c.pt.y; } bModified = bModified | bRedraw; c.pt.y += item->member.para.nHeight; 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; ME_DestroyContext(&c, editor->hWnd); /* Each paragraph may contain multiple rows, which should be scrollable, even if the containing paragraph has nYPos == 0 */ item = editor->pBuffer->pFirst; while ((item = ME_FindItemFwd(item, diStartRow)) != NULL) { assert(item->type == diStartRow); editor->nHeight = max(editor->nHeight, item->member.row.nYPos); } if (bModified || editor->nTotalLength < editor->nLastTotalLength) ME_InvalidateMarkedParagraphs(editor); return bModified; }
void ME_InvalidateSelection(ME_TextEditor *editor) { ME_DisplayItem *para1, *para2; int nStart, nEnd; int len = ME_GetTextLength(editor); ME_GetSelection(editor, &nStart, &nEnd); /* if both old and new selection are 0-char (= caret only), then there's no (inverted) area to be repainted, neither old nor new */ if (nStart == nEnd && editor->nLastSelStart == editor->nLastSelEnd) return; ME_WrapMarkedParagraphs(editor); ME_GetSelectionParas(editor, ¶1, ¶2); assert(para1->type == diParagraph); assert(para2->type == diParagraph); /* last selection markers aren't always updated, which means they can point past the end of the document */ if (editor->nLastSelStart > len) editor->nLastSelEnd = len; if (editor->nLastSelEnd > len) editor->nLastSelEnd = len; /* if the start part of selection is being expanded or contracted... */ if (nStart < editor->nLastSelStart) { ME_MarkForPainting(editor, para1, ME_FindItemFwd(editor->pLastSelStartPara, diParagraphOrEnd)); } else if (nStart > editor->nLastSelStart) { ME_MarkForPainting(editor, editor->pLastSelStartPara, ME_FindItemFwd(para1, diParagraphOrEnd)); } /* if the end part of selection is being contracted or expanded... */ if (nEnd < editor->nLastSelEnd) { ME_MarkForPainting(editor, para2, ME_FindItemFwd(editor->pLastSelEndPara, diParagraphOrEnd)); } else if (nEnd > editor->nLastSelEnd) { ME_MarkForPainting(editor, editor->pLastSelEndPara, ME_FindItemFwd(para2, diParagraphOrEnd)); } ME_InvalidateMarkedParagraphs(editor); /* remember the last invalidated position */ ME_GetSelection(editor, &editor->nLastSelStart, &editor->nLastSelEnd); ME_GetSelectionParas(editor, &editor->pLastSelStartPara, &editor->pLastSelEndPara); assert(editor->pLastSelStartPara->type == diParagraph); assert(editor->pLastSelEndPara->type == diParagraph); }
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) { if (!repaint_start) repaint_start = editor->pBuffer->pFirst; ME_InvalidateMarkedParagraphs(editor, repaint_start, repaint_end); } return !!repaint_start; }