home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / layout / laycell.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  24.8 KB  |  1,105 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 "layers.h"
  24.  
  25. #ifdef PROFILE
  26. #pragma profile on
  27. #endif
  28.  
  29. #ifdef TEST_16BIT
  30. #define XP_WIN16
  31. #endif /* TEST_16BIT */
  32.  
  33. void
  34. lo_DisplayCellContents(MWContext *context, LO_CellStruct *cell,
  35.                        int32 base_x, int32 base_y,
  36.                        int32 x, int32 y,
  37.                        uint32 width, uint32 height)
  38. {
  39.     LO_Element *eptr;
  40.  
  41.     eptr = cell->cell_list;
  42.     while (eptr)
  43.     {
  44.         lo_DisplayElement(context, eptr, base_x, base_y, x, y, width, height);
  45.         eptr = eptr->lo_any.next;
  46.     }
  47.  
  48.     eptr = cell->cell_float_list;
  49.     while (eptr)
  50.     {
  51.         lo_DisplayElement(context, eptr, base_x, base_y, x, y, width, height);
  52.         eptr = eptr->lo_any.next;
  53.     }
  54. }
  55.  
  56.  
  57. PRIVATE
  58. LO_Element *
  59. lo_search_element_list(MWContext *context, LO_Element *eptr, int32 x, int32 y)
  60. {
  61.     while (eptr != NULL)
  62.     {
  63.         int32 width, height;
  64.  
  65.         width = eptr->lo_any.width;
  66.         /*
  67.          * Images need to account for border width
  68.          */
  69.         if (eptr->type == LO_IMAGE)
  70.         {
  71.             width = width + (2 * eptr->lo_image.border_width);
  72.         }
  73.         if (width <= 0)
  74.         {
  75.             width = 1;
  76.         }
  77.  
  78.         height = eptr->lo_any.height;
  79.         /*
  80.          * Images need to account for border width
  81.          */
  82.         if (eptr->type == LO_IMAGE)
  83.         {
  84.             height = height + (2 * eptr->lo_image.border_width);
  85.         }
  86.  
  87.         if ((y < (eptr->lo_any.y + eptr->lo_any.y_offset + height))&&
  88.             (y >= eptr->lo_any.y))
  89.         {
  90.             if ((x < (eptr->lo_any.x + eptr->lo_any.x_offset +
  91.                 width))&&(x >= eptr->lo_any.x))
  92.             {
  93.                 /*
  94.                  * Don't stop on tables, they are containers
  95.                  * we must look inside of.
  96.                  */
  97.                 if (eptr->type != LO_TABLE)
  98.                 {
  99.                     break;
  100.                 }
  101.             }
  102.         }
  103.         eptr = eptr->lo_any.next;
  104.     }
  105.     return(eptr);
  106. }
  107.  
  108.  
  109. int32
  110. lo_GetCellBaseline(LO_CellStruct *cell)
  111. {
  112.     LO_Element *eptr;
  113.  
  114.     if (cell == NULL)
  115.     {
  116.         return(0);
  117.     }
  118.  
  119.     /*
  120.      * Make eptr point to the start of the element chain
  121.      * for this subdoc.
  122.      */
  123.     if (cell->cell_list == NULL)
  124.     {
  125.         return(0);
  126.     }
  127.  
  128.     eptr = cell->cell_list;
  129.  
  130.     while (eptr != NULL)
  131.     {
  132.         if (eptr->type == LO_LINEFEED)
  133.         {
  134.             break;
  135.         }
  136.         eptr = eptr->lo_any.next;
  137.     }
  138.     if (eptr == NULL)
  139.     {
  140.         return(0);
  141.     }
  142.     return(eptr->lo_linefeed.baseline);
  143. }
  144.  
  145.  
  146. LO_Element *
  147. lo_XYToCellElement(MWContext *context, lo_DocState *state,
  148.     LO_CellStruct *cell, int32 x, int32 y,
  149.     Bool check_float, Bool into_cells, Bool into_ilayers)
  150. {
  151.     LO_Element *eptr;
  152.     LO_Element *element;
  153.  
  154.     eptr = cell->cell_list;
  155.     element = lo_search_element_list(context, eptr, x, y);
  156.  
  157.     if ((element == NULL)&&(check_float != FALSE))
  158.     {
  159.         eptr = cell->cell_float_list;
  160.         element = lo_search_element_list(context, eptr, x, y);
  161.     }
  162.  
  163.     if ((element != NULL)&&(element->type == LO_SUBDOC))
  164.     {
  165.         LO_SubDocStruct *subdoc;
  166.         int32 new_x, new_y;
  167.         int32 ret_new_x, ret_new_y;
  168.  
  169.         subdoc = (LO_SubDocStruct *)element;
  170.  
  171.         new_x = x - (subdoc->x + subdoc->x_offset +
  172.             subdoc->border_width);
  173.         new_y = y - (subdoc->y + subdoc->y_offset +
  174.             subdoc->border_width);
  175.         element = lo_XYToDocumentElement(context,
  176.             (lo_DocState *)subdoc->state, new_x, new_y, 
  177.                         check_float, into_cells, into_ilayers, 
  178.                         &ret_new_x, &ret_new_y);
  179.         x = ret_new_x;
  180.         y = ret_new_y;
  181.     }
  182.     else if ((element != NULL)&&(element->type == LO_CELL)&&
  183.          (into_cells != FALSE))
  184.     {
  185.         if (!element->lo_cell.cell_inflow_layer || into_ilayers)
  186.             element = lo_XYToCellElement(context, state,
  187.                          (LO_CellStruct *)element, x, y,
  188.                          check_float, into_cells, into_ilayers);
  189.     }
  190.  
  191.     return(element);
  192. }
  193.  
  194.  
  195. LO_Element *
  196. lo_XYToNearestCellElement(MWContext *context, lo_DocState *state,
  197.     LO_CellStruct *cell, int32 x, int32 y)
  198. {
  199.     LO_Element *eptr, *eptrsave;
  200.     int32 x2;
  201.     /* int32 ysave; */
  202.  
  203.     eptr = lo_XYToCellElement(context, state, cell, x, y, TRUE, TRUE, TRUE);
  204.     eptrsave = NULL;
  205.  
  206.     /*
  207.      * If no exact hit, find nearest in Y (and then X) overlap.
  208.      */
  209.     if (eptr == NULL)
  210.     {
  211.         eptr = cell->cell_list;
  212.         while (eptr != NULL)
  213.         {
  214.             int32 y2;
  215.  
  216.             /*
  217.              * Skip tables, we just walk into them.
  218.              */
  219.             if (eptr->type == LO_TABLE)
  220.             {
  221.                 eptr = eptr->lo_any.next;
  222.                 continue;
  223.             }
  224.  
  225.             y2 = eptr->lo_any.y + eptr->lo_any.y_offset +
  226.                 eptr->lo_any.height;
  227.             /*
  228.              * Images and cells need to account for border width
  229.              */
  230.             if (eptr->type == LO_IMAGE)
  231.             {
  232.                 y2 = y2 + (2 * eptr->lo_image.border_width);
  233.             }
  234.             else if (eptr->type == LO_CELL)
  235.             {
  236.                 y2 = y2 + (2 * eptr->lo_cell.border_width);
  237.             }
  238.  
  239.             /* 
  240.              * If we've already found something that's greater in y,
  241.              * let's look for something that's closer in x.
  242.              */
  243.             if (eptrsave) 
  244.             {
  245.                 /* 
  246.                  * If the current y is larger than that of the saved element 
  247.                  * we'll just take the saved element.
  248.                  */
  249.                 /* if (y2 > ysave)
  250.                     break; */
  251.  
  252.                 eptrsave = eptr;
  253.                 /* ysave = y2; */
  254.  
  255.                 /* Calculate the x extent of the element */
  256.                 x2 = eptr->lo_any.x + eptr->lo_any.x_offset +
  257.                     eptr->lo_any.width;
  258.                 if (eptr->type == LO_IMAGE)
  259.                     x2 = x2 + (2 * eptr->lo_image.border_width);
  260.                 else if (eptr->type == LO_CELL)
  261.                     x2 = x2 + (2 * eptr->lo_cell.border_width);
  262.  
  263.                 /* 
  264.                  * If we've gone too far in x, we'll take the currently
  265.                  * saved element.
  266.                  */
  267.                 if (x <= x2) 
  268.                     break;
  269.             }
  270.             else if (y <= y2)
  271.             {
  272.                 /* 
  273.                  * This is the first element that's greater in y, so
  274.                  * save it and look out for others that are closer in
  275.                  * x, but identical in y.
  276.                  */
  277.                 eptrsave = eptr;
  278.                 /* ysave = y2; */
  279.  
  280.                 /* Calculate the x extent of the element */
  281.                 x2 = eptr->lo_any.x + eptr->lo_any.x_offset +
  282.                     eptr->lo_any.width;
  283.                 if (eptr->type == LO_IMAGE)
  284.                     x2 = x2 + (2 * eptr->lo_image.border_width);
  285.                 else if (eptr->type == LO_CELL)
  286.                     x2 = x2 + (2 * eptr->lo_cell.border_width);
  287.  
  288.                 /* 
  289.                  * If we've gone too far in x, we'll take the currently
  290.                  * saved element.
  291.                  */
  292.                 if (x <= x2) 
  293.                     break;
  294.             }
  295.             eptr = eptr->lo_any.next;
  296.         }
  297.  
  298.         eptr = eptrsave;
  299.         
  300.         /*
  301.          * If nothing overlaps y, match the last element in the cell.
  302.          */
  303.         if (eptr == NULL)
  304.         {
  305.             eptr = cell->cell_list_end;
  306.         }
  307.  
  308.         /*
  309.          * If we matched on a cell, recurse into it.
  310.          */
  311.         if ((eptr != NULL)&&(eptr->type == LO_CELL))
  312.         {
  313.             eptr = lo_XYToNearestCellElement(context, state,
  314.                 (LO_CellStruct *)eptr, x, y);
  315.         }
  316.     }
  317.     return(eptr);
  318. }
  319.  
  320.  
  321. static void lo_MoveElementLayers( LO_Element *eptr )
  322. {
  323.     if (eptr->type == LO_IMAGE)
  324.         
  325.     {
  326.         CL_MoveLayer(eptr->lo_image.layer, 
  327.             eptr->lo_any.x + eptr->lo_any.x_offset + eptr->lo_image.border_width, 
  328.             eptr->lo_any.y + eptr->lo_any.y_offset + eptr->lo_image.border_width);
  329.     }
  330.     else if (eptr->type == LO_EMBED)
  331.     {
  332.         CL_MoveLayer(eptr->lo_embed.layer, 
  333.             eptr->lo_any.x + eptr->lo_any.x_offset + eptr->lo_embed.border_width, 
  334.             eptr->lo_any.y + eptr->lo_any.y_offset + eptr->lo_embed.border_width);
  335.  
  336.     }
  337. #ifdef JAVA
  338.     else if (eptr->type == LO_JAVA)
  339.     {
  340.         CL_MoveLayer(eptr->lo_java.layer, 
  341.             eptr->lo_any.x + eptr->lo_any.x_offset + eptr->lo_java.border_width, 
  342.             eptr->lo_any.y + eptr->lo_any.y_offset + eptr->lo_java.border_width);
  343.         
  344.     }
  345. #endif
  346.     else if (eptr->type == LO_FORM_ELE)
  347.     {
  348.         CL_MoveLayer(eptr->lo_form.layer, 
  349.             eptr->lo_any.x + eptr->lo_any.x_offset + eptr->lo_form.border_horiz_space, 
  350.             eptr->lo_any.y + eptr->lo_any.y_offset + eptr->lo_form.border_vert_space);
  351.     }
  352. }
  353.  
  354. void
  355. lo_ShiftCell(LO_CellStruct *cell, int32 dx, int32 dy)
  356. {
  357.     LO_Element *eptr;
  358.  
  359.     if (cell == NULL)
  360.     {
  361.         return;
  362.     }
  363.  
  364.         if (cell->cell_bg_layer) {
  365.             int32 x_offset, y_offset;
  366.             lo_GetLayerXYShift(CL_GetLayerParent(cell->cell_bg_layer),
  367.                                &x_offset, &y_offset);
  368.             CL_MoveLayer(cell->cell_bg_layer,
  369.                          cell->x - x_offset, cell->y - y_offset);
  370.             CL_ResizeLayer(cell->cell_bg_layer, cell->width, cell->height);
  371.         }
  372.         if (cell->cell_inflow_layer)
  373.             lo_OffsetInflowLayer(cell->cell_inflow_layer, dx, dy);
  374.  
  375.     eptr = cell->cell_list;
  376.     while (eptr != NULL)
  377.     {
  378.         eptr->lo_any.x += dx;
  379.         eptr->lo_any.y += dy;
  380.         if (eptr->type == LO_CELL)
  381.         {
  382.             /*
  383.              * This would cause an infinite loop.
  384.              */
  385.             if ((LO_CellStruct *)eptr == cell)
  386.             {
  387.                 XP_ASSERT(FALSE);
  388.                 break;
  389.             }
  390.             lo_ShiftCell((LO_CellStruct *)eptr, dx, dy);
  391.         }
  392.  
  393.         lo_MoveElementLayers( eptr );
  394.  
  395.         eptr = eptr->lo_any.next;
  396.     }
  397.  
  398.     eptr = cell->cell_float_list;
  399.     while (eptr != NULL)
  400.     {
  401.         eptr->lo_any.x += dx;
  402.         eptr->lo_any.y += dy;
  403.         if (eptr->type == LO_CELL)
  404.         {
  405.             lo_ShiftCell((LO_CellStruct *)eptr, dx, dy);
  406.         }
  407.  
  408.         lo_MoveElementLayers( eptr );
  409.  
  410.         eptr = eptr->lo_any.next;
  411.     }
  412. }
  413.  
  414.  
  415. static void
  416. lo_recolor_backgrounds(lo_DocState *state, LO_CellStruct *cell,
  417.     LO_Element *eptr)
  418. {
  419.     LO_TextAttr *old_attr;
  420.     LO_TextAttr *attr;
  421.     LO_TextAttr tmp_attr;
  422.  
  423.     if (cell->backdrop.bg_color == NULL)
  424.     {
  425.         return;
  426.     }
  427.  
  428.     attr = NULL;
  429.     old_attr = NULL;
  430.     if (eptr->type == LO_TEXT)
  431.     {
  432.         old_attr = eptr->lo_text.text_attr;
  433.     }
  434.     else if (eptr->type == LO_LINEFEED)
  435.     {
  436.         old_attr = eptr->lo_linefeed.text_attr;
  437.     }
  438.     else if (eptr->type == LO_IMAGE)
  439.     {
  440.         old_attr = eptr->lo_image.text_attr;
  441.     }
  442.     else if (eptr->type == LO_FORM_ELE)
  443.     {
  444.         old_attr = eptr->lo_form.text_attr;
  445.     }
  446.  
  447.     if (old_attr != NULL)
  448.     {
  449.         lo_CopyTextAttr(old_attr, &tmp_attr);
  450.  
  451.         /* don't recolor the background if it was
  452.          * explicitly set to another color 
  453.          */
  454.         if(tmp_attr.no_background == TRUE)
  455.             tmp_attr.bg = *cell->backdrop.bg_color;
  456.  
  457.         /* removed by Lou 4-3-97 to allow overlapping
  458.          * text in tables to work right.  Windows
  459.          * never before payed attention to this attr
  460.          * so I'm guessing that it won't break anything :)
  461.          */
  462.         /* tmp_attr.no_background = FALSE; */
  463.  
  464.         attr = lo_FetchTextAttr(state, &tmp_attr);
  465.     }
  466.  
  467.     if (eptr->type == LO_TEXT)
  468.     {
  469.         eptr->lo_text.text_attr = attr;
  470.     }
  471.     else if (eptr->type == LO_LINEFEED)
  472.     {
  473.         eptr->lo_linefeed.text_attr = attr;
  474.     }
  475.     else if (eptr->type == LO_IMAGE)
  476.     {
  477.         eptr->lo_image.text_attr = attr;
  478.     }
  479.     else if (eptr->type == LO_FORM_ELE)
  480.     {
  481.         eptr->lo_form.text_attr = attr;
  482.     }
  483. }
  484.  
  485.  
  486. /*
  487.  * In addition to renumbering the cell, we now
  488.  * also make sure that text in cell with a bg_color
  489.  * have their text_attr->bg set correctly.
  490.  */
  491. void
  492. lo_RenumberCell(lo_DocState *state, LO_CellStruct *cell)
  493. {
  494.     LO_Element *eptr;
  495.  
  496.     if (cell == NULL)
  497.     {
  498.         return;
  499.     }
  500.  
  501.     eptr = cell->cell_list;
  502.     while (eptr != NULL)
  503.     {
  504.         /* Keep element IDs in order */
  505.         eptr->lo_any.ele_id = NEXT_ELEMENT;
  506.  
  507.         /*
  508.          * If the display is blocked for an element
  509.          * we havn't reached yet, check to see if
  510.          * this element is it, and if so, save its
  511.          * y position.
  512.          */
  513.         if ((state->display_blocked != FALSE)&&
  514.             (state->is_a_subdoc == SUBDOC_NOT)&&
  515.             (state->display_blocking_element_y == 0)&&
  516.             (state->display_blocking_element_id != -1)&&
  517.             (eptr->lo_any.ele_id >=
  518.             state->display_blocking_element_id))
  519.         {
  520.             state->display_blocking_element_y = eptr->lo_any.y;
  521.         }
  522.  
  523.         /*
  524.          * If this is a cell with a BGCOLOR attribute, pass
  525.          * that color on to the bg of all text in this cell.
  526.          */
  527.         if ((cell->backdrop.bg_color != NULL)&&((eptr->type == LO_TEXT)||
  528.             (eptr->type == LO_LINEFEED)||(eptr->type == LO_IMAGE)||
  529.             (eptr->type == LO_FORM_ELE)))
  530.         {
  531.             lo_recolor_backgrounds(state, cell, eptr);
  532.         }
  533.  
  534.         if (eptr->type == LO_CELL)
  535.         {
  536.             lo_RenumberCell(state, (LO_CellStruct *)eptr);
  537.         }
  538.  
  539.         eptr = eptr->lo_any.next;
  540.     }
  541.  
  542.     eptr = cell->cell_float_list;
  543.     while (eptr != NULL)
  544.     {
  545.         /* Keep element IDs in order */
  546.         eptr->lo_any.ele_id = NEXT_ELEMENT;
  547.  
  548.         /*
  549.          * If the display is blocked for an element
  550.          * we havn't reached yet, check to see if
  551.          * this element is it, and if so, save its
  552.          * y position.
  553.          */
  554.         if ((state->display_blocked != FALSE)&&
  555.             (state->is_a_subdoc == SUBDOC_NOT)&&
  556.             (state->display_blocking_element_y == 0)&&
  557.             (state->display_blocking_element_id != -1)&&
  558.             (eptr->lo_any.ele_id >=
  559.             state->display_blocking_element_id))
  560.         {
  561.             state->display_blocking_element_y = eptr->lo_any.y;
  562.         }
  563.  
  564.         /*
  565.          * If this is a cell with a BGCOLOR attribute, pass
  566.          * that color on to the bg of all text in this cell.
  567.          */
  568.         if ((cell->backdrop.bg_color != NULL)&&((eptr->type == LO_TEXT)||
  569.             (eptr->type == LO_LINEFEED)||(eptr->type == LO_IMAGE)||
  570.             (eptr->type == LO_FORM_ELE)))
  571.         {
  572.             lo_recolor_backgrounds(state, cell, eptr);
  573.         }
  574.  
  575.         if (eptr->type == LO_CELL)
  576.         {
  577.             lo_RenumberCell(state, (LO_CellStruct *)eptr);
  578.         }
  579.  
  580.         eptr = eptr->lo_any.next;
  581.     }
  582. }
  583.  
  584.  
  585. static void
  586. lo_free_subdoc_state(MWContext *context, lo_DocState *parent_state,
  587.             lo_DocState *state, Bool free_all)
  588. {
  589.     LO_Element **line_array;
  590.  
  591.     if (state == NULL)
  592.     {
  593.         return;
  594.     }
  595.  
  596.     /*
  597.      * If this subdoc is not nested inside another subdoc,
  598.      * free any re-parse tags stored on this subdoc.
  599.      */
  600.     if ((state->subdoc_tags != NULL)&&
  601.         (parent_state->is_a_subdoc != SUBDOC_CELL)&&
  602.         (parent_state->is_a_subdoc != SUBDOC_CAPTION))
  603.     {
  604.         PA_Tag *tptr;
  605.         PA_Tag *tag;
  606.  
  607.         tptr = state->subdoc_tags;
  608.         while ((tptr != state->subdoc_tags_end)&&(tptr != NULL))
  609.         {
  610.             tag = tptr;
  611.             tptr = tptr->next;
  612.             tag->next = NULL;
  613.             PA_FreeTag(tag);
  614.         }
  615.         if (tptr != NULL)
  616.         {
  617.             tptr->next = NULL;
  618.             PA_FreeTag(tptr);
  619.         }
  620.         state->subdoc_tags = NULL;
  621.         state->subdoc_tags_end = NULL;
  622.     }
  623.  
  624.     if (state->left_margin_stack != NULL)
  625.     {
  626.         lo_MarginStack *mptr;
  627.         lo_MarginStack *margin;
  628.  
  629.         mptr = state->left_margin_stack;
  630.         while (mptr != NULL)
  631.         {
  632.             margin = mptr;
  633.             mptr = mptr->next;
  634.             XP_DELETE(margin);
  635.         }
  636.         state->left_margin_stack = NULL;
  637.     }
  638.     if (state->right_margin_stack != NULL)
  639.     {
  640.         lo_MarginStack *mptr;
  641.         lo_MarginStack *margin;
  642.  
  643.         mptr = state->right_margin_stack;
  644.         while (mptr != NULL)
  645.         {
  646.             margin = mptr;
  647.             mptr = mptr->next;
  648.             XP_DELETE(margin);
  649.         }
  650.         state->right_margin_stack = NULL;
  651.     }
  652.  
  653.     if (state->line_list != NULL)
  654.     {
  655.         lo_FreeElementList(context, state->line_list);
  656.         state->line_list = NULL;
  657.     }
  658.  
  659.     if (state->font_stack != NULL)
  660.     {
  661.         lo_FontStack *fstack;
  662.         lo_FontStack *fptr;
  663.  
  664.         fptr = state->font_stack;
  665.         while (fptr != NULL)
  666.         {
  667.             fstack = fptr;
  668.             fptr = fptr->next;
  669.             XP_DELETE(fstack);
  670.         }
  671.         state->font_stack = NULL;
  672.     }
  673.  
  674.     if (state->align_stack != NULL)
  675.     {
  676.         lo_AlignStack *aptr;
  677.         lo_AlignStack *align;
  678.  
  679.         aptr = state->align_stack;
  680.         while (aptr != NULL)
  681.         {
  682.             align = aptr;
  683.             aptr = aptr->next;
  684.             XP_DELETE(align);
  685.         }
  686.         state->align_stack = NULL;
  687.     }
  688.  
  689.     if (state->list_stack != NULL)
  690.     {
  691.         lo_ListStack *lptr;
  692.         lo_ListStack *list;
  693.  
  694.         lptr = state->list_stack;
  695.         while (lptr != NULL)
  696.         {
  697.             list = lptr;
  698.             lptr = lptr->next;
  699.             XP_DELETE(list);
  700.         }
  701.         state->list_stack = NULL;
  702.     }
  703.  
  704.     if (state->line_buf != NULL)
  705.     {
  706.         PA_FREE(state->line_buf);
  707.         state->line_buf = NULL;
  708.     }
  709.  
  710.     if (state->float_list != NULL)
  711.     {
  712.         /*
  713.          * Don't free these, they are squished into the cell.
  714.          * Only free them if this is a free_all.
  715.          */
  716.  
  717.         if (free_all != FALSE)
  718.         {
  719.             lo_FreeElementList(context, state->float_list);
  720.         }
  721.  
  722.         state->float_list = NULL;
  723.     }
  724.  
  725.     if (state->line_array != NULL)
  726.     {
  727.         LO_Element *eptr;
  728.  
  729. #ifdef XP_WIN16
  730. {
  731.         XP_Block *larray_array;
  732.         intn cnt;
  733.  
  734.         XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array);
  735.         cnt = state->larray_array_size - 1;
  736.         while (cnt > 0)
  737.         {
  738.             XP_FREE_BLOCK(larray_array[cnt]);
  739.             cnt--;
  740.         }
  741.         state->line_array = larray_array[0];
  742.         XP_UNLOCK_BLOCK(state->larray_array);
  743.         XP_FREE_BLOCK(state->larray_array);
  744. }
  745. #endif /* XP_WIN16 */
  746.  
  747.         eptr = NULL;
  748.         XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array);
  749.         eptr = line_array[0];
  750.         if (eptr != NULL)
  751.         {
  752.             /*
  753.              * Don't free these, they are squished into the cell.
  754.              * Only free them if this is a free_all.
  755.              */
  756.             if (free_all != FALSE)
  757.             {
  758.                 lo_FreeElementList(context, eptr);
  759.             }
  760.  
  761.         }
  762.         XP_UNLOCK_BLOCK(state->line_array);
  763.         XP_FREE_BLOCK(state->line_array);
  764.     }
  765.  
  766.     XP_DELETE(state);
  767. }
  768.  
  769.  
  770.  
  771. void
  772. lo_FreePartialSubDoc(MWContext *context, lo_DocState *state,
  773.     LO_SubDocStruct *subdoc)
  774. {
  775.     lo_DocState *subdoc_state;
  776.  
  777.     if (subdoc == NULL)
  778.     {
  779.         return;
  780.     }
  781.  
  782.     subdoc_state = (lo_DocState *)subdoc->state;
  783.     if (subdoc_state != NULL)
  784.     {
  785.         lo_free_subdoc_state(context, state, subdoc_state, TRUE);
  786.     }
  787.  
  788.     subdoc->state = NULL;
  789.     lo_FreeElement(context, (LO_Element *)subdoc, TRUE);
  790. }
  791.  
  792.  
  793. void
  794. lo_FreePartialCell(MWContext *context, lo_DocState *state,
  795.     LO_CellStruct *cell)
  796. {
  797.     if (cell == NULL)
  798.     {
  799.         return;
  800.     }
  801.  
  802.     lo_FreeElement(context, (LO_Element *)cell, TRUE);
  803. }
  804.  
  805.  
  806. LO_CellStruct *
  807. lo_SmallSquishSubDocToCell(MWContext *context, lo_DocState *state,
  808.     LO_SubDocStruct *subdoc, int32 *ptr_dx, int32 *ptr_dy)
  809. {
  810.     LO_CellStruct *cell;
  811.     /* lo_DocState *subdoc_state; */
  812.  
  813.     if (subdoc == NULL)
  814.     {
  815.         return(NULL);
  816.     }
  817.  
  818.     cell = (LO_CellStruct *)lo_NewElement(context, state, LO_CELL, NULL, 0);
  819.     cell->isCaption = FALSE;
  820.  
  821.     cell->cell_bg_layer = NULL;
  822.     cell->cell_inflow_layer = NULL;
  823.  
  824.     lo_CreateCellFromSubDoc (context, state, subdoc, cell, ptr_dx, ptr_dy );
  825.  
  826.     return(cell);
  827.  
  828.  
  829.     /* Copied to lo_CreateCellFromSubDoc()
  830.      *
  831.     *ptr_dx = 0;
  832.     *ptr_dy = 0;
  833.  
  834.     if (cell == NULL)
  835.     {
  836.         return(NULL);
  837.     }
  838.  
  839.     cell->type = LO_CELL;
  840.  
  841.     cell->ele_id = NEXT_ELEMENT;
  842.     cell->x = subdoc->x;
  843.     cell->x_offset = subdoc->x_offset;
  844.     cell->y = subdoc->y;
  845.     cell->y_offset = subdoc->y_offset;
  846.     cell->width = subdoc->width;
  847.     cell->height = subdoc->height;
  848.     cell->next = subdoc->next;
  849.     cell->prev = subdoc->prev;
  850.     cell->FE_Data = subdoc->FE_Data;
  851.  
  852.     cell->backdrop = subdoc->backdrop;
  853.     */
  854.  
  855.     /*
  856.      * Clear out the bg_color struct from the subdocs so it doesn't
  857.      * get freed twice.
  858.      */
  859.     /*
  860.     subdoc->backdrop.bg_color = NULL;
  861.         subdoc->backdrop.url = NULL;
  862.  
  863.         cell->cell_bg_layer = NULL;
  864.         cell->cell_inflow_layer = NULL;
  865.  
  866.     /*
  867.     cell->border_width = subdoc->border_width;
  868.     cell->border_vert_space = subdoc->border_vert_space;
  869.     cell->border_horiz_space = subdoc->border_horiz_space;
  870.  
  871.     cell->ele_attrmask = 0;
  872.     cell->ele_attrmask |= (subdoc->ele_attrmask & LO_ELE_SECURE);
  873.     cell->ele_attrmask |= (subdoc->ele_attrmask & LO_ELE_SELECTED);
  874.  
  875.     cell->sel_start = subdoc->sel_start;
  876.     cell->sel_end = subdoc->sel_end;
  877.  
  878.     cell->cell_list = NULL;
  879.     cell->cell_list_end = NULL;
  880.     cell->cell_float_list = NULL;
  881.     subdoc_state = (lo_DocState *)subdoc->state;
  882.     if (subdoc_state != NULL)
  883.     {
  884.         LO_Element **line_array;
  885.         LO_Element *eptr;
  886.         int32 base_x, base_y;
  887.     */
  888.         /*
  889.          * Make eptr point to the start of the element chain
  890.          * for this subdoc.
  891.          */
  892.     /*
  893. #ifdef XP_WIN16
  894.         {
  895.             XP_Block *larray_array;
  896.  
  897.             XP_LOCK_BLOCK(larray_array, XP_Block *,
  898.                 subdoc_state->larray_array);
  899.             subdoc_state->line_array = larray_array[0];
  900.             XP_UNLOCK_BLOCK(subdoc_state->larray_array);
  901.         }
  902. #endif */ /* XP_WIN16 */
  903.     /*
  904.         XP_LOCK_BLOCK(line_array, LO_Element **,
  905.             subdoc_state->line_array);
  906.         eptr = line_array[0];
  907.         XP_UNLOCK_BLOCK(subdoc_state->line_array);
  908.  
  909.         cell->cell_list = eptr;
  910.  
  911.         base_x = subdoc->x + subdoc->x_offset + subdoc->border_width;
  912.         base_y = subdoc->y + subdoc->y_offset + subdoc->border_width;
  913.  
  914.         cell->cell_list_end = subdoc_state->end_last_line;
  915.         if (cell->cell_list_end == NULL)
  916.         {
  917.             cell->cell_list_end = cell->cell_list;
  918.         }
  919.  
  920.         cell->cell_float_list = subdoc_state->float_list;
  921.                         
  922.         *ptr_dx = base_x;
  923.         *ptr_dy = base_y;
  924.  
  925.     */
  926. /*
  927.  * MOCHA needs to reuse mocha objects allocated in the namelist
  928.  * when a cell is relaid out.  This means we must always squish
  929.  * back up to the top level state, instead of propogating up
  930.  * like we used to.
  931.  */
  932.  
  933.     /*
  934. #ifdef MOCHA
  935.         lo_AddNameList(state->top_state->doc_state, subdoc_state);
  936. #else
  937.         lo_AddNameList(state, subdoc_state);
  938. #endif */ /* MOCHA */
  939.     /*
  940.     }
  941.  
  942.     return(cell);
  943.     */
  944. }
  945.  
  946.  
  947. LO_CellStruct *
  948. lo_SquishSubDocToCell(MWContext *context, lo_DocState *state,
  949.     LO_SubDocStruct *subdoc, Bool free_subdoc)
  950. {
  951.     LO_CellStruct *cell;
  952.     int32 dx, dy;
  953.  
  954.     dx = 0;
  955.     dy = 0;
  956.     
  957.     cell = lo_SmallSquishSubDocToCell(context, state, subdoc, &dx, &dy);
  958.  
  959.     if (cell == NULL)
  960.     {
  961.         return(NULL);
  962.     }
  963.  
  964.     lo_ShiftCell(cell, dx, dy);
  965.     lo_RenumberCell(state, cell);
  966.  
  967.     if ((subdoc->state != NULL)&&(free_subdoc != FALSE))
  968.     {
  969.         lo_DocState *subdoc_state;
  970.  
  971.         subdoc_state = (lo_DocState *)subdoc->state;
  972.         lo_free_subdoc_state(context, state, subdoc_state, FALSE);
  973.         subdoc->state = NULL;
  974.     }
  975.     if (free_subdoc != FALSE)
  976.     {
  977.         lo_FreeElement(context, (LO_Element *)subdoc, free_subdoc);
  978.     }
  979.  
  980.     return(cell);
  981. }
  982.  
  983.  
  984. /* Used during layout and relayout and called from lo_SmallSquishSubdocToCell() */
  985. void lo_CreateCellFromSubDoc( MWContext *context, lo_DocState *state,
  986.     LO_SubDocStruct *subdoc, LO_CellStruct *cell, int32 *ptr_dx, int32 *ptr_dy )
  987. {
  988.     lo_DocState *subdoc_state;
  989.  
  990.     /* Fix this later */
  991.     if (subdoc == NULL)
  992.     {
  993.         return;
  994.     }
  995.  
  996.     *ptr_dx = 0;
  997.     *ptr_dy = 0;
  998.  
  999.     /* Fix this later */
  1000.     if (cell == NULL)
  1001.     {
  1002.         return;
  1003.     }
  1004.  
  1005.     cell->type = LO_CELL;
  1006.  
  1007.     cell->ele_id = NEXT_ELEMENT;
  1008.     cell->x = subdoc->x;
  1009.     cell->x_offset = subdoc->x_offset;
  1010.     cell->y = subdoc->y;
  1011.     cell->y_offset = subdoc->y_offset;
  1012.     cell->width = subdoc->width;
  1013.     cell->height = subdoc->height;
  1014.     cell->next = subdoc->next;
  1015.     cell->prev = subdoc->prev;
  1016.     cell->FE_Data = subdoc->FE_Data;
  1017.  
  1018.     cell->backdrop = subdoc->backdrop;
  1019.  
  1020.     /*
  1021.      * Clear out the bg_color struct from the subdocs so it doesn't
  1022.      * get freed twice.
  1023.      */
  1024.  
  1025.     subdoc->backdrop.bg_color = NULL;
  1026.         subdoc->backdrop.url = NULL;
  1027.  
  1028.     cell->border_width = subdoc->border_width;
  1029.     cell->border_vert_space = subdoc->border_vert_space;
  1030.     cell->border_horiz_space = subdoc->border_horiz_space;
  1031.  
  1032.     cell->ele_attrmask = 0;
  1033.     cell->ele_attrmask |= (subdoc->ele_attrmask & LO_ELE_SECURE);
  1034.     cell->ele_attrmask |= (subdoc->ele_attrmask & LO_ELE_SELECTED);
  1035.  
  1036.     cell->sel_start = subdoc->sel_start;
  1037.     cell->sel_end = subdoc->sel_end;
  1038.  
  1039.     cell->cell_list = NULL;
  1040.     cell->cell_list_end = NULL;
  1041.     cell->cell_float_list = NULL;
  1042.     subdoc_state = (lo_DocState *)subdoc->state;
  1043.     if (subdoc_state != NULL)
  1044.     {
  1045.         LO_Element **line_array;
  1046.         LO_Element *eptr;
  1047.         int32 base_x, base_y;
  1048.  
  1049.         /*
  1050.          * Make eptr point to the start of the element chain
  1051.          * for this subdoc.
  1052.          */
  1053. #ifdef XP_WIN16
  1054.         {
  1055.             XP_Block *larray_array;
  1056.  
  1057.             XP_LOCK_BLOCK(larray_array, XP_Block *,
  1058.                 subdoc_state->larray_array);
  1059.             subdoc_state->line_array = larray_array[0];
  1060.             XP_UNLOCK_BLOCK(subdoc_state->larray_array);
  1061.         }
  1062. #endif /* XP_WIN16 */
  1063.         XP_LOCK_BLOCK(line_array, LO_Element **,
  1064.             subdoc_state->line_array);
  1065.         eptr = line_array[0];
  1066.         XP_UNLOCK_BLOCK(subdoc_state->line_array);
  1067.  
  1068.         cell->cell_list = eptr;
  1069.  
  1070.         base_x = subdoc->x + subdoc->x_offset + subdoc->border_width;
  1071.         base_y = subdoc->y + subdoc->y_offset + subdoc->border_width;
  1072.  
  1073.         cell->cell_list_end = subdoc_state->end_last_line;
  1074.         if (cell->cell_list_end == NULL)
  1075.         {
  1076.             cell->cell_list_end = cell->cell_list;
  1077.         }
  1078.  
  1079.         cell->cell_float_list = subdoc_state->float_list;
  1080.                         
  1081.         *ptr_dx = base_x;
  1082.         *ptr_dy = base_y;
  1083.  
  1084. /*
  1085.  * MOCHA needs to reuse mocha objects allocated in the namelist
  1086.  * when a cell is relaid out.  This means we must always squish
  1087.  * back up to the top level state, instead of propogating up
  1088.  * like we used to.
  1089.  */
  1090. #ifdef MOCHA
  1091.         lo_AddNameList(state->top_state->doc_state, subdoc_state);
  1092. #else
  1093.         lo_AddNameList(state, subdoc_state);
  1094. #endif /* MOCHA */
  1095.     }
  1096. }
  1097.  
  1098. #ifdef TEST_16BIT
  1099. #undef XP_WIN16
  1100. #endif /* TEST_16BIT */
  1101.  
  1102. #ifdef PROFILE
  1103. #pragma profile off
  1104. #endif
  1105.