Commit 421c5b0e authored by Dylan Smith's avatar Dylan Smith Committed by Alexandre Julliard

richedit: Borders are now drawn for tables and nested tables.

parent 967c148a
...@@ -451,6 +451,10 @@ static void ME_RTFParAttrHook(RTF_Info *info) ...@@ -451,6 +451,10 @@ static void ME_RTFParAttrHook(RTF_Info *info)
switch(info->rtfMinor) switch(info->rtfMinor)
{ {
case rtfParDef: /* restores default paragraph attributes */ 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 | fmt.dwMask = PFM_ALIGNMENT | PFM_BORDER | PFM_LINESPACING | PFM_TABSTOPS |
PFM_OFFSET | PFM_RIGHTINDENT | PFM_SPACEAFTER | PFM_SPACEBEFORE | PFM_OFFSET | PFM_RIGHTINDENT | PFM_SPACEAFTER | PFM_SPACEBEFORE |
PFM_STARTINDENT; PFM_STARTINDENT;
...@@ -656,6 +660,7 @@ static void ME_RTFParAttrHook(RTF_Info *info) ...@@ -656,6 +660,7 @@ static void ME_RTFParAttrHook(RTF_Info *info)
fmt.wNumberingStart = info->rtfParam; fmt.wNumberingStart = info->rtfParam;
break; break;
case rtfBorderLeft: case rtfBorderLeft:
info->borderType = RTFBorderParaLeft;
ME_GetSelectionParaFormat(info->editor, &fmt); ME_GetSelectionParaFormat(info->editor, &fmt);
if (!(fmt.dwMask & PFM_BORDER)) if (!(fmt.dwMask & PFM_BORDER))
{ {
...@@ -667,6 +672,7 @@ static void ME_RTFParAttrHook(RTF_Info *info) ...@@ -667,6 +672,7 @@ static void ME_RTFParAttrHook(RTF_Info *info)
fmt.dwMask = PFM_BORDER; fmt.dwMask = PFM_BORDER;
break; break;
case rtfBorderRight: case rtfBorderRight:
info->borderType = RTFBorderParaRight;
ME_GetSelectionParaFormat(info->editor, &fmt); ME_GetSelectionParaFormat(info->editor, &fmt);
if (!(fmt.dwMask & PFM_BORDER)) if (!(fmt.dwMask & PFM_BORDER))
{ {
...@@ -678,6 +684,7 @@ static void ME_RTFParAttrHook(RTF_Info *info) ...@@ -678,6 +684,7 @@ static void ME_RTFParAttrHook(RTF_Info *info)
fmt.dwMask = PFM_BORDER; fmt.dwMask = PFM_BORDER;
break; break;
case rtfBorderTop: case rtfBorderTop:
info->borderType = RTFBorderParaTop;
ME_GetSelectionParaFormat(info->editor, &fmt); ME_GetSelectionParaFormat(info->editor, &fmt);
if (!(fmt.dwMask & PFM_BORDER)) if (!(fmt.dwMask & PFM_BORDER))
{ {
...@@ -689,6 +696,7 @@ static void ME_RTFParAttrHook(RTF_Info *info) ...@@ -689,6 +696,7 @@ static void ME_RTFParAttrHook(RTF_Info *info)
fmt.dwMask = PFM_BORDER; fmt.dwMask = PFM_BORDER;
break; break;
case rtfBorderBottom: case rtfBorderBottom:
info->borderType = RTFBorderParaBottom;
ME_GetSelectionParaFormat(info->editor, &fmt); ME_GetSelectionParaFormat(info->editor, &fmt);
if (!(fmt.dwMask & PFM_BORDER)) if (!(fmt.dwMask & PFM_BORDER))
{ {
...@@ -735,11 +743,24 @@ static void ME_RTFParAttrHook(RTF_Info *info) ...@@ -735,11 +743,24 @@ static void ME_RTFParAttrHook(RTF_Info *info)
fmt.dwMask = PFM_BORDER; fmt.dwMask = PFM_BORDER;
break; break;
case rtfBorderWidth: case rtfBorderWidth:
{
int borderSide = info->borderType & RTFBorderSideMask;
RTFTable *tableDef = info->tableDef;
ME_GetSelectionParaFormat(info->editor, &fmt); ME_GetSelectionParaFormat(info->editor, &fmt);
/* we assume that borders have been created before (RTF spec) */ /* we assume that borders have been created before (RTF spec) */
fmt.wBorderWidth |= ((info->rtfParam / 15) & 7) << 8; 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; fmt.dwMask = PFM_BORDER;
break; break;
}
case rtfBorderSpace: case rtfBorderSpace:
ME_GetSelectionParaFormat(info->editor, &fmt); ME_GetSelectionParaFormat(info->editor, &fmt);
/* we assume that borders have been created before (RTF spec) */ /* we assume that borders have been created before (RTF spec) */
...@@ -760,6 +781,10 @@ static void ME_RTFTblAttrHook(RTF_Info *info) ...@@ -760,6 +781,10 @@ static void ME_RTFTblAttrHook(RTF_Info *info)
{ {
case rtfRowDef: case rtfRowDef:
{ {
if (!info->editor->bEmulateVersion10) /* v4.1 */
info->borderType = 0; /* Not sure */
else /* v1.0 - 3.0 */
info->borderType = RTFBorderRowTop;
if (!info->tableDef) { if (!info->tableDef) {
info->tableDef = ME_MakeTableDef(info->editor); info->tableDef = ME_MakeTableDef(info->editor);
} else { } else {
...@@ -786,6 +811,30 @@ static void ME_RTFTblAttrHook(RTF_Info *info) ...@@ -786,6 +811,30 @@ static void ME_RTFTblAttrHook(RTF_Info *info)
} }
info->tableDef->numCellsDefined++; info->tableDef->numCellsDefined++;
break; 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: case rtfRowGapH:
if (info->tableDef) if (info->tableDef)
info->tableDef->gapH = info->rtfParam; info->tableDef->gapH = info->rtfParam;
...@@ -882,6 +931,10 @@ static void ME_RTFSpecialCharHook(RTF_Info *info) ...@@ -882,6 +931,10 @@ static void ME_RTFSpecialCharHook(RTF_Info *info)
for (i = 0; i < tableDef->numCellsDefined; i++) for (i = 0; i < tableDef->numCellsDefined; i++)
{ {
cell->member.cell.nRightBoundary = tableDef->cells[i].rightBoundary; 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; cell = cell->member.cell.next_cell;
if (!cell) if (!cell)
{ {
......
...@@ -165,6 +165,19 @@ typedef struct tagME_Document { ...@@ -165,6 +165,19 @@ typedef struct tagME_Document {
int last_wrapped_line; int last_wrapped_line;
} ME_Document; } 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 typedef struct tagME_Paragraph
{ {
PARAFORMAT2 *pFmt; PARAFORMAT2 *pFmt;
...@@ -184,8 +197,10 @@ typedef struct tagME_Cell /* v4.1 */ ...@@ -184,8 +197,10 @@ typedef struct tagME_Cell /* v4.1 */
{ {
int nNestingLevel; /* 0 for normal cells, and greater for nested cells */ int nNestingLevel; /* 0 for normal cells, and greater for nested cells */
int nRightBoundary; int nRightBoundary;
ME_BorderRect border;
POINT pt; POINT pt;
int nHeight, nWidth; int nHeight, nWidth;
int yTextOffset; /* The text offset is caused by the largest top border. */
struct tagME_DisplayItem *prev_cell, *next_cell, *parent_cell; struct tagME_DisplayItem *prev_cell, *next_cell, *parent_cell;
} ME_Cell; } ME_Cell;
......
...@@ -247,6 +247,7 @@ void RTFInit(RTF_Info *info) ...@@ -247,6 +247,7 @@ void RTFInit(RTF_Info *info)
info->tableDef = NULL; info->tableDef = NULL;
info->nestingLevel = 0; info->nestingLevel = 0;
info->canInheritInTbl = FALSE; info->canInheritInTbl = FALSE;
info->borderType = 0;
} }
/* /*
......
...@@ -950,6 +950,7 @@ typedef struct RTFFont RTFFont; ...@@ -950,6 +950,7 @@ typedef struct RTFFont RTFFont;
typedef struct RTFColor RTFColor; typedef struct RTFColor RTFColor;
typedef struct RTFStyle RTFStyle; typedef struct RTFStyle RTFStyle;
typedef struct RTFStyleElt RTFStyleElt; typedef struct RTFStyleElt RTFStyleElt;
typedef struct RTFBorder RTFBorder;
typedef struct RTFCell RTFCell; typedef struct RTFCell RTFCell;
typedef struct RTFTable RTFTable; typedef struct RTFTable RTFTable;
...@@ -1006,10 +1007,15 @@ struct RTFStyleElt ...@@ -1006,10 +1007,15 @@ struct RTFStyleElt
RTFStyleElt *rtfNextSE; /* next element in style */ RTFStyleElt *rtfNextSE; /* next element in style */
}; };
struct RTFBorder
{
int width;
};
struct RTFCell struct RTFCell
{ {
int rightBoundary; int rightBoundary;
RTFBorder border[4];
}; };
...@@ -1019,6 +1025,8 @@ struct RTFTable ...@@ -1019,6 +1025,8 @@ struct RTFTable
int numCellsDefined; int numCellsDefined;
int gapH, leftEdge; int gapH, leftEdge;
/* borders for the table row */
RTFBorder border[6];
/* Used in v1.0 - v3.0 */ /* Used in v1.0 - v3.0 */
int numCellsInserted; int numCellsInserted;
...@@ -1033,6 +1041,40 @@ struct RTFTable ...@@ -1033,6 +1041,40 @@ struct RTFTable
RTFTable *parent; 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 * Return pointer to new element of type t, or NULL
* if no memory available. * if no memory available.
...@@ -1141,6 +1183,7 @@ struct _RTF_Info { ...@@ -1141,6 +1183,7 @@ struct _RTF_Info {
RTFTable *tableDef; RTFTable *tableDef;
int nestingLevel; int nestingLevel;
BOOL canInheritInTbl; BOOL canInheritInTbl;
int borderType; /* value corresponds to the RTFBorder constants. */
}; };
......
...@@ -608,6 +608,7 @@ struct RTFTable *ME_MakeTableDef(ME_TextEditor *editor) ...@@ -608,6 +608,7 @@ struct RTFTable *ME_MakeTableDef(ME_TextEditor *editor)
void ME_InitTableDef(ME_TextEditor *editor, struct RTFTable *tableDef) void ME_InitTableDef(ME_TextEditor *editor, struct RTFTable *tableDef)
{ {
ZeroMemory(tableDef->cells, sizeof(tableDef->cells)); ZeroMemory(tableDef->cells, sizeof(tableDef->cells));
ZeroMemory(tableDef->border, sizeof(tableDef->border));
tableDef->numCellsDefined = 0; tableDef->numCellsDefined = 0;
tableDef->leftEdge = 0; tableDef->leftEdge = 0;
if (!editor->bEmulateVersion10) /* v4.1 */ if (!editor->bEmulateVersion10) /* v4.1 */
......
...@@ -606,8 +606,24 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) { ...@@ -606,8 +606,24 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
{ {
ME_DisplayItem *cell = ME_FindItemFwd(item, diCell); ME_DisplayItem *cell = ME_FindItemFwd(item, diCell);
ME_DisplayItem *endRowPara; ME_DisplayItem *endRowPara;
int borderWidth = 0;
cell->member.cell.pt = c.pt; 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) if (endRowPara->member.para.pFmt->dxStartIndent > 0)
{ {
int dxStartIndent = endRowPara->member.para.pFmt->dxStartIndent; int dxStartIndent = endRowPara->member.para.pFmt->dxStartIndent;
...@@ -620,13 +636,26 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) { ...@@ -620,13 +636,26 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
{ {
/* Set all the cells to the height of the largest cell */ /* Set all the cells to the height of the largest cell */
ME_DisplayItem *startRowPara; ME_DisplayItem *startRowPara;
int prevHeight, nHeight; int prevHeight, nHeight, bottomBorder = 0;
ME_DisplayItem *cell = ME_FindItemBack(item, diCell); 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; 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; cell->member.cell.nHeight = nHeight;
item->member.para.nHeight = nHeight; item->member.para.nHeight = nHeight;
cell = cell->member.cell.prev_cell; cell = cell->member.cell.prev_cell;
cell->member.cell.nHeight = nHeight;
while (cell->member.cell.prev_cell) while (cell->member.cell.prev_cell)
{ {
cell = cell->member.cell.prev_cell; cell = cell->member.cell.prev_cell;
...@@ -664,6 +693,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) { ...@@ -664,6 +693,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
c.pt.x = cell->pt.x + cell->nWidth; c.pt.x = cell->pt.x + cell->nWidth;
c.pt.y = cell->pt.y; c.pt.y = cell->pt.y;
cell->next_cell->member.cell.pt = c.pt; cell->next_cell->member.cell.pt = c.pt;
c.pt.y += cell->yTextOffset;
} }
else else
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment