home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
-
- /*
- layrelay.c --- reflow of layout elements.
- Created: Nisheeth Ranjan <nisheeth@netscape.com>, 7-Nov-1997.
- */
- #include "xp.h"
- #include "net.h"
- #include "pa_parse.h"
- #include "layout.h"
- #include "laylayer.h"
- #include "layers.h"
- #include "layrelay.h"
- #include "laytrav.h"
- #ifdef EDITOR
- #include "edt.h"
- #endif
-
- #include "libmocha.h"
- #include "libevent.h"
-
- extern int MK_OUT_OF_MEMORY;
-
- #ifdef PROFILE
- #pragma profile on
- #endif
-
- #ifdef TEST_16BIT
- #define XP_WIN16
- #endif /* TEST_16BIT */
-
- #ifdef XP_WIN16
- #define SIZE_LIMIT 32000
- #endif /* XP_WIN16 */
-
- static lo_DocState *lo_rl_InitDocState( MWContext *context, lo_DocState *state,
- int32 width, int32 height,
- int32 margin_width, int32 margin_height);
- static void lo_rl_PreLayoutElement ( MWContext *context, lo_DocState * state,
- LO_Element *lo_ele );
- static void lo_rl_CopyCellToState( LO_CellStruct *cell, lo_DocState *state );
- static void lo_rl_CopyStateToCell( lo_DocState *state, LO_CellStruct *cell);
-
- /* Loops through layout elements and calls their fitting functions */
- static void lo_rl_FitLayoutElements( lo_RelayoutState *relay_state, LO_Element *start_ele );
-
-
- static lo_DocState *
- lo_rl_InitDocState( MWContext *context, lo_DocState *state, int32 width, int32 height, int32 margin_width, int32 margin_height );
- static void lo_UpdateHeightSpanForBeginRow(lo_TableRec *table);
- static void lo_rl_BeginTableRelayout( MWContext *context, lo_DocState *state, lo_TableRec *table);
- static LO_LinefeedStruct * lo_rl_RecreateElementListsFromCells( lo_DocState *state, LO_TableStruct *table,
- LO_Element **lastElementInLastCell);
-
- typedef LO_Element * (*lo_FitFunction)( lo_RelayoutState *relay_state, LO_Element *lo_ele );
-
- static LO_Element * lo_rl_FitIgnore( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitError( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitText( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitLineFeed( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitHRule( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitImage( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitBullet( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitFormEle( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitTable( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitCell( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitEmbed( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitJava( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitObject( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitParagraph( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitCenter( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitMulticolumn( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitFloat( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitTextBlock( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitList( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitDescTitle( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitDescText( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitBlockQuote( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitLayer( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitHeading( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitSpan( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitDiv( lo_RelayoutState *relay_state, LO_Element *lo_ele );
- static LO_Element * lo_rl_FitSpacer( lo_RelayoutState *relay_state, LO_Element *lo_ele );
-
- /* The table of fitting functions for each layout element type... */
- static lo_FitFunction lo_rl_FitFunctionTable[] = {
- lo_rl_FitIgnore, /* LO_NONE */
- lo_rl_FitText, /* LO_TEXT */
- lo_rl_FitLineFeed, /* LO_LINEFEED */
- lo_rl_FitHRule, /* LO_HRULE */
- lo_rl_FitImage, /* LO_IMAGE */
- lo_rl_FitBullet, /* LO_BULLET */
- lo_rl_FitFormEle, /* LO_FORM_ELE */
- lo_rl_FitError, /* LO_SUBDOC elements should not occur in line list */
- lo_rl_FitTable, /* LO_TABLE */
- lo_rl_FitCell, /* LO_CELL */
- lo_rl_FitEmbed, /* LO_EMBED */
- lo_rl_FitError, /* LO_EDGE element: Either an error or we should ignore. ??? */
- lo_rl_FitJava, /* LO_JAVA */
- lo_rl_FitError, /* LO_SCRIPT elements should not occur in list of layout elements */
- lo_rl_FitObject, /* LO_OBJECT */
- lo_rl_FitParagraph, /* LO_PARAGRAPH */
- lo_rl_FitCenter, /* LO_CENTER */
- lo_rl_FitMulticolumn, /* LO_MULTICOLUMN */
- lo_rl_FitFloat, /* LO_FLOAT */
- lo_rl_FitTextBlock, /* LO_TEXTBLOCK */
- lo_rl_FitList, /* LO_LIST */
- lo_rl_FitDescTitle, /* LO_DESCTITLE */
- lo_rl_FitDescText, /* LO_DESCTEXT */
- lo_rl_FitBlockQuote, /* LO_BLOCKQUOTE */
- lo_rl_FitLayer, /* LO_LAYER */
- lo_rl_FitHeading, /* LO_HEADING */
- lo_rl_FitSpan, /* LO_SPAN */
- lo_rl_FitDiv, /* LO_DIV */
- lo_rl_FitSpacer /* LO_SPACER */
- };
-
-
- /* NRA - 10/3/97: Main Relayout Entry Point
- * This function walks through the layout element list and re-lays out
- * the elements to fit into a window of the specified width and height.
- *
- * It needs to be called on each resize of the window.
- *
- * Issues to be careful about: 1) Synchronization with Javascript that is running concurrently while this
- * re-layout is going on.
- *
- * 2) Keep a copy of elements that change. Will come in handy later to figure out the redraw rectangle.
- * For now, we dirty the entire document
- *
- * 3) FE needs to tell us the position in the current document. We will need to determine the element id
- * at that position and call FE_SetDocPosition to set the document to the saved position after relayout
- */
- void LO_RelayoutOnResize(MWContext *context, int32 width, int32 height, int32 leftMargin, int32 topMargin)
- {
- lo_RelayoutState *relay_state;
- lo_DocState *state;
- LO_Element *lo_ele;
- int32 docX, docY;
- lo_TopState *top_state;
-
- /* check to see if the context we've been passed is a grid context. If so, branch to the grid
- specific resize routine, which will call this one again on its grid cells. */
- top_state = lo_FetchTopState(XP_DOCID(context));
- if (top_state == NULL) {
- return;
- }
-
- LO_LockLayout();
-
- if (top_state->the_grid) {
- /* the document doesn't have any elements. It's a grid document */
- lo_RelayoutGridDocumentOnResize(context, top_state, width, height);
- LO_UnlockLayout();
- return;
- }
-
- relay_state = lo_rl_CreateRelayoutState();
- if (relay_state == NULL) {
- LO_UnlockLayout();
- return; /* Better error handling later */
- }
-
- /* Reset the scoping for any JavaScript to be the top-level layer. */
- /* ET_SetActiveLayer(context, LO_DOCUMENT_LAYER_ID); */
-
- /* remember where we are in the document */
- FE_GetDocPosition ( context, FE_VIEW, &docX, &docY );
-
- /* shrink the layout document in case we get smaller */
- LO_SetDocumentDimensions(context, 0, 0);
-
- if (lo_rl_InitRelayoutState(context, relay_state, width, height, leftMargin, topMargin) != NULL)
- {
- lo_ele = lo_tv_GetFirstLayoutElement(relay_state->doc_state);
- lo_rl_FitLayoutElements(relay_state, lo_ele);
-
- /* Flush out any remaining elements on the line list into the line array. */
- lo_rl_AddSoftBreakAndFlushLine(relay_state->context, relay_state->doc_state);
- lo_EndLayoutDuringReflow( relay_state->context, relay_state->doc_state );
- }
- else
- {
- lo_rl_DestroyRelayoutState(relay_state);
- LO_UnlockLayout();
- return;
- }
-
- state = relay_state->doc_state;
-
- /* Send JS load event. JS will treat it as a resize by looking at the resize_reload param */
- ET_SendLoadEvent(context, EVENT_LOAD, NULL, NULL,
- LO_DOCUMENT_LAYER_ID,
- state->top_state->resize_reload);
-
- /* Reset state for force loading images. */
- LO_SetForceLoadImage(NULL, FALSE);
-
- /* position the document */
- FE_SetDocPosition ( context, FE_VIEW, 0, docY );
-
- /* update the final document dimensions */
- state->y += state->win_bottom;
- LO_SetDocumentDimensions(context, state->max_width, state->y);
-
- if(!state->top_state->is_binary)
- FE_SetProgressBarPercent(context, 100);
-
- FE_FinishedLayout(context);
-
- /* Tell FE to redraw window */
- if (context->compositor)
- {
- CL_Compositor *compositor = context->compositor;
- XP_Rect rect;
- CL_OffscreenMode save_offscreen_mode;
-
- rect.left = rect.top = 0;
- rect.right = state->win_width;
- rect.bottom = state->y;
-
- CL_UpdateDocumentRect(compositor,
- &rect, (PRBool)FALSE);
-
- /* Temporarily force drawing to use the offscreen buffering area to reduce
- flicker when resizing. (If no offscreen store is allocated, this code will
- have no effect, but it will do no harm.) */
- save_offscreen_mode = CL_GetCompositorOffscreenDrawing(compositor);
- CL_SetCompositorOffscreenDrawing(compositor, CL_OFFSCREEN_ENABLED);
- CL_CompositeNow(compositor);
- CL_SetCompositorOffscreenDrawing(compositor, save_offscreen_mode);
- }
-
- lo_rl_DestroyRelayoutState(relay_state);
-
- LO_UnlockLayout();
- /* Postion is hard-coded to top of document for now.*/
- /* FE_SetDocPosition(context, 0, 0, 0); */
- /* 2nd parameter for FE_ClearView is iView which is ignored. */
- /* FE_ClearView(context, 0); */
-
- }
-
- /*
- ** Relayout a document given a change in one LO_Element*. This is of
- ** primary use for plugins (since there is now an API to change the
- ** size of a plugin), but could also be used once the LO_Elements are
- ** reflected in a DOM and style information affecting the element's
- ** size is changed.
- */
- void
- LO_RelayoutFromElement(MWContext *context, LO_Element *element)
- {
- /* toshok - we don't have all the plumbing in place yet to handle
- something like this, so we punt and make it a wrapper for
- LO_RelayoutOnResize. Given that all drawing is done through a
- compositor, the user shouldn't be aware of everything being
- relayed out anyway. */
- int32 leftMargin, topMargin;
- int32 width, height;
- lo_TopState *top_state = lo_FetchTopState(XP_DOCID(context));
-
- if (!top_state)
- return;
-
- width = LO_GetLayerScrollWidth(top_state->body_layer);
- height = LO_GetLayerScrollHeight(top_state->body_layer);
-
- LO_GetDocumentMargins(context, &leftMargin, &topMargin);
-
- LO_RelayoutOnResize(context, width, height, leftMargin, topMargin);
- }
-
- /*
- * This function reflows a document from a given element. It's primary function is for the editor.
- * The caller must provide a state record which is correctly initialized to the position the reflow
- * will start.
- *
- * It currently only works for text elements.
- */
- void LO_Reflow(MWContext *context, lo_DocState * state, LO_Element *startElement, LO_Element *endElement)
- {
- LO_Element *lo_ele;
- lo_TopState *top_state;
- lo_RelayoutState relay_state;
- lo_DocState * save_state;
- LO_TextBlock * block;
- Bool firstElement;
-
- #if defined( DEBUG_nisheeth ) || defined( DEBUG_toshok ) || defined( DEBUG_shannon )
- if (context) {
- lo_PrintLayout(context);
- }
- #endif
-
- /* check to see if the context we've been passed is a grid context. If so, branch to the grid
- specific resize routine, which will call this one again on its grid cells. */
- top_state = lo_FetchTopState(XP_DOCID(context));
- if (top_state == NULL) {
- return;
- }
-
- LO_LockLayout();
-
- /* init this by hand as we don't want to create a new state */
- relay_state.context = context;
- relay_state.top_state = lo_FetchTopState(XP_DOCID(context));
- relay_state.doc_state = state;
-
- firstElement = TRUE;
- lo_ele = startElement;
-
- while ( lo_ele != endElement ) {
- lo_rl_PreLayoutElement ( context, state, lo_ele );
- if (state->top_state->out_of_memory)
- {
- LO_UnlockLayout();
- return;
- }
-
- state->edit_force_offset = TRUE;
-
- save_state = top_state->doc_state;
- top_state->doc_state = state;
-
- block = NULL;
-
- /*
- * If we get a text element, we also need to retrieve the text block
- */
- if ( lo_ele->type == LO_TEXT )
- {
- /* I'm pretty sure this ifdef is ok since EDT_GetTextBlock should always return NULL
- if we're not in an editor context. hardts */
- #ifdef EDITOR
- block = EDT_GetTextBlock ( context, lo_ele );
- #endif /* EDITOR */
- }
-
- /*
- * if we found a text block, then call the reflow routine with this element, otherwise
- * use the default reflow code. Remember sometimes we get text elements without a text block
- * (such as list elements)
- */
- if ( block != NULL ) {
- lo_ele = lo_RelayoutTextBlock ( context, state, block, &lo_ele->lo_text );
- }
- else {
- /*
- * HACK: Until I find a better way to deal with this.
- *
- * The above lo_LayoutTag loop will handle setup for things like lists. This is fine
- * when we're inside a list (ie past element 1) as the first thing the reflow will
- * process is the bullet. However, (for a reason I don't entirely understand yet), if
- * we're on the first line of the document and the list is the first element, startElement
- * will point at the LO_LIST element. This means that reflow will reexecute the start list
- * and we'll do the wrong thing.
- *
- * So, for now only, if the first element is a LO_LIST element, then skip it!
- */
- if ( firstElement && ( lo_ele->type == LO_LIST ) )
- {
- LO_Element * next;
-
- next = lo_tv_GetNextLayoutElement ( state, lo_ele, FALSE );
-
- lo_ele->lo_any.ele_id = NEXT_ELEMENT;
- lo_ele->lo_any.x = state->x;
- lo_ele->lo_any.y = state->y;
-
- state->x += lo_ele->lo_text.width;
- lo_AppendToLineList( context, state, lo_ele, 0);
-
- lo_ele = next;
- }
- else
- {
- /* Dispatch the layout element to its fitting routine.
- Fitting routine returns the next layout element to process */
- lo_ele = (*lo_rl_FitFunctionTable[lo_ele->type])( &relay_state, lo_ele);
- }
- }
-
- firstElement = FALSE;
-
- top_state->doc_state = save_state;
-
- if (state->top_state->out_of_memory)
- {
- LO_UnlockLayout();
- return;
- }
-
- if ( lo_ele == NULL )
- {
- LO_UnlockLayout();
- break;
- }
-
- state->edit_force_offset = FALSE;
- }
-
- #if defined( DEBUG_nisheeth ) || defined( DEBUG_toshok ) || defined( DEBUG_shannon )
- if (context) {
- lo_PrintLayout(context);
- }
- #endif
-
- LO_UnlockLayout();
- }
-
- /* Selectively cut and pasted from lo_InitDocState(). Should we separate this stuff
- out into a common function rather than duplicating code? */
- static lo_DocState *
- lo_rl_InitDocState( MWContext *context, lo_DocState *state, int32 width, int32 height, int32 margin_width, int32 margin_height )
- {
- lo_TopState *top_state = state->top_state;
-
- state->subdoc_tags = NULL;
- state->subdoc_tags_end = NULL;
-
- state->win_top = margin_height;
- state->win_bottom = margin_height;
- state->win_width = width;
- state->win_height = height;
-
- state->base_x = 0;
- state->base_y = 0;
- state->x = 0;
- state->y = 0;
- state->width = 0;
-
- state->line_num = 1;
-
- state->win_left = margin_width;
- state->win_right = margin_width;
-
- state->max_width = state->win_left + state->win_right;
- state->max_height = state->win_top + state->win_bottom;
-
- state->x = state->win_left;
- state->y = state->win_top;
-
- state->left_margin = state->win_left;
- state->right_margin = state->win_width - state->win_right;
- state->left_margin_stack = NULL;
- state->right_margin_stack = NULL;
-
- state->break_holder = state->x;
- state->min_width = 0;
- state->text_divert = P_UNKNOWN;
- state->linefeed_state = 2;
- state->delay_align = FALSE;
- state->breakable = TRUE;
- state->allow_amp_escapes = TRUE;
- state->preformatted = PRE_TEXT_NO;
- state->preformat_cols = 0;
-
- state->in_paragraph = FALSE;
-
- state->display_blocked = FALSE;
- state->display_blocking_element_id = 0;
- state->display_blocking_element_y = 0;
-
- state->line_list = NULL;
- state->end_last_line = NULL;
-
- /* XXX - No font information is reset upon entering a layer, nor
- is it restored when the layer ends. Is this the right thing to do ? */
- if (!state->font_stack) {
- state->base_font_size = DEFAULT_BASE_FONT_SIZE;
- state->font_stack = lo_DefaultFont(state, context);
- if (state->font_stack == NULL)
- {
- /*
- XP_FREE_BLOCK(state->line_array);
- #ifdef XP_WIN16
- XP_FREE_BLOCK(state->larray_array);
- #endif
- */
- return(NULL);
- }
- state->font_stack->text_attr->size = state->base_font_size;
-
- state->text_info.max_width = 0;
- state->text_info.ascent = 0;
- state->text_info.descent = 0;
- state->text_info.lbearing = 0;
- state->text_info.rbearing = 0;
- }
-
- /* XXXX NRA: Possible memory leak here. What if these guys aren't freed at the end of initial layout?
- * Check before assigning to NULL
- */
- state->align_stack = NULL;
- state->line_height_stack = NULL;
- state->list_stack = lo_DefaultList(state);
- if (state->list_stack == NULL)
- {
- /*
- XP_FREE_BLOCK(state->line_array);
- #ifdef XP_WIN16
- XP_FREE_BLOCK(state->larray_array);
- #endif /* XP_WIN16 */
- /*
- XP_DELETE(state->font_stack);
- */
- return(NULL);
- }
-
- state->line_buf_size = 0;
- state->line_buf = PA_ALLOC(LINE_BUF_INC * sizeof(char));
- if (state->line_buf == NULL)
- { /*
- XP_FREE_BLOCK(state->line_array);
- #ifdef XP_WIN16
- XP_FREE_BLOCK(state->larray_array);
- #endif /* XP_WIN16 */
- /*
- XP_DELETE(state->font_stack);
- */
- return(NULL);
- }
- state->line_buf_size = LINE_BUF_INC;
- state->line_buf_len = 0;
-
- state->baseline = 0;
- state->line_height = 0;
- state->break_pos = -1;
- state->break_width = 0;
- state->last_char_CR = FALSE;
- state->trailing_space = FALSE;
- state->at_begin_line = TRUE;
- state->hide_content = FALSE;
-
- state->old_break = NULL;
- state->old_break_block = NULL;
- state->old_break_pos = -1;
- state->old_break_width = 0;
-
- state->current_named_anchor = NULL;
- state->current_anchor = NULL;
-
- state->cur_ele_type = LO_NONE;
- state->current_ele = NULL;
- state->current_java = NULL;
-
- state->current_table = NULL;
- state->current_grid = NULL;
- state->current_multicol = NULL;
-
- state->must_relayout_subdoc = FALSE;
- state->allow_percent_width = TRUE;
- state->allow_percent_height = TRUE;
- state->is_a_subdoc = SUBDOC_NOT;
- state->current_subdoc = 0;
- state->sub_documents = NULL;
- state->sub_state = NULL;
-
- state->current_cell = NULL;
-
- state->extending_start = FALSE;
- state->selection_start = NULL;
- state->selection_start_pos = 0;
- state->selection_end = NULL;
- state->selection_end_pos = 0;
- state->selection_new = NULL;
- state->selection_new_pos = 0;
- state->selection_layer = NULL;
-
- state->in_relayout = FALSE;
- state->tab_stop = DEF_TAB_WIDTH;
- state->beginning_tag_count = top_state->tag_count;
- return(state);
-
- }
-
- lo_RelayoutState * lo_rl_CreateRelayoutState( void )
- {
- lo_RelayoutState * relay_state = (lo_RelayoutState *) XP_ALLOC(sizeof(lo_RelayoutState));
- return relay_state;
- }
-
- void lo_rl_DestroyRelayoutState( lo_RelayoutState *relay_state )
- {
- if (relay_state) {
- XP_FREE(relay_state);
- }
- }
-
- lo_RelayoutState *
- lo_rl_InitRelayoutState( MWContext *context, lo_RelayoutState *blank_state, int32 newWidth, int32 newHeight, int32 margin_width, int32 margin_height )
- {
- lo_TopState *top_state;
- lo_DocState *state;
-
- if (!context || !blank_state) {
- return NULL;
- }
-
- /* Initialize context */
- blank_state->context = context;
-
- /* Initialize top state */
- top_state = lo_FetchTopState(XP_DOCID(context));
- if (top_state == NULL) {
- return NULL;
- }
-
- top_state->element_id = 0;
-
- blank_state->top_state = top_state;
-
- /* Initialize document state */
- state = top_state->doc_state;
- if (!lo_rl_InitDocState(context, state, newWidth, newHeight, margin_width, margin_height))
- {
- top_state->out_of_memory = TRUE;
- return NULL;
- }
- blank_state->doc_state = state;
-
- return blank_state;
- }
-
-
- static void lo_rl_PreLayoutElement ( MWContext *context, lo_DocState * state, LO_Element *lo_ele )
- {
- /*
- * If we get a non-text tag, and we have some previous text
- * elements we have been merging into state, flush those
- * before processing the new tag.
- */
- if ( lo_ele->type != LO_TEXTBLOCK )
- {
- lo_FlushLineBuffer(context, state);
- if (state->top_state->out_of_memory)
- {
- return;
- }
- }
- }
-
- static void lo_rl_FitLayoutElements( lo_RelayoutState *relay_state, LO_Element *start_ele )
- {
- LO_Element *lo_ele = start_ele;
-
- /* While not end of layout element list */
- while ( lo_ele != NULL) {
- lo_rl_PreLayoutElement ( relay_state->context, relay_state->doc_state, lo_ele );
- if (relay_state->doc_state->top_state->out_of_memory)
- {
- return;
- }
-
- /* Dispatch the layout element to its fitting routine.
- Fitting routine returns the next layout element to process */
- lo_ele = (*lo_rl_FitFunctionTable[lo_ele->type])(relay_state, lo_ele);
- if (relay_state->doc_state->top_state->out_of_memory)
- {
- return;
- }
-
- } /* End While */
- }
-
- static LO_Element *
- lo_rl_FitIgnore( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- XP_TRACE(("lo_rl_FitIgnore called...\n"));
- return lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
- }
-
- static LO_Element *
- lo_rl_FitError( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- XP_TRACE(("lo_rl_FitError called...\n"));
- return lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
- }
-
- static LO_Element *
- lo_rl_FitText( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
- lo_DocState *state = relay_state->doc_state;
-
- if (lo_ele->lo_text.bullet_type == BULLET_NONE)
- {
- /* move this element to the correct position and add it to the line list */
- lo_ele->lo_any.ele_id = NEXT_ELEMENT;
- lo_ele->lo_any.x = state->x;
- lo_ele->lo_any.y = state->y;
-
- state->x += lo_ele->lo_text.width;
- lo_AppendToLineList(relay_state->context, state, lo_ele, 0);
- }
- else if (lo_ele->lo_text.bullet_type == BULLET_MQUOTE)
- {
- /* Add to recycle list */
- lo_ele->lo_any.prev = NULL;
- lo_ele->lo_any.next = NULL;
- lo_RecycleElements( relay_state->context, relay_state->top_state->doc_state, lo_ele );
- }
- else if (lo_ele->lo_text.bullet_type == WORDBREAK)
- {
- /* Do nothing. Just return the next layout element */
- }
- else /* it's some other form of bullet, most probably resulting from an ordered list. */
- {
- int32 line_height, baseline;
-
- /* move this element to the correct position and add it to the line list */
- lo_ele->lo_any.ele_id = NEXT_ELEMENT;
-
- lo_FormatBulletStr(relay_state->context, state, (LO_TextStruct*)lo_ele, &line_height, &baseline);
-
- lo_AppendToLineList(relay_state->context, state, lo_ele, 0);
-
- lo_UpdateStateAfterBulletStr(relay_state->context, state,
- (LO_TextStruct*)lo_ele, line_height, baseline);
- }
-
- return next;
- }
-
- static LO_Element *
- lo_rl_FitLineFeed( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
-
- if (lo_ele->lo_linefeed.break_type == LO_LINEFEED_BREAK_SOFT) {
- /* Add linefeed to recycle list */
- lo_ele->lo_any.prev = NULL;
- lo_ele->lo_any.next = NULL;
- lo_RecycleElements( relay_state->context, relay_state->top_state->doc_state, lo_ele );
- }
- else if (lo_ele->lo_linefeed.break_type == LO_LINEFEED_BREAK_HARD) {
- LO_LinefeedStruct *linefeed = (LO_LinefeedStruct*)lo_ele;
-
- lo_rl_AppendLinefeedAndFlushLine(relay_state->context, relay_state->doc_state,
- linefeed, linefeed->break_type, linefeed->clear_type, TRUE, FALSE);
-
-
- switch(linefeed->clear_type)
- {
- case LO_CLEAR_TO_LEFT:
- lo_ClearToLeftMargin(relay_state->context, relay_state->doc_state);
- break;
- case LO_CLEAR_TO_RIGHT:
- lo_ClearToRightMargin(relay_state->context, relay_state->doc_state);
- break;
- case LO_CLEAR_TO_ALL:
- case LO_CLEAR_TO_BOTH:
- lo_ClearToBothMargins(relay_state->context, relay_state->doc_state);
- break;
- case LO_CLEAR_NONE:
- default:
- break;
- }
-
- /*
- * Reset the margins properly in case
- * we are inside a list.
- */
- lo_FindLineMargins(relay_state->context, relay_state->doc_state, TRUE);
- relay_state->doc_state->x = relay_state->doc_state->left_margin;
- }
- else if (lo_ele->lo_linefeed.break_type == LO_LINEFEED_BREAK_PARAGRAPH) {
- LO_LinefeedStruct *linefeed = (LO_LinefeedStruct*)lo_ele;
-
- lo_rl_AppendLinefeedAndFlushLine(relay_state->context, relay_state->doc_state,
- linefeed, linefeed->break_type, linefeed->clear_type, TRUE, FALSE);
- }
-
- return next;
- }
-
- static LO_Element *
- lo_rl_FitHRule( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
-
- /* need this or the hrule pops up to the previous line. */
- lo_rl_AddSoftBreakAndFlushLine(relay_state->context, relay_state->doc_state);
-
- lo_StartHorizontalRuleLayout(relay_state->context, relay_state->doc_state, (LO_HorizRuleStruct*)lo_ele);
-
- lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
-
- lo_UpdateStateAfterHorizontalRule(relay_state->doc_state, (LO_HorizRuleStruct*)lo_ele);
-
- lo_rl_AddSoftBreakAndFlushLine(relay_state->context, relay_state->doc_state);
-
- lo_FinishHorizontalRuleLayout(relay_state->context, relay_state->doc_state, (LO_HorizRuleStruct*)lo_ele);
-
- /* lo_DisplayHR(relay_state->context, (LO_HorizRuleStruct*)lo_ele); */
-
- return next;
- }
-
- static LO_Element *
- lo_rl_FitImage( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- int32 line_inc, baseline_inc;
- LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
-
-
- lo_FillInImageGeometry( relay_state->doc_state, (LO_ImageStruct *) lo_ele);
- lo_LayoutInflowImage( relay_state->context, relay_state->doc_state, (LO_ImageStruct *) lo_ele, TRUE, &line_inc, &baseline_inc);
- lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, baseline_inc);
- lo_UpdateStateAfterImageLayout( relay_state->doc_state, (LO_ImageStruct *)lo_ele, line_inc, baseline_inc );
-
- return next;
- }
-
- static LO_Element *
- lo_rl_FitBullet( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
-
- LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
- int32 line_height, baseline;
-
- if (lo_ele->lo_bullet.bullet_type == BULLET_MQUOTE)
- {
- /* Add bullet to recycle list */
- lo_ele->lo_any.prev = NULL;
- lo_ele->lo_any.next = NULL;
- lo_RecycleElements( relay_state->context, relay_state->top_state->doc_state, lo_ele );
- }
- else
- {
- /*
- * Artificially setting state to 2 here
- * allows us to put headers on list items
- * even if they aren't double spaced.
- */
- relay_state->doc_state->linefeed_state = 2;
-
- lo_FormatBullet(relay_state->context, relay_state->doc_state, (LO_BulletStruct*)lo_ele, &line_height, &baseline);
-
- lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
-
- lo_UpdateStateAfterBullet(relay_state->context, relay_state->doc_state, (LO_BulletStruct*)lo_ele, line_height, baseline);
-
- /* lo_DisplayBullet(relay_state->context, (LO_BulletStruct*)lo_ele); */
-
- /* XP_ASSERT(0);*/
- }
-
- return next;
- }
-
- static LO_Element *
- lo_rl_FitList( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
- LO_ListStruct *list = (LO_ListStruct*)lo_ele;
- lo_DocState *state = relay_state->doc_state;
-
- list->lo_any.ele_id = NEXT_ELEMENT;
- list->lo_any.x = state->x;
- list->lo_any.y = state->y;
-
- lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
-
- if (list->is_end == FALSE)
- lo_SetupStateForList(relay_state->context, relay_state->doc_state,
- list, TRUE);
- else
- lo_UpdateStateAfterList(relay_state->context, relay_state->doc_state,
- list, TRUE);
-
- return next;
- }
-
- static LO_Element *
- lo_rl_FitDescTitle( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
- LO_DescTitleStruct *title = (LO_DescTitleStruct*)lo_ele;
- lo_DocState *state = relay_state->doc_state;
-
- title->lo_any.ele_id = NEXT_ELEMENT;
- title->lo_any.x = state->x;
- title->lo_any.y = state->y;
-
- lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
-
- lo_ProcessDescTitleElement(relay_state->context, relay_state->doc_state, title, TRUE);
-
- return next;
- }
-
- static LO_Element *
- lo_rl_FitDescText( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
- LO_DescTextStruct *text = (LO_DescTextStruct*)lo_ele;
- lo_DocState *state = relay_state->doc_state;
-
- text->lo_any.ele_id = NEXT_ELEMENT;
- text->lo_any.x = state->x;
- text->lo_any.y = state->y;
-
- lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
-
- lo_ProcessDescTextElement(relay_state->context, relay_state->doc_state, text, TRUE);
-
- return next;
- }
-
- static LO_Element *
- lo_rl_FitBlockQuote( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
- lo_DocState *state = relay_state->doc_state;
-
- lo_ele->lo_any.x = state->x;
- lo_ele->lo_any.y = state->y;
- lo_ele->lo_any.ele_id = NEXT_ELEMENT;
-
- lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
- lo_ProcessBlockQuoteElement(relay_state->context,
- relay_state->doc_state,
- (LO_BlockQuoteStruct*)lo_ele,
- TRUE);
-
- return next;
- }
-
- static LO_Element *
- lo_rl_FitFormEle( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
- LO_FormElementStruct *form = (LO_FormElementStruct*)lo_ele;
- int32 baseline_inc = 0;
-
- lo_LayoutInflowFormElement(relay_state->context, relay_state->doc_state, form, &baseline_inc, TRUE);
-
- lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, baseline_inc);
-
- lo_UpdateStateAfterFormElement(relay_state->context, relay_state->doc_state, form, baseline_inc);
-
- CL_MoveLayer(form->layer,
- form->x + form->x_offset + form->border_horiz_space,
- form->y + form->y_offset + form->border_vert_space);
-
- return next;
- }
-
- /* Only called during relayout. Sets up current height span struct. */
- static void lo_UpdateHeightSpanForBeginRow(lo_TableRec *table)
- {
- lo_table_span *span_rec;
-
- /* Point to current height span struct. */
- if (table->height_span_ptr == NULL)
- {
- table->height_span_ptr = table->height_spans;
- }
- else
- {
- table->height_span_ptr = table->height_span_ptr->next;
- }
-
- /* Init. current height span struct */
- span_rec = table->height_span_ptr;
- span_rec->dim = 1;
-
- /*
- * Since min_dim on the heights is never used.
- * I am appropriating it to do baseline aligning. It will
- * start as 0, and eventually be the amount of baseline needed
- * to align all these cells in this row
- * by their baselines.
- */
- span_rec->min_dim = 0;
- span_rec->span = 0;
- }
-
-
- static LO_Element *
- lo_rl_FitTable( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- int32 cols, i;
- lo_TableRec *table = (lo_TableRec *) lo_ele->lo_table.table;
- MWContext *context = relay_state->context;
- lo_DocState *state = relay_state->doc_state;
- LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, TRUE);
-
- XP_ASSERT(table != NULL);
-
- if (table == NULL)
- return next;
-
- #ifndef FAST_TABLES
- /* Skip over top aligned caption element */
- if ((table->caption != NULL) &&
- (table->caption->vert_alignment == LO_ALIGN_TOP))
- {
- next = lo_tv_GetNextLayoutElement(state, next, TRUE);
- }
-
- /* Call common functions that set up document state and table state
- for a new table. All these functions are called from lo_BeginTableAttributes()
- also. */
- lo_rl_BeginTableRelayout(context, state, table );
-
- /* Reset row ptr to first row */
- table->row_ptr = table->row_list;
-
- /* Fit each row */
- do {
- cols = table->row_ptr->cells_in_row;
- lo_UpdateTableStateForBeginRow( table, table->row_ptr );
- lo_UpdateHeightSpanForBeginRow( table );
- /* Fit each cell in the row */
- for (i = 0; i < cols; i++)
- {
- next = lo_rl_FitCell(relay_state, next);
- }
- lo_EndTableRow(context, state, table);
- table->row_ptr = table->row_ptr->next;
- } while (table->row_ptr != NULL);
-
- /* Skip over bottom aligned caption element */
- if ((table->caption != NULL) &&
- (table->caption->vert_alignment != LO_ALIGN_TOP))
- {
- next = lo_tv_GetNextLayoutElement(state, next, TRUE);
- }
-
- lo_EndTable(context, state, table, TRUE);
-
-
- #else
- lo_rl_ReHookupCellStructs(table);
- lo_EndTable(context, state, table, TRUE);
- #endif /* FAST_TABLES */
-
- return next;
- }
-
- static void lo_rl_ReHookupCellStructs(lo_TableRec *table)
- {
-
- }
-
- static void lo_rl_BeginTableRelayout( MWContext *context, lo_DocState *state, lo_TableRec *table)
- {
- lo_PositionTableElement( state, table->table_ele );
- lo_InitTableRecord( table );
- lo_SetTableDimensions( state, table, TRUE, TRUE );
- lo_CalcFixedColWidths( context, state, table );
- lo_UpdateStateAfterBeginTable( state, table );
- }
-
- static void lo_rl_CopyCellToState( LO_CellStruct *cell, lo_DocState *state )
- {
- LO_Element ** line_array;
-
- PA_LOCK(line_array, LO_Element **, state->line_array );
- line_array[0] = cell->cell_list;
- state->float_list = cell->cell_float_list;
- }
-
- static void lo_rl_CopyStateToCell( lo_DocState *state, LO_CellStruct *cell)
- {
- LO_Element ** line_array;
-
- PA_LOCK(line_array, LO_Element **, state->line_array );
-
- cell->cell_list = (LO_Element *) line_array[0];
- /* cell->cell_list_end = state->end_last_line; */
- cell->cell_float_list = state->float_list;
- }
-
- LO_Element * lo_rl_FitCell( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- LO_CellStruct *cell = (LO_CellStruct *)lo_ele;
- lo_TableRec *table = (lo_TableRec *) cell->table;
- MWContext *context = relay_state->context;
- lo_DocState *state = relay_state->doc_state;
- LO_Element *first;
- LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, TRUE);
-
- XP_ASSERT( lo_ele->lo_any.type == LO_CELL );
-
- lo_InitForBeginCell((lo_TableRow *)cell->table_row, (lo_TableCell *)cell->table_cell);
- lo_InitSubDocForBeginCell(context, state, table );
-
- /* Copy over line lists, float lists to substate */
- lo_rl_CopyCellToState( cell, state->sub_state );
-
- /* Replace current doc. state with substate */
- relay_state->doc_state = state->sub_state;
-
- /* Fit layout elements on substate */
- first = lo_tv_GetFirstLayoutElement(relay_state->doc_state);
- lo_rl_FitLayoutElements(relay_state, first);
-
- /* Dummy Floating elements on a new line at the end of a document were not getting put into
- the line_array. This code should ensure that anything left on the line_list gets flushed
- to the line_array. */
- if (relay_state->doc_state->line_list != NULL)
- lo_AppendLineListToLineArray( relay_state->context, relay_state->doc_state, NULL);
-
- /* Restore relay state to original state */
- lo_rl_CopyStateToCell( relay_state->doc_state, cell );
- relay_state->doc_state = state;
-
- lo_EndTableCell( context, state->sub_state, TRUE );
-
- return next;
- }
-
- static LO_Element *
- lo_rl_FitEmbed( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- int32 line_inc, baseline_inc;
- LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
- LO_EmbedStruct *embed = (LO_EmbedStruct*)lo_ele;
-
- lo_FillInEmbedGeometry(relay_state->doc_state, embed, TRUE);
- lo_LayoutInflowEmbed(relay_state->context, relay_state->doc_state, embed, TRUE, &line_inc, &baseline_inc);
- lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, baseline_inc);
- lo_UpdateStateAfterEmbedLayout(relay_state->doc_state, embed, line_inc, baseline_inc);
-
- return next;
- }
-
- static LO_Element *
- lo_rl_FitJava( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- LO_Element *next = lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
- #ifdef JAVA
- LO_JavaAppStruct *java_app = (LO_JavaAppStruct*)lo_ele;
-
- int32 line_inc, baseline_inc;
-
- lo_FillInJavaAppGeometry( relay_state->doc_state, java_app, TRUE);
- lo_LayoutInflowJavaApp( relay_state->context, relay_state->doc_state, java_app, TRUE, &line_inc, &baseline_inc);
- lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, baseline_inc);
- lo_UpdateStateAfterJavaAppLayout( relay_state->doc_state, java_app, line_inc, baseline_inc );
-
- CL_MoveLayer(java_app->layer,
- java_app->x + java_app->x_offset + java_app->border_horiz_space,
- java_app->y + java_app->y_offset + java_app->border_vert_space);
- #endif
-
- return next;
- }
-
- static LO_Element *
- lo_rl_FitObject( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- XP_ASSERT(0);
- return lo_tv_GetNextLayoutElement(relay_state->doc_state, lo_ele, FALSE);
- }
-
- static LO_Element *
- lo_rl_FitParagraph( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
- lo_DocState *state = relay_state->doc_state;
-
- lo_ele->lo_any.x = state->x;
- lo_ele->lo_any.y = state->y;
- lo_ele->lo_any.ele_id = NEXT_ELEMENT;
-
- lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
- lo_ProcessParagraphElement(relay_state->context,
- &relay_state->doc_state,
- (LO_ParagraphStruct*)lo_ele, TRUE);
- return next;
- }
-
- static LO_Element *
- lo_rl_FitCenter( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
- lo_DocState *state = relay_state->doc_state;
-
- lo_ele->lo_any.x = state->x;
- lo_ele->lo_any.y = state->y;
- lo_ele->lo_any.ele_id = NEXT_ELEMENT;
-
- lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
- lo_ProcessCenterElement(relay_state->context,
- &relay_state->doc_state,
- (LO_CenterStruct*)lo_ele,
- TRUE);
-
- return next;
- }
-
- static LO_Element *
- lo_rl_FitMulticolumn( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- lo_DocState *state = relay_state->doc_state;
- MWContext *context = relay_state->context;
- LO_MulticolumnStruct *multicolElement = (LO_MulticolumnStruct *) lo_ele;
- LO_Element *next = lo_tv_GetNextLayoutElement( state, lo_ele, TRUE );
-
- if (multicolElement->is_end == FALSE )
- {
- int32 doc_width;
-
- lo_AppendMultiColToLineList(context, state, multicolElement);
-
- /* if (line will not be flushed by lo_SetSoftLineBreak) and (there exist some elements on the line list) */
- if (state->linefeed_state >= 2 && state->line_list != NULL)
- {
- /* Append zero width and height line feed to the line list and flush the line list into
- the line array. This forces the layout of elements contained within the MULTICOL tags
- to start on a blank line_list and hence on a new line. lo_EndMultiColumn needs this to
- do its line array hacking properly. */
- lo_AppendZeroWidthAndHeightLF(context, state);
- }
-
- lo_SetLineBreakState(context, state, FALSE, LO_LINEFEED_BREAK_SOFT, 2, TRUE);
- if (multicolElement->multicol != NULL)
- {
- LO_LinefeedStruct *linefeedAfterTable = NULL;
- LO_LinefeedStruct *linefeedBeforeTable = NULL;
- LO_Element *lastElementInLastCell;
- LO_CellStruct *lastCellElement;
-
- /* Call functions to set up doc state and the multicol structure state that
- get called during initial layout also. */
- lo_StartMultiColInit( state, multicolElement->multicol ) ;
- doc_width = state->right_margin - state->left_margin;
- lo_SetupStateForBeginMulticol( state, multicolElement->multicol, doc_width );
-
- /* Traverse all cells in the line list and concatenate their line lists and
- float lists. Return the first element of the first cell's line list to be
- fitted by the lo_rl_FitLayoutElements() loop */
- XP_ASSERT(next->lo_any.type == LO_LINEFEED);
- linefeedBeforeTable = (LO_LinefeedStruct *) next;
- next = next->lo_any.next;
-
- XP_ASSERT(next->lo_any.type == LO_TABLE);
- if (next->lo_any.type == LO_TABLE)
- linefeedAfterTable = (LO_LinefeedStruct *) lo_rl_RecreateElementListsFromCells(state, (LO_TableStruct *) next,
- &lastElementInLastCell);
-
- /* Trash all the LO_TABLE and LO_CELL elements that were created to hold MULTICOL contents
- for the earlier window size. */
- lastCellElement = (struct LO_CellStruct_struct*) linefeedAfterTable->prev;
- lastCellElement->next = NULL;
- next->lo_any.prev = NULL;
- lo_RecycleElements( context, state, next );
-
-
- /* Insert the state->linelist constructed above in between the linefeeds before and after
- the table. */
- linefeedBeforeTable->next = state->line_list;
- state->line_list->lo_any.prev = (LO_Element *) linefeedBeforeTable;
- lastElementInLastCell->lo_any.next = (LO_Element *) linefeedAfterTable;
- linefeedAfterTable->prev = lastElementInLastCell;
-
- /* Set the next layout element to be fitted to the linefeed before the table. This
- will fit all the elements that were on the cells of the table */
- next = (LO_Element *) linefeedBeforeTable;
-
- /* The linelist should be NULL because we the LO_Elements
- within the multicol tag get laid out on a new line in the line_array */
- state->line_list = NULL;
- }
- }
- else if ( multicolElement->is_end == TRUE )
- {
- if (state->current_multicol != NULL)
- {
- lo_EndMulticolumn(context, state, multicolElement->tag,
- state->current_multicol, TRUE);
-
- }
- lo_AppendMultiColToLineList(context, state, multicolElement);
- }
-
- return next;
- }
-
- static LO_LinefeedStruct * lo_rl_RecreateElementListsFromCells( lo_DocState *state, LO_TableStruct *table,
- LO_Element **lastElementInLastCell)
- {
- LO_Element *lineList = state->line_list;
- LO_Element *floatList = state->float_list;
- LO_Element *ele;
-
- /* Point to the first cell element */
- ele = table->next;
-
- /* Go to last element on line list and float list */
- lineList = lo_GetLastElementInList(lineList);
- floatList = lo_GetLastElementInList(floatList);
-
- /* For all cell elements, keep appending the cell line lists and float lists to the doc state's
- line lists and float lists. Keeps resetting each LO_CELL's line list and float list
- pointers to NULL. */
- for ( ; ele->lo_any.type == LO_CELL; ele = ele->lo_any.next )
- {
- /* Preconditions: 1) lineList points to the element to which the cell list has to be appended,
- 2) floatList points to the element to which the cell float list has to be appended */
- if (lineList == NULL)
- {
- lineList = ele->lo_cell.cell_list;
- state->line_list = lineList;
- }
- else
- lineList->lo_any.next = ele->lo_cell.cell_list;
-
- ele->lo_cell.cell_list = NULL;
-
- if (floatList == NULL)
- {
- floatList = ele->lo_cell.cell_float_list;
- state->float_list = floatList;
- }
- else
- floatList->lo_any.next = ele->lo_cell.cell_float_list;
-
- ele->lo_cell.cell_float_list = NULL;
-
- /* Go to last element on line list and float list */
- lineList = lo_GetLastElementInList(lineList);
- floatList = lo_GetLastElementInList(floatList);
- }
-
- *lastElementInLastCell = lineList;
-
- /* ele is the first element after the last cell in the table and should be a linefeed*/
- XP_ASSERT(ele->lo_any.type == LO_LINEFEED);
- return (LO_LinefeedStruct *) ele;
- }
-
-
- static LO_Element *
- lo_rl_FitFloat( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
- int32 x, y;
- CL_Layer *layer = NULL;
-
- if (lo_ele->lo_float.float_ele->lo_any.type == LO_IMAGE) {
- LO_ImageStruct *image = (LO_ImageStruct *)lo_ele->lo_float.float_ele;
-
- lo_LayoutFloatImage( relay_state->context, relay_state->doc_state, image, FALSE );
-
- /* Determine the new position of the layer. */
- x = image->x + image->x_offset + image->border_width;
- y = image->y + image->y_offset + image->border_width;
-
- layer = image->layer;
- }
- #ifdef JAVA
- else if (lo_ele->lo_float.float_ele->lo_any.type == LO_JAVA) {
- LO_JavaAppStruct *java_app = (LO_JavaAppStruct *)lo_ele->lo_float.float_ele;
-
- lo_LayoutFloatJavaApp( relay_state->context, relay_state->doc_state, java_app, FALSE );
-
- /* Determine the new position of the layer. */
- x = java_app->x + java_app->x_offset + java_app->border_width;
- y = java_app->y + java_app->y_offset + java_app->border_width;
-
- layer = java_app->layer;
- }
- #endif
- else if (lo_ele->lo_float.float_ele->lo_any.type == LO_EMBED) {
- LO_EmbedStruct *embed = (LO_EmbedStruct *)lo_ele->lo_float.float_ele;
-
- lo_LayoutFloatEmbed( relay_state->context, relay_state->doc_state, embed, FALSE );
-
- /* Determine the new position of the layer. */
- x = embed->x + embed->x_offset + embed->border_width;
- y = embed->y + embed->y_offset + embed->border_width;
-
- layer = embed->layer;
- }
- else if (lo_ele->lo_float.float_ele->lo_any.type == LO_TABLE) {
- LO_TableStruct *table_ele = (LO_TableStruct *)lo_ele->lo_float.float_ele;
- lo_DocState *state = relay_state->doc_state;
- LO_Element *save_float_list = state->float_list;
- LO_Element *save_line_list = state->line_list;
- LO_Element *save_elements_after_table = NULL;
- LO_Element *ele = NULL;
-
- /* We want to layout the table that is in the float list on the doc state in
- relay_state. So we need to save the float list and non-TABLE and non-CELL
- layout elements on the float list. Then we layout the floating table on
- the doc state. Then we restore the float list. */
-
- /* Table elements are followed by CELL elements. The end of the table occurs
- at the first element that is not a CELL. So step through the element list until
- the first non-CELL is encountered */
- LO_Element *prev_ele = (LO_Element *) table_ele;
- for ( ele = table_ele->next; ele->lo_any.type == LO_CELL; ele = ele->lo_any.next )
- {
- prev_ele = ele;
- if (ele->lo_any.next == NULL)
- {
- ele = NULL;
- break;
- }
- }
-
- if (ele != NULL)
- {
- /* Temporarily NULL out the last CELL's next pointer. */
- save_elements_after_table = ele;
- prev_ele->lo_any.next = NULL;
- }
- state->float_list = NULL;
- state->line_list = NULL;
-
- /* Layout the table onto relay_state->doc_state */
- lo_rl_FitTable( relay_state, (LO_Element *)table_ele );
-
- /* Restore line list, float list */
- state->line_list = save_line_list;
- state->float_list = save_float_list;
- if (save_elements_after_table != NULL)
- {
- prev_ele->lo_any.next = save_elements_after_table;
- }
- }
-
- /* Reset dummy float element's position and element id before inserting back into the line list */
- lo_ele->lo_any.x = relay_state->doc_state->x;
- lo_ele->lo_any.y = relay_state->doc_state->y;
- lo_ele->lo_any.ele_id = relay_state->top_state->element_id++;
-
- lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, 0);
-
- /* Move layer to new position */
- if (layer != NULL)
- {
- CL_MoveLayer(layer, x, y);
- }
-
- return next;
- }
-
- static LO_Element *
- lo_rl_FitTextBlock( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- LO_Element * next;
-
- next = lo_RelayoutTextBlock ( relay_state->context, relay_state->doc_state, &lo_ele->lo_textBlock, NULL );
- return next;
- }
-
- static LO_Element *
- lo_rl_FitLayer( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- LO_Element *next;
-
- XP_ASSERT(lo_ele->lo_layer.is_end == FALSE);
-
- /* Skip all elements between the start and end LO_LAYER elements */
- next = lo_ele;
- do
- {
- next = lo_tv_GetNextLayoutElement( relay_state->doc_state, next, TRUE);
- } while (next != NULL && next->lo_any.type != LO_LAYER);
-
- if (next->lo_any.type == LO_LAYER) {
- XP_ASSERT(next->lo_layer.is_end == TRUE);
- next = lo_tv_GetNextLayoutElement( relay_state->doc_state, next, TRUE);
- }
-
- return next;
- }
-
-
- static LO_Element *
- lo_rl_FitHeading( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- XP_ASSERT(0);
- return lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
- }
-
- static LO_Element *
- lo_rl_FitSpacer( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
- LO_SpacerStruct *spacer = (LO_SpacerStruct *) lo_ele;
- lo_DocState *state = relay_state->doc_state;
- MWContext *context = relay_state->context;
-
- /* Put the LO_SPACER element back on the line list */
- spacer->lo_any.x = state->x;
- spacer->lo_any.y = state->y;
- spacer->lo_any.ele_id = state->top_state->element_id++;
- lo_AppendToLineList(context, state, lo_ele, 0);
-
- /* Relayout the SPACER element */
- lo_LayoutSpacerElement(context, state, spacer, TRUE);
-
- return next;
- }
-
- static LO_Element * lo_rl_FitSpan( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- XP_ASSERT(0);
- return lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
- }
-
- static LO_Element * lo_rl_FitDiv( lo_RelayoutState *relay_state, LO_Element *lo_ele )
- {
- XP_ASSERT(0);
- return lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE);
- }
-
- /*
- * 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.
- * Should be used during relayout only. It is the relayout version of lo_SetSoftLineBreak().
- */
- void lo_rl_AddSoftBreakAndFlushLine( MWContext *context, lo_DocState *state )
- {
- lo_rl_AddBreakAndFlushLine( context, state, LO_LINEFEED_BREAK_SOFT, LO_CLEAR_NONE, TRUE);
- }
-
-
- void lo_rl_AddBreakAndFlushLine( MWContext *context, lo_DocState *state, int32 break_type, uint32 clear_type, Bool breaking)
- {
- LO_LinefeedStruct *linefeed;
-
- linefeed = NULL;
-
- lo_rl_AppendLinefeedAndFlushLine(context, state, linefeed, break_type, clear_type, breaking, TRUE);
- }
-
- void lo_rl_AppendLinefeedAndFlushLine( MWContext *context, lo_DocState *state, LO_LinefeedStruct *linefeed, int32 break_type, uint32 clear_type,
- Bool breaking, Bool createNewLF)
- {
- /* flush any text */
- lo_FlushLineBuffer(context, state);
-
- lo_UpdateStateWhileFlushingLine( context, state );
-
- if (createNewLF)
- linefeed = lo_NewLinefeed(state, context, break_type, clear_type);
- else
- lo_FillInLineFeed( context, state, break_type, clear_type, linefeed );
-
- if (linefeed != NULL)
- {
- lo_AppendLineFeed( context, state, linefeed, breaking, FALSE );
- }
-
- lo_UpdateStateAfterFlushingLine( context, state, linefeed, TRUE );
- lo_UpdateStateAfterLineBreak( context, state, FALSE );
- lo_UpdateFEProgressBar(context, state);
- }
-
- /*
- * Append a dummy layout element in the line list. When the relayout engine
- * will see this dummy element, it will call lo_LayoutFloat{Image,JavaApp,Embed}()
- */
- void lo_AppendFloatInLineList( lo_DocState *state, LO_Element *ele, LO_Element *restOfLine)
- {
- LO_Element *eptr;
- LO_FloatStruct *float_dummy = XP_NEW_ZAP(LO_FloatStruct);
- float_dummy->float_ele = ele;
- float_dummy->lo_any.type = LO_FLOAT;
- float_dummy->lo_any.ele_id = NEXT_ELEMENT;
- float_dummy->lo_any.x = state->x;
- float_dummy->lo_any.y = state->y;
- float_dummy->lo_any.next = restOfLine;
- float_dummy->lo_any.prev = NULL;
-
- if (state->line_list == NULL ) {
- state->line_list = (LO_Element *) float_dummy;
- }
- else {
- for (eptr = state->line_list; eptr->lo_any.next != NULL; eptr = eptr->lo_any.next)
- ;
- /* eptr now points to the last element in state->line_list */
- eptr->lo_any.next = (LO_Element *) float_dummy;
- float_dummy->lo_any.prev = eptr;
- }
- }
-
- void lo_rl_ReflowCell( MWContext *context, lo_DocState *state, LO_CellStruct *cell )
- {
- lo_RelayoutState *relay_state;
- LO_Element *first;
-
- LO_LockLayout();
-
- /* Copy over cell line lists, float lists to state */
- lo_rl_CopyCellToState( cell, state );
-
- /* Create relayout state */
- relay_state = lo_rl_CreateRelayoutState();
- relay_state->doc_state = state;
- relay_state->context = context;
- relay_state->top_state = state->top_state;
-
- /* Fit cell's layout elements */
- first = lo_tv_GetFirstLayoutElement(relay_state->doc_state);
- lo_rl_FitLayoutElements(relay_state, first);
-
- /* Dummy Floating elements on a new line at the end of a document were not getting put into
- the line_array. This code should ensure that anything left on the line_list gets flushed
- to the line_array. */
- if (state->line_list != NULL)
- lo_AppendLineListToLineArray( context, state, NULL);
-
- /* Restore cell line list and float list */
- lo_rl_CopyStateToCell( relay_state->doc_state, cell );
-
- /* Done with relayout. Destroy relayout state. */
- lo_rl_DestroyRelayoutState( relay_state );
-
- LO_UnlockLayout();
-
- }
-
- void lo_rl_ReflowDocState( MWContext *context, lo_DocState *state )
- {
- lo_RelayoutState *relay_state;
- LO_Element *first;
-
- LO_LockLayout();
-
- /* Create relayout state */
- relay_state = lo_rl_CreateRelayoutState();
- relay_state->doc_state = state;
- relay_state->context = context;
- relay_state->top_state = state->top_state;
-
- /* Fit cell's layout elements */
- first = lo_tv_GetFirstLayoutElement(relay_state->doc_state);
-
- lo_rl_FitLayoutElements(relay_state, first);
-
- /* Dummy Floating elements on a new line at the end of a document were not getting put into
- the line_array. This code should ensure that anything left on the line_list gets flushed
- to the line_array. */
- if (state->line_list != NULL)
- lo_AppendLineListToLineArray( context, state, NULL);
-
- /* Done with relayout. Destroy relayout state. */
- lo_rl_DestroyRelayoutState( relay_state );
-
- LO_UnlockLayout();
- }
-
- void lo_PrepareElementForReuse( MWContext *context, lo_DocState *state, LO_Element * eptr,
- ED_Element *edit_element, intn edit_offset)
- {
- #ifdef EDITOR
- eptr->lo_any.edit_element = NULL;
- eptr->lo_any.edit_offset = 0;
-
- if( EDT_IS_EDITOR(context) )
- {
- if( lo_EditableElement( eptr->type ) )
- {
- if( edit_element == 0 ){
- edit_element = state->edit_current_element;
- edit_offset = state->edit_current_offset;
- }
- EDT_SetLayoutElement( edit_element,
- edit_offset,
- eptr->type,
- eptr );
- } else if( edit_element && (eptr->type == LO_TABLE || eptr->type == LO_CELL) )
- {
- /* _TABLE_EXPERIMENT_ SAVE POINTER TO EDIT ELEMENT IN LO STRUCT */
- eptr->lo_any.edit_element = edit_element;
-
- }
- }
- state->edit_force_offset = FALSE;
- #endif
- }
-
-