richedit: Added in support for streaming in and out nested tables.

This commit is contained in:
Dylan Smith 2008-08-07 12:31:46 -04:00 committed by Alexandre Julliard
parent 300db3765f
commit 59195ed2ec
4 changed files with 135 additions and 28 deletions

View File

@ -482,6 +482,7 @@ static void ME_RTFParAttrHook(RTF_Info *info)
* table anymore. * table anymore.
*/ */
info->tableDef->tableRowStart = NULL; info->tableDef->tableRowStart = NULL;
info->canInheritInTbl = FALSE;
} }
} }
} else { /* v1.0 - v3.0 */ } else { /* v1.0 - v3.0 */
@ -489,13 +490,42 @@ static void ME_RTFParAttrHook(RTF_Info *info)
fmt.wEffects &= ~PFE_TABLE; fmt.wEffects &= ~PFE_TABLE;
} }
break; break;
case rtfInTable: case rtfNestLevel:
{
ME_Cursor cursor;
if (!info->editor->bEmulateVersion10) /* v4.1 */ if (!info->editor->bEmulateVersion10) /* v4.1 */
{ {
if (!info->tableDef || !info->tableDef->tableRowStart || while (info->rtfParam > info->nestingLevel) {
info->tableDef->tableRowStart->member.para.nFlags & MEPF_ROWEND) RTFTable *tableDef = ALLOC_OBJ(RTFTable);
ZeroMemory(tableDef, sizeof(RTFTable));
tableDef->parent = info->tableDef;
info->tableDef = tableDef;
RTFFlushOutputBuffer(info);
if (tableDef->tableRowStart &&
tableDef->tableRowStart->member.para.nFlags & MEPF_ROWEND)
{
ME_DisplayItem *para = tableDef->tableRowStart;
para = para->member.para.next_para;
para = ME_InsertTableRowStartAtParagraph(info->editor, para);
tableDef->tableRowStart = para;
} else {
ME_Cursor cursor;
WCHAR endl = '\r';
cursor = info->editor->pCursors[0];
if (cursor.nOffset || cursor.pRun->member.run.nCharOfs)
ME_InsertTextFromCursor(info->editor, 0, &endl, 1, info->style);
tableDef->tableRowStart = ME_InsertTableRowStartFromCursor(info->editor);
}
info->nestingLevel++;
}
info->canInheritInTbl = FALSE;
}
break;
case rtfInTable:
{
if (!info->editor->bEmulateVersion10) /* v4.1 */
{
if (info->nestingLevel < 1)
{ {
RTFTable *tableDef; RTFTable *tableDef;
if (!info->tableDef) if (!info->tableDef)
@ -505,19 +535,23 @@ static void ME_RTFParAttrHook(RTF_Info *info)
} }
tableDef = info->tableDef; tableDef = info->tableDef;
RTFFlushOutputBuffer(info); RTFFlushOutputBuffer(info);
if (!tableDef->tableRowStart) if (tableDef->tableRowStart &&
tableDef->tableRowStart->member.para.nFlags & MEPF_ROWEND)
{ {
ME_DisplayItem *para = tableDef->tableRowStart;
para = para->member.para.next_para;
para = ME_InsertTableRowStartAtParagraph(info->editor, para);
tableDef->tableRowStart = para;
} else {
ME_Cursor cursor;
WCHAR endl = '\r'; WCHAR endl = '\r';
cursor = info->editor->pCursors[0]; cursor = info->editor->pCursors[0];
if (cursor.nOffset || cursor.pRun->member.run.nCharOfs) if (cursor.nOffset || cursor.pRun->member.run.nCharOfs)
ME_InsertTextFromCursor(info->editor, 0, &endl, 1, info->style); ME_InsertTextFromCursor(info->editor, 0, &endl, 1, info->style);
tableDef->tableRowStart = ME_InsertTableRowStartFromCursor(info->editor);
} }
info->nestingLevel = 1;
/* FIXME: Remove the following condition once nested tables are supported */ info->canInheritInTbl = TRUE;
if (ME_GetParagraph(info->editor->pCursors[0].pRun)->member.para.pCell)
break;
tableDef->tableRowStart = ME_InsertTableRowStartFromCursor(info->editor);
} }
return; return;
} else { /* v1.0 - v3.0 */ } else { /* v1.0 - v3.0 */
@ -763,6 +797,10 @@ static void ME_RTFSpecialCharHook(RTF_Info *info)
RTFTable *tableDef = info->tableDef; RTFTable *tableDef = info->tableDef;
switch (info->rtfMinor) switch (info->rtfMinor)
{ {
case rtfNestCell:
if (info->editor->bEmulateVersion10) /* v1.0 - v3.0 */
break;
/* else fall through since v4.1 treats rtfNestCell and rtfCell the same */
case rtfCell: case rtfCell:
if (!tableDef) if (!tableDef)
break; break;
@ -770,12 +808,14 @@ static void ME_RTFSpecialCharHook(RTF_Info *info)
if (!info->editor->bEmulateVersion10) { /* v4.1 */ if (!info->editor->bEmulateVersion10) { /* v4.1 */
if (tableDef->tableRowStart) if (tableDef->tableRowStart)
{ {
if (tableDef->tableRowStart->member.para.nFlags & MEPF_ROWEND) if (!info->nestingLevel &&
tableDef->tableRowStart->member.para.nFlags & MEPF_ROWEND)
{ {
ME_DisplayItem *para = tableDef->tableRowStart; ME_DisplayItem *para = tableDef->tableRowStart;
para = para->member.para.next_para; para = para->member.para.next_para;
para = ME_InsertTableRowStartAtParagraph(info->editor, para); para = ME_InsertTableRowStartAtParagraph(info->editor, para);
tableDef->tableRowStart = para; tableDef->tableRowStart = para;
info->nestingLevel = 1;
} }
ME_InsertTableCellFromCursor(info->editor); ME_InsertTableCellFromCursor(info->editor);
} }
@ -791,6 +831,10 @@ static void ME_RTFSpecialCharHook(RTF_Info *info)
} }
} }
break; break;
case rtfNestRow:
if (info->editor->bEmulateVersion10) /* v1.0 - v3.0 */
break;
/* else fall through since v4.1 treats rtfNestRow and rtfRow the same */
case rtfRow: case rtfRow:
{ {
ME_DisplayItem *para, *cell, *run; ME_DisplayItem *para, *cell, *run;
@ -802,12 +846,14 @@ static void ME_RTFSpecialCharHook(RTF_Info *info)
if (!info->editor->bEmulateVersion10) { /* v4.1 */ if (!info->editor->bEmulateVersion10) { /* v4.1 */
if (!tableDef->tableRowStart) if (!tableDef->tableRowStart)
break; break;
if (tableDef->tableRowStart->member.para.nFlags & MEPF_ROWEND) if (!info->nestingLevel &&
tableDef->tableRowStart->member.para.nFlags & MEPF_ROWEND)
{ {
para = tableDef->tableRowStart; para = tableDef->tableRowStart;
para = para->member.para.next_para; para = para->member.para.next_para;
para = ME_InsertTableRowStartAtParagraph(info->editor, para); para = ME_InsertTableRowStartAtParagraph(info->editor, para);
tableDef->tableRowStart = para; tableDef->tableRowStart = para;
info->nestingLevel++;
} }
para = tableDef->tableRowStart; para = tableDef->tableRowStart;
cell = ME_FindItemFwd(para, diCell); cell = ME_FindItemFwd(para, diCell);
@ -855,7 +901,23 @@ static void ME_RTFSpecialCharHook(RTF_Info *info)
ME_InternalDeleteText(info->editor, nOfs, nChars, TRUE); ME_InternalDeleteText(info->editor, nOfs, nChars, TRUE);
} }
tableDef->tableRowStart = ME_InsertTableRowEndFromCursor(info->editor); para = ME_InsertTableRowEndFromCursor(info->editor);
info->nestingLevel--;
if (!info->nestingLevel)
{
if (info->canInheritInTbl) {
tableDef->tableRowStart = para;
} else {
while (info->tableDef) {
tableDef = info->tableDef;
info->tableDef = tableDef->parent;
heap_free(tableDef);
}
}
} else {
info->tableDef = tableDef->parent;
heap_free(tableDef);
}
} else { /* v1.0 - v3.0 */ } else { /* v1.0 - v3.0 */
WCHAR endl = '\r'; WCHAR endl = '\r';
ME_DisplayItem *para = ME_GetParagraph(info->editor->pCursors[0].pRun); ME_DisplayItem *para = ME_GetParagraph(info->editor->pCursors[0].pRun);
@ -1276,6 +1338,8 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
RTFSetReadHook(&parser, ME_RTFReadHook); RTFSetReadHook(&parser, ME_RTFReadHook);
RTFSetDestinationCallback(&parser, rtfPict, ME_RTFReadPictGroup); RTFSetDestinationCallback(&parser, rtfPict, ME_RTFReadPictGroup);
RTFSetDestinationCallback(&parser, rtfObject, ME_RTFReadObjectGroup); RTFSetDestinationCallback(&parser, rtfObject, ME_RTFReadObjectGroup);
if (!parser.editor->bEmulateVersion10) /* v4.1 */
RTFSetDestinationCallback(&parser, rtfNoNestTables, RTFSkipGroup);
BeginFile(&parser); BeginFile(&parser);
/* do the parsing */ /* do the parsing */
@ -1295,8 +1359,15 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
* By doing it this way we will have the current paragraph format set * By doing it this way we will have the current paragraph format set
* properly to reflect that is not in the complete table, and undo items * properly to reflect that is not in the complete table, and undo items
* will be added for this change to the current paragraph format. */ * will be added for this change to the current paragraph format. */
ME_RTFSpecialCharHook(&parser); if (parser.nestingLevel > 0)
if (para->member.para.nFlags & MEPF_ROWEND) {
while (parser.nestingLevel--)
ME_RTFSpecialCharHook(&parser);
} else if (parser.canInheritInTbl) {
ME_RTFSpecialCharHook(&parser);
}
if (parser.tableDef && parser.tableDef->tableRowStart &&
para->member.para.nFlags & MEPF_ROWEND)
{ {
para = para->member.para.next_para; para = para->member.para.next_para;
} }

View File

@ -169,10 +169,11 @@ RTFDestroy(RTF_Info *info)
} }
RTFDestroyAttrs(info); RTFDestroyAttrs(info);
heap_free(info->cpOutputBuffer); heap_free(info->cpOutputBuffer);
if (info->tableDef) while (info->tableDef)
{ {
heap_free(info->tableDef); RTFTable *tableDef = info->tableDef;
info->tableDef = NULL; info->tableDef = tableDef->parent;
heap_free(tableDef);
} }
} }
@ -244,6 +245,8 @@ void RTFInit(RTF_Info *info)
if (info->tableDef) if (info->tableDef)
ZeroMemory(info->tableDef, sizeof(info->tableDef)); ZeroMemory(info->tableDef, sizeof(info->tableDef));
info->tableDef = NULL; info->tableDef = NULL;
info->nestingLevel = 0;
info->canInheritInTbl = FALSE;
} }
/* /*
@ -1447,6 +1450,8 @@ static RTFKey rtfKey[] =
/* is this valid? */ /* is this valid? */
{ rtfSpecialChar, rtfCurHeadPict, "chpict", 0 }, { rtfSpecialChar, rtfCurHeadPict, "chpict", 0 },
{ rtfSpecialChar, rtfUnicode, "u", 0 }, { rtfSpecialChar, rtfUnicode, "u", 0 },
{ rtfSpecialChar, rtfNestCell, "nestcell", 0 },
{ rtfSpecialChar, rtfNestRow, "nestrow", 0 },
/* /*
* Character formatting attributes * Character formatting attributes
@ -1610,6 +1615,7 @@ static RTFKey rtfKey[] =
{ rtfParAttr, rtfDarkDiagHatchBgPat, "bgdkdcross", 0 }, { rtfParAttr, rtfDarkDiagHatchBgPat, "bgdkdcross", 0 },
{ rtfParAttr, rtfBgPatLineColor, "cfpat", 0 }, { rtfParAttr, rtfBgPatLineColor, "cfpat", 0 },
{ rtfParAttr, rtfBgPatColor, "cbpat", 0 }, { rtfParAttr, rtfBgPatColor, "cbpat", 0 },
{ rtfParAttr, rtfNestLevel, "itap", 0 },
/* /*
* Section formatting attributes * Section formatting attributes
@ -1912,6 +1918,8 @@ static RTFKey rtfKey[] =
{ rtfDestination, rtfIndexRange, "rxe", 0 }, { rtfDestination, rtfIndexRange, "rxe", 0 },
{ rtfDestination, rtfTOC, "tc", 0 }, { rtfDestination, rtfTOC, "tc", 0 },
{ rtfDestination, rtfNeXTGraphic, "NeXTGraphic", 0 }, { rtfDestination, rtfNeXTGraphic, "NeXTGraphic", 0 },
{ rtfDestination, rtfNestTableProps, "nesttableprops", 0 },
{ rtfDestination, rtfNoNestTables, "nonesttables", 0 },
/* /*
* Font families * Font families

View File

@ -182,7 +182,9 @@
# define rtfTOC 72 # define rtfTOC 72
# define rtfNeXTGraphic 73 # define rtfNeXTGraphic 73
# define rtfGenerator 74 # define rtfGenerator 74
# define rtfMaxDestination 75 /* highest dest + 1 */ # define rtfNestTableProps 75
# define rtfNoNestTables 76
# define rtfMaxDestination 77 /* highest dest + 1 */
# define rtfFontFamily 4 # define rtfFontFamily 4
# define rtfFFNil 0 # define rtfFFNil 0
@ -261,6 +263,8 @@
# define rtfCurHeadPict 57 /* valid? */ # define rtfCurHeadPict 57 /* valid? */
/*# define rtfCurAnnot 58*/ /* apparently not used */ /*# define rtfCurAnnot 58*/ /* apparently not used */
# define rtfUnicode 58 /* no better category*/ # define rtfUnicode 58 /* no better category*/
# define rtfNestCell 59
# define rtfNestRow 60
# define rtfStyleAttr 7 # define rtfStyleAttr 7
# define rtfAdditive 0 /* new in 1.10 */ # define rtfAdditive 0 /* new in 1.10 */
@ -551,6 +555,7 @@
# define rtfDarkDiagHatchBgPat 101 # define rtfDarkDiagHatchBgPat 101
# define rtfBgPatLineColor 102 # define rtfBgPatLineColor 102
# define rtfBgPatColor 103 # define rtfBgPatColor 103
# define rtfNestLevel 104
# define rtfCharAttr 12 # define rtfCharAttr 12
# define rtfPlain 0 # define rtfPlain 0
@ -1020,7 +1025,10 @@ struct RTFTable
/* tableRowStart may be the start row paragraph of the table row, /* tableRowStart may be the start row paragraph of the table row,
* or it may store the end of the previous row if it may still be * or it may store the end of the previous row if it may still be
* continued, otherwise NULL is stored. */ * continued, otherwise NULL is stored. */
ME_DisplayItem *tableRowStart; ME_DisplayItem *tableRowStart;
/* Table definitions are stored as a stack to support nested tables. */
RTFTable *parent;
}; };
/* /*
@ -1129,6 +1137,8 @@ struct _RTF_Info {
LPRICHEDITOLE lpRichEditOle; LPRICHEDITOLE lpRichEditOle;
RTFTable *tableDef; RTFTable *tableDef;
int nestingLevel;
BOOL canInheritInTbl;
}; };

View File

@ -334,6 +334,8 @@ ME_StreamOutRTFParaProps(ME_TextEditor *editor, ME_OutStream *pStream,
if (!editor->bEmulateVersion10) { /* v4.1 */ if (!editor->bEmulateVersion10) { /* v4.1 */
if (pStream->nNestingLevel > 0) if (pStream->nNestingLevel > 0)
strcat(props, "\\intbl"); strcat(props, "\\intbl");
if (pStream->nNestingLevel > 1)
sprintf(props + strlen(props), "\\itap%d", pStream->nNestingLevel);
} else { /* v1.0 - 3.0 */ } else { /* v1.0 - 3.0 */
if (fmt->dwMask & PFM_TABLE && fmt->wEffects & PFE_TABLE) if (fmt->dwMask & PFM_TABLE && fmt->wEffects & PFE_TABLE)
strcat(props, "\\intbl"); strcat(props, "\\intbl");
@ -715,12 +717,23 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC
if (!editor->bEmulateVersion10) { /* v4.1 */ if (!editor->bEmulateVersion10) { /* v4.1 */
if (p->member.para.nFlags & MEPF_ROWSTART) { if (p->member.para.nFlags & MEPF_ROWSTART) {
pStream->nNestingLevel++; pStream->nNestingLevel++;
if (!ME_StreamOutRTFTableProps(editor, pStream, p)) if (pStream->nNestingLevel == 1) {
return FALSE; if (!ME_StreamOutRTFTableProps(editor, pStream, p))
return FALSE;
}
} else if (p->member.para.nFlags & MEPF_ROWEND) { } else if (p->member.para.nFlags & MEPF_ROWEND) {
pStream->nNestingLevel--; pStream->nNestingLevel--;
if (!ME_StreamOutPrint(pStream, "\\row \r\n")) if (pStream->nNestingLevel > 1) {
return FALSE; if (!ME_StreamOutPrint(pStream, "{\\*\\nesttableprops"))
return FALSE;
if (!ME_StreamOutRTFTableProps(editor, pStream, p))
return FALSE;
if (!ME_StreamOutPrint(pStream, "\\nestrow}{\\nonesttables\\par}\r\n"))
return FALSE;
} else {
if (!ME_StreamOutPrint(pStream, "\\row \r\n"))
return FALSE;
}
} else if (!ME_StreamOutRTFParaProps(editor, pStream, p)) { } else if (!ME_StreamOutRTFParaProps(editor, pStream, p)) {
return FALSE; return FALSE;
} }
@ -757,8 +770,13 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC
return FALSE; return FALSE;
} }
} else if (p->member.run.nFlags & MERF_ENDCELL) { } else if (p->member.run.nFlags & MERF_ENDCELL) {
if (!ME_StreamOutPrint(pStream, "\\cell ")) if (pStream->nNestingLevel > 1) {
return FALSE; if (!ME_StreamOutPrint(pStream, "\\nestcell "))
return FALSE;
} else {
if (!ME_StreamOutPrint(pStream, "\\cell "))
return FALSE;
}
nChars--; nChars--;
} else if (p->member.run.nFlags & MERF_ENDPARA) { } else if (p->member.run.nFlags & MERF_ENDPARA) {
if (pPara->member.para.pFmt->dwMask & PFM_TABLE && if (pPara->member.para.pFmt->dwMask & PFM_TABLE &&