We redo the way tables get freed. Earlier when the LO_TABLE element got freed, it would free stuff that hangs of the subsequent LO_CELL elements. Now, only table related stuff gets freed and the LO_CELL peer data structures get freed when the LO_CELL is freed. Lots of code that was if-defed or commented out since Mariner hit the tip has been removed to improve code readability. git-svn-id: svn://10.0.0.236/trunk@5266 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
9baa06d225
commit
2b6e32c052
@ -824,124 +824,6 @@ lo_SmallSquishSubDocToCell(MWContext *context, lo_DocState *state,
|
||||
lo_CreateCellFromSubDoc (context, state, subdoc, cell, ptr_dx, ptr_dy );
|
||||
|
||||
return(cell);
|
||||
|
||||
|
||||
/* Copied to lo_CreateCellFromSubDoc()
|
||||
*
|
||||
*ptr_dx = 0;
|
||||
*ptr_dy = 0;
|
||||
|
||||
if (cell == NULL)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
cell->type = LO_CELL;
|
||||
|
||||
cell->ele_id = NEXT_ELEMENT;
|
||||
cell->x = subdoc->x;
|
||||
cell->x_offset = subdoc->x_offset;
|
||||
cell->y = subdoc->y;
|
||||
cell->y_offset = subdoc->y_offset;
|
||||
cell->width = subdoc->width;
|
||||
cell->height = subdoc->height;
|
||||
cell->next = subdoc->next;
|
||||
cell->prev = subdoc->prev;
|
||||
cell->FE_Data = subdoc->FE_Data;
|
||||
|
||||
cell->backdrop = subdoc->backdrop;
|
||||
*/
|
||||
|
||||
/*
|
||||
* Clear out the bg_color struct from the subdocs so it doesn't
|
||||
* get freed twice.
|
||||
*/
|
||||
/*
|
||||
subdoc->backdrop.bg_color = NULL;
|
||||
subdoc->backdrop.url = NULL;
|
||||
|
||||
cell->cell_bg_layer = NULL;
|
||||
cell->cell_inflow_layer = NULL;
|
||||
*/
|
||||
|
||||
/*
|
||||
cell->border_width = subdoc->border_width;
|
||||
cell->border_vert_space = subdoc->border_vert_space;
|
||||
cell->border_horiz_space = subdoc->border_horiz_space;
|
||||
|
||||
cell->ele_attrmask = 0;
|
||||
cell->ele_attrmask |= (subdoc->ele_attrmask & LO_ELE_SECURE);
|
||||
cell->ele_attrmask |= (subdoc->ele_attrmask & LO_ELE_SELECTED);
|
||||
|
||||
cell->sel_start = subdoc->sel_start;
|
||||
cell->sel_end = subdoc->sel_end;
|
||||
|
||||
cell->cell_list = NULL;
|
||||
cell->cell_list_end = NULL;
|
||||
cell->cell_float_list = NULL;
|
||||
subdoc_state = (lo_DocState *)subdoc->state;
|
||||
if (subdoc_state != NULL)
|
||||
{
|
||||
LO_Element **line_array;
|
||||
LO_Element *eptr;
|
||||
int32 base_x, base_y;
|
||||
*/
|
||||
/*
|
||||
* Make eptr point to the start of the element chain
|
||||
* for this subdoc.
|
||||
*/
|
||||
/*
|
||||
#ifdef XP_WIN16
|
||||
{
|
||||
XP_Block *larray_array;
|
||||
|
||||
XP_LOCK_BLOCK(larray_array, XP_Block *,
|
||||
subdoc_state->larray_array);
|
||||
subdoc_state->line_array = larray_array[0];
|
||||
XP_UNLOCK_BLOCK(subdoc_state->larray_array);
|
||||
}
|
||||
#endif */ /* XP_WIN16 */
|
||||
/*
|
||||
XP_LOCK_BLOCK(line_array, LO_Element **,
|
||||
subdoc_state->line_array);
|
||||
eptr = line_array[0];
|
||||
XP_UNLOCK_BLOCK(subdoc_state->line_array);
|
||||
|
||||
cell->cell_list = eptr;
|
||||
|
||||
base_x = subdoc->x + subdoc->x_offset + subdoc->border_width;
|
||||
base_y = subdoc->y + subdoc->y_offset + subdoc->border_width;
|
||||
|
||||
cell->cell_list_end = subdoc_state->end_last_line;
|
||||
if (cell->cell_list_end == NULL)
|
||||
{
|
||||
cell->cell_list_end = cell->cell_list;
|
||||
}
|
||||
|
||||
cell->cell_float_list = subdoc_state->float_list;
|
||||
|
||||
*ptr_dx = base_x;
|
||||
*ptr_dy = base_y;
|
||||
|
||||
*/
|
||||
/*
|
||||
* MOCHA needs to reuse mocha objects allocated in the namelist
|
||||
* when a cell is relaid out. This means we must always squish
|
||||
* back up to the top level state, instead of propogating up
|
||||
* like we used to.
|
||||
*/
|
||||
|
||||
/*
|
||||
#ifdef MOCHA
|
||||
lo_AddNameList(state->top_state->doc_state, subdoc_state);
|
||||
#else
|
||||
lo_AddNameList(state, subdoc_state);
|
||||
#endif */ /* MOCHA */
|
||||
/*
|
||||
}
|
||||
|
||||
return(cell);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -734,23 +734,25 @@ lo_ScrapeElement(MWContext *context, LO_Element *element)
|
||||
CL_DestroyLayer(layer);
|
||||
element->lo_cell.cell_bg_layer = NULL;
|
||||
}
|
||||
|
||||
/* Free the lo_TableCell record associated with this cell */
|
||||
if ( element->lo_cell.table_cell != NULL )
|
||||
{
|
||||
lo_TopState *top_state;
|
||||
lo_DocState *state;
|
||||
|
||||
top_state = lo_FetchTopState( XP_DOCID(context) );
|
||||
state = top_state->doc_state;
|
||||
if (state != NULL)
|
||||
lo_free_cell_record( context, state, element->lo_cell.table_cell );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LO_TABLE:
|
||||
{
|
||||
lo_TableRec *table = (lo_TableRec *) element->lo_table.table;
|
||||
lo_TopState *top_state;
|
||||
lo_DocState *state;
|
||||
|
||||
if (table != NULL)
|
||||
{
|
||||
top_state = lo_FetchTopState(XP_DOCID(context));
|
||||
state = top_state->doc_state;
|
||||
lo_free_table_record(context, state, table, TRUE);
|
||||
}
|
||||
|
||||
lo_ScrapeTableElement( context, element );
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@ -1000,8 +1000,9 @@ extern void lo_FreeGridRec(lo_GridRec *);
|
||||
extern void lo_FreeGridCellRec(MWContext *, lo_GridRec *, lo_GridCellRec *);
|
||||
extern void lo_FreeGridEdge(lo_GridEdge *);
|
||||
extern void lo_FreeFormElementData(LO_FormElementData *element_data);
|
||||
extern void lo_free_table_record(MWContext *context, lo_DocState *state,
|
||||
lo_TableRec *table, Bool partial);
|
||||
extern void lo_free_cell_record(MWContext *context, lo_DocState *state, lo_TableCell *cell);
|
||||
extern void lo_ScrapeTableElement( MWContext *context, LO_TableStruct *table_ele );
|
||||
|
||||
|
||||
#ifdef MEMORY_ARENAS
|
||||
extern void lo_InitializeMemoryArena(lo_TopState *);
|
||||
|
||||
@ -98,20 +98,15 @@ int32
|
||||
lo_align_cell(MWContext *context, lo_DocState *state, lo_TableCell *cell_ptr,
|
||||
LO_CellStruct *cell, lo_TableRec *table, lo_table_span *row_max);
|
||||
|
||||
#if 0 /* No longer used after Mariner */
|
||||
void
|
||||
lo_RelayoutTags(MWContext *context, lo_DocState *state, PA_Tag * tag_ptr,
|
||||
PA_Tag * tag_end_ptr, LO_Element * elem_list);
|
||||
#endif
|
||||
|
||||
PA_Tag *
|
||||
lo_FindReuseableElement(MWContext *context, lo_DocState *state,
|
||||
LO_Element ** elem_list);
|
||||
|
||||
static void
|
||||
lo_reuse_current_state(MWContext *context, lo_DocState *state,
|
||||
int32 width, int32 height, int32 margin_width, int32 margin_height,
|
||||
Bool destroyLineLists);
|
||||
|
||||
static void lo_FreeAllExceptRows( MWContext *context, lo_DocState *state,
|
||||
lo_TableRec *table );
|
||||
static void lo_FreeTableSpanArray( lo_table_span *spanArray );
|
||||
|
||||
/*
|
||||
********************************************************************************
|
||||
* Some Helper Functions
|
||||
@ -2907,204 +2902,6 @@ lo_RelayoutCaptionSubdoc(MWContext *context, lo_DocState *state, lo_TableCaption
|
||||
*/
|
||||
state = new_state;
|
||||
|
||||
/*
|
||||
tag_ptr = old_state->subdoc_tags;
|
||||
tag_end_ptr = old_state->subdoc_tags_end;
|
||||
old_state->subdoc_tags = NULL;
|
||||
old_state->subdoc_tags_end = NULL;
|
||||
if (tag_end_ptr != NULL)
|
||||
{
|
||||
tag_end_ptr = tag_end_ptr->next;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* Clean up memory used by old subdoc state.
|
||||
*/
|
||||
/*
|
||||
lo_cleanup_state(context, old_state);
|
||||
*/
|
||||
|
||||
#if 0 /* Doesn't need to happen any more because we do non-destructive reflow */
|
||||
/*
|
||||
* Save our parent's state levels
|
||||
*/
|
||||
save_diff_state = top_state->diff_state;
|
||||
save_state_pushes = top_state->state_pushes;
|
||||
save_state_pops = top_state->state_pops;
|
||||
|
||||
while (tag_ptr != tag_end_ptr)
|
||||
{
|
||||
PA_Tag *tag;
|
||||
lo_DocState *sub_state;
|
||||
lo_DocState *up_state;
|
||||
lo_DocState *tmp_state;
|
||||
Bool may_save;
|
||||
|
||||
tag = tag_ptr;
|
||||
tag_ptr = tag_ptr->next;
|
||||
tag->next = NULL;
|
||||
tag_list = tag_ptr;
|
||||
|
||||
up_state = NULL;
|
||||
sub_state = state;
|
||||
while (sub_state->sub_state != NULL)
|
||||
{
|
||||
up_state = sub_state;
|
||||
sub_state = sub_state->sub_state;
|
||||
}
|
||||
|
||||
if ((sub_state->is_a_subdoc == SUBDOC_CELL)||
|
||||
(sub_state->is_a_subdoc == SUBDOC_CAPTION))
|
||||
{
|
||||
may_save = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
may_save = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset these so we can tell if anything happened
|
||||
*/
|
||||
top_state->diff_state = FALSE;
|
||||
top_state->state_pushes = 0;
|
||||
top_state->state_pops = 0;
|
||||
|
||||
#ifdef MOCHA
|
||||
sub_state->in_relayout = TRUE;
|
||||
#endif
|
||||
lo_LayoutTag(context, sub_state, tag);
|
||||
tmp_state = lo_CurrentSubState(state);
|
||||
#ifdef MOCHA
|
||||
if (tmp_state == sub_state)
|
||||
{
|
||||
sub_state->in_relayout = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (may_save != FALSE)
|
||||
{
|
||||
int32 state_diff;
|
||||
|
||||
/* how has our state level changed? */
|
||||
state_diff = top_state->state_pushes - top_state->state_pops;
|
||||
|
||||
/*
|
||||
* That tag popped us up one state level. If this new
|
||||
* state is still a subdoc, save the tag there.
|
||||
*/
|
||||
if (state_diff == -1)
|
||||
{
|
||||
if ((tmp_state->is_a_subdoc == SUBDOC_CELL)||
|
||||
(tmp_state->is_a_subdoc == SUBDOC_CAPTION))
|
||||
{
|
||||
/* if we just popped a table we need to insert
|
||||
* a dummy end tag to pop the dummy start tag
|
||||
* we shove on the stack after createing a table
|
||||
*/
|
||||
PA_Tag *new_tag = LO_CreateStyleSheetDummyTag(tag);
|
||||
if(new_tag)
|
||||
{
|
||||
lo_SaveSubdocTags(context, tmp_state, new_tag);
|
||||
}
|
||||
|
||||
lo_SaveSubdocTags(context, tmp_state, tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
PA_FreeTag(tag);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Else that tag put us in a new subdoc on the same
|
||||
* level. It needs to be saved one level up,
|
||||
* if the parent is also a subdoc.
|
||||
*/
|
||||
else if (( up_state != NULL ) &&
|
||||
( top_state->diff_state != FALSE ) &&
|
||||
( state_diff == 0 ))
|
||||
{
|
||||
if ((up_state->is_a_subdoc == SUBDOC_CELL)||
|
||||
(up_state->is_a_subdoc == SUBDOC_CAPTION))
|
||||
{
|
||||
lo_SaveSubdocTags(context, up_state, tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
PA_FreeTag(tag);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Else we are still in the same subdoc
|
||||
*/
|
||||
else if (( top_state->diff_state == FALSE ) &&
|
||||
( state_diff == 0 ))
|
||||
{
|
||||
lo_SaveSubdocTags(context, sub_state, tag);
|
||||
}
|
||||
/*
|
||||
* Else that tag started a new, nested subdoc.
|
||||
* Add the starting tag to the parent.
|
||||
*/
|
||||
else if (( state_diff == 1 ))
|
||||
{
|
||||
lo_SaveSubdocTags(context, sub_state, tag);
|
||||
/*
|
||||
* Since we have extended the parent chain,
|
||||
* we need to reset the child to the new
|
||||
* parent end-chain.
|
||||
*/
|
||||
if ((tmp_state->is_a_subdoc == SUBDOC_CELL)||
|
||||
(tmp_state->is_a_subdoc == SUBDOC_CAPTION))
|
||||
{
|
||||
PA_Tag *new_tag;
|
||||
|
||||
tmp_state->subdoc_tags =
|
||||
sub_state->subdoc_tags_end;
|
||||
|
||||
/* add an aditional dummy tag so that style sheets
|
||||
* can use it to query styles from for this entry
|
||||
* that created a table
|
||||
*/
|
||||
new_tag = LO_CreateStyleSheetDummyTag(tag);
|
||||
if(new_tag)
|
||||
{
|
||||
lo_SaveSubdocTags(context, tmp_state, new_tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This can never happen.
|
||||
*/
|
||||
else
|
||||
{
|
||||
PA_FreeTag(tag);
|
||||
}
|
||||
}
|
||||
tag_ptr = tag_list;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore our parent's state levels
|
||||
*/
|
||||
top_state->diff_state = save_diff_state;
|
||||
top_state->state_pushes = save_state_pushes;
|
||||
top_state->state_pops = save_state_pops;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Link the end of this subdoc's tag chain back to
|
||||
* its parent. The beginning should have never been
|
||||
* unlinked from the parent.
|
||||
*/
|
||||
/*
|
||||
if (state->subdoc_tags_end != NULL)
|
||||
{
|
||||
state->subdoc_tags_end->next = tag_end_ptr;
|
||||
}
|
||||
*/
|
||||
|
||||
lo_rl_ReflowDocState( context, state );
|
||||
|
||||
/*
|
||||
@ -4385,7 +4182,7 @@ lo_BeginTableCaption(MWContext *context, lo_DocState *state, lo_TableRec *table,
|
||||
PA_Block buff;
|
||||
char *str;
|
||||
|
||||
caption = XP_NEW(lo_TableCaption);
|
||||
caption = XP_NEW_ZAP(lo_TableCaption);
|
||||
if (caption == NULL)
|
||||
{
|
||||
return;
|
||||
@ -6603,7 +6400,7 @@ lo_cell_rowspan_pass(MWContext *context, lo_TableRec *table, lo_cell_data XP_HUG
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
void
|
||||
lo_free_cell_record(MWContext *context, lo_DocState *state, lo_TableCell *cell)
|
||||
{
|
||||
if (cell == NULL)
|
||||
@ -6651,7 +6448,6 @@ lo_free_cell_record(MWContext *context, lo_DocState *state, lo_TableCell *cell)
|
||||
|
||||
|
||||
static void
|
||||
|
||||
lo_free_row_record(MWContext *context, lo_DocState *state,
|
||||
lo_TableRow *row, Bool partial)
|
||||
{
|
||||
@ -6727,71 +6523,9 @@ void lo_free_table_record(MWContext *context, lo_DocState *state,
|
||||
table->row_ptr = NULL;
|
||||
}
|
||||
|
||||
lo_FreeTableCaption( context, state, table );
|
||||
|
||||
if (table->width_spans != NULL)
|
||||
{
|
||||
lo_table_span *span_ptr;
|
||||
lo_table_span *span;
|
||||
|
||||
span_ptr = table->width_spans;
|
||||
while (span_ptr != NULL)
|
||||
{
|
||||
span = span_ptr;
|
||||
span_ptr = span_ptr->next;
|
||||
XP_DELETE(span);
|
||||
}
|
||||
table->width_spans = NULL;
|
||||
table->width_span_ptr = NULL;
|
||||
}
|
||||
|
||||
if (table->height_spans != NULL)
|
||||
{
|
||||
lo_table_span *span_ptr;
|
||||
lo_table_span *span;
|
||||
|
||||
span_ptr = table->height_spans;
|
||||
while (span_ptr != NULL)
|
||||
{
|
||||
span = span_ptr;
|
||||
span_ptr = span_ptr->next;
|
||||
XP_DELETE(span);
|
||||
}
|
||||
table->height_spans = NULL;
|
||||
table->height_span_ptr = NULL;
|
||||
}
|
||||
|
||||
XP_FREEIF(table->backdrop.bg_color);
|
||||
XP_FREEIF(table->backdrop.url);
|
||||
|
||||
/*
|
||||
* Whether the partial flag is set or not, we always
|
||||
* want to eliminate this subdoc and all its contents
|
||||
* when the table is done.
|
||||
*/
|
||||
if (table->current_subdoc != NULL)
|
||||
{
|
||||
lo_FreePartialSubDoc(context, state, table->current_subdoc);
|
||||
table->current_subdoc = NULL;
|
||||
}
|
||||
|
||||
if ( table->fixed_col_widths != NULL )
|
||||
{
|
||||
XP_FREE(table->fixed_col_widths);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset back pointer in table layout element
|
||||
*/
|
||||
if (table->table_ele != NULL) {
|
||||
table->table_ele->table = NULL;
|
||||
}
|
||||
|
||||
XP_DELETE(table);
|
||||
lo_FreeAllExceptRows( context, state, table );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
lo_FreePartialTable(MWContext *context, lo_DocState *state, lo_TableRec *table)
|
||||
{
|
||||
@ -7451,6 +7185,7 @@ fprintf(stderr, "lo_EndTable called\n");
|
||||
cell_ele = table->caption->cell_ele;
|
||||
lo_UpdateCaptionCellFromSubDoc(context, state, subdoc, cell_ele);
|
||||
}
|
||||
|
||||
/* table->caption->subdoc = NULL; */
|
||||
|
||||
if (cell_ele == NULL)
|
||||
@ -7863,11 +7598,11 @@ fprintf(stderr, "lo_EndTable called\n");
|
||||
|
||||
if (relayout == FALSE)
|
||||
{
|
||||
lo_AppendFloatInLineList(state, (LO_Element *)table->table_ele, save_line_list );
|
||||
lo_AppendFloatInLineList(state, (LO_Element *)table->table_ele, save_line_list );
|
||||
}
|
||||
else
|
||||
{
|
||||
state->line_list = save_line_list;
|
||||
state->line_list = save_line_list;
|
||||
}
|
||||
|
||||
|
||||
@ -7914,21 +7649,6 @@ fprintf(stderr, "lo_EndTable called\n");
|
||||
|
||||
}
|
||||
|
||||
/* Now cell records get freed when the LO_TABLE element in the line list gets recycled
|
||||
for (y=0; y < table->rows; y++)
|
||||
{
|
||||
for (x=0; x < table->cols; x++)
|
||||
{
|
||||
indx = (y * table->cols) + x;
|
||||
cell_ptr = cell_array[indx].cell;
|
||||
if ((cell_ptr != &blank_cell)&&(cell_ptr != NULL))
|
||||
{
|
||||
lo_free_cell_record(context, state, cell_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/* Decrement table nesting level (used for passing into lo_CreateCellBackGroundLayer() */
|
||||
if (!relayout)
|
||||
{
|
||||
@ -7942,349 +7662,9 @@ fprintf(stderr, "lo_EndTable called\n");
|
||||
XP_FREE_BLOCK(cell_array_buff);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Don't wanna free the table record any more because this information
|
||||
* is used during relayout.
|
||||
*/
|
||||
/*
|
||||
|
||||
lo_free_table_record(context, state, table, FALSE);
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* This function relaysout the tags in a table cell. It knows how to handle
|
||||
* certain types of elements that can be resused directly rather than thrown
|
||||
* away and relayedout from scratch (the default case).
|
||||
*/
|
||||
void
|
||||
lo_RelayoutTags(MWContext *context, lo_DocState *state, PA_Tag * tag_ptr,
|
||||
PA_Tag * tag_end_ptr, LO_Element * elem_list)
|
||||
{
|
||||
PA_Tag * next_tag;
|
||||
Bool save_diff_state;
|
||||
int32 save_state_pushes;
|
||||
int32 save_state_pops;
|
||||
lo_TopState *top_state;
|
||||
PA_Tag *tag_list;
|
||||
|
||||
next_tag = NULL;
|
||||
top_state = state->top_state;
|
||||
|
||||
/*
|
||||
* Save our parent's state levels
|
||||
*/
|
||||
save_diff_state = top_state->diff_state;
|
||||
save_state_pushes = top_state->state_pushes;
|
||||
save_state_pops = top_state->state_pops;
|
||||
|
||||
while (tag_ptr != tag_end_ptr)
|
||||
{
|
||||
PA_Tag *tag;
|
||||
lo_DocState *sub_state;
|
||||
lo_DocState *up_state;
|
||||
lo_DocState *tmp_state;
|
||||
Bool may_save;
|
||||
|
||||
tag = tag_ptr;
|
||||
tag_ptr = tag_ptr->next;
|
||||
tag->next = NULL;
|
||||
tag_list = tag_ptr;
|
||||
|
||||
up_state = NULL;
|
||||
sub_state = state;
|
||||
while (sub_state->sub_state != NULL)
|
||||
{
|
||||
up_state = sub_state;
|
||||
sub_state = sub_state->sub_state;
|
||||
}
|
||||
|
||||
if ((sub_state->is_a_subdoc == SUBDOC_CELL)||
|
||||
(sub_state->is_a_subdoc == SUBDOC_CAPTION))
|
||||
{
|
||||
may_save = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
may_save = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset these so we can tell if anything happened
|
||||
*/
|
||||
top_state->diff_state = FALSE;
|
||||
top_state->state_pushes = 0;
|
||||
top_state->state_pops = 0;
|
||||
|
||||
#ifdef MOCHA
|
||||
sub_state->in_relayout = TRUE;
|
||||
#endif
|
||||
/*
|
||||
* If we're not currently searching for a tag, then find the next
|
||||
* one to look for.
|
||||
*/
|
||||
if ( next_tag == NULL && elem_list != NULL )
|
||||
{
|
||||
next_tag = lo_FindReuseableElement ( context, state, &elem_list );
|
||||
}
|
||||
|
||||
/*
|
||||
* Can we reuse this current element?
|
||||
*/
|
||||
if ( (tag == next_tag) && (elem_list != NULL) )
|
||||
{
|
||||
LO_Element *eptr;
|
||||
LO_Element *enext;
|
||||
|
||||
/*
|
||||
* Yup, remove it from the list and call the object layout code to
|
||||
* do the relayout.
|
||||
*/
|
||||
eptr = elem_list;
|
||||
enext = eptr->lo_any.next;
|
||||
|
||||
elem_list = enext;
|
||||
|
||||
if ( enext != NULL )
|
||||
{
|
||||
enext->lo_any.prev = NULL;
|
||||
}
|
||||
|
||||
eptr->lo_any.next = 0L;
|
||||
eptr->lo_any.prev = 0L;
|
||||
|
||||
switch ( eptr->type )
|
||||
{
|
||||
case LO_EMBED:
|
||||
lo_RelayoutEmbed ( context, sub_state, &eptr->lo_embed, tag );
|
||||
break;
|
||||
#ifdef JAVA
|
||||
case LO_JAVA:
|
||||
lo_RelayoutJavaApp ( context, sub_state, tag, &eptr->lo_java );
|
||||
break;
|
||||
#endif /* JAVA */
|
||||
|
||||
default:
|
||||
/*
|
||||
* We goofed and got something we don't know how to relayout
|
||||
*/
|
||||
lo_relayout_recycle ( context, state, eptr );
|
||||
lo_LayoutTag(context, sub_state, tag);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Force us to look for the next reusable element.
|
||||
*/
|
||||
next_tag = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Nope, call the standard layout code.
|
||||
*/
|
||||
lo_LayoutTag(context, sub_state, tag);
|
||||
}
|
||||
|
||||
tmp_state = lo_CurrentSubState(state);
|
||||
#ifdef MOCHA
|
||||
if (tmp_state == sub_state)
|
||||
{
|
||||
sub_state->in_relayout = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
tmp_state = lo_CurrentSubState(state);
|
||||
#ifdef MOCHA
|
||||
if (tmp_state == sub_state)
|
||||
{
|
||||
sub_state->in_relayout = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (may_save != FALSE)
|
||||
{
|
||||
int32 state_diff;
|
||||
|
||||
/* how has our state level changed? */
|
||||
state_diff = top_state->state_pushes - top_state->state_pops;
|
||||
|
||||
/*
|
||||
* That tag popped us up one state level. If this new
|
||||
* state is still a subdoc, save the tag there.
|
||||
*/
|
||||
if (state_diff == -1)
|
||||
{
|
||||
if ((tmp_state->is_a_subdoc == SUBDOC_CELL)||
|
||||
(tmp_state->is_a_subdoc == SUBDOC_CAPTION))
|
||||
{
|
||||
/* if we just popped a table we need to insert
|
||||
* a dummy end tag to pop the dummy start tag
|
||||
* we shove on the stack after createing a table
|
||||
*/
|
||||
PA_Tag *new_tag = LO_CreateStyleSheetDummyTag(tag);
|
||||
if(new_tag)
|
||||
{
|
||||
lo_SaveSubdocTags(context, tmp_state, new_tag);
|
||||
}
|
||||
|
||||
lo_SaveSubdocTags(context, tmp_state, tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
PA_FreeTag(tag);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Else that tag put us in a new subdoc on the same
|
||||
* level. It needs to be saved one level up,
|
||||
* if the parent is also a subdoc.
|
||||
*/
|
||||
else if (( up_state != NULL ) &&
|
||||
( top_state->diff_state != FALSE ) &&
|
||||
( state_diff == 0 ))
|
||||
{
|
||||
if ((up_state->is_a_subdoc == SUBDOC_CELL)||
|
||||
(up_state->is_a_subdoc == SUBDOC_CAPTION))
|
||||
{
|
||||
lo_SaveSubdocTags(context, up_state, tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
PA_FreeTag(tag);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Else we are still in the same subdoc
|
||||
*/
|
||||
else if (( top_state->diff_state == FALSE ) &&
|
||||
( state_diff == 0 ))
|
||||
{
|
||||
lo_SaveSubdocTags(context, sub_state, tag);
|
||||
}
|
||||
/*
|
||||
* Else that tag started a new, nested subdoc.
|
||||
* Add the starting tag to the parent.
|
||||
*/
|
||||
else if (( state_diff == 1 ))
|
||||
{
|
||||
lo_SaveSubdocTags(context, sub_state, tag);
|
||||
/*
|
||||
* Since we have extended the parent chain,
|
||||
* we need to reset the child to the new
|
||||
* parent end-chain.
|
||||
*/
|
||||
if ((tmp_state->is_a_subdoc == SUBDOC_CELL)||
|
||||
(tmp_state->is_a_subdoc == SUBDOC_CAPTION))
|
||||
{
|
||||
PA_Tag *new_tag;
|
||||
|
||||
tmp_state->subdoc_tags =
|
||||
sub_state->subdoc_tags_end;
|
||||
|
||||
/* add an aditional dummy tag so that style sheets
|
||||
* can use it to query styles from for this entry
|
||||
* that created a table
|
||||
*/
|
||||
new_tag = LO_CreateStyleSheetDummyTag(tag);
|
||||
if(new_tag)
|
||||
{
|
||||
lo_SaveSubdocTags(context, tmp_state, new_tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This can never happen.
|
||||
*/
|
||||
else
|
||||
{
|
||||
PA_FreeTag(tag);
|
||||
}
|
||||
}
|
||||
tag_ptr = tag_list;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore our parent's state levels
|
||||
*/
|
||||
top_state->diff_state = save_diff_state;
|
||||
top_state->state_pushes = save_state_pushes;
|
||||
top_state->state_pops = save_state_pops;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Walk the element list, throwing them away until we find one
|
||||
* that can be reused.
|
||||
*/
|
||||
PA_Tag *
|
||||
lo_FindReuseableElement(MWContext *context, lo_DocState *state, LO_Element ** elem_list)
|
||||
{
|
||||
LO_Element * eptr;
|
||||
LO_Element * enext;
|
||||
PA_Tag * tag;
|
||||
|
||||
tag = NULL;
|
||||
eptr = *elem_list;
|
||||
enext = NULL;
|
||||
|
||||
/*
|
||||
* Keep going until we've gone through all the elements
|
||||
* or found one that we can reuse.
|
||||
*/
|
||||
while ( (eptr != NULL) && (tag == NULL) )
|
||||
{
|
||||
enext = eptr->lo_any.next;
|
||||
|
||||
/*
|
||||
* Any element found by this switch statement will attempt to be relayed out
|
||||
* using the same element structure. DO NOT put anything in here that can
|
||||
* have atributes set by style sheets until the lo_PreLayoutTag function
|
||||
* can correctly handle stylesheets.
|
||||
*/
|
||||
switch ( eptr->type )
|
||||
{
|
||||
case LO_EMBED:
|
||||
tag = eptr->lo_embed.objTag.tag;
|
||||
break;
|
||||
#ifdef JAVA
|
||||
case LO_JAVA:
|
||||
tag = eptr->lo_java.objTag.tag;
|
||||
break;
|
||||
#endif /* JAVA */
|
||||
}
|
||||
|
||||
/*
|
||||
* If we didn't find a tag from that element, then dispose of it and
|
||||
* keep looking.
|
||||
*/
|
||||
if ( tag == NULL )
|
||||
{
|
||||
/*
|
||||
* We dunno how to reuse this type of element, so throw
|
||||
* it away and someone else will relay it out from scratch.
|
||||
*/
|
||||
eptr->lo_any.prev = NULL;
|
||||
eptr->lo_any.next = NULL;
|
||||
lo_relayout_recycle ( context, state, eptr );
|
||||
if ( enext != NULL )
|
||||
{
|
||||
enext->lo_any.prev = NULL;
|
||||
}
|
||||
eptr = enext;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Advance the element list to the new head
|
||||
*/
|
||||
*elem_list = eptr;
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions separated out of lo_BeginTableAttributes
|
||||
*/
|
||||
@ -8506,6 +7886,126 @@ static void lo_FreeCaptionCell( MWContext *context, lo_DocState *state, LO_CellS
|
||||
lo_FreeElement(context, (LO_Element *)cell_ele, TRUE);
|
||||
|
||||
}
|
||||
|
||||
/* Delete the lo_TableRec data structure associated with the LO_TABLE element.
|
||||
Does not free the LO_TABLE element itself. */
|
||||
void lo_ScrapeTableElement( MWContext *context, LO_TableStruct *table_ele )
|
||||
{
|
||||
lo_TableRec *table = (lo_TableRec *) table_ele->table;
|
||||
lo_TopState *top_state = lo_FetchTopState(XP_DOCID(context));
|
||||
lo_DocState *state = top_state->doc_state;
|
||||
|
||||
if (table != NULL)
|
||||
{
|
||||
/* Free the table row list */
|
||||
if (table->row_list != NULL)
|
||||
{
|
||||
lo_TableRow *row_ptr;
|
||||
lo_TableRow *row;
|
||||
|
||||
row_ptr = table->row_list;
|
||||
while (row_ptr != NULL)
|
||||
{
|
||||
row = row_ptr;
|
||||
row_ptr = row_ptr->next;
|
||||
|
||||
/* The lo_TableCell structures will get freed when their peer
|
||||
LO_CELL elements get recycled, so just null out the pointers
|
||||
to those structures. */
|
||||
row->cell_list = NULL;
|
||||
row->cell_ptr = NULL;
|
||||
|
||||
XP_FREEIF(row->backdrop.bg_color);
|
||||
XP_FREEIF(row->backdrop.url);
|
||||
XP_DELETE(row);
|
||||
}
|
||||
table->row_list = NULL;
|
||||
table->row_ptr = NULL;
|
||||
}
|
||||
|
||||
/* Clean up the line array pointers to the elements contained inside the caption
|
||||
cell. Otherwise, the freeing of the caption frees those elements and a double
|
||||
free crash occurs when those elements are freed by their peer LO_CELL element */
|
||||
if (table->caption && table->caption->subdoc &&
|
||||
table->caption->subdoc->state)
|
||||
lo_cleanup_old_state( table->caption->subdoc->state );
|
||||
|
||||
lo_FreeAllExceptRows( context, state, table );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void lo_FreeAllExceptRows( MWContext *context, lo_DocState *state, lo_TableRec *table )
|
||||
{
|
||||
/* Free backdrop info */
|
||||
XP_FREEIF(table->backdrop.bg_color);
|
||||
XP_FREEIF(table->backdrop.url);
|
||||
|
||||
/* Free width and height span arrays */
|
||||
lo_FreeTableSpanArray(table->width_spans);
|
||||
table->width_spans = NULL;
|
||||
table->width_span_ptr = NULL;
|
||||
|
||||
lo_FreeTableSpanArray(table->height_spans);
|
||||
table->height_spans = NULL;
|
||||
table->height_span_ptr = NULL;
|
||||
|
||||
/* Free caption information. */
|
||||
if (table->caption != NULL)
|
||||
{
|
||||
/* The LO_CELL element associated with the caption will get freed
|
||||
when it gets recycled in the line list. So, just null out the
|
||||
pointer to it. */
|
||||
table->caption->cell_ele = NULL;
|
||||
|
||||
if ( table->caption->subdoc != NULL )
|
||||
{
|
||||
lo_FreePartialSubDoc ( context, state, table->caption->subdoc );
|
||||
table->caption->subdoc = NULL;
|
||||
}
|
||||
|
||||
XP_DELETE(table->caption);
|
||||
table->caption = NULL;
|
||||
}
|
||||
|
||||
/* Free the subdoc state */
|
||||
if (table->current_subdoc != NULL)
|
||||
{
|
||||
lo_FreePartialSubDoc(context, state, table->current_subdoc);
|
||||
table->current_subdoc = NULL;
|
||||
}
|
||||
|
||||
|
||||
if ( table->fixed_col_widths != NULL )
|
||||
{
|
||||
XP_FREE(table->fixed_col_widths);
|
||||
}
|
||||
|
||||
/* Reset back pointer in table layout element */
|
||||
if (table->table_ele != NULL) {
|
||||
table->table_ele->table = NULL;
|
||||
}
|
||||
|
||||
XP_DELETE(table);
|
||||
}
|
||||
|
||||
static void lo_FreeTableSpanArray( lo_table_span *spanArray )
|
||||
{
|
||||
if (spanArray != NULL)
|
||||
{
|
||||
lo_table_span *span_ptr;
|
||||
lo_table_span *span;
|
||||
|
||||
span_ptr = spanArray;
|
||||
while (span_ptr != NULL)
|
||||
{
|
||||
span = span_ptr;
|
||||
span_ptr = span_ptr->next;
|
||||
XP_DELETE(span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEST_16BIT
|
||||
#undef XP_WIN16
|
||||
#endif /* TEST_16BIT */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user