home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / layout / laytable.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  202.5 KB  |  8,482 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "xp.h"
  20. #include "pa_parse.h"
  21. #include "layout.h"
  22. #include "laylayer.h"
  23. #include "np.h"
  24. #include "laystyle.h"
  25. #include "edt.h"
  26.  
  27. #ifdef TEST_16BIT
  28. #define XP_WIN16
  29. #endif /* TEST_16BIT */
  30.  
  31.  
  32. #define    TABLE_BORDERS_ON        1
  33. #define    TABLE_BORDERS_OFF        0
  34. #define    TABLE_BORDERS_GONE        -1
  35.  
  36. #define    TABLE_DEF_INNER_CELL_PAD    1
  37. #define    TABLE_DEF_INTER_CELL_PAD    2
  38. #define    TABLE_DEF_CELL_BORDER        1
  39.  
  40. #define    TABLE_DEF_BORDER        0
  41. #define TABLE_DEF_BORDER_STYLE        BORDER_SOLID
  42. #define    TABLE_DEF_VERTICAL_SPACE    0
  43. #define    TABLE_DEF_HORIZONTAL_SPACE    0
  44.  
  45. #define    TABLE_MAX_COLSPAN        1000
  46. #define    TABLE_MAX_ROWSPAN        10000
  47.  
  48. typedef struct lo_cell_data_struct {
  49. #ifdef XP_WIN16
  50.     /*
  51.      * This struct must be a power of 2 if we are going to allocate an
  52.      * array of more than 128K
  53.      */
  54.     unsigned width, height;
  55. #else
  56.     int32 width, height;
  57. #endif
  58.     lo_TableCell *cell;
  59. } lo_cell_data;
  60.  
  61.  
  62. LO_SubDocStruct *
  63.     lo_EndCellSubDoc(MWContext *context, lo_DocState *state, lo_DocState *old_state,
  64.         LO_Element *element, Bool relayout);
  65. LO_SubDocStruct *
  66.     lo_RelayoutCaptionSubdoc(MWContext *context, lo_DocState *state, lo_TableCaption *caption,
  67.         LO_SubDocStruct *subdoc, int32 width, Bool is_a_header);
  68. LO_CellStruct *
  69. lo_RelayoutCell(MWContext *context, lo_DocState *state,
  70.     LO_SubDocStruct *subdoc, lo_TableCell *cell_ptr,
  71.     LO_CellStruct *cell, int32 width, Bool is_a_header,
  72.     Bool relayout);
  73. void
  74.     lo_BeginCaptionSubDoc(MWContext *context, lo_DocState *state,
  75.         lo_TableCaption *caption, PA_Tag *tag);
  76. void
  77.     lo_BeginCellSubDoc(MWContext *context, 
  78.                      lo_DocState *state,
  79.                      lo_TableRec *table,
  80.                      char *bgcolor_attr,
  81.                      char *background_attr,
  82.                     lo_TileMode tile_mode,
  83.                      char *valign_attr,
  84.                      char *halign_attr,
  85.                      char *width_attr,
  86.                      char *height_attr,
  87.                      Bool is_a_header, 
  88.                      intn draw_borders,
  89.                     Bool relayout);
  90. Bool
  91.     lo_subdoc_has_elements(lo_DocState *sub_state);
  92. Bool
  93.     lo_cell_has_elements(LO_CellStruct *cell);
  94. int32
  95.     lo_align_subdoc(MWContext *context, lo_DocState *state, lo_DocState *old_state,
  96.         LO_SubDocStruct *subdoc, lo_TableRec *table, lo_table_span *row_max);
  97. int32
  98.     lo_align_cell(MWContext *context, lo_DocState *state, lo_TableCell *cell_ptr,
  99.         LO_CellStruct *cell, lo_TableRec *table, lo_table_span *row_max);
  100.  
  101. void
  102.     lo_RelayoutTags(MWContext *context, lo_DocState *state, PA_Tag * tag_ptr,
  103.         PA_Tag * tag_end_ptr, LO_Element * elem_list);
  104.     
  105. PA_Tag *
  106.     lo_FindReuseableElement(MWContext *context, lo_DocState *state,
  107.         LO_Element ** elem_list);
  108.  
  109. static void
  110. lo_reuse_current_state(MWContext *context, lo_DocState *state,
  111.     int32 width, int32 height, int32 margin_width, int32 margin_height,
  112.     Bool destroyLineLists);
  113. /*
  114.  ********************************************************************************
  115.  * Some Helper Functions
  116.  */
  117.  
  118. static int32 lo_CalculateCellPercentWidth( lo_TableRec *table, int32 percent);
  119. static int32 lo_CalculateCellPercentHeight( lo_TableRec *table, lo_TableCell *table_cell);
  120.  
  121. static int32
  122.     lo_ComputeCellEmptySpace(MWContext *context,lo_TableRec *table,
  123.         LO_SubDocStruct *subdoc);
  124. static int32
  125.     lo_FindDefaultCellWidth(MWContext * context, lo_TableRec *table, lo_TableCell *table_cell,
  126.         int32 desired_width, int32 cell_empty_space);
  127. static int32
  128.     lo_ComputeInternalTableWidth(MWContext *context, lo_TableRec *table,
  129.         lo_DocState *state);
  130. static void
  131.     lo_SetDefaultCellWidth(MWContext *context, lo_TableRec *table, LO_SubDocStruct *subdoc,
  132.         lo_TableCell *table_cell, int32 cell_width);
  133.  
  134.  
  135. static void lo_ResetWidthSpans( lo_TableRec *table );
  136.  
  137. static void lo_UpdateCaptionCellFromSubDoc( MWContext *context, lo_DocState *state, LO_SubDocStruct *subdoc, LO_CellStruct *cell_ele);
  138. static void lo_FreeCaptionCell( MWContext *context, lo_DocState *state, LO_CellStruct *cell_ele);
  139. static void lo_FreeTableCaption( MWContext *context, lo_DocState *state, lo_TableRec *table );
  140.  
  141. static int32
  142. lo_ComputeCellEmptySpace(MWContext *context, lo_TableRec *table,
  143.     LO_SubDocStruct *subdoc)
  144. {
  145.     int32 left_inner_pad;
  146.     int32 right_inner_pad;
  147.     int32 cell_empty_space;
  148.     
  149.     left_inner_pad = FEUNITS_X(table->inner_left_pad, context);
  150.     right_inner_pad = FEUNITS_X(table->inner_right_pad, context);
  151.     
  152.     cell_empty_space =    (2 * subdoc->border_width) +
  153.                         (2 * subdoc->border_horiz_space) +
  154.                         (left_inner_pad + right_inner_pad);
  155.     
  156.     return cell_empty_space;
  157. }
  158.  
  159.  
  160. /*
  161.  * Handle Fixed Table Layout. If the table has a COLS attribute
  162.  * then the width of this cell may already be specified. The
  163.  * trick is to know if this is the first row of the table. If
  164.  * so, then this cell can choose it's width.
  165.  */
  166. static int32
  167. lo_FindDefaultCellWidth(MWContext * context, lo_TableRec *table, lo_TableCell *table_cell,
  168.     int32 desired_width, int32 cell_empty_space)
  169. {
  170.     lo_TableRow * row_ptr;
  171.     int32 cell_num;
  172.     int32 cell_width;
  173.     int32 count;
  174.     int32 cell_pad;
  175.         
  176.     cell_pad = FEUNITS_X(table->inter_cell_pad, context);
  177.     
  178.     row_ptr = table->row_ptr;
  179.     cell_num = row_ptr->cells;
  180.     
  181.     /* if we don't have a width table or we're out of bounds, bail */
  182.     if ( table->fixed_col_widths == NULL ||
  183.         ((cell_num+table_cell->colspan) > table->fixed_cols) )
  184.     {
  185.         table->fixed_cols = 0;
  186.         table->default_cell_width = 0;
  187.         return desired_width;
  188.     }
  189.     
  190.     /* does this cell already have a width defined? */
  191.     cell_width = table->fixed_col_widths[ cell_num ];
  192.     if ( cell_width == 0 )
  193.     {
  194.         int32 col_width;
  195.         
  196.         /* use it's desired width or the default */
  197.         cell_width = desired_width;
  198.         if ( cell_width == 0 )
  199.         {
  200.             /*
  201.              * Get our size from the default cell width. We
  202.              * may need to clip it to the table width remaining.
  203.              */
  204.             cell_width = table->default_cell_width * table_cell->colspan;
  205.             
  206.             /*
  207.              * If this is bigger than the width remaining the the table, then
  208.              * clip to the remaining space. If the table is already full, then
  209.              * we're going for broke and the cell gets all of it.
  210.              */
  211.             if ( ( table->fixed_width_remaining > 0 ) &&
  212.                 ( cell_width > table->fixed_width_remaining ) )
  213.             {
  214.                 cell_width = table->fixed_width_remaining;
  215.             }
  216.     
  217.             table->fixed_width_remaining -= cell_width;
  218.             
  219.             /*
  220.              * Remove any cell spacing so the cell will internally
  221.              * layout to the correct size.
  222.              */
  223.             cell_width -= cell_empty_space * table_cell->colspan;
  224.         }
  225.         else
  226.         {
  227.             /*
  228.              * The cell has a specified size. Allocate all of it. If we
  229.              * don't have enough space, then we'll keep doing fixed layout,
  230.              * but the table may end up larger than expected.
  231.              */
  232.             table->fixed_width_remaining -= cell_width + cell_empty_space;
  233.         }
  234.         
  235.         /* make sure this stays reasonable */
  236.         if ( table->fixed_width_remaining < 0 )
  237.         {
  238.             table->fixed_width_remaining = 0;
  239.         }
  240.                     
  241.         /* fill out the apropriate number of col widths */
  242.         col_width = cell_width / table_cell->colspan;
  243.         for ( count = table_cell->colspan; count > 0 ; --count )
  244.         {
  245.             table->fixed_col_widths[ cell_num ] = col_width;
  246.             cell_num++;
  247.         }
  248.         
  249.         /* add any odd amount to the last column */
  250.         table->fixed_col_widths[ cell_num-1 ] += (cell_width-
  251.             (col_width * table_cell->colspan));
  252.     }
  253.     else
  254.     {        
  255.         /* add up widths of each column our cell spans */
  256.         for ( count = 1; count < table_cell->colspan; ++count )
  257.         {
  258.             cell_width += table->fixed_col_widths[ cell_num+count ];
  259.         }
  260.     }
  261.             
  262.     /*
  263.      * Add the empty space this cell spans
  264.      */
  265.     cell_width += ( table_cell->colspan - 1 ) * ( cell_empty_space + cell_pad );
  266.     
  267.     return cell_width;
  268. }
  269.  
  270.  
  271. /*
  272.  * For fixed layout, set the cell width for a cell after layout. This is used
  273.  * for cases where we don't know how wide a cell is until after it's been layed
  274.  * out (for example, when NOWRAP is set).
  275.  *
  276.  * We will have already chosen a default width for this cell. If our new width
  277.  * is larger, then we need to resize the column/s.
  278.  */
  279. static void
  280. lo_SetDefaultCellWidth(MWContext *context, lo_TableRec *table, LO_SubDocStruct *subdoc,
  281.     lo_TableCell *table_cell, int32 cell_width)
  282. {
  283.     lo_TableRow * row_ptr;
  284.     int32 cell_num;
  285.     int32 count;
  286.     int32 cur_width;
  287.     int32 add_width;
  288.     int32 cell_empty_space;
  289.     int32 cell_pad;
  290.             
  291.     row_ptr = table->row_ptr;
  292.     cell_num = row_ptr->cells;
  293.     
  294.     /* if we don't have a width table or we're out of bounds, bail */
  295.     if ( table->fixed_col_widths == NULL ||
  296.         ((cell_num+table_cell->colspan) > table->fixed_cols) )
  297.     {
  298.         table->fixed_cols = 0;
  299.         table->default_cell_width = 0;
  300.         return;
  301.     }
  302.     
  303.     /*
  304.      * Figure out the current width for these cells
  305.      */
  306.     cur_width = 0;
  307.     
  308.     for ( count = table_cell->colspan-1; count >= 0 ; --count )
  309.     {
  310.         cur_width += table->fixed_col_widths[ cell_num+count ];
  311.     }
  312.     
  313.     /*
  314.      * Add space for the empty space that this cell spans
  315.      */
  316.     cell_empty_space = lo_ComputeCellEmptySpace(context, table, subdoc );
  317.     cell_pad = FEUNITS_X(table->inter_cell_pad, context);
  318.  
  319.     cur_width += ( table_cell->colspan - 1 ) * ( cell_empty_space + cell_pad );
  320.     
  321.     /*
  322.      * If our new width is bigger, we need to grow the default width
  323.      */
  324.     if ( cell_width > cur_width )
  325.     {
  326.         cell_width -= cur_width;
  327.         add_width = cell_width / table_cell->colspan;
  328.         
  329.         table->fixed_width_remaining -= add_width;
  330.         if ( table->fixed_width_remaining < 0 )
  331.         {
  332.             table->fixed_width_remaining = 0;
  333.         }
  334.         
  335.         for ( count = table_cell->colspan; count > 0 ; --count )
  336.         {
  337.             table->fixed_col_widths[ cell_num ] += add_width;
  338.             cell_width -= add_width;
  339.             cell_num++;
  340.         }
  341.         
  342.         /* add any odd amount to the last column */
  343.         table->fixed_col_widths[ cell_num-1 ] += cell_width;
  344.     }
  345. }
  346.  
  347. static int32
  348. lo_ComputeInternalTableWidth(MWContext *context,lo_TableRec *table,
  349.     lo_DocState *state)
  350. {
  351.     int32 table_width;
  352.     int32 cell_pad;
  353.     int32 table_pad;
  354.     
  355.     cell_pad = FEUNITS_X(table->inter_cell_pad, context);
  356.     
  357.     table_width = table->width;
  358.     if ( table_width == 0 )
  359.     {
  360.         /* Compute our starting width as the window width */
  361.         table_width = (state->win_width - state->win_left -
  362.             state->win_right);
  363.     }
  364.     
  365.     /* remove space for the table borders */
  366.     table_width -= ( table->table_ele->border_left_width
  367.         + table->table_ele->border_right_width );
  368.  
  369.     if (table->draw_borders == TABLE_BORDERS_OFF)
  370.     {
  371.         table_pad = FEUNITS_X(TABLE_DEF_CELL_BORDER, context);
  372.         table_width -= 2 * table_pad;
  373.     }
  374.     
  375.     if ( table->fixed_cols > 0 )
  376.     {
  377.         table_width -= ( table->fixed_cols + 1 ) * cell_pad;
  378.     }
  379.     else
  380.     {
  381.         table_width -= ( table->cols + 1 ) * cell_pad;
  382.     }
  383.  
  384.     return table_width;
  385. }
  386.  
  387. /*
  388.  ********************************************************************************
  389.  * Core Table Layout Code
  390.  */
  391.  
  392. void
  393. lo_BeginCaptionSubDoc(MWContext *context, lo_DocState *state,
  394.     lo_TableCaption *caption, PA_Tag *tag)
  395. {
  396.     LO_SubDocStruct *subdoc;
  397.     lo_DocState *new_state;
  398.     int32 first_width, first_height;
  399.     Bool allow_percent_width;
  400.     Bool allow_percent_height;
  401.  
  402.     /*
  403.      * Fill in the subdoc structure with default data
  404.      */
  405.     subdoc = (LO_SubDocStruct *)lo_NewElement(context, state, LO_SUBDOC, NULL, 0);
  406.     if (subdoc == NULL)
  407.     {
  408.         return;
  409.     }
  410.  
  411.     subdoc->type = LO_SUBDOC;
  412.     subdoc->ele_id = NEXT_ELEMENT;
  413.     subdoc->x = state->x;
  414.     subdoc->x_offset = 0;
  415.     subdoc->y = state->y;
  416.     subdoc->y_offset = 0;
  417.     subdoc->width = 0;
  418.     subdoc->height = 0;
  419.     subdoc->next = NULL;
  420.     subdoc->prev = NULL;
  421.  
  422.     subdoc->anchor_href = state->current_anchor;
  423.  
  424.     if (state->font_stack == NULL)
  425.     {
  426.         subdoc->text_attr = NULL;
  427.     }
  428.     else
  429.     {
  430.         subdoc->text_attr = state->font_stack->text_attr;
  431.     }
  432.  
  433.     subdoc->FE_Data = NULL;
  434.     subdoc->backdrop.bg_color = NULL;
  435.     subdoc->backdrop.url = NULL;
  436.     subdoc->backdrop.tile_mode = LO_TILE_BOTH;
  437.     subdoc->state = NULL;
  438.  
  439.     subdoc->vert_alignment = LO_ALIGN_CENTER;
  440.     subdoc->horiz_alignment = caption->horiz_alignment;
  441.  
  442.     subdoc->alignment = LO_ALIGN_BOTTOM;
  443.  
  444.     subdoc->border_width = 0;
  445.     subdoc->border_vert_space = 0;
  446.     subdoc->border_horiz_space = 0;
  447.  
  448.     subdoc->ele_attrmask = 0;
  449.  
  450.     subdoc->sel_start = -1;
  451.     subdoc->sel_end = -1;
  452.  
  453.     subdoc->border_width = FEUNITS_X(subdoc->border_width, context);
  454.  
  455.     if (subdoc->width == 0)
  456.     {
  457.         first_width = FEUNITS_X(5000, context);
  458.         allow_percent_width = FALSE;
  459.     }
  460.     else
  461.     {
  462.         first_width = subdoc->width;
  463.         allow_percent_width = TRUE;
  464.     }
  465.  
  466.     if (subdoc->height == 0)
  467.     {
  468.         first_height = FEUNITS_Y(10000, context);
  469.         allow_percent_height = FALSE;
  470.     }
  471.     else
  472.     {
  473.         first_height = subdoc->height;
  474.         allow_percent_height = TRUE;
  475.     }
  476.  
  477.     new_state = lo_NewLayout(context, first_width, first_height, 0, 0, NULL);
  478.     if (new_state == NULL)
  479.     {
  480.         lo_FreeElement(context, (LO_Element *)subdoc, FALSE);
  481.         return;
  482.     }
  483.     new_state->is_a_subdoc = SUBDOC_CAPTION;
  484.     lo_InheritParentState(context, new_state, state);
  485.     new_state->allow_percent_width = allow_percent_width;
  486.     new_state->allow_percent_height = allow_percent_height;
  487.  
  488.     new_state->base_x = 0;
  489.     new_state->base_y = 0;
  490.     new_state->display_blocked = TRUE;
  491.     if (subdoc->width == 0)
  492.     {
  493.         new_state->delay_align = TRUE;
  494.     }
  495.  
  496.     new_state->win_left = 0;
  497.     new_state->win_right = 0;
  498.     new_state->x = new_state->win_left;
  499.     new_state->y = 0;
  500.     new_state->max_width = new_state->x + 1;
  501.     new_state->left_margin = new_state->win_left;
  502.     new_state->right_margin = new_state->win_width - new_state->win_right;
  503.     new_state->list_stack->old_left_margin = new_state->left_margin;
  504.     new_state->list_stack->old_right_margin = new_state->right_margin;
  505.  
  506.     /*
  507.      * Initialize the alignment stack for this state
  508.      * to match the caption alignment.
  509.      */
  510.     if (subdoc->horiz_alignment != LO_ALIGN_LEFT)
  511.     {
  512.         lo_PushAlignment(new_state, tag->type, subdoc->horiz_alignment);
  513.     }
  514.  
  515.     state->sub_state = new_state;
  516.  
  517.     state->current_ele = (LO_Element *)subdoc;
  518.     
  519.     /*
  520.      * We added a new state.
  521.      */
  522.     lo_PushStateLevel ( context );
  523. }
  524.  
  525.  
  526. static void
  527. lo_reuse_current_state(MWContext *context, lo_DocState *state,
  528.     int32 width, int32 height, int32 margin_width, int32 margin_height,
  529.     Bool destroyLineLists)
  530. {
  531.     lo_TopState *top_state;
  532.     int32 doc_id;
  533.     lo_DocLists *doc_lists;
  534.  
  535.     doc_id = XP_DOCID(context);
  536.     top_state = lo_FetchTopState(doc_id);
  537.     if ((top_state == NULL)||(state == NULL))
  538.     {
  539.         return;
  540.     }
  541.  
  542.     state->subdoc_tags = NULL;
  543.     state->subdoc_tags_end = NULL;
  544.  
  545.     state->text_fg.red = lo_master_colors[LO_COLOR_FG].red;
  546.     state->text_fg.green = lo_master_colors[LO_COLOR_FG].green;
  547.     state->text_fg.blue = lo_master_colors[LO_COLOR_FG].blue;
  548.  
  549.     state->text_bg.red = lo_master_colors[LO_COLOR_BG].red;
  550.     state->text_bg.green = lo_master_colors[LO_COLOR_BG].green;
  551.     state->text_bg.blue = lo_master_colors[LO_COLOR_BG].blue;
  552.  
  553.     state->anchor_color.red = lo_master_colors[LO_COLOR_LINK].red;
  554.     state->anchor_color.green = lo_master_colors[LO_COLOR_LINK].green;
  555.     state->anchor_color.blue = lo_master_colors[LO_COLOR_LINK].blue;
  556.  
  557.     state->visited_anchor_color.red = lo_master_colors[LO_COLOR_VLINK].red;
  558.     state->visited_anchor_color.green = lo_master_colors[LO_COLOR_VLINK].green;
  559.     state->visited_anchor_color.blue = lo_master_colors[LO_COLOR_VLINK].blue;
  560.  
  561.     state->active_anchor_color.red = lo_master_colors[LO_COLOR_ALINK].red;
  562.     state->active_anchor_color.green = lo_master_colors[LO_COLOR_ALINK].green;
  563.     state->active_anchor_color.blue = lo_master_colors[LO_COLOR_ALINK].blue;
  564.  
  565.     state->win_top = margin_height;
  566.     state->win_bottom = margin_height;
  567.     state->win_width = width;
  568.     state->win_height = height;
  569.  
  570.     state->base_x = 0;
  571.     state->base_y = 0;
  572.     state->x = 0;
  573.     state->y = 0;
  574.     state->width = 0;
  575.     state->line_num = 1;
  576.  
  577.     state->win_left = margin_width;
  578.     state->win_right = margin_width;
  579.  
  580.     state->max_width = state->win_left + state->win_right;
  581.  
  582.     state->x = state->win_left;
  583.     state->y = state->win_top;
  584.  
  585.     state->left_margin = state->win_left;
  586.     state->right_margin = state->win_width - state->win_right;
  587.     if (state->left_margin_stack != NULL)
  588.     {
  589.         lo_MarginStack *mptr;
  590.         lo_MarginStack *margin;
  591.  
  592.         mptr = state->left_margin_stack;
  593.         while (mptr != NULL)
  594.         {
  595.             margin = mptr;
  596.             mptr = mptr->next;
  597.             XP_DELETE(margin);
  598.         }
  599.         state->left_margin_stack = NULL;
  600.     }
  601.     if (state->right_margin_stack != NULL)
  602.     {
  603.         lo_MarginStack *mptr;
  604.         lo_MarginStack *margin;
  605.  
  606.         mptr = state->right_margin_stack;
  607.         while (mptr != NULL)
  608.         {
  609.             margin = mptr;
  610.             mptr = mptr->next;
  611.             XP_DELETE(margin);
  612.         }
  613.         state->right_margin_stack = NULL;
  614.     }
  615.  
  616.     state->break_holder = state->x;
  617.     state->min_width = 0;
  618.     state->text_divert = P_UNKNOWN;
  619.     state->linefeed_state = 2;
  620.     state->delay_align = FALSE;
  621.     state->breakable = TRUE;
  622.     state->allow_amp_escapes = TRUE;
  623.     state->preformatted = PRE_TEXT_NO;
  624.     state->preformat_cols = 0;
  625.  
  626.     state->in_paragraph = FALSE;
  627.  
  628.     state->display_blocked = FALSE;
  629.     state->display_blocking_element_id = 0;
  630.     state->display_blocking_element_y = 0;
  631.  
  632.     if (destroyLineLists == TRUE)
  633.     {
  634.         if (state->line_list != NULL)
  635.         {
  636.             lo_FreeElementList(context, state->line_list);
  637.             state->line_list = NULL;
  638.         }
  639.         state->end_last_line = NULL;
  640.         if (state->float_list != NULL)
  641.         {    
  642.             lo_FreeElementList(context, state->float_list);
  643.             state->float_list = NULL;
  644.         }
  645.     }
  646.  
  647.     state->base_font_size = DEFAULT_BASE_FONT_SIZE;
  648.     if (state->font_stack != NULL)
  649.     {
  650.         lo_FontStack *fstack;
  651.         lo_FontStack *fptr;
  652.  
  653.         fptr = state->font_stack;
  654.         while (fptr != NULL)
  655.         {
  656.             fstack = fptr;
  657.             fptr = fptr->next;
  658.             XP_DELETE(fstack);
  659.         }
  660.         state->font_stack = NULL;
  661.     }
  662.     state->font_stack = lo_DefaultFont(state, context);
  663.  
  664.     state->font_stack->text_attr->size = state->base_font_size;
  665.  
  666.     if (state->align_stack != NULL)
  667.     {
  668.         lo_AlignStack *aptr;
  669.         lo_AlignStack *align;
  670.  
  671.         aptr = state->align_stack;
  672.         while (aptr != NULL)
  673.         {
  674.             align = aptr;
  675.             aptr = aptr->next;
  676.             XP_DELETE(align);
  677.         }
  678.         state->align_stack = NULL;
  679.     }
  680.     if (state->list_stack != NULL)
  681.     {
  682.         lo_ListStack *lptr;
  683.         lo_ListStack *list;
  684.  
  685.         lptr = state->list_stack;
  686.         while (lptr != NULL)
  687.         {
  688.             list = lptr;
  689.             lptr = lptr->next;
  690.             XP_DELETE(list);
  691.         }
  692.         state->list_stack = NULL;
  693.     }
  694.     state->list_stack = lo_DefaultList(state);
  695.  
  696.     state->text_info.max_width = 0;
  697.     state->text_info.ascent = 0;
  698.     state->text_info.descent = 0;
  699.     state->text_info.lbearing = 0;
  700.     state->text_info.rbearing = 0;
  701.  
  702.     state->line_buf_len = 0;
  703.  
  704.     state->baseline = 0;
  705.     state->line_height = 0;
  706.     state->break_pos = -1;
  707.     state->break_width = 0;
  708.     state->last_char_CR = FALSE;
  709.     state->trailing_space = FALSE;
  710.     state->at_begin_line = TRUE;
  711.  
  712.     state->old_break = NULL;
  713.     state->old_break_block = NULL;
  714.     state->old_break_pos = -1;
  715.     state->old_break_width = 0;
  716.  
  717.     state->current_named_anchor = NULL;
  718.     state->current_anchor = NULL;
  719.  
  720.     state->cur_ele_type = LO_NONE;
  721.     state->current_ele = NULL;
  722.     state->current_java = NULL;
  723.  
  724.     state->current_table = NULL;
  725.     state->current_grid = NULL;
  726.     state->current_multicol = NULL;
  727.  
  728.     if (state->top_state->doc_state)
  729.         doc_lists = lo_GetCurrentDocLists(state->top_state->doc_state);
  730.     else
  731.         doc_lists = lo_GetCurrentDocLists(state);
  732.     
  733.     /*
  734.      * These values are saved into the (sub)doc here
  735.      * so that if it gets Relayout() later, we know where
  736.      * to reset the from counts to.
  737.      */
  738.     if (doc_lists->form_list != NULL)
  739.     {
  740.         lo_FormData *form_list;
  741.  
  742.         form_list = doc_lists->form_list;
  743.         state->form_ele_cnt = form_list->form_ele_cnt;
  744.         state->form_id = form_list->id;
  745.     }
  746.     else
  747.     {
  748.         state->form_ele_cnt = 0;
  749.         state->form_id = 0;
  750.     }
  751.     state->start_in_form = top_state->in_form;
  752.     if (top_state->savedData.FormList != NULL)
  753.     {
  754.         lo_SavedFormListData *all_form_ele;
  755.  
  756.         all_form_ele = top_state->savedData.FormList;
  757.         state->form_data_index = all_form_ele->data_index;
  758.     }
  759.     else
  760.     {
  761.         state->form_data_index = 0;
  762.     }
  763.  
  764.     /*
  765.      * Remember number of embeds we had before beginning this
  766.      * (sub)doc. This information is used in laytable.c so
  767.      * it can preserve embed indices across a relayout.
  768.      */
  769.     state->embed_count_base = top_state->embed_count;
  770.  
  771.     /*
  772.      * Ditto for anchors, images, applets and embeds
  773.      */
  774.     state->url_count_base = doc_lists->url_list_len;
  775.     state->image_list_count_base = doc_lists->image_list_count;
  776.         state->applet_list_count_base = doc_lists->applet_list_count;
  777.         state->embed_list_count_base = doc_lists->embed_list_count;
  778.     state->current_layer_num_base = top_state->current_layer_num;
  779.     state->current_layer_num_max = top_state->current_layer_num;
  780.  
  781.     state->must_relayout_subdoc = FALSE;
  782.     state->allow_percent_width = TRUE;
  783.     state->allow_percent_height = TRUE;
  784.     state->is_a_subdoc = SUBDOC_NOT;
  785.     state->current_subdoc = 0;
  786.     state->sub_documents = NULL;
  787.     state->sub_state = NULL;
  788.  
  789.     state->current_cell = NULL;
  790.  
  791.     state->extending_start = FALSE;
  792.     state->selection_start = NULL;
  793.     state->selection_start_pos = 0;
  794.     state->selection_end = NULL;
  795.     state->selection_end_pos = 0;
  796.     state->selection_new = NULL;
  797.     state->selection_new_pos = 0;
  798.  
  799. #ifdef EDITOR
  800.     state->edit_force_offset = FALSE;
  801.     state->edit_current_element = 0;
  802.     state->edit_current_offset = 0;
  803.     state->edit_relayout_display_blocked = FALSE;
  804. #endif
  805. #ifdef MOCHA
  806.     state->in_relayout = FALSE;
  807. #endif
  808.  
  809.     state->cur_text_block = NULL;
  810.     
  811.     /* we need min widths during the initial table layout pass */
  812.     state->need_min_width = TRUE;
  813. }
  814.  
  815.  
  816. static void
  817. lo_reuse_current_subdoc(MWContext *context, LO_SubDocStruct *subdoc)
  818. {
  819.     if (subdoc == NULL)
  820.     {
  821.         return;
  822.     }
  823.  
  824.     subdoc->type = LO_SUBDOC;
  825.     subdoc->ele_id = 0;
  826.     subdoc->x = 0;
  827.     subdoc->x_offset = 0;
  828.     subdoc->y = 0;
  829.     subdoc->y_offset = 0;
  830.     subdoc->width = 0;
  831.     subdoc->height = 0;
  832.     subdoc->next = NULL;
  833.     subdoc->prev = NULL;
  834.  
  835.     subdoc->FE_Data = NULL;
  836.  
  837.     /*
  838.      * We leave subdoc->state alone as it will get reused later.
  839.      */
  840.  
  841.     XP_FREEIF(subdoc->backdrop.bg_color);
  842.     XP_FREEIF(subdoc->backdrop.url);
  843.  
  844.     /*
  845.      * These two come from lists of shared pointers, so
  846.      * we NULL them but don't free them.
  847.      */
  848.     subdoc->anchor_href = NULL;
  849.     subdoc->text_attr = NULL;
  850.  
  851.     subdoc->alignment = LO_ALIGN_LEFT;
  852.     subdoc->vert_alignment = LO_ALIGN_TOP;
  853.     subdoc->horiz_alignment = LO_ALIGN_LEFT;
  854.     subdoc->border_width = 0;
  855.     subdoc->border_vert_space = 0;
  856.     subdoc->border_horiz_space = 0;
  857.     subdoc->ele_attrmask = 0;
  858.     subdoc->sel_start = -1;
  859.     subdoc->sel_end = -1;
  860. }
  861.  
  862.  
  863. static void
  864. lo_cleanup_old_state(lo_DocState *state)
  865. {
  866.     LO_Element **line_array;
  867.  
  868.     if (state == NULL)
  869.     {
  870.         return;
  871.     }
  872.  
  873.     /*
  874.      * Clear out the start of the line_list.
  875.      */
  876. #ifdef XP_WIN16
  877.     {
  878.         XP_Block *larray_array;
  879.  
  880.         XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array);
  881.         state->line_array = larray_array[0];
  882.         XP_UNLOCK_BLOCK(state->larray_array);
  883.     }
  884. #endif /* XP_WIN16 */
  885.     XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array);
  886.     line_array[0] = NULL;
  887.     XP_UNLOCK_BLOCK(state->line_array);
  888.  
  889.     state->end_last_line = NULL;
  890.  
  891.     state->float_list = NULL;
  892. }
  893.  
  894.  
  895. static int32 lo_CalculateCellPercentWidth( lo_TableRec *table, int32 percent)
  896. {
  897.     int32 val = percent;
  898.  
  899.     if ( table->table_width_fixed != FALSE )
  900.     {
  901.         val = table->width * val / 100;
  902.     }
  903.     else
  904.     {
  905.         val = 0;
  906.     }
  907.     return val;
  908. }
  909.  
  910. static int32 lo_CalculateCellPercentHeight( lo_TableRec *table, lo_TableCell *table_cell)
  911. {
  912.     int32 val;
  913.  
  914.     if ((table->height > 0)&&
  915.         (table_cell->percent_height > 0))
  916.     {
  917.         val = table->height *
  918.             table_cell->percent_height / 100;
  919.     }
  920.     else
  921.     {
  922.         val = 0;
  923.     }
  924.     return val;
  925. }
  926.  
  927. void
  928. lo_BeginCellSubDoc(MWContext *context, 
  929.                      lo_DocState *state,
  930.                      lo_TableRec *table,
  931.                      char *bgcolor_attr,
  932.                      char *background_attr,
  933.                     lo_TileMode tile_mode,
  934.                      char *valign_attr,
  935.                      char *halign_attr,
  936.                      char *width_attr,
  937.                      char *height_attr,
  938.                      Bool is_a_header, 
  939.                      intn draw_borders,
  940.                     Bool relayout /* Is true during relayout without reload */)
  941. {
  942.     LO_SubDocStruct *subdoc;
  943.     lo_DocState *new_state;
  944.     lo_TableRow *table_row;
  945.     lo_TableCell *table_cell;
  946.     int32 val;
  947.     int32 first_width, first_height;
  948.     Bool allow_percent_width;
  949.     Bool allow_percent_height;
  950.     StyleStruct *style_struct=0;
  951. #ifdef LOCAL_DEBUG
  952.  fprintf(stderr, "lo_BeginCellSubDoc called\n");
  953. #endif /* LOCAL_DEBUG */
  954.  
  955.     table_row = table->row_ptr;
  956.     table_cell = table_row->cell_ptr;
  957.  
  958.     if (relayout == FALSE) 
  959.     {
  960.         if(state->top_state && state->top_state->style_stack)
  961.             style_struct = STYLESTACK_GetStyleByIndex(
  962.                                             state->top_state->style_stack,
  963.                                             0);
  964.     }
  965.  
  966.     /*
  967.      * Fill in the subdoc structure with default data
  968.      */
  969.     lo_reuse_current_subdoc(context, table->current_subdoc);
  970.     subdoc = table->current_subdoc;
  971.     if (subdoc == NULL)
  972.     {
  973.         return;
  974.     }
  975.  
  976.     subdoc->type = LO_SUBDOC;
  977.     subdoc->ele_id = NEXT_ELEMENT;
  978.     subdoc->x = state->x;
  979.     subdoc->x_offset = 0;
  980.     subdoc->y = state->y;
  981.     subdoc->y_offset = 0;
  982.     subdoc->width = 0;
  983.     subdoc->height = 0;
  984.     subdoc->next = NULL;
  985.     subdoc->prev = NULL;
  986.  
  987.     subdoc->anchor_href = state->current_anchor;
  988.  
  989.     if (state->font_stack == NULL)
  990.     {
  991.         subdoc->text_attr = NULL;
  992.     }
  993.     else
  994.     {
  995.         subdoc->text_attr = state->font_stack->text_attr;
  996.     }
  997.  
  998.     subdoc->FE_Data = NULL;
  999.  
  1000.     subdoc->vert_alignment = table_row->vert_alignment;
  1001.     if (subdoc->vert_alignment == LO_ALIGN_DEFAULT)
  1002.     {
  1003.         subdoc->vert_alignment = LO_ALIGN_CENTER;
  1004.     }
  1005.     subdoc->horiz_alignment = table_row->horiz_alignment;
  1006.     if (subdoc->horiz_alignment == LO_ALIGN_DEFAULT)
  1007.     {
  1008.         if (is_a_header == FALSE)
  1009.         {
  1010.             subdoc->horiz_alignment = LO_ALIGN_LEFT;
  1011.         }
  1012.         else
  1013.         {
  1014.             subdoc->horiz_alignment = LO_ALIGN_CENTER;
  1015.         }
  1016.     }
  1017.     subdoc->alignment = LO_ALIGN_BOTTOM;
  1018.  
  1019.     if (draw_borders == TABLE_BORDERS_OFF)
  1020.     {
  1021.         subdoc->border_width = 0;
  1022.         subdoc->border_vert_space = TABLE_DEF_CELL_BORDER;
  1023.         subdoc->border_horiz_space = TABLE_DEF_CELL_BORDER;
  1024.     }
  1025.     else if (draw_borders == TABLE_BORDERS_ON)
  1026.     {
  1027.         subdoc->border_width = TABLE_DEF_CELL_BORDER;
  1028.         subdoc->border_vert_space = 0;
  1029.         subdoc->border_horiz_space = 0;
  1030.     }
  1031.     else
  1032.     {
  1033.         subdoc->border_width = 0;
  1034.         subdoc->border_vert_space = 0;
  1035.         subdoc->border_horiz_space = 0;
  1036.     }
  1037.  
  1038.     subdoc->ele_attrmask = 0;
  1039.  
  1040.     subdoc->sel_start = -1;
  1041.     subdoc->sel_end = -1;
  1042.  
  1043.     subdoc->backdrop.bg_color = NULL;
  1044.     subdoc->backdrop.url = NULL;
  1045.     subdoc->backdrop.tile_mode = LO_TILE_BOTH;
  1046.  
  1047.     /*
  1048.      * May inherit a bg_color from your row.
  1049.      */
  1050.     if (table_row->backdrop.bg_color != NULL)
  1051.     {
  1052.         subdoc->backdrop.bg_color = XP_NEW(LO_Color);
  1053.         if (subdoc->backdrop.bg_color != NULL)
  1054.             *subdoc->backdrop.bg_color = *table_row->backdrop.bg_color;
  1055.     }
  1056.  
  1057.     if (relayout == FALSE)
  1058.     {
  1059.         subdoc->backdrop.bg_color = NULL;
  1060.         subdoc->backdrop.url = NULL;
  1061.         subdoc->backdrop.tile_mode = LO_TILE_BOTH;
  1062.  
  1063.         /*
  1064.          * May inherit a bg_color from your row.
  1065.          */
  1066.         if (table_row->backdrop.bg_color != NULL)
  1067.         {
  1068.             subdoc->backdrop.bg_color = XP_NEW(LO_Color);
  1069.             if (subdoc->backdrop.bg_color != NULL)
  1070.                 *subdoc->backdrop.bg_color = *table_row->backdrop.bg_color;
  1071.         }
  1072.  
  1073.         /*
  1074.          * Else may inherit a bg_color from your table.
  1075.          */
  1076.         else if (table->backdrop.bg_color != NULL)
  1077.         {
  1078.             subdoc->backdrop.bg_color = XP_NEW(LO_Color);
  1079.             if (subdoc->backdrop.bg_color != NULL)
  1080.                 *subdoc->backdrop.bg_color = *table->backdrop.bg_color;
  1081.         }
  1082.         /*
  1083.          * Else possibly inherit the background color attribute
  1084.          * of a parent table cell.
  1085.          */
  1086.         else if (state->is_a_subdoc == SUBDOC_CELL)
  1087.         {
  1088.             lo_DocState *up_state;
  1089.  
  1090.             /*
  1091.              * Find the parent subdoc's state.
  1092.              */
  1093.             up_state = state->top_state->doc_state;
  1094.             while ((up_state->sub_state != NULL)&&
  1095.                 (up_state->sub_state != state))
  1096.             {
  1097.                 up_state = up_state->sub_state;
  1098.             }
  1099.             if ((up_state->sub_state != NULL)&&
  1100.                 (up_state->current_ele != NULL)&&
  1101.                 (up_state->current_ele->type == LO_SUBDOC)&&
  1102.                 (up_state->current_ele->lo_subdoc.backdrop.bg_color != NULL))
  1103.             {
  1104.                 LO_Color *old_bg;
  1105.  
  1106.                 old_bg = up_state->current_ele->lo_subdoc.backdrop.bg_color;
  1107.                 subdoc->backdrop.bg_color = XP_NEW(LO_Color);
  1108.                 if (subdoc->backdrop.bg_color != NULL)
  1109.                     *subdoc->backdrop.bg_color = *old_bg;
  1110.             }
  1111.         }
  1112.  
  1113.  
  1114.         /* Use backdrop URL, if supplied. */
  1115.         if (background_attr)
  1116.         {
  1117.             subdoc->backdrop.url = XP_STRDUP(background_attr);
  1118.             subdoc->backdrop.tile_mode = tile_mode;
  1119.         }
  1120.     
  1121.         /*
  1122.          * May inherit a backdrop_url from parent row.
  1123.          */
  1124.         else if (table_row->backdrop.url)
  1125.         {
  1126.             subdoc->backdrop.url = XP_STRDUP(table_row->backdrop.url);
  1127.             subdoc->backdrop.tile_mode = table_row->backdrop.tile_mode;
  1128.         }
  1129.  
  1130.         /*
  1131.          * Else may inherit a backdrop_url from parent table.
  1132.          */
  1133.         else if (table->backdrop.url != NULL)
  1134.         {
  1135.             subdoc->backdrop.url = XP_STRDUP(table->backdrop.url);
  1136.             subdoc->backdrop.tile_mode = table->backdrop.tile_mode;
  1137.         }
  1138.         /*
  1139.          * Else possibly inherit the backdrop_url
  1140.          * of a parent table cell.
  1141.          */
  1142.         else if (state->is_a_subdoc == SUBDOC_CELL)
  1143.         {
  1144.             lo_DocState *up_state;
  1145.  
  1146.             /*
  1147.              * Find the parent subdoc's state.
  1148.              */
  1149.             up_state = state->top_state->doc_state;
  1150.             while ((up_state->sub_state != NULL)&&
  1151.                 (up_state->sub_state != state))
  1152.             {
  1153.                 up_state = up_state->sub_state;
  1154.             }
  1155.             if ((up_state->sub_state != NULL)&&
  1156.                 (up_state->current_ele != NULL)&&
  1157.                 (up_state->current_ele->type == LO_SUBDOC)&&
  1158.                 (up_state->current_ele->lo_subdoc.backdrop.url != NULL))
  1159.             {
  1160.                 lo_Backdrop *src_backdrop = &up_state->current_ele->lo_subdoc.backdrop;
  1161.                 subdoc->backdrop.url = XP_STRDUP(src_backdrop->url);
  1162.                 subdoc->backdrop.tile_mode = src_backdrop->tile_mode;
  1163.             }
  1164.         }
  1165.  
  1166.         /*
  1167.          * Check for a background color attribute
  1168.          */
  1169.         if (bgcolor_attr)
  1170.         {
  1171.             uint8 red, green, blue;
  1172.  
  1173.             LO_ParseRGB(bgcolor_attr, &red, &green, &blue);
  1174.             XP_FREEIF(subdoc->backdrop.bg_color);
  1175.             subdoc->backdrop.bg_color = XP_NEW(LO_Color);
  1176.             if (subdoc->backdrop.bg_color != NULL)
  1177.             {
  1178.                 subdoc->backdrop.bg_color->red = red;
  1179.                 subdoc->backdrop.bg_color->green = green;
  1180.                 subdoc->backdrop.bg_color->blue = blue;
  1181.             }
  1182.         }
  1183.  
  1184.         /* check for a style sheet directive for bgcolor */
  1185.         if(style_struct)
  1186.         {
  1187.             char *property = STYLESTRUCT_GetString(style_struct, BG_COLOR_STYLE);
  1188.         
  1189.             if(property)
  1190.             {
  1191.                 uint8 red, green, blue;
  1192.  
  1193.                 LO_ParseStyleSheetRGB(property, &red, &green, &blue);
  1194.  
  1195.                 XP_FREEIF(subdoc->backdrop.bg_color);
  1196.                 subdoc->backdrop.bg_color = XP_NEW(LO_Color);
  1197.                 if (subdoc->backdrop.bg_color != NULL)
  1198.                 {
  1199.                     subdoc->backdrop.bg_color->red = red;
  1200.                     subdoc->backdrop.bg_color->green = green;
  1201.                     subdoc->backdrop.bg_color->blue = blue;
  1202.                 }
  1203.                 XP_FREE(property);
  1204.             }
  1205.  
  1206.             property = STYLESTRUCT_GetString(style_struct, BG_IMAGE_STYLE);
  1207.             if(property)
  1208.             {
  1209.                 if(subdoc->backdrop.url)
  1210.                     XP_FREE(subdoc->backdrop.url);
  1211.                 subdoc->backdrop.url = NULL;
  1212.  
  1213.                 if(strcasecomp(property, "none"))
  1214.             {
  1215.                     subdoc->backdrop.url = XP_STRDUP(lo_ParseStyleSheetURL(property));
  1216.                 }
  1217.                 XP_FREE(property);
  1218.             }
  1219.  
  1220.             property = STYLESTRUCT_GetString(style_struct, BG_REPEAT_STYLE);
  1221.             if(property)
  1222.             {
  1223.                 if(!strcasecomp(property, BG_REPEAT_NONE_STYLE))
  1224.                     subdoc->backdrop.tile_mode = LO_NO_TILE;
  1225.                 else if(!strcasecomp(property, BG_REPEAT_X_STYLE))
  1226.                     subdoc->backdrop.tile_mode = LO_TILE_HORIZ;
  1227.                 else if(!strcasecomp(property, BG_REPEAT_Y_STYLE))
  1228.                     subdoc->backdrop.tile_mode = LO_TILE_VERT;
  1229.                 else 
  1230.                     subdoc->backdrop.tile_mode = LO_TILE_BOTH;
  1231.             }
  1232.         }
  1233.     }    
  1234.     else  /* If relayout is TRUE */
  1235.     {
  1236.         /*
  1237.         subdoc->backdrop.tile_mode = table_cell->cell->backdrop.tile_mode;        
  1238.         if (table_cell->cell->backdrop.bg_color != NULL)
  1239.         {
  1240.             subdoc->backdrop.bg_color = XP_NEW(LO_Color);
  1241.             subdoc->backdrop.bg_color->red = table_cell->cell->backdrop.bg_color->red;
  1242.             subdoc->backdrop.bg_color->green = table_cell->cell->backdrop.bg_color->green;
  1243.             subdoc->backdrop.bg_color->blue = table_cell->cell->backdrop.bg_color->blue;
  1244.         }
  1245.         if (table_cell->cell->backdrop.url != NULL)
  1246.         {
  1247.             subdoc->backdrop.url = XP_STRDUP(table_cell->cell->backdrop.url);
  1248.         }
  1249.         */
  1250.         subdoc->backdrop = table_cell->cell->backdrop;
  1251.     }
  1252.  
  1253.     /*
  1254.      * Check for a vertical align parameter
  1255.      */
  1256.     if (valign_attr)
  1257.     {
  1258.         subdoc->vert_alignment = lo_EvalVAlignParam(valign_attr);
  1259.     }
  1260.  
  1261.  
  1262.  
  1263.     if(style_struct)
  1264.     {
  1265.         char *property = STYLESTRUCT_GetString(style_struct, VERTICAL_ALIGN_STYLE);
  1266.     
  1267.         if(property)
  1268.         {
  1269.             subdoc->vert_alignment = lo_EvalVAlignParam(property);
  1270.             XP_FREE(property);
  1271.         }
  1272.     }
  1273.  
  1274.     if (relayout)
  1275.     {
  1276.         subdoc->vert_alignment = table_cell->vert_alignment;
  1277.     }
  1278.  
  1279.     /*
  1280.      * Check for a horizontal align parameter
  1281.      */
  1282.     if (halign_attr)
  1283.     {
  1284.         subdoc->horiz_alignment = lo_EvalCellAlignParam(halign_attr);
  1285.     }
  1286.  
  1287.     if (relayout)
  1288.     {
  1289.         subdoc->horiz_alignment = table_cell->horiz_alignment;
  1290.     }
  1291.  
  1292.     subdoc->border_width = FEUNITS_X(subdoc->border_width, context);
  1293.     subdoc->border_vert_space =
  1294.         FEUNITS_Y(subdoc->border_vert_space, context);
  1295.     subdoc->border_horiz_space =
  1296.         FEUNITS_X(subdoc->border_horiz_space, context);
  1297.  
  1298.     /*
  1299.      * Allow individual setting of cell
  1300.      * width and height.
  1301.      */
  1302.     if (width_attr)
  1303.     {
  1304.         Bool is_percent;
  1305.  
  1306.         val = lo_ValueOrPercent(width_attr, &is_percent);
  1307.         if (is_percent != FALSE)
  1308.         {
  1309.             /*
  1310.              * Percentage width cells must be handled
  1311.              * later after at least the whole row is
  1312.              * processed.
  1313.              */
  1314.             table_cell->percent_width = val;
  1315.             table_row->has_percent_width_cells = TRUE;
  1316.             table->has_percent_width_cells = TRUE;
  1317.             val = lo_CalculateCellPercentWidth( table, val );
  1318.  
  1319.             /* Copied to lo_CalculateCellPercentWidth() */
  1320.             /*
  1321.             if ( table->table_width_fixed != FALSE )
  1322.             {
  1323.                 val = table->width * val / 100;
  1324.             }
  1325.             else
  1326.             {
  1327.                 val = 0;
  1328.             }
  1329.             */
  1330.         }
  1331.         else
  1332.         {
  1333.             table_cell->percent_width = 0;
  1334.             val = FEUNITS_X(val, context);
  1335.         }
  1336.         if (val < 0)
  1337.         {
  1338.             val = 0;
  1339.         }
  1340.         
  1341.         subdoc->width = val;
  1342.         table_cell->specified_width = subdoc->width;
  1343.     }
  1344.  
  1345.     /* During relayout without reload, recalculate width of subdoc */
  1346.     if (relayout)
  1347.     {
  1348.         if (table_cell->percent_width > 0)
  1349.         {
  1350.             subdoc->width = lo_CalculateCellPercentWidth( table, table_cell->percent_width);
  1351.             table_cell->specified_width = subdoc->width;
  1352.         }
  1353.         else {
  1354.             subdoc->width = table_cell->specified_width;
  1355.             if (subdoc->width < 0) {
  1356.                 subdoc->width = 0;
  1357.             }
  1358.         }
  1359.         
  1360.     }
  1361.                             
  1362.     /*
  1363.      * If we're in the fixed layout case, figure out what our cell
  1364.      * width should be.
  1365.      */
  1366.     if ( table->fixed_cols > 0 )
  1367.     {
  1368.         int32 cell_empty_space;
  1369.         int32 def_cell_width;
  1370.         int32 desired_width;
  1371.         
  1372.         cell_empty_space = lo_ComputeCellEmptySpace ( context, table, subdoc);
  1373.  
  1374.         desired_width = subdoc->width;
  1375.         /*
  1376.          * Obey percentage cell width in fixed columns if we
  1377.          * already know table width.
  1378.          */
  1379.         if ((table_cell->percent_width > 0)&&(table->width > 0))
  1380.         {
  1381.             int32 avail_width;
  1382.             int32 cell_pad;
  1383.  
  1384.             /*
  1385.              * Percentage width is a percentage of the available
  1386.              * cell space.
  1387.              */
  1388.             cell_pad = FEUNITS_X(table->inter_cell_pad, context);
  1389.             avail_width = table->width -
  1390.                 ((table->fixed_cols + 1) * cell_pad);
  1391.             avail_width -= (table->table_ele->border_left_width +
  1392.                     table->table_ele->border_right_width);
  1393.             desired_width = avail_width *
  1394.                 table_cell->percent_width / 100;
  1395.             /*
  1396.              * Pecentage width takes into account the
  1397.              * cell padding/spacing already.
  1398.              */
  1399.             desired_width -= cell_empty_space;
  1400.         }
  1401.         def_cell_width = lo_FindDefaultCellWidth (context, table,
  1402.             table_cell, desired_width, cell_empty_space);
  1403.         
  1404.         /*
  1405.          * If NOWRAP is off, we can go ahead and layout to this width. Otherwise
  1406.          * we want to layout to a dynamic width and then use the bigger of the
  1407.          * default or computed width for the cell.
  1408.          */
  1409.         if ( table_cell->nowrap == FALSE )
  1410.         {
  1411.             subdoc->width = def_cell_width;
  1412.         }
  1413.     }
  1414.         
  1415.     if (height_attr)
  1416.     {
  1417.         Bool is_percent;
  1418.  
  1419.         val = lo_ValueOrPercent(height_attr, &is_percent);
  1420.         if (is_percent != FALSE)
  1421.         {
  1422.             /*
  1423.              * We can process percentage heights here if
  1424.              * we have a known table height.
  1425.              */
  1426.             table_cell->percent_height = val;
  1427.             table->has_percent_height_cells = TRUE;
  1428.             val = lo_CalculateCellPercentHeight(table, table_cell);
  1429.  
  1430.             /* Copied to lo_CalculateCellPercentHeight() */
  1431.             /*
  1432.             if ((table->height > 0)&&
  1433.                 (table_cell->percent_height > 0))
  1434.             {
  1435.                 val = table->height *
  1436.                     table_cell->percent_height / 100;
  1437.             }
  1438.             else
  1439.             {
  1440.                 val = 0;
  1441.             }
  1442.             */
  1443.         }
  1444.         else
  1445.         {
  1446.             table_cell->percent_height = 0;
  1447.             val = FEUNITS_X(val, context);
  1448.         }
  1449.         subdoc->height = val;
  1450.         if (subdoc->height < 0)
  1451.         {
  1452.             subdoc->height = 0;
  1453.         }
  1454.         table_cell->specified_height = subdoc->height;
  1455.     }
  1456.  
  1457.     /* During relayout without reload, recalculate height of subdoc */
  1458.     if (relayout)
  1459.     {
  1460.         if (table_cell->percent_height > 0)
  1461.         {
  1462.             subdoc->height = lo_CalculateCellPercentHeight( table, table_cell);
  1463.             table_cell->specified_height = subdoc->height;
  1464.         }
  1465.         else {
  1466.             subdoc->height = table_cell->specified_height;
  1467.             if (subdoc->height < 0) {
  1468.                 subdoc->height = 0;
  1469.             }
  1470.         }
  1471.         
  1472.     }
  1473.  
  1474.     if (subdoc->width == 0)
  1475.     {
  1476.         /*
  1477.          * Choose a default size that will fit within the current table. If NOWRAP is
  1478.          * on, we just want to go ahead and choose a big width so that we're sure
  1479.          * to get the correct nonwrapping text layout.
  1480.          */
  1481.         if ( table_cell->nowrap == FALSE )
  1482.         {
  1483.             first_width = lo_ComputeInternalTableWidth ( context, table, state );
  1484.             first_width -= lo_ComputeCellEmptySpace ( context, table, subdoc);
  1485.         }
  1486.         else
  1487.         {
  1488.             first_width = FEUNITS_X(5000, context);
  1489.         }
  1490.         
  1491.         allow_percent_width = FALSE;
  1492.     }
  1493.     else
  1494.     {
  1495.         first_width = subdoc->width;
  1496.         allow_percent_width = TRUE;
  1497.     }
  1498.  
  1499.     if (subdoc->height == 0)
  1500.     {
  1501.         first_height = FEUNITS_Y(10000, context);
  1502.         allow_percent_height = FALSE;
  1503.     }
  1504.     else
  1505.     {
  1506.         first_height = subdoc->height;
  1507.         allow_percent_height = TRUE;
  1508.     }
  1509.  
  1510.     lo_reuse_current_state(context, subdoc->state,
  1511.         first_width, first_height, 0, 0, TRUE);
  1512.     new_state = subdoc->state;
  1513.     subdoc->state = NULL;
  1514.  
  1515.     if (new_state == NULL)
  1516.     {
  1517.         lo_FreeElement(context, (LO_Element *)subdoc, FALSE);
  1518.         return;
  1519.     }
  1520.     new_state->is_a_subdoc = SUBDOC_CELL;
  1521.     lo_InheritParentState(context, new_state, state);
  1522.     new_state->allow_percent_width = allow_percent_width;
  1523.     new_state->allow_percent_height = allow_percent_height;
  1524.  
  1525.     new_state->base_x = 0;
  1526.     new_state->base_y = 0;
  1527.     new_state->display_blocked = TRUE;
  1528.     if (subdoc->width == 0)
  1529.     {
  1530.         new_state->delay_align = TRUE;
  1531.     }
  1532.  
  1533.     new_state->win_left = 0;
  1534.     new_state->win_right = 0;
  1535.     new_state->x = new_state->win_left;
  1536.     new_state->y = 0;
  1537.     new_state->max_width = new_state->x + 1;
  1538.     new_state->left_margin = new_state->win_left;
  1539.     new_state->right_margin = new_state->win_width - new_state->win_right;
  1540.     new_state->list_stack->old_left_margin = new_state->left_margin;
  1541.     new_state->list_stack->old_right_margin = new_state->right_margin;
  1542.  
  1543.     /*
  1544.      * Initialize the alignment stack for this state
  1545.      * to match the caption alignment.
  1546.      */
  1547.     if (subdoc->horiz_alignment != LO_ALIGN_LEFT)
  1548.     {
  1549.         lo_PushAlignment(new_state, P_TABLE_DATA, subdoc->horiz_alignment);
  1550.     }
  1551.  
  1552.     state->sub_state = new_state;
  1553.  
  1554.     state->current_ele = (LO_Element *)subdoc;
  1555.  
  1556.     if (is_a_header != FALSE)
  1557.     {
  1558.         LO_TextAttr *old_attr;
  1559.         LO_TextAttr *attr;
  1560.         LO_TextAttr tmp_attr;
  1561.  
  1562.         old_attr = new_state->font_stack->text_attr;
  1563.         lo_CopyTextAttr(old_attr, &tmp_attr);
  1564.         tmp_attr.fontmask |= LO_FONT_BOLD;
  1565.         attr = lo_FetchTextAttr(new_state, &tmp_attr);
  1566.  
  1567.         lo_PushFont(new_state, P_TABLE_DATA, attr);
  1568.     }
  1569. }
  1570.  
  1571.  
  1572. Bool
  1573. lo_subdoc_has_elements(lo_DocState *sub_state)
  1574. {
  1575.     if (sub_state->end_last_line != NULL)
  1576.     {
  1577.         return(TRUE);
  1578.     }
  1579.     if (sub_state->float_list != NULL)
  1580.     {
  1581.         return(TRUE);
  1582.     }
  1583.     return(FALSE);
  1584. }
  1585.  
  1586.  
  1587. Bool
  1588. lo_cell_has_elements(LO_CellStruct *cell)
  1589. {
  1590.     if (cell->cell_list != NULL)
  1591.     {
  1592.         return(TRUE);
  1593.     }
  1594.     if (cell->cell_float_list != NULL)
  1595.     {
  1596.         return(TRUE);
  1597.     }
  1598.     return(FALSE);
  1599. }
  1600.  
  1601.  
  1602. int32
  1603. lo_align_subdoc(MWContext *context, lo_DocState *state, lo_DocState *old_state,
  1604.     LO_SubDocStruct *subdoc, lo_TableRec *table, lo_table_span *row_max)
  1605. {
  1606.     int32 ele_cnt;
  1607.     LO_Element *eptr;
  1608.     int32 vert_inc;
  1609.     int32 top_inner_pad;
  1610.     int32 bottom_inner_pad;
  1611.     int32 left_inner_pad;
  1612.     int32 right_inner_pad;
  1613.     LO_Element **line_array;
  1614.  
  1615.     top_inner_pad = FEUNITS_X(table->inner_top_pad, context);
  1616.     bottom_inner_pad = FEUNITS_X(table->inner_bottom_pad, context);
  1617.     left_inner_pad = FEUNITS_X(table->inner_left_pad, context);
  1618.     right_inner_pad = FEUNITS_X(table->inner_right_pad, context);
  1619.  
  1620.     ele_cnt = 0;
  1621.  
  1622.     /*
  1623.      * Mess with vertical alignment.
  1624.      */
  1625.     vert_inc = subdoc->height - (2 * subdoc->border_width) - 
  1626.         (top_inner_pad + bottom_inner_pad) - old_state->y;
  1627.     if (vert_inc > 0)
  1628.     {
  1629.         if (subdoc->vert_alignment == LO_ALIGN_CENTER)
  1630.         {
  1631.             vert_inc = vert_inc / 2;
  1632.         }
  1633.         else if (subdoc->vert_alignment == LO_ALIGN_BOTTOM)
  1634.         {
  1635.             /* vert_inc unchanged */
  1636.         }
  1637.         else if ((subdoc->vert_alignment == LO_ALIGN_BASELINE)&&
  1638.             (row_max != NULL))
  1639.         {
  1640.             int32 baseline;
  1641.             int32 tmp_val;
  1642.  
  1643.             baseline = lo_GetSubDocBaseline(subdoc);
  1644.             tmp_val = row_max->min_dim - baseline;
  1645.             if (tmp_val > vert_inc)
  1646.             {
  1647.                 tmp_val = vert_inc;
  1648.             }
  1649.             if (tmp_val > 0)
  1650.             {
  1651.                 vert_inc = tmp_val;
  1652.             }
  1653.             else
  1654.             {
  1655.                 vert_inc = 0;
  1656.             }
  1657.         }
  1658.         else
  1659.         {
  1660.             vert_inc = 0;
  1661.         }
  1662.     }
  1663.     else
  1664.     {
  1665.         vert_inc = 0;
  1666.     }
  1667.  
  1668.     /*
  1669.      * Make eptr point to the start of the element chain
  1670.      * for this subdoc.
  1671.      */
  1672. #ifdef XP_WIN16
  1673. {
  1674.     XP_Block *larray_array;
  1675.  
  1676.     XP_LOCK_BLOCK(larray_array, XP_Block *, old_state->larray_array);
  1677.     old_state->line_array = larray_array[0];
  1678.     XP_UNLOCK_BLOCK(old_state->larray_array);
  1679. }
  1680. #endif /* XP_WIN16 */
  1681.     XP_LOCK_BLOCK(line_array, LO_Element **, old_state->line_array);
  1682.     eptr = line_array[0];
  1683.     XP_UNLOCK_BLOCK(old_state->line_array);
  1684.  
  1685.     while (eptr != NULL)
  1686.     {
  1687.         eptr->lo_any.x += left_inner_pad;
  1688.  
  1689.         switch (eptr->type)
  1690.         {
  1691.             case LO_LINEFEED:
  1692.             if (eptr->lo_linefeed.ele_attrmask &
  1693.                 LO_ELE_DELAY_ALIGNED)
  1694.             {
  1695.                 if (eptr->lo_linefeed.ele_attrmask &
  1696.                 LO_ELE_DELAY_CENTER)
  1697.                 {
  1698.                 int32 side_inc;
  1699.                 int32 inside_width;
  1700.                 LO_Element *c_eptr;
  1701.  
  1702.                 c_eptr = eptr;
  1703.                 inside_width = subdoc->width -
  1704.                     (2 * subdoc->border_width) -
  1705.                     (2 * subdoc->border_horiz_space) -
  1706.                     (left_inner_pad + right_inner_pad);
  1707.  
  1708.                 side_inc = inside_width -
  1709.                     (c_eptr->lo_linefeed.x +
  1710.                     c_eptr->lo_linefeed.x_offset -
  1711.                     left_inner_pad);
  1712.                 side_inc = side_inc / 2;
  1713.                 if (side_inc > 0)
  1714.                 {
  1715.                     c_eptr->lo_linefeed.width -= side_inc;
  1716.                     if (c_eptr->lo_linefeed.width < 0)
  1717.                     {
  1718.                         c_eptr->lo_linefeed.width = 0;
  1719.                     }
  1720.                     while ((c_eptr->lo_any.prev != NULL)&&
  1721.                         (c_eptr->lo_any.prev->type !=
  1722.                             LO_LINEFEED))
  1723.                     {
  1724.                         c_eptr->lo_any.x += side_inc;
  1725.                         if (c_eptr->type == LO_CELL)
  1726.                         {
  1727.                             lo_ShiftCell(
  1728.                             (LO_CellStruct *)c_eptr,
  1729.                             side_inc, 0);
  1730.                         }
  1731.                         c_eptr = c_eptr->lo_any.prev;
  1732.                     }
  1733.                     c_eptr->lo_any.x += side_inc;
  1734.                     if (c_eptr->type == LO_CELL)
  1735.                     {
  1736.                         lo_ShiftCell(
  1737.                         (LO_CellStruct *)c_eptr,
  1738.                         side_inc, 0);
  1739.                     }
  1740.                 }
  1741.                 }
  1742.                 else if (eptr->lo_linefeed.ele_attrmask &
  1743.                 LO_ELE_DELAY_RIGHT)
  1744.                 {
  1745.                 int32 side_inc;
  1746.                 int32 inside_width;
  1747.                 LO_Element *c_eptr;
  1748.  
  1749.                 c_eptr = eptr;
  1750.                 inside_width = subdoc->width -
  1751.                     (2 * subdoc->border_width) -
  1752.                     (2 * subdoc->border_horiz_space) -
  1753.                     (left_inner_pad + right_inner_pad);
  1754.  
  1755.                 side_inc = inside_width -
  1756.                     (c_eptr->lo_linefeed.x +
  1757.                     c_eptr->lo_linefeed.x_offset -
  1758.                     left_inner_pad);
  1759.                 if (side_inc > 0)
  1760.                 {
  1761.                     c_eptr->lo_linefeed.width -= side_inc;
  1762.                     if (c_eptr->lo_linefeed.width < 0)
  1763.                     {
  1764.                         c_eptr->lo_linefeed.width = 0;
  1765.                     }
  1766.                     while ((c_eptr->lo_any.prev != NULL)&&
  1767.                         (c_eptr->lo_any.prev->type !=
  1768.                             LO_LINEFEED))
  1769.                     {
  1770.                         c_eptr->lo_any.x += side_inc;
  1771.                         if (c_eptr->type == LO_CELL)
  1772.                         {
  1773.                             lo_ShiftCell(
  1774.                             (LO_CellStruct *)c_eptr,
  1775.                             side_inc, 0);
  1776.                         }
  1777.                         c_eptr = c_eptr->lo_any.prev;
  1778.                     }
  1779.                     c_eptr->lo_any.x += side_inc;
  1780.                     if (c_eptr->type == LO_CELL)
  1781.                     {
  1782.                         lo_ShiftCell(
  1783.                         (LO_CellStruct *)c_eptr,
  1784.                         side_inc, 0);
  1785.                     }
  1786.                 }
  1787.                 }
  1788.                 eptr->lo_linefeed.ele_attrmask &=
  1789.                     (~(LO_ELE_DELAY_ALIGNED));
  1790.             }
  1791.             break;
  1792.             default:
  1793.             break;
  1794.         }
  1795.         eptr->lo_any.y += (vert_inc + top_inner_pad);
  1796.         if (eptr->type == LO_CELL)
  1797.         {
  1798.             lo_ShiftCell((LO_CellStruct *)eptr, left_inner_pad,
  1799.                 (vert_inc + top_inner_pad));
  1800.         }
  1801.         eptr = eptr->lo_any.next;
  1802.         ele_cnt++;
  1803.     }
  1804.  
  1805.     eptr = old_state->float_list;
  1806.     while (eptr != NULL)
  1807.     {
  1808.         eptr->lo_any.x += left_inner_pad;
  1809.         eptr->lo_any.y += (vert_inc + top_inner_pad);
  1810.         if (eptr->type == LO_CELL)
  1811.         {
  1812.             lo_ShiftCell((LO_CellStruct *)eptr, left_inner_pad,
  1813.                 (vert_inc + top_inner_pad));
  1814.         }
  1815.         eptr = eptr->lo_any.next;
  1816.         ele_cnt++;
  1817.     }
  1818.  
  1819.     return(ele_cnt);
  1820. }
  1821.  
  1822.  
  1823. int32
  1824. lo_align_cell(MWContext *context, lo_DocState *state, lo_TableCell *cell_ptr,
  1825.     LO_CellStruct *cell, lo_TableRec *table, lo_table_span *row_max)
  1826. {
  1827.     int32 ele_cnt;
  1828.     LO_Element *eptr;
  1829.     int32 vert_inc;
  1830.     int32 top_inner_pad;
  1831.     int32 bottom_inner_pad;
  1832.     int32 left_inner_pad;
  1833.     int32 right_inner_pad;
  1834.  
  1835.     top_inner_pad = FEUNITS_X(table->inner_top_pad, context);
  1836.     bottom_inner_pad = FEUNITS_X(table->inner_bottom_pad, context);
  1837.     left_inner_pad = FEUNITS_X(table->inner_left_pad, context);
  1838.     right_inner_pad = FEUNITS_X(table->inner_right_pad, context);
  1839.  
  1840.     ele_cnt = 0;
  1841.  
  1842.     /*
  1843.      * Mess with vertical alignment.
  1844.      */
  1845.     vert_inc = cell->height - (2 * cell->border_width) - 
  1846.         (top_inner_pad + bottom_inner_pad) - cell_ptr->max_y;
  1847.     if (vert_inc > 0)
  1848.     {
  1849.         if (cell_ptr->vert_alignment == LO_ALIGN_CENTER)
  1850.         {
  1851.             vert_inc = vert_inc / 2;
  1852.         }
  1853.         else if (cell_ptr->vert_alignment == LO_ALIGN_BOTTOM)
  1854.         {
  1855.             /* vert_inc unchanged */
  1856.         }
  1857.         else if ((cell_ptr->vert_alignment == LO_ALIGN_BASELINE)&&
  1858.             (row_max != NULL))
  1859.         {
  1860.             int32 baseline;
  1861.             int32 tmp_val;
  1862.  
  1863.             baseline = lo_GetCellBaseline(cell);
  1864.             tmp_val = row_max->min_dim - baseline;
  1865.             if (tmp_val > vert_inc)
  1866.             {
  1867.                 tmp_val = vert_inc;
  1868.             }
  1869.             if (tmp_val > 0)
  1870.             {
  1871.                 vert_inc = tmp_val;
  1872.             }
  1873.             else
  1874.             {
  1875.                 vert_inc = 0;
  1876.             }
  1877.         }
  1878.         else
  1879.         {
  1880.             vert_inc = 0;
  1881.         }
  1882.     }
  1883.     else
  1884.     {
  1885.         vert_inc = 0;
  1886.     }
  1887.  
  1888.     /*
  1889.      * Make eptr point to the start of the element chain
  1890.      * for this cell.
  1891.      */
  1892.     eptr = cell->cell_list;
  1893.  
  1894.     while (eptr != NULL)
  1895.     {
  1896.         eptr->lo_any.x += left_inner_pad;
  1897.  
  1898.         switch (eptr->type)
  1899.         {
  1900.             case LO_LINEFEED:
  1901.             if (eptr->lo_linefeed.ele_attrmask &
  1902.                 LO_ELE_DELAY_ALIGNED)
  1903.             {
  1904.                 if (eptr->lo_linefeed.ele_attrmask &
  1905.                 LO_ELE_DELAY_CENTER)
  1906.                 {
  1907.                 int32 side_inc;
  1908.                 int32 inside_width;
  1909.                 LO_Element *c_eptr;
  1910.  
  1911.                 c_eptr = eptr;
  1912.                 inside_width = cell->width -
  1913.                     (2 * cell->border_width) -
  1914.                     (2 * cell->border_horiz_space) -
  1915.                     (left_inner_pad + right_inner_pad);
  1916.  
  1917.                 side_inc = inside_width -
  1918.                     (c_eptr->lo_linefeed.x +
  1919.                     c_eptr->lo_linefeed.x_offset -
  1920.                     left_inner_pad);
  1921.                 side_inc = side_inc / 2;
  1922.                 if (side_inc > 0)
  1923.                 {
  1924.                     c_eptr->lo_linefeed.width -= side_inc;
  1925.                     if (c_eptr->lo_linefeed.width < 0)
  1926.                     {
  1927.                         c_eptr->lo_linefeed.width = 0;
  1928.                     }
  1929.                     while ((c_eptr->lo_any.prev != NULL)&&
  1930.                         (c_eptr->lo_any.prev->type !=
  1931.                             LO_LINEFEED))
  1932.                     {
  1933.                         c_eptr->lo_any.x += side_inc;
  1934.                         if (c_eptr->type == LO_CELL)
  1935.                         {
  1936.                             lo_ShiftCell(
  1937.                             (LO_CellStruct *)c_eptr,
  1938.                             side_inc, 0);
  1939.                         }
  1940.                         c_eptr = c_eptr->lo_any.prev;
  1941.                     }
  1942.                     c_eptr->lo_any.x += side_inc;
  1943.                     if (c_eptr->type == LO_CELL)
  1944.                     {
  1945.                         lo_ShiftCell(
  1946.                         (LO_CellStruct *)c_eptr,
  1947.                         side_inc, 0);
  1948.                     }
  1949.                 }
  1950.                 }
  1951.                 else if (eptr->lo_linefeed.ele_attrmask &
  1952.                 LO_ELE_DELAY_RIGHT)
  1953.                 {
  1954.                 int32 side_inc;
  1955.                 int32 inside_width;
  1956.                 LO_Element *c_eptr;
  1957.  
  1958.                 c_eptr = eptr;
  1959.                 inside_width = cell->width -
  1960.                     (2 * cell->border_width) -
  1961.                     (2 * cell->border_horiz_space) -
  1962.                     (left_inner_pad + right_inner_pad);
  1963.  
  1964.                 side_inc = inside_width -
  1965.                     (c_eptr->lo_linefeed.x +
  1966.                     c_eptr->lo_linefeed.x_offset -
  1967.                     left_inner_pad);
  1968.                 if (side_inc > 0)
  1969.                 {
  1970.                     c_eptr->lo_linefeed.width -= side_inc;
  1971.                     if (c_eptr->lo_linefeed.width < 0)
  1972.                     {
  1973.                         c_eptr->lo_linefeed.width = 0;
  1974.                     }
  1975.                     while ((c_eptr->lo_any.prev != NULL)&&
  1976.                         (c_eptr->lo_any.prev->type !=
  1977.                             LO_LINEFEED))
  1978.                     {
  1979.                         c_eptr->lo_any.x += side_inc;
  1980.                         if (c_eptr->type == LO_CELL)
  1981.                         {
  1982.                             lo_ShiftCell(
  1983.                             (LO_CellStruct *)c_eptr,
  1984.                             side_inc, 0);
  1985.                         }
  1986.                         c_eptr = c_eptr->lo_any.prev;
  1987.                     }
  1988.                     c_eptr->lo_any.x += side_inc;
  1989.                     if (c_eptr->type == LO_CELL)
  1990.                     {
  1991.                         lo_ShiftCell(
  1992.                         (LO_CellStruct *)c_eptr,
  1993.                         side_inc, 0);
  1994.                     }
  1995.                 }
  1996.                 }
  1997.                 eptr->lo_linefeed.ele_attrmask &=
  1998.                     (~(LO_ELE_DELAY_ALIGNED));
  1999.             }
  2000.             break;
  2001.             default:
  2002.             break;
  2003.         }
  2004.         eptr->lo_any.y += (vert_inc + top_inner_pad);
  2005.         if (eptr->type == LO_CELL)
  2006.         {
  2007.             lo_ShiftCell((LO_CellStruct *)eptr, left_inner_pad,
  2008.                 (vert_inc + top_inner_pad));
  2009.         }
  2010.         eptr = eptr->lo_any.next;
  2011.         ele_cnt++;
  2012.     }
  2013.  
  2014.     eptr = cell->cell_float_list;
  2015.     while (eptr != NULL)
  2016.     {
  2017.         eptr->lo_any.x += left_inner_pad;
  2018.         eptr->lo_any.y += (vert_inc + top_inner_pad);
  2019.         if (eptr->type == LO_CELL)
  2020.         {
  2021.             lo_ShiftCell((LO_CellStruct *)eptr, left_inner_pad,
  2022.                 (vert_inc + top_inner_pad));
  2023.         }
  2024.         eptr = eptr->lo_any.next;
  2025.         ele_cnt++;
  2026.     }
  2027.  
  2028.     return(ele_cnt);
  2029. }
  2030.  
  2031.  
  2032. LO_SubDocStruct *
  2033. lo_EndCellSubDoc(MWContext *context, lo_DocState *state, lo_DocState *old_state,
  2034.     LO_Element *element, Bool relayout)
  2035. {
  2036.     LO_Element *eptr;
  2037.     LO_SubDocStruct *subdoc;
  2038.     PA_Block buff;
  2039.     char *str;
  2040.     Bool line_break;
  2041.     int32 baseline_inc;
  2042.     int32 line_inc;
  2043.     int32 subdoc_height, subdoc_width;
  2044.     int32 doc_height;
  2045.     LO_TextStruct tmp_text;
  2046.     LO_TextInfo text_info;
  2047.     LO_Element **line_array;
  2048.     Bool dynamic_width;
  2049.     Bool dynamic_height;
  2050. #ifdef LOCAL_DEBUG
  2051.  fprintf(stderr, "lo_EndCellSubDoc called\n");
  2052. #endif /* LOCAL_DEBUG */
  2053.  
  2054.     /* Close any layers (blocks) that were opened in this cell, in case
  2055.        the document author forgot to. */
  2056.     while (old_state->layer_nest_level > 0)
  2057.     {
  2058.         lo_EndLayer(context, old_state, PR_TRUE);
  2059.     }
  2060.  
  2061.     subdoc = (LO_SubDocStruct *)element;
  2062.     subdoc->state = (void *)old_state;
  2063.  
  2064.     /*
  2065.      * All this work is to get the text_info filled in for the current
  2066.      * font in the font stack. Yuck, there must be a better way.
  2067.      */
  2068.     memset (&tmp_text, 0, sizeof (tmp_text));
  2069.     buff = PA_ALLOC(1);
  2070.     if (buff == NULL)
  2071.     {
  2072.         state->top_state->out_of_memory = TRUE;
  2073.         return(NULL);
  2074.     }
  2075.     PA_LOCK(str, char *, buff);
  2076.     str[0] = ' ';
  2077.     PA_UNLOCK(buff);
  2078.     tmp_text.text = buff;
  2079.     tmp_text.text_len = 1;
  2080.     tmp_text.text_attr =
  2081.         state->font_stack->text_attr;
  2082.     FE_GetTextInfo(context, &tmp_text, &text_info);
  2083.     PA_FREE(buff);
  2084.  
  2085.     if (relayout == FALSE)
  2086.     {
  2087.         /*
  2088.          * We don't want to leave any end paragraph linbreaks in the subdoc
  2089.          * as they give us a really ugly blank line at the bottom of a cell. So,
  2090.          * if the last element in the list is paragraph break linefeed, then
  2091.          * we kill it.
  2092.          */
  2093.         eptr = old_state->end_last_line;
  2094.         if ( (eptr != NULL) && (eptr->type == LO_LINEFEED) &&
  2095.             (eptr->lo_linefeed.break_type == LO_LINEFEED_BREAK_PARAGRAPH) )
  2096.         {
  2097.             LO_Element *prev;
  2098.             
  2099.             prev = eptr->lo_any.prev;
  2100.  
  2101.             /*
  2102.              * Kill this layout element and reset the subdoc height
  2103.              */
  2104.             if ( prev != NULL )
  2105.             {
  2106.                 prev->lo_any.next = NULL;
  2107.                 old_state->end_last_line = prev;
  2108.             }
  2109.             else
  2110.             {
  2111.                 old_state->line_list = NULL;
  2112.                 old_state->end_last_line = NULL;
  2113.             }
  2114.             
  2115.             /* The if condition checks to make sure that the linefeed that we just killed
  2116.              * was sticking out of the bottom of the cell.  This fixes bug 81282.
  2117.              */
  2118.             if (eptr->lo_linefeed.y + eptr->lo_linefeed.line_height >= old_state->y) {
  2119.                 /* shrink the document */
  2120.                 old_state->y -= eptr->lo_linefeed.line_height;
  2121.             }
  2122.  
  2123.             lo_RecycleElements ( context, old_state, eptr );
  2124.         }
  2125.     }
  2126.     
  2127.     dynamic_width = FALSE;
  2128.     dynamic_height = FALSE;
  2129.     if (subdoc->width == 0)
  2130.     {
  2131.         dynamic_width = TRUE;
  2132.         /*
  2133.          * Subdocs that were dynamically widthed, and which
  2134.          * contained right aligned items, must be relaid out
  2135.          * once their width is determined.
  2136.          */
  2137.         eptr = old_state->float_list;
  2138.         while (eptr != NULL)
  2139.         {
  2140.             if ((eptr->type == LO_IMAGE)&&
  2141.                 (eptr->lo_image.image_attr->alignment == LO_ALIGN_RIGHT))
  2142.             {
  2143.                 old_state->must_relayout_subdoc = TRUE;
  2144.                 break;
  2145.             }
  2146.             else if ((eptr->type == LO_SUBDOC)&&
  2147.                 (eptr->lo_subdoc.alignment == LO_ALIGN_RIGHT))
  2148.             {
  2149.                 old_state->must_relayout_subdoc = TRUE;
  2150.                 break;
  2151.             }
  2152.             eptr = eptr->lo_any.next;
  2153.         }
  2154.  
  2155.         subdoc->width = old_state->max_width;
  2156.     }
  2157.  
  2158.     /*
  2159.      * Add in the size of the subdoc's borders
  2160.      */
  2161.     subdoc->width += (2 * subdoc->border_width);
  2162.  
  2163.     /*
  2164.      * Figure the height the subdoc laid out in.
  2165.      * Use this if we were passed no height, or if it is greater
  2166.      * than the passed height.
  2167.      */
  2168.     doc_height = old_state->y + (2 * subdoc->border_width);
  2169.     if (subdoc->height == 0)
  2170.     {
  2171.         dynamic_height = TRUE;
  2172.         subdoc->height = doc_height;
  2173.     }
  2174.     else if (subdoc->height < doc_height)
  2175.     {
  2176.         subdoc->height = doc_height;
  2177.     }
  2178.  
  2179.     /*
  2180.      * Make eptr point to the start of the element chain
  2181.      * for this subdoc.
  2182.      */
  2183. #ifdef XP_WIN16
  2184. {
  2185.     XP_Block *larray_array;
  2186.  
  2187.     XP_LOCK_BLOCK(larray_array, XP_Block *, old_state->larray_array);
  2188.     old_state->line_array = larray_array[0];
  2189.     XP_UNLOCK_BLOCK(old_state->larray_array);
  2190. }
  2191. #endif /* XP_WIN16 */
  2192.     XP_LOCK_BLOCK(line_array, LO_Element **, old_state->line_array);
  2193.     eptr = line_array[0];
  2194.     XP_UNLOCK_BLOCK(old_state->line_array);
  2195.  
  2196.     while (eptr != NULL)
  2197.     {
  2198.         switch (eptr->type)
  2199.         {
  2200.             case LO_LINEFEED:
  2201.             if ((eptr->lo_linefeed.x + eptr->lo_linefeed.x_offset +
  2202.                 eptr->lo_linefeed.width) >= (subdoc->width - 1 -
  2203.                 (2 * subdoc->border_width)))
  2204.             {
  2205.                 eptr->lo_linefeed.width = (subdoc->width - 1 -
  2206.                     (2 * subdoc->border_width)) -
  2207.                     (eptr->lo_linefeed.x +
  2208.                     eptr->lo_linefeed.x_offset);
  2209.                 if (eptr->lo_linefeed.width < 0)
  2210.                 {
  2211.                     eptr->lo_linefeed.width = 0;
  2212.                 }
  2213.             }
  2214. #ifdef OLD_DELAY_CENTERED
  2215.             if (eptr->lo_linefeed.ele_attrmask &
  2216.                 LO_ELE_DELAY_CENTERED)
  2217.             {
  2218.                 int32 side_inc;
  2219.                 LO_Element *c_eptr;
  2220.  
  2221.                 c_eptr = eptr;
  2222.  
  2223.                 side_inc = subdoc->width - 1 -
  2224.                     (2 * subdoc->border_width) -
  2225.                     (eptr->lo_linefeed.x +
  2226.                     eptr->lo_linefeed.x_offset);
  2227.                 side_inc = side_inc / 2;
  2228.                 if (side_inc > 0)
  2229.                 {
  2230.                     c_eptr->lo_linefeed.width -= side_inc;
  2231.                     if (c_eptr->lo_linefeed.width < 0)
  2232.                     {
  2233.                         c_eptr->lo_linefeed.width = 0;
  2234.                     }
  2235.                     while ((c_eptr->lo_any.prev != NULL)&&
  2236.                         (c_eptr->lo_any.prev->type !=
  2237.                             LO_LINEFEED))
  2238.                     {
  2239.                         c_eptr->lo_any.x += side_inc;
  2240.                         if (c_eptr->type == LO_CELL)
  2241.                         {
  2242.                             lo_ShiftCell(
  2243.                             (LO_CellStruct *)c_eptr,
  2244.                             side_inc, 0);
  2245.                         }
  2246.                         c_eptr = c_eptr->lo_any.prev;
  2247.                     }
  2248.                     c_eptr->lo_any.x += side_inc;
  2249.                     if (c_eptr->type == LO_CELL)
  2250.                     {
  2251.                         lo_ShiftCell(
  2252.                         (LO_CellStruct *)c_eptr,
  2253.                         side_inc, 0);
  2254.                     }
  2255.                 }
  2256.                 eptr->lo_linefeed.ele_attrmask &=
  2257.                     (~(LO_ELE_DELAY_CENTERED));
  2258.             }
  2259. #endif /* OLD_DELAY_CENTERED */
  2260.             break;
  2261.             /*
  2262.              * This is awful, but any dynamically dimenstioned
  2263.              * subdoc that contains one of these elements
  2264.              * must be relayed out to take care of window
  2265.              * width and height dependencies.
  2266.              */
  2267.             /* case LO_HRULE:
  2268.             case LO_SUBDOC:
  2269.             case LO_TABLE:
  2270.                 old_state->must_relayout_subdoc = TRUE;
  2271.             */
  2272.  
  2273.             break;
  2274.             case LO_IMAGE:
  2275. /* WILL NEED THIS LATER FOR PERCENT WIDTH IMAGES
  2276.             if ((old_state->allow_percent_width == FALSE)||
  2277.                 (old_state->allow_percent_height == FALSE))
  2278.             {
  2279.                 old_state->must_relayout_subdoc = TRUE;
  2280.             }
  2281. */
  2282.             break;
  2283.             default:
  2284.             break;
  2285.         }
  2286.         eptr = eptr->lo_any.next;
  2287.     }
  2288.  
  2289.     /*
  2290.      * Remember: (2 * subdoc->border_width) has already been added to the subdoc
  2291.      * width above...
  2292.      */
  2293.     subdoc_width = subdoc->width + (2 * subdoc->border_horiz_space);
  2294.     subdoc_height = subdoc->height + (2 * subdoc->border_width) +
  2295.         (2 * subdoc->border_vert_space);
  2296.  
  2297.     if (old_state->display_blocked != FALSE)
  2298.     {
  2299.         old_state->display_blocked = FALSE;
  2300.     }
  2301.  
  2302.     /*
  2303.      * Will this subdoc make the line too wide.
  2304.      */
  2305.     if ((state->x + subdoc_width) > state->right_margin)
  2306.     {
  2307.         line_break = TRUE;
  2308.     }
  2309.     else
  2310.     {
  2311.         line_break = FALSE;
  2312.     }
  2313.  
  2314.     /*
  2315.      * if we are at the beginning of the line.  There is
  2316.      * no point in breaking, we are just too wide.
  2317.      * Also don't break in unwrappedpreformatted text.
  2318.      * Also can't break inside a NOBR section.
  2319.      */
  2320.     if ((state->at_begin_line != FALSE)||
  2321.         (state->preformatted == PRE_TEXT_YES)||
  2322.         (state->breakable == FALSE))
  2323.     {
  2324.         line_break = FALSE;
  2325.     }
  2326.  
  2327.     /*
  2328.          * break on the subdoc if we have
  2329.          * a break.
  2330.          */
  2331. /* DOn't break in cell
  2332.         if (line_break != FALSE)
  2333.         {
  2334.                 lo_SoftLineBreak(context, state, TRUE);
  2335.                 subdoc->x = state->x;
  2336.                 subdoc->y = state->y;
  2337.         }
  2338. */
  2339.  
  2340.     /*
  2341.      * Figure out how to align this subdoc.
  2342.      * baseline_inc is how much to increase the baseline
  2343.      * of previous element of this line.  line_inc is how
  2344.      * much to increase the line height below the baseline.
  2345.      */
  2346.     baseline_inc = 0;
  2347.     line_inc = 0;
  2348.     /*
  2349.      * If we are at the beginning of a line, with no baseline,
  2350.      * we first set baseline and line_height based on the current
  2351.      * font, then place the subdoc.
  2352.      */
  2353.     if (state->baseline == 0)
  2354.     {
  2355.         state->baseline = 0;
  2356.     }
  2357.  
  2358.     lo_CalcAlignOffsets(state, &text_info, (intn)subdoc->alignment,
  2359.         subdoc_width, subdoc_height,
  2360.         &subdoc->x_offset, &subdoc->y_offset, &line_inc, &baseline_inc);
  2361.  
  2362.     subdoc->x_offset += (int16)subdoc->border_horiz_space;
  2363.     subdoc->y_offset += (int32)subdoc->border_vert_space;
  2364.  
  2365.     old_state->base_x = subdoc->x + subdoc->x_offset +
  2366.         subdoc->border_width;
  2367.     old_state->base_y = subdoc->y + subdoc->y_offset +
  2368.         subdoc->border_width;
  2369.  
  2370.     /*
  2371.      * Clean up state
  2372.     state->x = state->x + subdoc->x_offset +
  2373.         subdoc_width - subdoc->border_horiz_space;
  2374.     state->linefeed_state = 0;
  2375.     state->at_begin_line = FALSE;
  2376.     state->trailing_space = FALSE;
  2377.     state->cur_ele_type = LO_SUBDOC;
  2378.      */
  2379.  
  2380.     return(subdoc);
  2381. }
  2382.  
  2383.  
  2384. void
  2385. lo_relayout_recycle(MWContext *context, lo_DocState *state, LO_Element *elist)
  2386. {
  2387.     LO_LockLayout();
  2388.     
  2389.     while (elist != NULL)
  2390.     {
  2391.         LO_Element *eptr;
  2392.  
  2393.         eptr = elist;
  2394.         elist = elist->lo_any.next;
  2395.         eptr->lo_any.next = NULL;
  2396.  
  2397.         if (eptr->type == LO_IMAGE)
  2398.         {
  2399.             eptr->lo_any.next = state->top_state->trash;
  2400.             state->top_state->trash = eptr;
  2401.         }
  2402.         else if (eptr->type == LO_CELL)
  2403.         {
  2404.             if (eptr->lo_cell.cell_list != NULL)
  2405.             {
  2406.                 if (eptr->lo_cell.cell_list_end != NULL)
  2407.                 {
  2408.                 eptr->lo_cell.cell_list_end->lo_any.next = NULL;
  2409.                 }
  2410.                 lo_relayout_recycle(context, state,
  2411.                     eptr->lo_cell.cell_list);
  2412.                 eptr->lo_cell.cell_list = NULL;
  2413.                 eptr->lo_cell.cell_list_end = NULL;
  2414.             }
  2415.             if (eptr->lo_cell.cell_float_list != NULL)
  2416.             {
  2417.                 lo_relayout_recycle(context, state,
  2418.                     eptr->lo_cell.cell_float_list);
  2419.                 eptr->lo_cell.cell_float_list = NULL;
  2420.             }
  2421.             lo_RecycleElements(context, state, eptr);
  2422.         }
  2423.         else
  2424.         {
  2425.             /*
  2426.              * If this is an embed, tell it that it should
  2427.              * recycle rather than delete itself.
  2428.              */
  2429.             if (eptr->type == LO_EMBED)
  2430.             {
  2431.                 NPL_SameElement((LO_EmbedStruct*)eptr);
  2432.             }
  2433.             lo_RecycleElements(context, state, eptr);
  2434.         }
  2435.     }
  2436.     LO_UnlockLayout();
  2437. }
  2438.  
  2439.  
  2440. static void
  2441. lo_cleanup_state(MWContext *context, lo_DocState *state)
  2442. {
  2443.     LO_Element **line_array;
  2444.  
  2445.     if (state == NULL)
  2446.     {
  2447.         return;
  2448.     }
  2449.  
  2450.     if (state->left_margin_stack != NULL)
  2451.     {
  2452.         lo_MarginStack *mptr;
  2453.         lo_MarginStack *margin;
  2454.  
  2455.         mptr = state->left_margin_stack;
  2456.         while (mptr != NULL)
  2457.         {
  2458.             margin = mptr;
  2459.             mptr = mptr->next;
  2460.             XP_DELETE(margin);
  2461.         }
  2462.         state->left_margin_stack = NULL;
  2463.     }
  2464.     if (state->right_margin_stack != NULL)
  2465.     {
  2466.         lo_MarginStack *mptr;
  2467.         lo_MarginStack *margin;
  2468.  
  2469.         mptr = state->right_margin_stack;
  2470.         while (mptr != NULL)
  2471.         {
  2472.             margin = mptr;
  2473.             mptr = mptr->next;
  2474.             XP_DELETE(margin);
  2475.         }
  2476.         state->right_margin_stack = NULL;
  2477.     }
  2478.  
  2479.     if (state->line_list != NULL)
  2480.     {
  2481.         lo_relayout_recycle(context, state, state->line_list);
  2482.         state->line_list = NULL;
  2483.     }
  2484.  
  2485.     if (state->font_stack != NULL)
  2486.     {
  2487.         lo_FontStack *fstack;
  2488.         lo_FontStack *fptr;
  2489.  
  2490.         fptr = state->font_stack;
  2491.         while (fptr != NULL)
  2492.         {
  2493.             fstack = fptr;
  2494.             fptr = fptr->next;
  2495.             XP_DELETE(fstack);
  2496.         }
  2497.         state->font_stack = NULL;
  2498.     }
  2499.  
  2500.     if (state->align_stack != NULL)
  2501.     {
  2502.         lo_AlignStack *aptr;
  2503.         lo_AlignStack *align;
  2504.  
  2505.         aptr = state->align_stack;
  2506.         while (aptr != NULL)
  2507.         {
  2508.             align = aptr;
  2509.             aptr = aptr->next;
  2510.             XP_DELETE(align);
  2511.         }
  2512.         state->align_stack = NULL;
  2513.     }
  2514.  
  2515.     if (state->list_stack != NULL)
  2516.     {
  2517.         lo_ListStack *lptr;
  2518.         lo_ListStack *list;
  2519.  
  2520.         lptr = state->list_stack;
  2521.         while (lptr != NULL)
  2522.         {
  2523.             list = lptr;
  2524.             lptr = lptr->next;
  2525.             XP_DELETE(list);
  2526.         }
  2527.         state->list_stack = NULL;
  2528.     }
  2529.  
  2530.     if (state->line_buf != NULL)
  2531.     {
  2532.         PA_FREE(state->line_buf);
  2533.         state->line_buf = NULL;
  2534.     }
  2535.  
  2536.     if (state->float_list != NULL)
  2537.     {
  2538.         lo_relayout_recycle(context, state, state->float_list);
  2539.         state->float_list = NULL;
  2540.     }
  2541.  
  2542.     if (state->line_array != NULL)
  2543.     {
  2544.         LO_Element *eptr;
  2545.  
  2546. #ifdef XP_WIN16
  2547. {
  2548.         XP_Block *larray_array;
  2549.         intn cnt;
  2550.  
  2551.         XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array);
  2552.         cnt = state->larray_array_size - 1;
  2553.         while (cnt > 0)
  2554.         {
  2555.             XP_FREE_BLOCK(larray_array[cnt]);
  2556.             cnt--;
  2557.         }
  2558.         state->line_array = larray_array[0];
  2559.         XP_UNLOCK_BLOCK(state->larray_array);
  2560.         XP_FREE_BLOCK(state->larray_array);
  2561. }
  2562. #endif /* XP_WIN16 */
  2563.  
  2564.         eptr = NULL;
  2565.         XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array);
  2566.         eptr = line_array[0];
  2567.         if (eptr != NULL)
  2568.         {
  2569.             lo_relayout_recycle(context, state, eptr);
  2570.         }
  2571.         XP_UNLOCK_BLOCK(state->line_array);
  2572.         XP_FREE_BLOCK(state->line_array);
  2573.     }
  2574.  
  2575.     XP_DELETE(state);
  2576. }
  2577.  
  2578.  
  2579. static lo_FormData *
  2580. lo_merge_form_data(lo_FormData *new_form_list, lo_FormData *hold_form_list)
  2581. {
  2582.     intn i;
  2583.     LO_FormElementStruct **new_ele_list;
  2584.     LO_FormElementStruct **hold_ele_list;
  2585.  
  2586.     PA_LOCK(new_ele_list, LO_FormElementStruct **,
  2587.             new_form_list->form_elements);
  2588.     PA_LOCK(hold_ele_list, LO_FormElementStruct **,
  2589.             hold_form_list->form_elements);
  2590.     for (i=0; i<new_form_list->form_ele_cnt; i++)
  2591.     {
  2592.         if (hold_ele_list[i] != new_ele_list[i])
  2593.         {
  2594. #ifdef MOCHA
  2595.             if (new_ele_list[i]->mocha_object == NULL)
  2596.             {
  2597.                 new_ele_list[i]->mocha_object
  2598.                     = hold_ele_list[i]->mocha_object;
  2599.             }
  2600. #endif
  2601.             hold_ele_list[i] = new_ele_list[i];
  2602.         }
  2603.     }
  2604.     PA_UNLOCK(hold_form_list->form_elements);
  2605.     PA_UNLOCK(new_form_list->form_elements);
  2606.  
  2607. #ifdef MOCHA
  2608.     /* XXX sometimes the second pass does not reflect a form object! */
  2609.     if (new_form_list->mocha_object != NULL)
  2610.     {
  2611.         hold_form_list->mocha_object = new_form_list->mocha_object;
  2612.     }
  2613. #endif
  2614.     return(hold_form_list);
  2615. }
  2616.  
  2617.  
  2618. /*
  2619.  * Serious table magic.  Given a table cell subdoc,
  2620.  * redo the layout to the new width from the stored tag list,
  2621.  * and create a whole new subdoc, which is returned.
  2622.  */
  2623. LO_SubDocStruct *
  2624. lo_RelayoutCaptionSubdoc(MWContext *context, lo_DocState *state, lo_TableCaption *caption,
  2625.     LO_SubDocStruct *subdoc, int32 width, Bool is_a_header)
  2626. {
  2627.     int32 first_height;
  2628.     lo_TopState *top_state;
  2629.     lo_DocState *old_state;
  2630.     lo_DocState *new_state;
  2631.     PA_Tag *tag_list;
  2632.     PA_Tag *tag_ptr;
  2633.     PA_Tag *tag_end_ptr;
  2634.     int32 doc_id;
  2635.     Bool allow_percent_width;
  2636.     Bool allow_percent_height;
  2637.     int32 hold_form_ele_cnt;
  2638.     int32 hold_form_data_index;
  2639.     intn hold_form_id;
  2640.     intn hold_current_form_num;
  2641.     Bool hold_in_form;
  2642.     lo_FormData *hold_form_list;
  2643.     int32 hold_embed_global_index;
  2644.     int32 original_tag_count;
  2645.     intn hold_url_list_len;
  2646.     NET_ReloadMethod save_force;
  2647.     Bool save_diff_state;
  2648.     int32 save_state_pushes;
  2649.     int32 save_state_pops;
  2650.     lo_DocLists *doc_lists;
  2651.     int32 hold_image_list_count;
  2652.         int32 hold_applet_list_count;
  2653.         int32 hold_embed_list_count;
  2654.     int32 hold_current_layer_num;
  2655.  
  2656.     /*
  2657.      * Relayout is NOT allowed to block on images, so never
  2658.      * have the forced reload flag set.
  2659.      */
  2660.     save_force = state->top_state->force_reload;
  2661.     state->top_state->force_reload = NET_CACHE_ONLY_RELOAD;
  2662.  
  2663. #ifdef LOCAL_DEBUG
  2664.  fprintf(stderr, "lo_RelayoutSubdoc called\n");
  2665. #endif /* LOCAL_DEBUG */
  2666.  
  2667.     top_state = state->top_state;
  2668.     old_state = (lo_DocState *) subdoc->state;
  2669.     
  2670.     /*
  2671.      * We are going to reuse this subdoc element instead
  2672.      * of allocating a new one.
  2673.      */
  2674.     /* subdoc->state = NULL; */
  2675.     subdoc->width = width;
  2676.     subdoc->height = 0;
  2677.  
  2678.     doc_lists = lo_GetCurrentDocLists(state);
  2679.     
  2680.     /*
  2681.      * If this subdoc contained form elements.  We want to reuse
  2682.      * them without messing up the order of later form elements in
  2683.      * other subdocs.
  2684.      *
  2685.      * We assume that relaying out the doc will create the exact
  2686.      * same number of form elements in the same order as the first time.
  2687.      * so we reset global form counters to before this subdoc
  2688.      * was ever laid out, saving the current counts to restore later.
  2689.      */
  2690.     if (doc_lists->form_list != NULL)
  2691.     {
  2692.         lo_FormData *form_list;
  2693.         lo_FormData *tmp_fptr;
  2694.  
  2695.         hold_form_id = old_state->form_id;
  2696.         hold_current_form_num = doc_lists->current_form_num;
  2697.         form_list = doc_lists->form_list;
  2698.         hold_form_list = NULL;
  2699.         while ((form_list != NULL)&&
  2700.             (form_list->id > hold_form_id))
  2701.         {
  2702.             tmp_fptr = form_list;
  2703.             form_list = form_list->next;
  2704.             tmp_fptr->next = hold_form_list;
  2705.             hold_form_list = tmp_fptr;
  2706.         }
  2707.         doc_lists->form_list = form_list;
  2708.         doc_lists->current_form_num = hold_form_id;
  2709.         if (form_list != NULL)
  2710.         {
  2711.             hold_form_ele_cnt = form_list->form_ele_cnt;
  2712.             form_list->form_ele_cnt = old_state->form_ele_cnt;
  2713.         }
  2714.         else
  2715.         {
  2716.             hold_form_ele_cnt = 0;
  2717.         }
  2718.     }
  2719.     else
  2720.     {
  2721.         hold_form_id = 0;
  2722.         hold_form_ele_cnt = 0;
  2723.         hold_form_list = NULL;
  2724.         hold_current_form_num = 0;
  2725.     }
  2726.  
  2727.     /*
  2728.      * We're going to be deleting and then recreating the contents 
  2729.      * of this subdoc.  We want the newly-created embeds to have
  2730.      * the same embed indices as their recycled counterparts, so
  2731.      * we reset the master embed index in the top_state to be the
  2732.      * value it held at the time the old subdoc was created. When
  2733.      * we're finished creating the new subdoc, the master index
  2734.      * should be back to its original value (but just in case we
  2735.      * save that value in a local variable here).
  2736.      */
  2737.     hold_embed_global_index = top_state->embed_count;
  2738.     top_state->embed_count = old_state->embed_count_base;
  2739.  
  2740.     /* ditto here for the last comment.  We are trying to keep
  2741.      * a tag count that reflects the order of tags coming in
  2742.       * on the stream.  We need that count to be correct across
  2743.      * multiple relayout instances so we restore the top state
  2744.      * count with the saved state
  2745.      */
  2746.     original_tag_count = top_state->tag_count;
  2747.     top_state->tag_count = state->beginning_tag_count;
  2748.  
  2749.     /*
  2750.      * Same goes for anchors and images
  2751.      */
  2752.     hold_url_list_len = doc_lists->url_list_len;
  2753.     doc_lists->url_list_len = old_state->url_count_base;
  2754.  
  2755.     hold_image_list_count = doc_lists->image_list_count;
  2756.     doc_lists->image_list_count = old_state->image_list_count_base;
  2757.  
  2758.     hold_applet_list_count = doc_lists->applet_list_count;
  2759.     doc_lists->applet_list_count = old_state->applet_list_count_base;
  2760.     
  2761.     hold_embed_list_count = doc_lists->embed_list_count;
  2762.     doc_lists->embed_list_count = old_state->embed_list_count_base;
  2763.  
  2764.     hold_current_layer_num = top_state->current_layer_num;
  2765.     top_state->current_layer_num = old_state->current_layer_num_base;
  2766.     
  2767.     /*
  2768.      * Save whether we are in a form or not, and restore
  2769.      * to what we were when the subdoc was started.
  2770.      */
  2771.     hold_in_form = top_state->in_form;
  2772.     top_state->in_form = old_state->start_in_form;
  2773.  
  2774.     if (top_state->savedData.FormList != NULL)
  2775.     {
  2776.         lo_SavedFormListData *all_form_ele;
  2777.  
  2778.         all_form_ele = top_state->savedData.FormList;
  2779.         hold_form_data_index = all_form_ele->data_index;
  2780.         all_form_ele->data_index = old_state->form_data_index;
  2781.     }
  2782.     else
  2783.     {
  2784.         hold_form_data_index = 0;
  2785.     }
  2786.  
  2787.     /*
  2788.      * Still variable height, but we know the width now.
  2789.      */
  2790.     first_height = FEUNITS_Y(10000, context);
  2791.     allow_percent_height = FALSE;
  2792.     allow_percent_width = TRUE;
  2793.  
  2794.     /*
  2795.      * Get a new sub-state to create the new subdoc in.
  2796.      */
  2797.     /*
  2798.     new_state = lo_NewLayout(context, width, first_height, 0, 0, NULL);
  2799.     */
  2800.     lo_reuse_current_state(context, subdoc->state, width,
  2801.         first_height, 0, 0, FALSE);
  2802.  
  2803.     new_state = subdoc->state;
  2804.     subdoc->state = NULL;
  2805.  
  2806.     
  2807.     if (new_state == NULL)
  2808.     {
  2809.         state->top_state->force_reload = save_force;
  2810.         return(subdoc);
  2811.     }
  2812.  
  2813.     new_state->end_last_line = NULL;
  2814.     /*
  2815.     if (old_state->is_a_subdoc == SUBDOC_CAPTION)
  2816.     {
  2817.         new_state->is_a_subdoc = SUBDOC_CAPTION;
  2818.     }
  2819.     else
  2820.     {
  2821.         new_state->is_a_subdoc = SUBDOC_CELL;
  2822.     }
  2823.     */
  2824.     new_state->is_a_subdoc = SUBDOC_CAPTION;
  2825.  
  2826.     lo_InheritParentColors(context, new_state, state);
  2827.     new_state->allow_percent_width = allow_percent_width;
  2828.     new_state->allow_percent_height = allow_percent_height;
  2829.     /*
  2830.      * In relaying out subdocs, we NEVER link back up subdoc tags
  2831.      */
  2832.     new_state->subdoc_tags = NULL;
  2833.     new_state->subdoc_tags_end = NULL;
  2834.  
  2835.     /*
  2836.      * Initialize other new state sundries.
  2837.      */
  2838.     new_state->base_x = 0;
  2839.     new_state->base_y = 0;
  2840.     new_state->display_blocked = TRUE;
  2841.     if (subdoc->width == 0)
  2842.     {
  2843.         new_state->delay_align = TRUE;
  2844.     }
  2845.  
  2846.     new_state->win_left = 0;
  2847.     new_state->win_right = 0;
  2848.     new_state->x = new_state->win_left;
  2849.     new_state->y = 0;
  2850.     new_state->max_width = new_state->x + 1;
  2851.     new_state->left_margin = new_state->win_left;
  2852.     new_state->right_margin = new_state->win_width - new_state->win_right;
  2853.     new_state->list_stack->old_left_margin = new_state->left_margin;
  2854.     new_state->list_stack->old_right_margin = new_state->right_margin;
  2855.  
  2856.     /* we don't need min widths during relayout */
  2857.     new_state->need_min_width = FALSE;
  2858.  
  2859.     /* reset line_height stack */
  2860.     while (new_state->line_height_stack)
  2861.         lo_PopLineHeight(new_state);
  2862.  
  2863.     /* 
  2864.      * Initialize the alignment stack for this state
  2865.      * to match the caption alignment.
  2866.      */
  2867.     if (subdoc->horiz_alignment != LO_ALIGN_LEFT)
  2868.     {
  2869.         lo_PushAlignment(new_state, P_TABLE_DATA, subdoc->horiz_alignment);
  2870.     }
  2871.  
  2872.     state->sub_state = new_state;
  2873.  
  2874.     state->current_ele = (LO_Element *)subdoc;
  2875.     
  2876.     if (is_a_header != FALSE)
  2877.     {
  2878.         LO_TextAttr *old_attr;
  2879.         LO_TextAttr *attr;
  2880.         LO_TextAttr tmp_attr;
  2881.  
  2882.         old_attr = new_state->font_stack->text_attr;
  2883.         lo_CopyTextAttr(old_attr, &tmp_attr);
  2884.         tmp_attr.fontmask |= LO_FONT_BOLD;
  2885.         attr = lo_FetchTextAttr(new_state, &tmp_attr);
  2886.  
  2887.         lo_PushFont(new_state, P_TABLE_HEADER, attr);
  2888.     }
  2889.  
  2890.     /*
  2891.      * Move our current state down into the new sub-state.
  2892.      * Fetch the tag list from the old subdoc's state in preparation
  2893.      * for relayout.
  2894.      */
  2895.     state = new_state;
  2896.  
  2897.     /*
  2898.     tag_ptr = old_state->subdoc_tags;
  2899.     tag_end_ptr = old_state->subdoc_tags_end;
  2900.     old_state->subdoc_tags = NULL;
  2901.     old_state->subdoc_tags_end = NULL;
  2902.     if (tag_end_ptr != NULL)
  2903.     {
  2904.         tag_end_ptr = tag_end_ptr->next;
  2905.     }
  2906.     */
  2907.  
  2908.     /*
  2909.      * Clean up memory used by old subdoc state.
  2910.      */
  2911.     /*
  2912.     lo_cleanup_state(context, old_state);
  2913.     */
  2914.  
  2915. #if 0    /* Doesn't need to happen any more because we do non-destructive reflow
  2916.     /*
  2917.      * Save our parent's state levels
  2918.      */
  2919.     save_diff_state = top_state->diff_state;
  2920.     save_state_pushes = top_state->state_pushes;
  2921.     save_state_pops = top_state->state_pops;
  2922.  
  2923.     while (tag_ptr != tag_end_ptr)
  2924.     {
  2925.         PA_Tag *tag;
  2926.         lo_DocState *sub_state;
  2927.         lo_DocState *up_state;
  2928.         lo_DocState *tmp_state;
  2929.         Bool may_save;
  2930.  
  2931.         tag = tag_ptr;
  2932.         tag_ptr = tag_ptr->next;
  2933.         tag->next = NULL;
  2934.         tag_list = tag_ptr;
  2935.  
  2936.         up_state = NULL;
  2937.         sub_state = state;
  2938.         while (sub_state->sub_state != NULL)
  2939.         {
  2940.             up_state = sub_state;
  2941.             sub_state = sub_state->sub_state;
  2942.         }
  2943.  
  2944.         if ((sub_state->is_a_subdoc == SUBDOC_CELL)||
  2945.             (sub_state->is_a_subdoc == SUBDOC_CAPTION))
  2946.         {
  2947.             may_save = TRUE;
  2948.         }
  2949.         else
  2950.         {
  2951.             may_save = FALSE;
  2952.         }
  2953.  
  2954.         /*
  2955.          * Reset these so we can tell if anything happened
  2956.          */
  2957.         top_state->diff_state = FALSE;
  2958.         top_state->state_pushes = 0;
  2959.         top_state->state_pops = 0;
  2960.  
  2961. #ifdef MOCHA
  2962.         sub_state->in_relayout = TRUE;
  2963. #endif
  2964.         lo_LayoutTag(context, sub_state, tag);
  2965.         tmp_state = lo_CurrentSubState(state);
  2966. #ifdef MOCHA
  2967.         if (tmp_state == sub_state)
  2968.         {
  2969.             sub_state->in_relayout = FALSE;
  2970.         }
  2971. #endif
  2972.  
  2973.         if (may_save != FALSE)
  2974.         {
  2975.             int32 state_diff;
  2976.             
  2977.             /* how has our state level changed? */
  2978.             state_diff = top_state->state_pushes - top_state->state_pops;
  2979.             
  2980.             /*
  2981.              * That tag popped us up one state level.  If this new
  2982.              * state is still a subdoc, save the tag there.
  2983.              */
  2984.             if (state_diff == -1)
  2985.             {
  2986.                 if ((tmp_state->is_a_subdoc == SUBDOC_CELL)||
  2987.                     (tmp_state->is_a_subdoc == SUBDOC_CAPTION))
  2988.                 {
  2989.                     /* if we just popped a table we need to insert
  2990.                      * a dummy end tag to pop the dummy start tag
  2991.                      * we shove on the stack after createing a table
  2992.                      */
  2993.                        PA_Tag *new_tag = LO_CreateStyleSheetDummyTag(tag);
  2994.                     if(new_tag)
  2995.                     {
  2996.                         lo_SaveSubdocTags(context, tmp_state, new_tag);
  2997.                     }
  2998.  
  2999.                     lo_SaveSubdocTags(context, tmp_state, tag);
  3000.                 }
  3001.                 else
  3002.                 {
  3003.                     PA_FreeTag(tag);
  3004.                 }
  3005.             }
  3006.             /*
  3007.              * Else that tag put us in a new subdoc on the same
  3008.              * level.  It needs to be saved one level up,
  3009.              * if the parent is also a subdoc.
  3010.              */
  3011.             else if (( up_state != NULL ) &&
  3012.                 ( top_state->diff_state != FALSE ) &&
  3013.                 ( state_diff == 0 ))
  3014.             {
  3015.                 if ((up_state->is_a_subdoc == SUBDOC_CELL)||
  3016.                      (up_state->is_a_subdoc == SUBDOC_CAPTION))
  3017.                 {
  3018.                     lo_SaveSubdocTags(context, up_state, tag);
  3019.                 }
  3020.                 else
  3021.                 {
  3022.                     PA_FreeTag(tag);
  3023.                 }
  3024.             }
  3025.             /*
  3026.              * Else we are still in the same subdoc
  3027.              */
  3028.             else if (( top_state->diff_state == FALSE ) &&
  3029.                 ( state_diff == 0 ))
  3030.             {
  3031.                 lo_SaveSubdocTags(context, sub_state, tag);
  3032.             }
  3033.             /*
  3034.              * Else that tag started a new, nested subdoc.
  3035.              * Add the starting tag to the parent.
  3036.              */
  3037.             else if (( state_diff == 1 ))
  3038.             {
  3039.                 lo_SaveSubdocTags(context, sub_state, tag);
  3040.                 /*
  3041.                  * Since we have extended the parent chain,
  3042.                  * we need to reset the child to the new
  3043.                  * parent end-chain.
  3044.                  */
  3045.                 if ((tmp_state->is_a_subdoc == SUBDOC_CELL)||
  3046.                     (tmp_state->is_a_subdoc == SUBDOC_CAPTION))
  3047.                 {
  3048.                     PA_Tag *new_tag;
  3049.                     
  3050.                     tmp_state->subdoc_tags =
  3051.                         sub_state->subdoc_tags_end;
  3052.  
  3053.                     /* add an aditional dummy tag so that style sheets
  3054.                      * can use it to query styles from for this entry
  3055.                      * that created a table
  3056.                      */
  3057.                     new_tag = LO_CreateStyleSheetDummyTag(tag);
  3058.                     if(new_tag)
  3059.                     {
  3060.                         lo_SaveSubdocTags(context, tmp_state, new_tag);
  3061.                     }
  3062.                 }
  3063.             }
  3064.             /*
  3065.              * This can never happen.
  3066.              */
  3067.             else
  3068.             {
  3069.                 PA_FreeTag(tag);
  3070.             }
  3071.         }
  3072.         tag_ptr = tag_list;
  3073.     }
  3074.  
  3075.     /*
  3076.      * Restore our parent's state levels
  3077.      */
  3078.     top_state->diff_state = save_diff_state;
  3079.     top_state->state_pushes = save_state_pushes;
  3080.     top_state->state_pops = save_state_pops;
  3081. #endif
  3082.  
  3083.     /*
  3084.      * Link the end of this subdoc's tag chain back to
  3085.      * its parent.  The beginning should have never been
  3086.      * unlinked from the parent.
  3087.      */
  3088.     /*
  3089.     if (state->subdoc_tags_end != NULL)
  3090.     {
  3091.         state->subdoc_tags_end->next = tag_end_ptr;
  3092.     }
  3093.     */
  3094.  
  3095.     lo_rl_ReflowDocState( context, state );
  3096.  
  3097.     /*
  3098.      * makes sure we are at the bottom
  3099.      * of everything in the document.
  3100.      */
  3101.     /*
  3102.     lo_CloseOutLayout(context, state);
  3103.     */
  3104.  
  3105.     lo_EndLayoutDuringReflow( context, state );
  3106.  
  3107.     old_state = state;
  3108.     /*
  3109.      * Get the unique document ID, and retreive this
  3110.      * documents layout state.
  3111.      */
  3112.     doc_id = XP_DOCID(context);
  3113.     top_state = lo_FetchTopState(doc_id);
  3114.     state = top_state->doc_state;
  3115.  
  3116.     while ((state->sub_state != NULL)&&
  3117.         (state->sub_state != old_state))
  3118.     {
  3119.         state = state->sub_state;
  3120.     }
  3121.  
  3122.     /*
  3123.      * Ok, now reset the global form element counters
  3124.      * to their original values.
  3125.      */
  3126.     if ((doc_lists->form_list != NULL)||(hold_form_list != NULL))
  3127.     {
  3128.         lo_FormData *form_list;
  3129.         lo_FormData *new_form_list;
  3130.         lo_FormData *tmp_fptr;
  3131.  
  3132.         /*
  3133.          * Remove any new forms created in this subdocs to a
  3134.          * separate list.
  3135.          */
  3136.         form_list = doc_lists->form_list;
  3137.         new_form_list = NULL;
  3138.         while ((form_list != NULL)&&
  3139.             (form_list->id > hold_form_id))
  3140.         {
  3141.             tmp_fptr = form_list;
  3142.             form_list = form_list->next;
  3143.             tmp_fptr->next = new_form_list;
  3144.             new_form_list = tmp_fptr;
  3145.         }
  3146.  
  3147.         /*
  3148.          * Restore the element count in the form we started in
  3149.          * because the subdoc may have left it half finished.
  3150.          */
  3151.         if (form_list != NULL)
  3152.         {
  3153.             form_list->form_ele_cnt = hold_form_ele_cnt;
  3154.         }
  3155.  
  3156.         /*
  3157.          * Merge the newly created forms with the old ones
  3158.          * since the new ones may have partially complete
  3159.          * data.
  3160.          */
  3161.         while ((new_form_list != NULL)&&(hold_form_list != NULL))
  3162.         {
  3163.             tmp_fptr = lo_merge_form_data(new_form_list,
  3164.                     hold_form_list);
  3165.             new_form_list = new_form_list->next;
  3166.             hold_form_list = hold_form_list->next;
  3167.             tmp_fptr->next = form_list;
  3168.             form_list = tmp_fptr;
  3169.         }
  3170.  
  3171.         /*
  3172.          * Add back on forms that are from later subdocs.
  3173.          */
  3174.         while (hold_form_list != NULL)
  3175.         {
  3176.             tmp_fptr = hold_form_list;
  3177.             hold_form_list = hold_form_list->next;
  3178.             tmp_fptr->next = form_list;
  3179.             form_list = tmp_fptr;
  3180.         }
  3181.  
  3182.         doc_lists->form_list = form_list;
  3183.         doc_lists->current_form_num = hold_current_form_num;
  3184.     }
  3185.  
  3186.     /*
  3187.      * Restore in form status to what is
  3188.      * was before this relayout.
  3189.      */
  3190.     top_state->in_form = hold_in_form;
  3191.  
  3192.     if (top_state->savedData.FormList != NULL)
  3193.     {
  3194.         lo_SavedFormListData *all_form_ele;
  3195.  
  3196.         all_form_ele = top_state->savedData.FormList;
  3197.         all_form_ele->data_index = hold_form_data_index;
  3198.     }
  3199.  
  3200.     /*
  3201.      * The master embed index is typically now be back
  3202.      * to its original value, but might not be if we
  3203.      * only had to relayout some (not all) of the embeds
  3204.      * in this subdoc.  So, make sure it's set back to
  3205.      * its original value here.
  3206.      */
  3207.     top_state->embed_count = hold_embed_global_index;
  3208.  
  3209.     /* verify that the tag count is still correct */
  3210.     top_state->tag_count = original_tag_count;
  3211.  
  3212.     /*
  3213.      * Likewise for the anchor list.
  3214.      */
  3215.     doc_lists->url_list_len = hold_url_list_len;
  3216.     doc_lists->image_list_count = hold_image_list_count;
  3217.         doc_lists->applet_list_count = hold_applet_list_count;
  3218.         doc_lists->embed_list_count = hold_embed_list_count;
  3219.     top_state->current_layer_num = hold_current_layer_num;
  3220.  
  3221.     subdoc = NULL;
  3222.     if ((state != old_state)&&
  3223.         (state->current_ele != NULL))
  3224.     {
  3225.         subdoc = lo_EndCellSubDoc(context, state,
  3226.                 old_state, state->current_ele, TRUE);
  3227.         state->sub_state = NULL;
  3228.         state->current_ele = NULL;
  3229. /*
  3230.         if ((state->is_a_subdoc == SUBDOC_CELL)||
  3231.             (state->is_a_subdoc == SUBDOC_CAPTION))
  3232.         {
  3233.             if (old_state->subdoc_tags_end != NULL)
  3234.             {
  3235.                 state->subdoc_tags_end =
  3236.                     old_state->subdoc_tags_end;
  3237.             }
  3238.         }
  3239. */
  3240.     }
  3241.  
  3242.     old_state->must_relayout_subdoc = FALSE;
  3243.  
  3244.     state->top_state->force_reload = save_force;
  3245.     return(subdoc);
  3246. }
  3247.  
  3248.  
  3249. LO_CellStruct *
  3250. lo_RelayoutCell(MWContext *context, lo_DocState *state,
  3251.     LO_SubDocStruct *subdoc, lo_TableCell *cell_ptr,
  3252.     LO_CellStruct *cell, int32 width, Bool is_a_header,
  3253.     Bool relayout)
  3254. {
  3255.     LO_CellStruct *cell_ele;
  3256.     int32 first_height;
  3257.     lo_TopState *top_state;
  3258.     lo_DocState *old_state;
  3259.     lo_DocState *new_state;
  3260.     PA_Tag *tag_list;
  3261.     PA_Tag *tag_ptr;
  3262.     PA_Tag *tag_end_ptr;
  3263.     int32 doc_id;
  3264.     Bool allow_percent_width;
  3265.     Bool allow_percent_height;
  3266.     int32 hold_form_ele_cnt;
  3267.     int32 hold_form_data_index;
  3268.     intn hold_form_id;
  3269.     intn hold_current_form_num;
  3270.     Bool hold_in_form;
  3271.     lo_FormData *hold_form_list;
  3272.     int32 hold_embed_global_index;
  3273.     int32 original_tag_count;
  3274.     intn hold_url_list_len;
  3275.     NET_ReloadMethod save_force;
  3276.     Bool save_diff_state;
  3277.     int32 save_state_pushes;
  3278.     int32 save_state_pops;
  3279.     lo_DocLists *doc_lists;
  3280.     int32 hold_image_list_count;
  3281.         int32 hold_applet_list_count;
  3282.         int32 hold_embed_list_count;
  3283.     int32 hold_current_layer_num;
  3284.     LO_Element * elem_list;
  3285.  
  3286.     /*
  3287.      * Relayout is NOT allowed to block on images, so never
  3288.      * have the forced reload flag set.
  3289.      */
  3290.     save_force = state->top_state->force_reload;
  3291.     state->top_state->force_reload = NET_CACHE_ONLY_RELOAD;
  3292.  
  3293.     top_state = state->top_state;
  3294.     
  3295.     /*
  3296.      * We are going to reuse this subdoc element instead
  3297.      * of allocating a new one.
  3298.     lo_reuse_current_subdoc(context, subdoc);
  3299.     subdoc->state = NULL;
  3300.      */
  3301.     subdoc->width = width;
  3302.     subdoc->height = 0;
  3303.  
  3304.     subdoc->horiz_alignment = cell_ptr->horiz_alignment;
  3305.  
  3306.     doc_lists = lo_GetCurrentDocLists(state);
  3307.     
  3308.     /*
  3309.      * If this subdoc contained form elements.  We want to reuse
  3310.      * them without messing up the order of later form elements in
  3311.      * other subdocs.
  3312.      *
  3313.      * We assume that relaying out the doc will create the exact
  3314.      * same number of form elements in the same order as the first time.
  3315.      * so we reset global form counters to before this subdoc
  3316.      * was ever laid out, saving the current counts to restore later.
  3317.      */
  3318.     if (doc_lists->form_list != NULL)
  3319.     {
  3320.         lo_FormData *form_list;
  3321.         lo_FormData *tmp_fptr;
  3322.  
  3323.         hold_form_id = cell_ptr->form_id;
  3324.         hold_current_form_num = doc_lists->current_form_num;
  3325.         form_list = doc_lists->form_list;
  3326.         hold_form_list = NULL;
  3327.         while ((form_list != NULL)&&
  3328.             (form_list->id > hold_form_id))
  3329.         {
  3330.             tmp_fptr = form_list;
  3331.             form_list = form_list->next;
  3332.             tmp_fptr->next = hold_form_list;
  3333.             hold_form_list = tmp_fptr;
  3334.         }
  3335.         doc_lists->form_list = form_list;
  3336.         doc_lists->current_form_num = hold_form_id;
  3337.         if (form_list != NULL)
  3338.         {
  3339.             hold_form_ele_cnt = form_list->form_ele_cnt;
  3340.             form_list->form_ele_cnt = cell_ptr->form_ele_cnt;
  3341.         }
  3342.         else
  3343.         {
  3344.             hold_form_ele_cnt = 0;
  3345.         }
  3346.     }
  3347.     else
  3348.     {
  3349.         hold_form_id = 0;
  3350.         hold_form_ele_cnt = 0;
  3351.         hold_form_list = NULL;
  3352.         hold_current_form_num = 0;
  3353.     }
  3354.  
  3355.     /*
  3356.      * We're going to be deleting and then recreating the contents 
  3357.      * of this subdoc.  We want the newly-created embeds to have
  3358.      * the same embed indices as their recycled counterparts, so
  3359.      * we reset the master embed index in the top_state to be the
  3360.      * value it held at the time the old subdoc was created. When
  3361.      * we're finished creating the new subdoc, the master index
  3362.      * should be back to its original value (but just in case we
  3363.      * save that value in a local variable here).
  3364.      */
  3365.     hold_embed_global_index = top_state->embed_count;
  3366.     top_state->embed_count = cell_ptr->embed_count_base;
  3367.  
  3368.     /* same for tag count */
  3369.     original_tag_count = top_state->tag_count;
  3370.     top_state->tag_count = cell_ptr->beginning_tag_count;
  3371.  
  3372.     /*
  3373.      * Same goes for anchors and images
  3374.      */
  3375.     hold_url_list_len = doc_lists->url_list_len;
  3376.     doc_lists->url_list_len = cell_ptr->url_count_base;
  3377.  
  3378.     hold_image_list_count = doc_lists->image_list_count;
  3379.     doc_lists->image_list_count = cell_ptr->image_list_count_base;
  3380.  
  3381.     hold_applet_list_count = doc_lists->applet_list_count;
  3382.     doc_lists->applet_list_count = cell_ptr->applet_list_count_base;
  3383.     
  3384.     hold_embed_list_count = doc_lists->embed_list_count;
  3385.     doc_lists->embed_list_count = cell_ptr->embed_list_count_base;
  3386.  
  3387.     hold_current_layer_num = top_state->current_layer_num;
  3388.     top_state->current_layer_num = cell_ptr->current_layer_num_base;
  3389.  
  3390.     /*
  3391.      * Save whether we are in a form or not, and restore
  3392.      * to what we were when the subdoc was started.
  3393.      */
  3394.     hold_in_form = top_state->in_form;
  3395.     top_state->in_form = cell_ptr->start_in_form;
  3396.  
  3397.     if (top_state->savedData.FormList != NULL)
  3398.     {
  3399.         lo_SavedFormListData *all_form_ele;
  3400.  
  3401.         all_form_ele = top_state->savedData.FormList;
  3402.         hold_form_data_index = all_form_ele->data_index;
  3403.         all_form_ele->data_index = cell_ptr->form_data_index;
  3404.     }
  3405.     else
  3406.     {
  3407.         hold_form_data_index = 0;
  3408.     }
  3409.  
  3410.     /*
  3411.      * Still variable height, but we know the width now.
  3412.      */
  3413.     first_height = FEUNITS_Y(10000, context);
  3414.     allow_percent_height = FALSE;
  3415.     allow_percent_width = TRUE;
  3416.  
  3417.     /*
  3418.      * Get a new sub-state to create the new subdoc in.
  3419.      */
  3420.     lo_reuse_current_state(context, subdoc->state,
  3421.         width, first_height, 0, 0, TRUE);
  3422.     new_state = subdoc->state;
  3423.     subdoc->state = NULL;
  3424.  
  3425.  
  3426.     if (new_state == NULL)
  3427.     {
  3428.         state->top_state->force_reload = save_force;
  3429.         return(cell);
  3430.     }
  3431.     if (cell_ptr->is_a_subdoc == SUBDOC_CAPTION)
  3432.     {
  3433.         new_state->is_a_subdoc = SUBDOC_CAPTION;
  3434.     }
  3435.     else
  3436.     {
  3437.         new_state->is_a_subdoc = SUBDOC_CELL;
  3438.     }
  3439.  
  3440.     lo_InheritParentState(context, new_state, state);
  3441.     new_state->allow_percent_width = allow_percent_width;
  3442.     new_state->allow_percent_height = allow_percent_height;
  3443.     /*
  3444.      * In relaying out subdocs, we NEVER link back up subdoc tags
  3445.      */
  3446.     new_state->subdoc_tags = NULL;
  3447.     new_state->subdoc_tags_end = NULL;
  3448.  
  3449.     /*
  3450.      * Initialize other new state sundries.
  3451.      */
  3452.     new_state->base_x = 0;
  3453.     new_state->base_y = 0;
  3454.     new_state->display_blocked = TRUE;
  3455.     if (subdoc->width == 0)
  3456.     {
  3457.         new_state->delay_align = TRUE;
  3458.     }
  3459.  
  3460.     new_state->win_left = 0;
  3461.     new_state->win_right = 0;
  3462.     new_state->x = new_state->win_left;
  3463.     new_state->y = 0;
  3464.     new_state->max_width = new_state->x + 1;
  3465.     new_state->left_margin = new_state->win_left;
  3466.     new_state->right_margin = new_state->win_width - new_state->win_right;
  3467.     new_state->list_stack->old_left_margin = new_state->left_margin;
  3468.     new_state->list_stack->old_right_margin = new_state->right_margin;
  3469.     
  3470.     /* we don't need min widths during relayout */
  3471.     new_state->need_min_width = FALSE;
  3472.     
  3473.     /* reset line_height stack */
  3474.     while(new_state->line_height_stack)
  3475.         lo_PopLineHeight(new_state);
  3476.     
  3477.     /*
  3478.      * Initialize the alignment stack for this state
  3479.      * to match the caption alignment.
  3480.      */
  3481.     if (subdoc->horiz_alignment != LO_ALIGN_LEFT)
  3482.     {
  3483.         lo_PushAlignment(new_state, P_TABLE_DATA, subdoc->horiz_alignment);
  3484.     }
  3485.  
  3486.     state->sub_state = new_state;
  3487.  
  3488.     state->current_ele = (LO_Element *)subdoc;
  3489.  
  3490.     if (is_a_header != FALSE)
  3491.     {
  3492.         LO_TextAttr *old_attr;
  3493.         LO_TextAttr *attr;
  3494.         LO_TextAttr tmp_attr;
  3495.  
  3496.         old_attr = new_state->font_stack->text_attr;
  3497.         lo_CopyTextAttr(old_attr, &tmp_attr);
  3498.         tmp_attr.fontmask |= LO_FONT_BOLD;
  3499.         attr = lo_FetchTextAttr(new_state, &tmp_attr);
  3500.  
  3501.         lo_PushFont(new_state, P_TABLE_HEADER, attr);
  3502.     }
  3503.  
  3504.     /*
  3505.      * Move our current state down into the new sub-state.
  3506.      * Fetch the tag list from the old subdoc's state in preparation
  3507.      * for relayout.
  3508.      */
  3509.     
  3510.     state = new_state;
  3511.     /*
  3512.     tag_ptr = cell_ptr->subdoc_tags;
  3513.     tag_end_ptr = cell_ptr->subdoc_tags_end;
  3514.     cell_ptr->subdoc_tags = NULL;
  3515.     cell_ptr->subdoc_tags_end = NULL;
  3516.     
  3517.     if (tag_end_ptr != NULL)
  3518.     {
  3519.         tag_end_ptr = tag_end_ptr->next;
  3520.     }
  3521.     */
  3522.  
  3523.     /*
  3524.      * Copy some cell attribute state from the old cell to the subdoc
  3525.      * so that we retain the correct state. Make sure that the bg_color
  3526.      * doesn't get freed.
  3527.      */
  3528.     subdoc->horiz_alignment = cell_ptr->horiz_alignment;
  3529.     subdoc->vert_alignment = cell_ptr->vert_alignment;
  3530.     subdoc->backdrop = cell->backdrop;
  3531.     /*
  3532.     cell->backdrop.bg_color = NULL;
  3533.     cell->backdrop.url = NULL;
  3534.     */
  3535.     
  3536.     /*
  3537.      * Clean up memory used by old cell.
  3538.      */
  3539.     /*
  3540.     elem_list = cell->cell_list;
  3541.     cell->next = NULL;
  3542.     cell->cell_list = NULL;
  3543.     cell->cell_list_end = NULL;
  3544.     lo_relayout_recycle(context, state, (LO_Element *)cell);
  3545.     */
  3546.  
  3547.     /*
  3548.      * Relayout all the goodies
  3549.      */
  3550.     /*
  3551.     lo_RelayoutTags(context, state, tag_ptr, tag_end_ptr, elem_list);
  3552.     */
  3553.  
  3554.     /*
  3555.      * Link the end of this subdoc's tag chain back to
  3556.      * its parent.  The beginning should have never been
  3557.      * unlinked from the parent.
  3558.      */
  3559.     /*
  3560.     if (state->subdoc_tags_end != NULL)
  3561.     {
  3562.         state->subdoc_tags_end->next = tag_end_ptr;
  3563.     }
  3564.     */
  3565.  
  3566.     /*
  3567.      * makes sure we are at the bottom
  3568.      * of everything in the document.
  3569.      */
  3570.  
  3571.     lo_rl_ReflowCell( context, state, cell );
  3572.     
  3573.     /* Replaced with lo_EndLayoutDuringReflow()
  3574.     lo_CloseOutLayout(context, state);
  3575.     */
  3576.     
  3577.     lo_EndLayoutDuringReflow( context, state );
  3578.     
  3579.  
  3580.     old_state = state;
  3581.     /*
  3582.      * Get the unique document ID, and retreive this
  3583.      * documents layout state.
  3584.      */
  3585.     doc_id = XP_DOCID(context);
  3586.     top_state = lo_FetchTopState(doc_id);
  3587.     state = top_state->doc_state;
  3588.  
  3589.     while ((state->sub_state != NULL)&&
  3590.         (state->sub_state != old_state))
  3591.     {
  3592.         state = state->sub_state;
  3593.     }
  3594.  
  3595.     /*
  3596.      * Ok, now reset the global form element counters
  3597.      * to their original values.
  3598.      */
  3599.     if ((doc_lists->form_list != NULL)||(hold_form_list != NULL))
  3600.     {
  3601.         lo_FormData *form_list;
  3602.         lo_FormData *new_form_list;
  3603.         lo_FormData *tmp_fptr;
  3604.  
  3605.         /*
  3606.          * Remove any new forms created in this subdocs to a
  3607.          * separate list.
  3608.          */
  3609.         form_list = doc_lists->form_list;
  3610.         new_form_list = NULL;
  3611.         while ((form_list != NULL)&&
  3612.             (form_list->id > hold_form_id))
  3613.         {
  3614.             tmp_fptr = form_list;
  3615.             form_list = form_list->next;
  3616.             tmp_fptr->next = new_form_list;
  3617.             new_form_list = tmp_fptr;
  3618.         }
  3619.  
  3620.         /*
  3621.          * Restore the element count in the form we started in
  3622.          * because the subdoc may have left it half finished.
  3623.          */
  3624.         if (form_list != NULL)
  3625.         {
  3626.             form_list->form_ele_cnt = hold_form_ele_cnt;
  3627.         }
  3628.  
  3629.         /*
  3630.          * Merge the newly created forms with the old ones
  3631.          * since the new ones may have partially complete
  3632.          * data.
  3633.          */
  3634.         while ((new_form_list != NULL)&&(hold_form_list != NULL))
  3635.         {
  3636.             tmp_fptr = lo_merge_form_data(new_form_list,
  3637.                     hold_form_list);
  3638.             new_form_list = new_form_list->next;
  3639.             hold_form_list = hold_form_list->next;
  3640.             tmp_fptr->next = form_list;
  3641.             form_list = tmp_fptr;
  3642.         }
  3643.  
  3644.         /*
  3645.          * Add back on forms that are from later subdocs.
  3646.          */
  3647.         while (hold_form_list != NULL)
  3648.         {
  3649.             tmp_fptr = hold_form_list;
  3650.             hold_form_list = hold_form_list->next;
  3651.             tmp_fptr->next = form_list;
  3652.             form_list = tmp_fptr;
  3653.         }
  3654.  
  3655.         doc_lists->form_list = form_list;
  3656.         doc_lists->current_form_num = hold_current_form_num;
  3657.     }
  3658.  
  3659.     /*
  3660.      * Restore in form status to what is
  3661.      * was before this relayout.
  3662.      */
  3663.     top_state->in_form = hold_in_form;
  3664.  
  3665.     if (top_state->savedData.FormList != NULL)
  3666.     {
  3667.         lo_SavedFormListData *all_form_ele;
  3668.  
  3669.         all_form_ele = top_state->savedData.FormList;
  3670.         all_form_ele->data_index = hold_form_data_index;
  3671.     }
  3672.  
  3673.     /*
  3674.      * The master embed index is typically now be back
  3675.      * to its original value, but might not be if we
  3676.      * only had to relayout some (not all) of the embeds
  3677.      * in this subdoc.  So, make sure it's set back to
  3678.      * its original value here.
  3679.      */
  3680.     top_state->embed_count = hold_embed_global_index;
  3681.     
  3682.     /* ditto for tag_count */
  3683.     top_state->tag_count = original_tag_count;
  3684.  
  3685.     /*
  3686.      * Likewise for the anchor list and image list.
  3687.      */
  3688.     doc_lists->url_list_len = hold_url_list_len;
  3689.     doc_lists->image_list_count = hold_image_list_count;
  3690.         doc_lists->applet_list_count = hold_applet_list_count;
  3691.         doc_lists->embed_list_count = hold_embed_list_count;
  3692.     top_state->current_layer_num = hold_current_layer_num;
  3693.     
  3694.     subdoc = NULL;
  3695.     cell_ele = NULL;
  3696.     if ((state != old_state)&&
  3697.         (state->current_ele != NULL))
  3698.     {
  3699.         lo_DocState *subdoc_state;
  3700.         int32 dx, dy;
  3701.         int32 base_x, base_y;
  3702.  
  3703.         subdoc = lo_EndCellSubDoc(context, state,
  3704.                 old_state, state->current_ele, TRUE);
  3705.         state->sub_state = NULL;
  3706.         state->current_ele = NULL;
  3707. /*
  3708.         if ((state->is_a_subdoc == SUBDOC_CELL)||
  3709.             (state->is_a_subdoc == SUBDOC_CAPTION))
  3710.         {
  3711.             if (old_state->subdoc_tags_end != NULL)
  3712.             {
  3713.                 state->subdoc_tags_end =
  3714.                     old_state->subdoc_tags_end;
  3715.             }
  3716.         }
  3717. */
  3718.         subdoc_state = (lo_DocState *)(subdoc->state);
  3719.         cell_ptr->start_in_form = subdoc_state->start_in_form;
  3720.         cell_ptr->form_id = subdoc_state->form_id;
  3721.         cell_ptr->form_ele_cnt = subdoc_state->form_ele_cnt;
  3722.         cell_ptr->form_data_index = subdoc_state->form_data_index;
  3723.         cell_ptr->embed_count_base = subdoc_state->embed_count_base;
  3724.         cell_ptr->url_count_base = subdoc_state->url_count_base;
  3725.         cell_ptr->image_list_count_base = subdoc_state->image_list_count_base;
  3726.         cell_ptr->applet_list_count_base = subdoc_state->applet_list_count_base;
  3727.         cell_ptr->embed_list_count_base = subdoc_state->embed_list_count_base;                
  3728.         cell_ptr->current_layer_num_base = subdoc_state->current_layer_num_base;
  3729.         cell_ptr->must_relayout = subdoc_state->must_relayout_subdoc;
  3730.         cell_ptr->is_a_subdoc = subdoc_state->is_a_subdoc;
  3731.         /*
  3732.         cell_ptr->subdoc_tags = subdoc_state->subdoc_tags;
  3733.         cell_ptr->subdoc_tags_end = subdoc_state->subdoc_tags_end;
  3734.         */
  3735.         subdoc_state->subdoc_tags = NULL;
  3736.         subdoc_state->subdoc_tags_end = NULL;
  3737.         cell_ptr->max_y = subdoc_state->y;
  3738.         cell_ptr->horiz_alignment = subdoc->horiz_alignment;
  3739.         cell_ptr->vert_alignment = subdoc->vert_alignment;
  3740.             
  3741.         /*
  3742.         cell_ele = lo_SmallSquishSubDocToCell(context, state, subdoc,
  3743.                 &dx, &dy);
  3744.         */
  3745.  
  3746.         cell_ele = cell_ptr->cell;
  3747.         lo_CreateCellFromSubDoc(context, state, subdoc, cell_ele, &dx, &dy);
  3748.  
  3749.         lo_cleanup_old_state(subdoc->state);
  3750.         base_x = cell_ele->x + cell_ele->x_offset + cell_ele->border_width;
  3751.         base_y = cell_ele->y + cell_ele->y_offset + cell_ele->border_width;
  3752.         dx -= base_x;
  3753.         dy -= base_y;
  3754.         cell_ptr->cell_base_x = dx;
  3755.         cell_ptr->cell_base_y = dy;
  3756.     }
  3757.  
  3758.     XP_ASSERT ( cell_ele != NULL );
  3759.  
  3760.     old_state->must_relayout_subdoc = FALSE;
  3761.  
  3762.     state->top_state->force_reload = save_force;
  3763.  
  3764.     /* pop the style stack once to get rid of the extra dummy tag
  3765.      * that we added to the stack to force styles on the begin
  3766.      * subdoc in relayout
  3767.      */
  3768.     if (relayout == FALSE)
  3769.     {
  3770.         LO_PopStyleTagByIndex(context, &state, P_TABLE_DATA, 0);
  3771.     }
  3772.  
  3773.     return(cell_ele);
  3774. }
  3775.  
  3776. /*
  3777.  * if normal borders is TRUE draw cell borders if the rest of
  3778.  * the table has borders.  If FALSE, never draw cell borders
  3779.  */
  3780. void
  3781. lo_BeginTableCellAttributes(MWContext *context, 
  3782.                              lo_DocState *state, 
  3783.                              lo_TableRec *table,
  3784.                              char * colspan_attr,
  3785.                             char * rowspan_attr,
  3786.                              char * nowrap_attr,
  3787.                              char * bgcolor_attr,
  3788.                              char * background_attr,
  3789.                             lo_TileMode tile_mode,
  3790.                              char * valign_attr,
  3791.                              char * halign_attr,
  3792.                               char * width_attr,
  3793.                             char * height_attr,
  3794.                             Bool is_a_header,
  3795.                             Bool normal_borders)
  3796. {
  3797.     lo_TableRow *table_row;
  3798.     lo_TableCell *table_cell;
  3799.     int32 val;
  3800. #ifdef LOCAL_DEBUG
  3801.  fprintf(stderr, "lo_BeginTableCell called\n");
  3802. #endif /* LOCAL_DEBUG */
  3803.  
  3804.     table_row = table->row_ptr;
  3805.  
  3806.     table_cell = XP_NEW(lo_TableCell);
  3807.     if (table_cell == NULL)
  3808.     {
  3809.         return;
  3810.     }
  3811.  
  3812.     if (state->is_a_subdoc != SUBDOC_NOT) 
  3813.     {
  3814.         table_cell->in_nested_table = TRUE;
  3815.     }
  3816.     else 
  3817.     {
  3818.         table_cell->in_nested_table = FALSE;
  3819.     }    
  3820.  
  3821.     /* Copied to lo_InitForBeginCell()
  3822.     table_cell->must_relayout = FALSE;
  3823.     */
  3824.     table_cell->subdoc_tags = NULL;
  3825.     table_cell->subdoc_tags_end = NULL;
  3826.  
  3827.     /* Copied to lo_InitForBeginCell()
  3828.     table_cell->cell_done = FALSE;
  3829.     */
  3830.     table_cell->nowrap = FALSE;
  3831.     table_cell->is_a_header = is_a_header;
  3832.     table_cell->percent_width = 0;
  3833.     table_cell->percent_height = 0;
  3834.     table_cell->specified_width = 0;
  3835.     table_cell->specified_height = 0;
  3836.     table_cell->min_width = 0;
  3837.     table_cell->max_width = 0;
  3838.     table_cell->height = 0;
  3839.     table_cell->baseline = 0;
  3840.     table_cell->rowspan = 1;
  3841.     table_cell->colspan = 1;
  3842.     table_cell->cell = NULL;
  3843.     table_cell->next = NULL;
  3844.     table_cell->beginning_tag_count = state->top_state->tag_count;
  3845.  
  3846.     lo_InitForBeginCell( table_row, table_cell );
  3847.     
  3848.     if (table->current_subdoc == NULL)
  3849.     {
  3850.         XP_DELETE(table_cell);
  3851.         return;
  3852.     }
  3853.  
  3854.     if (colspan_attr)
  3855.     {
  3856.         val = XP_ATOI(colspan_attr);
  3857.         if (val < 1)
  3858.         {
  3859.             val = 1;
  3860.         }
  3861.         /*
  3862.          * Prevent huge colspan
  3863.          */
  3864.         if (val > TABLE_MAX_COLSPAN)
  3865.         {
  3866.             val = TABLE_MAX_COLSPAN;
  3867.         }
  3868.         table_cell->colspan = val;
  3869.     }
  3870.  
  3871.     if (rowspan_attr)
  3872.     {
  3873.         val = XP_ATOI(rowspan_attr);
  3874.         if (val < 1)
  3875.         {
  3876.             val = 1;
  3877.         }
  3878.         /*
  3879.          * Prevent huge rowspan
  3880.          */
  3881.         if (val > TABLE_MAX_ROWSPAN)
  3882.         {
  3883.             val = TABLE_MAX_ROWSPAN;
  3884.         }
  3885.         table_cell->rowspan = val;
  3886.     }
  3887.  
  3888.     if (nowrap_attr)
  3889.     {
  3890.         table_cell->nowrap = TRUE;
  3891.     }
  3892.  
  3893.     /* Copied to lo_InitForBeginCell()
  3894.     if (table_row->cell_list == NULL)
  3895.     {
  3896.         table_row->cell_list = table_cell;
  3897.         table_row->cell_ptr = table_cell;
  3898.     }
  3899.     else
  3900.     {
  3901.         table_row->cell_ptr->next = table_cell;
  3902.         table_row->cell_ptr = table_cell;
  3903.     }
  3904.     */
  3905.  
  3906.     lo_BeginCellSubDoc(context, 
  3907.                         state, 
  3908.                         table,
  3909.                         bgcolor_attr,
  3910.                         background_attr,
  3911.                         tile_mode,
  3912.                         valign_attr,
  3913.                         halign_attr,
  3914.                         width_attr,
  3915.                         height_attr,
  3916.                          is_a_header, 
  3917.                         normal_borders ? table->draw_borders : 0,
  3918.                         FALSE);
  3919.  
  3920.     /*
  3921.      * We added a new state.
  3922.      */
  3923.     lo_PushStateLevel ( context );
  3924. }
  3925.  
  3926.  
  3927. void
  3928. lo_BeginTableCell(MWContext *context, lo_DocState *state, lo_TableRec *table,
  3929.     PA_Tag *tag, Bool is_a_header)
  3930. {
  3931.     char *colspan_attr = (char*)lo_FetchParamValue(context, tag, PARAM_COLSPAN);
  3932.     char *rowspan_attr = (char*)lo_FetchParamValue(context, tag, PARAM_ROWSPAN);
  3933.     char *nowrap_attr  = (char*)lo_FetchParamValue(context, tag, PARAM_NOWRAP);
  3934.     char *bgcolor_attr = (char*)lo_FetchParamValue(context, tag, PARAM_BGCOLOR);
  3935.     char *background_attr= (char*)lo_FetchParamValue(context, tag, PARAM_BACKGROUND);
  3936.     char *valign_attr  = (char*)lo_FetchParamValue(context, tag, PARAM_VALIGN);
  3937.     char *halign_attr  = (char*)lo_FetchParamValue(context, tag, PARAM_ALIGN);
  3938.     char *width_attr   = (char*)lo_FetchParamValue(context, tag, PARAM_WIDTH);
  3939.     char *height_attr  = (char*)lo_FetchParamValue(context, tag, PARAM_HEIGHT);
  3940.  
  3941.     /* remove the PA_LOCK stuff */
  3942.  
  3943.     lo_BeginTableCellAttributes(context, 
  3944.                                 state, 
  3945.                                 table,
  3946.                                 colspan_attr,
  3947.                                 rowspan_attr,
  3948.                                 nowrap_attr,
  3949.                                 bgcolor_attr,
  3950.                                 background_attr,
  3951.                                 LO_TILE_BOTH, /* Default backdrop tile mode */
  3952.                                 valign_attr,
  3953.                                 halign_attr,
  3954.                                 width_attr,
  3955.                                 height_attr,
  3956.                                 is_a_header,
  3957.                                 TRUE);
  3958.  
  3959.     if(colspan_attr)
  3960.         PA_FREE(colspan_attr);
  3961.     if(rowspan_attr)
  3962.         PA_FREE(rowspan_attr);
  3963.     if(nowrap_attr)
  3964.         PA_FREE(nowrap_attr);
  3965.     if(bgcolor_attr)
  3966.         PA_FREE(bgcolor_attr);
  3967.     if(background_attr)
  3968.         PA_FREE(background_attr);
  3969.     if(valign_attr)
  3970.         PA_FREE(valign_attr);
  3971.     if(halign_attr)
  3972.         PA_FREE(halign_attr);
  3973.     if(width_attr)
  3974.         PA_FREE(width_attr);
  3975.     if(height_attr)
  3976.         PA_FREE(height_attr);
  3977. }
  3978.  
  3979.  
  3980. void
  3981. lo_EndTableCell(MWContext *context, lo_DocState *state, Bool relayout )
  3982. {
  3983.     LO_SubDocStruct *subdoc;
  3984.     LO_CellStruct *cell_ele;
  3985.     lo_TableRec *table;
  3986.     lo_TableRow *table_row;
  3987.     lo_TableCell *table_cell;
  3988.     lo_table_span *span_rec;
  3989.     int32 top_inner_pad;
  3990.     int32 bottom_inner_pad;
  3991.     int32 left_inner_pad;
  3992.     int32 right_inner_pad;
  3993.     int32 i;
  3994.     lo_TopState *top_state;
  3995.     lo_DocState *old_state;
  3996.     int32 doc_id;
  3997. #ifdef LOCAL_DEBUG
  3998.  fprintf(stderr, "lo_EndTableCell called\n");
  3999. #endif /* LOCAL_DEBUG */
  4000.  
  4001.     /*
  4002.      * makes sure we are at the bottom
  4003.      * of everything in the document.
  4004.      */
  4005.     if (relayout == FALSE) 
  4006.     {
  4007.         lo_CloseOutLayout(context, state);
  4008.     }
  4009.     else
  4010.     {
  4011.         lo_EndLayoutDuringReflow( context, state );
  4012.     }
  4013.  
  4014.     old_state = state;
  4015.     /*
  4016.      * Get the unique document ID, and retrieve this
  4017.      * documents layout state.
  4018.      */
  4019.     doc_id = XP_DOCID(context);
  4020.     top_state = lo_FetchTopState(doc_id);
  4021.     state = top_state->doc_state;
  4022.  
  4023.     while ((state->sub_state != NULL)&&
  4024.         (state->sub_state != old_state))
  4025.     {
  4026.         state = state->sub_state;
  4027.     }
  4028.  
  4029.     subdoc = NULL;
  4030.     cell_ele = NULL;
  4031.     if ((state != old_state)&&
  4032.         (state->current_ele != NULL))
  4033.     {
  4034.         subdoc = lo_EndCellSubDoc(context, state,
  4035.                 old_state, state->current_ele, relayout);
  4036.         state->sub_state = NULL;
  4037.         state->current_ele = NULL;
  4038.         if ((state->is_a_subdoc == SUBDOC_CELL)||
  4039.             (state->is_a_subdoc == SUBDOC_CAPTION))
  4040.         {
  4041.             if (old_state->subdoc_tags_end != NULL)
  4042.             {
  4043.                 state->subdoc_tags_end =
  4044.                     old_state->subdoc_tags_end;
  4045.             }
  4046.         }
  4047.         else
  4048.         {
  4049.         }
  4050.     }
  4051.  
  4052.     /*
  4053.      * We popped a state level.
  4054.      */
  4055.     lo_PopStateLevel ( context );
  4056.  
  4057.     table = state->current_table;
  4058.     table_row = table->row_ptr;
  4059.     table_cell = table_row->cell_ptr;
  4060.     
  4061.     top_inner_pad = FEUNITS_X(table->inner_top_pad, context);
  4062.     bottom_inner_pad = FEUNITS_X(table->inner_bottom_pad, context);
  4063.     left_inner_pad = FEUNITS_X(table->inner_left_pad, context);
  4064.     right_inner_pad = FEUNITS_X(table->inner_right_pad, context);
  4065.  
  4066.     if (subdoc != NULL)
  4067.     {
  4068.         int32 subdoc_width;
  4069.         int32 subdoc_height;
  4070.         int32 min_cellwidth;
  4071.         int32 base_x, base_y;
  4072.         int32 dx, dy;
  4073.         int32 cell_internal_width;
  4074.         lo_DocState *subdoc_state;
  4075.         Bool reset_min_width;
  4076.         
  4077.         reset_min_width = FALSE;
  4078.         
  4079.         cell_internal_width = old_state->max_width;
  4080.         
  4081.         /* how big do we think this cell should be? */
  4082.         min_cellwidth = old_state->min_width;
  4083.  
  4084.         /*
  4085.         * If the cell is smaller than this, we need to grow it so that
  4086.         * any internal elements don't overwrite the cell borders.
  4087.         */
  4088.         if (subdoc->width < min_cellwidth)
  4089.         {
  4090.             /*
  4091.             * We need to lay things out again as we now have more space.
  4092.             * Do we want to be smart and see if we contain things that
  4093.             * will change?
  4094.              * Be sure to add in the width of the borders as later code expects it
  4095.             */
  4096.             subdoc->width = min_cellwidth + (2 * subdoc->border_width);
  4097.             old_state->must_relayout_subdoc = TRUE;
  4098.             
  4099.             cell_internal_width = min_cellwidth;
  4100.         }
  4101.  
  4102.         subdoc_width = subdoc->width +
  4103.             (2 * subdoc->border_horiz_space) +
  4104.             (left_inner_pad + right_inner_pad);
  4105.         subdoc_height = subdoc->height +
  4106.             (2 * subdoc->border_vert_space) +
  4107.             (top_inner_pad + bottom_inner_pad);
  4108.         table_cell->max_width = subdoc_width;
  4109.         table_cell->min_width = old_state->min_width +
  4110.             (2 * subdoc->border_width) +
  4111.             (2 * subdoc->border_horiz_space) +
  4112.             (left_inner_pad + right_inner_pad);
  4113.  
  4114.         /*
  4115.          * This is some nasty logic. We need to reset the min_width
  4116.          * of the cell in cases where we're certain about how large
  4117.          * the cell is.
  4118.          */
  4119.         if ( (table_cell->min_width < table_cell->max_width) )
  4120.         {
  4121.             /*
  4122.              * If we're a fixed width cell and fixed layout (COLS) is on.
  4123.              * BRAIN DAMAGE: It's arguable that we should always do this - a width for
  4124.              * the cell was specified, we should respect it. However, certain popular
  4125.              * sites don't look too good if we do...
  4126.              */
  4127.             if ( (table_cell->specified_width > 0) &&
  4128.                  (table_cell->percent_width == 0) &&
  4129.                  (table->fixed_cols > 0) )
  4130.             {
  4131.                 reset_min_width = TRUE;
  4132.             }
  4133.             else
  4134.             /*
  4135.              * If we're in a fixed width table who's width does not
  4136.              * depend on it's parent and are using fixed layout (COLS).
  4137.              */
  4138.             if ( (table->fixed_cols > 0) &&
  4139.                  (table->table_width_fixed != FALSE) )
  4140.             {
  4141.                 reset_min_width = TRUE;
  4142.             }
  4143.         }
  4144.         
  4145.         /*
  4146.          * If nowrap is on or min_width ended up being bigger than
  4147.          * max_width
  4148.          */
  4149.         if ((table_cell->nowrap != FALSE)||
  4150.             (table_cell->min_width > table_cell->max_width))
  4151.         {
  4152.             reset_min_width = TRUE;
  4153.         }
  4154.         
  4155.         if ( reset_min_width != FALSE )
  4156.         {
  4157.             table_cell->min_width = table_cell->max_width;
  4158.         }
  4159.  
  4160.         /*
  4161.          * If we're in the fixed layout case, then we may need to grow this
  4162.          * column to fit this new cell width. This will allow any subsequent
  4163.          * columns to be layed out to the correct size and not have to be
  4164.          * relayed out.
  4165.          */
  4166.         if ( table->fixed_cols > 0 )
  4167.         {
  4168.             lo_SetDefaultCellWidth( context, table, subdoc, table_cell, cell_internal_width );
  4169.         }
  4170.                 
  4171.         table_cell->height = subdoc_height;
  4172.         table_cell->baseline = lo_GetSubDocBaseline(subdoc);
  4173.  
  4174.         subdoc_state = (lo_DocState *)(subdoc->state);
  4175.         table_cell->start_in_form = subdoc_state->start_in_form;
  4176.         table_cell->form_id = subdoc_state->form_id;
  4177.         table_cell->form_ele_cnt = subdoc_state->form_ele_cnt;
  4178.         table_cell->form_data_index = subdoc_state->form_data_index;
  4179.         table_cell->embed_count_base = subdoc_state->embed_count_base;
  4180.         table_cell->url_count_base = subdoc_state->url_count_base;
  4181.         table_cell->image_list_count_base = subdoc_state->image_list_count_base;
  4182.         table_cell->applet_list_count_base = subdoc_state->applet_list_count_base;
  4183.         table_cell->embed_list_count_base = subdoc_state->embed_list_count_base;
  4184.  
  4185.         table_cell->current_layer_num_base = subdoc_state->current_layer_num_base;
  4186.         table_cell->must_relayout = subdoc_state->must_relayout_subdoc;
  4187.         table_cell->is_a_subdoc = subdoc_state->is_a_subdoc;
  4188.         if (relayout == FALSE)
  4189.         {
  4190.             table_cell->subdoc_tags = subdoc_state->subdoc_tags;
  4191.             table_cell->subdoc_tags_end = subdoc_state->subdoc_tags_end;
  4192.         }
  4193.         subdoc_state->subdoc_tags = NULL;
  4194.         subdoc_state->subdoc_tags_end = NULL;
  4195.         table_cell->max_y = subdoc_state->y;
  4196.         table_cell->horiz_alignment = subdoc->horiz_alignment;
  4197.         table_cell->vert_alignment = subdoc->vert_alignment;
  4198.  
  4199.         if (relayout == FALSE)
  4200.         {
  4201.             cell_ele = lo_SmallSquishSubDocToCell(context, state, subdoc,
  4202.                 &dx, &dy);
  4203.             /* Keep ptr. back to table state structs for relayout */
  4204.             cell_ele->table_cell = table_cell;
  4205.             cell_ele->table_row = table_row;
  4206.             cell_ele->table = table;
  4207.         }
  4208.         else 
  4209.         {
  4210.             cell_ele = table_cell->cell;
  4211.             lo_CreateCellFromSubDoc(context, state, subdoc, cell_ele, &dx, &dy);
  4212.         }
  4213.  
  4214.         lo_cleanup_old_state(subdoc->state);
  4215.         base_x = cell_ele->x + cell_ele->x_offset + cell_ele->border_width;
  4216.         base_y = cell_ele->y + cell_ele->y_offset + cell_ele->border_width;
  4217.         dx -= base_x;
  4218.         dy -= base_y;
  4219.         table_cell->cell_base_x = dx;
  4220.         table_cell->cell_base_y = dy;
  4221.     }
  4222.  
  4223.     table_cell->cell = cell_ele;
  4224.     table_cell->cell_done = TRUE;
  4225.  
  4226.     i = 0;
  4227.     while (i < table_cell->colspan)
  4228.     {
  4229.  
  4230.         if ((table->width_spans == NULL)||
  4231.             ((table->width_span_ptr != NULL)&&
  4232.              (table->width_span_ptr->next == NULL)))
  4233.         {
  4234.             span_rec = XP_NEW(lo_table_span);
  4235.             if (span_rec == NULL)
  4236.             {
  4237.                 return;
  4238.             }
  4239.             span_rec->dim = 1;
  4240.             span_rec->min_dim = 1;
  4241.             span_rec->span = 0;
  4242.             span_rec->next = NULL;
  4243.  
  4244.             if (table->width_spans == NULL)
  4245.             {
  4246.                 table->width_spans = span_rec;
  4247.                 table->width_span_ptr = span_rec;
  4248.             }
  4249.             else
  4250.             {
  4251.                 table->width_span_ptr->next = span_rec;
  4252.                 table->width_span_ptr = span_rec;
  4253.             }
  4254.         }
  4255.         else
  4256.         {
  4257.             if (table->width_span_ptr == NULL)
  4258.             {
  4259.                 table->width_span_ptr = table->width_spans;
  4260.             }
  4261.             else
  4262.             {
  4263.                 table->width_span_ptr =
  4264.                     table->width_span_ptr->next;
  4265.             }
  4266.             span_rec = table->width_span_ptr;
  4267.         }
  4268.  
  4269.         if (span_rec->span > 0)
  4270.         {
  4271.             span_rec->span--;
  4272.             table_row->cells++;
  4273.  
  4274.             /*
  4275.              * This only happens if a colspan on this
  4276.              * row overlaps a rowspan from a previous row.
  4277.              */
  4278.             if (i > 0)
  4279.             {
  4280.                 int32 new_span;
  4281.  
  4282.                 new_span = table_cell->rowspan - 1;
  4283.                 if (new_span > span_rec->span)
  4284.                 {
  4285.                     span_rec->span = new_span;
  4286.                 }
  4287.                 i++;
  4288.                 /*
  4289.                  * Don't count this cell twice.
  4290.                  */
  4291.                 table_row->cells--;
  4292.             }
  4293.             continue;
  4294.         }
  4295.         else
  4296.         {
  4297.             span_rec->span = table_cell->rowspan - 1;
  4298.             i++;
  4299.             if (table_cell->colspan == 1)
  4300.             {
  4301.                 if (table_cell->max_width > span_rec->dim)
  4302.                 {
  4303.                     span_rec->dim = table_cell->max_width;
  4304.                 }
  4305.                 if (table_cell->min_width > span_rec->min_dim)
  4306.                 {
  4307.                     span_rec->min_dim = table_cell->min_width;
  4308.                 }
  4309.             }
  4310.         }
  4311.     }
  4312.  
  4313.     span_rec = table->height_span_ptr;
  4314.     if (table_cell->rowspan == 1)
  4315.     {
  4316.         int32 tmp_val;
  4317.  
  4318.         /*
  4319.          * If the user specified a height for the cell,
  4320.          * that becomes our min height.
  4321.          */
  4322.         if ((table_cell->specified_height > 0)&&
  4323.             (table_cell->specified_height > span_rec->min_dim))
  4324.         {
  4325.             span_rec->min_dim = table_cell->specified_height;
  4326.         }
  4327.  
  4328.         tmp_val = table_cell->baseline - span_rec->min_dim;
  4329.         if (tmp_val > 0)
  4330.         {
  4331.             span_rec->min_dim += tmp_val;
  4332.             if (table_row->vert_alignment == LO_ALIGN_BASELINE)
  4333.             {
  4334.                 span_rec->dim += tmp_val;
  4335.             }
  4336.         }
  4337.  
  4338.         if (table_row->vert_alignment == LO_ALIGN_BASELINE)
  4339.         {
  4340.             tmp_val = (table_cell->height - table_cell->baseline) -
  4341.                 (span_rec->dim - span_rec->min_dim);
  4342.             if (tmp_val > 0)
  4343.             {
  4344.                 span_rec->dim += tmp_val;
  4345.             }
  4346.         }
  4347.         else
  4348.         {
  4349.             if (table_cell->height > span_rec->dim)
  4350.             {
  4351.                 span_rec->dim = table_cell->height;
  4352.             }
  4353.         }
  4354.     }
  4355.  
  4356.     table_row->cells += table_cell->colspan;
  4357. }
  4358.  
  4359.  
  4360. void
  4361. lo_BeginTableCaption(MWContext *context, lo_DocState *state, lo_TableRec *table,
  4362.     PA_Tag *tag)
  4363. {
  4364.     lo_TableCaption *caption;
  4365.     PA_Block buff;
  4366.     char *str;
  4367.  
  4368.     caption = XP_NEW(lo_TableCaption);
  4369.     if (caption == NULL)
  4370.     {
  4371.         return;
  4372.     }
  4373.  
  4374.     caption->vert_alignment = LO_ALIGN_TOP;
  4375.     caption->horiz_alignment = LO_ALIGN_CENTER;
  4376.     caption->min_width = 0;
  4377.     caption->max_width = 0;
  4378.     caption->height = 0;
  4379.     caption->subdoc = NULL;
  4380.     caption->cell_ele = NULL;
  4381.  
  4382.     /*
  4383.      * Check for an align parameter
  4384.       */
  4385.     buff = lo_FetchParamValue(context, tag, PARAM_ALIGN);
  4386.     if (buff != NULL)
  4387.     {
  4388.         PA_LOCK(str, char *, buff);
  4389.         if (pa_TagEqual("bottom", str))
  4390.         {
  4391.             caption->vert_alignment = LO_ALIGN_BOTTOM;
  4392.         }
  4393.         PA_UNLOCK(buff);
  4394.         PA_FREE(buff);
  4395.     }
  4396.  
  4397.     table->caption = caption;
  4398.  
  4399.     lo_BeginCaptionSubDoc(context, state, caption, tag);
  4400. }
  4401.  
  4402.  
  4403. void
  4404. lo_EndTableCaption(MWContext *context, lo_DocState *state)
  4405. {
  4406.     LO_SubDocStruct *subdoc;
  4407.     lo_TableRec *table;
  4408.     lo_TableCaption *caption;
  4409.     lo_TopState *top_state;
  4410.     lo_DocState *old_state;
  4411.     int32 doc_id;
  4412.     int32 top_inner_pad;
  4413.     int32 bottom_inner_pad;
  4414.     int32 left_inner_pad;
  4415.     int32 right_inner_pad;
  4416.  
  4417.     /*
  4418.      * makes sure we are at the bottom
  4419.      * of everything in the document.
  4420.      */
  4421.     lo_CloseOutLayout(context, state);
  4422.  
  4423.     old_state = state;
  4424.     /*
  4425.      * Get the unique document ID, and retreive this
  4426.      * documents layout state.
  4427.      */
  4428.     doc_id = XP_DOCID(context);
  4429.     top_state = lo_FetchTopState(doc_id);
  4430.     state = top_state->doc_state;
  4431.  
  4432.     while ((state->sub_state != NULL)&&
  4433.         (state->sub_state != old_state))
  4434.     {
  4435.         state = state->sub_state;
  4436.     }
  4437.  
  4438.     subdoc = NULL;
  4439.     if ((state != old_state)&&
  4440.         (state->current_ele != NULL))
  4441.     {
  4442.         subdoc = lo_EndCellSubDoc(context, state,
  4443.                 old_state, state->current_ele, FALSE);
  4444.         state->sub_state = NULL;
  4445.         state->current_ele = NULL;
  4446.         if ((state->is_a_subdoc == SUBDOC_CELL)||
  4447.             (state->is_a_subdoc == SUBDOC_CAPTION))
  4448.         {
  4449.             if (old_state->subdoc_tags_end != NULL)
  4450.             {
  4451.                 state->subdoc_tags_end =
  4452.                     old_state->subdoc_tags_end;
  4453.             }
  4454.         }
  4455.     }
  4456.  
  4457.     table = state->current_table;
  4458.     caption = table->caption;
  4459.  
  4460.     top_inner_pad = FEUNITS_X(table->inner_top_pad, context);
  4461.     bottom_inner_pad = FEUNITS_X(table->inner_bottom_pad, context);
  4462.     left_inner_pad = FEUNITS_X(table->inner_left_pad, context);
  4463.     right_inner_pad = FEUNITS_X(table->inner_right_pad, context);
  4464.  
  4465.     if (subdoc != NULL)
  4466.     {
  4467.         int32 subdoc_width;
  4468.         int32 subdoc_height;
  4469.  
  4470.         subdoc_width = subdoc->width +
  4471.             (2 * subdoc->border_horiz_space) +
  4472.             (left_inner_pad + right_inner_pad);
  4473.         subdoc_height = subdoc->height +
  4474.             (2 * subdoc->border_vert_space) + 
  4475.             (top_inner_pad + bottom_inner_pad);
  4476.         caption->max_width = subdoc_width;
  4477.         caption->min_width = old_state->min_width +
  4478.             (2 * subdoc->border_width) +
  4479.             (2 * subdoc->border_horiz_space) +
  4480.             (left_inner_pad + right_inner_pad);
  4481.         if (caption->min_width > caption->max_width)
  4482.         {
  4483.             caption->min_width = caption->max_width;
  4484.         }
  4485.         caption->height = subdoc_height;
  4486.     }
  4487.  
  4488.     caption->subdoc = subdoc;
  4489.  
  4490.     /* If the caption is empty, free the memory used by it */
  4491.     if (lo_subdoc_has_elements(caption->subdoc->state) == FALSE)
  4492.     {
  4493.         lo_FreeTableCaption( context, state, table );
  4494.     }
  4495.     
  4496.     /*
  4497.      * We popped a state level.
  4498.      */
  4499.     lo_PopStateLevel ( context );
  4500. }
  4501.  
  4502.  
  4503. void
  4504. lo_BeginTableRowAttributes(MWContext *context, 
  4505.                              lo_DocState *state, 
  4506.                              lo_TableRec *table,
  4507.                              char *bgcolor_attr,
  4508.                             char *background_attr,
  4509.                              char *valign_attr,
  4510.                              char *halign_attr)
  4511. {
  4512.     lo_TableRow *table_row;
  4513.     lo_table_span *span_rec;
  4514.     char *bgcolor_from_style=NULL;
  4515. #ifdef LOCAL_DEBUG
  4516.  fprintf(stderr, "lo_BeginTableRow called\n");
  4517. #endif /* LOCAL_DEBUG */
  4518.  
  4519.     table_row = XP_NEW(lo_TableRow);
  4520.     if (table_row == NULL)
  4521.     {
  4522.         return;
  4523.     }
  4524.  
  4525.     /* copied to lo_UpdateTableStateForBeginRow()
  4526.     table_row->row_done = FALSE; 
  4527.     */
  4528.     table_row->has_percent_width_cells = FALSE;
  4529.     table_row->backdrop.bg_color = NULL;
  4530.     table_row->backdrop.url = NULL;
  4531.     table_row->backdrop.tile_mode = LO_TILE_BOTH;
  4532.     /* copied to lo_UpdateTableStateForBeginRow()
  4533.     table_row->cells = 0;
  4534.     */
  4535.     table_row->vert_alignment = LO_ALIGN_DEFAULT;
  4536.     table_row->horiz_alignment = LO_ALIGN_DEFAULT;
  4537.  
  4538.     /* copied to lo_UpdateTableStateForBeginRow()
  4539.     table_row->cell_list = NULL;
  4540.     table_row->cell_ptr = NULL;
  4541.     */
  4542.     table_row->next = NULL;
  4543.     
  4544.     
  4545.     lo_UpdateTableStateForBeginRow( table, table_row );
  4546.  
  4547.     /* check for style sheet color and override if necessary */
  4548.     if(state->top_state && state->top_state->style_stack)
  4549.     {
  4550.         StyleStruct *style_struct;
  4551.  
  4552.         style_struct = STYLESTACK_GetStyleByIndex(
  4553.                                             state->top_state->style_stack,
  4554.                                             0);
  4555.  
  4556.         if(style_struct)
  4557.         {
  4558.             bgcolor_from_style = STYLESTRUCT_GetString(style_struct, BG_COLOR_STYLE);
  4559.  
  4560.             if(bgcolor_from_style)
  4561.             {
  4562.                 bgcolor_attr = bgcolor_from_style;
  4563.             }
  4564.         }
  4565.     }
  4566.  
  4567.     /*
  4568.      * Check for a background color attribute
  4569.      */
  4570.     if (bgcolor_attr)
  4571.     {
  4572.         uint8 red, green, blue;
  4573.         XP_Bool rv;
  4574.  
  4575.         if(bgcolor_from_style)
  4576.             rv = LO_ParseStyleSheetRGB(bgcolor_attr, &red, &green, &blue);
  4577.         else
  4578.             rv = LO_ParseRGB(bgcolor_attr, &red, &green, &blue);
  4579.  
  4580.         if(rv)
  4581.         {
  4582.             table_row->backdrop.bg_color = XP_NEW(LO_Color);
  4583.             if (table_row->backdrop.bg_color != NULL)
  4584.             {
  4585.                 table_row->backdrop.bg_color->red = red;
  4586.                 table_row->backdrop.bg_color->green = green;
  4587.                 table_row->backdrop.bg_color->blue = blue;
  4588.             }
  4589.         }
  4590.     }
  4591.  
  4592.     if (background_attr)
  4593.         table_row->backdrop.url = XP_STRDUP(background_attr);
  4594.  
  4595.     XP_FREEIF(bgcolor_from_style);
  4596.  
  4597.  
  4598.     /*
  4599.      * Check for a vertical align parameter
  4600.      */
  4601.     if (valign_attr)
  4602.     {
  4603.         table_row->vert_alignment = lo_EvalVAlignParam(valign_attr);
  4604.     }
  4605.  
  4606.     /*
  4607.      * Check for a horizontal align parameter
  4608.      */
  4609.     if (halign_attr)
  4610.     {
  4611.         table_row->horiz_alignment = lo_EvalCellAlignParam(halign_attr);
  4612.     }
  4613.  
  4614.     
  4615.     if (table->row_list == NULL)
  4616.     {
  4617.         table->row_list = table_row;
  4618.         table->row_ptr = table_row;
  4619.     }
  4620.     else
  4621.     {
  4622.         table->row_ptr->next = table_row;
  4623.         table->row_ptr = table_row;
  4624.     }
  4625.  
  4626.     /* copied to lo_UpdateTableStateForBeginRow()
  4627.     table->width_span_ptr = NULL;
  4628.     */
  4629.  
  4630.     span_rec = XP_NEW(lo_table_span);
  4631.     if (span_rec == NULL)
  4632.     {
  4633.         return;
  4634.     }
  4635.     
  4636.     if (table->height_spans == NULL)
  4637.     {
  4638.         table->height_spans = span_rec;
  4639.         table->height_span_ptr = span_rec;
  4640.     }
  4641.     else
  4642.     {
  4643.         table->height_span_ptr->next = span_rec;
  4644.         table->height_span_ptr = span_rec;
  4645.     }
  4646.  
  4647.     span_rec->dim = 1;
  4648.     /*
  4649.      * Since min_dim on the heights is never used.
  4650.      * I am appropriating it to do baseline aligning.  It will
  4651.      * start as 0, and eventually be the amount of baseline needed
  4652.      * to align all these cells in this row
  4653.      * by their baselines.
  4654.      */
  4655.     span_rec->min_dim = 0;
  4656.     span_rec->span = 0;
  4657.     span_rec->next = NULL;
  4658. }
  4659.  
  4660.  
  4661. void
  4662. lo_BeginTableRow(MWContext *context, lo_DocState *state, lo_TableRec *table,
  4663.     PA_Tag *tag)
  4664. {
  4665.     char *bgcolor_attr = (char*)lo_FetchParamValue(context, tag, PARAM_BGCOLOR);
  4666.     char *background_attr = (char*)lo_FetchParamValue(context, tag, PARAM_BACKGROUND);
  4667.     char *valign_attr  = (char*)lo_FetchParamValue(context, tag, PARAM_VALIGN);
  4668.     char *halign_attr  = (char*)lo_FetchParamValue(context, tag, PARAM_ALIGN);
  4669.  
  4670.     /* remove the PA_LOCK stuff */
  4671.  
  4672.     lo_BeginTableRowAttributes(context,
  4673.                                 state, 
  4674.                                 table,
  4675.                                 bgcolor_attr,
  4676.                                 background_attr,
  4677.                                 valign_attr,
  4678.                                 halign_attr);
  4679.  
  4680.     if(bgcolor_attr)
  4681.         PA_FREE(bgcolor_attr);
  4682.     if(valign_attr)
  4683.         PA_FREE(valign_attr);
  4684.     if(halign_attr)
  4685.         PA_FREE(halign_attr);
  4686. }
  4687.  
  4688.  
  4689. void
  4690. lo_EndTableRow(MWContext *context, lo_DocState *state, lo_TableRec *table)
  4691. {
  4692.     lo_TableRow *table_row;
  4693. #ifdef LOCAL_DEBUG
  4694.  fprintf(stderr, "lo_EndTableRow called\n");
  4695. #endif /* LOCAL_DEBUG */
  4696.  
  4697.     table_row = table->row_ptr;
  4698.     table_row->row_done = TRUE;
  4699.     table->rows++;
  4700.  
  4701.     while (table->width_span_ptr != NULL)
  4702.     {
  4703.         table->width_span_ptr = table->width_span_ptr->next;
  4704.         if (table->width_span_ptr != NULL)
  4705.         {
  4706.             table->width_span_ptr->span--;
  4707.             table_row->cells++;
  4708.         }
  4709.     }
  4710.  
  4711.     if (table_row->cells > table->cols)
  4712.     {
  4713.         table->cols = table_row->cells;
  4714.     }
  4715.     
  4716.     /*
  4717.      * We've hit the end of a row, if it's the first row and
  4718.      * we haven't allocated all columns yet and table width
  4719.      * is remaining, then set their size now.
  4720.      */
  4721.     if ( table->fixed_width_remaining > 0 )
  4722.     {
  4723.         if ( (table_row->cells < table->fixed_cols) && (table->fixed_col_widths != NULL) )
  4724.         {
  4725.             int32 count;
  4726.             int32 colwidth;
  4727.             int32 cell_extra_space;
  4728.             int32 left_inner_pad;
  4729.             int32 right_inner_pad;
  4730.             
  4731.             /* how much border/pad space do we need per cell */
  4732.             if (table->draw_borders == TABLE_BORDERS_OFF)
  4733.             {
  4734.                 cell_extra_space = 2 * TABLE_DEF_CELL_BORDER;
  4735.             }
  4736.             else if (table->draw_borders == TABLE_BORDERS_ON)
  4737.             {
  4738.                 cell_extra_space = 2 * TABLE_DEF_CELL_BORDER;
  4739.             }
  4740.             else
  4741.             {
  4742.                 cell_extra_space = 0;
  4743.             }
  4744.             
  4745.             left_inner_pad = FEUNITS_X(table->inner_left_pad, context);
  4746.             right_inner_pad = FEUNITS_X(table->inner_right_pad, context);
  4747.             cell_extra_space += left_inner_pad + right_inner_pad;
  4748.             
  4749.             /* divide space up to the remaining cols */
  4750.             colwidth = ( table->fixed_width_remaining / 
  4751.                 ( table->fixed_cols - table_row->cells )) - cell_extra_space;
  4752.             
  4753.             if ( colwidth < 0 )
  4754.             {
  4755.                 colwidth = 0;
  4756.             }
  4757.             
  4758.             for ( count = table_row->cells; count < table->fixed_cols; ++count )
  4759.             {
  4760.                 table->fixed_col_widths[ count ] = colwidth;
  4761.                 table->fixed_width_remaining -= colwidth;
  4762.             }
  4763.             
  4764.             /* add any leftover space to the last row */
  4765.             table->fixed_col_widths[ table->fixed_cols - 1 ] += 
  4766.                 table->fixed_width_remaining;
  4767.         }
  4768.         table->fixed_width_remaining = 0;
  4769.     }
  4770. }
  4771.  
  4772. void
  4773. lo_BeginTableAttributes(MWContext *context, 
  4774.                         lo_DocState *state, 
  4775.                         char *align_attr,
  4776.                         char *border_attr,
  4777.                         char *border_top_attr,
  4778.                         char *border_bottom_attr,
  4779.                         char *border_left_attr,
  4780.                         char *border_right_attr,
  4781.                         char *border_color_attr,
  4782.                         char *border_style_attr,
  4783.                         char *vspace_attr,
  4784.                         char *hspace_attr,
  4785.                         char *bgcolor_attr,
  4786.                         char *background_attr,
  4787.                         char *width_attr,
  4788.                         char *height_attr,
  4789.                         char *cellpad_attr,
  4790.                         char *toppad_attr,
  4791.                         char *bottompad_attr,
  4792.                         char *leftpad_attr,
  4793.                         char *rightpad_attr,
  4794.                         char *cellspace_attr,
  4795.                         char *cols_attr)
  4796. {
  4797.     lo_TableRec *table;
  4798.     LO_TableStruct *table_ele;
  4799.     int32 val;
  4800.     char *bgcolor_from_style = NULL;
  4801.     Bool allow_percent_width;
  4802.     Bool allow_percent_height;
  4803. #ifdef LOCAL_DEBUG
  4804.  fprintf(stderr, "lo_BeginTable called\n");
  4805. #endif /* LOCAL_DEBUG */
  4806.  
  4807.     if (state == NULL)
  4808.     {
  4809.         return;
  4810.     }
  4811.  
  4812.     table_ele = (LO_TableStruct *)lo_NewElement(context, state, LO_TABLE, NULL, 0);
  4813.     if (table_ele == NULL)
  4814.     {
  4815.         state->top_state->out_of_memory = TRUE;
  4816.         return;
  4817.     }
  4818.  
  4819.     table_ele->type = LO_TABLE;
  4820.     /* Copied into lo_PositionTableElement() */
  4821.     /*
  4822.     table_ele->ele_id = NEXT_ELEMENT;
  4823.     table_ele->x = state->x;
  4824.     table_ele->x_offset = 0;
  4825.     table_ele->y = state->y;
  4826.     table_ele->y_offset = 0;
  4827.     table_ele->width = 0;
  4828.     table_ele->height = 0;
  4829.     table_ele->line_height = 0;
  4830.     */
  4831.     
  4832.     table_ele->FE_Data = NULL;
  4833.     table_ele->anchor_href = state->current_anchor;
  4834.  
  4835.     /*
  4836.      * Default to the current alignment
  4837.      */
  4838.     if ( state->align_stack != NULL )
  4839.     {
  4840.         table_ele->alignment = state->align_stack->alignment;
  4841.     }
  4842.     else
  4843.     {
  4844.         table_ele->alignment = LO_ALIGN_LEFT;
  4845.     }
  4846.  
  4847.     table_ele->border_width = TABLE_DEF_BORDER;
  4848.     table_ele->border_top_width = TABLE_DEF_BORDER;
  4849.     table_ele->border_bottom_width = TABLE_DEF_BORDER;
  4850.     table_ele->border_left_width = TABLE_DEF_BORDER;
  4851.     table_ele->border_right_width = TABLE_DEF_BORDER;
  4852.     table_ele->border_style = TABLE_DEF_BORDER_STYLE;
  4853.  
  4854.     table_ele->border_vert_space = TABLE_DEF_VERTICAL_SPACE;
  4855.     table_ele->border_horiz_space = TABLE_DEF_HORIZONTAL_SPACE;
  4856.  
  4857.     table_ele->border_color.red = 0;
  4858.     table_ele->border_color.green = 0;
  4859.     table_ele->border_color.blue = 0;
  4860.  
  4861.     table_ele->ele_attrmask = 0;
  4862.  
  4863.     table_ele->sel_start = -1;
  4864.     table_ele->sel_end = -1;
  4865.  
  4866.     /* Copied into lo_PositionTableElement() */
  4867.     /*
  4868.     table_ele->next = NULL;
  4869.     table_ele->prev = NULL;
  4870.     */
  4871.  
  4872.     /*
  4873.      * Check for an align parameter
  4874.      */
  4875.     if (align_attr)
  4876.     {
  4877.         Bool floating;
  4878.  
  4879.         floating = FALSE;
  4880.         table_ele->alignment = lo_EvalAlignParam(align_attr, &floating);
  4881.         /*
  4882.          * Only allow left and right (floating) and center.
  4883.          */
  4884.         if (floating != FALSE)
  4885.         {
  4886.             table_ele->ele_attrmask |= LO_ELE_FLOATING;
  4887.         }
  4888.         else
  4889.         {
  4890.             /*
  4891.              * Tables can be left, center, right, justify or char alignment.
  4892.              * We only do left, center and right. True left and right will
  4893.              * hit the floating case above. So, we set all alignments to
  4894.              * be either center or left.
  4895.              */
  4896.             switch ( table_ele->alignment )
  4897.             {
  4898.                 case LO_ALIGN_LEFT:
  4899.                 case LO_ALIGN_RIGHT:
  4900.                 case LO_ALIGN_CENTER:
  4901.                     break;
  4902.                     
  4903.                 case LO_ALIGN_NCSA_CENTER:
  4904.                     table_ele->alignment = LO_ALIGN_CENTER;
  4905.                     break;
  4906.                 
  4907.                 default:
  4908.                     table_ele->alignment = LO_ALIGN_LEFT;
  4909.                     break;
  4910.             }
  4911.         }
  4912.     }
  4913.  
  4914.     lo_PositionTableElement(state, table_ele);
  4915.  
  4916.     /*
  4917.      * Push our alignment state if we're not floating
  4918.      */
  4919.  
  4920.     /* Copied into lo_PositionTableElement() */
  4921.     /*
  4922.     if ( !(table_ele->ele_attrmask & LO_ELE_FLOATING) )
  4923.     {
  4924.         lo_PushAlignment(state, P_TABLE_DATA, table_ele->alignment);
  4925.     }
  4926.     */
  4927.  
  4928.     /*
  4929.      * Get the border parameter.
  4930.      */
  4931.     if (border_attr)
  4932.     {
  4933.         val = XP_ATOI(border_attr);
  4934.         if ((val == 0)&&(*border_attr == '0'))
  4935.         {
  4936.             val = -1;
  4937.         }
  4938.         else if (val < 1)
  4939.         {
  4940.             val = 1;
  4941.         }
  4942.         table_ele->border_width = val;
  4943.         table_ele->border_top_width = val;
  4944.         table_ele->border_bottom_width = val;
  4945.         table_ele->border_left_width = val;
  4946.         table_ele->border_right_width = val;
  4947.     }
  4948.     table_ele->border_width = FEUNITS_X(table_ele->border_width, context);
  4949.  
  4950.     /*
  4951.      * Get the top border parameter.
  4952.      */
  4953.     if (border_top_attr)
  4954.     {
  4955.         val = XP_ATOI(border_top_attr);
  4956.         if ((val == 0)&&(*border_top_attr == '0'))
  4957.         {
  4958.             val = -1;
  4959.         }
  4960.         else if (val < 1)
  4961.         {
  4962.             val = 1;
  4963.         }
  4964.         table_ele->border_top_width = val;
  4965.     }
  4966.     table_ele->border_top_width = FEUNITS_Y(table_ele->border_top_width, context);
  4967.     
  4968.     /*
  4969.      * Get the bottom border parameter.
  4970.      */
  4971.     if (border_bottom_attr)
  4972.     {
  4973.         val = XP_ATOI(border_bottom_attr);
  4974.         if ((val == 0)&&(*border_bottom_attr == '0'))
  4975.         {
  4976.             val = -1;
  4977.         }
  4978.         else if (val < 1)
  4979.         {
  4980.             val = 1;
  4981.         }
  4982.         table_ele->border_bottom_width = val;
  4983.     }
  4984.     table_ele->border_bottom_width = FEUNITS_Y(table_ele->border_bottom_width, context);
  4985.     
  4986.     /*
  4987.      * Get the left border parameter.
  4988.      */
  4989.     if (border_left_attr)
  4990.     {
  4991.         val = XP_ATOI(border_left_attr);
  4992.         if ((val == 0)&&(*border_left_attr == '0'))
  4993.         {
  4994.             val = -1;
  4995.         }
  4996.         else if (val < 1)
  4997.         {
  4998.             val = 1;
  4999.         }
  5000.         table_ele->border_left_width = val;
  5001.     }
  5002.     table_ele->border_left_width = FEUNITS_X(table_ele->border_left_width, context);
  5003.     
  5004.     /*
  5005.      * Get the right border parameter.
  5006.      */
  5007.     if (border_right_attr)
  5008.     {
  5009.         val = XP_ATOI(border_right_attr);
  5010.         if ((val == 0)&&(*border_right_attr == '0'))
  5011.         {
  5012.             val = -1;
  5013.         }
  5014.         else if (val < 1)
  5015.         {
  5016.             val = 1;
  5017.         }
  5018.         table_ele->border_right_width = val;
  5019.     }
  5020.     table_ele->border_right_width = FEUNITS_X(table_ele->border_right_width, context);
  5021.  
  5022.     /*
  5023.      * Get the border style parameter.
  5024.      */
  5025.     if (border_style_attr)
  5026.     {
  5027.         int32 border_style;
  5028.         
  5029.         border_style = BORDER_OUTSET;
  5030.         if ( pa_TagEqual("none", border_style_attr) )
  5031.         {
  5032.             border_style = BORDER_NONE;
  5033.         }
  5034.         else if ( pa_TagEqual("dotted", border_style_attr) )
  5035.         {
  5036.             border_style = BORDER_DOTTED;
  5037.         }
  5038.         else if ( pa_TagEqual("dashed", border_style_attr) )
  5039.         {
  5040.             border_style = BORDER_DASHED;
  5041.         }
  5042.         else if ( pa_TagEqual("solid", border_style_attr) )
  5043.         {
  5044.             border_style = BORDER_SOLID;
  5045.         }
  5046.         else if ( pa_TagEqual("double", border_style_attr) )
  5047.         {
  5048.             border_style = BORDER_DOUBLE;
  5049.         }
  5050.         else if ( pa_TagEqual("groove", border_style_attr) )
  5051.         {
  5052.             border_style = BORDER_GROOVE;
  5053.         }
  5054.         else if ( pa_TagEqual("ridge", border_style_attr) )
  5055.         {
  5056.             border_style = BORDER_RIDGE;
  5057.         }
  5058.         else if ( pa_TagEqual("inset", border_style_attr) )
  5059.         {
  5060.             border_style = BORDER_INSET;
  5061.         }
  5062.         else if ( pa_TagEqual("outset", border_style_attr) )
  5063.         {
  5064.             border_style = BORDER_OUTSET;
  5065.         }
  5066.         
  5067.         table_ele->border_style = border_style;
  5068.     }
  5069.  
  5070.     /*
  5071.      * Get the border color parameter.
  5072.      */
  5073.     if (border_color_attr)
  5074.     {
  5075.         uint8 red, green, blue;
  5076.  
  5077.         LO_ParseStyleSheetRGB(border_color_attr, &red, &green, &blue);
  5078.         table_ele->border_color.red = red;
  5079.         table_ele->border_color.green = green;
  5080.         table_ele->border_color.blue = blue;
  5081.     }
  5082.     
  5083.     /*
  5084.      * Get the extra vertical space parameter.
  5085.      */
  5086.     if (vspace_attr)
  5087.     {
  5088.         val = XP_ATOI(vspace_attr);
  5089.         if (val < 0)
  5090.         {
  5091.             val = 0;
  5092.         }
  5093.         table_ele->border_vert_space = val;
  5094.     }
  5095.     table_ele->border_vert_space = FEUNITS_Y(table_ele->border_vert_space,
  5096.                         context);
  5097.  
  5098.     /*
  5099.      * Get the extra horizontal space parameter.
  5100.      */
  5101.     if (hspace_attr)
  5102.     {
  5103.         val = XP_ATOI(hspace_attr);
  5104.         if (val < 0)
  5105.         {
  5106.             val = 0;
  5107.         }
  5108.         table_ele->border_horiz_space = val;
  5109.     }
  5110.     table_ele->border_horiz_space = FEUNITS_X(table_ele->border_horiz_space,
  5111.                         context);
  5112.  
  5113.     table = XP_NEW(lo_TableRec);
  5114.     
  5115.     /* Keep ptr to table state structure.  Will be needed during relayout */
  5116.     table_ele->table = table;
  5117.  
  5118.     if (table == NULL)
  5119.     {
  5120.         return;
  5121.     }
  5122.  
  5123.     if(table_ele->border_top_width < 0)
  5124.             table_ele->border_top_width = 0;
  5125.      if(table_ele->border_bottom_width < 0)
  5126.             table_ele->border_bottom_width = 0;
  5127.     if(table_ele->border_right_width < 0)
  5128.             table_ele->border_right_width = 0;
  5129.     if(table_ele->border_left_width < 0)
  5130.             table_ele->border_left_width = 0;
  5131.  
  5132.     if(table_ele->border_width < 0)
  5133.     {
  5134.         /* backwards compatibility */
  5135.         table->draw_borders = TABLE_BORDERS_GONE;            
  5136.         table_ele->border_width = 0;
  5137.         table_ele->border_top_width = 0;
  5138.         table_ele->border_bottom_width = 0;
  5139.         table_ele->border_right_width = 0;
  5140.         table_ele->border_left_width = 0;
  5141.     }
  5142.     else if (table_ele->border_top_width == 0
  5143.         && table_ele->border_bottom_width == 0
  5144.         && table_ele->border_left_width == 0
  5145.         && table_ele->border_right_width == 0)
  5146.     {
  5147.         table->draw_borders = TABLE_BORDERS_OFF;
  5148.     }
  5149.     else
  5150.     {
  5151.         table->draw_borders = TABLE_BORDERS_ON;
  5152.     }
  5153.     table->has_percent_width_cells = FALSE;
  5154.     table->has_percent_height_cells = FALSE;
  5155.     table->backdrop.bg_color = NULL;
  5156.     table->backdrop.url = NULL;
  5157.     table->backdrop.tile_mode = LO_TILE_BOTH;
  5158.  
  5159.     /* Copied to lo_InitTableRecord()
  5160.     /*
  5161.     table->rows = 0;
  5162.     table->cols = 0;
  5163.     */
  5164.  
  5165.     table->width_spans = NULL;
  5166.     table->width_span_ptr = NULL;
  5167.     table->height_spans = NULL;
  5168.     /* Copied to lo_InitTableRecord()
  5169.     table->height_span_ptr = NULL;
  5170.     */
  5171.     table->caption = NULL;
  5172.     table->table_ele = table_ele;
  5173.     table->current_subdoc = NULL;
  5174.     table->row_list = NULL;
  5175.     table->row_ptr = NULL;
  5176.     table->width = 0;
  5177.     table->height = 0;
  5178.     
  5179.     lo_InitTableRecord( table );
  5180.  
  5181.     /*
  5182.      * Percent width, height added for relayout
  5183.      */
  5184.     table->percent_width = 0;
  5185.     table->percent_height = 0;
  5186.  
  5187.     table->inner_top_pad = TABLE_DEF_INNER_CELL_PAD;
  5188.     table->inner_bottom_pad = TABLE_DEF_INNER_CELL_PAD;
  5189.     table->inner_left_pad = TABLE_DEF_INNER_CELL_PAD;
  5190.     table->inner_right_pad = TABLE_DEF_INNER_CELL_PAD;
  5191.     table->inter_cell_pad = TABLE_DEF_INTER_CELL_PAD;
  5192.  
  5193.     table->current_subdoc = (LO_SubDocStruct *)lo_NewElement(context, state, LO_SUBDOC, NULL, 0);
  5194.     table->current_subdoc->type = LO_SUBDOC;
  5195.     
  5196.     table->current_subdoc->backdrop.bg_color = NULL;
  5197.     table->current_subdoc->backdrop.url = NULL;
  5198.     table->current_subdoc->backdrop.tile_mode = LO_TILE_BOTH;
  5199.     table->current_subdoc->state = lo_NewLayout(context,
  5200.         state->win_width, state->win_height, 0, 0, NULL);
  5201.  
  5202.     table->default_cell_width = 0;
  5203.     table->fixed_width_remaining = 0;
  5204.     table->fixed_col_widths = NULL;
  5205.     table->table_width_fixed = FALSE;
  5206.     table->fixed_cols = 0;
  5207.     
  5208.     /*
  5209.      * You can't do percentage widths if the parent's
  5210.      * width is still undecided.
  5211.      */
  5212.     allow_percent_width = TRUE;
  5213.     allow_percent_height = TRUE;
  5214.     if ((state->is_a_subdoc == SUBDOC_CELL)||
  5215.         (state->is_a_subdoc == SUBDOC_CAPTION))
  5216.     {
  5217.         lo_TopState *top_state;
  5218.         lo_DocState *new_state;
  5219.         int32 doc_id;
  5220.  
  5221.         /*
  5222.          * Get the unique document ID, and retreive this
  5223.          * documents layout state.
  5224.          */
  5225.         doc_id = XP_DOCID(context);
  5226.         top_state = lo_FetchTopState(doc_id);
  5227.         new_state = top_state->doc_state;
  5228.  
  5229.         while ((new_state->sub_state != NULL)&&
  5230.             (new_state->sub_state != state))
  5231.         {
  5232.             new_state = new_state->sub_state;
  5233.         }
  5234.  
  5235.         if ((new_state->sub_state == state)&&
  5236.             (new_state->current_ele != NULL))
  5237.         {
  5238.             LO_SubDocStruct *subdoc;
  5239.  
  5240.             subdoc = (LO_SubDocStruct *)new_state->current_ele;
  5241.             if (subdoc->width == 0)
  5242.             {
  5243.                 allow_percent_width = FALSE;
  5244. #ifdef LOCAL_DEBUG
  5245.  fprintf(stderr, "Percent width not allowed in this subdoc!\n");
  5246. #endif /* LOCAL_DEBUG */
  5247.             }
  5248.             else
  5249.             {
  5250. #ifdef LOCAL_DEBUG
  5251.  fprintf(stderr, "Percent width IS allowed in this subdoc!\n");
  5252. #endif /* LOCAL_DEBUG */
  5253.             }
  5254.             if (subdoc->height == 0)
  5255.             {
  5256.                 allow_percent_height = FALSE;
  5257.             }
  5258.         }
  5259.     }
  5260.  
  5261.     
  5262.     /* check for style sheet color and override if necessary */
  5263.     if(state->top_state && state->top_state->style_stack)
  5264.     {
  5265.         StyleStruct *style_struct;
  5266.  
  5267.         style_struct = STYLESTACK_GetStyleByIndex(
  5268.                                             state->top_state->style_stack,
  5269.                                             0);
  5270.  
  5271.         if(style_struct)
  5272.         {
  5273.             bgcolor_from_style = STYLESTRUCT_GetString(style_struct, BG_COLOR_STYLE);
  5274.  
  5275.             if(bgcolor_from_style)
  5276.             {
  5277.                 bgcolor_attr = bgcolor_from_style;
  5278.             }
  5279.         }
  5280.     }
  5281.  
  5282.     /*
  5283.      * Check for a background color attribute
  5284.      */
  5285.     if (bgcolor_attr)
  5286.     {
  5287.         uint8 red, green, blue;
  5288.         XP_Bool rv;
  5289.  
  5290.         if(bgcolor_from_style)
  5291.             rv = LO_ParseStyleSheetRGB(bgcolor_attr, &red, &green, &blue);
  5292.         else
  5293.             rv = LO_ParseRGB(bgcolor_attr, &red, &green, &blue);
  5294.         if(rv)
  5295.         {
  5296.             table->backdrop.bg_color = XP_NEW(LO_Color);
  5297.             if (table->backdrop.bg_color != NULL)
  5298.             {
  5299.                 table->backdrop.bg_color->red = red;
  5300.                 table->backdrop.bg_color->green = green;
  5301.                 table->backdrop.bg_color->blue = blue;
  5302.             }
  5303.         }
  5304.     }
  5305.  
  5306.     if (background_attr)
  5307.         table->backdrop.url = XP_STRDUP(background_attr);
  5308.     XP_FREEIF(bgcolor_from_style);
  5309.  
  5310.  
  5311.     /*
  5312.      * Get the width and height parameters, in absolute or percentage.
  5313.      * If percentage, make it absolute.
  5314.      */
  5315.     if (width_attr)
  5316.     {
  5317.         Bool is_percent;
  5318.  
  5319.         val = lo_ValueOrPercent(width_attr, &is_percent);
  5320.         if (is_percent != FALSE)
  5321.         {
  5322.             table->percent_width = val;
  5323.             /*
  5324.             if (allow_percent_width == FALSE)
  5325.             {
  5326.                 val = 0;
  5327.             }
  5328.             else
  5329.             {
  5330.                 val = (state->win_width - state->win_left -
  5331.                     state->win_right) * val / 100;
  5332.             }
  5333.             */
  5334.             
  5335.         }
  5336.         else
  5337.         {
  5338.             table->percent_width = 0;
  5339.             table->table_width_fixed = TRUE;
  5340.             val = FEUNITS_X(val, context);
  5341.         }
  5342.         if (val < 0)
  5343.         {
  5344.             val = 0;
  5345.         }
  5346.         table->width = val;
  5347.     }
  5348.     
  5349.     if (height_attr)
  5350.     {
  5351.         Bool is_percent;
  5352.  
  5353.         val = lo_ValueOrPercent(height_attr, &is_percent);
  5354.         if (is_percent != FALSE)
  5355.         {
  5356.             table->percent_height = val;
  5357.             /*
  5358.             if (allow_percent_height == FALSE)
  5359.             {
  5360.                 val = 0;
  5361.             }
  5362.             else
  5363.             {
  5364.                 val = (state->win_height - state->win_top -
  5365.                     state->win_bottom) * val / 100;
  5366.             }
  5367.             */
  5368.         }
  5369.         else
  5370.         {
  5371.             table->percent_height = 0;
  5372.             val = FEUNITS_X(val, context);
  5373.         }
  5374.         if (val < 0)
  5375.         {
  5376.             val = 0;
  5377.         }
  5378.         table->height = val;
  5379.     }
  5380.  
  5381.     lo_SetTableDimensions(state, table, allow_percent_width, allow_percent_height);
  5382.  
  5383.     if (cellpad_attr)
  5384.     {
  5385.         val = XP_ATOI(cellpad_attr);
  5386.         if (val < 0)
  5387.         {
  5388.             val = 0;
  5389.         }
  5390.         /* set all our pads to this value */
  5391.         table->inner_top_pad = val;
  5392.         table->inner_bottom_pad = val;
  5393.         table->inner_left_pad = val;
  5394.         table->inner_right_pad = val;
  5395.     }
  5396.  
  5397.     if (toppad_attr)
  5398.     {
  5399.         val = XP_ATOI(toppad_attr);
  5400.         if (val < 0)
  5401.         {
  5402.             val = 0;
  5403.         }
  5404.         table->inner_top_pad = val;
  5405.     }
  5406.  
  5407.     if (bottompad_attr)
  5408.     {
  5409.         val = XP_ATOI(bottompad_attr);
  5410.         if (val < 0)
  5411.         {
  5412.             val = 0;
  5413.         }
  5414.         table->inner_bottom_pad = val;
  5415.     }
  5416.  
  5417.     if (leftpad_attr)
  5418.     {
  5419.         val = XP_ATOI(leftpad_attr);
  5420.         if (val < 0)
  5421.         {
  5422.             val = 0;
  5423.         }
  5424.         table->inner_left_pad = val;
  5425.     }
  5426.  
  5427.     if (rightpad_attr)
  5428.     {
  5429.         val = XP_ATOI(rightpad_attr);
  5430.         if (val < 0)
  5431.         {
  5432.             val = 0;
  5433.         }
  5434.         table->inner_right_pad = val;
  5435.     }
  5436.     
  5437.     if (cellspace_attr)
  5438.     {
  5439.         val = XP_ATOI(cellspace_attr);
  5440.         if (val < 0)
  5441.         {
  5442.             val = 0;
  5443.         }
  5444.         table->inter_cell_pad = val;
  5445.     }
  5446.  
  5447.     /*
  5448.      * Get the COLS parameter.
  5449.      */
  5450.     if (cols_attr)
  5451.     {
  5452.         val = XP_ATOI(cols_attr);
  5453.         if (val < 0)
  5454.         {
  5455.             val = 0;
  5456.         }
  5457.         table_ele->border_horiz_space = val;
  5458.         
  5459.         /*
  5460.          * If we have a specified number of columns, then
  5461.          * we first need to make sure we have a real table
  5462.          * width and then compute our default column width.
  5463.          */
  5464.         table->fixed_cols = val;        
  5465.         if ( val > 0 )
  5466.         {
  5467.         
  5468.             /* Copied to lo_CalcFixedColWidths() */
  5469.             /*
  5470.             int32 count;
  5471.             int32 table_width;
  5472.             
  5473.             table->fixed_cols = val;
  5474.             
  5475.             table_width = lo_ComputeInternalTableWidth ( context, table, state );
  5476.             */
  5477.  
  5478.             /* Split the space up evenly */
  5479.             /*
  5480.             table->default_cell_width = table_width / val;
  5481.             */
  5482.  
  5483.             /* and we have all the table width left to play with */
  5484.             /*
  5485.             table->fixed_width_remaining = table_width;
  5486.             */
  5487.             
  5488.             /* allocate and initialize our width array */            
  5489.             table->fixed_col_widths = XP_ALLOC(val * sizeof(int32));
  5490.             if (table->fixed_col_widths == NULL)
  5491.             {
  5492.                 state->top_state->out_of_memory = TRUE;
  5493.                 table->fixed_cols = 0;
  5494.                 table->default_cell_width = 0;
  5495.                 return;
  5496.             }
  5497.  
  5498.  
  5499.             /*
  5500.             for ( count = 0; count < val; ++count )
  5501.             {
  5502.                 table->fixed_col_widths[ count ] = 0;
  5503.             }
  5504.             */
  5505.  
  5506.             lo_CalcFixedColWidths( context, state, table );
  5507.         }
  5508.     }
  5509.  
  5510.     /* Copied to lo_UpdateStateAfterBeginTable() */
  5511.     /* 
  5512.     state->current_table = table;
  5513.     */
  5514.     
  5515.     lo_UpdateStateAfterBeginTable( state, table );
  5516. }
  5517.  
  5518.  
  5519. /*
  5520.  * Preparse the tag attributes and call the real begin table
  5521.  */
  5522. void
  5523. lo_BeginTable(MWContext *context, lo_DocState *state, PA_Tag *tag)
  5524. {
  5525.  
  5526.     /* style sheets variables */
  5527.     StyleStruct *style_struct=NULL;
  5528.     SS_Number *top_padding, *bottom_padding, *left_padding, *right_padding;
  5529.  
  5530.     char *align_attr =        (char*)lo_FetchParamValue(context, tag, PARAM_ALIGN);
  5531.     char *border_attr =       (char*)lo_FetchParamValue(context, tag, PARAM_BORDER);
  5532.     char *border_top_attr =        NULL;
  5533.     char *border_bottom_attr =    NULL;
  5534.     char *border_left_attr =    NULL;
  5535.     char *border_right_attr =    NULL;
  5536.     char *border_color_attr =    (char*)lo_FetchParamValue(context, tag, PARAM_BORDERCOLOR);
  5537.     char *border_style_attr =    NULL;
  5538.     char *vspace_attr =       (char*)lo_FetchParamValue(context, tag, PARAM_VSPACE);
  5539.     char *hspace_attr =       (char*)lo_FetchParamValue(context, tag, PARAM_HSPACE);
  5540.     char *bgcolor_attr =       (char*)lo_FetchParamValue(context, tag, PARAM_BGCOLOR);
  5541.     char *background_attr =      (char*)lo_FetchParamValue(context, tag, PARAM_BACKGROUND);
  5542.     char *width_attr =         (char*)lo_FetchParamValue(context, tag, PARAM_WIDTH);
  5543.     char *height_attr =       (char*)lo_FetchParamValue(context, tag, PARAM_HEIGHT);
  5544.     char *cellpad_attr =       (char*)lo_FetchParamValue(context, tag, PARAM_CELLPAD);
  5545.     char *toppad_attr =       (char*)lo_FetchParamValue(context, tag, PARAM_TOPPAD);
  5546.     char *bottompad_attr =  (char*)lo_FetchParamValue(context, tag, PARAM_BOTTOMPAD);
  5547.     char *leftpad_attr =       (char*)lo_FetchParamValue(context, tag, PARAM_LEFTPAD);
  5548.     char *rightpad_attr =   (char*)lo_FetchParamValue(context, tag, PARAM_RIGHTPAD);
  5549.     char *cellspace_attr =     (char*)lo_FetchParamValue(context, tag, PARAM_CELLSPACE);
  5550.     char *cols_attr =         (char*)lo_FetchParamValue(context, tag, PARAM_COLS);
  5551.  
  5552.     if(!border_style_attr)
  5553.     {
  5554.         border_style_attr = XP_STRDUP("outset"); 
  5555.     }
  5556.  
  5557.     if(!border_color_attr)
  5558.     {
  5559.         XP_ASSERT(state);
  5560.         if(state)
  5561.             border_color_attr = PR_smprintf("#%2x%2x%2x", 
  5562.                                    state->text_bg.red,
  5563.                                    state->text_bg.green,
  5564.                                    state->text_bg.blue);
  5565.     }
  5566.  
  5567.     if(state->top_state->style_stack)
  5568.         style_struct = STYLESTACK_GetStyleByIndex(state->top_state->style_stack, 0);
  5569.  
  5570.     if(style_struct)
  5571.     {
  5572.         left_padding = STYLESTRUCT_GetNumber(style_struct, LEFTPADDING_STYLE);
  5573.         if(left_padding)
  5574.         {
  5575.             LO_AdjustSSUnits(left_padding, LEFTPADDING_STYLE, context, state);
  5576.             XP_FREEIF(leftpad_attr);
  5577.             leftpad_attr = PR_smprintf("%ld", (int32)left_padding->value);
  5578.         }
  5579.  
  5580.         right_padding = STYLESTRUCT_GetNumber(style_struct, RIGHTPADDING_STYLE);
  5581.         if(right_padding)
  5582.         {
  5583.             LO_AdjustSSUnits(right_padding, RIGHTPADDING_STYLE, context, state);
  5584.             XP_FREEIF(rightpad_attr);
  5585.             rightpad_attr = PR_smprintf("%ld", (int32)right_padding->value);
  5586.         }
  5587.  
  5588.         top_padding = STYLESTRUCT_GetNumber(style_struct, TOPPADDING_STYLE);
  5589.         if(top_padding)
  5590.         {
  5591.             LO_AdjustSSUnits(top_padding, TOPPADDING_STYLE, context, state);
  5592.             XP_FREEIF(toppad_attr);
  5593.             toppad_attr = PR_smprintf("%ld", (int32)top_padding->value);
  5594.         }
  5595.  
  5596.         bottom_padding = STYLESTRUCT_GetNumber(style_struct, BOTTOMPADDING_STYLE);
  5597.         if(bottom_padding)
  5598.         {
  5599.             LO_AdjustSSUnits(bottom_padding, BOTTOMPADDING_STYLE, context, state);
  5600.             XP_FREEIF(bottompad_attr);
  5601.             bottompad_attr = PR_smprintf("%ld", (int32)bottom_padding->value);
  5602.         }
  5603.     }
  5604.  
  5605.     /* remove the PA_LOCK stuff, it does nothing anyways */
  5606.  
  5607.     lo_BeginTableAttributes(context, 
  5608.                             state, 
  5609.                             align_attr,
  5610.                             border_attr,
  5611.                             border_top_attr,
  5612.                             border_bottom_attr,
  5613.                             border_left_attr,
  5614.                             border_right_attr,
  5615.                             border_color_attr,
  5616.                             border_style_attr,
  5617.                             vspace_attr,
  5618.                             hspace_attr,
  5619.                             bgcolor_attr,
  5620.                             background_attr,
  5621.                             width_attr,
  5622.                             height_attr,
  5623.                             cellpad_attr,
  5624.                             toppad_attr,
  5625.                             bottompad_attr,
  5626.                             leftpad_attr,
  5627.                             rightpad_attr,
  5628.                             cellspace_attr,
  5629.                             cols_attr);
  5630.  
  5631.     if(align_attr)
  5632.         PA_FREE(align_attr);
  5633.     if(border_attr)
  5634.         PA_FREE(border_attr);
  5635.     if(border_top_attr)
  5636.         PA_FREE(border_top_attr);
  5637.     if(border_bottom_attr)
  5638.         PA_FREE(border_bottom_attr);
  5639.     if(border_left_attr)
  5640.         PA_FREE(border_left_attr);
  5641.     if(border_right_attr)
  5642.         PA_FREE(border_right_attr);
  5643.     if(border_color_attr)
  5644.         PA_FREE(border_color_attr);
  5645.     if(border_style_attr)
  5646.         PA_FREE(border_style_attr);
  5647.     if(vspace_attr)
  5648.         PA_FREE(vspace_attr);
  5649.     if(hspace_attr)
  5650.         PA_FREE(hspace_attr);
  5651.     if(bgcolor_attr)
  5652.         PA_FREE(bgcolor_attr);
  5653.     if(background_attr)
  5654.         PA_FREE(background_attr);
  5655.     if(width_attr)
  5656.         PA_FREE(width_attr);
  5657.     if(height_attr)
  5658.         PA_FREE(height_attr);
  5659.     if(cellpad_attr)
  5660.         PA_FREE(cellpad_attr);
  5661.     if(toppad_attr)
  5662.         PA_FREE(toppad_attr);
  5663.     if(bottompad_attr)
  5664.         PA_FREE(bottompad_attr);
  5665.     if(leftpad_attr)
  5666.         PA_FREE(leftpad_attr);
  5667.     if(rightpad_attr)
  5668.         PA_FREE(rightpad_attr);
  5669.     if(cellspace_attr)
  5670.         PA_FREE(cellspace_attr);
  5671.     if(cols_attr)
  5672.         PA_FREE(cols_attr);
  5673. }
  5674.  
  5675.  
  5676. static void
  5677. lo_fill_cell_array(lo_TableRec *table, lo_cell_data XP_HUGE *cell_array,
  5678.     lo_TableCell *blank_cell, int32 cell_pad, Bool *relayout_pass)
  5679. {
  5680.     int32 x, y;
  5681.     int32 indx;
  5682.     lo_table_span *row_max;
  5683.     lo_table_span *col_max;
  5684.     lo_TableRow *row_ptr;
  5685.     lo_TableCell *cell_ptr;
  5686.  
  5687.     row_max = table->height_spans;
  5688.     row_ptr = table->row_list;
  5689.     for (y = 0; y < table->rows; y++)
  5690.     {
  5691.         x = 0;
  5692.         col_max = table->width_spans;
  5693.         cell_ptr = row_ptr->cell_list;
  5694.         row_ptr->cells_in_row = 0;
  5695.         while (cell_ptr != NULL)
  5696.         {
  5697.             /*
  5698.              * Also on this pass check if any of the cells
  5699.              * NEED to be relaid out later.
  5700.              */
  5701.             if (cell_ptr->must_relayout != FALSE)
  5702.             {
  5703.                 *relayout_pass = TRUE;
  5704.             }
  5705.  
  5706.             /*
  5707.              * "fix" up badly specified row spans.
  5708.              */
  5709.             if ((y + cell_ptr->rowspan) > table->rows)
  5710.             {
  5711.                 cell_ptr->rowspan = table->rows - y;
  5712.                 if (cell_ptr->rowspan == 1)
  5713.                 {
  5714.                     if (cell_ptr->height > row_max->dim)
  5715.                     {
  5716.                         row_max->dim = cell_ptr->height;
  5717.                     }
  5718.                 }
  5719.             }
  5720.  
  5721.             indx = (y * table->cols) + x;
  5722.  
  5723.             if (cell_array[indx].cell == blank_cell)
  5724.             {
  5725.                 x++;
  5726.                 col_max = col_max->next;
  5727.                 continue;
  5728.             }
  5729.  
  5730.             /*
  5731.              * If the cell is not an empty cell, count it for this row
  5732.              */
  5733.             /* if (cell_ptr->cell->cell_list != NULL || cell_ptr->cell->cell_float_list != NULL) */
  5734.                 row_ptr->cells_in_row++;
  5735.  
  5736.             cell_array[indx].cell = cell_ptr;
  5737.             cell_array[indx].width = cell_ptr->max_width;
  5738.             cell_array[indx].height = cell_ptr->height;
  5739.  
  5740.             if (cell_ptr->colspan > 1)
  5741.             {
  5742.                 int32 i;
  5743.                 int32 width, min_width;
  5744.                 lo_table_span *max_ptr;
  5745.  
  5746.                 max_ptr = col_max;
  5747.  
  5748.                 width = max_ptr->dim;
  5749.                 min_width = max_ptr->min_dim;
  5750.                 for (i=1; i < cell_ptr->colspan; i++)
  5751.                 {
  5752.                     cell_array[indx + i].cell = blank_cell;
  5753.                     max_ptr = max_ptr->next;
  5754.                     width = width + cell_pad + max_ptr->dim;
  5755.                     min_width = min_width + cell_pad +
  5756.                         max_ptr->min_dim;
  5757.                 }
  5758.  
  5759.                 if (width < cell_ptr->max_width)
  5760.                 {
  5761.                     int32 add_width;
  5762.                     int32 add;
  5763.                     lo_table_span *add_ptr;
  5764.  
  5765.                     add_ptr = col_max;
  5766.                     add_width = cell_ptr->max_width -
  5767.                         width;
  5768.                     add = 0;
  5769.                     while (add_ptr != max_ptr)
  5770.                     {
  5771.                         int32 newWidth;
  5772.  
  5773.                         newWidth = add_width *
  5774.                             add_ptr->dim / width;
  5775.                         add_ptr->dim += newWidth;
  5776.                         add += newWidth;
  5777.                         add_ptr = add_ptr->next;
  5778.                     }
  5779.                     add_ptr->dim += (add_width - add);
  5780.                 }
  5781.  
  5782.                 if (min_width < cell_ptr->min_width)
  5783.                 {
  5784.                     int32 add_width;
  5785.                     int32 add;
  5786.                     lo_table_span *add_ptr;
  5787.  
  5788.                     add_ptr = col_max;
  5789.                     add_width = cell_ptr->min_width -
  5790.                         min_width;
  5791.                     add = 0;
  5792.                     while (add_ptr != max_ptr)
  5793.                     {
  5794.                         int32 newWidth;
  5795.  
  5796.                         newWidth = add_width *
  5797.                             add_ptr->min_dim /
  5798.                             min_width;
  5799.                         /*
  5800.                          * We are not allowed to add
  5801.                          * enough to put min_dim > dim.
  5802.                          */
  5803.                         if ((add_ptr->min_dim +
  5804.                              newWidth) > add_ptr->dim)
  5805.                         {
  5806.                             newWidth = add_ptr->dim -
  5807.                             add_ptr->min_dim;
  5808.                             /*
  5809.                              * don't let newWidth become
  5810.                              * negative.
  5811.                              */
  5812.                             if (newWidth < 0)
  5813.                             {
  5814.                                 newWidth = 0;
  5815.                             }
  5816.                         }
  5817.                         add_ptr->min_dim += newWidth;
  5818.                         add += newWidth;
  5819.                         add_ptr = add_ptr->next;
  5820.                     }
  5821.                     add_ptr->min_dim += (add_width - add);
  5822.                 }
  5823.                 col_max = max_ptr;
  5824.             }
  5825.  
  5826.             if (cell_ptr->rowspan > 1)
  5827.             {
  5828.                 int32 i;
  5829.                 int32 height;
  5830.                 int32 tmp_val;
  5831.                 lo_table_span *max_ptr;
  5832.  
  5833.                 max_ptr = row_max;
  5834.  
  5835.                 height = max_ptr->dim;
  5836.                 for (i=1; i < cell_ptr->rowspan; i++)
  5837.                 {
  5838.                     cell_array[indx + (i * table->cols)].cell =
  5839.                         blank_cell;
  5840.                     if (cell_ptr->colspan > 1)
  5841.                     {
  5842.                         int32 j;
  5843.  
  5844.                         for (j=1; j < cell_ptr->colspan; j++)
  5845.                         {
  5846.                             cell_array[indx +
  5847.                             (i * table->cols) + j].cell =
  5848.                             blank_cell;
  5849.                         }
  5850.                     }
  5851.                     max_ptr = max_ptr->next;
  5852.                     height = height + cell_pad + max_ptr->dim;
  5853.                 }
  5854.  
  5855.                 tmp_val = cell_ptr->baseline - row_max->min_dim;
  5856.                 if (tmp_val > 0)
  5857.                 {
  5858.                     row_max->min_dim += tmp_val;
  5859.                     if (row_ptr->vert_alignment ==
  5860.                         LO_ALIGN_BASELINE)
  5861.                     {
  5862.                         row_max->dim += tmp_val;
  5863.                         height += tmp_val;
  5864.                     }
  5865.                     /*
  5866.                      * Baseline spacing shouldn't grow the
  5867.                      * max height, except for baseline
  5868.                      * aligned rows as above.
  5869.                      */
  5870.                     if (row_max->min_dim > row_max->dim)
  5871.                     {
  5872.                         row_max->min_dim = row_max->dim;
  5873.                     }
  5874.                 }
  5875.  
  5876.                 if (height < cell_ptr->height)
  5877.                 {
  5878.                     int32 add_height;
  5879.                     int32 add;
  5880.                     lo_table_span *add_ptr;
  5881.  
  5882.                     add_ptr = row_max;
  5883.                     add_height = cell_ptr->height -
  5884.                         height;
  5885.                     add = 0;
  5886.                     while (add_ptr != max_ptr)
  5887.                     {
  5888.                         int32 newHeight;
  5889.  
  5890.                         newHeight = add_height *
  5891.                             add_ptr->dim / height;
  5892.                         add_ptr->dim += newHeight;
  5893.                         add += newHeight;
  5894.                         add_ptr = add_ptr->next;
  5895.                     }
  5896.                     add_ptr->dim += (add_height - add);
  5897.                 }
  5898.             }
  5899.  
  5900.             x += cell_ptr->colspan;
  5901.  
  5902.             col_max = col_max->next;
  5903.             cell_ptr = cell_ptr->next;
  5904.             cell_array[indx].cell->next = NULL;
  5905.         }
  5906.         row_ptr = row_ptr->next;
  5907.         row_max = row_max->next;
  5908.     }
  5909. }
  5910.  
  5911. static void
  5912. lo_percent_width_cells(lo_TableRec *table, lo_cell_data XP_HUGE *cell_array,
  5913.     lo_TableCell *blank_cell, int32 cell_pad, int32 table_pad,
  5914.     int32 *table_width, int32 *min_table_width,
  5915.     int32 *base_table_width, int32 *min_base_table_width)
  5916. {
  5917.     int32 x, y;
  5918.     int32 indx;
  5919.     int32 new_table_width;
  5920.     int32 new_min_table_width;
  5921.     int32 new_base_table_width;
  5922.     int32 new_min_base_table_width;
  5923.     Bool need_pass_two;
  5924.     lo_table_span *row_max;
  5925.     lo_table_span *col_max;
  5926.     lo_TableRow *row_ptr;
  5927.     lo_TableCell *cell_ptr;
  5928.  
  5929.     new_table_width = 0;
  5930.     row_ptr = table->row_list;
  5931.     row_max = table->height_spans;
  5932.     for (y=0; y < table->rows; y++)
  5933.     {
  5934.         if (row_ptr->has_percent_width_cells != FALSE)
  5935.         {
  5936.             int32 reserve;
  5937.             int32 unknown, unknown_base;
  5938.  
  5939.             unknown = 0;
  5940.             unknown_base = 0;
  5941.             reserve = 100 - table->cols;
  5942.             col_max = table->width_spans;
  5943.             for (x=0; x < table->cols; x++)
  5944.             {
  5945.                 indx = (y * table->cols) + x;
  5946.                 cell_ptr = cell_array[indx].cell;
  5947.                 if ((cell_ptr == blank_cell)||
  5948.                     (cell_ptr == NULL))
  5949.                 {
  5950.                     col_max = col_max->next;
  5951.                     continue;
  5952.                 }
  5953.                 if (cell_ptr->percent_width > 0)
  5954.                 {
  5955.                     int32 width;
  5956.  
  5957.                     reserve += cell_ptr->colspan;
  5958.                     if (cell_ptr->percent_width > reserve)
  5959.                     {
  5960.                         cell_ptr->percent_width = reserve;
  5961.                         reserve = 0;
  5962.                     }
  5963.                     else
  5964.                     {
  5965.                         reserve -= cell_ptr->percent_width;
  5966.                     }
  5967.                     width = cell_ptr->max_width * 100 /
  5968.                         cell_ptr->percent_width;
  5969.                     if (width > new_table_width)
  5970.                     {
  5971.                         new_table_width = width;
  5972.                     }
  5973.                 }
  5974.                 else
  5975.                 {
  5976.                     unknown++;
  5977.                     unknown_base += cell_ptr->max_width;
  5978.                 }
  5979.                 col_max = col_max->next;
  5980.             }
  5981.             if (unknown)
  5982.             {
  5983.                 col_max = table->width_spans;
  5984.                 for (x=0; x < table->cols; x++)
  5985.                 {
  5986.                 indx = (y * table->cols) + x;
  5987.                 cell_ptr = cell_array[indx].cell;
  5988.                 if ((cell_ptr == blank_cell)||
  5989.                     (cell_ptr == NULL))
  5990.                 {
  5991.                     col_max = col_max->next;
  5992.                     continue;
  5993.                 }
  5994.                 if (cell_ptr->percent_width == 0)
  5995.                 {
  5996.                     int32 width;
  5997.                     int32 percent;
  5998.  
  5999.                     if (unknown == 1)
  6000.                     {
  6001.                         percent = reserve;
  6002.                     }
  6003.                     else
  6004.                     {
  6005.                         percent = reserve *
  6006.                             cell_ptr->max_width /
  6007.                             unknown_base;
  6008.                     }
  6009.                     reserve -= percent;
  6010.                     if (reserve < 0)
  6011.                     {
  6012.                         reserve = 0;
  6013.                     }
  6014.                     percent += cell_ptr->colspan;
  6015.                     cell_ptr->percent_width = percent;
  6016.  
  6017.                     width = cell_ptr->max_width * 100 /
  6018.                         cell_ptr->percent_width;
  6019.                     if (width > new_table_width)
  6020.                     {
  6021.                         new_table_width = width;
  6022.                     }
  6023.  
  6024.                     unknown--;
  6025.                 }
  6026.                 col_max = col_max->next;
  6027.                 }
  6028.             }
  6029.         }
  6030.         else
  6031.         {
  6032.             int32 width;
  6033.  
  6034.             width = 0;
  6035.             col_max = table->width_spans;
  6036.             for (x=0; x < table->cols; x++)
  6037.             {
  6038.                 indx = (y * table->cols) + x;
  6039.                 cell_ptr = cell_array[indx].cell;
  6040.                 if ((cell_ptr == blank_cell)||
  6041.                     (cell_ptr == NULL))
  6042.                 {
  6043.                     col_max = col_max->next;
  6044.                     continue;
  6045.                 }
  6046.                 width += cell_ptr->max_width;
  6047.                 col_max = col_max->next;
  6048.             }
  6049.             if (width > new_table_width)
  6050.             {
  6051.                 new_table_width = width;
  6052.             }
  6053.         }
  6054.         row_ptr = row_ptr->next;
  6055.         row_max = row_max->next;
  6056.     }
  6057.  
  6058.     if (*table_width > new_table_width)
  6059.     {
  6060.         new_table_width = *table_width;
  6061.     }
  6062.  
  6063.     /*
  6064.      * If we already know how wide this table must be
  6065.      * Use that width when calculate percentage cell widths.
  6066.      */
  6067.     if ((table->width > 0)&&(table->width >= *min_table_width))
  6068.     {
  6069.         new_table_width = table->width;
  6070.     }
  6071.  
  6072.     need_pass_two = FALSE;
  6073.  
  6074.     col_max = table->width_spans;
  6075.     for (x=0; x < table->cols; x++)
  6076.     {
  6077.         int32 current_max;
  6078.  
  6079.         current_max = col_max->dim;
  6080.         col_max->dim = 1;
  6081.         row_max = table->height_spans;
  6082.         for (y=0; y < table->rows; y++)
  6083.         {
  6084.             indx = (y * table->cols) + x;
  6085.             cell_ptr = cell_array[indx].cell;
  6086.             if ((cell_ptr == blank_cell)||
  6087.                 (cell_ptr == NULL))
  6088.             {
  6089.                 row_max = row_max->next;
  6090.                 continue;
  6091.             }
  6092.             if ((cell_ptr->percent_width > 0)&&
  6093.                 (cell_ptr->colspan == 1))
  6094.             {
  6095.                 int32 p_width;
  6096.  
  6097.                 p_width = new_table_width *
  6098.                     cell_ptr->percent_width / 100;
  6099.                 if (p_width < cell_ptr->min_width)
  6100.                 {
  6101.                     p_width = cell_ptr->min_width;
  6102.                 }
  6103.                 if (p_width > col_max->dim)
  6104.                 {
  6105.                     col_max->dim = p_width;
  6106.                 }
  6107.             }
  6108.             else if (cell_ptr->colspan > 1)
  6109.             {
  6110.                 need_pass_two = TRUE;
  6111.             }
  6112.             else
  6113.             {
  6114.                 if (cell_ptr->max_width > col_max->dim)
  6115.                 {
  6116.                     col_max->dim =
  6117.                         cell_ptr->max_width;
  6118.                 }
  6119.             }
  6120.             row_max = row_max->next;
  6121.         }
  6122.         if (col_max->dim < col_max->min_dim)
  6123.         {
  6124.             col_max->dim = col_max->min_dim;
  6125.         }
  6126.         col_max = col_max->next;
  6127.     }
  6128.     /*
  6129.      * Take care of spanning columns if any
  6130.      */
  6131.     if (need_pass_two != FALSE)
  6132.     {
  6133.         row_max = table->height_spans;
  6134.         for (y=0; y < table->rows; y++)
  6135.         {
  6136.             col_max = table->width_spans;
  6137.             for (x=0; x < table->cols; x++)
  6138.             {
  6139.                 indx = (y * table->cols) + x;
  6140.                 cell_ptr = cell_array[indx].cell;
  6141.                 if ((cell_ptr == blank_cell)||
  6142.                     (cell_ptr == NULL))
  6143.                 {
  6144.                     col_max = col_max->next;
  6145.                     continue;
  6146.                 }
  6147.                 if (cell_ptr->colspan > 1)
  6148.                 {
  6149.                     int32 i;
  6150.                     int32 width;
  6151.                     lo_table_span *max_ptr;
  6152.                     int32 p_width;
  6153.                     int32 new_width;
  6154.  
  6155.                     new_width = cell_ptr->max_width;
  6156.                     if (cell_ptr->percent_width > 0)
  6157.                     {
  6158.                         p_width = new_table_width *
  6159.                             cell_ptr->percent_width / 100;
  6160.                         if (p_width >= cell_ptr->min_width)
  6161.                         {
  6162.                             new_width = p_width;
  6163.                         }
  6164.                     }
  6165.  
  6166.                     max_ptr = col_max;
  6167.  
  6168.                     width = max_ptr->dim;
  6169.                     for (i=1; i < cell_ptr->colspan; i++)
  6170.                     {
  6171.                         max_ptr = max_ptr->next;
  6172.                         width = width + cell_pad +
  6173.                             max_ptr->dim;
  6174.                     }
  6175.  
  6176.                     if (width < new_width)
  6177.                     {
  6178.                         int32 add_width;
  6179.                         int32 add;
  6180.                         lo_table_span *add_ptr;
  6181.  
  6182.                         add_ptr = col_max;
  6183.                         add_width = new_width - width;
  6184.                         add = 0;
  6185.                         while (add_ptr != max_ptr)
  6186.                         {
  6187.                             int32 newWidth;
  6188.  
  6189.                             newWidth = add_width *
  6190.                                 add_ptr->dim /
  6191.                                 width;
  6192.                             add_ptr->dim +=newWidth;
  6193.                             add += newWidth;
  6194.                             add_ptr = add_ptr->next;
  6195.                         }
  6196.                         add_ptr->dim += (add_width -
  6197.                             add);
  6198.                     }
  6199.                 }
  6200.                 col_max = col_max->next;
  6201.             }
  6202.             row_max = row_max->next;
  6203.         }
  6204.     }
  6205.  
  6206.     new_table_width = 0;
  6207.     new_min_table_width = 0;
  6208.     new_base_table_width = 0;
  6209.     new_min_base_table_width = 0;
  6210.     col_max = table->width_spans;
  6211.     while (col_max != NULL)
  6212.     {
  6213.         new_base_table_width += col_max->dim;
  6214.         new_min_base_table_width += col_max->min_dim;
  6215.         new_table_width = new_table_width + cell_pad +
  6216.             col_max->dim;
  6217.         new_min_table_width = new_min_table_width + cell_pad +
  6218.             col_max->min_dim;
  6219.         col_max = col_max->next;
  6220.     }
  6221.     new_table_width += cell_pad;
  6222.     new_table_width += (table->table_ele->border_left_width + 
  6223.         table->table_ele->border_right_width);
  6224.     new_min_table_width += cell_pad;
  6225.     new_min_table_width += (table->table_ele->border_left_width + 
  6226.         table->table_ele->border_right_width);
  6227.     if (table->draw_borders == TABLE_BORDERS_OFF)
  6228.     {
  6229.         new_table_width += (2 * table_pad);
  6230.         new_min_table_width += (2 * table_pad);
  6231.     }
  6232.  
  6233.     *table_width = new_table_width;
  6234.     *min_table_width = new_min_table_width;
  6235.     *base_table_width = new_base_table_width;
  6236.     *min_base_table_width = new_min_base_table_width;
  6237. }
  6238.  
  6239. static void
  6240. lo_cell_relayout_pass(MWContext *context, lo_DocState *state,
  6241.     lo_TableRec *table, lo_cell_data XP_HUGE *cell_array, lo_TableCell *blank_cell,
  6242.     int32 cell_pad, Bool *rowspan_pass, Bool relayout)
  6243. {
  6244.     int32 x, y;
  6245.     int32 indx;
  6246.     lo_table_span *row_max;
  6247.     lo_table_span *col_max;
  6248.     lo_TableRow *row_ptr;
  6249.     lo_TableCell *cell_ptr;
  6250.     int32 top_inner_pad;
  6251.     int32 bottom_inner_pad;
  6252.     int32 left_inner_pad;
  6253.     int32 right_inner_pad;
  6254.  
  6255.     top_inner_pad = FEUNITS_X(table->inner_top_pad, context);
  6256.     bottom_inner_pad = FEUNITS_X(table->inner_bottom_pad, context);
  6257.     left_inner_pad = FEUNITS_X(table->inner_left_pad, context);
  6258.     right_inner_pad = FEUNITS_X(table->inner_right_pad, context);
  6259.  
  6260.     row_ptr = table->row_list;
  6261.     row_max = table->height_spans;
  6262.     for (y=0; y < table->rows; y++)
  6263.     {
  6264.         Bool max_height_valid;
  6265.         Bool changed_row_height;
  6266.         int32 max_row_height;
  6267.             
  6268.         max_height_valid = FALSE;
  6269.         changed_row_height = FALSE;
  6270.         
  6271.         max_row_height = 0;
  6272.         
  6273.         col_max = table->width_spans;
  6274.  
  6275.         for (x=0; x < table->cols; x++)
  6276.         {
  6277.             LO_CellStruct *cell_struct;
  6278.             int32 width;
  6279.             int32 inside_width;
  6280.             Bool has_elements;
  6281.  
  6282.             indx = (y * table->cols) + x;
  6283.             cell_ptr = cell_array[indx].cell;
  6284.             if ((cell_ptr == blank_cell)||
  6285.                 (cell_ptr == NULL))
  6286.             {
  6287.                 col_max = col_max->next;
  6288.                 continue;
  6289.             }
  6290.             cell_struct = cell_ptr->cell;
  6291.             inside_width = col_max->dim;
  6292.             width = inside_width;
  6293.             if (cell_ptr->colspan > 1)
  6294.             {
  6295.                 int32 i;
  6296.                 lo_table_span *max_ptr;
  6297.  
  6298.                 max_ptr = col_max;
  6299.  
  6300.                 /*
  6301.                  * We need to add some cellpads for the spanned cells
  6302.                  * to our inside width
  6303.                  */
  6304.                 inside_width += ( cell_ptr->colspan - 1 ) * cell_pad;
  6305.                 
  6306.                 for (i=1; i < cell_ptr->colspan; i++)
  6307.                 {
  6308.                     max_ptr = max_ptr->next;
  6309.                     inside_width += max_ptr->dim;
  6310.                     width += cell_pad + max_ptr->dim;
  6311.                 }
  6312.             }
  6313.                                     
  6314.             /*
  6315.              * We want to relayout the cell if it's been tagged as
  6316.              * needing it or if it's been layed out to a different size.
  6317.              */
  6318.             if ( (cell_ptr->must_relayout != FALSE) || 
  6319.                 ((width != cell_ptr->max_width)) )
  6320.             {
  6321.                 cell_ptr->must_relayout = FALSE;
  6322.                 
  6323.                 inside_width = inside_width -
  6324.                     (2 * cell_struct->border_width) -
  6325.                     (2 * cell_struct->border_horiz_space) -
  6326.                     (left_inner_pad + right_inner_pad);
  6327.                     
  6328.                 /*
  6329.                  * Don't relayout documents that have no
  6330.                  * elements, it causes errors.
  6331.                  */
  6332.                 has_elements = lo_cell_has_elements(cell_ptr->cell);
  6333.                 if ( has_elements == FALSE )
  6334.                 {
  6335.                     /*
  6336.                      * Simply record our new width in this case.
  6337.                      */
  6338.                      cell_struct->width = inside_width;
  6339.                 }
  6340.                 else
  6341.                 {
  6342.  
  6343.                     cell_struct = lo_RelayoutCell(context, state,
  6344.                         table->current_subdoc, cell_ptr,
  6345.                         cell_struct, inside_width,
  6346.                         cell_ptr->is_a_header, relayout);
  6347.  
  6348.                     if (!cell_struct)    /* temporary fix for crash when cell_struct is null */
  6349.                     {
  6350.                         break;
  6351.                     }
  6352.                     cell_ptr->cell = cell_struct;
  6353.                     cell_ptr->baseline = lo_GetCellBaseline(cell_struct);
  6354.                     
  6355.                     if (cell_ptr->rowspan == 1)
  6356.                     {
  6357.                         int32 tmp_val;
  6358.  
  6359.                         /*
  6360.                          * We have changed the height of a single row cell, so we may need
  6361.                          * to update the row height later.
  6362.                          */
  6363.                         changed_row_height = TRUE;
  6364.                         
  6365.                         tmp_val = cell_ptr->baseline - row_max->min_dim;
  6366.                         if (tmp_val > 0)
  6367.                         {
  6368.                             row_max->min_dim += tmp_val;
  6369.                             if (row_ptr->vert_alignment ==
  6370.                                 LO_ALIGN_BASELINE)
  6371.                             {
  6372.                                 row_max->dim += tmp_val;
  6373.                             }
  6374.                             /*
  6375.                              * Baseline spacing shouldn't grow the
  6376.                              * max height, except for baseline
  6377.                              * aligned rows as above.
  6378.                              */
  6379.                             if (row_max->min_dim > row_max->dim)
  6380.                             {
  6381.                                 row_max->min_dim = row_max->dim;
  6382.                             }
  6383.                         }
  6384.                     }
  6385.                     else
  6386.                     {
  6387.                         *rowspan_pass = TRUE;
  6388.                     }
  6389.                 }
  6390.             }
  6391.             else
  6392.             {
  6393.                 if (cell_ptr->rowspan > 1)
  6394.                 {
  6395.                     *rowspan_pass = TRUE;
  6396.                 }
  6397.             }
  6398.             
  6399.             /*
  6400.              * If this cell has anything inside it, see if it's height
  6401.              * is the biggest for the row.
  6402.              */
  6403.             has_elements = lo_cell_has_elements(cell_ptr->cell);
  6404.             if ( has_elements != FALSE )
  6405.             {
  6406.                 int32 cell_row_height;
  6407.  
  6408.                 /*
  6409.                  * What row height does this cell want?
  6410.                  */
  6411.                 cell_row_height = cell_struct->height +
  6412.                     (top_inner_pad + bottom_inner_pad) +
  6413.                     (2 * cell_struct->border_vert_space);
  6414.                 
  6415.                 /*
  6416.                  * Munge the height if the row is vertically aligned along
  6417.                  * the baseline and the cell only spans one row.
  6418.                  */
  6419.                 if (cell_ptr->rowspan == 1)
  6420.                 {
  6421.                     if (row_ptr->vert_alignment == LO_ALIGN_BASELINE)
  6422.                     {
  6423.                         cell_row_height = (cell_row_height -
  6424.                             cell_ptr->baseline) + row_max->min_dim;
  6425.                     }
  6426.                 
  6427.                     if ( cell_row_height > max_row_height )
  6428.                     {
  6429.                         /*
  6430.                          * Update to our new maximum and flag that it
  6431.                          * contains valid data.
  6432.                          */
  6433.                         max_height_valid = TRUE;
  6434.                         max_row_height = cell_row_height;
  6435.                     }
  6436.                 }
  6437.             }
  6438.             col_max = col_max->next;
  6439.         }
  6440.         
  6441.         /*
  6442.          * If we did relayout anything on that row which gave us a new
  6443.          * valid max row height which is different to what we currently
  6444.          * have, then use that.
  6445.          */
  6446.         if ( max_height_valid != FALSE && changed_row_height != FALSE &&
  6447.             max_row_height != row_max->dim )
  6448.         {
  6449.             /*
  6450.              * Can't reset height to be smaller than
  6451.              * the minimum height.
  6452.              */
  6453.             if (max_row_height >= row_max->min_dim)
  6454.             {
  6455.                 row_max->dim = max_row_height;
  6456.             }
  6457.             else
  6458.             {
  6459.                 row_max->dim = row_max->min_dim;
  6460.             }
  6461.         }
  6462.         row_max = row_max->next;
  6463.         row_ptr = row_ptr->next;
  6464.     }
  6465.  
  6466. }
  6467.  
  6468.  
  6469. static void
  6470. lo_cell_rowspan_pass(MWContext *context, lo_TableRec *table, lo_cell_data XP_HUGE *cell_array,
  6471.     lo_TableCell *blank_cell, int32 cell_pad)
  6472. {
  6473.     int32 x, y;
  6474.     int32 indx;
  6475.     lo_table_span *row_max;
  6476.     lo_table_span *col_max;
  6477.     lo_TableRow *row_ptr;
  6478.     lo_TableCell *cell_ptr;
  6479.     int32 top_inner_pad;
  6480.     int32 bottom_inner_pad;
  6481.  
  6482.     top_inner_pad = FEUNITS_X(table->inner_top_pad, context);
  6483.     bottom_inner_pad = FEUNITS_X(table->inner_bottom_pad, context);
  6484.  
  6485.     row_max = table->height_spans;
  6486.     row_ptr = table->row_list;
  6487.     for (y=0; y < table->rows; y++)
  6488.     {
  6489.         col_max = table->width_spans;
  6490.         for (x=0; x < table->cols; x++)
  6491.         {
  6492.             LO_CellStruct *cell_struct;
  6493.  
  6494.             indx = (y * table->cols) + x;
  6495.             cell_ptr = cell_array[indx].cell;
  6496.             if ((cell_ptr == blank_cell)||
  6497.                 (cell_ptr == NULL))
  6498.             {
  6499.                 col_max = col_max->next;
  6500.                 continue;
  6501.             }
  6502.             cell_struct = cell_ptr->cell;
  6503.  
  6504.             if (cell_ptr->rowspan > 1)
  6505.             {
  6506.                 int32 i;
  6507.                 int32 height;
  6508.                 int32 tmp_val;
  6509.                 int32 cell_height;
  6510.                 lo_table_span *max_ptr;
  6511.  
  6512.                 max_ptr = row_max;
  6513.  
  6514.                 height = max_ptr->dim;
  6515.                 for (i=1; i < cell_ptr->rowspan; i++)
  6516.                 {
  6517.                     max_ptr = max_ptr->next;
  6518.                     height = height + cell_pad +
  6519.                     max_ptr->dim;
  6520.                 }
  6521.                 tmp_val = cell_ptr->baseline -
  6522.                     row_max->min_dim;
  6523.                 if (tmp_val > 0)
  6524.                 {
  6525.                     row_max->min_dim += tmp_val;
  6526.                     if (row_ptr->vert_alignment ==
  6527.                         LO_ALIGN_BASELINE)
  6528.                     {
  6529.                         row_max->dim += tmp_val;
  6530.                         height += tmp_val;
  6531.                     }
  6532.                     /*
  6533.                      * Baseline spacing shouldn't grow the
  6534.                      * max height, except for baseline
  6535.                      * aligned rows as above.
  6536.                      */
  6537.                     if (row_max->min_dim > row_max->dim)
  6538.                     {
  6539.                         row_max->min_dim = row_max->dim;
  6540.                     }
  6541.                 }
  6542.  
  6543.                 cell_height = cell_struct->height +
  6544.                     (top_inner_pad + bottom_inner_pad) +
  6545.                     (2 * cell_struct->border_vert_space);
  6546.  
  6547.                 if (height < cell_height)
  6548.                 {
  6549.                     int32 add_height;
  6550.                     int32 add;
  6551.                     lo_table_span *add_ptr;
  6552.  
  6553.                     add_ptr = row_max;
  6554.                     add_height = cell_height -
  6555.                         height;
  6556.                     add = 0;
  6557.                     while (add_ptr != max_ptr)
  6558.                     {
  6559.                         int32 newHeight;
  6560.  
  6561.                         newHeight = add_height *
  6562.                             add_ptr->dim /
  6563.                             height;
  6564.                         add_ptr->dim +=
  6565.                             newHeight;
  6566.                         add += newHeight;
  6567.                         add_ptr->min_dim = add_ptr->dim;
  6568.                         add_ptr = add_ptr->next;
  6569.                     }
  6570.                     add_ptr->dim +=
  6571.                         (add_height - add);
  6572.                     add_ptr->min_dim = add_ptr->dim;
  6573.                 }
  6574.             }
  6575.             col_max = col_max->next;
  6576.         }
  6577.         row_max = row_max->next;
  6578.         row_ptr = row_ptr->next;
  6579.     }
  6580. }
  6581.  
  6582.  
  6583. static void
  6584. lo_free_cell_record(MWContext *context, lo_DocState *state, lo_TableCell *cell)
  6585. {
  6586.     if (cell == NULL)
  6587.     {
  6588.         return;
  6589.     }
  6590.  
  6591.     /*
  6592.      * If this table cell is not nested inside another table cell
  6593.      * or caption, free any re-parse tags stored on this cell.
  6594.      */
  6595.     if ((cell->in_nested_table == FALSE) &&
  6596.         (cell->subdoc_tags != NULL)&&
  6597.         (state->is_a_subdoc != SUBDOC_CELL)&&
  6598.         (state->is_a_subdoc != SUBDOC_CAPTION))
  6599.     {
  6600.         PA_Tag *tptr;
  6601.         PA_Tag *tag;
  6602.  
  6603.         tptr = cell->subdoc_tags;
  6604.         while ((tptr != cell->subdoc_tags_end)&&(tptr != NULL))
  6605.         {
  6606.             tag = tptr;
  6607.             tptr = tptr->next;
  6608.             tag->next = NULL;
  6609.             PA_FreeTag(tag);
  6610.         }
  6611.         if (tptr != NULL)
  6612.         {
  6613.             tptr->next = NULL;
  6614.             PA_FreeTag(tptr);
  6615.         }
  6616.         cell->subdoc_tags = NULL;
  6617.         cell->subdoc_tags_end = NULL;
  6618.     }
  6619.  
  6620.     if (cell->cell != NULL) {
  6621.         cell->cell->table = NULL;
  6622.         cell->cell->table_row = NULL;
  6623.         cell->cell->table_cell = NULL;
  6624.     }    
  6625.  
  6626.     XP_DELETE(cell);
  6627. }
  6628.  
  6629.  
  6630. static void
  6631.  
  6632. lo_free_row_record(MWContext *context, lo_DocState *state,
  6633.             lo_TableRow *row, Bool partial)
  6634. {
  6635.     lo_TableCell *cell_ptr;
  6636.     lo_TableCell *cell;
  6637.  
  6638.     if (row->cell_list != NULL)
  6639.     {
  6640.         /*
  6641.          * These are already freed on a completed table, and
  6642.          * need to be freed on a partial table.
  6643.          */
  6644.  
  6645.         if (partial != FALSE)
  6646.         {
  6647.             cell_ptr = row->cell_list;
  6648.             while (cell_ptr != NULL)
  6649.             {
  6650.                 cell = cell_ptr;
  6651.                 cell_ptr = cell_ptr->next;
  6652.                 lo_free_cell_record(context, state, cell);
  6653.             }
  6654.         }
  6655.  
  6656.         row->cell_list = NULL;
  6657.         row->cell_ptr = NULL;
  6658.     }
  6659.  
  6660.     XP_FREEIF(row->backdrop.bg_color);
  6661.     XP_FREEIF(row->backdrop.url);
  6662.  
  6663.     XP_DELETE(row);
  6664. }
  6665.  
  6666.  
  6667. static void lo_FreeTableCaption( MWContext *context, lo_DocState *state, lo_TableRec *table )
  6668. {
  6669.     if (table->caption != NULL)
  6670.     {
  6671.         if (table->caption->cell_ele != NULL)
  6672.         {
  6673.             lo_FreeCaptionCell( context, state, table->caption->cell_ele );
  6674.             table->caption->cell_ele = NULL;
  6675.         }
  6676.  
  6677.         if ( table->caption->subdoc != NULL )
  6678.         {
  6679.             lo_FreePartialSubDoc ( context, state, table->caption->subdoc );
  6680.             table->caption->subdoc = NULL;
  6681.         }
  6682.         
  6683.         XP_DELETE(table->caption);
  6684.         table->caption = NULL;
  6685.     }
  6686. }
  6687.  
  6688. void lo_free_table_record(MWContext *context, lo_DocState *state,
  6689.             lo_TableRec *table, Bool partial)
  6690. {
  6691.     if (table->row_list != NULL)
  6692.     {
  6693.         lo_TableRow *row_ptr;
  6694.         lo_TableRow *row;
  6695.  
  6696.         row_ptr = table->row_list;
  6697.         while (row_ptr != NULL)
  6698.         {
  6699.             row = row_ptr;
  6700.             row_ptr = row_ptr->next;
  6701.             lo_free_row_record(context, state, row, partial);
  6702.         }
  6703.         table->row_list = NULL;
  6704.         table->row_ptr = NULL;
  6705.     }
  6706.  
  6707.     lo_FreeTableCaption( context, state, table );
  6708.  
  6709.     if (table->width_spans != NULL)
  6710.     {
  6711.         lo_table_span *span_ptr;
  6712.         lo_table_span *span;
  6713.  
  6714.         span_ptr = table->width_spans;
  6715.         while (span_ptr != NULL)
  6716.         {
  6717.             span = span_ptr;
  6718.             span_ptr = span_ptr->next;
  6719.             XP_DELETE(span);
  6720.         }
  6721.         table->width_spans = NULL;
  6722.         table->width_span_ptr = NULL;
  6723.     }
  6724.  
  6725.     if (table->height_spans != NULL)
  6726.     {
  6727.         lo_table_span *span_ptr;
  6728.         lo_table_span *span;
  6729.  
  6730.         span_ptr = table->height_spans;
  6731.         while (span_ptr != NULL)
  6732.         {
  6733.             span = span_ptr;
  6734.             span_ptr = span_ptr->next;
  6735.             XP_DELETE(span);
  6736.         }
  6737.         table->height_spans = NULL;
  6738.         table->height_span_ptr = NULL;
  6739.     }
  6740.  
  6741.     XP_FREEIF(table->backdrop.bg_color);
  6742.     XP_FREEIF(table->backdrop.url);
  6743.  
  6744.     /*
  6745.      * Whether the partial flag is set or not, we always
  6746.      * want to eliminate this subdoc and all its contents
  6747.      * when the table is done.
  6748.      */
  6749.     if (table->current_subdoc != NULL)
  6750.     {
  6751.         lo_FreePartialSubDoc(context, state, table->current_subdoc);
  6752.         table->current_subdoc = NULL;
  6753.     }
  6754.  
  6755.     if ( table->fixed_col_widths != NULL )
  6756.     {
  6757.         XP_FREE(table->fixed_col_widths);
  6758.     }
  6759.     
  6760.     /*
  6761.      * Reset back pointer in table layout element
  6762.      */
  6763.     if (table->table_ele != NULL) {
  6764.         table->table_ele->table = NULL;
  6765.     }
  6766.  
  6767.     XP_DELETE(table);
  6768. }
  6769.  
  6770.  
  6771.  
  6772. void
  6773. lo_FreePartialTable(MWContext *context, lo_DocState *state, lo_TableRec *table)
  6774. {
  6775.     lo_TableRow *row_ptr;
  6776.     lo_TableCell *cell_ptr;
  6777.     LO_SubDocStruct *subdoc;
  6778.     LO_CellStruct *cell_struct;
  6779.  
  6780.     if (table == NULL)
  6781.     {
  6782.         return;
  6783.     }
  6784.  
  6785.     row_ptr = table->row_list;
  6786.     while (row_ptr != NULL)
  6787.     {
  6788.         cell_ptr = row_ptr->cell_list;
  6789.         while (cell_ptr != NULL)
  6790.         {
  6791.             cell_struct = cell_ptr->cell;
  6792.             lo_FreePartialCell(context, state, cell_struct);
  6793.             cell_ptr->cell = NULL;
  6794.             cell_ptr = cell_ptr->next;
  6795.         }
  6796.         row_ptr = row_ptr->next;
  6797.     }
  6798.  
  6799.     if (table->caption != NULL)
  6800.     {
  6801.         subdoc = table->caption->subdoc;
  6802.         lo_FreePartialSubDoc(context, state, subdoc);
  6803.         table->caption->subdoc = NULL;
  6804.     }
  6805.  
  6806.     lo_free_table_record(context, state, table, TRUE);
  6807. }
  6808.  
  6809.  
  6810.  
  6811. void
  6812. lo_EndTable(MWContext *context, lo_DocState *state, lo_TableRec *table, Bool relayout)
  6813. {
  6814.     int32 save_doc_min_width;
  6815.     int32 x, y;
  6816.     int32 cell_x, cell_y;
  6817.     int32 indx;
  6818.     int32 cell_cnt;
  6819.     int32 ele_cnt;
  6820.     int32 table_width, min_table_width;
  6821.     int32 base_table_width, min_base_table_width;
  6822.     int32 table_height;
  6823.     int32 min_table_height;
  6824.     int32 width_limit;
  6825.     Bool relayout_pass;
  6826.     Bool rowspan_pass;
  6827.     Bool cut_to_window_width;
  6828.     lo_TableCell blank_cell;
  6829.     lo_cell_data XP_HUGE *cell_array;
  6830.     XP_Block cell_array_buff;
  6831.     lo_table_span *row_max;
  6832.     lo_table_span *col_max;
  6833.     lo_TableCell *cell_ptr;
  6834.     int32 cell_pad;
  6835.     int32 top_inner_pad;
  6836.     int32 bottom_inner_pad;
  6837.     int32 left_inner_pad;
  6838.     int32 right_inner_pad;
  6839.     int32 table_pad;
  6840.     Bool floating;
  6841.     int32 save_state_x, save_state_y;
  6842.     LO_Element *save_line_list;
  6843. #ifdef LOCAL_DEBUG
  6844. fprintf(stderr, "lo_EndTable called\n");
  6845. #endif /* LOCAL_DEBUG */
  6846.  
  6847.     cell_pad = FEUNITS_X(table->inter_cell_pad, context);
  6848.     table_pad = FEUNITS_X(TABLE_DEF_CELL_BORDER, context);
  6849.     
  6850.     top_inner_pad = FEUNITS_X(table->inner_top_pad, context);
  6851.     bottom_inner_pad = FEUNITS_X(table->inner_bottom_pad, context);
  6852.     left_inner_pad = FEUNITS_X(table->inner_left_pad, context);
  6853.     right_inner_pad = FEUNITS_X(table->inner_right_pad, context);
  6854.     
  6855.     relayout_pass = FALSE;
  6856.     cut_to_window_width = TRUE;
  6857.     floating = FALSE;
  6858.  
  6859.     /*
  6860.      * So gcc won't complain
  6861.      */
  6862.     save_state_x = 0;
  6863.     save_state_y = 0;
  6864.     save_line_list = NULL;
  6865. /*
  6866.     state->current_table = NULL;
  6867. */
  6868.  
  6869.     cell_cnt = table->rows * table->cols;
  6870.     /*
  6871.      * Empty tables are completely ignored!
  6872.      */
  6873.     if (cell_cnt <= 0)
  6874.     {
  6875.         /*
  6876.          * Clear table state, and free up this structure.
  6877.          */
  6878.         state->current_table = NULL;
  6879.  
  6880.         /* 
  6881.          * Don't wanna free table record any more because this information
  6882.          * is used during relayout.
  6883.          */
  6884.         /*
  6885.         if (table != NULL)
  6886.         {
  6887.             lo_free_table_record(context, state, table, FALSE);
  6888.         }          
  6889.         */
  6890.         return;
  6891.     }
  6892. #ifdef XP_WIN16
  6893.     /*
  6894.      * It had better be the case that the size of the struct is a
  6895.      * power of 2
  6896.      */
  6897.     XP_ASSERT(sizeof(lo_cell_data) == 8);
  6898.     cell_array = (lo_cell_data XP_HUGE *)_halloc(cell_cnt, sizeof(lo_cell_data));
  6899.  
  6900.     /*
  6901.      * There isn't a runtime routine that can initialize a huge array
  6902.      */
  6903.     if (cell_cnt * sizeof(lo_cell_data) <= 0xFFFFL)
  6904.         memset(cell_array, 0, (cell_cnt * sizeof(lo_cell_data)));
  6905.     else {
  6906.         BYTE XP_HUGE *tmp = (BYTE XP_HUGE *)cell_array;
  6907.  
  6908.         for (indx = 0; indx < cell_cnt * sizeof(lo_cell_data); indx++)
  6909.             tmp[indx] = 0;
  6910.     }
  6911. #else
  6912.     cell_array_buff = XP_ALLOC_BLOCK(cell_cnt * sizeof(lo_cell_data));
  6913.     XP_LOCK_BLOCK(cell_array, lo_cell_data *, cell_array_buff);
  6914.     memset(cell_array, 0, (cell_cnt * sizeof(lo_cell_data)));
  6915. #endif
  6916.  
  6917.     lo_fill_cell_array(table, cell_array, &blank_cell, cell_pad,
  6918.         &relayout_pass);
  6919.  
  6920.     table_width = 0;
  6921.     min_table_width = 0;
  6922.     base_table_width = 0;
  6923.     min_base_table_width = 0;
  6924.     col_max = table->width_spans;
  6925.     while (col_max != NULL)
  6926.     {
  6927.         base_table_width += col_max->dim;
  6928.         min_base_table_width += col_max->min_dim;
  6929.         table_width = table_width + cell_pad + col_max->dim;
  6930.         min_table_width = min_table_width + cell_pad + col_max->min_dim;
  6931.         col_max = col_max->next;
  6932.     }
  6933.     table_width += cell_pad;
  6934.     min_table_width += cell_pad;
  6935.     table_width += (table->table_ele->border_left_width + 
  6936.         table->table_ele->border_right_width);
  6937.     min_table_width += (table->table_ele->border_left_width + 
  6938.         table->table_ele->border_right_width);
  6939.     if (table->draw_borders == TABLE_BORDERS_OFF)
  6940.     {
  6941.         table_width += (2 * table_pad);
  6942.         min_table_width += (2 * table_pad);
  6943.     }
  6944.  
  6945.     /*
  6946.      * Take care of cells with percentage widths unless we're in
  6947.      * a fixed layout table (has the COLS attribute) in which case
  6948.      * the cell widths are already set.
  6949.      */
  6950.     if ((table->has_percent_width_cells != FALSE) &&
  6951.         (table->fixed_cols == 0))
  6952.     {
  6953.         lo_percent_width_cells(table, cell_array, &blank_cell,
  6954.             cell_pad, table_pad, &table_width, &min_table_width,
  6955.             &base_table_width, &min_base_table_width);
  6956.         relayout_pass = TRUE;
  6957.     }
  6958.  
  6959.     /*
  6960.      * Use state->left_margin here instead of state->win_left to take
  6961.      * indent from lists into account.
  6962.      */
  6963.     width_limit = (state->win_width - state->left_margin - state->win_right);
  6964.     if (table->width > 0)
  6965.     {
  6966.         width_limit = table->width;
  6967.     }
  6968.     /*
  6969.      * Else, if we are a nested table in an infinite width
  6970.      * layout space, we don't want to cut to "window width"
  6971.      */
  6972.     else if (state->allow_percent_width == FALSE)
  6973.     {
  6974.         cut_to_window_width = FALSE;
  6975.     }
  6976.  
  6977.     /*
  6978.      * If we're in a fixed layout table, then we never
  6979.      * want to cut to "window width" 
  6980.      */
  6981.     if ( table->fixed_cols > 0 )
  6982.     {
  6983.         cut_to_window_width = FALSE;
  6984.     }
  6985.  
  6986.     /*
  6987.      * If the table is too small, we always need to relayout.
  6988.      */
  6989.     if ((min_table_width >= width_limit))
  6990.     {
  6991.         lo_table_span *sub_ptr;
  6992.  
  6993.         relayout_pass = TRUE;
  6994.         sub_ptr = table->width_spans;
  6995.         while (sub_ptr != NULL)
  6996.         {
  6997.             sub_ptr->dim = sub_ptr->min_dim;
  6998.             sub_ptr = sub_ptr->next;
  6999.         }
  7000.     }
  7001.     else if ((table_width > width_limit)&&(cut_to_window_width != FALSE))
  7002.     {
  7003.         intn pass;
  7004.         Bool expand_failed;
  7005.         int32 add_width;
  7006.         int32 div_width;
  7007.         int32 div_width_next;
  7008.         int32 add;
  7009.         int32 total_to_add;
  7010.         lo_table_span *add_ptr;
  7011.  
  7012.         relayout_pass = TRUE;
  7013.  
  7014.         expand_failed = TRUE;
  7015.         pass = 0;
  7016.         total_to_add = width_limit - min_table_width;
  7017.         div_width = table_width;
  7018.         while ((total_to_add > 0)&&(pass < 10)&&(expand_failed !=FALSE))
  7019.         {
  7020.             int32 extra;
  7021.             int32 min_extra;
  7022.  
  7023.             expand_failed = FALSE;
  7024.             add_ptr = table->width_spans;
  7025.             add_width = total_to_add;
  7026.             total_to_add = 0;
  7027.             div_width_next = (table->cols + 1) * cell_pad;
  7028.             add = 0;
  7029.             while (add_ptr->next != NULL)
  7030.             {
  7031.                 if ((pass > 0)&&
  7032.                     (add_ptr->min_dim == add_ptr->dim))
  7033.                 {
  7034.                     add_ptr = add_ptr->next;
  7035.                     continue;
  7036.                 }
  7037.                 extra = add_width * add_ptr->dim /
  7038.                     div_width;
  7039.                 if ((add_ptr->min_dim + extra) > add_ptr->dim)
  7040.                 {
  7041.                     expand_failed = TRUE;
  7042.                     min_extra = add_ptr->dim -
  7043.                         add_ptr->min_dim;
  7044.                     extra = min_extra;
  7045.                 }
  7046.  
  7047.                 add_ptr->min_dim += extra;
  7048.                 if (add_ptr->min_dim < add_ptr->dim)
  7049.                 {
  7050.                     div_width_next += add_ptr->dim;
  7051.                 }
  7052.                 add += extra;
  7053.                 add_ptr = add_ptr->next;
  7054.             }
  7055.             if ((pass == 0)||(add_ptr->min_dim < add_ptr->dim))
  7056.             {
  7057.                 if (expand_failed == FALSE)
  7058.                 {
  7059.                     extra = add_width - add;
  7060.                 }
  7061.                 else
  7062.                 {
  7063.                     extra = add_width * add_ptr->dim /
  7064.                         div_width;
  7065.                 }
  7066.                 if ((add_ptr->min_dim + extra) > add_ptr->dim)
  7067.                 {
  7068.                     expand_failed = TRUE;
  7069.                     min_extra = add_ptr->dim -
  7070.                         add_ptr->min_dim;
  7071.                     extra = min_extra;
  7072.                 }
  7073.                 add_ptr->min_dim += extra;
  7074.                 if (add_ptr->min_dim < add_ptr->dim)
  7075.                 {
  7076.                     div_width_next += add_ptr->dim;
  7077.                 }
  7078.                 add += extra;
  7079.             }
  7080.             total_to_add = add_width - add;
  7081.             div_width = div_width_next;
  7082.             pass++;
  7083.         }
  7084.         if (total_to_add > 0)
  7085.         {
  7086.             add = 0;
  7087.             add_ptr = table->width_spans;
  7088.             while ((add_ptr->next != NULL)&&(total_to_add > 0))
  7089.             {
  7090.                 if ((add_ptr->min_dim + total_to_add) >
  7091.                     add_ptr->dim)
  7092.                 {
  7093.                     add = add_ptr->dim - add_ptr->min_dim;
  7094.                     total_to_add = total_to_add - add;
  7095.                     add_ptr->min_dim += add;
  7096.                 }
  7097.                 else
  7098.                 {
  7099.                     add_ptr->min_dim += total_to_add;
  7100.                     total_to_add = 0;
  7101.                 }
  7102.                 add_ptr = add_ptr->next;
  7103.             }
  7104.             add_ptr->min_dim += total_to_add;
  7105.         }
  7106.  
  7107.         add_ptr = table->width_spans;
  7108.         while (add_ptr != NULL)
  7109.         {
  7110.             add_ptr->dim = add_ptr->min_dim;
  7111.             add_ptr = add_ptr->next;
  7112.         }
  7113.     }
  7114.  
  7115.     /*
  7116.      * If the user specified a wider width than the minimum
  7117.      * width then we grow the sucker.
  7118.      */
  7119.     if ((table->width > 0)&&(width_limit > table_width))
  7120.     {
  7121.         int32 add_width;
  7122.         int32 add;
  7123.         int32 newWidth;
  7124.         int32 min_add_width;
  7125.         int32 min_add;
  7126.         lo_table_span *add_ptr;
  7127.  
  7128.         /* relayout to fill all the space we're adding */
  7129.         relayout_pass = TRUE;
  7130.         
  7131.         add_ptr = table->width_spans;
  7132.         add_width = width_limit - table_width;
  7133.         if ( add_width < 0 )
  7134.         {
  7135.             add_width = 0;
  7136.         }
  7137.         add = 0;
  7138.         min_add_width = width_limit - min_table_width;
  7139.         min_add = 0;
  7140.         while ((add_ptr != NULL)&&(add_ptr->next != NULL))
  7141.         {
  7142.             newWidth = add_width * add_ptr->dim / base_table_width;
  7143.             add_ptr->dim += newWidth;
  7144.             add += newWidth;
  7145.  
  7146.             /*
  7147.              * We only want to resize the min_dim's of the spans
  7148.              * if we're a fixed width table.
  7149.              */
  7150.             if ( table->table_width_fixed )
  7151.             {
  7152.                 newWidth = min_add_width * add_ptr->min_dim / min_base_table_width;
  7153.                 add_ptr->min_dim += newWidth;
  7154.                 min_add += newWidth;
  7155.             }
  7156.             add_ptr = add_ptr->next;
  7157.         }
  7158.         if ( table->table_width_fixed )
  7159.         {
  7160.             add_ptr->min_dim += (min_add_width - min_add);
  7161.         }
  7162.         add_ptr->dim += (add_width - add);
  7163.     }
  7164.  
  7165.     rowspan_pass = FALSE;
  7166.  
  7167.     if ((state->top_state->doc_state == state) ||
  7168.         (state->top_state->in_cell_relayout == TRUE))
  7169.     {
  7170.  
  7171.         if (state->top_state->doc_state == state)
  7172.         {
  7173.             state->top_state->in_cell_relayout = TRUE;
  7174.         }        
  7175.  
  7176.         if (relayout_pass != FALSE)
  7177.         {    
  7178.             lo_cell_relayout_pass(context, state, table, cell_array,
  7179.                 &blank_cell, cell_pad, &rowspan_pass, relayout);    
  7180.         }
  7181.  
  7182.         if (rowspan_pass != FALSE)
  7183.         {
  7184.             lo_cell_rowspan_pass(context, table, cell_array, &blank_cell,
  7185.                 cell_pad);
  7186.         }
  7187.  
  7188.         if (state->top_state->doc_state == state)
  7189.         {
  7190.             state->top_state->in_cell_relayout = FALSE;
  7191.         }
  7192.     }
  7193.  
  7194.     table_width = 0;
  7195.     min_table_width = 0;
  7196.     col_max = table->width_spans;
  7197.     while (col_max != NULL)
  7198.     {
  7199.         table_width = table_width + cell_pad + col_max->dim;
  7200.         min_table_width = min_table_width + cell_pad + col_max->min_dim;
  7201.         col_max = col_max->next;
  7202.     }
  7203.     table_width += cell_pad;
  7204.     table_width += (table->table_ele->border_left_width + 
  7205.         table->table_ele->border_right_width);
  7206.     min_table_width += cell_pad;
  7207.     min_table_width += (table->table_ele->border_left_width + 
  7208.         table->table_ele->border_right_width);
  7209.  
  7210.     table_height = 0;
  7211.     min_table_height = 0;
  7212.     row_max = table->height_spans;
  7213.     while (row_max != NULL)
  7214.     {
  7215.         table_height = table_height + cell_pad + row_max->dim;
  7216.         min_table_height = min_table_height + cell_pad + row_max->min_dim;
  7217.         row_max = row_max->next;
  7218.     }
  7219.     table_height += cell_pad;
  7220.     min_table_height += cell_pad;
  7221.     table_height += (table->table_ele->border_top_width + 
  7222.         table->table_ele->border_bottom_width);
  7223.     min_table_height += (table->table_ele->border_top_width + 
  7224.         table->table_ele->border_bottom_width);
  7225.     if (table->draw_borders == TABLE_BORDERS_OFF)
  7226.     {
  7227.         table_width += (2 * table_pad);
  7228.         min_table_width += (2 * table_pad);
  7229.         table_height += (2 * table_pad);
  7230.         min_table_height += (2 * table_pad);
  7231.     }
  7232.  
  7233.  
  7234.     /*
  7235.      * If the user specified a taller table than the min
  7236.      * height we need to adjust the heights of all the rows.
  7237.      */
  7238.     if ((table->height > 0)&&(table->height > min_table_height))
  7239.     {
  7240.         int32 add_height;
  7241.         int32 add;
  7242.         lo_table_span *add_ptr;
  7243.         int32 newHeight;
  7244.         int32 min_add_height;
  7245.         int32 min_add;
  7246.  
  7247.         add_ptr = table->height_spans;
  7248.         add_height = table->height - table_height;
  7249.         if ( add_height < 0 )
  7250.         {
  7251.             add_height = 0;
  7252.         }
  7253.         min_add_height = table->height - min_table_height;
  7254.         add = 0;
  7255.         min_add = 0;
  7256.         while((add_ptr != NULL) && (add_ptr->next != NULL))
  7257.         {
  7258.             newHeight = add_height * add_ptr->dim / table_height;
  7259.             add_ptr->dim += newHeight;
  7260.             add += newHeight;
  7261.             
  7262.             newHeight = min_add_height * add_ptr->min_dim / table_height;
  7263.             add_ptr->min_dim += newHeight;
  7264.             min_add += newHeight;
  7265.             
  7266.             add_ptr = add_ptr->next;
  7267.         }
  7268.         add_ptr->dim += (add_height - add);
  7269.         add_ptr->min_dim += (min_add_height - min_add);
  7270.  
  7271.         /*
  7272.          * We can't make the height be less than the sum
  7273.          * of the row heights.
  7274.          */
  7275.         if (table_height < table->height)
  7276.         {
  7277.             table_height = table->height;
  7278.         }
  7279.         min_table_height = table->height;
  7280.     }
  7281.  
  7282.     table->table_ele->width = table_width;
  7283.     table->table_ele->height = table_height;
  7284.  
  7285.     /*
  7286.      * Here, if we are floating we don't do the linebreak.
  7287.      * We do save some state info and then "fake" a linebreak
  7288.      * so we can use common code to place the rest of the table.
  7289.      */
  7290.     if (table->table_ele->ele_attrmask & LO_ELE_FLOATING)
  7291.     {
  7292.         save_line_list = state->line_list;
  7293.         save_state_x = state->x;
  7294.         save_state_y = state->y;
  7295.         floating = TRUE;
  7296.         state->x = state->left_margin;
  7297.         state->y = state->y + state->line_height;
  7298.         state->line_list = NULL;
  7299.     }
  7300.     else
  7301.     {
  7302.         /*
  7303.         lo_SetSoftLineBreakState(context, state, FALSE, 1);
  7304.         */
  7305.         lo_SetLineBreakState ( context, state, FALSE, LO_LINEFEED_BREAK_SOFT, 1, relayout );
  7306.     }
  7307.  
  7308.     table->table_ele->x = state->x;
  7309.     table->table_ele->y = state->y;
  7310.     /* Keep the element IDs in order */
  7311.     table->table_ele->ele_id = NEXT_ELEMENT;
  7312.     
  7313.     /*cmanske - Save spacing param for drawing table selection in Composer */
  7314.     table->table_ele->inter_cell_space = table->inter_cell_pad;
  7315.  
  7316.     lo_AppendToLineList(context, state,
  7317.         (LO_Element *)table->table_ele, 0);
  7318.  
  7319. #ifdef EDITOR
  7320.     /*cmanske - build list of tables we are laying out
  7321.      * so Editor can readjust it's data after all is finished 
  7322.      */
  7323.     EDT_AddToRelayoutTables(context, table->table_ele);
  7324. #endif
  7325.  
  7326.     state->x += (cell_pad + table->table_ele->border_left_width);
  7327.     state->y += (cell_pad + table->table_ele->border_top_width);
  7328.     if (table->draw_borders == TABLE_BORDERS_OFF)
  7329.     {
  7330.         state->x += table_pad;
  7331.         state->y += table_pad;
  7332.     }
  7333.  
  7334.     if (table->caption != NULL)
  7335.     {
  7336.         int32 new_width;
  7337.         LO_SubDocStruct *subdoc;
  7338.         Bool has_elements;
  7339.  
  7340.         subdoc = table->caption->subdoc;
  7341.  
  7342.         col_max = table->width_spans;
  7343.         new_width = col_max->dim;
  7344.         while (col_max->next != NULL)
  7345.         {
  7346.             col_max = col_max->next;
  7347.             new_width = new_width + cell_pad + col_max->dim;
  7348.         }
  7349.         /*
  7350.          * Don't relayout documents that have no
  7351.          * elements, it causes errors.
  7352.          */
  7353.         has_elements = lo_subdoc_has_elements(subdoc->state);
  7354.         if ((new_width < table->caption->max_width)&&
  7355.             (has_elements == FALSE))
  7356.         {
  7357.             int32 inside_width;
  7358.  
  7359.             inside_width = new_width -
  7360.                 (2 * subdoc->border_width) -
  7361.                 (2 * subdoc->border_horiz_space) -
  7362.                 (left_inner_pad + right_inner_pad);
  7363.             subdoc->width = inside_width;
  7364.         }
  7365.         else /* if (new_width < table->caption->max_width) */
  7366.         {
  7367.             int32 inside_width;
  7368.  
  7369.             inside_width = new_width -
  7370.                 (2 * subdoc->border_width) -
  7371.                 (2 * subdoc->border_horiz_space) -
  7372.                 (left_inner_pad + right_inner_pad);
  7373.             table->caption->subdoc = lo_RelayoutCaptionSubdoc(context,
  7374.                 state, table->caption, subdoc, inside_width, FALSE);
  7375.             subdoc = table->caption->subdoc;
  7376.  
  7377.             table->caption->height = subdoc->height +
  7378.                 (2 * subdoc->border_vert_space) +
  7379.                 (top_inner_pad + bottom_inner_pad);
  7380.             table->caption->max_width = new_width;
  7381.         }
  7382.         /*
  7383.         else
  7384.         {
  7385.             table->caption->max_width = new_width;
  7386.         }
  7387.         */
  7388.     }
  7389.  
  7390.     state->current_table = NULL;
  7391.     cell_x = state->x;
  7392.     cell_y = state->y;
  7393.  
  7394.     if ((table->caption != NULL)&&
  7395.         (table->caption->vert_alignment == LO_ALIGN_TOP))
  7396.     {
  7397.         LO_SubDocStruct *subdoc;
  7398.  
  7399.         cell_x = state->x;
  7400.         subdoc = table->caption->subdoc;
  7401.         subdoc->x = cell_x;
  7402.         subdoc->y = table->table_ele->y;
  7403.         subdoc->x_offset = (int16)subdoc->border_horiz_space;
  7404.         subdoc->y_offset = (int32)subdoc->border_vert_space;
  7405.         subdoc->width = table->caption->max_width -
  7406.             (2 * subdoc->border_horiz_space);
  7407.         subdoc->height = table->caption->height -
  7408.             (2 * subdoc->border_vert_space);
  7409.         ele_cnt = lo_align_subdoc(context, state,
  7410.             (lo_DocState *)subdoc->state, subdoc, table, NULL);
  7411.         if (ele_cnt > 0)
  7412.         {
  7413.             LO_CellStruct *cell_ele;
  7414.             
  7415.             if (relayout == FALSE)
  7416.             {
  7417.                 /*
  7418.                 cell_ele = lo_SquishSubDocToCell(context, state,
  7419.                     subdoc, TRUE);
  7420.                 */
  7421.                 cell_ele = lo_SquishSubDocToCell(context, state,
  7422.                     subdoc, FALSE);
  7423.                 cell_ele->isCaption = TRUE;
  7424.                 table->caption->cell_ele = cell_ele;
  7425.             }
  7426.             else
  7427.             {
  7428.                 cell_ele = table->caption->cell_ele;
  7429.                 lo_UpdateCaptionCellFromSubDoc(context, state, subdoc, cell_ele);
  7430.             }
  7431.             /* table->caption->subdoc = NULL; */
  7432.  
  7433.             if (cell_ele == NULL)
  7434.             {
  7435.                 lo_AppendToLineList(context, state,
  7436.                     (LO_Element *)subdoc, 0);
  7437.             }
  7438.             else
  7439.             {
  7440.                 /*cmanske - Save spacing param for drawing cell selection by FEs */
  7441.                 /* should we use cell_pad (converted to FE units) instead? */
  7442.                 cell_ele->inter_cell_space = table->inter_cell_pad;
  7443.                 lo_AppendToLineList(context, state,
  7444.                     (LO_Element *)cell_ele, 0);
  7445.             }
  7446.             cell_x = state->x;
  7447.             cell_y = cell_y + table->caption->height + cell_pad;
  7448.  
  7449.             table->table_ele->y_offset = cell_y -
  7450.                 table->table_ele->y;
  7451.             cell_y += (cell_pad + table->table_ele->border_top_width);
  7452.             if (table->draw_borders == TABLE_BORDERS_OFF)
  7453.             {
  7454.                 cell_y += table_pad;
  7455.             }
  7456.         }
  7457.         else
  7458.         {
  7459.             LO_CellStruct *cell_ele;
  7460.  
  7461.             /*
  7462.              * Free up the useless subdoc
  7463.              */
  7464.             cell_ele = lo_SquishSubDocToCell(context, state,
  7465.                         subdoc, TRUE);
  7466.             table->caption->subdoc = NULL;
  7467.  
  7468.             if (cell_ele != NULL)
  7469.             {
  7470.                 lo_FreeElement(context,
  7471.                     (LO_Element *)cell_ele, TRUE);
  7472.             }
  7473.         }
  7474.     }
  7475.  
  7476.     row_max = table->height_spans;
  7477.     for (y=0; y < table->rows; y++)
  7478.     {
  7479.         cell_x = state->x;
  7480.         col_max = table->width_spans;
  7481.         for (x=0; x < table->cols; x++)
  7482.         {
  7483.             LO_CellStruct *cell_struct;
  7484.             int32 new_x, new_y;
  7485.  
  7486.             indx = (y * table->cols) + x;
  7487.             cell_ptr = cell_array[indx].cell;
  7488.             if ((cell_ptr == &blank_cell)||(cell_ptr == NULL))
  7489.             {
  7490.                 cell_x = cell_x + col_max->dim + cell_pad;
  7491.                 col_max = col_max->next;
  7492.                 continue;
  7493.             }
  7494.             cell_struct = cell_ptr->cell;
  7495. /*
  7496.             cell_struct->x = cell_x;
  7497.             cell_struct->y = cell_y;
  7498.             cell_struct->x_offset = (int16)cell_struct->border_horiz_space;
  7499.             cell_struct->y_offset = (int32)cell_struct->border_vert_space;
  7500. */
  7501.  
  7502.             new_x = cell_x + (int16)cell_struct->border_horiz_space + cell_struct->border_width;
  7503.             new_y = cell_y + (int32)cell_struct->border_vert_space + cell_struct->border_width;
  7504.  
  7505.             cell_struct->width = col_max->dim;
  7506.             if (cell_ptr->colspan > 1)
  7507.             {
  7508.                 int32 i;
  7509.                 lo_table_span *max_ptr;
  7510.  
  7511.                 max_ptr = col_max;
  7512.  
  7513.                 for (i=1; i < cell_ptr->colspan; i++)
  7514.                 {
  7515.                     max_ptr = max_ptr->next;
  7516.                     cell_struct->width = cell_struct->width +
  7517.                         cell_pad + max_ptr->dim;
  7518.                 }
  7519.             }
  7520.             cell_struct->width = cell_struct->width -
  7521.                 (2 * cell_struct->border_horiz_space);
  7522.             cell_struct->height = row_max->dim;
  7523.             if (cell_ptr->rowspan > 1)
  7524.             {
  7525.                 int32 i;
  7526.                 lo_table_span *max_ptr;
  7527.  
  7528.                 max_ptr = row_max;
  7529.  
  7530.                 for (i=1; i < cell_ptr->rowspan; i++)
  7531.                 {
  7532.                     max_ptr = max_ptr->next;
  7533.                     cell_struct->height = cell_struct->height +
  7534.                         cell_pad + max_ptr->dim;
  7535.                 }
  7536.             }
  7537.             cell_struct->height = cell_struct->height -
  7538.                 (2 * cell_struct->border_vert_space);
  7539.  
  7540.             lo_ShiftCell(cell_struct,
  7541.                 cell_ptr->cell_base_x, cell_ptr->cell_base_y);
  7542.             cell_ptr->cell_base_x = 0;
  7543.             cell_ptr->cell_base_y = 0;
  7544.             ele_cnt = lo_align_cell(context, state, cell_ptr,
  7545.                     cell_struct, table, row_max);
  7546.             /*
  7547.             if (ele_cnt > 0)
  7548.             */
  7549.             {
  7550.                 LO_CellStruct *cell_ele;
  7551.                 int32 shift_x, shift_y;
  7552.  
  7553.  
  7554.  
  7555.                 shift_x = new_x - cell_struct->x -
  7556.                     cell_struct->x_offset -
  7557.                     cell_struct->border_width;
  7558.                 shift_y = new_y - cell_struct->y -
  7559.                     cell_struct->y_offset -
  7560.                     cell_struct->border_width;
  7561.                 cell_struct->x = cell_x;
  7562.                 cell_struct->y = cell_y;
  7563.                 cell_struct->x_offset = (int16)cell_struct->border_horiz_space;
  7564.                 cell_struct->y_offset = (int32)cell_struct->border_vert_space;
  7565.                 cell_ele = cell_struct;
  7566.  
  7567. /*
  7568.                 lo_ShiftCell(cell_ele, shift_x, shift_y);
  7569. */
  7570.                 lo_ShiftCell(cell_ele, new_x, new_y);
  7571.                 /*
  7572.                  * Keep element ids sequential.
  7573.                  */
  7574.                 if (cell_ele != NULL)
  7575.                 {
  7576.                     cell_ele->ele_id = NEXT_ELEMENT;
  7577.                     lo_RenumberCell(state, cell_ele);
  7578.                 }
  7579.  
  7580.                 if (cell_ele == NULL)
  7581.                 {
  7582.                     lo_AppendToLineList(context, state,
  7583.                         (LO_Element *)cell_struct, 0);
  7584.                 }
  7585.                 else
  7586.                 {
  7587.                     /*cmanske - Save spacing param for drawing cell selection by FEs */
  7588.                     cell_ele->inter_cell_space = table->inter_cell_pad;
  7589.                     lo_AppendToLineList(context, state,
  7590.                         (LO_Element *)cell_ele, 0);
  7591.                 }
  7592.  
  7593.                 if ( relayout == FALSE )
  7594.                 {
  7595.                     /*
  7596.                      * Cell backgrounds now sit in their own layer. This is needed
  7597.                      * for selection to work correctly.
  7598.                      * Cell backgrounds can exist in the main _BODY layer,
  7599.                      * so we need to special case the parent layer of the
  7600.                      * cell background,
  7601.                      */
  7602.                     if (context->compositor &&
  7603.                         (cell_ele->backdrop.bg_color || cell_ele->backdrop.url))
  7604.                     {
  7605.                         lo_TopState *top_state = state->top_state;
  7606.                         CL_Layer *parent_layer = lo_CurrentLayer(state);
  7607.                         if (parent_layer == top_state->doc_layer)
  7608.                             parent_layer = top_state->body_layer;
  7609.                         cell_ele->cell_bg_layer =
  7610.                             lo_CreateCellBackgroundLayer(context, cell_ele,
  7611.                                                          parent_layer);
  7612.                     }
  7613.                     else
  7614.                     {
  7615.                         cell_ele->cell_bg_layer = NULL;
  7616.                     }
  7617.                 }
  7618.             }
  7619.             /*
  7620.             else
  7621.             {
  7622.             */
  7623.                 /*
  7624.                 LO_CellStruct *cell_ele;
  7625.                 */
  7626.                 /*
  7627.                  * Free up the useless cell
  7628.                  */            
  7629.             /*
  7630.                 cell_ele = cell_struct;
  7631.                 if (cell_ele != NULL)
  7632.                 {
  7633.                     lo_FreeElement(context,
  7634.                         (LO_Element *)cell_ele, TRUE);
  7635.                 }
  7636.                 
  7637.             }
  7638.             */
  7639.             cell_x = cell_x + col_max->dim + cell_pad;
  7640.             col_max = col_max->next;
  7641.         }
  7642.         cell_y = cell_y + row_max->dim + cell_pad;
  7643.         row_max = row_max->next;
  7644.     }
  7645.     cell_x = cell_x + table->table_ele->border_left_width;
  7646.     cell_y = cell_y + table->table_ele->border_top_width;
  7647.     if (table->draw_borders == TABLE_BORDERS_OFF)
  7648.     {
  7649.         cell_x += table_pad;
  7650.         cell_y += table_pad;
  7651.     }
  7652.  
  7653.     if ((table->caption != NULL)&&
  7654.         (table->caption->vert_alignment != LO_ALIGN_TOP))
  7655.     {
  7656.         LO_SubDocStruct *subdoc;
  7657.  
  7658.         subdoc = table->caption->subdoc;
  7659.         subdoc->x = state->x;
  7660.         subdoc->y = cell_y;
  7661.         subdoc->x_offset = (int16)subdoc->border_horiz_space;
  7662.         subdoc->y_offset = (int32)subdoc->border_vert_space;
  7663.         subdoc->width = table->caption->max_width -
  7664.             (2 * subdoc->border_horiz_space);
  7665.         subdoc->height = table->caption->height -
  7666.             (2 * subdoc->border_vert_space);
  7667.         ele_cnt = lo_align_subdoc(context, state,
  7668.             (lo_DocState *)subdoc->state, subdoc, table, NULL);
  7669.         if (ele_cnt > 0)
  7670.         {
  7671.             LO_CellStruct *cell_ele;
  7672.  
  7673.             if (relayout == FALSE)
  7674.             {
  7675.                 /*
  7676.                 cell_ele = lo_SquishSubDocToCell(context, state,
  7677.                         subdoc, TRUE);
  7678.                 */
  7679.                 cell_ele = lo_SquishSubDocToCell(context, state,
  7680.                         subdoc, FALSE);
  7681.                 cell_ele->isCaption = TRUE;
  7682.                 table->caption->cell_ele = cell_ele;
  7683.             }
  7684.             else 
  7685.             {
  7686.                 cell_ele = table->caption->cell_ele;
  7687.                 lo_UpdateCaptionCellFromSubDoc(context, state, subdoc, cell_ele);
  7688.             }
  7689.             
  7690.             /* table->caption->subdoc = NULL; */
  7691.  
  7692.             if (cell_ele == NULL)
  7693.             {
  7694.                 lo_AppendToLineList(context, state,
  7695.                     (LO_Element *)subdoc, 0);
  7696.             }
  7697.             else
  7698.             {
  7699.                 /*cmanske - Save spacing param for drawing cell selection by FEs */
  7700.                 cell_ele->inter_cell_space = table->inter_cell_pad;
  7701.                 lo_AppendToLineList(context, state,
  7702.                     (LO_Element *)cell_ele, 0);
  7703.             }
  7704.             cell_y = cell_y + table->caption->height + cell_pad;
  7705.         }
  7706.         else
  7707.         {
  7708.             LO_CellStruct *cell_ele;
  7709.  
  7710.             /*
  7711.              * Free up the useless subdoc
  7712.              */
  7713.             cell_ele = lo_SquishSubDocToCell(context, state,
  7714.                         subdoc, TRUE);
  7715.             table->caption->subdoc = NULL;
  7716.             
  7717.             if (cell_ele != NULL)
  7718.             {
  7719.                 lo_FreeElement(context,
  7720.                     (LO_Element *)cell_ele, TRUE);
  7721.             }
  7722.         }
  7723.     }
  7724.  
  7725.     /*
  7726.      * This table may have contained named anchors.
  7727.      * This will correct their positions in the name_list,
  7728.      * and unblock us if we were blocked on them.
  7729.      */
  7730.     lo_CheckNameList(context, state, table->table_ele->ele_id);
  7731.  
  7732.     /*
  7733.      * The usual stuff for a table.
  7734.      */
  7735.     if (floating == FALSE)
  7736.     {
  7737.         lo_AlignStack *aptr;
  7738.         int32 indent;
  7739.  
  7740.         state->x = cell_x;
  7741.         state->baseline = 0;
  7742.         state->line_height = cell_y - state->y;
  7743.         state->linefeed_state = 0;
  7744.         state->at_begin_line = FALSE;
  7745.         state->trailing_space = FALSE;
  7746.         state->cur_ele_type = LO_SUBDOC;
  7747.  
  7748.         table->table_ele->line_height = state->line_height;
  7749.  
  7750.         /*
  7751.          * Find how far the table might be indented from
  7752.          * being inside a list.
  7753.          */
  7754.         indent = state->list_stack->old_left_margin - state->win_left;
  7755.         if (indent < 0)
  7756.         {
  7757.             indent = 0;
  7758.         }
  7759.  
  7760.         save_doc_min_width = state->min_width;
  7761.         if (relayout == FALSE) 
  7762.         {
  7763.             lo_SoftLineBreak(context, state, FALSE);
  7764.         }
  7765.         else
  7766.         {
  7767.             lo_rl_AddBreakAndFlushLine( context, state, LO_LINEFEED_BREAK_SOFT, LO_CLEAR_NONE, FALSE );
  7768.         }
  7769.  
  7770.         if ((min_table_width + indent) > save_doc_min_width)
  7771.         {
  7772.             save_doc_min_width = min_table_width + indent;
  7773.         }
  7774.         state->min_width = save_doc_min_width;
  7775.         
  7776.         /*
  7777.          * Pop the table's alignment.
  7778.          */
  7779.         aptr = lo_PopAlignment(state);
  7780.         if (aptr != NULL)
  7781.         {
  7782.             XP_DELETE(aptr);
  7783.         }
  7784.     }
  7785.     /*
  7786.      * Else this is a floating table, rip it out of the "faked"
  7787.      * line list, stuff itin the margin, and restore our state
  7788.      * to where we left off.
  7789.      */
  7790.     else
  7791.     {
  7792.         int32 push_right;
  7793.         int32 line_height;
  7794.                 LO_Element *tptr;
  7795.                 LO_Element *last;
  7796.  
  7797.         line_height = cell_y - state->y;
  7798.         push_right = 0;
  7799.         if (table->table_ele->alignment == LO_ALIGN_RIGHT)
  7800.         {
  7801.             push_right = state->right_margin - cell_x;
  7802.         }
  7803.  
  7804.         table->table_ele->x_offset +=
  7805.             (int16)table->table_ele->border_horiz_space;
  7806.         table->table_ele->y_offset +=
  7807.             (int32)table->table_ele->border_vert_space;
  7808.  
  7809.         last = NULL;
  7810.         tptr = state->line_list;
  7811.         while (tptr != NULL)
  7812.         {
  7813.             tptr->lo_any.x += push_right;
  7814.             if (tptr->type == LO_CELL)
  7815.             {
  7816.                 tptr->lo_any.x +=
  7817.                     table->table_ele->border_horiz_space;
  7818.                 tptr->lo_any.y +=
  7819.                     table->table_ele->border_vert_space;
  7820.                 lo_ShiftCell((LO_CellStruct *)tptr,
  7821.                     (push_right +
  7822.                     table->table_ele->border_horiz_space),
  7823.                     table->table_ele->border_vert_space);
  7824.             }
  7825.             last = tptr;
  7826.             tptr->lo_any.line_height = line_height;
  7827.             tptr = tptr->lo_any.next;
  7828.         }
  7829.  
  7830.         /*
  7831.          * Stuff the whole line list into the float list, and
  7832.          * restore the line list to its pre-table state.
  7833.          */
  7834.         if (state->line_list != NULL)
  7835.         {
  7836.             last->lo_any.next = state->float_list;
  7837.             state->float_list = state->line_list;
  7838.             state->line_list = NULL;
  7839.         }
  7840.  
  7841.         if (relayout == FALSE)
  7842.         {
  7843.             lo_AppendFloatInLineList(state, (LO_Element *)table->table_ele, save_line_list );
  7844.         }
  7845.         else
  7846.         {
  7847.             state->line_list = save_line_list;
  7848.         }
  7849.         
  7850.  
  7851.         table->table_ele->line_height = line_height;
  7852.         table->table_ele->expected_y = table->table_ele->y;
  7853.         table->table_ele->y = -1;
  7854.  
  7855.         lo_AddMarginStack(state,
  7856.             table->table_ele->x, table->table_ele->y,
  7857.                         table->table_ele->width, table->table_ele->line_height,
  7858.                         table->table_ele->border_left_width + 
  7859.                             table->table_ele->border_right_width,
  7860.                         table->table_ele->border_vert_space,
  7861.             table->table_ele->border_horiz_space,
  7862.                         (intn)table->table_ele->alignment);
  7863.  
  7864.         /*
  7865.          * Restore state to pre-table values.
  7866.          */
  7867.         state->x = save_state_x;
  7868.         state->y = save_state_y;
  7869.  
  7870.         /*
  7871.          * All the doc_min_width stuff makes state->min_width
  7872.          * be correct for tables nested inside tables.
  7873.          */
  7874.         save_doc_min_width = state->min_width;
  7875.  
  7876.         /*
  7877.          * Standard float stuff, if we happen to be at the start
  7878.          * of a line, place the table now.
  7879.          */
  7880.         if (state->at_begin_line != FALSE)
  7881.         {
  7882.             lo_FindLineMargins(context, state, (! relayout));
  7883.             state->x = state->left_margin;
  7884.         }
  7885.  
  7886.         if (min_table_width > save_doc_min_width)
  7887.         {
  7888.             save_doc_min_width = min_table_width;
  7889.         }
  7890.         state->min_width = save_doc_min_width;
  7891.  
  7892.     }
  7893.  
  7894.     /*  Now cell records get freed when the LO_TABLE element in the line list gets recycled
  7895.     for (y=0; y < table->rows; y++)
  7896.     {
  7897.         for (x=0; x < table->cols; x++)
  7898.         {
  7899.             indx = (y * table->cols) + x;
  7900.             cell_ptr = cell_array[indx].cell;
  7901.             if ((cell_ptr != &blank_cell)&&(cell_ptr != NULL))
  7902.             {
  7903.                 lo_free_cell_record(context, state, cell_ptr);
  7904.             }
  7905.         }
  7906.     }
  7907.     */
  7908.  
  7909.     
  7910. #ifdef XP_WIN16
  7911.     _hfree(cell_array);
  7912. #else
  7913.     XP_UNLOCK_BLOCK(cell_array_buff);
  7914.     XP_FREE_BLOCK(cell_array_buff);
  7915. #endif
  7916.  
  7917.     /* 
  7918.      * Don't wanna free the table record any more because this information
  7919.      * is used during relayout.
  7920.      */
  7921.     /*
  7922.  
  7923.     lo_free_table_record(context, state, table, FALSE);
  7924.  
  7925.     */
  7926. }
  7927.  
  7928. /*
  7929.  * This function relaysout the tags in a table cell. It knows how to handle
  7930.  * certain types of elements that can be resused directly rather than thrown
  7931.  * away and relayedout from scratch (the default case).
  7932.  */
  7933. void
  7934. lo_RelayoutTags(MWContext *context, lo_DocState *state, PA_Tag * tag_ptr,
  7935.     PA_Tag * tag_end_ptr, LO_Element * elem_list)
  7936. {
  7937.     PA_Tag * next_tag;
  7938.     Bool save_diff_state;
  7939.     int32 save_state_pushes;
  7940.     int32 save_state_pops;
  7941.     lo_TopState *top_state;
  7942.     PA_Tag *tag_list;
  7943.     
  7944.     next_tag = NULL;
  7945.     top_state = state->top_state;
  7946.  
  7947.     /*
  7948.      * Save our parent's state levels
  7949.      */
  7950.     save_diff_state = top_state->diff_state;
  7951.     save_state_pushes = top_state->state_pushes;
  7952.     save_state_pops = top_state->state_pops;
  7953.  
  7954.     while (tag_ptr != tag_end_ptr)
  7955.     {
  7956.         PA_Tag *tag;
  7957.         lo_DocState *sub_state;
  7958.         lo_DocState *up_state;
  7959.         lo_DocState *tmp_state;
  7960.         Bool may_save;
  7961.  
  7962.         tag = tag_ptr;
  7963.         tag_ptr = tag_ptr->next;
  7964.         tag->next = NULL;
  7965.         tag_list = tag_ptr;
  7966.  
  7967.         up_state = NULL;
  7968.         sub_state = state;
  7969.         while (sub_state->sub_state != NULL)
  7970.         {
  7971.             up_state = sub_state;
  7972.             sub_state = sub_state->sub_state;
  7973.         }
  7974.  
  7975.         if ((sub_state->is_a_subdoc == SUBDOC_CELL)||
  7976.             (sub_state->is_a_subdoc == SUBDOC_CAPTION))
  7977.         {
  7978.             may_save = TRUE;
  7979.         }
  7980.         else
  7981.         {
  7982.             may_save = FALSE;
  7983.         }
  7984.  
  7985.         /*
  7986.          * Reset these so we can tell if anything happened
  7987.          */
  7988.         top_state->diff_state = FALSE;
  7989.         top_state->state_pushes = 0;
  7990.         top_state->state_pops = 0;
  7991.  
  7992. #ifdef MOCHA
  7993.         sub_state->in_relayout = TRUE;
  7994. #endif
  7995.         /*
  7996.          * If we're not currently searching for a tag, then find the next
  7997.          * one to look for.
  7998.          */
  7999.         if ( next_tag == NULL && elem_list != NULL )
  8000.         {
  8001.             next_tag = lo_FindReuseableElement ( context, state, &elem_list );
  8002.         }
  8003.                 
  8004.         /*
  8005.          * Can we reuse this current element?
  8006.          */
  8007.         if ( (tag == next_tag) && (elem_list != NULL) )
  8008.         {            
  8009.             LO_Element *eptr;
  8010.             LO_Element *enext;
  8011.             
  8012.             /*
  8013.              * Yup, remove it from the list and call the object layout code to
  8014.              * do the relayout.
  8015.              */
  8016.             eptr = elem_list;
  8017.             enext = eptr->lo_any.next;
  8018.             
  8019.             elem_list = enext;
  8020.             
  8021.             if ( enext != NULL )
  8022.             {
  8023.                 enext->lo_any.prev = NULL;
  8024.             }
  8025.             
  8026.             eptr->lo_any.next = 0L;
  8027.             eptr->lo_any.prev = 0L;
  8028.             
  8029.             switch ( eptr->type )
  8030.             {
  8031.                 case LO_EMBED:
  8032.                     lo_RelayoutEmbed ( context, sub_state, &eptr->lo_embed, tag );
  8033.                     break;
  8034. #ifdef JAVA
  8035.                 case LO_JAVA:
  8036.                     lo_RelayoutJavaApp ( context, sub_state, tag, &eptr->lo_java );
  8037.                     break;
  8038. #endif /* JAVA */
  8039.                 
  8040.                 default:
  8041.                     /*
  8042.                      * We goofed and got something we don't know how to relayout
  8043.                      */
  8044.                     lo_relayout_recycle ( context, state, eptr );
  8045.                     lo_LayoutTag(context, sub_state, tag);
  8046.                     break;
  8047.             }
  8048.             
  8049.             /*
  8050.              * Force us to look for the next reusable element.
  8051.              */
  8052.             next_tag = NULL;
  8053.         }
  8054.         else
  8055.         {
  8056.             /*
  8057.              * Nope, call the standard layout code.
  8058.              */
  8059.             lo_LayoutTag(context, sub_state, tag);
  8060.         }
  8061.  
  8062.         tmp_state = lo_CurrentSubState(state);
  8063. #ifdef MOCHA
  8064.         if (tmp_state == sub_state)
  8065.         {
  8066.             sub_state->in_relayout = FALSE;
  8067.         }
  8068. #endif
  8069.  
  8070.         tmp_state = lo_CurrentSubState(state);
  8071. #ifdef MOCHA
  8072.         if (tmp_state == sub_state)
  8073.         {
  8074.             sub_state->in_relayout = FALSE;
  8075.         }
  8076. #endif
  8077.  
  8078.         if (may_save != FALSE)
  8079.         {
  8080.             int32 state_diff;
  8081.             
  8082.             /* how has our state level changed? */
  8083.             state_diff = top_state->state_pushes - top_state->state_pops;
  8084.             
  8085.             /*
  8086.              * That tag popped us up one state level.  If this new
  8087.              * state is still a subdoc, save the tag there.
  8088.              */
  8089.             if (state_diff == -1)
  8090.             {
  8091.                 if ((tmp_state->is_a_subdoc == SUBDOC_CELL)||
  8092.                     (tmp_state->is_a_subdoc == SUBDOC_CAPTION))
  8093.                 {
  8094.                     /* if we just popped a table we need to insert
  8095.                      * a dummy end tag to pop the dummy start tag
  8096.                      * we shove on the stack after createing a table
  8097.                      */
  8098.                        PA_Tag *new_tag = LO_CreateStyleSheetDummyTag(tag);
  8099.                     if(new_tag)
  8100.                     {
  8101.                         lo_SaveSubdocTags(context, tmp_state, new_tag);
  8102.                     }
  8103.  
  8104.                     lo_SaveSubdocTags(context, tmp_state, tag);
  8105.                 }
  8106.                 else
  8107.                 {
  8108.                     PA_FreeTag(tag);
  8109.                 }
  8110.             }
  8111.             /*
  8112.              * Else that tag put us in a new subdoc on the same
  8113.              * level.  It needs to be saved one level up,
  8114.              * if the parent is also a subdoc.
  8115.              */
  8116.             else if (( up_state != NULL ) &&
  8117.                 ( top_state->diff_state != FALSE ) &&
  8118.                 ( state_diff == 0 ))
  8119.             {
  8120.                 if ((up_state->is_a_subdoc == SUBDOC_CELL)||
  8121.                      (up_state->is_a_subdoc == SUBDOC_CAPTION))
  8122.                 {
  8123.                     lo_SaveSubdocTags(context, up_state, tag);
  8124.                 }
  8125.                 else
  8126.                 {
  8127.                     PA_FreeTag(tag);
  8128.                 }
  8129.             }
  8130.             /*
  8131.              * Else we are still in the same subdoc
  8132.              */
  8133.             else if (( top_state->diff_state == FALSE ) &&
  8134.                 ( state_diff == 0 ))
  8135.             {
  8136.                 lo_SaveSubdocTags(context, sub_state, tag);
  8137.             }
  8138.             /*
  8139.              * Else that tag started a new, nested subdoc.
  8140.              * Add the starting tag to the parent.
  8141.              */
  8142.             else if (( state_diff == 1 ))
  8143.             {
  8144.                 lo_SaveSubdocTags(context, sub_state, tag);
  8145.                 /*
  8146.                  * Since we have extended the parent chain,
  8147.                  * we need to reset the child to the new
  8148.                  * parent end-chain.
  8149.                  */
  8150.                 if ((tmp_state->is_a_subdoc == SUBDOC_CELL)||
  8151.                     (tmp_state->is_a_subdoc == SUBDOC_CAPTION))
  8152.                 {
  8153.                     PA_Tag *new_tag;
  8154.                     
  8155.                     tmp_state->subdoc_tags =
  8156.                         sub_state->subdoc_tags_end;
  8157.  
  8158.                     /* add an aditional dummy tag so that style sheets
  8159.                      * can use it to query styles from for this entry
  8160.                      * that created a table
  8161.                      */
  8162.                     new_tag = LO_CreateStyleSheetDummyTag(tag);
  8163.                     if(new_tag)
  8164.                     {
  8165.                         lo_SaveSubdocTags(context, tmp_state, new_tag);
  8166.                     }
  8167.                 }
  8168.             }
  8169.             /*
  8170.              * This can never happen.
  8171.              */
  8172.             else
  8173.             {
  8174.                 PA_FreeTag(tag);
  8175.             }
  8176.         }
  8177.         tag_ptr = tag_list;
  8178.     }
  8179.  
  8180.     /*
  8181.      * Restore our parent's state levels
  8182.      */
  8183.     top_state->diff_state = save_diff_state;
  8184.     top_state->state_pushes = save_state_pushes;
  8185.     top_state->state_pops = save_state_pops;
  8186. }
  8187.  
  8188.  
  8189. /*
  8190.  * Walk the element list, throwing them away until we find one
  8191.  * that can be reused.
  8192.  */
  8193. PA_Tag *
  8194. lo_FindReuseableElement(MWContext *context, lo_DocState *state, LO_Element ** elem_list)
  8195. {
  8196.     LO_Element * eptr;
  8197.     LO_Element * enext;
  8198.     PA_Tag * tag;
  8199.     
  8200.     tag = NULL;
  8201.     eptr = *elem_list;
  8202.     enext = NULL;
  8203.     
  8204.     /*
  8205.      * Keep going until we've gone through all the elements
  8206.      * or found one that we can reuse.
  8207.      */
  8208.     while ( (eptr != NULL) && (tag == NULL) )
  8209.     {        
  8210.         enext = eptr->lo_any.next;
  8211.         
  8212.         /*
  8213.          * Any element found by this switch statement will attempt to be relayed out
  8214.          * using the same element structure. DO NOT put anything in here that can
  8215.          * have atributes set by style sheets until the lo_PreLayoutTag function
  8216.          * can correctly handle stylesheets.
  8217.          */
  8218.         switch ( eptr->type )
  8219.         {
  8220.             case LO_EMBED:
  8221.                 tag = eptr->lo_embed.tag;
  8222.                 break;
  8223. #ifdef JAVA
  8224.             case LO_JAVA:
  8225.                 tag = eptr->lo_java.tag;
  8226.                 break;
  8227. #endif /* JAVA */
  8228.         }
  8229.         
  8230.         /*
  8231.          * If we didn't find a tag from that element, then dispose of it and
  8232.          * keep looking.
  8233.          */
  8234.         if ( tag == NULL )
  8235.         {
  8236.             /*
  8237.              * We dunno how to reuse this type of element, so throw
  8238.              * it away and someone else will relay it out from scratch.
  8239.              */                
  8240.             eptr->lo_any.prev = NULL;
  8241.             eptr->lo_any.next = NULL;
  8242.             lo_relayout_recycle ( context, state, eptr );
  8243.             if ( enext != NULL )
  8244.             {
  8245.                 enext->lo_any.prev = NULL;
  8246.             }
  8247.             eptr = enext;
  8248.         }
  8249.     }
  8250.     /*
  8251.      * Advance the element list to the new head
  8252.      */
  8253.     *elem_list = eptr;
  8254.     
  8255.     return tag;
  8256. }
  8257.  
  8258. /* 
  8259.  * Functions separated out of lo_BeginTableAttributes
  8260.  */
  8261.  
  8262. void lo_PositionTableElement(lo_DocState *state, LO_TableStruct *table_ele) 
  8263. {
  8264.     table_ele->ele_id = NEXT_ELEMENT;
  8265.     table_ele->x = state->x;
  8266.     table_ele->x_offset = 0;
  8267.     table_ele->y = state->y;
  8268.     table_ele->y_offset = 0;
  8269.     table_ele->width = 0;
  8270.     table_ele->height = 0;
  8271.     table_ele->line_height = 0;
  8272.  
  8273.     table_ele->next = NULL;
  8274.     table_ele->prev = NULL;
  8275.  
  8276.     /*
  8277.      * Push our alignment state if we're not floating
  8278.      */
  8279.     
  8280.     if ( !(table_ele->ele_attrmask & LO_ELE_FLOATING) )
  8281.     {
  8282.         lo_PushAlignment(state, P_TABLE_DATA, table_ele->alignment);
  8283.     }
  8284.     
  8285. }
  8286.  
  8287.  
  8288. void lo_InitTableRecord( lo_TableRec *table )
  8289. {
  8290.     /* Reset row and col counters */
  8291.     table->rows = 0;
  8292.     table->cols = 0;
  8293.  
  8294.     /* Reset width span array */
  8295.     lo_ResetWidthSpans(table);
  8296.  
  8297.     table->height_span_ptr = NULL;
  8298. }
  8299.  
  8300. static void lo_ResetWidthSpans( lo_TableRec *table )
  8301. {
  8302.     lo_table_span *span = table->width_spans;
  8303.  
  8304.     while (span != NULL)
  8305.     {
  8306.         span->dim = 1;
  8307.         span->min_dim = 1;
  8308.         span->span = 0;        
  8309.         span = span->next;
  8310.     }
  8311.  
  8312. }
  8313.  
  8314. void lo_SetTableDimensions( lo_DocState *state, lo_TableRec *table, int32 allow_percent_width, int32 allow_percent_height)
  8315. {
  8316.     int32 val;
  8317.  
  8318.     if (table->percent_width > 0) 
  8319.     {
  8320.         val = table->percent_width;
  8321.         if (allow_percent_width == FALSE)
  8322.         {
  8323.             val = 0;
  8324.         }
  8325.         else
  8326.         {
  8327.             val = (state->win_width - state->win_left -
  8328.                 state->win_right) * val / 100;
  8329.         }
  8330.         if (val < 0)
  8331.         {
  8332.             val = 0;
  8333.         }
  8334.         table->width = val;
  8335.     }
  8336.     
  8337.     if (table->percent_height > 0)
  8338.     {
  8339.         val = table->percent_height;
  8340.         if (allow_percent_height == FALSE)
  8341.         {
  8342.             val = 0;
  8343.         }
  8344.         else
  8345.         {
  8346.             val = (state->win_height - state->win_top -
  8347.                 state->win_bottom) * val / 100;
  8348.         }
  8349.         if (val < 0)
  8350.         {
  8351.             val = 0;
  8352.         }
  8353.         table->height = val;
  8354.     }
  8355. }
  8356.  
  8357. void lo_CalcFixedColWidths( MWContext *context, lo_DocState *state, lo_TableRec *table)
  8358. {
  8359.     int32 cols = table->fixed_cols;
  8360.     if (cols > 0) {
  8361.         int32 count;
  8362.         int32 table_width;
  8363.         
  8364.         table_width = lo_ComputeInternalTableWidth ( context, table, state );
  8365.         
  8366.         /* Split the space up evenly */
  8367.         table->default_cell_width = table_width / cols;
  8368.         
  8369.         /* and we have all the table width left to play with */
  8370.         table->fixed_width_remaining = table_width;
  8371.         
  8372.         /* Initialize our width array */
  8373.         for ( count = 0; count < cols; ++count )
  8374.         {
  8375.             table->fixed_col_widths[ count ] = 0;
  8376.         }
  8377.     }
  8378. }
  8379.  
  8380. void lo_UpdateStateAfterBeginTable( lo_DocState *state, lo_TableRec *table)
  8381. {
  8382.     state->current_table = table;
  8383. }
  8384.  
  8385. /* Relayout version of lo_BeginTableRowAttributes()  */
  8386. void lo_UpdateTableStateForBeginRow(lo_TableRec *table, lo_TableRow *table_row)
  8387. {
  8388.     table_row->row_done = FALSE;
  8389.     table_row->cells = 0;
  8390.     table_row->cell_list = NULL;
  8391.     table_row->cell_ptr = NULL;
  8392.     /* table_row->next = NULL;
  8393.  
  8394.     if (table->row_list == NULL)
  8395.     {
  8396.         table->row_list = table_row;
  8397.         table->row_ptr = table_row;
  8398.     }
  8399.     else
  8400.     {
  8401.         table->row_ptr->next = table_row;
  8402.         table->row_ptr = table_row;
  8403.     }
  8404.     */
  8405.  
  8406.     table->width_span_ptr = NULL;
  8407.     
  8408. }
  8409.  
  8410. /* 
  8411.  * Functions for breaking up lo_BeginTableCellAttributes()
  8412.  */
  8413. void lo_InitForBeginCell(lo_TableRow *table_row, lo_TableCell *table_cell)
  8414. {
  8415.     table_cell->must_relayout = FALSE;
  8416.     table_cell->cell_done = FALSE;
  8417.     
  8418.     if (table_row->cell_list == NULL)
  8419.     {
  8420.         table_row->cell_list = table_cell;
  8421.         table_row->cell_ptr = table_cell;
  8422.     }
  8423.     else
  8424.     {
  8425.         table_row->cell_ptr->next = table_cell;
  8426.         table_row->cell_ptr = table_cell;
  8427.     }
  8428. }
  8429.  
  8430. void lo_InitSubDocForBeginCell( MWContext *context, lo_DocState *state, lo_TableRec *table )
  8431. {
  8432.     lo_TableCell *table_cell = table->row_ptr->cell_ptr;
  8433.     lo_BeginCellSubDoc(context, 
  8434.                         state, 
  8435.                         table,
  8436.                         NULL,
  8437.                         NULL,
  8438.                         LO_TILE_BOTH,
  8439.                         NULL,
  8440.                         NULL,
  8441.                         NULL,
  8442.                         NULL,
  8443.                          table_cell->is_a_header, 
  8444.                         table->draw_borders,
  8445.                         TRUE);
  8446.  
  8447.     /*
  8448.      * We added a new state.
  8449.      */
  8450.     lo_PushStateLevel ( context );
  8451. }
  8452.  
  8453. static void lo_UpdateCaptionCellFromSubDoc( MWContext *context, lo_DocState *state, LO_SubDocStruct *subdoc, LO_CellStruct *cell_ele)
  8454. {
  8455.     int32 dx = 0;
  8456.     int32 dy = 0;
  8457.  
  8458.     lo_CreateCellFromSubDoc(context, state, subdoc, cell_ele, &dx, &dy);
  8459.     lo_ShiftCell(cell_ele, dx, dy);
  8460.     lo_RenumberCell(state, cell_ele);
  8461. }
  8462.  
  8463. /* Only deletes the cell itself.  Assumes that stuff the cell points to will get deleted
  8464.    elsewhere */
  8465. static void lo_FreeCaptionCell( MWContext *context, lo_DocState *state, LO_CellStruct *cell_ele)
  8466. {
  8467.     cell_ele->next = NULL;
  8468.     cell_ele->prev = NULL;
  8469.     cell_ele->cell_list = NULL;
  8470.     cell_ele->cell_list_end = NULL;
  8471.     cell_ele->cell_float_list = NULL;
  8472.     cell_ele->table_cell = NULL;
  8473.     cell_ele->table_row = NULL;
  8474.     cell_ele->table = NULL;
  8475.  
  8476.     lo_FreeElement(context, (LO_Element *)cell_ele, TRUE);
  8477.  
  8478. }
  8479. #ifdef TEST_16BIT
  8480. #undef XP_WIN16
  8481. #endif /* TEST_16BIT */
  8482.