home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / layout / layfree.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  23.7 KB  |  1,030 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 "layout.h"
  21. #ifdef EDITOR
  22. #include "edt.h"
  23. #endif
  24. #include "java.h"
  25. #include "layers.h"
  26. #include "pa_parse.h"
  27.  
  28. #define IL_CLIENT               /* XXXM12N Defined by Image Library clients */
  29. #include "libimg.h"             /* Image Library public API. */
  30.  
  31. extern void NPL_DeleteSessionData(MWContext*, void*);
  32.  
  33. #ifdef PROFILE
  34. #pragma profile on
  35. #endif
  36.  
  37.  
  38. void
  39. lo_FreeFormElementData(LO_FormElementData *element_data)
  40. {
  41.     int32 element_type;
  42.  
  43.     if (element_data == NULL)
  44.     {
  45.         return;
  46.     }
  47.  
  48.     element_type = element_data->type;
  49.  
  50.     switch(element_type)
  51.     {
  52.         case FORM_TYPE_TEXT:
  53.         case FORM_TYPE_PASSWORD:
  54.         case FORM_TYPE_FILE:
  55.             {
  56.                 lo_FormElementTextData *form_data;
  57.  
  58.                 form_data = (lo_FormElementTextData *)
  59.                         element_data;
  60.                 if (form_data->name != NULL)
  61.                 {
  62.                     PA_FREE(form_data->name);
  63.                 }
  64.                 if (form_data->default_text != NULL)
  65.                 {
  66.                     PA_FREE(form_data->default_text);
  67.                 }
  68.                 if (form_data->current_text != NULL)
  69.                 {
  70.                     PA_FREE(form_data->current_text);
  71.                 }
  72.             }
  73.             break;
  74.         case FORM_TYPE_SUBMIT:
  75.         case FORM_TYPE_RESET:
  76.         case FORM_TYPE_BUTTON:
  77.         case FORM_TYPE_HIDDEN:
  78.         case FORM_TYPE_READONLY:
  79.             {
  80.                 lo_FormElementMinimalData *form_data;
  81.  
  82.                 form_data = (lo_FormElementMinimalData *)
  83.                         element_data;
  84.                 if (form_data->name != NULL)
  85.                 {
  86.                     PA_FREE(form_data->name);
  87.                 }
  88.                 if (form_data->value != NULL)
  89.                 {
  90.                     PA_FREE(form_data->value);
  91.                 }
  92.             }
  93.             break;
  94.         case FORM_TYPE_RADIO:
  95.         case FORM_TYPE_CHECKBOX:
  96.             {
  97.                 lo_FormElementToggleData *form_data;
  98.  
  99.                 form_data = (lo_FormElementToggleData *)
  100.                         element_data;
  101.                 if (form_data->name != NULL)
  102.                 {
  103.                     PA_FREE(form_data->name);
  104.                 }
  105.                 if (form_data->value != NULL)
  106.                 {
  107.                     PA_FREE(form_data->value);
  108.                 }
  109.             }
  110.             break;
  111.         case FORM_TYPE_TEXTAREA:
  112.             {
  113.                 lo_FormElementTextareaData *form_data;
  114.  
  115.                 form_data = (lo_FormElementTextareaData *)
  116.                         element_data;
  117.                 if (form_data->name != NULL)
  118.                 {
  119.                     PA_FREE(form_data->name);
  120.                 }
  121.                 if (form_data->default_text != NULL)
  122.                 {
  123.                     PA_FREE(form_data->default_text);
  124.                 }
  125.                 if (form_data->current_text != NULL)
  126.                 {
  127.                     PA_FREE(form_data->current_text);
  128.                 }
  129.             }
  130.             break;
  131.         case FORM_TYPE_SELECT_ONE:
  132.         case FORM_TYPE_SELECT_MULT:
  133.             {
  134.                 int i;
  135.                 lo_FormElementSelectData *form_data;
  136.                 lo_FormElementOptionData *options;
  137.  
  138.                 form_data = (lo_FormElementSelectData *)
  139.                         element_data;
  140.                 if (form_data->name != NULL)
  141.                 {
  142.                     PA_FREE(form_data->name);
  143.                 }
  144.                 if (form_data->option_cnt > 0)
  145.                 {
  146.                     PA_LOCK(options,
  147.                     lo_FormElementOptionData *,
  148.                     form_data->options);
  149.                     for (i=0; i < form_data->option_cnt; i++)
  150.                     {
  151.                     if (options[i].text_value != NULL)
  152.                     {
  153.                        PA_FREE(options[i].text_value);
  154.                     }
  155.                     if (options[i].value != NULL)
  156.                     {
  157.                        PA_FREE(options[i].value);
  158.                     }
  159.                     }
  160.                     PA_UNLOCK(form_data->options);
  161.                     PA_FREE(form_data->options);
  162.                 }
  163.             }
  164.             break;
  165.         case FORM_TYPE_KEYGEN:
  166.             {
  167.                 lo_FormElementKeygenData *form_data;
  168.  
  169.                 form_data = (lo_FormElementKeygenData *)
  170.                         element_data;
  171.                 if (form_data->name != NULL)
  172.                 {
  173.                     PA_FREE(form_data->name);
  174.                 }
  175.                 if (form_data->challenge != NULL)
  176.                 {
  177.                     PA_FREE(form_data->challenge);
  178.                 }
  179.                 if (form_data->value_str != NULL)
  180.                 {
  181.                     XP_FREE(form_data->value_str);
  182.                 }
  183.             }
  184.             break;
  185.         case FORM_TYPE_OBJECT:
  186.             {
  187.                 lo_FormElementObjectData *form_data;
  188.  
  189.                 form_data = (lo_FormElementObjectData *)
  190.                         element_data;
  191.                 if (form_data->name != NULL)
  192.                 {
  193.                     PA_FREE(form_data->name);
  194.                 }
  195.             }
  196.             break;
  197.         default:
  198.             break;
  199.     }
  200. }
  201.  
  202.  
  203. void
  204. lo_CleanFormElementData(LO_FormElementData *element_data)
  205. {
  206.     int32 element_type;
  207.  
  208.     if (element_data == NULL)
  209.     {
  210.         return;
  211.     }
  212.  
  213.     element_type = element_data->type;
  214.  
  215.     switch(element_type)
  216.     {
  217.         case FORM_TYPE_TEXT:
  218.         case FORM_TYPE_PASSWORD:
  219.         case FORM_TYPE_FILE:
  220.             {
  221.                 lo_FormElementTextData *form_data;
  222.  
  223.                 form_data = (lo_FormElementTextData *)
  224.                         element_data;
  225.                 if (form_data->name != NULL)
  226.                 {
  227.                     PA_FREE(form_data->name);
  228.                     form_data->name = NULL;
  229.                 }
  230.                 if (form_data->default_text != NULL)
  231.                 {
  232.                     PA_FREE(form_data->default_text);
  233.                     form_data->default_text = NULL;
  234.                 }
  235.             }
  236.             break;
  237.         case FORM_TYPE_SUBMIT:
  238.         case FORM_TYPE_RESET:
  239.         case FORM_TYPE_BUTTON:
  240.         case FORM_TYPE_HIDDEN:
  241.         case FORM_TYPE_READONLY:
  242.             {
  243.                 lo_FormElementMinimalData *form_data;
  244.  
  245.                 form_data = (lo_FormElementMinimalData *)
  246.                         element_data;
  247.                 if (form_data->name != NULL)
  248.                 {
  249.                     PA_FREE(form_data->name);
  250.                     form_data->name = NULL;
  251.                 }
  252.                 if (form_data->value != NULL)
  253.                 {
  254.                     PA_FREE(form_data->value);
  255.                     form_data->value = NULL;
  256.                 }
  257.             }
  258.             break;
  259.         case FORM_TYPE_RADIO:
  260.         case FORM_TYPE_CHECKBOX:
  261.             {
  262.                 lo_FormElementToggleData *form_data;
  263.  
  264.                 form_data = (lo_FormElementToggleData *)
  265.                         element_data;
  266.                 if (form_data->name != NULL)
  267.                 {
  268.                     PA_FREE(form_data->name);
  269.                     form_data->name = NULL;
  270.                 }
  271.                 if (form_data->value != NULL)
  272.                 {
  273.                     PA_FREE(form_data->value);
  274.                     form_data->value = NULL;
  275.                 }
  276.             }
  277.             break;
  278.         case FORM_TYPE_TEXTAREA:
  279.             {
  280.                 lo_FormElementTextareaData *form_data;
  281.  
  282.                 form_data = (lo_FormElementTextareaData *)
  283.                         element_data;
  284.                 if (form_data->name != NULL)
  285.                 {
  286.                     PA_FREE(form_data->name);
  287.                     form_data->name = NULL;
  288.                 }
  289.                 if (form_data->default_text != NULL)
  290.                 {
  291.                     PA_FREE(form_data->default_text);
  292.                     form_data->default_text = NULL;
  293.                 }
  294.             }
  295.             break;
  296.         case FORM_TYPE_SELECT_ONE:
  297.         case FORM_TYPE_SELECT_MULT:
  298.             {
  299. /* OPTION arrays are freed later
  300.                 int i;
  301.                 lo_FormElementOptionData *options;
  302. */
  303.                 lo_FormElementSelectData *form_data;
  304.  
  305.                 form_data = (lo_FormElementSelectData *)
  306.                         element_data;
  307.                 if (form_data->name != NULL)
  308.                 {
  309.                     PA_FREE(form_data->name);
  310.                     form_data->name = NULL;
  311.                 }
  312. /* OPTION arrays are freed later
  313.                 if (form_data->option_cnt > 0)
  314.                 {
  315.                     PA_LOCK(options,
  316.                     lo_FormElementOptionData *,
  317.                     form_data->options);
  318.                     for (i=0; i < form_data->option_cnt; i++)
  319.                     {
  320.                     if (options[i].text_value != NULL)
  321.                     {
  322.                        PA_FREE(options[i].text_value);
  323.                     }
  324.                     if (options[i].value != NULL)
  325.                     {
  326.                        PA_FREE(options[i].value);
  327.                     }
  328.                     }
  329.                     PA_UNLOCK(form_data->options);
  330.                     PA_FREE(form_data->options);
  331.                 }
  332. */
  333.             }
  334.             break;
  335.         case FORM_TYPE_KEYGEN:
  336.             {
  337.                 lo_FormElementKeygenData *form_data;
  338.  
  339.                 form_data = (lo_FormElementKeygenData *)
  340.                         element_data;
  341.                 if (form_data->name != NULL)
  342.                 {
  343.                     PA_FREE(form_data->name);
  344.                     form_data->name = NULL;
  345.                 }
  346.                 if (form_data->challenge != NULL)
  347.                 {
  348.                     PA_FREE(form_data->challenge);
  349.                     form_data->challenge = NULL;
  350.                 }
  351.                 if (form_data->value_str != NULL)
  352.                 {
  353.                     XP_FREE(form_data->value_str);
  354.                     form_data->value_str = NULL;
  355.                 }
  356.             }
  357.             break;
  358.         case FORM_TYPE_OBJECT:
  359.             {
  360.                 lo_FormElementObjectData *form_data;
  361.  
  362.                 form_data = (lo_FormElementObjectData *)
  363.                         element_data;
  364.                 if (form_data->name != NULL)
  365.                 {
  366.                     PA_FREE(form_data->name);
  367.                     form_data->name = NULL;
  368.                 }
  369.             }
  370.             break;
  371.         default:
  372.             break;
  373.     }
  374. }
  375.  
  376. PRIVATE
  377. Bool
  378. lo_remove_image(lo_DocLists *doc_lists, LO_Element *element)
  379. {
  380.     LO_ImageStruct *image, *last = NULL;
  381.     
  382.     for (image = doc_lists->image_list;
  383.          image != (LO_ImageStruct *)element;
  384.          image = image->next_image)
  385.     {
  386.         if (image == NULL)
  387.             break;
  388.         last = image;
  389.     }
  390.     if (image != NULL)
  391.     {
  392.         if (last != NULL)
  393.         {
  394.             last->next_image = image->next_image;
  395.         }
  396.         else
  397.         {
  398.             doc_lists->image_list = image->next_image;
  399.         }
  400.         if (image == doc_lists->last_image)
  401.         {
  402.             doc_lists->last_image = last;
  403.         }
  404.         
  405.         return TRUE;
  406.     }
  407.     
  408.     return FALSE;
  409. }
  410.  
  411.  
  412. void
  413. lo_ScrapeElement(MWContext *context, LO_Element *element)
  414. {
  415.     if (element == NULL)
  416.     {
  417.         return;
  418.     }
  419. #ifdef EDITOR
  420.     if ( EDT_IS_EDITOR(context) )
  421.     {
  422.         if ( element->lo_any.edit_element != NULL )
  423.         {
  424.             EDT_ResetLayoutElement(element->lo_any.edit_element, element->lo_any.edit_offset, element);
  425.             element->lo_any.edit_element = NULL;
  426.             element->lo_any.edit_offset = 0;
  427.         }
  428.     }
  429. #endif
  430.     switch(element->type)
  431.     {
  432.         case LO_TEXT:
  433.             /* BRAIN DAMAGE: We currently override LO_ELE_INVISIBLE to flag that the text element uses the */
  434.             /* new layout scheme and hence the text ptr is not a real ptr */
  435.             if ( ( element->lo_text.text != NULL ) && !( element->lo_text.ele_attrmask & LO_ELE_INVISIBLE ))
  436.             {
  437.                 PA_FREE(element->lo_text.text);
  438.                 element->lo_text.text = NULL;
  439.             }
  440.             break;
  441.  
  442.         case LO_LINEFEED:
  443.         case LO_HRULE:
  444.         case LO_BULLET:
  445.             break;
  446.  
  447.         case LO_EDGE:
  448.             FE_FreeEdgeElement(context, (LO_EdgeStruct *)element);
  449.             break;
  450.  
  451.         case LO_FORM_ELE:
  452. /*
  453.  * these are now persistent, don't free element->lo_form.element_data
  454.  */
  455.             element->lo_form.element_data = NULL;
  456.             break;
  457.  
  458.         case LO_EMBED:
  459.             FE_FreeEmbedElement(context, (LO_EmbedStruct *)element);
  460.             if (element->lo_embed.embed_src != NULL)
  461.             {
  462.                 PA_FREE(element->lo_embed.embed_src);
  463.             }
  464.             element->lo_embed.embed_src = NULL;
  465.  
  466.             /* Free all the attribute names */
  467.             if (element->lo_embed.attribute_list != NULL)
  468.             {
  469.                 int32     current;
  470.                 
  471.                 for (current=0; current<element->lo_embed.attribute_cnt; current++)
  472.                 {
  473.                     PA_FREE(element->lo_embed.attribute_list[current]);
  474.                     element->lo_embed.attribute_list[current] = NULL;
  475.                 }
  476.                         
  477.                 PA_FREE(element->lo_embed.attribute_list);
  478.                 element->lo_embed.attribute_list = NULL;
  479.             }
  480.  
  481.             /* Free all the attribute values */
  482.             if (element->lo_embed.value_list != NULL)
  483.             {
  484.                 int32     current;
  485.                 
  486.                 for (current=0; current<element->lo_embed.attribute_cnt; current++)
  487.                 {
  488.                     PA_FREE(element->lo_embed.value_list[current]);
  489.                     element->lo_embed.value_list[current] = NULL;
  490.                 }
  491.  
  492.                 PA_FREE(element->lo_embed.value_list);
  493.                 element->lo_embed.value_list = NULL;
  494.             }
  495.  
  496.             /*
  497.              * If there is session data here after we
  498.              * return from the front end freeing the embed 
  499.              * element, they want us to save this in history,
  500.              * and pass it back if/when we come back here.
  501.              * Otherwise, save the NULL.
  502.              */
  503.             lo_AddEmbedData(context,
  504.                     element->lo_embed.session_data,
  505.                     NPL_DeleteSessionData,
  506.                     element->lo_embed.embed_index);
  507.             element->lo_embed.session_data = NULL;
  508.             break;
  509. #ifdef JAVA
  510.         case LO_JAVA:
  511.             FE_HideJavaAppElement(context, element->lo_java.session_data);
  512.             if (element->lo_java.attr_code != NULL)
  513.             {
  514.                 PA_FREE(element->lo_java.attr_code);
  515.                 element->lo_java.attr_code = NULL;
  516.             }
  517.             if (element->lo_java.attr_codebase != NULL)
  518.             {
  519.                 PA_FREE(element->lo_java.attr_codebase);
  520.                 element->lo_java.attr_codebase = NULL;
  521.             }
  522.             if (element->lo_java.attr_archive != NULL)
  523.             {
  524.                 PA_FREE(element->lo_java.attr_archive);
  525.                 element->lo_java.attr_archive = NULL;
  526.             }
  527.             if (element->lo_java.attr_name != NULL)
  528.             {
  529.                 PA_FREE(element->lo_java.attr_name);
  530.                 element->lo_java.attr_name = NULL;
  531.             }
  532.             if (element->lo_java.base_url != NULL)
  533.             {
  534.                 PA_FREE(element->lo_java.base_url);
  535.                 element->lo_java.base_url = NULL;
  536.             }
  537.             if (element->lo_java.param_names != NULL)
  538.             {
  539.                 int32     current;
  540.                 
  541.                 for (current=0; current<element->lo_java.param_cnt; current++)
  542.                 {
  543.                     PA_FREE(element->lo_java.param_names[current]);
  544.                     element->lo_java.param_names[current] = NULL;
  545.                 }
  546.                         
  547.                 PA_FREE(element->lo_java.param_names);
  548.                 element->lo_java.param_names = NULL;
  549.             }
  550.             if (element->lo_java.param_values != NULL)
  551.             {
  552.                 int32     current;
  553.                 
  554.                 for (current=0; current<element->lo_java.param_cnt; current++)
  555.                 {
  556.                     PA_FREE(element->lo_java.param_values[current]);
  557.                     element->lo_java.param_values[current] = NULL;
  558.                 }
  559.  
  560.                 PA_FREE(element->lo_java.param_values);
  561.                 element->lo_java.param_values = NULL;
  562.             }
  563.  
  564.             /*
  565.              * If there is session data here after we
  566.              * return from the front end freeing the java applet 
  567.              * element, they want us to save this in history,
  568.              * and pass it back if/when we come back here.
  569.              * Otherwise, save the NULL.
  570.              */
  571.             lo_AddEmbedData(context,
  572.                     element->lo_java.session_data,
  573.                     LJ_DeleteSessionData,
  574.                     element->lo_java.embed_index);
  575.             element->lo_java.session_data = NULL;
  576.             break;
  577. #endif /* JAVA */
  578.         case LO_IMAGE:
  579.                         if (element->lo_image.image_req != NULL) 
  580.                             IL_DestroyImage(element->lo_image.image_req);
  581.                         element->lo_image.image_req = NULL;
  582.  
  583.                         if (element->lo_image.image_attr &&
  584.                             !(element->lo_image.image_attr->attrmask & LO_ATTR_BACKDROP) &&
  585.                             element->lo_image.layer) {
  586.                 CL_Layer *parent = CL_GetLayerParent(element->lo_image.layer);
  587.                 /* We might not have yet attached the image layer to its parent 
  588.                    because we don't know which layer it should be place in. */
  589.                 if (parent)
  590.                 CL_RemoveChild(parent, element->lo_image.layer);
  591.                             CL_DestroyLayer(element->lo_image.layer);
  592.                             element->lo_image.layer = NULL;
  593.                         }
  594.                     
  595.             if (element->lo_image.alt != NULL)
  596.             {
  597.                 PA_FREE(element->lo_image.alt);
  598.             }
  599.             element->lo_image.alt = NULL;
  600.             if (element->lo_image.image_url != NULL)
  601.             {
  602.                 PA_FREE(element->lo_image.image_url);
  603.             }
  604.             element->lo_image.image_url = NULL;
  605.             if (element->lo_image.lowres_image_url != NULL)
  606.             {
  607.                 PA_FREE(element->lo_image.lowres_image_url);
  608.             }
  609.             element->lo_image.lowres_image_url = NULL;
  610.             lo_FreeImageAttributes(element->lo_image.image_attr);
  611.             element->lo_image.image_attr = NULL;
  612.  
  613.             /* 
  614.              * make sure this element isn't sitting on the
  615.              *   image list
  616.              */
  617.             {
  618.                 int32 doc_id;
  619.                 lo_TopState *top_state;
  620.                             
  621.                 doc_id = XP_DOCID(context);
  622.                 top_state = lo_FetchTopState(doc_id);
  623.                 if (top_state == NULL)
  624.                 break;
  625.  
  626.                 /* need to remove from the top_state->image_list */
  627.                             lo_remove_image(&top_state->doc_lists,
  628.                                             element);
  629.             }
  630.             break;
  631.         case LO_CELL:
  632.             {
  633.                 int32 doc_id;
  634.                 lo_TopState *top_state;
  635.  
  636.                 doc_id = XP_DOCID(context);
  637.                 top_state = lo_FetchTopState(doc_id);
  638.                 if ((top_state != NULL)&&
  639.                 (top_state->doc_state != NULL))
  640.                 {
  641.                 lo_DocState *state;
  642.  
  643.                 state = top_state->doc_state;
  644.                 if (element->lo_cell.cell_list != NULL)
  645.                 {
  646.                     if (element->lo_cell.cell_list_end != NULL)
  647.                     {
  648.                     element->lo_cell.cell_list_end->lo_any.next = NULL;
  649.                     }
  650.                     lo_RecycleElements(context, state,
  651.                     element->lo_cell.cell_list);
  652.                     element->lo_cell.cell_list = NULL;
  653.                     element->lo_cell.cell_list_end = NULL;
  654.                 }
  655.                 if (element->lo_cell.cell_float_list != NULL)
  656.                 {
  657.                     lo_RecycleElements(context, state,
  658.                     element->lo_cell.cell_float_list);
  659.                     element->lo_cell.cell_float_list = NULL;
  660.                 }
  661.                                 XP_FREEIF(element->lo_cell.backdrop.bg_color);
  662.                 }
  663.  
  664.                             /* Free the background layer */
  665.                             if ( element->lo_cell.cell_bg_layer != NULL)
  666.                             {
  667.                                 CL_Layer *layer = element->lo_cell.cell_bg_layer;
  668.                                 CL_RemoveChild(CL_GetLayerParent(layer),
  669.                                                layer);
  670.                                 CL_DestroyLayer(layer);
  671.                                 element->lo_cell.cell_bg_layer = NULL;
  672.                             }
  673.             }
  674.             break;
  675.  
  676.  
  677.         case LO_TABLE:
  678.             {
  679.                 lo_TableRec *table = (lo_TableRec *) element->lo_table.table;
  680.                 lo_TopState *top_state;
  681.                 lo_DocState *state;
  682.                             
  683.                 if (table != NULL)
  684.                 {
  685.                     top_state = lo_FetchTopState(XP_DOCID(context));
  686.                     state = top_state->doc_state;
  687.                     lo_free_table_record(context, state, table, TRUE);
  688.                 }
  689.  
  690.             }
  691.             break;
  692.  
  693.  
  694.         case LO_MULTICOLUMN:
  695.             /* should we do this? */
  696.               if (element->lo_multicolumn.tag != NULL)
  697.               {
  698.                 PA_FreeTag(element->lo_multicolumn.tag);
  699.                 if (element->lo_multicolumn.multicol == NULL)
  700.                 {
  701.                     XP_DELETE(element->lo_multicolumn.multicol);
  702.                 }
  703.                 element->lo_multicolumn.tag = NULL;
  704.               }
  705.             break;
  706.  
  707.         case LO_BLOCKQUOTE:
  708.             /* should we do this? */
  709.               if (element->lo_blockquote.tag != NULL)
  710.               {
  711.                 PA_FreeTag(element->lo_blockquote.tag);
  712.                 element->lo_blockquote.tag = NULL;
  713.               }
  714.             break;
  715.         case LO_SPACER:            
  716.             if (element->lo_spacer.tag != NULL)
  717.               {
  718.                 PA_FreeTag(element->lo_spacer.tag);
  719.                 element->lo_spacer.tag = NULL;
  720.               }
  721.             break;
  722.         case LO_TEXTBLOCK:
  723.             /* LO_TEXTBLOCK */
  724.             if ( element->lo_textBlock.text_buffer != NULL )
  725.             {
  726.                 XP_FREE ( element->lo_textBlock.text_buffer );
  727.                 element->lo_textBlock.text_buffer = NULL;
  728.             }
  729.             
  730.             if ( element->lo_textBlock.break_table != NULL )
  731.             {
  732.                 XP_FREE ( element->lo_textBlock.break_table );
  733.                 element->lo_textBlock.break_table = NULL;
  734.             }
  735.             break;
  736.     }
  737. }
  738.  
  739.  
  740. void
  741. lo_FreeElement(MWContext *context, LO_Element *element, Bool do_scrape)
  742. {
  743.     if (element == NULL)
  744.     {
  745.         return;
  746.     }
  747.  
  748.     if (do_scrape != FALSE)
  749.     {
  750.         lo_ScrapeElement(context, element);
  751.     }
  752.  
  753. #ifdef MEMORY_ARENAS
  754.     if (EDT_IS_EDITOR(context)) {
  755.         XP_DELETE(element);
  756.     }
  757. #else
  758.     XP_DELETE(element);
  759. #endif /* MEMORY_ARENAS */
  760. }
  761.  
  762. void
  763. lo_FreeImageAttributes(LO_ImageAttr *image_attr)
  764. {
  765.     if (image_attr)
  766.     {
  767.         if (image_attr->usemap_name)
  768.         {
  769.             XP_FREE(image_attr->usemap_name);
  770.             image_attr->usemap_name = NULL;
  771.         }
  772.         
  773.         /*    ***** WARNING *****  Do NOT free "usemap_ptr" here since it is a pointer
  774.             into a shared list in top_state that will get freed later. */
  775.         
  776.         XP_DELETE(image_attr);
  777.     }
  778. }
  779.  
  780. #ifdef XP_WIN16
  781. #include <malloc.h>
  782. #endif
  783.  
  784. int32
  785. lo_FreeRecycleList(MWContext* context, LO_Element *recycle_list)
  786. {
  787.     LO_Element *element;
  788.     LO_Element *eptr;
  789.  
  790.     int32 cnt;
  791.  
  792.     LO_LockLayout();
  793.  
  794.     cnt = 0;
  795. #ifdef MEMORY_ARENAS
  796.     if ( EDT_IS_EDITOR(context) ) {
  797. #endif /* MEMORY_ARENAS */
  798.         eptr = recycle_list;
  799.         while (eptr != NULL)
  800.         {
  801.         element = eptr;
  802.         eptr = eptr->lo_any.next;
  803.         element->lo_any.next = NULL;
  804.         element->lo_any.prev = NULL;
  805.         XP_DELETE(element);
  806.         cnt++;
  807.         }
  808.         cnt = cnt * sizeof(LO_Element);
  809. #ifdef MEMORY_ARENAS
  810.     }
  811. #endif /* MEMORY_ARENAS */
  812.  
  813. #ifdef XP_WIN16
  814.     _heapmin();
  815. #endif
  816.  
  817.     LO_UnlockLayout();
  818.  
  819.     return(cnt);
  820. }
  821.  
  822.  
  823. void
  824. lo_FreeElementList(MWContext *context, LO_Element *elist)
  825. {
  826.     LO_Element *eptr;
  827.     LO_Element *element;
  828.  
  829.     eptr = elist;
  830.     while (eptr != NULL)
  831.     {
  832.         element = eptr;
  833.         eptr = eptr->lo_any.next;
  834.         lo_FreeElement(context, element, TRUE);
  835.     }
  836. }
  837.  
  838.  
  839. void
  840. lo_FreeDocumentFormListData(MWContext *context, lo_SavedFormListData *fptr)
  841. {
  842.     int i;
  843.     LO_FormElementData **data_list;
  844.  
  845.     if (fptr == NULL)
  846.     {
  847.         return;
  848.     }
  849.  
  850.     fptr->valid = FALSE;
  851.     PA_LOCK(data_list, LO_FormElementData **, fptr->data_list);
  852.     if (data_list != NULL)
  853.     {
  854.         for (i=0; i < (fptr->data_count); i++)
  855.         {
  856.         if (data_list[i] != NULL)
  857.         {
  858.             FE_FreeFormElement(context, (LO_FormElementData *)data_list[i]);
  859.             lo_FreeFormElementData(data_list[i]);
  860.             XP_DELETE(data_list[i]);
  861.         }
  862.         }
  863.     }
  864.     PA_UNLOCK(fptr->data_list);
  865.  
  866.     if (fptr->data_list != NULL)
  867.     {
  868.         PA_FREE(fptr->data_list);
  869.     }
  870.  
  871.     fptr->data_index = 0;
  872.         fptr->data_count = 0;
  873.         fptr->data_list = NULL;
  874.         fptr->next = NULL;
  875. }
  876.  
  877.  
  878. void
  879. lo_FreeDocumentEmbedListData(MWContext *context, lo_SavedEmbedListData *eptr)
  880. {
  881.     if (eptr == NULL)
  882.     {
  883.         return;
  884.     }
  885.     /* MWH -- If this routine is changed, place make sure that cmd\winfe\cxprint.cpp and 
  886.     cmd\winfe\cxmeat.cpp is changed also.   */
  887. #ifdef XP_WIN
  888.     
  889.     /* do not free the data, we need it for printing and metafile.*/
  890.     if (context->type == MWContextPrint || context->type == MWContextMetaFile)
  891.         return;
  892. #endif
  893.     if (eptr->embed_data_list != NULL)
  894.     {
  895.         int32 i;
  896.         lo_EmbedDataElement* embed_data_list;
  897.  
  898.         PA_LOCK(embed_data_list, lo_EmbedDataElement*, eptr->embed_data_list);
  899.         for (i=0; i < eptr->embed_count; i++)
  900.         {
  901.             if (embed_data_list[i].freeProc && embed_data_list[i].data)
  902.                 (*(embed_data_list[i].freeProc))(context, embed_data_list[i].data);
  903.         }
  904.         PA_UNLOCK(eptr->embed_data_list);
  905.         PA_FREE(eptr->embed_data_list);
  906.     }
  907.  
  908.     eptr->embed_count = 0;
  909.     eptr->embed_data_list = NULL;
  910. }
  911.  
  912.  
  913. void
  914. lo_FreeDocumentGridData(MWContext *context, lo_SavedGridData *sgptr)
  915. {
  916.     if (sgptr == NULL)
  917.     {
  918.         return;
  919.     }
  920.  
  921.     if (sgptr->the_grid != NULL)
  922.     {
  923.         lo_GridRec *grid;
  924.         lo_GridCellRec *cell_ptr;
  925.  
  926.         grid = sgptr->the_grid;
  927.         cell_ptr = grid->cell_list;
  928.         while (cell_ptr != NULL)
  929.         {
  930.             lo_GridCellRec *tmp_cell;
  931.  
  932.             tmp_cell = cell_ptr;
  933.             cell_ptr = cell_ptr->next;
  934.             lo_FreeGridCellRec(context, grid, tmp_cell);
  935.         }
  936.         lo_FreeGridRec(grid);
  937.     }
  938.  
  939.     sgptr->main_width = 0;
  940.     sgptr->main_height = 0;
  941.     sgptr->the_grid = NULL;
  942. }
  943.  
  944. void
  945. LO_FreeSubmitData(LO_FormSubmitData *submit_data)
  946. {
  947.     int32 i;
  948.     PA_Block *name_array, *value_array;
  949.  
  950.     if (submit_data == NULL)
  951.     {
  952.         return;
  953.     }
  954.  
  955.     if (submit_data->action != NULL)
  956.     {
  957.         PA_FREE(submit_data->action);
  958.     }
  959.  
  960.     PA_LOCK(name_array, PA_Block *, submit_data->name_array);
  961.     PA_LOCK(value_array, PA_Block *, submit_data->value_array);
  962.     for (i=0; i < (submit_data->value_cnt); i++)
  963.     {
  964.         if (name_array[i] != NULL)
  965.         {
  966.             PA_FREE(name_array[i]);
  967.         }
  968.         if (value_array[i] != NULL)
  969.         {
  970.             PA_FREE(value_array[i]);
  971.         }
  972.     }
  973.     PA_UNLOCK(submit_data->value_array);
  974.     PA_UNLOCK(submit_data->name_array);
  975.     if (submit_data->name_array != NULL)
  976.     {
  977.         PA_FREE(submit_data->name_array);
  978.     }
  979.     if (submit_data->value_array != NULL)
  980.     {
  981.         PA_FREE(submit_data->value_array);
  982.     }
  983.     if (submit_data->type_array != NULL)
  984.     {
  985.         PA_FREE(submit_data->type_array);
  986.     }
  987.  
  988.     XP_DELETE(submit_data);
  989. }
  990.  
  991.  
  992. int32
  993. LO_EmptyRecyclingBin(MWContext *context)
  994. {
  995.     int32 doc_id;
  996.     lo_TopState *top_state;
  997.     int32 cnt;
  998.  
  999.     /*
  1000.      * Get the unique document ID, and retreive this
  1001.      * documents layout state.
  1002.      */
  1003.     doc_id = XP_DOCID(context);
  1004.     top_state = lo_FetchTopState(doc_id);
  1005.     if ((top_state == NULL)||(top_state->doc_state == NULL))
  1006.     {
  1007.         return(0);
  1008.     }
  1009.  
  1010.     cnt = lo_FreeRecycleList(context, top_state->recycle_list);
  1011.     top_state->recycle_list = NULL;
  1012. #ifdef MEMORY_ARENAS
  1013.     if (top_state->current_arena != NULL)
  1014.     {
  1015.         int32 cnt2;
  1016.  
  1017.         cnt2 = lo_FreeMemoryArena(top_state->current_arena->next);
  1018.         top_state->current_arena->next = NULL;
  1019.         cnt += cnt2;
  1020.     }
  1021. #endif /* MEMORY_ARENAS */
  1022.  
  1023.     return(cnt);
  1024. }
  1025.  
  1026.  
  1027. #ifdef PROFILE
  1028. #pragma profile off
  1029. #endif
  1030.