From 11c80396995065701205f2facb3dba10a6f8170f Mon Sep 17 00:00:00 2001 From: Dylan Smith Date: Mon, 4 Aug 2008 19:18:54 -0400 Subject: [PATCH] richedit: Use tabstops to store cell positions. --- dlls/riched20/caret.c | 27 ---------- dlls/riched20/editor.c | 106 +++++++++++++++++++++++++++------------- dlls/riched20/editor.h | 2 - dlls/riched20/editstr.h | 14 +----- dlls/riched20/list.c | 18 ------- dlls/riched20/paint.c | 2 +- dlls/riched20/para.c | 29 ----------- dlls/riched20/reader.c | 10 +++- dlls/riched20/rtf.h | 18 ++++++- dlls/riched20/run.c | 9 +--- dlls/riched20/writer.c | 57 +++++++++++++-------- 11 files changed, 140 insertions(+), 152 deletions(-) diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c index 30bb9563668..3f89398524c 100644 --- a/dlls/riched20/caret.c +++ b/dlls/riched20/caret.c @@ -432,33 +432,6 @@ void ME_InsertEndRowFromCursor(ME_TextEditor *editor, int nCursor) ME_SendSelChange(editor); } -void -ME_InsertTableCellFromCursor(ME_TextEditor *editor, int nCursor) -{ - WCHAR tab = '\t'; - ME_DisplayItem *p, *run; - ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor); - - p = ME_InternalInsertTextFromCursor(editor, nCursor, &tab, 1, pStyle, - MERF_CELL); - run = p; - while ((run = ME_FindItemBack(run, diRunOrParagraph))->type == diRun) - { - if (run->member.run.nFlags & MERF_CELL) - { - assert(run->member.run.pCell->next); - p->member.run.pCell = run->member.run.pCell->next; - return; - } - } - assert(run->type == diParagraph); - assert(run->member.para.pFmt); - assert(run->member.para.pFmt->dwMask & PFM_TABLE); - assert(run->member.para.pFmt->wEffects & PFE_TABLE); - assert(run->member.para.pCells); - p->member.run.pCell = run->member.para.pCells; -} - void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor, const WCHAR *str, int len, ME_Style *style) diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index db9728c3c10..b5d1df5f279 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -466,11 +466,6 @@ static void ME_RTFParAttrHook(RTF_Info *info) break; case rtfInTable: { - ME_DisplayItem *para; - - RTFFlushOutputBuffer(info); - para = ME_GetParagraph(info->editor->pCursors[0].pRun); - assert(para->member.para.pCells); fmt.dwMask |= PFM_TABLE; fmt.wEffects |= PFE_TABLE; break; @@ -512,7 +507,7 @@ static void ME_RTFParAttrHook(RTF_Info *info) fmt.dwMask |= PFM_TABSTOPS; fmt.cTabCount = 0; } - if (fmt.cTabCount < MAX_TAB_STOPS) + if (fmt.cTabCount < MAX_TAB_STOPS && info->rtfParam < 0x1000000) fmt.rgxTabs[fmt.cTabCount++] = info->rtfParam; break; case rtfKeep: @@ -666,35 +661,83 @@ static void ME_RTFParAttrHook(RTF_Info *info) static void ME_RTFTblAttrHook(RTF_Info *info) { - ME_DisplayItem *para; - switch (info->rtfMinor) { case rtfRowDef: - RTFFlushOutputBuffer(info); - para = ME_GetParagraph(info->editor->pCursors[0].pRun); - - /* Release possibly inherited cell definitions */ - ME_DestroyTableCellList(para); - - para->member.para.pCells = ALLOC_OBJ(ME_TableCell); - para->member.para.pCells->nRightBoundary = 0; - para->member.para.pCells->next = NULL; - para->member.para.pLastCell = para->member.para.pCells; + if (!info->tableDef) + info->tableDef = ALLOC_OBJ(RTFTable); + ZeroMemory(info->tableDef, sizeof(RTFTable)); break; case rtfCellPos: - RTFFlushOutputBuffer(info); - para = ME_GetParagraph(info->editor->pCursors[0].pRun); - - if (para->member.para.pLastCell->nRightBoundary) + if (!info->tableDef) { - ME_TableCell *pCell = ALLOC_OBJ(ME_TableCell); - - pCell->next = NULL; - para->member.para.pLastCell->next = pCell; - para->member.para.pLastCell = pCell; + info->tableDef = ALLOC_OBJ(RTFTable); + ZeroMemory(info->tableDef, sizeof(RTFTable)); } - para->member.para.pLastCell->nRightBoundary = info->rtfParam; + if (info->tableDef->numCellsDefined >= MAX_TABLE_CELLS) + break; + info->tableDef->cells[info->tableDef->numCellsDefined].rightBoundary = info->rtfParam; + { + /* Tab stops store the cell positions. */ + ME_DisplayItem *para = ME_GetParagraph(info->editor->pCursors[0].pRun); + PARAFORMAT2 *pFmt = para->member.para.pFmt; + int cellNum = info->tableDef->numCellsDefined; + pFmt->rgxTabs[cellNum] &= ~0x00FFFFFF; + pFmt->rgxTabs[cellNum] = 0x00FFFFFF & info->rtfParam; + } + info->tableDef->numCellsDefined++; + break; + } +} + +static void ME_RTFSpecialCharHook(RTF_Info *info) +{ + RTFTable *tableDef = info->tableDef; + switch (info->rtfMinor) + { + case rtfCell: + if (!tableDef) + break; + RTFFlushOutputBuffer(info); + { + ME_DisplayItem *para = ME_GetParagraph(info->editor->pCursors[0].pRun); + PARAFORMAT2 *pFmt = para->member.para.pFmt; + if (pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE && + tableDef->numCellsInserted < tableDef->numCellsDefined) + { + WCHAR tab = '\t'; + ME_InsertTextFromCursor(info->editor, 0, &tab, 1, info->style); + tableDef->numCellsInserted++; + } + } + break; + case rtfRow: + { + if (!tableDef) + break; + RTFFlushOutputBuffer(info); + + { + WCHAR endl = '\r'; + ME_DisplayItem *para = ME_GetParagraph(info->editor->pCursors[0].pRun); + PARAFORMAT2 *pFmt = para->member.para.pFmt; + while (tableDef->numCellsInserted < tableDef->numCellsDefined) + { + WCHAR tab = '\t'; + ME_InsertTextFromCursor(info->editor, 0, &tab, 1, info->style); + tableDef->numCellsInserted++; + } + pFmt->cTabCount = tableDef->numCellsDefined; + if (!tableDef->numCellsDefined) + pFmt->wEffects &= ~PFE_TABLE; + ME_InsertTextFromCursor(info->editor, 0, &endl, 1, info->style); + tableDef->numCellsInserted = 0; + } + break; + } + case rtfPar: + if (tableDef) + tableDef->numCellsInserted = 0; break; } } @@ -1001,11 +1044,8 @@ static void ME_RTFReadHook(RTF_Info *info) { ME_RTFTblAttrHook(info); break; case rtfSpecialChar: - if (info->rtfMinor == rtfCell) - { - RTFFlushOutputBuffer(info); - ME_InsertTableCellFromCursor(info->editor, 0); - } + ME_RTFSpecialCharHook(info); + break; } break; } diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index 6e0733121d5..51f7e5375be 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -84,7 +84,6 @@ ME_DisplayItem *ME_FindItemFwdOrHere(ME_DisplayItem *di, ME_DIType nTypeOrClass) BOOL ME_DITypesEqual(ME_DIType type, ME_DIType nTypeOrClass); ME_DisplayItem *ME_MakeDI(ME_DIType type); void ME_DestroyDisplayItem(ME_DisplayItem *item); -void ME_DestroyTableCellList(ME_DisplayItem *item); void ME_DumpDocument(ME_TextBuffer *buffer); const char *ME_GetDITypeName(ME_DIType type); @@ -199,7 +198,6 @@ BOOL ME_IsSelection(ME_TextEditor *editor); void ME_DeleteSelection(ME_TextEditor *editor); void ME_SendSelChange(ME_TextEditor *editor); void ME_InsertOLEFromCursor(ME_TextEditor *editor, const REOBJECT* reo, int nCursor); -void ME_InsertTableCellFromCursor(ME_TextEditor *editor, int nCursor); void ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars); int ME_GetTextLength(ME_TextEditor *editor); int ME_GetTextLengthEx(ME_TextEditor *editor, const GETTEXTLENGTHEX *how); diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h index ba0c0d2d210..9e2e84fff12 100644 --- a/dlls/riched20/editstr.h +++ b/dlls/riched20/editstr.h @@ -97,10 +97,8 @@ typedef enum { #define MERF_GRAPHICS 0x001 /* run is a tab (or, in future, any kind of content whose size is dependent on run position) */ #define MERF_TAB 0x002 -/* run is a cell boundary */ -#define MERF_CELL 0x004 -#define MERF_NONTEXT (MERF_GRAPHICS | MERF_TAB | MERF_CELL) +#define MERF_NONTEXT (MERF_GRAPHICS | MERF_TAB) /* run is splittable (contains white spaces in the middle or end) */ #define MERF_SPLITTABLE 0x001000 @@ -148,7 +146,6 @@ typedef struct tagME_Run int nFlags; int nAscent, nDescent; /* pixels above/below baseline */ POINT pt; /* relative to para's position */ - struct tagME_TableCell *pCell; /* for MERF_CELL: points to respective cell in ME_Paragraph */ REOBJECT *ole_obj; /* FIXME: should be a union with strText (at least) */ int nCR; int nLF; /* for MERF_ENDPARA: number of \r and \n characters encoded by run */ } ME_Run; @@ -159,19 +156,10 @@ typedef struct tagME_Document { int last_wrapped_line; } ME_Document; -typedef struct tagME_TableCell -{ - int nRightBoundary; - struct tagME_TableCell *next; -} ME_TableCell; - typedef struct tagME_Paragraph { PARAFORMAT2 *pFmt; - struct tagME_TableCell *pCells; /* list of cells and their properties */ - struct tagME_TableCell *pLastCell; /* points to the last cell in the list */ - int nCharOfs; int nFlags; int nYPos, nHeight; diff --git a/dlls/riched20/list.c b/dlls/riched20/list.c index 0b14aec0d69..87f55136b6c 100644 --- a/dlls/riched20/list.c +++ b/dlls/riched20/list.c @@ -112,7 +112,6 @@ void ME_DestroyDisplayItem(ME_DisplayItem *item) { /* TRACE("type=%s\n", ME_GetDITypeName(item->type)); */ if (item->type==diParagraph || item->type == diUndoSetParagraphFormat) { FREE_OBJ(item->member.para.pFmt); - ME_DestroyTableCellList(item); } if (item->type==diRun || item->type == diUndoInsertRun) { if (item->member.run.ole_obj) ME_DeleteReObject(item->member.run.ole_obj); @@ -127,23 +126,6 @@ void ME_DestroyDisplayItem(ME_DisplayItem *item) { FREE_OBJ(item); } -void -ME_DestroyTableCellList(ME_DisplayItem *item) -{ - if (item->member.para.pCells) - { - ME_TableCell *pCell = item->member.para.pCells; - ME_TableCell *pNext; - - while (pCell) { - pNext = pCell->next; - FREE_OBJ(pCell); - pCell = pNext; - } - item->member.para.pCells = NULL; - } -} - ME_DisplayItem *ME_MakeDI(ME_DIType type) { ME_DisplayItem *item = ALLOC_OBJ(ME_DisplayItem); ZeroMemory(item, sizeof(ME_DisplayItem)); diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c index adae4cb8097..921d3faaed5 100644 --- a/dlls/riched20/paint.c +++ b/dlls/riched20/paint.c @@ -400,7 +400,7 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa return; } - if (run->nFlags & (MERF_TAB | MERF_CELL)) + if (run->nFlags & MERF_TAB) { /* wszSpace is used instead of the tab character because otherwise * an unwanted symbol can be inserted instead. */ diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c index 4da17217083..4ac234dcda5 100644 --- a/dlls/riched20/para.c +++ b/dlls/riched20/para.c @@ -144,35 +144,6 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, ME /* FIXME initialize format style and call ME_SetParaFormat blah blah */ *new_para->member.para.pFmt = *run_para->member.para.pFmt; - /* Inherit previous cell definitions if any */ - new_para->member.para.pCells = NULL; - if (run_para->member.para.pCells) - { - ME_TableCell *pCell, *pNewCell; - - for (pCell = run_para->member.para.pCells; pCell; pCell = pCell->next) - { - pNewCell = ALLOC_OBJ(ME_TableCell); - pNewCell->nRightBoundary = pCell->nRightBoundary; - pNewCell->next = NULL; - if (new_para->member.para.pCells) - new_para->member.para.pLastCell->next = pNewCell; - else - new_para->member.para.pCells = pNewCell; - new_para->member.para.pLastCell = pNewCell; - } - } - - /* fix paragraph properties. FIXME only needed when called from RTF reader */ - if (run_para->member.para.pCells && - !(run_para->member.para.pFmt->wEffects & PFE_TABLE - && run_para->member.para.pFmt->dwMask & PFM_TABLE)) - { - /* Paragraph does not have an \intbl keyword, so any table definition - * stored is invalid */ - ME_DestroyTableCellList(run_para); - } - /* insert paragraph into paragraph double linked list */ new_para->member.para.prev_para = run_para; new_para->member.para.next_para = next_para; diff --git a/dlls/riched20/reader.c b/dlls/riched20/reader.c index f456a09fdc3..82038f69cdf 100644 --- a/dlls/riched20/reader.c +++ b/dlls/riched20/reader.c @@ -169,6 +169,11 @@ RTFDestroy(RTF_Info *info) } RTFDestroyAttrs(info); heap_free(info->cpOutputBuffer); + if (info->tableDef) + { + heap_free(info->tableDef); + info->tableDef = NULL; + } } @@ -235,6 +240,10 @@ void RTFInit(RTF_Info *info) info->dwMaxCPOutputCount = 0x1000; info->cpOutputBuffer = heap_alloc(info->dwMaxCPOutputCount); } + + if (info->tableDef) + ZeroMemory(info->tableDef, sizeof(info->tableDef)); + info->tableDef = NULL; } /* @@ -2605,7 +2614,6 @@ static void SpecialChar (RTF_Info *info) break; case rtfPage: case rtfSect: - case rtfRow: case rtfPar: RTFPutUnicodeChar (info, '\r'); if (info->editor->bEmulateVersion10) RTFPutUnicodeChar (info, '\n'); diff --git a/dlls/riched20/rtf.h b/dlls/riched20/rtf.h index 8b39f60f647..87bab166253 100644 --- a/dlls/riched20/rtf.h +++ b/dlls/riched20/rtf.h @@ -945,7 +945,8 @@ typedef struct RTFFont RTFFont; typedef struct RTFColor RTFColor; typedef struct RTFStyle RTFStyle; typedef struct RTFStyleElt RTFStyleElt; - +typedef struct RTFCell RTFCell; +typedef struct RTFTable RTFTable; struct RTFFont { @@ -1001,6 +1002,19 @@ struct RTFStyleElt }; +struct RTFCell +{ + int rightBoundary; +}; + + +struct RTFTable +{ + RTFCell cells[MAX_TABLE_CELLS]; + int numCellsDefined; + int numCellsInserted; +}; + /* * Return pointer to new element of type t, or NULL * if no memory available. @@ -1105,6 +1119,8 @@ struct _RTF_Info { int stackTop; BOOL styleChanged; LPRICHEDITOLE lpRichEditOle; + + RTFTable *tableDef; }; diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c index 19ebf1b7cfd..e7ce035980c 100644 --- a/dlls/riched20/run.c +++ b/dlls/riched20/run.c @@ -483,7 +483,7 @@ int ME_CharFromPoint(ME_Context *c, int cx, ME_Run *run) if (!run->strText->nLen) return 0; - if (run->nFlags & (MERF_TAB | MERF_CELL)) + if (run->nFlags & MERF_TAB) { if (cx < run->nWidth/2) return 0; @@ -540,7 +540,7 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run) if (!run->strText->nLen) return 0; - if (run->nFlags & (MERF_TAB | MERF_CELL)) + if (run->nFlags & MERF_TAB) { if (cx < run->nWidth/2) return 0; @@ -697,11 +697,6 @@ static SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run /* descent is unchanged */ return size; } - if (run->nFlags & MERF_CELL) - { - size.cx = ME_twips2pointsX(c, run->pCell->nRightBoundary) - run->pt.x; - return size; - } return size; } diff --git a/dlls/riched20/writer.c b/dlls/riched20/writer.c index 98454173320..13afb3cc4fd 100644 --- a/dlls/riched20/writer.c +++ b/dlls/riched20/writer.c @@ -283,6 +283,26 @@ ME_StreamOutRTFFontAndColorTbl(ME_OutStream *pStream, ME_DisplayItem *pFirstRun, return TRUE; } +static BOOL +ME_StreamOutRTFTableProps(ME_OutStream *pStream, const ME_DisplayItem *para) +{ + PARAFORMAT2 *pFmt; + char props[STREAMOUT_BUFFER_SIZE] = ""; + int i; + + if (!ME_StreamOutPrint(pStream, "\\trowd")) + return FALSE; + pFmt = para->member.para.pFmt; + + for (i = 0; i < pFmt->cTabCount; i++) + { + sprintf(props, "\\cellx%d", pFmt->rgxTabs[i] & 0x00FFFFFF); + if (!ME_StreamOutPrint(pStream, props)) + return FALSE; + } + props[0] = '\0'; + return TRUE; +} static BOOL ME_StreamOutRTFParaProps(ME_OutStream *pStream, const ME_DisplayItem *para) @@ -290,21 +310,6 @@ ME_StreamOutRTFParaProps(ME_OutStream *pStream, const ME_DisplayItem *para) PARAFORMAT2 *fmt = para->member.para.pFmt; char props[STREAMOUT_BUFFER_SIZE] = ""; int i; - - if (para->member.para.pCells) - { - ME_TableCell *cell = para->member.para.pCells; - - if (!ME_StreamOutPrint(pStream, "\\trowd")) - return FALSE; - do { - sprintf(props, "\\cellx%d", cell->nRightBoundary); - if (!ME_StreamOutPrint(pStream, props)) - return FALSE; - cell = cell->next; - } while (cell); - props[0] = '\0'; - } /* TODO: Don't emit anything if the last PARAFORMAT2 is inherited */ if (!ME_StreamOutPrint(pStream, "\\pard")) @@ -686,6 +691,12 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC switch(p->type) { case diParagraph: + if (p->member.para.pFmt->dwMask & PFM_TABLE && + p->member.para.pFmt->wEffects & PFE_TABLE) + { + if (!ME_StreamOutRTFTableProps(pStream, p)) + return FALSE; + } if (!ME_StreamOutRTFParaProps(pStream, p)) return FALSE; pPara = p; @@ -695,12 +706,18 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC break; TRACE("flags %xh\n", p->member.run.nFlags); /* TODO: emit embedded objects */ - if (p->member.run.nFlags & MERF_GRAPHICS) + if (p->member.run.nFlags & MERF_GRAPHICS) { FIXME("embedded objects are not handled\n"); - if (p->member.run.nFlags & MERF_CELL) { - if (!ME_StreamOutPrint(pStream, "\\cell ")) - return FALSE; - nChars--; + } else if (p->member.run.nFlags & MERF_TAB) { + if (pPara->member.para.pFmt->dwMask & PFM_TABLE && + pPara->member.para.pFmt->wEffects & PFE_TABLE) + { + if (!ME_StreamOutPrint(pStream, "\\cell ")) + return FALSE; + } else { + if (!ME_StreamOutPrint(pStream, "\\tab ")) + return FALSE; + } } else if (p->member.run.nFlags & MERF_ENDPARA) { if (pPara->member.para.pFmt->dwMask & PFM_TABLE && pPara->member.para.pFmt->wEffects & PFE_TABLE)