richedit: Borders are now drawn for tables and nested tables.
This commit is contained in:
parent
967c148a68
commit
421c5b0e02
|
@ -451,6 +451,10 @@ static void ME_RTFParAttrHook(RTF_Info *info)
|
|||
switch(info->rtfMinor)
|
||||
{
|
||||
case rtfParDef: /* restores default paragraph attributes */
|
||||
if (!info->editor->bEmulateVersion10) /* v4.1 */
|
||||
info->borderType = RTFBorderParaLeft;
|
||||
else /* v1.0 - 3.0 */
|
||||
info->borderType = RTFBorderParaTop;
|
||||
fmt.dwMask = PFM_ALIGNMENT | PFM_BORDER | PFM_LINESPACING | PFM_TABSTOPS |
|
||||
PFM_OFFSET | PFM_RIGHTINDENT | PFM_SPACEAFTER | PFM_SPACEBEFORE |
|
||||
PFM_STARTINDENT;
|
||||
|
@ -656,6 +660,7 @@ static void ME_RTFParAttrHook(RTF_Info *info)
|
|||
fmt.wNumberingStart = info->rtfParam;
|
||||
break;
|
||||
case rtfBorderLeft:
|
||||
info->borderType = RTFBorderParaLeft;
|
||||
ME_GetSelectionParaFormat(info->editor, &fmt);
|
||||
if (!(fmt.dwMask & PFM_BORDER))
|
||||
{
|
||||
|
@ -667,6 +672,7 @@ static void ME_RTFParAttrHook(RTF_Info *info)
|
|||
fmt.dwMask = PFM_BORDER;
|
||||
break;
|
||||
case rtfBorderRight:
|
||||
info->borderType = RTFBorderParaRight;
|
||||
ME_GetSelectionParaFormat(info->editor, &fmt);
|
||||
if (!(fmt.dwMask & PFM_BORDER))
|
||||
{
|
||||
|
@ -678,6 +684,7 @@ static void ME_RTFParAttrHook(RTF_Info *info)
|
|||
fmt.dwMask = PFM_BORDER;
|
||||
break;
|
||||
case rtfBorderTop:
|
||||
info->borderType = RTFBorderParaTop;
|
||||
ME_GetSelectionParaFormat(info->editor, &fmt);
|
||||
if (!(fmt.dwMask & PFM_BORDER))
|
||||
{
|
||||
|
@ -689,6 +696,7 @@ static void ME_RTFParAttrHook(RTF_Info *info)
|
|||
fmt.dwMask = PFM_BORDER;
|
||||
break;
|
||||
case rtfBorderBottom:
|
||||
info->borderType = RTFBorderParaBottom;
|
||||
ME_GetSelectionParaFormat(info->editor, &fmt);
|
||||
if (!(fmt.dwMask & PFM_BORDER))
|
||||
{
|
||||
|
@ -735,11 +743,24 @@ static void ME_RTFParAttrHook(RTF_Info *info)
|
|||
fmt.dwMask = PFM_BORDER;
|
||||
break;
|
||||
case rtfBorderWidth:
|
||||
{
|
||||
int borderSide = info->borderType & RTFBorderSideMask;
|
||||
RTFTable *tableDef = info->tableDef;
|
||||
ME_GetSelectionParaFormat(info->editor, &fmt);
|
||||
/* we assume that borders have been created before (RTF spec) */
|
||||
fmt.wBorderWidth |= ((info->rtfParam / 15) & 7) << 8;
|
||||
if ((info->borderType & RTFBorderTypeMask) == RTFBorderTypeCell)
|
||||
{
|
||||
RTFBorder *border;
|
||||
if (!tableDef || tableDef->numCellsDefined >= MAX_TABLE_CELLS)
|
||||
break;
|
||||
border = &tableDef->cells[tableDef->numCellsDefined].border[borderSide];
|
||||
border->width = info->rtfParam;
|
||||
break;
|
||||
}
|
||||
fmt.dwMask = PFM_BORDER;
|
||||
break;
|
||||
}
|
||||
case rtfBorderSpace:
|
||||
ME_GetSelectionParaFormat(info->editor, &fmt);
|
||||
/* we assume that borders have been created before (RTF spec) */
|
||||
|
@ -760,6 +781,10 @@ static void ME_RTFTblAttrHook(RTF_Info *info)
|
|||
{
|
||||
case rtfRowDef:
|
||||
{
|
||||
if (!info->editor->bEmulateVersion10) /* v4.1 */
|
||||
info->borderType = 0; /* Not sure */
|
||||
else /* v1.0 - 3.0 */
|
||||
info->borderType = RTFBorderRowTop;
|
||||
if (!info->tableDef) {
|
||||
info->tableDef = ME_MakeTableDef(info->editor);
|
||||
} else {
|
||||
|
@ -786,6 +811,30 @@ static void ME_RTFTblAttrHook(RTF_Info *info)
|
|||
}
|
||||
info->tableDef->numCellsDefined++;
|
||||
break;
|
||||
case rtfRowBordTop:
|
||||
info->borderType = RTFBorderRowTop;
|
||||
break;
|
||||
case rtfRowBordLeft:
|
||||
info->borderType = RTFBorderRowLeft;
|
||||
break;
|
||||
case rtfRowBordBottom:
|
||||
info->borderType = RTFBorderRowBottom;
|
||||
break;
|
||||
case rtfRowBordRight:
|
||||
info->borderType = RTFBorderRowRight;
|
||||
break;
|
||||
case rtfCellBordTop:
|
||||
info->borderType = RTFBorderCellTop;
|
||||
break;
|
||||
case rtfCellBordLeft:
|
||||
info->borderType = RTFBorderCellLeft;
|
||||
break;
|
||||
case rtfCellBordBottom:
|
||||
info->borderType = RTFBorderCellBottom;
|
||||
break;
|
||||
case rtfCellBordRight:
|
||||
info->borderType = RTFBorderCellRight;
|
||||
break;
|
||||
case rtfRowGapH:
|
||||
if (info->tableDef)
|
||||
info->tableDef->gapH = info->rtfParam;
|
||||
|
@ -882,6 +931,10 @@ static void ME_RTFSpecialCharHook(RTF_Info *info)
|
|||
for (i = 0; i < tableDef->numCellsDefined; i++)
|
||||
{
|
||||
cell->member.cell.nRightBoundary = tableDef->cells[i].rightBoundary;
|
||||
cell->member.cell.border.top.width = tableDef->cells[i].border[0].width;
|
||||
cell->member.cell.border.left.width = tableDef->cells[i].border[1].width;
|
||||
cell->member.cell.border.bottom.width = tableDef->cells[i].border[2].width;
|
||||
cell->member.cell.border.right.width = tableDef->cells[i].border[3].width;
|
||||
cell = cell->member.cell.next_cell;
|
||||
if (!cell)
|
||||
{
|
||||
|
|
|
@ -165,6 +165,19 @@ typedef struct tagME_Document {
|
|||
int last_wrapped_line;
|
||||
} ME_Document;
|
||||
|
||||
typedef struct tagME_Border
|
||||
{
|
||||
int width;
|
||||
} ME_Border;
|
||||
|
||||
typedef struct tagME_BorderRect
|
||||
{
|
||||
ME_Border top;
|
||||
ME_Border left;
|
||||
ME_Border bottom;
|
||||
ME_Border right;
|
||||
} ME_BorderRect;
|
||||
|
||||
typedef struct tagME_Paragraph
|
||||
{
|
||||
PARAFORMAT2 *pFmt;
|
||||
|
@ -184,8 +197,10 @@ typedef struct tagME_Cell /* v4.1 */
|
|||
{
|
||||
int nNestingLevel; /* 0 for normal cells, and greater for nested cells */
|
||||
int nRightBoundary;
|
||||
ME_BorderRect border;
|
||||
POINT pt;
|
||||
int nHeight, nWidth;
|
||||
int yTextOffset; /* The text offset is caused by the largest top border. */
|
||||
struct tagME_DisplayItem *prev_cell, *next_cell, *parent_cell;
|
||||
} ME_Cell;
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *
|
|||
item = editor->pBuffer->pFirst->next;
|
||||
c.pt.y -= yoffset;
|
||||
while(item != editor->pBuffer->pLast) {
|
||||
int yTextOffset = 0;
|
||||
int ye;
|
||||
assert(item->type == diParagraph);
|
||||
if (item->member.para.pCell
|
||||
|
@ -47,6 +48,19 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *
|
|||
} else {
|
||||
ye = c.pt.y + item->member.para.nHeight;
|
||||
}
|
||||
if (!(item->member.para.nFlags & MEPF_ROWEND) &&
|
||||
item->member.para.pCell != item->member.para.prev_para->member.para.pCell)
|
||||
{
|
||||
ME_DisplayItem *cell;
|
||||
if (item->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART)
|
||||
cell = item->member.para.pCell;
|
||||
else
|
||||
cell = item->member.para.prev_para->member.para.pCell;
|
||||
assert(cell);
|
||||
/* the border shifts the text down */
|
||||
yTextOffset = cell->member.cell.yTextOffset;
|
||||
ye += yTextOffset;
|
||||
}
|
||||
if (!bOnlyNew || (item->member.para.nFlags & MEPF_REPAINT))
|
||||
{
|
||||
BOOL bPaint = (rcUpdate == NULL);
|
||||
|
@ -54,30 +68,33 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *
|
|||
bPaint = c.pt.y<rcUpdate->bottom && ye>rcUpdate->top;
|
||||
if (bPaint)
|
||||
{
|
||||
c.pt.y += yTextOffset;
|
||||
ME_DrawParagraph(&c, item);
|
||||
if (!rcUpdate || (rcUpdate->top<=c.pt.y && rcUpdate->bottom>=ye))
|
||||
if (!rcUpdate || (rcUpdate->top<=c.pt.y-yTextOffset && rcUpdate->bottom>=ye))
|
||||
item->member.para.nFlags &= ~MEPF_REPAINT;
|
||||
}
|
||||
}
|
||||
if (item->member.para.pCell)
|
||||
{
|
||||
ME_Cell *cell = &item->member.para.pCell->member.cell;
|
||||
ME_DisplayItem *next_para = item->member.para.next_para;
|
||||
c.pt.x = cell->pt.x + cell->nWidth;
|
||||
if (item->member.para.pCell == item->member.para.next_para->member.para.pCell)
|
||||
if (item->member.para.pCell == next_para->member.para.pCell &&
|
||||
!(next_para->member.para.nFlags & (MEPF_ROWSTART|MEPF_ROWEND)))
|
||||
{
|
||||
c.pt.y = ye;
|
||||
} else {
|
||||
if (item->member.para.next_para->member.para.nFlags & MEPF_ROWSTART)
|
||||
if (next_para->member.para.nFlags & MEPF_ROWSTART)
|
||||
{
|
||||
cell = &ME_FindItemFwd(item->member.para.next_para, diCell)->member.cell;
|
||||
cell = &ME_FindItemFwd(next_para, diCell)->member.cell;
|
||||
}
|
||||
else if (item->member.para.next_para->member.para.nFlags & MEPF_ROWEND)
|
||||
else if (next_para->member.para.nFlags & MEPF_ROWEND)
|
||||
{
|
||||
cell = &cell->next_cell->member.cell;
|
||||
}
|
||||
else
|
||||
{
|
||||
cell = &item->member.para.next_para->member.para.pCell->member.cell;
|
||||
cell = &next_para->member.para.pCell->member.cell;
|
||||
}
|
||||
c.pt.y = cell->pt.y - yoffset;
|
||||
}
|
||||
|
@ -548,14 +565,45 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT
|
|||
{
|
||||
int idx, border_width, top_border, bottom_border;
|
||||
RECT rc;
|
||||
BOOL hasParaBorder;
|
||||
|
||||
SetRectEmpty(bounds);
|
||||
if (!(para->pFmt->dwMask & (PFM_BORDER | PFM_SPACEBEFORE | PFM_SPACEAFTER))) return;
|
||||
|
||||
border_width = top_border = bottom_border = 0;
|
||||
idx = (para->pFmt->wBorders >> 8) & 0xF;
|
||||
if ((para->pFmt->dwMask & PFM_BORDER) && idx != 0 && (para->pFmt->wBorders & 0xF))
|
||||
hasParaBorder = (!(c->editor->bEmulateVersion10 &&
|
||||
para->pFmt->dwMask & PFM_TABLE &&
|
||||
para->pFmt->wEffects & PFE_TABLE) &&
|
||||
(para->pFmt->dwMask & PFM_BORDER) &&
|
||||
idx != 0 &&
|
||||
(para->pFmt->wBorders & 0xF));
|
||||
if (hasParaBorder)
|
||||
{
|
||||
/* FIXME: wBorders is not stored as MSDN says in v1.0 - 4.1 of richedit
|
||||
* controls. It actually stores the paragraph or row border style. Although
|
||||
* the value isn't used for drawing, it is used for streaming out rich text.
|
||||
*
|
||||
* wBorders stores the border style for each side (top, left, bottom, right)
|
||||
* using nibble (4 bits) to store each border style. The rich text format
|
||||
* control words, and their associated value are the following:
|
||||
* \brdrdash 0
|
||||
* \brdrdashsm 1
|
||||
* \brdrdb 2
|
||||
* \brdrdot 3
|
||||
* \brdrhair 4
|
||||
* \brdrs 5
|
||||
* \brdrth 6
|
||||
* \brdrtriple 7
|
||||
*
|
||||
* The order of the sides stored actually differs from v1.0 to 3.0 and v4.1.
|
||||
* The mask corresponding to each side for the version are the following:
|
||||
* mask v1.0-3.0 v4.1
|
||||
* 0x000F top left
|
||||
* 0x00F0 left top
|
||||
* 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->editor, para->pFmt->wBorders);
|
||||
|
@ -583,7 +631,9 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT
|
|||
FillRect(c->hDC, &rc, c->editor->hbrBackground);
|
||||
}
|
||||
|
||||
if ((para->pFmt->dwMask & PFM_BORDER) && idx != 0 && (para->pFmt->wBorders & 0xF)) {
|
||||
/* Native richedit doesn't support paragraph borders in v1.0 - 4.1,
|
||||
* but might support it in later versions. */
|
||||
if (hasParaBorder) {
|
||||
int pen_width;
|
||||
COLORREF pencr;
|
||||
HPEN pen = NULL, oldpen = NULL;
|
||||
|
@ -665,8 +715,139 @@ static void ME_DrawParaDecoration(ME_Context* c, ME_Paragraph* para, int y, RECT
|
|||
static void ME_DrawTableBorders(ME_Context *c, ME_DisplayItem *paragraph)
|
||||
{
|
||||
ME_Paragraph *para = ¶graph->member.para;
|
||||
if (c->editor->bEmulateVersion10) /* v1.0 - 3.0 */
|
||||
if (!c->editor->bEmulateVersion10) /* v4.1 */
|
||||
{
|
||||
if (para->pCell)
|
||||
{
|
||||
RECT rc;
|
||||
ME_Cell *cell = ¶->pCell->member.cell;
|
||||
ME_DisplayItem *paraAfterRow;
|
||||
HPEN pen, oldPen;
|
||||
LOGBRUSH logBrush;
|
||||
HBRUSH brush;
|
||||
COLORREF color;
|
||||
POINT oldPt;
|
||||
int width;
|
||||
BOOL atTop = (para->pCell != para->prev_para->member.para.pCell);
|
||||
BOOL atBottom = (para->pCell != para->next_para->member.para.pCell);
|
||||
int top = (atTop ? cell->pt.y : para->pt.y) - ME_GetYScrollPos(c->editor);
|
||||
int bottom = (atBottom ?
|
||||
cell->pt.y + cell->nHeight - ME_GetYScrollPos(c->editor):
|
||||
top + para->nHeight + (atTop ? cell->yTextOffset : 0));
|
||||
rc.left = cell->pt.x;
|
||||
rc.right = rc.left + cell->nWidth;
|
||||
if (atTop) {
|
||||
/* Erase gap before text if not all borders are the same height. */
|
||||
width = max(ME_twips2pointsY(c, cell->border.top.width), 1);
|
||||
rc.top = top + width;
|
||||
width = cell->yTextOffset - width;
|
||||
rc.bottom = rc.top + width;
|
||||
if (width) {
|
||||
FillRect(c->hDC, &rc, c->editor->hbrBackground);
|
||||
}
|
||||
}
|
||||
/* Draw cell borders.
|
||||
* The borders borders are draw in is left, top, bottom, right in order
|
||||
* to be consistent with native richedit. This is noticeable from the
|
||||
* overlap of borders of different colours. */
|
||||
if (!(para->nFlags & MEPF_ROWEND)) {
|
||||
rc.top = top;
|
||||
rc.bottom = bottom;
|
||||
if (cell->border.left.width > 0)
|
||||
{
|
||||
color = RGB(0,0,0);
|
||||
width = max(ME_twips2pointsX(c, cell->border.left.width), 1);
|
||||
} else {
|
||||
color = RGB(192,192,192);
|
||||
width = 1;
|
||||
}
|
||||
logBrush.lbStyle = BS_SOLID;
|
||||
logBrush.lbColor = color;
|
||||
logBrush.lbHatch = 0;
|
||||
pen = ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
|
||||
width, &logBrush, 0, NULL);
|
||||
oldPen = SelectObject(c->hDC, pen);
|
||||
MoveToEx(c->hDC, rc.left, rc.top, &oldPt);
|
||||
LineTo(c->hDC, rc.left, rc.bottom);
|
||||
SelectObject(c->hDC, oldPen);
|
||||
DeleteObject(pen);
|
||||
MoveToEx(c->hDC, oldPt.x, oldPt.y, NULL);
|
||||
}
|
||||
|
||||
if (atTop) {
|
||||
if (cell->border.top.width > 0)
|
||||
{
|
||||
brush = GetStockObject(BLACK_BRUSH);
|
||||
width = max(ME_twips2pointsY(c, cell->border.top.width), 1);
|
||||
} else {
|
||||
brush = GetStockObject(LTGRAY_BRUSH);
|
||||
width = 1;
|
||||
}
|
||||
rc.top = top;
|
||||
rc.bottom = rc.top + width;
|
||||
FillRect(c->hDC, &rc, brush);
|
||||
}
|
||||
|
||||
/* Draw the bottom border if at the last paragraph in the cell, and when
|
||||
* in the last row of the table. */
|
||||
if (atBottom) {
|
||||
int oldLeft = rc.left;
|
||||
width = max(ME_twips2pointsY(c, cell->border.bottom.width), 1);
|
||||
paraAfterRow = ME_GetTableRowEnd(paragraph)->member.para.next_para;
|
||||
if (paraAfterRow->member.para.nFlags & MEPF_ROWSTART) {
|
||||
ME_DisplayItem *nextEndCell;
|
||||
nextEndCell = ME_FindItemBack(ME_GetTableRowEnd(paraAfterRow), diCell);
|
||||
assert(nextEndCell && !nextEndCell->member.cell.next_cell);
|
||||
rc.left = nextEndCell->member.cell.pt.x;
|
||||
/* FIXME: Native draws FROM the bottom of the table rather than
|
||||
* TO the bottom of the table in this case, but just doing so here
|
||||
* will case the next row to erase the border. */
|
||||
/*
|
||||
rc.top = bottom;
|
||||
rc.bottom = rc.top + width;
|
||||
*/
|
||||
}
|
||||
if (rc.left < rc.right) {
|
||||
if (cell->border.bottom.width > 0) {
|
||||
brush = GetStockObject(BLACK_BRUSH);
|
||||
} else {
|
||||
brush = GetStockObject(LTGRAY_BRUSH);
|
||||
}
|
||||
rc.bottom = bottom;
|
||||
rc.top = rc.bottom - width;
|
||||
FillRect(c->hDC, &rc, brush);
|
||||
}
|
||||
rc.left = oldLeft;
|
||||
}
|
||||
|
||||
/* Right border only drawn if at the end of the table row. */
|
||||
if (!cell->next_cell->member.cell.next_cell &&
|
||||
!(para->nFlags & MEPF_ROWSTART))
|
||||
{
|
||||
rc.top = top;
|
||||
rc.bottom = bottom;
|
||||
if (cell->border.right.width > 0) {
|
||||
color = RGB(0,0,0);
|
||||
width = max(ME_twips2pointsX(c, cell->border.right.width), 1);
|
||||
} else {
|
||||
color = RGB(192,192,192);
|
||||
width = 1;
|
||||
}
|
||||
logBrush.lbStyle = BS_SOLID;
|
||||
logBrush.lbColor = color;
|
||||
logBrush.lbHatch = 0;
|
||||
pen = ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,
|
||||
width, &logBrush, 0, NULL);
|
||||
oldPen = SelectObject(c->hDC, pen);
|
||||
MoveToEx(c->hDC, rc.right - 1, rc.top, &oldPt);
|
||||
LineTo(c->hDC, rc.right - 1, rc.bottom);
|
||||
SelectObject(c->hDC, oldPen);
|
||||
DeleteObject(pen);
|
||||
MoveToEx(c->hDC, oldPt.x, oldPt.y, NULL);
|
||||
}
|
||||
}
|
||||
} else { /* v1.0 - 3.0 */
|
||||
/* Draw simple table border */
|
||||
if (para->pFmt->dwMask & PFM_TABLE && para->pFmt->wEffects & PFE_TABLE) {
|
||||
HPEN pen = NULL, oldpen = NULL;
|
||||
int i, firstX, startX, endX, rowY, rowBottom, nHeight;
|
||||
|
@ -830,6 +1011,7 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) {
|
|||
{
|
||||
FillRect(c->hDC, &rc, c->editor->hbrBackground);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -247,6 +247,7 @@ void RTFInit(RTF_Info *info)
|
|||
info->tableDef = NULL;
|
||||
info->nestingLevel = 0;
|
||||
info->canInheritInTbl = FALSE;
|
||||
info->borderType = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -950,6 +950,7 @@ typedef struct RTFFont RTFFont;
|
|||
typedef struct RTFColor RTFColor;
|
||||
typedef struct RTFStyle RTFStyle;
|
||||
typedef struct RTFStyleElt RTFStyleElt;
|
||||
typedef struct RTFBorder RTFBorder;
|
||||
typedef struct RTFCell RTFCell;
|
||||
typedef struct RTFTable RTFTable;
|
||||
|
||||
|
@ -1006,10 +1007,15 @@ struct RTFStyleElt
|
|||
RTFStyleElt *rtfNextSE; /* next element in style */
|
||||
};
|
||||
|
||||
struct RTFBorder
|
||||
{
|
||||
int width;
|
||||
};
|
||||
|
||||
struct RTFCell
|
||||
{
|
||||
int rightBoundary;
|
||||
RTFBorder border[4];
|
||||
};
|
||||
|
||||
|
||||
|
@ -1019,6 +1025,8 @@ struct RTFTable
|
|||
int numCellsDefined;
|
||||
|
||||
int gapH, leftEdge;
|
||||
/* borders for the table row */
|
||||
RTFBorder border[6];
|
||||
|
||||
/* Used in v1.0 - v3.0 */
|
||||
int numCellsInserted;
|
||||
|
@ -1033,6 +1041,40 @@ struct RTFTable
|
|||
RTFTable *parent;
|
||||
};
|
||||
|
||||
|
||||
# define RTFBorderTypeNone 0x00
|
||||
# define RTFBorderTypePara 0x10 /* for \brdrX control words */
|
||||
# define RTFBorderTypeRow 0x20 /* for \trbrdrX control words */
|
||||
# define RTFBorderTypeCell 0x30 /* for \clbrdrX control words */
|
||||
# define RTFBorderTypeMask 0xf0
|
||||
|
||||
/* The X in the control words \brdrX \trbrdrX and \clbrdrX mentioned above
|
||||
* should be one of t, l, b, r which stand for top, left, bottom, right
|
||||
* respectively. */
|
||||
# define RTFBorderSideTop 0x00
|
||||
# define RTFBorderSideLeft 0x01
|
||||
# define RTFBorderSideBottom 0x02
|
||||
# define RTFBorderSideRight 0x03
|
||||
# define RTFBorderSideHorizontal 0x04
|
||||
# define RTFBorderSideVertical 0x05
|
||||
# define RTFBorderSideMask 0x0f
|
||||
|
||||
/* Here are the values from the border types and sides put together. */
|
||||
# define RTFBorderParaTop 0x10
|
||||
# define RTFBorderParaLeft 0x11
|
||||
# define RTFBorderParaBottom 0x12
|
||||
# define RTFBorderParaRight 0x13
|
||||
# define RTFBorderRowTop 0x20
|
||||
# define RTFBorderRowLeft 0x21
|
||||
# define RTFBorderRowBottom 0x22
|
||||
# define RTFBorderRowRight 0x23
|
||||
# define RTFBorderRowHorizontal 0x24
|
||||
# define RTFBorderRowVertical 0x25
|
||||
# define RTFBorderCellTop 0x30
|
||||
# define RTFBorderCellLeft 0x31
|
||||
# define RTFBorderCellBottom 0x32
|
||||
# define RTFBorderCellRight 0x33
|
||||
|
||||
/*
|
||||
* Return pointer to new element of type t, or NULL
|
||||
* if no memory available.
|
||||
|
@ -1141,6 +1183,7 @@ struct _RTF_Info {
|
|||
RTFTable *tableDef;
|
||||
int nestingLevel;
|
||||
BOOL canInheritInTbl;
|
||||
int borderType; /* value corresponds to the RTFBorder constants. */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -608,6 +608,7 @@ struct RTFTable *ME_MakeTableDef(ME_TextEditor *editor)
|
|||
void ME_InitTableDef(ME_TextEditor *editor, struct RTFTable *tableDef)
|
||||
{
|
||||
ZeroMemory(tableDef->cells, sizeof(tableDef->cells));
|
||||
ZeroMemory(tableDef->border, sizeof(tableDef->border));
|
||||
tableDef->numCellsDefined = 0;
|
||||
tableDef->leftEdge = 0;
|
||||
if (!editor->bEmulateVersion10) /* v4.1 */
|
||||
|
|
|
@ -606,8 +606,24 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
|
|||
{
|
||||
ME_DisplayItem *cell = ME_FindItemFwd(item, diCell);
|
||||
ME_DisplayItem *endRowPara;
|
||||
int borderWidth = 0;
|
||||
cell->member.cell.pt = c.pt;
|
||||
endRowPara = ME_GetTableRowEnd(item);
|
||||
/* 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;
|
||||
|
@ -620,13 +636,26 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
|
|||
{
|
||||
/* Set all the cells to the height of the largest cell */
|
||||
ME_DisplayItem *startRowPara;
|
||||
int prevHeight, nHeight;
|
||||
int prevHeight, nHeight, bottomBorder = 0;
|
||||
ME_DisplayItem *cell = ME_FindItemBack(item, diCell);
|
||||
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;
|
||||
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;
|
||||
|
@ -664,6 +693,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
|
|||
c.pt.x = cell->pt.x + cell->nWidth;
|
||||
c.pt.y = cell->pt.y;
|
||||
cell->next_cell->member.cell.pt = c.pt;
|
||||
c.pt.y += cell->yTextOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue