richedit: Use tabstops to store cell positions.

This commit is contained in:
Dylan Smith 2008-08-04 19:18:54 -04:00 committed by Alexandre Julliard
parent dff3a42233
commit 11c8039699
11 changed files with 140 additions and 152 deletions

View File

@ -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)

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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));

View File

@ -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. */

View File

@ -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;

View File

@ -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');

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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)