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

  1. /* -*- Mode: C; tab-width: 8; 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.  
  20. /*
  21.    layrelay.c --- reflow of layout elements.
  22.    Created: Nisheeth Ranjan <nisheeth@netscape.com>, 7-Nov-1997.
  23.  */
  24. #include "xp.h"
  25. #include "net.h"
  26. #include "pa_parse.h"
  27. #include "layout.h"
  28. #include "laylayer.h"
  29. #include "layers.h"
  30. #include "layrelay.h"
  31. #include "laytrav.h"
  32. #ifdef EDITOR
  33. #include "edt.h"
  34. #endif
  35.  
  36. #include "libmocha.h"
  37. #include "libevent.h"
  38.  
  39. extern int MK_OUT_OF_MEMORY;
  40.  
  41. #ifdef PROFILE
  42. #pragma profile on
  43. #endif
  44.  
  45. #ifdef TEST_16BIT
  46. #define XP_WIN16
  47. #endif /* TEST_16BIT */
  48.  
  49. #ifdef XP_WIN16
  50. #define SIZE_LIMIT        32000
  51. #endif /* XP_WIN16 */
  52.  
  53. static lo_DocState *lo_rl_InitDocState( MWContext *context, lo_DocState *state,
  54.                     int32 width, int32 height,
  55.                     int32 margin_width, int32 margin_height);
  56. static void lo_rl_PreLayoutElement ( MWContext *context, lo_DocState * state,
  57.                      LO_Element *lo_ele );
  58. static void lo_rl_CopyCellToState( LO_CellStruct *cell, lo_DocState *state );
  59. static void lo_rl_CopyStateToCell( lo_DocState *state, LO_CellStruct *cell);
  60.  
  61. /* Loops through layout elements and calls their fitting functions */
  62. static void lo_rl_FitLayoutElements( lo_RelayoutState *relay_state, LO_Element *start_ele );
  63.  
  64.  
  65. static lo_DocState *
  66. lo_rl_InitDocState( MWContext *context, lo_DocState *state, int32 width, int32 height, int32 margin_width, int32 margin_height );
  67. static void lo_UpdateHeightSpanForBeginRow(lo_TableRec *table);
  68. static void lo_rl_BeginTableRelayout( MWContext *context, lo_DocState *state, lo_TableRec *table);
  69. static LO_LinefeedStruct * lo_rl_RecreateElementListsFromCells( lo_DocState *state, LO_TableStruct *table, 
  70.                                                                LO_Element **lastElementInLastCell);
  71.  
  72. typedef LO_Element * (*lo_FitFunction)( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  73.  
  74. static LO_Element * lo_rl_FitIgnore( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  75. static LO_Element * lo_rl_FitError( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  76. static LO_Element * lo_rl_FitText( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  77. static LO_Element * lo_rl_FitLineFeed( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  78. static LO_Element * lo_rl_FitHRule( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  79. static LO_Element * lo_rl_FitImage( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  80. static LO_Element * lo_rl_FitBullet( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  81. static LO_Element * lo_rl_FitFormEle( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  82. static LO_Element * lo_rl_FitTable( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  83. static LO_Element * lo_rl_FitCell( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  84. static LO_Element * lo_rl_FitEmbed( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  85. static LO_Element * lo_rl_FitJava( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  86. static LO_Element * lo_rl_FitObject( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  87. static LO_Element * lo_rl_FitParagraph( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  88. static LO_Element * lo_rl_FitCenter( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  89. static LO_Element * lo_rl_FitMulticolumn( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  90. static LO_Element * lo_rl_FitFloat( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  91. static LO_Element * lo_rl_FitTextBlock( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  92. static LO_Element * lo_rl_FitList( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  93. static LO_Element * lo_rl_FitDescTitle( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  94. static LO_Element * lo_rl_FitDescText( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  95. static LO_Element * lo_rl_FitBlockQuote( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  96. static LO_Element * lo_rl_FitLayer( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  97. static LO_Element * lo_rl_FitHeading( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  98. static LO_Element * lo_rl_FitSpan( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  99. static LO_Element * lo_rl_FitDiv( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  100. static LO_Element * lo_rl_FitSpacer( lo_RelayoutState *relay_state, LO_Element *lo_ele );
  101.  
  102. /* The table of fitting functions for each layout element type... */
  103. static lo_FitFunction lo_rl_FitFunctionTable[] = {
  104.     lo_rl_FitIgnore,        /* LO_NONE */
  105.     lo_rl_FitText,            /* LO_TEXT */
  106.     lo_rl_FitLineFeed,        /* LO_LINEFEED */
  107.     lo_rl_FitHRule,            /* LO_HRULE */
  108.     lo_rl_FitImage,            /* LO_IMAGE */
  109.     lo_rl_FitBullet,        /* LO_BULLET */
  110.     lo_rl_FitFormEle,        /* LO_FORM_ELE */
  111.     lo_rl_FitError,            /* LO_SUBDOC elements should not occur in line list */
  112.     lo_rl_FitTable,            /* LO_TABLE */
  113.     lo_rl_FitCell,            /* LO_CELL */
  114.     lo_rl_FitEmbed,            /* LO_EMBED */
  115.     lo_rl_FitError,            /* LO_EDGE element: Either an error or we should ignore. ??? */
  116.     lo_rl_FitJava,            /* LO_JAVA */
  117.     lo_rl_FitError,            /* LO_SCRIPT elements should not occur in list of layout elements */
  118.     lo_rl_FitObject,        /* LO_OBJECT */
  119.     lo_rl_FitParagraph,        /* LO_PARAGRAPH */
  120.     lo_rl_FitCenter,        /* LO_CENTER */
  121.     lo_rl_FitMulticolumn,    /* LO_MULTICOLUMN */
  122.     lo_rl_FitFloat,            /* LO_FLOAT */
  123.     lo_rl_FitTextBlock,        /* LO_TEXTBLOCK */
  124.     lo_rl_FitList,            /* LO_LIST */
  125.     lo_rl_FitDescTitle,        /* LO_DESCTITLE */
  126.     lo_rl_FitDescText,        /* LO_DESCTEXT */
  127.     lo_rl_FitBlockQuote,    /* LO_BLOCKQUOTE */
  128.     lo_rl_FitLayer,            /* LO_LAYER */
  129.     lo_rl_FitHeading,        /* LO_HEADING */
  130.     lo_rl_FitSpan,            /* LO_SPAN */
  131.     lo_rl_FitDiv,            /* LO_DIV */
  132.     lo_rl_FitSpacer            /* LO_SPACER */
  133. };
  134.  
  135.  
  136. /*    NRA - 10/3/97: Main Relayout Entry Point
  137.  *  This function walks through the layout element list and re-lays out
  138.  *  the elements to fit into a window of the specified width and height.
  139.  *
  140.  *    It needs to be called on each resize of the window.
  141.  *
  142.  *    Issues to be careful about: 1) Synchronization with Javascript that is running concurrently while this
  143.  *    re-layout is going on.
  144.  *
  145.  *    2) Keep a copy of elements that change.  Will come in handy later to figure out the redraw rectangle.
  146.  *    For now, we dirty the entire document
  147.  *
  148.  *    3) FE needs to tell us the position in the current document.  We will need to determine the element id
  149.  *    at that position and call FE_SetDocPosition to set the document to the saved position after relayout
  150.  */
  151. void LO_RelayoutOnResize(MWContext *context, int32 width, int32 height, int32 leftMargin, int32 topMargin)
  152. {
  153.     lo_RelayoutState *relay_state;
  154.     lo_DocState *state;
  155.     LO_Element *lo_ele;
  156.     int32 docX, docY;
  157.     lo_TopState *top_state;
  158.  
  159.     /* check to see if the context we've been passed is a grid context.  If so, branch to the grid
  160.        specific resize routine, which will call this one again on its grid cells. */
  161.     top_state = lo_FetchTopState(XP_DOCID(context));
  162.     if (top_state == NULL)  {
  163.       return;
  164.     }
  165.  
  166.     LO_LockLayout();
  167.  
  168.     if (top_state->the_grid) {
  169.       /* the document doesn't have any elements.  It's a grid document */
  170.       lo_RelayoutGridDocumentOnResize(context, top_state, width, height);
  171.       LO_UnlockLayout();
  172.       return;
  173.     }
  174.  
  175.     relay_state = lo_rl_CreateRelayoutState();
  176.     if (relay_state == NULL) {
  177.         LO_UnlockLayout();
  178.         return;  /* Better error handling later */
  179.     }
  180.  
  181.     /* Reset the scoping for any JavaScript to be the top-level layer. */
  182.     /* ET_SetActiveLayer(context, LO_DOCUMENT_LAYER_ID); */
  183.  
  184.     /* remember where we are in the document */
  185.     FE_GetDocPosition ( context, FE_VIEW, &docX, &docY );
  186.  
  187.     /* shrink the layout document in case we get smaller */
  188.     LO_SetDocumentDimensions(context, 0, 0);
  189.  
  190.     if (lo_rl_InitRelayoutState(context, relay_state, width, height, leftMargin, topMargin) != NULL) 
  191.     {
  192.         lo_ele = lo_tv_GetFirstLayoutElement(relay_state->doc_state);
  193.         lo_rl_FitLayoutElements(relay_state, lo_ele);
  194.             
  195.         /* Flush out any remaining elements on the line list into the line array. */        
  196.         lo_rl_AddSoftBreakAndFlushLine(relay_state->context, relay_state->doc_state);
  197.         lo_EndLayoutDuringReflow( relay_state->context, relay_state->doc_state );
  198.     }        
  199.     else 
  200.     {
  201.         lo_rl_DestroyRelayoutState(relay_state);
  202.         LO_UnlockLayout();
  203.         return;
  204.     }
  205.  
  206.     state = relay_state->doc_state;
  207.  
  208.     /* Send JS load event.  JS will treat it as a resize by looking at the resize_reload param */
  209.     ET_SendLoadEvent(context, EVENT_LOAD, NULL, NULL, 
  210.                              LO_DOCUMENT_LAYER_ID, 
  211.                              state->top_state->resize_reload);
  212.  
  213.     /* Reset state for force loading images. */
  214.     LO_SetForceLoadImage(NULL, FALSE);
  215.  
  216.     /* position the document */
  217.     FE_SetDocPosition ( context, FE_VIEW, 0, docY );
  218.  
  219.     /* update the final document dimensions */
  220.     state->y += state->win_bottom;
  221.     LO_SetDocumentDimensions(context, state->max_width, state->y);
  222.     
  223.     if(!state->top_state->is_binary)
  224.         FE_SetProgressBarPercent(context, 100);
  225.  
  226.     FE_FinishedLayout(context);
  227.  
  228.     /* Tell FE to redraw window */
  229.     if (context->compositor)
  230.     {
  231.         CL_Compositor *compositor = context->compositor;
  232.         XP_Rect rect;
  233.         CL_OffscreenMode save_offscreen_mode;
  234.  
  235.         rect.left = rect.top = 0;
  236.         rect.right = state->win_width;
  237.         rect.bottom = state->y;
  238.         
  239.         CL_UpdateDocumentRect(compositor,
  240.                               &rect, (PRBool)FALSE);
  241.  
  242.         /* Temporarily force drawing to use the offscreen buffering area to reduce
  243.            flicker when resizing. (If no offscreen store is allocated, this code will
  244.            have no effect, but it will do no harm.) */
  245.         save_offscreen_mode = CL_GetCompositorOffscreenDrawing(compositor);
  246.         CL_SetCompositorOffscreenDrawing(compositor, CL_OFFSCREEN_ENABLED);
  247.         CL_CompositeNow(compositor);
  248.         CL_SetCompositorOffscreenDrawing(compositor, save_offscreen_mode);
  249.     }
  250.  
  251.     lo_rl_DestroyRelayoutState(relay_state);
  252.  
  253.     LO_UnlockLayout();
  254.     /* Postion is hard-coded to top of document for now.*/
  255.     /* FE_SetDocPosition(context, 0, 0, 0); */
  256.     /* 2nd parameter for FE_ClearView is iView which is ignored. */
  257.     /* FE_ClearView(context, 0); */
  258.  
  259. }
  260.  
  261. /*
  262. ** Relayout a document given a change in one LO_Element*.  This is of
  263. ** primary use for plugins (since there is now an API to change the
  264. ** size of a plugin), but could also be used once the LO_Elements are
  265. ** reflected in a DOM and style information affecting the element's
  266. ** size is changed.
  267. */
  268. void
  269. LO_RelayoutFromElement(MWContext *context, LO_Element *element)
  270. {
  271.   /* toshok - we don't have all the plumbing in place yet to handle
  272.      something like this, so we punt and make it a wrapper for
  273.      LO_RelayoutOnResize.  Given that all drawing is done through a
  274.      compositor, the user shouldn't be aware of everything being
  275.      relayed out anyway.  */
  276.   int32 leftMargin, topMargin;
  277.   int32 width, height;
  278.   lo_TopState *top_state = lo_FetchTopState(XP_DOCID(context));
  279.  
  280.   if (!top_state)
  281.     return;
  282.  
  283.   width = LO_GetLayerScrollWidth(top_state->body_layer);
  284.   height = LO_GetLayerScrollHeight(top_state->body_layer);
  285.  
  286.   LO_GetDocumentMargins(context, &leftMargin, &topMargin);
  287.  
  288.   LO_RelayoutOnResize(context, width, height, leftMargin, topMargin);
  289. }
  290.  
  291. /*    
  292.  *  This function reflows a document from a given element. It's primary function is for the editor.
  293.  *    The caller must provide a state record which is correctly initialized to the position the reflow
  294.  *    will start.
  295.  *
  296.  *    It currently only works for text elements.
  297.  */
  298. void LO_Reflow(MWContext *context, lo_DocState * state, LO_Element *startElement, LO_Element *endElement)
  299. {
  300.     LO_Element *lo_ele;
  301.     lo_TopState *top_state;
  302.     lo_RelayoutState relay_state;
  303.     lo_DocState * save_state;
  304.     LO_TextBlock * block;
  305.     Bool firstElement;
  306.     
  307. #if defined( DEBUG_nisheeth ) || defined( DEBUG_toshok ) || defined( DEBUG_shannon )
  308.     if (context) {
  309.         lo_PrintLayout(context);
  310.     }
  311. #endif
  312.  
  313.     /* check to see if the context we've been passed is a grid context.  If so, branch to the grid
  314.        specific resize routine, which will call this one again on its grid cells. */
  315.     top_state = lo_FetchTopState(XP_DOCID(context));
  316.     if (top_state == NULL)  {
  317.       return;
  318.     }
  319.     
  320.     LO_LockLayout();
  321.  
  322.     /* init this by hand as we don't want to create a new state */
  323.     relay_state.context = context;
  324.     relay_state.top_state = lo_FetchTopState(XP_DOCID(context));
  325.     relay_state.doc_state = state;
  326.  
  327.     firstElement = TRUE;
  328.     lo_ele = startElement;
  329.     
  330.     while ( lo_ele != endElement ) {
  331.         lo_rl_PreLayoutElement ( context, state, lo_ele );
  332.         if (state->top_state->out_of_memory)
  333.         {
  334.             LO_UnlockLayout();
  335.             return;
  336.         }
  337.         
  338.         state->edit_force_offset = TRUE;
  339.     
  340.         save_state = top_state->doc_state;
  341.         top_state->doc_state = state;
  342.         
  343.         block = NULL;
  344.         
  345.         /*
  346.          * If we get a text element, we also need to retrieve the text block
  347.          */
  348.         if ( lo_ele->type == LO_TEXT )
  349.         {
  350. /* I'm pretty sure this ifdef is ok since EDT_GetTextBlock should always return NULL
  351.    if we're not in an editor context. hardts */
  352. #ifdef EDITOR
  353.             block = EDT_GetTextBlock ( context, lo_ele );
  354. #endif /* EDITOR */
  355.         }
  356.         
  357.         /*
  358.          * if we found a text block, then call the reflow routine with this element, otherwise
  359.          * use the default reflow code. Remember sometimes we get text elements without a text block
  360.          * (such as list elements)
  361.          */
  362.         if ( block != NULL ) {
  363.             lo_ele = lo_RelayoutTextBlock ( context, state, block, &lo_ele->lo_text );
  364.         }
  365.         else {
  366.             /*
  367.              * HACK: Until I find a better way to deal with this.
  368.              *
  369.              * The above lo_LayoutTag loop will handle setup for things like lists. This is fine
  370.              * when we're inside a list (ie past element 1) as the first thing the reflow will
  371.              * process is the bullet. However, (for a reason I don't entirely understand yet), if
  372.              * we're on the first line of the document and the list is the first element, startElement
  373.              * will point at the LO_LIST element. This means that reflow will reexecute the start list
  374.              * and we'll do the wrong thing.
  375.              *
  376.              * So, for now only, if the first element is a LO_LIST element, then skip it!
  377.              */
  378.             if ( firstElement && ( lo_ele->type == LO_LIST ) )
  379.             {
  380.                 LO_Element * next;
  381.                 
  382.                 next = lo_tv_GetNextLayoutElement ( state, lo_ele, FALSE );
  383.                 
  384.                 lo_ele->lo_any.ele_id = NEXT_ELEMENT;
  385.                 lo_ele->lo_any.x = state->x;
  386.                 lo_ele->lo_any.y = state->y;
  387.  
  388.                 state->x += lo_ele->lo_text.width;
  389.                 lo_AppendToLineList( context, state, lo_ele, 0);
  390.                 
  391.                 lo_ele = next;
  392.             }
  393.             else
  394.             {
  395.                 /* Dispatch the layout element to its fitting routine. 
  396.                    Fitting routine returns the next layout element to process */
  397.                 lo_ele = (*lo_rl_FitFunctionTable[lo_ele->type])( &relay_state, lo_ele);
  398.             }
  399.         }
  400.         
  401.         firstElement = FALSE;
  402.         
  403.         top_state->doc_state = save_state;
  404.  
  405.         if (state->top_state->out_of_memory)
  406.         {
  407.             LO_UnlockLayout();
  408.             return;
  409.         }
  410.         
  411.         if ( lo_ele == NULL )
  412.         {
  413.             LO_UnlockLayout();
  414.             break;
  415.         }
  416.         
  417.         state->edit_force_offset = FALSE;
  418.     }
  419.  
  420. #if defined( DEBUG_nisheeth ) || defined( DEBUG_toshok ) || defined( DEBUG_shannon )
  421.     if (context) {
  422.         lo_PrintLayout(context);
  423.     }
  424. #endif
  425.  
  426.     LO_UnlockLayout();
  427. }
  428.  
  429. /* Selectively cut and pasted from lo_InitDocState().  Should we separate this stuff
  430. out into a common function rather than duplicating code?  */
  431. static lo_DocState *
  432. lo_rl_InitDocState( MWContext *context, lo_DocState *state, int32 width, int32 height, int32 margin_width, int32 margin_height )
  433. {
  434.     lo_TopState *top_state = state->top_state;
  435.  
  436.     state->subdoc_tags = NULL;
  437.     state->subdoc_tags_end = NULL;
  438.  
  439.     state->win_top = margin_height;
  440.     state->win_bottom = margin_height;
  441.     state->win_width = width;
  442.     state->win_height = height;
  443.  
  444.     state->base_x = 0;
  445.     state->base_y = 0;
  446.     state->x = 0;
  447.     state->y = 0;
  448.     state->width = 0;
  449.  
  450.     state->line_num = 1;
  451.  
  452.     state->win_left = margin_width;
  453.     state->win_right = margin_width;
  454.  
  455.     state->max_width = state->win_left + state->win_right;
  456.     state->max_height = state->win_top + state->win_bottom;
  457.  
  458.     state->x = state->win_left;
  459.     state->y = state->win_top;
  460.  
  461.     state->left_margin = state->win_left;
  462.     state->right_margin = state->win_width - state->win_right;
  463.     state->left_margin_stack = NULL;
  464.     state->right_margin_stack = NULL;
  465.  
  466.     state->break_holder = state->x;
  467.     state->min_width = 0;
  468.     state->text_divert = P_UNKNOWN;
  469.     state->linefeed_state = 2;
  470.     state->delay_align = FALSE;
  471.     state->breakable = TRUE;
  472.     state->allow_amp_escapes = TRUE;
  473.     state->preformatted = PRE_TEXT_NO;
  474.     state->preformat_cols = 0;
  475.  
  476.     state->in_paragraph = FALSE;
  477.  
  478.     state->display_blocked = FALSE;
  479.     state->display_blocking_element_id = 0;
  480.     state->display_blocking_element_y = 0;
  481.  
  482.     state->line_list = NULL;
  483.     state->end_last_line = NULL;
  484.  
  485. /* XXX - No font information is reset upon entering a layer, nor
  486.        is it restored when the layer ends.  Is this the right thing to do ? */
  487.     if (!state->font_stack) {
  488.         state->base_font_size = DEFAULT_BASE_FONT_SIZE;
  489.         state->font_stack = lo_DefaultFont(state, context);
  490.         if (state->font_stack == NULL)
  491.         {
  492.             /*
  493.             XP_FREE_BLOCK(state->line_array);
  494. #ifdef XP_WIN16
  495.             XP_FREE_BLOCK(state->larray_array);
  496. #endif 
  497.             */
  498.             return(NULL);
  499.         }
  500.         state->font_stack->text_attr->size = state->base_font_size;
  501.  
  502.         state->text_info.max_width = 0;
  503.         state->text_info.ascent = 0;
  504.         state->text_info.descent = 0;
  505.         state->text_info.lbearing = 0;
  506.         state->text_info.rbearing = 0;
  507.     }
  508.  
  509.     /*    XXXX NRA: Possible memory leak here.  What if these guys aren't freed at the end of initial layout? 
  510.      *    Check before assigning to NULL 
  511.      */
  512.     state->align_stack = NULL;
  513.     state->line_height_stack = NULL;
  514.     state->list_stack = lo_DefaultList(state);
  515.     if (state->list_stack == NULL)
  516.     {
  517.         /*
  518.         XP_FREE_BLOCK(state->line_array);
  519. #ifdef XP_WIN16
  520.         XP_FREE_BLOCK(state->larray_array);
  521. #endif  /* XP_WIN16 */
  522.         /*
  523.         XP_DELETE(state->font_stack);
  524.         */
  525.         return(NULL);
  526.     }
  527.  
  528.     state->line_buf_size = 0;
  529.     state->line_buf = PA_ALLOC(LINE_BUF_INC * sizeof(char));
  530.     if (state->line_buf == NULL)
  531.     {    /*
  532.         XP_FREE_BLOCK(state->line_array);
  533. #ifdef XP_WIN16
  534.         XP_FREE_BLOCK(state->larray_array);
  535. #endif /* XP_WIN16 */
  536.         /*
  537.         XP_DELETE(state->font_stack);
  538.         */
  539.         return(NULL);
  540.     }
  541.     state->line_buf_size = LINE_BUF_INC;
  542.     state->line_buf_len = 0;
  543.  
  544.     state->baseline = 0;
  545.     state->line_height = 0;
  546.     state->break_pos = -1;
  547.     state->break_width = 0;
  548.     state->last_char_CR = FALSE;
  549.     state->trailing_space = FALSE;
  550.     state->at_begin_line = TRUE;
  551.     state->hide_content = FALSE;
  552.  
  553.     state->old_break = NULL;
  554.     state->old_break_block = NULL;
  555.     state->old_break_pos = -1;
  556.     state->old_break_width = 0;
  557.  
  558.     state->current_named_anchor = NULL;
  559.     state->current_anchor = NULL;
  560.  
  561.     state->cur_ele_type = LO_NONE;
  562.     state->current_ele = NULL;
  563.     state->current_java = NULL;
  564.  
  565.     state->current_table = NULL;
  566.     state->current_grid = NULL;
  567.     state->current_multicol = NULL;
  568.  
  569.     state->must_relayout_subdoc = FALSE;
  570.     state->allow_percent_width = TRUE;
  571.     state->allow_percent_height = TRUE;
  572.     state->is_a_subdoc = SUBDOC_NOT;
  573.     state->current_subdoc = 0;
  574.     state->sub_documents = NULL;
  575.     state->sub_state = NULL;
  576.  
  577.     state->current_cell = NULL;
  578.  
  579.     state->extending_start = FALSE;
  580.     state->selection_start = NULL;
  581.     state->selection_start_pos = 0;
  582.     state->selection_end = NULL;
  583.     state->selection_end_pos = 0;
  584.     state->selection_new = NULL;
  585.     state->selection_new_pos = 0;
  586.     state->selection_layer = NULL;
  587.  
  588.     state->in_relayout = FALSE;
  589.     state->tab_stop = DEF_TAB_WIDTH;
  590.     state->beginning_tag_count = top_state->tag_count;
  591.     return(state);
  592.  
  593. }
  594.  
  595. lo_RelayoutState * lo_rl_CreateRelayoutState( void )
  596. {
  597.     lo_RelayoutState * relay_state = (lo_RelayoutState *) XP_ALLOC(sizeof(lo_RelayoutState));
  598.     return relay_state;
  599. }
  600.  
  601. void lo_rl_DestroyRelayoutState( lo_RelayoutState *relay_state )
  602. {
  603.     if (relay_state) {
  604.         XP_FREE(relay_state);
  605.     }
  606. }
  607.  
  608. lo_RelayoutState *
  609. lo_rl_InitRelayoutState( MWContext *context, lo_RelayoutState *blank_state, int32 newWidth, int32 newHeight, int32 margin_width, int32 margin_height )
  610. {
  611.     lo_TopState *top_state;
  612.     lo_DocState *state;
  613.  
  614.     if (!context || !blank_state) {
  615.         return NULL;
  616.     }
  617.  
  618.     /* Initialize context */
  619.     blank_state->context = context;
  620.  
  621.     /* Initialize top state */
  622.     top_state = lo_FetchTopState(XP_DOCID(context));
  623.     if (top_state == NULL) {
  624.         return NULL;
  625.     }
  626.     
  627.     top_state->element_id = 0;
  628.  
  629.     blank_state->top_state = top_state;
  630.  
  631.     /* Initialize document state */
  632.     state = top_state->doc_state;
  633.     if (!lo_rl_InitDocState(context, state, newWidth, newHeight, margin_width, margin_height))
  634.     {
  635.         top_state->out_of_memory = TRUE;
  636.         return NULL;
  637.     }
  638.     blank_state->doc_state = state;
  639.  
  640.     return blank_state;
  641. }
  642.  
  643.  
  644. static void lo_rl_PreLayoutElement ( MWContext *context, lo_DocState * state, LO_Element *lo_ele )
  645. {
  646.     /*
  647.      * If we get a non-text tag, and we have some previous text
  648.      * elements we have been merging into state, flush those
  649.      * before processing the new tag.
  650.      */
  651.     if ( lo_ele->type != LO_TEXTBLOCK )
  652.     {
  653.         lo_FlushLineBuffer(context, state);
  654.         if (state->top_state->out_of_memory)
  655.         {
  656.             return;
  657.         }
  658.     }
  659. }
  660.  
  661. static void lo_rl_FitLayoutElements( lo_RelayoutState *relay_state, LO_Element *start_ele )
  662. {
  663.     LO_Element *lo_ele = start_ele;
  664.  
  665.     /* While not end of layout element list */
  666.     while ( lo_ele != NULL) {
  667.         lo_rl_PreLayoutElement ( relay_state->context, relay_state->doc_state, lo_ele );
  668.         if (relay_state->doc_state->top_state->out_of_memory)
  669.         {
  670.             return;
  671.         }
  672.         
  673.         /* Dispatch the layout element to its fitting routine. 
  674.            Fitting routine returns the next layout element to process */
  675.         lo_ele = (*lo_rl_FitFunctionTable[lo_ele->type])(relay_state, lo_ele);
  676.         if (relay_state->doc_state->top_state->out_of_memory)
  677.         {
  678.             return;
  679.         }
  680.  
  681.     } /* End While */
  682. }
  683.  
  684. static LO_Element *
  685. lo_rl_FitIgnore( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  686. {
  687.     XP_TRACE(("lo_rl_FitIgnore called...\n"));
  688.     return lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
  689. }
  690.  
  691. static LO_Element *
  692. lo_rl_FitError( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  693. {
  694.     XP_TRACE(("lo_rl_FitError called...\n"));
  695.     return lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
  696. }
  697.  
  698. static LO_Element *
  699. lo_rl_FitText( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  700. {
  701.     LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
  702.     lo_DocState *state = relay_state->doc_state;
  703.  
  704.     if (lo_ele->lo_text.bullet_type == BULLET_NONE)
  705.       {
  706.         /* move this element to the correct position and add it to the line list */
  707.         lo_ele->lo_any.ele_id = NEXT_ELEMENT;
  708.         lo_ele->lo_any.x = state->x;
  709.         lo_ele->lo_any.y = state->y;
  710.     
  711.         state->x += lo_ele->lo_text.width;
  712.         lo_AppendToLineList(relay_state->context, state, lo_ele, 0);
  713.       }
  714.     else if (lo_ele->lo_text.bullet_type == BULLET_MQUOTE)
  715.       {
  716.         /* Add to recycle list */
  717.         lo_ele->lo_any.prev = NULL;
  718.         lo_ele->lo_any.next = NULL;
  719.         lo_RecycleElements( relay_state->context, relay_state->top_state->doc_state, lo_ele );
  720.       }
  721.     else if (lo_ele->lo_text.bullet_type == WORDBREAK)
  722.     {
  723.         /* Do nothing.  Just return the next layout element */
  724.     }
  725.     else /* it's some other form of bullet, most probably resulting from an ordered list. */
  726.       {
  727.         int32 line_height, baseline;
  728.  
  729.         /* move this element to the correct position and add it to the line list */
  730.         lo_ele->lo_any.ele_id = NEXT_ELEMENT;
  731.  
  732.         lo_FormatBulletStr(relay_state->context, state, (LO_TextStruct*)lo_ele, &line_height, &baseline);
  733.  
  734.         lo_AppendToLineList(relay_state->context, state, lo_ele, 0);
  735.  
  736.         lo_UpdateStateAfterBulletStr(relay_state->context, state,
  737.                      (LO_TextStruct*)lo_ele, line_height, baseline);
  738.       }
  739.  
  740.     return next;
  741. }
  742.  
  743. static LO_Element *
  744. lo_rl_FitLineFeed( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  745. {
  746.     LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
  747.  
  748.     if (lo_ele->lo_linefeed.break_type == LO_LINEFEED_BREAK_SOFT) {        
  749.         /* Add linefeed to recycle list */
  750.         lo_ele->lo_any.prev = NULL;
  751.         lo_ele->lo_any.next = NULL;
  752.         lo_RecycleElements( relay_state->context, relay_state->top_state->doc_state, lo_ele );
  753.     }
  754.     else if (lo_ele->lo_linefeed.break_type == LO_LINEFEED_BREAK_HARD) {
  755.       LO_LinefeedStruct *linefeed = (LO_LinefeedStruct*)lo_ele;
  756.  
  757.       lo_rl_AppendLinefeedAndFlushLine(relay_state->context, relay_state->doc_state,
  758.                        linefeed, linefeed->break_type, linefeed->clear_type, TRUE, FALSE);
  759.  
  760.  
  761.       switch(linefeed->clear_type)
  762.         {
  763.         case LO_CLEAR_TO_LEFT:
  764.           lo_ClearToLeftMargin(relay_state->context, relay_state->doc_state);
  765.           break;
  766.         case LO_CLEAR_TO_RIGHT:
  767.           lo_ClearToRightMargin(relay_state->context, relay_state->doc_state);
  768.           break;
  769.         case LO_CLEAR_TO_ALL:
  770.         case LO_CLEAR_TO_BOTH:
  771.           lo_ClearToBothMargins(relay_state->context, relay_state->doc_state);
  772.           break;
  773.         case LO_CLEAR_NONE:
  774.         default:
  775.           break;
  776.         }
  777.  
  778.       /*
  779.        * Reset the margins properly in case
  780.        * we are inside a list.
  781.        */
  782.       lo_FindLineMargins(relay_state->context, relay_state->doc_state, TRUE);
  783.       relay_state->doc_state->x = relay_state->doc_state->left_margin;
  784.     }
  785.     else if (lo_ele->lo_linefeed.break_type == LO_LINEFEED_BREAK_PARAGRAPH) {
  786.       LO_LinefeedStruct *linefeed = (LO_LinefeedStruct*)lo_ele;
  787.       
  788.       lo_rl_AppendLinefeedAndFlushLine(relay_state->context, relay_state->doc_state,
  789.                        linefeed, linefeed->break_type, linefeed->clear_type, TRUE, FALSE);
  790.     }
  791.  
  792.     return next;
  793. }
  794.  
  795. static LO_Element *
  796. lo_rl_FitHRule( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  797. {
  798.   LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
  799.  
  800.   /* need this or the hrule pops up to the previous line. */
  801.   lo_rl_AddSoftBreakAndFlushLine(relay_state->context, relay_state->doc_state);
  802.   
  803.   lo_StartHorizontalRuleLayout(relay_state->context, relay_state->doc_state, (LO_HorizRuleStruct*)lo_ele);
  804.  
  805.   lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
  806.  
  807.   lo_UpdateStateAfterHorizontalRule(relay_state->doc_state, (LO_HorizRuleStruct*)lo_ele);
  808.  
  809.   lo_rl_AddSoftBreakAndFlushLine(relay_state->context, relay_state->doc_state);
  810.  
  811.   lo_FinishHorizontalRuleLayout(relay_state->context, relay_state->doc_state, (LO_HorizRuleStruct*)lo_ele);
  812.  
  813.   /* lo_DisplayHR(relay_state->context, (LO_HorizRuleStruct*)lo_ele); */
  814.  
  815.   return next;
  816. }
  817.  
  818. static LO_Element *
  819. lo_rl_FitImage( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  820. {
  821.     int32 line_inc, baseline_inc;
  822.     LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
  823.     
  824.     
  825.     lo_FillInImageGeometry( relay_state->doc_state, (LO_ImageStruct *) lo_ele);
  826.     lo_LayoutInflowImage( relay_state->context, relay_state->doc_state, (LO_ImageStruct *) lo_ele, TRUE, &line_inc, &baseline_inc);
  827.     lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, baseline_inc);
  828.     lo_UpdateStateAfterImageLayout( relay_state->doc_state, (LO_ImageStruct *)lo_ele, line_inc, baseline_inc );
  829.  
  830.     return next;
  831. }
  832.  
  833. static LO_Element *
  834. lo_rl_FitBullet( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  835. {
  836.  
  837.   LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
  838.   int32 line_height, baseline;
  839.  
  840.   if (lo_ele->lo_bullet.bullet_type == BULLET_MQUOTE) 
  841.     {
  842.       /* Add bullet to recycle list */
  843.       lo_ele->lo_any.prev = NULL;
  844.       lo_ele->lo_any.next = NULL;
  845.       lo_RecycleElements( relay_state->context, relay_state->top_state->doc_state, lo_ele );
  846.     }
  847.   else
  848.     {
  849.       /*
  850.        * Artificially setting state to 2 here
  851.        * allows us to put headers on list items
  852.        * even if they aren't double spaced.
  853.        */
  854.       relay_state->doc_state->linefeed_state = 2;
  855.       
  856.       lo_FormatBullet(relay_state->context, relay_state->doc_state, (LO_BulletStruct*)lo_ele, &line_height, &baseline);
  857.       
  858.       lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
  859.       
  860.       lo_UpdateStateAfterBullet(relay_state->context, relay_state->doc_state, (LO_BulletStruct*)lo_ele, line_height, baseline);
  861.       
  862.       /* lo_DisplayBullet(relay_state->context, (LO_BulletStruct*)lo_ele); */
  863.       
  864.       /*  XP_ASSERT(0);*/
  865.     }        
  866.   
  867.   return next;
  868. }
  869.  
  870. static LO_Element *
  871. lo_rl_FitList( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  872. {
  873.   LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
  874.   LO_ListStruct *list = (LO_ListStruct*)lo_ele;
  875.   lo_DocState *state = relay_state->doc_state;
  876.   
  877.   list->lo_any.ele_id = NEXT_ELEMENT;
  878.   list->lo_any.x = state->x;
  879.   list->lo_any.y = state->y;
  880.  
  881.   lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
  882.  
  883.   if (list->is_end == FALSE)
  884.     lo_SetupStateForList(relay_state->context, relay_state->doc_state,
  885.                  list, TRUE);
  886.   else
  887.     lo_UpdateStateAfterList(relay_state->context, relay_state->doc_state,
  888.                 list, TRUE);
  889.  
  890.   return next;
  891. }
  892.  
  893. static LO_Element *
  894. lo_rl_FitDescTitle( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  895. {
  896.   LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
  897.   LO_DescTitleStruct *title = (LO_DescTitleStruct*)lo_ele;
  898.   lo_DocState *state = relay_state->doc_state;
  899.   
  900.   title->lo_any.ele_id = NEXT_ELEMENT;
  901.   title->lo_any.x = state->x;
  902.   title->lo_any.y = state->y;
  903.  
  904.   lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
  905.  
  906.   lo_ProcessDescTitleElement(relay_state->context, relay_state->doc_state, title, TRUE);
  907.  
  908.   return next;
  909. }
  910.  
  911. static LO_Element *
  912. lo_rl_FitDescText( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  913. {
  914.   LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
  915.   LO_DescTextStruct *text = (LO_DescTextStruct*)lo_ele;
  916.   lo_DocState *state = relay_state->doc_state;
  917.   
  918.   text->lo_any.ele_id = NEXT_ELEMENT;
  919.   text->lo_any.x = state->x;
  920.   text->lo_any.y = state->y;
  921.  
  922.   lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
  923.  
  924.   lo_ProcessDescTextElement(relay_state->context, relay_state->doc_state, text, TRUE);
  925.  
  926.   return next;
  927. }
  928.  
  929. static LO_Element *
  930. lo_rl_FitBlockQuote( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  931. {
  932.   LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
  933.   lo_DocState *state = relay_state->doc_state;
  934.  
  935.   lo_ele->lo_any.x = state->x;
  936.   lo_ele->lo_any.y = state->y;
  937.   lo_ele->lo_any.ele_id = NEXT_ELEMENT;
  938.  
  939.   lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
  940.   lo_ProcessBlockQuoteElement(relay_state->context,
  941.                   relay_state->doc_state,
  942.                   (LO_BlockQuoteStruct*)lo_ele,
  943.                   TRUE);
  944.  
  945.   return next;
  946. }
  947.  
  948. static LO_Element *
  949. lo_rl_FitFormEle( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  950. {
  951.   LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
  952.   LO_FormElementStruct *form = (LO_FormElementStruct*)lo_ele;
  953.   int32 baseline_inc = 0;
  954.  
  955.   lo_LayoutInflowFormElement(relay_state->context, relay_state->doc_state, form, &baseline_inc, TRUE);
  956.  
  957.   lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, baseline_inc);
  958.  
  959.   lo_UpdateStateAfterFormElement(relay_state->context, relay_state->doc_state, form, baseline_inc);
  960.  
  961.   CL_MoveLayer(form->layer,
  962.                form->x + form->x_offset + form->border_horiz_space,
  963.                form->y + form->y_offset + form->border_vert_space);
  964.  
  965.   return next;
  966. }
  967.  
  968. /* Only called during relayout.  Sets up current height span struct. */
  969. static void lo_UpdateHeightSpanForBeginRow(lo_TableRec *table)
  970. {
  971.     lo_table_span *span_rec;
  972.  
  973.     /* Point to current height span struct. */
  974.     if (table->height_span_ptr == NULL)
  975.     {
  976.         table->height_span_ptr = table->height_spans;
  977.     }
  978.     else
  979.     {
  980.         table->height_span_ptr = table->height_span_ptr->next;
  981.     }
  982.  
  983.     /* Init. current height span struct */
  984.     span_rec = table->height_span_ptr;
  985.     span_rec->dim = 1;
  986.     
  987.     /*
  988.      * Since min_dim on the heights is never used.
  989.      * I am appropriating it to do baseline aligning.  It will
  990.      * start as 0, and eventually be the amount of baseline needed
  991.      * to align all these cells in this row
  992.      * by their baselines.
  993.      */
  994.     span_rec->min_dim = 0;
  995.     span_rec->span = 0;
  996. }
  997.  
  998.  
  999. static LO_Element *
  1000. lo_rl_FitTable( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  1001. {
  1002.     int32 cols, i;
  1003.     lo_TableRec *table = (lo_TableRec *) lo_ele->lo_table.table;
  1004.     MWContext *context = relay_state->context;
  1005.     lo_DocState *state = relay_state->doc_state;
  1006.     LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, TRUE);
  1007.  
  1008.     XP_ASSERT(table != NULL);
  1009.     
  1010.     if (table == NULL)
  1011.         return next;
  1012.  
  1013. #ifndef FAST_TABLES
  1014.     /* Skip over top aligned caption element */
  1015.     if ((table->caption != NULL) &&
  1016.         (table->caption->vert_alignment == LO_ALIGN_TOP))
  1017.     {
  1018.         next = lo_tv_GetNextLayoutElement(state, next, TRUE);
  1019.     }
  1020.  
  1021.     /* Call common functions that set up document state and table state
  1022.        for a new table.  All these functions are called from lo_BeginTableAttributes()
  1023.        also. */
  1024.     lo_rl_BeginTableRelayout(context, state, table );
  1025.  
  1026.     /* Reset row ptr to first row */
  1027.     table->row_ptr = table->row_list;
  1028.  
  1029.     /* Fit each row */
  1030.     do {
  1031.         cols = table->row_ptr->cells_in_row;
  1032.         lo_UpdateTableStateForBeginRow( table, table->row_ptr );
  1033.         lo_UpdateHeightSpanForBeginRow( table );
  1034.         /* Fit each cell in the row */
  1035.         for (i = 0; i < cols; i++)
  1036.         {
  1037.             next = lo_rl_FitCell(relay_state, next);
  1038.         }
  1039.         lo_EndTableRow(context, state, table);
  1040.         table->row_ptr = table->row_ptr->next;
  1041.     } while (table->row_ptr != NULL);
  1042.     
  1043.     /* Skip over bottom aligned caption element */
  1044.     if ((table->caption != NULL) &&
  1045.         (table->caption->vert_alignment != LO_ALIGN_TOP))
  1046.     {
  1047.         next = lo_tv_GetNextLayoutElement(state, next, TRUE);
  1048.     }
  1049.     
  1050.     lo_EndTable(context, state, table, TRUE);
  1051.  
  1052.     
  1053. #else
  1054.     lo_rl_ReHookupCellStructs(table);
  1055.     lo_EndTable(context, state, table, TRUE);
  1056. #endif /* FAST_TABLES */
  1057.     
  1058.     return next;
  1059. }
  1060.  
  1061. static void lo_rl_ReHookupCellStructs(lo_TableRec *table)
  1062. {
  1063.     
  1064. }
  1065.  
  1066. static void lo_rl_BeginTableRelayout( MWContext *context, lo_DocState *state, lo_TableRec *table)
  1067. {
  1068.     lo_PositionTableElement( state, table->table_ele );
  1069.     lo_InitTableRecord( table );
  1070.     lo_SetTableDimensions( state, table, TRUE, TRUE );
  1071.     lo_CalcFixedColWidths( context, state, table );
  1072.     lo_UpdateStateAfterBeginTable( state, table );
  1073. }
  1074.  
  1075. static void lo_rl_CopyCellToState( LO_CellStruct *cell, lo_DocState *state )
  1076. {
  1077.     LO_Element **    line_array;
  1078.     
  1079.     PA_LOCK(line_array, LO_Element **, state->line_array );
  1080.     line_array[0] = cell->cell_list;
  1081.     state->float_list = cell->cell_float_list;
  1082. }
  1083.  
  1084. static void lo_rl_CopyStateToCell( lo_DocState *state, LO_CellStruct *cell)
  1085. {
  1086.     LO_Element **    line_array;
  1087.     
  1088.     PA_LOCK(line_array, LO_Element **, state->line_array );
  1089.  
  1090.     cell->cell_list = (LO_Element *) line_array[0];
  1091.     /* cell->cell_list_end = state->end_last_line; */
  1092.     cell->cell_float_list = state->float_list;
  1093. }
  1094.  
  1095. LO_Element * lo_rl_FitCell( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  1096. {
  1097.     LO_CellStruct *cell = (LO_CellStruct *)lo_ele;
  1098.     lo_TableRec *table = (lo_TableRec *) cell->table;
  1099.     MWContext *context = relay_state->context;
  1100.     lo_DocState *state = relay_state->doc_state;
  1101.     LO_Element *first;
  1102.     LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, TRUE);
  1103.  
  1104.     XP_ASSERT( lo_ele->lo_any.type == LO_CELL );
  1105.     
  1106.     lo_InitForBeginCell((lo_TableRow *)cell->table_row, (lo_TableCell *)cell->table_cell);
  1107.     lo_InitSubDocForBeginCell(context, state, table );
  1108.  
  1109.     /* Copy over line lists, float lists to substate */
  1110.     lo_rl_CopyCellToState( cell, state->sub_state );
  1111.  
  1112.     /* Replace current doc. state with substate */
  1113.     relay_state->doc_state = state->sub_state;
  1114.  
  1115.     /* Fit layout elements on substate */
  1116.     first = lo_tv_GetFirstLayoutElement(relay_state->doc_state);
  1117.     lo_rl_FitLayoutElements(relay_state, first);
  1118.  
  1119.     /* Dummy Floating elements on a new line at the end of a document were not getting put into
  1120.        the line_array.  This code should ensure that anything left on the line_list gets flushed
  1121.        to the line_array. */
  1122.     if (relay_state->doc_state->line_list != NULL)
  1123.         lo_AppendLineListToLineArray( relay_state->context, relay_state->doc_state, NULL);
  1124.  
  1125.     /* Restore relay state to original state */
  1126.     lo_rl_CopyStateToCell( relay_state->doc_state, cell );
  1127.     relay_state->doc_state = state;
  1128.  
  1129.     lo_EndTableCell( context, state->sub_state, TRUE );
  1130.  
  1131.     return next;
  1132. }
  1133.  
  1134. static LO_Element *
  1135. lo_rl_FitEmbed( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  1136. {
  1137.   int32 line_inc, baseline_inc;
  1138.   LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
  1139.   LO_EmbedStruct *embed = (LO_EmbedStruct*)lo_ele;
  1140.  
  1141.   lo_FillInEmbedGeometry(relay_state->doc_state, embed, TRUE);
  1142.   lo_LayoutInflowEmbed(relay_state->context, relay_state->doc_state, embed, TRUE, &line_inc, &baseline_inc);
  1143.   lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, baseline_inc);
  1144.   lo_UpdateStateAfterEmbedLayout(relay_state->doc_state, embed, line_inc, baseline_inc);
  1145.  
  1146.   return next;
  1147. }
  1148.  
  1149. static LO_Element *
  1150. lo_rl_FitJava( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  1151. {
  1152.   LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
  1153. #ifdef JAVA
  1154.   LO_JavaAppStruct *java_app = (LO_JavaAppStruct*)lo_ele;
  1155.  
  1156.   int32 line_inc, baseline_inc;
  1157.  
  1158.   lo_FillInJavaAppGeometry( relay_state->doc_state, java_app, TRUE);
  1159.   lo_LayoutInflowJavaApp( relay_state->context, relay_state->doc_state, java_app, TRUE, &line_inc, &baseline_inc);
  1160.   lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, baseline_inc);
  1161.   lo_UpdateStateAfterJavaAppLayout( relay_state->doc_state, java_app, line_inc, baseline_inc );
  1162.  
  1163.   CL_MoveLayer(java_app->layer,
  1164.                java_app->x + java_app->x_offset + java_app->border_horiz_space,
  1165.                java_app->y + java_app->y_offset + java_app->border_vert_space);
  1166. #endif
  1167.  
  1168.   return next;
  1169. }
  1170.  
  1171. static LO_Element *
  1172. lo_rl_FitObject( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  1173. {
  1174.   XP_ASSERT(0);
  1175.   return lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
  1176. }
  1177.  
  1178. static LO_Element *
  1179. lo_rl_FitParagraph( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  1180. {
  1181.   LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
  1182.   lo_DocState *state = relay_state->doc_state;
  1183.  
  1184.   lo_ele->lo_any.x = state->x;
  1185.   lo_ele->lo_any.y = state->y;
  1186.   lo_ele->lo_any.ele_id = NEXT_ELEMENT;
  1187.  
  1188.   lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
  1189.   lo_ProcessParagraphElement(relay_state->context,
  1190.                  &relay_state->doc_state,
  1191.                  (LO_ParagraphStruct*)lo_ele, TRUE);
  1192.   return next;
  1193. }
  1194.  
  1195. static LO_Element *
  1196. lo_rl_FitCenter( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  1197. {
  1198.   LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
  1199.   lo_DocState *state = relay_state->doc_state;
  1200.  
  1201.   lo_ele->lo_any.x = state->x;
  1202.   lo_ele->lo_any.y = state->y;
  1203.   lo_ele->lo_any.ele_id = NEXT_ELEMENT;
  1204.  
  1205.   lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
  1206.   lo_ProcessCenterElement(relay_state->context,
  1207.               &relay_state->doc_state,
  1208.               (LO_CenterStruct*)lo_ele,
  1209.               TRUE);
  1210.  
  1211.   return next;
  1212. }
  1213.  
  1214. static LO_Element *
  1215. lo_rl_FitMulticolumn( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  1216. {    
  1217.     lo_DocState *state = relay_state->doc_state;
  1218.     MWContext *context = relay_state->context;
  1219.     LO_MulticolumnStruct *multicolElement = (LO_MulticolumnStruct *) lo_ele;
  1220.     LO_Element *next = lo_tv_GetNextLayoutElement(  state, lo_ele, TRUE );
  1221.  
  1222.     if (multicolElement->is_end == FALSE )
  1223.     {
  1224.         int32 doc_width;        
  1225.  
  1226.         lo_AppendMultiColToLineList(context, state, multicolElement);
  1227.  
  1228.         /* if (line will not be flushed by lo_SetSoftLineBreak) and (there exist some elements on the line list) */
  1229.         if (state->linefeed_state >= 2 && state->line_list != NULL)
  1230.         {
  1231.             /* Append zero width and height line feed to the line list and flush the line list into
  1232.                the line array. This forces the layout of elements contained within the MULTICOL tags
  1233.                to start on a blank line_list and hence on a new line.  lo_EndMultiColumn needs this to
  1234.                do its line array hacking properly. */
  1235.             lo_AppendZeroWidthAndHeightLF(context, state);            
  1236.         }
  1237.  
  1238.         lo_SetLineBreakState(context, state, FALSE, LO_LINEFEED_BREAK_SOFT, 2, TRUE);
  1239.         if (multicolElement->multicol != NULL)
  1240.         {
  1241.             LO_LinefeedStruct *linefeedAfterTable = NULL;
  1242.             LO_LinefeedStruct *linefeedBeforeTable = NULL;
  1243.             LO_Element *lastElementInLastCell;
  1244.             LO_CellStruct *lastCellElement;
  1245.  
  1246.             /*    Call functions to set up doc state and the multicol structure state that
  1247.                 get called during initial layout also. */
  1248.             lo_StartMultiColInit( state, multicolElement->multicol ) ;
  1249.             doc_width = state->right_margin - state->left_margin;
  1250.             lo_SetupStateForBeginMulticol( state, multicolElement->multicol, doc_width );
  1251.  
  1252.             /*    Traverse all cells in the line list and concatenate their line lists and
  1253.                 float lists.  Return the first element of the first cell's line list to be
  1254.                 fitted by the lo_rl_FitLayoutElements() loop */
  1255.             XP_ASSERT(next->lo_any.type == LO_LINEFEED);
  1256.             linefeedBeforeTable = (LO_LinefeedStruct *) next;
  1257.             next = next->lo_any.next;
  1258.             
  1259.             XP_ASSERT(next->lo_any.type == LO_TABLE);
  1260.             if (next->lo_any.type == LO_TABLE)
  1261.                 linefeedAfterTable = (LO_LinefeedStruct *) lo_rl_RecreateElementListsFromCells(state, (LO_TableStruct *) next,
  1262.                     &lastElementInLastCell);
  1263.  
  1264.             /* Trash all the LO_TABLE and LO_CELL elements that were created to hold MULTICOL contents
  1265.                for the earlier window size. */
  1266.             lastCellElement = (struct LO_CellStruct_struct*) linefeedAfterTable->prev;
  1267.             lastCellElement->next = NULL;
  1268.             next->lo_any.prev = NULL;
  1269.             lo_RecycleElements( context, state, next );
  1270.  
  1271.             
  1272.             /* Insert the state->linelist constructed above in between the linefeeds before and after
  1273.                the table. */
  1274.             linefeedBeforeTable->next = state->line_list;
  1275.             state->line_list->lo_any.prev = (LO_Element *) linefeedBeforeTable;
  1276.             lastElementInLastCell->lo_any.next = (LO_Element *) linefeedAfterTable;
  1277.             linefeedAfterTable->prev = lastElementInLastCell;
  1278.  
  1279.             /* Set the next layout element to be fitted to the linefeed before the table.  This
  1280.                will fit all the elements that were on the cells of the table */
  1281.             next = (LO_Element *) linefeedBeforeTable;
  1282.  
  1283.             /* The linelist should be NULL because we the LO_Elements
  1284.                within the multicol tag get laid out on a new line in the line_array */
  1285.             state->line_list = NULL;
  1286.         }
  1287.     }
  1288.     else if ( multicolElement->is_end == TRUE )
  1289.     {
  1290.         if (state->current_multicol != NULL)
  1291.         {
  1292.             lo_EndMulticolumn(context, state, multicolElement->tag,
  1293.                 state->current_multicol, TRUE);
  1294.             
  1295.         }
  1296.         lo_AppendMultiColToLineList(context, state, multicolElement);
  1297.     }
  1298.  
  1299.     return next;
  1300. }
  1301.  
  1302. static LO_LinefeedStruct * lo_rl_RecreateElementListsFromCells( lo_DocState *state, LO_TableStruct *table, 
  1303.                                                                LO_Element **lastElementInLastCell)
  1304. {    
  1305.     LO_Element *lineList = state->line_list;
  1306.     LO_Element *floatList = state->float_list;
  1307.     LO_Element *ele;
  1308.         
  1309.     /* Point to the first cell element */
  1310.     ele = table->next;
  1311.  
  1312.     /* Go to last element on line list and float list */
  1313.     lineList = lo_GetLastElementInList(lineList);
  1314.     floatList = lo_GetLastElementInList(floatList);
  1315.  
  1316.     /*    For all cell elements, keep appending the cell line lists and float lists to the doc state's
  1317.         line lists and float lists.  Keeps resetting each LO_CELL's line list and float list 
  1318.         pointers to NULL. */
  1319.     for (  ; ele->lo_any.type == LO_CELL; ele = ele->lo_any.next )
  1320.     {
  1321.         /* Preconditions: 1) lineList points to the element to which the cell list has to be appended,
  1322.                           2) floatList points to the element to which the cell float list has to be appended */
  1323.         if (lineList == NULL)
  1324.         {
  1325.             lineList = ele->lo_cell.cell_list;            
  1326.             state->line_list = lineList;
  1327.         }
  1328.         else
  1329.             lineList->lo_any.next = ele->lo_cell.cell_list;
  1330.  
  1331.         ele->lo_cell.cell_list = NULL;
  1332.         
  1333.         if (floatList == NULL)
  1334.         {
  1335.             floatList = ele->lo_cell.cell_float_list;
  1336.             state->float_list = floatList;
  1337.         }
  1338.         else
  1339.             floatList->lo_any.next = ele->lo_cell.cell_float_list;
  1340.  
  1341.         ele->lo_cell.cell_float_list = NULL;
  1342.  
  1343.         /* Go to last element on line list and float list */
  1344.         lineList = lo_GetLastElementInList(lineList);
  1345.         floatList = lo_GetLastElementInList(floatList);
  1346.     }
  1347.  
  1348.     *lastElementInLastCell = lineList;
  1349.  
  1350.     /* ele is the first element after the last cell in the table and should be a linefeed*/
  1351.     XP_ASSERT(ele->lo_any.type == LO_LINEFEED);
  1352.     return (LO_LinefeedStruct *) ele;
  1353. }
  1354.  
  1355.  
  1356. static LO_Element *
  1357. lo_rl_FitFloat( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  1358. {
  1359.     LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
  1360.     int32 x, y;
  1361.     CL_Layer *layer = NULL;
  1362.  
  1363.     if (lo_ele->lo_float.float_ele->lo_any.type == LO_IMAGE) {
  1364.         LO_ImageStruct *image = (LO_ImageStruct *)lo_ele->lo_float.float_ele;
  1365.  
  1366.         lo_LayoutFloatImage( relay_state->context, relay_state->doc_state, image, FALSE );
  1367.  
  1368.         /* Determine the new position of the layer. */
  1369.         x = image->x + image->x_offset + image->border_width;
  1370.         y = image->y + image->y_offset + image->border_width;
  1371.  
  1372.         layer = image->layer;
  1373.     }
  1374. #ifdef JAVA
  1375.     else if (lo_ele->lo_float.float_ele->lo_any.type == LO_JAVA) {
  1376.         LO_JavaAppStruct *java_app = (LO_JavaAppStruct *)lo_ele->lo_float.float_ele;
  1377.  
  1378.         lo_LayoutFloatJavaApp( relay_state->context, relay_state->doc_state, java_app, FALSE );
  1379.  
  1380.         /* Determine the new position of the layer. */
  1381.         x = java_app->x + java_app->x_offset + java_app->border_width;
  1382.         y = java_app->y + java_app->y_offset + java_app->border_width;
  1383.  
  1384.         layer = java_app->layer;
  1385.     }
  1386. #endif
  1387.     else if (lo_ele->lo_float.float_ele->lo_any.type == LO_EMBED) {
  1388.         LO_EmbedStruct *embed = (LO_EmbedStruct *)lo_ele->lo_float.float_ele;
  1389.         
  1390.         lo_LayoutFloatEmbed( relay_state->context, relay_state->doc_state, embed, FALSE );
  1391.  
  1392.         /* Determine the new position of the layer. */
  1393.         x = embed->x + embed->x_offset + embed->border_width;
  1394.         y = embed->y + embed->y_offset + embed->border_width;
  1395.  
  1396.         layer = embed->layer;
  1397.     }
  1398.     else if (lo_ele->lo_float.float_ele->lo_any.type == LO_TABLE) {
  1399.         LO_TableStruct *table_ele = (LO_TableStruct *)lo_ele->lo_float.float_ele;
  1400.         lo_DocState *state = relay_state->doc_state;
  1401.         LO_Element *save_float_list = state->float_list;
  1402.         LO_Element *save_line_list = state->line_list;
  1403.         LO_Element *save_elements_after_table = NULL;
  1404.         LO_Element *ele = NULL;
  1405.  
  1406.         /* We want to layout the table that is in the float list on the doc state in
  1407.            relay_state.  So we need to save the float list and non-TABLE and non-CELL
  1408.            layout elements on the float list.  Then we layout the floating table on
  1409.            the doc state.  Then we restore the float list. */
  1410.  
  1411.         /* Table elements are followed by CELL elements.  The end of the table occurs
  1412.            at the first element that is not a CELL.  So step through the element list until 
  1413.            the first non-CELL is encountered */
  1414.         LO_Element *prev_ele = (LO_Element *) table_ele;
  1415.         for ( ele = table_ele->next; ele->lo_any.type == LO_CELL; ele = ele->lo_any.next )
  1416.         {
  1417.             prev_ele = ele;
  1418.             if (ele->lo_any.next == NULL)
  1419.             {
  1420.                 ele = NULL;
  1421.                 break;
  1422.             }
  1423.         }
  1424.         
  1425.         if (ele != NULL)
  1426.         {
  1427.             /* Temporarily NULL out the last CELL's next pointer. */
  1428.             save_elements_after_table = ele;
  1429.             prev_ele->lo_any.next = NULL;
  1430.         }
  1431.         state->float_list = NULL;
  1432.         state->line_list = NULL;
  1433.         
  1434.         /* Layout the table onto relay_state->doc_state */
  1435.         lo_rl_FitTable( relay_state, (LO_Element *)table_ele );
  1436.  
  1437.         /* Restore line list, float list */
  1438.         state->line_list = save_line_list;
  1439.         state->float_list = save_float_list;
  1440.         if (save_elements_after_table != NULL)
  1441.         {
  1442.             prev_ele->lo_any.next = save_elements_after_table;
  1443.         }
  1444.     }
  1445.  
  1446.     /* Reset dummy float element's position and element id before inserting back into the line list */
  1447.     lo_ele->lo_any.x = relay_state->doc_state->x;
  1448.     lo_ele->lo_any.y = relay_state->doc_state->y;
  1449.     lo_ele->lo_any.ele_id = relay_state->top_state->element_id++;
  1450.  
  1451.     lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
  1452.  
  1453.     /* Move layer to new position */
  1454.     if (layer != NULL)
  1455.     {
  1456.         CL_MoveLayer(layer, x, y);
  1457.     }
  1458.  
  1459.     return next;
  1460. }
  1461.  
  1462. static LO_Element *
  1463. lo_rl_FitTextBlock( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  1464. {
  1465.     LO_Element *    next;
  1466.     
  1467.     next = lo_RelayoutTextBlock ( relay_state->context, relay_state->doc_state, &lo_ele->lo_textBlock, NULL );
  1468.     return next;
  1469. }
  1470.  
  1471. static LO_Element *
  1472. lo_rl_FitLayer( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  1473. {
  1474.     LO_Element *next;
  1475.     
  1476.     XP_ASSERT(lo_ele->lo_layer.is_end == FALSE);
  1477.  
  1478.     /* Skip all elements between the start and end LO_LAYER elements */
  1479.     next = lo_ele;
  1480.     do 
  1481.     {
  1482.         next = lo_tv_GetNextLayoutElement( relay_state->doc_state, next, TRUE);
  1483.     } while (next != NULL && next->lo_any.type != LO_LAYER);
  1484.  
  1485.     if (next->lo_any.type == LO_LAYER) {
  1486.         XP_ASSERT(next->lo_layer.is_end == TRUE);
  1487.         next = lo_tv_GetNextLayoutElement( relay_state->doc_state, next, TRUE);
  1488.     }
  1489.  
  1490.     return next;
  1491. }
  1492.  
  1493.  
  1494. static LO_Element *
  1495. lo_rl_FitHeading( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  1496. {
  1497.     XP_ASSERT(0);
  1498.     return lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
  1499. }
  1500.  
  1501. static LO_Element * 
  1502. lo_rl_FitSpacer( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  1503. {
  1504.     LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
  1505.     LO_SpacerStruct *spacer = (LO_SpacerStruct *) lo_ele;
  1506.     lo_DocState *state = relay_state->doc_state;
  1507.     MWContext *context = relay_state->context;
  1508.  
  1509.     /* Put the LO_SPACER element back on the line list */
  1510.     spacer->lo_any.x = state->x;
  1511.     spacer->lo_any.y = state->y;
  1512.     spacer->lo_any.ele_id = state->top_state->element_id++;
  1513.     lo_AppendToLineList(context, state, lo_ele, 0);
  1514.  
  1515.     /* Relayout the SPACER element */
  1516.     lo_LayoutSpacerElement(context, state, spacer, TRUE);
  1517.  
  1518.     return next;
  1519. }
  1520.  
  1521. static LO_Element * lo_rl_FitSpan( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  1522. {
  1523.     XP_ASSERT(0);
  1524.     return lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
  1525. }
  1526.  
  1527. static LO_Element * lo_rl_FitDiv( lo_RelayoutState *relay_state, LO_Element *lo_ele )
  1528. {
  1529.     XP_ASSERT(0);
  1530.     return lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
  1531. }
  1532.  
  1533. /* 
  1534.  * Adds a soft line break to the end of the line list and adds the line list to the line array.  Resets line list to NULL. 
  1535.  * Should be used during relayout only.  It is the relayout version of lo_SetSoftLineBreak().
  1536.  */
  1537. void lo_rl_AddSoftBreakAndFlushLine( MWContext *context, lo_DocState *state )
  1538. {
  1539.     lo_rl_AddBreakAndFlushLine( context, state, LO_LINEFEED_BREAK_SOFT, LO_CLEAR_NONE, TRUE);
  1540. }
  1541.  
  1542.  
  1543. void lo_rl_AddBreakAndFlushLine( MWContext *context, lo_DocState *state, int32 break_type, uint32 clear_type, Bool breaking)
  1544. {
  1545.     LO_LinefeedStruct *linefeed;
  1546.     
  1547.     linefeed = NULL;
  1548.     
  1549.     lo_rl_AppendLinefeedAndFlushLine(context, state, linefeed, break_type, clear_type, breaking, TRUE);
  1550. }
  1551.  
  1552. void lo_rl_AppendLinefeedAndFlushLine( MWContext *context, lo_DocState *state, LO_LinefeedStruct *linefeed, int32 break_type, uint32 clear_type,
  1553.                                       Bool breaking, Bool createNewLF)
  1554. {
  1555.     /* flush any text */
  1556.     lo_FlushLineBuffer(context, state);
  1557.  
  1558.     lo_UpdateStateWhileFlushingLine( context, state );
  1559.     
  1560.     if (createNewLF)
  1561.         linefeed = lo_NewLinefeed(state, context, break_type, clear_type);
  1562.     else
  1563.         lo_FillInLineFeed( context, state, break_type, clear_type, linefeed );
  1564.  
  1565.     if (linefeed != NULL)
  1566.     {
  1567.         lo_AppendLineFeed( context, state, linefeed, breaking, FALSE );
  1568.     }
  1569.  
  1570.     lo_UpdateStateAfterFlushingLine( context, state, linefeed, TRUE );
  1571.     lo_UpdateStateAfterLineBreak( context, state, FALSE );
  1572.     lo_UpdateFEProgressBar(context, state);
  1573. }
  1574.  
  1575. /* 
  1576.  * Append a dummy layout element in the line list.  When the relayout engine
  1577.  * will see this dummy element, it will call lo_LayoutFloat{Image,JavaApp,Embed}()
  1578.  */
  1579. void lo_AppendFloatInLineList( lo_DocState *state, LO_Element *ele, LO_Element *restOfLine)
  1580. {
  1581.     LO_Element *eptr;
  1582.     LO_FloatStruct *float_dummy = XP_NEW_ZAP(LO_FloatStruct);
  1583.     float_dummy->float_ele = ele;
  1584.     float_dummy->lo_any.type = LO_FLOAT;
  1585.     float_dummy->lo_any.ele_id = NEXT_ELEMENT;
  1586.     float_dummy->lo_any.x = state->x;
  1587.     float_dummy->lo_any.y = state->y;
  1588.     float_dummy->lo_any.next = restOfLine;
  1589.     float_dummy->lo_any.prev = NULL;
  1590.  
  1591.     if (state->line_list == NULL ) {
  1592.         state->line_list = (LO_Element *) float_dummy;
  1593.     }
  1594.     else {
  1595.         for (eptr = state->line_list; eptr->lo_any.next != NULL; eptr = eptr->lo_any.next)
  1596.             ;
  1597.         /* eptr now points to the last element in state->line_list */
  1598.         eptr->lo_any.next = (LO_Element *) float_dummy;
  1599.         float_dummy->lo_any.prev = eptr;
  1600.     }
  1601. }
  1602.  
  1603. void lo_rl_ReflowCell( MWContext *context, lo_DocState *state, LO_CellStruct *cell )
  1604. {
  1605.     lo_RelayoutState *relay_state;
  1606.     LO_Element *first;
  1607.  
  1608.     LO_LockLayout();
  1609.  
  1610.     /* Copy over cell line lists, float lists to state */
  1611.     lo_rl_CopyCellToState( cell, state );
  1612.  
  1613.     /* Create relayout state */
  1614.     relay_state = lo_rl_CreateRelayoutState();
  1615.     relay_state->doc_state = state;
  1616.     relay_state->context = context;
  1617.     relay_state->top_state = state->top_state;
  1618.  
  1619.     /* Fit cell's layout elements */
  1620.     first = lo_tv_GetFirstLayoutElement(relay_state->doc_state);
  1621.     lo_rl_FitLayoutElements(relay_state, first);
  1622.  
  1623.     /* Dummy Floating elements on a new line at the end of a document were not getting put into
  1624.        the line_array.  This code should ensure that anything left on the line_list gets flushed
  1625.        to the line_array. */
  1626.     if (state->line_list != NULL)
  1627.         lo_AppendLineListToLineArray( context, state, NULL);
  1628.  
  1629.     /* Restore cell line list and float list */
  1630.     lo_rl_CopyStateToCell( relay_state->doc_state, cell );
  1631.     
  1632.     /* Done with relayout.  Destroy relayout state. */
  1633.     lo_rl_DestroyRelayoutState( relay_state );
  1634.  
  1635.     LO_UnlockLayout();
  1636.  
  1637. }
  1638.  
  1639. void lo_rl_ReflowDocState( MWContext *context, lo_DocState *state )
  1640. {
  1641.     lo_RelayoutState *relay_state;
  1642.     LO_Element *first;
  1643.  
  1644.     LO_LockLayout();
  1645.  
  1646.     /* Create relayout state */
  1647.     relay_state = lo_rl_CreateRelayoutState();
  1648.     relay_state->doc_state = state;
  1649.     relay_state->context = context;
  1650.     relay_state->top_state = state->top_state;
  1651.  
  1652.     /* Fit cell's layout elements */
  1653.     first = lo_tv_GetFirstLayoutElement(relay_state->doc_state);
  1654.     
  1655.     lo_rl_FitLayoutElements(relay_state, first);
  1656.  
  1657.     /* Dummy Floating elements on a new line at the end of a document were not getting put into
  1658.        the line_array.  This code should ensure that anything left on the line_list gets flushed
  1659.        to the line_array. */
  1660.     if (state->line_list != NULL)
  1661.         lo_AppendLineListToLineArray( context, state, NULL);
  1662.  
  1663.     /* Done with relayout.  Destroy relayout state. */
  1664.     lo_rl_DestroyRelayoutState( relay_state );
  1665.  
  1666.     LO_UnlockLayout();
  1667. }
  1668.  
  1669. void lo_PrepareElementForReuse( MWContext *context, lo_DocState *state, LO_Element * eptr,
  1670.         ED_Element *edit_element, intn edit_offset)
  1671. {
  1672. #ifdef EDITOR
  1673.     eptr->lo_any.edit_element = NULL;
  1674.     eptr->lo_any.edit_offset = 0;
  1675.  
  1676.     if( EDT_IS_EDITOR(context) )
  1677.     {
  1678.         if( lo_EditableElement( eptr->type ) )
  1679.         {
  1680.             if( edit_element == 0 ){
  1681.                 edit_element = state->edit_current_element;
  1682.                 edit_offset = state->edit_current_offset;
  1683.             }
  1684.             EDT_SetLayoutElement( edit_element, 
  1685.                                     edit_offset,
  1686.                                     eptr->type,
  1687.                                     eptr );
  1688.         } else if( edit_element && (eptr->type == LO_TABLE || eptr->type == LO_CELL) )
  1689.         {
  1690.             /* _TABLE_EXPERIMENT_  SAVE POINTER TO EDIT ELEMENT IN LO STRUCT */
  1691.             eptr->lo_any.edit_element = edit_element;
  1692.  
  1693.         }
  1694.     }
  1695.     state->edit_force_offset = FALSE;
  1696. #endif
  1697. }
  1698.  
  1699.