From df4a7696b4b1580c0aceef8a4f46465781a23344 Mon Sep 17 00:00:00 2001 From: "shaver%netscape.com" Date: Mon, 19 Oct 1998 20:45:03 +0000 Subject: [PATCH] remove stale DOM span/transclusion code --- lib/layout/Makefile | 113 - lib/layout/Makefile.in | 1 - lib/layout/layblock.c | 3313 --------------- lib/layout/laymocha.c | 974 ----- lib/layout/layout.c | 7861 ---------------------------------- lib/layout/layout.h | 1761 -------- lib/layout/layrelay.c | 1914 --------- lib/layout/layspan.c | 0 lib/layout/laytable.c | 8097 ----------------------------------- lib/layout/laytags.c | 66 - lib/layout/laytext.c | 8735 -------------------------------------- lib/layout/layutil.c | 3914 ----------------- lib/libmocha/Makefile | 2 - lib/libmocha/Makefile.in | 2 - lib/libmocha/et_mocha.c | 9 - lib/libmocha/et_moz.c | 151 +- lib/libmocha/lm_doc.c | 79 +- lib/libmocha/lm_init.c | 9 - lib/libmocha/lm_input.c | 8 - lib/libmocha/lm_span.c | 0 lib/libmocha/lm_trans.c | 0 lib/libmocha/lm_win.c | 17 - 22 files changed, 20 insertions(+), 37006 deletions(-) delete mode 100644 lib/layout/layspan.c delete mode 100644 lib/libmocha/lm_span.c delete mode 100644 lib/libmocha/lm_trans.c diff --git a/lib/layout/Makefile b/lib/layout/Makefile index 8d10c621fe0..e69de29bb2d 100644 --- a/lib/layout/Makefile +++ b/lib/layout/Makefile @@ -1,113 +0,0 @@ -#!gmake -# -# 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. - -DEPTH = ../.. - -MODULE = lay -LIBRARY_NAME = lay - -include $(DEPTH)/config/config.mk - -EXPORTS = laylayer.h layout.h lo_funcs.h - -# XXX Perignon hack -ifdef DOM -EXPORTS += laydom.h laystyle.h -endif - -CSRCS = bullet.c \ - clipline.c \ - layarena.c \ - layblock.c \ - laybuiltin.c \ - laycell.c \ - laycols.c \ - laydisp.c \ - layembed.c \ - layfind.c \ - layform.c \ - laygrid.c \ - layhrule.c \ - layinfo.c \ - laylist.c \ - laymap.c \ - layobj.c \ - layscrip.c \ - layspace.c \ - layspan.c \ - laystyle.c \ - laysub.c \ - ptinpoly.c \ - laymocha.c \ - layjava.c \ - laylayer.c \ - layrelay.c \ - laytrav.c \ - layfree.c \ - layimage.c \ - layout.c \ - laysel.c \ - laytable.c \ - laytags.c \ - laytext.c \ - layutil.c \ - $(NULL) - -ifdef DOM -CSRCS +=laydom.c -endif - -REQUIRES = parse style js layer applet nspr security dbm img util jtools edtplug java hook pref libfont lay rdf network htmldlgs privacy mocha oji ojiimpl xpcom mailto - -ifdef DOM -REQUIRES += dom -endif - -ifdef MOZ_EDITOR -CSRCS += layedit.c \ - $(NULL) - -CPPSRCS = streams.cpp \ - fsfile.cpp \ - editor.cpp \ - edtbuf.cpp \ - edtcmd.cpp \ - edtele.cpp \ - edtjava.cpp \ - edtlist.cpp \ - edtsave.cpp \ - edtutil.cpp \ - $(NULL) -endif - -include $(DEPTH)/config/rules.mk - -ifdef DOM -DEFINES += -DDOM=1 -endif - -ifneq ($(OS_ARCH),OS2) -$(OBJDIR)/laymocha.o: laymocha.c - @$(MAKE_OBJDIR) - $(CC) -o $@ -c $(CFLAGS) -I$(DEPTH)/mocha/include $< -else -$(OBJDIR)/laymocha.o: laymocha.c - @$(MAKE_OBJDIR) - $(CC) -Fo$@ -c $(CFLAGS) -I$(DEPTH)/mocha/include $< -endif - -$(LIBRARY): $(OBJS) diff --git a/lib/layout/Makefile.in b/lib/layout/Makefile.in index bcbc3410e2f..5f5d23372c2 100644 --- a/lib/layout/Makefile.in +++ b/lib/layout/Makefile.in @@ -52,7 +52,6 @@ CSRCS = bullet.c \ layobj.c \ layscrip.c \ layspace.c \ - layspan.c \ laystyle.c \ laysub.c \ ptinpoly.c \ diff --git a/lib/layout/layblock.c b/lib/layout/layblock.c index 3d28018b418..e69de29bb2d 100644 --- a/lib/layout/layblock.c +++ b/lib/layout/layblock.c @@ -1,3313 +0,0 @@ -/* -*- Mode: C; tab-width: 4; 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. - */ - - -#include "xp.h" -#include "pa_parse.h" -#include "pa_tags.h" -#include "layout.h" -#include "laylayer.h" -#include "laystyle.h" -#include "libmocha.h" -#include "libevent.h" -#include "layers.h" -#include "intl_csi.h" -#ifdef DOM -#include "domstyle.h" -#include "lm_dom.h" -#include "laydom.h" -#endif - -/* This struct is used during the processing of a or - * tag, but discarded after the tag is closed. It is used to store the - * current document state while process the tag and channel everything - * into the layer. - */ -struct lo_Block { - MWContext *context; - - /* Saved document state, restored after block is layed out */ - lo_DocState *saved_state; - - int32 start_x, start_y; /* Initial upper-left corner of block, - in parent layer coord system */ - char *old_base_url; - uint8 old_body_attr; - - char * name; /* Identifier for this layer */ - char * above; /* Name of layer above this layer or NULL */ - char * below; /* Name of layer below this layer or NULL */ - int32 z_order; /* Z-order if above/below unspecified */ - - int32 x_offset, y_offset; /* Layer coordinate translation - (for in-flow layers) */ - PRPackedBool is_inflow; /* Is this an out-of-flow or in-flow layer ? */ - PRPackedBool is_inline; /* Is this inline or SRCed */ - PRPackedBool is_dynamic; /* Has the SRC been dynamically changed? */ - PRPackedBool uses_ss_positioning; /* Created using style-sheet 'position' - property instead of tag ? */ - int clip_expansion_policy; /* Expand clip to contain layer content ? */ - - CL_Layer *layer; - LO_CellStruct *cell; - - lo_LayerDocState *old_layer_state; /* Used during table relayout */ - char *match_code; /* Value of layer tag's MATCH parameter */ - char *source_url; -}; - -static int lo_AppendLayerElement(MWContext *context, lo_DocState *state, - LO_BlockInitializeStruct *param, - lo_LayerDocState *layerDoc, Bool is_end); - -static PRBool -lo_SetupDocStateForLayer(lo_DocState *state, - lo_LayerDocState *layer_state, - int32 width, - int32 height, - PRBool is_inflow, - PRBool reflow); - -#ifdef XP_MAC -PRIVATE -#endif -lo_LayerDocState * -lo_GetLayerStateFromId(MWContext *context, int32 layer_id) -{ - int32 doc_id; - lo_TopState *top_state; - lo_LayerDocState *layer_state; - - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - XP_ASSERT(top_state); - if (!top_state) - return NULL; - - XP_ASSERT(layer_id <= top_state->max_layer_num); - if (layer_id > top_state->max_layer_num) - return NULL; - layer_state = top_state->layers[layer_id]; -/* XP_ASSERT(layer_state); */ - return layer_state; -} - -void * -LO_GetLayerMochaObjectFromId(MWContext *context, int32 layer_id) -{ - lo_LayerDocState *layer_state = lo_GetLayerStateFromId(context, layer_id); - if (!layer_state) - return NULL; - return layer_state->mocha_object; -} - -void * -LO_GetLayerMochaObjectFromLayer(MWContext *context, CL_Layer *layer) -{ - lo_LayerDocState *layer_state = lo_GetLayerState(layer); - if (!layer_state) - return NULL; - return layer_state->mocha_object; -} - -void -LO_SetLayerMochaObject(MWContext *context, int32 layer_id, void *mocha_object) -{ - lo_LayerDocState *layer_state = lo_GetLayerStateFromId(context, layer_id); - if (!layer_state) - return; - layer_state->mocha_object = mocha_object; -} - -CL_Layer * -LO_GetLayerFromId(MWContext *context, int32 layer_id) -{ - lo_LayerDocState *layer_state = lo_GetLayerStateFromId(context, layer_id); - if (!layer_state) - return NULL; - return layer_state->layer; -} - -int32 -LO_GetIdFromLayer(MWContext *context, CL_Layer *layer) -{ - lo_LayerDocState *layer_state = lo_GetLayerState(layer); - XP_ASSERT(layer_state); - if (!layer_state) - return 0; - return layer_state->id; -} - -int32 -LO_GetNumberOfLayers(MWContext *context) -{ - int32 doc_id; - lo_TopState *top_state; - - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if (!top_state) - return 0; - - return (top_state->max_layer_num); -} - -PRBool -lo_IsCurrentLayerDynamic(lo_DocState *state) -{ - lo_LayerDocState *layer_state = lo_CurrentLayerState(state); - lo_Block *block = layer_state->temp_block; - - if (layer_state->id == LO_DOCUMENT_LAYER_ID) - return PR_FALSE; - - XP_ASSERT(block); - if (!block) - return PR_FALSE; - - return (PRBool)block->is_dynamic; -} - -PRBool -lo_IsAnyCurrentAncestorSourced(lo_DocState *state) -{ - lo_LayerStack *lptr; - lo_TopState *top_state = state->top_state; - - if (top_state->layer_stack == NULL) - return PR_FALSE; - - lptr = top_state->layer_stack; - while (lptr && lptr->layer_state && - (lptr->layer_state->id != LO_DOCUMENT_LAYER_ID)) { - lo_Block *block = lptr->layer_state->temp_block; - if (block && !block->is_inline) - return PR_TRUE; - - lptr = lptr->next; - } - - return PR_FALSE; -} - -PRBool -lo_IsTagInSourcedLayer(lo_DocState *state, PA_Tag *tag) -{ - PRBool ancestor_sourced = PR_FALSE; - PRBool current_layer_sourced = PR_FALSE; - lo_LayerStack *lptr; - lo_TopState *top_state = state->top_state; - - if (top_state->layer_stack == NULL) - return PR_FALSE; - - lptr = top_state->layer_stack; - while (lptr && lptr->layer_state && - (lptr->layer_state->id != LO_DOCUMENT_LAYER_ID)) { - lo_Block *block = lptr->layer_state->temp_block; - if (block && !block->is_inline) { - if (top_state->layer_stack == lptr) - current_layer_sourced = PR_TRUE; - else { - ancestor_sourced = PR_TRUE; - break; - } - } - lptr = lptr->next; - } - - /* - * If we're not dealing with a or tag, - * then we just return whether any current layer ancestor - * has a SRC attribute. - */ - if (((tag->type != P_LAYER) && (tag->type != P_ILAYER)) || - (tag->is_end == FALSE) || - (top_state->ignore_layer_nest_level != 0)) - return (PRBool)(ancestor_sourced || current_layer_sourced); - /* - * Otherwise, it may be possible that the current close tag - * actually closes out the sourced layer and isn't actually - * part of the content of the sourced layer. - */ - else - return ancestor_sourced; -} - - -/* - * Are there any dynamic layers on the current layer_stack? - */ -PRBool -lo_IsAnyCurrentAncestorDynamic(lo_DocState *state) -{ - lo_LayerStack *lptr; - lo_TopState *top_state = state->top_state; - - if (top_state->layer_stack == NULL) - return PR_FALSE; - - lptr = top_state->layer_stack; - while (lptr && lptr->layer_state && - (lptr->layer_state->id != LO_DOCUMENT_LAYER_ID)) { - lo_Block *block = lptr->layer_state->temp_block; - if (block && block->is_dynamic) - return PR_TRUE; - - lptr = lptr->next; - } - - return PR_FALSE; -} - -static void -lo_init_block_cell(MWContext *context, lo_DocState *state, lo_Block *block) -{ - LO_CellStruct *cell; - - if ((block == NULL)||(block->cell == NULL)) - { - return; - } - - cell = block->cell; - - cell->type = LO_CELL; - cell->ele_id = NEXT_ELEMENT; - cell->x = state->x; - cell->x_offset = 0; - cell->y = state->y; - cell->y_offset = 0; - cell->width = 0; - cell->height = 0; - cell->line_height = state->line_height; - cell->next = NULL; - cell->prev = NULL; - cell->FE_Data = NULL; - cell->cell_float_list = NULL; - cell->backdrop.bg_color = NULL; - cell->backdrop.url = NULL; - cell->border_width = 0; - cell->border_vert_space = 0; - cell->border_horiz_space = 0; - cell->ele_attrmask = 0; - cell->sel_start = -1; - cell->sel_end = -1; - cell->cell_list = NULL; - cell->cell_list_end = NULL; - cell->cell_float_list = NULL; - cell->cell_inflow_layer = NULL; - cell->cell_bg_layer = NULL; - cell->table_cell = NULL; - cell->table_row = NULL; - cell->table = NULL; -} - -lo_LayerDocState * -lo_NewLayerState(MWContext *context) -{ - lo_LayerDocState *layer_state; - XP_Rect everything = CL_MAX_RECT; - - layer_state = XP_NEW_ZAP(lo_LayerDocState); - if (layer_state == NULL) - return NULL; - - layer_state->id = 0; /* This will be filled in later */ - layer_state->cell = NULL; - layer_state->viewRect = everything; - layer_state->doc_lists = XP_NEW_ZAP(lo_DocLists); - if (!layer_state->doc_lists) { - XP_FREE(layer_state); - return NULL; - } - if (!lo_InitDocLists(context, layer_state->doc_lists)) { - XP_FREE(layer_state->doc_lists); - XP_FREE(layer_state); - return NULL; - } - - return layer_state; -} - -#ifdef XP_MAC -PRIVATE -#endif -void -lo_DeleteBlock(lo_Block* block) -{ - XP_FREEIF(block->name); - XP_FREEIF(block->above); - XP_FREEIF(block->below); - XP_FREEIF(block->saved_state); - XP_FREEIF(block->match_code); - XP_FREEIF(block->source_url); - XP_FREE(block); -} - -void -lo_DeleteLayerState(MWContext *context, lo_DocState *state, - lo_LayerDocState *layer_state) -{ - /* Get rid of the layer_state's contents */ - if (layer_state->cell) - lo_RecycleElements(context, state, (LO_Element *)layer_state->cell); - - /* Get rid of the layer_state's layer */ - if (layer_state->layer) { - CL_Layer *parent_layer = CL_GetLayerParent(layer_state->layer); - if (parent_layer) - CL_RemoveChild(parent_layer, layer_state->layer); - LO_LockLayout(); - CL_DestroyLayerTree(layer_state->layer); - LO_UnlockLayout(); - } - - lo_DeleteDocLists(context, layer_state->doc_lists); - if (layer_state->id != LO_DOCUMENT_LAYER_ID) - XP_FREE(layer_state->doc_lists); - if (layer_state->temp_block) - lo_DeleteBlock(layer_state->temp_block); - XP_FREE(layer_state); -} - -/* Number of entries to grow layers array when it is too small */ -#define LAYER_ARRAY_GROW_SIZE 50 - -/* - * Adds the layer_state to the layer list. If one with the same - * id already exists (because of table relayout), we replace - * it with the new one. The old layer_state is returned, so that - * it may be discarded when the new layer is done loading. - */ -lo_LayerDocState * -lo_append_to_layer_array(MWContext *context, lo_TopState *top_state, - lo_DocState *state, - lo_LayerDocState *layer_state) -{ - int32 id; - - XP_ASSERT(top_state); - if (!top_state) - return NULL; - - id = ++top_state->current_layer_num; - layer_state->id = id; - - if (state) - state->current_layer_num_max = id; - - /* - * If we're doing table relayout, we find the corresponding layer in - * the layer list from a previous pass and replace it with the current - * layer. - */ - if (state && state->in_relayout) { - lo_LayerDocState **old_layer_statep = &top_state->layers[id]; - lo_LayerDocState *old_layer_state = *old_layer_statep; - - XP_ASSERT(old_layer_state); - XP_ASSERT(old_layer_state->id == id); - - /* - * Copy over the mocha object, since the reflection might - * already have happened. - */ - layer_state->mocha_object = old_layer_state->mocha_object; - - /* Out with the old and in with the new */ - *old_layer_statep = layer_state; - return old_layer_state; - } - - /* Extend the layers array if it's full */ - if (id >= top_state->num_layers_allocated) { - int32 new_count = top_state->num_layers_allocated + LAYER_ARRAY_GROW_SIZE; - int32 nsize = new_count * sizeof(lo_LayerDocState*); - lo_LayerDocState **new_layers; - - if (top_state->num_layers_allocated == 0) - new_layers = (lo_LayerDocState**)XP_ALLOC(nsize); - else - new_layers = (lo_LayerDocState**)XP_REALLOC(top_state->layers, nsize); - - XP_ASSERT(new_layers); - if (!new_layers) - return NULL; - top_state->layers = new_layers; - top_state->num_layers_allocated = new_count; - } - - top_state->layers[id] = layer_state; - - if (id > top_state->max_layer_num) - top_state->max_layer_num = id; - return NULL; -} - -static void -lo_block_src_exit_fn(URL_Struct *url_struct, int status, MWContext *context) -{ - int32 doc_id; - lo_TopState *top_state; - lo_DocState *state; - - /* XXX need state to be subdoc state? */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL) || - ((state = top_state->doc_state) == NULL)) { - return; - } - - /* Flush tags blocked by this tag. We treat - the special case of an interrupted stream as normal completion, - as this is the resulting error code when we do - and some.gif is in the image cache. */ - if (status >= 0 || status == MK_INTERRUPTED) { - top_state->layout_blocking_element = NULL; - lo_FlushBlockage(context, state, state); - } - /* XXX What's the right thing to do when we fail??? - * Presumably we don't want to flush the blockage and - * continue as if nothing happened. But in some cases, - * we do want to recover in some way. - */ - NET_FreeURLStruct(url_struct); -} - -#ifndef DOM -static void -lo_free_stream(MWContext *context, NET_StreamClass *stream) -{ - XP_DELETE(stream); -} -#endif - -int32 -lo_GetEnclosingLayerWidth(lo_DocState *state) -{ - lo_LayerDocState *layer_state = lo_CurrentLayerState(state); - - /* Special case 100% value for top-level document so that - it doesn't include window margins. */ - if (layer_state->id == LO_DOCUMENT_LAYER_ID) - return state->win_left + state->win_width + state->win_right; - - return state->right_margin - state->left_margin; -} - -/* Convert a string containing a horizontal dimension into layout coordinates, - handling percentages if necessary. */ -static int32 -lo_parse_horizontal_param(char *value, lo_DocState *state, MWContext *context) -{ - int32 parent_width = lo_GetEnclosingLayerWidth(state); - XP_Bool is_percent; - int32 ival; - - ival = lo_ValueOrPercent(value, &is_percent); - if (is_percent) - { - if (state->allow_percent_width == FALSE) - { - ival = 0; - } - else - { - ival = (parent_width * ival) / 100; - } - } - else - { - ival = FEUNITS_X(ival, context); - } - return ival; -} - -int32 -lo_GetEnclosingLayerHeight(lo_DocState *state) -{ - lo_LayerDocState *layer_state = lo_CurrentLayerState(state); - return layer_state->height; -} - -/* Convert a string containing a vertical dimension into layout coordinates, - handling percentages if necessary. */ -static int32 -lo_parse_vertical_param(char *value, lo_DocState *state, MWContext *context) -{ - XP_Bool is_percent; - int32 ival; - int32 parent_height = lo_GetEnclosingLayerHeight(state); - - ival = lo_ValueOrPercent(value, &is_percent); - if (is_percent) - ival = (parent_height * ival) / 100; - else - ival = FEUNITS_Y(ival, context); - return ival; -} - -#ifdef XP_MAC -PRIVATE -#endif -int -lo_parse_clip(char *str, XP_Rect *clip, - lo_DocState *state, MWContext *context) -{ - int32 coord, coords[4]; - int coord_count; - int clip_expansion_policy = LO_AUTO_EXPAND_NONE; - for (coord_count = 0; coord_count <= 3; coord_count++) { - - /* Skip leading whitespace and commas */ - while (XP_IS_SPACE(*str) || (*str == ',')) - str++; - - if (!*str) - break; - - /* Parse distinguished "auto" value */ - if (!XP_STRNCASECMP(str, "auto", 4)) { - str += 4; - clip_expansion_policy |= 1; - coords[coord_count] = 0; - } else { - if (coord_count & 1) - coord = lo_parse_vertical_param(str, state, context); - else - coord = lo_parse_horizontal_param(str, state, context); - coords[coord_count] = coord; - - /* Skip over the number and percentage sign */ - while (*str && !XP_IS_SPACE(*str) && !(*str == ',')) - str++; - } - clip_expansion_policy <<= 1; - } - clip_expansion_policy >>= 1; - - if (coord_count == 2) { - clip->right = coords[0]; - clip->bottom = coords[1]; - return clip_expansion_policy; - } else if (coord_count >= 4) { - clip->left = coords[0]; - clip->top = coords[1]; - clip->right = coords[2]; - clip->bottom = coords[3]; - return clip_expansion_policy; - } - - /* Error - don't clip at all */ - return LO_AUTO_EXPAND_CLIP; -} - -extern XP_Bool -lo_BeginLayer(MWContext *context, - lo_DocState *state, - LO_BlockInitializeStruct *param, - XP_Bool is_inflow); - - -void -lo_FreeBlockInitializeStruct(LO_BlockInitializeStruct *param) -{ - if(param) - { - XP_FREEIF(param->clip); - XP_FREEIF(param->overflow); - XP_FREEIF(param->name); - XP_FREEIF(param->id); - XP_FREEIF(param->above); - XP_FREEIF(param->below); - XP_FREEIF(param->visibility); - XP_FREEIF(param->bgcolor); - XP_FREEIF(param->bgimage); - XP_FREEIF(param->src); - - XP_FREE(param); - } -} - -/* Start a or an . */ -void -lo_BeginLayerTag(MWContext *context, lo_DocState *state, PA_Tag *tag) -{ - INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo(context); - int16 win_csid = INTL_GetCSIWinCSID(c); - LO_BlockInitializeStruct *param; - char *val; - lo_LayerDocState *layer_state; - CL_Layer *parent_layer; -#ifdef DOM - DOM_AttributeEntry *entry; - DOM_Node *node = ACTIVE_NODE(state); - DOM_StyleDatabase *db = state->top_state->style_db; - JSContext *cx = context->mocha_context; -#endif - - if (!context->compositor) - return; - - layer_state = lo_CurrentLayerState(state); - parent_layer = layer_state->layer; - - param = XP_NEW_ZAP(LO_BlockInitializeStruct); - - if(!param) - { - state->top_state->out_of_memory = TRUE; - return; - } - - /* - * Get the horizontal position of the block - */ - val = (char*) lo_FetchParamValue(context, tag, PARAM_LEFT); - if(val) - { - param->has_left = TRUE; - param->left = lo_parse_horizontal_param(val, state, context); - XP_FREE(val); - } else { - /* No LEFT attribute. Is there an X attribute ? */ - val = (char*) lo_FetchParamValue(context, tag, PARAM_PAGEX); - if(val) - { - param->has_left = TRUE; - param->left = (int32)XP_ATOI(val); - - /* Convert from absolute coordinates to layer-relative coordinates */ - param->left -= CL_GetLayerXOrigin(parent_layer); - XP_FREE(val); - } - } - - /* - * Get the vertical position of the block - */ - val = (char*)lo_FetchParamValue(context, tag, PARAM_TOP); - if (val) - { - param->has_top = TRUE; - param->top = lo_parse_vertical_param(val, state, context); - XP_FREE(val); - } else { - /* No TOP attribute. Is there a Y attribute ? */ - val = (char*) lo_FetchParamValue(context, tag, PARAM_PAGEY); - if(val) - { - param->has_top = TRUE; - param->top = (int32)XP_ATOI(val); - - /* Convert from absolute coordinates to layer-relative coordinates */ - param->top -= CL_GetLayerYOrigin(parent_layer); - XP_FREE(val); - } - } - - /* - * Parse the comma separated coordinate list into an - * array of integers. - */ - val = (char*)lo_FetchParamValue(context, tag, PARAM_CLIP); - if(val) - { - param->clip = XP_NEW_ZAP(XP_Rect); - - if(param->clip) - { - XP_BZERO(param->clip, sizeof(XP_Rect)); - param->clip_expansion_policy = - lo_parse_clip(val, param->clip, state, context); - } - } - else - param->clip_expansion_policy = LO_AUTO_EXPAND_CLIP; - - /* - * Get the width parameter, in absolute or percentage. - * If percentage, make it absolute. - */ - val = (char*)lo_FetchParamValue(context, tag, PARAM_WIDTH); - if(val) - { - Bool is_percent; - int32 ival; - - ival = lo_ValueOrPercent(val, &is_percent); - if (is_percent) - param->percent_width = (uint8) ival; - - param->has_width = TRUE; - param->width = lo_parse_horizontal_param(val, state, context); - XP_FREE(val); - } - - /* - * Get the height parameter, in absolute or percentage. - * If percentage, make it absolute. - */ - val = (char*)lo_FetchParamValue(context, tag, PARAM_HEIGHT); - if(val) - { - Bool is_percent; - int32 ival; - - ival = lo_ValueOrPercent(val, &is_percent); - if (is_percent) - param->percent_height = (uint8) ival; - - param->has_height = TRUE; - param->height = lo_parse_vertical_param(val, state, context); - XP_FREE(val); - } - - /* Get the OVERFLOW attribute. */ - param->overflow = (char*)lo_FetchParamValue(context, tag, PARAM_OVERFLOW); - - /* - * Get the optional name for this layer. - */ - param->name = (char*)PA_FetchParamValue(tag, PARAM_NAME, win_csid); - - /* Use either NAME or ID, since we will probably be switching to - the latter */ - param->id = (char*)PA_FetchParamValue(tag, PARAM_ID, win_csid); - - /* - * Get the optional "above" name for the layer we are above. - */ - param->above = (char*)PA_FetchParamValue(tag, PARAM_ABOVE, win_csid); - - /* - * Get the optional "below" name for the layer we are below. - */ - param->below = (char*)PA_FetchParamValue(tag, PARAM_BELOW, win_csid); - - /* - * Get the Z-order of the block - */ - val = (char*)lo_FetchParamValue(context, tag, PARAM_ZINDEX); - if (val) { - param->zindex = XP_ATOI(val); - param->has_zindex = TRUE; - XP_FREE(val); - } - else - param->has_zindex = FALSE; - - /* Get the VISIBILITY parameter to know if this layer starts hidden. */ - param->visibility = (char*)PA_FetchParamValue(tag, PARAM_VISIBILITY, win_csid); - - /* Process background color (BGCOLOR) attribute, if present. */ - param->bgcolor = (char*)PA_FetchParamValue(tag, PARAM_BGCOLOR, win_csid); - -#ifdef DOM - /* if there was no bgcolor specified for the layer, find one in style */ - if (!param->bgcolor) { - if (!DOM_StyleGetProperty(cx, db, node, BG_COLOR_STYLE, &entry)) - /* what now? */ - return; - if (entry) - param->bgcolor = XP_STRDUP(entry->value); - } -#endif - - /* Process backdrop (BACKGROUND) image attribute, if present. */ - param->bgimage = lo_ParseBackgroundAttribute(context, - state, - tag, FALSE); - - param->src = (char*)PA_FetchParamValue(tag, PARAM_SRC, win_csid); - - param->tag = tag; - param->ss_tag = NULL; - - lo_BeginLayer(context, state, param, tag->type == P_ILAYER); - - /* lo_FreeBlockInitializeStruct(param); */ -} - -static int lo_AppendLayerElement(MWContext *context, lo_DocState *state, - LO_BlockInitializeStruct *param, - lo_LayerDocState *layerDoc, Bool is_end) -{ - LO_LayerStruct *layer; - layer = (LO_LayerStruct*)lo_NewElement(context, state, LO_LAYER, NULL, 0); - - XP_ASSERT(layer); - if (!layer) - return FALSE; - - layer->lo_any.type = LO_LAYER; - layer->lo_any.x = state->x; - layer->lo_any.y = state->y; - layer->lo_any.x_offset = 0; - layer->lo_any.y_offset = 0; - layer->lo_any.width = 0; - layer->lo_any.height = 0; - layer->lo_any.line_height = 0; - layer->lo_any.ele_id = NEXT_ELEMENT; - - layer->is_end = is_end; - layer->initParams = param; - layer->layerDoc = layerDoc; - - lo_AppendToLineList(context, state, (LO_Element*)layer, 0); - - return TRUE; -} - -/* parse a comma separated list of 2 or 4 values - * - * Format is "rect(top, right, bottom, left)" - * or "rect(right, bottom)" - * or degenerate case of "top,right,bottom,left" with no rect() - */ -#ifdef XP_MAC -PRIVATE -#endif -XP_Rect * -lo_ParseStyleCoords(MWContext *context, - lo_DocState *state, - StyleStruct *style_struct, - char *coord_string) -{ - - XP_Rect *coords = XP_NEW_ZAP(XP_Rect); - int32 val[4]; - int index=0; - char *value; - SS_Number *ss_num; - - if(!coords) - return(NULL); - - coord_string = XP_StripLine(coord_string); - - /* go past "rect(" and kill ")" character */ -#define _RECT "rect" - if(!strncasecomp(coord_string, _RECT, sizeof(_RECT)-1)) { - char *t; - - /* go past "rect" */ - coord_string += sizeof(_RECT)-1; - - /* go past spaces */ - while(XP_IS_SPACE(*coord_string)) coord_string++; - - /* go past '(' */ - if(*coord_string == '(') - coord_string++; - - /* kill any more spaces */ - while(XP_IS_SPACE(*coord_string)) coord_string++; - - /* Kill the ending ')' */ - t = XP_STRCHR(coord_string, ')'); - if (t) - *t = '\0'; - } - - value = XP_STRTOK(coord_string, ", "); - - while(value && index < 4) - { - ss_num = STYLESTRUCT_StringToSSNumber(style_struct, value); - - /* First and third args are heights. Note that we use - LAYER_WIDTH_STYLE instead of WIDTH_STYLE, since the two are - subtly different. (For the top-level DOCUMENT layer, 100% - WIDTH is the distance between the margins and 100% - LAYER_WIDTH is the width of the window.) */ - if(index & 1) - LO_AdjustSSUnits(ss_num, LAYER_WIDTH_STYLE, context, state); - else - LO_AdjustSSUnits(ss_num, HEIGHT_STYLE, context, state); - - val[index++] = (int32)ss_num->value; - - value = XP_STRTOK(NULL, ",) "); - } - - if (index == 2) - { - coords->right = FEUNITS_X(val[0], context); - coords->bottom = FEUNITS_Y(val[1], context); - } - else if (index == 4) - { - coords->top = FEUNITS_Y(val[0], context); - coords->right = FEUNITS_X(val[1], context); - coords->bottom = FEUNITS_Y(val[2], context); - coords->left = FEUNITS_X(val[3], context); - } - else - { - XP_FREE(coords); - return NULL; - } - - return coords; -} - -#ifdef DOM -void -lo_SetStyleSheetLayerProperties(MWContext *context, lo_DocState *state, - DOM_StyleDatabase *db, DOM_Node *node, - PA_Tag *tag) -{ - DOM_Element *element; - LO_BlockInitializeStruct *param; - DOM_AttributeEntry *entry; - JSBool inflow; - struct SSUnitContext arg; - JSContext *cx = context->mocha_context; - char *src_prop; - - if (node->type != NODE_TYPE_ELEMENT || - lo_IsEmptyTag(tag->type)) - /* other code says we can't handle empty tags, so I bail...for now! */ - return; - - arg.context = context; - -#ifdef DEBUG_shaver - fprintf(stderr, "setting layer data on <%s>\n", PA_TagString(tag->type)); -#endif - - element = (DOM_Element *)node; - - if (!DOM_StyleGetProperty(cx, db, node, LAYER_SRC_STYLE, &entry)) - return; - if (entry) { - src_prop = (char *)entry->value; - } else { - src_prop = NULL; - } - - if (!DOM_StyleGetProperty(cx, db, node, POSITION_STYLE, &entry)) - return; - - if (entry) { - if (!DOM_GetCleanEntryData(cx, entry, PositionParser, NULL, - (uint32 *)&inflow, NULL)) - return; - } else { - if (!src_prop) - return; - } - - param = XP_NEW_ZAP(LO_BlockInitializeStruct); - if (!param) - return; - -#define CHECK_PERCENTAGE(entry, arg) \ - if (arg.units == STYLE_UNITS_PERCENT) \ - entry->dirty = JS_TRUE; - - if (node->name) - param->name = XP_STRDUP(node->name); - if (node->type == NODE_TYPE_ELEMENT) - param->id = element->styleID ? XP_STRDUP(element->styleID) : NULL; - - if (!DOM_StyleGetProperty(cx, db, node, LEFT_STYLE, &entry)) - goto error; - if (entry) { - arg.axisAdjust = AXIS_X; - arg.enclosingVal = 0; - if (!DOM_GetCleanEntryData(cx, entry, lo_ParseSSNumToData, NULL, - ¶m->left, (void *)&arg)) - goto error; - CHECK_PERCENTAGE(entry, arg); - param->has_left = TRUE; - } - - if (!DOM_StyleGetProperty(cx, db, node, TOP_STYLE, &entry)) - goto error; - if (entry) { - arg.axisAdjust = AXIS_Y; - arg.enclosingVal = 0; - if (!DOM_GetCleanEntryData(cx, entry, lo_ParseSSNumToData, NULL, ¶m->top, - (void *)&arg)) - goto error; - CHECK_PERCENTAGE(entry, arg); - param->has_top = TRUE; - } - - if (!DOM_StyleGetProperty(cx, db, node, HEIGHT_STYLE, &entry)) - goto error; - if (entry) { - arg.axisAdjust = AXIS_Y; - arg.enclosingVal = lo_GetEnclosingLayerHeight(state); - if (!DOM_GetCleanEntryData(cx, entry, lo_ParseSSNumToData, NULL, - ¶m->height, (void *)&arg)) - goto error; - CHECK_PERCENTAGE(entry, arg); - param->has_height = TRUE; - } - -#if 0 /* waiting on DOM-savvy lo_ParseStyleCoords */ - if (!DOM_StyleGetProperty(cx, db, node, CLIP_STYLE, &entry)) - goto error; - if (entry) { - /* XXX GetCleanAttributeData, with coord hash somewhere? */ - param->clip = lo_ParseStyleCoords(context, state, entry->value); - param->clip_expansion_policy = LO_AUTO_EXPAND_NONE; - } -#endif - - param->above = NULL; - param->below = NULL; - if (!DOM_StyleGetProperty(cx, db, node, ZINDEX_STYLE, &entry)) - goto error; - if (entry) { - if (!DOM_GetCleanEntryData(cx, entry, lo_atoi, NULL, ¶m->zindex, NULL)) - goto error; - param->has_zindex = TRUE; - } else { - param->has_zindex = FALSE; - } - - if (!DOM_StyleGetProperty(cx, db, node, VISIBILITY_STYLE, &entry)) - goto error; - if (entry) - param->visibility = XP_STRDUP(entry->value); - - if (src_prop) - param->src = NET_MakeAbsoluteURL(state->top_state->base_url, - lo_ParseStyleSheetURL(src_prop)); - else - param->src = NULL; - - param->tag = NULL; - param->ss_tag = tag; - - if (!DOM_StyleGetProperty(cx, db, node, OVERFLOW_STYLE, &entry)) - goto error; - - if (entry) - param->overflow = XP_STRDUP(entry->value); - - if (!DOM_StyleGetProperty(cx, db, node, LAYER_BG_COLOR_STYLE, &entry)) - goto error; - if (entry) - param->bgcolor = XP_STRDUP(entry->value); - param->is_style_bgcolor = TRUE; - - if (!DOM_StyleGetProperty(cx, db, node, LAYER_BG_IMAGE_STYLE, &entry)) - goto error; - if (entry && strcasecomp(entry->value, "none")) - param->bgimage = NET_MakeAbsoluteURL(state->top_state->base_url, - lo_ParseStyleSheetURL(entry->value)); - - if (!LM_SetNodeFlags(node, STYLE_NODE_NEED_TO_POP_LAYER)) - goto error; - -#ifdef DEBUG_shaver - fprintf(stderr, "starting layer for <%s>\n", ((DOM_Element *)node)->tagName); -#endif - if (lo_BeginLayer(context, state, param, inflow)) - error: - lo_FreeBlockInitializeStruct(param); -} -#else - -void -lo_SetStyleSheetLayerProperties(MWContext *context, - lo_DocState *state, - StyleStruct *style_struct, - PA_Tag *tag) -{ - LO_BlockInitializeStruct *param; - char *prop; - char *src_prop; - XP_Bool is_inflow; - SS_Number *ss_num; - - if(!style_struct) - return; - - prop = STYLESTRUCT_GetString(style_struct, POSITION_STYLE); - src_prop = STYLESTRUCT_GetString(style_struct, LAYER_SRC_STYLE); - - if(!prop && !src_prop) - return; - - if(lo_IsEmptyTag(tag->type)) - { - /* setting positioning on an empty tag will - * cause things to not work because of blocked image - * problems, so don't allow it. - */ - return; - } - - if(prop && !strcasecomp(prop, ABSOLUTE_STYLE)) - { - is_inflow = FALSE; - } - else if(prop && !strcasecomp(prop, RELATIVE_STYLE)) - { - is_inflow = TRUE; - } - else if(src_prop) - { - /* not positioned, but an include src attribute */ - is_inflow = TRUE; - } - else - { - XP_FREEIF(prop); - return; /* don't do layers */ - } - - XP_FREEIF(prop); - - param = XP_NEW_ZAP(LO_BlockInitializeStruct); - - if(!param) - return; - - param->name = (char*)lo_FetchParamValue(context, tag, PARAM_NAME); - param->id = (char*)lo_FetchParamValue(context, tag, PARAM_ID); - - ss_num = STYLESTRUCT_GetNumber(style_struct, LEFT_STYLE); - if(ss_num) - { - LO_AdjustSSUnits(ss_num, LEFT_STYLE, context, state); - param->left = FEUNITS_X((int32)ss_num->value, context); - param->has_left = TRUE; - STYLESTRUCT_FreeSSNumber(style_struct, ss_num); - } - - ss_num = STYLESTRUCT_GetNumber(style_struct, TOP_STYLE); - if(ss_num) - { - LO_AdjustSSUnits(ss_num, TOP_STYLE, context, state); - param->top = FEUNITS_Y((int32)ss_num->value, context); - param->has_top = TRUE; - STYLESTRUCT_FreeSSNumber(style_struct, ss_num); - } - - ss_num = STYLESTRUCT_GetNumber(style_struct, HEIGHT_STYLE); - if(ss_num) - { - if(!XP_STRCMP(ss_num->units, "%")) - param->percent_height = (uint8) ss_num->value; - LO_AdjustSSUnits(ss_num, HEIGHT_STYLE, context, state); - param->height = FEUNITS_Y((int32)ss_num->value, context); - param->has_height = TRUE; - STYLESTRUCT_FreeSSNumber(style_struct, ss_num); - } - - /* don't set width. normal style sheets will handle it */ - /* NRA: I think we do need to set the width. But, need to check with Scott. */ - ss_num = STYLESTRUCT_GetNumber(style_struct, WIDTH_STYLE); - if(ss_num) - { - if(!XP_STRCMP(ss_num->units, "%")) - param->percent_width = (uint8) ss_num->value; - LO_AdjustSSUnits(ss_num, WIDTH_STYLE, context, state); - param->width = FEUNITS_X((int32)ss_num->value, context); - param->has_width = TRUE; - STYLESTRUCT_FreeSSNumber(style_struct, ss_num); - } - - prop = STYLESTRUCT_GetString(style_struct, CLIP_STYLE); - if(prop) { - param->clip = lo_ParseStyleCoords(context, state, style_struct, prop); - param->clip_expansion_policy = LO_AUTO_EXPAND_NONE; - } - - param->above = NULL; - param->below = NULL; - ss_num = STYLESTRUCT_GetNumber(style_struct, ZINDEX_STYLE); - if (ss_num) { - param->zindex = (int32)ss_num->value; - param->has_zindex = TRUE; - STYLESTRUCT_FreeSSNumber(style_struct, ss_num); - } - else - param->has_zindex = FALSE; - - param->visibility = STYLESTRUCT_GetString(style_struct, VISIBILITY_STYLE); - - param->src = src_prop; - if(param->src) - { - char *tmp = param->src; - - param->src = lo_ParseStyleSheetURL(param->src); - param->src = NET_MakeAbsoluteURL(state->top_state->base_url, param->src); - XP_FREE(tmp); - } - - param->overflow = STYLESTRUCT_GetString(style_struct, OVERFLOW_STYLE); - - param->bgcolor = STYLESTRUCT_GetString(style_struct, LAYER_BG_COLOR_STYLE); - param->is_style_bgcolor = TRUE; - param->bgimage = STYLESTRUCT_GetString(style_struct, LAYER_BG_IMAGE_STYLE); - if(param->bgimage) - { - char *tmp = param->bgimage; - if(!strcasecomp(param->bgimage, "none")) - { - param->bgimage = NULL; - } - else - { - param->bgimage = lo_ParseStyleSheetURL(param->bgimage); - param->bgimage = NET_MakeAbsoluteURL(state->top_state->base_url, param->bgimage); - } - XP_FREE(tmp); - } - - STYLESTRUCT_SetString(style_struct, STYLE_NEED_TO_POP_LAYER, "1", 0); - - param->tag = NULL; - param->ss_tag = tag; - - lo_BeginLayer(context, state, param, is_inflow); -} -#endif /* DOM */ - -static void -lo_expand_parent_bbox(CL_Layer *layer); /* Forward declaration */ - - -/* Save a copy of the document state, so that we can restore it later. */ -static PRBool -lo_SaveDocState(lo_Block *block, lo_DocState *state) -{ - lo_DocState *saved_state; - - block->start_x = state->x; - block->start_y = state->y; - - saved_state = XP_NEW(lo_DocState); - if (!saved_state) - return PR_FALSE; - - block->saved_state = saved_state; - XP_BCOPY(state, saved_state, sizeof *saved_state); - if (!block->is_inflow) { - state->top_state->in_head = TRUE; - state->top_state->in_body = FALSE; - } - block->old_body_attr = state->top_state->body_attr; - state->top_state->body_attr = 0; - return PR_TRUE; -} - -static void -lo_RestoreDocState(lo_Block *block, lo_DocState *state, Bool reflow) -{ - lo_DocState *saved = block->saved_state; - lo_FontStack *font_stack; - PA_Tag *subdoc_tags_end, *subdoc_tags; - LO_TextInfo text_info; - intn layer_nest_level; - int32 layer_num_max; - - /* - * If there was a BODY tag with a TEXT attribute in this layer, - * then we pop the font that was pushed to enable layer-specific - * text coloring. - */ - if (state->top_state->body_attr & BODY_ATTR_TEXT) { - lo_PopFont(state, P_BODY); - } - state->top_state->body_attr = block->old_body_attr; - - if (!reflow) - lo_SetBaseUrl(state->top_state, block->old_base_url, FALSE); - - if (block->is_inflow) { - state->line_num = saved->line_num; - state->float_list = saved->float_list; - state->line_list = saved->line_list; - state->end_last_line = saved->end_last_line; - - /* Push the cell representing the inflow layer onto the line - list, so that it appears like any other (non-layer) - element. */ - if (state->line_list == NULL) { - state->line_list = (LO_Element*)block->cell; - } else { - LO_Element *eptr = state->line_list; - while (eptr->lo_any.next != NULL) - eptr = eptr->lo_any.next; - eptr->lo_any.next = (LO_Element*)block->cell; - block->cell->prev = eptr; - } - - if (state->end_last_line != NULL) - state->end_last_line->lo_any.next = NULL; - state->linefeed_state = 0; - state->text_fg = saved->text_fg; - state->text_bg = saved->text_bg; - state->anchor_color = saved->anchor_color; - state->visited_anchor_color = saved->visited_anchor_color; - state->active_anchor_color = saved->active_anchor_color; - return; - } - - state->top_state->in_head = FALSE; - state->top_state->in_body = TRUE; - - /* Save a few special state variables that we *don't* restore. - See lo_InitDocState(). */ - - /* XXX - Right now, font info is not reset when entering and - exiting layers. Is that right ? */ - font_stack = state->font_stack; - text_info = state->text_info; - layer_nest_level = state->layer_nest_level; - layer_num_max = state->current_layer_num_max; - subdoc_tags_end = state->subdoc_tags_end; - subdoc_tags = state->subdoc_tags; - - /* First, free up the pieces of the document state that we're - about to overwrite with their restored values. This gets rid of - default values or values left on the stack because the document - author didn't properly close tags inside the layer. */ - state->font_stack = NULL; /* But, don't free the font stack */ - lo_free_layout_state_data(block->context, state); - - /* Restore the entire document state ... */ - XP_BCOPY(saved, state, sizeof *state); - - /* ...except for these variables which are retained across LAYERs */ - state->font_stack = font_stack; - state->text_info = text_info; - state->layer_nest_level = layer_nest_level; - state->current_layer_num_max = layer_num_max; - state->subdoc_tags_end = subdoc_tags_end; - state->subdoc_tags = subdoc_tags; - - if (state->end_last_line != NULL) - state->end_last_line->lo_any.next = NULL; - - XP_FREE(block->saved_state); - block->saved_state = NULL; -} - -static PRBool -lo_SetupDocStateForLayer(lo_DocState *state, - lo_LayerDocState *layer_state, - int32 width, - int32 height, - PRBool is_inflow, - PRBool reflow) -{ - lo_Block *block = layer_state->temp_block; - MWContext *context = block->context; - lo_DocState *saved_state; - - block->is_inflow = is_inflow; - - /* Save old document state so that we can selectively restore - parts of it after the layer is closed. */ - if (!lo_SaveDocState(block, state)) - return PR_FALSE; - - state->float_list = NULL; - state->line_list = NULL; - - if (state->top_state->base_url && !reflow) - block->old_base_url = XP_STRDUP(state->top_state->base_url); - - if (is_inflow) - return PR_TRUE; - - /* - * XXX This doesn't seem right. We're saving some of the doc's - * layout state and resetting all of it while the block - * is laid out. This layout state will be restored once the block - * is completed. However, things like the float_list are part of the - * incremental layout state as well as a representation of the final - * document. So, if we're asked to redraw while the block is being laid - * out, we will probably do the wrong thing for floating elements. - */ - - /* Unspecified height won't change state's height property. */ - if (height == 0) - height = state->win_height; - - state = lo_InitDocState(state, context, - width, height, - 0, 0, /* margin_width, margin_height */ - NULL, /* clone_state */ - layer_state->doc_lists, PR_TRUE); - - if (!state) - return PR_FALSE; - - /* Though most state variables are reset to their virgin state (in - lo_InitDocState, above), there are a few state variables - related to table layout that are preserved when a layer tag is - opened. */ - saved_state = block->saved_state; - state->is_a_subdoc = saved_state->is_a_subdoc; - state->in_relayout = saved_state->in_relayout; - state->subdoc_tags = saved_state->subdoc_tags; - state->subdoc_tags_end = saved_state->subdoc_tags_end; - - state->text_fg = saved_state->text_fg; - state->text_bg = saved_state->text_bg; - state->anchor_color = saved_state->anchor_color; - state->visited_anchor_color = saved_state->visited_anchor_color; - state->active_anchor_color = saved_state->active_anchor_color; - - return PR_TRUE; -} - -static char layer_end_tag[] = ""; -static char layer_suppress_tag[] = "<" PT_LAYER " suppress>"; -static char display_none_style[] = PARAM_STYLE "='display:none'>"; - -#ifdef XP_MAC -PRIVATE -#endif -void -lo_insert_suppress_tags(MWContext *context, lo_TopState *top_state, - LO_BlockInitializeStruct *param) -{ - PA_Tag *end_tag; - uint32 i; - - /* - * Since we're adding tags to the blocked tags list without going through - * lo_BlockTag, we need to see if this is a flushed to block transition - * and, if so, add to the doc_data's ref count. We don't want to do this - * if we're in the process of flushing blockage - in that case, the count - * has already been incremented. - */ - if (top_state->tags == NULL && top_state->flushing_blockage == FALSE) - PA_HoldDocData(top_state->doc_data); - - /* If we can here through a LAYER or ILAYER tag */ - if (param->tag) { - /* - * Shove in a sequence into the - * tag stream so that all inline content of this layer is - * suppressed. The sourced content comes in before the - * first end tag, the inline conent comes in after the - * tag. - */ - end_tag = pa_CreateMDLTag(top_state->doc_data, - layer_end_tag, - sizeof layer_end_tag - 1); - - if (end_tag) { - end_tag->newline_count = LO_IGNORE_TAG_MARKER; - end_tag->next = pa_CreateMDLTag(top_state->doc_data, - layer_suppress_tag, - sizeof layer_suppress_tag - 1); - if (end_tag->next) { - end_tag->next->newline_count = LO_IGNORE_TAG_MARKER; - if (top_state->tags == NULL) - top_state->tags_end = &end_tag->next->next; - else - end_tag->next->next = top_state->tags; - top_state->tags = end_tag; - - /* - * If there are any other input_write_levels on the stack - * that correspond to the front of the tag list, move them - * to account for the newly inserted tags. - */ - for (i = 0; i < top_state->input_write_level; i++) - if (top_state->input_write_point[i] == &top_state->tags) - top_state->input_write_point[i] = &end_tag->next->next; - } - else { - top_state->out_of_memory = TRUE; - PA_FreeTag(end_tag); - } - } - else - top_state->out_of_memory = TRUE; - } - /* - * If we came here through the include-source style and - * the tag is a container tag - */ - else if (param->ss_tag && !lo_IsEmptyTag(param->ss_tag->type)) { - /* - * Shove in a sequence into - * the tag stream. The sourced content comes in before the - * first end tag, the inline conent comes in after the - * display:none tag and is ignored. - */ - end_tag = (PA_Tag *)XP_NEW_ZAP(PA_Tag); - - if (end_tag) { - end_tag->type = param->ss_tag->type; - end_tag->is_end = TRUE; - end_tag->newline_count = LO_IGNORE_TAG_MARKER; - - end_tag->next = PA_CloneMDLTag(param->ss_tag); - if (end_tag->next) { - PA_Tag *begin_tag = end_tag->next; - - begin_tag->newline_count = LO_IGNORE_TAG_MARKER; - if (begin_tag->data) - PA_FREE(begin_tag->data); - /* Can't do a strdup because it's parser memory */ - begin_tag->data_len = XP_STRLEN(display_none_style); - begin_tag->true_len = begin_tag->data_len; - begin_tag->data = PA_ALLOC(begin_tag->data_len + 1); - if (begin_tag->data) { - char *buff; - - /* Copy over the new tag data */ - PA_LOCK(buff, char *, begin_tag->data); - XP_BCOPY(display_none_style, buff, begin_tag->data_len); - buff[begin_tag->data_len] = '\0'; - PA_UNLOCK(buff); - - if (top_state->tags == NULL) - top_state->tags_end = &begin_tag->next; - else - begin_tag->next = top_state->tags; - top_state->tags = end_tag; - } - else { - top_state->out_of_memory = TRUE; - PA_FreeTag(begin_tag); - PA_FreeTag(end_tag); - } - } - else { - top_state->out_of_memory = TRUE; - PA_FreeTag(end_tag); - } - } - else - top_state->out_of_memory = TRUE; - } -} - - -/* Start a or an . */ -#ifdef XP_MAC -PRIVATE -#endif -void -lo_begin_layer_internal(MWContext *context, - lo_DocState *state, - LO_BlockInitializeStruct *param, - XP_Bool is_inflow) -{ - INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo(context); - int16 win_csid = INTL_GetCSIWinCSID(c); - lo_Block *block; - lo_LayerDocState *layer_state, *parent_layer_state; - char *str, *layer_name; - int32 block_wrap_width, x_parent_offset, y_parent_offset; - int32 block_x, block_y; - lo_TopState *top_state; - XP_Rect bbox; - PRBool hidden, inherit_visibility; - CL_Layer *layer, *parent_layer; - char *backdrop_image_url = NULL; - LO_Color rgb, *bg_color = NULL; - char *url = NULL; - - if (!context->compositor || !param) - return; - - /* - * If this is a nested inflow layer, then flush the line list into our parent - * (without introducing a line break). This ensures that whatever line changes - * (specifically shifting of cell origin) that occur while laying out this ilayer - * are reflected in our parent. - */ - if (lo_InsideInflowLayer(state) && is_inflow) - { - lo_FlushLineList(context, state, LO_LINEFEED_BREAK_SOFT, LO_CLEAR_NONE, FALSE); - } - - top_state = state->top_state; - block = XP_NEW_ZAP(lo_Block); - if (block == NULL) - { - state->top_state->out_of_memory = TRUE; - return; - } - block->context = context; - layer_state = lo_NewLayerState(context); - if (layer_state == NULL) { - state->top_state->out_of_memory = TRUE; - lo_DeleteBlock(block); - return; - } - layer_state->temp_block = block; - - /* Retain MATCH attribute for use in comparison of attribute of - same name in matching closing layer tag. */ - block->match_code = NULL; - if (param->tag) { - char *match = - (char*)PA_FetchParamValue(param->tag, PARAM_MATCH, win_csid); - if (match) { - block->match_code = XP_STRDUP(match); - PA_FREE(match); - } - } - - block->name = NULL; - block->above = NULL; - block->below = NULL; - hidden = PR_FALSE; - inherit_visibility = PR_TRUE; - block->z_order = -1; - block->old_layer_state = NULL; - - /* If there is no tag associated with this layer, then it was - created as a result of a style sheet. */ - block->uses_ss_positioning = (param->tag == NULL); - - block->is_inflow = is_inflow; - - /* In-flow layers use coordinates that are relative to their - "natural", in-flow position. */ - if (block->is_inflow) { - block->x_offset = state->x; - block->y_offset = state->y; - } else { - block->x_offset = 0; - block->y_offset = 0; - } - - - x_parent_offset = y_parent_offset = 0; - parent_layer_state = lo_CurrentLayerState(state); - parent_layer = parent_layer_state->layer; - if (parent_layer) /* Paranoia */ - lo_GetLayerXYShift(parent_layer, &x_parent_offset, &y_parent_offset); - - /* - * Get the X position of the block - */ - if (param->has_left) - { - block_x = param->left; - } else { - if (block->is_inflow) { - block_x = 0; - } else { - block_x = state->x - x_parent_offset; - } - } - - /* - * Get the Y position of the block - */ - if (param->has_top) - { - block_y = param->top; - } else { - if (block->is_inflow) { - block_y = 0; - } else { - block_y = state->y - y_parent_offset; - } - } - - XP_BZERO(&bbox, sizeof(bbox)); - - /* - * Get the width parameter, in absolute or percentage. - * If percentage, make it absolute. - */ - if (param->has_width) - block_wrap_width = param->width; - else if (param->has_left) - block_wrap_width = state->right_margin - param->left; - else - block_wrap_width = state->right_margin - state->x; - - /* - * Parse the comma separated coordinate list into an - * array of integers. - */ - if (param->clip) - { - bbox = *param->clip; - - /* Don't allow the layer's clip to expand */ - block->clip_expansion_policy = param->clip_expansion_policy; - } else { - /* Allow the clip to expand to include the layer's contents. */ - block->clip_expansion_policy = LO_AUTO_EXPAND_CLIP; - if (param->has_width) - bbox.right = block_wrap_width; - } - - if (param->has_height) { - layer_state->height = param->height; - /* If no CLIP set, set initial bottom edge of layer clip to be - the same as HEIGHT. */ - if (block->clip_expansion_policy & LO_AUTO_EXPAND_CLIP_BOTTOM) - bbox.bottom = param->height; - } - - /* Treat any value of OVERFLOW, except "hidden" to be the same as - "visible". For compatibility with the older CSS positioning - spec, we also treat "none" specially. Can't set OVERFLOW - unless HEIGHT is provided. */ - if (param->has_height && - param->overflow && - XP_STRCASECMP(param->overflow, "none") && - XP_STRCASECMP(param->overflow, "visible")) { - - /* Constrain all drawing to {0, 0, width, height} box */ - XP_Rect *viewRect = &layer_state->viewRect; - viewRect->left = 0; - viewRect->top = 0; - viewRect->right = block_wrap_width; - viewRect->bottom = param->height; - } - - /* - * Get the optional name for this layer. - */ - layer_name = NULL; - if(param->name) - layer_name = param->name; - else if(param->id) - layer_name = param->id; - - /* Don't allow layer names that start with a number or underscore */ - if (layer_name && ((layer_name[0] < '0') || (layer_name[0] > '9')) && - (layer_name[0] != '_')) - block->name = XP_STRDUP(layer_name); - - /* - * Get the optional "above" name for the layer we are above. - */ - if(param->above) - block->above = XP_STRDUP(param->above); - - /* - * Get the optional "below" name for the layer we are below. - */ - if (!block->above) - { - if(param->below) - block->below = XP_STRDUP(param->below); - - if (!block->below) - { - /* - * Get the Z-order of the block - */ - if (param->has_zindex) - { - block->z_order = param->zindex; - } - } - } - - /* Get the VISIBILITY parameter to know if this layer starts hidden. */ - if (param->visibility) - { - /* Handle "HIDE", "HIDDEN", etc. */ - hidden = (PRBool)!XP_STRNCASECMP(param->visibility, "hid", 3); - inherit_visibility = (PRBool)!XP_STRCASECMP(param->visibility, "inherit"); - } - - /* Add a new LO_LAYER dummy layout element to the line list. Relayout will step through - the line list and reflow the layer when the LO_LAYER element is encountered. */ - if (!lo_AppendLayerElement(context, state, param, layer_state, FALSE)) - return; - - /* Reset document layout state, saving old state to be restored - after we lay out this layer. */ - if (!lo_SetupDocStateForLayer(state, layer_state, - block_wrap_width, layer_state->height, - (PRBool)is_inflow, PR_FALSE)) { - state->top_state->out_of_memory = TRUE; - lo_DeleteLayerState(context, state, layer_state); - return; - } - - block->cell = layer_state->cell = - (LO_CellStruct *)lo_NewElement(context, state, - LO_CELL, NULL, 0); - if (block->cell == NULL) - { - state->top_state->out_of_memory = TRUE; - lo_DeleteLayerState(context, state, layer_state); - return; - } - lo_init_block_cell(context, state, block); - - /* Create the layer that corresponds to this block, initially invisible - and with empty clip and [0,0] origin. */ - PA_LOCK(str, char *, block->name); - layer = lo_CreateBlockLayer(context, - str, - (PRBool)block->is_inflow, - block->x_offset, - block->y_offset, - block_wrap_width, - layer_state, state); - PA_UNLOCK(block->name); - if (!layer) { - state->top_state->out_of_memory = TRUE; - lo_DeleteLayerState(context, state, layer_state); - return; - } - block->layer = layer_state->layer = layer; - if (block->is_inflow) - block->cell->cell_inflow_layer = layer; - - /* Indicate that this layer's contents were not obtained as a - result of setting the JavaScript 'src' property of the layer. */ - block->is_dynamic = FALSE; - block->is_inline = TRUE; - - /* - * Attach the layer doc_state to the layer list. The return - * value is the old layer_state if we're in table relayout. - * We need to wait till we're done processing this layer tag - * before we actually get rid of the layer_state and its - * contents. - */ - block->old_layer_state = lo_append_to_layer_array(context, state->top_state, - state, - layer_state); - - /* Attach the layer into the layer tree */ - lo_AttachHTMLLayer(context, layer, parent_layer, - block->above, block->below, block->z_order); - - /* Reflect the layer into JavaScript */ - ET_ReflectObject(context, NULL, param->tag, - parent_layer_state->id, - layer_state->id, LM_LAYERS); - - /* Process background color (BGCOLOR) attribute, if present. */ - if (param->bgcolor) { - - XP_Bool rv; - if(param->is_style_bgcolor) - rv = LO_ParseStyleSheetRGB(param->bgcolor, &rgb.red, &rgb.green, &rgb.blue); - else - rv = LO_ParseRGB(param->bgcolor, &rgb.red, &rgb.green, &rgb.blue); - if(rv) - bg_color = &rgb; - } - if (bg_color) - LO_SetLayerBgColor(layer, bg_color); - - /* Process backdrop (BACKGROUND) image attribute, if present. */ - if(param->bgimage) - backdrop_image_url = XP_STRDUP(param->bgimage); - - if (!bg_color && !backdrop_image_url) { - /* This is a transparent block, so let's go offscreen */ - CL_ChangeLayerFlag(layer, CL_PREFER_DRAW_OFFSCREEN, PR_TRUE); - } - if (backdrop_image_url) { - LO_SetLayerBackdropURL(layer, backdrop_image_url); - XP_FREE(backdrop_image_url); - } - - lo_SetLayerClipExpansionPolicy(layer, block->clip_expansion_policy); - - /* Move layer into position. Set clip dimensions and initial visibility. */ - LO_MoveLayer(layer, block_x, block_y); - LO_SetLayerBbox(layer, &bbox); - lo_expand_parent_bbox(layer); - CL_ChangeLayerFlag(layer, CL_HIDDEN, hidden); -#ifdef XP_MAC - CL_ChangeLayerFlag(layer, CL_OVERRIDE_INHERIT_VISIBILITY, - (PRBool)!inherit_visibility); -#else - CL_ChangeLayerFlag(layer, CL_OVERRIDE_INHERIT_VISIBILITY, - (int32)!inherit_visibility); -#endif - - /* Push this layer on the layer stack */ - lo_PushLayerState(state->top_state, layer_state); - ET_SetActiveLayer(context, layer_state->id); - state->layer_nest_level++; - - if (param->src) { - url = NET_MakeAbsoluteURL(top_state->base_url, param->src); - if (url == NULL) { - top_state->out_of_memory = TRUE; - return; - } - } - - if ((url != NULL) && (top_state->doc_data != NULL)) { - URL_Struct *url_struct; - int status; - - block->source_url = XP_STRDUP(url); - block->is_inline = FALSE; - url_struct = NET_CreateURLStruct(url, top_state->force_reload); - if (block->source_url == NULL || url_struct == NULL) { - top_state->out_of_memory = TRUE; - if (url_struct != NULL) - NET_FreeURLStruct(url_struct); - } - else { - char *referer; - lo_LayerStack *lptr; - - /* - * The referer for this SRC="url" fetch will be the base document - * url if there are no enclosing out-of-line or dynamic layer tags, - * otherwise it will be the nearest enclosing layer block's source - * url (set via a previous SRC= or by LO_PrepareLayerForWriting). - */ - referer = top_state->base_url; - lptr = top_state->layer_stack->next; - while (lptr && lptr->layer_state && - (lptr->layer_state->id != LO_DOCUMENT_LAYER_ID)) { - lo_Block *temp_block; - - temp_block = lptr->layer_state->temp_block; - if (temp_block && - (!temp_block->is_inline || temp_block->is_dynamic)) { - referer = temp_block->source_url; - break; - } - lptr = lptr->next; - } - - url_struct->referer = XP_STRDUP(referer); - if (url_struct->referer == NULL) { - top_state->out_of_memory = TRUE; - NET_FreeURLStruct(url_struct); - return; - } - - /* - * We're blocking on the current element till we - * read in the new stream. - */ - top_state->layout_blocking_element = (LO_Element *)block->cell; - - lo_insert_suppress_tags(context, top_state, param); - - /* - * New tags will be inserted at the start of the - * blocked tags list. - */ - top_state->input_write_point[top_state->input_write_level] = - &top_state->tags; - - lo_SetBaseUrl(state->top_state, url, FALSE); - XP_FREEIF(top_state->inline_stream_blocked_base_url); - - status = NET_GetURL(url_struct, FO_CACHE_AND_PRESENT_INLINE, context, - lo_block_src_exit_fn); - - if (status < 0) - top_state->layout_blocking_element = NULL; - - } - XP_FREE(url); - } -} - -static Bool -lo_create_layer_blockage(MWContext *context, lo_DocState *state) -{ - lo_TopState *top_state; - top_state = state->top_state; - - top_state->layout_blocking_element - = lo_NewElement(context, state, LO_CELL, NULL, 0); - if (top_state->layout_blocking_element == NULL) { - top_state->out_of_memory = TRUE; - } else { - top_state->layout_blocking_element->type = LO_CELL; - top_state->layout_blocking_element->lo_any.ele_id = NEXT_ELEMENT; - top_state->layout_blocking_element->lo_cell.cell_list = NULL; - top_state->layout_blocking_element->lo_cell.cell_list_end = NULL; - top_state->layout_blocking_element->lo_cell.cell_float_list = NULL; - top_state->layout_blocking_element->lo_cell.cell_bg_layer = NULL; - top_state->layout_blocking_element->lo_cell.backdrop.bg_color = NULL; - } - - return(top_state->layout_blocking_element != NULL); -} - -typedef struct -{ - MWContext *context; - lo_DocState *state; - XP_Bool is_inflow; - int32 doc_id; -} lo_RestoreLayerClosure; - -static void -lo_RestoreLayerExitFn(void *myclosure, - LO_BlockInitializeStruct *param) -{ - lo_RestoreLayerClosure *closure = (lo_RestoreLayerClosure *)myclosure; - MWContext *context = closure->context; - lo_DocState *state = closure->state; - lo_TopState *top_state = NULL; - int32 doc_id = closure->doc_id; - PRBool flushp = (PRBool)(param->src == NULL); - LO_Element *blocking_element=NULL; - - if (doc_id == XP_DOCID(context)) { - top_state = state->top_state; - /* - * We check that we're still blocking, since it's possible that - * something's come along and changed things under us e.g. if - * the context is interrupted while we were out to mocha. - */ - blocking_element = top_state->layout_blocking_element; - if (blocking_element) - lo_begin_layer_internal(context, state, param, closure->is_inflow); - } - - XP_FREE(closure); - - /* Get rid of the cloned tag */ - if(param->tag) { - PA_FreeTag(param->tag); - } - else if (param->ss_tag) { - PA_FreeTag(param->ss_tag); - } - - lo_FreeBlockInitializeStruct(param); - - /* Get rid of the fake layout blocking element */ - if ((doc_id == XP_DOCID(context)) && - (blocking_element)) { - lo_FreeElement(context, blocking_element, FALSE); - - /* - * If there was a SRC attribute in the param list, then - * the block layout will have created a new blocking element. - * Otherwise, flush the blocked list and carry on as if - * nothing happened. - */ - if (flushp) { - top_state->layout_blocking_element = NULL; - lo_FlushBlockage(context, state, state->top_state->doc_state); - } - } -} - -XP_Bool -lo_BeginLayer(MWContext *context, - lo_DocState *state, - LO_BlockInitializeStruct *param, - XP_Bool is_inflow) -{ - if (!context->compositor || !param) - return TRUE; - - lo_begin_layer_internal(context, state, param, is_inflow); - return TRUE; - -/* We no longer recreate layers on resizes, so the following code that rehooks up - layout's layer data structures with the JS layer objects can go away. */ -#if 0 - if (state->top_state->resize_reload && !state->in_relayout && - !lo_IsAnyCurrentAncestorDynamic(state) && LM_CanDoJS(context)) { - lo_RestoreLayerClosure *closure; - PA_Tag *new_tag; - - /* I guess this whole section can go away, now that we have resize - without reload a la Mariner??? */ - - closure = XP_NEW_ZAP(lo_RestoreLayerClosure); - if (!closure) - return TRUE; - - closure->context = context; - closure->state = state; - closure->is_inflow = is_inflow; - closure->doc_id = XP_DOCID(context); - - /* - * Block layout and send an event mocha to restore the layer - * state from the preserved mocha object. - */ - lo_create_layer_blockage(context, state); - lo_BlockLayerTag(context, state, NULL); - - if (param->tag) { - new_tag = PA_CloneMDLTag(param->tag); - if (!new_tag) { - state->top_state->out_of_memory = TRUE; - return TRUE; - } - param->tag = new_tag; - } - else if (param->ss_tag) { - new_tag = PA_CloneMDLTag(param->ss_tag); - if (!new_tag) { - state->top_state->out_of_memory = TRUE; - return TRUE; - } - param->ss_tag = new_tag; - } - - ET_RestoreLayerState(context, state->top_state->current_layer_num + 1, - param, lo_RestoreLayerExitFn, closure); - return FALSE; - } - else { - lo_begin_layer_internal(context, state, param, is_inflow); - return TRUE; - } -#endif -} - -void -lo_BlockLayerTag(MWContext *context, lo_DocState *state, PA_Tag *tag) -{ - lo_TopState *top_state; - pa_DocData *doc_data; - - top_state = state->top_state; - doc_data = top_state->doc_data; - XP_ASSERT(doc_data != NULL && doc_data->url_struct != NULL); - if (doc_data == NULL || doc_data->url_struct == NULL) /* Paranoia */ - return; -} - -void -lo_UnblockLayerTag(lo_DocState *state) -{ - /* - * I guess we don't really need this anymore, since we're not - * maintaining a blocked_tag count. - */ -} - -static void -lo_set_layer_bbox(CL_Layer *layer, XP_Rect *bbox, PRBool grow_parent); - -/* A layer has expanded in order to contain its content. Expand it's - parent also.*/ -static void -lo_expand_parent_bbox(CL_Layer *layer) -{ - XP_Rect parent_bbox, child_bbox; - CL_Compositor *compositor = CL_GetLayerCompositor(layer); - - /* Get the parent's and child's bbox */ - CL_Layer *parent_layer = CL_GetLayerParent(layer); - - if (! parent_layer) - return; - - CL_GetLayerBbox(parent_layer, &parent_bbox); - CL_GetLayerBbox(layer, &child_bbox); - - /* Convert the child and parent to the same coordinate system. */ - CL_LayerToWindowRect(compositor, parent_layer, &parent_bbox); - CL_LayerToWindowRect(compositor, layer, &child_bbox); - - /* Expand the parent's bbox to encompass the child layer. */ - XP_RectsBbox(&child_bbox, &parent_bbox, &parent_bbox); - CL_WindowToLayerRect(compositor, parent_layer, &parent_bbox); - lo_set_layer_bbox(parent_layer, &parent_bbox, PR_TRUE); - - lo_expand_parent_bbox(parent_layer); -} - -/* Set the clipping bounds of a layer, but don't override any - explicit clip set by the user with the CLIP attribute. */ -static void -lo_set_layer_bbox(CL_Layer *layer, XP_Rect *bbox, PRBool grow_parent) -{ - XP_Rect new_bbox, old_bbox; - - int clip_expansion_policy = lo_GetLayerClipExpansionPolicy(layer); - - CL_GetLayerBbox(layer, &old_bbox); - XP_CopyRect(&old_bbox, &new_bbox); - - if (clip_expansion_policy & LO_AUTO_EXPAND_CLIP_LEFT) - new_bbox.left = bbox->left; - - if (clip_expansion_policy & LO_AUTO_EXPAND_CLIP_RIGHT) - new_bbox.right = bbox->right; - - if (clip_expansion_policy & LO_AUTO_EXPAND_CLIP_TOP) - new_bbox.top = bbox->top; - - if (clip_expansion_policy & LO_AUTO_EXPAND_CLIP_BOTTOM) - new_bbox.bottom = bbox->bottom; - - /* If the layer's clip didn't change, there's nothing to do */ - if (XP_EqualRect(&old_bbox, &new_bbox)) - return; - - LO_SetLayerBbox(layer, &new_bbox); - - /* Expand the parent layer's bbox to contain this child's bbox */ - if (grow_parent) - lo_expand_parent_bbox(layer); -} - -/* Expand the layer associated with an HTML block in case the block - has grown. Don't expand the layer's width if the width is fixed - and don't expand the layer's height if the height is fixed. */ -static void -lo_block_grown(lo_Block *block) -{ - CL_Layer *layer = block->layer; - lo_LayerDocState *layer_state; - LO_CellStruct *cell = block->cell; - - XP_Rect clip, existing_clip; - - clip.left = cell->x; - clip.top = cell->y; - clip.right = cell->x + cell->width; - clip.bottom = cell->y + cell->height; - - layer_state = lo_GetLayerState(layer); - layer_state->contentWidth = cell->width; - layer_state->contentHeight = cell->height; - - /* The coordinates of elements inside in-flow layers is with respect - to the containing layer. */ - if (block->is_inflow) - XP_OffsetRect(&clip, -block->start_x, -block->start_y); - - /* Don't allow a layer's clip to shrink. */ - CL_GetLayerBbox(layer, &existing_clip); - XP_RectsBbox(&existing_clip, &clip, &clip); - - lo_set_layer_bbox(layer, &clip, (PRBool)!block->is_dynamic); -} - -static LO_CellStruct * -lo_compose_block(MWContext *context, lo_DocState *state, lo_Block *block) -{ - int32 shift; - XP_Rect update_rect, ele_bbox; - LO_Element *tptr; - LO_CellStruct *cell; - - cell = block->cell; - - XP_BZERO(&update_rect, sizeof(XP_Rect)); - - /* Expands the dimensions of the cell to encompass any floating - * elements that are outside its bounds. - */ - tptr = state->float_list; - while (tptr != NULL) { - lo_GetElementBbox(tptr, &ele_bbox); - - shift = cell->x - ele_bbox.left; - if (shift > 0) { - cell->x -= shift; - cell->width += shift; - } - shift = ele_bbox.right - (cell->x + cell->width); - if (shift > 0) - cell->width += shift; - shift = cell->y - ele_bbox.top; - if (shift > 0) { - cell->y -= shift; - cell->height += shift; - } - shift = ele_bbox.bottom - (cell->y + cell->height); - if (shift > 0) - cell->height += shift; - - XP_RectsBbox(&ele_bbox, &update_rect, &update_rect); - - tptr = tptr->lo_any.next; - } - tptr = state->float_list; - cell->cell_float_list = tptr; - - if (context->compositor) { - /* Expand the block layer. */ - lo_block_grown(block); - - if (block->is_inflow) - XP_OffsetRect(&update_rect, -block->start_x, -block->start_y); - - /* Update the area occupied by the floating elements. */ - CL_UpdateLayerRect(context->compositor, block->layer, &update_rect, - PR_FALSE); - } - - return(cell); -} - -/* Process a or tag. */ -void -lo_EndLayerTag(MWContext *context, - lo_DocState *state, - PA_Tag *tag) -{ - INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo(context); - int16 win_csid = INTL_GetCSIWinCSID(c); - lo_LayerDocState *layer_state = lo_CurrentLayerState(state); - lo_Block *block = layer_state->temp_block; - - if (! block) - return; - - /* If opening layer tag had a MATCH attribute. The value of the - MATCH attribute in the closing tag must be identical or we - refuse to really close the layer. This capability is used by - libmime to prevent renegade mail messages from escaping the - bounds of their layer-enforced encapsulation using extra layer - end tags in the message. */ - if (block->match_code) { - char *attempted_match = - (char*)PA_FetchParamValue(tag, PARAM_MATCH, win_csid); - if (!attempted_match) - return; - if (XP_STRCMP(attempted_match, block->match_code)) { - XP_TRACE(("Failed attempt to circumvent mail message security")); - XP_ASSERT(0); - PA_FREE(attempted_match); - return; - } - PA_FREE(attempted_match); - } - - lo_EndLayer(context, state, PR_TRUE); -} - -static PRBool -lo_destroy_ancillary_child_layers(CL_Layer *layer, void *unused) -{ - LO_LayerType type; - type = LO_GetLayerType(layer); - if (type == LO_GROUP_LAYER) - return PR_TRUE; - CL_DestroyLayer(layer); - return PR_TRUE; -} - -void -lo_EndLayer(MWContext *context, - lo_DocState *state, - PRBool send_load_event) -{ - int32 right_edge; - LO_CellStruct *cell; - lo_LayerDocState *enclosing_layer_state; - lo_LayerDocState *layer_state = lo_CurrentLayerState(state); - lo_Block *block = layer_state->temp_block; - - /* During destruction, the compositor can disappear out from underneath us. */ - if (!context->compositor) - return; - - /* - * Protect from bad params. - */ - if (! block) { - return; - } - - if (! block->is_inflow) { - lo_CloseOutLayout(context, state); - } - else { - /* - * Flush out the last line of the block, without - * introducing a line break. - * BUGBUG In reality, calling lo_FlushLineList - * also introduces a linefeed. We've set it up - * so that linefeeds within blocks are of 0 - * size, so the linefeed is effectively ignored. - * The 0 linefeed stuff is a hack! - */ - lo_FlushLineList(context, state, LO_LINEFEED_BREAK_SOFT, LO_CLEAR_NONE, FALSE); - } - - cell = lo_compose_block(context, state, block); - - /* For an in-flow layer, expand the enclosing cell's size on the - right and bottom edges to contain any descendant - layers. However, we only do this for ILAYER tags, not for - layers created as a result of 'position:relative' applied to - style-sheet elements. */ - if (block->is_inflow && !block->uses_ss_positioning) { - int32 grow_width, grow_height; - XP_Rect bbox; - - CL_GetLayerBbox(block->layer, &bbox); - grow_width = (bbox.right - cell->width); - grow_height = (bbox.bottom - cell->height); - - /* Position of right-edge of cell containing layer */ - right_edge = state->x; - - /* If the inflow layer is caused to grow vertically, force a - line break. */ - if (grow_height > 0) { - lo_SetSoftLineBreakState(context, state, FALSE, 1); - cell->height = bbox.bottom; - state->y += grow_height; - } - - /* Compute new position of cell's right edge. */ - if (grow_width > 0) { - right_edge += grow_width; - cell->width = bbox.right; - } - - /* Set minimum and maximum possible layout widths so that any - enclosing table cells will be dimensioned properly. */ - if (right_edge + state->win_right > state->max_width) - state->max_width = right_edge + state->win_right; - if (right_edge + state->win_right > state->min_width) - state->min_width = right_edge + state->win_right; - } - - /* Restore document layout state, if necessary */ - lo_RestoreDocState(block, state, FALSE); - - /* Mark the tag by appending a LO_LAYER element to the line list. */ - if (!lo_AppendLayerElement(context, state, NULL, NULL, TRUE)) - return; - - if (cell != NULL && !block->is_inflow) - { - int32 max_y; - - cell->next = NULL; - cell->ele_id = NEXT_ELEMENT; - lo_RenumberCell(state, cell); - - /* XXX - Do we really want to expand the document size to - include the layer ? */ - max_y = cell->y + cell->y_offset + cell->height; - if (max_y > state->max_height) - { - state->max_height = max_y; - } - } - - /* - * If we're in table relayout, we can now safely delete the - * layer from a previous layout pass. - */ - if (state->in_relayout && block->old_layer_state) { - /* Get rid of child image layers, cell background layers, embedded window layers and blink layers */ - CL_ForEachChildOfLayer(block->old_layer_state->layer, - lo_destroy_ancillary_child_layers, - (void *)block->old_layer_state->layer); - CL_DestroyLayer(block->old_layer_state->layer); - } - - state->layer_nest_level--; - lo_PopLayerState(state); - enclosing_layer_state = lo_CurrentLayerState(state); - ET_SetActiveLayer(context, enclosing_layer_state->id); - - if (block->is_dynamic) { - lo_TopState * top_state; - - top_state = state->top_state; - top_state->nurl = NULL; - top_state->layout_status = PA_COMPLETE; - - lo_CloseMochaWriteStream(top_state, EVENT_LOAD); - - lo_FreeLayoutData(context, state); - - /* - * We force a composite so that the layer is drawn, even - * if it is immediately changed again (as is sometimes the - * case when we're dynamically resizing layers. - */ - if (context->compositor) { - XP_Rect bbox; - - CL_GetLayerBbox(block->layer, &bbox); - CL_UpdateLayerRect(context->compositor, block->layer, - &bbox, PR_TRUE); - } - } - - if (send_load_event) - ET_SendLoadEvent(context, EVENT_LOAD, NULL, NULL, layer_state->id, - state->top_state->resize_reload); - -} - -void -lo_AddLineListToLayer(MWContext *context, - lo_DocState *state, - LO_Element *line_list_end) -{ - int32 max_y, max_x, min_x, height, width; - LO_Element *line_list; - LO_CellStruct *cell; - lo_LayerDocState *layer_state = lo_CurrentLayerState(state); - lo_Block *block = layer_state->temp_block; - - line_list = state->line_list; - if (line_list == NULL) - return; - - cell = block->cell; - - /* - * For dynamic src changing, we just refresh the area occupied by - * the old layer. For the autoexpanding case, we reset the size - * of the layer to zero. - */ - if ((cell->cell_list == NULL) && (cell->cell_float_list == NULL)) { - - /* If no page background color is specified, we must - commit to one as soon as any layout element is - displayed in order to avoid the excessive flashing that - would occur had we created the background later. */ - if (state->top_state->nothing_displayed != FALSE) { - lo_use_default_doc_background(context, state); - state->top_state->nothing_displayed = FALSE; - } - - if (block->is_dynamic) { - XP_Rect bbox; - - CL_GetLayerBbox(block->layer, &bbox); - CL_UpdateLayerRect(context->compositor, block->layer, &bbox, PR_FALSE); - - if (block->clip_expansion_policy == LO_AUTO_EXPAND_CLIP) - { - XP_Rect empty_bbox = {0, 0, 0, 0}; - - CL_SetLayerBbox(block->layer, &empty_bbox); - } - } - } - - if (cell->cell_list_end == NULL) - { - line_list->lo_any.prev = NULL; - cell->cell_list = line_list; - line_list_end->lo_any.next = NULL; - cell->cell_list_end = line_list_end; - } - else - { - cell->cell_list_end->lo_any.next = line_list; - line_list->lo_any.prev = cell->cell_list_end; - line_list_end->lo_any.next = NULL; - cell->cell_list_end = line_list_end; - } - - max_y = line_list_end->lo_any.y + line_list_end->lo_any.y_offset + - line_list_end->lo_any.height; - - if (block->is_inflow) - height = max_y - cell->y; - else - height = max_y; - if (height > cell->height) - cell->height = height; - - /* - * If the new line extends past the previous bounds of the - * cell, extend the bounds of the cell. - */ - max_x = line_list_end->lo_any.x + line_list_end->lo_any.x_offset + - line_list_end->lo_any.width; - - if (block->is_inflow) - width = max_x - cell->x; - else - width = max_x; - if (width > cell->width) - cell->width = width; - - /* - * This deals with the case where the new line laid out - * has a start position to the left of the start of the - * block. This can happen if the layer (with no absolute - * positioning starts to the right of an element that - * been aligned left and then its contents flow to the - * left of the start position below the aligned element i.e. - * - * ******* - * ******* ----- - * ******* ----- - * ******* ----- - * ------------- - * ------------- - * - * where * represents the element aligned left (an image - * for instance) and - represents the contents of the layer. - * The layer is shifted left (to the start position of - * the new line and expanded) i.e. - * - * ******* - * ####### ----- - * ####### ----- - * ####### ----- - * ------------- - * ------------- - * - * where # represents the (transparent) part of the layer - * overlapping the aligned element. - */ - min_x = line_list->lo_any.x + line_list->lo_any.x_offset; - if (min_x < cell->x) { - cell->width += cell->x - min_x; - cell->x = min_x; - } - - if (context->compositor && (block->layer != NULL)) { - int32 min_y; - XP_Rect update_rect; - - /* Expand the block layer. */ - lo_block_grown(block); - - /* Update the area of the line we just added. */ - min_y = max_y - state->line_height; - update_rect.left = min_x; - update_rect.top = min_y; - update_rect.right = max_x; - update_rect.bottom = max_y; - - if (block->is_inflow) - XP_OffsetRect(&update_rect, -block->start_x, -block->start_y); - - CL_UpdateLayerRect(context->compositor, block->layer, &update_rect, - PR_FALSE); - } -} - - -void -lo_FinishLayerLayout(MWContext *context, lo_DocState *state, int mocha_event) -{ - lo_TopState *top_state = state->top_state; - PA_Tag *tag; - - /* End the current block if we're done processing all tags */ - if ((top_state->layout_blocking_element == NULL) && - (top_state->tags == NULL)) - lo_EndLayer(context, state, PR_TRUE); - /* We're still blocked on something, so - * create a fake tag and add it to the end of the - * blocked list. Processing this tag will eventually close - * out layout. - */ - else - { - tag = pa_CreateMDLTag(top_state->doc_data, - layer_end_tag, - sizeof layer_end_tag - 1); - - if (tag != NULL) { - /* Put it at the end of the tag list */ - if (top_state->tags == NULL) - top_state->tags = tag; - else - *top_state->tags_end = tag; - top_state->tags_end = &tag->next; - } - else - top_state->out_of_memory = TRUE; - } -} - -static void -lo_block_src_setter_exit_fn(URL_Struct *url_struct, - int status, - MWContext *context) -{ - NET_FreeURLStruct(url_struct); -} - -static lo_Block * -lo_init_block(MWContext *context, lo_DocState *state, - lo_LayerDocState *layer_state, int32 block_x, int32 block_y, - int32 width) -{ - lo_Block *block; - - /* Create a new block and initialize it */ - block = XP_NEW_ZAP(lo_Block); - if (block == NULL) - return NULL; - block->context = context; - - layer_state->temp_block = block; - - if (!lo_SetupDocStateForLayer(state, layer_state, - width, layer_state->height, PR_FALSE, PR_FALSE)) { - lo_DeleteBlock(block); - layer_state->temp_block = NULL; - return NULL; - } - - return block; -} - -static PRBool -lo_remove_extra_layers(CL_Layer *child, void *closure) -{ - LO_LayerType type; - CL_Layer *parent = (CL_Layer *)closure; - - type = LO_GetLayerType(child); - if ((type == LO_HTML_BLOCK_LAYER) || (type == LO_HTML_BACKGROUND_LAYER)) - return PR_TRUE; - CL_RemoveChild(parent, child); - LO_LockLayout(); - CL_DestroyLayerTree(child); - LO_UnlockLayout(); - return PR_TRUE; -} - -Bool -LO_PrepareLayerForWriting(MWContext *context, int32 layer_id, - const char *referer, int32 width) -{ - int32 doc_id; - lo_TopState *top_state; - lo_DocState *state; - CL_Layer *layer; - lo_LayerDocState *layer_state; - lo_Block *block; - int32 block_x, block_y; - - /* Get the top state of the document */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return FALSE; - } - state = top_state->doc_state; - - /* - * XXX For now, if we're still loading, we can't - * change the src of a layer. Is this the right - * thing to check that we're done with the original - * HTML stream? - */ - if ((top_state->doc_data != NULL) || lo_InsideLayer(state)) - return FALSE; - - layer_state = lo_GetLayerStateFromId(context, layer_id); - if (!layer_state) - return FALSE; - layer = layer_state->layer; - - /* Delete the contents of the old layer */ - lo_SaveFormElementStateInFormList(context, - layer_state->doc_lists->form_list, - TRUE); - if (layer_state->cell) - lo_RecycleElements(context, state, (LO_Element *)layer_state->cell); - lo_DeleteDocLists(context, layer_state->doc_lists); - - /* - * Get rid of all "extra" layers associated (blink, cell_bg, images, etc.) - * associated with this layer and its content. Get rid of all group - * layer descendants, too. - */ - CL_ForEachChildOfLayer(layer, - lo_remove_extra_layers, - (void *)layer); - /* - * XXX We're assuming that FinishLayout has already been called and - * some of the doc_state has been trashed. Here we reset some of the - * state so that new tags can be parsed. - */ - state->base_font_size = DEFAULT_BASE_FONT_SIZE; - state->font_stack = lo_DefaultFont(state, context); - state->line_buf = PA_ALLOC(LINE_BUF_INC * sizeof(char)); - if (state->line_buf == NULL) { - state->top_state->out_of_memory = TRUE; - return FALSE; - } - state->line_buf_size = LINE_BUF_INC; - state->line_buf_len = 0; - - /* - * We reset the script_tag_count so that we'll reset the - * mocha decoder stream. - */ - top_state->script_tag_count = 0; - - block_x = CL_GetLayerXOffset(layer); - block_y = CL_GetLayerYOffset(layer); - - if (!lo_InitDocLists(context, layer_state->doc_lists)) { - state->top_state->out_of_memory = FALSE; - return FALSE; - } - - block = lo_init_block(context, state, layer_state, block_x, block_y, - width); - if (block) - block->cell = (LO_CellStruct *)lo_NewElement(context, state, - LO_CELL, NULL, 0); - - if ((block == NULL) || (block->cell == NULL)) - { - state->top_state->out_of_memory = TRUE; - if (block) { - lo_DeleteBlock(block); - layer_state->temp_block = NULL; - } - - return FALSE; - } - - layer_state->cell = block->cell; - - lo_init_block_cell(context, state, block); - - block->layer = layer; - block->is_dynamic = TRUE; - block->is_inline = TRUE; - block->source_url = referer ? XP_STRDUP(referer) : NULL; - - state->layer_nest_level++; - /* Push this layer on the layer stack */ - lo_PushLayerState(state->top_state, layer_state); - ET_SetActiveLayer(context, layer_state->id); - - block->clip_expansion_policy = lo_GetLayerClipExpansionPolicy(layer); - - return TRUE; -} - - -Bool -LO_SetLayerSrc(MWContext *context, int32 layer_id, char *str, - const char *referer, int32 width) -{ - int32 doc_id; - lo_TopState *top_state; - lo_DocState *state; - char *url; - URL_Struct *url_struct; - int status; - lo_LayerDocState *layer_state; - - /* Get the top state of the document */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return FALSE; - } - state = top_state->doc_state; - - if (!LO_PrepareLayerForWriting(context, layer_id, referer, width)) - return FALSE; - - layer_state = lo_CurrentLayerState(state); - if (layer_state && layer_state->temp_block) - layer_state->temp_block->is_inline = FALSE; - - /* Ask netlib to start loading the new URL */ - url = NET_MakeAbsoluteURL(top_state->base_url, str); - if (url == NULL) { - /*lo_Block *block;*/ - - top_state->out_of_memory = TRUE; -/* XXX block = state->current_block; - if (block) { - lo_RecycleElements(context, state, (LO_Element *)block->cell); - XP_DELETE(block); - } - state->current_block = NULL; */ - return FALSE; - } - - url_struct = NET_CreateURLStruct(url, top_state->force_reload); - if (url_struct == NULL) - top_state->out_of_memory = TRUE; - else { - url_struct->referer = XP_STRDUP(referer); - if (!url_struct->referer) { - top_state->out_of_memory = TRUE; - NET_FreeURLStruct(url_struct); - XP_FREE(url); - return FALSE; - } - - lo_SetBaseUrl(state->top_state, url, FALSE); - XP_FREEIF(top_state->inline_stream_blocked_base_url); - - status = NET_GetURL(url_struct, FO_CACHE_AND_PRESENT_INLINE, context, - lo_block_src_setter_exit_fn); - } - - XP_FREE(url); - return TRUE; -} - -/* Create an anonymous layer, not tied to the HTML source. - Returns -1 on error, 0 if unable to create a new layer because the parser - stream is still active. */ -int32 -LO_CreateNewLayer(MWContext *context, int32 wrap_width, int32 parent_layer_id) -{ - int32 doc_id, layer_id; - LO_BlockInitializeStruct *param; - CL_Layer *parent_layer; - lo_TopState *top_state; - lo_DocState *state; - lo_LayerDocState *layer_state; - CL_Layer *layer; - - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if (!top_state) - return 0; - - /* - * XXX For now, if we're still loading, we can't - * change the src of a layer. Is this the right - * thing to check that we're done with the original - * HTML stream? - */ - state = top_state->doc_state; - if ((top_state->doc_data != NULL) || lo_InsideLayer(state)) - return 0; - - param = XP_NEW_ZAP(LO_BlockInitializeStruct); - if(!param) - return -1; - - param->has_width = PR_TRUE; - param->width = wrap_width; - param->has_left = PR_TRUE; - param->left = 0; - param->has_top = PR_TRUE; - param->top = 0; - param->visibility = "hide"; - param->clip_expansion_policy = LO_AUTO_EXPAND_CLIP; - - layer_id = top_state->max_layer_num; - - /* Create a fake layer and append it to the document */ - lo_begin_layer_internal(context, state, param, FALSE); - lo_EndLayer(context, state, PR_FALSE); - XP_FREE(param); - - /* The only way we know if we succeeded is to see if the - top_state->layers array has grown. */ - if (layer_id == top_state->max_layer_num) - return -1; - - /* Reparent the layer, in case the parent wasn't the _DOCUMENT */ - parent_layer = LO_GetLayerFromId(context, parent_layer_id); - layer_id = top_state->max_layer_num; - layer_state = lo_GetLayerStateFromId(context, layer_id); - layer_state->is_constructed_layer = PR_TRUE; - layer = layer_state->layer; - CL_RemoveChild(CL_GetLayerParent(layer), layer); - CL_InsertChild(parent_layer, layer, NULL, CL_ABOVE); - - return layer_id; -} - - -/* Called when you see a start LO_LAYER element. Reflow version of lo_begin_layer_internal */ -void -lo_BeginLayerReflow(MWContext *context, lo_DocState *state, - LO_BlockInitializeStruct *param, - lo_LayerDocState *layer_state) -{ - lo_Block *block; - lo_LayerDocState *parent_layer_state; - int32 block_wrap_width, x_parent_offset, y_parent_offset; - CL_Layer *layer, *parent_layer; - int32 block_x, block_y; - Bool is_inflow; - XP_Rect bbox; - LO_CellStruct *cell; - lo_GroupLayerClosure *closure; - lo_HTMLBlockClosure *content_closure; - - if (!context->compositor || !param || !layer_state) - return; - - block = layer_state->temp_block; - is_inflow = block->is_inflow; - cell = layer_state->cell; - layer = layer_state->layer; - - /* - * If this is a nested inflow layer, then flush the line list into our parent - * (without introducing a line break). This ensures that whatever line changes - * (specifically shifting of cell origin) that occur while laying out this ilayer - * are reflected in our parent. - */ - if (lo_InsideInflowLayer(state) && is_inflow) - { - lo_rl_AddBreakAndFlushLine(context, state, LO_LINEFEED_BREAK_SOFT, LO_CLEAR_NONE, FALSE); - } - - /* In-flow layers use coordinates that are relative to their - "natural", in-flow position. */ - if (block->is_inflow) { - block->x_offset = state->x; - block->y_offset = state->y; - } else { - block->x_offset = 0; - block->y_offset = 0; - } - - x_parent_offset = y_parent_offset = 0; - parent_layer_state = lo_CurrentLayerState(state); - parent_layer = parent_layer_state->layer; - if (parent_layer) /* Paranoia */ - lo_GetLayerXYShift(parent_layer, &x_parent_offset, &y_parent_offset); - - /* - * Get the X position of the block - */ - if (param->has_left) - { - block_x = param->left; - } else { - if (block->is_inflow) { - block_x = 0; - } else { - block_x = state->x - x_parent_offset; - } - } - - /* - * Get the Y position of the block - */ - if (param->has_top) - { - block_y = param->top; - } else { - if (block->is_inflow) { - block_y = 0; - } else { - block_y = state->y - y_parent_offset; - } - } - - XP_BZERO(&bbox, sizeof(bbox)); - - /* - * Get the width parameter, in absolute or percentage. - * If percentage, make it absolute. - */ - if (param->has_width) - block_wrap_width = param->width; - else if (param->has_left) - block_wrap_width = state->right_margin - param->left; - else - block_wrap_width = state->right_margin - state->x; - - - /* - * Parse the comma separated coordinate list into an - * array of integers. - */ - if (param->clip) - { - bbox = *param->clip; - - /* Don't allow the layer's clip to expand */ - block->clip_expansion_policy = param->clip_expansion_policy; - } else { - /* Allow the clip to expand to include the layer's contents. */ - block->clip_expansion_policy = LO_AUTO_EXPAND_CLIP; - if (param->has_width) - bbox.right = block_wrap_width; - } - - if (param->has_height) { - layer_state->height = param->height; - /* If no CLIP set, set initial bottom edge of layer clip to be - the same as HEIGHT. */ - if (block->clip_expansion_policy & LO_AUTO_EXPAND_CLIP_BOTTOM) - bbox.bottom = param->height; - } - - /* Treat any value of OVERFLOW, except "hidden" to be the same as - "visible". For compatibility with the older CSS positioning - spec, we also treat "none" specially. Can't set OVERFLOW - unless HEIGHT is provided. */ - if (param->has_height && - param->overflow && - XP_STRCASECMP(param->overflow, "none") && - XP_STRCASECMP(param->overflow, "visible")) { - - /* Constrain all drawing to {0, 0, width, height} box */ - XP_Rect *viewRect = &layer_state->viewRect; - viewRect->left = 0; - viewRect->top = 0; - viewRect->right = block_wrap_width; - viewRect->bottom = param->height; - } - - /* Reset document layout state, saving old state to be restored - after we lay out this layer. */ - if (!lo_SetupDocStateForLayer(state, layer_state, - block_wrap_width, layer_state->height, - (PRBool)is_inflow, PR_TRUE)) { - state->top_state->out_of_memory = TRUE; - lo_DeleteLayerState(context, state, layer_state); - return; - } - - /* Reset cell struct variables that depend on the doc state */ - cell->ele_id = NEXT_ELEMENT; - cell->x = state->x; - cell->y = state->y; - cell->width = 0; - cell->height = 0; - cell->x_offset = 0; - cell->y_offset = 0; - - - closure = (lo_GroupLayerClosure *)CL_GetLayerClientData(layer); - if (closure) - { - /* Reset group layer closure's properties */ - XP_ASSERT(closure->type == LO_GROUP_LAYER); - closure->x_offset = block->x_offset; - closure->y_offset = block->y_offset; - closure->wrap_width = block_wrap_width; - } - - /* Move layer into position. Set clip dimensions and initial visibility. */ - LO_MoveLayer(layer, block_x, block_y); - LO_SetLayerBbox(layer, &bbox); - lo_expand_parent_bbox(layer); - - /* Resize the layer */ - CL_ResizeLayer(layer, block_wrap_width, layer_state->height); - - /* Push this layer on the layer stack */ - lo_PushLayerState(state->top_state, layer_state); - state->layer_nest_level++; -} - -/* Called when the end LO_LAYER element is seen by the reflow code */ -void -lo_EndLayerReflow(MWContext *context, lo_DocState *state) -{ - lo_LayerDocState *layer_state = lo_CurrentLayerState(state); - lo_Block *block = layer_state->temp_block; - LO_CellStruct *cell = NULL; - int32 right_edge; - - /* During destruction, the compositor can disappear out from underneath us. */ - if (!context->compositor || !block) - return; - - if (! block->is_inflow) { - lo_EndLayoutDuringReflow(context, state); - } - else { - lo_rl_FlushLineList(context, state, LO_LINEFEED_BREAK_SOFT, LO_CLEAR_NONE, FALSE); - } - - cell = lo_compose_block(context, state, block); - - /* For an in-flow layer, expand the enclosing cell's size on the - right and bottom edges to contain any descendant - layers. However, we only do this for ILAYER tags, not for - layers created as a result of 'position:relative' applied to - style-sheet elements. */ - if (block->is_inflow && !block->uses_ss_positioning) { - int32 grow_width, grow_height; - XP_Rect bbox; - - CL_GetLayerBbox(block->layer, &bbox); - grow_width = (bbox.right - cell->width); - grow_height = (bbox.bottom - cell->height); - - /* Position of right-edge of cell containing layer */ - right_edge = state->x; - - /* If the inflow layer is caused to grow vertically, force a - line break. */ - if (grow_height > 0) { - lo_SetLineBreakState ( context, state, FALSE, LO_LINEFEED_BREAK_HARD, 1, TRUE); - cell->height = bbox.bottom; - state->y += grow_height; - } - - /* Compute new position of cell's right edge. */ - if (grow_width > 0) { - right_edge += grow_width; - cell->width = bbox.right; - } - - /* Set minimum and maximum possible layout widths so that any - enclosing table cells will be dimensioned properly. */ - if (right_edge + state->win_right > state->max_width) - state->max_width = right_edge + state->win_right; - if (right_edge + state->win_right > state->min_width) - state->min_width = right_edge + state->win_right; - } - - /* Restore document layout state, if necessary */ - lo_RestoreDocState(block, state, TRUE); - - if (cell != NULL && !block->is_inflow) - { - int32 max_y; - - cell->next = NULL; - cell->ele_id = NEXT_ELEMENT; - lo_RenumberCell(state, cell); - - /* XXX - Do we really want to expand the document size to - include the layer ? */ - max_y = cell->y + cell->y_offset + cell->height; - if (max_y > state->max_height) - { - state->max_height = max_y; - } - } - state->layer_nest_level--; - lo_PopLayerState(state); - - ET_SendLoadEvent(context, EVENT_LOAD, NULL, NULL, layer_state->id, - TRUE); - -} diff --git a/lib/layout/laymocha.c b/lib/layout/laymocha.c index f48e95247da..e69de29bb2d 100644 --- a/lib/layout/laymocha.c +++ b/lib/layout/laymocha.c @@ -1,974 +0,0 @@ -/* -*- Mode: C; tab-width: 4; 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. - */ - - -#include "xp.h" -/* - * Mocha layout interface. - */ -#include "lo_ele.h" -#include "layout.h" -#include "laylayer.h" -#include "pa_parse.h" -#include "libevent.h" -#if defined (JAVA) -#include "jsjava.h" -#elif defined (OJI) -#include "jsjava.h" -#include "jvmmgr.h" -#endif -#include "layers.h" - -PRIVATE -lo_TopState * -lo_GetTopState(MWContext *context) -{ - int32 doc_id; - lo_TopState *top_state; - - if (!context) - return NULL ; - - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if (top_state != NULL && top_state->doc_state == NULL) - return NULL; - return top_state; -} - -lo_TopState * -lo_GetMochaTopState(MWContext *context) -{ - lo_TopState *top_state; - - top_state = lo_GetTopState(context); - if (top_state == NULL) - return NULL; - return top_state; -} - -lo_FormData * -LO_GetFormDataByID(MWContext *context, int32 layer_id, intn form_id) -{ - lo_TopState *top_state; - lo_FormData *form; - lo_DocLists *doc_lists; - - top_state = lo_GetTopState(context); - if (top_state == NULL) - return NULL; - - doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id); - if (!doc_lists) - return NULL; - - for (form = doc_lists->form_list; form != NULL; form = form->next) { - if (form->id == form_id) - return form; - } - return NULL; -} - -/* - * This can only safely be called while holding the JS_Lock - */ -uint -LO_EnumerateForms(MWContext *context, int32 layer_id) -{ - lo_TopState *top_state; - lo_FormData *form; - lo_DocLists *doc_lists; - - top_state = lo_GetMochaTopState(context); - if (top_state == NULL) - return 0; - - doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id); - if (!doc_lists) - return 0; - - /* Try to reflect all forms in case someone is enumerating. */ - for (form = doc_lists->form_list; form != NULL; form = form->next) { - if (form->mocha_object == NULL) - LM_ReflectForm(context, form, NULL, layer_id, 0); - } - return doc_lists->current_form_num; -} - -/* - * Note that index is zero-based from the first form, and if in the second - * form, is one more than the index of the last element in the first form. - * So we subtract form's first element index before subscripting. - */ -LO_FormElementStruct * -LO_GetFormElementByIndex(lo_FormData *form, int32 index) -{ - LO_Element **ele_list; - LO_FormElementStruct *form_element; - - if (form->form_elements == NULL) - return NULL; - PA_LOCK(ele_list, LO_Element **, form->form_elements); - form_element = (LO_FormElementStruct *)ele_list[0]; - index -= form_element->element_index; - if ((uint32)index < (uint32)form->form_ele_cnt) - form_element = (LO_FormElementStruct *)ele_list[index]; - else - form_element = NULL; - PA_UNLOCK(form->form_elements); - if (form_element == NULL || form_element->element_data == NULL) - return NULL; - return form_element; -} - - -/* - * This can only safely be called while holding the JS_Lock - */ -uint -LO_EnumerateFormElements(MWContext *context, lo_FormData *form) -{ - LO_Element **ele_list; - LO_FormElementStruct *form_element; - uint i; - - /* Try to reflect all elements in case someone is enumerating. */ - PA_LOCK(ele_list, LO_Element **, form->form_elements); - for (i = 0; i < (uint)form->form_ele_cnt; i++) { - form_element = (LO_FormElementStruct *)ele_list[i]; - if (form_element->mocha_object == NULL) - LM_ReflectFormElement(context, form_element->layer_id, - form->id, form_element->element_index, NULL); - } - PA_UNLOCK(form->form_elements); - return form->form_ele_cnt; -} - -void -lo_BeginReflectForm(MWContext *context, lo_DocState *doc_state, PA_Tag *tag, - lo_FormData *form) -{ - int32 layer_id; - - if(!PA_HasMocha(tag)) - return; - - layer_id = lo_CurrentLayerId(doc_state); - ET_ReflectObject(context, (void *) form, tag, layer_id, - form->id, LM_FORMS); - ET_SetActiveForm(context, form); - -} - -LO_ImageStruct * -LO_GetImageByIndex(MWContext *context, int32 layer_id, intn index) -{ - lo_TopState *top_state; - LO_ImageStruct *image; - lo_DocLists *doc_lists; - - top_state = lo_GetTopState(context); - if (top_state == NULL) - return NULL; - - doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id); - if (!doc_lists) - return NULL; - - for (image = doc_lists->image_list; image != NULL; - image = image->next_image) { - if (image && image->seq_num == index) - return image; - } - return NULL; -} - -uint -LO_EnumerateImages(MWContext *context, int32 layer_id) -{ - lo_TopState *top_state; - uint image_num; - LO_ImageStruct *img; - lo_DocLists *doc_lists; - - top_state = lo_GetMochaTopState(context); - if (top_state == NULL) - return 0; - - doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id); - if (!doc_lists) - return 0; - - /* - * Try to reflect all images in case someone is enumerating. - * If its already on the image_list then it already has a valid - * seq_num - */ - image_num = 0; - for (img = doc_lists->image_list; img; img = img->next_image) { - if (img->mocha_object == NULL) - LM_ReflectImage(context, img, NULL, layer_id, img->seq_num); - image_num++; - } - return image_num; -} - -void -lo_EndReflectForm(MWContext *context, lo_FormData *form_data) -{ - ET_SetActiveForm(context, NULL); -} - -void -lo_ReflectImage(MWContext *context, lo_DocState *doc_state, PA_Tag *tag, - LO_ImageStruct *image, Bool blocked, int32 layer_id) -{ - lo_DocLists *doc_lists; - - /* Reflect only IMG tags, not form INPUT tags of TYPE=IMAGE */ - if (tag->type != P_IMAGE && tag->type != P_NEW_IMAGE) - return; - - /* Has this image already been reflected ? */ - if ((image->image_attr->attrmask & LO_ATTR_ON_IMAGE_LIST)) { - if (! blocked) { - /* Flush any image events that were sent when the image - was blocked */ - ET_SendImageEvent(context, image, LM_IMGUNBLOCK); - } - return; - } else { - /* Add image to global list of images for this document. */ - doc_lists = lo_GetDocListsById(doc_state, layer_id); - if (!doc_lists) - return; - - image->image_attr->attrmask |= LO_ATTR_ON_IMAGE_LIST; - image->seq_num = doc_lists->image_list_count++; - /* - * If we're in table relayout, we replace the old image - * in the image list. Note that we also look to see if - * the corresponding mocha object has already been allocated. - * If so, we copy it. If not, it will be set when the - * the JS thread gets around to it (the mocha reflection - * code gets the image by index, so it will get the right - * one. - */ - if (doc_state->in_relayout) { - LO_ImageStruct *cur_image, *prev_image; - prev_image = NULL; - - for (cur_image = doc_lists->image_list; cur_image != NULL; - prev_image=cur_image, cur_image=cur_image->next_image) { - if (cur_image->seq_num == image->seq_num) { - /* Copy over the mocha object (it might not exist) */ - image->mocha_object = cur_image->mocha_object; - - /* Replace the old image with the new one */ - image->next_image = cur_image->next_image; - if (prev_image == NULL) - doc_lists->image_list = image; - else - prev_image->next_image = image; - if (doc_lists->last_image == cur_image) - doc_lists->last_image = image; - /* Note that the old image is recycled by the table code */ - break; - } - } - return; - } - /* Add it to the end of the list */ - else { - if (doc_lists->last_image) - doc_lists->last_image->next_image = image; - else - doc_lists->image_list = image; - doc_lists->last_image = image; - } - } - - /* The image is reflected into a Javascript object lazily: - Immediate reflection only occurs if there are Javascript-only - attributes in the IMG tag */ - if(!PA_HasMocha(tag)) - return; - - ET_ReflectObject(context, (LO_Element *) image, tag, layer_id, - image->seq_num, LM_IMAGES); - - /* Since the image is unblocked, there is no need to buffer - any JavaScript image events. Deliver them as they're generated. */ - if (! blocked) - ET_SendImageEvent(context, image, LM_IMGUNBLOCK); - -} - -void -lo_ReflectFormElement(MWContext *context, lo_DocState *doc_state, PA_Tag *tag, - LO_FormElementStruct *form_element) -{ - lo_DocLists *doc_lists; - - /* Don't reflect form elements twice, it makes arrays out of them! */ - if (doc_state->in_relayout) - return; - - /* don't do squat if we don't have any mocha */ - if (!PA_HasMocha(tag)) - return; - - doc_lists = lo_GetDocListsById(doc_state, form_element->layer_id); - if (!doc_lists) - return; - - /* reflect the form element */ - ET_ReflectFormElement(context, doc_lists->form_list, form_element, tag); - -} - -void -lo_ReflectNamedAnchor(MWContext *context, lo_DocState *doc_state, PA_Tag *tag, - lo_NameList *name_rec, int32 layer_id) -{ - lo_DocLists *doc_lists; - - if (!doc_state->in_relayout) { - doc_lists = lo_GetDocListsById(doc_state, layer_id); - if (!doc_lists) - return; - name_rec->index = doc_lists->anchor_count++; - - if(!PA_HasMocha(tag)) - return; - - ET_ReflectObject(context, (void *) name_rec, tag, - layer_id, name_rec->index, LM_NAMEDANCHORS); - - } -} - - -lo_NameList * -LO_GetNamedAnchorByIndex(MWContext *context, int32 layer_id, uint index) -{ - lo_TopState *top_state; - lo_NameList *name_rec, *nptr; - lo_DocLists *doc_lists; - - top_state = lo_GetTopState(context); - if (top_state == NULL) - return NULL; - - doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id); - if (!doc_lists) - return NULL; - - /* The list is not guaranteed to be in reverse-source order when nested - tables are involved, so search for matching index instead. */ - name_rec = NULL; - for (nptr = doc_lists->name_list; nptr != NULL; nptr = nptr->next) { - if (nptr->index == index) { - name_rec = nptr; - break; - } - } - return name_rec; -} - -uint -LO_EnumerateNamedAnchors(MWContext *context, int32 layer_id) -{ - lo_TopState *top_state; - lo_NameList *name_rec; - uint count; - lo_DocLists *doc_lists; - - top_state = lo_GetTopState(context); - if (top_state == NULL) - return 0; - - doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id); - if (!doc_lists) - return 0; - - count = 0; - for (name_rec = doc_lists->name_list; name_rec != NULL; - name_rec = name_rec->next) { - if (name_rec->mocha_object == NULL) - LM_ReflectNamedAnchor(context, (void *) name_rec, NULL, - layer_id, name_rec->index); - count++; - } - return count; -} - -#ifdef DOM -void -lo_ReflectSpan(MWContext *context, lo_DocState *doc_state, PA_Tag *tag, - lo_NameList *name_rec, int32 layer_id) -{ - lo_DocLists *doc_lists; - - if (!doc_state->in_relayout) { - doc_lists = lo_GetDocListsById(doc_state, layer_id); - if (!doc_lists) - return; - name_rec->index = doc_lists->span_count++; - - if(!PA_HasMocha(tag)) - return; - - ET_ReflectObject(context, (void *) name_rec, tag, - layer_id, name_rec->index, LM_SPANS); - - } -} - -lo_NameList * -LO_GetSpanByIndex(MWContext *context, int32 layer_id, uint index) -{ - lo_TopState *top_state; - lo_NameList *name_rec, *nptr; - lo_DocLists *doc_lists; - - top_state = lo_GetTopState(context); - if (top_state == NULL) - return NULL; - - doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id); - if (!doc_lists) - return NULL; - - /* The list is not guaranteed to be in reverse-source order when nested - tables are involved, so search for matching index instead. */ - name_rec = NULL; - for (nptr = doc_lists->span_list; nptr != NULL; nptr = nptr->next) { - if (nptr->index == index) { - name_rec = nptr; - break; - } - } - return name_rec; -} - -uint -LO_EnumerateSpans(MWContext *context, int32 layer_id) -{ - lo_TopState *top_state; - lo_NameList *name_rec; - uint count; - lo_DocLists *doc_lists; - - top_state = lo_GetTopState(context); - if (top_state == NULL) - return 0; - - doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id); - if (!doc_lists) - return 0; - - count = 0; - for (name_rec = doc_lists->span_list; name_rec != NULL; - name_rec = name_rec->next) { - if (name_rec->mocha_object == NULL) - LM_ReflectSpan(context, (void *) name_rec, NULL, - layer_id, name_rec->index); - count++; - } - return count; -} -#endif - -void -lo_ReflectLink(MWContext *context, lo_DocState *doc_state, PA_Tag *tag, - LO_AnchorData *anchor_data, int32 layer_id, uint index) -{ - /* if this tag has any mocha, reflect it now */ - if(!PA_HasMocha(tag)) - return; - - ET_ReflectObject(context, anchor_data, tag, layer_id, index, LM_LINKS); -} - -LO_AnchorData * -LO_GetLinkByIndex(MWContext *context, int32 layer_id, uint index) -{ - lo_TopState *top_state; - LO_AnchorData **anchor_array; - LO_AnchorData *anchor_data; - lo_DocLists *doc_lists; - - top_state = lo_GetTopState(context); - if (top_state == NULL) - return NULL; - - doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id); - if (!doc_lists) - return NULL; - - if (index >= (uint)doc_lists->url_list_len) - return NULL; - - XP_LOCK_BLOCK(anchor_array, LO_AnchorData **, doc_lists->url_list); - anchor_data = anchor_array[index]; - XP_UNLOCK_BLOCK(doc_lists->url_list); - return anchor_data; -} - -uint -LO_EnumerateLinks(MWContext *context, int32 layer_id) -{ - lo_TopState *top_state; - uint count, index; - LO_AnchorData **anchor_array; - LO_AnchorData *anchor_data; - lo_DocLists *doc_lists; - - top_state = lo_GetMochaTopState(context); - if (top_state == NULL) - return 0; - - doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id); - if (!doc_lists) - return 0; - - /* Try to reflect all links in case someone is enumerating. */ - count = (uint)doc_lists->url_list_len; - XP_LOCK_BLOCK(anchor_array, LO_AnchorData **, doc_lists->url_list); - for (index = 0; index < count; index++) { - anchor_data = anchor_array[index]; - if (anchor_data->mocha_object == NULL) - LM_ReflectLink(context, anchor_data, NULL, layer_id, index); - } - XP_UNLOCK_BLOCK(doc_lists->url_list); - return count; -} - -#if defined(JAVA) || defined (OJI) -LO_JavaAppStruct * -LO_GetAppletByIndex(MWContext *context, int32 layer_id, uint index) -{ - lo_TopState *top_state; - LO_JavaAppStruct *applet; - int i, count; - lo_DocLists *doc_lists; - - -#ifdef OJI - if (!JVM_IsLiveConnectEnabled()) - return NULL; -#else - /* XXX */ - if (!JSJ_IsEnabled()) - return NULL; -#endif - - top_state = lo_GetTopState(context); - if (top_state == NULL) - return NULL; - - doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id); - if (!doc_lists) - return NULL; - - /* count 'em */ - count = 0; - applet = doc_lists->applet_list; - while (applet) { - applet = applet->nextApplet; - count++; - } - - /* reverse order... */ - applet = doc_lists->applet_list; - for (i = count-1; i >= 0; i--) { - if ((uint)i == index) - return applet; - applet = applet->nextApplet; - } - return NULL; -} - -uint -LO_EnumerateApplets(MWContext *context, int32 layer_id) -{ - lo_TopState *top_state; - int count, index; - LO_JavaAppStruct *applet; - lo_DocLists *doc_lists; - -#ifdef OJI - if (!JVM_IsLiveConnectEnabled()) - return 0; -#else - /* XXX */ - if (!JSJ_IsEnabled()) - return 0; -#endif - - - top_state = lo_GetMochaTopState(context); - if (top_state == NULL) - return 0; - - doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id); - if (!doc_lists) - return 0; - - /* count 'em */ - count = 0; - applet = doc_lists->applet_list; - while (applet) { - applet = applet->nextApplet; - count++; - } - - /* reflect all applets in reverse order */ - applet = doc_lists->applet_list; - for (index = count-1; index >= 0; index--) { - if (applet->objTag.mocha_object == NULL) - LM_ReflectApplet(context, (void *) applet, NULL, layer_id, index); - applet = applet->nextApplet; - } - - return count; -} - -LO_EmbedStruct * -LO_GetEmbedByIndex(MWContext *context, int32 layer_id, uint index) -{ - lo_TopState *top_state; - LO_EmbedStruct *embed; - int i, count; - lo_DocLists *doc_lists; - -#ifdef OJI - if (!JVM_IsLiveConnectEnabled()) - return NULL; -#else - /* XXX */ - if (!JSJ_IsEnabled()) - return NULL; -#endif - - - top_state = lo_GetTopState(context); - if (top_state == NULL) - return NULL; - - doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id); - if (!doc_lists) - return NULL; - - /* count 'em */ - count = 0; - embed = doc_lists->embed_list; - while (embed) { - embed = embed->nextEmbed; - count++; - } - - /* reverse order... */ - embed = doc_lists->embed_list; - for (i = count-1; i >= 0; i--) { - if ((uint)i == index) - return embed; - embed = embed->nextEmbed; - } - return NULL; -} - -uint -LO_EnumerateEmbeds(MWContext *context, int32 layer_id) -{ - lo_TopState *top_state; - int count, index; - LO_EmbedStruct *embed; - lo_DocLists *doc_lists; - -#ifdef OJI - if (!JVM_IsLiveConnectEnabled()) - return 0; -#else - /* XXX */ - if (!JSJ_IsEnabled()) - return 0; -#endif - - top_state = lo_GetMochaTopState(context); - if (top_state == NULL) - return 0; - - doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id); - if (!doc_lists) - return 0; - - /* count 'em */ - count = 0; - embed = doc_lists->embed_list; - while (embed) { - embed = embed->nextEmbed; - count++; - } - - /* reflect all embeds in reverse order */ - embed = doc_lists->embed_list; - for (index = count-1; index >= 0; index--) { - if (embed->objTag.mocha_object == NULL) - LM_ReflectEmbed(context, (void *) embed, NULL, layer_id, index); - embed = embed->nextEmbed; - } - - return count; -} -#endif /* JAVA || OJI */ - -LO_BuiltinStruct * -LO_GetBuiltinByIndex(MWContext *context, int32 layer_id, uint index) -{ - lo_TopState *top_state; - LO_BuiltinStruct *builtin; - int i, count; - lo_DocLists *doc_lists; - - top_state = lo_GetTopState(context); - if (top_state == NULL) - return NULL; - - doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id); - if (!doc_lists) - return NULL; - - /* count 'em */ - count = 0; - builtin = doc_lists->builtin_list; - while (builtin) { - builtin = builtin->nextBuiltin; - count++; - } - - /* reverse order... */ - builtin = doc_lists->builtin_list; - for (i = count-1; i >= 0; i--) { - if ((uint)i == index) - return builtin; - builtin = builtin->nextBuiltin; - } - return NULL; -} - - -/* XXX lo_DocState should use a colors[LO_NCOLORS] array to shrink code here - and in layout.c. - */ -void -LO_GetDocumentColor(MWContext *context, int type, LO_Color *color) -{ - lo_TopState *top_state; - lo_DocState *doc_state; - - top_state = lo_GetTopState(context); - if (top_state == NULL) - return; - doc_state = top_state->doc_state; - - switch (type) { - case LO_COLOR_BG: - *color = doc_state->text_bg; - break; - case LO_COLOR_FG: - *color = doc_state->text_fg; - break; - case LO_COLOR_LINK: - *color = doc_state->anchor_color; - break; - case LO_COLOR_VLINK: - *color = doc_state->visited_anchor_color; - break; - case LO_COLOR_ALINK: - *color = doc_state->active_anchor_color; - break; - default: - break; - } -} - -void -LO_SetDocumentColor(MWContext *context, int type, LO_Color *color) -{ - lo_TopState *top_state; - lo_DocState *doc_state; - - top_state = lo_GetTopState(context); - if (top_state == NULL) - return; - doc_state = top_state->doc_state; - if (color == NULL) - color = &lo_master_colors[type]; - - switch (type) { - case LO_COLOR_BG: - doc_state->text_bg = *color; - top_state->doc_specified_bg = TRUE; - LO_SetDocBgColor(context, color); - break; - case LO_COLOR_FG: - /* Note: The color will be changed only if no one else - has called this function before */ - lo_ChangeBodyTextFGColor(context, doc_state, color); - break; - case LO_COLOR_LINK: - doc_state->anchor_color = *color; - break; - case LO_COLOR_VLINK: - doc_state->visited_anchor_color = *color; - break; - case LO_COLOR_ALINK: - doc_state->active_anchor_color = *color; - break; - default:; - } -} - -XP_Bool -lo_ProcessContextEventHandlers(MWContext *context, lo_DocState *doc_state, - PA_Tag *tag) -{ - PA_Block onload, onunload, onfocus, onblur, onhelp, onmouseover, onmouseout, - ondragdrop, onmove, onresize, id; - lo_TopState *top_state; - char *all = 0; - XP_Bool ret; - - ret = FALSE; - onload = lo_FetchParamValue(context, tag, PARAM_ONLOAD); - onunload = lo_FetchParamValue(context, tag, PARAM_ONUNLOAD); - onfocus = lo_FetchParamValue(context, tag, PARAM_ONFOCUS); - onblur = lo_FetchParamValue(context, tag, PARAM_ONBLUR); - onhelp = lo_FetchParamValue(context, tag, PARAM_ONHELP); - onmouseover = lo_FetchParamValue(context, tag, PARAM_ONMOUSEOVER); - onmouseout = lo_FetchParamValue(context, tag, PARAM_ONMOUSEOUT); - ondragdrop = lo_FetchParamValue(context, tag, PARAM_ONDRAGDROP); - onmove = lo_FetchParamValue(context, tag, PARAM_ONMOVE); - onresize = lo_FetchParamValue(context, tag, PARAM_ONRESIZE); - - if (onload == NULL && onunload == NULL && onfocus == NULL && onblur == NULL - && onhelp == NULL && onmouseover == NULL && onmouseout == NULL && ondragdrop == NULL - && onmove == NULL && onresize == NULL) - { - return ret; - } - - ret = TRUE; - - id = lo_FetchParamValue(context, tag, PARAM_ID); - all = NULL; - StrAllocCopy(all, (char *) tag->data); - - top_state = doc_state->top_state; - - /* - * If we're in a layer, pass along the tag to the layer reflection - * function so that the event handlers get attached to the layer. - */ - if (lo_InsideLayer(doc_state)) { - int32 cur_layer_id = lo_CurrentLayerId(doc_state); - CL_Layer *layer = LO_GetLayerFromId(context, cur_layer_id); - CL_Layer *parent = CL_GetLayerParent(layer); - int32 parent_layer_id = LO_GetIdFromLayer(context, parent); - - ET_ReflectObject(context, NULL, tag, parent_layer_id, cur_layer_id, - LM_LAYERS); - } - else { - ET_ReflectWindow(context, onload, onunload, onfocus, onblur, onhelp, onmouseover, - onmouseout, ondragdrop, onmove, onresize, - id, all, tag->type != P_GRID, tag->newline_count); - - if (onload != NULL && tag->type == P_BODY) - top_state->mocha_has_onload = TRUE; - - if (onunload != NULL && tag->type == P_BODY) - top_state->mocha_has_onunload = TRUE; - - if (tag->type == P_GRID) { - top_state->savedData.OnUnload = onunload; - top_state->savedData.OnFocus = onfocus; - top_state->savedData.OnBlur = onblur; - top_state->savedData.OnLoad = onload; - top_state->savedData.OnHelp = onhelp; - top_state->savedData.OnMouseOver = onmouseover; - top_state->savedData.OnMouseOut = onmouseout; - top_state->savedData.OnDragDrop = ondragdrop; - top_state->savedData.OnMove = onmove; - top_state->savedData.OnResize = onresize; - } - } - return ret; -} - -void -lo_RestoreContextEventHandlers(MWContext *context, lo_DocState *doc_state, - PA_Tag *tag, SHIST_SavedData *saved_data) -{ - PA_Block onload, onunload, onfocus, onblur, onhelp, onmouseover, onmouseout, ondragdrop, - onmove, onresize; - lo_TopState *top_state; - - onload = saved_data->OnLoad; - onunload = saved_data->OnUnload; - onfocus = saved_data->OnFocus; - onblur = saved_data->OnBlur; - onhelp = saved_data->OnHelp; - onmouseover = saved_data->OnMouseOver; - onmouseout = saved_data->OnMouseOut; - ondragdrop = saved_data->OnDragDrop; - onmove = saved_data->OnMove; - onresize = saved_data->OnResize; - if (onload == NULL && onunload == NULL && onfocus == NULL && onblur == NULL - && onhelp == NULL && onmouseover == NULL && onmouseout == NULL && ondragdrop == NULL - && onmove == NULL && onresize == NULL) - return; - - top_state = doc_state->top_state; - - /* XXX - could these be signed? */ - ET_ReflectWindow(context, onload, onunload, onfocus, onblur, onhelp, onmouseover, - onmouseout, ondragdrop, onmove, onresize, - NULL, NULL, FALSE, tag->newline_count); - - if (onload != NULL && tag->type == P_BODY) - top_state->mocha_has_onload = TRUE; - - if (onunload != NULL && tag->type == P_BODY) - top_state->mocha_has_onunload = TRUE; - - top_state->savedData.OnUnload = onunload; - top_state->savedData.OnFocus = onfocus; - top_state->savedData.OnBlur = onblur; - top_state->savedData.OnLoad = onload; - top_state->savedData.OnHelp = onhelp; - top_state->savedData.OnMouseOver = onmouseover; - top_state->savedData.OnMouseOut = onmouseout; - top_state->savedData.OnDragDrop = ondragdrop; - top_state->savedData.OnMove = onmove; - top_state->savedData.OnResize = onresize; - -} - diff --git a/lib/layout/layout.c b/lib/layout/layout.c index 51cbc1345a6..e69de29bb2d 100644 --- a/lib/layout/layout.c +++ b/lib/layout/layout.c @@ -1,7861 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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. - */ - - -#include "xp.h" -#include "lo_ele.h" -#include "net.h" -#include "glhist.h" -#include "shist.h" -#include "merrors.h" -#include "layout.h" -#include "laylayer.h" -#include "layers.h" - -#define IL_CLIENT /* XXXM12N Defined by Image Library clients */ -#include "libimg.h" /* Image Library public API. */ - -#include "pa_parse.h" -#include "edt.h" -#include "libmocha.h" -#ifdef DOM -#include "lm_dom.h" -#endif -#include "libevent.h" -#include "laystyle.h" -#include "hk_funcs.h" -#include "pics.h" -#include "xp_ncent.h" -#include "prefetch.h" -#include "plvector.h" -#include "htrdf.h" - -#ifdef LAYPROBE_API -#include "layprobe.h" -#endif - - -/* WEBFONTS are defined only in laytags.c and layout.c */ -#define WEBFONTS - -#ifdef WEBFONTS -#include "nf.h" -#include "Mnffbu.h" -#endif /* WEBFONTS */ - -#ifdef HTML_CERTIFICATE_SUPPORT -#include "cert.h" -#endif - -#include "timing.h" - -#ifndef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#endif - -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 */ - - -#define DEF_LINE_HEIGHT 20 -#define URL_LIST_INC 20 -#define LINE_INC 100 - - -typedef struct lo_StateList_struct { - int32 doc_id; - lo_TopState *state; - struct lo_StateList_struct *next; -} lo_StateList; - -static lo_StateList *StateList = NULL; - -LO_Color lo_master_colors[] = { - {LO_DEFAULT_BG_RED, LO_DEFAULT_BG_GREEN, LO_DEFAULT_BG_BLUE}, - {LO_DEFAULT_FG_RED, LO_DEFAULT_FG_GREEN, LO_DEFAULT_FG_BLUE}, - {LO_UNVISITED_ANCHOR_RED, LO_UNVISITED_ANCHOR_GREEN, - LO_UNVISITED_ANCHOR_BLUE}, - {LO_VISITED_ANCHOR_RED, LO_VISITED_ANCHOR_GREEN, - LO_VISITED_ANCHOR_BLUE}, - {LO_SELECTED_ANCHOR_RED, LO_SELECTED_ANCHOR_GREEN, - LO_SELECTED_ANCHOR_BLUE} -}; -static char *Master_backdrop_url = NULL; -Bool UserOverride = FALSE; - -/********** BEGIN PROTOTYPES **************/ - -static void lo_process_deferred_image_info(void *closure); -static void lo_DisplayLine(MWContext *context, lo_DocState *state, int32 line_num, - int32 x, int32 y, uint32 w, uint32 h); -lo_SavedEmbedListData * lo_NewDocumentEmbedListData(void); -lo_SavedGridData * lo_NewDocumentGridData(void); -int32 lo_calc_push_right_for_justify(lo_DocState *state, int32 *remainder); -void lo_BodyMargins(MWContext *context, lo_DocState *state, PA_Tag *tag); -void lo_FinishLayout_OutOfMemory(MWContext *context, lo_DocState *state); -#ifdef MEMORY_ARENAS -void lo_GetRecycleList( - MWContext* context, int32 doc_id, pa_DocData* doc_data, - LO_Element* *recycle_list, lo_arena* *old_arena); -#else -void lo_GetRecycleList( - MWContext* context, int32 doc_id, pa_DocData* doc_data, - LO_Element* *recycle_list); -#endif /* MEMORY_ARENAS */ -intn lo_ProcessTag_OutOfMemory(MWContext* context, LO_Element* recycle_list, lo_TopState* top_state); -static void lo_FreeTagList( TagList *tags ); -/********** END PROTOTYPES **************/ - -void -LO_SetDefaultBackdrop(char *url) -{ - if ((url != NULL)&&(*url != '\0')) - { - Master_backdrop_url = XP_STRDUP(url); - } - else - { - Master_backdrop_url = NULL; - } -} - - -void -LO_SetUserOverride(Bool override) -{ - UserOverride = override; -} - - -void -LO_SetDefaultColor(intn type, uint8 red, uint8 green, uint8 blue) -{ - LO_Color *color; - - if (type < sizeof lo_master_colors / sizeof lo_master_colors[0]) - { - color = &lo_master_colors[type]; - color->red = red; - color->green = green; - color->blue = blue; - } -} - -Bool -lo_InitDocLists(MWContext *context, lo_DocLists *doc_lists) -{ - LO_AnchorData **anchor_array; - int32 i; - - doc_lists->embed_list = NULL; - doc_lists->embed_list_count = 0; -#ifdef notyet /* SHACK */ - doc_lists->builtin_list = NULL; - doc_lists->builtin_list_count = 0; -#endif /* SHACK */ - doc_lists->applet_list = NULL; - doc_lists->applet_list_count = 0; - - doc_lists->name_list = NULL; - doc_lists->image_list = doc_lists->last_image = NULL; - doc_lists->image_list_count = 0; - doc_lists->anchor_count = 0; - doc_lists->form_list = NULL; - doc_lists->current_form_num = 0; - - doc_lists->url_list = - XP_ALLOC_BLOCK(URL_LIST_INC * sizeof(LO_AnchorData *)); - if (doc_lists->url_list == NULL) - { - return(FALSE); - } - doc_lists->url_list_size = URL_LIST_INC; - /* url_list is a Handle of (LO_AnchorData*) so the pointer is a (LO_AnchorData**) */ - XP_LOCK_BLOCK(anchor_array, LO_AnchorData **, - doc_lists->url_list); - for (i=0; i < URL_LIST_INC; i++) - { - anchor_array[i] = NULL; - } - XP_UNLOCK_BLOCK(doc_lists->url_list); - doc_lists->url_list_len = 0; - -#ifdef XP_WIN16 - { - XP_Block *ulist_array; - - doc_lists->ulist_array = XP_ALLOC_BLOCK(sizeof(XP_Block)); - if (doc_lists->ulist_array == NULL) - { - XP_FREE_BLOCK(doc_lists->url_list); - return(FALSE); - } - XP_LOCK_BLOCK(ulist_array, XP_Block *, - doc_lists->ulist_array); - ulist_array[0] = doc_lists->url_list; - XP_UNLOCK_BLOCK(doc_lists->ulist_array); - doc_lists->ulist_array_size = 1; - } -#endif /* XP_WIN16 */ - - return TRUE; -} - - -lo_TopState * -lo_NewTopState(MWContext *context, char *url) -{ - lo_TopState *top_state; - char *name_target; - LO_TextAttr **text_attr_hash; - int32 i; - lo_LayerDocState *layer_state; - - top_state = XP_NEW_ZAP(lo_TopState); - if (top_state == NULL) - { - return(NULL); - } - -#ifdef MEMORY_ARENAS - if ( EDT_IS_EDITOR(context) ) { - top_state->current_arena = NULL; - } - else - { - lo_InitializeMemoryArena(top_state); - if (top_state->first_arena == NULL) - { - XP_DELETE(top_state); - return(NULL); - } - } -#endif /* MEMORY_ARENAS */ - - top_state->tags = NULL; - top_state->tags_end = &top_state->tags; - top_state->insecure_images = FALSE; - top_state->out_of_memory = FALSE; - top_state->force_reload = NET_DONT_RELOAD; - top_state->script_tag_count = 0; - top_state->script_lineno = 0; - top_state->in_script = SCRIPT_TYPE_NOT; - top_state->default_style_script_type = SCRIPT_TYPE_CSS; - top_state->resize_reload = FALSE; - top_state->version = JSVERSION_UNKNOWN; - top_state->scriptData = NULL; - top_state->doc_state = NULL; -#ifdef DOM - top_state->top_node = NULL; - top_state->current_node = NULL; - top_state->active_node = NULL; - top_state->style_db = NULL; -#endif - - if (url == NULL) - { - top_state->url = NULL; - } - else - { - top_state->url = XP_STRDUP(url); - } - top_state->base_url = NULL; - top_state->inline_stream_blocked_base_url = NULL; - top_state->main_stream_blocked_base_url = NULL; - top_state->base_target = NULL; - lo_SetBaseUrl(top_state, url, FALSE); - - /* - * This is the special named anchor we are jumping to in this - * document, it changes the starting display position. - */ - name_target = NET_ParseURL(top_state->url, GET_HASH_PART); - if ((name_target[0] != '#')||(name_target[1] == '\0')) - { - XP_FREE(name_target); - top_state->name_target = NULL; - } - else - { - top_state->name_target = name_target; - } - - top_state->element_id = 0; - top_state->layout_blocking_element = NULL; - top_state->current_script = NULL; - top_state->doc_specified_bg = FALSE; - top_state->nothing_displayed = TRUE; - top_state->in_head = TRUE; - top_state->in_body = FALSE; - top_state->body_attr = 0; - top_state->have_title = FALSE; - top_state->scrolling_doc = FALSE; - top_state->is_grid = FALSE; - top_state->ignore_tag_nest_level = 0; - top_state->ignore_layer_nest_level = 0; - top_state->in_applet = FALSE; - top_state->unknown_head_tag = NULL; - top_state->the_grid = NULL; - top_state->old_grid = NULL; - - top_state->map_list = NULL; - top_state->current_map = NULL; - - top_state->layers = NULL; - top_state->current_layer_num = -1; /* incremented on layer allocation */ - top_state->num_layers_allocated = 0; - top_state->max_layer_num = 0; - - layer_state = lo_NewLayerState(context); - if (!layer_state) { - XP_FREE_BLOCK(top_state); - return NULL; - } - if (context->compositor) - layer_state->layer = CL_GetCompositorRoot(context->compositor); - lo_append_to_layer_array(context, top_state, NULL, layer_state); - lo_PushLayerState(top_state, layer_state); - - top_state->in_form = FALSE; - top_state->savedData.FormList = NULL; - top_state->savedData.EmbedList = NULL; - top_state->savedData.Grid = NULL; - top_state->savedData.OnLoad = NULL; - top_state->savedData.OnUnload = NULL; - top_state->savedData.OnFocus = NULL; - top_state->savedData.OnBlur = NULL; - top_state->savedData.OnHelp = NULL; - top_state->savedData.OnMouseOver = NULL; - top_state->savedData.OnMouseOut = NULL; - top_state->savedData.OnDragDrop = NULL; - top_state->savedData.OnMove = NULL; - top_state->savedData.OnResize = NULL; - top_state->embed_count = 0; - - top_state->total_bytes = 0; - top_state->current_bytes = 0; - top_state->layout_bytes = 0; - top_state->script_bytes = 0; - top_state->layout_percent = 0; - - top_state->text_attr_hash = XP_ALLOC_BLOCK(FONT_HASH_SIZE * - sizeof(LO_TextAttr *)); - if (top_state->text_attr_hash == NULL) - { - XP_DELETE(top_state); - return(NULL); - } - XP_LOCK_BLOCK(text_attr_hash, LO_TextAttr **,top_state->text_attr_hash); - for (i=0; itext_attr_hash); - - top_state->font_face_array = NULL; - top_state->font_face_array_len = 0; - top_state->font_face_array_size = 0; - - if (!lo_InitDocLists(context, &top_state->doc_lists)) - { - XP_FREE_BLOCK(top_state->text_attr_hash); - XP_FREE_BLOCK(top_state); - return(NULL); - } - /* Document layer state keeps its doc_lists in the top_state */ - if ( layer_state->doc_lists ) - { - lo_DeleteDocLists(context, layer_state->doc_lists); - XP_FREE( layer_state->doc_lists ); - } - layer_state->doc_lists = &top_state->doc_lists; - - top_state->recycle_list = NULL; - top_state->trash = NULL; - - top_state->mocha_write_stream = NULL; - top_state->mocha_loading_applets_count = 0; - top_state->mocha_loading_embeds_count = 0; - top_state->mocha_has_onload = FALSE; - top_state->mocha_has_onunload = FALSE; - - top_state->doc_data = NULL; - for (i = 0; i < MAX_INPUT_WRITE_LEVEL; i++) - top_state->input_write_point[i] = NULL; - top_state->input_write_level = 0; - top_state->tag_from_inline_stream = FALSE; - -#ifdef HTML_CERTIFICATE_SUPPORT - top_state->cert_list = NULL; -#endif - - top_state->style_stack = SML_StyleStack_Factory_Create(); - if(!top_state->style_stack) - { - XP_FREE_BLOCK(top_state->text_attr_hash); - XP_FREE_BLOCK(top_state->doc_lists.url_list); - XP_DELETE(top_state); - return(NULL); - } - - STYLESTACK_Init(top_state->style_stack, context); - - top_state->diff_state = FALSE; - top_state->state_pushes = 0; - top_state->state_pops = 0; - - top_state->object_stack = NULL; - top_state->object_cache = NULL; - - top_state->tag_count = 0; - - top_state->flushing_blockage = FALSE; - top_state->wedged_on_mocha = FALSE; - top_state->in_cell_relayout = FALSE; /* Used for resize without reload stuff */ - top_state->metaTags = NULL; - top_state->LAPIprobe = NULL; - - return(top_state); -} - - -/************************************* - * Function: lo_PushStateLevel - * - * Description: Record that we're going one level further - * in the state hierarchy. - * - * Params: Window context. - *************************************/ -void -lo_PushStateLevel(MWContext *context) -{ - lo_TopState *top_state; - - top_state = lo_FetchTopState( XP_DOCID(context) ); - top_state->state_pushes++; - - /* - * If we've pushed back to our original state level, then we - * need to set a flag saying that we really have a new - * state record at the original level. We know this to - * be true as we've just added a new state record to the - * end of the list. - */ - if ( top_state->state_pushes == top_state->state_pops ) - { - top_state->diff_state = TRUE; - } -} - - -/************************************* - * Function: lo_PopStateLevel - * - * Description: Record that we've popped one level up - * in the state hierarchy. - * - * Params: Window context. - *************************************/ -void -lo_PopStateLevel(MWContext *context) -{ - lo_TopState *top_state; - - top_state = lo_FetchTopState( XP_DOCID(context) ); - top_state->state_pops++; -} - -/************************************* - * Function: lo_GetCurrentDocLists - * - * Description: Get the doc_lists for the - * "current" document i.e. from the top_state - * in the normal case, from the layer if a - * layer is being laid out. - * - * Params: DocState - *************************************/ -lo_DocLists * -lo_GetCurrentDocLists(lo_DocState *state) -{ - lo_LayerDocState *layer_state = lo_CurrentLayerState(state); - return layer_state->doc_lists; -} - -lo_DocLists * -lo_GetDocListsById(lo_DocState *state, int32 id) -{ - lo_LayerDocState *layer_state; - - if (id > state->top_state->max_layer_num) - return NULL; - - layer_state = state->top_state->layers[id]; - if (layer_state) { - XP_ASSERT(layer_state->doc_lists); - return layer_state->doc_lists; - } - else - return NULL; -} - -/************************************* - * Function: lo_NewLayout - * - * Description: This function creates and initializes a new - * layout state structure to be used for all state information - * about this document (or sub-document) during its lifetime. - * - * Params: Window context, - * the width and height of the - * window we are formatting to. - * - * Returns: A pointer to a lo_DocState structure. - * Returns a NULL on error (such as out of memory); - *************************************/ -lo_DocState * -lo_NewLayout(MWContext *context, int32 width, int32 height, - int32 margin_width, int32 margin_height, lo_DocState* clone_state ) -{ - lo_DocLists *doc_lists; - lo_TopState *top_state; - lo_DocState *state; -#ifdef XP_WIN16 - int32 i; - PA_Block *sblock_array; -#endif /* XP_WIN16 */ - int32 doc_id; - - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if (top_state == NULL) - { - return(NULL); - } - - state = XP_NEW_ZAP(lo_DocState); - if (state == NULL) - { - top_state->out_of_memory = TRUE; - return(NULL); - } - state->top_state = top_state; - - state->subdoc_tags = NULL; - state->subdoc_tags_end = NULL; - - if (top_state->doc_state) - doc_lists = lo_GetCurrentDocLists(top_state->doc_state); - else - doc_lists = lo_GetCurrentDocLists(state); - - if (!lo_InitDocState(state, context, - width, height, margin_width, margin_height, - clone_state, doc_lists, PR_FALSE)) - { - top_state->out_of_memory = TRUE; - XP_FREE(state); - return NULL; - } - return state; -} - - -lo_DocState * -lo_InitDocState(lo_DocState *state, MWContext *context, - int32 width, int32 height, - int32 margin_width, int32 margin_height, - lo_DocState* clone_state, - lo_DocLists *doc_lists, - PRBool is_for_new_layer) -{ - lo_TopState *top_state = state->top_state; - - /* - * Set colors early so default text is correct. - */ - - if( clone_state == NULL ){ - state->text_fg.red = lo_master_colors[LO_COLOR_FG].red; - state->text_fg.green = lo_master_colors[LO_COLOR_FG].green; - state->text_fg.blue = lo_master_colors[LO_COLOR_FG].blue; - - state->text_bg.red = lo_master_colors[LO_COLOR_BG].red; - state->text_bg.green = lo_master_colors[LO_COLOR_BG].green; - state->text_bg.blue = lo_master_colors[LO_COLOR_BG].blue; - - state->anchor_color.red = lo_master_colors[LO_COLOR_LINK].red; - state->anchor_color.green = lo_master_colors[LO_COLOR_LINK].green; - state->anchor_color.blue = lo_master_colors[LO_COLOR_LINK].blue; - - state->visited_anchor_color.red = lo_master_colors[LO_COLOR_VLINK].red; - state->visited_anchor_color.green = lo_master_colors[LO_COLOR_VLINK].green; - state->visited_anchor_color.blue = lo_master_colors[LO_COLOR_VLINK].blue; - - state->active_anchor_color.red = lo_master_colors[LO_COLOR_ALINK].red; - state->active_anchor_color.green = lo_master_colors[LO_COLOR_ALINK].green; - state->active_anchor_color.blue = lo_master_colors[LO_COLOR_ALINK].blue; - } - else - { - state->text_fg.red = clone_state->text_fg.red; - state->text_fg.green = clone_state->text_fg.green; - state->text_fg.blue = clone_state->text_fg.blue; - - state->text_bg.red = clone_state->text_bg.red; - state->text_bg.green = clone_state->text_bg.green; - state->text_bg.blue = clone_state->text_bg.blue; - - state->anchor_color.red = clone_state->anchor_color.red; - state->anchor_color.green = clone_state->anchor_color.green; - state->anchor_color.blue = clone_state->anchor_color.blue; - - state->visited_anchor_color.red = clone_state->visited_anchor_color.red; - state->visited_anchor_color.green = clone_state->visited_anchor_color.green; - state->visited_anchor_color.blue = clone_state->visited_anchor_color.blue; - - state->active_anchor_color.red = clone_state->active_anchor_color.red; - state->active_anchor_color.green = clone_state->active_anchor_color.green; - state->active_anchor_color.blue = clone_state->active_anchor_color.blue; - } - - 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; - - /* Layers don't use the line array, and resetting the line_num while laying out - a layer causes display bugs when displaying the _BODY layer. */ - if (!is_for_new_layer) - 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; - state->float_list = NULL; - - /* Don't bother creating a line array for a layer. Layers don't use them. */ - if (!is_for_new_layer) { - LO_Element **line_array; - - state->line_array = XP_ALLOC_BLOCK(LINE_INC * sizeof(LO_Element *)); - if (state->line_array == NULL) - { - return(NULL); - } - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array); - line_array[0] = NULL; - XP_UNLOCK_BLOCK(state->line_array); - state->line_array_size = LINE_INC; - -#ifdef XP_WIN16 - { - XP_Block *larray_array; - - state->larray_array = XP_ALLOC_BLOCK(sizeof(XP_Block)); - if (state->larray_array == NULL) - { - XP_FREE_BLOCK(state->line_array); - XP_DELETE(state); - return(NULL); - } - XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array); - larray_array[0] = state->line_array; - XP_UNLOCK_BLOCK(state->larray_array); - state->larray_array_size = 1; - } -#endif /* XP_WIN16 */ - } - - /* 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 (!is_for_new_layer || !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 /* XP_WIN16 */ - 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; - } - - 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); - } - - /* - * To initialize the default line height, we need to - * jump through hoops here to get the front end - * to tell us the default fonts line height. - */ - { - LO_TextStruct tmp_text; - unsigned char str[1]; - - memset (&tmp_text, 0, sizeof (tmp_text)); - str[0] = ' '; - tmp_text.text = (PA_Block)str; - tmp_text.text_len = 1; -#ifdef DOM - tmp_text.text_attr = lo_GetCurrentTextAttr(state, context); -#else - tmp_text.text_attr = state->font_stack->text_attr; -#endif - FE_GetTextInfo(context, &tmp_text, &(state->text_info)); - - state->default_line_height = state->text_info.ascent + - state->text_info.descent; - } - if (state->default_line_height <= 0) - { - state->default_line_height = FEUNITS_Y(DEF_LINE_HEIGHT,context); - } - - 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; - -#ifdef DOM - state->current_span = NULL; - state->in_span = FALSE; -#endif - - 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; - - if (!is_for_new_layer) - state->layer_nest_level = 0; - - /* - * These values are saved into the (sub)doc here - * so that if it gets Relayout() later, we know where - * to reset the from counts to. - */ - if (doc_lists->form_list != NULL) - { - lo_FormData *form_list; - - form_list = doc_lists->form_list; - state->form_ele_cnt = form_list->form_ele_cnt; - state->form_id = form_list->id; - } - else - { - state->form_ele_cnt = 0; - state->form_id = 0; - } - state->start_in_form = top_state->in_form; - if (top_state->savedData.FormList != NULL) - { - lo_SavedFormListData *all_form_ele; - - all_form_ele = top_state->savedData.FormList; - state->form_data_index = all_form_ele->data_index; - } - else - { - state->form_data_index = 0; - } - - /* - * Remember number of embeds we had before beginning this - * (sub)doc. This information is used in laytable.c so - * it can preserve embed indices across a relayout. - */ - state->embed_count_base = top_state->embed_count; - - /* - * Ditto for anchors, images, applets and embeds - */ - state->url_count_base = doc_lists->url_list_len; - state->image_list_count_base = doc_lists->image_list_count; - state->applet_list_count_base = doc_lists->applet_list_count; - state->embed_list_count_base = doc_lists->embed_list_count; - if (!is_for_new_layer) { - state->current_layer_num_base = top_state->current_layer_num; - state->current_layer_num_max = top_state->current_layer_num; - } - - 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; - - if (!is_for_new_layer) { - 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; - } - -#ifdef EDITOR - state->edit_force_offset = FALSE; - state->edit_current_element = 0; - state->edit_current_offset = 0; - state->edit_relayout_display_blocked = FALSE; -#endif - state->in_relayout = FALSE; - state->tab_stop = DEF_TAB_WIDTH; - state->beginning_tag_count = top_state->tag_count; - - state->cur_text_block = NULL; - state->need_min_width = FALSE; - - return(state); -} - -void LO_SetBackgroundImage( MWContext *context, char *pUrl ) -{ - lo_TopState* top_state; - - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - top_state = lo_FetchTopState(XP_DOCID(context)); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return; - } - if (!top_state->doc_layer) - return; - - top_state->doc_specified_bg = TRUE; - - LO_SetLayerBackdropURL(top_state->doc_layer, pUrl); -} - -static void -lo_load_user_backdrop(MWContext *context, lo_DocState *state) -{ - LO_SetBackgroundImage( context, Master_backdrop_url ); -} - -void -LO_SetDocBgColor(MWContext *context, LO_Color *rgb) -{ - lo_TopState* top_state; - - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - top_state = lo_FetchTopState(XP_DOCID(context)); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return; - } - - if (!top_state->doc_layer) - return; - -#ifdef XP_MAC - /* This allows the front end to set a background color for - this context only. Without this call, the color will - still be the one from the global table */ - FE_GetDefaultBackgroundColor(context, rgb); -#endif - if (context->compositor) - LO_SetLayerBgColor(top_state->doc_layer, rgb); -} - -int32 -lo_calc_push_right_for_justify(lo_DocState *state, int32 *remainder) -{ - int32 count = -1; /* start at -1 */ - int32 push_right; - LO_Element *tptr; - LO_Element *last=NULL; - - tptr = state->line_list; - - push_right = state->right_margin - state->x; - - if(push_right > (state->right_margin - state->left_margin)/4) - { - return 0; /* don't do justify if it's too large */ - } - - while (tptr != NULL) - { - if(tptr->type == LO_TEXT - && tptr->lo_text.text) - count++; - last = tptr; - tptr = tptr->lo_any.next; - } - - /* if the last element is a space character then - * this must be the last line of a paragraph. - * don't justify. - */ - if(last->type == LO_TEXT - && (*last).lo_text.text - && !XP_STRCMP((char*)last->lo_text.text, " ")) - return 0; - - /* the push_right is the number of pixels to add to - * each space - */ - - if(count > 0) - { - *remainder = push_right % count; - return push_right/count; - } - else - { - return 0; - } -} - -#ifndef DOM -PRIVATE void -lo_add_to_y_for_all_elements_in_line(lo_DocState *state, int32 y_add) -{ - LO_Element *tptr; - - if(!state) - return; - - tptr = state->line_list; - - while (tptr != NULL) - { - tptr->lo_any.y_offset += y_add; - - if (tptr->type == LO_CELL) - { - lo_ShiftCell((LO_CellStruct *)tptr, 0, y_add); - } - tptr = tptr->lo_any.next; - } -} -#endif - -void -lo_use_default_doc_background(MWContext *context, lo_DocState *state) -{ - lo_TopState *top_state = state->top_state; - if (top_state->doc_specified_bg == FALSE) { - if ((Master_backdrop_url != NULL) && - (UserOverride == FALSE || context->type == MWContextDialog)) { - lo_load_user_backdrop(context, state); - } else { - /* Force an opaque solid background. */ - LO_SetDocBgColor(context, &state->text_bg); - } - } -} - -/************************************* - * Function: lo_FlushLineList - * - * Description: This function adds a linefeed element to the end - * of the current line, and now that the line is done, it asks - * the front end to display the line. This function is only - * called by a hard linebreak. - * - * Params: Window context, document state, and flag for whether this is - * a breaking linefeed of not. A breaking linefeed is one inserted - * just to break a text flow to the current window width. - * - * Returns: Nothing - *************************************/ -void -lo_FlushLineList(MWContext *context, lo_DocState *state, uint32 break_type, uint32 clear_type, Bool breaking) -{ - - LO_LinefeedStruct *linefeed; - - lo_UpdateStateWhileFlushingLine( context, state ); - -#if 0 - /* apply line-height stack mods (if exists) */ - if(state->line_height_stack && state->end_last_line) - { - LO_LinefeedStruct *linefeed = (LO_LinefeedStruct*)state->end_last_line; - int32 cur_line_height; - int32 new_line_height; - int32 line_height_diff; - - if(state->line_height == 0) - { - int32 new_height = state->text_info.ascent + - state->text_info.descent; - int32 new_baseline = state->text_info.ascent; - - if ((new_height <= 0)&&(state->font_stack != NULL)&& - (state->font_stack->text_attr != NULL)) - { - lo_fillin_text_info(context, state); - - new_height = state->text_info.ascent + state->text_info.descent; - new_baseline = state->text_info.ascent; - - } - - if(new_height <= 0) - { - new_height = state->default_line_height; - new_baseline = state->default_line_height; - } - - state->line_height = new_height; - state->baseline = new_baseline; - } - - cur_line_height = (state->y + state->baseline) - - (linefeed->y + linefeed->baseline); - - new_line_height = state->line_height_stack->height; - line_height_diff = new_line_height - cur_line_height; - - /* only allow increasing line heights - * explicitly disallow negative diffs - */ - if(line_height_diff > 0) - { - lo_add_to_y_for_all_elements_in_line(state, line_height_diff); - - state->baseline += line_height_diff; - state->line_height += line_height_diff; - } - } -#endif - - - /* - * Tack a linefeed element on to the end of the line list. - * Take advantage of this necessary pass thorugh the line's - * elements to set the line_height field in all - * elements, and to look and see if we have reached a - * possibly display blocking element. - */ - linefeed = lo_NewLinefeed(state, context, break_type, clear_type); - - if (linefeed != NULL) - { - lo_AppendLineFeed( context, state, linefeed, breaking, TRUE ); - } - else - { - return; /* ALEKS OUT OF MEMORY RETURN */ - } - - /* - * Nothing to flush - */ - if (state->line_list == NULL) - { - return; - } - - lo_UpdateStateAfterFlushingLine( context, state, linefeed, FALSE ); -} - - -/************************************* - * Function: lo_CleanTextWhitespace - * - * Description: Utility function to pass through a line an clean up - * all its whitespace. Compress multiple whitespace between - * element to a single space, and remove heading and - * trailing whitespace. - * Text is cleaned in place in the passed buffer. - * - * Params: Pointer to text to be cleand, and its length. - * - * Returns: Length of cleaned text. - *************************************/ -int32 -lo_CleanTextWhitespace(char *text, int32 text_len) -{ - char *from_ptr; - char *to_ptr; - int32 len; - int32 new_len; - - if (text == NULL) - { - return(0); - } - - len = 0; - new_len = 0; - from_ptr = text; - to_ptr = text; - - while (len < text_len) - { - /* - * Compress chunk of whitespace - */ - while ((len < text_len)&&(XP_IS_SPACE(*from_ptr))) - { - len++; - from_ptr++; - } - if (len == text_len) - { - continue; - } - - /* - * Skip past "good" text - */ - while ((len < text_len)&&(!XP_IS_SPACE(*from_ptr))) - { - *to_ptr++ = *from_ptr++; - len++; - new_len++; - } - - /* - * Put in one space to represent the compressed spaces. - */ - if (len != text_len) - { - *to_ptr++ = ' '; - new_len++; - } - } - - /* - * Remove the trailing space, and terminate string. - */ - if ((new_len > 0)&&(*(to_ptr - 1) == ' ')) - { - to_ptr--; - new_len--; - } - *to_ptr = '\0'; - - return(new_len); -} - - -/* - * Used to strip white space off of HREF parameter values to make - * valid URLs out of them. Remove whitespace from both ends, and - * remove all non-space whitespace from the middle. - */ -int32 -lo_StripTextWhitespace(char *text, int32 text_len) -{ - char *from_ptr; - char *to_ptr; - int32 len; - int32 tail; - - if ((text == NULL)||(text_len < 1)) - { - return(0); - } - - len = 0; - from_ptr = text; - /* - * strip leading whitespace - */ - while ((len < text_len)&&(XP_IS_SPACE(*from_ptr))) - { - len++; - from_ptr++; - } - - if (len == text_len) - { - *text = '\0'; - return(0); - } - - tail = 0; - from_ptr = (char *)(text + text_len - 1); - /* - * Remove any trailing space - */ - while (XP_IS_SPACE(*from_ptr)) - { - from_ptr--; - tail++; - } - - /* - * terminate string - */ - from_ptr++; - *from_ptr = '\0'; - - /* - * remove all non-space whitespace from the middle of the string. - */ - from_ptr = (char *)(text + len); - len = text_len - len - tail; - to_ptr = text; - while (*from_ptr != '\0') - { - if (XP_IS_SPACE(*from_ptr) && (*from_ptr != ' ')) - { - from_ptr++; - len--; - } - else - { - *to_ptr++ = *from_ptr++; - } - } - *to_ptr = '\0'; - - return(len); -} - - -LO_AnchorData * -lo_NewAnchor(lo_DocState *state, PA_Block href, PA_Block targ) -{ - LO_AnchorData *anchor_data; - lo_LayerDocState *layer_state; - - anchor_data = XP_NEW_ZAP(LO_AnchorData); - if (anchor_data) - { - anchor_data->anchor = href; - anchor_data->target = targ; -#ifdef DOM - /* - * XXX What if we create anchors out of order? I guess the - * lo_CurrentLayerState call below means that we can't. - */ - anchor_data->node = ACTIVE_NODE(state); /* CURRENT_NODE? */ -#endif - layer_state = lo_CurrentLayerState(state); - if (layer_state ) - anchor_data->layer = layer_state->layer; - } - else - { - state->top_state->out_of_memory = TRUE; - } - return anchor_data; -} - - -void -lo_DestroyAnchor(LO_AnchorData *anchor_data) -{ - if (anchor_data->anchor != NULL) - { - PA_FREE(anchor_data->anchor); - } - if (anchor_data->target != NULL) - { - PA_FREE(anchor_data->target); - } - XP_DELETE(anchor_data); -} - - -/* - * Add this url's block to the list - * of all allocated urls so we can free - * it later. - */ -void -lo_AddToUrlList(MWContext *context, lo_DocState *state, - LO_AnchorData *url_buff) -{ - lo_TopState *top_state; - int32 i; - LO_AnchorData **anchor_array; - intn a_url; -#ifdef XP_WIN16 - intn a_size; - intn a_indx; - XP_Block *ulist_array; -#endif /* XP_WIN16 */ - lo_DocLists *doc_lists; - - doc_lists = lo_GetCurrentDocLists(state); - - /* - * Error checking - */ - if ((url_buff == NULL)||(state == NULL)) - { - return; - } - - top_state = state->top_state; - - /* - * We may need to grow the url_list. - */ -#ifdef XP_WIN16 - a_size = SIZE_LIMIT / sizeof(XP_Block *); - a_indx = doc_lists->url_list_len / a_size; - a_url = doc_lists->url_list_len - (a_indx * a_size); - - XP_LOCK_BLOCK(ulist_array, XP_Block *, doc_lists->ulist_array); - - - if ((a_url == 0)&&(a_indx > 0)) - { - doc_lists->url_list = XP_ALLOC_BLOCK(URL_LIST_INC * - sizeof(LO_AnchorData *)); - if (doc_lists->url_list == NULL) - { - XP_UNLOCK_BLOCK(doc_lists->ulist_array); - top_state->out_of_memory = TRUE; - return; - } - doc_lists->url_list_size = URL_LIST_INC; - XP_LOCK_BLOCK(anchor_array, LO_AnchorData **, - doc_lists->url_list); - for (i=0; i < URL_LIST_INC; i++) - { - anchor_array[i] = NULL; - } - XP_UNLOCK_BLOCK(doc_lists->url_list); - - doc_lists->ulist_array_size++; - XP_UNLOCK_BLOCK(doc_lists->ulist_array); - doc_lists->ulist_array = XP_REALLOC_BLOCK( - doc_lists->ulist_array, (doc_lists->ulist_array_size - * sizeof(XP_Block))); - if (doc_lists->ulist_array == NULL) - { - top_state->out_of_memory = TRUE; - return; - } - XP_LOCK_BLOCK(ulist_array, XP_Block *, doc_lists->ulist_array); - ulist_array[doc_lists->ulist_array_size - 1] = doc_lists->url_list; - doc_lists->url_list = ulist_array[a_indx]; - } - else if (a_url >= doc_lists->url_list_size) - { - int32 url_list_inc; - - if ((doc_lists->url_list_size / 10) > URL_LIST_INC) - { - url_list_inc = doc_lists->url_list_size / 10; - } - else - { - url_list_inc = URL_LIST_INC; - } - doc_lists->url_list_size += (intn)url_list_inc; - if (doc_lists->url_list_size > a_size) - { - doc_lists->url_list_size = a_size; - } - - doc_lists->url_list = ulist_array[a_indx]; - doc_lists->url_list = XP_REALLOC_BLOCK(doc_lists->url_list, - (doc_lists->url_list_size * sizeof(LO_AnchorData *))); - if (doc_lists->url_list == NULL) - { - XP_UNLOCK_BLOCK(doc_lists->ulist_array); - top_state->out_of_memory = TRUE; - return; - } - ulist_array[a_indx] = doc_lists->url_list; - /* - * Clear the new entries - */ - XP_LOCK_BLOCK(anchor_array, LO_AnchorData **, - doc_lists->url_list); - for (i = doc_lists->url_list_len; i < doc_lists->url_list_size; i++) - { - anchor_array[i] = NULL; - } - XP_UNLOCK_BLOCK(doc_lists->url_list); - } - doc_lists->url_list = ulist_array[a_indx]; -#else - if (doc_lists->url_list_len == - doc_lists->url_list_size) - { - int32 url_list_inc; - - if ((doc_lists->url_list_size / 10) > URL_LIST_INC) - { - url_list_inc = doc_lists->url_list_size / 10; - } - else - { - url_list_inc = URL_LIST_INC; - } - doc_lists->url_list_size += url_list_inc; - doc_lists->url_list = XP_REALLOC_BLOCK(doc_lists->url_list, - (doc_lists->url_list_size * - sizeof(LO_AnchorData *))); - if (doc_lists->url_list == NULL) - { - top_state->out_of_memory = TRUE; - return; - } - - /* - * Clear the new entries - */ - XP_LOCK_BLOCK(anchor_array, LO_AnchorData **, doc_lists->url_list); - for (i = doc_lists->url_list_len; i < doc_lists->url_list_size; i++) - { - anchor_array[i] = NULL; - } - XP_UNLOCK_BLOCK(doc_lists->url_list); - } - a_url = doc_lists->url_list_len; -#endif /* XP_WIN16 */ - - XP_LOCK_BLOCK(anchor_array, LO_AnchorData **, doc_lists->url_list); - if (anchor_array[a_url] != NULL) - { - lo_DestroyAnchor(anchor_array[a_url]); - } - anchor_array[a_url] = url_buff; - doc_lists->url_list_len++; - XP_UNLOCK_BLOCK(doc_lists->url_list); -} - - -void -lo_BodyMargins(MWContext *context, lo_DocState *state, PA_Tag *tag) -{ - PA_Block buff; - char *str; - int32 margin_width; - int32 margin_height; - Bool changes; - - margin_width = state->win_left; - margin_height = state->win_top; - changes = FALSE; - - /* - * Get the margin width. - */ - buff = lo_FetchParamValue(context, tag, PARAM_MARGINWIDTH); - if (buff != NULL) - { - int32 val; - - PA_LOCK(str, char *, buff); - val = XP_ATOI(str); - if (val < 0) - { - val = 0; - } - margin_width = val; - PA_UNLOCK(buff); - PA_FREE(buff); - margin_width = FEUNITS_X(margin_width, context); - /* - * Sanify based on window width. - */ - if (margin_width > ((state->win_width / 2) - 1)) - { - margin_width = ((state->win_width / 2) - 1); - } - state->top_state->body_attr |= BODY_ATTR_MARGINS; - changes = TRUE; - } - - /* - * Get the margin height. - */ - buff = lo_FetchParamValue(context, tag, PARAM_MARGINHEIGHT); - if (buff != NULL) - { - int32 val; - - PA_LOCK(str, char *, buff); - val = XP_ATOI(str); - if (val < 0) - { - val = 0; - } - margin_height = val; - PA_UNLOCK(buff); - PA_FREE(buff); - margin_height = FEUNITS_Y(margin_height, context); - /* - * Sanify based on window height. - */ - if (margin_height > ((state->win_height / 2) - 1)) - { - margin_height = ((state->win_height / 2) - 1); - } - state->top_state->body_attr |= BODY_ATTR_MARGINS; - changes = TRUE; - } - - if (changes != FALSE) - { - state->win_top = margin_height; - state->win_bottom = margin_height; - - 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->break_holder = state->x; - - /* - * Need to reset the margin values in the default list stack - */ - if ((state->list_stack->type == P_UNKNOWN)&& - (state->list_stack->next == NULL)) - { - state->list_stack->old_left_margin = state->win_left; - state->list_stack->old_right_margin = - state->win_width - state->win_right; - } - else - { - /* - * This should never happen. If it doesm it means we somehow - * started a list without knowing that we had entered the BODY - * of the document. - */ - } - } -} - - -void -lo_ProcessBodyTag(MWContext *context, lo_DocState *state, PA_Tag *tag) -{ - if (tag->is_end == FALSE) - { - if ((state->end_last_line == NULL)&& - ((state->top_state->body_attr & BODY_ATTR_MARGINS) == 0)) - { - lo_BodyMargins(context, state, tag); - } - if (UserOverride == FALSE || context->type == MWContextDialog) - { - lo_BodyBackground(context, state, tag, FALSE); - } - if (( !EDT_IS_EDITOR( context ) )&& - ((state->top_state->body_attr & BODY_ATTR_JAVA) == 0)) - { - if (lo_ProcessContextEventHandlers(context, state, tag)) - { - state->top_state->body_attr |= BODY_ATTR_JAVA; - } - } - } -} - -void -lo_SetBaseUrl(lo_TopState *top_state, char *url, Bool is_blocked) -{ - if (url) - url = XP_STRDUP(url); - - if (is_blocked) - { - if (top_state->tag_from_inline_stream) - { - XP_FREEIF(top_state->inline_stream_blocked_base_url); - top_state->inline_stream_blocked_base_url = url; - } - else - { - XP_FREEIF(top_state->main_stream_blocked_base_url); - top_state->main_stream_blocked_base_url = url; - } - } - else - { - XP_FREEIF(top_state->base_url); - top_state->base_url = url; - } -} - -/************************************* - * Function: lo_BlockTag - * - * Description: This function blocks the layout of the tag, and - * saves them in the context. - * - * Params: Window context and document state, and the tag to be blocked. - * - * Returns: Nothing - *************************************/ -void -lo_BlockTag(MWContext *context, lo_DocState *state, PA_Tag *tag) -{ - PA_Tag ***tags_end_ptr, **tags_end; /* triple-indirect, wow! see below */ - int32 doc_id; - lo_TopState *top_state; - lo_DocState *new_state; - char *save_base=NULL; - - /* - * All blocked tags should be at the top level of state - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return; - } - state = top_state->doc_state; - - new_state = lo_CurrentSubState(state); - - if (top_state->tags == NULL) - PA_HoldDocData(top_state->doc_data); - - /* - * For everything except BASE tags, we need to use - * the blocked base here as our real base so that - * relative URLs are processed properly. - */ - if (tag->type != P_BASE) - { - save_base = top_state->base_url; - if (top_state->tag_from_inline_stream) - { - if (top_state->inline_stream_blocked_base_url) - top_state->base_url = top_state->inline_stream_blocked_base_url; - } - else - { - if (top_state->main_stream_blocked_base_url) - top_state->base_url = top_state->main_stream_blocked_base_url; - } - } - - switch (tag->type) - { - /* - * We need to process these when blocked so that - * relative URLs of images that are processed when - * blocked are correct. - */ - case P_BASE: - { - PA_Block buff; - char *url; - - buff = lo_FetchParamValue(context, tag, - PARAM_HREF); - if (buff != NULL) - { - PA_LOCK(url, char *, buff); - if (url != NULL) - { - int32 len; - - len = lo_StripTextWhitespace( - url, XP_STRLEN(url)); - } - lo_SetBaseUrl(top_state, url, TRUE); - PA_UNLOCK(buff); - PA_FREE(buff); - } - } - break; - case P_IMAGE: - case P_NEW_IMAGE: - if (tag->is_end == FALSE) - { - /* - * For images that are part of the main document, we - * can use the doc_data's url as the base URL. For - * images that are part of a LAYER that has a SRC - * attribute, we use the top_state's version (the base_url - * is temporarily changed to that of the LAYER while - * we process tags within the layer). The input_write_level - * tells us whether the tag is part of the main document - * or the layer. - */ - lo_BlockedImageLayout(context, new_state, tag, - top_state->base_url); - } - break; - case P_SCRIPT: - case P_STYLE: - case P_LINK: - lo_BlockScriptTag(context, new_state, tag); - break; - case P_LAYER: - lo_BlockLayerTag(context, new_state, tag); - break; - case P_PARAM: - lo_ProcessParamTag(context, new_state, tag, TRUE); - break; - case P_OBJECT: - lo_ProcessObjectTag(context, new_state, tag, TRUE); - break; - } - /* - * Now restore the base that you switched if it - * wasn't a BASE tag. - */ - if (tag->type != P_BASE) - { - top_state->base_url = save_base; - } - - /* - * Unify the basis and induction cases of singly-linked list insert - * using a double-indirect pointer. Instead of - * - * if (head == NULL) - * head = tail = elem; - * else - * tail = tail->next = elem; - * - * where head = tail = NULL is the empty state and elem->next = NULL, - * use a pointer to the pointer to the last element: - * - * *tail_ptr = elem; - * tail_ptr = &elem->next; - * - * where head = NULL, tail_ptr = &head is the empty state. - * - * The triple-indirection below is to avoid further splitting cases - * based on whether we're inserting at the input_write_point or - * at the end of the tags list. The - * 'if (top_state->input_write_level)' test is unavoidable, but - * once the tags_end_ptr variable is set to point at the right - * double-indirect "tail_ptr" (per above sketch), there is shared code. - */ - - if (top_state->input_write_level) - { - tags_end_ptr = &top_state->input_write_point[top_state->input_write_level-1]; - if (*tags_end_ptr == NULL) - { - *tags_end_ptr = top_state->tags_end; - } - if (top_state->tags_end == *tags_end_ptr) - { - *tags_end_ptr = &tag->next; - tags_end_ptr = &top_state->tags_end; - } - } - else - { - tags_end_ptr = &top_state->tags_end; - } - tags_end = *tags_end_ptr; - tag->next = *tags_end; - *tags_end = tag; - *tags_end_ptr = &tag->next; -} - - -lo_DocState * -lo_TopSubState(lo_TopState *top_state) -{ - lo_DocState *new_state; - - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return(NULL); - } - - new_state = top_state->doc_state; - while (new_state->sub_state != NULL) - { - new_state = new_state->sub_state; - } - - return(new_state); -} - - -lo_DocState * -lo_CurrentSubState(lo_DocState *state) -{ - lo_DocState *new_state; - - if (state == NULL) - { - return(NULL); - } - - new_state = state; - while (new_state->sub_state != NULL) - { - new_state = new_state->sub_state; - } - - return(new_state); -} - - -/************************************* - * Function: lo_FetchTopState - * - * Description: This function uses the document ID to locate the - * lo_TopState structure for this document. - * Eventually this state will be kept somewhere in the - * Window context. - * - * Params: A unique document ID as derived from the window context. - * - * Returns: A pointer to the lo_TopState structure for this document. - * NULL on error. - *************************************/ -lo_TopState * -lo_FetchTopState(int32 doc_id) -{ - lo_StateList *sptr; - lo_TopState *state; - - sptr = StateList; - while (sptr != NULL) - { - if (sptr->doc_id == doc_id) - { - break; - } - sptr = sptr->next; - } - if (sptr == NULL) - { - state = NULL; - } - else - { - state = sptr->state; - } - - return(state); -} - - -static void -lo_RemoveTopState(int32 doc_id) -{ - lo_StateList *state; - lo_StateList *sptr; - - state = StateList; - sptr = StateList; - while (sptr != NULL) - { - if (sptr->doc_id == doc_id) - { - break; - } - state = sptr; - sptr = sptr->next; - } - if (sptr != NULL) - { - if (sptr == StateList) - { - StateList = StateList->next; - } - else - { - state->next = sptr->next; - } - XP_DELETE(sptr); - } -} - - -Bool -lo_StoreTopState(int32 doc_id, lo_TopState *new_state) -{ - lo_StateList *sptr; - - sptr = StateList; - while (sptr != NULL) - { - if (sptr->doc_id == doc_id) - { - break; - } - sptr = sptr->next; - } - - if (sptr == NULL) - { - sptr = XP_NEW(lo_StateList); - if (sptr == NULL) - { - return FALSE; - } - sptr->doc_id = doc_id; - sptr->next = StateList; - StateList = sptr; - } - sptr->state = new_state; - return TRUE; -} - - -void -lo_SaveSubdocTags(MWContext *context, lo_DocState *state, PA_Tag *tag) -{ - PA_Tag *tag_ptr; - - tag->next = NULL; - - if (state->subdoc_tags_end == NULL) - { - if (state->subdoc_tags == NULL) - { - state->subdoc_tags = tag; - state->subdoc_tags_end = tag; - } - else - { - state->subdoc_tags->next = tag; - state->subdoc_tags = tag; - state->subdoc_tags_end = tag; - } - } - else - { - tag_ptr = state->subdoc_tags_end; - tag_ptr->next = tag; - state->subdoc_tags_end = tag; - } -} - - - -void -lo_FlushBlockage(MWContext *context, lo_DocState *state, - lo_DocState *main_doc_state) -{ - PA_Tag *tag_ptr; - int32 doc_id; - lo_TopState *top_state; - lo_DocState *orig_state; - lo_DocState *up_state; - Bool was_blockage; - - /* - * All blocked tags should be at the top level of state - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return; - } - /* Prevent re-entering */ - if (top_state->flushing_blockage) - return; - top_state->flushing_blockage = TRUE; - - was_blockage = (top_state->tags != NULL); - tag_ptr = top_state->tags; - - orig_state = top_state->doc_state; - - up_state = NULL; - state = orig_state; - while (state->sub_state != NULL) - { - up_state = state; - state = state->sub_state; - } - - top_state->layout_blocking_element = NULL; - - while ((tag_ptr != NULL)&&(top_state->layout_blocking_element == NULL)) - { - PA_Tag *tag; - lo_DocState *new_state; - lo_DocState *new_up_state; - lo_DocState *tmp_state; - Bool may_save; - int32 state_diff; - - tag = tag_ptr; - tag_ptr = tag_ptr->next; - tag->next = NULL; - - /* - * Always keep top_state->tags sane - */ - top_state->tags = tag_ptr; - if (tag_ptr == NULL) - { - top_state->tags_end = &top_state->tags; - } - - /* - * Since script processing is asynchronous we need to do this - * whenever we flush blockage - */ - if (lo_FilterTag(context, state, tag) == FALSE) - { - PA_FreeTag(tag); - continue; - } - - if ((state->is_a_subdoc == SUBDOC_CELL)|| - (state->is_a_subdoc == SUBDOC_CAPTION)) - { - may_save = TRUE; - } - else - { - may_save = FALSE; - } - - /* - * Reset these so we can tell if anything happened - */ - top_state->diff_state = FALSE; - top_state->state_pushes = 0; - top_state->state_pops = 0; - - if (state->top_state->out_of_memory == FALSE) - { - lo_LayoutTag(context, state, tag); - if (tag->type == P_LAYER) - { - lo_UnblockLayerTag(state); - } - if(top_state->wedged_on_mocha) { - top_state->wedged_on_mocha = FALSE; - goto done; - } - } - - /* how has our state level changed? */ - state_diff = top_state->state_pushes - top_state->state_pops; - - new_up_state = NULL; - new_state = orig_state; - while (new_state->sub_state != NULL) - { - new_up_state = new_state; - new_state = new_state->sub_state; - } - tmp_state = new_state; - if (may_save != FALSE) - { - if (state_diff == -1) - { - /* - * That tag popped us up one state level. If this new - * state is still a subdoc, save the tag there. - */ - if ((tmp_state->is_a_subdoc == SUBDOC_CELL)|| - (tmp_state->is_a_subdoc == SUBDOC_CAPTION)) - { - - /* if we just popped a table we need to insert - * a dummy end tag to pop the dummy start tag - * we shove on the stack after createing a table - */ - PA_Tag *new_tag = LO_CreateStyleSheetDummyTag(tag); - if(new_tag) - { - lo_SaveSubdocTags(context, tmp_state, new_tag); - } - - lo_SaveSubdocTags(context, tmp_state, tag); - } - else - { - PA_FreeTag(tag); - } - } - else if (( up_state != NULL ) && - ( top_state->diff_state != FALSE ) && - ( state_diff == 0 )) - { - /* - * We have returned to the same state level but - * we have a different subdoc. - */ - if ((up_state->is_a_subdoc == SUBDOC_CELL)|| - (up_state->is_a_subdoc == SUBDOC_CAPTION)) - { - lo_SaveSubdocTags(context, up_state, tag); - } - else - { - PA_FreeTag(tag); - } - } - else if (( top_state->diff_state == FALSE ) && - ( state_diff == 0 )) - { - /* - * We are still in the same subdoc - */ - lo_SaveSubdocTags(context, state, tag); - } - else if (( state_diff == 1 )) - { - PA_Tag *new_tag; - - /* - * That tag started a new, nested subdoc. - * Add the starting tag to the parent. - */ - lo_SaveSubdocTags(context, state, tag); - /* - * Since we have extended the parent chain, - * we need to reset the child to the new - * parent end-chain. - */ - if ((tmp_state->is_a_subdoc == SUBDOC_CELL)|| - (tmp_state->is_a_subdoc == SUBDOC_CAPTION)) - { - tmp_state->subdoc_tags = - state->subdoc_tags_end; - - /* add an aditional dummy tag so that style sheets - * can use it to query styles from for this entry - * that created a table - */ - new_tag = LO_CreateStyleSheetDummyTag(tag); - if(new_tag) - { - lo_SaveSubdocTags(context, tmp_state, new_tag); - } - } - - } - /* - * This can never happen. - */ - else - { - PA_FreeTag(tag); - } - } - else - { - if(state_diff == 1) - { - /* everytime a table is started we need to save the - * tag that created it so that style sheets can apply - * styles to it. So we will save even in the "dont save" - * case - */ - PA_Tag *new_tag = LO_CreateStyleSheetDummyTag(tag); - if(new_tag) - { - /* We just pushed another table into a previous table - * we need to do some table magic to make the subdoc - * list work right - */ - lo_SaveSubdocTags(context, tmp_state, new_tag); - } - } - else if(state_diff == -1) - { - /* if we just popped a table we need to insert - * a dummy end tag to pop the dummy start tag - * we shove on the stack after createing a table - */ - PA_Tag *new_tag = LO_CreateStyleSheetDummyTag(tag); - if(new_tag) - { - lo_SaveSubdocTags(context, tmp_state, new_tag); - } - - lo_SaveSubdocTags(context, tmp_state, tag); - - } - PA_FreeTag(tag); - } - tag_ptr = top_state->tags; - state = new_state; - up_state = new_up_state; - } - - if (tag_ptr != NULL) - { - top_state->tags = tag_ptr; - } - else - { - int i; - top_state->tags = NULL; - top_state->tags_end = &top_state->tags; - for (i = 0; i < MAX_INPUT_WRITE_LEVEL; i++) - top_state->input_write_point[i] = NULL; - if (was_blockage) { - NET_StreamClass s; - s.data_object=(pa_DocData *)top_state->doc_data; - top_state->doc_data = PA_DropDocData(&s); - } - } - - if ((top_state->layout_blocking_element == NULL)&& - (top_state->tags == NULL)&& - (top_state->layout_status == PA_COMPLETE) && - !top_state->finished) - { - /* - * makes sure we are at the bottom - * of everything in the document. - */ - state = lo_CurrentSubState(main_doc_state); - lo_CloseOutLayout(context, state); - lo_FinishLayout(context, state, EVENT_LOAD); - } -done: - top_state->flushing_blockage = FALSE; -} - - -/************************************* - * Function: lo_DisplayLine - * - * Description: This function displays a single line - * of the document, by having the front end individually - * display each element in it. - * - * Params: Window context, docuemnt state, and an index into - * the line array. - * - * Returns: Nothing. - *************************************/ -void -lo_DisplayLine(MWContext *context, lo_DocState *state, int32 line_num, - int32 x, int32 y, uint32 w, uint32 h) -{ - LO_Element *tptr; - LO_Element *end_ptr; - LO_Element **line_array; - -#ifdef LOCAL_DEBUG -XP_TRACE(("lo_DisplayLine(%d)\n", line_num)); -#endif - if (state == NULL) - { - return; - } - - if (state->display_blocked != FALSE) - { - return; - } - -#ifdef XP_WIN16 - { - intn a_size; - intn a_indx; - intn a_line; - XP_Block *larray_array; - - a_size = SIZE_LIMIT / sizeof(LO_Element *); - a_indx = (intn)(line_num / a_size); - a_line = (intn)(line_num - (a_indx * a_size)); - - XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array); - state->line_array = larray_array[a_indx]; - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array); - tptr = line_array[a_line]; - - if (line_num >= (state->line_num - 2)) - { - end_ptr = NULL; - } - else - { - if ((a_line + 1) == a_size) - { - XP_UNLOCK_BLOCK(state->line_array); - state->line_array = larray_array[a_indx + 1]; - XP_LOCK_BLOCK(line_array, LO_Element **, - state->line_array); - end_ptr = line_array[0]; - } - else - { - end_ptr = line_array[a_line + 1]; - } - } - XP_UNLOCK_BLOCK(state->line_array); - XP_UNLOCK_BLOCK(state->larray_array); - } -#else - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array); - tptr = line_array[line_num]; - - if (line_num >= (state->line_num - 2)) - { - end_ptr = NULL; - } - else - { - end_ptr = line_array[line_num + 1]; - } - XP_UNLOCK_BLOCK(state->line_array); -#endif /* XP_WIN16 */ - -#ifdef LOCAL_DEBUG - if (tptr == NULL) - { - XP_TRACE((" line %d is NULL!\n", line_num)); - } -#endif - - while (tptr != NULL && tptr != end_ptr) - { - lo_DisplayElement(context, tptr, - state->base_x, state->base_y, - x, y, w, h); - - tptr = tptr->lo_any.next; - } -} - -/************************************* - * Function: lo_PointToLine - * - * Description: This function calculates the line which contains - * a point. It's used for tracking mouse motion and button presses. - * - * Params: Window context, x, y position of point. - * - * Returns: The line that contains the point. - * Returns -1 on error. - *************************************/ -int32 -lo_PointToLine (MWContext *context, lo_DocState *state, int32 x, int32 y) -{ - int32 line, start, middle, end; - LO_Element **line_array; -#ifdef XP_WIN16 - int32 line_add; -#endif /* XP_WIN16 */ - - line = -1; - - /* - * No document state yet. - */ - if (state == NULL) - { - return(line); - } - - /* - * No laid out lines yet. - */ - if (state->line_num == 1 || !state->line_array) - { - return(line); - } - -#ifdef XP_WIN16 - { - intn a_size; - intn a_indx; - intn a_line; - XP_Block *larray_array; - - a_size = SIZE_LIMIT / sizeof(LO_Element *); - a_indx = (intn)((state->line_num - 2) / a_size); - a_line = (intn)((state->line_num - 2) - (a_indx * a_size)); - - XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array); - while (a_indx > 0) - { - XP_LOCK_BLOCK(line_array, LO_Element **, - larray_array[a_indx]); - if (y < line_array[0]->lo_any.y) - { - XP_UNLOCK_BLOCK(larray_array[a_indx]); - a_indx--; - } - else - { - XP_UNLOCK_BLOCK(larray_array[a_indx]); - break; - } - } - state->line_array = larray_array[a_indx]; - XP_UNLOCK_BLOCK(state->larray_array); - - /* - * We are about to do a binary search through the line - * array, lock it down. - */ - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array); - line_add = a_indx * a_size; - start = 0; - end = ((a_indx + 1) * a_size) - 1; - if (end > (state->line_num - 2)) - { - end = state->line_num - 2; - } - end = end - line_add; - } -#else - /* - * We are about to do a binary search through the line - * array, lock it down. - */ - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array); - start = 0; - end = (intn) state->line_num - 2; -#endif /* XP_WIN16 */ - - /* - * Special case if area is off the top. - */ - if (y <= 0) - { - line = 0; - } - /* - * Else another special case if area is off the bottom. - */ - else if (y >= line_array[end]->lo_any.y) - { - line = end; - } - /* - * Else a binary search through the document - * line list to find the line that contains the point. - */ - else - { - /* - * find the containing line. - */ - while ((end - start) > 0) - { - middle = (start + end + 1) / 2; - if (y < line_array[middle]->lo_any.y) - { - end = middle - 1; - } - else - { - start = middle; - } - } - line = start; - end = (intn) state->line_num - 2; /* reset end */ - } - - /* check for a match higher up - * if it matches find the highest matching line - * - * matches higher up can be caused by stylesheet - * negative margins - */ - while(line > 0 - && line_array[line-1]->lo_any.y <= y - && line_array[line-1]->lo_any.y+line_array[line-1]->lo_any.height > y) - { - line--; - } - - /* search through any lines that have the same Y coordinates and - * find the closes x directly to the left of the current point - */ - if(line != end - && line_array[line+1]->lo_any.y <= y - && line_array[line+1]->lo_any.y+line_array[line+1]->lo_any.height > y) - { - int32 closest=line; - int32 cur_line=line+1; - - for(; cur_line <= end - && line_array[cur_line]->lo_any.y <= y - && line_array[cur_line]->lo_any.y+line_array[cur_line]->lo_any.height > y - ; cur_line++) - { - if(line_array[cur_line]->lo_any.x < x - && (line_array[closest]->lo_any.x > x - || line_array[closest]->lo_any.x < line_array[cur_line]->lo_any.x)) - { - closest = cur_line; - } - } - - line = closest; - } - - XP_UNLOCK_BLOCK(state->line_array); -#ifdef XP_WIN16 - line = line + line_add; -#endif /* XP_WIN16 */ - return(line); -} - - - -/************************************* - * Function: lo_RegionToLines - * - * Description: This function calculates the lines which intersect - * a front end drawable region. It's used for drawing and in - * calculating page breaks for printing. - * - * Params: Window context, x, y position of upper left corner, - * and width X height of the rectangle. Also pointers to - * return values. dontCrop is true if we do not want to draw lines - * which would be cropped (fall on the top/bottom region boundary). - * This is for printing. - * - * Returns: Sets top and bottom to the lines numbers - * to display. Sets them to -1 on error. - *************************************/ -void -lo_RegionToLines (MWContext *context, lo_DocState *state, int32 x, int32 y, - uint32 width, uint32 height, Bool dontCrop, int32 * topLine, int32 * bottomLine) -{ - LO_Element **line_array; - int32 top, bottom; - int32 y2; - int32 topCrop; - int32 bottomCrop; - - /* - Set drawable lines to -1 (assuming error by default) - */ - *topLine = -1; - *bottomLine = -1; - - /* - * No document state yet. - */ - if (state == NULL) - { - return; - } - - /* - * No laid out lines yet. - */ - if (state->line_num == 1) - { - return; - } - - y2 = y + height; - - top = lo_PointToLine(context, state, x, y); - bottom = lo_PointToLine(context, state, x, y2); - - if ( dontCrop ) - { - XP_LOCK_BLOCK(line_array, LO_Element**, state->line_array ); - - topCrop = line_array[ top ]->lo_any.y; - bottomCrop = line_array[ bottom ]->lo_any.y + line_array[ bottom ]->lo_any.line_height; - XP_UNLOCK_BLOCK( state->line_array ); - - if ( y > topCrop ) - { - top++; - if ( top > ( state->line_num - 2 ) ) - top = -1; - } - if ( y2 < bottomCrop ) - bottom--; - } - - /* - * Sanity check - */ - if (bottom < top) - { - bottom = top; - } - - *topLine = top; - *bottomLine = bottom; -} - -/* - LO_CalcPrintArea - - Takes a region and adjusts it inward so that the top and bottom lines - are not cropped. Results can be passed to LO_RefreshArea to print - one page. To calculate the next page, use y+height as the next y. -*/ -intn -LO_CalcPrintArea (MWContext *context, int32 x, int32 y, - uint32 width, uint32 height, - int32 *top, int32 *bottom) -{ - LO_Element **line_array; - int32 doc_id; - lo_TopState *top_state; - lo_DocState *state; - int32 lineTop; - int32 lineBottom; - - *top = -1; - *bottom = -1; - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return(0); - } - state = top_state->doc_state; - - /* - Find which lines intersect the drawable region. - */ - lo_RegionToLines( context, state, x, y, width, height, TRUE, &lineTop, &lineBottom ); - - if ( lineTop != -1 && lineBottom != -1 ) - { - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array ); - - *top = line_array[ lineTop ]->lo_any.y; - *bottom = line_array[ lineBottom ]->lo_any.y + line_array[ lineBottom ]->lo_any.line_height - 1; - - XP_UNLOCK_BLOCK( state->line_array ); - return (1); - } - return (0); -} - -void -lo_CloseOutLayout(MWContext *context, lo_DocState *state) -{ - lo_FlushLineBuffer(context, state); - - /* - * makes sure we are at the bottom - * of everything in the document. - * - * Only close forms if we aren't in a subdoc because - * forms can span subdocs. - */ - if ((state->is_a_subdoc == SUBDOC_NOT)&& - (state->top_state->in_form != FALSE)) - { - lo_EndForm(context, state); - } - - lo_SetLineBreakState( context, state, FALSE, LO_LINEFEED_BREAK_SOFT, 1, FALSE); - lo_ClearToBothMargins(context, state); - - /* 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, lo_GetLastElementInList(state->line_list) ); -} - -/* Relayout version of lo_CloseOutLayout() */ -void lo_EndLayoutDuringReflow( MWContext *context, lo_DocState *state ) -{ - /* - * makes sure we are at the bottom - * of everything in the document. - * - * Only close forms if we aren't in a subdoc because - * forms can span subdocs. - */ - if ((state->is_a_subdoc == SUBDOC_NOT)&& - (state->top_state->in_form != FALSE)) - { - state->top_state->in_form = FALSE; - } - - - lo_SetLineBreakState( context, state, FALSE, LO_LINEFEED_BREAK_SOFT, 1, TRUE); - lo_ClearToBothMargins(context, state); -} - -void -LO_CloseAllTags(MWContext *context) -{ - int32 doc_id; - lo_TopState *top_state; - lo_DocState *state; - lo_DocState *sub_state; - - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return; - } - state = top_state->doc_state; - - /* - * If we are in a table, get us out. - */ - sub_state = lo_CurrentSubState(state); - while (sub_state != state) - { - lo_DocState *old_state; - - lo_CloseOutTable(context, sub_state); - old_state = sub_state; - sub_state = lo_CurrentSubState(state); - /* - * If sub_state doesn't change we could be in a loop. - * break it here. - */ - if (sub_state == old_state) - { - break; - } - } - state->sub_state = NULL; - - /* - * First do the normal closing. - */ - lo_CloseOutLayout(context, state); - - /* - * Reset a bunch of state variables. - */ - state->text_divert = P_UNKNOWN; - 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; - /* - * clear the alignment stack. - */ - while (lo_PopAlignment(state) != NULL) {;} - /* - * clear the list stack. - */ - while (lo_PopList(state, NULL) != NULL) {;} - /* - * clear all open anchors. - */ - lo_PopAllAnchors(state); - /* - * clear the font stack. - */ - while (state->font_stack->next != NULL) - { - (void)lo_PopFont(state, P_UNKNOWN); - } - state->base_font_size = DEFAULT_BASE_FONT_SIZE; - state->font_stack->text_attr->size = state->base_font_size; - state->current_anchor = NULL; - state->current_ele = NULL; - state->current_table = NULL; - state->current_cell = NULL; - state->current_java = 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; - - /* - * Escape an open script - */ - if (top_state->in_script != SCRIPT_TYPE_NOT) - { - top_state->in_script = SCRIPT_TYPE_NOT; - state->line_buf_len = 0; - lo_UnblockLayout(context, top_state); - } - - /* - * Reset a few top_state variables. - */ - top_state->current_map = NULL; - top_state->in_nogrids = FALSE; - top_state->ignore_tag_nest_level = 0; - top_state->ignore_layer_nest_level = 0; - top_state->in_applet = FALSE; -} - - -void -lo_free_layout_state_data(MWContext *context, lo_DocState *state) -{ - /* - * Short circuit out if the state was freed out from - * under us. - */ - if (state == NULL) - { - return; - } - - if (state->current_table != NULL) - { - lo_FreePartialTable(context, state, state->current_table); - state->current_table = NULL; - } - - if (state->left_margin_stack != NULL) - { - lo_MarginStack *mptr; - lo_MarginStack *margin; - - mptr = state->left_margin_stack; - while (mptr != NULL) - { - margin = mptr; - mptr = mptr->next; - XP_DELETE(margin); - } - state->left_margin_stack = NULL; - } - if (state->right_margin_stack != NULL) - { - lo_MarginStack *mptr; - lo_MarginStack *margin; - - mptr = state->right_margin_stack; - while (mptr != NULL) - { - margin = mptr; - mptr = mptr->next; - XP_DELETE(margin); - } - state->right_margin_stack = NULL; - } - - if (state->line_list != NULL) - { - LO_Element *eptr; - LO_Element *element; - - eptr = state->line_list; - while (eptr != NULL) - { - element = eptr; - eptr = eptr->lo_any.next; - lo_FreeElement(context, element, TRUE); - } - state->line_list = NULL; - } - - if (state->font_stack != NULL) - { - lo_FontStack *fstack; - lo_FontStack *fptr; - - fptr = state->font_stack; - while (fptr != NULL) - { - fstack = fptr; - fptr = fptr->next; - XP_DELETE(fstack); - } - state->font_stack = NULL; - } - - if (state->align_stack != NULL) - { - lo_AlignStack *aptr; - lo_AlignStack *align; - - aptr = state->align_stack; - while (aptr != NULL) - { - align = aptr; - aptr = aptr->next; - XP_DELETE(align); - } - state->align_stack = NULL; - } - - if (state->list_stack != NULL) - { - lo_ListStack *lptr; - lo_ListStack *list; - - lptr = state->list_stack; - while (lptr != NULL) - { - list = lptr; - lptr = lptr->next; - XP_DELETE(list); - } - state->list_stack = NULL; - } - - if (state->line_height_stack != NULL) - { - lo_LineHeightStack *lptr; - lo_LineHeightStack *height; - - lptr = state->line_height_stack; - while (lptr != NULL) { - height = lptr; - lptr = lptr->next; - XP_DELETE(height); - } - state->line_height_stack = NULL; - } - - if (state->line_buf != NULL) - { - PA_FREE(state->line_buf); - state->line_buf = NULL; - } -} - - -/* Clean up the layout data structures. This used to be inside lo_FinishLayout, - * but we needed to call it from the editor, without all of the UI code that - * lo_FinishLayout also calls. - */ - -void -lo_FreeLayoutData(MWContext *context, lo_DocState *state) -{ - int32 i, cnt; - - /* - * Clean out the lo_DocState - */ - lo_free_layout_state_data(context, state); - - /* - * Short circuit out if the state was freed out from - * under us. - */ - if (state == NULL) - { - return; - } - - LO_LockLayout(); - - /* - * These are tags that were blocked instead of laid out. - * If there was an image in here, we already started the - * layout of it, we better free it now. - */ - if (state->top_state->tags != NULL) - { - PA_Tag *tptr; - PA_Tag *tag; - - tptr = state->top_state->tags; - while (tptr != NULL) - { - tag = tptr; - tptr = tptr->next; - if (((tag->type == P_IMAGE)|| - (tag->type == P_NEW_IMAGE))&& - (tag->lo_data != NULL)) - { - LO_Element *element; - element = (LO_Element *)tag->lo_data; - lo_FreeElement(context, element, TRUE); - tag->lo_data = NULL; - } - PA_FreeTag(tag); - } - state->top_state->tags = NULL; - state->top_state->tags_end = &state->top_state->tags; - for (i = 0; i < MAX_INPUT_WRITE_LEVEL; i++) - state->top_state->input_write_point[i] = NULL; - } - - /* - * If we were blocked on and image when we left this page, we need to - * free up that partially loaded image structure. - */ - if (state->top_state->layout_blocking_element != NULL) - { - LO_Element *element; - - element = state->top_state->layout_blocking_element; - lo_FreeElement(context, element, TRUE); - state->top_state->layout_blocking_element = NULL; - } - - /* Delete object stack */ - if (state->top_state->object_stack != NULL) - { - lo_ObjectStack* top; - lo_ObjectStack* object; - - top = state->top_state->object_stack; - while (top != NULL) - { - object = top; - top = top->next; - lo_DeleteObjectStack(object); - } - state->top_state->object_stack = NULL; - } - - /* Delete object cache */ - if (state->top_state->object_cache != NULL) - { - lo_ObjectStack* top; - lo_ObjectStack* object; - - top = state->top_state->object_cache; - while (top != NULL) - { - object = top; - top = top->next; - lo_DeleteObjectStack(object); - } - state->top_state->object_cache = NULL; - } - - LO_UnlockLayout(); - - /* - * now we're done laying out the entire document. we had saved all - * the layout structures from the previous document so we're throwing - * away unused ones. - */ - cnt = lo_FreeRecycleList(context, state->top_state->recycle_list); -#ifdef MEMORY_ARENAS - if (state->top_state->current_arena != NULL) - { - cnt = lo_FreeMemoryArena(state->top_state->current_arena->next); - state->top_state->current_arena->next = NULL; - } -#endif /* MEMORY_ARENAS */ - state->top_state->recycle_list = NULL; -} - - -void -lo_CloseMochaWriteStream(lo_TopState *top_state, int mocha_event) -{ - NET_StreamClass *stream = top_state->mocha_write_stream; - - if (stream != NULL) - { - top_state->mocha_write_stream = NULL; - if (mocha_event == EVENT_LOAD) - { - stream->complete(stream); - } - else - { - stream->abort(stream, top_state->layout_status); - } - XP_DELETE(stream); - } -} - - - -void -lo_FinishLayout_OutOfMemory(MWContext *context, lo_DocState *state) -{ - lo_TopState *top_state; - lo_DocState *main_state; - lo_DocState *sub_state; - - /* Reset state for force loading images. */ - LO_SetForceLoadImage(NULL, FALSE); - - /* - * Short circuit out if the state was freed out from - * under us. - */ - if (state == NULL) - { - return; - } - - /* - * Check for dangling sub-states, and clean them up if they exist. - */ - top_state = state->top_state; - main_state = top_state->doc_state; - sub_state = lo_TopSubState(top_state); - while ((sub_state != NULL)&&(sub_state != main_state)) - { - state = main_state; - while ((state != NULL)&&(state->sub_state != sub_state)) - { - state = state->sub_state; - } - if (state != NULL) - { - lo_free_layout_state_data(context, sub_state); - XP_DELETE(sub_state); - state->sub_state = NULL; - } - sub_state = lo_TopSubState(top_state); - } - state = lo_TopSubState(top_state); - - lo_CloseMochaWriteStream(top_state, EVENT_ABORT); - - /* Could be left over if someone forgets to close a tag */ - if (state->top_state->scriptData) - lo_DestroyScriptData(state->top_state->scriptData); - - /* - * Short circuit out if the state was freed out from - * under us. - */ - if (state == NULL) - { - return; - } - - lo_free_layout_state_data(context, state); -} - - -void -lo_FinishLayout(MWContext *context, lo_DocState *state, int32 mocha_event) -{ - lo_TopState *top_state; - lo_DocState *main_state; - lo_DocState *sub_state; - - /* Close any layers (blocks) that were opened in this document, in - case the document author forgot to. */ - if (state != NULL ) { - if (state->layer_nest_level) { - while (state->layer_nest_level > 0) - lo_EndLayer(context, state, PR_TRUE); - /* - * This call ensures that we flush the line list (which still might - * have something on it if we had unclosed ILAYERs). - */ - lo_CloseOutLayout(context, state); - } - } - - if ((state != NULL) && - (state->top_state != NULL)) - { - lo_TopState * top_state = state->top_state; - - /* only finish once, please */ - XP_ASSERT(!top_state->finished); - if (top_state->finished) - return; - - top_state->finished = TRUE; - lo_CloseMochaWriteStream(top_state, mocha_event); - - /* Could be left over if someone forgets to close a tag */ - if (top_state->scriptData) - lo_DestroyScriptData(top_state->scriptData); - - /* Handle the page background for the case of a document that contains - no displayed layout elements. */ - if (top_state->nothing_displayed != FALSE) - lo_use_default_doc_background(context, state); - } - -#ifdef LAYPROBE_API - { - /* Send a notification when a frame has finished loading */ - XP_List* pList = LAPIGetCallbackFuncList((int32)FRAME_DOCUMENT_COMPLETE); - - if (pList) - { - while (pList = pList->next) - { - if (pList->object) - (*((ID_NOTIFY_PT)(pList->object)))((void*)context); - } - } - } -#endif /* LAYPROBE_API */ - - ET_SendLoadEvent(context, mocha_event, NULL, NULL, - LO_DOCUMENT_LAYER_ID, - (state && state->top_state) - ? state->top_state->resize_reload - : FALSE); - - /* Reset state for force loading images. */ - LO_SetForceLoadImage(NULL, FALSE); - - /* - * Short circuit out if the state was freed out from - * under us. - */ - if (state == NULL) - { -#if !defined(SMOOTH_PROGRESS) - FE_SetProgressBarPercent(context, 100); -#endif /* !defined(SMOOTH_PROGRESS) */ -#ifdef OLD_MSGS - FE_Progress(context, "Layout Phase Complete"); -#endif /* OLD_MSGS */ - - /* Flush out layer callbacks so that document dimensions are correct. */ - if (context->compositor) - CL_CompositeNow(context->compositor); - - FE_FinishedLayout(context); - return; - } - - /* - * Check for dangling sub-states, and clean them up if they exist. - */ - top_state = state->top_state; - main_state = top_state->doc_state; - sub_state = lo_TopSubState(top_state); - while ((sub_state != NULL)&&(sub_state != main_state)) - { - state = main_state; - while ((state != NULL)&&(state->sub_state != sub_state)) - { - state = state->sub_state; - } - if (state != NULL) - { - lo_free_layout_state_data(context, sub_state); - XP_DELETE(sub_state); - state->sub_state = NULL; - } - sub_state = lo_TopSubState(top_state); - } - state = lo_TopSubState(top_state); - - /* - * Short circuit out if the state was freed out from - * under us. - */ - if (state == NULL) - { -#if !defined(SMOOTH_PROGRESS) - FE_SetProgressBarPercent(context, 100); -#endif /* !defined(SMOOTH_PROGRESS) */ -#ifdef OLD_MSGS - FE_Progress(context, "Layout Phase Complete"); -#endif /* OLD_MSGS */ - - /* Flush out layer callbacks so that document dimensions are correct. */ - if (context->compositor) - CL_CompositeNow(context->compositor); - - FE_FinishedLayout(context); - return; - } - - lo_FreeLayoutData(context, state); - - if (state->display_blocked != FALSE) - { - int32 y; - - if (state->top_state->name_target != NULL) - { - XP_FREE(state->top_state->name_target); - state->top_state->name_target = NULL; - } - state->display_blocking_element_id = 0; - state->display_blocked = FALSE; - y = state->display_blocking_element_y; - state->display_blocking_element_y = 0; - state->y += state->win_bottom; - - LO_SetDocumentDimensions(context, state->max_width, state->y); - - if (y != state->win_top) - { - y = state->y - state->win_height; - if (y < 0) - { - y = 0; - } - } - FE_SetDocPosition(context, FE_VIEW, 0, y); - - if (context->compositor) - { - XP_Rect rect; - - rect.left = 0; - rect.top = y; - rect.right = state->win_width; - rect.bottom = y + state->win_height; - CL_UpdateDocumentRect(context->compositor, - &rect, (PRBool)FALSE); - } - } - else - { - state->y += state->win_bottom; - LO_SetDocumentDimensions(context, state->max_width, state->y); - } - - /* get rid of the style stack data since it wont - * be needed any more - */ - if(top_state->style_stack) - { - /* LJM: Need to purge stack to free memory - */ - STYLESTACK_Purge(top_state->style_stack); - } - -#if !defined(SMOOTH_PROGRESS) - if(!state->top_state->is_binary) - FE_SetProgressBarPercent(context, 100); -#endif /* !defined(SMOOTH_PROGRESS) */ - -#ifdef OLD_MSGS - FE_Progress(context, "Layout Phase Complete"); -#endif /* OLD_MSGS */ - - /* Flush out layer callbacks so that document dimensions are correct. */ - if (context->compositor) - CL_CompositeNow(context->compositor); - - if (state->is_a_subdoc == SUBDOC_NOT && state->top_state && !state->top_state->have_title) - { - /* We never got a title. We better notify the FE that the title is blank */ - - FE_SetDocTitle(context, ""); - } - - FE_FinishedLayout(context); -#ifdef EDITOR - if (EDT_IS_EDITOR (context)) - EDT_FinishedLayout(context); -#endif - - /* - * Update the blink layers to reflect the current positions of their - * associated text elements. - */ - if (context->compositor) - lo_UpdateBlinkLayers(context); - - if (top_state && top_state->metaTags) - { - /* Tell RDF HT code that layout of the current document is complete */ - HT_LayoutComplete( context, top_state->metaTags, top_state->url ); - - /* Free the meta tag list */ - lo_FreeTagList( top_state->metaTags ); - top_state->metaTags = NULL; - } - - /* Prefetch links of this context */ - PRE_Fetch(context); -} - - -static void lo_FreeTagList( TagList *tags ) -{ - if (tags != NULL && tags->tagList != NULL) - { - PA_Tag *tag; - PA_Tag *next_tag; - - tag = tags->tagList; - do - { - next_tag = tag->next; - PA_FreeTag( tag ); - tag = next_tag; - - } while ( tag != NULL ); - XP_FREE( tags ); - } -} -/******************************************************************************* - * LO_ProcessTag helper routines - ******************************************************************************/ - -#ifdef MEMORY_ARENAS -void -lo_GetRecycleList(MWContext* context, int32 doc_id, pa_DocData* doc_data, - LO_Element* *recycle_list, lo_arena* *old_arena) -#else -void -lo_GetRecycleList(MWContext* context, int32 doc_id, pa_DocData* doc_data, - LO_Element* *recycle_list) -#endif /* MEMORY_ARENAS */ -{ - lo_TopState* old_top_state; - lo_DocState* old_state; - - LO_LockLayout(); - - /* - * Free up any old document displayed in this - * window. - */ - old_top_state = lo_FetchTopState(XP_DOCID(context)); - if (old_top_state == NULL) - { - old_state = NULL; - } - else - { - old_state = old_top_state->doc_state; - } - if (old_state != NULL) - { -#ifdef MEMORY_ARENAS - *old_arena = old_top_state->first_arena; -#endif /* MEMORY_ARENAS */ - lo_SaveFormElementState(context, old_state, TRUE); - /* - * If this document has no session history - * there is no place to save this data. - * It will be freed by history cleanup. - */ - if (SHIST_GetCurrent(&context->hist) == NULL) - { - lo_TopState *top_state = old_state->top_state; - top_state->savedData.FormList = NULL; - top_state->savedData.EmbedList = NULL; - top_state->savedData.Grid = NULL; - } - *recycle_list = - lo_InternalDiscardDocument(context, old_state, doc_data, TRUE); - } - - /* Now that we've discarded the old document, set the new doc_id. */ - XP_SET_DOCID(context, doc_id); - LO_UnlockLayout(); - -} - -intn -lo_ProcessTag_OutOfMemory(MWContext* context, LO_Element* recycle_list, lo_TopState* top_state) -{ - int32 cnt; - - if ((top_state != NULL)&&(top_state->doc_state != NULL)) - { - lo_FinishLayout_OutOfMemory(context, top_state->doc_state); - } - - cnt = lo_FreeRecycleList(context, recycle_list); - -#ifdef MEMORY_ARENAS - if ((top_state != NULL)&&(top_state->first_arena != NULL)) - { - cnt = lo_FreeMemoryArena(top_state->first_arena->next); - top_state->first_arena->next = NULL; - } -#endif /* MEMORY_ARENAS */ - - return MK_OUT_OF_MEMORY; -} - -#define RESTORE_SAVED_DATA(Type, var, doc_data, recycle_list, top_state) \ -{ \ - var = (lo_Saved##Type##Data *) \ - (doc_data->url_struct->savedData.Type); \ - if (var == NULL) \ - { \ - /* \ - * A document we have never visited, insert a pointer \ - * to a form list into its history, if it has one. \ - */ \ - var = lo_NewDocument##Type##Data(); \ - if (SHIST_GetCurrent(&context->hist) != NULL) \ - { \ - SHIST_SetCurrentDoc##Type##Data(context, (void *)var); \ - } \ - /* \ - * Stuff it in the url_struct as well for \ - * continuous loading documents. \ - */ \ - doc_data->url_struct->savedData.Type = (void *)var; \ - } \ - else if (doc_data->from_net != FALSE) \ - { \ - lo_FreeDocument##Type##Data(context, var); \ - } \ - \ - /* \ - * If we don't have a form list, something very bad \ - * has happened. Like we are out of memory. \ - */ \ - if (var == NULL) \ - return lo_ProcessTag_OutOfMemory(context, recycle_list, top_state); \ - \ - top_state->savedData.Type = var; \ -} - -/**************************************************************************** - **************************************************************************** - ** - ** Beginning of Public Utility Functions - ** - **************************************************************************** - ****************************************************************************/ - - -static void *hooked_data_object = NULL; -static intn hooked_status = 0; -static PA_Tag *hooked_tag = NULL; - -#ifdef DOM -char *element_names[] = { - "NONE", - "TEXT", - "LINEFEED", - "HRULE", - "IMAGE", - "BULLET", - "FORM_ELE", - "SUBDOC", - "TABLE", - "CELL", - "EMBED", - "EDGE", - "JAVA", - "SCRIPT", - "OBJECT", - "PARAGRAPH", - "CENTER", - "MULTICOL", - "FLOAT", - "TEXTBLOCK", - "LIST", - "DESCTITLE", - "DESCTEXT", - "BLOCKQUOTE", - "LAYER", - "HEADING", - "SPAN", - "BUILTIN", - "SPACER", - "SUPER", - "SUB" -}; - -static void -DumpNodeElements(DOM_Node *node) -{ -#ifdef DEBUG_shaver - LO_Element *eptr; - if (node->type != NODE_TYPE_ELEMENT && - node->type != NODE_TYPE_TEXT) - return; - fprintf(stderr, "%s %s elements:", - PA_TagString(ELEMENT_PRIV(node)->tagtype), - node->name ? node->name : ""); - if (ELEMENT_PRIV(node)->tagtype == P_TABLE_ROW || - ELEMENT_PRIV(node)->tagtype == P_TABLE_DATA) { - fprintf(stderr, " \n"); - return; - } - eptr = ELEMENT_PRIV(node)->ele_start; - if (!eptr) { - fprintf(stderr, " (SHOULD REMOVE FROM TREE!)\n"); - return; - } - while (eptr && eptr != ELEMENT_PRIV(node)->ele_end) { - fprintf(stderr, " %s", element_names[eptr->type]); - eptr = eptr->lo_any.next; - } - if (eptr) - fprintf(stderr, " %s", element_names[eptr->type]); - fprintf(stderr, "\n"); -#endif -} -#endif - -/************************************* - * Function: LO_ProcessTag - * - * Description: This function is the main layout entry point. - * New tags or tag lists are sent here along with the - * status as to where they came from. - * - * Params: A blank data object from the parser, right now it - * is parse document data. The tag or list of tags to process. - * and a status field as to why it came. - * - * Returns: 1 - Done ok, continuing. - * 0 - Done ok, stopping. - * -1 - not done, error. - *************************************/ -intn -LO_ProcessTag(void *data_object, PA_Tag *tag, intn status) -{ - pa_DocData *doc_data; - int32 doc_id; - MWContext *context; - CL_Layer *doc_layer = NULL, *body_layer = NULL; - lo_TopState *top_state; - lo_DocState *state; - lo_DocState *orig_state; - lo_DocState *up_state; -#ifdef DOM - DOM_Node *last_node; -#endif - - /* - * If this call came from a hook feed - */ - if (hooked_data_object != NULL) - { - data_object = hooked_data_object; - status = hooked_status; - /* - * Ignore hooked calls with no tags. - */ - if (tag == NULL) - { - return(1); - } - if (hooked_tag != NULL) - { - tag->newline_count += hooked_tag->newline_count; - } - } - - doc_data = (pa_DocData *)data_object; - doc_id = doc_data->doc_id; - top_state = (lo_TopState *)(doc_data->layout_state); - - /* - * If this is an "inline" stream and we don't have a top_state - * associated with it, it's targetted at a layer in - * the current document. In this case, we need to get the - * top_state using the context and not directly from the doc_data. - */ - if ((top_state == NULL) && (doc_data->is_inline_stream == TRUE)) { - top_state = lo_FetchTopState(doc_id); - doc_data->layout_state = top_state; - if (top_state) { - top_state->doc_data = doc_data; - top_state->nurl = doc_data->url_struct; - } - } - - - if (top_state == NULL) - { - state = NULL; - } - else - { - state = top_state->doc_state; - } - context = doc_data->window_id; - - /* - * if we get called with abort/complete then ignore oom condition - * and clean up - */ - if ((state != NULL)&&(state->top_state != NULL)&& - (state->top_state->out_of_memory != FALSE)&&(tag != NULL)) - { - lo_FinishLayout_OutOfMemory(context, state); - return(MK_OUT_OF_MEMORY); - } - - if ((tag != NULL)&&(context != NULL)&&(hooked_data_object == NULL)&& - (HK_IsHook(HK_TAG, (void *)tag))) - { - char *tptr; - char *in_str; - char *out_str; - XP_Bool delete_tag; - XP_Bool replace_tag; - - out_str = NULL; - delete_tag = FALSE; - replace_tag = FALSE; - if (tag->type == P_TEXT) - { - PA_LOCK (tptr, char *, tag->data); - in_str = XP_ALLOC(tag->data_len + 1); - if (in_str == NULL) - { - return(MK_OUT_OF_MEMORY); - } - XP_BCOPY(tptr, in_str, tag->data_len); - in_str[tag->data_len] = '\0'; - PA_UNLOCK(tag->data); - } - else if (tag->type == P_UNKNOWN) - { - int32 start; - - PA_LOCK (tptr, char *, tag->data); - in_str = XP_ALLOC(tag->data_len + 3); - if (in_str == NULL) - { - return(MK_OUT_OF_MEMORY); - } - in_str[0] = '<'; - start = 1; - if (tag->is_end != FALSE) - { - in_str[1] = '/'; - start = 2; - } - XP_BCOPY(tptr, (char *)(in_str + start), tag->data_len); - in_str[tag->data_len + start] = '\0'; - PA_UNLOCK(tag->data); - } - else - { - XP_Bool free_tag_str; - const char *tag_str; - int32 start; - - free_tag_str = FALSE; - tag_str = PA_TagString((int32)tag->type); - if (tag_str == NULL) - { - tag_str = XP_STRDUP("UNKNOWN"); - if (tag_str == NULL) - { - return(MK_OUT_OF_MEMORY); - } - free_tag_str = TRUE; - } - start = XP_STRLEN(tag_str); - - PA_LOCK (tptr, char *, tag->data); - in_str = XP_ALLOC(tag->data_len + start + 3); - if (in_str == NULL) - { - if (free_tag_str != FALSE) - { - XP_FREE((char *)tag_str); - } - return(MK_OUT_OF_MEMORY); - } - in_str[0] = '<'; - in_str[1] = '\0'; - start += 1; - if (tag->is_end != FALSE) - { - in_str[1] = '/'; - in_str[2] = '\0'; - start += 1; - } - XP_STRCAT(in_str, tag_str); - XP_BCOPY(tptr, (char *)(in_str + start), tag->data_len); - in_str[tag->data_len + start] = '\0'; - PA_UNLOCK(tag->data); - if (free_tag_str != FALSE) - { - XP_FREE((char *)tag_str); - } - } - if (HK_CallHook(HK_TAG, (void *)tag, XP_CONTEXTID(context), - in_str, &out_str)) - { - /* - * out_str of NULL means change nothing. - * Returning the same string passed in also - * changes nothing. - */ - if ((out_str != NULL)&&(out_str[0] == '\0')) - { - delete_tag = TRUE; - } - else if ((out_str != NULL)&& - (XP_STRCMP(in_str, out_str) != 0)) - { - replace_tag = TRUE; - } - } - XP_FREE(in_str); - - if (delete_tag != FALSE) - { - PA_FreeTag(tag); - tag = NULL; - XP_FREE(out_str); - return(1); - } - else if (replace_tag != FALSE) - { - intn ok; - - hooked_data_object = data_object; - hooked_status = status; - hooked_tag = tag; - - ok = PA_ParseStringToTags(context, - out_str, XP_STRLEN(out_str), - (void *)LO_ProcessTag); - - hooked_data_object = NULL; - - /* - * This tag has been replaced, and never happened. - */ - if (ok) - { - PA_FreeTag(tag); - tag = NULL; - XP_FREE(out_str); - return(1); - } - } - if (out_str != NULL) - { - XP_FREE(out_str); - } - } - - /* - Test to see if this is a new stream. - If it is, kill the old one (NET_InterruptStream(url)), - free its data, and continue. - */ - if (!state) { /* this is a new document being laid out */ - /* is there already a state for this context? */ - lo_TopState *top_state; - lo_DocState *old_state; - - /* initialize PICS */ - PICS_Init(context); - - top_state = lo_FetchTopState(doc_id); - if (top_state == NULL) - { - old_state = NULL; - } - else - { - old_state = top_state->doc_state; - } - - if (old_state) { - if (top_state->nurl) { /* is it still running? */ -/* ALEKS NET_InterruptStream (top_state->nurl); */ - /* We've done a complete "cancel" now. We shouldn't need to do any more - work; we'll find this "old state" again and recycle it */ - } - } - } - - /* - * We be done. - */ - if (tag == NULL) - { - /* - * If this is an inline stream that is not the result of a - * dynamic layer src change, then don't do anything. The - * layer will be closed out by the closing tag - */ - if (doc_data && doc_data->is_inline_stream && (!state || - (lo_InsideLayer(state) && !lo_IsCurrentLayerDynamic(state)))) - return 0; - - if (context->compositor) - CL_SetCompositorEnabled(context->compositor, PR_TRUE); - - if (status == PA_ABORT) - { -#ifdef OLD_MSGS - FE_Progress (context, "Document Load Aborted"); -#endif /* OLD_MSGS */ - lo_process_deferred_image_info(NULL); - if (state != NULL) - { - state->top_state->layout_status = status; - } - /* - * If this is an inline stream (the result of a dynamic - * layer src change) close out the layer. - */ - if (doc_data && doc_data->is_inline_stream) - lo_FinishLayerLayout(context, state, EVENT_ABORT); - else - lo_FinishLayout(context, state, EVENT_ABORT); - } - else if (status == PA_COMPLETE) - { - orig_state = state; - state = lo_CurrentSubState(state); - - /* - * If this is an inline stream (the result of a dynamic - * layer src change) close out the layer. - */ - if (doc_data && doc_data->is_inline_stream) - lo_FinishLayerLayout(context, state, EVENT_LOAD); - else - /* - * IF the document is complete, we need to flush - * out any remaining unfinished elements. - */ - if (state != NULL) - { - state->top_state->total_bytes = state->top_state->current_bytes; - - if (state->top_state->layout_blocking_element != NULL) - { -#ifdef OLD_MSGS - FE_Progress(context, "Layout Phase Complete but Blocked"); -#endif /* OLD_MSGS */ - } - else - { - /* - * makes sure we are at the bottom - * of everything in the document. - */ - lo_CloseOutLayout(context, state); - -#ifdef OLD_MSGS - FE_Progress(context, "Layout Phase Complete"); -#endif /* OLD_MSGS */ - - lo_FinishLayout(context, state, EVENT_LOAD); - TIMING_STOPCLOCK_OBJECT("lo:doc", doc_id, context, "ok"); - } - orig_state->top_state->layout_status = status; - } - else - { - LO_Element *recycle_list = NULL; - int32 cnt; - int32 width, height; - int32 margin_width, margin_height; -#ifdef MEMORY_ARENAS - lo_arena *old_arena = NULL; - - lo_GetRecycleList(context, doc_id, doc_data, - &recycle_list, &old_arena); -#else - lo_GetRecycleList(context, doc_id, doc_data, - &recycle_list); -#endif /* MEMORY_ARENAS */ - margin_width = 0; - margin_height = 0; - - /* Because Mocha is in a separate thread, the - complete destruction of contexts is deferred until - Mocha cleans up its data structures. (See - ET_RemoveWindowContext()). If this context was - previously a frameset context, it may still have grid - children that haven't been deleted yet. Pull them - off the grid_children list so that we don't mistakenly - conclude that this context is a frameset context. */ - if (context->grid_children) { - XP_ListDestroy (context->grid_children); - context->grid_children = 0; - } - FE_LayoutNewDocument(context, - doc_data->url_struct, - &width, &height, - &margin_width, - &margin_height); - - if(context && doc_data && doc_data->url_struct) { - /* Tell XP NavCenter API about the new document. - */ - XP_SetNavCenterUrl(context, doc_data->url_struct->address); - } - - /* see first lo_FreeRecycleList comment. safe */ - cnt = lo_FreeRecycleList(context, recycle_list); -#ifdef MEMORY_ARENAS - cnt = lo_FreeMemoryArena(old_arena); -#endif /* MEMORY_ARENAS */ - - FE_SetDocPosition(context, FE_VIEW, 0, 0); - FE_SetDocDimension(context, FE_VIEW, 1, 1); - -#ifdef OLD_MSGS - FE_Progress(context, "Layout Phase Complete"); -#endif /* OLD_MSGS */ - lo_FinishLayout(context, state, EVENT_LOAD); - } - } - - /* - * Since lo_FinishLayout make have caused state to be - * freed if it was a dangling sub_state, we need to - * reinitialize state here so it is safe to use it. - */ - state = lo_TopSubState(top_state); - - if (state != NULL) - { - /* done with netlib stream */ - state->top_state->nurl = NULL; - state->top_state->doc_data = NULL; - } - - - /* - * Make sure we are done with all images now. - */ - lo_NoMoreImages(context); - - return(0); - } - - /* - * Check if this is a new document being laid out - */ - if (top_state == NULL) - { - int32 width, height; - int32 margin_width, margin_height; - lo_SavedFormListData *form_list; - lo_SavedEmbedListData *embed_list; - lo_SavedGridData *grid_data; - LO_Element *recycle_list = NULL; - int32 start_element; - -#ifdef MEMORY_ARENAS - lo_arena *old_arena = NULL; - - lo_GetRecycleList(context, doc_id, doc_data, &recycle_list, &old_arena); /* whh */ -#else - lo_GetRecycleList(context, doc_id, doc_data, &recycle_list); /* whh */ -#endif /* MEMORY_ARENAS */ - - TIMING_STARTCLOCK_OBJECT("lo:blank", context); - TIMING_STARTCLOCK_OBJECT("lo:doc", doc_id); - -#ifdef LOCAL_DEBUG -XP_TRACE(("Initializing new doc %d\n", doc_id)); -#endif /* DEBUG */ - width = 1; - height = 1; - margin_width = 0; - margin_height = 0; - /* - * Grid cells can set their own margin dimensions. - */ - if (context->is_grid_cell != FALSE) - { - lo_GetGridCellMargins(context, - &margin_width, &margin_height); - } - - /* Because Mocha is in a separate thread, the complete - destruction of contexts is deferred until Mocha cleans up - its data structures. (See ET_RemoveWindowContext()). If - this context was previously a frameset context, it may - still have grid children that haven't been deleted yet. - Pull them off the grid_children list so that we don't - mistakenly conclude that this context is a frameset - context. */ - if (context->grid_children) { - XP_ListDestroy (context->grid_children); - context->grid_children = 0; - } - FE_LayoutNewDocument(context, doc_data->url_struct, - &width, &height, &margin_width, &margin_height); - - if(context && doc_data && doc_data->url_struct) { - /* Tell XP NavCenter API about the new document. - */ - XP_SetNavCenterUrl(context, doc_data->url_struct->address); - } - - if (context->compositor) { - lo_CreateDefaultLayers(context, &doc_layer, &body_layer); - CL_ScrollCompositorWindow(context->compositor, 0, 0); - - /* Instead of enabling the compositor here, we do so at - the end of layout so that perceived performance increases - because blank page time is reduced. */ - /* CL_SetCompositorEnabled(context->compositor, PR_TRUE); */ - } - - top_state = lo_NewTopState(context, doc_data->url); - if ((context->compositor && (!doc_layer || !body_layer)) || - top_state == NULL) - { -#ifdef MEMORY_ARENAS - if (old_arena != NULL) - { - int32 cnt; - - cnt = lo_FreeMemoryArena(old_arena); - } -#endif /* MEMORY_ARENAS */ - return lo_ProcessTag_OutOfMemory(context, recycle_list, top_state); - } -#ifdef MEMORY_ARENAS - if ( ! EDT_IS_EDITOR(context) ) { - top_state->first_arena->next = old_arena; - } -#endif /* MEMORY_ARENAS */ - - /* take a special hacks from URL_Struct */ - top_state->auto_scroll =(intn)doc_data->url_struct->auto_scroll; - top_state->is_binary = doc_data->url_struct->is_binary; - /* - * Security dialogs only for FO_PRESENT docs. - */ - if (CLEAR_CACHE_BIT(doc_data->format_out) == FO_PRESENT) - { - top_state->security_level = - doc_data->url_struct->security_on; - } - else - { - top_state->security_level = 0; - } - top_state->doc_layer = doc_layer; - top_state->body_layer = body_layer; - top_state->force_reload = doc_data->url_struct->force_reload; - top_state->nurl = doc_data->url_struct; - top_state->total_bytes = doc_data->url_struct->content_length; - top_state->doc_data = doc_data; - top_state->resize_reload = doc_data->url_struct->resize_reload; - - if (top_state->auto_scroll != 0) - { - top_state->scrolling_doc = TRUE; - if (top_state->auto_scroll < 1) - { - top_state->auto_scroll = 1; - } - if (top_state->auto_scroll > 1000) - { - top_state->auto_scroll = 1000; - } - } - - /* - * give the parser a pointer to the layout data so we can - * get to it next time - */ - doc_data->layout_state = top_state; - - /* - * Add this new top state to the global state list. - */ - if (lo_StoreTopState(doc_id, top_state) == FALSE) - { - return lo_ProcessTag_OutOfMemory(context, recycle_list, - top_state); - } - -#ifdef EDITOR - /* LTNOTE: maybe this should be passed into New_Layout. - * For now, it is not. - */ - top_state->edit_buffer = doc_data->edit_buffer; -#endif - state = lo_NewLayout(context, width, height, - margin_width, margin_height, NULL); - if (state == NULL) - return lo_ProcessTag_OutOfMemory(context, recycle_list, top_state); - top_state->doc_state = state; - - /* The DOCUMENT layer's height is always the height of the - window, at least for the purpose of computing percentage - heights in child layers. */ - top_state->layers[LO_DOCUMENT_LAYER_ID]->height = - state->win_top + state->win_height + state->win_bottom; - - /* Reset the scoping for any JavaScript to be the top-level layer. */ - ET_SetActiveLayer(context, LO_DOCUMENT_LAYER_ID); - - /* RESTORE style stack - */ - if(top_state->resize_reload) - { - History_entry *he = SHIST_GetCurrent(&context->hist); - if (he) - { - if(he->savedData.style_stack) - { - if(top_state->style_stack) - STYLESTACK_Delete(top_state->style_stack); - top_state->style_stack = he->savedData.style_stack; - he->savedData.style_stack = NULL; - } - } - } - - /* - * Take care of forms. - * If we have been here before, we can pull the old form - * data out of the URL_Struct. It may be invalid if the - * form was interrupted. - */ - RESTORE_SAVED_DATA(FormList, form_list, doc_data, recycle_list, top_state); - if (!form_list->valid) - lo_FreeDocumentFormListData(context, form_list); - form_list->data_index = 0; - - /* - * Take care of embeds. - * If we have been here before, we can pull the old embed - * data out of the URL_Struct. - */ - RESTORE_SAVED_DATA(EmbedList, embed_list, doc_data, recycle_list, top_state); - - /* - * Take care of saved grid data. - * If we have been here before, we can pull the old - * grid data out of the URL_Struct. - */ - RESTORE_SAVED_DATA(Grid, grid_data, doc_data, recycle_list, top_state); - - /* XXX just in case a grid had onLoad or onUnload handlers */ - if (!doc_data->url_struct->resize_reload) - { - lo_RestoreContextEventHandlers(context, state, tag, - &doc_data->url_struct->savedData); - } - - top_state->recycle_list = recycle_list; - - if (state->top_state->name_target != NULL) - { - state->display_blocking_element_id = -1; - } - - start_element = doc_data->url_struct->position_tag; - if (start_element == 1) - { - start_element = 0; - } - - if (start_element > 0) - { - state->display_blocking_element_id = start_element; - } - - if ((state->display_blocking_element_id > state->top_state->element_id)|| - (state->display_blocking_element_id == -1)) - { - state->display_blocked = TRUE; - } - else - { - FE_SetDocPosition(context, FE_VIEW, 0, state->base_y); - } - - if ((Master_backdrop_url != NULL)&&(UserOverride != FALSE) - &&(context->type != MWContextDialog)) - { - lo_load_user_backdrop(context, state); - } - - /* This will be set if we ever encounter an image with no size - information, and will indicate to the FE that a reflow needs - to be done when all the connections have completed. */ - context->requires_reflow = PR_FALSE; - } - - if (state == NULL) - { - return(-1); - } - - /* - * If we're processing an inline stream, we need to make a note of it - * so that the tag goes into the correct place. - */ - if (doc_data && doc_data->is_inline_stream && - (top_state->doc_data != doc_data)) - { - if (top_state->input_write_level >= MAX_INPUT_WRITE_LEVEL-1) { - top_state->out_of_memory = TRUE; - return (MK_OUT_OF_MEMORY); - } - top_state->input_write_level++; - top_state->tag_from_inline_stream = TRUE; - } - - if (tag->data != NULL) - { - state->top_state->current_bytes += tag->data_len; - } - - /* - * Divert all tags to the current sub-document if there is one. - */ - up_state = NULL; - orig_state = state; - while (state->sub_state != NULL) - { - up_state = state; - state = state->sub_state; - } - - orig_state->top_state->layout_status = status; - - /* - * The filter checks for all the NOFRAMES, NOEMBED, NOSCRIPT, and - * the APPLET ignore setup. - */ - if (top_state->layout_blocking_element != NULL) - { - lo_BlockTag(context, state, tag); - } - else if (lo_FilterTag(context, state, tag) == FALSE) - { - PA_FreeTag(tag); - } - else - { - lo_DocState *tmp_state; - Bool may_save; - int32 state_diff; - - if ((state->is_a_subdoc == SUBDOC_CELL)|| - (state->is_a_subdoc == SUBDOC_CAPTION)) - { - may_save = TRUE; - } - else - { - may_save = FALSE; - } - - /* - * Reset these so we can tell if anything happened - */ - top_state->diff_state = FALSE; - top_state->state_pushes = 0; - top_state->state_pops = 0; - - lo_LayoutTag(context, state, tag); - - if (top_state->wedged_on_mocha) { - top_state->wedged_on_mocha = FALSE; - return(1); - } - - tmp_state = lo_CurrentSubState(orig_state); - - /* how has our state level changed? */ - state_diff = top_state->state_pushes - top_state->state_pops; - - if (may_save != FALSE) - { - /* - * Store the tag in the correct subdoc. - */ - if (state_diff == -1) - { - /* - * That tag popped us up one state level. If this new - * state is still a subdoc, save the tag there. - */ - if ((tmp_state->is_a_subdoc == SUBDOC_CELL)|| - (tmp_state->is_a_subdoc == SUBDOC_CAPTION)) - { - /* if we just popped a table we need to insert - * a dummy end tag to pop the dummy start tag - * we shove on the stack after createing a table - */ - PA_Tag *new_tag = LO_CreateStyleSheetDummyTag(tag); - if(new_tag) - { - lo_SaveSubdocTags(context, tmp_state, new_tag); - } - - lo_SaveSubdocTags(context, tmp_state, tag); - } - else - { - PA_FreeTag(tag); - } - } - else if (( up_state != NULL ) && - ( top_state->diff_state != FALSE ) && - ( state_diff == 0 )) - { - /* - * We have returned to the same state level but - * we have a different subdoc. - */ - if ((up_state->is_a_subdoc == SUBDOC_CELL)|| - (up_state->is_a_subdoc == SUBDOC_CAPTION)) - { - lo_SaveSubdocTags(context, up_state, tag); - } - else - { - PA_FreeTag(tag); - } - } - else if (( top_state->diff_state == FALSE ) && - ( state_diff == 0 )) - { - /* - * We are still in the same subdoc - */ - lo_SaveSubdocTags(context, state, tag); - } - else if (( state_diff == 1 )) - { - PA_Tag *new_tag; - - /* - * That tag started a new, nested subdoc. - * Add the starting tag to the parent. - */ - lo_SaveSubdocTags(context, state, tag); - /* - * Since we have extended the parent chain, - * we need to reset the child to the new - * parent end-chain. - */ - if ((tmp_state->is_a_subdoc == SUBDOC_CELL)|| - (tmp_state->is_a_subdoc == SUBDOC_CAPTION)) - { - tmp_state->subdoc_tags = - state->subdoc_tags_end; - - /* add an aditional dummy tag so that style sheets - * can use it to query styles from for this entry - * that created a table - */ - new_tag = LO_CreateStyleSheetDummyTag(tag); - if(new_tag) - { - lo_SaveSubdocTags(context, tmp_state, new_tag); - } - } - } - /* - * This can never happen. - */ - else - { - PA_FreeTag(tag); - } - - state = tmp_state; - } - else - { - if(state_diff == 1) - { - /* everytime a table is started we need to save the - * tag that created it so that style sheets can apply - * styles to it. So we will save even in the "dont save" - * case - */ - PA_Tag *new_tag = LO_CreateStyleSheetDummyTag(tag); - if(new_tag) - { - /* We just pushed another table into a previous table - * we need to do some table magic to make the subdoc - * list work right - */ - lo_SaveSubdocTags(context, tmp_state, new_tag); - } - } - else if(state_diff == -1) - { - /* if we just popped a table we need to insert - * a dummy end tag to pop the dummy start tag - * we shove on the stack after createing a table - */ - PA_Tag *new_tag = LO_CreateStyleSheetDummyTag(tag); - if(new_tag) - { - lo_SaveSubdocTags(context, tmp_state, new_tag); - } - } - - PA_FreeTag(tag); - } - } - - if (doc_data && doc_data->is_inline_stream && - (top_state->doc_data != doc_data)) - { - top_state->input_write_level--; - } - top_state->tag_from_inline_stream = FALSE; - - if (state->top_state->out_of_memory != FALSE) - { - lo_FinishLayout_OutOfMemory(context, state); - return(MK_OUT_OF_MEMORY); - } - - /* - * The parser (libparse/pa_parse.c) only calls us with these status - * codes when tag is null, and we handled that case far above (in fact, - * we will crash less far above on a null tag pointer, so we can't get - * here when aborting or completing). - */ - XP_ASSERT(status != PA_ABORT && status != PA_COMPLETE); - - return(1); -} - -void -lo_RefreshDocumentArea(MWContext *context, lo_DocState *state, int32 x, int32 y, - uint32 width, uint32 height) -{ - LO_Element *eptr; - int32 i; - int32 top, bottom; - - if (state->display_blocked != FALSE) - { - return; - } - - /* - * Find which lines intersect the drawable region. - */ - lo_RegionToLines (context, state, x, y, width, height, FALSE, - &top, &bottom); - - /* - * Display all these lines, if there are any. - */ - if (bottom >= 0) - { - for (i=top; i <= bottom; i++) - { - lo_DisplayLine(context, state, i, - x, y, width, height); - } - } - - /* - * Check the floating element list. - */ - eptr = state->float_list; - while (eptr != NULL) - { - /* I'm not sure exactly why we need to do this, but this code - has been here, in some form or another, since this file was - first created -- fur. */ - if (eptr->type == LO_SUBDOC) - { - LO_SubDocStruct *subdoc; - lo_DocState *sub_state; - - subdoc = (LO_SubDocStruct *)eptr; - sub_state = (lo_DocState *)subdoc->state; - - if (sub_state == NULL) - break; - - if (sub_state->base_y < 0) - sub_state->display_blocked = FALSE; - } - lo_DisplayElement(context, eptr, - state->base_x, state->base_y, - x, y, width, height); - eptr = eptr->lo_any.next; - } -} - - -/************************************* - * Function: LO_RefreshArea - * - * Description: This is a public function that allows the front end - * to ask that a particulat portion of the document be refreshed. - * The layout then finds the relevant elements, and calls - * the appropriate front end functions to display those - * elements. - * - * Params: Window context, x, y position of upper left corner, - * and width X height of the rectangle. - * - * Returns: Nothing - *************************************/ -void -LO_RefreshArea(MWContext *context, int32 x, int32 y, - uint32 width, uint32 height) -{ - int32 doc_id; - lo_TopState *top_state; - lo_DocState *state; - - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return; - } - state = top_state->doc_state; - - lo_RefreshDocumentArea(context, state, x, y, width, height); -} - - -/************************************* - * Function: lo_GetLineEnds - * - * Description: This is a private function that returns the line ends for - * a particular line. - * - * Params: Window context, line number. - * - * Returns: A pointer to the first and last elements in the line at that location, - * or NULLs if there is no matching line. - *************************************/ -void -lo_GetLineEnds(MWContext *context, lo_DocState *state, - int32 line, LO_Element** retBegin, LO_Element** retEnd) -{ - LO_Element **line_array; - LO_Element *begin = 0; - LO_Element *end = 0; - - *retBegin = NULL; - *retEnd = NULL; - - /* - * No document state yet. - */ - if (state == NULL) - { - return; - } - - if (line >= 0) -#ifdef XP_WIN16 - { - intn a_size; - intn a_indx; - intn a_line; - XP_Block *larray_array; - - a_size = SIZE_LIMIT / sizeof(LO_Element *); - a_indx = (intn)(line / a_size); - a_line = (intn)(line - (a_indx * a_size)); - - XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array); - state->line_array = larray_array[a_indx]; - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array); - begin = line_array[a_line]; - - if (line >= (state->line_num - 2)) - { - end = NULL; - } - else - { - if ((a_line + 1) == a_size) - { - XP_UNLOCK_BLOCK(state->line_array); - state->line_array = larray_array[a_indx + 1]; - XP_LOCK_BLOCK(line_array, LO_Element **, - state->line_array); - end = line_array[0]; - } - else - { - end = line_array[a_line + 1]; - } - } - XP_UNLOCK_BLOCK(state->line_array); - XP_UNLOCK_BLOCK(state->larray_array); - } -#else - { - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array); - begin = line_array[line]; - if (line == (state->line_num - 2)) - { - end = NULL; - } - else - { - end = line_array[line + 1]; - } - XP_UNLOCK_BLOCK(state->line_array); - } -#endif /* XP_WIN16 */ - /* Be sure we aren't pointing to internal dummy elements */ - if( begin ) - { - while( begin && lo_IsDummyLayoutElement(begin) ) - begin = begin->lo_any.next; - *retBegin = begin; - } - if( end ) - { - while( end && lo_IsDummyLayoutElement(end) ) - { - if( end->lo_any.prev ) - end = end->lo_any.prev; - else - end = end->lo_any.next; - } - *retEnd = end; - } -} - -Bool lo_IsDummyLayoutElement(LO_Element *ele) -{ - Bool isDummy = FALSE; - switch(ele->lo_any.type) - { - case LO_PARAGRAPH: - case LO_CENTER: - case LO_MULTICOLUMN: - case LO_FLOAT: - case LO_TEXTBLOCK: - case LO_LIST: - case LO_DESCTITLE: - case LO_DESCTEXT: - case LO_BLOCKQUOTE: - case LO_LAYER: - case LO_HEADING: - case LO_SPAN: - case LO_DIV: - isDummy = TRUE; - break; - } - return isDummy; -} - -/************************************* - * Function: lo_XYToDocumentElement - * - * Description: This is a public function that allows the front end - * to ask for the particular element residing at the passed - * (x, y) position in the window. This is very important - * for resolving button clicks on anchors. - * - * Params: Window context, x, y position of the window location. - * - * Returns: A pointer to the element record at that location, - * or NULL if there is no matching element. - *************************************/ -LO_Element * -lo_XYToDocumentElement2(MWContext *context, lo_DocState *state, - int32 x, int32 y, Bool check_float, Bool into_cells, Bool into_ilayers, - Bool editMode, int32 *ret_x, int32 *ret_y) -{ - Bool in_table, is_inflow_layer; - int32 line; - LO_Element *tptr, *eptr; - LO_Element *end_ptr; - LO_Element *tptrTable = NULL; - LO_Element *tptrCell = NULL; - - /* - * No document state yet. - */ - if (state == NULL) - { - return(NULL); - } - - tptr = NULL; - - line = lo_PointToLine(context, state, x, y); - -#ifdef LOCAL_DEBUG -XP_TRACE(("lo_PointToLine says line %d\n", line)); -#endif /* LOCAL_DEBUG */ - - lo_GetLineEnds(context, state, line, &tptr, &end_ptr); - - in_table = FALSE; - while (tptr != end_ptr) - { - int32 y2; - int32 x1; - int32 t_width, t_height; - - if (lo_IsDummyLayoutElement(tptr)) - { - tptr = tptr->lo_any.next; - continue; - } - - x1 = tptr->lo_any.x + tptr->lo_any.x_offset; - - t_width = tptr->lo_any.width; - /* - * Images need to account for border width - */ - if (tptr->type == LO_IMAGE) - { - t_width += (2 * tptr->lo_image.border_width); - /* - * If we're editing, images also account for their border space - */ - if ( editMode ) - { - t_width += 2 * tptr->lo_image.border_horiz_space; - x1 -= tptr->lo_image.border_horiz_space; - } - } - else if(tptr->type == LO_CELL && editMode ) - { - /* In editor, include intercell space so we - * don't "get lost" when clicking inbetween cells - * This assures a cell will be found if we are in a table - */ - t_width += tptr->lo_cell.inter_cell_space; - } - - if (t_width <= 0) - { - t_width = 1; - } - - t_height = tptr->lo_any.height; - /* - * Images need to account for border width - */ - if (tptr->type == LO_IMAGE) - { - t_height += (2 * tptr->lo_image.border_width); - - /* - * If we're editing, images also account for their border space - */ - if ( editMode ) - { - t_height += 2 * tptr->lo_image.border_vert_space; - } - } - else if(tptr->type == LO_CELL && editMode ) - { - t_height += tptr->lo_cell.inter_cell_space; - } - - is_inflow_layer = - (tptr->type == LO_CELL) && tptr->lo_cell.cell_inflow_layer; - - if (!in_table && !is_inflow_layer) - { - y2 = tptr->lo_any.y + tptr->lo_any.line_height; - if (tptr->lo_any.line_height <= 0) - { - y2 = tptr->lo_any.y + tptr->lo_any.y_offset + t_height; - } - } - else - { - y2 = tptr->lo_any.y + tptr->lo_any.y_offset + - t_height; - } - if ((y >= tptr->lo_any.y)&&(y < y2)) - { - if (tptr->type == LO_TABLE) - { - /* Save to return if no other elements are found */ - tptrTable = tptr; - } - if((x >= tptr->lo_any.x)&& - (x < (x1 + t_width))) - { - - /* - * Tables are containers. Don't stop on them, - * look inside them. - */ - if (tptr->type != LO_TABLE) - { - /* Inflow layers look just like table cells, but we - always look inside them, as if the layout elements - were part of the line's list of element's. */ - if (is_inflow_layer && into_ilayers) { - eptr = lo_XYToCellElement(context, state, - (LO_CellStruct *)tptr, x, y, - TRUE, into_cells, into_ilayers); - if (eptr) { - tptr = eptr; - break; - } - - /* No matching element found inside cell, keep - looking on rest of line. */ - } else - break; - } - else - { - in_table = TRUE; - } - } - } - tptr = tptr->lo_any.next; - } - if (tptr == end_ptr) - { - tptr = NULL; - } - - /* - * Check the floating element list. - */ - if ((tptr == NULL)&&(check_float != FALSE)) - { - LO_Element *eptr; - - eptr = state->float_list; - while (eptr != NULL) - { - int32 t_width, t_height; - - t_width = eptr->lo_any.width; - /* - * Images need to account for border width - */ - if (eptr->type == LO_IMAGE) - { - t_width = t_width + - (2 * eptr->lo_image.border_width); - } - if (t_width <= 0) - { - t_width = 1; - } - - t_height = eptr->lo_any.height; - /* - * Images need to account for border width - */ - if (eptr->type == LO_IMAGE) - { - t_height = t_height + - (2 * eptr->lo_image.border_width); - } - - if ((y >= eptr->lo_any.y)&& - (y < (eptr->lo_any.y + eptr->lo_any.y_offset + - t_height))) - { - if ((x >= eptr->lo_any.x)&& - (x < (eptr->lo_any.x + - eptr->lo_any.x_offset + - t_width))) - { - /* - * Tables are containers. - * Don't stop on them, - * look inside them. - */ - if (eptr->type != LO_TABLE) - { - break; - } - } - } - eptr = eptr->lo_any.next; - } - tptr = eptr; - } - - if ((tptr != NULL)&&(tptr->type == LO_SUBDOC)) - { - LO_SubDocStruct *subdoc; - int32 new_x, new_y; - int32 ret_new_x, ret_new_y; - - subdoc = (LO_SubDocStruct *)tptr; - - new_x = x - (subdoc->x + subdoc->x_offset + - subdoc->border_width); - new_y = y - (subdoc->y + subdoc->y_offset + - subdoc->border_width); - tptr = lo_XYToDocumentElement(context, - (lo_DocState *)subdoc->state, new_x, new_y, check_float, - into_cells, into_ilayers, &ret_new_x, &ret_new_y); - x = ret_new_x; - y = ret_new_y; - } - else if ((tptr != NULL)&&(tptr->type == LO_CELL)&&(into_cells != FALSE)) - { - /* - * Save the cell element - * to return if no other element is found - */ - tptrCell = tptr; - tptr = lo_XYToCellElement(context, state, &(tptr->lo_cell), - x, y, TRUE, into_cells, into_ilayers); - if (!tptr && editMode) - { - tptr = lo_XYToNearestCellElement(context, state, - &(tptrCell->lo_cell), - x, y); - if (!tptr) - tptr = tptrCell; - } - } - - *ret_x = x; - *ret_y = y; - - /* cmanske: Return table if no other element is found (we are before a table) - * or the element is a non-editable linefeed (we are after a table), - * and return this only if we are outside the table boundary - */ - if( editMode /*EDT_IS_EDITOR(context)*/ && tptrTable && !in_table && - (tptr == 0 || (tptr->type == LO_LINEFEED && tptr->lo_linefeed.break_type == LO_LINEFEED_BREAK_SOFT)) ) - { - tptr = tptrTable; - } - - return(tptr); -} - -LO_Element * -lo_XYToDocumentElement(MWContext *context, lo_DocState *state, - int32 x, int32 y, Bool check_float, Bool into_cells, Bool into_ilayers, - int32 *ret_x, int32 *ret_y) -{ - return lo_XYToDocumentElement2(context, state, x, y, check_float, into_cells, into_ilayers, FALSE, ret_x, ret_y); -} - -/************************************* - * Function: LO_XYToElement - * - * Description: This is a public function that allows the front end - * to ask for the particular element residing at the passed - * (x, y) position in the window. This is very important - * for resolving button clicks on anchors. - * - * Params: Window context, x, y position of the window location. - * - * Returns: A pointer to the element record at that location, - * or NULL if there is no matching element. - *************************************/ -LO_Element * -LO_XYToElement(MWContext *context, int32 x, int32 y, CL_Layer *layer) -{ - int32 doc_id; - lo_TopState *top_state; - lo_DocState *state; - LO_Element *tptr = NULL; - int32 ret_x, ret_y; - LO_CellStruct *layer_cell; - - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return(NULL); - } - state = top_state->doc_state; - - layer_cell = lo_GetCellFromLayer(context, layer); - - if (layer_cell != NULL) { - tptr = lo_XYToCellElement(context, - state, - layer_cell, - x, y, TRUE, TRUE, TRUE); - } - else - tptr = lo_XYToDocumentElement(context, state, x, y, TRUE, TRUE, TRUE, - &ret_x, &ret_y); - - if ((tptr == NULL)&&(top_state->is_grid != FALSE)) - { - tptr = lo_XYToGridEdge(context, state, x, y); - } - - /* - * Make sure we do not return an invisible edge. - */ - if ((tptr != NULL)&&(tptr->type == LO_EDGE)&& - (tptr->lo_edge.visible == FALSE)) - { - tptr = NULL; - } - return(tptr); -} - -static void -lo_set_image_info(MWContext *context, int32 ele_id, int32 width, int32 height) -{ - int32 doc_id; - lo_TopState *top_state; - lo_DocState *main_doc_state; - lo_DocState *state; - LO_ImageStruct *image; - -#ifdef EDITOR - if ( ele_id == ED_IMAGE_LOAD_HACK_ID ){ - EDT_SetImageInfo( context, ele_id, width, height ); - return; - } -#endif - - - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return; - } - main_doc_state = top_state->doc_state; - state = lo_CurrentSubState(main_doc_state); - - /* - * If the font stack has already been freed, we are too far gone - * to deal with delayed images coming in. Ignore them. - */ - if (state->font_stack == NULL) - { - top_state->layout_blocking_element = NULL; - return; - } - - if ((top_state->layout_blocking_element != NULL)&& - (top_state->layout_blocking_element->lo_any.ele_id == ele_id)) - { - image = (LO_ImageStruct *)top_state->layout_blocking_element; - - if (image->image_attr->attrmask & LO_ATTR_BACKDROP) - { - return; - } - - image->width = width; - image->height = height; - lo_FinishImage(context, state, image); - - TIMING_STOPCLOCK_NAME("lo:blk-img", image->image_url, context, "ok"); - lo_FlushBlockage(context, state, main_doc_state); - } - else if (top_state->tags != NULL) - { - PA_Tag *tag_ptr; - - tag_ptr = top_state->tags; - while (tag_ptr != NULL) - { - if (((tag_ptr->type == P_IMAGE)|| - (tag_ptr->type == P_NEW_IMAGE))&& - (tag_ptr->lo_data != NULL)&& - (tag_ptr->is_end == FALSE)) - { - image = (LO_ImageStruct *)tag_ptr->lo_data; - if (image->ele_id == ele_id) - { - image->width = width; - image->height = height; - break; - } - } - tag_ptr = tag_ptr->next; - } - } -} - -typedef struct setImageInfoClosure_struct -{ - MWContext *context; - int32 ele_id; - int32 width; - int32 height; - struct setImageInfoClosure_struct - *next; -} setImageInfoClosure; - -static int8 deferred_list_busy = 0; -static int8 destroy_deferred_list = 0; - -/* List of images for which image size info is available, - but for which the layout process is deferred */ -static setImageInfoClosure *image_info_deferred_list; -static void *deferred_image_info_timeout = NULL; - -static void -lo_discard_unprocessed_deferred_images(MWContext *context) -{ - setImageInfoClosure *c, *prev_c; - - prev_c = NULL; - c = image_info_deferred_list; - if (deferred_list_busy) - { - /* set a flag to cause the list to get destroyed - * as soon as we are not reentrant - */ - destroy_deferred_list = TRUE; - return; - } - else - { - destroy_deferred_list = FALSE; - } - - while (c) { - if(c->context == context) { - setImageInfoClosure *free_tmp; - - if(prev_c) - prev_c->next = c->next; - else - image_info_deferred_list = c->next; - - free_tmp = c; - c = c->next; - XP_FREE(free_tmp); - } - else - { - prev_c = c; - c = c->next; - } - } -} - - -/* A helper routine that adds a context to a set of contexts ready for - reflow, but only if the context isn't already present in the - set. */ -static void -lo_AddContextToReflow(PLVector* v, MWContext* context) -{ - PR_ASSERT(v); - if (v) { - PRUint32 size = PL_VectorGetSize(v); - PRUint32 i; - - for (i = 0; i < size; ++i) { - if (PL_VectorGet(v, i) == context) - return; - } - - PL_VectorAdd(v, context); - } -} - -/* Handle image dimension information that has been reported to - layout since the last time we were called. */ -static void -lo_process_deferred_image_info(void *closure) -{ - setImageInfoClosure *c, *next_c; - PLVector contextsToReflow; - PL_VectorInitialize(&contextsToReflow, 0, 0); - - /* Don't allow reentrant calls. */ - if (deferred_list_busy) - return; - - deferred_list_busy = 1; - for (c = image_info_deferred_list; c; c = next_c) { - next_c = c->next; - lo_set_image_info(c->context, c->ele_id, c->width, c->height); - - /* Determine if the image is visible, and if so, add the - context that contains it to the set of contexts that need - to be reflowed. */ - { - lo_TopState* top_state = lo_FetchTopState(XP_DOCID(c->context)); - PR_ASSERT(top_state); - - /* Do not perform reflow for Aurora custom icons (MWContextIcon) */ - if (top_state && (c->context->type != MWContextIcon)) { - int32 docWidth = LO_GetLayerScrollWidth(top_state->body_layer); - int32 docHeight = LO_GetLayerScrollHeight(top_state->body_layer); - int32 docX, docY; - LO_ImageStruct* image; - - FE_GetDocPosition(c->context, FE_VIEW, &docX, &docY); - - image = top_state->doc_lists.image_list; - while (image) { - if (image->ele_id == c->ele_id) - break; - - image = image->next_image; - } - - if (image - && /* It's visible */ - ((image->x + c->width >= docX) && - (image->y + c->height >= docY) && - (image->x <= docX + docWidth) && - (image->y <= docY + docHeight))) { - /* If the image is visible, the context needs to be reflowed */ - lo_AddContextToReflow(&contextsToReflow, c->context); - } - } - } - - if(destroy_deferred_list) - { - /* discared the images for the context that just tried to - * call lo_discard_unprocessed_deferred_images. After - * that continue to pump this list until empty. - */ - image_info_deferred_list = c; - deferred_list_busy = FALSE; - lo_discard_unprocessed_deferred_images(image_info_deferred_list->context); - deferred_list_busy = TRUE; - next_c = image_info_deferred_list; - } - else - { - XP_FREE(c); - } - } - deferred_list_busy = 0; - image_info_deferred_list = NULL; - deferred_image_info_timeout = NULL; - - /* Iterate through the contexts that need to be reflowed: if - layout is complete in that context, then reflow *now*: there's - an incorrectly sized, visible image. */ - { - PRUint32 size = PL_VectorGetSize(&contextsToReflow); - PRUint32 i; - - for (i = 0; i < size; ++i) { - lo_TopState* top_state; - MWContext* context = (MWContext*) PL_VectorGet(&contextsToReflow, i); - - PR_ASSERT(context); - if (!context) - continue; - - top_state = lo_FetchTopState(XP_DOCID(context)); - PR_ASSERT(top_state); - if (!top_state) - continue; - - /* We reflow *immediately* if layout is done. */ - - if (!LO_LayingOut(context)) - LO_RelayoutFromElement(context, NULL); - } - - PL_VectorFinalize(&contextsToReflow); - } -} - -/* Tell layout the dimensions of an image. Actually, to avoid subtle - bugs involving mutual recursion between the imagelib and the - netlib, we don't process this information immediately, but rather - thread it on a list to be processed later. */ -void -LO_SetImageInfo(MWContext *context, int32 ele_id, int32 width, int32 height) -{ - setImageInfoClosure *c = XP_NEW(setImageInfoClosure); - - if (! c) - return; - c->context = context; - c->ele_id = ele_id; - c->width = width; - c->height = height; - c->next = image_info_deferred_list; - image_info_deferred_list = c; - - if (! deferred_image_info_timeout) { - deferred_image_info_timeout = - FE_SetTimeout(lo_process_deferred_image_info, NULL, 0); - } -} - -void -lo_DeleteDocLists(MWContext *context, lo_DocLists *doc_lists) -{ - if ( doc_lists->url_list != NULL) - { - int i; - LO_AnchorData **anchor_array; - -#ifdef XP_WIN16 - { - XP_Block *ulist_array; - int32 j; - intn a_size, a_indx, a_url; - - a_size = SIZE_LIMIT / sizeof(XP_Block *); - a_indx = doc_lists->url_list_len / a_size; - a_url = doc_lists->url_list_len - (a_indx * a_size); - - XP_LOCK_BLOCK(ulist_array, XP_Block *, doc_lists->ulist_array); - for (j=0; j < (doc_lists->ulist_array_size - 1); j++) - { - doc_lists->url_list = ulist_array[j]; - XP_LOCK_BLOCK(anchor_array, LO_AnchorData **, - doc_lists->url_list); - for (i=0; i < a_size; i++) - { - if (anchor_array[i] != NULL) - { - lo_DestroyAnchor(anchor_array[i]); - } - } - XP_UNLOCK_BLOCK(doc_lists->url_list); - XP_FREE_BLOCK(doc_lists->url_list); - } - doc_lists->url_list = ulist_array[doc_lists->ulist_array_size - 1]; - XP_LOCK_BLOCK(anchor_array, LO_AnchorData **, - doc_lists->url_list); - for (i=0; i < a_url; i++) - { - if (anchor_array[i] != NULL) - { - lo_DestroyAnchor(anchor_array[i]); - } - } - XP_UNLOCK_BLOCK(doc_lists->url_list); - XP_FREE_BLOCK(doc_lists->url_list); - - XP_UNLOCK_BLOCK(doc_lists->ulist_array); - XP_FREE_BLOCK(doc_lists->ulist_array); - } -#else - XP_LOCK_BLOCK(anchor_array, LO_AnchorData **, - doc_lists->url_list); - for (i=0; i < doc_lists->url_list_len; i++) - { - if (anchor_array[i] != NULL) - { - lo_DestroyAnchor(anchor_array[i]); - } - } - XP_UNLOCK_BLOCK(doc_lists->url_list); - XP_FREE_BLOCK(doc_lists->url_list); -#endif /* XP_WIN16 */ - doc_lists->url_list = NULL; - doc_lists->url_list_len = 0; - } - - if (doc_lists->name_list != NULL) - { - lo_NameList *nptr; - - nptr = doc_lists->name_list; - while (nptr != NULL) - { - lo_NameList *name_rec; - - name_rec = nptr; - nptr = nptr->next; - if (name_rec->name != NULL) - { - PA_FREE(name_rec->name); - } - XP_DELETE(name_rec); - } - doc_lists->name_list = NULL; - doc_lists->anchor_count = 0; - } - - if ( doc_lists->form_list != NULL) - { - lo_FormData *fptr; - - fptr = doc_lists->form_list; - while (fptr != NULL) - { - lo_FormData *form; - - form = fptr; - fptr = fptr->next; - if (form->name != NULL) - { - PA_FREE(form->name); - } - if (form->action != NULL) - { - PA_FREE(form->action); - } - if (form->form_elements != NULL) - { - PA_FREE(form->form_elements); - } - XP_DELETE(form); - } - doc_lists->form_list = NULL; - doc_lists->current_form_num = 0; - } - - doc_lists->embed_list = NULL; - doc_lists->embed_list_count = 0; - doc_lists->applet_list = NULL; - doc_lists->applet_list_count = 0; - doc_lists->image_list = doc_lists->last_image = NULL; - doc_lists->image_list_count = 0; -} - -/* XXX need to pass resize_reload through FE_FreeGridWindow */ -static pa_DocData *lo_internal_doc_data; - -LO_Element * -lo_InternalDiscardDocument(MWContext *context, lo_DocState *state, - pa_DocData *doc_data, Bool bWholeDoc) -{ - int32 doc_id; - LO_Element *recycle_list; - LO_Element **line_array; - LO_TextAttr **text_attr_hash; - - /* Look in doc_data->url_struct for the *new* document's reload flag. */ - JSBool resize_reload = - (JSBool)(doc_data != NULL && doc_data->url_struct->resize_reload); - - /* XXX We're not getting rid of stuff on the deferred image list when - * the editor does a relayout. The problem is that there might still be - * entries on the list that corresponds to the old state of the document. - */ - if (bWholeDoc) - lo_discard_unprocessed_deferred_images(context); - - /* - * Order is crucial here: run the onunload handlers in a frames tree - * from the top down, but destroy frames bottom-up. Look for the - * LM_ReleaseDocument call below, almost at the end of this function. - * This way, onunload handlers get to use their kids' properties, and - * kids get to use their parent's properties and functions. - */ - if (bWholeDoc) - { - pa_DocData *old_doc_data; - - old_doc_data = state->top_state->doc_data; - if (old_doc_data != NULL) - { - NET_StreamClass *parser_stream; - parser_stream = old_doc_data->parser_stream; - parser_stream->abort(parser_stream, 0); - state->top_state->doc_data = NULL; - } - } - -#ifdef LAYPROBE_API - { - /* Send a notification when a frame unloads */ - XP_List * pList = LAPIGetCallbackFuncList((int32)FRAME_ON_UNLOAD); - - if (pList) - { - while (pList = pList->next) - { - if (pList->object) - (*((ID_NOTIFY_PT)pList->object))((void*)context); - } - } - - /* clean up allocated memory */ - if (state->top_state->LAPIprobe) - { - LAPIDestroyProbe(state->top_state->LAPIprobe); - state->top_state->LAPIprobe = NULL; - } - } -#endif /* LAYPROBE_API */ - - if ( state->top_state->trash != NULL) - { - lo_RecycleElements(context, state, - state->top_state->trash); - state->top_state->trash = NULL; - } - - if (state->float_list != NULL) - { - lo_RecycleElements(context, state, state->float_list); - state->float_list = NULL; - } - - if (state->line_array != NULL) - { - LO_Element *eptr; - LO_Element **line_array_tmp; - -#ifdef XP_WIN16 - { - XP_Block *larray_array; - intn cnt; - - XP_LOCK_BLOCK(larray_array, XP_Block *, - state->larray_array); - cnt = state->larray_array_size - 1; - while (cnt > 0) - { - XP_FREE_BLOCK(larray_array[cnt]); - cnt--; - } - state->line_array = larray_array[0]; - XP_UNLOCK_BLOCK(state->larray_array); - XP_FREE_BLOCK(state->larray_array); - } -#endif /* XP_WIN16 */ - - eptr = NULL; - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array); - eptr = line_array[0]; - line_array_tmp = (LO_Element **)state->line_array; - state->line_array = NULL; - - /* If this is a relayout delete, the elements are already owned by the document. So - * don't recycle them. - */ - if ( bWholeDoc && eptr != NULL) - { - lo_RecycleElements(context, state, eptr); - } - XP_UNLOCK_BLOCK(line_array_tmp); - XP_FREE_BLOCK(line_array_tmp); - } - - if ( bWholeDoc && state->top_state->text_attr_hash != NULL) - { - LO_TextAttr *attr; - LO_TextAttr *attr_ptr; - int i; - - XP_LOCK_BLOCK(text_attr_hash, LO_TextAttr **, - state->top_state->text_attr_hash); - for (i=0; iFE_Data != NULL) - { - FE_ReleaseTextAttrFeData(context, attr); - attr->FE_Data = NULL; - } - attr_ptr = attr_ptr->next; - XP_DELETE(attr); - } - text_attr_hash[i] = NULL; - } - XP_UNLOCK_BLOCK(state->top_state->text_attr_hash); - XP_FREE_BLOCK(state->top_state->text_attr_hash); - state->top_state->text_attr_hash = NULL; - } - - if ( bWholeDoc && state->top_state->font_face_array != NULL) - { - int i; - char **face_list; - - PA_LOCK(face_list, char **, state->top_state->font_face_array); - for (i=0; i < state->top_state->font_face_array_len; i++) - { - XP_FREE(face_list[i]); - } - PA_UNLOCK(state->top_state->font_face_array); - PA_FREE(state->top_state->font_face_array); - state->top_state->font_face_array = NULL; - state->top_state->font_face_array_len = 0; - state->top_state->font_face_array_size = 0; - } - - if ( bWholeDoc && state->top_state->map_list != NULL) - { - lo_MapRec *map_list; - - map_list = state->top_state->map_list; - while (map_list != NULL) - { - map_list = lo_FreeMap(map_list); - } - state->top_state->map_list = NULL; - } - - if (bWholeDoc) - lo_DeleteDocLists(context, &state->top_state->doc_lists); - else if (state->top_state->doc_lists.name_list != NULL) - { - lo_NameList *nptr; - - nptr = state->top_state->doc_lists.name_list; - while (nptr != NULL) - { - lo_NameList *name_rec; - - name_rec = nptr; - nptr = nptr->next; - if (name_rec->name != NULL) - { - PA_FREE(name_rec->name); - } - XP_DELETE(name_rec); - } - state->top_state->doc_lists.name_list = NULL; - } - - if ( bWholeDoc && state->top_state->the_grid != NULL) - { - pa_DocData *save; - lo_GridRec *grid; - lo_GridCellRec *cell_ptr; - Bool incomplete; - - save = lo_internal_doc_data; - lo_internal_doc_data = doc_data; - grid = state->top_state->the_grid; - cell_ptr = grid->cell_list; - /* - * If this grid document finished loading, save - * its grid data to be restored when we return through - * history. - * We still have to free the FE grid windows. - */ - incomplete = (state->top_state->layout_status != PA_COMPLETE); - if (incomplete == FALSE) - { - while (cell_ptr != NULL) - { - intn cell_status; - char *old_url; - - cell_status = - lo_GetCurrentGridCellStatus(cell_ptr); - - /* - * Only save cell history for COMPLETE cells. - */ - if (cell_status == PA_COMPLETE) - { - /* - * free the original url for this cell. - */ - old_url = cell_ptr->url; - if (cell_ptr->url != NULL) - { - XP_FREE(cell_ptr->url); - } - - /* - * Fetch the url for the current contents - * of the cell, and save that. - */ - cell_ptr->url = - lo_GetCurrentGridCellUrl(cell_ptr); - - cell_ptr->hist_list = NULL; - if (cell_ptr->context != NULL) - { - cell_ptr->hist_list = FE_FreeGridWindow( - cell_ptr->context, TRUE); - } - } - else - { - incomplete = TRUE; - cell_ptr->hist_list = NULL; - if (cell_ptr->context != NULL) - { - (void)FE_FreeGridWindow( - cell_ptr->context, FALSE); - } - } - cell_ptr->context = NULL; - - cell_ptr = cell_ptr->next; - } - } - /* - * Check again in case one or more frames were incomplete. - * Also, some special windows have no history (such as - * the document info window). We can't save grid - * data for those windows and should free it instead. - */ - if ((incomplete == FALSE)&& - (state->top_state->savedData.Grid != NULL)) - { - state->top_state->savedData.Grid->the_grid = - state->top_state->the_grid; - state->top_state->savedData.Grid->main_width = - grid->main_width; - state->top_state->savedData.Grid->main_height = - grid->main_height; - } - /* - * Else free up everything now. - */ - else - { - cell_ptr = grid->cell_list; - /* - * It is important to NULL out the cell_list - * now because FE_FreeGridWindow() could lead to - * somone trying to traverse it while we are in - * the middle of deleting it. - */ - grid->cell_list = NULL; - while (cell_ptr != NULL) - { - lo_GridCellRec *tmp_cell; - - if (cell_ptr->context != NULL) - { - /* - * The context still owns its history - * list, so null the cell's pointer to - * be clear. If this cell doesn't have - * a context, then it owns the history - * list and lo_FreeGridCellRec() will - * free it. - */ - cell_ptr->hist_list = NULL; - (void)FE_FreeGridWindow( - cell_ptr->context, FALSE); - } - tmp_cell = cell_ptr; - cell_ptr = cell_ptr->next; - lo_FreeGridCellRec(context, grid, tmp_cell); - } - lo_FreeGridRec(grid); - } - state->top_state->the_grid = NULL; - lo_internal_doc_data = save; - } - - if ( bWholeDoc && state->top_state->url != NULL) - { - XP_FREE(state->top_state->url); - state->top_state->url = NULL; - } - - if ( bWholeDoc ) - { - XP_FREEIF(state->top_state->inline_stream_blocked_base_url); - XP_FREEIF(state->top_state->main_stream_blocked_base_url); - XP_FREEIF(state->top_state->base_url); - } - - if ( bWholeDoc && state->top_state->base_target != NULL) - { - XP_FREE(state->top_state->base_target); - state->top_state->base_target = NULL; - } - - if ( bWholeDoc && state->top_state->name_target != NULL) - { - XP_FREE(state->top_state->name_target); - state->top_state->name_target = NULL; - } - -#ifdef HTML_CERTIFICATE_SUPPORT - if ( bWholeDoc && state->top_state->cert_list != NULL) - { - lo_Certificate *cptr; - - cptr = state->top_state->cert_list; - while (cptr != NULL) - { - lo_Certificate *lo_cert; - - lo_cert = cptr; - cptr = cptr->next; - if (lo_cert->name != NULL) - { - PA_FREE(lo_cert->name); - } - if (lo_cert->cert != NULL) - { - CERT_DestroyCertificate(lo_cert->cert); - } - XP_DELETE(lo_cert); - } - state->top_state->cert_list = NULL; - } -#endif /* HTML_CERTIFICATE_SUPPORT */ - - if (bWholeDoc && state->top_state->unknown_head_tag != NULL) - { - XP_FREE(state->top_state->unknown_head_tag); - state->top_state->unknown_head_tag = NULL; - } - - if(resize_reload) - { - /* LJM: Save the JSS state in the hist so that we can get it - * once the resize is complete - */ - History_entry *he = SHIST_GetCurrent(&context->hist); - if (he) - { - he->savedData.style_stack = state->top_state->style_stack; - state->top_state->style_stack = 0; - } - else - { - if (state->top_state->style_stack != 0) - STYLESTACK_Delete(state->top_state->style_stack); - state->top_state->style_stack = 0; - } - } - else - { - if (state->top_state->style_stack != 0) - STYLESTACK_Delete(state->top_state->style_stack); - state->top_state->style_stack = 0; - } - - /* XXX all this because grid docs are never re-parsed after first load. */ - if (!resize_reload && - ((state->top_state->savedData.OnLoad != NULL)|| - (state->top_state->savedData.OnUnload != NULL)|| - (state->top_state->savedData.OnFocus != NULL)|| - (state->top_state->savedData.OnBlur != NULL)|| - (state->top_state->savedData.OnHelp != NULL)|| - (state->top_state->savedData.OnMouseOver != NULL)|| - (state->top_state->savedData.OnMouseOut != NULL)|| - (state->top_state->savedData.OnDragDrop != NULL)|| - (state->top_state->savedData.OnMove != NULL)|| - (state->top_state->savedData.OnResize != NULL))) - { - History_entry *he = SHIST_GetCurrent(&context->hist); - if (he) - { - he->savedData.OnLoad = state->top_state->savedData.OnLoad; - he->savedData.OnUnload = state->top_state->savedData.OnUnload; - he->savedData.OnFocus = state->top_state->savedData.OnFocus; - he->savedData.OnBlur = state->top_state->savedData.OnBlur; - he->savedData.OnHelp = state->top_state->savedData.OnHelp; - he->savedData.OnMouseOver = state->top_state->savedData.OnMouseOver; - he->savedData.OnMouseOut = state->top_state->savedData.OnMouseOut; - he->savedData.OnDragDrop = state->top_state->savedData.OnDragDrop; - he->savedData.OnMove = state->top_state->savedData.OnMove; - he->savedData.OnResize = state->top_state->savedData.OnResize; - } - else - { - if (state->top_state->savedData.OnLoad != NULL) - PA_FREE(state->top_state->savedData.OnLoad); - if (state->top_state->savedData.OnUnload != NULL) - PA_FREE(state->top_state->savedData.OnUnload); - if (state->top_state->savedData.OnFocus != NULL) - PA_FREE(state->top_state->savedData.OnFocus); - if (state->top_state->savedData.OnBlur != NULL) - PA_FREE(state->top_state->savedData.OnBlur); - if (state->top_state->savedData.OnHelp != NULL) - PA_FREE(state->top_state->savedData.OnHelp); - if (state->top_state->savedData.OnMouseOver != NULL) - PA_FREE(state->top_state->savedData.OnMouseOver); - if (state->top_state->savedData.OnMouseOut != NULL) - PA_FREE(state->top_state->savedData.OnMouseOut); - if (state->top_state->savedData.OnDragDrop != NULL) - PA_FREE(state->top_state->savedData.OnDragDrop); - if (state->top_state->savedData.OnMove != NULL) - PA_FREE(state->top_state->savedData.OnMove); - if (state->top_state->savedData.OnResize != NULL) - PA_FREE(state->top_state->savedData.OnResize); - } - state->top_state->savedData.OnLoad = NULL; - state->top_state->savedData.OnUnload = NULL; - state->top_state->savedData.OnFocus = NULL; - state->top_state->savedData.OnBlur = NULL; - state->top_state->savedData.OnHelp = NULL; - state->top_state->savedData.OnMouseOver = NULL; - state->top_state->savedData.OnMouseOut = NULL; - state->top_state->savedData.OnDragDrop = NULL; - state->top_state->savedData.OnMove = NULL; - state->top_state->savedData.OnResize = NULL; - } - - - if ( bWholeDoc ) - { -#ifdef WEBFONTS - /* Release webfonts loaded by this document */ - if (WF_fbu && !resize_reload) - { - nffbu_ReleaseWebfonts(WF_fbu, context, NULL); - } -#endif /* WEBFONTS */ - - recycle_list = state->top_state->recycle_list; - - /* Some lo_ImageStructs may have been reclaimed by the Memory Arenas - code without actually calling IL_DestroyImage first. This call - frees up any remaining image lib requests. */ - IL_DestroyImageGroup(context->img_cx); - - lo_DestroyBlinkers(context); - if (state->top_state->layers) - { - int i; - lo_TopState *top_state = state->top_state; - - /* If we're resizing, prevent the GC'ing of the JS object - * associated with this layer when the layer destructor is - * called, since we want to preserve it across a resize, - * except for those layers created with JS's new operator, - * which aren't preserved across resize. */ - if (resize_reload) - { - for (i = 1; i <= state->top_state->max_layer_num; i++) - { - lo_LayerDocState *layer_state = state->top_state->layers[i]; - if (!layer_state || layer_state->is_constructed_layer) - continue; - - layer_state->mocha_object = NULL; - state->top_state->layers[i] = NULL; - } - } - - /* Delete the main document layer_state */ - top_state->layers[0]->layer = NULL; - lo_DeleteLayerState(context, state, top_state->layers[0]); - - top_state->num_layers_allocated = 0; - top_state->max_layer_num = 0; - - lo_DeleteLayerStack(state); - } - - if (context->compositor){ - lo_DestroyLayers(context); - - /* Reset the compositor to do on-screen compositing by default. */ - CL_SetCompositorOffscreenDrawing(context->compositor, - CL_OFFSCREEN_AUTO); - CL_SetCompositorEnabled(context->compositor, PR_FALSE); - } - XP_FREEIF(state->top_state->layers); - } - - if ( bWholeDoc ) { - /* throw out mocha cruft */ - ET_ReleaseDocument(context, resize_reload); - - XP_DELETE(state->top_state); - XP_DELETE(state); - /* - * Get the unique document ID, and remove this - * documents layout state. - */ - doc_id = XP_DOCID(context); - lo_RemoveTopState(doc_id); - - } - else - { - XP_DELETE(state); - recycle_list = NULL; - } - return(recycle_list); -} - - -void -LO_DiscardDocument(MWContext *context) -{ - int32 doc_id; - lo_TopState *top_state; - lo_DocState *state; - LO_Element *recycle_list; - int32 cnt; -#ifdef MEMORY_ARENAS - lo_arena *old_arena=NULL; -#endif /* MEMORY_ARENAS */ - - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return; - } - state = top_state->doc_state; - -#ifdef MEMORY_ARENAS - if ( ! EDT_IS_EDITOR(context) ) { - old_arena = top_state->first_arena; - } -#endif /* MEMORY_ARENAS */ - - /* - * Order is crucial here: run the onunload handlers in a frames tree - * from the top down, but destroy frames bottom-up. Look for the - * LM_ReleaseDocument call below, almost at the end of this function. - * This way, onunload handlers get to use their kids' properties, and - * kids get to use their parent's properties and functions. - */ - ET_SendLoadEvent(context, EVENT_UNLOAD, NULL, NULL, - LO_DOCUMENT_LAYER_ID, FALSE); - - /* make sure no other threads are looking at our structures */ - LO_LockLayout(); - - lo_SaveFormElementState(context, state, TRUE); - /* - * If this document has no session history - * this data is not saved. - * It will be freed by history cleanup. - */ - if (SHIST_GetCurrent(&context->hist) == NULL) - { - top_state->savedData.FormList = NULL; - top_state->savedData.EmbedList = NULL; - top_state->savedData.Grid = NULL; - } - recycle_list = - lo_InternalDiscardDocument(context, state, lo_internal_doc_data, TRUE); - /* see first lo_FreeRecycleList comment. safe */ - cnt = lo_FreeRecycleList(context, recycle_list); -#ifdef MEMORY_ARENAS - if ( ! EDT_IS_EDITOR(context) ) { - cnt = lo_FreeMemoryArena(old_arena); - } -#endif /* MEMORY_ARENAS */ - - /* we currently have no document loaded */ - context->doc_id = 0; - - /* the danger has passed. let others look up our shorts again */ - LO_UnlockLayout(); - -} - - -lo_SavedFormListData * -lo_NewDocumentFormListData(void) -{ - lo_SavedFormListData *fptr; - - fptr = XP_NEW(lo_SavedFormListData); - if (fptr == NULL) - { - return(NULL); - } - - fptr->valid = FALSE; - fptr->data_index = 0; - fptr->data_count = 0; - fptr->data_list = NULL; - fptr->next = NULL; - - return(fptr); -} - - -void -LO_FreeDocumentFormListData(MWContext *context, void *data) -{ - lo_SavedFormListData *forms = (lo_SavedFormListData *)data; - - if (forms != NULL) - { - lo_FreeDocumentFormListData(context, forms); - XP_DELETE(forms); - } -} - - -lo_SavedGridData * -lo_NewDocumentGridData(void) -{ - lo_SavedGridData *sgptr; - - sgptr = XP_NEW(lo_SavedGridData); - if (sgptr == NULL) - { - return(NULL); - } - - sgptr->main_width = 0; - sgptr->main_height = 0; - sgptr->the_grid = NULL; - - return(sgptr); -} - - -void -LO_FreeDocumentGridData(MWContext *context, void *data) -{ - lo_SavedGridData *sgptr = (lo_SavedGridData *)data; - - if (sgptr != NULL) - { - lo_FreeDocumentGridData(context, sgptr); - XP_DELETE(sgptr); - } -} - - -lo_SavedEmbedListData * -lo_NewDocumentEmbedListData(void) -{ - lo_SavedEmbedListData *eptr; - - eptr = XP_NEW(lo_SavedEmbedListData); - if (eptr == NULL) - { - return(NULL); - } - - eptr->embed_count = 0; - eptr->embed_data_list = NULL; - - return(eptr); -} - - -void -LO_FreeDocumentEmbedListData(MWContext *context, void *data) -{ - lo_SavedEmbedListData *eptr = (lo_SavedEmbedListData *)data; - - if (eptr != NULL) - { - lo_FreeDocumentEmbedListData(context, eptr); - XP_DELETE(eptr); - } -} - -void -LO_HighlightAnchor(MWContext *context, LO_Element *element, Bool on) -{ - int32 doc_id; - lo_TopState *top_state; - lo_DocState *state; - LO_Element *start, *end; - LO_AnchorData *anchor; - - /* - * Get the unique document ID, and retrieve this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return; - } - state = top_state->doc_state; - - if (element == NULL) - return; - - anchor = lo_GetElementAnchor(element); - if (anchor == NULL) - return; - - /* Find all the preceding layout elements that share the same anchor. */ - start = element; - while (start->lo_any.prev) - { - LO_AnchorData *anchor2 = lo_GetElementAnchor(start->lo_any.prev); - if (anchor != anchor2) - break; - start = start->lo_any.prev; - } - - /* Find all the following layout elements that share the same anchor. */ - end = element; - while (end->lo_any.next) - { - LO_AnchorData *anchor2 = lo_GetElementAnchor(end->lo_any.next); - if (anchor != anchor2) - break; - end = end->lo_any.next; - } - - end = end->lo_any.next; - element = start; - while (element != end) - { - Bool restoreUnselected; - LO_Color save_fg; - - element->lo_any.x += state->base_x; - element->lo_any.y += state->base_y; - - restoreUnselected = FALSE; - switch (element->type) - { - case LO_IMAGE: - /* Save image selection state */ - if (! (element->lo_image.ele_attrmask & LO_ELE_SELECTED)) - restoreUnselected = TRUE; - - /* Force display of selection rectangle. */ - element->lo_image.ele_attrmask = LO_ELE_SELECTED; - - /* Fall through ... */ - - case LO_TEXT: - case LO_SUBDOC: - - /* Temporarily set element color to selection color. */ - if (on) { - lo_GetElementFGColor(element, &save_fg); - lo_SetElementFGColor(element, &state->active_anchor_color); - } - - /* Use the compositor to synchronously update the element's area. */ - lo_RefreshElement(element, anchor->layer, TRUE); - - /* Restore the element's color. */ - if (on) - lo_SetElementFGColor(element, &save_fg); - - /* Restore image selection state */ - if (restoreUnselected) - element->lo_image.ele_attrmask &= ~(LO_ELE_SELECTED); - - default: - /* No highlighting for other types of elements */ - break; - } - - element->lo_any.x -= state->base_x; - element->lo_any.y -= state->base_y; - - element = element->lo_any.next; - } -} - -LO_Element * -LO_XYToNearestElement(MWContext *context, int32 x, int32 y, CL_Layer *layer) -{ - int32 doc_id; - lo_TopState *top_state; - lo_DocState *state; - LO_Element *eptr; - LO_Element **line_array; - int32 ret_x, ret_y; - LO_CellStruct *layer_cell; - - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return(NULL); - } - state = top_state->doc_state; - - layer_cell = lo_GetCellFromLayer(context, layer); - if (layer_cell != NULL) - { - int32 new_x, new_y; - - new_y = y; - if (new_y > layer_cell->height) - new_y = layer_cell->height - 1; - if (new_y < 0) - new_y = 0; - - new_x = x; - if (new_x > layer_cell->width) - new_x = layer_cell->width - 1; - if (new_x < 0) - new_x = 0; - eptr = lo_XYToNearestCellElement(context, - state, - layer_cell, new_x, new_y); - return eptr; - } - - if (x <= state->win_left) - { - x = state->win_left + 1; - } - - if (y < state->win_top) - { - y = state->win_top + 1; - } - - eptr = lo_XYToDocumentElement(context, state, x, y, TRUE, TRUE, TRUE, - &ret_x, &ret_y); - - if (eptr == NULL) - { - int32 top, bottom; - - /* - * Find the nearest line. - */ - lo_RegionToLines (context, state, x, y, 1, 1, FALSE, - &top, &bottom); - - if (top >= 0) -#ifdef XP_WIN16 - { - intn a_size; - intn a_indx; - intn a_line; - XP_Block *larray_array; - - a_size = SIZE_LIMIT / sizeof(LO_Element *); - a_indx = (intn)(top / a_size); - a_line = (intn)(top - (a_indx * a_size)); - XP_LOCK_BLOCK(larray_array, XP_Block *, - state->larray_array); - state->line_array = larray_array[a_indx]; - XP_LOCK_BLOCK(line_array, LO_Element **, - state->line_array); - eptr = line_array[a_line]; - XP_UNLOCK_BLOCK(state->line_array); - XP_UNLOCK_BLOCK(state->larray_array); - } -#else - { - XP_LOCK_BLOCK(line_array, LO_Element **, - state->line_array); - eptr = line_array[top]; - XP_UNLOCK_BLOCK(state->line_array); - } -#endif /* XP_WIN16 */ - - /* - * The nearest line may be a table with cells. In which case - * we really need to move into that table to find the nearest - * cell, and possibly nearest element in that cell. - */ - if ((eptr != NULL)&&(eptr->type == LO_TABLE)&& - (eptr->lo_any.next->type == LO_CELL)) - { - LO_Element *new_eptr; - - new_eptr = eptr->lo_any.next; - /* - * Find the cell that overlaps in Y. Move to the lower - * cell if between cells. - */ - while ((new_eptr != NULL)&&(new_eptr->type == LO_CELL)) - { - int32 y2; - - y2 = new_eptr->lo_any.y + new_eptr->lo_any.y_offset + - new_eptr->lo_any.height + - (2 * new_eptr->lo_cell.border_width); - if (y <= y2) - { - break; - } - new_eptr = new_eptr->lo_any.next; - } - /* - * If we walked through the table to a non-cell element - * and still didn't match, match to the last cell in - * the table. - */ - if ((new_eptr != NULL)&&(new_eptr->type != LO_CELL)) - { - new_eptr = new_eptr->lo_any.prev; - } - - /* - * If new_eptr is not NULL it is the cell we matched. - * Move us just into that cell and see if we can match - * an element inside it. - */ - if ((new_eptr != NULL)&&(new_eptr->type == LO_CELL)) - { - LO_Element *cell_eptr; - int32 new_x, new_y; - - new_y = y; - if (new_y >= (new_eptr->lo_any.y + - new_eptr->lo_any.y_offset + - new_eptr->lo_cell.border_width + - new_eptr->lo_any.height)) - { - new_y = new_eptr->lo_any.y + - new_eptr->lo_any.y_offset + - new_eptr->lo_cell.border_width + - new_eptr->lo_any.height - 1; - } - if (new_y < (new_eptr->lo_any.y + - new_eptr->lo_any.y_offset + - new_eptr->lo_cell.border_width)) - { - new_y = new_eptr->lo_any.y + - new_eptr->lo_any.y_offset + - new_eptr->lo_cell.border_width; - } - new_x = x; - if (new_x >= (new_eptr->lo_any.x + - new_eptr->lo_any.x_offset + - new_eptr->lo_cell.border_width + - new_eptr->lo_any.width)) - { - new_x = new_eptr->lo_any.x + - new_eptr->lo_any.x_offset + - new_eptr->lo_cell.border_width + - new_eptr->lo_any.width - 1; - } - if (new_x < (new_eptr->lo_any.x + - new_eptr->lo_any.x_offset + - new_eptr->lo_cell.border_width)) - { - new_x = new_eptr->lo_any.x + - new_eptr->lo_any.x_offset + - new_eptr->lo_cell.border_width; - } - cell_eptr = lo_XYToNearestCellElement(context, state, - (LO_CellStruct *)new_eptr, new_x, new_y); - if (cell_eptr != NULL) - { - new_eptr = cell_eptr; - } - } - if (new_eptr != NULL) - { - eptr = new_eptr; - } - } - } - - return(eptr); -} - -static void -lo_RefreshCellAnchors(lo_DocState *state, LO_CellStruct *cell); - -/* return TRUE if the color of the current anchor is - * one of the two default visted or unvisited colors - * it will be FALSE in the case that style sheets sets - * a specific color for the anchor - */ -static Bool -lo_is_default_anchor_color(lo_DocState *state, LO_TextAttr *tmp_attr) -{ - if( (tmp_attr->fg.red == STATE_VISITED_ANCHOR_RED(state) - && tmp_attr->fg.green == STATE_VISITED_ANCHOR_GREEN(state) - && tmp_attr->fg.blue == STATE_VISITED_ANCHOR_BLUE(state)) - || (tmp_attr->fg.red == STATE_UNVISITED_ANCHOR_RED(state) - && tmp_attr->fg.green == STATE_UNVISITED_ANCHOR_GREEN(state) - && tmp_attr->fg.blue == STATE_UNVISITED_ANCHOR_BLUE(state))) - return TRUE; - - return FALSE; -} - -#ifdef DOM -/* XXX honour style data here */ -#endif - -static void -lo_RefreshElementAnchor(lo_DocState *state, LO_Element *element) -{ - LO_TextAttr tmp_attr, *new_attr, *attr; - LO_AnchorData *anchor_href; - char *url; - - if (element->type == LO_CELL) { - lo_RefreshCellAnchors(state, (LO_CellStruct *)element); - return; - } - - attr = lo_GetElementTextAttr(element); - if (! attr) - return; - if (! (attr->attrmask & LO_ATTR_ANCHOR)) - return; - - anchor_href = lo_GetElementAnchor(element); - if (!anchor_href) - return; - - if(!lo_is_default_anchor_color(state, attr)) - return; - - lo_CopyTextAttr(attr, &tmp_attr); - - url = (char*)anchor_href->anchor; - if (GH_CheckGlobalHistory(url) != -1) - { - tmp_attr.fg.red = STATE_VISITED_ANCHOR_RED(state); - tmp_attr.fg.green = STATE_VISITED_ANCHOR_GREEN(state); - tmp_attr.fg.blue = STATE_VISITED_ANCHOR_BLUE(state); - } - else - { - tmp_attr.fg.red = STATE_UNVISITED_ANCHOR_RED(state); - tmp_attr.fg.green = STATE_UNVISITED_ANCHOR_GREEN(state); - tmp_attr.fg.blue = STATE_UNVISITED_ANCHOR_BLUE(state); - } - - new_attr = lo_FetchTextAttr(state, &tmp_attr); - - if (new_attr != attr) { - lo_SetElementTextAttr(element, new_attr); - if (element->type == LO_TEXT || element->type == LO_IMAGE) { - element->lo_any.x += state->base_x; - element->lo_any.y += state->base_y; - lo_RefreshElement(element, anchor_href->layer, TRUE); - element->lo_any.x -= state->base_x; - element->lo_any.y -= state->base_y; - } - } -} - -static void -lo_RefreshCellAnchors(lo_DocState *state, LO_CellStruct *cell) -{ - LO_Element *eptr; - - eptr = cell->cell_list; - while (eptr) - { - lo_RefreshElementAnchor(state, eptr); - eptr = eptr->lo_any.next; - } - - eptr = cell->cell_float_list; - while (eptr) - { - lo_RefreshElementAnchor(state, eptr); - eptr = eptr->lo_any.next; - } -} - -void -LO_RefreshAnchors(MWContext *context) -{ - int32 doc_id; - lo_TopState *top_state; - lo_DocState *state; - LO_Element *eptr; - LO_Element **line_array; - - if (!context->compositor) - return; - - /* - * Get the unique document ID, and retrieve this - * document's layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - return; - state = top_state->doc_state; - - /* - * line_array could be NULL when discarding the document, so - * check it and exit early to avoid dereferencing it below. - */ - if (state->line_array == NULL) - return; - -#ifdef XP_WIN16 - { - XP_Block *larray_array; - - XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array); - state->line_array = larray_array[0]; - XP_UNLOCK_BLOCK(state->larray_array); - } -#endif /* XP_WIN16 */ - - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array); - eptr = line_array[0]; - XP_UNLOCK_BLOCK(state->line_array); - - for (; eptr; eptr = eptr->lo_any.next) - lo_RefreshElementAnchor(state, eptr); -} - -static void -lo_split_named_anchor(char *url, char **cmp_url, char **cmp_name) -{ - char tchar, *tptr, *tname; - - *cmp_url = NULL; - - if ( cmp_name ) - *cmp_name = NULL; - - if (url == NULL) - { - return; - } - - tptr = url; - while (((tchar = *tptr) != '\0')&&(tchar != '#')) - { - tptr++; - } - if (tchar == '\0') - { - *cmp_url = (char *)XP_STRDUP(url); - return; - } - - *tptr = '\0'; - *cmp_url = (char *)XP_STRDUP(url); - *tptr = tchar; - tname = ++tptr; - while (((tchar = *tptr) != '\0')&&(tchar != '?')) - { - tptr++; - } - *tptr = '\0'; - if ( cmp_name ) - *cmp_name = (char *)XP_STRDUP(tname); - *tptr = tchar; - if (tchar == '?') - { - StrAllocCat(*cmp_url, tptr); - } -} - - -/* - * Is this anchor local to this document? - */ -Bool -lo_IsAnchorInDoc(lo_DocState *state, char *url) -{ - char *cmp_url; - char *doc_url; - Bool local; - - local = FALSE; - /* - * Extract the base from the name part. - */ - lo_split_named_anchor(url, &cmp_url, NULL); - - /* - * Extract the base from the name part. - */ - doc_url = NULL; - lo_split_named_anchor(state->top_state->url, &doc_url, NULL); - - /* - * If the document itself has no base URL (probably an error) - * then the only way we are local is if the passed in url has no - * base either. - */ - if (doc_url == NULL) - { - if (cmp_url == NULL) - { - local = TRUE; - } - } - /* - * Else if the passed in url has no base, and we have a bas, you must - * be local because you are relative to our base. - */ - else if (cmp_url == NULL) - { - local = TRUE; - } - /* - * Else if the base of the two urls is equal, you are local. - */ - else if (XP_STRCMP(cmp_url, doc_url) == 0) - { - local = TRUE; - } - - if (cmp_url != NULL) - { - XP_FREE(cmp_url); - } - if (doc_url != NULL) - { - XP_FREE(doc_url); - } - return(local); -} - - -static LO_Element * -lo_cell_id_to_element(lo_DocState *state, int32 ele_id, LO_CellStruct *cell) -{ - LO_Element *eptr; - - if (cell == NULL) - { - return(NULL); - } - - eptr = cell->cell_list; - while (eptr != NULL) - { - if (eptr->lo_any.ele_id == ele_id) - { - break; - } - if (eptr->type == LO_CELL) - { - LO_Element *cell_eptr; - - cell_eptr = lo_cell_id_to_element(state, ele_id, - (LO_CellStruct *)eptr); - if (cell_eptr != NULL) - { - eptr = cell_eptr; - break; - } - } - if (eptr->lo_any.ele_id > ele_id) - { - break; - } - eptr = eptr->lo_any.next; - } - return(eptr); -} - - -/* - * Find the x, y, coords of the element id passed in, and return them. - * If can't find the exact element, return the closest (next greater) - * element id's position. - * We need to walk into cells. - * On severe error return 0, 0. - */ -static void -lo_element_id_to_xy(lo_DocState *state, int32 ele_id, int32 *xpos, int32 *ypos) -{ - LO_Element *eptr; - LO_Element **line_array; - - *xpos = 0; - *ypos = 0; - - /* - * On error return the top - */ - if (state == NULL) - { - return; - } - -#ifdef XP_WIN16 - { - XP_Block *larray_array; - - XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array); - state->line_array = larray_array[0]; - XP_UNLOCK_BLOCK(state->larray_array); - } -#endif /* XP_WIN16 */ - - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array); - eptr = line_array[0]; - XP_UNLOCK_BLOCK(state->line_array); - - while (eptr != NULL) - { - /* - * Exact match? - */ - if (eptr->lo_any.ele_id == ele_id) - { - *xpos = eptr->lo_any.x; - *ypos = eptr->lo_any.y; - break; - } - - /* - * Look for a match in this cell - */ - if (eptr->type == LO_CELL) - { - LO_Element *cell_eptr; - - cell_eptr = lo_cell_id_to_element(state, ele_id, - (LO_CellStruct *)eptr); - if (cell_eptr != NULL) - { - *xpos = cell_eptr->lo_any.x; - *ypos = cell_eptr->lo_any.y; - break; - } - } - - /* - * If we passed it, fake a match. - */ - if (eptr->lo_any.ele_id > ele_id) - { - *xpos = eptr->lo_any.x; - *ypos = eptr->lo_any.y; - break; - } - eptr = eptr->lo_any.next; - } -} - - -/* - * Check the current URL to see if it is the URL for this doc, and if - * so return the position of the named anchor referenced after the '#' in - * the URL. If there is no name or no match, return 0,0. In comparing URLs - * both NULL are considered equal - */ -Bool -LO_LocateNamedAnchor(MWContext *context, URL_Struct *url_struct, - int32 *xpos, int32 *ypos) -{ - int i; - int32 doc_id; - lo_TopState *top_state; - lo_DocState *state; - lo_NameList *nptr; - char *url; - char *cmp_url; - char *cmp_name; - - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return(FALSE); - } - state = top_state->doc_state; - - /* - * obvious error - */ - if ((url_struct == NULL)||(url_struct->address == NULL)) - { - return(FALSE); - } - - /* - * Extract the URL we are going to. - */ - url = url_struct->address; - - - /* - * Split the passed url into the real url part - * and the name part. The parts (if non-NULL) must - * be freed. - */ - cmp_url = NULL; - cmp_name = NULL; - lo_split_named_anchor(url, &cmp_url, &cmp_name); - - /* - * can't strcmp on NULL strings. - */ - if (state->top_state->url == NULL) - { - /* - * 2 NULLs are considered equal. - * If not equal fail here - */ - if (cmp_url != NULL) - { - if (cmp_name != NULL) - { - XP_FREE(cmp_name); - } - return(FALSE); - } - } - /* - * Else lets compare the 2 URLs now - */ - else - { - /* - * The current URL might itself have a name part. Lose it. - */ - char *this_url; - int same_p; - - lo_split_named_anchor(state->top_state->url, &this_url, NULL); - /* - * If the 2 URLs are not equal fail out here - */ - same_p = ((this_url)&&(XP_STRCMP(cmp_url, this_url) == 0)); - - if (this_url != NULL) - { - XP_FREE (this_url); - } - - if (!same_p) - { - XP_FREE(cmp_url); - if (cmp_name != NULL) - { - XP_FREE(cmp_name); - } - return(FALSE); - } - } - - /* - * If we got here the URLs are considered equal. - * Free this one. - */ - if (cmp_url != NULL) - { - XP_FREE(cmp_url); - } - - /* - * Do we have a saved element ID that is not the start - * of the document to return to because we are moving through history? - * If so, go there and return. - */ - if (url_struct->position_tag > 1) - { - lo_element_id_to_xy(state, url_struct->position_tag, - xpos, ypos); - return(TRUE); - } - - /* - * Special case for going to a NULL or empty - * name to return the beginning of the - * document. - */ - if (cmp_name == NULL) - { - *xpos = 0; - *ypos = 0; - - if (state->top_state->url != NULL) - { - XP_FREE(state->top_state->url); - } - state->top_state->url = XP_STRDUP(url); - return(TRUE); - } - else if (*cmp_name == '\0') - { - *xpos = 0; - *ypos = 0; - XP_FREE(cmp_name); - - if (state->top_state->url != NULL) - { - XP_FREE(state->top_state->url); - } - state->top_state->url = XP_STRDUP(url); - return(TRUE); - } - - /* - * Actually search the name list for a matching name. - */ - for (i = 0; i <= state->top_state->max_layer_num; i++) - { - lo_LayerDocState *layer_state = state->top_state->layers[i]; - CL_Layer *layer; - if (!layer_state) - continue; - layer = layer_state->layer; - nptr = layer_state->doc_lists->name_list; - - while (nptr != NULL) - { - char *name; - - PA_LOCK(name, char *, nptr->name); - /* - * If this is a match, return success - * here. - */ - if (XP_STRCMP(cmp_name, name) == 0) - { - PA_UNLOCK(nptr->name); - if (nptr->element == NULL) - { - *xpos = 0; - *ypos = 0; - } - else - { - /* Convert from element coordinates to document coordinates */ - lo_GetLayerXYShift(layer, xpos, ypos); - *xpos = - *xpos; - *ypos = - *ypos; - *xpos += nptr->element->lo_any.x + CL_GetLayerXOrigin(layer); - *ypos += nptr->element->lo_any.y + CL_GetLayerYOrigin(layer); - } - XP_FREE(cmp_name); - - if (state->top_state->url != NULL) - { - XP_FREE(state->top_state->url); - } - state->top_state->url = XP_STRDUP(url); - LM_SendOnLocate(context, nptr); - return(TRUE); - } - PA_UNLOCK(nptr->name); - nptr = nptr->next; - } - } - - /* - * Failed to find the matchng name. - * If no match return the top of the doc. - */ - XP_FREE(cmp_name); - *xpos = 0; - *ypos = 0; - - if (state->top_state->url != NULL) - { - XP_FREE(state->top_state->url); - } - state->top_state->url = XP_STRDUP(url); - return(TRUE); -} - - -Bool -LO_HasBGImage(MWContext *context) -{ - int32 doc_id; - lo_TopState *top_state; - - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if (top_state == NULL) - return(FALSE); - -#ifdef XP_WIN - /* - * Evil hack alert. - * We don't want print context's under windows to use backdrops - * currently as it causes bad display (black in the transparent - * area due to drawing problems under windows). - */ - if(context->type == MWContextPrint || context->type == MWContextMetaFile) - { - return(FALSE); - } -#endif - - return (LO_GetLayerBackdropURL(top_state->doc_layer) != NULL); -} - -void -LO_GetDocumentMargins(MWContext *context, - int32 *margin_width, int32 *margin_height) -{ - int32 doc_id; - lo_TopState *top_state; - lo_DocState *state; - - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return; - } - state = top_state->doc_state; - - *margin_width = state->win_left; - *margin_height = state->win_top; -} - - -/* - * Provide a way for the parser to see if the currently loaded - * document who might need a call to mocha to unload - */ -Bool -LO_CheckForUnload(MWContext *context) -{ - lo_TopState *top_state; - - top_state = lo_FetchTopState(XP_DOCID(context)); - if (!top_state) - return FALSE; - - return top_state->mocha_has_onunload; -} - -/* - * netlib is done sending data to the parser - */ -void -LO_NetlibComplete(MWContext * context) -{ - lo_TopState *top_state; - - top_state = lo_FetchTopState(XP_DOCID(context)); - if (!top_state) - return; - top_state->nurl = NULL; -} - -/* - * Even though netlib is idle someone could be shoving data - * through layout/libparse. Provide a way for people on - * the outside to tell if this is the case or not. - */ - -Bool -LO_LayingOut(MWContext * context) -{ - lo_TopState *top_state; - - top_state = lo_FetchTopState(XP_DOCID(context)); - if (!top_state) - return FALSE; - return (top_state->doc_data != NULL); -} - - -void lo_UpdateStateWhileFlushingLine( MWContext *context, lo_DocState *state ) -{ - int32 justification_remainder=0; - - if (state->top_state->nothing_displayed != FALSE) { - /* - * If we are displaying elements we are - * no longer in the HEAD section of the HTML - * we are in the BODY section. - */ - state->top_state->in_head = FALSE; - state->top_state->in_body = TRUE; - - lo_use_default_doc_background(context, state); - state->top_state->nothing_displayed = FALSE; - } - - /* - * There is a break at the end of this line. - * this may change min_width. - */ - { - int32 new_break_holder; - int32 min_width; - int32 indent; - - new_break_holder = state->x; - min_width = new_break_holder - state->break_holder; - indent = state->list_stack->old_left_margin - state->win_left; - min_width += indent; - if (min_width > state->min_width) - { - state->min_width = min_width; - } - /* If we are not within content, allow break_holder - * to be set to the new position where a line break can occur. - * This fixes BUG #70782 - */ - if (state->breakable != FALSE) { - state->break_holder = new_break_holder; - } - } - - /* - * If in a division centering or right aligning this line - */ - if ((state->align_stack != NULL)&&(state->delay_align == FALSE)) - { - int32 push_right; - LO_Element *tptr; - - if (state->align_stack->alignment == LO_ALIGN_CENTER) - { - push_right = (state->right_margin - state->x) / 2; - } - else if (state->align_stack->alignment == LO_ALIGN_RIGHT) - { - push_right = state->right_margin - state->x; - } - else if(state->align_stack->alignment == LO_ALIGN_JUSTIFY) - { - push_right = lo_calc_push_right_for_justify(state, &justification_remainder); - } - else - { - push_right = 0; - } - - if ((push_right > 0 || justification_remainder) - &&(state->line_list != NULL)) - { - int32 count = 0; - int32 move_delta; - tptr = state->line_list; - - if(state->align_stack->alignment == LO_ALIGN_JUSTIFY) - move_delta = 0; - else - move_delta = push_right; - - while (tptr != NULL) - { - /* - * We don't shift over inflow layers, since their contents - * have already been shifted over. - */ - /* - * We also don't shift bullets of type BULLET_MQUOTE. - */ - if (((tptr->type != LO_CELL)|| - (!tptr->lo_cell.cell_inflow_layer))&& - ((tptr->type != LO_BULLET)|| - ((tptr->type == LO_BULLET)&& - (tptr->lo_bullet.bullet_type != BULLET_MQUOTE)))) - { - tptr->lo_any.x += move_delta; - } - - { - CL_Layer *layer = NULL; - int32 x, y; - int32 border_width; - int32 x_offset, y_offset; - - border_width = 0; - x = tptr->lo_any.x; - y = tptr->lo_any.y; - x_offset = tptr->lo_any.x_offset; - y_offset = tptr->lo_any.y_offset; - - switch (tptr->type) - { - case LO_IMAGE: - layer = tptr->lo_image.layer; - border_width = tptr->lo_image.border_width; - break; -#ifdef JAVA - case LO_JAVA: - layer = tptr->lo_java.objTag.layer; - border_width = tptr->lo_java.objTag.border_width; - break; -#endif - case LO_BUILTIN: - layer = tptr->lo_builtin.layer; - border_width = tptr->lo_builtin.border_width; - break; - case LO_EMBED: - layer = tptr->lo_embed.objTag.layer; - border_width = tptr->lo_embed.objTag.border_width; - break; - case LO_FORM_ELE: - layer = tptr->lo_form.layer; - break; - default: - layer = NULL; - break; - } - - if (layer) - CL_MoveLayer(layer, - x + x_offset + border_width, - y + y_offset + border_width); - } - - /* justification push_rights are additive */ - if(state->align_stack->alignment == LO_ALIGN_JUSTIFY) - { - move_delta += push_right; - - /* if there is a justification remainder, add a pixel - * to the first n word breaks - */ - if(count < justification_remainder) - move_delta++; - } - - /* - * Note that if this is an inflow layer, we don't want - * to shift it since the alignment has already propogated - * to its contents. - */ - if ((tptr->type == LO_CELL) && - !tptr->lo_cell.cell_inflow_layer) - { - lo_ShiftCell((LO_CellStruct *)tptr, move_delta, 0); - } - tptr = tptr->lo_any.next; - - count++; - } - - if(state->align_stack->alignment == LO_ALIGN_JUSTIFY) - state->x = state->right_margin; - else - state->x += push_right; - } - } -} - -/* Add line feed to line list, update doc state, and set line height of - other elements on that line */ -void lo_AppendLineFeed( MWContext *context, lo_DocState *state, LO_LinefeedStruct *linefeed, int32 breaking, Bool updateFE ) -{ - LO_Element *tptr; - - if (breaking != FALSE) - { - linefeed->ele_attrmask |= LO_ELE_BREAKING; - } - - /* - * Horrible bitflag overuse!!! For multicolumn text - * we need to know if a line of text can be used for - * a column break, or if it cannot because it is wrapped - * around some object in the margin. For lines that can be - * used for column breaks, we will set the BREAKABLE - * flag in their element mask. - */ - if ((state->left_margin_stack == NULL)&& - (state->right_margin_stack == NULL)) - { - linefeed->ele_attrmask |= LO_ELE_BREAKABLE; - } - - if ((state->align_stack != NULL)&& - (state->delay_align != FALSE)&& - (state->align_stack->alignment != LO_ALIGN_LEFT)) - { - if (state->align_stack->alignment == LO_ALIGN_CENTER) - { - linefeed->ele_attrmask |= LO_ELE_DELAY_CENTER; - } - else if (state->align_stack->alignment == LO_ALIGN_RIGHT) - { - linefeed->ele_attrmask |= LO_ELE_DELAY_RIGHT; - } - } - - tptr = state->line_list; - - if (tptr == NULL) - { - state->line_list = (LO_Element *)linefeed; - linefeed->prev = NULL; - } - else - { - LO_Element *next_tptr = tptr; - do - { - tptr = next_tptr; - if (updateFE) - { - /* - * If the display is blocked for an element - * we havn't reached yet, check to see if - * it is in this line, and if so, save its - * y position. - */ - if ((state->display_blocked != FALSE)&& - #ifdef EDITOR - (!state->edit_relayout_display_blocked)&& - #endif - (state->is_a_subdoc == SUBDOC_NOT)&& - (state->display_blocking_element_y == 0)&& - (state->display_blocking_element_id != -1)&& - (tptr->lo_any.ele_id >= - state->display_blocking_element_id)) - { - state->display_blocking_element_y = - state->y; - /* - * Special case, if the blocking element - * is on the first line, no blocking - * at all needs to happen. - */ - if (state->y == state->win_top) - { - state->display_blocked = FALSE; - FE_SetDocPosition(context, - FE_VIEW, 0, state->base_y); - if (context->compositor) - { - XP_Rect rect; - - rect.left = 0; - rect.top = 0; - rect.right = state->win_width; - rect.bottom = state->win_height; - CL_UpdateDocumentRect(context->compositor, - &rect, (PRBool)FALSE); - } - } - } - } - - tptr->lo_any.line_height = state->line_height; - /* - * Special for bullets of type BULLET_MQUOTE - * They should always be as tall as the line. - */ - if ((tptr->type == LO_BULLET)&& - (tptr->lo_bullet.bullet_type == - BULLET_MQUOTE)) - { - tptr->lo_any.y_offset = 0; - tptr->lo_any.height = - tptr->lo_any.line_height; - } - - if ( (next_tptr = tptr->lo_any.next) == NULL ) - { - tptr->lo_any.next = (LO_Element*)linefeed; - linefeed->prev = tptr; - } - } while( next_tptr != NULL ); - } - state->x += linefeed->width; -} - -void lo_AppendLineListToLineArray( MWContext *context, lo_DocState *state, LO_Element *lastElementOnLineList) -{ - LO_Element **line_array; -#ifdef XP_WIN16 - int32 a_size; - int32 a_indx; - int32 a_line; - XP_Block *larray_array; -#endif /* XP_WIN16 */ - - /* - * If necessary, grow the line array to hold more lines. - */ -#ifdef XP_WIN16 - a_size = SIZE_LIMIT / sizeof(LO_Element *); - a_indx = (state->line_num - 1) / a_size; - a_line = state->line_num - (a_indx * a_size); - - XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array); - state->line_array = larray_array[a_indx]; - - if (a_line == a_size) - { - state->line_array = XP_ALLOC_BLOCK(LINE_INC * - sizeof(LO_Element *)); - if (state->line_array == NULL) - { - XP_UNLOCK_BLOCK(state->larray_array); - state->top_state->out_of_memory = TRUE; - return; - } - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array); - line_array[0] = NULL; - XP_UNLOCK_BLOCK(state->line_array); - state->line_array_size = LINE_INC; - - state->larray_array_size++; - XP_UNLOCK_BLOCK(state->larray_array); - state->larray_array = XP_REALLOC_BLOCK( - state->larray_array, (state->larray_array_size - * sizeof(XP_Block))); - if (state->larray_array == NULL) - { - state->top_state->out_of_memory = TRUE; - return; - } - XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array); - larray_array[state->larray_array_size - 1] = state->line_array; - state->line_array = larray_array[a_indx]; - } - else if (a_line >= state->line_array_size) - { - state->line_array_size += LINE_INC; - if (state->line_array_size > a_size) - { - state->line_array_size = (intn)a_size; - } - state->line_array = XP_REALLOC_BLOCK(state->line_array, - (state->line_array_size * sizeof(LO_Element *))); - if (state->line_array == NULL) - { - XP_UNLOCK_BLOCK(state->larray_array); - state->top_state->out_of_memory = TRUE; - return; - } - larray_array[a_indx] = state->line_array; - } - - /* - * Place this line of elements into the line array. - */ - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array); - line_array[a_line - 1] = state->line_list; - XP_UNLOCK_BLOCK(state->line_array); - - XP_UNLOCK_BLOCK(state->larray_array); -#else - if (state->line_num > state->line_array_size) - { - int32 line_inc; - - if (state->line_array_size > (LINE_INC * 10)) - { - line_inc = state->line_array_size / 10; - } - else - { - line_inc = LINE_INC; - } - - state->line_array = XP_REALLOC_BLOCK(state->line_array, - ((state->line_array_size + line_inc) * - sizeof(LO_Element *))); - if (state->line_array == NULL) - { - state->top_state->out_of_memory = TRUE; - return; - } - state->line_array_size += line_inc; - } - - /* - * Place this line of elements into the line array. - */ - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array); - line_array[state->line_num - 1] = state->line_list; - XP_UNLOCK_BLOCK(state->line_array); -#endif /* XP_WIN16 */ - - /* - * connect the complete doubly linked list between this line - * and the last one. - */ - if (state->end_last_line != NULL) - { - state->end_last_line->lo_any.next = state->line_list; - state->line_list->lo_any.prev = state->end_last_line; - } - - state->end_last_line = lastElementOnLineList; - - state->line_list = NULL; - state->line_num++; -} - -void lo_UpdateStateAfterFlushingLine( MWContext *context, lo_DocState *state, LO_LinefeedStruct *linefeed, Bool inRelayout ) -{ - /* LO_LinefeedStruct *linefeed; */ - - /* - * We are in a layer within this (sub)doc, stuff the line there instead. - */ - if (state->layer_nest_level > 0) - { - lo_AddLineListToLayer(context, state, (LO_Element *)linefeed); - state->line_list = NULL; - state->old_break = NULL; - state->old_break_block = NULL; - state->old_break_pos = -1; - state->old_break_width = 0; - state->baseline = 0; - return; - } - - lo_AppendLineListToLineArray( context, state, (LO_Element *) linefeed ); - - /* - *Don't draw if we're doing layers...we'll just refresh when the - * the layer size increases. - */ - /* - * Have the front end display this line. - */ - /* For layers, only draw if a compositor doesn't exist */ - if (!context->compositor && !inRelayout) - /* We need to supply a display rectangle that is guaranteed to - encompass all elements on the line. The special 0x3fffffff - value is approximately half the range of a 32-bit int, so - it leaves room for overflow if arithmetic is done on these - values. */ - lo_DisplayLine(context, state, (state->line_num - 2), - 0, 0, 0x3fffffffL, 0x3fffffffL); - - /* - * We are starting a new line. Clear any old break - * positions left over, clear the line_list, and increase - * the line number. - */ - state->old_break = NULL; - state->old_break_block = NULL; - state->old_break_pos = -1; - state->old_break_width = 0; - state->baseline = 0; -} - -#ifdef TEST_16BIT -#undef XP_WIN16 -#endif /* TEST_16BIT */ - -#ifdef PROFILE -#pragma profile off -#endif diff --git a/lib/layout/layout.h b/lib/layout/layout.h index 436e9e0726a..e69de29bb2d 100644 --- a/lib/layout/layout.h +++ b/lib/layout/layout.h @@ -1,1761 +0,0 @@ -/* -*- Mode: C; tab-width: 4; 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. - */ - -#ifndef _Layout_h_ -#define _Layout_h_ - -#define M12N /* XXXM12N include m12n changes, exclude old - stuff. */ - -#include "xp_core.h" -#include "net.h" -#include "cl_types.h" - -#include "xp_obs.h" /* Observer/observables. */ -#include "il_types.h" - -/* stylesheets stuff */ -#include "stystruc.h" -#include "stystack.h" - -#include "libmocha.h" -#ifdef DOM -struct DOM_Node; -#endif - -#define MEMORY_ARENAS 1 - -#define NEXT_ELEMENT state->top_state->element_id++ - -#define MAX_INPUT_WRITE_LEVEL 10 -#define LINE_BUF_INC 200 -#define FONT_HASH_SIZE 127 -#define DEFAULT_BASE_FONT_SIZE 3 - -#define PRE_TEXT_NO 0 /* not preformatted */ -#define PRE_TEXT_YES 1 /* preformatted, no wrapping */ -#define PRE_TEXT_WRAP 2 /* preformatted, but wrapped */ -#define PRE_TEXT_COLS 3 /* preformatted, but set to wrap at a specific column */ - -#define QUOTE_NONE 0 /* no quote marker */ -#define QUOTE_MQUOTE 1 /* use blue bars to mark the quoted area. */ -#define QUOTE_JWZ 2 /* use '>'s to mark the quoted area. */ -#define QUOTE_CITE 3 /* use extra leading space to indicate the quoted area */ - -#define SUBDOC_NOT 0 /* not really a subdoc. */ -#define SUBDOC_IS 1 /* normal subdoc -- not used. */ -#define SUBDOC_CELL 2 /* table cell */ -#define SUBDOC_CAPTION 3 /* table caption */ - -#define LO_ALIGN_DEFAULT -1 -#define LO_ALIGN_CENTER 0 -#define LO_ALIGN_LEFT 1 -#define LO_ALIGN_RIGHT 2 -#define LO_ALIGN_TOP 3 -#define LO_ALIGN_BOTTOM 4 -#define LO_ALIGN_BASELINE 5 -#define LO_ALIGN_NCSA_CENTER 6 -#define LO_ALIGN_NCSA_BOTTOM 7 -#define LO_ALIGN_NCSA_TOP 8 -#define LO_ALIGN_JUSTIFY 9 - -#define ICON_X_OFFSET 4 -#define ICON_Y_OFFSET 4 - -/* Moved from laytags.c so Composer can use them */ -#define MIN_FONT_SIZE 1 -#define MAX_FONT_SIZE 7 - -#define DEFAULT_BASE_POINT_SIZE 12 -#define MIN_POINT_SIZE 1 -#define MAX_POINT_SIZE 1600 - -#ifdef EDITOR -extern char* lo_alignStrings[]; -#endif - -#define S_FORM_TYPE_TEXT "text" -#define S_FORM_TYPE_RADIO "radio" -#define S_FORM_TYPE_CHECKBOX "checkbox" -#define S_FORM_TYPE_HIDDEN "hidden" -#define S_FORM_TYPE_SUBMIT "submit" -#define S_FORM_TYPE_RESET "reset" -#define S_FORM_TYPE_PASSWORD "password" -#define S_FORM_TYPE_BUTTON "button" -#define S_FORM_TYPE_IMAGE "image" -#define S_FORM_TYPE_FILE "file" -#define S_FORM_TYPE_JOT "jot" -#define S_FORM_TYPE_READONLY "readonly" -#define S_FORM_TYPE_OBJECT "object" - -#define S_AREA_SHAPE_DEFAULT "default" -#define S_AREA_SHAPE_RECT "rect" -#define S_AREA_SHAPE_CIRCLE "circle" -#define S_AREA_SHAPE_POLY "poly" -#define S_AREA_SHAPE_POLYGON "polygon" /* maps to AREA_SHAPE_POLY */ - -#define AREA_SHAPE_UNKNOWN 0 -#define AREA_SHAPE_DEFAULT 1 -#define AREA_SHAPE_RECT 2 -#define AREA_SHAPE_CIRCLE 3 -#define AREA_SHAPE_POLY 4 - -#define BODY_ATTR_BACKGROUND 0x01 -#define BODY_ATTR_BGCOLOR 0x02 -#define BODY_ATTR_TEXT 0x04 -#define BODY_ATTR_LINK 0x08 -#define BODY_ATTR_VLINK 0x10 -#define BODY_ATTR_ALINK 0x20 -#define BODY_ATTR_MARGINS 0x40 -#define BODY_ATTR_JAVA 0x80 - -#define DEF_TAB_WIDTH 8 - -extern LO_Color lo_master_colors[]; - -typedef struct lo_NameList_struct { - int32 x, y; - LO_Element *element; - PA_Block name; /* really a (char *) */ - struct lo_NameList_struct *next; - uint32 index; /* Needed because with nested tables, the list - is not guaranteed to be ordered. */ - struct JSObject *mocha_object; -} lo_NameList; - -typedef struct lo_SavedFormListData_struct { - XP_Bool valid; - int32 data_index; - int32 data_count; - PA_Block data_list; /* really a (LO_FormElementData **) */ - struct lo_SavedFormListData_struct *next; -} lo_SavedFormListData; - -typedef void (*lo_FreeProc)(MWContext*, void*); - -typedef struct lo_EmbedDataElement { - void *data; - lo_FreeProc freeProc; -} lo_EmbedDataElement; - -typedef struct lo_SavedEmbedListData_struct { - int32 embed_count; - PA_Block embed_data_list; /* really a (lo_EmbedDataElement **) */ -} lo_SavedEmbedListData; - -typedef struct lo_SavedGridData_struct { - int32 main_width; - int32 main_height; - struct lo_GridRec_struct *the_grid; -} lo_SavedGridData; - -typedef struct lo_MarginStack_struct { - int32 margin; - int32 y_min, y_max; - struct lo_MarginStack_struct *next; -} lo_MarginStack; - - -typedef struct lo_FontStack_struct { - int32 tag_type; - LO_TextAttr *text_attr; - struct lo_FontStack_struct *next; -} lo_FontStack; - - -typedef struct lo_AlignStack_struct { - intn type; - int32 alignment; - struct lo_AlignStack_struct *next; -} lo_AlignStack; - - -typedef struct lo_ListStack_struct { - intn level; - int type; - int32 value; - Bool compact; - int bullet_type; - int8 quote_type; - int32 mquote_line_num; /* First line to put the mquote bullets on. */ - int32 mquote_x; /* How far to indent the mquote. */ - int32 old_left_margin; - int32 old_right_margin; - struct lo_ListStack_struct *next; -} lo_ListStack; - -typedef struct lo_LayerDocState lo_LayerDocState; -typedef struct lo_LayerStack lo_LayerStack; - -typedef struct lo_ObjectStack_struct { - LO_ObjectStruct *object; - struct lo_ObjectStack_struct *next; - lo_NVList parameters; - char* data_url; - MWContext* context; - struct lo_DocState_struct* state; - PA_Tag* real_tag; - PA_Tag* clone_tag; - Bool read_params; - Bool formatted_object; -} lo_ObjectStack; - - -typedef struct lo_LineHeightStack_struct { - int32 height; - struct lo_LineHeightStack_struct *next; -} lo_LineHeightStack; - -typedef struct lo_FormData_struct { - intn id; - PA_Block action; - PA_Block encoding; - PA_Block window_target; - int32 method; - int32 form_ele_cnt; - int32 form_ele_size; - PA_Block form_elements; /* really a (LO_Element **) */ - struct lo_FormData_struct *next; - PA_Block name; - struct JSObject *mocha_object; -} lo_FormData; - - -typedef struct lo_TableCell_struct { - Bool start_in_form; - intn form_id; - int32 form_ele_cnt; - int32 form_data_index; - int32 embed_count_base; - int32 url_count_base; - int32 image_list_count_base; - int32 applet_list_count_base; - int32 embed_list_count_base; - int32 current_layer_num_base; - Bool must_relayout; - intn is_a_subdoc; - PA_Tag *subdoc_tags; - PA_Tag *subdoc_tags_end; - int32 max_y; - int32 horiz_alignment; - int32 vert_alignment; - int32 cell_base_x; - int32 cell_base_y; - - Bool cell_done; - Bool nowrap; - Bool is_a_header; - int32 specified_width, specified_height; - int32 percent_width, percent_height; - int32 min_width, max_width; - int32 height, baseline; - int32 rowspan, colspan; - LO_CellStruct *cell; - struct lo_TableCell_struct *next; - int32 beginning_tag_count; - Bool in_nested_table; /* Can be removed once we remove subdoc tags. - * Used to figure out whether we shoul free subdoc tags or not - */ -} lo_TableCell; - - -typedef struct lo_TableRow_struct { - int16 type; /* to match lo_Any */ -#ifdef DOM - struct DOM_Node *node; /* to match lo_Any */ -#endif - Bool row_done; - Bool has_percent_width_cells; - lo_Backdrop backdrop; /* default for cells to inherit */ - int32 cells; /* is a counter that gets updated as a new cell is seen for a row */ - int32 cells_in_row; /* is the exact number of LO_CELLS in the line list for each row. Calculated in lo_fill_cell_array */ - int32 vert_alignment; - int32 horiz_alignment; - lo_TableCell *cell_list; - lo_TableCell *cell_ptr; - struct lo_TableRow_struct *next; -} lo_TableRow; - - -typedef struct lo_TableCaption_struct { - int32 vert_alignment; - int32 horiz_alignment; - int32 min_width, max_width; - int32 height; - int32 rowspan, colspan; - LO_SubDocStruct *subdoc; - LO_CellStruct *cell_ele; /* Kept around for relayout without reload */ -} lo_TableCaption; - - -typedef struct lo_table_span_struct { - int32 dim, min_dim; - int32 span; - struct lo_table_span_struct *next; -} lo_table_span; - -typedef struct lo_TableRec_struct { - intn draw_borders; - Bool has_percent_width_cells; - Bool table_width_fixed; - Bool has_percent_height_cells; - int32 percent_width; - int32 percent_height; - lo_Backdrop backdrop; /* default for cells to inherit */ - int32 rows, cols; - int32 width, height; - int32 inner_top_pad; - int32 inner_bottom_pad; - int32 inner_left_pad; - int32 inner_right_pad; - int32 inter_cell_pad; - int32 default_cell_width; - int32 fixed_cols; - int32 fixed_width_remaining; - lo_table_span *width_spans; - lo_table_span *width_span_ptr; - lo_table_span *height_spans; - lo_table_span *height_span_ptr; - lo_TableCaption *caption; - LO_TableStruct *table_ele; - LO_SubDocStruct *current_subdoc; - lo_TableRow *row_list; - lo_TableRow *row_ptr; - int32 *fixed_col_widths; -} lo_TableRec; - - -/* - * This structure contains all the element lists associated with a - * document that are reflected into mocha. There's one per top-level - * document (in the top_state), and one per layer. - * XXX BUGBUG The things that are missing from this list include: - * - The savedData stuff - * - A document's map_list - * Why? I don't feel comfortable moving these guys around at this point. - */ -typedef struct lo_DocLists_struct { - LO_EmbedStruct *embed_list; /* embeds linked in reverse order */ - int32 embed_list_count; /* The number of embeds in the list */ - - LO_BuiltinStruct *builtin_list; /* builtin/tree linked in reverse order */ - int32 builtin_list_count; - - LO_JavaAppStruct *applet_list; /* applets linked in reverse order */ - int32 applet_list_count; /* The number of applets in the list */ - - LO_ImageStruct *image_list; /* list of images in doc */ - LO_ImageStruct *last_image; /* last image in image_list */ - uint32 image_list_count; /* Number of images in the list */ - - lo_NameList *name_list; /* list of positions of named anchors */ - uint32 anchor_count; /* Count of named anchors in this document */ - -#ifdef DOM - lo_NameList *span_list; /* list of positions of named spans*/ - uint32 span_count; /* Count of named spans in this document */ -#endif - - lo_FormData *form_list; /* list of forms in doc */ - intn current_form_num; /* The id of the next form to lay out */ - -#ifdef XP_WIN16 - intn ulist_array_size; - XP_Block ulist_array; /* really a (XP_Block *) */ -#endif /* XP_WIN16 */ - XP_Block url_list; /* really a (LO_AnchorData **) PA_Block */ - intn url_list_len; /* Number of URLs in the list */ - intn url_list_size; /* Size of the list buffer */ - -} lo_DocLists; - -typedef struct lo_MultiCol_struct { - LO_Element *end_last_line; - int32 start_ele; - int32 start_line, end_line; - int32 start_y, end_y; - int32 start_x; - int32 cols; - int32 col_width; - int32 orig_margin; - int32 orig_min_width; - int32 orig_display_blocking_element_y; - int32 gutter; - Bool orig_display_blocked; - Bool close_table; - int32 width; /* For relayout without reload */ - Bool isPercentWidth; /* For relayout without reload */ - struct lo_MultiCol_struct *next; -} lo_MultiCol; - -#define LO_PERCENT_NORMAL 0 -#define LO_PERCENT_FREE 1 -#define LO_PERCENT_FIXED 2 - -typedef struct lo_GridPercent_struct { - uint8 type; - int32 value; - int32 original_value; -} lo_GridPercent; - -typedef struct lo_GridHistory_struct { - void *hist; /* really a SHIST history pointer */ - int32 position; -} lo_GridHistory; - -typedef struct lo_GridCellRec_struct { - int32 x, y; - int32 width, height; - int32 margin_width, margin_height; - intn width_percent; - intn height_percent; - char *url; - char *name; - MWContext *context; - void *hist_list; /* really a (XP_List *) */ - lo_GridHistory *hist_array; - int32 hist_indx; - int8 scrolling; - Bool resizable; - Bool no_edges; - int16 edge_size; - int8 color_priority; - LO_Color *border_color; - struct lo_GridEdge_struct *side_edges[4]; /* top, bottom, left, right */ - struct lo_GridCellRec_struct *next; - struct lo_GridRec_struct *subgrid; - - Bool needs_restructuring; - Bool has_percent_width, has_percent_height; -} lo_GridCellRec; - -typedef struct lo_GridEdge_struct { - int32 x, y; - int32 width, height; - Bool is_vertical; - int32 left_top_bound; - int32 right_bottom_bound; - int32 cell_cnt; - int32 cell_max; - lo_GridCellRec **cell_array; - LO_EdgeStruct *fe_edge; - struct lo_GridEdge_struct *next; - - Bool dealt_with_in_relayout; -} lo_GridEdge; - -typedef struct lo_GridRec_struct { - int32 main_width, main_height; - int32 current_hist, max_hist, hist_size; - int32 grid_cell_border; - int32 grid_cell_min_dim; - int32 rows, cols; - int32 current_cell_margin_width; - int32 current_cell_margin_height; - lo_GridPercent *row_percents; - lo_GridPercent *col_percents; - lo_GridCellRec *cell_list; - lo_GridCellRec *cell_list_last; - int32 cell_count; - Bool no_edges; - int16 edge_size; - int8 color_priority; - LO_Color *border_color; - lo_GridEdge *edge_list; - struct lo_GridRec_struct *subgrid; -} lo_GridRec; - -extern lo_GridCellRec * -lo_ContextToCell(MWContext *context, Bool reconnect, lo_GridRec **grid_ptr); - - -typedef struct lo_MapRec_struct { - char *name; - struct lo_MapAreaRec_struct *areas; - struct lo_MapAreaRec_struct *areas_last; - struct lo_MapRec_struct *next; -} lo_MapRec; - -typedef struct lo_MapAreaRec_struct { - int16 type; - int16 alt_len; - PA_Block alt; - int32 *coords; - int32 coord_cnt; - LO_AnchorData *anchor; - struct lo_MapAreaRec_struct *next; -} lo_MapAreaRec; - -#ifdef HTML_CERTIFICATE_SUPPORT -typedef struct lo_Certificate_struct { - PA_Block name; /* really a (char *) */ - void *cert; /* really a (char *) */ - struct lo_Certificate_struct *next; -} lo_Certificate; -#endif /* HTML_CERTIFICATE_SUPPORT */ - -typedef struct lo_TopState_struct lo_TopState; - - -#ifdef TEST_16BIT -#define XP_WIN16 -#endif /* TEST_16BIT */ -typedef struct lo_DocState_struct { - lo_TopState *top_state; - PA_Tag *subdoc_tags; /* tags that created this subdoc */ - PA_Tag *subdoc_tags_end; /* End of subdoc tags list */ - - int32 base_x, base_y; /* upper left of document */ - int32 x, y; /* upper left of element in progress */ - int32 width; /* width of element in progress */ - int32 win_width; /* Document or subdoc dimensions */ - int32 win_height; - int32 max_height; /* farthest down item so far. */ - int32 max_width; /* width of widest line so far. */ - int32 min_width; /* minimum possible line width */ - int32 break_holder; /* holder for last break position width */ - int32 line_num; /* line number of the next line to be placed */ - int32 preformat_cols; /* Column to break special PRE_TEXT_COLS at */ - intn linefeed_state; - int8 preformatted; /* processing preformatted (maybe wrap) text */ - Bool allow_amp_escapes; /* Let & entites be expanded */ - Bool breakable; /* Working on a breakable element */ - Bool delay_align; /* in subdoc, delay aligning lines */ - Bool display_blocked; /* do not display during layout */ - Bool in_paragraph; /* inside an HTML 3.0 paragraph container */ - int32 display_blocking_element_id; - int32 display_blocking_element_y; - - int32 win_top; - int32 win_bottom; - int32 win_left; - int32 win_right; - int32 left_margin; - int32 right_margin; - lo_MarginStack *left_margin_stack; - lo_MarginStack *right_margin_stack; - - int32 text_divert; /* the tag type of a text diverter (like P_TITLE) */ - -#ifdef XP_WIN16 - intn larray_array_size; - XP_Block larray_array; /* really a (XP_Block *) */ -#endif /* XP_WIN16 */ - intn line_array_size; - XP_Block line_array; /* really a (LO_Element **) */ - LO_Element *line_list; /* Element list for the current line so far */ - LO_Element *end_last_line; /* Element at end of last line */ - - LO_Element *float_list; /* Floating element list for the current doc */ - - intn base_font_size; /* size of font at bottom of font stack */ - lo_FontStack *font_stack; - - lo_AlignStack *align_stack; - - lo_ListStack *list_stack; - - lo_LineHeightStack *line_height_stack; - - LO_TextInfo text_info; /* for text of last text element created */ - /* this is a buffer for a single (currently processed) line of text */ - PA_Block line_buf; /* lock to a (char *) */ - int32 line_buf_len; - int32 line_buf_size; - int32 baseline; - int32 line_height; - int32 default_line_height; - int32 break_pos; /* position in middle of current element */ - int32 break_width; - Bool last_char_CR; - Bool trailing_space; - Bool at_begin_line; - Bool hide_content; /* set to not display text */ - - LO_TextStruct *old_break; - LO_TextBlock *old_break_block; - int32 old_break_pos; /* in middle of older element on this line */ - int32 old_break_width; - - PA_Block current_named_anchor; /* lock to a (char *) */ - LO_AnchorData *current_anchor; - - intn cur_ele_type; - LO_Element *current_ele; /* element in process, no end tag yet */ - - LO_JavaAppStruct *current_java; /* java applet in process, no end tag yet */ - - lo_TableRec *current_table; - lo_GridRec *current_grid; - lo_MultiCol *current_multicol; - intn layer_nest_level; /* Layer nesting level for this (sub)doc */ - - Bool start_in_form; /* Was in a form at start of (sub)doc */ - intn form_id; /* first form entering this (sub)doc */ - int32 form_ele_cnt; /* first form element entering this (sub)doc */ - int32 form_data_index; /* first form data entering this (sub)doc */ - int32 embed_count_base; /* number of embedded elements (applets and embeds) before beginning this (sub)doc */ - /* - * Just to clarify: the embed_count is the total of all applets and - * embeds in the document. This is used for indexing into the saved - * data structure. The applet_list_count and embed_list_count are - * applets and embeds in the current container. This is used to index - * into the applet and embed lists of the container. - */ - int32 url_count_base; /* number of anchors before beginning this (sub)doc */ - int32 image_list_count_base; /* number of images before this (sub)doc */ - int32 applet_list_count_base; /* number of applets before this (sub)doc */ - int32 embed_list_count_base; /* number of embeds before this (sub)doc */ - int32 current_layer_num_base; /* id of last layer before this (sub)doc */ - int32 current_layer_num_max; /* id of the last layer in this (sub)doc */ - Bool must_relayout_subdoc; - Bool allow_percent_width; - Bool allow_percent_height; - intn is_a_subdoc; - int32 current_subdoc; - XP_Block sub_documents; /* really a lo_DocState ** array */ - struct lo_DocState_struct *sub_state; - - LO_Element *current_cell; - - Bool extending_start; - LO_Element *selection_start; - int32 selection_start_pos; - LO_Element *selection_end; - int32 selection_end_pos; - LO_Element *selection_new; - int32 selection_new_pos; - CL_Layer *selection_layer; - - LO_Color text_fg; - LO_Color text_bg; - LO_Color anchor_color; - LO_Color visited_anchor_color; - LO_Color active_anchor_color; - ED_Element *edit_current_element; - int edit_current_offset; - Bool edit_force_offset; - Bool edit_relayout_display_blocked; - Bool in_relayout; /* true if we're in lo_RelayoutSubdoc */ - - int32 tab_stop; - int32 beginning_tag_count; /* the tag count at the beginning of this state */ - - LO_TextBlock * cur_text_block; - Bool need_min_width; - uint32 src_text_offset; - -#ifdef DOM - Bool in_span; - PA_Block current_span; -#endif -} lo_DocState; - -#ifdef TEST_16BIT -#undef XP_WIN16 -#endif /* TEST_16BIT */ - -#define STATE_DEFAULT_FG_RED(state) ((state)->text_fg.red) -#define STATE_DEFAULT_FG_GREEN(state) ((state)->text_fg.green) -#define STATE_DEFAULT_FG_BLUE(state) ((state)->text_fg.blue) - -#define STATE_DEFAULT_BG_RED(state) ((state)->text_bg.red) -#define STATE_DEFAULT_BG_GREEN(state) ((state)->text_bg.green) -#define STATE_DEFAULT_BG_BLUE(state) ((state)->text_bg.blue) - -#define STATE_UNVISITED_ANCHOR_RED(state) ((state)->anchor_color.red) -#define STATE_UNVISITED_ANCHOR_GREEN(state) ((state)->anchor_color.green) -#define STATE_UNVISITED_ANCHOR_BLUE(state) ((state)->anchor_color.blue) - -#define STATE_VISITED_ANCHOR_RED(state) ((state)->visited_anchor_color.red) -#define STATE_VISITED_ANCHOR_GREEN(state) ((state)->visited_anchor_color.green) -#define STATE_VISITED_ANCHOR_BLUE(state) ((state)->visited_anchor_color.blue) - -#define STATE_SELECTED_ANCHOR_RED(state) ((state)->active_anchor_color.red) -#define STATE_SELECTED_ANCHOR_GREEN(state) ((state)->active_anchor_color.green) -#define STATE_SELECTED_ANCHOR_BLUE(state) ((state)->active_anchor_color.blue) - - -#ifdef MEMORY_ARENAS -typedef struct lo_arena_struct { - struct lo_arena_struct *next; - char *limit; - char *avail; -} lo_arena; -#endif /* MEMORY_ARENAS */ - -/* -** This is just like SHIST_SavedData except the fields are more strictly -** typed. -*/ -typedef struct lo_SavedData { - lo_SavedFormListData* FormList; /* Data for all form elements in doc */ - lo_SavedEmbedListData* EmbedList; /* session data for all embeds and applets in doc */ - lo_SavedGridData* Grid; /* saved for grid history. */ - PA_Block OnLoad; /* JavaScript onload event handler source */ - PA_Block OnUnload; /* JavaScript onunload event handler source */ - PA_Block OnFocus; /* JavaScript onfocus event handler source */ - PA_Block OnBlur; /* JavaScript onblur event handler source */ - PA_Block OnHelp; /* JavaScript onhelp event handler source */ - PA_Block OnMouseOver; /* JavaScript onmouseover event handler source */ - PA_Block OnMouseOut; /* JavaScript onmouseout event handler source */ - PA_Block OnDragDrop; /* JavaScript ondragdrop event handler source */ - PA_Block OnMove; /* JavaScript onmove event handler source */ - PA_Block OnResize; /* JavaScript onresize event handler source */ -} lo_SavedData; - -/* - * This is used when we have an input stream and we need to defer - * the destruction of the main parser stream till we're done - * processing all inline streams. - */ -typedef void lo_FreeStreamFunc(MWContext *, NET_StreamClass *); - -/* - * Top level state - */ -struct lo_TopState_struct { -#ifdef MEMORY_ARENAS - lo_arena *first_arena; - lo_arena *current_arena; -#endif /* MEMORY_ARENAS */ - PA_Tag *tags; /* Held tags while layout is blocked */ - PA_Tag **tags_end; /* End of held tags list */ - PRPackedBool doc_specified_bg; - PRPackedBool nothing_displayed; - PRPackedBool in_head; /* Still in the HEAD of the HTML doc. */ - PRPackedBool in_body; /* In the BODY of the HTML doc. */ - PRPackedBool scrolling_doc; /* Is this a special scrolling doc (hack) */ - PRPackedBool have_title; /* set by first */ - PRPackedBool in_form; /* true if in <FORM>...</FORM> */ - uint8 body_attr; /* What attributes were set by BODY */ - char *unknown_head_tag; /* ignore content in this case if non-NULL */ - char *base_target; /* Base target of urls in this document */ - char *base_url; /* Base url of this document */ - char *inline_stream_blocked_base_url; /* Base url for prefetched images */ - char *main_stream_blocked_base_url; /* Base url for prefetched images */ - char *url; /* Real url of this document */ - char *name_target; /* The #name part of the url */ - int32 element_id; - LO_Element *layout_blocking_element; - LO_Element *current_script; - intn layout_status; - - lo_DocLists doc_lists; /* Lists of reflected elements */ - - lo_LayerDocState **layers; /* Array of ptrs to all layers in current doc */ - int32 num_layers_allocated; /* Length of layers array */ - int32 current_layer_num; /* Id of last layer to be laid out */ - int32 max_layer_num; /* Largest id of any layer yet laid out */ - - lo_LayerStack *layer_stack; - - lo_MapRec *map_list; /* list of maps in doc */ - lo_MapRec *current_map; /* Current open MAP tag */ - - int32 embed_count; /* master count of embeds in this document */ - lo_SavedData savedData; /* layout data */ - - int32 total_bytes; - int32 current_bytes; - int32 layout_bytes; - int32 script_bytes; - intn layout_percent; - - lo_GridRec *the_grid; - lo_GridRec *old_grid; - - PRPackedBool is_grid; /* once a grid is started, ignore other tags */ - int ignore_tag_nest_level; /* For NOSCRIPT, NOEMBED, NOLAYER */ - int ignore_layer_nest_level; /* For <LAYER SUPPRESS> */ - - PRPackedBool in_nogrids; /* special way to ignore tags in <noframes> */ - PRPackedBool in_applet; /* special way to ignore tags in java applet */ - PRPackedBool is_binary; /* hack for images instead of HTML doc */ - PRPackedBool insecure_images; /* secure doc with insecure images */ - PRPackedBool out_of_memory; /* ran out of memory mid-layout */ - PRPackedBool finished; /* lo_FinishLayout() has been called */ - NET_ReloadMethod - force_reload; /* URL_Struct reload flag */ - intn auto_scroll; /* Chat auto-scrolling layout, # of lines */ - intn security_level; /* non-zero for secure docs. */ - URL_Struct *nurl; /* the netlib url struct */ - - PA_Block font_face_array; /* really a (char **) */ - intn font_face_array_len; - intn font_face_array_size; - - XP_Block text_attr_hash; /* really a (LO_TextAttr **) */ - - LO_Element *recycle_list; /* List of Elements to be reused */ - LO_Element *trash; /* List of Elements to discard later */ - - lo_DocState *doc_state; - - ED_Buffer *edit_buffer; - uint32 script_tag_count; /* number of script tags processed so far */ - uint script_lineno; /* parser newline count at last <SCRIPT> tag */ - int8 in_script; /* script type if in script, see below */ - PRPackedBool in_blocked_script; /* inside blocked <SCRIPT> tag container */ - int8 default_style_script_type; /* the default script type or the last - * type of script encountered - */ - PRPackedBool resize_reload; /* is this a resize-induced reload? */ - PRPackedBool mocha_has_onload; - PRPackedBool mocha_has_onunload; - JSVersion version; - uint32 mocha_loading_applets_count; - uint32 mocha_loading_embeds_count; - NET_StreamClass *mocha_write_stream; - void *scriptData; - - struct pa_DocData_struct *doc_data; - PA_Tag **input_write_point[MAX_INPUT_WRITE_LEVEL]; - uint32 input_write_level; - PRPackedBool tag_from_inline_stream; - -#ifdef HTML_CERTIFICATE_SUPPORT - lo_Certificate *cert_list; /* list of certificates in doc */ -#endif - StyleAndTagStack * style_stack; - char *small_bm_icon; - char *large_bm_icon; - - Bool diff_state; /* set if our state record is different but at the same level */ - int32 state_pushes; /* how many new states have we added */ - int32 state_pops; /* how many states have we removed */ - CL_Layer *doc_layer; /* Root document layer */ - CL_Layer *body_layer; /* Layer enclosing contents of BODY tag */ - lo_ObjectStack *object_stack; /* See layobj.c */ - lo_ObjectStack *object_cache; - int32 tag_count; /* sequential tag numbering */ - PRPackedBool flushing_blockage; - PRPackedBool wedged_on_mocha; - Bool in_cell_relayout; - int16 table_nesting_level; /* Counter to keep track of depth of nesting within tables */ - TagList *metaTags; /* The meta tags encountered by layout in the currently loaded document. */ -#ifdef DEBUG_ScriptPlugin - char * mimetype; -#endif -#ifdef DOM - struct DOM_Node *top_node; /* top of the DOM_Node tree */ - struct DOM_Node *current_node; /* node that's parent of next content */ - struct DOM_Node *active_node; /* node for which we're making elements */ - struct DOM_StyleDatabase *style_db; -#endif - void* LAPIprobe; -}; - -/* Script type codes, stored in top_state->in_script. */ -#define SCRIPT_TYPE_NOT 0 -#define SCRIPT_TYPE_MOCHA 1 -#define SCRIPT_TYPE_CSS 2 -#define SCRIPT_TYPE_JSSS 3 -#define SCRIPT_TYPE_UNKNOWN 4 -#ifdef DEBUG_ScriptPlugin -#define SCRIPT_TYPE_PLUGIN 5 -#endif -extern void -lo_DestroyScriptData(void *data); - -/* Define to get the reload flag of the current document */ -#define FORCE_RELOAD_FLAG(top_state) \ - ((top_state)->resize_reload ? NET_RESIZE_RELOAD : (top_state)->force_reload) - - -/* - Internal Prototypes -*/ - -extern lo_FontStack *lo_DefaultFont(lo_DocState *, MWContext *); -extern Bool lo_FilterTag(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_LayoutTag(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_PreLayoutTag(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_PostLayoutTag(MWContext *, lo_DocState *, PA_Tag *, XP_Bool); -extern void lo_SaveSubdocTags(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_FreshText(lo_DocState *); -extern void lo_InsertLineBreak(MWContext *, lo_DocState *, uint32, uint32, Bool); -extern void lo_HardLineBreak(MWContext *, lo_DocState *, Bool); -extern void lo_HardLineBreakWithClearType(MWContext *, lo_DocState *, uint32, Bool); -extern void lo_SoftLineBreak(MWContext *, lo_DocState *, Bool); -extern void lo_SetSoftLineBreakState(MWContext *, lo_DocState *, Bool, intn); -extern void lo_SetLineBreakState(MWContext *context, lo_DocState *state, Bool breaking, - uint32 break_type, intn linefeed_state, Bool relayout); -extern void lo_InsertWordBreak(MWContext *, lo_DocState *); -extern void lo_FormatText(MWContext *, lo_DocState *, char *); -extern void lo_PreformatedText(MWContext *, lo_DocState *, char *); -extern LO_Element * lo_RelayoutTextBlock ( MWContext * context, lo_DocState * state, LO_TextBlock * block, LO_TextStruct * fromElement ); -extern Bool lo_ChangeText ( LO_TextBlock * block, char * text ); -extern void lo_FlushLineBuffer(MWContext *, lo_DocState *); -extern void lo_FlushTextBlock ( MWContext *context, lo_DocState *state ); -extern void lo_ResetFontStack(MWContext *, lo_DocState *); -/* This always sets the color. "state" will be obtained in function if NULL */ -extern void lo_SetBodyTextFGColor(MWContext *context, lo_DocState *state, LO_Color *color); -/* This sets the color only the first time its called for one GetURL+layout cycle */ -extern void lo_ChangeBodyTextFGColor(MWContext *context, lo_DocState *state, LO_Color *color); -extern void lo_PushFont(lo_DocState *, intn, LO_TextAttr *); -extern LO_TextAttr *lo_PopFont(lo_DocState *, intn); -extern void lo_PopAllAnchors(lo_DocState *); -extern void lo_FlushLineList(MWContext *, lo_DocState *, uint32, uint32, Bool); -extern LO_LinefeedStruct *lo_NewLinefeed(lo_DocState *, MWContext *, uint32, uint32); -extern void lo_HorizontalRule(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_FormatImage(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_FormatEmbed(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_RelayoutEmbed ( MWContext *context, lo_DocState *state, - LO_EmbedStruct * embed, PA_Tag * tag ); -extern void lo_FormatJavaApp(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_JavaAppParam(MWContext *, lo_DocState *, PA_Tag *, LO_JavaAppStruct *); -extern void lo_CloseJavaApp(MWContext *, lo_DocState *, LO_JavaAppStruct *); -void lo_RelayoutJavaApp(MWContext *, lo_DocState *, PA_Tag *, LO_JavaAppStruct * ); -extern void lo_ProcessSpacerTag(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_ProcessBodyTag(MWContext *, lo_DocState *, PA_Tag *); -extern char *lo_ParseBackgroundAttribute(MWContext *, - lo_DocState *, PA_Tag *, - Bool); -extern void lo_BodyBackground(MWContext *, lo_DocState *, PA_Tag *, Bool); -extern void lo_BodyForeground(MWContext *, lo_DocState *, PA_Tag *); -extern int32 lo_ValueOrPercent(char *, Bool *); -extern void lo_BreakOldElement(MWContext *, lo_DocState *); -extern void lo_BreakOldTextBlockElement(MWContext *context, lo_DocState *state); -extern int32 lo_baseline_adjust(MWContext *context, lo_DocState *state, LO_Element *ele_list, - int32 old_baseline, int32 old_line_height); -extern void lo_UpdateElementPosition ( lo_DocState * state, LO_Element * element ); -extern void lo_CopyTextAttr(LO_TextAttr *, LO_TextAttr *); - -/* - * Get a TextAttr that matches the one passed in, by finding an existing one - * in the text_attr_hash collection or creating a new one. - */ -extern LO_TextAttr * -lo_FetchTextAttr(lo_DocState *, LO_TextAttr *); - -/* - * Get a new (unshared) TextAttr that's a copy of the existing one. - */ -extern LO_TextAttr * -lo_NewCopyTextAttr(lo_DocState *, LO_TextAttr *); - -#ifdef DOM -/* - * Get a TextAttr that has all the data from the font stack and Perignon. - */ -extern LO_TextAttr * -lo_GetCurrentTextAttr(lo_DocState *state, MWContext *context); - -/* - * Return a TextAttr that has the Perignon data filled in. If isMutable - * is true, it will alter the TextAttr in place, and always return the - * same pointer. Otherwise, the return value may not be the same as - * the TextAttr passed in, since it will lo_FetchTextAttr the final TextAttr - * if mutated. (If it hasn't changed anything, it will return tptr, so that - * can be used to check.) - */ -extern LO_TextAttr * -lo_FillInTextStyleInfo(lo_DocState *state, MWContext *context, - LO_TextAttr *tptr, JSBool isMutable); -#endif /* DOM */ - -extern void lo_FindLineMargins(MWContext *, lo_DocState *, Bool updateFE); -extern void lo_AddMarginStack(lo_DocState *, int32, int32, int32, int32, - int32, int32, int32, intn); -extern LO_AnchorData *lo_NewAnchor(lo_DocState *, PA_Block, PA_Block); - -/* should we underline anchors? */ -extern Bool lo_underline_anchors(void); -extern void lo_DestroyAnchor(LO_AnchorData *anchor_data); -extern void lo_AddToUrlList(MWContext *, lo_DocState *, LO_AnchorData *); -extern void lo_AddEmbedData(MWContext *, void *, lo_FreeProc, int32); -extern lo_ListStack *lo_DefaultList(lo_DocState *); -extern void lo_PushList(lo_DocState *, PA_Tag *, int8); -extern lo_ListStack *lo_PopList(lo_DocState *, PA_Tag *); - -extern void lo_PushAlignment(lo_DocState *, intn, int32); -extern lo_AlignStack *lo_PopAlignment(lo_DocState *); - -extern void lo_PushLineHeight(lo_DocState *, int32); -extern lo_LineHeightStack *lo_PopLineHeight(lo_DocState *); - -extern Bool lo_InitDocLists(MWContext *context, lo_DocLists *doc_lists); -extern void lo_DeleteDocLists(MWContext *context, lo_DocLists *doc_lists); - -extern lo_TopState *lo_NewTopState(MWContext *, char *); -extern void lo_PushStateLevel(MWContext *context); -extern void lo_PopStateLevel(MWContext *context); -extern lo_DocState *lo_NewLayout(MWContext *, int32, int32, int32, int32, - lo_DocState*); -extern lo_DocState * -lo_InitDocState(lo_DocState *state, MWContext *context, - int32 width, int32 height, - int32 margin_width, int32 margin_height, - lo_DocState* clone_state, - lo_DocLists *doc_lists, - PRBool is_for_new_layer); - -extern lo_SavedFormListData *lo_NewDocumentFormListData(void); -extern Bool lo_StoreTopState(int32, lo_TopState *); - -/* get the TopState for a given doc_id (MWContext.doc_id) */ -extern lo_TopState *lo_FetchTopState(int32); - -extern lo_DocState *lo_TopSubState(lo_TopState *); -extern lo_DocState *lo_CurrentSubState(lo_DocState *); - -extern void lo_InheritParentState(MWContext *, lo_DocState *, lo_DocState *); -extern void lo_InheritParentColors(MWContext *context, lo_DocState *child_state, lo_DocState *parent_state); -extern void lo_GetImage(MWContext *context, IL_GroupContext *img_cx, - LO_ImageStruct *lo_image, XP_ObserverList obs_list, - NET_ReloadMethod requested_reload_method); -extern void lo_NoMoreImages(MWContext *); -extern void lo_FinishImage(MWContext *, lo_DocState *, LO_ImageStruct *); -extern void lo_FinishEmbed(MWContext *, lo_DocState *, LO_EmbedStruct *); -extern void lo_BlockedImageLayout(MWContext *, lo_DocState *, PA_Tag *, char *base_url); -extern void lo_PartialFormatImage(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_FlushBlockage(MWContext *, lo_DocState *, lo_DocState *); -extern void lo_FinishLayout(MWContext *, lo_DocState *, int32); -extern void lo_FreeLayoutData(MWContext *, lo_DocState *); -extern void lo_CloseMochaWriteStream(lo_TopState *top_state, int mocha_event); -struct pa_DocData_struct; -extern LO_Element *lo_InternalDiscardDocument(MWContext *, lo_DocState *, struct pa_DocData_struct *, Bool bWholeDoc); -extern void lo_FreePartialTable(MWContext *, lo_DocState *, lo_TableRec *); -extern void lo_FreePartialSubDoc(MWContext *, lo_DocState *, LO_SubDocStruct *); -extern void lo_FreePartialCell(MWContext *context, lo_DocState *state, - LO_CellStruct *cell); -extern void lo_FreeElement(MWContext *context, LO_Element *, Bool); -extern void lo_FreeElementList(MWContext *, LO_Element *); -extern void lo_FreeImageAttributes(LO_ImageAttr *image_attr); -extern void lo_ScrapeElement(MWContext *context, LO_Element *, Bool); -extern int32 lo_FreeRecycleList(MWContext *context, LO_Element *); -extern void lo_FreeGridRec(lo_GridRec *); -extern void lo_FreeGridCellRec(MWContext *, lo_GridRec *, lo_GridCellRec *); -extern void lo_FreeGridEdge(lo_GridEdge *); -extern void lo_FreeFormElementData(LO_FormElementData *element_data); -extern void lo_free_cell_record(MWContext *context, lo_DocState *state, lo_TableCell *cell); -extern void lo_ScrapeTableElement( MWContext *context, LO_TableStruct *table_ele ); - - -#ifdef MEMORY_ARENAS -extern void lo_InitializeMemoryArena(lo_TopState *); -extern int32 lo_FreeMemoryArena(lo_arena *); -extern char *lo_MemoryArenaAllocate(lo_TopState *, int32); -#endif /* MEMORY_ARENAS */ - -extern void lo_fillin_text_info(MWContext *context, lo_DocState *state); -/* are we allowed to use page-provided font faces? */ -extern Bool lo_face_attribute(void); -extern char *lo_FetchFontFace(MWContext *, lo_DocState *, char *); -extern PA_Block lo_FetchParamValue(MWContext *, PA_Tag *, char *); -extern PA_Block lo_ValueToAlpha(int32, Bool, intn *); -extern void lo_PlaceQuoteMarker(MWContext *, lo_DocState *, lo_ListStack *); -extern void lo_PlaceBulletStr(MWContext *, lo_DocState *); -extern void lo_PlaceBullet (MWContext *, lo_DocState *); -extern PA_Block lo_ValueToRoman(int32, Bool, intn *); -extern void lo_ConvertAllValues(MWContext *, char **, int32, uint); -extern void lo_CloseOutLayout(MWContext *, lo_DocState *); -extern void lo_CloseOutTable(MWContext *, lo_DocState *); -extern void lo_CloseParagraph(MWContext *context, lo_DocState **state, PA_Tag *tag, intn blank_lines); -extern void lo_ProcessHeader(MWContext *context, lo_DocState *state, LO_HeadingStruct *header, Bool in_relayout); -extern void lo_CloseTable(MWContext *, lo_DocState *); /* from laytags.c */ -extern void lo_ShiftMarginsUp(MWContext *, lo_DocState *, int32); -extern void lo_ClearToLeftMargin(MWContext *, lo_DocState *); -extern void lo_ClearToRightMargin(MWContext *, lo_DocState *); -extern void lo_ClearToBothMargins(MWContext *, lo_DocState *); -extern void lo_BeginForm(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_ProcessInputTag(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_FreeDocumentGridData(MWContext *, lo_SavedGridData *); -extern void lo_FreeDocumentEmbedListData(MWContext *, lo_SavedEmbedListData *); -extern void lo_FreeDocumentFormListData(MWContext *, lo_SavedFormListData *); -extern void lo_SaveFormElementStateInFormList(MWContext *context, lo_FormData *form_list, Bool discard_elements); -extern void lo_SaveFormElementState(MWContext *, lo_DocState *, Bool); -extern void lo_BeginTextareaTag(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_EndTextareaTag(MWContext *, lo_DocState *, PA_Block ); -extern void lo_BeginOptionTag(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_EndOptionTag(MWContext *, lo_DocState *, PA_Block ); -extern void lo_BeginSelectTag(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_EndSelectTag(MWContext *, lo_DocState *); -extern void lo_ProcessKeygenTag(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_BeginSubDoc(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_EndSubDoc(MWContext *, lo_DocState *,lo_DocState *,LO_Element *); -extern void lo_BeginCell(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_EndCell(MWContext *, lo_DocState *, LO_Element *); -extern void lo_RecreateGrid(MWContext *, lo_DocState *, lo_GridRec *); -extern void lo_BeginGrid(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_EndGrid(MWContext *, lo_DocState *, lo_GridRec *); -extern void lo_BeginGridCell(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_BeginSubgrid(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_EndSubgrid(MWContext *, lo_DocState *, lo_GridRec *); -extern void lo_BeginMap(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_EndMap(MWContext *, lo_DocState *, lo_MapRec *); -extern lo_MapRec *lo_FreeMap(lo_MapRec *); -extern void lo_BeginMapArea(MWContext *, lo_DocState *, PA_Tag *); -extern lo_MapRec *lo_FindNamedMap(MWContext *, lo_DocState *, char *); -extern LO_AnchorData *lo_MapXYToAnchorData(MWContext *, lo_DocState *, - lo_MapRec *, int32, int32); -extern void lo_BeginLayerTag(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_EndLayer(MWContext *, lo_DocState *, PRBool); -extern void lo_BeginMulticolumn(MWContext *context, lo_DocState *state, PA_Tag *tag, - LO_MulticolumnStruct *multicolEle); -extern void lo_EndMulticolumn(MWContext *context, lo_DocState *state, PA_Tag *tag, - lo_MultiCol *multicol, Bool relayout); -extern void lo_AppendMultiColToLineList (MWContext *context, lo_DocState *state, - LO_MulticolumnStruct *multicol); -extern void lo_AppendZeroWidthAndHeightLF(MWContext *context, lo_DocState *state); - -extern void lo_BeginTable(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_EndTable(MWContext *context, lo_DocState *state, lo_TableRec *table, Bool relayout); - -extern void lo_BeginTableAttributes(MWContext *context, - lo_DocState *state, - char *align_attr, - char *border_attr, - char *border_top_attr, - char *border_bottom_attr, - char *border_left_attr, - char *border_right_attr, - char *border_color_attr, - char *border_style_attr, - char *vspace_attr, - char *hspace_attr, - char *bgcolor_attr, - char *background_attr, - char *width_attr, - char *height_attr, - char *cellpad_attr, - char *toppad_attr, - char *bottompad_attr, - char *leftpad_attr, - char *rightpad_attr, - char *cellspace_attr, - char *cols_attr); - -extern void lo_BeginTableRow(MWContext *, lo_DocState *,lo_TableRec *,PA_Tag *); - -void lo_BeginTableRowAttributes(MWContext *context, - lo_DocState *state, - lo_TableRec *table, - char *bgcolor_attr, - char *background_attr, - char *valign_attr, - char *halign_attr); - -extern void lo_EndTableRow(MWContext *, lo_DocState *, lo_TableRec *); -extern void lo_BeginTableCell(MWContext *, lo_DocState *, lo_TableRec *, - PA_Tag *, Bool); -extern void lo_BeginTableCellAttributes(MWContext *context, - lo_DocState *state, - lo_TableRec *table, - char * colspan_attr, - char * rowspan_attr, - char * nowrap_attr, - char * bgcolor_attr, - char * background_attr, - lo_TileMode tile_mode, - char * valign_attr, - char * halign_attr, - char * width_attr, - char * height_attr, - Bool is_a_header, - Bool normal_borders); - -extern void lo_EndTableCell(MWContext *, lo_DocState *, Bool relayout); -extern void lo_BeginTableCaption(MWContext *, lo_DocState *, lo_TableRec *, - PA_Tag *); -extern void lo_EndTableCaption(MWContext *, lo_DocState *); -extern int32 lo_GetSubDocBaseline(LO_SubDocStruct *); -extern int32 lo_GetCellBaseline(LO_CellStruct *); -extern LO_CellStruct *lo_CaptureLines(MWContext *, lo_DocState *, - int32, int32, int32, int32, int32); -extern LO_CellStruct *lo_SmallSquishSubDocToCell(MWContext *, lo_DocState *, - LO_SubDocStruct *, int32 *ptr_dx, int32 *ptr_dy); -extern LO_CellStruct *lo_SquishSubDocToCell(MWContext *, lo_DocState *, - LO_SubDocStruct *, Bool); -extern LO_Element *lo_JumpCellWall(MWContext *, lo_DocState *, LO_Element *); - -extern LO_TextAttr *lo_GetElementTextAttr(LO_Element *element); -extern void lo_SetElementTextAttr(LO_Element *element, LO_TextAttr *attr); -extern void lo_GetElementBbox(LO_Element *element, XP_Rect *rect); -extern void lo_RefreshElement(LO_Element *element, CL_Layer *layer, - Bool update_now); -extern LO_AnchorData *lo_GetElementAnchor(LO_Element *element); -extern void lo_GetElementFGColor(LO_Element *element, LO_Color *color); -extern void lo_SetElementFGColor(LO_Element *element, LO_Color *color); - -extern void lo_RenumberCell(lo_DocState *, LO_CellStruct *); -extern void lo_ShiftCell(LO_CellStruct *, int32, int32); -extern int32 lo_CleanTextWhitespace(char *, int32); -extern void lo_ProcessIsIndexTag(MWContext *, lo_DocState *, PA_Tag *); -extern void lo_EndForm(MWContext *, lo_DocState *); -extern void lo_RecycleElements(MWContext *, lo_DocState *, LO_Element *); -extern void lo_relayout_recycle(MWContext *context, lo_DocState *state, - LO_Element *elist); -extern LO_Element *lo_NewElement(MWContext *, lo_DocState *, intn, - ED_Element *, intn edit_offset); -#if DOM -extern void lo_SetNodeElement(lo_DocState *, LO_Element *); -#endif -extern void lo_AppendToLineList(MWContext *, lo_DocState *, LO_Element *,int32); -extern void lo_SetLineArrayEntry(lo_DocState *, LO_Element *, int32); -extern LO_Element *lo_FirstElementOfLine(MWContext *, lo_DocState *, int32); -extern void lo_ClipLines(MWContext *, lo_DocState *, int32); -extern void lo_SetDefaultFontAttr(lo_DocState *, LO_TextAttr *, MWContext *); -extern Bool lo_EvalTrueOrFalse(char *str, Bool default_val); -extern intn lo_EvalAlignParam(char *str, Bool *floating); -extern intn lo_EvalVAlignParam(char *str); -extern void lo_EvalStyleSheetAlignment(StyleStruct *, intn *, Bool *floating); -#ifdef DOM -struct DOM_StyleDatabase; -struct DOM_Node; -void lo_SetStyleSheetLayerProperties(MWContext *context, lo_DocState *state, - struct DOM_StyleDatabase *db, - struct DOM_Node *node, - PA_Tag *tag); -struct DOM_StyleDatabase * -DOMMOZ_NewStyleDatabase(JSContext *context, lo_DocState *state); -#else -void lo_SetStyleSheetLayerProperties(MWContext *context, - lo_DocState *state, - StyleStruct *style_struct, - PA_Tag *tag); -#endif -char * lo_ParseStyleSheetURL(char *url_string); -extern intn lo_EvalCellAlignParam(char *str); -extern intn lo_EvalDivisionAlignParam(char *str); -extern PA_Block lo_ConvertToFELinebreaks(char *, int32, int32 *); -extern PA_Block lo_FEToNetLinebreaks(PA_Block); -extern void lo_CleanFormElementData(LO_FormElementData *); -extern Bool lo_SetNamedAnchor(lo_DocState *, PA_Block); - -#ifdef DOM -extern Bool lo_SetNamedSpan(lo_DocState *, PA_Block); -extern void lo_SetColor( LO_Element *ele, LO_Color *color, lo_DocState *state, - Bool background); -#endif - -extern void lo_AddNameList(lo_DocState *, lo_DocState *); -extern void lo_DisplayBuiltin(MWContext *, LO_BuiltinStruct *); -extern void lo_CheckNameList(MWContext *, lo_DocState *, int32); -extern int32 lo_StripTextWhitespace(char *, int32); -extern int32 lo_StripTextNewlines(char *, int32); -extern int32 lo_ResolveInputType(char *); -extern Bool lo_IsValidTarget(char *); -extern Bool lo_IsAnchorInDoc(lo_DocState *, char *); - -extern void lo_DisplayElement(MWContext *context, LO_Element *tptr, - int32 base_x, int32 base_y, - int32 x, int32 y, - uint32 width, uint32 height); -extern void lo_DisplaySubtext(MWContext *context, LO_TextStruct *text, - int32 start_pos, int32 end_pos, Bool need_bg, - CL_Layer *sel_layer); -extern void lo_DisplayText(MWContext *, LO_TextStruct *, Bool); -extern void lo_DisplayEmbed(MWContext *, LO_EmbedStruct *); -extern void lo_DisplayJavaApp(MWContext *, LO_JavaAppStruct *); -extern void lo_DisplayImageWithoutCompositor(MWContext *, LO_ImageStruct *); -extern void lo_DisplaySubImageWithoutCompositor(MWContext *, LO_ImageStruct *, - int32, int32, uint32, uint32); -extern void lo_ClipImage(MWContext *, LO_ImageStruct *, - int32, int32, uint32, uint32); -extern void lo_DisplaySubDoc(MWContext *, LO_SubDocStruct *); -extern void lo_DisplayCell(MWContext *, LO_CellStruct *); -extern void lo_DisplayCellContents(MWContext *context, LO_CellStruct *cell, - int32 base_x, int32 base_y, - int32 x, int32 y, - uint32 width, uint32 height); -extern void lo_DisplayEdge(MWContext *, LO_EdgeStruct *); -extern void lo_DisplayTable(MWContext *, LO_TableStruct *); -extern void lo_DisplayLineFeed(MWContext *, LO_LinefeedStruct *, Bool); -extern void lo_DisplayHR(MWContext *, LO_HorizRuleStruct *); -extern void lo_DisplayBullet(MWContext *, LO_BullettStruct *); -extern void lo_DisplayFormElement(MWContext *, LO_FormElementStruct *); -extern void LO_HighlightSelection(MWContext *, Bool); - -extern void lo_RefreshDocumentArea(MWContext *, lo_DocState *, - int32, int32, uint32, uint32); - -extern intn lo_GetCurrentGridCellStatus(lo_GridCellRec *); -extern char *lo_GetCurrentGridCellUrl(lo_GridCellRec *); -extern void lo_GetGridCellMargins(MWContext *, int32 *, int32 *); -extern LO_Element *lo_XYToGridEdge(MWContext *, lo_DocState *, int32, int32); -extern LO_Element *lo_XYToDocumentElement(MWContext *, lo_DocState *, - int32, int32, Bool, Bool, Bool, int32 *, int32 *); -extern LO_Element *lo_XYToDocumentElement2(MWContext *, lo_DocState *, - int32, int32, Bool, Bool, Bool, Bool, int32 *, int32 *); -extern LO_Element *lo_XYToCellElement(MWContext *, lo_DocState *, - LO_CellStruct *, int32, int32, Bool, Bool, Bool); -extern LO_Element *lo_XYToNearestCellElement(MWContext *, lo_DocState *, - LO_CellStruct *, int32, int32); -extern void lo_RegionToLines (MWContext *, lo_DocState *, int32 x, int32 y, - uint32 width, uint32 height, Bool dontCrop, - int32* topLine, int32* bottomLine); -extern int32 lo_PointToLine (MWContext *, lo_DocState *, int32 x, int32 y); -extern void lo_FormatBuiltinObject(MWContext*, lo_DocState*, PA_Tag*, LO_BuiltinStruct*, Bool, - uint32 count, char** names, char** values); -extern void lo_GetLineEnds(MWContext *, lo_DocState *, - int32 line, LO_Element** retBegin, LO_Element** retEnd); -extern void lo_CalcAlignOffsets(lo_DocState *, LO_TextInfo *, intn, - int32, int32, int16 *, int32 *, int32 *, int32 *); -extern intn LO_CalcPrintArea(MWContext *, int32 x, int32 y, - uint32 width, uint32 height, int32* top, int32* bottom); -extern Bool lo_FindWord(MWContext *, lo_DocState *, - LO_Position *where, LO_Selection *word); - -/* Object */ -extern void lo_FormatObject(MWContext*, lo_DocState*, PA_Tag*); -extern void lo_ObjectParam(MWContext*, lo_DocState*, PA_Tag*, uint32*, char***, char***); -extern void lo_ProcessObjectTag(MWContext*, lo_DocState*, PA_Tag*, Bool); -extern void lo_ProcessParamTag(MWContext*, lo_DocState*, PA_Tag*, Bool); -extern void lo_FormatEmbedObject(MWContext*, lo_DocState*, PA_Tag*, LO_EmbedStruct*, Bool, - uint32 count, char** names, char** values); -extern void lo_FormatJavaObject(MWContext *context, lo_DocState *state, - PA_Tag *tag, LO_JavaAppStruct *object); -extern void lo_AppendParamList(uint32* count1, char*** names1, char*** values1, - uint32 count2, char** names2, char** values2); -extern void lo_DeleteObjectStack(lo_ObjectStack*); - -extern void lo_BlockTag(MWContext *context, lo_DocState *state, - PA_Tag *tag); -extern void lo_ReflectFormElement(MWContext *context, - lo_DocState *doc_state, PA_Tag *tag, - LO_FormElementStruct *form_element); - - -extern void lo_ProcessSuperElement(MWContext *context, - lo_DocState *state, - LO_SuperStruct *super); -extern void lo_ProcessSubElement(MWContext *context, - lo_DocState *state, - LO_SubStruct *sub); -extern void lo_ProcessParagraphElement(MWContext *context, lo_DocState **state, - LO_ParagraphStruct *paragraph, - XP_Bool in_relayout); - -extern void lo_ProcessCenterElement(MWContext *context, lo_DocState **state, - LO_CenterStruct *center, - XP_Bool in_relayout); - -extern void lo_ProcessMulticolumnElement(MWContext *context, - lo_DocState **state, - LO_MulticolumnStruct *multicolumn); - -extern void lo_ProcessDescTitleElement(MWContext *context, - lo_DocState *state, - LO_DescTitleStruct *title, - XP_Bool in_relayout); -extern void lo_ProcessDescTextElement(MWContext *context, - lo_DocState *state, - LO_DescTextStruct *text, - XP_Bool in_relayout); -extern void lo_ProcessBlockQuoteElement(MWContext *context, - lo_DocState *state, - LO_BlockQuoteStruct *quote, - XP_Bool in_relayout); - -/* - * Functions that get called from layout and non-destructive relayout - * - */ -extern void lo_FillInImageGeometry( lo_DocState *state, LO_ImageStruct *image ); -extern void lo_LayoutFloatImage( MWContext *context, lo_DocState *state, LO_ImageStruct *image, Bool updateFE ); -extern void lo_LayoutInflowImage(MWContext *context, lo_DocState *state, LO_ImageStruct *image, - Bool inRelayout, int32 *line_inc, int32 *baseline_inc); -extern void lo_UpdateStateAfterImageLayout( lo_DocState *state, LO_ImageStruct *image, int32 line_inc, int32 baseline_inc ); - -extern void lo_FillInJavaAppGeometry(lo_DocState *state, LO_JavaAppStruct *java_app, Bool relayout); -extern void lo_LayoutFloatJavaApp( MWContext *context, lo_DocState *state, LO_JavaAppStruct *java_app, Bool updateFE ); -extern void lo_LayoutInflowJavaApp(MWContext *context, lo_DocState *state, LO_JavaAppStruct *java_app, - Bool inRelayout, int32 *line_inc, int32 *baseline_inc); -extern void lo_UpdateStateAfterJavaAppLayout( lo_DocState *state, LO_JavaAppStruct *java_app, - int32 line_inc, int32 baseline_inc ); - -extern void lo_FillInEmbedGeometry(lo_DocState *state, LO_EmbedStruct *embed, Bool relayout); -extern void lo_LayoutInflowEmbed(MWContext *context, lo_DocState *state, LO_EmbedStruct *embed, - Bool inRelayout, int32 *line_inc, int32 *baseline_inc); -extern void lo_LayoutInflowBuiltin(MWContext *context, lo_DocState *state, LO_BuiltinStruct *builtin, - Bool inRelayout, int32 *line_inc, int32 *baseline_inc); -extern void lo_LayoutFloatEmbed(MWContext *context, lo_DocState *state, LO_EmbedStruct *embed, Bool updateFE); -extern void lo_UpdateStateAfterEmbedLayout( lo_DocState *state, LO_EmbedStruct *embed, - int32 line_inc, int32 baseline_inc ); - -extern void lo_LayoutInflowFormElement(MWContext *context, lo_DocState *state, LO_FormElementStruct *form_element, - int32 *baseline_inc, Bool inRelayout); -extern void lo_UpdateStateAfterFormElement(MWContext *context, lo_DocState *state, LO_FormElementStruct *form_element, - int32 baseline_inc); - -extern void lo_StartHorizontalRuleLayout(MWContext *, lo_DocState *, LO_HorizRuleStruct*); -extern void lo_FillInHorizontalRuleGeometry(MWContext *context, lo_DocState *state, LO_HorizRuleStruct *hrule); -extern void lo_FinishHorizontalRuleLayout(MWContext *, lo_DocState *, LO_HorizRuleStruct*); -extern void lo_UpdateStateAfterHorizontalRule(lo_DocState *state, LO_HorizRuleStruct *hrule); - -extern void lo_FormatBullet(MWContext *context, lo_DocState *state, - LO_BulletStruct *bullet, - int32 *line_height, - int32 *baseline); -extern void lo_UpdateStateAfterBullet(MWContext *context, lo_DocState *state, - LO_BulletStruct *bullet, - int32 line_height, - int32 baseline); - -extern void lo_FormatBulletStr(MWContext *context, lo_DocState *state, - LO_TextStruct *bullet_text, - int32 *line_height, - int32 *baseline); -extern void lo_UpdateStateAfterBulletStr(MWContext *context, lo_DocState *state, - LO_TextStruct *bullet_text, - int32 line_height, - int32 baseline); - -extern void lo_SetupStateForList(MWContext *context, - lo_DocState *state, - LO_ListStruct *list, - XP_Bool in_resize_reflow); -extern void lo_UpdateStateAfterList(MWContext *context, - lo_DocState *state, - LO_ListStruct *list, - XP_Bool in_resize_reflow); - -extern void lo_UpdateStateAfterLineBreak( MWContext *context, lo_DocState *state, Bool updateFE); -extern void lo_UpdateFEProgressBar( MWContext *context, lo_DocState *state ); -extern void lo_UpdateFEDocSize( MWContext *context, lo_DocState *state ); -extern void lo_FillInLineFeed( MWContext *context, lo_DocState *state, int32 break_type, uint32 clear_type, LO_LinefeedStruct *linefeed ); - -extern void lo_UpdateStateWhileFlushingLine( MWContext *context, lo_DocState *state ); -extern void lo_AppendLineFeed( MWContext *context, lo_DocState *state, LO_LinefeedStruct *linefeed, int32 breaking, Bool updateFE ); -extern void lo_UpdateStateAfterFlushingLine( MWContext *context, lo_DocState *state, LO_LinefeedStruct *linefeed, Bool inRelayout ); -extern void lo_AppendFloatInLineList( MWContext *context, lo_DocState *state, LO_Element *ele, LO_Element *restOfLine); - -/* - * Common code for layout and relayout of tables - */ -extern void lo_PositionTableElement(lo_DocState *state, LO_TableStruct *table_ele); -extern void lo_SetTableDimensions( lo_DocState *state, lo_TableRec *table, int32 allow_percent_width, int32 allow_percent_height); -extern void lo_CalcFixedColWidths( MWContext *context, lo_DocState *state, lo_TableRec *table); -extern void lo_UpdateStateAfterBeginTable( lo_DocState *state, lo_TableRec *table); -extern void lo_UpdateTableStateForBeginRow(lo_TableRec *table, lo_TableRow *table_row); -extern void lo_InitForBeginCell(lo_TableRow *table_row, lo_TableCell *table_cell); -extern void lo_InitSubDocForBeginCell( MWContext *context, lo_DocState *state, lo_TableRec *table); -extern void lo_InitTableRecord( lo_TableRec *table ); -extern void lo_CreateCellFromSubDoc( MWContext *context, lo_DocState *state, LO_SubDocStruct *subdoc, LO_CellStruct *cell, int32 *ptr_dx, int32 *ptr_dy ); -extern void lo_EndLayoutDuringReflow( MWContext *context, lo_DocState *state ); -extern void lo_AppendLineListToLineArray( MWContext *context, lo_DocState *state, LO_Element *lastElementOnLineList); - -/* Common code for layout and relayout of multicols */ -extern void lo_StartMultiColInit( lo_DocState *state, lo_MultiCol *multicol ); -extern void lo_SetupStateForBeginMulticol( lo_DocState *state, lo_MultiCol *multicol, int32 doc_width ); - -/* Common code for layout and relayout of spacers */ -extern void lo_LayoutSpacerElement(MWContext *context, lo_DocState *state, LO_SpacerStruct *spacer, Bool relayout); - -/* Reflow of layers */ -extern void lo_BeginLayerReflow(MWContext *context, lo_DocState *state, - LO_BlockInitializeStruct *param, - lo_LayerDocState *layer_state); -extern void lo_EndLayerReflow(MWContext *context, lo_DocState *state); - -extern void lo_FreeBlockInitializeStruct(LO_BlockInitializeStruct *param); - -/* - * 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. - */ - -extern void lo_rl_AddSoftBreakAndFlushLine( MWContext *context, lo_DocState *state ); -extern void lo_rl_AddBreakAndFlushLine( MWContext *context, lo_DocState *state, int32 break_type, uint32 clear_type, Bool breaking); -extern void lo_rl_AppendLinefeedAndFlushLine( MWContext *context, lo_DocState *state, LO_LinefeedStruct *linefeed, int32 break_type, uint32 clear_type, - Bool breaking, Bool createNewLF); -extern void lo_FillInLineFeed( MWContext *context, lo_DocState *state, int32 break_type, uint32 clear_type, LO_LinefeedStruct *linefeed ); - -extern void lo_rl_ReflowCell( MWContext *context, lo_DocState *state, LO_CellStruct *cell); -extern void lo_rl_ReflowDocState( MWContext *context, lo_DocState *state ); -extern void lo_PrepareElementForReuse( MWContext *context, lo_DocState *state, LO_Element * eptr, - ED_Element *edit_element, intn edit_offset); -extern void LO_Reflow(MWContext *context, lo_DocState * state, LO_Element *startElement, - LO_Element *endElement); - -/* Reflow version of lo_FlushLineList() */ -extern void lo_rl_FlushLineList( MWContext *context, lo_DocState *state, - uint32 break_type, uint32 clear_type, Bool breaking ); - -extern Bool lo_IsDummyLayoutElement(LO_Element *ele); - -/* Useful Macros */ - -#define COPY_COLOR(from_color, to_color) \ - to_color.red = from_color.red; \ - to_color.green = from_color.green; \ - to_color.blue = from_color.blue - - -extern Bool lo_FindBestPositionOnLine( MWContext *pContext, - lo_DocState* state, int32 iLine, - int32 iDesiredX, int32 iDesiredY, - Bool bForward, int32* pRetX, int32 *pRetY ); - -extern LO_Element * lo_GetLastElementInList( LO_Element *eleList ); - -#ifdef EDITOR - -#ifdef DEBUG -/* lo_VerifyLayout does a consistency check on the layout structure. - * returns TRUE if the layout structure is consistent. */ -extern Bool lo_VerifyLayout(MWContext *pContext); - -/* PrintLayout prints the layout structure. */ -extern void lo_PrintLayout(MWContext *pContext); -extern Bool -lo_VerifyList( MWContext *pContext, lo_TopState* top_state, - lo_DocState* state, - LO_Element* start, - LO_Element* end, - LO_Element* floating, - Bool print); - -#endif /* DEBUG */ - -#endif /* EDITOR */ - -/* - * Returns length in selectable parts of this element. 1 for images, length of text for text, etc. - */ -int32 -lo_GetElementLength(LO_Element* eptr); - -extern Bool lo_EditableElement(int iType); - -/* Moves by one editable position forward or backward. Returns FALSE if it couldn't. - * position can be denormalized on entry and may be denormalized on exit. - */ - -Bool -lo_BumpEditablePosition(MWContext *context, lo_DocState *state, - LO_Element **pEptr, int32 *pPosition, Bool direction); - -Bool -lo_IsEmptyTag(TagType type); - - -extern lo_TopState * -lo_GetMochaTopState(MWContext *context); - -extern void -lo_BeginReflectForm(MWContext *context, lo_DocState *state, PA_Tag *tag, - lo_FormData *form); - -extern void -lo_EndReflectForm(MWContext *context, lo_FormData *form); - -extern void -lo_ReflectImage(MWContext *context, lo_DocState *doc_state, PA_Tag *tag, - LO_ImageStruct *image_data, Bool blocked, int32 layer_id); - -extern void -lo_ReflectNamedAnchor(MWContext *context, lo_DocState *state, PA_Tag *tag, - lo_NameList *name_rec, int32 layer_id); - -#ifdef DOM -extern void -lo_ReflectSpan(MWContext *context, lo_DocState *doc_state, PA_Tag *tag, - lo_NameList *name_rec, int32 layer_id); -#endif - -extern void -lo_ReflectLink(MWContext *context, lo_DocState *state, PA_Tag *tag, - LO_AnchorData *anchor_data, int32 layer_id, uint index); - -extern XP_Bool -lo_ProcessContextEventHandlers(MWContext *context, lo_DocState *state, - PA_Tag *tag); - -extern void -lo_RestoreContextEventHandlers(MWContext *context, lo_DocState *state, - PA_Tag *tag, SHIST_SavedData *saved_data); - -extern void -lo_ProcessScriptTag(MWContext *context, lo_DocState *state, PA_Tag *tag, - struct JSObject * /* scope to use. can be NULL */); - - -extern XP_Bool -lo_ProcessStyleAttribute(MWContext *context, lo_DocState *state, PA_Tag *tag, char *script_buff); - -extern void -lo_ProcessStyleTag(MWContext *context, lo_DocState *state, PA_Tag *tag); - -extern void -lo_BlockScriptTag(MWContext *context, lo_DocState *state, PA_Tag *tag); - -extern lo_DocLists * -lo_GetCurrentDocLists(lo_DocState *state); - -extern lo_DocLists * -lo_GetDocListsById(lo_DocState *state, int32 id); - -Bool -lo_CloneTagAndBlockLayout(MWContext *context, lo_DocState *state, PA_Tag *tag); - -void -lo_UnblockLayout(MWContext *context, lo_TopState *top_state); - -void -lo_UnblockLayoutAndFreeExtraElement(MWContext *context); - -extern void -lo_SetBaseUrl(lo_TopState *top_state, char *url, Bool is_blocked); - -extern void -lo_FlushedBlockedTags(lo_TopState *top_state); - -extern int32 * -lo_parse_coord_list(char *str, int32 *value_cnt, Bool must_be_odd); - -extern void -lo_add_leading_bullets(MWContext *context, lo_DocState *state, - int32 start,int32 end,int32 mquote_x); - -extern void -lo_TeardownList(MWContext *context, lo_DocState *state, PA_Tag *tag); - - -extern void -lo_SetDocumentDimension( MWContext* context, lo_DocState *state ); - -extern void -lo_ScriptEvalExitFn(void * data, char * str, size_t len, char * wysiwyg_url, - char * base_href, Bool valid); - -extern Bool -lo_ConvertMochaEntities(MWContext * pContext, lo_DocState *state, PA_Tag * tag); - -extern void -lo_EditorReflow(MWContext *pContext, ED_TagCursor *pCursor, - int32 iStartLine, int iStartEditOffset); - -/* Reflow contents of a cell into a new docstate, then merge back into table */ -extern void -lo_EditorCellReflow(MWContext *context, ED_TagCursor *pCursor, LO_CellStruct *pCell); - - -/********************** Image observers and observer lists. ******************/ -/* The layout observer for an image request. */ -extern void -lo_ImageObserver(XP_Observable observable, XP_ObservableMsg message, - void *message_data, void *closure); - -/* Create a new observer list which will be passed into to IL_GetImage (via - FE_GetImageInfo) in order to permit an Image Library request to be - monitored. The layout image observer is added to this new observer list - before the function returns. */ -extern XP_ObserverList -lo_NewImageObserverList(MWContext *context, LO_ImageStruct *lo_image); - - -/* #ifndef NO_TAB_NAVIGATION */ -extern lo_MapAreaRec *LO_getTabableMapArea(MWContext *context, LO_ImageStruct *image, int32 wantedIndex ); -extern Bool LO_findApointInArea( lo_MapAreaRec *pArea, int32 *xx, int32 *yy ); -/* NO_TAB_NAVIGATION */ - -/****************************************************************************/ -/* Converts ("snaps") input X, Y (doc coordinates) to X, Y needed for drop caret - * and calls appropriate front-end FE_Display<Text|Generic|Image>Caret to use show where - * a drop would occur. It does NOT change current selection or internal caret position - * Returns the element that we will drop at and position - * within this element for text data -*/ -LO_Element * lo_PositionDropCaret(MWContext *pContext, int32 x, int32 y, int32 * pPosition); - -void -lo_free_layout_state_data(MWContext *context, lo_DocState *state); - -extern void -lo_use_default_doc_background(MWContext *context, lo_DocState *state); - -Bool -lo_BindNamedAnchorToElement(lo_DocState *state, PA_Block name, - LO_Element *element); - -#ifdef DOM -Bool -lo_BindNamedSpanToElement(lo_DocState *state, PA_Block name, - LO_Element *element); - -LO_SpanStruct * lo_FindParentSpan( LO_Element *ele ); -#endif - -/* Return the table element containing the given element (usually a LO_CELL type) */ -LO_TableStruct *lo_GetParentTable(MWContext *pContext, LO_Element *pElement); - -/* Return the cell element containing the given element */ -LO_CellStruct *lo_GetParentCell(MWContext *pContext, LO_Element *pElement); - -/* Find the first cell with with closest left border x-value less than the given x - * value or, if bGetColumn=FALSE, find the cell with closest top border y-value less - * than the given Y value. Also returns the pointer to the last LO element in row/column so - * we can search for other cells until last is reached. - * pElement is any element in the table - * This is most efficient if pElement is LO_TABLE containg cursor, - * very efficient if pElement is LO_CELL, - * and least if any other type (must search through all nested tables to find enclosing cell) -*/ -LO_Element* lo_GetFirstCellInColumnOrRow(MWContext *pContext, LO_Element *pElement, int32 x, int32 y, XP_Bool bGetColumn, LO_Element **ppLastCellInTable); - -/* Get next cell. If x or y is 0, use values from previous call or lo_GetFirstCellInColumnOrRow */ -LO_Element* lo_GetNextCellInColumnOrRow(MWContext *pContext, int32 x, int32 y, LO_Element *pElement, XP_Bool bGetColumn); - -/* Returns first cell in table, and last cell if pLastCell != NULL - * pElement can be any LO_Element in the table (quickest search if it is a LO_TABLE or LO_CELL) -*/ -LO_Element *lo_GetFirstAndLastCellsInTable(MWContext *pContext, LO_Element *pElement, LO_Element **ppLastCell); - -/* Find first and last cell from any cell in the table - * pElement->type MUST be LO_CELL -*/ -LO_Element *lo_GetFirstAndLastCellsInColumnOrRow(LO_Element *pElement, LO_Element **ppLastCell, XP_Bool bInColumn); - -/* Check if all cells containing given cell are selected */ -XP_Bool lo_AllCellsSelectedInColumnOrRow(LO_CellStruct *pCell, XP_Bool bInColumn ); - -int32 lo_GetNumberOfCellsInTable(LO_TableStruct *pTable ); - -/* Subtract borders and inter-cell spacing to get the available table width - * to use when cell width in HTML is "percent of table" - * Element MUST be of type LO_CELL (LO_CellStruct not used to avoid unecessary casting) -*/ -int32 lo_CalcTableWidthForPercentMode(LO_Element *pCellElement); - -/* The LO_CellStruct.width does not include border, cell padding etc and is complicated - * by Column Span as well. Calculate the value to use for <TD WIDTH> param that - * would result in current pCellElement->lo_cell.width during the next layout -*/ -int32 lo_GetCellTagWidth(LO_Element *pCellElement); - -/* Similar calculation for height. Unfortunately, there are differences from width. - * e.g., the cell border must be subtracted from width, but not height! (a bug?) -*/ -int32 lo_GetCellTagHeight(LO_Element *pCellElement); - -/* Helpers to access the lo_TableCell members now accessible through the LO_CellStruct */ -int32 lo_GetRowSpan(LO_Element *pCellElement); -int32 lo_GetColSpan(LO_Element *pCellElement); -int32 lo_GetCellPadding(LO_Element *pCellElement); - -lo_DocState * lo_CreateStateForCellLayout(MWContext *context, LO_CellStruct *cell); -void lo_RebuildCell(MWContext *context, lo_DocState *state, LO_CellStruct *cell); - -/* Even though this is an EDT function, this avoids having to place this in EDT.H - * It is only called by lo_ProcessClick() in laysel.c */ -extern void edt_ForceTableSelection(MWContext *pMWContext, LO_TableStruct *pLoTable); - -#endif /* _Layout_h_ */ diff --git a/lib/layout/layrelay.c b/lib/layout/layrelay.c index bd180c9c690..e69de29bb2d 100644 --- a/lib/layout/layrelay.c +++ b/lib/layout/layrelay.c @@ -1,1914 +0,0 @@ -/* -*- 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_FitBuiltin( 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 ); -static LO_Element * lo_rl_FitSuper( lo_RelayoutState *relay_state, LO_Element *lo_ele ); -static LO_Element * lo_rl_FitSub( 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_FitBuiltin, /* LO_BUILTIN */ - lo_rl_FitSpacer, /* LO_SPACER */ - lo_rl_FitSuper, /* LO_SUPER */ - lo_rl_FitSub /* LO_SUB */ -}; - - -void lo_FillInBuiltinGeometry(lo_DocState *state, LO_BuiltinStruct *builtin, - Bool relayout); -void lo_UpdateStateAfterBuiltinLayout (lo_DocState *state, LO_BuiltinStruct *builtin, - int32 line_inc, int32 baseline_inc); -static void -lo_rl_SetLayerDimensions( lo_RelayoutState *relay_state, LO_BlockInitializeStruct *layerParams ); - -/* 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(); - - /* Abort if the document is currently being laid out */ - if (LO_LayingOut( context )) - { - LO_UnlockLayout(); - return; - } - - 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); - - /* update the final document dimensions */ - state->y += state->win_bottom; - LO_SetDocumentDimensions(context, state->max_width, state->y); - -#if !defined(SMOOTH_PROGRESS) - if(!state->top_state->is_binary) - FE_SetProgressBarPercent(context, 100); -#endif /* !defined(SMOOTH_PRORGESS) */ - - lo_FreeLayoutData(context, state); - 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); - } - - /* position the document */ - FE_SetDocPosition ( context, FE_VIEW, 0, docY ); - - 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 = 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) - { -#if 0 - XP_FREE_BLOCK(state->line_array); -#ifdef XP_WIN16 - XP_FREE_BLOCK(state->larray_array); -#endif /* XP_WIN16 */ - - XP_DELETE(state->font_stack); -#endif - 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_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; - -#ifdef DOM - state->current_span = NULL; - state->in_span = FALSE; -#endif - - 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, state->allow_percent_width, state->allow_percent_height ); - 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, lo_GetLastElementInList(relay_state->doc_state->line_list) ); - - /* 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_FitBuiltin( 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_BuiltinStruct *builtin = (LO_BuiltinStruct*)lo_ele; - - lo_FillInBuiltinGeometry(relay_state->doc_state, builtin, TRUE); - lo_LayoutInflowBuiltin(relay_state->context, relay_state->doc_state, builtin, TRUE, &line_inc, &baseline_inc); - lo_AppendToLineList(relay_state->context, relay_state->doc_state, lo_ele, baseline_inc); - lo_UpdateStateAfterBuiltinLayout(relay_state->doc_state, builtin, 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->objTag.layer, - java_app->objTag.x + java_app->objTag.x_offset + java_app->objTag.border_horiz_space, - java_app->objTag.y + java_app->objTag.y_offset + java_app->objTag.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. */ - if (state->line_list) { - linefeedBeforeTable->next = state->line_list; - state->line_list->lo_any.prev = (LO_Element *) linefeedBeforeTable; - lastElementInLastCell->lo_any.next = (LO_Element *) linefeedAfterTable; - linefeedAfterTable->prev = lastElementInLastCell; - } - else { - /* This means that the MULTICOL tag did not contain anything. So we just - hook up the linefeeds before and after the table element. */ - linefeedBeforeTable->next = (LO_Element *) linefeedAfterTable; - linefeedAfterTable->prev = (LO_Element *) linefeedBeforeTable; - } - - /* 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=0, y=0; - 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->objTag.x + java_app->objTag.x_offset + java_app->objTag.border_width; - y = java_app->objTag.y + java_app->objTag.y_offset + java_app->objTag.border_width; - - layer = java_app->objTag.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->objTag.x + embed->objTag.x_offset + embed->objTag.border_width; - y = embed->objTag.y + embed->objTag.y_offset + embed->objTag.border_width; - - layer = embed->objTag.layer; - } - else if (lo_ele->lo_float.float_ele->lo_any.type == LO_BUILTIN) { - LO_BuiltinStruct *builtin = (LO_BuiltinStruct *)lo_ele->lo_float.float_ele; - - lo_LayoutFloatEmbed( relay_state->context, relay_state->doc_state, - (LO_EmbedStruct *)builtin, FALSE ); - - /* Determine the new position of the layer. */ - x = builtin->x + builtin->x_offset + builtin->border_width; - y = builtin->y + builtin->y_offset + builtin->border_width; - - layer = builtin->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 void -lo_rl_SetLayerDimensions( lo_RelayoutState *relay_state, LO_BlockInitializeStruct *layerParams ) -{ - XP_ASSERT(layerParams != NULL); - if (layerParams) - { - if (layerParams->percent_width > 0) - { - int32 parent_width = lo_GetEnclosingLayerWidth(relay_state->doc_state); - layerParams->width = (parent_width * layerParams->percent_width) / 100; - } - - if (layerParams->percent_height > 0) - { - int32 parent_height = lo_GetEnclosingLayerHeight(relay_state->doc_state); - layerParams->height = (parent_height * layerParams->percent_height) / 100; - } - } -} - -static LO_Element * -lo_rl_FitLayer( lo_RelayoutState *relay_state, LO_Element *lo_ele ) -{ - LO_LayerStruct *layerEle = (LO_LayerStruct *)lo_ele; - LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE ); - - if(layerEle && layerEle->is_end == FALSE) - { - LO_LayerStruct *endLayer = NULL; - LO_Element *lastFloat = NULL; - LO_CellStruct *cell = NULL; - - lo_AppendToLineList( relay_state->context, relay_state->doc_state, lo_ele, 0 ); - lo_rl_SetLayerDimensions( relay_state, layerEle->initParams ); - lo_BeginLayerReflow( relay_state->context, relay_state->doc_state, layerEle->initParams, - layerEle->layerDoc ); - - if (next->lo_any.type == LO_CELL) - { - /* We are reflowing an ILAYER */ - cell = (LO_CellStruct *) next; - - /* Set "next" to the layout element following the LO_CELL */ - next = lo_tv_GetNextLayoutElement( relay_state->doc_state, next, TRUE); - - /* Set the cell's next pointer to null. We've got to fool the end layer - code into thinking that this cell is the last element on the line list. */ - cell->next = NULL; - } - else - { - /* We are reflowing a LAYER. So, we get the cell from the lo_LayerDocState structure */ - lo_LayerDocState *layerDoc = (lo_LayerDocState *) layerEle->layerDoc; - cell = layerDoc->cell; - } - - /* Assert that next is a dummy layout element marking the end of the layer */ - XP_ASSERT(next->lo_any.type == LO_LAYER && next->lo_layer.is_end == TRUE); - endLayer = (LO_LayerStruct *) next; - - next = cell->cell_list; - if (next) - { - /* The next layout element to be fitted is the first element on the cell list. - Once the cell list has been fitted we want to end the layer, so we append - the end layer element to the cell list. */ - XP_ASSERT(cell->cell_list_end && cell->cell_list_end->lo_any.next == NULL); - cell->cell_list_end->lo_any.next = (LO_Element*) endLayer; - - /* We also need to append the cell's float list to the state's float list */ - lastFloat = lo_GetLastElementInList(relay_state->doc_state->float_list); - if (lastFloat) - lastFloat->lo_any.next = cell->cell_float_list; - } - else - { - /* There is nothing on the cell's line list to reflow. So, the float list should - also be null. The next element to be fitted is set to the end layer element. */ - XP_ASSERT(cell->cell_float_list == NULL); - next = (LO_Element *) endLayer; - } - - /* Since the elements inside the layer are going to be reflowed while state->layer_nest_level - is greater than zero, lo_FlushLineList() will append the layout elements onto the cell's - line list. So, the cell's line list and float lists need to be initialized to null. */ - if (cell) - { - cell->cell_list = NULL; - cell->cell_float_list = NULL; - cell->cell_list_end = NULL; - } - } - else - { - lo_EndLayerReflow( relay_state->context, relay_state->doc_state ); - lo_AppendToLineList( relay_state->context, relay_state->doc_state, lo_ele, 0 ); - } - - return next; -} - - -static LO_Element * -lo_rl_FitHeading( lo_RelayoutState *relay_state, LO_Element *lo_ele ) -{ - LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE); - LO_HeadingStruct *header = (LO_HeadingStruct*)lo_ele; - lo_DocState *state = relay_state->doc_state; - MWContext *context = relay_state->context; - - /* Put the LO_HEADING element back on the line list */ - header->lo_any.x = state->x; - header->lo_any.y = state->y; - header->lo_any.ele_id = NEXT_ELEMENT; - lo_AppendToLineList(context, state, lo_ele, 0); - - lo_ProcessHeader(context, state, header, TRUE); - return next; -} - -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_FitSuper( lo_RelayoutState *relay_state, LO_Element *lo_ele ) -{ - LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE); - LO_SuperStruct *super = (LO_SuperStruct *) lo_ele; - lo_DocState *state = relay_state->doc_state; - MWContext *context = relay_state->context; - - /* Put the LO_SUPER element back on the line list */ - super->lo_any.x = state->x; - super->lo_any.y = state->y; - super->lo_any.ele_id = state->top_state->element_id++; - lo_AppendToLineList(context, state, lo_ele, 0); - - /* Relayout the SUPER element */ - lo_ProcessSuperElement(context, state, super); - - return next; -} - -static LO_Element * lo_rl_FitSub( lo_RelayoutState *relay_state, LO_Element *lo_ele ) -{ - LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE); - LO_SubStruct *sub = (LO_SubStruct *) lo_ele; - lo_DocState *state = relay_state->doc_state; - MWContext *context = relay_state->context; - - /* Put the LO_SUB element back on the line list */ - sub->lo_any.x = state->x; - sub->lo_any.y = state->y; - sub->lo_any.ele_id = state->top_state->element_id++; - lo_AppendToLineList(context, state, lo_ele, 0); - - /* Relayout the SUB element */ - lo_ProcessSubElement(context, state, sub); - - return next; -} - -static LO_Element * lo_rl_FitSpan( lo_RelayoutState *relay_state, LO_Element *lo_ele ) -{ -#ifndef DOM - XP_ASSERT(0); - return lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE); -#else - 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); - - /* Skip the SPAN element */ - if (lo_ele->lo_span.is_end == FALSE) - { - lo_AppendToLineList(context, state, lo_ele, 0); - state->in_span = TRUE; - } - else - { - state->in_span = FALSE; - lo_AppendToLineList(context, state, lo_ele, 0); - } - - return next; -#endif -} - -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); -} - -/* Reflow version of lo_FlushLineList() */ -void lo_rl_FlushLineList( MWContext *context, lo_DocState *state, - uint32 break_type, uint32 clear_type, Bool breaking ) -{ - LO_LinefeedStruct *linefeed = NULL; - - lo_UpdateStateWhileFlushingLine( context, state ); - linefeed = lo_NewLinefeed( state, context, break_type, clear_type ); - if (linefeed != NULL) - { - lo_AppendLineFeed( context, state, linefeed, breaking, FALSE ); - } - lo_UpdateStateAfterFlushingLine( context, state, linefeed, TRUE ); -} - -/* - * 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(MWContext *context, - lo_DocState *state, LO_Element *ele, LO_Element *restOfLine) -{ - LO_Element *eptr; - LO_FloatStruct *float_dummy = (LO_FloatStruct*)lo_NewElement(context, state, - LO_FLOAT, NULL, 0); - 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; - - /* 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); - - /* 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 ); - -} - -void lo_rl_ReflowDocState( MWContext *context, lo_DocState *state ) -{ - lo_RelayoutState *relay_state; - LO_Element *first; - - /* 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, lo_GetLastElementInList(state->line_list) ); - */ - - /* Done with relayout. Destroy relayout state. */ - lo_rl_DestroyRelayoutState( relay_state ); -} - -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 -} - diff --git a/lib/layout/layspan.c b/lib/layout/layspan.c deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/lib/layout/laytable.c b/lib/layout/laytable.c index 94cc6da6b99..e69de29bb2d 100644 --- a/lib/layout/laytable.c +++ b/lib/layout/laytable.c @@ -1,8097 +0,0 @@ -/* -*- Mode: C; tab-width: 4; 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. - */ - -#include "xp.h" -#include "pa_parse.h" -#include "layout.h" -#include "laylayer.h" -#include "np.h" -#include "laystyle.h" -#include "edt.h" -#include "timing.h" - -#ifdef TEST_16BIT -#define XP_WIN16 -#endif /* TEST_16BIT */ - - -#define TABLE_BORDERS_ON 1 -#define TABLE_BORDERS_OFF 0 -#define TABLE_BORDERS_GONE -1 - -#define TABLE_DEF_INNER_CELL_PAD 1 -#define TABLE_DEF_INTER_CELL_PAD 2 -#define TABLE_DEF_CELL_BORDER 1 - -#define TABLE_DEF_BORDER 0 -#define TABLE_DEF_BORDER_STYLE BORDER_SOLID -#define TABLE_DEF_VERTICAL_SPACE 0 -#define TABLE_DEF_HORIZONTAL_SPACE 0 - -#define TABLE_MAX_COLSPAN 1000 -#define TABLE_MAX_ROWSPAN 10000 - -typedef struct lo_cell_data_struct { -#ifdef XP_WIN16 - /* - * This struct must be a power of 2 if we are going to allocate an - * array of more than 128K - */ - unsigned width, height; -#else - int32 width, height; -#endif - lo_TableCell *cell; -} lo_cell_data; - - -LO_SubDocStruct * - lo_EndCellSubDoc(MWContext *context, lo_DocState *state, lo_DocState *old_state, - LO_Element *element, Bool relayout); -LO_SubDocStruct * - lo_RelayoutCaptionSubdoc(MWContext *context, lo_DocState *state, lo_TableCaption *caption, - LO_SubDocStruct *subdoc, int32 width, Bool is_a_header); -LO_CellStruct * -lo_RelayoutCell(MWContext *context, lo_DocState *state, - LO_SubDocStruct *subdoc, lo_TableCell *cell_ptr, - LO_CellStruct *cell, int32 width, Bool is_a_header, - Bool relayout); -void - lo_BeginCaptionSubDoc(MWContext *context, lo_DocState *state, - lo_TableCaption *caption, PA_Tag *tag); -void - lo_BeginCellSubDoc(MWContext *context, - lo_DocState *state, - lo_TableRec *table, - char *bgcolor_attr, - char *background_attr, - lo_TileMode tile_mode, - char *valign_attr, - char *halign_attr, - char *width_attr, - char *height_attr, - Bool is_a_header, - intn draw_borders, - Bool relayout); -Bool - lo_subdoc_has_elements(lo_DocState *sub_state); -Bool - lo_cell_has_elements(LO_CellStruct *cell); -int32 - lo_align_subdoc(MWContext *context, lo_DocState *state, lo_DocState *old_state, - LO_SubDocStruct *subdoc, lo_TableRec *table, lo_table_span *row_max); -int32 - lo_align_cell(MWContext *context, lo_DocState *state, lo_TableCell *cell_ptr, - LO_CellStruct *cell, lo_TableRec *table, lo_table_span *row_max); - -static void -lo_reuse_current_state(MWContext *context, lo_DocState *state, - int32 width, int32 height, int32 margin_width, int32 margin_height, - Bool destroyLineLists); - -static void lo_FreeAllExceptRows( MWContext *context, lo_DocState *state, - lo_TableRec *table ); -static void lo_FreeTableSpanArray( lo_table_span *spanArray ); - -/* - ******************************************************************************** - * Some Helper Functions - */ - -static int32 lo_CalculateCellPercentWidth( lo_TableRec *table, int32 percent); -static int32 lo_CalculateCellPercentHeight( lo_TableRec *table, lo_TableCell *table_cell); - -static int32 - lo_ComputeCellEmptySpace(MWContext *context,lo_TableRec *table, - LO_SubDocStruct *subdoc); -static int32 - lo_FindDefaultCellWidth(MWContext * context, lo_TableRec *table, lo_TableCell *table_cell, - int32 desired_width, int32 cell_empty_space); -static int32 - lo_ComputeInternalTableWidth(MWContext *context, lo_TableRec *table, - lo_DocState *state); -static void - lo_SetDefaultCellWidth(MWContext *context, lo_TableRec *table, LO_SubDocStruct *subdoc, - lo_TableCell *table_cell, int32 cell_width); - - -static void lo_ResetWidthSpans( lo_TableRec *table ); - -static void lo_UpdateCaptionCellFromSubDoc( MWContext *context, lo_DocState *state, LO_SubDocStruct *subdoc, LO_CellStruct *cell_ele); -static void lo_FreeCaptionCell( MWContext *context, lo_DocState *state, LO_CellStruct *cell_ele); -static void lo_FreeTableCaption( MWContext *context, lo_DocState *state, lo_TableRec *table ); - -#ifdef DEBUG_shaver -extern char *element_names[]; -#endif - -#ifdef DOM -void LO_SetTableCellAttributes(MWContext *context, void *cell_v, - const char *name, const char *value) -{ - lo_TableCell *cell = (lo_TableCell *)cell_v; - LO_Element *start = cell->cell->cell_list; - /* LO_Element *end = cell->cell->cell_list_end; */ - lo_DocState *state; - lo_TopState *top = lo_FetchTopState(context->doc_id); - if (!top) - return; - - state = top->doc_state; - - if (!start) - return; -#ifdef DEBUG_shaver - fprintf(stderr, "setting %s=%s on <TD>\n", name, value); -#endif - - if (!XP_STRCASECMP(name, "bgcolor")) { - LO_Color rgb; - LO_Element *iter = start; - if (!LO_ParseRGB((char *)value, &rgb.red, &rgb.green, &rgb.blue)) - return; -/* while (iter && iter != end) { */ -#ifdef DEBUG_shaver - fprintf(stderr, "setting bgcolor of %s to %s\n", - element_names[iter->type], value); -#endif - lo_SetColor(start, &rgb, state, TRUE); -/* iter = iter->lo_any.next; - } - if (iter != start) { -#ifdef DEBUG_shaver - fprintf(stderr, "setting bgcolor of %s to %s\n", - element_names[iter->type], value); -#endif - lo_SetColor(start, &rgb, state, TRUE); - } -*/ - } - /* XXX LO_JustRedrawNothingChangedThatsImportant */ - LO_RelayoutFromElement(context, start); -} -#endif - -static int32 -lo_ComputeCellEmptySpace(MWContext *context, lo_TableRec *table, - LO_SubDocStruct *subdoc) -{ - int32 left_inner_pad; - int32 right_inner_pad; - int32 cell_empty_space; - - left_inner_pad = FEUNITS_X(table->inner_left_pad, context); - right_inner_pad = FEUNITS_X(table->inner_right_pad, context); - - cell_empty_space = (2 * subdoc->border_width) + - (2 * subdoc->border_horiz_space) + - (left_inner_pad + right_inner_pad); - - return cell_empty_space; -} - - -/* - * Handle Fixed Table Layout. If the table has a COLS attribute - * then the width of this cell may already be specified. The - * trick is to know if this is the first row of the table. If - * so, then this cell can choose it's width. - */ -static int32 -lo_FindDefaultCellWidth(MWContext * context, lo_TableRec *table, lo_TableCell *table_cell, - int32 desired_width, int32 cell_empty_space) -{ - lo_TableRow * row_ptr; - int32 cell_num; - int32 cell_width; - int32 count; - int32 cell_pad; - - cell_pad = FEUNITS_X(table->inter_cell_pad, context); - - row_ptr = table->row_ptr; - cell_num = row_ptr->cells; - - /* if we don't have a width table or we're out of bounds, bail */ - if ( table->fixed_col_widths == NULL || - ((cell_num+table_cell->colspan) > table->fixed_cols) ) - { - table->fixed_cols = 0; - table->default_cell_width = 0; - return desired_width; - } - - /* does this cell already have a width defined? */ - cell_width = table->fixed_col_widths[ cell_num ]; - if ( cell_width == 0 ) - { - int32 col_width; - - /* use it's desired width or the default */ - cell_width = desired_width; - if ( cell_width == 0 ) - { - /* - * Get our size from the default cell width. We - * may need to clip it to the table width remaining. - */ - cell_width = table->default_cell_width * table_cell->colspan; - - /* - * If this is bigger than the width remaining the the table, then - * clip to the remaining space. If the table is already full, then - * we're going for broke and the cell gets all of it. - */ - if ( ( table->fixed_width_remaining > 0 ) && - ( cell_width > table->fixed_width_remaining ) ) - { - cell_width = table->fixed_width_remaining; - } - - table->fixed_width_remaining -= cell_width; - - /* - * Remove any cell spacing so the cell will internally - * layout to the correct size. - */ - cell_width -= cell_empty_space * table_cell->colspan; - } - else - { - /* - * The cell has a specified size. Allocate all of it. If we - * don't have enough space, then we'll keep doing fixed layout, - * but the table may end up larger than expected. - */ - table->fixed_width_remaining -= cell_width + cell_empty_space; - } - - /* make sure this stays reasonable */ - if ( table->fixed_width_remaining < 0 ) - { - table->fixed_width_remaining = 0; - } - - /* fill out the apropriate number of col widths */ - col_width = cell_width / table_cell->colspan; - for ( count = table_cell->colspan; count > 0 ; --count ) - { - table->fixed_col_widths[ cell_num ] = col_width; - cell_num++; - } - - /* add any odd amount to the last column */ - table->fixed_col_widths[ cell_num-1 ] += (cell_width- - (col_width * table_cell->colspan)); - } - else - { - /* add up widths of each column our cell spans */ - for ( count = 1; count < table_cell->colspan; ++count ) - { - cell_width += table->fixed_col_widths[ cell_num+count ]; - } - } - - /* - * Add the empty space this cell spans - */ - cell_width += ( table_cell->colspan - 1 ) * ( cell_empty_space + cell_pad ); - - return cell_width; -} - - -/* - * For fixed layout, set the cell width for a cell after layout. This is used - * for cases where we don't know how wide a cell is until after it's been layed - * out (for example, when NOWRAP is set). - * - * We will have already chosen a default width for this cell. If our new width - * is larger, then we need to resize the column/s. - */ -static void -lo_SetDefaultCellWidth(MWContext *context, lo_TableRec *table, LO_SubDocStruct *subdoc, - lo_TableCell *table_cell, int32 cell_width) -{ - lo_TableRow * row_ptr; - int32 cell_num; - int32 count; - int32 cur_width; - int32 add_width; - int32 cell_empty_space; - int32 cell_pad; - - row_ptr = table->row_ptr; - cell_num = row_ptr->cells; - - /* if we don't have a width table or we're out of bounds, bail */ - if ( table->fixed_col_widths == NULL || - ((cell_num+table_cell->colspan) > table->fixed_cols) ) - { - table->fixed_cols = 0; - table->default_cell_width = 0; - return; - } - - /* - * Figure out the current width for these cells - */ - cur_width = 0; - - for ( count = table_cell->colspan-1; count >= 0 ; --count ) - { - cur_width += table->fixed_col_widths[ cell_num+count ]; - } - - /* - * Add space for the empty space that this cell spans - */ - cell_empty_space = lo_ComputeCellEmptySpace(context, table, subdoc ); - cell_pad = FEUNITS_X(table->inter_cell_pad, context); - - cur_width += ( table_cell->colspan - 1 ) * ( cell_empty_space + cell_pad ); - - /* - * If our new width is bigger, we need to grow the default width - */ - if ( cell_width > cur_width ) - { - cell_width -= cur_width; - add_width = cell_width / table_cell->colspan; - - table->fixed_width_remaining -= add_width; - if ( table->fixed_width_remaining < 0 ) - { - table->fixed_width_remaining = 0; - } - - for ( count = table_cell->colspan; count > 0 ; --count ) - { - table->fixed_col_widths[ cell_num ] += add_width; - cell_width -= add_width; - cell_num++; - } - - /* add any odd amount to the last column */ - table->fixed_col_widths[ cell_num-1 ] += cell_width; - } -} - -static int32 -lo_ComputeInternalTableWidth(MWContext *context,lo_TableRec *table, - lo_DocState *state) -{ - int32 table_width; - int32 cell_pad; - int32 table_pad; - - cell_pad = FEUNITS_X(table->inter_cell_pad, context); - - table_width = table->width; - if ( table_width == 0 ) - { - /* Compute our starting width as the window width */ - table_width = (state->win_width - state->win_left - - state->win_right); - } - - /* remove space for the table borders */ - table_width -= ( table->table_ele->border_left_width - + table->table_ele->border_right_width ); - - if (table->draw_borders == TABLE_BORDERS_OFF) - { - table_pad = FEUNITS_X(TABLE_DEF_CELL_BORDER, context); - table_width -= 2 * table_pad; - } - - if ( table->fixed_cols > 0 ) - { - table_width -= ( table->fixed_cols + 1 ) * cell_pad; - } - else - { - table_width -= ( table->cols + 1 ) * cell_pad; - } - - return table_width; -} - -/* - ******************************************************************************** - * Core Table Layout Code - */ - -void -lo_BeginCaptionSubDoc(MWContext *context, lo_DocState *state, - lo_TableCaption *caption, PA_Tag *tag) -{ - LO_SubDocStruct *subdoc; - lo_DocState *new_state; - int32 first_width, first_height; - Bool allow_percent_width; - Bool allow_percent_height; - - /* - * Fill in the subdoc structure with default data - */ - subdoc = (LO_SubDocStruct *)lo_NewElement(context, state, LO_SUBDOC, NULL, 0); - if (subdoc == NULL) - { - return; - } - - subdoc->type = LO_SUBDOC; - subdoc->ele_id = NEXT_ELEMENT; - subdoc->x = state->x; - subdoc->x_offset = 0; - subdoc->y = state->y; - subdoc->y_offset = 0; - subdoc->width = 0; - subdoc->height = 0; - subdoc->next = NULL; - subdoc->prev = NULL; - - subdoc->anchor_href = state->current_anchor; - -#ifdef DOM - subdoc->text_attr = lo_GetCurrentTextAttr(state, context); -#else - if (state->font_stack == NULL) - { - subdoc->text_attr = NULL; - } - else - { - subdoc->text_attr = state->font_stack->text_attr; - } -#endif - - subdoc->FE_Data = NULL; - subdoc->backdrop.bg_color = NULL; - subdoc->backdrop.url = NULL; - subdoc->backdrop.tile_mode = LO_TILE_BOTH; - subdoc->state = NULL; - - subdoc->vert_alignment = LO_ALIGN_CENTER; - subdoc->horiz_alignment = caption->horiz_alignment; - - subdoc->alignment = LO_ALIGN_BOTTOM; - - subdoc->border_width = 0; - subdoc->border_vert_space = 0; - subdoc->border_horiz_space = 0; - - subdoc->ele_attrmask = 0; - - subdoc->sel_start = -1; - subdoc->sel_end = -1; - - subdoc->border_width = FEUNITS_X(subdoc->border_width, context); - - if (subdoc->width == 0) - { - first_width = FEUNITS_X(5000, context); - allow_percent_width = FALSE; - } - else - { - first_width = subdoc->width; - allow_percent_width = TRUE; - } - - if (subdoc->height == 0) - { - first_height = FEUNITS_Y(10000, context); - allow_percent_height = FALSE; - } - else - { - first_height = subdoc->height; - allow_percent_height = TRUE; - } - - new_state = lo_NewLayout(context, first_width, first_height, 0, 0, NULL); - if (new_state == NULL) - { - lo_FreeElement(context, (LO_Element *)subdoc, FALSE); - return; - } - new_state->is_a_subdoc = SUBDOC_CAPTION; - lo_InheritParentState(context, new_state, state); - new_state->allow_percent_width = allow_percent_width; - new_state->allow_percent_height = allow_percent_height; - - new_state->base_x = 0; - new_state->base_y = 0; - new_state->display_blocked = TRUE; - if (subdoc->width == 0) - { - new_state->delay_align = TRUE; - } - - new_state->win_left = 0; - new_state->win_right = 0; - new_state->x = new_state->win_left; - new_state->y = 0; - new_state->max_width = new_state->x + 1; - new_state->left_margin = new_state->win_left; - new_state->right_margin = new_state->win_width - new_state->win_right; - new_state->list_stack->old_left_margin = new_state->left_margin; - new_state->list_stack->old_right_margin = new_state->right_margin; - - /* - * Initialize the alignment stack for this state - * to match the caption alignment. - */ - if (subdoc->horiz_alignment != LO_ALIGN_LEFT) - { - lo_PushAlignment(new_state, tag->type, subdoc->horiz_alignment); - } - - state->sub_state = new_state; - - state->current_ele = (LO_Element *)subdoc; - - /* - * We added a new state. - */ - lo_PushStateLevel ( context ); -} - - -static void -lo_reuse_current_state(MWContext *context, lo_DocState *state, - int32 width, int32 height, int32 margin_width, int32 margin_height, - Bool destroyLineLists) -{ - lo_TopState *top_state; - int32 doc_id; - lo_DocLists *doc_lists; - - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(state == NULL)) - { - return; - } - - state->subdoc_tags = NULL; - state->subdoc_tags_end = NULL; - - state->text_fg.red = lo_master_colors[LO_COLOR_FG].red; - state->text_fg.green = lo_master_colors[LO_COLOR_FG].green; - state->text_fg.blue = lo_master_colors[LO_COLOR_FG].blue; - - state->text_bg.red = lo_master_colors[LO_COLOR_BG].red; - state->text_bg.green = lo_master_colors[LO_COLOR_BG].green; - state->text_bg.blue = lo_master_colors[LO_COLOR_BG].blue; - - state->anchor_color.red = lo_master_colors[LO_COLOR_LINK].red; - state->anchor_color.green = lo_master_colors[LO_COLOR_LINK].green; - state->anchor_color.blue = lo_master_colors[LO_COLOR_LINK].blue; - - state->visited_anchor_color.red = lo_master_colors[LO_COLOR_VLINK].red; - state->visited_anchor_color.green = lo_master_colors[LO_COLOR_VLINK].green; - state->visited_anchor_color.blue = lo_master_colors[LO_COLOR_VLINK].blue; - - state->active_anchor_color.red = lo_master_colors[LO_COLOR_ALINK].red; - state->active_anchor_color.green = lo_master_colors[LO_COLOR_ALINK].green; - state->active_anchor_color.blue = lo_master_colors[LO_COLOR_ALINK].blue; - - 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->x = state->win_left; - state->y = state->win_top; - - state->left_margin = state->win_left; - state->right_margin = state->win_width - state->win_right; - if (state->left_margin_stack != NULL) - { - lo_MarginStack *mptr; - lo_MarginStack *margin; - - mptr = state->left_margin_stack; - while (mptr != NULL) - { - margin = mptr; - mptr = mptr->next; - XP_DELETE(margin); - } - state->left_margin_stack = NULL; - } - if (state->right_margin_stack != NULL) - { - lo_MarginStack *mptr; - lo_MarginStack *margin; - - mptr = state->right_margin_stack; - while (mptr != NULL) - { - margin = mptr; - mptr = mptr->next; - XP_DELETE(margin); - } - 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; - - if (destroyLineLists == TRUE) - { - if (state->line_list != NULL) - { - lo_FreeElementList(context, state->line_list); - state->line_list = NULL; - } - state->end_last_line = NULL; - if (state->float_list != NULL) - { - lo_FreeElementList(context, state->float_list); - state->float_list = NULL; - } - } - - state->base_font_size = DEFAULT_BASE_FONT_SIZE; - if (state->font_stack != NULL) - { - lo_FontStack *fstack; - lo_FontStack *fptr; - - fptr = state->font_stack; - while (fptr != NULL) - { - fstack = fptr; - fptr = fptr->next; - XP_DELETE(fstack); - } - state->font_stack = NULL; - } - state->font_stack = lo_DefaultFont(state, context); - - state->font_stack->text_attr->size = state->base_font_size; - - if (state->align_stack != NULL) - { - lo_AlignStack *aptr; - lo_AlignStack *align; - - aptr = state->align_stack; - while (aptr != NULL) - { - align = aptr; - aptr = aptr->next; - XP_DELETE(align); - } - state->align_stack = NULL; - } - if (state->list_stack != NULL) - { - lo_ListStack *lptr; - lo_ListStack *list; - - lptr = state->list_stack; - while (lptr != NULL) - { - list = lptr; - lptr = lptr->next; - XP_DELETE(list); - } - state->list_stack = NULL; - } - state->list_stack = lo_DefaultList(state); - - 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; - - 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->old_break = NULL; - state->old_break_block = NULL; - state->old_break_pos = -1; - state->old_break_width = 0; - -#ifdef DOM - state->current_span = NULL; - state->in_span = FALSE; -#endif - - 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; - - if (state->top_state->doc_state) - doc_lists = lo_GetCurrentDocLists(state->top_state->doc_state); - else - doc_lists = lo_GetCurrentDocLists(state); - - /* - * These values are saved into the (sub)doc here - * so that if it gets Relayout() later, we know where - * to reset the from counts to. - */ - if (doc_lists->form_list != NULL) - { - lo_FormData *form_list; - - form_list = doc_lists->form_list; - state->form_ele_cnt = form_list->form_ele_cnt; - state->form_id = form_list->id; - } - else - { - state->form_ele_cnt = 0; - state->form_id = 0; - } - state->start_in_form = top_state->in_form; - if (top_state->savedData.FormList != NULL) - { - lo_SavedFormListData *all_form_ele; - - all_form_ele = top_state->savedData.FormList; - state->form_data_index = all_form_ele->data_index; - } - else - { - state->form_data_index = 0; - } - - /* - * Remember number of embeds we had before beginning this - * (sub)doc. This information is used in laytable.c so - * it can preserve embed indices across a relayout. - */ - state->embed_count_base = top_state->embed_count; - - /* - * Ditto for anchors, images, applets and embeds - */ - state->url_count_base = doc_lists->url_list_len; - state->image_list_count_base = doc_lists->image_list_count; - state->applet_list_count_base = doc_lists->applet_list_count; - state->embed_list_count_base = doc_lists->embed_list_count; - state->current_layer_num_base = top_state->current_layer_num; - state->current_layer_num_max = top_state->current_layer_num; - - 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; - -#ifdef EDITOR - state->edit_force_offset = FALSE; - state->edit_current_element = 0; - state->edit_current_offset = 0; - state->edit_relayout_display_blocked = FALSE; -#endif - state->in_relayout = FALSE; - - state->cur_text_block = NULL; - - /* we need min widths during the initial table layout pass */ - state->need_min_width = TRUE; -} - - -static void -lo_reuse_current_subdoc(MWContext *context, LO_SubDocStruct *subdoc) -{ - if (subdoc == NULL) - { - return; - } - - subdoc->type = LO_SUBDOC; - subdoc->ele_id = 0; - subdoc->x = 0; - subdoc->x_offset = 0; - subdoc->y = 0; - subdoc->y_offset = 0; - subdoc->width = 0; - subdoc->height = 0; - subdoc->next = NULL; - subdoc->prev = NULL; - - subdoc->FE_Data = NULL; - - /* - * We leave subdoc->state alone as it will get reused later. - */ - - XP_FREEIF(subdoc->backdrop.bg_color); - XP_FREEIF(subdoc->backdrop.url); - - /* - * These two come from lists of shared pointers, so - * we NULL them but don't free them. - */ - subdoc->anchor_href = NULL; - subdoc->text_attr = NULL; - - subdoc->alignment = LO_ALIGN_LEFT; - subdoc->vert_alignment = LO_ALIGN_TOP; - subdoc->horiz_alignment = LO_ALIGN_LEFT; - subdoc->border_width = 0; - subdoc->border_vert_space = 0; - subdoc->border_horiz_space = 0; - subdoc->ele_attrmask = 0; - subdoc->sel_start = -1; - subdoc->sel_end = -1; -} - - -static void -lo_cleanup_old_state(lo_DocState *state) -{ - LO_Element **line_array; - - if (state == NULL) - { - return; - } - - /* - * Clear out the start of the line_list. - */ -#ifdef XP_WIN16 - { - XP_Block *larray_array; - - XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array); - state->line_array = larray_array[0]; - XP_UNLOCK_BLOCK(state->larray_array); - } -#endif /* XP_WIN16 */ - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array); - line_array[0] = NULL; - XP_UNLOCK_BLOCK(state->line_array); - - state->end_last_line = NULL; - - state->float_list = NULL; -} - - -static int32 lo_CalculateCellPercentWidth( lo_TableRec *table, int32 percent) -{ - int32 val = percent; - - if ( table->table_width_fixed != FALSE ) - { - val = table->width * val / 100; - } - else - { - val = 0; - } - return val; -} - -static int32 lo_CalculateCellPercentHeight( lo_TableRec *table, lo_TableCell *table_cell) -{ - int32 val; - - if ((table->height > 0)&& - (table_cell->percent_height > 0)) - { - val = table->height * - table_cell->percent_height / 100; - } - else - { - val = 0; - } - return val; -} - -void -lo_BeginCellSubDoc(MWContext *context, - lo_DocState *state, - lo_TableRec *table, - char *bgcolor_attr, - char *background_attr, - lo_TileMode tile_mode, - char *valign_attr, - char *halign_attr, - char *width_attr, - char *height_attr, - Bool is_a_header, - intn draw_borders, - Bool relayout /* Is true during relayout without reload */) -{ - LO_SubDocStruct *subdoc; - lo_DocState *new_state; - lo_TableRow *table_row; - lo_TableCell *table_cell; - int32 val; - int32 first_width, first_height; - Bool allow_percent_width; - Bool allow_percent_height; - StyleStruct *style_struct=0; -#ifdef LOCAL_DEBUG - fprintf(stderr, "lo_BeginCellSubDoc called\n"); -#endif /* LOCAL_DEBUG */ - - table_row = table->row_ptr; - table_cell = table_row->cell_ptr; - - if (relayout == FALSE) - { - if(state->top_state && state->top_state->style_stack) - style_struct = STYLESTACK_GetStyleByIndex( - state->top_state->style_stack, - 0); - } - - /* - * Fill in the subdoc structure with default data - */ - lo_reuse_current_subdoc(context, table->current_subdoc); - subdoc = table->current_subdoc; - if (subdoc == NULL) - { - return; - } - - subdoc->type = LO_SUBDOC; - subdoc->ele_id = NEXT_ELEMENT; - subdoc->x = state->x; - subdoc->x_offset = 0; - subdoc->y = state->y; - subdoc->y_offset = 0; - subdoc->width = 0; - subdoc->height = 0; - subdoc->next = NULL; - subdoc->prev = NULL; - - subdoc->anchor_href = state->current_anchor; - -#ifdef DOM - subdoc->text_attr = lo_GetCurrentTextAttr(state, context); -#else - if (state->font_stack == NULL) - { - subdoc->text_attr = NULL; - } - else - { - subdoc->text_attr = state->font_stack->text_attr; - } -#endif - - subdoc->FE_Data = NULL; - - subdoc->vert_alignment = table_row->vert_alignment; - if (subdoc->vert_alignment == LO_ALIGN_DEFAULT) - { - subdoc->vert_alignment = LO_ALIGN_CENTER; - } - subdoc->horiz_alignment = table_row->horiz_alignment; - if (subdoc->horiz_alignment == LO_ALIGN_DEFAULT) - { - if (is_a_header == FALSE) - { - subdoc->horiz_alignment = LO_ALIGN_LEFT; - } - else - { - subdoc->horiz_alignment = LO_ALIGN_CENTER; - } - } - subdoc->alignment = LO_ALIGN_BOTTOM; - - if (draw_borders == TABLE_BORDERS_OFF) - { - subdoc->border_width = 0; - subdoc->border_vert_space = TABLE_DEF_CELL_BORDER; - subdoc->border_horiz_space = TABLE_DEF_CELL_BORDER; - } - else if (draw_borders == TABLE_BORDERS_ON) - { - subdoc->border_width = TABLE_DEF_CELL_BORDER; - subdoc->border_vert_space = 0; - subdoc->border_horiz_space = 0; - } - else - { - subdoc->border_width = 0; - subdoc->border_vert_space = 0; - subdoc->border_horiz_space = 0; - } - - subdoc->ele_attrmask = 0; - - subdoc->sel_start = -1; - subdoc->sel_end = -1; - - subdoc->backdrop.bg_color = NULL; - subdoc->backdrop.url = NULL; - subdoc->backdrop.tile_mode = LO_TILE_BOTH; - - /* - * May inherit a bg_color from your row. - */ - if (table_row->backdrop.bg_color != NULL) - { - subdoc->backdrop.bg_color = XP_NEW(LO_Color); - if (subdoc->backdrop.bg_color != NULL) - *subdoc->backdrop.bg_color = *table_row->backdrop.bg_color; - } - - if (relayout == FALSE) - { - subdoc->backdrop.bg_color = NULL; - subdoc->backdrop.url = NULL; - subdoc->backdrop.tile_mode = LO_TILE_BOTH; - - /* - * May inherit a bg_color from your row. - */ - if (table_row->backdrop.bg_color != NULL) - { - subdoc->backdrop.bg_color = XP_NEW(LO_Color); - if (subdoc->backdrop.bg_color != NULL) - *subdoc->backdrop.bg_color = *table_row->backdrop.bg_color; - } - - /* - * Else may inherit a bg_color from your table. - */ - else if (table->backdrop.bg_color != NULL) - { - subdoc->backdrop.bg_color = XP_NEW(LO_Color); - if (subdoc->backdrop.bg_color != NULL) - *subdoc->backdrop.bg_color = *table->backdrop.bg_color; - } - /* - * Else possibly inherit the background color attribute - * of a parent table cell. - */ - else if (state->is_a_subdoc == SUBDOC_CELL) - { - lo_DocState *up_state; - - /* - * Find the parent subdoc's state. - */ - up_state = state->top_state->doc_state; - while ((up_state->sub_state != NULL)&& - (up_state->sub_state != state)) - { - up_state = up_state->sub_state; - } - if ((up_state->sub_state != NULL)&& - (up_state->current_ele != NULL)&& - (up_state->current_ele->type == LO_SUBDOC)&& - (up_state->current_ele->lo_subdoc.backdrop.bg_color != NULL)) - { - LO_Color *old_bg; - - old_bg = up_state->current_ele->lo_subdoc.backdrop.bg_color; - subdoc->backdrop.bg_color = XP_NEW(LO_Color); - if (subdoc->backdrop.bg_color != NULL) - *subdoc->backdrop.bg_color = *old_bg; - } - } - - - /* Use backdrop URL, if supplied. */ - if (background_attr) - { - subdoc->backdrop.url = XP_STRDUP(background_attr); - subdoc->backdrop.tile_mode = tile_mode; - } - - /* - * May inherit a backdrop_url from parent row. - */ - else if (table_row->backdrop.url) - { - subdoc->backdrop.url = XP_STRDUP(table_row->backdrop.url); - subdoc->backdrop.tile_mode = table_row->backdrop.tile_mode; - } - - /* - * Else may inherit a backdrop_url from parent table. - */ - else if (table->backdrop.url != NULL) - { - subdoc->backdrop.url = XP_STRDUP(table->backdrop.url); - subdoc->backdrop.tile_mode = table->backdrop.tile_mode; - } - /* - * Else possibly inherit the backdrop_url - * of a parent table cell. - */ - else if (state->is_a_subdoc == SUBDOC_CELL) - { - lo_DocState *up_state; - - /* - * Find the parent subdoc's state. - */ - up_state = state->top_state->doc_state; - while ((up_state->sub_state != NULL)&& - (up_state->sub_state != state)) - { - up_state = up_state->sub_state; - } - if ((up_state->sub_state != NULL)&& - (up_state->current_ele != NULL)&& - (up_state->current_ele->type == LO_SUBDOC)&& - (up_state->current_ele->lo_subdoc.backdrop.url != NULL)) - { - lo_Backdrop *src_backdrop = &up_state->current_ele->lo_subdoc.backdrop; - subdoc->backdrop.url = XP_STRDUP(src_backdrop->url); - subdoc->backdrop.tile_mode = src_backdrop->tile_mode; - } - } - - /* - * Check for a background color attribute - */ - if (bgcolor_attr) - { - uint8 red, green, blue; - - LO_ParseRGB(bgcolor_attr, &red, &green, &blue); - XP_FREEIF(subdoc->backdrop.bg_color); - subdoc->backdrop.bg_color = XP_NEW(LO_Color); - if (subdoc->backdrop.bg_color != NULL) - { - subdoc->backdrop.bg_color->red = red; - subdoc->backdrop.bg_color->green = green; - subdoc->backdrop.bg_color->blue = blue; - } - } - - /* check for a style sheet directive for bgcolor */ - if(style_struct) - { - char *property = STYLESTRUCT_GetString(style_struct, BG_COLOR_STYLE); - - if(property) - { - uint8 red, green, blue; - - LO_ParseStyleSheetRGB(property, &red, &green, &blue); - - XP_FREEIF(subdoc->backdrop.bg_color); - subdoc->backdrop.bg_color = XP_NEW(LO_Color); - if (subdoc->backdrop.bg_color != NULL) - { - subdoc->backdrop.bg_color->red = red; - subdoc->backdrop.bg_color->green = green; - subdoc->backdrop.bg_color->blue = blue; - } - XP_FREE(property); - } - - property = STYLESTRUCT_GetString(style_struct, BG_IMAGE_STYLE); - if(property) - { - if(subdoc->backdrop.url) - XP_FREE(subdoc->backdrop.url); - subdoc->backdrop.url = NULL; - - if(strcasecomp(property, "none")) - { - subdoc->backdrop.url = XP_STRDUP(lo_ParseStyleSheetURL(property)); - } - XP_FREE(property); - } - - property = STYLESTRUCT_GetString(style_struct, BG_REPEAT_STYLE); - if(property) - { - if(!strcasecomp(property, BG_REPEAT_NONE_STYLE)) - subdoc->backdrop.tile_mode = LO_NO_TILE; - else if(!strcasecomp(property, BG_REPEAT_X_STYLE)) - subdoc->backdrop.tile_mode = LO_TILE_HORIZ; - else if(!strcasecomp(property, BG_REPEAT_Y_STYLE)) - subdoc->backdrop.tile_mode = LO_TILE_VERT; - else - subdoc->backdrop.tile_mode = LO_TILE_BOTH; - XP_FREE(property); - } - } - } - else /* If relayout is TRUE */ - { - /* - subdoc->backdrop.tile_mode = table_cell->cell->backdrop.tile_mode; - if (table_cell->cell->backdrop.bg_color != NULL) - { - subdoc->backdrop.bg_color = XP_NEW(LO_Color); - subdoc->backdrop.bg_color->red = table_cell->cell->backdrop.bg_color->red; - subdoc->backdrop.bg_color->green = table_cell->cell->backdrop.bg_color->green; - subdoc->backdrop.bg_color->blue = table_cell->cell->backdrop.bg_color->blue; - } - if (table_cell->cell->backdrop.url != NULL) - { - subdoc->backdrop.url = XP_STRDUP(table_cell->cell->backdrop.url); - } - */ - subdoc->backdrop = table_cell->cell->backdrop; - } - - /* - * Check for a vertical align parameter - */ - if (valign_attr) - { - subdoc->vert_alignment = lo_EvalVAlignParam(valign_attr); - } - - - - if(style_struct) - { - char *property = STYLESTRUCT_GetString(style_struct, VERTICAL_ALIGN_STYLE); - - if(property) - { - subdoc->vert_alignment = lo_EvalVAlignParam(property); - XP_FREE(property); - } - } - - if (relayout) - { - subdoc->vert_alignment = table_cell->vert_alignment; - } - - /* - * Check for a horizontal align parameter - */ - if (halign_attr) - { - subdoc->horiz_alignment = lo_EvalCellAlignParam(halign_attr); - } - - if (relayout) - { - subdoc->horiz_alignment = table_cell->horiz_alignment; - } - - subdoc->border_width = FEUNITS_X(subdoc->border_width, context); - subdoc->border_vert_space = - FEUNITS_Y(subdoc->border_vert_space, context); - subdoc->border_horiz_space = - FEUNITS_X(subdoc->border_horiz_space, context); - - /* - * Allow individual setting of cell - * width and height. - */ - if (width_attr) - { - Bool is_percent; - - val = lo_ValueOrPercent(width_attr, &is_percent); - if (is_percent != FALSE) - { - /* - * Percentage width cells must be handled - * later after at least the whole row is - * processed. - */ - table_cell->percent_width = val; - table_row->has_percent_width_cells = TRUE; - table->has_percent_width_cells = TRUE; - val = lo_CalculateCellPercentWidth( table, val ); - - /* Copied to lo_CalculateCellPercentWidth() */ - /* - if ( table->table_width_fixed != FALSE ) - { - val = table->width * val / 100; - } - else - { - val = 0; - } - */ - } - else - { - table_cell->percent_width = 0; - val = FEUNITS_X(val, context); - } - if (val < 0) - { - val = 0; - } - - subdoc->width = val; - table_cell->specified_width = subdoc->width; - } - - /* During relayout without reload, recalculate width of subdoc */ - if (relayout) - { - if (table_cell->percent_width > 0) - { - subdoc->width = lo_CalculateCellPercentWidth( table, table_cell->percent_width); - table_cell->specified_width = subdoc->width; - } - else { - subdoc->width = table_cell->specified_width; - if (subdoc->width < 0) { - subdoc->width = 0; - } - } - - } - - /* - * If we're in the fixed layout case, figure out what our cell - * width should be. - */ - if ( table->fixed_cols > 0 ) - { - int32 cell_empty_space; - int32 def_cell_width; - int32 desired_width; - - cell_empty_space = lo_ComputeCellEmptySpace ( context, table, subdoc); - - desired_width = subdoc->width; - /* - * Obey percentage cell width in fixed columns if we - * already know table width. - */ - if ((table_cell->percent_width > 0)&&(table->width > 0)) - { - int32 avail_width; - int32 cell_pad; - - /* - * Percentage width is a percentage of the available - * cell space. - */ - cell_pad = FEUNITS_X(table->inter_cell_pad, context); - avail_width = table->width - - ((table->fixed_cols + 1) * cell_pad); - avail_width -= (table->table_ele->border_left_width + - table->table_ele->border_right_width); - desired_width = avail_width * - table_cell->percent_width / 100; - /* - * Pecentage width takes into account the - * cell padding/spacing already. - */ - desired_width -= cell_empty_space; - } - def_cell_width = lo_FindDefaultCellWidth (context, table, - table_cell, desired_width, cell_empty_space); - - /* - * If NOWRAP is off, we can go ahead and layout to this width. Otherwise - * we want to layout to a dynamic width and then use the bigger of the - * default or computed width for the cell. - */ - if ( table_cell->nowrap == FALSE ) - { - subdoc->width = def_cell_width; - } - } - - if (height_attr) - { - Bool is_percent; - - val = lo_ValueOrPercent(height_attr, &is_percent); - if (is_percent != FALSE) - { - /* - * We can process percentage heights here if - * we have a known table height. - */ - table_cell->percent_height = val; - table->has_percent_height_cells = TRUE; - val = lo_CalculateCellPercentHeight(table, table_cell); - - /* Copied to lo_CalculateCellPercentHeight() */ - /* - if ((table->height > 0)&& - (table_cell->percent_height > 0)) - { - val = table->height * - table_cell->percent_height / 100; - } - else - { - val = 0; - } - */ - } - else - { - table_cell->percent_height = 0; - val = FEUNITS_X(val, context); - } - subdoc->height = val; - if (subdoc->height < 0) - { - subdoc->height = 0; - } - table_cell->specified_height = subdoc->height; - } - - /* During relayout without reload, recalculate height of subdoc */ - if (relayout) - { - if (table_cell->percent_height > 0) - { - subdoc->height = lo_CalculateCellPercentHeight( table, table_cell); - table_cell->specified_height = subdoc->height; - } - else { - subdoc->height = table_cell->specified_height; - if (subdoc->height < 0) { - subdoc->height = 0; - } - } - - } - - if (subdoc->width == 0) - { - /* - * Choose a default size that will fit within the current table. If NOWRAP is - * on, we just want to go ahead and choose a big width so that we're sure - * to get the correct nonwrapping text layout. - */ - if ( table_cell->nowrap == FALSE ) - { - first_width = lo_ComputeInternalTableWidth ( context, table, state ); - first_width -= lo_ComputeCellEmptySpace ( context, table, subdoc); - } - else - { - first_width = FEUNITS_X(5000, context); - } - - allow_percent_width = FALSE; - } - else - { - first_width = subdoc->width; - allow_percent_width = TRUE; - } - - if (subdoc->height == 0) - { - first_height = FEUNITS_Y(10000, context); - allow_percent_height = FALSE; - } - else - { - first_height = subdoc->height; - allow_percent_height = TRUE; - } - - lo_reuse_current_state(context, subdoc->state, - first_width, first_height, 0, 0, TRUE); - new_state = subdoc->state; - subdoc->state = NULL; - - if (new_state == NULL) - { - lo_FreeElement(context, (LO_Element *)subdoc, FALSE); - return; - } - new_state->is_a_subdoc = SUBDOC_CELL; - lo_InheritParentState(context, new_state, state); - new_state->allow_percent_width = allow_percent_width; - new_state->allow_percent_height = allow_percent_height; - - new_state->base_x = 0; - new_state->base_y = 0; - new_state->display_blocked = TRUE; - if (subdoc->width == 0) - { - new_state->delay_align = TRUE; - } - - new_state->win_left = 0; - new_state->win_right = 0; - new_state->x = new_state->win_left; - new_state->y = 0; - new_state->max_width = new_state->x + 1; - new_state->left_margin = new_state->win_left; - new_state->right_margin = new_state->win_width - new_state->win_right; - new_state->list_stack->old_left_margin = new_state->left_margin; - new_state->list_stack->old_right_margin = new_state->right_margin; - - /* - * Initialize the alignment stack for this state - * to match the caption alignment. - */ - if (subdoc->horiz_alignment != LO_ALIGN_LEFT) - { - lo_PushAlignment(new_state, P_TABLE_DATA, subdoc->horiz_alignment); - } - - state->sub_state = new_state; - - state->current_ele = (LO_Element *)subdoc; - - if (is_a_header != FALSE) - { - LO_TextAttr *old_attr; - LO_TextAttr *attr; - LO_TextAttr tmp_attr; - -#ifdef DOM - old_attr = lo_GetCurrentTextAttr(new_state, context); -#else - old_attr = new_state->font_stack->text_attr; -#endif - lo_CopyTextAttr(old_attr, &tmp_attr); - tmp_attr.fontmask |= LO_FONT_BOLD; - attr = lo_FetchTextAttr(new_state, &tmp_attr); - - lo_PushFont(new_state, P_TABLE_DATA, attr); - } -} - - -Bool -lo_subdoc_has_elements(lo_DocState *sub_state) -{ - if (sub_state->end_last_line != NULL) - { - return(TRUE); - } - if (sub_state->float_list != NULL) - { - return(TRUE); - } - return(FALSE); -} - - -Bool -lo_cell_has_elements(LO_CellStruct *cell) -{ - if (cell->cell_list != NULL) - { - return(TRUE); - } - if (cell->cell_float_list != NULL) - { - return(TRUE); - } - return(FALSE); -} - - -int32 -lo_align_subdoc(MWContext *context, lo_DocState *state, lo_DocState *old_state, - LO_SubDocStruct *subdoc, lo_TableRec *table, lo_table_span *row_max) -{ - int32 ele_cnt; - LO_Element *eptr; - int32 vert_inc; - int32 top_inner_pad; - int32 bottom_inner_pad; - int32 left_inner_pad; - int32 right_inner_pad; - LO_Element **line_array; - - top_inner_pad = FEUNITS_X(table->inner_top_pad, context); - bottom_inner_pad = FEUNITS_X(table->inner_bottom_pad, context); - left_inner_pad = FEUNITS_X(table->inner_left_pad, context); - right_inner_pad = FEUNITS_X(table->inner_right_pad, context); - - ele_cnt = 0; - - /* - * Mess with vertical alignment. - */ - vert_inc = subdoc->height - (2 * subdoc->border_width) - - (top_inner_pad + bottom_inner_pad) - old_state->y; - if (vert_inc > 0) - { - if (subdoc->vert_alignment == LO_ALIGN_CENTER) - { - vert_inc = vert_inc / 2; - } - else if (subdoc->vert_alignment == LO_ALIGN_BOTTOM) - { - /* vert_inc unchanged */ - } - else if ((subdoc->vert_alignment == LO_ALIGN_BASELINE)&& - (row_max != NULL)) - { - int32 baseline; - int32 tmp_val; - - baseline = lo_GetSubDocBaseline(subdoc); - tmp_val = row_max->min_dim - baseline; - if (tmp_val > vert_inc) - { - tmp_val = vert_inc; - } - if (tmp_val > 0) - { - vert_inc = tmp_val; - } - else - { - vert_inc = 0; - } - } - else - { - vert_inc = 0; - } - } - else - { - vert_inc = 0; - } - - /* - * Make eptr point to the start of the element chain - * for this subdoc. - */ -#ifdef XP_WIN16 -{ - XP_Block *larray_array; - - XP_LOCK_BLOCK(larray_array, XP_Block *, old_state->larray_array); - old_state->line_array = larray_array[0]; - XP_UNLOCK_BLOCK(old_state->larray_array); -} -#endif /* XP_WIN16 */ - XP_LOCK_BLOCK(line_array, LO_Element **, old_state->line_array); - eptr = line_array[0]; - XP_UNLOCK_BLOCK(old_state->line_array); - - while (eptr != NULL) - { - eptr->lo_any.x += left_inner_pad; - - switch (eptr->type) - { - case LO_LINEFEED: - if (eptr->lo_linefeed.ele_attrmask & - LO_ELE_DELAY_ALIGNED) - { - if (eptr->lo_linefeed.ele_attrmask & - LO_ELE_DELAY_CENTER) - { - int32 side_inc; - int32 inside_width; - LO_Element *c_eptr; - - c_eptr = eptr; - inside_width = subdoc->width - - (2 * subdoc->border_width) - - (2 * subdoc->border_horiz_space) - - (left_inner_pad + right_inner_pad); - - side_inc = inside_width - - (c_eptr->lo_linefeed.x + - c_eptr->lo_linefeed.x_offset - - left_inner_pad); - side_inc = side_inc / 2; - if (side_inc > 0) - { - c_eptr->lo_linefeed.width -= side_inc; - if (c_eptr->lo_linefeed.width < 0) - { - c_eptr->lo_linefeed.width = 0; - } - while ((c_eptr->lo_any.prev != NULL)&& - (c_eptr->lo_any.prev->type != - LO_LINEFEED)) - { - c_eptr->lo_any.x += side_inc; - if (c_eptr->type == LO_CELL) - { - lo_ShiftCell( - (LO_CellStruct *)c_eptr, - side_inc, 0); - } - c_eptr = c_eptr->lo_any.prev; - } - c_eptr->lo_any.x += side_inc; - if (c_eptr->type == LO_CELL) - { - lo_ShiftCell( - (LO_CellStruct *)c_eptr, - side_inc, 0); - } - } - } - else if (eptr->lo_linefeed.ele_attrmask & - LO_ELE_DELAY_RIGHT) - { - int32 side_inc; - int32 inside_width; - LO_Element *c_eptr; - - c_eptr = eptr; - inside_width = subdoc->width - - (2 * subdoc->border_width) - - (2 * subdoc->border_horiz_space) - - (left_inner_pad + right_inner_pad); - - side_inc = inside_width - - (c_eptr->lo_linefeed.x + - c_eptr->lo_linefeed.x_offset - - left_inner_pad); - if (side_inc > 0) - { - c_eptr->lo_linefeed.width -= side_inc; - if (c_eptr->lo_linefeed.width < 0) - { - c_eptr->lo_linefeed.width = 0; - } - while ((c_eptr->lo_any.prev != NULL)&& - (c_eptr->lo_any.prev->type != - LO_LINEFEED)) - { - c_eptr->lo_any.x += side_inc; - if (c_eptr->type == LO_CELL) - { - lo_ShiftCell( - (LO_CellStruct *)c_eptr, - side_inc, 0); - } - c_eptr = c_eptr->lo_any.prev; - } - c_eptr->lo_any.x += side_inc; - if (c_eptr->type == LO_CELL) - { - lo_ShiftCell( - (LO_CellStruct *)c_eptr, - side_inc, 0); - } - } - } - eptr->lo_linefeed.ele_attrmask &= - (~(LO_ELE_DELAY_ALIGNED)); - } - break; - default: - break; - } - eptr->lo_any.y += (vert_inc + top_inner_pad); - if (eptr->type == LO_CELL) - { - lo_ShiftCell((LO_CellStruct *)eptr, left_inner_pad, - (vert_inc + top_inner_pad)); - } - eptr = eptr->lo_any.next; - ele_cnt++; - } - - eptr = old_state->float_list; - while (eptr != NULL) - { - eptr->lo_any.x += left_inner_pad; - eptr->lo_any.y += (vert_inc + top_inner_pad); - if (eptr->type == LO_CELL) - { - lo_ShiftCell((LO_CellStruct *)eptr, left_inner_pad, - (vert_inc + top_inner_pad)); - } - eptr = eptr->lo_any.next; - ele_cnt++; - } - - return(ele_cnt); -} - - -int32 -lo_align_cell(MWContext *context, lo_DocState *state, lo_TableCell *cell_ptr, - LO_CellStruct *cell, lo_TableRec *table, lo_table_span *row_max) -{ - int32 ele_cnt; - LO_Element *eptr; - int32 vert_inc; - int32 top_inner_pad; - int32 bottom_inner_pad; - int32 left_inner_pad; - int32 right_inner_pad; - - top_inner_pad = FEUNITS_X(table->inner_top_pad, context); - bottom_inner_pad = FEUNITS_X(table->inner_bottom_pad, context); - left_inner_pad = FEUNITS_X(table->inner_left_pad, context); - right_inner_pad = FEUNITS_X(table->inner_right_pad, context); - - ele_cnt = 0; - - /* - * Mess with vertical alignment. - */ - vert_inc = cell->height - (2 * cell->border_width) - - (top_inner_pad + bottom_inner_pad) - cell_ptr->max_y; - if (vert_inc > 0) - { - if (cell_ptr->vert_alignment == LO_ALIGN_CENTER) - { - vert_inc = vert_inc / 2; - } - else if (cell_ptr->vert_alignment == LO_ALIGN_BOTTOM) - { - /* vert_inc unchanged */ - } - else if ((cell_ptr->vert_alignment == LO_ALIGN_BASELINE)&& - (row_max != NULL)) - { - int32 baseline; - int32 tmp_val; - - baseline = lo_GetCellBaseline(cell); - tmp_val = row_max->min_dim - baseline; - if (tmp_val > vert_inc) - { - tmp_val = vert_inc; - } - if (tmp_val > 0) - { - vert_inc = tmp_val; - } - else - { - vert_inc = 0; - } - } - else - { - vert_inc = 0; - } - } - else - { - vert_inc = 0; - } - - /* - * Make eptr point to the start of the element chain - * for this cell. - */ - eptr = cell->cell_list; - - while (eptr != NULL) - { - eptr->lo_any.x += left_inner_pad; - - switch (eptr->type) - { - case LO_LINEFEED: - if (eptr->lo_linefeed.ele_attrmask & - LO_ELE_DELAY_ALIGNED) - { - if (eptr->lo_linefeed.ele_attrmask & - LO_ELE_DELAY_CENTER) - { - int32 side_inc; - int32 inside_width; - LO_Element *c_eptr; - - c_eptr = eptr; - inside_width = cell->width - - (2 * cell->border_width) - - (2 * cell->border_horiz_space) - - (left_inner_pad + right_inner_pad); - - side_inc = inside_width - - (c_eptr->lo_linefeed.x + - c_eptr->lo_linefeed.x_offset - - left_inner_pad); - side_inc = side_inc / 2; - if (side_inc > 0) - { - c_eptr->lo_linefeed.width -= side_inc; - if (c_eptr->lo_linefeed.width < 0) - { - c_eptr->lo_linefeed.width = 0; - } - while ((c_eptr->lo_any.prev != NULL)&& - (c_eptr->lo_any.prev->type != - LO_LINEFEED)) - { - c_eptr->lo_any.x += side_inc; - if (c_eptr->type == LO_CELL) - { - lo_ShiftCell( - (LO_CellStruct *)c_eptr, - side_inc, 0); - } - c_eptr = c_eptr->lo_any.prev; - } - c_eptr->lo_any.x += side_inc; - if (c_eptr->type == LO_CELL) - { - lo_ShiftCell( - (LO_CellStruct *)c_eptr, - side_inc, 0); - } - } - } - else if (eptr->lo_linefeed.ele_attrmask & - LO_ELE_DELAY_RIGHT) - { - int32 side_inc; - int32 inside_width; - LO_Element *c_eptr; - - c_eptr = eptr; - inside_width = cell->width - - (2 * cell->border_width) - - (2 * cell->border_horiz_space) - - (left_inner_pad + right_inner_pad); - - side_inc = inside_width - - (c_eptr->lo_linefeed.x + - c_eptr->lo_linefeed.x_offset - - left_inner_pad); - if (side_inc > 0) - { - c_eptr->lo_linefeed.width -= side_inc; - if (c_eptr->lo_linefeed.width < 0) - { - c_eptr->lo_linefeed.width = 0; - } - while ((c_eptr->lo_any.prev != NULL)&& - (c_eptr->lo_any.prev->type != - LO_LINEFEED)) - { - c_eptr->lo_any.x += side_inc; - if (c_eptr->type == LO_CELL) - { - lo_ShiftCell( - (LO_CellStruct *)c_eptr, - side_inc, 0); - } - c_eptr = c_eptr->lo_any.prev; - } - c_eptr->lo_any.x += side_inc; - if (c_eptr->type == LO_CELL) - { - lo_ShiftCell( - (LO_CellStruct *)c_eptr, - side_inc, 0); - } - } - } - eptr->lo_linefeed.ele_attrmask &= - (~(LO_ELE_DELAY_ALIGNED)); - } - break; - default: - break; - } - eptr->lo_any.y += (vert_inc + top_inner_pad); - if (eptr->type == LO_CELL) - { - lo_ShiftCell((LO_CellStruct *)eptr, left_inner_pad, - (vert_inc + top_inner_pad)); - } - eptr = eptr->lo_any.next; - ele_cnt++; - } - - eptr = cell->cell_float_list; - while (eptr != NULL) - { - eptr->lo_any.x += left_inner_pad; - eptr->lo_any.y += (vert_inc + top_inner_pad); - if (eptr->type == LO_CELL) - { - lo_ShiftCell((LO_CellStruct *)eptr, left_inner_pad, - (vert_inc + top_inner_pad)); - } - eptr = eptr->lo_any.next; - ele_cnt++; - } - - return(ele_cnt); -} - - -LO_SubDocStruct * -lo_EndCellSubDoc(MWContext *context, lo_DocState *state, lo_DocState *old_state, - LO_Element *element, Bool relayout) -{ - LO_Element *eptr; - LO_SubDocStruct *subdoc; - PA_Block buff; - char *str; - Bool line_break; - int32 baseline_inc; - int32 line_inc; - int32 subdoc_height, subdoc_width; - int32 doc_height; - LO_TextStruct tmp_text; - LO_TextInfo text_info; - LO_Element **line_array; - Bool dynamic_width; - Bool dynamic_height; -#ifdef LOCAL_DEBUG - fprintf(stderr, "lo_EndCellSubDoc called\n"); -#endif /* LOCAL_DEBUG */ - - /* Close any layers (blocks) that were opened in this cell, in case - the document author forgot to. */ - while (old_state->layer_nest_level > 0) - { - lo_EndLayer(context, old_state, PR_TRUE); - } - - subdoc = (LO_SubDocStruct *)element; - subdoc->state = (void *)old_state; - - /* - * All this work is to get the text_info filled in for the current - * font in the font stack. Yuck, there must be a better way. - */ - memset (&tmp_text, 0, sizeof (tmp_text)); - buff = PA_ALLOC(1); - if (buff == NULL) - { - state->top_state->out_of_memory = TRUE; - return(NULL); - } - PA_LOCK(str, char *, buff); - str[0] = ' '; - PA_UNLOCK(buff); - tmp_text.text = buff; - tmp_text.text_len = 1; - tmp_text.text_attr = -#ifdef DOM - lo_GetCurrentTextAttr(state, context); -#else - state->font_stack->text_attr; -#endif - FE_GetTextInfo(context, &tmp_text, &text_info); - PA_FREE(buff); - - if (relayout == FALSE) - { - /* - * We don't want to leave any end paragraph linbreaks in the subdoc - * as they give us a really ugly blank line at the bottom of a cell. So, - * if the last element in the list is paragraph break linefeed, then - * we kill it. - */ - eptr = old_state->end_last_line; - if ( (eptr != NULL) && (eptr->type == LO_LINEFEED) && - (eptr->lo_linefeed.break_type == LO_LINEFEED_BREAK_PARAGRAPH) ) - { - LO_Element *prev; - - prev = eptr->lo_any.prev; - - /* - * Kill this layout element and reset the subdoc height - */ - if ( prev != NULL ) - { - prev->lo_any.next = NULL; - old_state->end_last_line = prev; - } - else - { - old_state->line_list = NULL; - old_state->end_last_line = NULL; - } - - /* The if condition checks to make sure that the linefeed that we just killed - * was sticking out of the bottom of the cell. This fixes bug 81282. - */ - if (eptr->lo_linefeed.y + eptr->lo_linefeed.line_height >= old_state->y) { - /* shrink the document */ - old_state->y -= eptr->lo_linefeed.line_height; - } - - lo_RecycleElements ( context, old_state, eptr ); - } - } - - dynamic_width = FALSE; - dynamic_height = FALSE; - if (subdoc->width == 0) - { - dynamic_width = TRUE; - /* - * Subdocs that were dynamically widthed, and which - * contained right aligned items, must be relaid out - * once their width is determined. - */ - eptr = old_state->float_list; - while (eptr != NULL) - { - if ((eptr->type == LO_IMAGE)&& - (eptr->lo_image.image_attr->alignment == LO_ALIGN_RIGHT)) - { - old_state->must_relayout_subdoc = TRUE; - break; - } - else if ((eptr->type == LO_SUBDOC)&& - (eptr->lo_subdoc.alignment == LO_ALIGN_RIGHT)) - { - old_state->must_relayout_subdoc = TRUE; - break; - } - eptr = eptr->lo_any.next; - } - - subdoc->width = old_state->max_width; - } - - /* - * Add in the size of the subdoc's borders - */ - subdoc->width += (2 * subdoc->border_width); - - /* - * Figure the height the subdoc laid out in. - * Use this if we were passed no height, or if it is greater - * than the passed height. - */ - doc_height = old_state->y + (2 * subdoc->border_width); - if (subdoc->height == 0) - { - dynamic_height = TRUE; - subdoc->height = doc_height; - } - else if (subdoc->height < doc_height) - { - subdoc->height = doc_height; - } - - /* - * Make eptr point to the start of the element chain - * for this subdoc. - */ -#ifdef XP_WIN16 -{ - XP_Block *larray_array; - - XP_LOCK_BLOCK(larray_array, XP_Block *, old_state->larray_array); - old_state->line_array = larray_array[0]; - XP_UNLOCK_BLOCK(old_state->larray_array); -} -#endif /* XP_WIN16 */ - XP_LOCK_BLOCK(line_array, LO_Element **, old_state->line_array); - eptr = line_array[0]; - XP_UNLOCK_BLOCK(old_state->line_array); - - while (eptr != NULL) - { - switch (eptr->type) - { - case LO_LINEFEED: - if ((eptr->lo_linefeed.x + eptr->lo_linefeed.x_offset + - eptr->lo_linefeed.width) >= (subdoc->width - 1 - - (2 * subdoc->border_width))) - { - eptr->lo_linefeed.width = (subdoc->width - 1 - - (2 * subdoc->border_width)) - - (eptr->lo_linefeed.x + - eptr->lo_linefeed.x_offset); - if (eptr->lo_linefeed.width < 0) - { - eptr->lo_linefeed.width = 0; - } - } -#ifdef OLD_DELAY_CENTERED - if (eptr->lo_linefeed.ele_attrmask & - LO_ELE_DELAY_CENTERED) - { - int32 side_inc; - LO_Element *c_eptr; - - c_eptr = eptr; - - side_inc = subdoc->width - 1 - - (2 * subdoc->border_width) - - (eptr->lo_linefeed.x + - eptr->lo_linefeed.x_offset); - side_inc = side_inc / 2; - if (side_inc > 0) - { - c_eptr->lo_linefeed.width -= side_inc; - if (c_eptr->lo_linefeed.width < 0) - { - c_eptr->lo_linefeed.width = 0; - } - while ((c_eptr->lo_any.prev != NULL)&& - (c_eptr->lo_any.prev->type != - LO_LINEFEED)) - { - c_eptr->lo_any.x += side_inc; - if (c_eptr->type == LO_CELL) - { - lo_ShiftCell( - (LO_CellStruct *)c_eptr, - side_inc, 0); - } - c_eptr = c_eptr->lo_any.prev; - } - c_eptr->lo_any.x += side_inc; - if (c_eptr->type == LO_CELL) - { - lo_ShiftCell( - (LO_CellStruct *)c_eptr, - side_inc, 0); - } - } - eptr->lo_linefeed.ele_attrmask &= - (~(LO_ELE_DELAY_CENTERED)); - } -#endif /* OLD_DELAY_CENTERED */ - break; - /* - * This is awful, but any dynamically dimenstioned - * subdoc that contains one of these elements - * must be relayed out to take care of window - * width and height dependencies. - */ - - /* case LO_HRULE: */ - case LO_SUBDOC: - case LO_TABLE: - old_state->must_relayout_subdoc = TRUE; - - break; - case LO_IMAGE: -/* WILL NEED THIS LATER FOR PERCENT WIDTH IMAGES - if ((old_state->allow_percent_width == FALSE)|| - (old_state->allow_percent_height == FALSE)) - { - old_state->must_relayout_subdoc = TRUE; - } -*/ - break; - default: - break; - } - eptr = eptr->lo_any.next; - } - - /* - * Remember: (2 * subdoc->border_width) has already been added to the subdoc - * width above... - */ - subdoc_width = subdoc->width + (2 * subdoc->border_horiz_space); - subdoc_height = subdoc->height + (2 * subdoc->border_width) + - (2 * subdoc->border_vert_space); - - if (old_state->display_blocked != FALSE) - { - old_state->display_blocked = FALSE; - } - - /* - * Will this subdoc make the line too wide. - */ - if ((state->x + subdoc_width) > state->right_margin) - { - line_break = TRUE; - } - else - { - line_break = FALSE; - } - - /* - * if we are at the beginning of the line. There is - * no point in breaking, we are just too wide. - * Also don't break in unwrappedpreformatted text. - * Also can't break inside a NOBR section. - */ - if ((state->at_begin_line != FALSE)|| - (state->preformatted == PRE_TEXT_YES)|| - (state->breakable == FALSE)) - { - line_break = FALSE; - } - - /* - * break on the subdoc if we have - * a break. - */ -/* DOn't break in cell - if (line_break != FALSE) - { - lo_SoftLineBreak(context, state, TRUE); - subdoc->x = state->x; - subdoc->y = state->y; - } -*/ - - /* - * Figure out how to align this subdoc. - * baseline_inc is how much to increase the baseline - * of previous element of this line. line_inc is how - * much to increase the line height below the baseline. - */ - baseline_inc = 0; - line_inc = 0; - /* - * If we are at the beginning of a line, with no baseline, - * we first set baseline and line_height based on the current - * font, then place the subdoc. - */ - if (state->baseline == 0) - { - state->baseline = 0; - } - - lo_CalcAlignOffsets(state, &text_info, (intn)subdoc->alignment, - subdoc_width, subdoc_height, - &subdoc->x_offset, &subdoc->y_offset, &line_inc, &baseline_inc); - - subdoc->x_offset += (int16)subdoc->border_horiz_space; - subdoc->y_offset += (int32)subdoc->border_vert_space; - - old_state->base_x = subdoc->x + subdoc->x_offset + - subdoc->border_width; - old_state->base_y = subdoc->y + subdoc->y_offset + - subdoc->border_width; - - /* - * Clean up state - state->x = state->x + subdoc->x_offset + - subdoc_width - subdoc->border_horiz_space; - state->linefeed_state = 0; - state->at_begin_line = FALSE; - state->trailing_space = FALSE; - state->cur_ele_type = LO_SUBDOC; - */ - - return(subdoc); -} - - -void -lo_relayout_recycle(MWContext *context, lo_DocState *state, LO_Element *elist) -{ - LO_LockLayout(); - - while (elist != NULL) - { - LO_Element *eptr; - - eptr = elist; - elist = elist->lo_any.next; - eptr->lo_any.next = NULL; - - if (eptr->type == LO_IMAGE) - { - eptr->lo_any.next = state->top_state->trash; - state->top_state->trash = eptr; - } - else if (eptr->type == LO_CELL) - { - if (eptr->lo_cell.cell_list != NULL) - { - if (eptr->lo_cell.cell_list_end != NULL) - { - eptr->lo_cell.cell_list_end->lo_any.next = NULL; - } - lo_relayout_recycle(context, state, - eptr->lo_cell.cell_list); - eptr->lo_cell.cell_list = NULL; - eptr->lo_cell.cell_list_end = NULL; - } - if (eptr->lo_cell.cell_float_list != NULL) - { - lo_relayout_recycle(context, state, - eptr->lo_cell.cell_float_list); - eptr->lo_cell.cell_float_list = NULL; - } - lo_RecycleElements(context, state, eptr); - } - else - { - /* - * If this is an embed, tell it that it should - * recycle rather than delete itself. - */ - if (eptr->type == LO_EMBED) - { - NPL_SameElement((LO_EmbedStruct*)eptr); - } - lo_RecycleElements(context, state, eptr); - } - } - LO_UnlockLayout(); -} - - -static void -lo_cleanup_state(MWContext *context, lo_DocState *state) -{ - LO_Element **line_array; - - if (state == NULL) - { - return; - } - - if (state->left_margin_stack != NULL) - { - lo_MarginStack *mptr; - lo_MarginStack *margin; - - mptr = state->left_margin_stack; - while (mptr != NULL) - { - margin = mptr; - mptr = mptr->next; - XP_DELETE(margin); - } - state->left_margin_stack = NULL; - } - if (state->right_margin_stack != NULL) - { - lo_MarginStack *mptr; - lo_MarginStack *margin; - - mptr = state->right_margin_stack; - while (mptr != NULL) - { - margin = mptr; - mptr = mptr->next; - XP_DELETE(margin); - } - state->right_margin_stack = NULL; - } - - if (state->line_list != NULL) - { - lo_relayout_recycle(context, state, state->line_list); - state->line_list = NULL; - } - - if (state->font_stack != NULL) - { - lo_FontStack *fstack; - lo_FontStack *fptr; - - fptr = state->font_stack; - while (fptr != NULL) - { - fstack = fptr; - fptr = fptr->next; - XP_DELETE(fstack); - } - state->font_stack = NULL; - } - - if (state->align_stack != NULL) - { - lo_AlignStack *aptr; - lo_AlignStack *align; - - aptr = state->align_stack; - while (aptr != NULL) - { - align = aptr; - aptr = aptr->next; - XP_DELETE(align); - } - state->align_stack = NULL; - } - - if (state->list_stack != NULL) - { - lo_ListStack *lptr; - lo_ListStack *list; - - lptr = state->list_stack; - while (lptr != NULL) - { - list = lptr; - lptr = lptr->next; - XP_DELETE(list); - } - state->list_stack = NULL; - } - - if (state->line_buf != NULL) - { - PA_FREE(state->line_buf); - state->line_buf = NULL; - } - - if (state->float_list != NULL) - { - lo_relayout_recycle(context, state, state->float_list); - state->float_list = NULL; - } - - if (state->line_array != NULL) - { - LO_Element *eptr; - -#ifdef XP_WIN16 -{ - XP_Block *larray_array; - intn cnt; - - XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array); - cnt = state->larray_array_size - 1; - while (cnt > 0) - { - XP_FREE_BLOCK(larray_array[cnt]); - cnt--; - } - state->line_array = larray_array[0]; - XP_UNLOCK_BLOCK(state->larray_array); - XP_FREE_BLOCK(state->larray_array); -} -#endif /* XP_WIN16 */ - - eptr = NULL; - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array); - eptr = line_array[0]; - if (eptr != NULL) - { - lo_relayout_recycle(context, state, eptr); - } - XP_UNLOCK_BLOCK(state->line_array); - XP_FREE_BLOCK(state->line_array); - } - - XP_DELETE(state); -} - - -static lo_FormData * -lo_merge_form_data(lo_FormData *new_form_list, lo_FormData *hold_form_list) -{ - intn i; - LO_FormElementStruct **new_ele_list; - LO_FormElementStruct **hold_ele_list; - - PA_LOCK(new_ele_list, LO_FormElementStruct **, - new_form_list->form_elements); - PA_LOCK(hold_ele_list, LO_FormElementStruct **, - hold_form_list->form_elements); - for (i=0; i<new_form_list->form_ele_cnt; i++) - { - if (hold_ele_list[i] != new_ele_list[i]) - { - if (new_ele_list[i]->mocha_object == NULL) - { - new_ele_list[i]->mocha_object - = hold_ele_list[i]->mocha_object; - } - hold_ele_list[i] = new_ele_list[i]; - } - } - PA_UNLOCK(hold_form_list->form_elements); - PA_UNLOCK(new_form_list->form_elements); - - /* XXX sometimes the second pass does not reflect a form object! */ - if (new_form_list->mocha_object != NULL) - { - hold_form_list->mocha_object = new_form_list->mocha_object; - } - return(hold_form_list); -} - - -/* - * Serious table magic. Given a table cell subdoc, - * redo the layout to the new width from the stored tag list, - * and create a whole new subdoc, which is returned. - */ -LO_SubDocStruct * -lo_RelayoutCaptionSubdoc(MWContext *context, lo_DocState *state, lo_TableCaption *caption, - LO_SubDocStruct *subdoc, int32 width, Bool is_a_header) -{ - int32 first_height; - lo_TopState *top_state; - lo_DocState *old_state; - lo_DocState *new_state; - /* ifdef-ed out of service: - PA_Tag *tag_list; */ - /* Commented and ifdef-ed out of service: - PA_Tag *tag_ptr; */ - /* Commented out of service: - PA_Tag *tag_end_ptr; */ - int32 doc_id; - Bool allow_percent_width; - Bool allow_percent_height; - int32 hold_form_ele_cnt; - int32 hold_form_data_index; - intn hold_form_id; - intn hold_current_form_num; - Bool hold_in_form; - lo_FormData *hold_form_list; - int32 hold_embed_global_index; - int32 original_tag_count; - intn hold_url_list_len; - NET_ReloadMethod save_force; - /* ifdef-ed out of service: - Bool save_diff_state; */ - /* ifdef-ed out of service: - int32 save_state_pushes; */ - /* ifdef-ed out of service: - int32 save_state_pops; */ - lo_DocLists *doc_lists; - int32 hold_image_list_count; - int32 hold_applet_list_count; - int32 hold_embed_list_count; - int32 hold_current_layer_num; - - /* - * Relayout is NOT allowed to block on images, so never - * have the forced reload flag set. - */ - save_force = state->top_state->force_reload; - state->top_state->force_reload = NET_CACHE_ONLY_RELOAD; - -#ifdef LOCAL_DEBUG - fprintf(stderr, "lo_RelayoutSubdoc called\n"); -#endif /* LOCAL_DEBUG */ - - top_state = state->top_state; - old_state = (lo_DocState *) subdoc->state; - - /* - * We are going to reuse this subdoc element instead - * of allocating a new one. - */ - /* subdoc->state = NULL; */ - subdoc->width = width; - subdoc->height = 0; - - doc_lists = lo_GetCurrentDocLists(state); - - /* - * If this subdoc contained form elements. We want to reuse - * them without messing up the order of later form elements in - * other subdocs. - * - * We assume that relaying out the doc will create the exact - * same number of form elements in the same order as the first time. - * so we reset global form counters to before this subdoc - * was ever laid out, saving the current counts to restore later. - */ - if (doc_lists->form_list != NULL) - { - lo_FormData *form_list; - lo_FormData *tmp_fptr; - - hold_form_id = old_state->form_id; - hold_current_form_num = doc_lists->current_form_num; - form_list = doc_lists->form_list; - hold_form_list = NULL; - while ((form_list != NULL)&& - (form_list->id > hold_form_id)) - { - tmp_fptr = form_list; - form_list = form_list->next; - tmp_fptr->next = hold_form_list; - hold_form_list = tmp_fptr; - } - doc_lists->form_list = form_list; - doc_lists->current_form_num = hold_form_id; - if (form_list != NULL) - { - hold_form_ele_cnt = form_list->form_ele_cnt; - form_list->form_ele_cnt = old_state->form_ele_cnt; - } - else - { - hold_form_ele_cnt = 0; - } - } - else - { - hold_form_id = 0; - hold_form_ele_cnt = 0; - hold_form_list = NULL; - hold_current_form_num = 0; - } - - /* - * We're going to be deleting and then recreating the contents - * of this subdoc. We want the newly-created embeds to have - * the same embed indices as their recycled counterparts, so - * we reset the master embed index in the top_state to be the - * value it held at the time the old subdoc was created. When - * we're finished creating the new subdoc, the master index - * should be back to its original value (but just in case we - * save that value in a local variable here). - */ - hold_embed_global_index = top_state->embed_count; - top_state->embed_count = old_state->embed_count_base; - - /* ditto here for the last comment. We are trying to keep - * a tag count that reflects the order of tags coming in - * on the stream. We need that count to be correct across - * multiple relayout instances so we restore the top state - * count with the saved state - */ - original_tag_count = top_state->tag_count; - top_state->tag_count = state->beginning_tag_count; - - /* - * Same goes for anchors and images - */ - hold_url_list_len = doc_lists->url_list_len; - doc_lists->url_list_len = old_state->url_count_base; - - hold_image_list_count = doc_lists->image_list_count; - doc_lists->image_list_count = old_state->image_list_count_base; - - hold_applet_list_count = doc_lists->applet_list_count; - doc_lists->applet_list_count = old_state->applet_list_count_base; - - hold_embed_list_count = doc_lists->embed_list_count; - doc_lists->embed_list_count = old_state->embed_list_count_base; - - hold_current_layer_num = top_state->current_layer_num; - top_state->current_layer_num = old_state->current_layer_num_base; - - /* - * Save whether we are in a form or not, and restore - * to what we were when the subdoc was started. - */ - hold_in_form = top_state->in_form; - top_state->in_form = old_state->start_in_form; - - if (top_state->savedData.FormList != NULL) - { - lo_SavedFormListData *all_form_ele; - - all_form_ele = top_state->savedData.FormList; - hold_form_data_index = all_form_ele->data_index; - all_form_ele->data_index = old_state->form_data_index; - } - else - { - hold_form_data_index = 0; - } - - /* - * Still variable height, but we know the width now. - */ - first_height = FEUNITS_Y(10000, context); - allow_percent_height = FALSE; - allow_percent_width = TRUE; - - /* - * Get a new sub-state to create the new subdoc in. - */ - /* - new_state = lo_NewLayout(context, width, first_height, 0, 0, NULL); - */ - lo_reuse_current_state(context, subdoc->state, width, - first_height, 0, 0, FALSE); - - new_state = subdoc->state; - subdoc->state = NULL; - - - if (new_state == NULL) - { - state->top_state->force_reload = save_force; - return(subdoc); - } - - new_state->end_last_line = NULL; - /* - if (old_state->is_a_subdoc == SUBDOC_CAPTION) - { - new_state->is_a_subdoc = SUBDOC_CAPTION; - } - else - { - new_state->is_a_subdoc = SUBDOC_CELL; - } - */ - new_state->is_a_subdoc = SUBDOC_CAPTION; - - lo_InheritParentColors(context, new_state, state); - new_state->allow_percent_width = allow_percent_width; - new_state->allow_percent_height = allow_percent_height; - /* - * In relaying out subdocs, we NEVER link back up subdoc tags - */ - new_state->subdoc_tags = NULL; - new_state->subdoc_tags_end = NULL; - - /* - * Initialize other new state sundries. - */ - new_state->base_x = 0; - new_state->base_y = 0; - new_state->display_blocked = TRUE; - if (subdoc->width == 0) - { - new_state->delay_align = TRUE; - } - - new_state->win_left = 0; - new_state->win_right = 0; - new_state->x = new_state->win_left; - new_state->y = 0; - new_state->max_width = new_state->x + 1; - new_state->left_margin = new_state->win_left; - new_state->right_margin = new_state->win_width - new_state->win_right; - new_state->list_stack->old_left_margin = new_state->left_margin; - new_state->list_stack->old_right_margin = new_state->right_margin; - - /* we don't need min widths during relayout */ - new_state->need_min_width = FALSE; - - /* reset line_height stack */ - while (new_state->line_height_stack) - lo_PopLineHeight(new_state); - - /* - * Initialize the alignment stack for this state - * to match the caption alignment. - */ - if (subdoc->horiz_alignment != LO_ALIGN_LEFT) - { - lo_PushAlignment(new_state, P_TABLE_DATA, subdoc->horiz_alignment); - } - - state->sub_state = new_state; - - state->current_ele = (LO_Element *)subdoc; - - if (is_a_header != FALSE) - { - LO_TextAttr *old_attr; - LO_TextAttr *attr; - LO_TextAttr tmp_attr; - -#ifdef DOM - old_attr = lo_GetCurrentTextAttr(new_state, context); -#else - old_attr = new_state->font_stack->text_attr; -#endif - lo_CopyTextAttr(old_attr, &tmp_attr); - tmp_attr.fontmask |= LO_FONT_BOLD; - attr = lo_FetchTextAttr(new_state, &tmp_attr); - - lo_PushFont(new_state, P_TABLE_HEADER, attr); - } - - /* - * Move our current state down into the new sub-state. - * Fetch the tag list from the old subdoc's state in preparation - * for relayout. - */ - state = new_state; - - lo_rl_ReflowDocState( context, state ); - - /* - * makes sure we are at the bottom - * of everything in the document. - */ - /* - lo_CloseOutLayout(context, state); - */ - - lo_EndLayoutDuringReflow( context, state ); - - old_state = state; - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - state = top_state->doc_state; - - while ((state->sub_state != NULL)&& - (state->sub_state != old_state)) - { - state = state->sub_state; - } - - /* - * Ok, now reset the global form element counters - * to their original values. - */ - if ((doc_lists->form_list != NULL)||(hold_form_list != NULL)) - { - lo_FormData *form_list; - lo_FormData *new_form_list; - lo_FormData *tmp_fptr; - - /* - * Remove any new forms created in this subdocs to a - * separate list. - */ - form_list = doc_lists->form_list; - new_form_list = NULL; - while ((form_list != NULL)&& - (form_list->id > hold_form_id)) - { - tmp_fptr = form_list; - form_list = form_list->next; - tmp_fptr->next = new_form_list; - new_form_list = tmp_fptr; - } - - /* - * Restore the element count in the form we started in - * because the subdoc may have left it half finished. - */ - if (form_list != NULL) - { - form_list->form_ele_cnt = hold_form_ele_cnt; - } - - /* - * Merge the newly created forms with the old ones - * since the new ones may have partially complete - * data. - */ - while ((new_form_list != NULL)&&(hold_form_list != NULL)) - { - tmp_fptr = lo_merge_form_data(new_form_list, - hold_form_list); - new_form_list = new_form_list->next; - hold_form_list = hold_form_list->next; - tmp_fptr->next = form_list; - form_list = tmp_fptr; - } - - /* - * Add back on forms that are from later subdocs. - */ - while (hold_form_list != NULL) - { - tmp_fptr = hold_form_list; - hold_form_list = hold_form_list->next; - tmp_fptr->next = form_list; - form_list = tmp_fptr; - } - - doc_lists->form_list = form_list; - doc_lists->current_form_num = hold_current_form_num; - } - - /* - * Restore in form status to what is - * was before this relayout. - */ - top_state->in_form = hold_in_form; - - if (top_state->savedData.FormList != NULL) - { - lo_SavedFormListData *all_form_ele; - - all_form_ele = top_state->savedData.FormList; - all_form_ele->data_index = hold_form_data_index; - } - - /* - * The master embed index is typically now be back - * to its original value, but might not be if we - * only had to relayout some (not all) of the embeds - * in this subdoc. So, make sure it's set back to - * its original value here. - */ - top_state->embed_count = hold_embed_global_index; - - /* verify that the tag count is still correct */ - top_state->tag_count = original_tag_count; - - /* - * Likewise for the anchor list. - */ - doc_lists->url_list_len = hold_url_list_len; - doc_lists->image_list_count = hold_image_list_count; - doc_lists->applet_list_count = hold_applet_list_count; - doc_lists->embed_list_count = hold_embed_list_count; - top_state->current_layer_num = hold_current_layer_num; - - subdoc = NULL; - if ((state != old_state)&& - (state->current_ele != NULL)) - { - subdoc = lo_EndCellSubDoc(context, state, - old_state, state->current_ele, TRUE); - state->sub_state = NULL; - state->current_ele = NULL; -/* - if ((state->is_a_subdoc == SUBDOC_CELL)|| - (state->is_a_subdoc == SUBDOC_CAPTION)) - { - if (old_state->subdoc_tags_end != NULL) - { - state->subdoc_tags_end = - old_state->subdoc_tags_end; - } - } -*/ - } - - old_state->must_relayout_subdoc = FALSE; - - state->top_state->force_reload = save_force; - return(subdoc); -} - - -LO_CellStruct * -lo_RelayoutCell(MWContext *context, lo_DocState *state, - LO_SubDocStruct *subdoc, lo_TableCell *cell_ptr, - LO_CellStruct *cell, int32 width, Bool is_a_header, - Bool relayout) -{ - LO_CellStruct *cell_ele; - int32 first_height; - lo_TopState *top_state; - lo_DocState *old_state; - lo_DocState *new_state; - /* Unused: - PA_Tag *tag_list; */ - /* COmmented out of service: - PA_Tag *tag_ptr; */ - /* Commented out of service: - PA_Tag *tag_end_ptr; */ - int32 doc_id; - Bool allow_percent_width; - Bool allow_percent_height; - int32 hold_form_ele_cnt; - int32 hold_form_data_index; - intn hold_form_id; - intn hold_current_form_num; - Bool hold_in_form; - lo_FormData *hold_form_list; - int32 hold_embed_global_index; - int32 original_tag_count; - intn hold_url_list_len; - NET_ReloadMethod save_force; - /* Unused: - Bool save_diff_state; */ - /* Unused: - int32 save_state_pushes; */ - /* Unused: - ;int32 save_state_pops; */ - lo_DocLists *doc_lists; - int32 hold_image_list_count; - int32 hold_applet_list_count; - int32 hold_embed_list_count; - int32 hold_current_layer_num; - /* Commented out of service: - LO_Element * elem_list; */ - - /* - * Relayout is NOT allowed to block on images, so never - * have the forced reload flag set. - */ - save_force = state->top_state->force_reload; - state->top_state->force_reload = NET_CACHE_ONLY_RELOAD; - - top_state = state->top_state; - - /* - * We are going to reuse this subdoc element instead - * of allocating a new one. - lo_reuse_current_subdoc(context, subdoc); - subdoc->state = NULL; - */ - subdoc->width = width; - subdoc->height = 0; - - subdoc->horiz_alignment = cell_ptr->horiz_alignment; - - doc_lists = lo_GetCurrentDocLists(state); - - /* - * If this subdoc contained form elements. We want to reuse - * them without messing up the order of later form elements in - * other subdocs. - * - * We assume that relaying out the doc will create the exact - * same number of form elements in the same order as the first time. - * so we reset global form counters to before this subdoc - * was ever laid out, saving the current counts to restore later. - */ - if (doc_lists->form_list != NULL) - { - lo_FormData *form_list; - lo_FormData *tmp_fptr; - - hold_form_id = cell_ptr->form_id; - hold_current_form_num = doc_lists->current_form_num; - form_list = doc_lists->form_list; - hold_form_list = NULL; - while ((form_list != NULL)&& - (form_list->id > hold_form_id)) - { - tmp_fptr = form_list; - form_list = form_list->next; - tmp_fptr->next = hold_form_list; - hold_form_list = tmp_fptr; - } - doc_lists->form_list = form_list; - doc_lists->current_form_num = hold_form_id; - if (form_list != NULL) - { - hold_form_ele_cnt = form_list->form_ele_cnt; - form_list->form_ele_cnt = cell_ptr->form_ele_cnt; - } - else - { - hold_form_ele_cnt = 0; - } - } - else - { - hold_form_id = 0; - hold_form_ele_cnt = 0; - hold_form_list = NULL; - hold_current_form_num = 0; - } - - /* - * We're going to be deleting and then recreating the contents - * of this subdoc. We want the newly-created embeds to have - * the same embed indices as their recycled counterparts, so - * we reset the master embed index in the top_state to be the - * value it held at the time the old subdoc was created. When - * we're finished creating the new subdoc, the master index - * should be back to its original value (but just in case we - * save that value in a local variable here). - */ - hold_embed_global_index = top_state->embed_count; - top_state->embed_count = cell_ptr->embed_count_base; - - /* same for tag count */ - original_tag_count = top_state->tag_count; - top_state->tag_count = cell_ptr->beginning_tag_count; - - /* - * Same goes for anchors and images - */ - hold_url_list_len = doc_lists->url_list_len; - doc_lists->url_list_len = cell_ptr->url_count_base; - - hold_image_list_count = doc_lists->image_list_count; - doc_lists->image_list_count = cell_ptr->image_list_count_base; - - hold_applet_list_count = doc_lists->applet_list_count; - doc_lists->applet_list_count = cell_ptr->applet_list_count_base; - - hold_embed_list_count = doc_lists->embed_list_count; - doc_lists->embed_list_count = cell_ptr->embed_list_count_base; - - hold_current_layer_num = top_state->current_layer_num; - top_state->current_layer_num = cell_ptr->current_layer_num_base; - - /* - * Save whether we are in a form or not, and restore - * to what we were when the subdoc was started. - */ - hold_in_form = top_state->in_form; - top_state->in_form = cell_ptr->start_in_form; - - if (top_state->savedData.FormList != NULL) - { - lo_SavedFormListData *all_form_ele; - - all_form_ele = top_state->savedData.FormList; - hold_form_data_index = all_form_ele->data_index; - all_form_ele->data_index = cell_ptr->form_data_index; - } - else - { - hold_form_data_index = 0; - } - - /* - * Still variable height, but we know the width now. - */ - first_height = FEUNITS_Y(10000, context); - allow_percent_height = FALSE; - allow_percent_width = TRUE; - - /* - * Get a new sub-state to create the new subdoc in. - */ - lo_reuse_current_state(context, subdoc->state, - width, first_height, 0, 0, TRUE); - new_state = subdoc->state; - subdoc->state = NULL; - - - if (new_state == NULL) - { - state->top_state->force_reload = save_force; - return(cell); - } - if (cell_ptr->is_a_subdoc == SUBDOC_CAPTION) - { - new_state->is_a_subdoc = SUBDOC_CAPTION; - } - else - { - new_state->is_a_subdoc = SUBDOC_CELL; - } - - lo_InheritParentState(context, new_state, state); - new_state->allow_percent_width = allow_percent_width; - new_state->allow_percent_height = allow_percent_height; - /* - * In relaying out subdocs, we NEVER link back up subdoc tags - */ - new_state->subdoc_tags = NULL; - new_state->subdoc_tags_end = NULL; - - /* - * Initialize other new state sundries. - */ - new_state->base_x = 0; - new_state->base_y = 0; - new_state->display_blocked = TRUE; - if (subdoc->width == 0) - { - new_state->delay_align = TRUE; - } - - new_state->win_left = 0; - new_state->win_right = 0; - new_state->x = new_state->win_left; - new_state->y = 0; - new_state->max_width = new_state->x + 1; - new_state->left_margin = new_state->win_left; - new_state->right_margin = new_state->win_width - new_state->win_right; - new_state->list_stack->old_left_margin = new_state->left_margin; - new_state->list_stack->old_right_margin = new_state->right_margin; - - /* we don't need min widths during relayout */ - new_state->need_min_width = FALSE; - - /* reset line_height stack */ - while(new_state->line_height_stack) - lo_PopLineHeight(new_state); - - /* - * Initialize the alignment stack for this state - * to match the caption alignment. - */ - if (subdoc->horiz_alignment != LO_ALIGN_LEFT) - { - lo_PushAlignment(new_state, P_TABLE_DATA, subdoc->horiz_alignment); - } - - state->sub_state = new_state; - - state->current_ele = (LO_Element *)subdoc; - - if (is_a_header != FALSE) - { - LO_TextAttr *old_attr; - LO_TextAttr *attr; - LO_TextAttr tmp_attr; - -#ifdef DOM - old_attr = lo_GetCurrentTextAttr(new_state, context); -#else - old_attr = new_state->font_stack->text_attr; -#endif - lo_CopyTextAttr(old_attr, &tmp_attr); - tmp_attr.fontmask |= LO_FONT_BOLD; - attr = lo_FetchTextAttr(new_state, &tmp_attr); - - lo_PushFont(new_state, P_TABLE_HEADER, attr); - } - - /* - * Move our current state down into the new sub-state. - * Fetch the tag list from the old subdoc's state in preparation - * for relayout. - */ - - state = new_state; - /* - tag_ptr = cell_ptr->subdoc_tags; - tag_end_ptr = cell_ptr->subdoc_tags_end; - cell_ptr->subdoc_tags = NULL; - cell_ptr->subdoc_tags_end = NULL; - - if (tag_end_ptr != NULL) - { - tag_end_ptr = tag_end_ptr->next; - } - */ - - /* - * Copy some cell attribute state from the old cell to the subdoc - * so that we retain the correct state. Make sure that the bg_color - * doesn't get freed. - */ - subdoc->horiz_alignment = cell_ptr->horiz_alignment; - subdoc->vert_alignment = cell_ptr->vert_alignment; - subdoc->backdrop = cell->backdrop; - /* - cell->backdrop.bg_color = NULL; - cell->backdrop.url = NULL; - */ - - /* - * Clean up memory used by old cell. - */ - /* - elem_list = cell->cell_list; - cell->next = NULL; - cell->cell_list = NULL; - cell->cell_list_end = NULL; - lo_relayout_recycle(context, state, (LO_Element *)cell); - */ - - /* - * Relayout all the goodies - */ - /* - lo_RelayoutTags(context, state, tag_ptr, tag_end_ptr, elem_list); - */ - - /* - * Link the end of this subdoc's tag chain back to - * its parent. The beginning should have never been - * unlinked from the parent. - */ - /* - if (state->subdoc_tags_end != NULL) - { - state->subdoc_tags_end->next = tag_end_ptr; - } - */ - - /* - * makes sure we are at the bottom - * of everything in the document. - */ - - lo_rl_ReflowCell( context, state, cell ); - - /* Replaced with lo_EndLayoutDuringReflow() - lo_CloseOutLayout(context, state); - */ - - lo_EndLayoutDuringReflow( context, state ); - - - old_state = state; - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - state = top_state->doc_state; - - while ((state->sub_state != NULL)&& - (state->sub_state != old_state)) - { - state = state->sub_state; - } - - /* - * Ok, now reset the global form element counters - * to their original values. - */ - if ((doc_lists->form_list != NULL)||(hold_form_list != NULL)) - { - lo_FormData *form_list; - lo_FormData *new_form_list; - lo_FormData *tmp_fptr; - - /* - * Remove any new forms created in this subdocs to a - * separate list. - */ - form_list = doc_lists->form_list; - new_form_list = NULL; - while ((form_list != NULL)&& - (form_list->id > hold_form_id)) - { - tmp_fptr = form_list; - form_list = form_list->next; - tmp_fptr->next = new_form_list; - new_form_list = tmp_fptr; - } - - /* - * Restore the element count in the form we started in - * because the subdoc may have left it half finished. - */ - if (form_list != NULL) - { - form_list->form_ele_cnt = hold_form_ele_cnt; - } - - /* - * Merge the newly created forms with the old ones - * since the new ones may have partially complete - * data. - */ - while ((new_form_list != NULL)&&(hold_form_list != NULL)) - { - tmp_fptr = lo_merge_form_data(new_form_list, - hold_form_list); - new_form_list = new_form_list->next; - hold_form_list = hold_form_list->next; - tmp_fptr->next = form_list; - form_list = tmp_fptr; - } - - /* - * Add back on forms that are from later subdocs. - */ - while (hold_form_list != NULL) - { - tmp_fptr = hold_form_list; - hold_form_list = hold_form_list->next; - tmp_fptr->next = form_list; - form_list = tmp_fptr; - } - - doc_lists->form_list = form_list; - doc_lists->current_form_num = hold_current_form_num; - } - - /* - * Restore in form status to what is - * was before this relayout. - */ - top_state->in_form = hold_in_form; - - if (top_state->savedData.FormList != NULL) - { - lo_SavedFormListData *all_form_ele; - - all_form_ele = top_state->savedData.FormList; - all_form_ele->data_index = hold_form_data_index; - } - - /* - * The master embed index is typically now be back - * to its original value, but might not be if we - * only had to relayout some (not all) of the embeds - * in this subdoc. So, make sure it's set back to - * its original value here. - */ - top_state->embed_count = hold_embed_global_index; - - /* ditto for tag_count */ - top_state->tag_count = original_tag_count; - - /* - * Likewise for the anchor list and image list. - */ - doc_lists->url_list_len = hold_url_list_len; - doc_lists->image_list_count = hold_image_list_count; - doc_lists->applet_list_count = hold_applet_list_count; - doc_lists->embed_list_count = hold_embed_list_count; - top_state->current_layer_num = hold_current_layer_num; - - subdoc = NULL; - cell_ele = NULL; - if ((state != old_state)&& - (state->current_ele != NULL)) - { - lo_DocState *subdoc_state; - int32 dx, dy; - int32 base_x, base_y; - - subdoc = lo_EndCellSubDoc(context, state, - old_state, state->current_ele, TRUE); - state->sub_state = NULL; - state->current_ele = NULL; -/* - if ((state->is_a_subdoc == SUBDOC_CELL)|| - (state->is_a_subdoc == SUBDOC_CAPTION)) - { - if (old_state->subdoc_tags_end != NULL) - { - state->subdoc_tags_end = - old_state->subdoc_tags_end; - } - } -*/ - subdoc_state = (lo_DocState *)(subdoc->state); - cell_ptr->start_in_form = subdoc_state->start_in_form; - cell_ptr->form_id = subdoc_state->form_id; - cell_ptr->form_ele_cnt = subdoc_state->form_ele_cnt; - cell_ptr->form_data_index = subdoc_state->form_data_index; - cell_ptr->embed_count_base = subdoc_state->embed_count_base; - cell_ptr->url_count_base = subdoc_state->url_count_base; - cell_ptr->image_list_count_base = subdoc_state->image_list_count_base; - cell_ptr->applet_list_count_base = subdoc_state->applet_list_count_base; - cell_ptr->embed_list_count_base = subdoc_state->embed_list_count_base; - cell_ptr->current_layer_num_base = subdoc_state->current_layer_num_base; - cell_ptr->must_relayout = subdoc_state->must_relayout_subdoc; - cell_ptr->is_a_subdoc = subdoc_state->is_a_subdoc; - /* - cell_ptr->subdoc_tags = subdoc_state->subdoc_tags; - cell_ptr->subdoc_tags_end = subdoc_state->subdoc_tags_end; - */ - subdoc_state->subdoc_tags = NULL; - subdoc_state->subdoc_tags_end = NULL; - cell_ptr->max_y = subdoc_state->y; - cell_ptr->horiz_alignment = subdoc->horiz_alignment; - cell_ptr->vert_alignment = subdoc->vert_alignment; - - /* - cell_ele = lo_SmallSquishSubDocToCell(context, state, subdoc, - &dx, &dy); - */ - - cell_ele = cell_ptr->cell; - lo_CreateCellFromSubDoc(context, state, subdoc, cell_ele, &dx, &dy); - - lo_cleanup_old_state(subdoc->state); - base_x = cell_ele->x + cell_ele->x_offset + cell_ele->border_width; - base_y = cell_ele->y + cell_ele->y_offset + cell_ele->border_width; - dx -= base_x; - dy -= base_y; - cell_ptr->cell_base_x = dx; - cell_ptr->cell_base_y = dy; - } - - XP_ASSERT ( cell_ele != NULL ); - - old_state->must_relayout_subdoc = FALSE; - - state->top_state->force_reload = save_force; - - /* pop the style stack once to get rid of the extra dummy tag - * that we added to the stack to force styles on the begin - * subdoc in relayout - */ - if (relayout == FALSE) - { - /* LO_PopStyleTagByIndex(context, &state, P_TABLE_DATA, 0); */ - } - - return(cell_ele); -} - -/* - * if normal borders is TRUE draw cell borders if the rest of - * the table has borders. If FALSE, never draw cell borders - */ -void -lo_BeginTableCellAttributes(MWContext *context, - lo_DocState *state, - lo_TableRec *table, - char * colspan_attr, - char * rowspan_attr, - char * nowrap_attr, - char * bgcolor_attr, - char * background_attr, - lo_TileMode tile_mode, - char * valign_attr, - char * halign_attr, - char * width_attr, - char * height_attr, - Bool is_a_header, - Bool normal_borders) -{ - lo_TableRow *table_row; - lo_TableCell *table_cell; - int32 val; -#ifdef LOCAL_DEBUG - fprintf(stderr, "lo_BeginTableCell called\n"); -#endif /* LOCAL_DEBUG */ - - table_row = table->row_ptr; - - table_cell = XP_NEW(lo_TableCell); - if (table_cell == NULL) - { - return; - } - - if (state->is_a_subdoc != SUBDOC_NOT) - { - table_cell->in_nested_table = TRUE; - } - else - { - table_cell->in_nested_table = FALSE; - } - - /* Copied to lo_InitForBeginCell() - table_cell->must_relayout = FALSE; - */ - table_cell->subdoc_tags = NULL; - table_cell->subdoc_tags_end = NULL; - - /* Copied to lo_InitForBeginCell() - table_cell->cell_done = FALSE; - */ - table_cell->nowrap = FALSE; - table_cell->is_a_header = is_a_header; - table_cell->percent_width = 0; - table_cell->percent_height = 0; - table_cell->specified_width = 0; - table_cell->specified_height = 0; - table_cell->min_width = 0; - table_cell->max_width = 0; - table_cell->height = 0; - table_cell->baseline = 0; - table_cell->rowspan = 1; - table_cell->colspan = 1; - table_cell->cell = NULL; - table_cell->next = NULL; - table_cell->beginning_tag_count = state->top_state->tag_count; - - lo_InitForBeginCell( table_row, table_cell ); - - if (table->current_subdoc == NULL) - { - XP_DELETE(table_cell); - return; - } - - if (colspan_attr) - { - val = XP_ATOI(colspan_attr); - if (val < 1) - { - val = 1; - } - /* - * Prevent huge colspan - */ - if (val > TABLE_MAX_COLSPAN) - { - val = TABLE_MAX_COLSPAN; - } - table_cell->colspan = val; - } - - if (rowspan_attr) - { - val = XP_ATOI(rowspan_attr); - if (val < 1) - { - val = 1; - } - /* - * Prevent huge rowspan - */ - if (val > TABLE_MAX_ROWSPAN) - { - val = TABLE_MAX_ROWSPAN; - } - table_cell->rowspan = val; - } - - if (nowrap_attr) - { - table_cell->nowrap = TRUE; - } - - /* Copied to lo_InitForBeginCell() - if (table_row->cell_list == NULL) - { - table_row->cell_list = table_cell; - table_row->cell_ptr = table_cell; - } - else - { - table_row->cell_ptr->next = table_cell; - table_row->cell_ptr = table_cell; - } - */ - - lo_BeginCellSubDoc(context, - state, - table, - bgcolor_attr, - background_attr, - tile_mode, - valign_attr, - halign_attr, - width_attr, - height_attr, - is_a_header, - normal_borders ? table->draw_borders : 0, - FALSE); - - /* - * We added a new state. - */ - lo_PushStateLevel ( context ); -} - - -void -lo_BeginTableCell(MWContext *context, lo_DocState *state, lo_TableRec *table, - PA_Tag *tag, Bool is_a_header) -{ - char *colspan_attr = (char*)lo_FetchParamValue(context, tag, PARAM_COLSPAN); - char *rowspan_attr = (char*)lo_FetchParamValue(context, tag, PARAM_ROWSPAN); - char *nowrap_attr = (char*)lo_FetchParamValue(context, tag, PARAM_NOWRAP); - char *bgcolor_attr = (char*)lo_FetchParamValue(context, tag, PARAM_BGCOLOR); - char *background_attr= (char*)lo_FetchParamValue(context, tag, PARAM_BACKGROUND); - char *valign_attr = (char*)lo_FetchParamValue(context, tag, PARAM_VALIGN); - char *halign_attr = (char*)lo_FetchParamValue(context, tag, PARAM_ALIGN); - char *width_attr = (char*)lo_FetchParamValue(context, tag, PARAM_WIDTH); - char *height_attr = (char*)lo_FetchParamValue(context, tag, PARAM_HEIGHT); - - /* remove the PA_LOCK stuff */ - - lo_BeginTableCellAttributes(context, - state, - table, - colspan_attr, - rowspan_attr, - nowrap_attr, - bgcolor_attr, - background_attr, - LO_TILE_BOTH, /* Default backdrop tile mode */ - valign_attr, - halign_attr, - width_attr, - height_attr, - is_a_header, - TRUE); - - if(colspan_attr) - PA_FREE(colspan_attr); - if(rowspan_attr) - PA_FREE(rowspan_attr); - if(nowrap_attr) - PA_FREE(nowrap_attr); - if(bgcolor_attr) - PA_FREE(bgcolor_attr); - if(background_attr) - PA_FREE(background_attr); - if(valign_attr) - PA_FREE(valign_attr); - if(halign_attr) - PA_FREE(halign_attr); - if(width_attr) - PA_FREE(width_attr); - if(height_attr) - PA_FREE(height_attr); -} - - -void -lo_EndTableCell(MWContext *context, lo_DocState *state, Bool relayout ) -{ - LO_SubDocStruct *subdoc; - LO_CellStruct *cell_ele; - lo_TableRec *table; - lo_TableRow *table_row; - lo_TableCell *table_cell; - lo_table_span *span_rec; - int32 top_inner_pad; - int32 bottom_inner_pad; - int32 left_inner_pad; - int32 right_inner_pad; - int32 i; - lo_TopState *top_state; - lo_DocState *old_state; - int32 doc_id; -#ifdef LOCAL_DEBUG - fprintf(stderr, "lo_EndTableCell called\n"); -#endif /* LOCAL_DEBUG */ - - /* - * makes sure we are at the bottom - * of everything in the document. - */ - if (relayout == FALSE) - { - lo_CloseOutLayout(context, state); - } - else - { - lo_EndLayoutDuringReflow( context, state ); - } - - old_state = state; - /* - * Get the unique document ID, and retrieve this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - state = top_state->doc_state; - - while ((state->sub_state != NULL)&& - (state->sub_state != old_state)) - { - state = state->sub_state; - } - - subdoc = NULL; - cell_ele = NULL; - if ((state != old_state)&& - (state->current_ele != NULL)) - { - subdoc = lo_EndCellSubDoc(context, state, - old_state, state->current_ele, relayout); - state->sub_state = NULL; - state->current_ele = NULL; - if ((state->is_a_subdoc == SUBDOC_CELL)|| - (state->is_a_subdoc == SUBDOC_CAPTION)) - { - if (old_state->subdoc_tags_end != NULL) - { - state->subdoc_tags_end = - old_state->subdoc_tags_end; - } - } - else - { - } - } - - /* - * We popped a state level. - */ - lo_PopStateLevel ( context ); - - table = state->current_table; - table_row = table->row_ptr; - table_cell = table_row->cell_ptr; - - top_inner_pad = FEUNITS_X(table->inner_top_pad, context); - bottom_inner_pad = FEUNITS_X(table->inner_bottom_pad, context); - left_inner_pad = FEUNITS_X(table->inner_left_pad, context); - right_inner_pad = FEUNITS_X(table->inner_right_pad, context); - - if (subdoc != NULL) - { - int32 subdoc_width; - int32 subdoc_height; - int32 min_cellwidth; - int32 base_x, base_y; - int32 dx, dy; - int32 cell_internal_width; - lo_DocState *subdoc_state; - Bool reset_min_width; - - reset_min_width = FALSE; - - cell_internal_width = old_state->max_width; - - /* how big do we think this cell should be? */ - min_cellwidth = old_state->min_width; - - /* - * If the cell is smaller than this, we need to grow it so that - * any internal elements don't overwrite the cell borders. - */ - if (subdoc->width < min_cellwidth) - { - /* - * We need to lay things out again as we now have more space. - * Do we want to be smart and see if we contain things that - * will change? - * Be sure to add in the width of the borders as later code expects it - */ - subdoc->width = min_cellwidth + (2 * subdoc->border_width); - old_state->must_relayout_subdoc = TRUE; - - cell_internal_width = min_cellwidth; - } - - subdoc_width = subdoc->width + - (2 * subdoc->border_horiz_space) + - (left_inner_pad + right_inner_pad); - subdoc_height = subdoc->height + - (2 * subdoc->border_vert_space) + - (top_inner_pad + bottom_inner_pad); - table_cell->max_width = subdoc_width; - table_cell->min_width = old_state->min_width + - (2 * subdoc->border_width) + - (2 * subdoc->border_horiz_space) + - (left_inner_pad + right_inner_pad); - - /* - * This is some nasty logic. We need to reset the min_width - * of the cell in cases where we're certain about how large - * the cell is. - */ - if ( (table_cell->min_width < table_cell->max_width) ) - { - /* - * If we're a fixed width cell and fixed layout (COLS) is on. - * BRAIN DAMAGE: It's arguable that we should always do this - a width for - * the cell was specified, we should respect it. However, certain popular - * sites don't look too good if we do... - */ - if ( (table_cell->specified_width > 0) && - (table_cell->percent_width == 0) && - (table->fixed_cols > 0) ) - { - reset_min_width = TRUE; - } - else - /* - * If we're in a fixed width table who's width does not - * depend on it's parent and are using fixed layout (COLS). - */ - if ( (table->fixed_cols > 0) && - (table->table_width_fixed != FALSE) ) - { - reset_min_width = TRUE; - } - } - - /* - * If nowrap is on or min_width ended up being bigger than - * max_width - */ - if ((table_cell->nowrap != FALSE)|| - (table_cell->min_width > table_cell->max_width)) - { - reset_min_width = TRUE; - } - - if ( reset_min_width != FALSE ) - { - table_cell->min_width = table_cell->max_width; - } - - /* - * If we're in the fixed layout case, then we may need to grow this - * column to fit this new cell width. This will allow any subsequent - * columns to be layed out to the correct size and not have to be - * relayed out. - */ - if ( table->fixed_cols > 0 ) - { - lo_SetDefaultCellWidth( context, table, subdoc, table_cell, cell_internal_width ); - } - - table_cell->height = subdoc_height; - table_cell->baseline = lo_GetSubDocBaseline(subdoc); - - subdoc_state = (lo_DocState *)(subdoc->state); - table_cell->start_in_form = subdoc_state->start_in_form; - table_cell->form_id = subdoc_state->form_id; - table_cell->form_ele_cnt = subdoc_state->form_ele_cnt; - table_cell->form_data_index = subdoc_state->form_data_index; - table_cell->embed_count_base = subdoc_state->embed_count_base; - table_cell->url_count_base = subdoc_state->url_count_base; - table_cell->image_list_count_base = subdoc_state->image_list_count_base; - table_cell->applet_list_count_base = subdoc_state->applet_list_count_base; - table_cell->embed_list_count_base = subdoc_state->embed_list_count_base; - - table_cell->current_layer_num_base = subdoc_state->current_layer_num_base; - table_cell->must_relayout = subdoc_state->must_relayout_subdoc; - table_cell->is_a_subdoc = subdoc_state->is_a_subdoc; - if (relayout == FALSE) - { - table_cell->subdoc_tags = subdoc_state->subdoc_tags; - table_cell->subdoc_tags_end = subdoc_state->subdoc_tags_end; - } - subdoc_state->subdoc_tags = NULL; - subdoc_state->subdoc_tags_end = NULL; - table_cell->max_y = subdoc_state->y; - table_cell->horiz_alignment = subdoc->horiz_alignment; - table_cell->vert_alignment = subdoc->vert_alignment; - - if (relayout == FALSE) - { - cell_ele = lo_SmallSquishSubDocToCell(context, state, subdoc, - &dx, &dy); - /* Keep ptr. back to table state structs for relayout */ - cell_ele->table_cell = table_cell; - cell_ele->table_row = table_row; - cell_ele->table = table; - } - else - { - cell_ele = table_cell->cell; - lo_CreateCellFromSubDoc(context, state, subdoc, cell_ele, &dx, &dy); - } - - lo_cleanup_old_state(subdoc->state); - base_x = cell_ele->x + cell_ele->x_offset + cell_ele->border_width; - base_y = cell_ele->y + cell_ele->y_offset + cell_ele->border_width; - dx -= base_x; - dy -= base_y; - table_cell->cell_base_x = dx; - table_cell->cell_base_y = dy; - } - - table_cell->cell = cell_ele; - table_cell->cell_done = TRUE; - - i = 0; - while (i < table_cell->colspan) - { - - if ((table->width_spans == NULL)|| - ((table->width_span_ptr != NULL)&& - (table->width_span_ptr->next == NULL))) - { - span_rec = XP_NEW(lo_table_span); - if (span_rec == NULL) - { - return; - } - span_rec->dim = 1; - span_rec->min_dim = 1; - span_rec->span = 0; - span_rec->next = NULL; - - if (table->width_spans == NULL) - { - table->width_spans = span_rec; - table->width_span_ptr = span_rec; - } - else - { - table->width_span_ptr->next = span_rec; - table->width_span_ptr = span_rec; - } - } - else - { - if (table->width_span_ptr == NULL) - { - table->width_span_ptr = table->width_spans; - } - else - { - table->width_span_ptr = - table->width_span_ptr->next; - } - span_rec = table->width_span_ptr; - } - - if (span_rec->span > 0) - { - span_rec->span--; - table_row->cells++; - - /* - * This only happens if a colspan on this - * row overlaps a rowspan from a previous row. - */ - if (i > 0) - { - int32 new_span; - - new_span = table_cell->rowspan - 1; - if (new_span > span_rec->span) - { - span_rec->span = new_span; - } - i++; - /* - * Don't count this cell twice. - */ - table_row->cells--; - } - continue; - } - else - { - span_rec->span = table_cell->rowspan - 1; - i++; - if (table_cell->colspan == 1) - { - if (table_cell->max_width > span_rec->dim) - { - span_rec->dim = table_cell->max_width; - } - if (table_cell->min_width > span_rec->min_dim) - { - span_rec->min_dim = table_cell->min_width; - } - } - } - } - - span_rec = table->height_span_ptr; - if (table_cell->rowspan == 1) - { - int32 tmp_val; - - /* - * If the user specified a height for the cell, - * that becomes our min height. - */ - if ((table_cell->specified_height > 0)&& - (table_cell->specified_height > span_rec->min_dim)) - { - span_rec->min_dim = table_cell->specified_height; - } - - tmp_val = table_cell->baseline - span_rec->min_dim; - if (tmp_val > 0) - { - span_rec->min_dim += tmp_val; - if (table_row->vert_alignment == LO_ALIGN_BASELINE) - { - span_rec->dim += tmp_val; - } - } - - if (table_row->vert_alignment == LO_ALIGN_BASELINE) - { - tmp_val = (table_cell->height - table_cell->baseline) - - (span_rec->dim - span_rec->min_dim); - if (tmp_val > 0) - { - span_rec->dim += tmp_val; - } - } - else - { - if (table_cell->height > span_rec->dim) - { - span_rec->dim = table_cell->height; - } - } - } - - table_row->cells += table_cell->colspan; -} - - -void -lo_BeginTableCaption(MWContext *context, lo_DocState *state, lo_TableRec *table, - PA_Tag *tag) -{ - lo_TableCaption *caption; - PA_Block buff; - char *str; - - caption = XP_NEW_ZAP(lo_TableCaption); - if (caption == NULL) - { - return; - } - - caption->vert_alignment = LO_ALIGN_TOP; - caption->horiz_alignment = LO_ALIGN_CENTER; - caption->min_width = 0; - caption->max_width = 0; - caption->height = 0; - caption->subdoc = NULL; - caption->cell_ele = NULL; - - /* - * Check for an align parameter - */ - buff = lo_FetchParamValue(context, tag, PARAM_ALIGN); - if (buff != NULL) - { - PA_LOCK(str, char *, buff); - if (pa_TagEqual("bottom", str)) - { - caption->vert_alignment = LO_ALIGN_BOTTOM; - } - PA_UNLOCK(buff); - PA_FREE(buff); - } - - table->caption = caption; - - lo_BeginCaptionSubDoc(context, state, caption, tag); -} - - -void -lo_EndTableCaption(MWContext *context, lo_DocState *state) -{ - LO_SubDocStruct *subdoc; - lo_TableRec *table; - lo_TableCaption *caption; - lo_TopState *top_state; - lo_DocState *old_state; - int32 doc_id; - int32 top_inner_pad; - int32 bottom_inner_pad; - int32 left_inner_pad; - int32 right_inner_pad; - - /* - * makes sure we are at the bottom - * of everything in the document. - */ - lo_CloseOutLayout(context, state); - - old_state = state; - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - state = top_state->doc_state; - - while ((state->sub_state != NULL)&& - (state->sub_state != old_state)) - { - state = state->sub_state; - } - - subdoc = NULL; - if ((state != old_state)&& - (state->current_ele != NULL)) - { - subdoc = lo_EndCellSubDoc(context, state, - old_state, state->current_ele, FALSE); - state->sub_state = NULL; - state->current_ele = NULL; - if ((state->is_a_subdoc == SUBDOC_CELL)|| - (state->is_a_subdoc == SUBDOC_CAPTION)) - { - if (old_state->subdoc_tags_end != NULL) - { - state->subdoc_tags_end = - old_state->subdoc_tags_end; - } - } - } - - table = state->current_table; - caption = table->caption; - - top_inner_pad = FEUNITS_X(table->inner_top_pad, context); - bottom_inner_pad = FEUNITS_X(table->inner_bottom_pad, context); - left_inner_pad = FEUNITS_X(table->inner_left_pad, context); - right_inner_pad = FEUNITS_X(table->inner_right_pad, context); - - if (subdoc != NULL) - { - int32 subdoc_width; - int32 subdoc_height; - - subdoc_width = subdoc->width + - (2 * subdoc->border_horiz_space) + - (left_inner_pad + right_inner_pad); - subdoc_height = subdoc->height + - (2 * subdoc->border_vert_space) + - (top_inner_pad + bottom_inner_pad); - caption->max_width = subdoc_width; - caption->min_width = old_state->min_width + - (2 * subdoc->border_width) + - (2 * subdoc->border_horiz_space) + - (left_inner_pad + right_inner_pad); - if (caption->min_width > caption->max_width) - { - caption->min_width = caption->max_width; - } - caption->height = subdoc_height; - } - - caption->subdoc = subdoc; - - /* If the caption is empty, free the memory used by it */ - if (lo_subdoc_has_elements(caption->subdoc->state) == FALSE) - { - lo_FreeTableCaption( context, state, table ); - } - - /* - * We popped a state level. - */ - lo_PopStateLevel ( context ); -} - - -void -lo_BeginTableRowAttributes(MWContext *context, - lo_DocState *state, - lo_TableRec *table, - char *bgcolor_attr, - char *background_attr, - char *valign_attr, - char *halign_attr) -{ - lo_TableRow *table_row; - lo_table_span *span_rec; - char *bgcolor_from_style=NULL; -#ifdef LOCAL_DEBUG - fprintf(stderr, "lo_BeginTableRow called\n"); -#endif /* LOCAL_DEBUG */ - - table_row = XP_NEW(lo_TableRow); - if (table_row == NULL) - { - return; - } - -#if DOM - /* - * need to make lo_TableRow have a DOM_Node at the same place as all - * the LO_Elements. - */ - lo_SetNodeElement(state, (LO_Element *)table_row); -#endif - - /* copied to lo_UpdateTableStateForBeginRow() - table_row->row_done = FALSE; - */ - table_row->has_percent_width_cells = FALSE; - table_row->backdrop.bg_color = NULL; - table_row->backdrop.url = NULL; - table_row->backdrop.tile_mode = LO_TILE_BOTH; - /* copied to lo_UpdateTableStateForBeginRow() - table_row->cells = 0; - */ - table_row->vert_alignment = LO_ALIGN_DEFAULT; - table_row->horiz_alignment = LO_ALIGN_DEFAULT; - - /* copied to lo_UpdateTableStateForBeginRow() - table_row->cell_list = NULL; - table_row->cell_ptr = NULL; - */ - table_row->next = NULL; - - - lo_UpdateTableStateForBeginRow( table, table_row ); - - /* check for style sheet color and override if necessary */ - if(state->top_state && state->top_state->style_stack) - { - StyleStruct *style_struct; - - style_struct = STYLESTACK_GetStyleByIndex( - state->top_state->style_stack, - 0); - - if(style_struct) - { - bgcolor_from_style = STYLESTRUCT_GetString(style_struct, BG_COLOR_STYLE); - - if(bgcolor_from_style) - { - bgcolor_attr = bgcolor_from_style; - } - } - } - - /* - * Check for a background color attribute - */ - if (bgcolor_attr) - { - uint8 red, green, blue; - XP_Bool rv; - - if(bgcolor_from_style) - rv = LO_ParseStyleSheetRGB(bgcolor_attr, &red, &green, &blue); - else - rv = LO_ParseRGB(bgcolor_attr, &red, &green, &blue); - - if(rv) - { - table_row->backdrop.bg_color = XP_NEW(LO_Color); - if (table_row->backdrop.bg_color != NULL) - { - table_row->backdrop.bg_color->red = red; - table_row->backdrop.bg_color->green = green; - table_row->backdrop.bg_color->blue = blue; - } - } - } - - if (background_attr) - table_row->backdrop.url = XP_STRDUP(background_attr); - - XP_FREEIF(bgcolor_from_style); - - - /* - * Check for a vertical align parameter - */ - if (valign_attr) - { - table_row->vert_alignment = lo_EvalVAlignParam(valign_attr); - } - - /* - * Check for a horizontal align parameter - */ - if (halign_attr) - { - table_row->horiz_alignment = lo_EvalCellAlignParam(halign_attr); - } - - - if (table->row_list == NULL) - { - table->row_list = table_row; - table->row_ptr = table_row; - } - else - { - table->row_ptr->next = table_row; - table->row_ptr = table_row; - } - - /* copied to lo_UpdateTableStateForBeginRow() - table->width_span_ptr = NULL; - */ - - span_rec = XP_NEW(lo_table_span); - if (span_rec == NULL) - { - return; - } - - if (table->height_spans == NULL) - { - table->height_spans = span_rec; - table->height_span_ptr = span_rec; - } - else - { - table->height_span_ptr->next = span_rec; - table->height_span_ptr = span_rec; - } - - 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; - span_rec->next = NULL; -} - - -void -lo_BeginTableRow(MWContext *context, lo_DocState *state, lo_TableRec *table, - PA_Tag *tag) -{ - char *bgcolor_attr = (char*)lo_FetchParamValue(context, tag, PARAM_BGCOLOR); - char *background_attr = (char*)lo_FetchParamValue(context, tag, PARAM_BACKGROUND); - char *valign_attr = (char*)lo_FetchParamValue(context, tag, PARAM_VALIGN); - char *halign_attr = (char*)lo_FetchParamValue(context, tag, PARAM_ALIGN); - - /* remove the PA_LOCK stuff */ - - lo_BeginTableRowAttributes(context, - state, - table, - bgcolor_attr, - background_attr, - valign_attr, - halign_attr); - - if(bgcolor_attr) - PA_FREE(bgcolor_attr); - if(valign_attr) - PA_FREE(valign_attr); - if(halign_attr) - PA_FREE(halign_attr); -} - - -void -lo_EndTableRow(MWContext *context, lo_DocState *state, lo_TableRec *table) -{ - lo_TableRow *table_row; -#ifdef LOCAL_DEBUG - fprintf(stderr, "lo_EndTableRow called\n"); -#endif /* LOCAL_DEBUG */ - - table_row = table->row_ptr; - table_row->row_done = TRUE; - table->rows++; - - while (table->width_span_ptr != NULL) - { - table->width_span_ptr = table->width_span_ptr->next; - if (table->width_span_ptr != NULL) - { - table->width_span_ptr->span--; - table_row->cells++; - } - } - - if (table_row->cells > table->cols) - { - table->cols = table_row->cells; - } - - /* - * We've hit the end of a row, if it's the first row and - * we haven't allocated all columns yet and table width - * is remaining, then set their size now. - */ - if ( table->fixed_width_remaining > 0 ) - { - if ( (table_row->cells < table->fixed_cols) && (table->fixed_col_widths != NULL) ) - { - int32 count; - int32 colwidth; - int32 cell_extra_space; - int32 left_inner_pad; - int32 right_inner_pad; - - /* how much border/pad space do we need per cell */ - if (table->draw_borders == TABLE_BORDERS_OFF) - { - cell_extra_space = 2 * TABLE_DEF_CELL_BORDER; - } - else if (table->draw_borders == TABLE_BORDERS_ON) - { - cell_extra_space = 2 * TABLE_DEF_CELL_BORDER; - } - else - { - cell_extra_space = 0; - } - - left_inner_pad = FEUNITS_X(table->inner_left_pad, context); - right_inner_pad = FEUNITS_X(table->inner_right_pad, context); - cell_extra_space += left_inner_pad + right_inner_pad; - - /* divide space up to the remaining cols */ - colwidth = ( table->fixed_width_remaining / - ( table->fixed_cols - table_row->cells )) - cell_extra_space; - - if ( colwidth < 0 ) - { - colwidth = 0; - } - - for ( count = table_row->cells; count < table->fixed_cols; ++count ) - { - table->fixed_col_widths[ count ] = colwidth; - table->fixed_width_remaining -= colwidth; - } - - /* add any leftover space to the last row */ - table->fixed_col_widths[ table->fixed_cols - 1 ] += - table->fixed_width_remaining; - } - table->fixed_width_remaining = 0; - } -} - -void -lo_BeginTableAttributes(MWContext *context, - lo_DocState *state, - char *align_attr, - char *border_attr, - char *border_top_attr, - char *border_bottom_attr, - char *border_left_attr, - char *border_right_attr, - char *border_color_attr, - char *border_style_attr, - char *vspace_attr, - char *hspace_attr, - char *bgcolor_attr, - char *background_attr, - char *width_attr, - char *height_attr, - char *cellpad_attr, - char *toppad_attr, - char *bottompad_attr, - char *leftpad_attr, - char *rightpad_attr, - char *cellspace_attr, - char *cols_attr) -{ - lo_TableRec *table; - LO_TableStruct *table_ele; - int32 val; - char *bgcolor_from_style = NULL; - Bool allow_percent_width; - Bool allow_percent_height; -#ifdef LOCAL_DEBUG - fprintf(stderr, "lo_BeginTable called\n"); -#endif /* LOCAL_DEBUG */ - - if (state == NULL) - { - return; - } - - /* Increment table nesting level (used for passing into lo_CreateCellBackGroundLayer() */ - state->top_state->table_nesting_level++; - - table_ele = (LO_TableStruct *)lo_NewElement(context, state, LO_TABLE, NULL, 0); - if (table_ele == NULL) - { - state->top_state->out_of_memory = TRUE; - return; - } - - if (state->top_state->table_nesting_level == 1) - TIMING_STARTCLOCK_OBJECT("lo:blk-tab", table_ele); - - table_ele->type = LO_TABLE; - /* Copied into lo_PositionTableElement() */ - /* - table_ele->ele_id = NEXT_ELEMENT; - table_ele->x = state->x; - table_ele->x_offset = 0; - table_ele->y = state->y; - table_ele->y_offset = 0; - table_ele->width = 0; - table_ele->height = 0; - table_ele->line_height = 0; - */ - - table_ele->FE_Data = NULL; - table_ele->anchor_href = state->current_anchor; - -#if DOM - lo_SetNodeElement(state, (LO_Element *)table_ele); -#endif - - /* - * Default to the current alignment - */ - if ( state->align_stack != NULL ) - { - table_ele->alignment = state->align_stack->alignment; - } - else - { - table_ele->alignment = LO_ALIGN_LEFT; - } - - table_ele->border_width = TABLE_DEF_BORDER; - table_ele->border_top_width = TABLE_DEF_BORDER; - table_ele->border_bottom_width = TABLE_DEF_BORDER; - table_ele->border_left_width = TABLE_DEF_BORDER; - table_ele->border_right_width = TABLE_DEF_BORDER; - table_ele->border_style = TABLE_DEF_BORDER_STYLE; - - table_ele->border_vert_space = TABLE_DEF_VERTICAL_SPACE; - table_ele->border_horiz_space = TABLE_DEF_HORIZONTAL_SPACE; - - table_ele->border_color.red = 0; - table_ele->border_color.green = 0; - table_ele->border_color.blue = 0; - - table_ele->ele_attrmask = 0; - - table_ele->sel_start = -1; - table_ele->sel_end = -1; - - /* Copied into lo_PositionTableElement() */ - /* - table_ele->next = NULL; - table_ele->prev = NULL; - */ - - /* - * Check for an align parameter - */ - if (align_attr) - { - Bool floating; - - floating = FALSE; - table_ele->alignment = lo_EvalAlignParam(align_attr, &floating); - /* - * Only allow left and right (floating) and center. - */ - if (floating != FALSE) - { - table_ele->ele_attrmask |= LO_ELE_FLOATING; - } - else - { - /* - * Tables can be left, center, right, justify or char alignment. - * We only do left, center and right. True left and right will - * hit the floating case above. So, we set all alignments to - * be either center or left. - */ - switch ( table_ele->alignment ) - { - case LO_ALIGN_LEFT: - case LO_ALIGN_RIGHT: - case LO_ALIGN_CENTER: - break; - - case LO_ALIGN_NCSA_CENTER: - table_ele->alignment = LO_ALIGN_CENTER; - break; - - default: - table_ele->alignment = LO_ALIGN_LEFT; - break; - } - } - } - - lo_PositionTableElement(state, table_ele); - - /* - * Push our alignment state if we're not floating - */ - - /* Copied into lo_PositionTableElement() */ - /* - if ( !(table_ele->ele_attrmask & LO_ELE_FLOATING) ) - { - lo_PushAlignment(state, P_TABLE_DATA, table_ele->alignment); - } - */ - - /* - * Get the border parameter. - */ - if (border_attr) - { - val = XP_ATOI(border_attr); - if ((val == 0)&&(*border_attr == '0')) - { - val = -1; - } - else if (val < 1) - { - val = 1; - } - table_ele->border_width = val; - table_ele->border_top_width = val; - table_ele->border_bottom_width = val; - table_ele->border_left_width = val; - table_ele->border_right_width = val; - } - table_ele->border_width = FEUNITS_X(table_ele->border_width, context); - - /* - * Get the top border parameter. - */ - if (border_top_attr) - { - val = XP_ATOI(border_top_attr); - if ((val == 0)&&(*border_top_attr == '0')) - { - val = -1; - } - else if (val < 1) - { - val = 1; - } - table_ele->border_top_width = val; - } - table_ele->border_top_width = FEUNITS_Y(table_ele->border_top_width, context); - - /* - * Get the bottom border parameter. - */ - if (border_bottom_attr) - { - val = XP_ATOI(border_bottom_attr); - if ((val == 0)&&(*border_bottom_attr == '0')) - { - val = -1; - } - else if (val < 1) - { - val = 1; - } - table_ele->border_bottom_width = val; - } - table_ele->border_bottom_width = FEUNITS_Y(table_ele->border_bottom_width, context); - - /* - * Get the left border parameter. - */ - if (border_left_attr) - { - val = XP_ATOI(border_left_attr); - if ((val == 0)&&(*border_left_attr == '0')) - { - val = -1; - } - else if (val < 1) - { - val = 1; - } - table_ele->border_left_width = val; - } - table_ele->border_left_width = FEUNITS_X(table_ele->border_left_width, context); - - /* - * Get the right border parameter. - */ - if (border_right_attr) - { - val = XP_ATOI(border_right_attr); - if ((val == 0)&&(*border_right_attr == '0')) - { - val = -1; - } - else if (val < 1) - { - val = 1; - } - table_ele->border_right_width = val; - } - table_ele->border_right_width = FEUNITS_X(table_ele->border_right_width, context); - - /* - * Get the border style parameter. - */ - if (border_style_attr) - { - int32 border_style; - - border_style = BORDER_OUTSET; - if ( pa_TagEqual("none", border_style_attr) ) - { - border_style = BORDER_NONE; - } - else if ( pa_TagEqual("dotted", border_style_attr) ) - { - border_style = BORDER_DOTTED; - } - else if ( pa_TagEqual("dashed", border_style_attr) ) - { - border_style = BORDER_DASHED; - } - else if ( pa_TagEqual("solid", border_style_attr) ) - { - border_style = BORDER_SOLID; - } - else if ( pa_TagEqual("double", border_style_attr) ) - { - border_style = BORDER_DOUBLE; - } - else if ( pa_TagEqual("groove", border_style_attr) ) - { - border_style = BORDER_GROOVE; - } - else if ( pa_TagEqual("ridge", border_style_attr) ) - { - border_style = BORDER_RIDGE; - } - else if ( pa_TagEqual("inset", border_style_attr) ) - { - border_style = BORDER_INSET; - } - else if ( pa_TagEqual("outset", border_style_attr) ) - { - border_style = BORDER_OUTSET; - } - - table_ele->border_style = border_style; - } - - /* - * Get the border color parameter. - */ - if (border_color_attr) - { - uint8 red, green, blue; - - LO_ParseStyleSheetRGB(border_color_attr, &red, &green, &blue); - table_ele->border_color.red = red; - table_ele->border_color.green = green; - table_ele->border_color.blue = blue; - } - - /* - * Get the extra vertical space parameter. - */ - if (vspace_attr) - { - val = XP_ATOI(vspace_attr); - if (val < 0) - { - val = 0; - } - table_ele->border_vert_space = val; - } - table_ele->border_vert_space = FEUNITS_Y(table_ele->border_vert_space, - context); - - /* - * Get the extra horizontal space parameter. - */ - if (hspace_attr) - { - val = XP_ATOI(hspace_attr); - if (val < 0) - { - val = 0; - } - table_ele->border_horiz_space = val; - } - table_ele->border_horiz_space = FEUNITS_X(table_ele->border_horiz_space, - context); - - table = XP_NEW(lo_TableRec); - - /* Keep ptr to table state structure. Will be needed during relayout */ - table_ele->table = table; - - if (table == NULL) - { - return; - } - - if(table_ele->border_top_width < 0) - table_ele->border_top_width = 0; - if(table_ele->border_bottom_width < 0) - table_ele->border_bottom_width = 0; - if(table_ele->border_right_width < 0) - table_ele->border_right_width = 0; - if(table_ele->border_left_width < 0) - table_ele->border_left_width = 0; - - if(table_ele->border_width < 0) - { - /* backwards compatibility */ - table->draw_borders = TABLE_BORDERS_GONE; - table_ele->border_width = 0; - table_ele->border_top_width = 0; - table_ele->border_bottom_width = 0; - table_ele->border_right_width = 0; - table_ele->border_left_width = 0; - } - else if (table_ele->border_top_width == 0 - && table_ele->border_bottom_width == 0 - && table_ele->border_left_width == 0 - && table_ele->border_right_width == 0) - { - table->draw_borders = TABLE_BORDERS_OFF; - } - else - { - table->draw_borders = TABLE_BORDERS_ON; - } - table->has_percent_width_cells = FALSE; - table->has_percent_height_cells = FALSE; - table->backdrop.bg_color = NULL; - table->backdrop.url = NULL; - table->backdrop.tile_mode = LO_TILE_BOTH; - - /* Copied to lo_InitTableRecord() */ - /* - table->rows = 0; - table->cols = 0; - */ - - table->width_spans = NULL; - table->width_span_ptr = NULL; - table->height_spans = NULL; - /* Copied to lo_InitTableRecord() - table->height_span_ptr = NULL; - */ - table->caption = NULL; - table->table_ele = table_ele; - table->current_subdoc = NULL; - table->row_list = NULL; - table->row_ptr = NULL; - table->width = 0; - table->height = 0; - - lo_InitTableRecord( table ); - - /* - * Percent width, height added for relayout - */ - table->percent_width = 0; - table->percent_height = 0; - - table->inner_top_pad = TABLE_DEF_INNER_CELL_PAD; - table->inner_bottom_pad = TABLE_DEF_INNER_CELL_PAD; - table->inner_left_pad = TABLE_DEF_INNER_CELL_PAD; - table->inner_right_pad = TABLE_DEF_INNER_CELL_PAD; - table->inter_cell_pad = TABLE_DEF_INTER_CELL_PAD; - - table->current_subdoc = (LO_SubDocStruct *)lo_NewElement(context, state, LO_SUBDOC, NULL, 0); - table->current_subdoc->type = LO_SUBDOC; - - table->current_subdoc->backdrop.bg_color = NULL; - table->current_subdoc->backdrop.url = NULL; - table->current_subdoc->backdrop.tile_mode = LO_TILE_BOTH; - table->current_subdoc->state = lo_NewLayout(context, - state->win_width, state->win_height, 0, 0, NULL); - - table->default_cell_width = 0; - table->fixed_width_remaining = 0; - table->fixed_col_widths = NULL; - table->table_width_fixed = FALSE; - table->fixed_cols = 0; - - /* - * You can't do percentage widths if the parent's - * width is still undecided. - */ - allow_percent_width = TRUE; - allow_percent_height = TRUE; - if ((state->is_a_subdoc == SUBDOC_CELL)|| - (state->is_a_subdoc == SUBDOC_CAPTION)) - { - lo_TopState *top_state; - lo_DocState *new_state; - int32 doc_id; - - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - new_state = top_state->doc_state; - - while ((new_state->sub_state != NULL)&& - (new_state->sub_state != state)) - { - new_state = new_state->sub_state; - } - - if ((new_state->sub_state == state)&& - (new_state->current_ele != NULL)) - { - LO_SubDocStruct *subdoc; - - subdoc = (LO_SubDocStruct *)new_state->current_ele; - if (subdoc->width == 0) - { - allow_percent_width = FALSE; -#ifdef LOCAL_DEBUG - fprintf(stderr, "Percent width not allowed in this subdoc!\n"); -#endif /* LOCAL_DEBUG */ - } - else - { -#ifdef LOCAL_DEBUG - fprintf(stderr, "Percent width IS allowed in this subdoc!\n"); -#endif /* LOCAL_DEBUG */ - } - if (subdoc->height == 0) - { - allow_percent_height = FALSE; - } - } - } - - - /* check for style sheet color and override if necessary */ - if(state->top_state && state->top_state->style_stack) - { - StyleStruct *style_struct; - - style_struct = STYLESTACK_GetStyleByIndex( - state->top_state->style_stack, - 0); - - if(style_struct) - { - bgcolor_from_style = STYLESTRUCT_GetString(style_struct, BG_COLOR_STYLE); - - if(bgcolor_from_style) - { - bgcolor_attr = bgcolor_from_style; - } - } - } - - /* - * Check for a background color attribute - */ - if (bgcolor_attr) - { - uint8 red, green, blue; - XP_Bool rv; - - if(bgcolor_from_style) - rv = LO_ParseStyleSheetRGB(bgcolor_attr, &red, &green, &blue); - else - rv = LO_ParseRGB(bgcolor_attr, &red, &green, &blue); - if(rv) - { - table->backdrop.bg_color = XP_NEW(LO_Color); - if (table->backdrop.bg_color != NULL) - { - table->backdrop.bg_color->red = red; - table->backdrop.bg_color->green = green; - table->backdrop.bg_color->blue = blue; - } - } - } - - if (background_attr) - table->backdrop.url = XP_STRDUP(background_attr); - XP_FREEIF(bgcolor_from_style); - - - /* - * Get the width and height parameters, in absolute or percentage. - * If percentage, make it absolute. - */ - if (width_attr) - { - Bool is_percent; - - val = lo_ValueOrPercent(width_attr, &is_percent); - if (is_percent != FALSE) - { - table->percent_width = val; - /* - if (allow_percent_width == FALSE) - { - val = 0; - } - else - { - val = (state->win_width - state->win_left - - state->win_right) * val / 100; - } - */ - - } - else - { - table->percent_width = 0; - table->table_width_fixed = TRUE; - val = FEUNITS_X(val, context); - } - if (val < 0) - { - val = 0; - } - table->width = val; - } - - if (height_attr) - { - Bool is_percent; - - val = lo_ValueOrPercent(height_attr, &is_percent); - if (is_percent != FALSE) - { - table->percent_height = val; - /* - if (allow_percent_height == FALSE) - { - val = 0; - } - else - { - val = (state->win_height - state->win_top - - state->win_bottom) * val / 100; - } - */ - } - else - { - table->percent_height = 0; - val = FEUNITS_X(val, context); - } - if (val < 0) - { - val = 0; - } - table->height = val; - } - - lo_SetTableDimensions(state, table, allow_percent_width, allow_percent_height); - - if (cellpad_attr) - { - val = XP_ATOI(cellpad_attr); - if (val < 0) - { - val = 0; - } - /* set all our pads to this value */ - table->inner_top_pad = val; - table->inner_bottom_pad = val; - table->inner_left_pad = val; - table->inner_right_pad = val; - } - - if (toppad_attr) - { - val = XP_ATOI(toppad_attr); - if (val < 0) - { - val = 0; - } - table->inner_top_pad = val; - } - - if (bottompad_attr) - { - val = XP_ATOI(bottompad_attr); - if (val < 0) - { - val = 0; - } - table->inner_bottom_pad = val; - } - - if (leftpad_attr) - { - val = XP_ATOI(leftpad_attr); - if (val < 0) - { - val = 0; - } - table->inner_left_pad = val; - } - - if (rightpad_attr) - { - val = XP_ATOI(rightpad_attr); - if (val < 0) - { - val = 0; - } - table->inner_right_pad = val; - } - - if (cellspace_attr) - { - val = XP_ATOI(cellspace_attr); - if (val < 0) - { - val = 0; - } - table->inter_cell_pad = val; - } - - /* - * Get the COLS parameter. - */ - if (cols_attr) - { - val = XP_ATOI(cols_attr); - if (val < 0) - { - val = 0; - } - table_ele->border_horiz_space = val; - - /* - * If we have a specified number of columns, then - * we first need to make sure we have a real table - * width and then compute our default column width. - */ - table->fixed_cols = val; - if ( val > 0 ) - { - - /* Copied to lo_CalcFixedColWidths() */ - /* - int32 count; - int32 table_width; - - table->fixed_cols = val; - - table_width = lo_ComputeInternalTableWidth ( context, table, state ); - */ - - /* Split the space up evenly */ - /* - table->default_cell_width = table_width / val; - */ - - /* and we have all the table width left to play with */ - /* - table->fixed_width_remaining = table_width; - */ - - /* allocate and initialize our width array */ - table->fixed_col_widths = XP_ALLOC(val * sizeof(int32)); - if (table->fixed_col_widths == NULL) - { - state->top_state->out_of_memory = TRUE; - table->fixed_cols = 0; - table->default_cell_width = 0; - return; - } - - - /* - for ( count = 0; count < val; ++count ) - { - table->fixed_col_widths[ count ] = 0; - } - */ - - lo_CalcFixedColWidths( context, state, table ); - } - } - - /* Copied to lo_UpdateStateAfterBeginTable() */ - /* - state->current_table = table; - */ - - lo_UpdateStateAfterBeginTable( state, table ); -} - - -/* - * Preparse the tag attributes and call the real begin table - */ -void -lo_BeginTable(MWContext *context, lo_DocState *state, PA_Tag *tag) -{ - - /* style sheets variables */ - StyleStruct *style_struct=NULL; - SS_Number *top_padding, *bottom_padding, *left_padding, *right_padding; - - char *align_attr = (char*)lo_FetchParamValue(context, tag, PARAM_ALIGN); - char *border_attr = (char*)lo_FetchParamValue(context, tag, PARAM_BORDER); - char *border_top_attr = NULL; - char *border_bottom_attr = NULL; - char *border_left_attr = NULL; - char *border_right_attr = NULL; - char *border_color_attr = (char*)lo_FetchParamValue(context, tag, PARAM_BORDERCOLOR); - char *border_style_attr = NULL; - char *vspace_attr = (char*)lo_FetchParamValue(context, tag, PARAM_VSPACE); - char *hspace_attr = (char*)lo_FetchParamValue(context, tag, PARAM_HSPACE); - char *bgcolor_attr = (char*)lo_FetchParamValue(context, tag, PARAM_BGCOLOR); - char *background_attr = (char*)lo_FetchParamValue(context, tag, PARAM_BACKGROUND); - char *width_attr = (char*)lo_FetchParamValue(context, tag, PARAM_WIDTH); - char *height_attr = (char*)lo_FetchParamValue(context, tag, PARAM_HEIGHT); - char *cellpad_attr = (char*)lo_FetchParamValue(context, tag, PARAM_CELLPAD); - char *toppad_attr = (char*)lo_FetchParamValue(context, tag, PARAM_TOPPAD); - char *bottompad_attr = (char*)lo_FetchParamValue(context, tag, PARAM_BOTTOMPAD); - char *leftpad_attr = (char*)lo_FetchParamValue(context, tag, PARAM_LEFTPAD); - char *rightpad_attr = (char*)lo_FetchParamValue(context, tag, PARAM_RIGHTPAD); - char *cellspace_attr = (char*)lo_FetchParamValue(context, tag, PARAM_CELLSPACE); - char *cols_attr = (char*)lo_FetchParamValue(context, tag, PARAM_COLS); - - if(!border_style_attr) - { - border_style_attr = XP_STRDUP("outset"); - } - - if(!border_color_attr) - { - XP_ASSERT(state); - if(state) - border_color_attr = PR_smprintf("#%2x%2x%2x", - state->text_bg.red, - state->text_bg.green, - state->text_bg.blue); - } - - if(state->top_state->style_stack) - style_struct = STYLESTACK_GetStyleByIndex(state->top_state->style_stack, 0); - - if(style_struct) - { - left_padding = STYLESTRUCT_GetNumber(style_struct, LEFTPADDING_STYLE); - if(left_padding) - { - LO_AdjustSSUnits(left_padding, LEFTPADDING_STYLE, context, state); - XP_FREEIF(leftpad_attr); - leftpad_attr = PR_smprintf("%ld", (int32)left_padding->value); - } - - right_padding = STYLESTRUCT_GetNumber(style_struct, RIGHTPADDING_STYLE); - if(right_padding) - { - LO_AdjustSSUnits(right_padding, RIGHTPADDING_STYLE, context, state); - XP_FREEIF(rightpad_attr); - rightpad_attr = PR_smprintf("%ld", (int32)right_padding->value); - } - - top_padding = STYLESTRUCT_GetNumber(style_struct, TOPPADDING_STYLE); - if(top_padding) - { - LO_AdjustSSUnits(top_padding, TOPPADDING_STYLE, context, state); - XP_FREEIF(toppad_attr); - toppad_attr = PR_smprintf("%ld", (int32)top_padding->value); - } - - bottom_padding = STYLESTRUCT_GetNumber(style_struct, BOTTOMPADDING_STYLE); - if(bottom_padding) - { - LO_AdjustSSUnits(bottom_padding, BOTTOMPADDING_STYLE, context, state); - XP_FREEIF(bottompad_attr); - bottompad_attr = PR_smprintf("%ld", (int32)bottom_padding->value); - } - } - - /* remove the PA_LOCK stuff, it does nothing anyways */ - - lo_BeginTableAttributes(context, - state, - align_attr, - border_attr, - border_top_attr, - border_bottom_attr, - border_left_attr, - border_right_attr, - border_color_attr, - border_style_attr, - vspace_attr, - hspace_attr, - bgcolor_attr, - background_attr, - width_attr, - height_attr, - cellpad_attr, - toppad_attr, - bottompad_attr, - leftpad_attr, - rightpad_attr, - cellspace_attr, - cols_attr); - - if(align_attr) - PA_FREE(align_attr); - if(border_attr) - PA_FREE(border_attr); - if(border_top_attr) - PA_FREE(border_top_attr); - if(border_bottom_attr) - PA_FREE(border_bottom_attr); - if(border_left_attr) - PA_FREE(border_left_attr); - if(border_right_attr) - PA_FREE(border_right_attr); - if(border_color_attr) - PA_FREE(border_color_attr); - if(border_style_attr) - PA_FREE(border_style_attr); - if(vspace_attr) - PA_FREE(vspace_attr); - if(hspace_attr) - PA_FREE(hspace_attr); - if(bgcolor_attr) - PA_FREE(bgcolor_attr); - if(background_attr) - PA_FREE(background_attr); - if(width_attr) - PA_FREE(width_attr); - if(height_attr) - PA_FREE(height_attr); - if(cellpad_attr) - PA_FREE(cellpad_attr); - if(toppad_attr) - PA_FREE(toppad_attr); - if(bottompad_attr) - PA_FREE(bottompad_attr); - if(leftpad_attr) - PA_FREE(leftpad_attr); - if(rightpad_attr) - PA_FREE(rightpad_attr); - if(cellspace_attr) - PA_FREE(cellspace_attr); - if(cols_attr) - PA_FREE(cols_attr); -} - - -static void -lo_fill_cell_array(lo_TableRec *table, lo_cell_data XP_HUGE *cell_array, - lo_TableCell *blank_cell, int32 cell_pad, Bool *relayout_pass) -{ - int32 x, y; - int32 indx; - lo_table_span *row_max; - lo_table_span *col_max; - lo_TableRow *row_ptr; - lo_TableCell *cell_ptr; - - row_max = table->height_spans; - row_ptr = table->row_list; - for (y = 0; y < table->rows; y++) - { - x = 0; - col_max = table->width_spans; - cell_ptr = row_ptr->cell_list; - row_ptr->cells_in_row = 0; - while (cell_ptr != NULL) - { - /* - * Also on this pass check if any of the cells - * NEED to be relaid out later. - */ - if (cell_ptr->must_relayout != FALSE) - { - *relayout_pass = TRUE; - } - - /* - * "fix" up badly specified row spans. - */ - if ((y + cell_ptr->rowspan) > table->rows) - { - cell_ptr->rowspan = table->rows - y; - if (cell_ptr->rowspan == 1) - { - if (cell_ptr->height > row_max->dim) - { - row_max->dim = cell_ptr->height; - } - } - } - - indx = (y * table->cols) + x; - - if (cell_array[indx].cell == blank_cell) - { - x++; - col_max = col_max->next; - continue; - } - - /* - * If the cell is not an empty cell, count it for this row - */ - /* if (cell_ptr->cell->cell_list != NULL || cell_ptr->cell->cell_float_list != NULL) */ - row_ptr->cells_in_row++; - - cell_array[indx].cell = cell_ptr; - cell_array[indx].width = cell_ptr->max_width; - cell_array[indx].height = cell_ptr->height; - - if (cell_ptr->colspan > 1) - { - int32 i; - int32 width, min_width; - lo_table_span *max_ptr; - - max_ptr = col_max; - - width = max_ptr->dim; - min_width = max_ptr->min_dim; - for (i=1; i < cell_ptr->colspan; i++) - { - cell_array[indx + i].cell = blank_cell; - max_ptr = max_ptr->next; - width = width + cell_pad + max_ptr->dim; - min_width = min_width + cell_pad + - max_ptr->min_dim; - } - - if (width < cell_ptr->max_width) - { - int32 add_width; - int32 add; - lo_table_span *add_ptr; - - add_ptr = col_max; - add_width = cell_ptr->max_width - - width; - add = 0; - while (add_ptr != max_ptr) - { - int32 newWidth; - - newWidth = add_width * - add_ptr->dim / width; - add_ptr->dim += newWidth; - add += newWidth; - add_ptr = add_ptr->next; - } - add_ptr->dim += (add_width - add); - } - - if (min_width < cell_ptr->min_width) - { - int32 add_width; - int32 add; - lo_table_span *add_ptr; - - add_ptr = col_max; - add_width = cell_ptr->min_width - - min_width; - add = 0; - while (add_ptr != max_ptr) - { - int32 newWidth; - - newWidth = add_width * - add_ptr->min_dim / - min_width; - /* - * We are not allowed to add - * enough to put min_dim > dim. - */ - if ((add_ptr->min_dim + - newWidth) > add_ptr->dim) - { - newWidth = add_ptr->dim - - add_ptr->min_dim; - /* - * don't let newWidth become - * negative. - */ - if (newWidth < 0) - { - newWidth = 0; - } - } - add_ptr->min_dim += newWidth; - add += newWidth; - add_ptr = add_ptr->next; - } - add_ptr->min_dim += (add_width - add); - } - col_max = max_ptr; - } - - if (cell_ptr->rowspan > 1) - { - int32 i; - int32 height; - int32 tmp_val; - lo_table_span *max_ptr; - - max_ptr = row_max; - - height = max_ptr->dim; - for (i=1; i < cell_ptr->rowspan; i++) - { - cell_array[indx + (i * table->cols)].cell = - blank_cell; - if (cell_ptr->colspan > 1) - { - int32 j; - - for (j=1; j < cell_ptr->colspan; j++) - { - cell_array[indx + - (i * table->cols) + j].cell = - blank_cell; - } - } - max_ptr = max_ptr->next; - height = height + cell_pad + max_ptr->dim; - } - - tmp_val = cell_ptr->baseline - row_max->min_dim; - if (tmp_val > 0) - { - row_max->min_dim += tmp_val; - if (row_ptr->vert_alignment == - LO_ALIGN_BASELINE) - { - row_max->dim += tmp_val; - height += tmp_val; - } - /* - * Baseline spacing shouldn't grow the - * max height, except for baseline - * aligned rows as above. - */ - if (row_max->min_dim > row_max->dim) - { - row_max->min_dim = row_max->dim; - } - } - - if (height < cell_ptr->height) - { - int32 add_height; - int32 add; - lo_table_span *add_ptr; - - add_ptr = row_max; - add_height = cell_ptr->height - - height; - add = 0; - while (add_ptr != max_ptr) - { - int32 newHeight; - - newHeight = add_height * - add_ptr->dim / height; - add_ptr->dim += newHeight; - add += newHeight; - add_ptr = add_ptr->next; - } - add_ptr->dim += (add_height - add); - } - } - - x += cell_ptr->colspan; - - col_max = col_max->next; - cell_ptr = cell_ptr->next; - cell_array[indx].cell->next = NULL; - } - row_ptr = row_ptr->next; - row_max = row_max->next; - } -} - -static void -lo_percent_width_cells(lo_TableRec *table, lo_cell_data XP_HUGE *cell_array, - lo_TableCell *blank_cell, int32 cell_pad, int32 table_pad, - int32 *table_width, int32 *min_table_width, - int32 *base_table_width, int32 *min_base_table_width) -{ - int32 x, y; - int32 indx; - int32 new_table_width; - int32 new_min_table_width; - int32 new_base_table_width; - int32 new_min_base_table_width; - Bool need_pass_two; - lo_table_span *row_max; - lo_table_span *col_max; - lo_TableRow *row_ptr; - lo_TableCell *cell_ptr; - - new_table_width = 0; - row_ptr = table->row_list; - row_max = table->height_spans; - for (y=0; y < table->rows; y++) - { - if (row_ptr->has_percent_width_cells != FALSE) - { - int32 reserve; - int32 unknown, unknown_base; - - unknown = 0; - unknown_base = 0; - reserve = 100 - table->cols; - col_max = table->width_spans; - for (x=0; x < table->cols; x++) - { - indx = (y * table->cols) + x; - cell_ptr = cell_array[indx].cell; - if ((cell_ptr == blank_cell)|| - (cell_ptr == NULL)) - { - col_max = col_max->next; - continue; - } - if (cell_ptr->percent_width > 0) - { - int32 width; - - reserve += cell_ptr->colspan; - if (cell_ptr->percent_width > reserve) - { - cell_ptr->percent_width = reserve; - reserve = 0; - } - else - { - reserve -= cell_ptr->percent_width; - } - width = cell_ptr->max_width * 100 / - cell_ptr->percent_width; - if (width > new_table_width) - { - new_table_width = width; - } - } - else - { - unknown++; - unknown_base += cell_ptr->max_width; - } - col_max = col_max->next; - } - if (unknown) - { - col_max = table->width_spans; - for (x=0; x < table->cols; x++) - { - indx = (y * table->cols) + x; - cell_ptr = cell_array[indx].cell; - if ((cell_ptr == blank_cell)|| - (cell_ptr == NULL)) - { - col_max = col_max->next; - continue; - } - if (cell_ptr->percent_width == 0) - { - int32 width; - int32 percent; - - if (unknown == 1) - { - percent = reserve; - } - else - { - percent = reserve * - cell_ptr->max_width / - unknown_base; - } - reserve -= percent; - if (reserve < 0) - { - reserve = 0; - } - percent += cell_ptr->colspan; - cell_ptr->percent_width = percent; - - width = cell_ptr->max_width * 100 / - cell_ptr->percent_width; - if (width > new_table_width) - { - new_table_width = width; - } - - unknown--; - } - col_max = col_max->next; - } - } - } - else - { - int32 width; - - width = 0; - col_max = table->width_spans; - for (x=0; x < table->cols; x++) - { - indx = (y * table->cols) + x; - cell_ptr = cell_array[indx].cell; - if ((cell_ptr == blank_cell)|| - (cell_ptr == NULL)) - { - col_max = col_max->next; - continue; - } - width += cell_ptr->max_width; - col_max = col_max->next; - } - if (width > new_table_width) - { - new_table_width = width; - } - } - row_ptr = row_ptr->next; - row_max = row_max->next; - } - - if (*table_width > new_table_width) - { - new_table_width = *table_width; - } - - /* - * If we already know how wide this table must be - * Use that width when calculate percentage cell widths. - */ - if ((table->width > 0)&&(table->width >= *min_table_width)) - { - new_table_width = table->width; - } - - need_pass_two = FALSE; - - col_max = table->width_spans; - for (x=0; x < table->cols; x++) - { - int32 current_max; - - current_max = col_max->dim; - col_max->dim = 1; - row_max = table->height_spans; - for (y=0; y < table->rows; y++) - { - indx = (y * table->cols) + x; - cell_ptr = cell_array[indx].cell; - if ((cell_ptr == blank_cell)|| - (cell_ptr == NULL)) - { - row_max = row_max->next; - continue; - } - if ((cell_ptr->percent_width > 0)&& - (cell_ptr->colspan == 1)) - { - int32 p_width; - - p_width = new_table_width * - cell_ptr->percent_width / 100; - if (p_width < cell_ptr->min_width) - { - p_width = cell_ptr->min_width; - } - if (p_width > col_max->dim) - { - col_max->dim = p_width; - } - } - else if (cell_ptr->colspan > 1) - { - need_pass_two = TRUE; - } - else - { - if (cell_ptr->max_width > col_max->dim) - { - col_max->dim = - cell_ptr->max_width; - } - } - row_max = row_max->next; - } - if (col_max->dim < col_max->min_dim) - { - col_max->dim = col_max->min_dim; - } - col_max = col_max->next; - } - /* - * Take care of spanning columns if any - */ - if (need_pass_two != FALSE) - { - row_max = table->height_spans; - for (y=0; y < table->rows; y++) - { - col_max = table->width_spans; - for (x=0; x < table->cols; x++) - { - indx = (y * table->cols) + x; - cell_ptr = cell_array[indx].cell; - if ((cell_ptr == blank_cell)|| - (cell_ptr == NULL)) - { - col_max = col_max->next; - continue; - } - if (cell_ptr->colspan > 1) - { - int32 i; - int32 width; - lo_table_span *max_ptr; - int32 p_width; - int32 new_width; - - new_width = cell_ptr->max_width; - if (cell_ptr->percent_width > 0) - { - p_width = new_table_width * - cell_ptr->percent_width / 100; - if (p_width >= cell_ptr->min_width) - { - new_width = p_width; - } - } - - max_ptr = col_max; - - width = max_ptr->dim; - for (i=1; i < cell_ptr->colspan; i++) - { - max_ptr = max_ptr->next; - width = width + cell_pad + - max_ptr->dim; - } - - if (width < new_width) - { - int32 add_width; - int32 add; - lo_table_span *add_ptr; - - add_ptr = col_max; - add_width = new_width - width; - add = 0; - while (add_ptr != max_ptr) - { - int32 newWidth; - - newWidth = add_width * - add_ptr->dim / - width; - add_ptr->dim +=newWidth; - add += newWidth; - add_ptr = add_ptr->next; - } - add_ptr->dim += (add_width - - add); - } - } - col_max = col_max->next; - } - row_max = row_max->next; - } - } - - new_table_width = 0; - new_min_table_width = 0; - new_base_table_width = 0; - new_min_base_table_width = 0; - col_max = table->width_spans; - while (col_max != NULL) - { - new_base_table_width += col_max->dim; - new_min_base_table_width += col_max->min_dim; - new_table_width = new_table_width + cell_pad + - col_max->dim; - new_min_table_width = new_min_table_width + cell_pad + - col_max->min_dim; - col_max = col_max->next; - } - new_table_width += cell_pad; - new_table_width += (table->table_ele->border_left_width + - table->table_ele->border_right_width); - new_min_table_width += cell_pad; - new_min_table_width += (table->table_ele->border_left_width + - table->table_ele->border_right_width); - if (table->draw_borders == TABLE_BORDERS_OFF) - { - new_table_width += (2 * table_pad); - new_min_table_width += (2 * table_pad); - } - - *table_width = new_table_width; - *min_table_width = new_min_table_width; - *base_table_width = new_base_table_width; - *min_base_table_width = new_min_base_table_width; -} - -static void -lo_cell_relayout_pass(MWContext *context, lo_DocState *state, - lo_TableRec *table, lo_cell_data XP_HUGE *cell_array, lo_TableCell *blank_cell, - int32 cell_pad, Bool *rowspan_pass, Bool relayout) -{ - int32 x, y; - int32 indx; - lo_table_span *row_max; - lo_table_span *col_max; - lo_TableRow *row_ptr; - lo_TableCell *cell_ptr; - int32 top_inner_pad; - int32 bottom_inner_pad; - int32 left_inner_pad; - int32 right_inner_pad; - - top_inner_pad = FEUNITS_X(table->inner_top_pad, context); - bottom_inner_pad = FEUNITS_X(table->inner_bottom_pad, context); - left_inner_pad = FEUNITS_X(table->inner_left_pad, context); - right_inner_pad = FEUNITS_X(table->inner_right_pad, context); - - row_ptr = table->row_list; - row_max = table->height_spans; - for (y=0; y < table->rows; y++) - { - Bool max_height_valid; - Bool changed_row_height; - int32 max_row_height; - - max_height_valid = FALSE; - changed_row_height = FALSE; - - max_row_height = 0; - - col_max = table->width_spans; - - for (x=0; x < table->cols; x++) - { - LO_CellStruct *cell_struct; - int32 width; - int32 inside_width; - Bool has_elements; - - indx = (y * table->cols) + x; - cell_ptr = cell_array[indx].cell; - if ((cell_ptr == blank_cell)|| - (cell_ptr == NULL)) - { - col_max = col_max->next; - continue; - } - cell_struct = cell_ptr->cell; - inside_width = col_max->dim; - width = inside_width; - if (cell_ptr->colspan > 1) - { - int32 i; - lo_table_span *max_ptr; - - max_ptr = col_max; - - /* - * We need to add some cellpads for the spanned cells - * to our inside width - */ - inside_width += ( cell_ptr->colspan - 1 ) * cell_pad; - - for (i=1; i < cell_ptr->colspan; i++) - { - max_ptr = max_ptr->next; - inside_width += max_ptr->dim; - width += cell_pad + max_ptr->dim; - } - } - - /* - * We want to relayout the cell if it's been tagged as - * needing it or if it's been layed out to a different size. - */ - if ( (cell_ptr->must_relayout != FALSE) || - ((width != cell_ptr->max_width)) ) - { - cell_ptr->must_relayout = FALSE; - - inside_width = inside_width - - (2 * cell_struct->border_width) - - (2 * cell_struct->border_horiz_space) - - (left_inner_pad + right_inner_pad); - - /* - * Don't relayout documents that have no - * elements, it causes errors. - */ - has_elements = lo_cell_has_elements(cell_ptr->cell); - if ( has_elements == FALSE ) - { - /* - * Simply record our new width in this case. - */ - cell_struct->width = inside_width; - } - else - { - - cell_struct = lo_RelayoutCell(context, state, - table->current_subdoc, cell_ptr, - cell_struct, inside_width, - cell_ptr->is_a_header, relayout); - - if (!cell_struct) /* temporary fix for crash when cell_struct is null */ - { - break; - } - cell_ptr->cell = cell_struct; - cell_ptr->baseline = lo_GetCellBaseline(cell_struct); - - if (cell_ptr->rowspan == 1) - { - int32 tmp_val; - - /* - * We have changed the height of a single row cell, so we may need - * to update the row height later. - */ - changed_row_height = TRUE; - - tmp_val = cell_ptr->baseline - row_max->min_dim; - if (tmp_val > 0) - { - row_max->min_dim += tmp_val; - if (row_ptr->vert_alignment == - LO_ALIGN_BASELINE) - { - row_max->dim += tmp_val; - } - /* - * Baseline spacing shouldn't grow the - * max height, except for baseline - * aligned rows as above. - */ - if (row_max->min_dim > row_max->dim) - { - row_max->min_dim = row_max->dim; - } - } - } - else - { - *rowspan_pass = TRUE; - } - } - } - else - { - if (cell_ptr->rowspan > 1) - { - *rowspan_pass = TRUE; - } - } - - /* - * If this cell has anything inside it, see if it's height - * is the biggest for the row. - */ - has_elements = lo_cell_has_elements(cell_ptr->cell); - if ( has_elements != FALSE ) - { - int32 cell_row_height; - - /* - * What row height does this cell want? - */ - cell_row_height = cell_struct->height + - (top_inner_pad + bottom_inner_pad) + - (2 * cell_struct->border_vert_space); - - /* - * Munge the height if the row is vertically aligned along - * the baseline and the cell only spans one row. - */ - if (cell_ptr->rowspan == 1) - { - if (row_ptr->vert_alignment == LO_ALIGN_BASELINE) - { - cell_row_height = (cell_row_height - - cell_ptr->baseline) + row_max->min_dim; - } - - if ( cell_row_height > max_row_height ) - { - /* - * Update to our new maximum and flag that it - * contains valid data. - */ - max_height_valid = TRUE; - max_row_height = cell_row_height; - } - } - } - col_max = col_max->next; - } - - /* - * If we did relayout anything on that row which gave us a new - * valid max row height which is different to what we currently - * have, then use that. - */ - if ( max_height_valid != FALSE && changed_row_height != FALSE && - max_row_height != row_max->dim ) - { - /* - * Can't reset height to be smaller than - * the minimum height. - */ - if (max_row_height >= row_max->min_dim) - { - row_max->dim = max_row_height; - } - else - { - row_max->dim = row_max->min_dim; - } - } - row_max = row_max->next; - row_ptr = row_ptr->next; - } - -} - - -static void -lo_cell_rowspan_pass(MWContext *context, lo_TableRec *table, lo_cell_data XP_HUGE *cell_array, - lo_TableCell *blank_cell, int32 cell_pad) -{ - int32 x, y; - int32 indx; - lo_table_span *row_max; - lo_table_span *col_max; - lo_TableRow *row_ptr; - lo_TableCell *cell_ptr; - int32 top_inner_pad; - int32 bottom_inner_pad; - - top_inner_pad = FEUNITS_X(table->inner_top_pad, context); - bottom_inner_pad = FEUNITS_X(table->inner_bottom_pad, context); - - row_max = table->height_spans; - row_ptr = table->row_list; - for (y=0; y < table->rows; y++) - { - col_max = table->width_spans; - for (x=0; x < table->cols; x++) - { - LO_CellStruct *cell_struct; - - indx = (y * table->cols) + x; - cell_ptr = cell_array[indx].cell; - if ((cell_ptr == blank_cell)|| - (cell_ptr == NULL)) - { - col_max = col_max->next; - continue; - } - cell_struct = cell_ptr->cell; - - if (cell_ptr->rowspan > 1) - { - int32 i; - int32 height; - int32 tmp_val; - int32 cell_height; - lo_table_span *max_ptr; - - max_ptr = row_max; - - height = max_ptr->dim; - for (i=1; i < cell_ptr->rowspan; i++) - { - max_ptr = max_ptr->next; - height = height + cell_pad + - max_ptr->dim; - } - tmp_val = cell_ptr->baseline - - row_max->min_dim; - if (tmp_val > 0) - { - row_max->min_dim += tmp_val; - if (row_ptr->vert_alignment == - LO_ALIGN_BASELINE) - { - row_max->dim += tmp_val; - height += tmp_val; - } - /* - * Baseline spacing shouldn't grow the - * max height, except for baseline - * aligned rows as above. - */ - if (row_max->min_dim > row_max->dim) - { - row_max->min_dim = row_max->dim; - } - } - - cell_height = cell_struct->height + - (top_inner_pad + bottom_inner_pad) + - (2 * cell_struct->border_vert_space); - - if (height < cell_height) - { - int32 add_height; - int32 add; - lo_table_span *add_ptr; - - add_ptr = row_max; - add_height = cell_height - - height; - add = 0; - while (add_ptr != max_ptr) - { - int32 newHeight; - - newHeight = add_height * - add_ptr->dim / - height; - add_ptr->dim += - newHeight; - add += newHeight; - add_ptr->min_dim = add_ptr->dim; - add_ptr = add_ptr->next; - } - add_ptr->dim += - (add_height - add); - add_ptr->min_dim = add_ptr->dim; - } - } - col_max = col_max->next; - } - row_max = row_max->next; - row_ptr = row_ptr->next; - } -} - - -void -lo_free_cell_record(MWContext *context, lo_DocState *state, lo_TableCell *cell) -{ - if (cell == NULL) - { - return; - } - - /* - * If this table cell is not nested inside another table cell - * or caption, free any re-parse tags stored on this cell. - */ - if ((cell->in_nested_table == FALSE) && - (cell->subdoc_tags != NULL)&& - (state->is_a_subdoc != SUBDOC_CELL)&& - (state->is_a_subdoc != SUBDOC_CAPTION)) - { - PA_Tag *tptr; - PA_Tag *tag; - - tptr = cell->subdoc_tags; - while ((tptr != cell->subdoc_tags_end)&&(tptr != NULL)) - { - tag = tptr; - tptr = tptr->next; - tag->next = NULL; - PA_FreeTag(tag); - } - if (tptr != NULL) - { - tptr->next = NULL; - PA_FreeTag(tptr); - } - cell->subdoc_tags = NULL; - cell->subdoc_tags_end = NULL; - } - - if (cell->cell != NULL) { - cell->cell->table = NULL; - cell->cell->table_row = NULL; - cell->cell->table_cell = NULL; - } - - XP_DELETE(cell); -} - - -static void -lo_free_row_record(MWContext *context, lo_DocState *state, - lo_TableRow *row, Bool partial) -{ - lo_TableCell *cell_ptr; - lo_TableCell *cell; - - if (row->cell_list != NULL) - { - /* - * These are already freed on a completed table, and - * need to be freed on a partial table. - */ - - if (partial != FALSE) - { - cell_ptr = row->cell_list; - while (cell_ptr != NULL) - { - cell = cell_ptr; - cell_ptr = cell_ptr->next; - lo_free_cell_record(context, state, cell); - } - } - - row->cell_list = NULL; - row->cell_ptr = NULL; - } - - XP_FREEIF(row->backdrop.bg_color); - XP_FREEIF(row->backdrop.url); - - XP_DELETE(row); -} - - -static void lo_FreeTableCaption( MWContext *context, lo_DocState *state, lo_TableRec *table ) -{ - if (table->caption != NULL) - { - if (table->caption->cell_ele != NULL) - { - lo_FreeCaptionCell( context, state, table->caption->cell_ele ); - table->caption->cell_ele = NULL; - } - - if ( table->caption->subdoc != NULL ) - { - lo_FreePartialSubDoc ( context, state, table->caption->subdoc ); - table->caption->subdoc = NULL; - } - - XP_DELETE(table->caption); - table->caption = NULL; - } -} - -void lo_free_table_record(MWContext *context, lo_DocState *state, - lo_TableRec *table, Bool partial) -{ - if (table->row_list != NULL) - { - lo_TableRow *row_ptr; - lo_TableRow *row; - - row_ptr = table->row_list; - while (row_ptr != NULL) - { - row = row_ptr; - row_ptr = row_ptr->next; - lo_free_row_record(context, state, row, partial); - } - table->row_list = NULL; - table->row_ptr = NULL; - } - - lo_FreeAllExceptRows( context, state, table ); -} - -void -lo_FreePartialTable(MWContext *context, lo_DocState *state, lo_TableRec *table) -{ - lo_TableRow *row_ptr; - lo_TableCell *cell_ptr; - LO_SubDocStruct *subdoc; - LO_CellStruct *cell_struct; - - if (table == NULL) - { - return; - } - - row_ptr = table->row_list; - while (row_ptr != NULL) - { - cell_ptr = row_ptr->cell_list; - while (cell_ptr != NULL) - { - cell_struct = cell_ptr->cell; - lo_FreePartialCell(context, state, cell_struct); - cell_ptr->cell = NULL; - cell_ptr = cell_ptr->next; - } - row_ptr = row_ptr->next; - } - - if (table->caption != NULL) - { - subdoc = table->caption->subdoc; - lo_FreePartialSubDoc(context, state, subdoc); - table->caption->subdoc = NULL; - } - - lo_free_table_record(context, state, table, TRUE); -} - - - -void -lo_EndTable(MWContext *context, lo_DocState *state, lo_TableRec *table, Bool relayout) -{ - int32 save_doc_min_width; - int32 x, y; - int32 cell_x, cell_y; - int32 indx; - int32 cell_cnt; - int32 ele_cnt; - int32 table_width, min_table_width; - int32 base_table_width, min_base_table_width; - int32 table_height; - int32 min_table_height; - int32 width_limit; - Bool relayout_pass; - Bool rowspan_pass; - Bool cut_to_window_width; - lo_TableCell blank_cell; - lo_cell_data XP_HUGE *cell_array; - XP_Block cell_array_buff; - lo_table_span *row_max; - lo_table_span *col_max; - lo_TableCell *cell_ptr; - int32 cell_pad; - int32 top_inner_pad; - int32 bottom_inner_pad; - int32 left_inner_pad; - int32 right_inner_pad; - int32 table_pad; - Bool floating; - int32 save_state_x, save_state_y; - LO_Element *save_line_list; -#ifdef LOCAL_DEBUG -fprintf(stderr, "lo_EndTable called\n"); -#endif /* LOCAL_DEBUG */ - - cell_pad = FEUNITS_X(table->inter_cell_pad, context); - table_pad = FEUNITS_X(TABLE_DEF_CELL_BORDER, context); - - top_inner_pad = FEUNITS_X(table->inner_top_pad, context); - bottom_inner_pad = FEUNITS_X(table->inner_bottom_pad, context); - left_inner_pad = FEUNITS_X(table->inner_left_pad, context); - right_inner_pad = FEUNITS_X(table->inner_right_pad, context); - - relayout_pass = FALSE; - cut_to_window_width = TRUE; - floating = FALSE; - - /* - * So gcc won't complain - */ - save_state_x = 0; - save_state_y = 0; - save_line_list = NULL; -/* - state->current_table = NULL; -*/ - - cell_cnt = table->rows * table->cols; - /* - * Empty tables are completely ignored! - */ - if (cell_cnt <= 0) - { - /* - * Clear table state, and free up this structure. - */ - state->current_table = NULL; - - /* - * Don't wanna free table record any more because this information - * is used during relayout. - */ - /* - if (table != NULL) - { - lo_free_table_record(context, state, table, FALSE); - } - */ - return; - } -#ifdef XP_WIN16 - /* - * It had better be the case that the size of the struct is a - * power of 2 - */ - XP_ASSERT(sizeof(lo_cell_data) == 8); - cell_array = (lo_cell_data XP_HUGE *)_halloc(cell_cnt, sizeof(lo_cell_data)); - - /* - * There isn't a runtime routine that can initialize a huge array - */ - if (cell_cnt * sizeof(lo_cell_data) <= 0xFFFFL) - memset(cell_array, 0, (cell_cnt * sizeof(lo_cell_data))); - else { - BYTE XP_HUGE *tmp = (BYTE XP_HUGE *)cell_array; - - for (indx = 0; indx < cell_cnt * sizeof(lo_cell_data); indx++) - tmp[indx] = 0; - } -#else - cell_array_buff = XP_ALLOC_BLOCK(cell_cnt * sizeof(lo_cell_data)); - XP_LOCK_BLOCK(cell_array, lo_cell_data *, cell_array_buff); - memset(cell_array, 0, (cell_cnt * sizeof(lo_cell_data))); -#endif - - lo_fill_cell_array(table, cell_array, &blank_cell, cell_pad, - &relayout_pass); - - table_width = 0; - min_table_width = 0; - base_table_width = 0; - min_base_table_width = 0; - col_max = table->width_spans; - while (col_max != NULL) - { - base_table_width += col_max->dim; - min_base_table_width += col_max->min_dim; - table_width = table_width + cell_pad + col_max->dim; - min_table_width = min_table_width + cell_pad + col_max->min_dim; - col_max = col_max->next; - } - table_width += cell_pad; - min_table_width += cell_pad; - table_width += (table->table_ele->border_left_width + - table->table_ele->border_right_width); - min_table_width += (table->table_ele->border_left_width + - table->table_ele->border_right_width); - if (table->draw_borders == TABLE_BORDERS_OFF) - { - table_width += (2 * table_pad); - min_table_width += (2 * table_pad); - } - - /* - * Take care of cells with percentage widths unless we're in - * a fixed layout table (has the COLS attribute) in which case - * the cell widths are already set. - */ - if ((table->has_percent_width_cells != FALSE) && - (table->fixed_cols == 0)) - { - lo_percent_width_cells(table, cell_array, &blank_cell, - cell_pad, table_pad, &table_width, &min_table_width, - &base_table_width, &min_base_table_width); - relayout_pass = TRUE; - } - - /* - * Use state->left_margin here instead of state->win_left to take - * indent from lists into account. - */ - width_limit = (state->win_width - state->left_margin - state->win_right); - if (table->width > 0) - { - width_limit = table->width; - } - /* - * Else, if we are a nested table in an infinite width - * layout space, we don't want to cut to "window width" - */ - else if (state->allow_percent_width == FALSE) - { - cut_to_window_width = FALSE; - } - - /* - * If we're in a fixed layout table, then we never - * want to cut to "window width" - */ - if ( table->fixed_cols > 0 ) - { - cut_to_window_width = FALSE; - } - - /* - * If the table is too small, we always need to relayout. - */ - if ((min_table_width >= width_limit)) - { - lo_table_span *sub_ptr; - - relayout_pass = TRUE; - sub_ptr = table->width_spans; - while (sub_ptr != NULL) - { - sub_ptr->dim = sub_ptr->min_dim; - sub_ptr = sub_ptr->next; - } - } - else if ((table_width > width_limit)&&(cut_to_window_width != FALSE)) - { - intn pass; - Bool expand_failed; - int32 add_width; - int32 div_width; - int32 div_width_next; - int32 add; - int32 total_to_add; - lo_table_span *add_ptr; - - relayout_pass = TRUE; - - expand_failed = TRUE; - pass = 0; - total_to_add = width_limit - min_table_width; - div_width = table_width; - while ((total_to_add > 0)&&(pass < 10)&&(expand_failed !=FALSE)) - { - int32 extra; - int32 min_extra; - - expand_failed = FALSE; - add_ptr = table->width_spans; - add_width = total_to_add; - total_to_add = 0; - div_width_next = (table->cols + 1) * cell_pad; - add = 0; - while (add_ptr->next != NULL) - { - if ((pass > 0)&& - (add_ptr->min_dim == add_ptr->dim)) - { - add_ptr = add_ptr->next; - continue; - } - extra = add_width * add_ptr->dim / - div_width; - if ((add_ptr->min_dim + extra) > add_ptr->dim) - { - expand_failed = TRUE; - min_extra = add_ptr->dim - - add_ptr->min_dim; - extra = min_extra; - } - - add_ptr->min_dim += extra; - if (add_ptr->min_dim < add_ptr->dim) - { - div_width_next += add_ptr->dim; - } - add += extra; - add_ptr = add_ptr->next; - } - if ((pass == 0)||(add_ptr->min_dim < add_ptr->dim)) - { - if (expand_failed == FALSE) - { - extra = add_width - add; - } - else - { - extra = add_width * add_ptr->dim / - div_width; - } - if ((add_ptr->min_dim + extra) > add_ptr->dim) - { - expand_failed = TRUE; - min_extra = add_ptr->dim - - add_ptr->min_dim; - extra = min_extra; - } - add_ptr->min_dim += extra; - if (add_ptr->min_dim < add_ptr->dim) - { - div_width_next += add_ptr->dim; - } - add += extra; - } - total_to_add = add_width - add; - div_width = div_width_next; - pass++; - } - if (total_to_add > 0) - { - add = 0; - add_ptr = table->width_spans; - while ((add_ptr->next != NULL)&&(total_to_add > 0)) - { - if ((add_ptr->min_dim + total_to_add) > - add_ptr->dim) - { - add = add_ptr->dim - add_ptr->min_dim; - total_to_add = total_to_add - add; - add_ptr->min_dim += add; - } - else - { - add_ptr->min_dim += total_to_add; - total_to_add = 0; - } - add_ptr = add_ptr->next; - } - add_ptr->min_dim += total_to_add; - } - - add_ptr = table->width_spans; - while (add_ptr != NULL) - { - add_ptr->dim = add_ptr->min_dim; - add_ptr = add_ptr->next; - } - } - - /* - * If the user specified a wider width than the minimum - * width then we grow the sucker. - */ - if ((table->width > 0)&&(width_limit > table_width)) - { - int32 add_width; - int32 add; - int32 newWidth; - int32 min_add_width; - int32 min_add; - lo_table_span *add_ptr; - - /* relayout to fill all the space we're adding */ - relayout_pass = TRUE; - - add_ptr = table->width_spans; - add_width = width_limit - table_width; - if ( add_width < 0 ) - { - add_width = 0; - } - add = 0; - min_add_width = width_limit - min_table_width; - min_add = 0; - while ((add_ptr != NULL)&&(add_ptr->next != NULL)) - { - newWidth = add_width * add_ptr->dim / base_table_width; - add_ptr->dim += newWidth; - add += newWidth; - - /* - * We only want to resize the min_dim's of the spans - * if we're a fixed width table. - */ - if ( table->table_width_fixed ) - { - newWidth = min_add_width * add_ptr->min_dim / min_base_table_width; - add_ptr->min_dim += newWidth; - min_add += newWidth; - } - add_ptr = add_ptr->next; - } - if ( table->table_width_fixed ) - { - add_ptr->min_dim += (min_add_width - min_add); - } - add_ptr->dim += (add_width - add); - } - - rowspan_pass = FALSE; - - if ((state->top_state->doc_state == state) || - (state->top_state->in_cell_relayout == TRUE)) - { - - if (state->top_state->doc_state == state) - { - state->top_state->in_cell_relayout = TRUE; - } - - if (relayout_pass != FALSE) - { - lo_cell_relayout_pass(context, state, table, cell_array, - &blank_cell, cell_pad, &rowspan_pass, relayout); - } - - if (rowspan_pass != FALSE) - { - lo_cell_rowspan_pass(context, table, cell_array, &blank_cell, - cell_pad); - } - - if (state->top_state->doc_state == state) - { - state->top_state->in_cell_relayout = FALSE; - } - } - - table_width = 0; - min_table_width = 0; - col_max = table->width_spans; - while (col_max != NULL) - { - table_width = table_width + cell_pad + col_max->dim; - min_table_width = min_table_width + cell_pad + col_max->min_dim; - col_max = col_max->next; - } - table_width += cell_pad; - table_width += (table->table_ele->border_left_width + - table->table_ele->border_right_width); - min_table_width += cell_pad; - min_table_width += (table->table_ele->border_left_width + - table->table_ele->border_right_width); - - table_height = 0; - min_table_height = 0; - row_max = table->height_spans; - while (row_max != NULL) - { - table_height = table_height + cell_pad + row_max->dim; - min_table_height = min_table_height + cell_pad + row_max->min_dim; - row_max = row_max->next; - } - table_height += cell_pad; - min_table_height += cell_pad; - table_height += (table->table_ele->border_top_width + - table->table_ele->border_bottom_width); - min_table_height += (table->table_ele->border_top_width + - table->table_ele->border_bottom_width); - if (table->draw_borders == TABLE_BORDERS_OFF) - { - table_width += (2 * table_pad); - min_table_width += (2 * table_pad); - table_height += (2 * table_pad); - min_table_height += (2 * table_pad); - } - - - /* - * If the user specified a taller table than the min - * height we need to adjust the heights of all the rows. - */ - if ((table->height > 0)&&(table->height > min_table_height)) - { - int32 add_height; - int32 add; - lo_table_span *add_ptr; - int32 newHeight; - int32 min_add_height; - int32 min_add; - - add_ptr = table->height_spans; - add_height = table->height - table_height; - if ( add_height < 0 ) - { - add_height = 0; - } - min_add_height = table->height - min_table_height; - add = 0; - min_add = 0; - while((add_ptr != NULL) && (add_ptr->next != NULL)) - { - newHeight = add_height * add_ptr->dim / table_height; - add_ptr->dim += newHeight; - add += newHeight; - - newHeight = min_add_height * add_ptr->min_dim / table_height; - add_ptr->min_dim += newHeight; - min_add += newHeight; - - add_ptr = add_ptr->next; - } - add_ptr->dim += (add_height - add); - add_ptr->min_dim += (min_add_height - min_add); - - /* - * We can't make the height be less than the sum - * of the row heights. - */ - if (table_height < table->height) - { - table_height = table->height; - } - min_table_height = table->height; - } - - table->table_ele->width = table_width; - table->table_ele->height = table_height; - - /* - * Here, if we are floating we don't do the linebreak. - * We do save some state info and then "fake" a linebreak - * so we can use common code to place the rest of the table. - */ - if (table->table_ele->ele_attrmask & LO_ELE_FLOATING) - { - save_line_list = state->line_list; - save_state_x = state->x; - save_state_y = state->y; - floating = TRUE; - state->x = state->left_margin; - state->y = state->y + state->line_height; - state->line_list = NULL; - } - else - { - /* - lo_SetSoftLineBreakState(context, state, FALSE, 1); - */ - lo_SetLineBreakState ( context, state, FALSE, LO_LINEFEED_BREAK_SOFT, 1, relayout ); - } - - table->table_ele->x = state->x; - table->table_ele->y = state->y; - /* Keep the element IDs in order */ - table->table_ele->ele_id = NEXT_ELEMENT; - - /*cmanske - Save spacing param for drawing table selection in Composer */ - table->table_ele->inter_cell_space = table->inter_cell_pad; - - lo_AppendToLineList(context, state, - (LO_Element *)table->table_ele, 0); - -#ifdef EDITOR - /*cmanske - build list of tables we are laying out - * so Editor can readjust it's data after all is finished - */ - EDT_AddToRelayoutTables(context, table->table_ele); -#endif - - state->x += (cell_pad + table->table_ele->border_left_width); - state->y += (cell_pad + table->table_ele->border_top_width); - if (table->draw_borders == TABLE_BORDERS_OFF) - { - state->x += table_pad; - state->y += table_pad; - } - - if (table->caption != NULL) - { - int32 new_width; - LO_SubDocStruct *subdoc; - Bool has_elements; - - subdoc = table->caption->subdoc; - - col_max = table->width_spans; - new_width = col_max->dim; - while (col_max->next != NULL) - { - col_max = col_max->next; - new_width = new_width + cell_pad + col_max->dim; - } - /* - * Don't relayout documents that have no - * elements, it causes errors. - */ - has_elements = lo_subdoc_has_elements(subdoc->state); - if ((new_width < table->caption->max_width)&& - (has_elements == FALSE)) - { - int32 inside_width; - - inside_width = new_width - - (2 * subdoc->border_width) - - (2 * subdoc->border_horiz_space) - - (left_inner_pad + right_inner_pad); - subdoc->width = inside_width; - } - else /* if (new_width < table->caption->max_width) */ - { - int32 inside_width; - - inside_width = new_width - - (2 * subdoc->border_width) - - (2 * subdoc->border_horiz_space) - - (left_inner_pad + right_inner_pad); - table->caption->subdoc = lo_RelayoutCaptionSubdoc(context, - state, table->caption, subdoc, inside_width, FALSE); - subdoc = table->caption->subdoc; - - table->caption->height = subdoc->height + - (2 * subdoc->border_vert_space) + - (top_inner_pad + bottom_inner_pad); - table->caption->max_width = new_width; - } - /* - else - { - table->caption->max_width = new_width; - } - */ - } - - state->current_table = NULL; - cell_x = state->x; - cell_y = state->y; - - if ((table->caption != NULL)&& - (table->caption->vert_alignment == LO_ALIGN_TOP)) - { - LO_SubDocStruct *subdoc; - - cell_x = state->x; - subdoc = table->caption->subdoc; - subdoc->x = cell_x; - subdoc->y = table->table_ele->y; - subdoc->x_offset = (int16)subdoc->border_horiz_space; - subdoc->y_offset = (int32)subdoc->border_vert_space; - subdoc->width = table->caption->max_width - - (2 * subdoc->border_horiz_space); - subdoc->height = table->caption->height - - (2 * subdoc->border_vert_space); - ele_cnt = lo_align_subdoc(context, state, - (lo_DocState *)subdoc->state, subdoc, table, NULL); - if (ele_cnt > 0) - { - LO_CellStruct *cell_ele; - - if (relayout == FALSE) - { - /* - cell_ele = lo_SquishSubDocToCell(context, state, - subdoc, TRUE); - */ - cell_ele = lo_SquishSubDocToCell(context, state, - subdoc, FALSE); - cell_ele->isCaption = TRUE; - table->caption->cell_ele = cell_ele; - } - else - { - cell_ele = table->caption->cell_ele; - lo_UpdateCaptionCellFromSubDoc(context, state, subdoc, cell_ele); - } - - /* table->caption->subdoc = NULL; */ - - if (cell_ele == NULL) - { - lo_AppendToLineList(context, state, - (LO_Element *)subdoc, 0); - } - else - { - /*cmanske - Save spacing param for drawing cell selection by FEs */ - /* should we use cell_pad (converted to FE units) instead? */ - cell_ele->inter_cell_space = table->inter_cell_pad; - lo_AppendToLineList(context, state, - (LO_Element *)cell_ele, 0); - } - cell_x = state->x; - cell_y = cell_y + table->caption->height + cell_pad; - - table->table_ele->y_offset = cell_y - - table->table_ele->y; - cell_y += (cell_pad + table->table_ele->border_top_width); - if (table->draw_borders == TABLE_BORDERS_OFF) - { - cell_y += table_pad; - } - } - else - { - LO_CellStruct *cell_ele; - - /* - * Free up the useless subdoc - */ - cell_ele = lo_SquishSubDocToCell(context, state, - subdoc, TRUE); - table->caption->subdoc = NULL; - - if (cell_ele != NULL) - { - lo_FreeElement(context, - (LO_Element *)cell_ele, TRUE); - } - } - } - - row_max = table->height_spans; - for (y=0; y < table->rows; y++) - { - cell_x = state->x; - col_max = table->width_spans; - for (x=0; x < table->cols; x++) - { - LO_CellStruct *cell_struct; - int32 new_x, new_y; - - indx = (y * table->cols) + x; - cell_ptr = cell_array[indx].cell; - if ((cell_ptr == &blank_cell)||(cell_ptr == NULL)) - { - cell_x = cell_x + col_max->dim + cell_pad; - col_max = col_max->next; - continue; - } - cell_struct = cell_ptr->cell; -/* - cell_struct->x = cell_x; - cell_struct->y = cell_y; - cell_struct->x_offset = (int16)cell_struct->border_horiz_space; - cell_struct->y_offset = (int32)cell_struct->border_vert_space; -*/ - - new_x = cell_x + (int16)cell_struct->border_horiz_space + cell_struct->border_width; - new_y = cell_y + (int32)cell_struct->border_vert_space + cell_struct->border_width; - - cell_struct->width = col_max->dim; - if (cell_ptr->colspan > 1) - { - int32 i; - lo_table_span *max_ptr; - - max_ptr = col_max; - - for (i=1; i < cell_ptr->colspan; i++) - { - max_ptr = max_ptr->next; - cell_struct->width = cell_struct->width + - cell_pad + max_ptr->dim; - } - } - cell_struct->width = cell_struct->width - - (2 * cell_struct->border_horiz_space); - cell_struct->height = row_max->dim; - if (cell_ptr->rowspan > 1) - { - int32 i; - lo_table_span *max_ptr; - - max_ptr = row_max; - - for (i=1; i < cell_ptr->rowspan; i++) - { - max_ptr = max_ptr->next; - cell_struct->height = cell_struct->height + - cell_pad + max_ptr->dim; - } - } - cell_struct->height = cell_struct->height - - (2 * cell_struct->border_vert_space); - - lo_ShiftCell(cell_struct, - cell_ptr->cell_base_x, cell_ptr->cell_base_y); - cell_ptr->cell_base_x = 0; - cell_ptr->cell_base_y = 0; - ele_cnt = lo_align_cell(context, state, cell_ptr, - cell_struct, table, row_max); - /* - if (ele_cnt > 0) - */ - { - LO_CellStruct *cell_ele; - int32 shift_x, shift_y; - - - - shift_x = new_x - cell_struct->x - - cell_struct->x_offset - - cell_struct->border_width; - shift_y = new_y - cell_struct->y - - cell_struct->y_offset - - cell_struct->border_width; - cell_struct->x = cell_x; - cell_struct->y = cell_y; - cell_struct->x_offset = (int16)cell_struct->border_horiz_space; - cell_struct->y_offset = (int32)cell_struct->border_vert_space; - cell_ele = cell_struct; - -/* - lo_ShiftCell(cell_ele, shift_x, shift_y); -*/ - lo_ShiftCell(cell_ele, new_x, new_y); - /* - * Keep element ids sequential. - */ - if (cell_ele != NULL) - { - cell_ele->ele_id = NEXT_ELEMENT; - lo_RenumberCell(state, cell_ele); - } - - if (cell_ele == NULL) - { - lo_AppendToLineList(context, state, - (LO_Element *)cell_struct, 0); - } - else - { - /*cmanske - Save spacing param for drawing cell selection by FEs */ - cell_ele->inter_cell_space = table->inter_cell_pad; - lo_AppendToLineList(context, state, - (LO_Element *)cell_ele, 0); - } - - if ( relayout == FALSE ) - { - /* - * Cell backgrounds now sit in their own layer. This is needed - * for selection to work correctly. - * Cell backgrounds can exist in the main _BODY layer, - * so we need to special case the parent layer of the - * cell background, - */ - if (context->compositor && - (cell_ele->backdrop.bg_color || cell_ele->backdrop.url)) - { - lo_TopState *top_state = state->top_state; - CL_Layer *parent_layer = lo_CurrentLayer(state); - if (parent_layer == top_state->doc_layer) - parent_layer = top_state->body_layer; - cell_ele->cell_bg_layer = - lo_CreateCellBackgroundLayer(context, cell_ele, - parent_layer, top_state->table_nesting_level); - } - else - { - cell_ele->cell_bg_layer = NULL; - } - } - } - /* - else - { - */ - /* - LO_CellStruct *cell_ele; - */ - /* - * Free up the useless cell - */ - /* - cell_ele = cell_struct; - if (cell_ele != NULL) - { - lo_FreeElement(context, - (LO_Element *)cell_ele, TRUE); - } - - } - */ - cell_x = cell_x + col_max->dim + cell_pad; - col_max = col_max->next; - } - cell_y = cell_y + row_max->dim + cell_pad; - row_max = row_max->next; - } - cell_x = cell_x + table->table_ele->border_left_width; - cell_y = cell_y + table->table_ele->border_top_width; - if (table->draw_borders == TABLE_BORDERS_OFF) - { - cell_x += table_pad; - cell_y += table_pad; - } - - if ((table->caption != NULL)&& - (table->caption->vert_alignment != LO_ALIGN_TOP)) - { - LO_SubDocStruct *subdoc; - - subdoc = table->caption->subdoc; - subdoc->x = state->x; - subdoc->y = cell_y; - subdoc->x_offset = (int16)subdoc->border_horiz_space; - subdoc->y_offset = (int32)subdoc->border_vert_space; - subdoc->width = table->caption->max_width - - (2 * subdoc->border_horiz_space); - subdoc->height = table->caption->height - - (2 * subdoc->border_vert_space); - ele_cnt = lo_align_subdoc(context, state, - (lo_DocState *)subdoc->state, subdoc, table, NULL); - if (ele_cnt > 0) - { - LO_CellStruct *cell_ele; - - if (relayout == FALSE) - { - /* - cell_ele = lo_SquishSubDocToCell(context, state, - subdoc, TRUE); - */ - cell_ele = lo_SquishSubDocToCell(context, state, - subdoc, FALSE); - cell_ele->isCaption = TRUE; - table->caption->cell_ele = cell_ele; - } - else - { - cell_ele = table->caption->cell_ele; - lo_UpdateCaptionCellFromSubDoc(context, state, subdoc, cell_ele); - } - - /* table->caption->subdoc = NULL; */ - - if (cell_ele == NULL) - { - lo_AppendToLineList(context, state, - (LO_Element *)subdoc, 0); - } - else - { - /*cmanske - Save spacing param for drawing cell selection by FEs */ - cell_ele->inter_cell_space = table->inter_cell_pad; - lo_AppendToLineList(context, state, - (LO_Element *)cell_ele, 0); - } - cell_y = cell_y + table->caption->height + cell_pad; - } - else - { - LO_CellStruct *cell_ele; - - /* - * Free up the useless subdoc - */ - cell_ele = lo_SquishSubDocToCell(context, state, - subdoc, TRUE); - table->caption->subdoc = NULL; - - if (cell_ele != NULL) - { - lo_FreeElement(context, - (LO_Element *)cell_ele, TRUE); - } - } - } - - /* - * This table may have contained named anchors. - * This will correct their positions in the name_list, - * and unblock us if we were blocked on them. - */ - lo_CheckNameList(context, state, table->table_ele->ele_id); - - /* - * The usual stuff for a table. - */ - if (floating == FALSE) - { - lo_AlignStack *aptr; - int32 indent; - - state->x = cell_x; - state->baseline = 0; - state->line_height = cell_y - state->y; - state->linefeed_state = 0; - state->at_begin_line = FALSE; - state->trailing_space = FALSE; - state->cur_ele_type = LO_SUBDOC; - - table->table_ele->line_height = state->line_height; - - /* - * Find how far the table might be indented from - * being inside a list. - */ - indent = state->list_stack->old_left_margin - state->win_left; - if (indent < 0) - { - indent = 0; - } - - save_doc_min_width = state->min_width; - if (relayout == FALSE) - { - lo_SoftLineBreak(context, state, FALSE); - } - else - { - lo_rl_AddBreakAndFlushLine( context, state, LO_LINEFEED_BREAK_SOFT, LO_CLEAR_NONE, FALSE ); - } - - if ((min_table_width + indent) > save_doc_min_width) - { - save_doc_min_width = min_table_width + indent; - } - state->min_width = save_doc_min_width; - - /* - * Pop the table's alignment. - */ - aptr = lo_PopAlignment(state); - if (aptr != NULL) - { - XP_DELETE(aptr); - } - } - /* - * Else this is a floating table, rip it out of the "faked" - * line list, stuff itin the margin, and restore our state - * to where we left off. - */ - else - { - int32 push_right; - int32 line_height; - LO_Element *tptr; - LO_Element *last; - - line_height = cell_y - state->y; - push_right = 0; - if (table->table_ele->alignment == LO_ALIGN_RIGHT) - { - push_right = state->right_margin - cell_x; - } - - table->table_ele->x_offset += - (int16)table->table_ele->border_horiz_space; - table->table_ele->y_offset += - (int32)table->table_ele->border_vert_space; - - last = NULL; - tptr = state->line_list; - while (tptr != NULL) - { - tptr->lo_any.x += push_right; - if (tptr->type == LO_CELL) - { - tptr->lo_any.x += - table->table_ele->border_horiz_space; - tptr->lo_any.y += - table->table_ele->border_vert_space; - lo_ShiftCell((LO_CellStruct *)tptr, - (push_right + - table->table_ele->border_horiz_space), - table->table_ele->border_vert_space); - } - last = tptr; - tptr->lo_any.line_height = line_height; - tptr = tptr->lo_any.next; - } - - /* - * Stuff the whole line list into the float list, and - * restore the line list to its pre-table state. - */ - if (state->line_list != NULL) - { - last->lo_any.next = state->float_list; - state->float_list = state->line_list; - state->line_list = NULL; - } - - state->line_list = save_line_list; - - if (relayout == FALSE) - { - lo_AppendFloatInLineList(context, state, (LO_Element *)table->table_ele, NULL); - } - - table->table_ele->line_height = line_height; - table->table_ele->expected_y = table->table_ele->y; - table->table_ele->y = -1; - - lo_AddMarginStack(state, - table->table_ele->x, table->table_ele->y, - table->table_ele->width, table->table_ele->line_height, - table->table_ele->border_left_width + - table->table_ele->border_right_width, - table->table_ele->border_vert_space, - table->table_ele->border_horiz_space, - (intn)table->table_ele->alignment); - - /* - * Restore state to pre-table values. - */ - state->x = save_state_x; - state->y = save_state_y; - - /* - * All the doc_min_width stuff makes state->min_width - * be correct for tables nested inside tables. - */ - save_doc_min_width = state->min_width; - - /* - * Standard float stuff, if we happen to be at the start - * of a line, place the table now. - */ - if (state->at_begin_line != FALSE) - { - lo_FindLineMargins(context, state, (! relayout)); - state->x = state->left_margin; - } - - if (min_table_width > save_doc_min_width) - { - save_doc_min_width = min_table_width; - } - state->min_width = save_doc_min_width; - - } - - /* Decrement table nesting level (used for passing into lo_CreateCellBackGroundLayer() */ - if (!relayout) - { - if (state->top_state->table_nesting_level == 1) - TIMING_STOPCLOCK_OBJECT("lo:blk-tab", table->table_ele, context, "ok"); - - state->top_state->table_nesting_level--; - } - -#ifdef XP_WIN16 - _hfree(cell_array); -#else - XP_UNLOCK_BLOCK(cell_array_buff); - XP_FREE_BLOCK(cell_array_buff); -#endif - -} - - -/* - * Functions separated out of lo_BeginTableAttributes - */ - -void lo_PositionTableElement(lo_DocState *state, LO_TableStruct *table_ele) -{ - table_ele->ele_id = NEXT_ELEMENT; - table_ele->x = state->x; - table_ele->x_offset = 0; - table_ele->y = state->y; - table_ele->y_offset = 0; - table_ele->width = 0; - table_ele->height = 0; - table_ele->line_height = 0; - - table_ele->next = NULL; - table_ele->prev = NULL; - - /* - * Push our alignment state if we're not floating - */ - - if ( !(table_ele->ele_attrmask & LO_ELE_FLOATING) ) - { - lo_PushAlignment(state, P_TABLE_DATA, table_ele->alignment); - } - -} - - -void lo_InitTableRecord( lo_TableRec *table ) -{ - /* Reset row and col counters */ - table->rows = 0; - table->cols = 0; - - /* Reset width span array */ - lo_ResetWidthSpans(table); - - table->height_span_ptr = NULL; -} - -static void lo_ResetWidthSpans( lo_TableRec *table ) -{ - lo_table_span *span = table->width_spans; - - while (span != NULL) - { - span->dim = 1; - span->min_dim = 1; - span->span = 0; - span = span->next; - } - -} - -void lo_SetTableDimensions( lo_DocState *state, lo_TableRec *table, int32 allow_percent_width, int32 allow_percent_height) -{ - int32 val; - - if (table->percent_width > 0) - { - val = table->percent_width; - if (allow_percent_width == FALSE) - { - val = 0; - } - else - { - val = (state->win_width - state->win_left - - state->win_right) * val / 100; - } - if (val < 0) - { - val = 0; - } - table->width = val; - } - - if (table->percent_height > 0) - { - val = table->percent_height; - if (allow_percent_height == FALSE) - { - val = 0; - } - else - { - val = (state->win_height - state->win_top - - state->win_bottom) * val / 100; - } - if (val < 0) - { - val = 0; - } - table->height = val; - } -} - -void lo_CalcFixedColWidths( MWContext *context, lo_DocState *state, lo_TableRec *table) -{ - int32 cols = table->fixed_cols; - if (cols > 0) { - int32 count; - int32 table_width; - - table_width = lo_ComputeInternalTableWidth ( context, table, state ); - - /* Split the space up evenly */ - table->default_cell_width = table_width / cols; - - /* and we have all the table width left to play with */ - table->fixed_width_remaining = table_width; - - /* Initialize our width array */ - for ( count = 0; count < cols; ++count ) - { - table->fixed_col_widths[ count ] = 0; - } - } -} - -void lo_UpdateStateAfterBeginTable( lo_DocState *state, lo_TableRec *table) -{ - state->current_table = table; -} - -/* Relayout version of lo_BeginTableRowAttributes() */ -void lo_UpdateTableStateForBeginRow(lo_TableRec *table, lo_TableRow *table_row) -{ - table_row->row_done = FALSE; - table_row->cells = 0; - table_row->cell_list = NULL; - table_row->cell_ptr = NULL; - /* table_row->next = NULL; - - if (table->row_list == NULL) - { - table->row_list = table_row; - table->row_ptr = table_row; - } - else - { - table->row_ptr->next = table_row; - table->row_ptr = table_row; - } - */ - - table->width_span_ptr = NULL; - -} - -/* - * Functions for breaking up lo_BeginTableCellAttributes() - */ -void lo_InitForBeginCell(lo_TableRow *table_row, lo_TableCell *table_cell) -{ - table_cell->must_relayout = FALSE; - table_cell->cell_done = FALSE; - - if (table_row->cell_list == NULL) - { - table_row->cell_list = table_cell; - table_row->cell_ptr = table_cell; - } - else - { - table_row->cell_ptr->next = table_cell; - table_row->cell_ptr = table_cell; - } -} - -void lo_InitSubDocForBeginCell( MWContext *context, lo_DocState *state, lo_TableRec *table ) -{ - lo_TableCell *table_cell = table->row_ptr->cell_ptr; - lo_BeginCellSubDoc(context, - state, - table, - NULL, - NULL, - LO_TILE_BOTH, - NULL, - NULL, - NULL, - NULL, - table_cell->is_a_header, - table->draw_borders, - TRUE); - - /* - * We added a new state. - */ - lo_PushStateLevel ( context ); -} - -static void lo_UpdateCaptionCellFromSubDoc( MWContext *context, lo_DocState *state, LO_SubDocStruct *subdoc, LO_CellStruct *cell_ele) -{ - int32 dx = 0; - int32 dy = 0; - - lo_CreateCellFromSubDoc(context, state, subdoc, cell_ele, &dx, &dy); - lo_ShiftCell(cell_ele, dx, dy); - lo_RenumberCell(state, cell_ele); -} - -/* Only deletes the cell itself. Assumes that stuff the cell points to will get deleted - elsewhere */ -static void lo_FreeCaptionCell( MWContext *context, lo_DocState *state, LO_CellStruct *cell_ele) -{ - cell_ele->next = NULL; - cell_ele->prev = NULL; - cell_ele->cell_list = NULL; - cell_ele->cell_list_end = NULL; - cell_ele->cell_float_list = NULL; - cell_ele->table_cell = NULL; - cell_ele->table_row = NULL; - cell_ele->table = NULL; - - lo_FreeElement(context, (LO_Element *)cell_ele, TRUE); - -} - -/* Delete the lo_TableRec data structure associated with the LO_TABLE element. - Does not free the LO_TABLE element itself. */ -void lo_ScrapeTableElement( MWContext *context, LO_TableStruct *table_ele ) -{ - lo_TableRec *table = (lo_TableRec *) table_ele->table; - lo_TopState *top_state = lo_FetchTopState(XP_DOCID(context)); - lo_DocState *state = top_state->doc_state; - - if (table != NULL) - { - /* Free the table row list */ - if (table->row_list != NULL) - { - lo_TableRow *row_ptr; - lo_TableRow *row; - - row_ptr = table->row_list; - while (row_ptr != NULL) - { - row = row_ptr; - row_ptr = row_ptr->next; - - /* The lo_TableCell structures will get freed when their peer - LO_CELL elements get recycled, so just null out the pointers - to those structures. */ - row->cell_list = NULL; - row->cell_ptr = NULL; - - XP_FREEIF(row->backdrop.bg_color); - XP_FREEIF(row->backdrop.url); - XP_DELETE(row); - } - table->row_list = NULL; - table->row_ptr = NULL; - } - - /* Clean up the line array pointers to the elements contained inside the caption - cell. Otherwise, the freeing of the caption frees those elements and a double - free crash occurs when those elements are freed by their peer LO_CELL element */ - if (table->caption && table->caption->subdoc && - table->caption->subdoc->state) - lo_cleanup_old_state( table->caption->subdoc->state ); - - lo_FreeAllExceptRows( context, state, table ); - } -} - - -static void lo_FreeAllExceptRows( MWContext *context, lo_DocState *state, lo_TableRec *table ) -{ - /* Free backdrop info */ - XP_FREEIF(table->backdrop.bg_color); - XP_FREEIF(table->backdrop.url); - - /* Free width and height span arrays */ - lo_FreeTableSpanArray(table->width_spans); - table->width_spans = NULL; - table->width_span_ptr = NULL; - - lo_FreeTableSpanArray(table->height_spans); - table->height_spans = NULL; - table->height_span_ptr = NULL; - - /* Free caption information. */ - if (table->caption != NULL) - { - /* The LO_CELL element associated with the caption will get freed - when it gets recycled in the line list. So, just null out the - pointer to it. */ - table->caption->cell_ele = NULL; - - if ( table->caption->subdoc != NULL ) - { - lo_FreePartialSubDoc ( context, state, table->caption->subdoc ); - table->caption->subdoc = NULL; - } - - XP_DELETE(table->caption); - table->caption = NULL; - } - - /* Free the subdoc state */ - if (table->current_subdoc != NULL) - { - lo_FreePartialSubDoc(context, state, table->current_subdoc); - table->current_subdoc = NULL; - } - - - if ( table->fixed_col_widths != NULL ) - { - XP_FREE(table->fixed_col_widths); - } - - /* Reset back pointer in table layout element */ - if (table->table_ele != NULL) { - table->table_ele->table = NULL; - } - - XP_DELETE(table); -} - -static void lo_FreeTableSpanArray( lo_table_span *spanArray ) -{ - if (spanArray != NULL) - { - lo_table_span *span_ptr; - lo_table_span *span; - - span_ptr = spanArray; - while (span_ptr != NULL) - { - span = span_ptr; - span_ptr = span_ptr->next; - XP_DELETE(span); - } - } -} - -#ifdef TEST_16BIT -#undef XP_WIN16 -#endif /* TEST_16BIT */ diff --git a/lib/layout/laytags.c b/lib/layout/laytags.c index 209881bc506..cd4a940a4f8 100644 --- a/lib/layout/laytags.c +++ b/lib/layout/laytags.c @@ -1367,63 +1367,6 @@ lo_process_header_tag(MWContext *context, lo_DocState *state, PA_Tag *tag, int t } } -static void -lo_process_span_tag(MWContext *context, lo_DocState *state, PA_Tag *tag) -{ - LO_SpanStruct *span; - PA_Block buff; - lo_DocLists *doc_lists; - - doc_lists = lo_GetCurrentDocLists(state); - - span = (LO_SpanStruct*)lo_NewElement(context, state, LO_SPAN, NULL, 0); - XP_ASSERT(span); - if (!span) return; - - span->lo_any.type = LO_SPAN; - span->lo_any.ele_id = NEXT_ELEMENT; - span->is_end = tag->is_end; - - span->lo_any.x = state->x; - span->lo_any.y = state->y; - span->lo_any.x_offset = 0; - span->lo_any.y_offset = 0; - span->lo_any.width = 0; - span->lo_any.height = 0; - span->lo_any.line_height = 0; - -#ifdef DOM - span->name_rec = NULL; - if (tag->is_end == FALSE) - { - /* get the span's ID. */ - buff = lo_FetchParamValue(context, tag, PARAM_ID); - if (buff != NULL) - { - state->in_span = TRUE; - state->current_span = buff; - if (lo_SetNamedSpan(state, buff)) - { - lo_BindNamedSpanToElement(state, buff, NULL); - lo_ReflectSpan(context, state, tag, - doc_lists->span_list, - lo_CurrentLayerId(state)); - span->name_rec = doc_lists->span_list; - } - - PA_UNLOCK(buff); - } - lo_AppendToLineList(context, state, (LO_Element*)span, 0); - state->in_span = TRUE; - } - else - { - state->in_span = FALSE; - lo_AppendToLineList(context, state, (LO_Element*)span, 0); - } -#endif -} - static void lo_process_div_tag(MWContext *context, lo_DocState *state, PA_Tag *tag) { @@ -4397,12 +4340,6 @@ lo_IsEmptyTag(TagType type) || type == P_EMBED || type == P_KEYGEN || type == P_JAVA_APPLET -#ifndef DOM - || type == P_LIST_ITEM /* not really empty! */ - || type == P_DESC_TITLE - || type == P_NSDT - || type == P_DESC_TEXT -#endif || type == P_BASEFONT || type == P_AREA || type == P_BASE) @@ -7548,9 +7485,6 @@ XP_TRACE(("lo_LayoutTag(%d)\n", tag->type)); */ case P_SPAN: { -#ifdef DOM - lo_process_span_tag(context, state, tag); -#endif break; } diff --git a/lib/layout/laytext.c b/lib/layout/laytext.c index 79f33cb7203..e69de29bb2d 100644 --- a/lib/layout/laytext.c +++ b/lib/layout/laytext.c @@ -1,8735 +0,0 @@ -/* -*- Mode: C; tab-width: 4; 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. - */ - -#include "xp.h" -#include "pa_tags.h" -#include "layout.h" -#include "laylayer.h" -#include "layers.h" -#include "libi18n.h" -#include "edt.h" -#include "laystyle.h" -#include "laytrav.h" - -#ifdef DOM -#include "domstyle.h" -#include "lm_dom.h" -#include "laydom.h" -#endif - -/* - * Turn this define on to get the new multibyte parsing code -#define FAST_MULTI -*/ - -#define FAST_EDITOR - -#ifdef TEST_16BIT -#define XP_WIN16 -#endif /* TEST_16BIT */ - -#ifdef XP_WIN16 -#define SIZE_LIMIT 32000 -#endif /* XP_WIN16 */ - -#ifdef XP_UNIX -#define TEXT_CHUNK_LIMIT 500 -#else -#define TEXT_CHUNK_LIMIT 1600 -#endif - -#ifdef XP_MAC -#define NON_BREAKING_SPACE 0x07 -#else -#define NON_BREAKING_SPACE 160 -#endif - -#ifdef PROFILE -#pragma profile on -#endif - -int32 lo_correct_text_element_width(LO_TextInfo *); - -static void lo_insert_quote_characters(MWContext *context, - lo_DocState *state); -static LO_TextStruct * lo_new_text_element(MWContext *context, - lo_DocState *state, - ED_Element *edit_element, - intn edit_offset ); - -void lo_LayoutFormattedText(MWContext *context, - lo_DocState *state, - LO_TextBlock * block); -void lo_LayoutPreformattedText(MWContext *context, - lo_DocState *state, - LO_TextBlock * block); -LO_TextBlock * lo_NewTextBlock (MWContext * context, - lo_DocState * state, - char * text, - uint16 formatMode ); -int32 lo_compute_text_basline_inc (lo_DocState * state, - LO_TextBlock * block, - LO_TextStruct * text_data ); - -uint32 lo_FindBlockOffset (LO_TextBlock * block, - LO_TextStruct * fromElement ); -void lo_RelayoutTextElements (MWContext * context, - lo_DocState * state, - LO_TextBlock * block, - LO_TextStruct * fromElement ); -Bool lo_CanUseBreakTable (lo_DocState * state ); -Bool lo_UseBreakTable (LO_TextBlock * block ); - -void lo_AppendTextToBlock (MWContext *context, - lo_DocState *state, - LO_TextBlock * block, - char *text ); -void lo_LayoutTextBlock (MWContext * context, - lo_DocState * state, - Bool flushLastLine ); -static void lo_FlushText (MWContext * context, - lo_DocState * state ); -static void lo_SetupBreakState (LO_TextBlock * block ); - -Bool lo_GrowTextBlock (LO_TextBlock * block, - uint32 length ); - -typedef enum { - kSimpleSBTextParseAttribute = 0, - kMBTextParseAttribute, - kThaiTextParseAttribute - } loTextParseAttribute; -static loTextParseAttribute lo_GetTextParseAttributes (lo_DocState * state); - -#ifdef XP_MAC -#define kStaticMeasureTextBufferSize 512 -static uint16 gMeasureTextBuffer[ kStaticMeasureTextBufferSize ]; - -/* This needs to go in fe_proto.h - will move it there once we're out - of the branch */ -#define FE_MeasureText(context, text, charLocs) \ - (*context->funcs->MeasureText)(context, text, charLocs) -#endif - -#ifdef XP_MAC -Bool gCallNewText = TRUE; -#endif - -LO_TextBlock * lo_NewTextBlock ( MWContext * context, - lo_DocState * state, - char * text, - uint16 formatMode ) -{ - LO_TextBlock * block; - uint32 length; - - length = strlen ( text ); - - block = (LO_TextBlock *)lo_NewElement ( context, state, - LO_TEXTBLOCK, NULL, 0 ); - if ( block == NULL ) - { - state->top_state->out_of_memory = TRUE; - return NULL; - } - - block->type = LO_TEXTBLOCK; - block->x_offset = 0; - block->ele_id = NEXT_ELEMENT; - block->x = state->x; - block->y = state->y; - block->y_offset = 0; - block->width = 0; - block->height = 0; - block->line_height = 0; - block->next = NULL; - block->prev = NULL; - block->text_attr = NULL; - block->anchor_href = NULL; - block->ele_attrmask = 0; - block->format_mode = 0; - - block->startTextElement = NULL; - block->endTextElement = NULL; - - block->text_buffer = NULL; - block->buffer_length = 0; - block->buffer_write_index = 0; - block->last_buffer_write_index = 0; - block->buffer_read_index = 0; - block->last_line_break = 0; - - block->break_table = NULL; - block->break_length = 0; - block->break_write_index = 0; - block->break_read_index = 0; - block->last_break_offset = 0; - - block->multibyte_index = 0; - block->multibyte_length = 0; - - block->old_break = NULL; - block->old_break_pos = 0; - block->old_break_width = 0; - - block->totalWidth = 0; - block->totalChars = 0; - block->break_pending = 0; - block->last_char_is_whitespace = 0; - - block->ascent = 0; - block->descent = 0; - - block->text_buffer = XP_ALLOC ( length + 1 ); - if ( block->text_buffer == NULL ) - { - XP_FREE ( block ); - state->top_state->out_of_memory = TRUE; - return NULL; - } - - block->buffer_length = length + 1; - XP_BCOPY ( text, block->text_buffer, length ); - block->text_buffer[ length ] = '\0'; - block->buffer_write_index = length; - - /* default text does not have a break table */ - block->break_table = NULL; - block->break_length = 0; - - block->format_mode = formatMode; - - /* - * Since we're creating a new text block, grab some of the text - * state out of the layout state. - */ - block->anchor_href = state->current_anchor; - - if ( state->font_stack != NULL ) - { - /* TEXTATTR HERE */ -#ifdef DOM - block->text_attr = lo_GetCurrentTextAttr(state, context); -#else - block->text_attr = state->font_stack->text_attr; -#endif - } - - if (state->breakable != FALSE) - { - block->ele_attrmask |= LO_ELE_BREAKABLE; - } - - state->cur_text_block = block; - - lo_AppendToLineList ( context, state, (LO_Element *) block, 0 ); - - return block; -} - -void -lo_SetDefaultFontAttr(lo_DocState *state, LO_TextAttr *tptr, - MWContext *context) -{ - tptr->size = DEFAULT_BASE_FONT_SIZE; - tptr->fontmask = 0; - tptr->no_background = TRUE; - tptr->attrmask = 0; - tptr->fg.red = STATE_DEFAULT_FG_RED(state); - tptr->fg.green = STATE_DEFAULT_FG_GREEN(state); - tptr->fg.blue = STATE_DEFAULT_FG_BLUE(state); - tptr->bg.red = STATE_DEFAULT_BG_RED(state); - tptr->bg.green = STATE_DEFAULT_BG_GREEN(state); - tptr->bg.blue = STATE_DEFAULT_BG_BLUE(state); - tptr->charset = INTL_DefaultTextAttributeCharSetID(context); - tptr->font_face = NULL; - tptr->FE_Data = NULL; - tptr->point_size = 0; - tptr->font_weight = 0; -} - - -/************************************* - * Function: lo_DefaultFont - * - * Description: This function sets up the text attribute - * structure for the default text drawing font. - * This is the font that sits at the bottom of the font - * stack, and can never be popped off. - * - * Params: Document state - * - * Returns: A pointer to a lo_FontStack structure. - * Returns a NULL on error (such as out of memory); - *************************************/ -lo_FontStack * -lo_DefaultFont(lo_DocState *state, MWContext *context) -{ - LO_TextAttr tmp_attr; - lo_FontStack *fptr; - LO_TextAttr *tptr; - - /* - * Fill in default font information. - */ - lo_SetDefaultFontAttr(state, &tmp_attr, context); - tptr = lo_FetchTextAttr(state, &tmp_attr); - - fptr = XP_NEW(lo_FontStack); - if (fptr == NULL) - { - return(NULL); - } - fptr->tag_type = P_UNKNOWN; - fptr->text_attr = tptr; - fptr->next = NULL; - - return(fptr); -} - -/* -** lo_PushAlignment -** -** Pushes a new alignment entry onto the alignment stack. Alignment -** entries are tagged with both the actually alignment type (CENTER, -** LEFT, RIGHT, MIDDLE, etc.) as well as the tag that contained the -** alignment attribute. The latter is so we can accurately lookup the -** alignment for a given tag type.. -*/ -void -lo_PushAlignment(lo_DocState *state, intn tag_type, int32 alignment) -{ - lo_AlignStack *aptr; - - aptr = XP_NEW(lo_AlignStack); - if (aptr == NULL) - { - state->top_state->out_of_memory = TRUE; - return; - } - - aptr->type = tag_type; - aptr->alignment = alignment; - - aptr->next = state->align_stack; - state->align_stack = aptr; -} - - -/* -** lo_PopAlignment -** -** Pops off the top entry from the alignment stack. -*/ -lo_AlignStack * -lo_PopAlignment(lo_DocState *state) -{ - lo_AlignStack *aptr; - - aptr = state->align_stack; - if (aptr != NULL) - { - state->align_stack = aptr->next; - aptr->next = NULL; - } - return(aptr); -} - -void -lo_PushLineHeight(lo_DocState *state, int32 height) -{ - lo_LineHeightStack *aptr; - - aptr = XP_NEW(lo_LineHeightStack); - if (aptr == NULL) - { - state->top_state->out_of_memory = TRUE; - return; - } - - aptr->height = height; - - aptr->next = state->line_height_stack; - state->line_height_stack = aptr; -} - -lo_LineHeightStack * -lo_PopLineHeight(lo_DocState *state) -{ - lo_LineHeightStack *aptr; - - aptr = state->line_height_stack; - if (aptr != NULL) - { - state->line_height_stack = aptr->next; - aptr->next = NULL; - } - return(aptr); -} - -/************************************* - * Function: lo_FreshText - * - * Description: This function clears out the information from the - * document state that refers to text in the midst of being - * laid out. It is called to clear the layout state before - * Laying out new text potentially in a new font. - * - * Params: Document state structure. - * - * Returns: Nothing - *************************************/ -void -lo_FreshText(lo_DocState *state) -{ - 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; - state->line_buf_len = 0; - state->break_pos = -1; - state->break_width = 0; - state->last_char_CR = FALSE; -#ifdef EDITOR - if( !state->edit_force_offset ) - { - state->edit_current_offset = 0; - } -#endif -} - - -/************************************* - * Function: lo_new_text_element - * - * Description: Create a new text element structure based - * on the current text information stored in the document - * state. - * - * Params: Document state - * - * Returns: A pointer to a LO_TextStruct structure. - * Returns a NULL on error (such as out of memory); - *************************************/ -static LO_TextStruct * -lo_new_text_element(MWContext *context, - lo_DocState *state, - ED_Element *edit_element, - intn edit_offset ) -{ - LO_TextStruct *text_ele = NULL; -#ifdef DEBUG - assert (state); -#endif - - if (state == NULL) - { - return(NULL); - } - - text_ele = (LO_TextStruct *)lo_NewElement(context, state, LO_TEXT, - edit_element, edit_offset); - if (text_ele == NULL) - { -#ifdef DEBUG - assert (state->top_state->out_of_memory); -#endif - return(NULL); - } - - text_ele->type = LO_TEXT; - text_ele->ele_id = NEXT_ELEMENT; - text_ele->x = state->x; - text_ele->x_offset = 0; - text_ele->y = state->y; - text_ele->y_offset = 0; - text_ele->width = 0; - text_ele->height = 0; - text_ele->line_height = 0; - text_ele->next = NULL; - text_ele->prev = NULL; - - if (state->line_buf_len > 0) - { - text_ele->text = PA_ALLOC((state->line_buf_len + 1) * - sizeof(char)); - if (text_ele->text != NULL) - { - char *text_buf; - char *line; - - PA_LOCK(line, char *, state->line_buf); - PA_LOCK(text_buf, char *, text_ele->text); - XP_BCOPY(line, text_buf, state->line_buf_len); - text_buf[state->line_buf_len] = '\0'; - PA_UNLOCK(text_ele->text); - PA_UNLOCK(state->line_buf); - text_ele->text_len = (int16)state->line_buf_len; - } - else - { - state->top_state->out_of_memory = TRUE; - /* - * free text element && return; it's no different - * than if we had run out of memory allocating - * the text element - */ - lo_FreeElement(context, (LO_Element *)text_ele, FALSE); - return(NULL); - } - } - else - { - text_ele->text = NULL; - text_ele->text_len = 0; - } - - /* Fix for bug#124552. Look at both the state structure and the - current text block for anchor information. */ - text_ele->anchor_href = state->current_anchor; - if (state->current_anchor == NULL && - state->cur_text_block != NULL && - state->cur_text_block->anchor_href != NULL) - { - text_ele->anchor_href = state->cur_text_block->anchor_href; - } - - if (state->font_stack == NULL) - { - text_ele->text_attr = NULL; - } - else - { - text_ele->text_attr = state->cur_text_block->text_attr; - } - - text_ele->ele_attrmask = 0; - if (state->breakable != FALSE) - { - text_ele->ele_attrmask |= LO_ELE_BREAKABLE; - } - - text_ele->sel_start = -1; - text_ele->sel_end = -1; - - return(text_ele); -} - - -/* - * A bogus an probably too expensive function to fill in the - * textinfo for whatever font is now on the font stack. - */ -MODULE_PRIVATE void -lo_fillin_text_info(MWContext *context, lo_DocState *state) -{ - LO_TextStruct tmp_text; - PA_Block buff; - char *str; - - memset (&tmp_text, 0, sizeof (tmp_text)); - buff = PA_ALLOC(1); - if (buff == NULL) - { - return; - } - PA_LOCK(str, char *, buff); - str[0] = ' '; - PA_UNLOCK(buff); - tmp_text.text = buff; - tmp_text.text_len = 1; - - /* if we have a text block, use it's font info, otherwise get it - from the state */ - if ( state->cur_text_block == NULL ) - { - /* TEXTATTR HERE */ -#ifdef DOM - tmp_text.text_attr = lo_GetCurrentTextAttr(state, context); -#else - tmp_text.text_attr = state->font_stack->text_attr; -#endif - } - else - { - tmp_text.text_attr = state->cur_text_block->text_attr; - } - - FE_GetTextInfo(context, &tmp_text, &(state->text_info)); - PA_FREE(buff); -} - - -/************************************* - * Function: lo_NewLinefeed - * - * Description: Create a new linefeed element structure based - * on the current information stored in the document - * state. - * - * Params: Document state, linefeed type - * - * Returns: A pointer to a LO_LinefeedStruct structure. - * Returns a NULL on error (such as out of memory); - *************************************/ -LO_LinefeedStruct * -lo_NewLinefeed(lo_DocState *state, - MWContext * context, - uint32 break_type, - uint32 clear_type) -{ - LO_LinefeedStruct *linefeed = NULL; - - if (state == NULL) - { - return(NULL); - } - - linefeed = (LO_LinefeedStruct *)lo_NewElement(context, state, LO_LINEFEED, NULL, 0); -#ifdef DEBUG - assert (state); -#endif - if (linefeed == NULL) - { -#ifdef DEBUG - assert (state->top_state->out_of_memory); -#endif - state->top_state->out_of_memory = TRUE; - return(NULL); - } - - lo_FillInLineFeed( context, state, break_type, clear_type, linefeed ); - - return(linefeed); -} - - - -/************************************* - * Function: lo_InsertLineBreak - * - * Description: This function forces a linebreak at this time. - * Forcing the current text insetion point down one line - * and back to the left margin. - * It also maintains the linefeed state: - * 0 - middle of a line. - * 1 - at left margin below a line of text. - * 2 - at left margin below a blank line. - * - * Params: Window context, Document state, break type and a boolean - * That describes whether this is a breaking linefeed or not. - * (Breaking linefeed is one inserted just to break a formatted - * line to the current document width.) - * - * Returns: Nothing - *************************************/ -void -lo_InsertLineBreak(MWContext *context, - lo_DocState *state, - uint32 break_type, - uint32 clear_type, - Bool breaking) -{ - /* int32 line_width; */ - Bool scroll_at_bottom; - - scroll_at_bottom = FALSE; - /* - * If this is an auto-scrolling doc, we will be scrolling - * later if we are at the bottom now. - */ - if ((state->is_a_subdoc == SUBDOC_NOT)&& - (state->display_blocked == FALSE)&& - (state->top_state->auto_scroll > 0)) - { - int32 doc_x, doc_y; - - FE_GetDocPosition(context, FE_VIEW, &doc_x, &doc_y); - if ((doc_y + state->win_height + state->win_bottom) >= state->y) - { - scroll_at_bottom = TRUE; - } - } - - /* - * This line is done, flush it into the line table and - * display it to the front end. - */ - lo_FlushLineList(context, state, break_type, clear_type, breaking); - if (state->top_state->out_of_memory != FALSE) - { - return; - } - - lo_UpdateStateAfterLineBreak( context, state, TRUE ); - - lo_UpdateFEProgressBar(context, state); - - lo_UpdateFEDocSize( context, state ); - - - /* - * Tell the front end how big the document is right now. - * Only do this for the top level document. - */ - if ((state->display_blocked != FALSE)&& -#ifdef EDITOR - (!state->edit_relayout_display_blocked)&& -#endif - (state->display_blocking_element_y > 0)&& - (state->y > (state->display_blocking_element_y + state->win_height))) - { - int32 y; - - state->display_blocked = FALSE; - y = state->display_blocking_element_y; - state->display_blocking_element_y = 0; - if (!lo_InsideLayer(state)) - { - LO_SetDocumentDimensions(context, state->max_width, state->y); - } - FE_SetDocPosition(context, FE_VIEW, 0, y); - - if (context->compositor) - { - XP_Rect rect; - - rect.left = 0; - rect.top = y; - rect.right = state->win_width; - rect.bottom = y + state->win_height; - CL_UpdateDocumentRect(context->compositor, - &rect, (PRBool)FALSE); - } - } - - /* - * Reset the left and right margins - */ - /* - lo_FindLineMargins(context, state, TRUE); - state->x = state->left_margin; - */ - if ((state->is_a_subdoc == SUBDOC_NOT)&& - (state->top_state->auto_scroll > 0)&& - ((state->line_num - 1) > state->top_state->auto_scroll)) - { - Bool redraw; - int32 old_y, dy, new_y; - int32 doc_x, doc_y; - - old_y = state->y; - FE_GetDocPosition(context, FE_VIEW, &doc_x, &doc_y); - lo_ClipLines(context, state, 1); - /* - * Calculate how much of the top was clipped - * off, and if any of that area was in the users - * window we need to redraw their window. - */ - redraw = FALSE; - dy = old_y - state->y; - if (dy >= doc_y) - { - redraw = TRUE; - } - new_y = doc_y - dy; - if (new_y < 0) - { - new_y = 0; - } - - FE_SetDocPosition(context, FE_VIEW, doc_x, new_y); - if (!lo_InsideLayer(state)) - { - LO_SetDocumentDimensions(context, state->max_width, state->y); - } - - if (redraw != FALSE) - { - FE_ClearView(context, FE_VIEW ); - if (context->compositor) - { - XP_Rect rect; - - rect.left = 0; - rect.top = new_y; - rect.right = state->win_width; - rect.bottom = new_y + state->win_height; - CL_UpdateDocumentRect(context->compositor, - &rect, (PRBool)FALSE); - } - } - } - - if ((state->is_a_subdoc == SUBDOC_NOT)&& - (state->display_blocked == FALSE)&& - (state->top_state->auto_scroll > 0)) - { - int32 doc_x, doc_y; - - FE_GetDocPosition(context, FE_VIEW, &doc_x, &doc_y); - if (((doc_y + state->win_height) < state->y)&& - (scroll_at_bottom != FALSE)) - { - int32 y; - - y = state->y - state->win_height + state->win_bottom; - if (y < 0) - { - y = 0; - } - else - { - FE_SetDocPosition(context, FE_VIEW, 0, y); - } - } - } - - lo_insert_quote_characters(context, state); -} - -/************************************* - * Function: lo_HardLineBreak - * - * Description: This function forces a linebreak at this time. - * Forcing the current text insetion point down one line - * and back to the left margin. - * - * Params: Window context, Document state and a boolean - * That describes whether this is a breaking linefeed or not. - * (Breaking linefeed is one inserted just to break a formatted - * line to the current document width.) - * - * Returns: Nothing - *************************************/ -void -lo_HardLineBreak(MWContext *context, lo_DocState *state, Bool breaking) -{ - lo_InsertLineBreak ( context, state, LO_LINEFEED_BREAK_HARD, - LO_CLEAR_NONE, breaking ); -} - -/************************************* - * Function: lo_HardLineBreakWithBreak - * - * Returns: Nothing - *************************************/ -void -lo_HardLineBreakWithClearType(MWContext *context, - lo_DocState *state, - uint32 clear_type, - Bool breaking) -{ - lo_InsertLineBreak ( context, state, LO_LINEFEED_BREAK_HARD, - clear_type, breaking ); -} - -/************************************* - * Function: lo_SoftLineBreak - * - * Description: This function adds a single soft line break. - * - * Params: Window context, Document state and a boolean that - * describes if this is a breaking linefeed. - * - * Returns: Nothing - *************************************/ -void -lo_SoftLineBreak(MWContext *context, lo_DocState *state, Bool breaking) -{ - lo_InsertLineBreak ( context, state, LO_LINEFEED_BREAK_SOFT, - LO_CLEAR_NONE, breaking); -} - -/************************************* - * Function: lo_SetSoftLineBreakState - * - * Description: Add soft linebreaks to bring the linefeed state to the - * specified level. - * Linefeed states: - * 0 - middle of a line. - * 1 - at left margin below a line of text. - * 2 - at left margin below a blank line. - * - * Params: Window context, Document state, a boolean that - * describes if this is a breaking linefeed, and the desired - * linefeed state. - * - * Returns: Nothing - *************************************/ -void -lo_SetSoftLineBreakState(MWContext *context, - lo_DocState *state, - Bool breaking, - intn linefeed_state) -{ - lo_SetLineBreakState ( context, state, breaking, LO_LINEFEED_BREAK_SOFT, - linefeed_state, FALSE); -} - -/************************************* - * Function: lo_SetLineBreakState - * - * Description: Add linebreaks to bring the linefeed state to the - * specified level. - * Linefeed states: - * 0 - middle of a line. - * 1 - at left margin below a line of text. - * 2 - at left margin below a blank line. - * - * Params: Window context, Document state, a boolean that - * describes if this is a breaking linefeed, and the desired - * linefeed state. - * - * Returns: Nothing - *************************************/ -void -lo_SetLineBreakState(MWContext *context, - lo_DocState *state, - Bool breaking, - uint32 break_type, - intn linefeed_state, - Bool relayout) -{ - /* - * Linefeeds are partially disabled if we are placing - * preformatted text. - */ - if (state->preformatted != PRE_TEXT_NO) - { - if ((breaking == FALSE)&&(state->linefeed_state < 1)&& - (state->top_state->out_of_memory == FALSE)) - { - if (relayout == FALSE) - { - lo_InsertLineBreak(context, state, break_type, - LO_CLEAR_NONE, breaking); - } - else - { - lo_rl_AddBreakAndFlushLine( context, state, - break_type, LO_CLEAR_NONE, - breaking); - } - } - return; - } - - /* check for the style sheet display: inline property. - * ignore newlines if it is set - */ - if(state->top_state && state->top_state->style_stack) - { - StyleStruct *style = STYLESTACK_GetStyleByIndex( - state->top_state->style_stack, - 0); - if(style) - { - char * property = STYLESTRUCT_GetString(style, DISPLAY_STYLE); - if(property && !strcasecomp(property, INLINE_STYLE)) - { - XP_FREE(property); - return; - } - XP_FREEIF(property); - } - } - - if (linefeed_state > 2) - { - linefeed_state = 2; - } - - while ((state->linefeed_state < linefeed_state)&& - (state->top_state->out_of_memory == FALSE)) - { - if (relayout == FALSE) - { - lo_InsertLineBreak(context, state, break_type, - LO_CLEAR_NONE, breaking); - } - else - { - lo_rl_AddBreakAndFlushLine( context, state, break_type, - LO_CLEAR_NONE, breaking ); - } - } -} - -/************************************* - * Function: lo_InsertWordBreak - * - * Description: This insert a word break into the laid out - * element chain for the current line. A word break is - * basically an empty text element structure. All - * word break elements should probably be removed - * from the layout chain once the line list for this - * line is flushed. - * - * Params: Window context and document state. - * - * Returns: Nothing - *************************************/ -void -lo_InsertWordBreak(MWContext *context, lo_DocState *state) -{ - LO_TextStruct *text_ele = NULL; - - if (state == NULL) - { - return; - } - - text_ele = (LO_TextStruct *)lo_NewElement(context, state, - LO_TEXT, NULL, 0); - if (text_ele == NULL) - { -#ifdef DEBUG - assert (state->top_state->out_of_memory); -#endif - return; - } - - text_ele->type = LO_TEXT; - text_ele->ele_id = NEXT_ELEMENT; - text_ele->x = state->x; - text_ele->x_offset = 0; - text_ele->y = state->y; - text_ele->y_offset = 0; - text_ele->width = 0; - text_ele->height = 0; - text_ele->line_height = 0; - text_ele->next = NULL; - text_ele->prev = NULL; - - text_ele->block_offset = 0; - text_ele->doc_width = 0; - -#if 0 - text_ele->text = PA_ALLOC(sizeof(char)); - if (text_ele->text != NULL) - { - PA_LOCK(text_buf, char *, text_ele->text); - text_buf[0] = '\0'; - PA_UNLOCK(text_ele->text); - } - else - { - state->top_state->out_of_memory = TRUE; - } -#else - text_ele->text = NULL; -#endif - text_ele->text_len = 0; - text_ele->anchor_href = state->current_anchor; - - /* TEXTATTR HERE */ - if (state->font_stack == NULL) - { - text_ele->text_attr = NULL; - } - else - { -#ifdef DOM - text_ele->text_attr = lo_GetCurrentTextAttr(state, context); -#else - text_ele->text_attr = state->font_stack->text_attr; -#endif - } - - text_ele->ele_attrmask = 0; - if (state->breakable != FALSE) - { - text_ele->ele_attrmask |= LO_ELE_BREAKABLE; - } - - text_ele->sel_start = -1; - text_ele->sel_end = -1; - text_ele->bullet_type = WORDBREAK; - - lo_AppendToLineList(context, state, (LO_Element *)text_ele, 0); - - state->old_break = text_ele; - state->old_break_block = state->cur_text_block; - state->old_break_pos = 0; - state->old_break_width = 0; -} - - -int32 -lo_baseline_adjust(MWContext *context, - lo_DocState * state, - LO_Element *ele_list, - int32 old_baseline, - int32 old_line_height) -{ - LO_Element *eptr; - int32 baseline; - int32 new_height; - int32 baseline_adjust; - LO_TextInfo text_info; - - baseline = 0; - new_height = 0; - eptr = ele_list; - while (eptr != NULL) - { - switch (eptr->type) - { - case LO_TEXT: - FE_GetTextInfo(context, (LO_TextStruct *)eptr, - &text_info); - if (text_info.ascent > baseline) - { - baseline = text_info.ascent; - } - if ((text_info.ascent + text_info.descent) > - new_height) - { - new_height = text_info.ascent + - text_info.descent; - } - break; - case LO_FORM_ELE: - if (eptr->lo_form.baseline > baseline) - { - baseline = eptr->lo_form.baseline; - } - if (eptr->lo_any.height > new_height) - { - new_height = eptr->lo_any.height; - } - break; - case LO_IMAGE: - if ((old_baseline - eptr->lo_any.y_offset) > - baseline) - { - baseline = old_baseline - - eptr->lo_any.y_offset; - } - if ((eptr->lo_image.height + - (2 * eptr->lo_image.border_width) + - (2 * eptr->lo_image.border_vert_space)) - > new_height) - { - new_height = eptr->lo_image.height + - (2 * eptr->lo_image.border_width) + - (2 * eptr->lo_image.border_vert_space); - } - break; - case LO_HRULE: - case LO_BULLET: - if ((old_baseline - eptr->lo_any.y_offset) > - baseline) - { - baseline = old_baseline - - eptr->lo_any.y_offset; - } - if (eptr->lo_any.height > new_height) - { - new_height = eptr->lo_any.height; - } - break; - default: - break; - } - eptr = eptr->lo_any.next; - } - baseline_adjust = old_baseline - baseline; - return(baseline_adjust); -} - - -/************************************* - * Function: lo_BreakOldElement - * - * Description: This function goes back to a previous - * element in the element chain, that is still on the - * same line, and breaks the line there, putting the - * remaining elements (if any) on the next line. - * - * Params: Window context and document state. - * - * Returns: Nothing - *************************************/ -void -lo_BreakOldElement(MWContext *context, lo_DocState *state) -{ - char *text_buf; - char *break_ptr; - char *word_ptr; - char *new_buf; - PA_Block new_block; - intn word_len; - int32 save_width; - int32 old_baseline; - int32 old_line_height; - int32 adjust; - LO_TextStruct *text_data; - LO_TextStruct *new_text_data; - LO_Element *tptr; - int16 charset; - int multi_byte; - LO_TextBlock * block; -#ifdef LOCAL_DEBUG -XP_TRACE(("lo_BreakOldElement, flush text.\n")); -#endif /* LOCAL_DEBUG */ - - if (state == NULL) - { - return; - } - - /* BRAIN DAMAGE: Make sure the correct element is at the end of - the list for this block */ - block = state->old_break_block; - - if ( block == NULL ) - { - return; - } - - /* - * If this text block is using the new breaktable algorithm, - * call that code - */ - if ( lo_UseBreakTable ( block ) ) - { - lo_BreakOldTextBlockElement ( context, state ); - return; - } - - charset = block->text_attr->charset; - multi_byte = (INTL_CharSetType(charset) != SINGLEBYTE); - - /* - * Move to the element we will break - */ - text_data = state->old_break; - - /* - * If there is no text there to break - * it is an error. - */ - if ( text_data == NULL ) - { - return; - } - - /* - * Later operations will trash the width field. - * So save it now to restore later. - */ - save_width = state->width; - - /* - * If this buffer is just an empty string, then we are - * breaking at a previously inserted word break element. - * Knowing that, the breaking is easier, so it is special - * cased here. - */ - if (text_data->text == NULL) - { - LO_Element *line_ptr; - - /* - * Back the state up to this element's - * location, break off the rest of the elements - * and save them for later. - * Flush this line, and insert a linebreak. - */ - state->x = text_data->x; - state->y = text_data->y; - tptr = text_data->next; - text_data->next = NULL; - PA_UNLOCK(text_data->text); - state->width = text_data->width; - state->x += state->width; - lo_SoftLineBreak(context, state, TRUE); - - /* - * The remaining elements go on the next line. - * The nextline may already have special mail - * bullets on it. - */ - line_ptr = state->line_list; - while ((line_ptr != NULL)&&(line_ptr->lo_any.next != NULL)) - { - line_ptr = line_ptr->lo_any.next; - } - if (line_ptr == NULL) - { - state->line_list = tptr; - if (tptr != NULL) - { - tptr->lo_any.prev = NULL; - } - } - else - { - line_ptr->lo_any.next = tptr; - if (tptr != NULL) - { - tptr->lo_any.prev = line_ptr; - } - } - - /* - * If there are no elements to place on the next - * line, and we have new text buffered, - * remove any spaces at the start of that new - * text since new lines are not allowed to begin - * with whitespace. - */ - if ((tptr == NULL)&&(state->line_buf_len != 0)) - { - char *cptr; - int32 wlen; - - PA_LOCK(text_buf, char *, state->line_buf); - cptr = text_buf; - wlen = 0; - while ((XP_IS_SPACE(*cptr))&&(*cptr != '\0')) - { - cptr++; - wlen++; - } - if (wlen) - { - LO_TextStruct tmp_text; - - memset (&tmp_text, 0, sizeof (tmp_text)); - - /* - * We removed space, move the string up - * and recalculate its current width. - */ - XP_BCOPY(cptr, text_buf, - (state->line_buf_len - wlen + 1)); - state->line_buf_len -= (intn) wlen; - PA_UNLOCK(state->line_buf); - tmp_text.text = state->line_buf; - tmp_text.text_len = (int16)state->line_buf_len; - tmp_text.text_attr = - block->text_attr; - FE_GetTextInfo(context, &tmp_text, - &(state->text_info)); - - /* - * Override the saved width since we did want - * to change the real width in this case. - */ - save_width = lo_correct_text_element_width( - &(state->text_info)); - } - else - { - PA_UNLOCK(state->line_buf); - } - } - } - /* - * We are breaking somewhere in the middle of an old - * text element, this will mean splitting it into 2 text - * elements, and putting a line break between them. - */ - else - { - LO_TextInfo text_info; - int32 base_change; - - PA_LOCK(text_buf, char *, text_data->text); - - /* - * Locate our break location, and a pointer to - * the remaining word (with its preceeding space removed). - */ - break_ptr = (char *)(text_buf + state->old_break_pos); - /* - * On multibyte, we often break on character which is - * not space. - */ - if (multi_byte == FALSE || XP_IS_SPACE(*break_ptr)) - { - *break_ptr = '\0'; - word_ptr = (char *)(break_ptr + 1); - } - else - { - word_ptr = (char *)break_ptr; - } - - /* - * Copy the remaining word into its own block. - */ - word_len = XP_STRLEN(word_ptr); - new_block = PA_ALLOC((word_len + 1)); - if (new_block == NULL) - { - state->top_state->out_of_memory = TRUE; - return; - } - PA_LOCK(new_buf, char *, new_block); - XP_BCOPY(word_ptr, new_buf, (word_len + 1)); - new_buf[word_len] = '\0'; - - /* - * Back the state up to this element's - * location, break off the rest of the elements - * and save them for later. - * Flush this line, and insert a linebreak. - */ - state->x = text_data->x; - state->y = text_data->y; - tptr = text_data->next; - text_data->next = NULL; - if (word_ptr != break_ptr) - text_data->text_len = text_data->text_len - word_len - 1; - else - text_data->text_len = text_data->text_len - word_len; - FE_GetTextInfo(context, text_data, &text_info); - state->width = lo_correct_text_element_width(&text_info); - PA_UNLOCK(text_data->text); - state->x += state->width; - - /* - * Make the split element know its new width. - */ - text_data->width = state->width; - - /* - * If the element that caused this break has a different - * baseline than the element we are breaking, we need to - * preserve that difference after the break. - */ - base_change = state->baseline - - (text_data->y_offset + text_info.ascent); - - old_baseline = state->baseline; - old_line_height = state->line_height; - - /* - * Reset element_id so they are still sequencial. - */ - state->top_state->element_id = text_data->ele_id + 1; - - /* - * If we are breaking an anchor, we need to make sure the - * linefeed gets its anchor href set properly. - */ - if (text_data->anchor_href != NULL) - { - LO_AnchorData *tmp_anchor; - - tmp_anchor = state->current_anchor; - state->current_anchor = text_data->anchor_href; - lo_SoftLineBreak(context, state, TRUE); - state->current_anchor = tmp_anchor; - } - else - { - lo_SoftLineBreak(context, state, TRUE); - } - - adjust = lo_baseline_adjust(context, state, tptr, - old_baseline, old_line_height); - state->baseline = old_baseline - adjust; - state->line_height = (intn) old_line_height - adjust; - - /* - * If there was really no remaining word, free the - * unneeded buffer. - */ - if (word_len == 0) - { - LO_Element *eptr; - LO_Element *line_ptr; - - PA_UNLOCK(new_block); - PA_FREE(new_block); - - line_ptr = state->line_list; - while ((line_ptr != NULL)&& - (line_ptr->lo_any.next != NULL)) - { - line_ptr = line_ptr->lo_any.next; - } - if (line_ptr == NULL) - { - state->line_list = tptr; - if (tptr != NULL) - { - tptr->lo_any.prev = NULL; - } - } - else - { - line_ptr->lo_any.next = tptr; - if (tptr != NULL) - { - tptr->lo_any.prev = line_ptr; - } - } - - state->width = 0; - - eptr = tptr; - while (eptr != NULL) - { - eptr->lo_any.ele_id = NEXT_ELEMENT; - eptr->lo_any.y_offset -= adjust; - eptr = eptr->lo_any.next; - } - } - /* - * Else create a new text element for the remaining word. - * and stick it in the begining of the next line of - * text elements. - */ - else - { - LO_Element *line_ptr; - LO_Element *eptr; - int32 baseline_inc; - LO_TextInfo text_info; - baseline_inc = -1 * adjust; - new_text_data = lo_new_text_element(context, state, - text_data->edit_element, - text_data->edit_offset+text_data->text_len+1 ); - if (new_text_data == NULL) - { - return; - } - if (new_text_data->text != NULL) - { - PA_FREE(new_text_data->text); - new_text_data->text = NULL; - new_text_data->text_len = 0; - } - new_text_data->anchor_href = text_data->anchor_href; - new_text_data->text_attr = text_data->text_attr; - new_text_data->x = state->x; - new_text_data->y = state->y; - -#ifdef LOCAL_DEBUG -XP_TRACE(("lo_BreakOldElement, left over word (%s)\n", new_buf)); -#endif /* LOCAL_DEBUG */ - - PA_UNLOCK(new_block); - new_text_data->text = new_block; - new_text_data->text_len = word_len; - FE_GetTextInfo(context, new_text_data, &text_info); - new_text_data->width = - lo_correct_text_element_width(&text_info); - - /* - * Some fonts (particulatly italic ones with curly - * tails on letters like 'f') have a left bearing - * that extends back into the previous character. - * Since in this case the previous character is - * probably not in the same font, we move forward - * to avoid overlap. - */ - if (text_info.lbearing < 0) - { - new_text_data->x_offset = - text_info.lbearing * -1; - } - - /* - * The baseline of the text element just inserted in - * the line may be less than or greater than the - * baseline of the rest of the line due to font - * changes. If the baseline is less, this is easy, - * we just increase y_offest to move the text down - * so the baselines line up. For greater baselines, - * we can't move the text up to line up the baselines - * because we will overlay the previous line, so we - * have to move all rest of the elements in this line - * down. - * - * If the baseline is zero, we are the first element - * on the line, and we get to set the baseline. - */ - if (state->baseline == 0) - { - state->baseline = text_info.ascent; - } - else if (text_info.ascent < state->baseline) - { - new_text_data->y_offset = state->baseline - - text_info.ascent; - } - else - { - baseline_inc = baseline_inc + - (text_info.ascent - state->baseline); - state->baseline = - text_info.ascent; - } - - /* - * Now that we have broken, and added the new - * element, we need to move it down to restore the - * baseline difference that previously existed. - */ - new_text_data->y_offset -= base_change; - - /* - * Calculate the height of this new - * text element. - */ - new_text_data->height = text_info.ascent + - text_info.descent; - state->x += new_text_data->width; - - /* - * Stick this new text element at the beginning - * of the remaining line elements - * There may be some special mail bullets already - * on the line that we have to insert after. - */ - line_ptr = state->line_list; - while ((line_ptr != NULL)&& - (line_ptr->lo_any.next != NULL)) - { - line_ptr = line_ptr->lo_any.next; - } - if (line_ptr == NULL) - { - state->line_list = (LO_Element *)new_text_data; - new_text_data->prev = NULL; - } - else - { - line_ptr->lo_any.next = - (LO_Element *)new_text_data; - new_text_data->prev = line_ptr; - } - new_text_data->next = tptr; - if (tptr != NULL) - { - tptr->lo_any.prev = (LO_Element *)new_text_data; - } - - eptr = tptr; - - while (eptr != NULL) - { - eptr->lo_any.ele_id = NEXT_ELEMENT; - eptr->lo_any.y_offset += baseline_inc; - eptr = eptr->lo_any.next; - } - - if ((new_text_data->y_offset + new_text_data->height) > - state->line_height) - { - state->line_height = (intn) new_text_data->y_offset + - new_text_data->height; - } - - state->at_begin_line = FALSE; - } - } - - /* - * If we are at the beginning of a line, and there is - * remaining text to place here, remove leading space - * which is not allowed at the start of lines. - * ERIC, make a test case for this, I suspect right now - * this code is never being executed and may contain an error. - */ - if ((state->at_begin_line != FALSE)&&(tptr != NULL)&& - (tptr->type == LO_TEXT)) - { - char *cptr; - int32 wlen; - LO_TextStruct *tmp_text; - LO_TextInfo text_info; - - tmp_text = (LO_TextStruct *)tptr; - - PA_LOCK(text_buf, char *, tmp_text->text); - cptr = text_buf; - wlen = 0; - while ((XP_IS_SPACE(*cptr))&&(*cptr != '\0')) - { - cptr++; - wlen++; - } - if (wlen) - { - XP_BCOPY(cptr, text_buf, - (tmp_text->text_len - wlen + 1)); - tmp_text->text_len -= (intn) wlen; - - PA_UNLOCK(tmp_text->text); - FE_GetTextInfo(context, tmp_text, &text_info); - tmp_text->width = lo_correct_text_element_width( - &text_info); - } - else - { - PA_UNLOCK(tmp_text->text); - } - } - - /* - * Upgrade forward the x and y text positions in the document - * state. - */ - while (tptr != NULL) - { - lo_UpdateElementPosition ( state, tptr ); - tptr = tptr->lo_any.next; - } - - state->at_begin_line = FALSE; - state->width = save_width; -} - - -void lo_UpdateElementPosition ( lo_DocState * state, LO_Element * element ) -{ - element->lo_any.x = state->x; - element->lo_any.y = state->y; - state->x = state->x + element->lo_any.width; - - /* move any element specific items */ - switch ( element->lo_any.type ) - { - case LO_IMAGE: - CL_MoveLayer(element->lo_image.layer, - element->lo_any.x, element->lo_any.y); - break; - - case LO_EMBED: - CL_MoveLayer(element->lo_embed.objTag.layer, - element->lo_any.x, element->lo_any.y); - break; - } -} - - -/************************************* - * Function: lo_correct_text_element_width - * - * Description: Calculate the correct width of this text element - * if it is a complete element surrounded by elements of potentially - * different fonts, so we have to take care not to truncate - * any slanted characters at either end of the element. - * - * Params: LO_TextInfo structure for this text element's text string. - * - * Returns: The width this element would have if it stood alone. - *************************************/ -int32 -lo_correct_text_element_width(LO_TextInfo *text_info) -{ - int32 x_offset; - int32 width; - - width = text_info->max_width; - x_offset = 0; - - /* - * For text that leans into the previous character. - */ - if (text_info->lbearing < 0) - { - x_offset = text_info->lbearing * -1; - width += x_offset; - } - - /* - * For text that leans right into the following characters. - */ - if (text_info->rbearing > text_info->max_width) - { - width += (text_info->rbearing - text_info->max_width); - } - - return(width); -} - - -PRIVATE -int32 -lo_characters_in_line(lo_DocState *state) -{ - int32 cnt; - LO_Element *eptr; - - cnt = 0; - eptr = state->line_list; - while (eptr != NULL) - { - if (eptr->type == LO_TEXT) - { - cnt += eptr->lo_text.text_len; - } - eptr = eptr->lo_any.next; - } - return(cnt); -} - -void -lo_PreformatedText(MWContext *context, lo_DocState *state, char *text) -{ - LO_TextBlock * block; - - block = lo_NewTextBlock ( context, state, text, state->preformatted ); - if ( !state->top_state->out_of_memory && ( block != NULL ) ) - { - block->buffer_read_index = 0; - lo_LayoutPreformattedText ( context, state, block ); - } -} - - -void -lo_LayoutPreformattedText(MWContext *context, - lo_DocState *state, - LO_TextBlock * block) -{ - char *tptr; - char *w_start; - char *w_end; - char *text_buf; - char tchar1; - Bool have_CR; - Bool line_break; - Bool white_space; - LO_TextStruct text_data; - char *tmp_buf; - PA_Block tmp_block; - int32 tab_count, ignore_cnt, line_length; - int16 charset; - int multi_byte; - int kinsoku_class, last_kinsoku_class; - int i; - int bytestocopy; - char * text = NULL; - Bool lineBufMeasured; - - /* start at the current text position in this text block */ - if (block->text_buffer) - text = (char *) &block->text_buffer[ block->buffer_read_index ]; - - kinsoku_class = PROHIBIT_NOWHERE; - - lineBufMeasured = FALSE; - - /* - * Initialize the structures to 0 (mark) - */ - memset (&text_data, 0, sizeof (LO_TextStruct)); - - /* - * Error conditions - */ - if ((state == NULL)||(state->cur_ele_type != LO_TEXT)||(text == NULL)) - { - return; - } - - - charset = block->text_attr->charset; - multi_byte = (INTL_CharSetType(charset) != SINGLEBYTE); - - /* - * Move through this text fragment, expand tabs, honor LF/CR. - */ - have_CR = state->last_char_CR; - tptr = text; - while ((*tptr != '\0')&&(state->top_state->out_of_memory == FALSE)) - { - Bool has_nbsp; - Bool in_word; - Bool wrap_break; - Bool pre_wrap_break; - - /* - * white_space is a tag to tell us if the current word - * ends in whitespace. - */ - white_space = FALSE; - line_break = FALSE; - has_nbsp = FALSE; - if (multi_byte) - has_nbsp = TRUE; - - /* - * Find the end of the line, counting tabs. - */ - tab_count = 0; - ignore_cnt = 0; - line_length = 0; - w_start = tptr; - - /* - * If the last character processed was a CR, and the next - * char is a LF, ignore it. Otherwise we know we - * can break the line on the first CR or LF found. - */ - if ((have_CR != FALSE)&&(*tptr == LF)) - { - ignore_cnt++; - tptr++; - } - have_CR = FALSE; - - in_word = FALSE; - wrap_break = FALSE; - pre_wrap_break = FALSE; - -#ifdef XP_WIN16 - while ((*tptr != CR)&&(*tptr != LF)&&(*tptr != '\0')&& - ((line_length + (tab_count * state->tab_stop)) < TEXT_CHUNK_LIMIT)&& - (((state->line_buf_len + line_length + (tab_count * state->tab_stop))) < SIZE_LIMIT)) -#else - while ((*tptr != CR)&&(*tptr != LF)&&(*tptr != '\0') - &&((line_length + (tab_count * state->tab_stop)) < TEXT_CHUNK_LIMIT) - ) -#endif /* XP_WIN16 */ - { - /* - * In the special wrapping preformatted text - * we need to chunk by word instead of by - * line. - */ - if ((state->preformatted == PRE_TEXT_WRAP)|| - (state->preformatted == PRE_TEXT_COLS)) - { - if(multi_byte && (! (INTL_CharSetType(charset) & CS_SPACE))) - { - last_kinsoku_class = kinsoku_class; - kinsoku_class = INTL_KinsokuClass(charset, (unsigned char *)tptr); - /* We need to conser PROHIBIT_WORD_BREAK for UTF8 case */ - if(( PROHIBIT_WORD_BREAK == kinsoku_class) || (0x00 == (*tptr & 0x80))) - { - if ((in_word == FALSE)&&(!XP_IS_SPACE(*tptr)) ) - { - in_word = TRUE; - } - else if ((in_word != FALSE)&& - (XP_IS_SPACE(*tptr))) - { - wrap_break = TRUE; - break; - } - } - else - { - if( (line_length != 0) && - (PROHIBIT_END_OF_LINE != last_kinsoku_class) && - (PROHIBIT_BEGIN_OF_LINE != kinsoku_class) - ) - { - wrap_break = TRUE; - break; - } - } - } - else - { - if ((in_word == FALSE)&&(!XP_IS_SPACE(*tptr))) - { - in_word = TRUE; - } - else if ((in_word != FALSE)&& - (XP_IS_SPACE(*tptr))) - { - wrap_break = TRUE; - break; - } - } - } - - if ((*tptr == FF)||(*tptr == VTAB)) - { - /* - * Ignore the form feeds - * thrown in by some platforms. - * Ignore vertical tabs since we don't know - * what else to do with them. - */ - ignore_cnt++; - } - else if (*tptr == TAB) - { - tab_count++; - } - else if (!multi_byte && (unsigned char)*tptr == NON_BREAKING_SPACE) - { - /* *tptr = ' '; Replace this later */ - has_nbsp = TRUE; - line_length++; - } - else - { - if(multi_byte) - line_length += INTL_CharLen(charset, (unsigned char*)tptr); - else - line_length++; - } - - if(multi_byte) - tptr = INTL_NextChar(charset, tptr); - else - tptr++; - } - line_length = line_length + (state->tab_stop * tab_count); - - if ((state->line_buf_len + line_length) > TEXT_CHUNK_LIMIT) - { - lo_FlushLineBuffer(context, state); - if (state->cur_ele_type != LO_TEXT) - { - lo_FreshText(state); - state->cur_ele_type = LO_TEXT; - } - } - -#ifdef XP_WIN16 - if ((state->line_buf_len + line_length) >= SIZE_LIMIT) - { - line_break = TRUE; - } -#endif /* XP_WIN16 */ - - /* - * Terminate the word, saving the char we replaced - * with the terminator so it can be restored later. - */ - w_end = tptr; - tchar1 = *w_end; - *w_end = '\0'; - - tmp_block = PA_ALLOC(line_length + 1); - if (tmp_block == NULL) - { - *w_end = tchar1; - state->top_state->out_of_memory = TRUE; - break; - } - PA_LOCK(tmp_buf, char *, tmp_block); - - if ((tab_count)||(ignore_cnt)) - { - char *cptr; - char *text_ptr; - int32 cnt; - - text_ptr = tmp_buf; - cptr = w_start; - cnt = lo_characters_in_line(state); - cnt += state->line_buf_len; - while (*cptr != '\0') - { - if ((*cptr == LF)||(*cptr == FF)|| - (*cptr == VTAB)) - { - /* - * Ignore any linefeeds that must have - * been after CR, and form feeds. - * Ignore vertical tabs since we - * don't know what else to do with them. - */ - cptr++; - } - else if (*cptr == TAB) - { - int32 i, tab_pos; - - tab_pos = ((cnt / state->tab_stop) + - 1) * state->tab_stop; - for (i=0; i<(tab_pos - cnt); i++) - { - *text_ptr++ = ' '; - } - cnt = tab_pos; - cptr++; - } - else - { - /* - * Bug #77467 - * If multibyte, character != char by default, so copy - * the CHARACTER, not the char - */ - if(multi_byte) - { - bytestocopy = INTL_CharLen(charset, (unsigned char*)cptr); - for (i=0; i<bytestocopy; i++) - { - *text_ptr++ = *cptr++; - cnt++; - } - } - else - { - *text_ptr++ = *cptr++; - cnt++; - } - } - } - *text_ptr = *cptr; - } - else - { - XP_BCOPY(w_start, tmp_buf, line_length + 1); - } - - /* - * Now we catch those nasty non-breaking space special - * characters and make them spaces. - */ - if (has_nbsp != FALSE) - { - char *tmp_ptr; - - tmp_ptr = tmp_buf; - while (*tmp_ptr != '\0') - { - if (((unsigned char)*tmp_ptr == NON_BREAKING_SPACE) - && (CS_USER_DEFINED_ENCODING != charset)) - { - *tmp_ptr = ' '; - } - if(multi_byte) - tmp_ptr = INTL_NextChar(charset, tmp_ptr); - else - tmp_ptr++; - } - } - - /* don't need this any more since we're converting - * elsewhere -- erik - tmp_buf = FE_TranslateISOText(context, charset, tmp_buf); - */ - line_length = XP_STRLEN(tmp_buf); - - if ((line_length > 0)&&(XP_IS_SPACE(tmp_buf[line_length - 1]))) - { - state->trailing_space = TRUE; - } -#ifdef LOCAL_DEBUG -XP_TRACE(("Found Preformatted text (%s)\n", tmp_buf)); -#endif /* LOCAL_DEBUG */ - PA_UNLOCK(tmp_block); - -#if WHAT - /* - * If this is an empty string, just throw it out - * and move on - */ - if (*w_start == '\0') - { - *w_end = tchar1; -#ifdef LOCAL_DEBUG -XP_TRACE(("Throwing out empty string!\n")); -#endif /* LOCAL_DEBUG */ - continue; - } -#endif - - /* - * If we have extra text, Append it to the line buffer. - * It may be necessary to expand the line - * buffer. - */ - if (*w_start != '\0') - { - int32 old_len; - Bool old_begin_line; - - old_len = state->line_buf_len; - old_begin_line = state->at_begin_line; - - if ((state->line_buf_len + line_length + 1) > - state->line_buf_size) - { - state->line_buf = PA_REALLOC( - state->line_buf, (state->line_buf_size + - line_length + LINE_BUF_INC)); - if (state->line_buf == NULL) - { - *w_end = tchar1; - state->top_state->out_of_memory = TRUE; - break; - } - state->line_buf_size += (line_length + - LINE_BUF_INC); - } - PA_LOCK(text_buf, char *, state->line_buf); - PA_LOCK(tmp_buf, char *, tmp_block); - - XP_BCOPY(tmp_buf, - (char *)(text_buf + state->line_buf_len), - (line_length + 1)); - state->line_buf_len += (intn) line_length; - PA_UNLOCK(state->line_buf); - PA_UNLOCK(tmp_block); - - /* we have not measured this new text yet */ - lineBufMeasured = FALSE; - - /* - * Having added text, we cannot be at the start - * of a line - */ - state->cur_ele_type = LO_TEXT; - state->at_begin_line = FALSE; - -#ifdef OLD_WAY - /* - * Most common case is appending to the same line. - * assume that is what we are doing here. - */ - text_data.text = state->line_buf; - text_data.text_len = (int16)state->line_buf_len; - text_data.text_attr = block->text_attr; - FE_GetTextInfo(context, &text_data, - &(state->text_info)); - state->width = - lo_correct_text_element_width( - &(state->text_info)); - - /* - * If this is a special wrapping pre, and we would - * wrap here, break before this, and strip all - * following whitespace so there is none at - * the start of the next line. - * If we were at the beginning of the line before - * this, then obviously trying to wrap here will - * be pointless, and will in fact cause an - * infinite loop. - * - * Also wrap here is we are in fixed column wrapping - * pre text, and we would pass our set column. - */ - if (((state->preformatted == PRE_TEXT_WRAP)&& - (old_begin_line == FALSE)&& - ((state->x + state->width) > state->right_margin))|| - ((state->preformatted == PRE_TEXT_COLS)&& - (old_begin_line == FALSE)&& - (state->preformat_cols > 0)&& - (state->line_buf_len > state->preformat_cols))) - { - PA_LOCK(text_buf, char *, state->line_buf); - text_buf[old_len] = '\0'; - PA_UNLOCK(state->line_buf); - state->line_buf_len = old_len; - - *w_end = tchar1; - tptr = w_start; - while ((XP_IS_SPACE(*tptr))&&(*tptr != '\0')) - { - tptr++; - } - line_break = TRUE; - w_start = tptr; - w_end = tptr; - tchar1 = *w_end; - } -#else - - text_data.text = state->line_buf; - text_data.text_len = (int16)state->line_buf_len; - text_data.text_attr = block->text_attr; - FE_GetTextInfo ( context, &text_data, &(state->text_info) ); - - /* update the block's font info cache */ - block->ascent = state->text_info.ascent; - block->descent = state->text_info.descent; - - /* - * If this is a special wrapping pre, then we need to measure this line of text to see - * if we need to wrap. - */ - if ( ( state->preformatted == PRE_TEXT_WRAP ) && ( old_begin_line == FALSE ) ) - { - state->width = lo_correct_text_element_width ( &(state->text_info) ); - - lineBufMeasured = TRUE; - - /* - * If this line is now too long, wrap - */ - if ( ( state->x + state->width ) > state->right_margin ) - { - pre_wrap_break = TRUE; - } - } - - /* - * Now check to see if we need to wrap based on being too long for the special pre modes - */ - if ( ( pre_wrap_break != FALSE ) || - ( ( state->preformatted == PRE_TEXT_COLS ) && - ( old_begin_line == FALSE ) && - ( state->preformat_cols > 0 ) && - ( state->line_buf_len > state->preformat_cols ) )) - { - PA_LOCK(text_buf, char *, state->line_buf); - text_buf[old_len] = '\0'; - PA_UNLOCK(state->line_buf); - state->line_buf_len = old_len; - - *w_end = tchar1; - tptr = w_start; - while ((XP_IS_SPACE(*tptr))&&(*tptr != '\0')) - { - tptr++; - } - line_break = TRUE; - w_start = tptr; - w_end = tptr; - tchar1 = *w_end; - } -#endif - } - - if (tchar1 == LF) - { - line_break = TRUE; - } - else if (tchar1 == CR) - { - line_break = TRUE; - have_CR = TRUE; - } - - /* update the buffer position to refleft the new word */ - block->buffer_read_index = tptr - (char *) block->text_buffer; - - /* - * If we are breaking the line here, flush the - * line_buf, and then insert a linebreak. - */ - if (line_break != FALSE) - { -#ifdef LOCAL_DEBUG -XP_TRACE(("LineBreak, flush text.\n")); -#endif /* LOCAL_DEBUG */ - - /* - * Flush the line and insert the linebreak. - */ - PA_LOCK(text_buf, char *, state->line_buf); - text_data.text = state->line_buf; - text_data.text_len = (int16)state->line_buf_len; - text_data.text_attr = block->text_attr; - FE_GetTextInfo(context, &text_data,&(state->text_info)); - PA_UNLOCK(state->line_buf); - state->width = lo_correct_text_element_width( - &(state->text_info)); - - lo_FlushLineBuffer(context, state); - - lineBufMeasured = TRUE; -#ifdef EDITOR - /* LTNOTE: do something here like: */ - /*state->edit_current_offset += (word_ptr - text_buf);*/ -#endif - if (state->top_state->out_of_memory != FALSE) - { - PA_FREE(tmp_block); - return; - } - /* - * Put on a linefeed element. - * This line is finished and will be added - * to the line array. - */ - lo_SoftLineBreak(context, state, TRUE); - - state->line_buf_len = 0; - state->width = 0; - - /* - * having just broken the line, we have no break - * position. - */ - state->break_pos = -1; - state->break_width = 0; - } - - *w_end = tchar1; - if ((*tptr == CR)||(*tptr == LF)) - { - tptr++; - } - PA_FREE(tmp_block); - } - -#ifndef OLD_WAY - /* - * If we haven't measured this line of text yet, do so now - */ - if ( !lineBufMeasured ) - { - text_data.text = state->line_buf; - text_data.text_len = (int16)state->line_buf_len; - text_data.text_attr = block->text_attr; - FE_GetTextInfo ( context, &text_data, &(state->text_info) ); - state->width = lo_correct_text_element_width ( &(state->text_info) ); - } -#endif - - /* - * Because we just might get passed text broken between the - * CR and the LF, we need to save this state. - */ - if ((tptr > text)&&(*(tptr - 1) == CR)) - { - state->last_char_CR = TRUE; - } - - if ( ( state->cur_ele_type != LO_TEXT ) || ( state->line_buf_len == 0 ) ) - { - state->cur_text_block = NULL; - } -} - -#define CAPITALIZE 0 -#define UPPERCASE 1 -#define LOWERCASE 2 - -/* transform the text inline. - * "capitalize" : uppercase first letter of each word. - * "uppercase" : uppercase every letter - * "lowercase" : lowercase every letter - * else : do nothing - */ -PRIVATE void -lo_transform_text(char *ptr, int method) -{ - XP_Bool possible_first_letter = TRUE; - - for(; *ptr; ptr++) - { - switch(method) - { - case CAPITALIZE: - if(!(XP_IS_SPACE(*ptr))) - { - if(possible_first_letter) - { - *ptr = XP_TO_UPPER(*ptr); - possible_first_letter = FALSE; - } - } - else /* is a space */ - { - possible_first_letter = TRUE; - } - break; - - case UPPERCASE: - *ptr = XP_TO_UPPER(*ptr); - break; - - case LOWERCASE: - *ptr = XP_TO_LOWER(*ptr); - break; - - default: - XP_ASSERT(0); - - } - } -} - -/* see lo_transform_text - * - * This function just maps the string method to an int - */ -PRIVATE void -lo_transform_text_from_string_method(char *ptr, char *method) -{ - if(!strcasecomp(method, "capitalize")) - lo_transform_text(ptr, CAPITALIZE); - else if(!strcasecomp(method, "lowercase")) - lo_transform_text(ptr, LOWERCASE); - else if(!strcasecomp(method, "uppercase")) - lo_transform_text(ptr, UPPERCASE); -} - -/************************************* - * Function: lo_FormatText - * - * Description: This function creates a text block element and then calls the - * format text function for it. - * - * Params: Window context and document state., and the text to be formatted. - * - * Returns: Nothing - *************************************/ -void -lo_FormatText(MWContext *context, lo_DocState *state, char *text) -{ - LO_TextBlock * block; - - /* can we use the new style layout? */ - if ( lo_CanUseBreakTable ( state ) ) - { - block = state->cur_text_block; - - /* flush any existing text in a partial buffer */ - if ( ( block != NULL ) && lo_UseBreakTable ( block ) ) - { - lo_LayoutTextBlock ( context, state, TRUE ); - } - - /* parse the new text and flush all but any stragglers */ - lo_AppendTextToBlock ( context, state, NULL, text ); - lo_LayoutTextBlock ( context, state, FALSE ); - } - else - { - block = lo_NewTextBlock ( context, state, text, state->preformatted ); - if ( !state->top_state->out_of_memory && ( block != NULL ) ) - { - block->buffer_read_index = 0; - lo_LayoutFormattedText ( context, state, block ); - } - } -} - - -/************************************* - * Function: lo_FormatText - * - * Description: This function formats text by breaking it into lines - * at word boundries. Word boundries are whitespace, or special - * word break tags. - * - * Params: Window context and document state., and the text to be formatted. - * - * Returns: Nothing - *************************************/ -void -lo_LayoutFormattedText(MWContext *context, - lo_DocState *state, - LO_TextBlock * block) -{ - char *tptr; - char *w_start; - char *w_end; - char *text_buf; - char tchar1; - int32 word_len; - Bool line_break; - Bool word_break; - Bool prev_word_breakable; - Bool white_space; - int16 charset; - Bool multi_byte; - LO_TextStruct text_data; - char * text = NULL; - -#ifdef XP_OS2 /* performance */ - int32 maxw; /* performance - max char width for font */ - int32 estwidth; /* performance - estimated width for line */ - int textsw; /* performance */ - maxw = 0; - textsw = 0; /* performance - need to mark no width taken */ -#endif - - /* start at the current text position in this text block */ - if (block->text_buffer) - text = (char *) &block->text_buffer[ block->buffer_read_index ]; - - /* - * Initialize the structures to 0 (mark) - */ - memset (&text_data, 0, sizeof (LO_TextStruct)); - - /* - * Error conditions - */ - if ((state == NULL)||(state->cur_ele_type != LO_TEXT)||(text == NULL)) - { - return; - } - - charset = block->text_attr->charset; - if ((INTL_CharSetType(charset) == SINGLEBYTE) || - (INTL_CharSetType(charset) & CS_SPACE)) - { - multi_byte = FALSE; - } - else - { - multi_byte = TRUE; - } - - /* - * Move through this text fragment, breaking it up into - * words, and then grouping the words into lines. - */ - tptr = text; - prev_word_breakable = FALSE; - while ((*tptr != '\0')&&(state->top_state->out_of_memory == FALSE)) - { - PA_Block nbsp_block; - Bool has_nbsp; - int32 w_char_cnt; -#ifdef XP_WIN16 - int32 ccnt; -#endif /* XP_WIN16 */ - Bool mb_sp; /* Allow space between multibyte */ - - /* - * white_space is a tag to tell us if the currenct word - * contains nothing but whitespace. - * word_break tells us if there was whitespace - * before this word so we know we can break it. - */ - white_space = FALSE; - word_break = FALSE; - line_break = FALSE; - nbsp_block = NULL; - has_nbsp = FALSE; - mb_sp = FALSE; - - if (multi_byte == FALSE) - { - /* check for textTransform properties and apply them */ - if(state->top_state && state->top_state->style_stack) - { - char *property; - StyleStruct *style_struct = STYLESTACK_GetStyleByIndex( - state->top_state->style_stack, - 0); - - if(style_struct) - { - property = STYLESTRUCT_GetString(style_struct, - TEXT_TRANSFORM_STYLE); - - if(property) - { - lo_transform_text_from_string_method(tptr, property); - } - } - } - - /* - * Find the start of the word, skipping whitespace. - */ - w_start = tptr; - while ((XP_IS_SPACE(*tptr))&&(*tptr != '\0')) - { - tptr++; - } - - /* - * if tptr has been moved at all, that means - * there was some whitespace to skip, which means - * we are allowed to put a linebreak before this - * word if we want to. - */ - if (tptr != w_start) - { - int32 new_break_holder; - int32 min_width; - int32 indent; - - w_start = tptr; - word_break = TRUE; - - new_break_holder = state->x + state->width; - min_width = new_break_holder - state->break_holder; - indent = state->list_stack->old_left_margin - - state->win_left; - min_width += indent; - if (min_width > state->min_width) - { - state->min_width = min_width; - } - /* If we are not within <NOBR> content, allow break_holder - * to be set to the new position where a line break can occur. - * This fixes BUG #70782 - */ - if (state->breakable != FALSE) { - state->break_holder = new_break_holder; - } - } - - /* - * If we are in text that is supposed to be - * justified, we want each word to be in a separate - * text element, so if we just found a word break, - * and there is already a word in the line buffer, - * flush that word into its own element. - */ - if ((state->align_stack != NULL)&& - (state->align_stack->alignment ==LO_ALIGN_JUSTIFY)&& - (word_break != FALSE)&& - (state->cur_ele_type == LO_TEXT)&& - (state->line_buf_len != 0)) - { - /* set the current text offset for this new word */ - block->buffer_read_index = tptr - (char *) block->text_buffer; - - lo_FlushLineBuffer(context, state); - if (state->top_state->out_of_memory != FALSE) - { - return; - } - } - - /* - * Find the end of the word. - * Terminate the word, saving the char we replaced - * with the terminator so it can be restored later. - */ - w_char_cnt = 0; -#ifdef XP_WIN16 - ccnt = state->line_buf_len; - while ((!XP_IS_SPACE(*tptr))&&(*tptr != '\0')&&(ccnt < SIZE_LIMIT)) - { - if ((unsigned char)*tptr == NON_BREAKING_SPACE) - { - has_nbsp = TRUE; - } - tptr++; - w_char_cnt++; - ccnt++; - } - if (ccnt >= SIZE_LIMIT) - { - line_break = TRUE; - } -#else - while ((!XP_IS_SPACE(*tptr))&&(*tptr != '\0')) - { - if ((unsigned char)*tptr == NON_BREAKING_SPACE) - { - /* *tptr = ' '; Replace this later */ - has_nbsp = TRUE; - } - tptr++; - w_char_cnt++; - } -#endif /* XP_WIN16 */ - } - else - { - has_nbsp = TRUE; - /* - * Find the start of the word, skipping whitespace. - */ - w_start = tptr; - while ((XP_IS_SPACE(*tptr))&&(*tptr != '\0')) - { - tptr = INTL_NextChar(charset, tptr); - } - if (w_start != tptr) - mb_sp = TRUE; - - /* - * if tptr has been moved at all, that means - * there was some whitespace to skip, which means - * we are allowed to put a linebreak before this - * word if we want to. - */ - /* - * If this char is a two-byte thing, we can break - * before it. - */ - if ((tptr != w_start)||((unsigned char)*tptr > 127)) - { - int32 new_break_holder; - int32 min_width; - int32 indent; - - /* If it's multibyte character, it always be able to break */ - if (tptr == w_start) - prev_word_breakable = TRUE; - w_start = tptr; - word_break = TRUE; - - new_break_holder = state->x + state->width; - min_width = new_break_holder - state->break_holder; - indent = state->list_stack->old_left_margin - - state->win_left; - min_width += indent; - if (min_width > state->min_width) - { - state->min_width = min_width; - } - /* If we are not within <NOBR> content, allow break_holder - * to be set to the new position where a line break can occur. - * This fixes BUG #70782 - */ - if (state->breakable != FALSE) { - state->break_holder = new_break_holder; - } - } - else if (prev_word_breakable) - { - int32 new_break_holder; - int32 min_width; - int32 indent; - - prev_word_breakable = FALSE; - w_start = tptr; - word_break = TRUE; - - new_break_holder = state->x + state->width; - min_width = new_break_holder - state->break_holder; - indent = state->list_stack->old_left_margin - - state->win_left; - min_width += indent; - if (min_width > state->min_width) - { - state->min_width = min_width; - } - /* If we are not within <NOBR> content, allow break_holder - * to be set to the new position where a line break can occur. - * This fixes BUG #70782 - */ - if (state->breakable != FALSE) { - state->break_holder = new_break_holder; - } - } - - /* - * Find the end of the word. - * Terminate the word, saving the char we replaced - * with the terminator so it can be restored later. - */ - w_char_cnt = 0; -#ifdef XP_WIN16 - ccnt = state->line_buf_len; - while (( ((unsigned char)*tptr < 128) - || (INTL_KinsokuClass(charset, (unsigned char *)tptr) == PROHIBIT_WORD_BREAK ) - ) && (!XP_IS_SPACE(*tptr)) - && (*tptr != '\0') - && (ccnt < SIZE_LIMIT)) - { - intn c_len; - char *tptr2; - - tptr2 = INTL_NextChar(charset, tptr); - c_len = (intn)(tptr2 - tptr); - tptr = tptr2; - w_char_cnt += c_len; - ccnt += c_len; - } - if (ccnt >= SIZE_LIMIT) - { - line_break = TRUE; - } -#else - -#if 0 - while ( /* Change the order so we have better performance */ - (*tptr != '\0') - && (!XP_IS_SPACE(*tptr)) - && ( ((unsigned char)*tptr < 128) - || ((CS_UTF8 == charset) /* hack, since we know only CS_UTF8 have PROHIBIT_WORD_BREAK*/ - && (INTL_KinsokuClass(charset, (unsigned char *)tptr) == PROHIBIT_WORD_BREAK )) - ) - ) -#else - while ( - (*tptr != '\0') - && (!XP_IS_SPACE(*tptr)) - && ( ((unsigned char)*tptr < 128) - || ((CS_UTF8 == charset) && (*(unsigned char *)tptr <= 0xE2)) - /* In case of CS_UTF8, some code range like CJK character baundary is breakable. - * While in range UCS2 < 0x2000 (roman), character baundary is not breakable. - */ - ) - ) -#endif - { - intn c_len; - char *tptr2; - - tptr2 = INTL_NextChar(charset, tptr); - c_len = (intn)(tptr2 - tptr); - tptr = tptr2; - w_char_cnt += c_len; - } -#endif /* XP_WIN16 */ - } /* multi byte */ - - if (w_char_cnt > TEXT_CHUNK_LIMIT) - { - tptr = (char *)(tptr - (w_char_cnt - TEXT_CHUNK_LIMIT)); - w_char_cnt = TEXT_CHUNK_LIMIT; - } - - if ((state->line_buf_len + w_char_cnt) > TEXT_CHUNK_LIMIT) - { - lo_FlushLineBuffer(context, state); - if (state->top_state->out_of_memory != FALSE) - { - return; - } - - if (state->cur_ele_type != LO_TEXT) - { - lo_FreshText(state); - state->cur_ele_type = LO_TEXT; - } - } - if (multi_byte != FALSE) - { - if ((w_start == tptr)&&((unsigned char)*tptr > 127)) - { - tptr = INTL_NextChar(charset, tptr); - } - } - w_end = tptr; - tchar1 = *w_end; - *w_end = '\0'; - - /* - * If the "word" is just an empty string, this - * is just whitespace that we may wish to compress out. - */ - if (*w_start == '\0') - { - white_space = TRUE; - } - - /* - * compress out whitespace if the last word added was also - * whitespace. - */ - if ((white_space != FALSE)&&(state->trailing_space != FALSE)) - { - *w_end = tchar1; -#ifdef LOCAL_DEBUG -XP_TRACE(("Discarding(%s)\n", w_start)); -#endif /* LOCAL_DEBUG */ - continue; - } - - /* - * This places the preceeding space in front of - * separate words on a line. - * Unecessary if last item was trailng space. - * - * If there was a word break before this word, so we know it - * was supposed to be separate, and if we are not at the - * beginning of the line, and if the - * preceeding word is not already whitespace, then add - * a space before this word. - */ - if ((word_break != FALSE)&& - (state->at_begin_line == FALSE)&& - (state->trailing_space == FALSE)) - { - /* - * Since word_break is true, we know - * we skipped some spaces previously - * so we know there is space to back up - * the word pointer inside the buffer. - */ - if ((multi_byte == FALSE)||mb_sp) - { - w_start--; - *w_start = ' '; - } - - /* - * If we are formatting breakable text - * set break position to be just before this word. - * This is where we will break this line if the - * new word makes it too long. - */ - if (state->breakable != FALSE) - { - state->break_pos = state->line_buf_len; - state->break_width = state->width; - } - } - -#ifdef LOCAL_DEBUG -XP_TRACE(("Found Word (%s)\n", w_start)); -#endif /* LOCAL_DEBUG */ - /* - * If this is an empty string, just throw it out - * and move on - */ - if (*w_start == '\0') - { - *w_end = tchar1; -#ifdef LOCAL_DEBUG -XP_TRACE(("Throwing out empty string!\n")); -#endif /* LOCAL_DEBUG */ - continue; - } - - /* - * Now we catch those nasty non-breaking space special - * characters and make them spaces. Yuck, so that - * relayout in tables will still see the non-breaking - * spaces, we need to copy the buffer here. - */ - if (has_nbsp != FALSE) - { - char *tmp_ptr; - char *to_ptr; - char *tmp_buf; - - nbsp_block = PA_ALLOC(XP_STRLEN(w_start) + 1); - if (nbsp_block == NULL) - { - *w_end = tchar1; - state->top_state->out_of_memory = TRUE; - break; - } - PA_LOCK(tmp_buf, char *, nbsp_block); - - tmp_ptr = w_start; - to_ptr = tmp_buf; - while (*tmp_ptr != '\0') - { - *to_ptr = *tmp_ptr; - if (((unsigned char)*to_ptr == NON_BREAKING_SPACE) - && (CS_USER_DEFINED_ENCODING != charset)) - { - *to_ptr = ' '; - } - if(multi_byte) { - int i; - int len = INTL_CharLen(charset, - (unsigned char *)tmp_ptr); - to_ptr++; - tmp_ptr++; - for (i=1; (i<len) && (*tmp_ptr != '\0'); i++) { - *to_ptr++ = *tmp_ptr++; - } - } - else { - to_ptr++; - tmp_ptr++; - } - } - *w_end = tchar1; - w_start = tmp_buf; - w_end = to_ptr; - *w_end = '\0'; - } - - /* - * Make this Front End specific text, and count - * the length of the word. - */ - /* don't need this any more since we're converting - * elsewhere -- erik - w_start = FE_TranslateISOText(context, charset, w_start); - */ - word_len = XP_STRLEN(w_start); - - /* - * Append this word to the line buffer. - * It may be necessary to expand the line - * buffer. - */ - if ((state->line_buf_len + word_len + 1) > - state->line_buf_size) - { - state->line_buf = PA_REALLOC( state->line_buf, - (state->line_buf_size + - word_len + LINE_BUF_INC)); - if (state->line_buf == NULL) - { - *w_end = tchar1; - if ((has_nbsp != FALSE)&&(nbsp_block != NULL)) - { - PA_UNLOCK(nbsp_block); - PA_FREE(nbsp_block); - nbsp_block = NULL; - } - state->top_state->out_of_memory = TRUE; - break; - } - state->line_buf_size += (word_len + LINE_BUF_INC); - } - PA_LOCK(text_buf, char *, state->line_buf); - XP_BCOPY(w_start, - (char *)(text_buf + state->line_buf_len), - (word_len + 1)); - state->line_buf_len += word_len; - PA_UNLOCK(state->line_buf); - - /* - * Having added a word, we cannot be at the start of a line - */ - state->cur_ele_type = LO_TEXT; - state->at_begin_line = FALSE; - - /* - * Most common case is appending to the same line. - * assume that is what we are doing here. - */ - text_data.text = state->line_buf; - text_data.text_len = (int16)state->line_buf_len; - text_data.text_attr = state->cur_text_block->text_attr; - FE_GetTextInfo(context, &text_data, &(state->text_info)); - state->width = - lo_correct_text_element_width(&(state->text_info)); - - /* udpate the block's font info cache */ - block->ascent = state->text_info.ascent; - block->descent = state->text_info.descent; - - /* - * Set line_break based on document window width - */ -#ifdef XP_WIN16 - if (((state->x + state->width) > state->right_margin)||(line_break != FALSE)) -#else - if ((state->x + state->width) > state->right_margin) -#endif /* XP_WIN16 */ - { - /* - * INTL kinsoku line break, some of characters are not allowed to put - * in the end of line or beginning of line - */ - if (multi_byte && (state->break_pos != -1)) - { - int cur_wordtype, pre_wordtype, pre_break_pos; - cur_wordtype = INTL_KinsokuClass(charset, (unsigned char *) w_start); - - PA_LOCK(text_buf, char *, state->line_buf); - pre_break_pos = INTL_PrevCharIdx(charset, - (unsigned char *)text_buf, state->break_pos); - pre_wordtype = INTL_KinsokuClass(charset, - (unsigned char *)(text_buf + pre_break_pos)); - - if (pre_wordtype == PROHIBIT_END_OF_LINE || - (cur_wordtype == PROHIBIT_BEGIN_OF_LINE && - XP_IS_ALPHA(*(text_buf+pre_break_pos)) == FALSE)) - state->break_pos = pre_break_pos; - - PA_UNLOCK(state->line_buf); - } - line_break = TRUE; - } - else - { - line_break = FALSE; - } - - /* - * We cannot break a line if we have no break positions. - * Usually happens with a single line of unbreakable text. - */ - if ((line_break != FALSE)&&(state->break_pos == -1)) - { - /* - * It may be possible to break a previous - * text element on the same line. - */ - if (state->old_break_pos != -1) - { - lo_BreakOldElement(context, state); - line_break = FALSE; - } -#ifdef XP_WIN16 - else if (ccnt >= SIZE_LIMIT) - { - state->break_pos = state->line_buf_len - 1; - } - else - { - line_break = FALSE; - } -#else - else - { - line_break = FALSE; - } -#endif /* XP_WIN16 */ - } - - /* - * If we are breaking the line here, flush the - * line_buf, and then insert a linebreak. - */ - if (line_break != FALSE) - { - char *break_ptr; - char *word_ptr; - char *new_buf; - PA_Block new_block; -#ifdef LOCAL_DEBUG -XP_TRACE(("LineBreak, flush text.\n")); -#endif /* LOCAL_DEBUG */ - - /* - * Find the breaking point, and the pointer - * to the remaining word without its leading - * space. - */ - PA_LOCK(text_buf, char *, state->line_buf); - break_ptr = (char *)(text_buf + state->break_pos); -/* word_ptr = (char *)(break_ptr + 1); */ - word_ptr = break_ptr; - - if ((multi_byte == FALSE)||mb_sp) - { - word_ptr++; - } - - /* - * Copy the remaining word into its - * own buffer. - */ - word_len = XP_STRLEN(word_ptr); - new_block = PA_ALLOC((word_len + 1) * - sizeof(char)); - if (new_block == NULL) - { - PA_UNLOCK(state->line_buf); - *w_end = tchar1; - if ((has_nbsp != FALSE)&&(nbsp_block != NULL)) - { - PA_UNLOCK(nbsp_block); - PA_FREE(nbsp_block); - nbsp_block = NULL; - } - state->top_state->out_of_memory = TRUE; - break; - } - PA_LOCK(new_buf, char *, new_block); - XP_BCOPY(word_ptr, new_buf, (word_len + 1)); - - *break_ptr = '\0'; - state->line_buf_len = state->line_buf_len - - word_len; - if ((multi_byte == FALSE)||(word_ptr != break_ptr)) - { - state->line_buf_len--; - } - text_data.text = state->line_buf; - text_data.text_len = (int16)state->line_buf_len; - text_data.text_attr = state->cur_text_block->text_attr; - FE_GetTextInfo(context, &text_data,&(state->text_info)); - PA_UNLOCK(state->line_buf); - state->width = lo_correct_text_element_width( - &(state->text_info)); - - lo_FlushLineBuffer(context, state); -#ifdef EDITOR - state->edit_current_offset += (word_ptr - text_buf); -#endif - if (state->top_state->out_of_memory != FALSE) - { - PA_UNLOCK(new_block); - PA_FREE(new_block); - if ((has_nbsp != FALSE)&&(nbsp_block != NULL)) - { - PA_UNLOCK(nbsp_block); - PA_FREE(nbsp_block); - nbsp_block = NULL; - } - return; - } - - /* - * Put on a linefeed element. - * This line is finished and will be added - * to the line array. - */ - lo_SoftLineBreak(context, state, TRUE); - - /* - * If there was no remaining word, free up - * the unnecessary buffer, and empty out - * the line buffer. - */ - if (word_len == 0) - { - PA_UNLOCK(new_block); - PA_FREE(new_block); - state->line_buf_len = 0; - state->width = 0; - } - else - { - PA_LOCK(text_buf, char *,state->line_buf); - XP_BCOPY(new_buf, text_buf, (word_len + 1)); - PA_UNLOCK(state->line_buf); - PA_UNLOCK(new_block); - PA_FREE(new_block); - state->line_buf_len = word_len; - text_data.text = state->line_buf; - text_data.text_len = (int16)state->line_buf_len; - text_data.text_attr = - state->cur_text_block->text_attr; - FE_GetTextInfo(context, &text_data, - &(state->text_info)); - state->width = lo_correct_text_element_width( - &(state->text_info)); - - /* - * Having added text, we are no longer at the - * start of the line. - */ - state->at_begin_line = FALSE; - state->cur_ele_type = LO_TEXT; - } - - - /* - * having just broken the line, we have no break - * position. - */ - state->break_pos = -1; - state->break_width = 0; - } - else - { - /* this word fits, so update the text buffer position */ - block->buffer_read_index = tptr - (char *) block->text_buffer; - - if (white_space != FALSE) - { - state->trailing_space = TRUE; - } - else - { - state->trailing_space = FALSE; - } - } - - *w_end = tchar1; - /* - * Free up the extra block used for non-breaking - * spaces if we had to allocate one. - */ - if ((has_nbsp != FALSE)&&(nbsp_block != NULL)) - { - PA_UNLOCK(nbsp_block); - PA_FREE(nbsp_block); - nbsp_block = NULL; - } - } - /* - * if last char is multibyte, break position need to be set to - * end of string - */ - if (multi_byte != FALSE && *tptr == '\0' && prev_word_breakable != FALSE) - state->break_pos = state->line_buf_len; - - if ( ( state->cur_ele_type != LO_TEXT ) || ( state->line_buf_len == 0 ) ) - { - state->cur_text_block = NULL; - } -} - - -/************************************* - * Function: lo_FlushLineBuffer - * - * Description: Flush out the current line buffer of text - * into a new text element, and add that element to - * the end of the line list of elements. - * - * Params: Window context and document state. - * - * Returns: Nothing - *************************************/ -void -lo_FlushLineBuffer(MWContext *context, lo_DocState *state) -{ - LO_TextStruct *text_data; - int32 baseline_inc; - LO_TextBlock * block; - - baseline_inc = 0; -#ifdef DEBUG - assert (state); -#endif - - block = state->cur_text_block; - - /* bail if we have nothing to do with text */ - if ( ( block == NULL ) || ( state->cur_ele_type != LO_TEXT ) ) - { - return; - } - - /* - * If we're currently using the new break table layout, then bail to it - */ - if ( lo_UseBreakTable ( block ) ) - { - lo_FlushText ( context, state ); - return; - } - - /* - * Make sure we have some text to flush - */ - if ( state->line_buf_len == 0 ) - { - return; - } - - /* - * LTNOTE: probably should be grabbing state edit_element and offset from - * state. - */ - text_data = lo_new_text_element(context, state, NULL, 0); - - if (text_data == NULL) - { - state->top_state->out_of_memory = TRUE; - return; - } - state->linefeed_state = 0; - - /* - * Some fonts (particulatly italic ones with curly tails - * on letters like 'f') have a left bearing that extends - * back into the previous character. Since in this case the - * previous character is probably not in the same font, we - * move forward to avoid overlap. - * - * Those same funny fonts can extend past the last character, - * and we also have to catch that, and advance the following text - * to eliminate cutoff. - */ - if (state->text_info.lbearing < 0) - { - text_data->x_offset = state->text_info.lbearing * -1; - } - text_data->width = state->width; - - /* - * record the current doc width and text buffer offset for use - * during relayout. - */ - text_data->doc_width = state->right_margin - state->x; - text_data->block_offset = block->buffer_read_index; - XP_ASSERT(block->buffer_read_index <= 65535); - - baseline_inc = lo_compute_text_basline_inc ( state, block, text_data ); - - lo_AppendToLineList(context, state, (LO_Element *)text_data, baseline_inc); - - if ( block->startTextElement == NULL ) - { - block->startTextElement = text_data; - block->endTextElement = text_data; - } - else - { - block->endTextElement = text_data; - } - - text_data->height = state->text_info.ascent + - state->text_info.descent; - - /* - * If the element we just flushed had a breakable word - * position in it, save that position in case we have - * to go back and break this element before we finish - * the line. - */ - if (state->break_pos != -1) - { - state->old_break = text_data; - state->old_break_block = block; - state->old_break_pos = state->break_pos; - state->old_break_width = state->break_width; - } - - state->line_buf_len = 0; - state->x += state->width; - state->width = 0; - state->cur_ele_type = LO_NONE; -} - -void -lo_FlushTextBlock ( MWContext *context, lo_DocState *state ) -{ - lo_FlushLineBuffer ( context, state ); - - state->cur_text_block = NULL; -} - -/* Only the first call here actually changes the text color */ -void -lo_ChangeBodyTextFGColor(MWContext *context, lo_DocState *state, LO_Color *color) -{ - if( (state->top_state->body_attr & BODY_ATTR_TEXT) != 0) - return; - - /* Set the flag so we don't change the color again - unless we relayout from the URL again. - */ - state->top_state->body_attr |= BODY_ATTR_TEXT; - - lo_SetBodyTextFGColor(context, state, color); -} - - -/* This REALLY sets the color. "state" may be NULL and it will be figured out */ -void -lo_SetBodyTextFGColor(MWContext *context, lo_DocState *state, LO_Color *color) -{ - int32 doc_id; - lo_TopState *top_state; - lo_FontStack *fptr; - LO_TextAttr *attr; - - if( !context ) - return; - - if( !state ) - { - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if (top_state != NULL && top_state->doc_state == NULL) - return; - - state = top_state->doc_state; - - if (color == NULL) - color = &lo_master_colors[LO_COLOR_FG]; - } - - state->text_fg = *color; - fptr = state->font_stack; - - /* - * If we're inside a layer, then we want this color change - * to only affect text in the layer. So, we push a font - * (a copy of the top of the stack) onto the font stack - * and change its color. This font will be popped in the - * closing of the layer. - */ - if (lo_InsideLayer(state)) { - LO_TextAttr tmp_attr; - - if (fptr) - lo_CopyTextAttr(fptr->text_attr, &tmp_attr); - else - lo_SetDefaultFontAttr(state, &tmp_attr, context); - - tmp_attr.fg.red = STATE_DEFAULT_FG_RED(state); - tmp_attr.fg.green = STATE_DEFAULT_FG_GREEN(state); - tmp_attr.fg.blue = STATE_DEFAULT_FG_BLUE(state); - attr = lo_FetchTextAttr(state, &tmp_attr); - lo_PushFont(state, P_BODY, attr); - } - else if (fptr != NULL) - { - attr = fptr->text_attr; - attr->fg.red = STATE_DEFAULT_FG_RED(state); - attr->fg.green = STATE_DEFAULT_FG_GREEN(state); - attr->fg.blue = STATE_DEFAULT_FG_BLUE(state); - } -} - - -/* - * Something has changed (probably the default FG and BG colors) - * since the font stack was initialized in this state. - * We need to reinitialie it to the new default font. - * WARNING: This function depends on the assumption that no - * elements have yet been placed in this state. - */ -void -lo_ResetFontStack(MWContext *context, lo_DocState *state) -{ - if (state->font_stack != NULL) - { - lo_FontStack *fstack; - lo_FontStack *fptr; - - fptr = state->font_stack; - while (fptr != NULL) - { - fstack = fptr; - fptr = fptr->next; - XP_DELETE(fstack); - } - state->font_stack = NULL; - } - state->font_stack = lo_DefaultFont(state, context); -} - - -/************************************* - * Function: lo_PushFont - * - * Description: Push the text attribute information for a new - * font onto the font stack. Also save the type of the - * tag that caused the change. - * - * Params: Document state, tag type, and the text attribute - * structure for the new font. - * - * Returns: Nothing - *************************************/ -void -lo_PushFont(lo_DocState *state, intn tag_type, LO_TextAttr *attr) -{ - lo_FontStack *fptr; - - fptr = XP_NEW(lo_FontStack); - if (fptr == NULL) - { - return; - } - fptr->tag_type = tag_type; - fptr->text_attr = attr; - fptr->next = state->font_stack; - state->font_stack = fptr;; -} - - -/************************************* - * Function: lo_PopFontStack - * - * Description: This function pops the next font - * off the font stack, and return the text attribute of the - * previous font. - * The last font on the font stack cannot be popped off. - * - * Params: Document state, and the tag type that caused the change. - * - * Returns: The LO_TextAttr structure of the font just passed. - *************************************/ -#ifndef DOM -PRIVATE -LO_TextAttr * -lo_PopFontStack(lo_DocState *state, intn tag_type) -{ - LO_TextAttr *attr; - lo_FontStack *fptr; - - if (state->font_stack->next == NULL) - { -#ifdef LOCAL_DEBUG -XP_TRACE(("Popped too many fonts!\n")); -#endif /* LOCAL_DEBUG */ - return(NULL); - } - - fptr = state->font_stack; - attr = fptr->text_attr; - if (fptr->tag_type != tag_type) - { -#ifdef LOCAL_DEBUG -XP_TRACE(("Warning: Font popped by different TAG than pushed it %d != %d\n", fptr->tag_type, tag_type)); -#endif /* LOCAL_DEBUG */ - } - state->font_stack = fptr->next; - XP_DELETE(fptr); - - return(attr); -} -#endif - -LO_TextAttr * -lo_PopFont(lo_DocState *state, intn tag_type) -{ - LO_TextAttr *attr; - lo_FontStack *fptr; - - /* - * This should never happen, but we are patching a - * more serious problem that causes us to be called - * here after the font stack has been freed. - */ - if ((state->font_stack == NULL)||(state->font_stack->next == NULL)) - { -#ifdef LOCAL_DEBUG -XP_TRACE(("Popped too many fonts!\n")); -#endif /* LOCAL_DEBUG */ - return(NULL); - } - - fptr = state->font_stack; - attr = NULL; - - if (fptr->tag_type != P_ANCHOR) - { - attr = fptr->text_attr; - if (fptr->tag_type != tag_type) - { -#ifdef LOCAL_DEBUG -XP_TRACE(("Warning: Font popped by different TAG than pushed it %d != %d\n", fptr->tag_type, tag_type)); -#endif /* LOCAL_DEBUG */ - } - state->font_stack = fptr->next; - XP_DELETE(fptr); - } - else - { - while ((fptr->next != NULL)&&(fptr->next->tag_type == P_ANCHOR)) - { - fptr = fptr->next; - } - if (fptr->next->next != NULL) - { - lo_FontStack *f_tmp; - - f_tmp = fptr->next; - fptr->next = fptr->next->next; - attr = f_tmp->text_attr; - XP_DELETE(f_tmp); - } - } - - return(attr); -} - - -void -lo_PopAllAnchors(lo_DocState *state) -{ - lo_FontStack *fptr; - - if (state->font_stack->next == NULL) - { -#ifdef LOCAL_DEBUG -XP_TRACE(("Popped too many fonts!\n")); -#endif /* LOCAL_DEBUG */ - return; - } - - /* - * Remove all anchors on top of the font stack - */ - fptr = state->font_stack; - while ((fptr->tag_type == P_ANCHOR)&&(fptr->next != NULL)) - { - lo_FontStack *f_tmp; - - f_tmp = fptr; - fptr = fptr->next; - XP_DELETE(f_tmp); - } - state->font_stack = fptr; - - /* - * Remove all anchors buried in the stack - */ - while (fptr->next != NULL) - { - /* - * Reset spurrious anchor color text entries - */ - if ((fptr->text_attr != NULL)&& - (fptr->text_attr->attrmask & LO_ATTR_ANCHOR)) - { - LO_TextAttr tmp_attr; - - lo_CopyTextAttr(fptr->text_attr, &tmp_attr); - tmp_attr.attrmask = - tmp_attr.attrmask & (~LO_ATTR_ANCHOR); - tmp_attr.fg.red = STATE_DEFAULT_FG_RED(state); - tmp_attr.fg.green = STATE_DEFAULT_FG_GREEN(state); - tmp_attr.fg.blue = STATE_DEFAULT_FG_BLUE(state); - tmp_attr.bg.red = STATE_DEFAULT_BG_RED(state); - tmp_attr.bg.green = STATE_DEFAULT_BG_GREEN(state); - tmp_attr.bg.blue = STATE_DEFAULT_BG_BLUE(state); - fptr->text_attr = lo_FetchTextAttr(state, &tmp_attr); - } - - if (fptr->next->tag_type == P_ANCHOR) - { - lo_FontStack *f_tmp; - - f_tmp = fptr->next; - fptr->next = fptr->next->next; - XP_DELETE(f_tmp); - } - else - { - fptr = fptr->next; - } - } -} - -void -lo_FormatBullet(MWContext *context, lo_DocState *state, - LO_BulletStruct *bullet, - int32 *line_height, - int32 *baseline) -{ - LO_TextStruct tmp_text; - LO_TextInfo text_info; - LO_TextAttr *tptr; - PA_Block buff; - char *str; - -#define MIN_BULLET_SIZE 5 - - bullet->ele_id = NEXT_ELEMENT; - - /* bullet = (LO_BulletStruct *)lo_NewElement(context, state, LO_BULLET, NULL, 0); */ - if (bullet == NULL) - { -#ifdef DEBUG - assert (state->top_state->out_of_memory); -#endif - return; - } - - /* TEXTATTR HERE */ - tptr = bullet->text_attr; - - memset (&tmp_text, 0, sizeof (tmp_text)); - buff = PA_ALLOC(1); - if (buff == NULL) - { - state->top_state->out_of_memory = TRUE; - return; - } - PA_LOCK(str, char *, buff); - str[0] = ' '; - PA_UNLOCK(buff); - tmp_text.text = buff; - tmp_text.text_len = 1; - tmp_text.text_attr = tptr; - FE_GetTextInfo(context, &tmp_text, &text_info); - PA_FREE(buff); - - /* contain the bullet size so that it doesn't extend off the - * left side of the page since we are using a negative offset - * to place the bullet - * - * also subtract one to avoid the header code at the bottom - * from triggering and messing up the alignment - */ - if(bullet->bullet_size*2 >= state->x-state->win_left) - bullet->bullet_size = ((state->x-state->win_left)/2)-1; - - /* enforce a minumum bullet size */ - if(bullet->bullet_size < 1) - bullet->bullet_size = MIN_BULLET_SIZE; - - bullet->x = state->x - (2 * bullet->bullet_size); - if (bullet->x < state->win_left) - { - bullet->x = state->win_left; - } - bullet->x_offset = 0; - bullet->y = state->y; - bullet->y_offset = - (text_info.ascent + text_info.descent - bullet->bullet_size) / 2; - bullet->width = bullet->bullet_size; - bullet->height = bullet->bullet_size; - - *line_height = text_info.ascent + text_info.descent; - *baseline = text_info.ascent; -} - -void -lo_UpdateStateAfterBullet(MWContext * context, lo_DocState *state, - LO_BulletStruct *bullet, - int32 line_height, - int32 baseline) -{ - state->baseline = baseline; - state->line_height = line_height; - - /* - * Clean up state - */ -/* - * Supporting old mistakes made in some other browsers. - * I will put the "correct code" here, but comment it out, since - * some other browsers allowed headers inside lists, so we should to, sigh. - state->linefeed_state = 0; - */ - state->at_begin_line = TRUE; - state->cur_ele_type = LO_BULLET; - if (bullet->x == state->win_left) - { - state->x += (bullet->x_offset + (2 * bullet->width)); - } - - /* - * Make at_begin_line be accurate - * so we can detect the header - * linefeed state deception later. - */ - state->at_begin_line = FALSE; - - /* - * After much soul-searching (and brow-beating - * by Jamie, I've agreed that really whitespace - * should be compressed out at the start of a - * list item. They can always add non-breaking - * spaces if they want them. - * Setting trailing space true means it won't - * let the users add whitespace because it - * thinks there already is some. - */ - state->trailing_space = TRUE; -} - -void -lo_PlaceBullet(MWContext *context, lo_DocState *state) -{ - LO_BulletStruct *bullet = NULL; - int32 line_height, baseline; -#ifndef DOM - LO_TextAttr tmp_attr; -#endif - LO_TextStruct tmp_text; - LO_TextInfo text_info; - LO_TextAttr *tptr; - PA_Block buff; - char *str; - - bullet = (LO_BulletStruct *)lo_NewElement(context, state, - LO_BULLET, NULL, 0); - if (bullet == NULL) - { -#ifdef DEBUG - assert (state->top_state->out_of_memory); -#endif - return; - } - - bullet->type = LO_BULLET; - bullet->next = NULL; - bullet->prev = NULL; - - bullet->FE_Data = NULL; - - bullet->level = state->list_stack->level; - - bullet->bullet_type = state->list_stack->bullet_type; - - /* try and get a bullet type from style sheets */ - if(state && state->top_state && state->top_state->style_stack) - { - StyleStruct *style_struct = STYLESTACK_GetStyleByIndex( - state->top_state->style_stack, 0); - - if(style_struct) - { - char *list_style_prop = STYLESTRUCT_GetString( - style_struct, - LIST_STYLE_TYPE_STYLE); - if(list_style_prop) - { - bullet->bullet_type = lo_list_bullet_type(list_style_prop, - P_UNUM_LIST); - XP_FREE(list_style_prop); - } - } - } - - bullet->ele_attrmask = 0; - - bullet->sel_start = -1; - bullet->sel_end = -1; - - /* TEXTATTR HERE */ -#ifdef DOM - tptr = lo_GetCurrentTextAttr(state, context); -#else - if(state->font_stack) - { - lo_CopyTextAttr(state->font_stack->text_attr, &tmp_attr); - } - else - { - lo_SetDefaultFontAttr(state, &tmp_attr, context); - } - tptr = lo_FetchTextAttr(state, &tmp_attr); -#endif - - memset (&tmp_text, 0, sizeof (tmp_text)); - buff = PA_ALLOC(1); - if (buff == NULL) - { - state->top_state->out_of_memory = TRUE; - return; - } - PA_LOCK(str, char *, buff); - str[0] = ' '; - PA_UNLOCK(buff); - tmp_text.text = buff; - tmp_text.text_len = 1; - tmp_text.text_attr = tptr; - FE_GetTextInfo(context, &tmp_text, &text_info); - PA_FREE(buff); - - bullet->bullet_size = (text_info.ascent + text_info.descent) / 2; - bullet->text_attr = tptr; - - lo_FormatBullet(context, state, bullet, &line_height, &baseline); - - lo_AppendToLineList(context, state, (LO_Element *)bullet, 0); - - lo_UpdateStateAfterBullet(context, state, bullet, - line_height, - baseline); -} - - -void -lo_FormatBulletStr(MWContext *context, lo_DocState *state, - LO_TextStruct *bullet_text, - int32 *line_height, - int32 *baseline) -{ - LO_TextInfo text_info; - - FE_GetTextInfo(context, bullet_text, &text_info); - - bullet_text->x = state->x - (bullet_text->height / 2) - - bullet_text->width; - if (bullet_text->x < state->win_left) - { - bullet_text->x = state->win_left; - } - bullet_text->x_offset = 0; - bullet_text->y = state->y; - bullet_text->y_offset = 0; - - state->baseline = text_info.ascent; - state->line_height = (intn) bullet_text->height; - - *baseline = text_info.ascent; - *line_height = bullet_text->height; -} - -void -lo_UpdateStateAfterBulletStr(MWContext *context, - lo_DocState *state, - LO_TextStruct *bullet_text, - int32 line_height, - int32 baseline) -{ - state->baseline = baseline; - state->line_height = line_height; - - /* - * Clean up state - */ -/* - * Supporting old mistakes made in some other browsers. - * I will put the "correct code" here, but comment it out, since - * some other browsers allowed headers inside lists, so we should to, sigh. - state->linefeed_state = 0; - state->at_begin_line = FALSE; - */ - state->at_begin_line = TRUE; - state->cur_ele_type = LO_TEXT; -} - -void -lo_PlaceBulletStr(MWContext *context, lo_DocState *state) -{ - intn len; - char str2[22]; - char *str; - char *str3; - PA_Block buff; - LO_TextStruct *bullet_text = NULL; - LO_TextInfo text_info; - int bullet_type; - int32 line_height, baseline; - - bullet_text = (LO_TextStruct *)lo_NewElement(context, state, - LO_TEXT, NULL, 0); - if (bullet_text == NULL) - { -#ifdef DEBUG - assert (state->top_state->out_of_memory); -#endif - return; - } - - bullet_type = state->list_stack->bullet_type; - - /* try and get a bullet type from style sheets */ - if(state && state->top_state && state->top_state->style_stack) - { - StyleStruct *style_struct = STYLESTACK_GetStyleByIndex( - state->top_state->style_stack, 0); - - if(style_struct) - { - char *list_style_prop = STYLESTRUCT_GetString( - style_struct, - LIST_STYLE_TYPE_STYLE); - if(list_style_prop) - { - bullet_type = lo_list_bullet_type(list_style_prop, P_NUM_LIST); - XP_FREE(list_style_prop); - } - } - } - - - if( EDT_IS_EDITOR( context )) - { - switch( bullet_type ){ - case BULLET_ALPHA_L: - str = "A"; - break; - case BULLET_ALPHA_S: - str = "a"; - break; - case BULLET_NUM_S_ROMAN: - str = "x"; - break; - case BULLET_NUM_L_ROMAN: - str = "X"; - break; - default: - str = "#"; - break; - } - len = XP_STRLEN(str); - buff = PA_ALLOC(len + 1); - if (buff != NULL) - { - PA_LOCK(str3, char *, buff); - XP_STRCPY(str3, str); - PA_UNLOCK(buff); - } - } - else { - if (bullet_type == BULLET_ALPHA_S) - { - buff = lo_ValueToAlpha(state->list_stack->value, FALSE, &len); - } - else if (bullet_type == BULLET_ALPHA_L) - { - buff = lo_ValueToAlpha(state->list_stack->value, TRUE, &len); - } - else if (bullet_type == BULLET_NUM_S_ROMAN) - { - buff = lo_ValueToRoman(state->list_stack->value, FALSE, &len); - } - else if (bullet_type == BULLET_NUM_L_ROMAN) - { - buff = lo_ValueToRoman(state->list_stack->value, TRUE, &len); - } - else - { - XP_SPRINTF(str2, "%d.", (intn)state->list_stack->value); - len = XP_STRLEN(str2); - buff = PA_ALLOC(len + 1); - if (buff != NULL) - { - PA_LOCK(str, char *, buff); - XP_STRCPY(str, str2); - PA_UNLOCK(buff); - } - else - { - state->top_state->out_of_memory = TRUE; - } - } - } - - if (buff == NULL) - { - return; - } - - bullet_text->bullet_type = bullet_type; - bullet_text->text = buff; - bullet_text->text_len = len; - /* TEXTATTR HERE */ -#ifdef DOM - bullet_text->text_attr = lo_GetCurrentTextAttr(state, context); -#else - bullet_text->text_attr = state->font_stack->text_attr; -#endif - FE_GetTextInfo(context, bullet_text, &text_info); - bullet_text->width = lo_correct_text_element_width(&text_info); - bullet_text->height = text_info.ascent + text_info.descent; - bullet_text->line_height = 0; - bullet_text->y_offset = 0; - bullet_text->x_offset = 0; - - bullet_text->type = LO_TEXT; - bullet_text->ele_id = NEXT_ELEMENT; - - lo_FormatBulletStr(context, state, bullet_text, &line_height, &baseline); - - bullet_text->anchor_href = state->current_anchor; - - bullet_text->ele_attrmask = 0; - if (state->breakable != FALSE) - { - bullet_text->ele_attrmask |= LO_ELE_BREAKABLE; - } - - bullet_text->sel_start = -1; - bullet_text->sel_end = -1; - - bullet_text->next = NULL; - bullet_text->prev = NULL; - - bullet_text->FE_Data = NULL; - - lo_AppendToLineList(context, state, (LO_Element *)bullet_text, 0); - - state->baseline = text_info.ascent; - state->line_height = (intn) bullet_text->height; - - lo_UpdateStateAfterBulletStr(context, state, bullet_text, - line_height, baseline); -} - - -static LO_Element * -lo_make_quote_text(MWContext *context, lo_DocState *state, int32 margin) -{ - PA_Block buff; - char *str; - LO_TextStruct *quote_text; - LO_TextAttr tmp_attr; - LO_TextInfo text_info; - - quote_text = (LO_TextStruct *)lo_NewElement(context, state, LO_TEXT, - NULL, 0); - if (quote_text == NULL) - { -#ifdef DEBUG - assert (state->top_state->out_of_memory); -#endif - return(NULL); - } - - buff = PA_ALLOC(2); - if (buff == NULL) - { - state->top_state->out_of_memory = TRUE; - return(NULL); - } - PA_LOCK(str, char *, buff); - str[0] = '>'; - str[1] = '\0'; - PA_UNLOCK(buff); - - quote_text->text = buff; - quote_text->text_len = 1; - /* - * Fill in default fixed font information. - */ - /* TEXTATTR HERE -- why does this not use the font stack? */ - lo_SetDefaultFontAttr(state, &tmp_attr, context); - tmp_attr.fontmask |= LO_FONT_FIXED; - quote_text->text_attr = lo_FetchTextAttr(state, &tmp_attr); - FE_GetTextInfo(context, quote_text, &text_info); - quote_text->width = lo_correct_text_element_width(&text_info); - quote_text->height = text_info.ascent + text_info.descent; - - quote_text->type = LO_TEXT; - quote_text->ele_id = 0; - quote_text->x = margin; - if (quote_text->x < state->win_left) - { - quote_text->x = state->win_left; - } - quote_text->x_offset = 0; - quote_text->y = state->y; - quote_text->y_offset = 0; - quote_text->line_height = 0; - - quote_text->anchor_href = state->current_anchor; - - quote_text->ele_attrmask = 0; - if (state->breakable != FALSE) - { - quote_text->ele_attrmask |= LO_ELE_BREAKABLE; - } - - quote_text->bullet_type = BULLET_MQUOTE; - - quote_text->sel_start = -1; - quote_text->sel_end = -1; - - quote_text->next = NULL; - quote_text->prev = NULL; - - quote_text->FE_Data = NULL; - - state->baseline = text_info.ascent; - - return((LO_Element *)quote_text); -} - - -static LO_Element * -lo_make_quote_bullet(MWContext *context, lo_DocState *state, int32 margin) -{ - PA_Block buff; - char *str; - LO_BulletStruct *bullet = NULL; - LO_TextAttr tmp_attr; - LO_TextInfo text_info; - LO_TextStruct tmp_text; - LO_TextAttr *tptr; - int32 bullet_size; - - bullet = (LO_BulletStruct *)lo_NewElement(context, state, - LO_BULLET, NULL, 0); - if (bullet == NULL) - { -#ifdef DEBUG - assert (state->top_state->out_of_memory); -#endif - return(NULL); - } - - /* TEXTATTR HERE -- why does this not use font/style info? */ - lo_SetDefaultFontAttr(state, &tmp_attr, context); - tmp_attr.fg.red = 0; - tmp_attr.fg.green = 0; - tmp_attr.fg.blue = 255; -#ifdef DOM - tptr = lo_FillInTextStyleInfo(state, context, &tmp_attr, JS_TRUE); -#else - tptr = lo_FetchTextAttr(state, &tmp_attr); -#endif - - memset (&tmp_text, 0, sizeof (tmp_text)); - buff = PA_ALLOC(1); - if (buff == NULL) - { - state->top_state->out_of_memory = TRUE; - return(NULL); - } - PA_LOCK(str, char *, buff); - str[0] = ' '; - PA_UNLOCK(buff); - tmp_text.text = buff; - tmp_text.text_len = 1; - tmp_text.text_attr = tptr; - FE_GetTextInfo(context, &tmp_text, &text_info); - PA_FREE(buff); - - bullet_size = text_info.ascent + text_info.descent; - - if (bullet_size < 5) - { - bullet_size = 5; - } - - bullet->type = LO_BULLET; - bullet->ele_id = 0; - bullet->x = margin; - if (bullet->x < state->win_left) - { - bullet->x = state->win_left; - } - bullet->x_offset = 0; - bullet->y = state->y; - bullet->y_offset = 0; - bullet->width = 5; - bullet->height = bullet_size; - bullet->next = NULL; - bullet->prev = NULL; - - bullet->FE_Data = NULL; - - bullet->level = state->list_stack->level; - bullet->bullet_type = BULLET_MQUOTE; - bullet->text_attr = tptr; - - bullet->ele_attrmask = 0; - - bullet->sel_start = -1; - bullet->sel_end = -1; - - state->baseline = text_info.ascent; - - return((LO_Element *)bullet); -} - - -static void -lo_insert_quote_characters(MWContext *context, lo_DocState *state) -{ - LO_Element *eptr; - LO_Element *elist; - lo_ListStack *lptr; - - elist = NULL; - lptr = state->list_stack; - while (lptr != NULL) - { - eptr = NULL; - if (lptr->quote_type == QUOTE_JWZ) - { - eptr = lo_make_quote_text(context, state, - lptr->mquote_x); - } - else if (lptr->quote_type == QUOTE_CITE) - { - eptr = lo_make_quote_bullet(context, state, - lptr->mquote_x); - } - if (eptr != NULL) - { - eptr->lo_any.next = elist; - elist = eptr; - } - lptr = lptr->next; - } - - eptr = elist; - while (eptr != NULL) - { - LO_Element *tmp_ele; - - tmp_ele = eptr; - eptr = eptr->lo_any.next; - tmp_ele->lo_any.next = NULL; - - tmp_ele->lo_any.ele_id = NEXT_ELEMENT; - lo_AppendToLineList(context, state, tmp_ele, 0); - state->line_height = (intn)tmp_ele->lo_any.height; - state->at_begin_line = TRUE; - state->cur_ele_type = LO_TEXT; - } -} - - -void -lo_PlaceQuoteMarker(MWContext *context, lo_DocState *state, lo_ListStack *lptr) -{ - LO_Element *eptr; - - if (lptr != NULL) - { - eptr = NULL; - if (lptr->quote_type == QUOTE_JWZ) - { - eptr = lo_make_quote_text(context, state, - lptr->mquote_x); - } - else if (lptr->quote_type == QUOTE_CITE) - { - eptr = lo_make_quote_bullet(context, state, - lptr->mquote_x); - } - if (eptr != NULL) - { - eptr->lo_any.ele_id = NEXT_ELEMENT; - lo_AppendToLineList(context, state, eptr, 0); - state->line_height = (intn)eptr->lo_any.height; - state->at_begin_line = TRUE; - if (lptr->quote_type == QUOTE_JWZ) - { - state->cur_ele_type = LO_TEXT; - } - else if (lptr->quote_type == QUOTE_CITE) - { - state->cur_ele_type = LO_BULLET; - } - } - } -} - - -void lo_UpdateStateAfterLineBreak( MWContext *context, - lo_DocState *state, - Bool updateFE ) -{ - int32 line_width; - - /* - * if this linefeed has a zero height, make it the height - * of the current font. - */ - if (state->line_height == 0) - { - state->line_height = state->text_info.ascent + - state->text_info.descent; - if ((state->line_height <= 0) -#ifndef DOM - &&(state->font_stack != NULL)&& - (state->font_stack->text_attr != NULL) -#endif - ) - { - lo_fillin_text_info(context, state); - state->line_height = state->text_info.ascent + - state->text_info.descent; - } - /* - * This should never happen, but we have it - * covered just in case it does :-) - */ - if (state->line_height <= 0) - { - state->line_height = state->default_line_height; - } - } - - if (state->end_last_line != NULL) - { - line_width = state->end_last_line->lo_any.x + state->win_right; - } - else - { - line_width = state->x + state->win_right; - } - - if (line_width > state->max_width) - { - state->max_width = line_width; - } - - /* if LineHeightStack exists use it to offset the new Y value */ - if(state->cur_ele_type != LO_SUBDOC && state->line_height_stack) - { - state->y += state->line_height_stack->height; - } - else - { - state->y = state->y + state->line_height; - } - - state->x = state->left_margin; - state->width = 0; - state->at_begin_line = TRUE; - state->trailing_space = FALSE; - state->line_height = 0; - state->break_holder = state->x; - - state->linefeed_state++; - if (state->linefeed_state > 2) - { - state->linefeed_state = 2; - } - - /* - * Reset the left and right margins - */ - lo_FindLineMargins(context, state, updateFE); - state->x = state->left_margin; - -} - -void lo_UpdateFEProgressBar( MWContext *context, lo_DocState *state ) -{ - if (state->is_a_subdoc == SUBDOC_NOT) - { - int32 percent; - - if (state->top_state->total_bytes < 1) - { - percent = -1; - } - else - { - percent = (100 * state->top_state->layout_bytes) / - state->top_state->total_bytes; - if (percent > 100) - { - percent = 100; - } - } - if ((percent == 100)||(percent < 0)|| - (percent > (state->top_state->layout_percent + 1))) - { -#if !defined(SMOOTH_PROGRESS) - if(!state->top_state->is_binary) - FE_SetProgressBarPercent(context, percent); -#endif /* !defined(SMOOTH_PROGRESS) */ - state->top_state->layout_percent = (intn)percent; - } - } -} - -void lo_UpdateFEDocSize( MWContext *context, lo_DocState *state ) -{ - /* - * Tell the front end how big the document is right now. - * Only do this for the top level document. - */ - if ((state->is_a_subdoc == SUBDOC_NOT) - &&(state->display_blocked == FALSE) -#ifdef EDITOR - &&(!state->edit_relayout_display_blocked) -#endif - ) - { - - /* - * Don't resize the layer if we're laying out a block. This - * will be done when the line is added to the block. - */ - if (!lo_InsideLayer(state)) - { - LO_SetDocumentDimensions(context, state->max_width, state->y); - } - } -} - - -void lo_FillInLineFeed( MWContext *context, - lo_DocState *state, - int32 break_type, - uint32 clear_type, - LO_LinefeedStruct *linefeed ) -{ - linefeed->type = LO_LINEFEED; - linefeed->ele_id = NEXT_ELEMENT; - linefeed->x = state->x; - linefeed->x_offset = 0; - linefeed->y = state->y; - linefeed->y_offset = 0; - /* - * If we're laying out a block, we want the contents of the block - * to determine the size of the block. The right margin is nothing - * more than a hint for where to wrap the contents. We don't want - * the linefeed to extend out to the right margin, because it - * unnecessarily extends the block contents. - */ - if (state->layer_nest_level > 0) { - linefeed->width = 0; - } - else - linefeed->width = state->right_margin - state->x; - if (linefeed->width < 0) - { - linefeed->width = 0; - } - linefeed->height = state->line_height; - /* - * if this linefeed has a zero height, make it the height - * of the current font. - */ - if (linefeed->height == 0) - { - linefeed->height = state->text_info.ascent + - state->text_info.descent; - if ((linefeed->height <= 0) -#ifndef DOM - &&(state->font_stack != NULL)&& - (state->font_stack->text_attr != NULL) -#endif - ) - { - lo_fillin_text_info(context, state); - linefeed->height = state->text_info.ascent + - state->text_info.descent; - } - /* - * This should never happen, but we have it - * covered just in case it does :-) - */ - if (linefeed->height <= 0) - { - linefeed->height = state->default_line_height; - } - } - linefeed->line_height = linefeed->height; - - linefeed->FE_Data = NULL; - linefeed->anchor_href = state->current_anchor; - -#ifdef DOM - linefeed->text_attr = lo_GetCurrentTextAttr(state, context); -#else - if (state->font_stack == NULL) - { - LO_TextAttr tmp_attr; - LO_TextAttr *tptr; - - /* - * Fill in default font information. - */ - lo_SetDefaultFontAttr(state, &tmp_attr, context); - tptr = lo_FetchTextAttr(state, &tmp_attr); - linefeed->text_attr = tptr; - } - else - { - /* TEXTATTR HERE */ - linefeed->text_attr = state->font_stack->text_attr; - } -#endif - - linefeed->baseline = state->baseline; - - linefeed->ele_attrmask = 0; - - linefeed->sel_start = -1; - linefeed->sel_end = -1; - - linefeed->next = NULL; - linefeed->prev = NULL; - linefeed->break_type = (uint8) break_type; - linefeed->clear_type = (uint8) clear_type; -} - -Bool lo_CanUseBreakTable ( lo_DocState * state ) -{ - Bool useBreakTable; - - useBreakTable = TRUE; - -#ifndef FAST_MULTI - /* - * We also need some sort of check for the script - for example - * Arabic should go through the old algorithm for now. - */ - if ( kMBTextParseAttribute == lo_GetTextParseAttributes(state) ) - { - useBreakTable = FALSE; - } -#endif - - /* - * Justified text is currently broken, route it through old layout for now - */ - if ( ( state->align_stack != NULL ) && - ( state->align_stack->alignment == LO_ALIGN_JUSTIFY ) ) - { - useBreakTable = FALSE; - } - -#ifndef FAST_EDITOR - if ( EDT_IS_EDITOR( context ) ) - { - useBreakTable = FALSE; - } -#endif - -#ifdef XP_MAC - if ( !gCallNewText ) - { - useBreakTable = FALSE; - } -#endif - - return useBreakTable; -} - -/* - * Is the current text that's being layed out using the break table - * layout algorithm? - */ -Bool lo_UseBreakTable ( LO_TextBlock * block ) -{ - Bool useBreakTable; - - useBreakTable = FALSE; - - if ( block != NULL ) - { - if ( block->break_table != NULL ) - { - useBreakTable = TRUE; - } - } - - return useBreakTable; -} - -int32 lo_compute_text_basline_inc ( lo_DocState * state, - LO_TextBlock * block, - LO_TextStruct * text_data ) -{ - int32 line_inc; - int32 baseline_inc; - - /* - * The baseline of the text element just added to the line may be - * less than or greater than the baseline of the rest of the line - * due to font changes. If the baseline is less, this is easy, - * we just increase y_offest to move the text down so the baselines - * line up. For greater baselines, we can't move the text up to - * line up the baselines because we will overlay the previous line, - * so we have to move all the previous elements in this line down. - * - * If the baseline is zero, we are the first element on the line, - * and we get to set the baseline. - */ - - line_inc = 0; - baseline_inc = 0; - - if (state->baseline == 0) - { - state->baseline = block->ascent; - if (state->line_height < (state->baseline + block->descent)) - { - state->line_height = state->baseline + block->descent; - } - } - else if (block->ascent < state->baseline) - { - text_data->y_offset = state->baseline - block->ascent; - if ((text_data->y_offset + block->ascent + block->descent) > state->line_height) - { - line_inc = text_data->y_offset + - block->ascent + - block->descent - - state->line_height; - } - } - else - { - baseline_inc = block->ascent - state->baseline; - if ((text_data->y_offset + block->ascent + block->descent - baseline_inc) > state->line_height) - { - line_inc = text_data->y_offset + - block->ascent + - block->descent - - state->line_height - baseline_inc; - } - } - - state->baseline += (intn) baseline_inc; - state->line_height += (intn) (baseline_inc + line_inc); - - return baseline_inc; -} - - -void lo_FlushTextElement ( MWContext * context, - lo_DocState * state, - LO_TextBlock * block, - LO_TextStruct * element ) -{ - int32 baseline_inc; - - /* update the text layout state as if we had just layed this element out */ - block->buffer_read_index = element->block_offset; - - state->width = element->width; - - element->ele_id = NEXT_ELEMENT; - element->x = state->x; - element->y = state->y; - element->y_offset = 0; - - element->sel_start = -1; - element->sel_end = -1; - - baseline_inc = lo_compute_text_basline_inc ( state, block, element ); - - element->prev = NULL; - element->next = NULL; - lo_AppendToLineList ( context, state, (LO_Element *) element, - baseline_inc ); - - state->line_buf_len = 0; - state->x += state->width; - state->width = 0; - state->cur_ele_type = LO_NONE; - - /* update the element list for this block */ - if ( block->startTextElement == NULL ) - { - block->startTextElement = element; - } - - block->endTextElement = element; -} - -uint32 lo_FindBlockOffset ( LO_TextBlock * block, LO_TextStruct * fromElement ) -{ - uint32 blockOffset; - LO_Element * endElement; - LO_Element * element; - - blockOffset = 0; - - if ( fromElement != NULL ) - { - /* run through all elements in this text block. the correct - block offset is belongs to */ - /* the previous element in this list */ - element = (LO_Element *) block->startTextElement; - endElement = (LO_Element *) block->endTextElement; - - while ( element != NULL ) - { - if ( element == endElement ) - { - break; - } - - /* is it the one we're looking for? */ - if ( element == (LO_Element *) fromElement ) - { - break; - } - - if ( element->type == LO_TEXT ) - { - blockOffset = element->lo_text.block_offset; - } - - element = element->lo_any.next; - } - } - - return blockOffset; -} - -void lo_RelayoutTextElements ( MWContext * context, - lo_DocState * state, - LO_TextBlock * block, - LO_TextStruct * fromElement ) -{ - LO_Element * next; - LO_Element * element; - LO_Element * startElement; - LO_Element * endElement; - uint32 lineWidth; - Bool done; - Bool fastPreformat; - - /* start at the beginning of this text block */ - block->buffer_read_index = 0; - block->break_read_index = 0; - - /* we will rebuild the element list for this block as we go */ - startElement = (LO_Element *) block->startTextElement; - endElement = (LO_Element *) block->endTextElement; - - block->startTextElement = NULL; - block->endTextElement = NULL; - - if ( fromElement == NULL ) - fromElement = (LO_TextStruct *)lo_tv_GetNextLayoutElement ( state, (LO_Element*)block, FALSE ); - - if ( fromElement == NULL) - fromElement = (LO_TextStruct *) startElement; - - /* sanity check */ - if ( fromElement == NULL ) - return; - - /* - * We need to run through all elements up to start element and place them - * back in the line list. We also need to recycle anything that's not text - * (linefeeds and bullets) - */ - element = startElement; - - while ( element != (LO_Element *) fromElement ) - { - next = lo_tv_GetNextLayoutElement ( state, element, FALSE ); - - /* if this element is text, put it on the line list */ - switch ( element->lo_any.type ) - { - case LO_TEXT: - lo_PrepareElementForReuse ( context, state, element, - element->lo_any.edit_element, - element->lo_any.edit_offset ); - lo_FlushTextElement ( context, state, block, - (LO_TextStruct *) element ); - break; - - case LO_LINEFEED: - /* recycle this element */ - element->lo_any.prev = NULL; - element->lo_any.next = NULL; - lo_RecycleElements( context, state, element ); - - /* and then add a new linefeed */ - lo_rl_AddSoftBreakAndFlushLine ( context, state ); - - break; - - default: - element->lo_any.prev = NULL; - element->lo_any.next = NULL; - lo_RecycleElements( context, state, element ); - break; - } - - element = next; - } - - /* - * Now, we may not need to lay any of the following elements out as out - * layout environment may not have changed. So, run through the remaining - * elements until we find the first one that's changed. - * - * We have to layout the last element using the proper code path - * so that we can correctly update the state record with the last - * break position and other flags. - * - * Column and line wrapped preformatted text can always reuse the - * elements as it's wrapping will never change. Word wrapped - * preformatted text may change if the document width changes. - */ - - element = (LO_Element *) fromElement; - fastPreformat = ( block->format_mode == PRE_TEXT_YES ) || ( block->format_mode == PRE_TEXT_COLS ); - - while ( element != NULL ) - { - next = lo_tv_GetNextLayoutElement ( state, element, FALSE ); - - /* if this element is text, see if it will fit. otherwise recycle it */ - switch ( element->lo_any.type ) - { - case LO_TEXT: - /* - * We only assume this element can be reused if the - * line width is exactly the same as last time. If the - * line is longer, we could potentially reuse this - * element (the next one may appear on this line as - * well) but we won't be able to set the state's - * old_break_position, which may be needed! - * - * We can also always flush column or line wrapped - * preformatted text (word wrapped preformatted text - * may need to be layed out again as it's wrapping may - * change). - */ - lineWidth = state->right_margin - state->x; - - if ( fastPreformat || ( element->lo_text.doc_width == lineWidth ) ) - { - lo_PrepareElementForReuse ( context, state, element, element->lo_any.edit_element, - element->lo_any.edit_offset ); - lo_FlushTextElement ( context, state, block, (LO_TextStruct *) element ); - } - else - { - /* the size has changed, we must relayout this element */ - done = TRUE; - } - - break; - - case LO_LINEFEED: - /* recycle this element */ - element->lo_any.prev = NULL; - element->lo_any.next = NULL; - lo_RecycleElements( context, state, element ); - - /* Fix for bug 129639: Only add the new linefeed for preformatted text. - Calling lo_rl_AddSoftBreakAndFlushLine() causes extra line feeds to - be generated for regular text. */ - if (fastPreformat) - lo_rl_AddSoftBreakAndFlushLine ( context, state ); - - break; - - default: - element->lo_any.prev = NULL; - element->lo_any.next = NULL; - lo_RecycleElements( context, state, element ); - break; - } - - if ( element == endElement ) - break; - - element = next; - } -} - -LO_Element * lo_RelayoutTextBlock ( MWContext * context, lo_DocState * state, LO_TextBlock * block, LO_TextStruct * fromElement ) -{ - LO_Element * next; - LO_Element * endElement; - LO_Element * lo_ele; - - state->cur_text_block = block; - - /* - * Update some of the global state information - */ - state->breakable = block->ele_attrmask & LO_ELE_BREAKABLE; - - /* get the next element for the overall relayout process */ - if ( block->endTextElement != NULL ) - { - next = lo_tv_GetNextLayoutElement ( state, (LO_Element *) block->endTextElement, FALSE ); - } - else - { - next = lo_tv_GetNextLayoutElement ( state, (LO_Element *) block, FALSE ); - } - - /* - * In the relayout case we might be able to skip layout for some - * elements that have not changed. This happens frequenty for - * typing in the editor and occasionaly in table layout (very - * occasionally on resizes). - * - * To do this, we run through the text elements until we come - * across one whose width does not match the layout width or whose - * text has changed. That element and all others are then - * recycled. - */ - - if ( EDT_IS_EDITOR( context ) ) - { - /* - * for the editor we don't want to relayout the text elements - * that precede the current one. we just want to start laying - * out afresh from this specified element to the end of the - * text block. the editor will take care of merging the - * elements back in - */ - block->buffer_read_index = lo_FindBlockOffset ( block, fromElement ); - - state->edit_current_element = block->edit_element; - state->edit_current_offset = 0; - - /* if we're laying this element out, then we need to reinsert - it on the line list */ - if ( ( block->startTextElement == fromElement ) || ( fromElement == NULL ) ) - { - /* record the current edit element for later use */ - lo_PrepareElementForReuse ( context, state, (LO_Element *) block, block->edit_element, - block->edit_offset ); - - block->ele_id = NEXT_ELEMENT; - block->x = state->x; - block->y = state->y; - block->x_offset = 0; - block->y_offset = 0; - - /* free all the text elements that we're going to reflow */ - endElement = (LO_Element *) block->endTextElement; - lo_ele = (LO_Element *) block->startTextElement; - while ( lo_ele != NULL ) - { - LO_Element * next_ele; - - next_ele = lo_ele->lo_any.next; - - lo_ele->lo_any.next = NULL; - lo_ele->lo_any.prev = NULL; - lo_RecycleElements( context, state, lo_ele ); - - if ( lo_ele == endElement ) - { - break; - } - - lo_ele = next_ele; - } - - block->startTextElement = NULL; - block->endTextElement = NULL; - - block->prev = NULL; - block->next = NULL; - lo_AppendToLineList ( context, state, (LO_Element *) block, 0 ); - } - else - { - LO_TextStruct * lastText; - Bool hitFromElement; - - /* We're reflowing from somewhere within the text block - * (past the first element). We need to reset the - * endTextElement as well as recycle from the fromElement - * to the end of the text block */ - - hitFromElement = FALSE; - endElement = (LO_Element *) block->endTextElement; - lo_ele = (LO_Element *) block->startTextElement; - lastText = block->startTextElement; - - while ( lo_ele != NULL ) - { - LO_Element * next_ele; - - next_ele = lo_ele->lo_any.next; - - if ( lo_ele == (LO_Element *) fromElement ) - { - hitFromElement = TRUE; - } - - /* if we've found the fromElement, we need to start - recycling */ - if ( hitFromElement ) - { - lo_ele->lo_any.next = NULL; - lo_ele->lo_any.prev = NULL; - lo_RecycleElements( context, state, lo_ele ); - } - - if ( lo_ele == endElement ) - { - break; - } - - /* if we haven't hit the from element and this is a - text element, it may be the new end */ - /* element for the block */ - if ( !hitFromElement && ( lo_ele->type == LO_TEXT ) ) - { - lastText = &lo_ele->lo_text; - } - - lo_ele = next_ele; - } - - /* reset the endElement for the block */ - block->endTextElement = lastText; - } - } - else - { - /* put the text block back in the line list and then add any - existing elements that we can */ - block->prev = NULL; - block->next = NULL; - block->ele_id = NEXT_ELEMENT; - block->x = state->x; - block->y = state->y; - lo_AppendToLineList ( context, state, (LO_Element *) block, 0 ); - - lo_RelayoutTextElements ( context, state, block, fromElement ); - } - - /* Because we're lame for now we just delete all the old linefeeds - * and lay the text out afresh */ - - /* Tell everybody we're laying out text */ - if (state->cur_ele_type != LO_TEXT) - { - lo_FreshText(state); - state->cur_ele_type = LO_TEXT; - } - - /* actually layout the text */ - state->preformatted = block->format_mode; - - if ( lo_UseBreakTable ( block ) ) - { - lo_SetupBreakState ( block ); - - /* be sure to set up the editor offset */ - if ( EDT_IS_EDITOR( context ) ) - { - state->edit_force_offset = TRUE; - state->edit_current_offset = block->buffer_read_index; - } - - lo_LayoutTextBlock ( context, state, TRUE ); - } - else - if ( block->format_mode == PRE_TEXT_NO ) - { - lo_LayoutFormattedText ( context, state, block ); - } - else - { - lo_LayoutPreformattedText ( context, state, block ); - } - - /* - * If there's text left in the line buffer, then flush it. - * - * BRAIN DAMAGE: We don't want to do that here - there may be a - * following text block that continues this same text buffer. - */ - lo_FlushLineBuffer(context, state); - - return next; -} - -Bool lo_ChangeText ( LO_TextBlock * block, char * text ) -{ - uint32 length; - /* - * Reset the text contents for this text block. If we have a break table, - * then we need to rebuild it. - */ - -#ifdef LOCAL_DEBUG - XP_TRACE( ("Setting text for text block %lx to %s", block, text) ); -#endif - - length = XP_STRLEN ( text ) + 1; - if ( length > block->buffer_write_index ) - { - if ( !lo_GrowTextBlock ( block, length - block->buffer_write_index ) ) - { - return FALSE; - } - } - - if ( lo_UseBreakTable ( block ) ) - { - block->buffer_write_index = 0; - block->last_buffer_write_index = 0; - block->break_write_index = 0; - block->last_break_offset = 0; - - lo_AppendTextToBlock ( NULL, NULL, block, text ); - } - else - { - /* for old style text we just want to replace the buffer */ - XP_BCOPY ( text, (char *) block->text_buffer, length ); - block->buffer_write_index = length; - } - - return TRUE; -} - -/* - * - * =========================================================================== - * - * New text layout - * - * ========================================================================== - */ - -/* - * Break Table constants - */ - -#define MAX_NATURAL_LENGTH 0xAL -#define LINE_FEED 0xBL -#define BYTE_LENGTH 0xCL -#define WORD_LENGTH 0xDL -#define LONG_LENGTH 0xEL -#define MULTI_BYTE 0xFL - -#define MULTI_BYTE_DATA_SIZE 16 - -/* - * Break Position Magic Constants - */ -#define OVERRAN_BREAK_TABLE -1 -#define BREAK_LINEFEED -2 - -#define TEXT_BUFFER_INC 256 -#define BREAK_TABLE_INC 64 - -typedef struct BreakState -{ - uint32 buffer_read_index; - uint32 break_read_index; - uint32 multibyte_index; - uint32 multibyte_length; - uint32 last_line_break; - uint32 lineLength; -} BreakState; - -static LO_TextBlock * lo_CurrentTextBlock ( MWContext * context, lo_DocState * state ); - -/* routines to walk through our break table */ -static uint8 * lo_GetNextTextPosition ( LO_TextBlock * block, uint32 * outWordLength, uint32 * outLineLength, Bool * canBreak ); -static uint8 * lo_GetPrevTextPosition ( LO_TextBlock * block, uint32 * outWordLength, uint32 * outLineLength, Bool * canBreak ); -static uint8 * lo_RestoreBreakState ( LO_TextBlock * block, BreakState * state, uint32 * lineLength ); -static void lo_SetLineBreak ( LO_TextBlock * block, Bool skipSpace ); -static uint8 * lo_GetLineStart ( LO_TextBlock * block ); -static void lo_SkipCharacter ( LO_TextBlock * block ); -static Bool lo_SkipInitialSpace ( LO_TextBlock * block ); - -static Bool lo_SetBreakPosition ( LO_TextBlock * block ); -static Bool lo_SetMultiByteRun ( LO_TextBlock * block, int32 charSize, Bool breakable, Bool eachCharBreakable ); -static Bool lo_SetBreakCommand ( LO_TextBlock * block, uint32 command, uint32 commandLength ); -static void lo_CopyText ( uint8 * src, uint8 * dst, uint32 length ); -static void lo_CopyTextToLineBuffer ( lo_DocState * state, uint8 * src, uint32 length ); - -static uint32 lo_FindLineBreak ( MWContext * context, lo_DocState * state, LO_TextBlock * block, uint8 * text, - uint16 * widthTable, uint32 * width, int32 * minWidth, Bool * allTextFits ); - -/* the parsers */ -static void lo_ParseSingleText ( lo_DocState * state, LO_TextBlock * block, Bool parseAllText, char * text ); -static void lo_ParseThaiText ( lo_DocState * state, LO_TextBlock * block, Bool parseAllText, char * text ); -#ifndef DOM -static void lo_ParseSinglePreformattedText ( lo_DocState * state, LO_TextBlock * block, Bool parseAllText, char * text ); -static void lo_ParseDoublePreformattedText ( lo_DocState * state, LO_TextBlock * block, Bool parseAllText, char * text ); -#endif -static void lo_ParseDoubleText ( lo_DocState * state, LO_TextBlock * block, Bool parseAllText, char * text ); - -extern int32 lo_correct_text_element_width(LO_TextInfo *text_info); - -#ifdef LOG -static Bool gHaveLog = FALSE; -#endif - - -/* - * Some helpful macros for code inlining - */ - -#define SAVE_BREAK_STATE(block,state,line_length) \ - (state)->buffer_read_index = (block)->buffer_read_index; \ - (state)->break_read_index = (block)->break_read_index; \ - (state)->multibyte_index = (block)->multibyte_index; \ - (state)->multibyte_length = (block)->multibyte_length; \ - (state)->last_line_break = (block)->last_line_break; \ - (state)->lineLength = line_length; - - -static LO_TextBlock * -lo_CurrentTextBlock ( MWContext * context, lo_DocState * state ) -{ - LO_TextBlock * textBlock; - - textBlock = state->cur_text_block; - if ( textBlock == NULL ) - { - textBlock = (LO_TextBlock *)lo_NewElement ( context, state, LO_TEXTBLOCK, NULL, 0 ); - - textBlock->type = LO_TEXTBLOCK; - textBlock->x_offset = 0; - textBlock->ele_id = NEXT_ELEMENT; - textBlock->x = state->x; - textBlock->y = state->y; - textBlock->y_offset = 0; - textBlock->width = 0; - textBlock->height = 0; - textBlock->line_height = 0; - textBlock->next = NULL; - textBlock->prev = NULL; - textBlock->text_attr = NULL; - textBlock->anchor_href = NULL; - textBlock->ele_attrmask = 0; - textBlock->format_mode = 0; - - textBlock->startTextElement = NULL; - textBlock->endTextElement = NULL; - - textBlock->text_buffer = NULL; - textBlock->buffer_length = 0; - textBlock->buffer_write_index = 0; - textBlock->last_buffer_write_index = 0; - textBlock->buffer_read_index = 0; - textBlock->last_line_break = 0; - - textBlock->break_table = NULL; - textBlock->break_length = 0; - textBlock->break_write_index = 0; - textBlock->break_read_index = 0; - textBlock->last_break_offset = 0; - textBlock->multibyte_index = 0; - textBlock->multibyte_length = 0; - - textBlock->old_break = NULL; - textBlock->old_break_pos = 0; - textBlock->old_break_width = 0; - - textBlock->totalWidth = 0; - textBlock->totalChars = 0; - textBlock->break_pending = 0; - textBlock->last_char_is_whitespace = 0; - - textBlock->ascent = 0; - textBlock->descent = 0; - - /* BRAIN DAMAGE: Add this enum to lo_ele.h! */ - textBlock->text_buffer = XP_ALLOC ( TEXT_BUFFER_INC ); - textBlock->buffer_length = TEXT_BUFFER_INC; - - textBlock->break_table = XP_ALLOC ( BREAK_TABLE_INC ); - textBlock->break_length = BREAK_TABLE_INC * 2; - - /* Since we're creating a new text block, grab some of the - * text state out of the layout state. */ - textBlock->anchor_href = state->current_anchor; - - if ( state->font_stack != NULL ) - { - /* TEXTATTR HERE */ -#ifdef DOM - textBlock->text_attr = lo_GetCurrentTextAttr(state, context); -#else - textBlock->text_attr = state->font_stack->text_attr; -#endif - } - - if (state->breakable != FALSE) - { - textBlock->ele_attrmask |= LO_ELE_BREAKABLE; - } - - state->cur_text_block = textBlock; - - lo_AppendToLineList ( context, state, (LO_Element *) textBlock, 0 ); - } - - return textBlock; -} - -void lo_AppendTextToBlock ( MWContext *context, lo_DocState *state, LO_TextBlock * block, char *text ) -{ - Bool parseAllText; - - /* - * We have several cases in which we can just bail: - * 1. The text string and the line buffer is empty. - * 2. The text string is all whitespace and we already have a trailing - * space. - */ - - if ( ( state != NULL ) && ( state->line_buf_len == 0 ) ) - { - char * t_ptr; - - /* if this string is empty, bail */ - if ( *text == '\0' ) - { - return; - } - - /* if it's only whitespace and we have a trailing space, then bail */ - if ( state->trailing_space ) - { - t_ptr = text; - - while ( *t_ptr != '\0' ) - { - if ( !XP_IS_SPACE( *t_ptr ) ) - { - break; - } - - ++t_ptr; - } - - if ( ( *t_ptr == '\0' ) && ( t_ptr != text ) ) - { - return; - } - } - } - - /* If we don't have a block, create one if we have a valid state - * record. Otherwise we have an error */ - - if ( block == NULL ) - { - /* the editor may call us with a NULL state and context - record, in this case we must always have a block */ - XP_ASSERT(( state != NULL ) && ( context != NULL )); - if ( ( state != NULL ) && ( context != NULL ) ) - { - block = lo_CurrentTextBlock ( context, state ); - } - } - - /* OPTIMIZATION: If the parser could tell us if we have a split - * buffer then we could intelligently set parseAllText here and - * not buffer words that we think may be split across a buffer but - * in reality are whole. */ - - /* If we're in an editor context, then we can always parse the - * whole buffer of text, we never need to worry about partial - * buffers being passed to us. */ - parseAllText = EDT_IS_EDITOR( context ); - - /* Scan through the text, removing whitespace and adding words to - * the text buffer as we come across them. - * - * Particular things we have to deal with: - * - Preformatted text (normal, word wrapped and column wrapped) - * - Normal single byte text - * - Multibyte text - * - non-breaking spaces - */ - - switch( lo_GetTextParseAttributes ( state )) - { - case kSimpleSBTextParseAttribute: - lo_ParseSingleText ( state, block, parseAllText, text ); - break; - - case kMBTextParseAttribute: - lo_ParseDoubleText ( state, block, parseAllText, text ); - break; - - case kThaiTextParseAttribute: - lo_ParseThaiText ( state, block, parseAllText, text ); - break; - - default: - XP_ASSERT(0); /* wrong text parse attribute value */ - break; - } -} -static loTextParseAttribute -lo_GetTextParseAttributes ( lo_DocState * state) -{ - - /* XP_ASSERT(NULL != state); */ - if ( state != NULL ) - { - uint16 charset = state->font_stack->text_attr->charset; - if ( charset == CS_TIS620 ) - return kThaiTextParseAttribute; - - if ( (INTL_CharSetType ( charset ) != SINGLEBYTE ) && - !( INTL_CharSetType ( charset ) & CS_SPACE ) ) - return kMBTextParseAttribute; - } - - return kSimpleSBTextParseAttribute; -} - -static void -lo_ParseThaiText ( lo_DocState * state, LO_TextBlock * block, Bool parseAllText, char * text ) -{ - - XP_ASSERT(0); /* delete when we really have the code */ - - /* Call the single byte one untill we have the real lo_ParseThaiText ready */ - - lo_ParseSingleText(state, block, parseAllText, text); -} - -static void -lo_ParseSingleText ( lo_DocState * state, LO_TextBlock * block, Bool parseAllText, char * text ) -{ - uint8 * t_ptr; - uint8 * w_start; - uint8 * w_end; - uint8 * line_buff; - uint32 w_length; - Bool skipped_space; - uint32 textLength; - - /* check for textTransform properties and aply them */ - if( ( state != NULL ) && ( state->top_state && state->top_state->style_stack ) ) - { - char * property; - - StyleStruct *style_struct = STYLESTACK_GetStyleByIndex( state->top_state->style_stack, 0); - - if( style_struct ) - { - property = STYLESTRUCT_GetString(style_struct, TEXT_TRANSFORM_STYLE); - if(property) - { - lo_transform_text_from_string_method(text, property); - } - } - } - - t_ptr = (uint8 *) text; - skipped_space = FALSE; - - if ( ( state != NULL ) && ( state->line_buf_len > 0 ) ) - { - PA_LOCK(line_buff, uint8 *, state->line_buf); - textLength = state->line_buf_len; - - if ( *line_buff == '\0' ) - { - line_buff = NULL; - textLength = 0; - state->line_buf_len = 0; - } - } - else - { - line_buff = NULL; - textLength = 0; - } - - /* Make sure the text block has enough space to hold this block of text */ - textLength += XP_STRLEN ( text ); - lo_GrowTextBlock ( block, textLength + 1 ); - - /* - * If there's anything in the line buffer, then pull that out now - */ - if ( line_buff != NULL ) - { - /* was there any trailing space left for us? */ - skipped_space = state->trailing_space; - - /* skip any white space at the head of our text */ - while ( ( *line_buff != '\0' ) && XP_IS_SPACE ( *line_buff ) ) - { - line_buff++; - state->line_buf_len--; - skipped_space = TRUE; - } - - /* - * if we skipped any space and we're not at the end of the buffer, - * then insert a break position - */ - if ( *line_buff != '\0' ) - { - if ( skipped_space ) - { - if ( !lo_SetBreakPosition ( block ) ) - { - state->top_state->out_of_memory = TRUE; - return; - } - - /* If the space was real whitespace and not a trailing - * space from a previous layout, then copy the space - * to the text block. */ - if ( !state->trailing_space ) - { - block->text_buffer[ block->buffer_write_index ] = ' '; - block->buffer_write_index++; - block->last_buffer_write_index++; - skipped_space = TRUE; - } - - skipped_space = FALSE; - } - - /* copy in the line buffer. it is only allowed to be one word */ - lo_CopyText ( line_buff, &block->text_buffer[ block->buffer_write_index ], state->line_buf_len ); - block->buffer_write_index += state->line_buf_len; - state->line_buf_len = 0; - } - } - - /* The last chunk of text may have left a single piece of - * whitespace at the end of the buffer. If so, we need to skip any - * whitespace at the front of the buffer so we don't have to worry - * about this inside the main loop. - * - * When called from the editor, we may not have a state - * record. However, we also won't need to worry about this case as - * it will have taken care of it for us. */ - if ( ( state != NULL ) && ( state->trailing_space ) && ( *t_ptr != '\0' ) ) - { - skipped_space = TRUE; - - while ( ( *t_ptr != '\0' ) && XP_IS_SPACE ( *t_ptr ) ) - { - t_ptr++; - } - } - - while ( *t_ptr != '\0' ) - { - w_start = t_ptr; - - /* skip past any whitespace before this word. */ - while ( ( *w_start != '\0' ) && XP_IS_SPACE ( *w_start ) ) - { - w_start++; - } - - /* run through the text and find the end of the word */ - w_end = w_start; - w_length = 0; - - while ( ( *w_end != '\0' ) && !XP_IS_SPACE ( *w_end ) ) - { - w_end++; - w_length++; - } - - /* If we hit the end of the buffer then we may be inside a - * partial word. This can cause problems with interword - * kerning, multibyte characters and other contextually - * sensitive script systems. - * - * We buffer this word in the line_buff. If this is truly the - * end of the text, then we'll be called to flush the last - * line. We'll do this by appending this word to our text - * block and then laying out the last of the text. - * - * If this word is just split across a buffer, then it will be - * inserted to the beginning of the next text block. - * - * If the caller tells us to parse the whole buffer, then we - * don't care. */ - - if ( !parseAllText && ( *w_end == '\0' ) && ( w_length > 0 ) && ( state != NULL ) ) - { - if ( w_start != t_ptr ) - { - /* put a space in the line buffer */ - lo_CopyTextToLineBuffer ( state, (uint8 *) " ", 1 ); - if ( state->top_state->out_of_memory ) - { - return; - } - } - - /* put this text in the line buffer */ - lo_CopyTextToLineBuffer ( state, w_start, w_length ); - if ( state->top_state->out_of_memory ) - { - return; - } - - /* we now have text after the whitespace */ - skipped_space = FALSE; - - break; - } - - /* If we skipped some white space, then we know that we can - * put a break here. */ - if ( w_start != t_ptr ) - { - skipped_space = TRUE; - - /* add the break position */ - if ( !lo_SetBreakPosition ( block ) ) - { - if ( state != NULL ) - { - state->top_state->out_of_memory = TRUE; - } - return; - } - - if ( block->buffer_length < ( block->buffer_write_index + 1 ) ) - { - if ( !lo_GrowTextBlock ( block, 1 ) ) - { - if ( state != NULL ) - { - state->top_state->out_of_memory = TRUE; - } - return; - } - } - - block->text_buffer[ block->buffer_write_index ] = ' '; - block->buffer_write_index++; - - /* BRAIN DAMAGE: Add a new field to the text block struct - * to indicate how many chars to skip when calculating the - * length of the next run. */ - block->last_buffer_write_index++; - } - else - { - skipped_space = FALSE; - } - - /* if we found anything, add it to the buffer */ - if ( w_length > 0 ) - { - if ( block->buffer_length < ( block->buffer_write_index + w_length ) ) - { - if ( !lo_GrowTextBlock ( block, w_length ) ) - { - if ( state != NULL ) - { - state->top_state->out_of_memory = TRUE; - } - return; - } - } - - lo_CopyText ( w_start, &block->text_buffer[ block->buffer_write_index ], w_length ); - block->buffer_write_index += w_length; - - /* we now have text after the whitespace */ - skipped_space = FALSE; - } - - t_ptr = w_end; - } - - /* - * Remember whether the last thing we added was whitespace - */ - block->last_char_is_whitespace = skipped_space; -} - - -/* - * Parse State Table for two byte text - */ - -typedef enum { - kUnprohibited = PROHIBIT_NOWHERE, - kBeginProhibited = PROHIBIT_BEGIN_OF_LINE, - kEndProhibited = PROHIBIT_END_OF_LINE, - kWordBreakProhibited = PROHIBIT_WORD_BREAK, - kSingleByte, - kBreakableSpace, - kFlushFinalRun, - kNumCharTypes -} ParseState; - -/* - * Flags for the state table command - */ - -#define SET_BREAKABLE 0x01 /* dump the current run as a single breakable run */ -#define SET_MULTI_BREAKABLE 0x02 /* dump the current run as a mutibyte breakable run */ -#define DUMP_TEXT_AND_BREAK 0x04 /* dump the text to the buffer with no break point and then stop processing */ -#define CARRY_LAST_CHAR 0x08 /* move the last char of this run into the next state */ -#define INC_RUN_LENGTH 0x10 /* inc the length of this run (we could do without this one) */ -#define INSERT_WHITESPACE 0x20 /* insert a single whitespace into the text buffer */ -#define SKIP_CHAR 0x40 /* skip the current char */ -#define MAINTAIN_CHAR_TYPE 0x80 /* don't change the curCharType */ - -/* - * Things to Note: - * - * 1. SET_BREAKABLE means to insert a normal break command. This run can - * be broken at the end of the run. - * 2. SET_MULTI_BREAKABLE means that we have a run which can be broken at - * the end of every character. - * - */ - -/* - * The mutibyte breakable run data word is 16 bits big. It is organized as: - * - * BIT: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - * FIELD: CHAR SIZE RUN LENGTH - */ - -#define MULTI_CHAR_SIZE_MASK 0xE000 -#define MULTI_CHAR_SIZE_SHIFT 12 - -#define MULTI_LENGTH_MASK 0x1FFF - -/* - * The state table - */ - -static uint8 gParseTable[ kNumCharTypes ][ kNumCharTypes ] = -{ - /* current char next char operations */ - -/* Unprohibited two byte text */ - /* kUnprohibited, kUnprohibited, */ INC_RUN_LENGTH, - /* kUnprohibited, kBeginProhibited, */ SET_MULTI_BREAKABLE + CARRY_LAST_CHAR, - /* kUnprohibited, kEndProhibited, */ SET_MULTI_BREAKABLE, - /* kUnprohibited, kWordBreakProhibited, */ SET_MULTI_BREAKABLE, - /* kUnprohibited, kSingleByte, */ SET_MULTI_BREAKABLE, - /* kUnprohibited, kBreakableSpace, */ SET_MULTI_BREAKABLE + INSERT_WHITESPACE + SKIP_CHAR, - /* kUnprohibited, kFlushFinalRun, */ SET_MULTI_BREAKABLE, - -/* Begin Line Prohibited two byte text */ - /* kBeginProhibited, kUnprohibited, */ SET_BREAKABLE, - /* kBeginProhibited, kBeginProhibited, */ INC_RUN_LENGTH, - /* kBeginProhibited, kEndProhibited, */ SET_BREAKABLE, - /* kBeginProhibited, kWordBreakProhibited, */ SET_BREAKABLE, - /* kBeginProhibited, kSingleByte, */ SET_BREAKABLE, - /* kBeginProhibited, kBreakableSpace, */ SET_BREAKABLE + INSERT_WHITESPACE + SKIP_CHAR, - /* kBeginProhibited, kFlushFinalRun, */ DUMP_TEXT_AND_BREAK, - -/* End Line Prohibited two byte text */ - /* kEndProhibited, kUnprohibited, */ INC_RUN_LENGTH + SET_BREAKABLE, - /* kEndProhibited, kBeginProhibited, */ INC_RUN_LENGTH + SET_BREAKABLE, - /* kEndProhibited, kEndProhibited, */ INC_RUN_LENGTH, - /* kEndProhibited, kWordBreakProhibited, */ INC_RUN_LENGTH, - /* kEndProhibited, kSingleByte, */ INC_RUN_LENGTH, - /* kEndProhibited, kBreakableSpace, */ INC_RUN_LENGTH + MAINTAIN_CHAR_TYPE, /* BIZZARE CASE! */ - /* kEndProhibited, kFlushFinalRun, */ DUMP_TEXT_AND_BREAK, /* not much we can do here */ - -/* Word Break Prohibited two byte text */ - /* kWordBreakProhibited, kUnprohibited, */ SET_BREAKABLE, - /* kWordBreakProhibited, kBeginProhibited, */ INC_RUN_LENGTH, - /* kWordBreakProhibited, kEndProhibited, */ SET_BREAKABLE, - /* kWordBreakProhibited, kWordBreakProhibited, */ INC_RUN_LENGTH, - /* kWordBreakProhibited, kSingleByte, */ INC_RUN_LENGTH, - /* kWordBreakProhibited, kBreakableSpace, */ SET_BREAKABLE + INSERT_WHITESPACE + SKIP_CHAR, - /* kWordBreakProhibited, kFlushFinalRun, */ DUMP_TEXT_AND_BREAK, - -/* Single byte text */ - /* kSingleByte, kUnprohibited, */ SET_BREAKABLE, - /* kSingleByte, kBeginProhibited, */ INC_RUN_LENGTH, - /* kSingleByte, kEndProhibited, */ SET_BREAKABLE, - /* kSingleByte, kWordBreakProhibited, */ SET_BREAKABLE, - /* kSingleByte, kSingleByte, */ INC_RUN_LENGTH, - /* kSingleByte, kBreakableSpace, */ SET_BREAKABLE + INSERT_WHITESPACE + SKIP_CHAR, - /* kSingleByte, kFlushFinalRun, */ DUMP_TEXT_AND_BREAK, - -/* Single byte breakable space */ - /* kBreakableSpace, kUnprohibited, */ 0, - /* kBreakableSpace, kBeginProhibited, */ 0, - /* kBreakableSpace, kEndProhibited, */ 0, - /* kBreakableSpace, kWordBreakProhibited, */ 0, - /* kBreakableSpace, kSingleByte, */ 0, - /* kBreakableSpace, kBreakableSpace, */ SKIP_CHAR, - /* kBreakableSpace, kFlushFinalRun, */ 0, - -/* These are never hit */ - /* kFlushFinalRun, kUnprohibited, */ 0, - /* kFlushFinalRun, kBeginProhibited, */ 0, - /* kFlushFinalRun, kEndProhibited, */ 0, - /* kFlushFinalRun, kWordBreakProhibited, */ 0, - /* kFlushFinalRun, kSingleByte, */ 0, - /* kFlushFinalRun, kBreakableSpace, */ 0, - /* kFlushFinalRun, kFlushFinalRun, */ 0, -}; - -static void -lo_ParseDoubleText ( lo_DocState * state, LO_TextBlock * block, Bool parseAllText, char * text ) -{ - char * tptr; - char * wordStart; - char * nextWordStart; - int32 runLength; - int32 nextRunLength; - int32 curCharBytes; - int32 nextCharBytes; - int16 charset; - ParseState curCharType; - ParseState nextCharType; - uint8 parseCommand; - uint32 textLength; - Bool startNewRun; - Bool eachCharBreakable; - Bool processLastRun; - - tptr = text; - wordStart = text; - runLength = 0; - - textLength = 0; - - processLastRun = FALSE; - - /* BRAIN DAMAGE: We need to see if there's anything in the line - buffer for us */ - - /* Make sure the text block has enough space to hold this block of text */ - textLength += XP_STRLEN ( text ); - lo_GrowTextBlock ( block, textLength + 1 ); - - charset = block->text_attr->charset; - curCharType = kSingleByte; - curCharBytes = 1; - - eachCharBreakable = FALSE; - - /* if we have a trailing space, then set our state to be a space */ - if ( state->trailing_space ) - { - curCharType = kBreakableSpace; - runLength = curCharBytes; - } - - startNewRun = FALSE; - - while ( ( *tptr != '\0' ) || processLastRun ) - { - if ( processLastRun ) - { - /* force the last run to be flushed */ - nextCharType = kFlushFinalRun; - nextCharBytes = 0; - } - else - { - /* do we have an ascii char? */ - if ( ( (unsigned char) *tptr ) <= 0x7F ) - { - nextCharBytes = 1; - - /* is the next char a breakable space? */ - if ( XP_IS_SPACE( *tptr ) ) - { - nextCharType = kBreakableSpace; - } - else - /* it's a normal char */ - { - nextCharType = kSingleByte; - } - } - else - { - /* multibyte, do that international thing */ - nextCharBytes = INTL_CharLen( charset, (unsigned char *) tptr); - nextCharType = (ParseState) INTL_KinsokuClass( charset, (unsigned char *) tptr ); - } - } - - /* now get our parse command */ - parseCommand = gParseTable[ curCharType ][ nextCharType ]; - nextRunLength = nextCharBytes; - nextWordStart = tptr; - - /* Unprohibited multibyte check - we need to catch cases where - * our byte size changes. We might want to add a command bit - * for this check, for now I shall do it this way. */ - - if ( ( curCharType == kUnprohibited ) && ( nextCharType == kUnprohibited ) ) - { - if ( nextCharBytes != curCharBytes ) - { - /* ok, our char size changed. we need to dump this run */ - parseCommand |= SET_BREAKABLE; - } - } - - /* process the command */ - if ( parseCommand & CARRY_LAST_CHAR ) - { - /* move the last char of this run into the next run */ - runLength -= curCharBytes; - nextWordStart -= curCharBytes; - - /* and move the carried char of the previous run to the next one */ - nextRunLength = curCharBytes + nextCharBytes; - - /* if the old run is empty, we don't want to do anything else */ - if ( runLength == 0 ) - { - parseCommand = 0; - startNewRun = TRUE; - } - } - - if ( parseCommand & INC_RUN_LENGTH ) - { - runLength += nextCharBytes; - } - - if ( parseCommand & SET_BREAKABLE ) - { - lo_CopyText ( (uint8 *) wordStart, &block->text_buffer[ block->buffer_write_index ], runLength ); - block->buffer_write_index += runLength; - - /* set a breakable run */ - lo_SetBreakPosition ( block ); - - startNewRun = TRUE; - } - - if ( parseCommand & SET_MULTI_BREAKABLE ) - { - lo_CopyText ( (uint8 *) wordStart, &block->text_buffer[ block->buffer_write_index ], runLength ); - block->buffer_write_index += runLength; - - /* set an unbreakable run */ - lo_SetMultiByteRun ( block, curCharBytes, TRUE, eachCharBreakable ); - startNewRun = TRUE; - } - - if ( parseCommand & DUMP_TEXT_AND_BREAK ) - { - /* copy the text out but don't set a break (only happens - when flushing at the end) */ - lo_CopyText ( (uint8 *) wordStart, &block->text_buffer[ block->buffer_write_index ], runLength ); - block->buffer_write_index += runLength; - - /* now break out of the loop - we're done */ - break; - } - - if ( startNewRun ) - { - wordStart = nextWordStart; - runLength = nextRunLength; - startNewRun = FALSE; - } - - if ( parseCommand & SKIP_CHAR ) - { - wordStart++; - } - - if ( parseCommand & INSERT_WHITESPACE ) - { - block->text_buffer[ block->buffer_write_index ] = ' '; - block->buffer_write_index++; - block->last_buffer_write_index++; - } - - curCharBytes = nextCharBytes; - - if ( !( parseCommand & MAINTAIN_CHAR_TYPE ) ) - { - curCharType = nextCharType; - } - - eachCharBreakable = curCharType == kUnprohibited; - - tptr += nextCharBytes; - - /* if we got here with processLastRun, then we need to bail */ - if ( processLastRun ) - { - break; - } - - /* if we're on the last character, then we may have a partial - * run left over. if we're parsing all text then we need to - * dump it. */ - if ( parseAllText && ( *tptr == 0 ) && ( runLength > 0 ) ) - { - processLastRun = TRUE; - } - } - - /* if we've ended and we have a run, then we need to save it in - the line buffer */ - if ( ( runLength > 0 ) && ( *wordStart != 0 ) ) - { - lo_CopyTextToLineBuffer ( state,(uint8 *) wordStart, runLength ); - } -} - -static void -lo_FlushText ( MWContext * context, lo_DocState * state ) -{ - LO_TextBlock * block; - char * text_buf; - - block = state->cur_text_block; - - if ( block != NULL ) - { - - /* add any text to the text block that may be sitting in the - line buffer */ - /* BRAIN DAMAGE: These should both be handled the same way */ - if ( kMBTextParseAttribute == lo_GetTextParseAttributes(state) ) - { - if ( state->line_buf_len > 0 ) - { - PA_LOCK(text_buf, char *, state->line_buf); - lo_ParseDoubleText ( state, block, TRUE, text_buf ); - PA_UNLOCK(state->line_buf); - } - } - else - { - lo_AppendTextToBlock ( context, state, block, "" ); - } - - lo_LayoutTextBlock ( context, state, TRUE ); - } -} - -static void -lo_SetupBreakState ( LO_TextBlock * block ) -{ - Bool canBreak; - uint32 wordLength; - uint32 lineLength; - uint8 * runEnd; - uint32 searchReadIndex; - BreakState breakState; - - searchReadIndex = block->buffer_read_index; - - block->buffer_read_index = 0; - block->break_read_index = 0; - block->last_line_break = 0; - - /* We need to update our state to be at the current text position - * (specified by buffer_read_index) */ - - lineLength = 0; - - /* run through the break table until we get to the correct read index */ - while ( block->buffer_read_index < searchReadIndex ) - { - SAVE_BREAK_STATE ( block, &breakState, lineLength ); - - runEnd = lo_GetNextTextPosition ( block, &wordLength, &lineLength, &canBreak ); - if ( runEnd == NULL ) - { - /* this should not happen, but just in case, let's do - something kinda reasonable */ - lo_RestoreBreakState ( block, &breakState, NULL ); - break; - } - } - - /* If we're not at the beginning of the text buffer, then we need - * to increment buffer_read_index so that we skip the breakable - * space we're currently at. */ - if ( ( block->buffer_read_index > 0 ) && XP_IS_SPACE ( block->text_buffer[ block->buffer_read_index ] ) ) - { - block->buffer_read_index++; - } - - block->last_line_break = block->buffer_read_index; -} - -void lo_LayoutTextBlock ( MWContext * context, lo_DocState * state, Bool flushLastLine ) -{ - LO_TextBlock * block; - Bool allTextFits; - Bool canBreakAtStart; - LO_TextStruct * text_data; - LO_TextStruct msTextData; - uint32 width; - uint32 lineLength; - uint8 * text; - int32 baseline_inc; - int32 line_inc; - int32 minWidth; - int32 * minWidthPtr; - BreakState breakState; - uint16 * charLocs; - Bool freeMeasureBuffer; - Bool justify; - - block = state->cur_text_block; - if ( block == NULL ) - { - return; - } - - justify = ( state->align_stack != NULL ) && ( state->align_stack->alignment == LO_ALIGN_JUSTIFY ); - - /* bail if we're at the end of this block */ - /* XXX MATT XXX sometimes buffer_read_index may be larger then - * buffer_write_index, don't know why XXX - */ - if ( block->buffer_read_index >= block->buffer_write_index ) - { - /* if there's also no text in the line buffer, clear this block */ - if ( state->line_buf_len == 0 ) - { - state->cur_ele_type = LO_NONE; - state->cur_text_block = NULL; - state->trailing_space = block->last_char_is_whitespace; - } - return; - } - - lineLength = 0; - - charLocs = NULL; - freeMeasureBuffer = FALSE; - - /* find the width of an average character */ - if ( block->totalWidth == 0 ) - { - memset (&msTextData, 0, sizeof (LO_TextStruct)); - msTextData.text = (PA_Block) "aeiou"; - msTextData.text_attr = block->text_attr; - msTextData.text_len = 5; - - FE_GetTextInfo ( context, &msTextData, &state->text_info ); - block->totalWidth = state->text_info.max_width; - block->totalChars = msTextData.text_len; - } - -#ifdef XP_MAC - /* do a quick test to see if we could overflow a UInt16 */ - if ( ( block->buffer_write_index * block->totalWidth / block->totalChars ) < 65535 ) - { - /* measure the text using the fast measure text */ - if ( ( block->buffer_write_index + 1 ) < kStaticMeasureTextBufferSize ) - { - charLocs = gMeasureTextBuffer; - } - else - { - charLocs = XP_ALLOC( ( block->buffer_write_index + 1 ) * sizeof(uint16) ); - freeMeasureBuffer = TRUE; - } - - if ( charLocs != NULL ) - { - memset (&msTextData, 0, sizeof (LO_TextStruct)); - msTextData.text = (PA_Block) block->text_buffer; - msTextData.text_attr = block->text_attr; - msTextData.text_len = block->buffer_write_index; - FE_MeasureText ( context, &msTextData, (int16 *) charLocs ); - - /* BRAIN DAMAGE: We need to figure out for sure if the - width has ever exceeded a uint16! */ - /* the actual interface for MeasureText says it takes an - array of signed ints, however */ - /* the data stuffed in there is unsigned (we quickly - overflow a int16 with an 8Kb buffer) */ - } - } -#endif - - /* Given the current layout state, run through this text block and - * convert all that we can into text elements. If flushLastLine - * is set, we want to flush all the text, rather than keeping the - * last bit in case more text comes. */ - - allTextFits = FALSE; - - /* if we're laying out a table, then we need to calculate min widths */ - minWidthPtr = state->need_min_width ? &minWidth : NULL; - - while ( !allTextFits ) - { - canBreakAtStart = FALSE; - - /* Save the current break state in case we need to delay on - the last line */ - SAVE_BREAK_STATE ( block, &breakState, lineLength ); - - /* We need to handle the case where we're at the beginning of - * the line and the first character is a breakable space. */ - if ( state->at_begin_line ) - { - canBreakAtStart = lo_SkipInitialSpace ( block ); -#ifdef LOG - PR_LogPrint ( "canBreakAtStart: %d\n", canBreakAtStart ); - PR_LogFlush(); -#endif - } - - /* we're looking for a new break position */ - state->break_pos = -1; - state->break_width = -1; - - text = lo_GetLineStart ( block ); - - lineLength = lo_FindLineBreak ( context, state, block, text, charLocs, &width, minWidthPtr, &allTextFits ); - - /* update the state's min_width if we need to - this will be - constant even if we don't flush this line */ - if ( minWidthPtr != NULL ) - { - if ( minWidth > state->min_width ) - { - state->min_width = minWidth; - } - } - - /* if this line is too long, we either need to break at the - * beginning of the run (if we can) or break at an old - * element. If we can't do either of those then we just have - * to make the line too big */ - - if ( ( width > ( state->right_margin - state->x ) ) && ( state->x > state->left_margin ) ) - { - /* could we have broken at the start of this line? */ - if ( canBreakAtStart ) - { -#ifdef LOG - PR_LogPrint ( "Too long - Breaking at the start of the line\n" ); - PR_LogFlush(); -#endif - - /* break the line here */ - lo_SoftLineBreak( context, state, TRUE ); - - /* BUG BUG: We're restoring the break state to the - * beginning of the buffer - ie to before the space we - * skipped above. We need to fix the space skipping - * mechanism to remove this case (we can go into an - * infinite loop here if there's not enough space for - * the first word). - * - * Should be able to have a new flag "canSkipSpace" - * but then actually don't skip it. Then if the line - * does fit and it's at the beginning, we can skip the - * space. lo_FindLineBreak should probably be the one - * to do this work so that the width we get back is - * correct. */ - lo_RestoreBreakState ( block, &breakState, NULL ); - - /* if all the text fits (ie there was only an - * unbreakable run left in this block), then we need - * to stick with this break position. Otherwise we can - * go find a new one */ - if ( !allTextFits ) - { - continue; - } - } - else - /* do we have an old break position we can use? */ - if ( state->old_break_pos != -1 && state->old_break_block != NULL ) - { -#ifdef LOG - PR_LogPrint ( "Too long - Breaking at the old_break_pos: %ld, width %ld\n" - state->old_break_pos, state->old_break_width ); - PR_LogFlush(); -#endif - lo_BreakOldElement ( context, state ); - lo_RestoreBreakState ( block, &breakState, NULL ); - - /* if all the text fits (ie there was only an - * unbreakable run left in this block), then we need - * to stick with this break position. Otherwise we can - * go find a new one */ - if ( !allTextFits ) - { - continue; - } - } - - /* we're screwed, we just have to make this line too long */ - } - - /* We may not necessarily want to flush the whole buffer out - * to layout elements (the case where were processing part of - * a text chunk based on what netlib has streamed to us). - * - * We know we do want to flush this next line out if we still - * have more text in this buffer to process or layout really - * does want us to flush this whole buffer (because some other - * element is after us). */ - if ( !allTextFits || flushLastLine ) - { - state->width = width; - - if ( lineLength > 0 ) - { - text_data = (LO_TextStruct *)lo_NewElement ( context, state, LO_TEXT, NULL, 0 ); - if (text_data == NULL) - { -#ifdef DEBUG - assert (state->top_state->out_of_memory); -#endif - break; - } - - text_data->type = LO_TEXT; - text_data->ele_id = NEXT_ELEMENT; - text_data->x = state->x; - text_data->x_offset = 0; - text_data->y = state->y; - text_data->y_offset = 0; - text_data->width = width; - text_data->height = 0; - text_data->line_height = 0; - text_data->next = NULL; - text_data->prev = NULL; - - text_data->text = (PA_Block) text; - /* HACK: The editor needs spaces to be included in the length of the last text element on a line. - If we do not do this, navigation between lines gets broken. So, for "1111 2222", if we break the - line after the first number, the text element should contain "1111 " rather than "1111". The fix is - to add 1 to the length of the text element once we have ensured that the extra character being added - is a space and that this text element is going to be followed by a linebreak. */ - if (EDT_IS_EDITOR( context ) && !allTextFits && !justify && XP_IS_SPACE(((char *) text_data->text)[lineLength])) - text_data->text_len = lineLength + 1; - else - text_data->text_len = lineLength; - - - text_data->anchor_href = block->anchor_href; - text_data->text_attr = block->text_attr; - text_data->ele_attrmask = block->ele_attrmask; - - /* BRAIN DAMAGE: Set LO_ELE_INVISIBLE to mark the - element as not having a valid text ptr */ - XP_ASSERT ( !(text_data->ele_attrmask & LO_ELE_INVISIBLE ) ); - text_data->ele_attrmask |= LO_ELE_INVISIBLE; - - text_data->sel_start = -1; - text_data->sel_end = -1; - - text_data->doc_width = state->right_margin - state->x; - text_data->doc_width = 0; - text_data->block_offset = block->buffer_read_index; - XP_ASSERT(block->buffer_read_index <= 65535); - - /* - * Some fonts (particulatly italic ones with curly tails - * on letters like 'f') have a left bearing that extends - * back into the previous character. Since in this case the - * previous character is probably not in the same font, we - * move forward to avoid overlap. - * - * Those same funny fonts can extend past the last - * character, and we also have to catch that, and - * advance the following text to eliminate cutoff. */ - if ( state->text_info.lbearing < 0 ) - { - text_data->x_offset = state->text_info.lbearing * -1; - } - - baseline_inc = 0; - line_inc = 0; - - /* The baseline of the text element just added to the - * line may be less than or greater than the baseline - * of the rest of the line due to font changes. If - * the baseline is less, this is easy, we just - * increase y_offest to move the text down so the - * baselines line up. For greater baselines, we can't - * move the text up to line up the baselines because - * we will overlay the previous line, so we have to - * move all the previous elements in this line down. - * - * If the baseline is zero, we are the first element - * on the line, and we get to set the baseline. */ - if ( state->baseline == 0 ) - { - state->baseline = state->text_info.ascent; - if (state->line_height < - (state->baseline + state->text_info.descent)) - { - state->line_height = state->baseline + - state->text_info.descent; - } - } - else if ( state->text_info.ascent < state->baseline ) - { - text_data->y_offset = state->baseline - state->text_info.ascent; - if ( ( text_data->y_offset + state->text_info.ascent + state->text_info.descent ) > state->line_height ) - { - line_inc = text_data->y_offset + state->text_info.ascent + state->text_info.descent - - state->line_height; - } - } - else - { - baseline_inc = state->text_info.ascent - state->baseline; - if ( ( text_data->y_offset + state->text_info.ascent + state->text_info.descent - baseline_inc ) > - state->line_height) - { - line_inc = text_data->y_offset + state->text_info.ascent + state->text_info.descent - - state->line_height - baseline_inc; - } - } - - /* Append this element to layout's linelist and our - * own list of text elements belonging to this block */ - lo_AppendToLineList ( context, state, (LO_Element *) text_data, baseline_inc ); - if ( block->startTextElement == NULL ) - { - block->startTextElement = text_data; - block->endTextElement = text_data; - } - else - { - block->endTextElement = text_data; - } - - /* we know we're not at the beginning of the line anymore */ - state->at_begin_line = FALSE; - - state->baseline += (intn) baseline_inc; - state->line_height += (intn) (baseline_inc + line_inc); - text_data->height = state->text_info.ascent + state->text_info.descent; - - /* - * If the element we just flushed had a breakable word - * position in it, save that position in case we have - * to go back and break this element before we finish - * the line. - */ - if ( state->break_pos != -1 ) - { - state->old_break = text_data; - state->old_break_block = block; - state->old_break_pos = state->break_pos; - state->old_break_width = state->break_width; - } - - state->linefeed_state = 0; - state->x += state->width; - state->width = 0; - } - - /* If we're still processing text in this buffer, put a - * linebreak out there */ - if ( !allTextFits && !justify ) - { - lo_SoftLineBreak(context, state, TRUE); - - /* tell the break engine that we broke the line here */ - lo_SetLineBreak ( block, !justify ); - } - - -#ifdef EDITOR - /* tell the editor where we are */ - state->edit_current_offset = block->last_line_break; -#endif - - if ( !( allTextFits && !flushLastLine ) ) - { - /* Skip the break character if it's whitespace. We - * don't need to worry about non-breaking spaces here - * as if the space was non-breaking, we would not have - * broken the line here */ - - if ( !allTextFits && XP_IS_SPACE ( *text ) ) - { - /* BRAIN DAMAGE: We should be able to do this at - the start of the line */ -/* lo_SkipCharacter ( block ); */ - } - } - - } - } - - if ( flushLastLine ) - { - state->cur_ele_type = LO_NONE; - state->cur_text_block = NULL; - state->trailing_space = block->last_char_is_whitespace; - } - else - if ( allTextFits ) - { - /* we're still inside a group of text elements */ - state->cur_ele_type = LO_TEXT; - state->trailing_space = block->last_char_is_whitespace; - - /* We're not going to flush the last line, so restore our - break state to the start of the line */ - lo_RestoreBreakState ( block, &breakState, NULL ); - } - - if ( freeMeasureBuffer ) - { - XP_FREE( charLocs ); - } -} - -int32 lo_ComputeTextMinWidth ( lo_DocState * state, int32 wordWidth, Bool canBreak ); -int32 lo_ComputeTextMinWidth ( lo_DocState * state, int32 wordWidth, Bool canBreak ) -{ - int32 new_break_holder; - int32 min_width; - int32 indent; - - new_break_holder = state->x + wordWidth; - min_width = new_break_holder - state->break_holder; - indent = state->list_stack->old_left_margin - state->win_left; - min_width += indent; - - /* If we are not within <NOBR> content, allow break_holder - * to be set to the new position where a line break can occur. - * This fixes BUG #70782 - */ - if ( ( state->breakable != FALSE ) && canBreak) { - state->break_holder = new_break_holder; - } - - return min_width; -} - -static uint32 -lo_FindLineBreak ( MWContext * context, lo_DocState * state, LO_TextBlock * block, uint8 * text, - uint16 * widthTable, uint32 * width, int32 * minWidth, Bool * allTextFits ) -{ - LO_TextStruct text_data; - uint32 breakCount; - Bool skipEndSpace; - Bool haveTooShort; - Bool canBreak; - BreakState tooShortBreak; - Bool haveTooLong; - uint32 wordLength; - uint32 breakChar; - uint32 lineLength; - uint32 prevLineLength; - uint8 * wordStart; - LO_TextInfo text_info; - uint32 runLength; - int32 docWidth; - BreakState breakState; - uint8 * runEnd; - int32 oldBreakPos; - int32 oldBreakWidth; - int32 lineWidth; - Bool justify; -#ifdef BREAK_GUESS_TRACK - uint32 numForwardMoves; - uint32 numBackwardMoves; - - numForwardMoves = 0; - numBackwardMoves = 0; -#endif - - *allTextFits = FALSE; - - memset (&text_data, 0, sizeof (LO_TextStruct)); - text_data.text = (PA_Block) text; - text_data.text_attr = block->text_attr; - - if ( minWidth != NULL ) - { - *minWidth = 0; - } - - justify = ( state->align_stack != NULL ) && ( state->align_stack->alignment == LO_ALIGN_JUSTIFY ); - - /* guess where we want to break this line */ - docWidth = state->right_margin - state->x; - if ( docWidth < 0 ) - { - /* we should never get here - the line before us needs to have been broken */ - docWidth = 0; - } - - lineLength = block->buffer_write_index - block->buffer_read_index; - if ( state->breakable ) - { - breakChar = docWidth * block->totalChars / block->totalWidth; - if ( breakChar > lineLength ) - { - breakChar = lineLength; - } - } - else - { - breakChar = lineLength; - } - - /* We first need to walk through the word runs until we get to the - * first one before our break character. - * - * OPTIMIZATION: Make lo_GetNextTextPosition take a breakChar and - * have it walk forward to that position in an inner loop. This - * will save us a ton of calls (we currently spend about 5% if our - * time in lo_GetNextTextPosition - not huge but significant). */ - - lineLength = 0; - - breakCount = 0; - skipEndSpace = FALSE; - - wordStart = text; - - haveTooShort = FALSE; - haveTooLong = FALSE; - - oldBreakPos = -1; - oldBreakWidth = -1; - - lineWidth = 0; -#ifdef LOG - if ( !gHaveLog ) - { - PR_SetLogFile ( "TextLog" ); - gHaveLog = true; - } - - PR_LogPrint ( "Finding initial break position\n" ); -#endif - - /* get the next break position */ - while ( TRUE ) - { - prevLineLength = lineLength; - -#ifdef LOG - PR_LogPrint ( "Get next break position\n" ); - PR_LogFlush(); -#endif - /* Save the current break position in case it ends up being - the one we need */ - if ( breakCount > 0 && canBreak ) - { - oldBreakPos = lineLength; - } - - SAVE_BREAK_STATE ( block, &breakState, lineLength ); - runEnd = lo_GetNextTextPosition ( block, &wordLength, &lineLength, &canBreak ); - if ( runEnd == NULL ) - { -#ifdef LOG - PR_LogPrint ( "End of break table\n" ); - PR_LogFlush(); -#endif - - /* we hit the end of the break table */ - runEnd = lo_RestoreBreakState ( block, &breakState, &lineLength ); - break; - } - - /* do we need to calculate min_width's? */ - if ( minWidth != NULL ) - { - int32 min_width; - - if ( widthTable != NULL ) - { - uint32 startWordWidth; - uint32 endWordWidth; - - startWordWidth = widthTable[ block->last_line_break + prevLineLength ]; - endWordWidth = widthTable[ block->last_line_break + lineLength ]; - - runLength = endWordWidth - startWordWidth; - } - else - { - text_data.text = (PA_Block) wordStart; - text_data.text_len = lineLength - prevLineLength; - FE_GetTextInfo ( context, &text_data, &text_info ); - - runLength = text_info.max_width; - } - - /* add the width of this word into our line width */ - lineWidth += runLength; - - /* compute the real min width based on the last break position */ - min_width = lo_ComputeTextMinWidth ( state, lineWidth, canBreak ); - if ( min_width > *minWidth ) - { - *minWidth = min_width; - } - - wordStart = runEnd; - } - -#ifdef LOG - PR_LogPrint ( "wordlen: %lu, lineLength: %lu, canBreak: %d, runEnd: %s\n", wordLength, lineLength, canBreak, runEnd ); - PR_LogFlush(); -#endif - - /* Are we where we want to be yet? */ - if ( lineLength >= breakChar ) - { -#ifdef LOG - PR_LogPrint ( "Moved past, back up\n" ); - PR_LogFlush(); -#endif - - /* if we moved past it then back up if we can */ - if ( ( lineLength > breakChar ) && ( breakCount > 0 ) ) - { - runEnd = lo_RestoreBreakState ( block, &breakState, &lineLength ); - --breakCount; - } - - break; - } - - /* if we're justifying text, then we just dump the next break - position */ - if ( justify ) - { - break; - } - - /* we can now back up to something */ - ++breakCount; - } - - /* So now we're looking at the nearest break position to where we - * guessed we'd want to be. Now we loop measuring this line of - * text until we find the best break position */ - -#ifdef LOG - PR_LogPrint ( "Finding actual break position\n" ); - PR_LogFlush(); -#endif - - while ( TRUE ) - { - if ( widthTable != NULL ) - { - uint32 startLineWidth; - uint32 endLineWidth; - - startLineWidth = widthTable[ block->last_line_break ]; - endLineWidth = widthTable[ block->last_line_break + lineLength ]; - - runLength = endLineWidth - startLineWidth; - } - else - { - text_data.text = (PA_Block) text; - text_data.text_len = lineLength; - FE_GetTextInfo ( context, &text_data, &text_info ); - - runLength = text_info.max_width; - } - -#ifdef LOG - PR_LogPrint ( "lineLength: %lu, width: %lu, docWidth: %lu, text: %s\n", lineLength, runLength, docWidth, text ); - PR_LogFlush(); -#endif - /* if we're justified text, then we just dump the word we have now */ - if ( justify ) - { - /* save this break position */ - if ( canBreak ) - { - oldBreakPos = lineLength; - oldBreakWidth = runLength; - - /* if the next char along is a space, then we need to include it */ - if ( ( runEnd != NULL ) && XP_IS_SPACE ( *runEnd ) ) - { - ++lineLength; - } - } - - break; - } - else - /* are we non-breakable text? */ - if ( !state->breakable ) - { - /* We always want to move to the end of the text block. We - * should already be there from the loop above. */ -#ifdef LOG - PR_LogPrint ( "Non-breakable, always get next break point\n" ); - PR_LogFlush(); -#endif - - /* go forward one break position and measure again - (including min width) */ - SAVE_BREAK_STATE ( block, &tooShortBreak, lineLength ); - haveTooShort = TRUE; - -#ifdef BREAK_GUESS_TRACK - ++numForwardMoves; -#endif - wordStart = runEnd; - runEnd = lo_GetNextTextPosition ( block, &wordLength, &lineLength, &canBreak ); - if ( runEnd == NULL ) - { - /* we've already at the end of the line */ - runEnd = lo_RestoreBreakState ( block, &tooShortBreak, &lineLength ); -#ifdef LOG - PR_LogPrint ( "Non-breakable text, hit end of block: %lu, runEnd: %s\n", lineLength, runEnd ); - PR_LogFlush(); -#endif - /* update min_width */ - if ( minWidth != NULL ) - { - int32 min_width; - - /* compute the real min width based on the last - break position - we cannot break here */ - min_width = lo_ComputeTextMinWidth ( state, runLength, FALSE ); - if ( min_width > *minWidth ) - { - *minWidth = min_width; - } - } - break; - } - } - else - /* have we gone too far? */ - if ( runLength > docWidth ) - { -#ifdef LOG - PR_LogPrint ( "Too long\n" ); - PR_LogFlush(); -#endif - - /* if we found a break position before this one that was - too short, choose the too short one */ - if ( haveTooShort ) - { -#ifdef LOG - PR_LogPrint ( "Using too short\n" ); - PR_LogFlush(); -#endif - runEnd = lo_RestoreBreakState ( block, &tooShortBreak, &lineLength ); - break; - } - - /* if we have something to back up to, then do - so. Otherwise we have to break here */ - if ( breakCount > 0 ) - { -#ifdef LOG - PR_LogPrint ( "Backing up to previous break position\n" ); - PR_LogFlush(); -#endif -#ifdef BREAK_GUESS_TRACK - ++numBackwardMoves; -#endif - - /* mark that we've been to far and back up one */ - haveTooLong = TRUE; - runEnd = lo_GetPrevTextPosition ( block, &wordLength, &lineLength, &canBreak ); - if ( runEnd == NULL ) - { - /* we need to break at a previous break position - on this line... */ - break; - } - - wordStart = runEnd; - --breakCount; - continue; - } - else - { -#ifdef LOG - PR_LogPrint ( "Nothing to back up to, bailing\n" ); - PR_LogFlush(); -#endif - break; - } - } - else - /* have we not gone far enough? */ - if ( runLength < docWidth ) - { -#ifdef LOG - PR_LogPrint ( "Too short\n" ); - PR_LogFlush(); -#endif - /* if we have a too long break position, then we know - we're straddling the break point, choose */ - /* this one */ - if ( haveTooLong ) - { -#ifdef LOG - PR_LogPrint ( "Using this break, next is too long\n" ); - PR_LogFlush(); -#endif - break; - } - - /* save this break position */ - if ( canBreak ) - { - oldBreakPos = lineLength; - oldBreakWidth = runLength; - } - - /* go forward one break position and measure again - (including min width) */ - SAVE_BREAK_STATE ( block, &tooShortBreak, lineLength ); - haveTooShort = TRUE; - -#ifdef BREAK_GUESS_TRACK - ++numForwardMoves; -#endif - - wordStart = runEnd; - runEnd = lo_GetNextTextPosition ( block, &wordLength, &lineLength, &canBreak ); - if ( runEnd == NULL ) - { - /* we've already at the end of the line */ - runEnd = lo_RestoreBreakState ( block, &tooShortBreak, &lineLength ); -#ifdef LOG - PR_LogPrint ( "No next break position, use this one. length: %lu, runEnd: %s\n", lineLength, runEnd ); - PR_LogFlush(); -#endif - break; - } - - /* - * Update min width. - */ - if ( minWidth != NULL ) - { - int32 min_width; - - if ( widthTable != NULL ) - { - uint32 startLineWidth; - uint32 endLineWidth; - - startLineWidth = widthTable[ block->last_line_break ]; - endLineWidth = widthTable[ block->last_line_break + lineLength ]; - - runLength = endLineWidth - startLineWidth; - } - else - { - text_data.text = (PA_Block) wordStart; - text_data.text_len = wordLength; - FE_GetTextInfo ( context, &text_data, &text_info ); - - /* add the length of this word into the length of - the line */ - runLength += text_info.max_width; - } - - /* compute the real min width based on the last break - position */ - min_width = lo_ComputeTextMinWidth ( state, runLength, canBreak ); - if ( min_width > *minWidth ) - { - *minWidth = min_width; - } - } - - ++breakCount; - continue; - } - else - { - /* we're spot on! */ - break; - } - } - - /* We may be in a nasty case where our current break position is - * before our last saved one in oldBreakPos. This can happen when - * we move backwards from our initial break guess. To correct - * this, we need to back up from our current break point, get the - * new position and then move forward again. */ - if ( ( oldBreakPos != -1 ) && ( oldBreakPos >= lineLength ) ) - { - uint32 dummyWordLength; - uint32 prevBreakPos; - Bool dummyCanBreak; - uint8 * prevRunEnd; - -#ifdef BREAK_GUESS_TRACK - ++numBackwardMoves; -#endif - prevBreakPos = lineLength; - - SAVE_BREAK_STATE ( block, &breakState, prevBreakPos ); - prevRunEnd = lo_GetPrevTextPosition ( block, &dummyWordLength, &prevBreakPos, &dummyCanBreak ); - if ( prevRunEnd != NULL ) - { - /* we found a valid previous break, so use it */ - oldBreakPos = prevBreakPos; - oldBreakWidth = -1; - } - else - { - /* nothing to back up to, so don't record any old break */ - oldBreakPos = -1; - oldBreakWidth = -1; - } - - /* restore the current break state */ - lo_RestoreBreakState ( block, &breakState, &prevBreakPos ); - } - - text_data.text = (PA_Block) text; - - /* If we don't have a width for the oldBreakPos, measure one now */ - if ( ( oldBreakPos != -1 ) && ( oldBreakWidth == -1 ) ) - { - if ( widthTable != NULL ) - { - uint32 startLineWidth; - uint32 endLineWidth; - - startLineWidth = widthTable[ block->last_line_break ]; - endLineWidth = widthTable[ block->last_line_break + oldBreakPos ]; - - oldBreakWidth = endLineWidth - startLineWidth; - } - else - { - text_data.text_len = oldBreakPos; - FE_GetTextInfo ( context, &text_data, &text_info ); - oldBreakWidth = text_info.max_width; - } - } - - text_data.text_len = lineLength; - - /* if we're breaking at a space at the end of this line, don't - measure it */ - if ( skipEndSpace ) - { - --text_data.text_len; - } - - /* BRAIN DAMAGE: We don't need this - already got all the info */ - if ( widthTable != NULL ) - { - uint32 startLineWidth; - uint32 endLineWidth; - - /* this is really lame */ - text_data.text = (PA_Block) text; - text_data.text_len = 1; - FE_GetTextInfo ( context, &text_data, &text_info ); - - startLineWidth = widthTable[ block->last_line_break ]; - endLineWidth = widthTable[ block->last_line_break + lineLength ]; - - text_info.max_width = endLineWidth - startLineWidth; - } - else - { - text_data.text = (PA_Block) text; - text_data.text_len = lineLength; - FE_GetTextInfo ( context, &text_data, &text_info ); - } - - /* update our char width average */ - block->totalWidth += text_info.max_width; - block->totalChars += lineLength; - - *width = lo_correct_text_element_width( &text_info ); - - /* BRAIN DAMAGE: Pass this into the FE call */ - state->text_info = text_info; - - /* check to see if we're at the end of the buffer */ - if ( block->buffer_read_index == block->buffer_write_index ) - { - *allTextFits = TRUE; - } - - /* save the last break position */ - if ( oldBreakPos != -1 ) - { - state->break_pos = oldBreakPos; - state->break_width = oldBreakWidth; - } - -#ifdef LOG - PR_LogPrint ( "Final lineLength: %lu, allTextFits: %d, text: %s\n", text_data.text_len, *allTextFits, text ); - PR_LogFlush(); -#endif - -#ifdef BREAK_GUESS_TRACK - XP_TRACE(("Num forward, backward break moves after initial guess: %ld, %ld", numForwardMoves, numBackwardMoves )); -#endif - - return lineLength; -} - - -static uint8 * -lo_GetNextTextPosition ( LO_TextBlock * block, uint32 * outWordLength, uint32 * outLineLength, Bool * canBreak ) -{ - uint32 breakCommand; - uint32 breakLong; - uint32 breakIndex; - uint32 lineLength; - uint32 nibbleCount; - uint32 dataNibbles; - int32 wordLength=0; - uint32 * breakTable; - uint8 * endTextRun; - - /* - * Sanity check for already being at the end of the buffer - */ - - if ( block->buffer_read_index == block->buffer_write_index ) - { - *outWordLength = 0; - *canBreak = FALSE; - return NULL; - } - - /* are we in a run of breakable multibyte characters? */ - if ( block->multibyte_length > 0 ) - { - uint16 charSize; - - /* BRAIN DAMAGE */ - /* turn this next line on when the uint16 multibyte_char_size - field is added to LO_TextBlock */ -#if 0 - charSize = block->multibyte_char_size; -#else - charSize = 2; -#endif - block->multibyte_index += charSize; - - /* are we at the end of this run? */ - if ( block->multibyte_index == block->multibyte_length ) - { - block->multibyte_length = 0; - block->multibyte_index = 0; - } - - /* bump by one character */ - *outWordLength = charSize; - (*outLineLength) += charSize; - *canBreak = TRUE; - - block->buffer_read_index += 2; - endTextRun = &block->text_buffer[ block->buffer_read_index ]; - - return endTextRun; - } - - /* assume we will be able to break */ - *canBreak = TRUE; - - lineLength = block->buffer_read_index; - breakIndex = block->break_read_index; - - /* are we at the end of the break table? */ - if ( breakIndex < block->break_write_index ) - { - /* nope, so grab the next break position */ - breakTable = &block->break_table[ breakIndex >> 3 ]; - - /* cache this in the TextBlock */ - breakLong = ( *breakTable++ ) << ( ( breakIndex & 0x7 ) << 2 ); - wordLength = 0; - - /* get the next break command */ - breakCommand = breakLong >> 28; - breakLong <<= 4; - if ( ( ++breakIndex & 0x7 ) == 0 ) - { - breakLong = *breakTable++; - } - - if ( breakCommand <= MAX_NATURAL_LENGTH ) - { - /* a nibble of length data, we already have all the info we need */ - wordLength = breakCommand; - dataNibbles = 0; - } - else - if ( breakCommand == LINE_FEED ) - { - /* we should only get this when parsing preformatted text */ - wordLength = BREAK_LINEFEED; - dataNibbles = 0; - } - else - if ( breakCommand == BYTE_LENGTH ) - { - dataNibbles = 2; - } - else - if ( breakCommand == WORD_LENGTH ) - { - dataNibbles = 4; - } - else - if ( breakCommand == MULTI_BYTE ) - { - dataNibbles = 4; - } - else - { - /* a 24 bits of data */ - dataNibbles = 6; - } - - if ( dataNibbles > 0 ) - { - /* read in the actual count and the tail command header */ - for ( nibbleCount = dataNibbles; nibbleCount > 0; --nibbleCount ) - { - wordLength <<= 4; - wordLength |= breakLong >> 28; - - breakLong <<= 4; - if ( ( ++breakIndex & 0x7 ) == 0 ) - { - breakLong = *breakTable++; - } - } - - /* now skip the tail end of the command */ - ++breakIndex; - } - - /* if multi byte, then extract the real data */ - if ( breakCommand == MULTI_BYTE ) - { - int32 runLength; - - *canBreak = TRUE; - - runLength = wordLength & MULTI_LENGTH_MASK; - - block->multibyte_length = runLength; - block->multibyte_index = 2; - - /* make sure we're not already at the end of the run */ - if ( block->multibyte_index == block->multibyte_length ) - { - block->multibyte_index = 0; - block->multibyte_length = 0; - } - - /* extract the real word length from the command */ - wordLength = ( wordLength & MULTI_CHAR_SIZE_MASK ) >> MULTI_CHAR_SIZE_SHIFT; - - /* MAJOR BRAIN DAMAGE: WE NEED TO STORE THIS IN THE TEXT BLOCK AS IT WILL NOT */ - /* ALWAYS BE TWO BYTE!!!! */ - XP_ASSERT( wordLength == 2 ); - } - - lineLength += wordLength; - - /* if we actually have a word here and are not the first word - * on the line, then add one to the length to account for the - * interword space. We know we're not the first word on the - * line if we're not at the linebreak or if we're at the start - * of the buffer but have already skipped a break position - * (this happens when the first character of the buffer is a - * breaking space). */ - if ( ( wordLength > 0 ) && ( ( block->last_line_break != block->buffer_read_index ) || - ( ( block->buffer_read_index == 0 ) && ( block->break_read_index > 0 ) ) ) ) - { - /* only true if there's a space here */ - if ( XP_IS_SPACE ( block->text_buffer[ block->buffer_read_index ] ) ) - { - lineLength++; - (*outLineLength)++; - } - } - } - else - { - /* We're at the end of the break table. We may have some text - * after this last break. Either way, we cannot break here */ - - *canBreak = FALSE; - - if ( lineLength < block->buffer_write_index ) - { - lineLength = block->buffer_write_index; - wordLength = lineLength - block->buffer_read_index; - } - } - - block->break_read_index = breakIndex; - block->buffer_read_index = lineLength; - - endTextRun = &block->text_buffer[ lineLength ]; - - *outLineLength += wordLength; - *outWordLength = wordLength; - - return endTextRun; -} - - -static Bool -lo_ExtractPrevBreakCommand ( LO_TextBlock * block, Bool * multiByte, uint32 * command ) -{ - Bool hasPrev; - uint32 breakCommand; - uint32 commandData; - uint32 breakLong; - uint32 breakIndex; - uint32 * breakTable; - uint32 nibbleCount; - uint32 dataNibbles; - Bool readPrevCommand; - - commandData = 0; - *multiByte = FALSE; - - breakIndex = block->break_read_index; - - hasPrev = block->break_read_index > 0; - if ( hasPrev ) - { - readPrevCommand = TRUE; - - /* are we at the absolute end of the buffer? */ - if ( block->buffer_read_index == block->buffer_write_index ) - { - /* Yup, so back up to the last break offset. */ - commandData = block->buffer_read_index - block->last_break_offset; - - /* was there really a true ending break command? */ - if ( commandData > 0 ) - { - readPrevCommand = FALSE; - - /* this length was before the breaking space, add it back in */ - --commandData; - } - } - - /* extract the previous command from the table if we need to */ - if ( readPrevCommand ) - { - /* nope, so back up within the break table */ - --breakIndex; - breakTable = &block->break_table[ breakIndex >> 3 ]; - - breakLong = *breakTable; - - /* shift the command down and extract the data */ - breakCommand = ( breakLong >> ( ( 7 - ( breakIndex & 0x7 ) ) << 2 ) ) & 0xF; - if ( breakCommand <= MAX_NATURAL_LENGTH ) - { - /* a nibble of length data, we already have all the - info we need */ - dataNibbles = 0; - commandData = breakCommand; - } - else - if ( breakCommand == LINE_FEED ) - { - /* we should only get this when parsing preformatted text */ - dataNibbles = 0; - commandData = breakCommand; - } - else - if ( breakCommand == BYTE_LENGTH ) - { - /* a byte of length data */ - dataNibbles = 2; - } - else - if ( breakCommand == WORD_LENGTH ) - { - /* a short of length data */ - dataNibbles = 4; - } - else - if ( breakCommand == MULTI_BYTE ) - { - /* 16 bits of data */ - dataNibbles = 4; - *multiByte = TRUE; - } - else - { - /* a 24 bits of data */ - dataNibbles = 6; - } - - if ( dataNibbles > 0 ) - { - /* skip the command tail */ - if ( ( --breakIndex & 0x7 ) == 7 ) - { - breakLong = *--breakTable; - } - - /* read in the actual count and the tail command header */ - for ( nibbleCount = 0; nibbleCount < dataNibbles; ++nibbleCount ) - { - uint32 nibble; - - /* grab the next nibble */ - nibble = ( breakLong >> ( ( 7 - ( breakIndex & 0x7 ) ) << 2 ) ) & 0xF; - commandData |= nibble << ( nibbleCount << 2 ); - - if ( ( --breakIndex & 0x7 ) == 7 ) - { - breakLong = *--breakTable; - } - } - } - } - } - - block->break_read_index = breakIndex; - - *command = commandData; - - return hasPrev; -} - -static uint8 * -lo_GetPrevTextPosition ( LO_TextBlock * block, uint32 * outWordLength, uint32 * outLineLength, Bool * canBreak ) -{ - uint32 wordLength; - uint32 breakCommand; - uint32 lineLength; - uint8 * endTextRun; - uint32 totalSkip; - Bool havePrevCommand; - Bool multiByte; - - *canBreak = FALSE; - totalSkip = 0; - - /* - * Sanity check for already being at the beginning of the line - */ - if ( block->buffer_read_index == block->last_line_break ) - { - *outWordLength = 0; - return NULL; - } - - /* are we in a run of breakable multibyte characters? */ - if ( block->multibyte_length > 0 ) - { - uint16 charSize; - - /* BRAIN DAMAGE */ - /* turn this next line on when the uint16 multibyte_char_size - field is added to LO_TextBlock */ -#if 0 - charSize = block->multibyte_char_size; -#else - charSize = 2; -#endif - block->multibyte_index -= charSize; - - /* are we at the end of this run? */ - if ( block->multibyte_index == 0 ) - { - block->multibyte_length = 0; - } - - /* bump by one character */ - *outWordLength = charSize; - (*outLineLength) -= charSize; - *canBreak = TRUE; - - block->buffer_read_index -= 2; - endTextRun = &block->text_buffer[ block->buffer_read_index ]; - - return endTextRun; - } - - /* back up to the previous command */ - havePrevCommand = lo_ExtractPrevBreakCommand ( block, &multiByte, &breakCommand ); - if ( !havePrevCommand ) - { - *outWordLength = 0; - return NULL; - } - - /* back ourselves up in the buffer */ - if ( multiByte ) - { - uint32 charSize; - - *canBreak = TRUE; - - /* extract the real word length from the command */ - charSize = ( breakCommand & MULTI_CHAR_SIZE_MASK ) >> MULTI_CHAR_SIZE_SHIFT; - - block->multibyte_length = breakCommand & MULTI_LENGTH_MASK; - block->multibyte_index = block->multibyte_length - charSize; - - /* make sure we're not already at the beginning of the run */ - if ( block->multibyte_index == 0 ) - { - block->multibyte_length = 0; - } - - /* MAJOR BRAIN DAMAGE: WE NEED TO STORE THIS IN THE TEXT BLOCK - AS IT WILL NOT */ - /* ALWAYS BE TWO BYTE!!!! */ - XP_ASSERT( charSize == 2 ); - - /* the length of this run is the char size */ - wordLength = charSize; - } - else - { - wordLength = breakCommand; - } - - lineLength = block->buffer_read_index; - - /* if we actually have a word here and are not the first word on - * the line, then subtract one to the length to account for the - * interword space. */ - if ( ( wordLength > 0 ) && ( block->last_line_break != ( lineLength - wordLength )) ) - { - /* only true if there's a space here */ - if ( XP_IS_SPACE ( block->text_buffer[ lineLength - wordLength - 1 ] ) ) - { - lineLength--; - (*outLineLength)--; - } - } - - lineLength -= wordLength; - - block->buffer_read_index = lineLength; - - endTextRun = &block->text_buffer[ lineLength ]; - - *outLineLength -= wordLength; - *outWordLength = wordLength; - - /* We can't break if we've backed up all the way to the start of - the buffer and there is */ - /* no break position there */ - if ( ( block->break_read_index == 0 ) && ( wordLength == 0 ) ) - { - *canBreak = FALSE; - } - else - { - *canBreak = TRUE; - } - - return endTextRun; -} - -static Bool -lo_SetBreakCommand ( LO_TextBlock * block, uint32 command, uint32 commandLength ) -{ - uint32 break_write_index; - uint32 * break_table; - - /* record the current break position as it may be the last entry - in the break table */ - block->last_break_offset = block->buffer_write_index; - block->last_buffer_write_index = block->buffer_write_index; - - break_write_index = block->break_write_index; - - /* grow the break table if we need to - always have space for one - long of data */ - if ( ( break_write_index + 8 ) > block->break_length ) - { - /* allocate in bytes, count in nibbles */ - block->break_length += BREAK_TABLE_INC * 2; - block->break_table = XP_REALLOC ( block->break_table, block->break_length / 2 ); - } - - break_table = block->break_table; - - if ( break_table != NULL ) - { - uint32 nibble_index; - - nibble_index = break_write_index & 0x7; - - /* write the command */ - if ( nibble_index == 0 ) - { - /* we're long aligned, write the sucker */ - break_table[ break_write_index >> 3 ] = command; - } - else - { - uint32 table_long; - uint32 table_index; - - table_index = break_write_index >> 3; - table_long = break_table[ table_index ]; - - table_long |= command >> ( nibble_index << 2 ); - break_table[ table_index ] = table_long; - - /* how many nibbles did we write, and were they enough? */ - nibble_index = 0x8 - nibble_index; - if ( commandLength > nibble_index ) - { - /* need to write out some more data */ - break_table[ table_index + 1 ] = command << ( nibble_index << 2 ); - } - } - - break_write_index += commandLength; - } - - block->break_write_index = break_write_index; - - return break_table != NULL; -} - -static Bool -lo_SetBreakPosition ( LO_TextBlock * block ) -{ - uint32 w_length; - uint32 data_long; - uint32 command_size; - Bool success; - - /* how many characters were added for this run */ - w_length = block->buffer_write_index - block->last_buffer_write_index; - XP_ASSERT ( w_length >= 0 ); - - if ( w_length <= MAX_NATURAL_LENGTH ) - { - /* one data nibble */ - command_size = 1; - data_long = w_length << 28; - } - else - if ( w_length <= 255 ) - { - /* a command nibble, two data nibbles and then a terminator nibble */ - command_size = 4; - data_long = ( BYTE_LENGTH << 28 ) | ( w_length << 20 ) | ( BYTE_LENGTH << 16 ); - } - else - if ( w_length <= 65535 ) - { - /* a command nibble, four data nibbles and then a terminator nibble */ - command_size = 6; - data_long = ( WORD_LENGTH << 28 ) | ( w_length << 12 ) | ( WORD_LENGTH << 8 ); - } - else - { - /* we can have 24 bits of data at most... */ - XP_ASSERT ( w_length <= ( ( 1 << 24 ) - 1 ) ); - - /* a command nibble, six data nibbles and then a terminator nibble */ - command_size = 8; - data_long = ( LONG_LENGTH << 28 ) | ( w_length << 4 ) | ( LONG_LENGTH ); - } - - success = lo_SetBreakCommand ( block, data_long, command_size ); - - return success; -} - -static Bool -lo_SetMultiByteRun ( LO_TextBlock * block, int32 charSize, Bool breakable, Bool eachCharBreakable ) -{ - uint32 w_length; - uint32 data_long; - uint32 command_size; - Bool success; - - /* how many characters were added for this run */ - w_length = block->buffer_write_index - block->last_buffer_write_index; - XP_ASSERT ( w_length >= 0 ); - - /* * There are two cases where we can use a normal simple break - * entry: 1. We are not breakable on every char and the text is - * breakable (the normal break table case). 2. We can break on - * every char, but we only have one char in the run */ - if ( breakable ) - { - if ( !eachCharBreakable || ( charSize == w_length ) ) - { - return lo_SetBreakPosition ( block ); - } - } - - /* BRAIN DAMAGE: We need to handle overflow of our data word */ - - /* this break command always has 16 bits of data and so it is 24 - bits big */ - command_size = 6; - - data_long = w_length; - - data_long |= ( charSize << MULTI_CHAR_SIZE_SHIFT ) & MULTI_CHAR_SIZE_MASK; - - XP_ASSERT( w_length <= MULTI_LENGTH_MASK ); - data_long |= ( w_length & MULTI_LENGTH_MASK ); - - /* set the command nibbles */ - data_long = ( (uint32) MULTI_BYTE << ( MULTI_BYTE_DATA_SIZE + 4 ) ) | (uint32) ( data_long << 4 ) | (uint32) MULTI_BYTE; - data_long <<= 8; - - success = lo_SetBreakCommand ( block, data_long, command_size ); - - return success; -} - -void lo_BreakOldTextBlockElement(MWContext *context, lo_DocState *state) -{ - LO_TextBlock * block; - LO_TextStruct * text_data; - LO_TextStruct * new_text_data; - char * text; - char * breakPtr; - int32 save_width; - uint32 newTextlength; - LO_TextInfo text_info; - int32 base_change; - int32 old_baseline; - int32 old_line_height; - int32 adjust; - int32 baseline_inc=0; - LO_Element * tptr; - LO_Element * eptr; - LO_Element * line_ptr; - - /* note that the block can be null for a word break element */ - block = state->old_break_block; - - /* Move to the element we will break */ - text_data = state->old_break; - - /* If there is no text there to break it is an error. */ - if ( text_data == NULL ) - { - return; - } - - new_text_data = NULL; - - /* - * Later operations will trash the width field. - * So save it now to restore later. - */ - save_width = state->width; - - /* - * If this element has no text, then it's a special word break - * element. We can simply remove it and then add a linefeed and then - * insert the remaining text on the line buffer - */ - if ( text_data->text == NULL ) - { - /* - * Back up the state to this element's location - */ - state->x = text_data->x; - state->y = text_data->y; - - tptr = text_data->next; - text_data->next = NULL; - - state->width = text_data->width; - state->x += state->width; - - /* add a line feed */ - lo_SoftLineBreak(context, state, TRUE); - } - else - { - /* We're trying to break inside an actual text element. We - * need to shorten this element to point up to this break - * position, then add a linefeed, then create a new element - * that contains the remaining text and place it on the line - * buffer */ - - /* if we're breaking an element, we must have a text block */ - if ( block == NULL ) - { - return; - } - - PA_LOCK(text, char *, text_data->text); - - /* - * Back the state up to this element's - * location, break off the rest of the elements - * and save them for later. - * Flush this line, and insert a linebreak. - */ - state->x = text_data->x; - state->y = text_data->y; - tptr = text_data->next; - text_data->next = NULL; - - breakPtr = &text[ state->old_break_pos ]; - newTextlength = text_data->text_len - state->old_break_pos; - - text_data->block_offset = text_data->block_offset - text_data->text_len + state->old_break_pos; - text_data->text_len = state->old_break_pos; - - FE_GetTextInfo(context, text_data, &text_info); - state->width = lo_correct_text_element_width( &text_info ); - - text_data->width = state->width; - PA_UNLOCK(text_data->text); - state->x += state->width; - - /* this element should point at the space before the next - word, so skip it */ - if ( XP_IS_SPACE ( *breakPtr ) ) - { - ++breakPtr; - --newTextlength; - } - - /* - * If the element that caused this break has a different - * baseline than the element we are breaking, we need to - * preserve that difference after the break. - */ - base_change = state->baseline - (text_data->y_offset + text_info.ascent); - - old_baseline = state->baseline; - old_line_height = state->line_height; - - /* - * Reset element_id so they are still sequencial. - */ - state->top_state->element_id = text_data->ele_id + 1; - - /* - * If we are breaking an anchor, we need to make sure the - * linefeed gets its anchor href set properly. - */ - if (text_data->anchor_href != NULL) - { - LO_AnchorData *tmp_anchor; - - tmp_anchor = state->current_anchor; - state->current_anchor = text_data->anchor_href; - lo_SoftLineBreak(context, state, TRUE); - state->current_anchor = tmp_anchor; - } - else - { - lo_SoftLineBreak(context, state, TRUE); - } - - adjust = lo_baseline_adjust( context, state, tptr, old_baseline, old_line_height ); - state->baseline = old_baseline - adjust; - state->line_height = (intn) old_line_height - adjust; - - /* now create a new text element */ - baseline_inc = -1 * adjust; - - new_text_data = (LO_TextStruct *)lo_NewElement ( context, state, LO_TEXT, text_data->edit_element, text_data->edit_offset+text_data->text_len+1 ); - if (text_data == NULL) - { -#ifdef DEBUG - assert (state->top_state->out_of_memory); -#endif - return; - } - - new_text_data->type = LO_TEXT; - new_text_data->ele_id = NEXT_ELEMENT; - new_text_data->x = state->x; - new_text_data->x_offset = 0; - new_text_data->y = state->y; - new_text_data->y_offset = 0; - new_text_data->line_height = 0; - new_text_data->height = 0; - new_text_data->next = NULL; - new_text_data->prev = NULL; - - new_text_data->anchor_href = block->anchor_href; - new_text_data->text_attr = block->text_attr; - new_text_data->ele_attrmask = block->ele_attrmask; - - /* BRAIN DAMAGE: Set LO_ELE_INVISIBLE to mark the element as - not having a valid text ptr */ - XP_ASSERT ( !(new_text_data->ele_attrmask & LO_ELE_INVISIBLE ) ); - new_text_data->ele_attrmask |= LO_ELE_INVISIBLE; - - new_text_data->sel_start = -1; - new_text_data->sel_end = -1; - - new_text_data->doc_width = state->right_margin - state->x; - new_text_data->doc_width = 0; - new_text_data->block_offset = text_data->block_offset + text_data->text_len; - XP_ASSERT(new_text_data->block_offset <= 65535); - - new_text_data->text = (PA_Block) breakPtr; - new_text_data->text_len = newTextlength; - FE_GetTextInfo(context, new_text_data, &text_info); - new_text_data->width = lo_correct_text_element_width(&text_info); - - /* - * Some fonts (particulatly italic ones with curly - * tails on letters like 'f') have a left bearing - * that extends back into the previous character. - * Since in this case the previous character is - * probably not in the same font, we move forward - * to avoid overlap. - */ - if (text_info.lbearing < 0) - { - new_text_data->x_offset = text_info.lbearing * -1; - } - - /* - * The baseline of the text element just inserted in - * the line may be less than or greater than the - * baseline of the rest of the line due to font - * changes. If the baseline is less, this is easy, - * we just increase y_offest to move the text down - * so the baselines line up. For greater baselines, - * we can't move the text up to line up the baselines - * because we will overlay the previous line, so we - * have to move all rest of the elements in this line - * down. - * - * If the baseline is zero, we are the first element - * on the line, and we get to set the baseline. - */ - if (state->baseline == 0) - { - state->baseline = text_info.ascent; - } - else - if (text_info.ascent < state->baseline) - { - new_text_data->y_offset = state->baseline - text_info.ascent; - } - else - { - baseline_inc = baseline_inc + (text_info.ascent - state->baseline); - state->baseline = text_info.ascent; - } - - /* - * Now that we have broken, and added the new - * element, we need to move it down to restore the - * baseline difference that previously existed. - */ - new_text_data->y_offset -= base_change; - - /* - * Calculate the height of this new - * text element. - */ - new_text_data->height = text_info.ascent + text_info.descent; - state->x += new_text_data->width; - } - - /* if our previous element was the last text element for this - * block, then our new element is the new end */ - if ( block->endTextElement == text_data ) - { - block->endTextElement = new_text_data; - } - - /* - * Now add the remaining elements to the line list - */ - - /* first find the end of the line list */ - line_ptr = state->line_list; - while ((line_ptr != NULL)&&(line_ptr->lo_any.next != NULL)) - { - line_ptr = line_ptr->lo_any.next; - } - - /* now add the new_text_data if there is one */ - if ( new_text_data != NULL ) - { - if (line_ptr == NULL) - { - state->line_list = (LO_Element *) new_text_data; - new_text_data->prev = NULL; - line_ptr = (LO_Element *) new_text_data; - } - else - { - line_ptr->lo_any.next = (LO_Element *) new_text_data; - new_text_data->prev = line_ptr; - line_ptr = (LO_Element *) new_text_data; - } - } - - /* and then add tptr */ - if ( tptr != NULL ) - { - if (line_ptr == NULL) - { - state->line_list = tptr; - tptr->lo_any.prev = NULL; - line_ptr = tptr; - } - else - { - line_ptr->lo_any.next = tptr; - tptr->lo_any.prev = line_ptr; - line_ptr = tptr; - } - } - - /* if we've added a new element then increment the element id's of - the following elements */ - if ( new_text_data != NULL ) - { - eptr = tptr; - - while (eptr != NULL) - { - eptr->lo_any.ele_id = NEXT_ELEMENT; - eptr->lo_any.y_offset += baseline_inc; - eptr = eptr->lo_any.next; - } - - /* and bump the line height if we need to */ - if ( ( new_text_data->y_offset + new_text_data->height ) > state->line_height ) - { - state->line_height = (intn) new_text_data->y_offset + new_text_data->height; - } - } - - /* - * Upgrade forward the x and y text positions in the document - * state. - */ - while ( tptr != NULL ) - { - lo_UpdateElementPosition ( state, tptr ); - tptr = tptr->lo_any.next; - } - - state->at_begin_line = FALSE; - state->width = save_width; -} - -static uint8 * -lo_GetLineStart ( LO_TextBlock * block ) -{ - return &block->text_buffer[ block->last_line_break ]; -} - -#ifdef DOM -static void -lo_SkipCharacter ( LO_TextBlock * block ) -{ - ++block->buffer_read_index; -} -#endif - -static void -lo_SetLineBreak ( LO_TextBlock * block, Bool skipSpace ) -{ - /* if the current character is a space, we can skip it as we're - breaking here */ - /* NOT FOR PREFORMATTED TEXT THOUGH */ - if ( skipSpace && ( XP_IS_SPACE ( block->text_buffer[ block->buffer_read_index ] ) ) ) - { - ++block->buffer_read_index; - } - - block->last_line_break = block->buffer_read_index; -} - -static uint8 * -lo_RestoreBreakState ( LO_TextBlock * block, BreakState * state, uint32 * lineLength ) -{ - uint8 * runEnd; - - block->buffer_read_index = state->buffer_read_index; - block->break_read_index = state->break_read_index; - block->multibyte_index = state->multibyte_index; - block->multibyte_length = state->multibyte_length; - block->last_line_break = state->last_line_break; - - if ( lineLength != NULL ) - { - *lineLength = state->lineLength; - } - - runEnd = &block->text_buffer[ block->buffer_read_index ]; - - return runEnd; -} - - -static Bool -lo_SkipInitialSpace ( LO_TextBlock * block ) -{ - Bool canBreak; - uint32 breakLong; - uint32 breakIndex; - - canBreak = FALSE; - breakIndex = block->break_read_index; - - /* do we have a break point at the current text offset */ - if ( ( breakIndex == 0 ) && ( breakIndex < block->break_write_index ) && XP_IS_SPACE ( block->text_buffer[ 0 ] ) ) - { - breakLong = block->break_table[ breakIndex >> 3 ]; - breakLong >>= ( 7 - ( breakIndex & 0x7 ) ) << 2; - - if ( breakLong == 0 ) - { - block->buffer_read_index++; - block->break_read_index++; - block->last_line_break++; - canBreak = TRUE; - } - } - - return canBreak; -} - - -Bool lo_GrowTextBlock ( LO_TextBlock * block, uint32 length ) -{ - Bool success = TRUE; - uint32 growBy; - uint32 oldTextBase; - uint32 offset; - LO_TextStruct * textElement; - LO_TextStruct * endElement; - - if ( block->buffer_length < ( block->buffer_write_index + length ) ) - { - /* need to make sure that the new size is enough to contain - the new data */ - growBy = TEXT_BUFFER_INC; - if ( growBy < length ) - { - growBy = length; - } - - oldTextBase = (uint32) block->text_buffer; - - growBy += block->buffer_length; - block->text_buffer = XP_REALLOC ( block->text_buffer, growBy ); - - block->buffer_length = growBy; - success = block->text_buffer != NULL; - - /* update any break table related information */ - if ( success && ( block->break_table != NULL ) ) - { - /* Run through all the text elements and adjust their text - * addresses to point to the newly relocated block */ - - textElement = block->startTextElement; - endElement = block->endTextElement; - - while ( textElement != NULL ) - { - if ( textElement->type == LO_TEXT ) - { - offset = (uint32) textElement->text - oldTextBase; - textElement->text = (PA_Block) ( (uint32) block->text_buffer + offset ); - } - - if ( textElement == endElement ) - { - break; - } - - textElement = (LO_TextStruct *) textElement->next; - } - } - } - - return success; -} - -static void -lo_CopyText ( uint8 * src, uint8 * dst, uint32 length ) -{ - uint8 c; - - /* copy a text string, converting non breaking spaces to normal - spaces as we go */ - while ( length-- ) - { - c = *src++; - - if ( c == NON_BREAKING_SPACE ) - { - c = ' '; - } - - *dst++ = c; - } -} - -static void -lo_CopyTextToLineBuffer ( lo_DocState * state, uint8 * src, uint32 length ) -{ - char * text_buf; - - /* do we need to grow the buffer? */ - if ( ( state->line_buf_len + length + 1 ) > state->line_buf_size ) - { - state->line_buf = PA_REALLOC ( state->line_buf, ( state->line_buf_size + length + LINE_BUF_INC ) ); - if ( state->line_buf == NULL ) - { - state->top_state->out_of_memory = TRUE; - return; - } - } - - PA_LOCK(text_buf, char *, state->line_buf); - - XP_BCOPY ( (char *) src, (char *) ( text_buf + state->line_buf_len ), ( length + 1 ) ); - state->line_buf_len += length; - - text_buf[ state->line_buf_len ] = 0; - - PA_UNLOCK(state->line_buf); -} - -#ifdef DOM -LO_TextAttr * -lo_GetCurrentTextAttr(lo_DocState *state, MWContext *context) -{ - LO_TextAttr tmp_attr, *tptr, *styleptr; - JSBool isMutable; - - if (!state->font_stack) { - /* - * XXX we should keep a text_attr with the default values around so that - * we can just bump the refcount instead of copying all that data and - * stuff. - */ - lo_SetDefaultFontAttr(state, &tmp_attr, context); - tptr = &tmp_attr; - isMutable = JS_TRUE; - } else { - /* - * we can just dup the pointer, because lo_FillInTextStyleInfo will - * copy-on-write for us. - */ - tptr = state->font_stack->text_attr; - tptr->refcnt++; - isMutable = JS_FALSE; - } - - styleptr = lo_FillInTextStyleInfo(state, context, tptr, isMutable); - if (styleptr != tptr) - isMutable = JS_FALSE; /* already fetched, so no need to refetch */ - tptr = styleptr; - - if (isMutable) - /* we're working on the stack-allocated text_attr, so get a heap copy */ - tptr = lo_FetchTextAttr(state, tptr); - - return tptr; -} - -#ifdef DEBUG_shaver -/* #define DEBUG_shaver_textattr */ -#endif - -LO_TextAttr * -lo_FillInTextStyleInfo(lo_DocState *state, MWContext *context, - LO_TextAttr *tptr, JSBool isMutable) -{ - JSContext *cx = context->mocha_context; - DOM_StyleDatabase *db = state->top_state->style_db; - DOM_AttributeEntry *entry; - DOM_Node *node = ACTIVE_NODE(state); - LO_TextAttr text_attr, *newptr = NULL; - JSBool copied = JS_FALSE; - LO_Color col; - - if (!node) - return tptr; - - if (node->type != NODE_TYPE_TEXT) { - if (node->type == NODE_TYPE_ELEMENT) { - DOM_HTMLElementPrivate *priv = node->data; - if (priv && - (priv->tagtype == P_LIST_ITEM || - priv->tagtype == P_IMAGE || - priv->tagtype == P_HRULE /* layout NYI */)) { -#ifdef DEBUG_shaver_textattr - fprintf(stderr, "setting textattr on <%s>\n", - ((DOM_Element *)node)->tagName); -#endif - } else { -#ifdef DEBUG_shaver_textattr - fprintf(stderr, "NOT setting textattr on <%s>\n", - ((DOM_Element *)node)->tagName); -#endif - return tptr; - } - } - } - -#define COW() \ - if (!isMutable && !copied) { \ - lo_CopyTextAttr(tptr, &text_attr); \ - copied = JS_TRUE; \ - } - - if (!isMutable) { - XP_BZERO(&text_attr, sizeof(text_attr)); - newptr = &text_attr; - } else { - newptr = tptr; - } - - if (!db) { - /* find enclosing link object, and set the appropriate default color */ - DOM_StyleToken pseudo; - DOM_Element *link; - -#ifdef DEBUG_shaver_textattr - fprintf(stderr, "no db, setting default attrs "); -#endif - - if (!state->current_anchor) { -#ifdef DEBUG_shaver - fprintf(stderr, "no anchor, done\n"); -#endif - goto done; - } - - link = state->current_anchor->node; - XP_ASSERT(link && link->node.type == NODE_TYPE_ELEMENT); - pseudo = DOM_GetElementPseudo(cx, link); - if (pseudo) { - /* XXX assuming that we only set pseudo on links! */ - LO_Color col; -#ifdef DEBUG_shaver_textattr - fprintf(stderr, "pseudo is %s", pseudo); -#endif - COW(); - if (lo_underline_anchors()) - newptr->attrmask |= LO_ATTR_UNDERLINE; - if (!XP_STRCMP(pseudo, "link")) { - col.red = STATE_UNVISITED_ANCHOR_RED(state); - col.blue = STATE_UNVISITED_ANCHOR_BLUE(state); - col.green = STATE_UNVISITED_ANCHOR_GREEN(state); - newptr->fg = col; - } else if (!XP_STRCMP(pseudo, "visited")) { - col.red = STATE_VISITED_ANCHOR_RED(state); - col.blue = STATE_VISITED_ANCHOR_BLUE(state); - col.green = STATE_VISITED_ANCHOR_GREEN(state); - newptr->fg = col; - } - } -#ifdef DEBUG_shaver_textattr - fputs("\n", stderr); -#endif - goto done; - } - - /* check "color" property */ - if (!DOM_StyleGetProperty(cx, db, node, COLOR_STYLE, &entry)) - /* XXX report error? return NULL? */ - goto done; - if (entry) { - if (!DOM_GetCleanEntryData(cx, entry, lo_ColorStringToData, NULL, (uint32*)&col, - NULL)) - goto done; - if (*(uint32 *)&col != *(uint32 *)&tptr->fg) { - COW(); - newptr->fg = col; - } - } - - /* check bgcolor property, including transparent */ - if (!DOM_StyleGetProperty(cx, db, node, BG_COLOR_STYLE, &entry)) - goto done; - if (entry) { - COW(); - if (!DOM_GetCleanEntryData(cx, entry, lo_ColorStringToData, NULL, (uint32*)&col, - NULL)) - goto done; - newptr->bg = col; - if (!strcasecomp(entry->value, "transparent")) - newptr->no_background = TRUE; - else - newptr->no_background = FALSE; - } - - /* check font-face */ - if (lo_face_attribute()) { - if (!DOM_StyleGetProperty(cx, db, node, FONTFACE_STYLE, &entry)) - goto done; - if (entry) { - COW(); - /* XXXshaver use GetCleanEntryData when I figure out mem mgmt */ -#if 0 - if (newptr->font_face) - XP_FREE(newptr->font_face); -#endif - newptr->font_face = lo_FetchFontFace(context, state, - (char *)entry->value); - } - } - - /* check font-size */ - if (!DOM_StyleGetProperty(cx, db, node, FONTSIZE_STYLE, &entry)) - return NULL; - if (entry) { - double *fontsize; - struct SSUnitContext arg; - arg.context = context; - - if (!DOM_GetCleanEntryData(cx, entry, lo_ParseFontSizeToData, lo_DeleteFontSize, - (uint32*)&fontsize, (void *)&arg)) - return NULL; - if (newptr->point_size != *fontsize) { - COW(); - newptr->point_size = *fontsize; - } - } - - /* check font-weight */ - if (!DOM_StyleGetProperty(cx, db, node, FONTWEIGHT_STYLE, &entry)) - goto done; - if (entry) { - uint32 weight; - /* - * For "bolder" and "lighter", we need to keep them dirty because they're - * dependent on the enclosing state. - */ - if (!DOM_GetCleanEntryData(cx, entry, FontWeightToData, NULL, &weight, NULL)) - goto done; - if (weight) { - if (!newptr->font_weight) { - COW(); - newptr->font_weight = 400; - } - if (weight == FONT_WEIGHT_BOLDER) { - weight = MAX(newptr->font_weight + 100, 100); - entry->dirty = JS_TRUE; - } else if (weight == FONT_WEIGHT_LIGHTER) { - weight = MIN(newptr->font_weight - 100, 900); - entry->dirty = JS_TRUE; - } - if (weight != (uint32)newptr->font_weight) { - COW(); - newptr->font_weight = weight; - } - } - } - - /* font-style */ - if (!DOM_StyleGetProperty(cx, db, node, FONTSTYLE_STYLE, &entry)) - goto done; - if (entry) { - if (!strcasecomp(entry->value, NORMAL_STYLE)) { - /* { font-style:normal} */ - if (newptr->fontmask & LO_FONT_ITALIC) { - COW(); - newptr->fontmask &= ~LO_FONT_ITALIC; - } - } else if (!strcasecomp(entry->value, ITALIC_STYLE)) { - /* { font-style:italic} */ - if (!(newptr->fontmask & LO_FONT_ITALIC)) { - COW(); - newptr->fontmask |= LO_FONT_ITALIC; - } - } - /* XXX need LO_FONT_OBLIQUE */ - } - - /* text-decoration */ - if (!DOM_StyleGetProperty(cx, db, node, TEXTDECORATION_STYLE, &entry)) - goto done; - if (entry) { - uint32 attrs; -#define ATTRMASK (LO_ATTR_BLINK | LO_ATTR_STRIKEOUT | LO_ATTR_UNDERLINE) - if (!DOM_GetCleanEntryData(cx, entry, TextDecorationToData, NULL, &attrs, NULL)) - goto done; - attrs = (tptr->attrmask & ~ATTRMASK) | (attrs & ATTRMASK); - if (attrs != tptr->attrmask) { - COW(); - newptr->attrmask = attrs; - } -#undef ATTRMASK - } - -#undef COW - done: - if (!isMutable && copied) { - tptr = lo_FetchTextAttr(state, &text_attr); -#ifdef DEBUG_shaver_textattr - fprintf(stderr, "returning new TextAttr: %p\n", tptr); -#endif - return tptr; - } -#ifdef DEBUG_shaver_textattr - fprintf(stderr, "returning unmodified TextAttr %p\n", tptr); -#endif - return tptr; -} - -#endif /* DOM */ - -#ifdef TEST_16BIT -#undef XP_WIN16 -#endif /* TEST_16BIT */ - -#ifdef PROFILE -#pragma profile off -#endif diff --git a/lib/layout/layutil.c b/lib/layout/layutil.c index 13f6e9153d6..e69de29bb2d 100644 --- a/lib/layout/layutil.c +++ b/lib/layout/layutil.c @@ -1,3914 +0,0 @@ -/* -*- 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. - */ - - - -#include "xp.h" -#include "pa_parse.h" -#include "layout.h" -#include "laylayer.h" -#include "laystyle.h" -#include "libmocha.h" -#include "stystruc.h" -#include "stystack.h" -#include "layers.h" -#ifdef XP_MAC -#include "prpriv.h" -#else -#include "private/prpriv.h" /* for PR_NewNamedMonitor */ -#endif -#include "intl_csi.h" - -#ifdef DOM -#include "lm_dom.h" -#endif - -#ifdef EDITOR -#include "edt.h" -#endif -#ifdef PROFILE -#pragma profile on -#endif - -#ifdef XP_WIN16 -#define SIZE_LIMIT 32000 -#endif /* XP_WIN16 */ - -#define FONT_FACE_INC 10 -#define FONT_FACE_MAX 1000 - -#ifdef DOM -static void lo_SetInSpanAttribute( LO_Element *ele ); -#endif - -void -lo_GetElementBbox(LO_Element *element, XP_Rect *rect) -{ - rect->left = element->lo_any.x + element->lo_any.x_offset; - rect->top = element->lo_any.y + element->lo_any.y_offset; - rect->right = rect->left + element->lo_any.width; - rect->bottom = rect->top + element->lo_any.height; - - switch(element->type) - { - case LO_IMAGE: - { - LO_ImageStruct *image = &element->lo_image; - rect->right += 2 * (image->border_width + image->border_horiz_space); - rect->bottom += 2 * (image->border_width + image->border_vert_space); - } - break; - - case LO_SUBDOC: - { - LO_SubDocStruct *subdoc = &element->lo_subdoc; - rect->right += 2 * (subdoc->border_width + subdoc->border_horiz_space); - rect->bottom += 2 * (subdoc->border_width + subdoc->border_vert_space); - } - break; - - case LO_TABLE: - { - LO_TableStruct *table = &element->lo_table; - rect->right += 2 * (table->border_width + table->border_horiz_space); - rect->bottom += 2 * (table->border_width + table->border_vert_space); - } - break; - - case LO_CELL: - { - LO_CellStruct *cell = &element->lo_cell; - rect->right += 2 * (cell->border_width + cell->border_horiz_space); - rect->bottom += 2 * (cell->border_width + cell->border_vert_space); - } - break; - - case LO_EMBED: - { - LO_EmbedStruct *embed = &element->lo_embed; - rect->right += 2 * (embed->objTag.border_width + embed->objTag.border_horiz_space); - rect->bottom += 2 * (embed->objTag.border_width + embed->objTag.border_vert_space); - } - break; - - case LO_BUILTIN: - { - LO_BuiltinStruct *builtin = &element->lo_builtin; - rect->right += 2 * (builtin->border_width + builtin->border_horiz_space); - rect->bottom += 2 * (builtin->border_width + builtin->border_vert_space); - } - break; - -#ifdef JAVA - case LO_JAVA: - { - LO_JavaAppStruct *java = &element->lo_java; - rect->right += 2 * (java->objTag.border_width + java->objTag.border_horiz_space); - rect->bottom += 2 * (java->objTag.border_width + java->objTag.border_vert_space); - } - break; -#endif - - default: - break; - } -} - -void -lo_RefreshElement(LO_Element *element, CL_Layer *layer, Bool update_now) -{ - XP_Rect rect; - int32 x_offset, y_offset; - CL_Compositor *compositor = CL_GetLayerCompositor(layer); - - lo_GetElementBbox(element, &rect); - - lo_GetLayerXYShift(layer, &x_offset, &y_offset); - XP_OffsetRect(&rect, -x_offset, -y_offset); - CL_UpdateLayerRect(compositor, layer, &rect, (PRBool)update_now); -} - -/* Given a layout element, retrieve its anchor information. */ -LO_AnchorData * -lo_GetElementAnchor(LO_Element *element) -{ - switch(element->type) - { - case LO_TEXT: - return element->lo_text.anchor_href; - - case LO_IMAGE: - return element->lo_image.anchor_href; - - case LO_TABLE: - return element->lo_table.anchor_href; - - case LO_SUBDOC: - return element->lo_subdoc.anchor_href; - - case LO_LINEFEED: - return element->lo_linefeed.anchor_href; - - default: - return NULL; - } -} - -/* Return an element's foreground color */ -void -lo_GetElementFGColor(LO_Element *element, LO_Color *color) -{ - switch (element->type) - { - case LO_TEXT: - color->red = element->lo_text.text_attr->fg.red; - color->green = element->lo_text.text_attr->fg.green; - color->blue = element->lo_text.text_attr->fg.blue; - break; - - case LO_IMAGE: - color->red = element->lo_image.text_attr->fg.red; - color->green = element->lo_image.text_attr->fg.green; - color->blue = element->lo_image.text_attr->fg.blue; - break; - - case LO_SUBDOC: - color->red = element->lo_subdoc.text_attr->fg.red; - color->green = element->lo_subdoc.text_attr->fg.green; - color->blue = element->lo_subdoc.text_attr->fg.blue; - break; - - default: - XP_ASSERT(0); /* Not implemented */ - break; - } -} - -/* Set an element's foreground color */ -void -lo_SetElementFGColor(LO_Element *element, LO_Color *color) -{ - switch (element->type) - { - case LO_TEXT: - element->lo_text.text_attr->fg.red = color->red; - element->lo_text.text_attr->fg.green = color->green; - element->lo_text.text_attr->fg.blue = color->blue; - break; - - case LO_IMAGE: - element->lo_image.text_attr->fg.red = color->red; - element->lo_image.text_attr->fg.green = color->green; - element->lo_image.text_attr->fg.blue = color->blue; - break; - - case LO_SUBDOC: - element->lo_subdoc.text_attr->fg.red = color->red; - element->lo_subdoc.text_attr->fg.green = color->green; - element->lo_subdoc.text_attr->fg.blue = color->blue; - break; - - default: - XP_ASSERT(0); /* Not implemented */ - break; - } -} - -NET_ReloadMethod -LO_GetReloadMethod(MWContext *context) -{ - int32 doc_id; - lo_TopState *top_state; - lo_DocState *state; - - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return NET_NORMAL_RELOAD; - } - state = top_state->doc_state; - - return (FORCE_RELOAD_FLAG(state->top_state)); -} - - -void -LO_InvalidateFontData(MWContext *context) -{ - int32 i, doc_id; - lo_TopState *top_state; - lo_DocState *state; - LO_TextAttr **text_attr_hash; - LO_TextAttr *attr_ptr; - - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return; - } - state = top_state->doc_state; - - if (state->top_state->text_attr_hash == NULL) - { - return; - } - - XP_LOCK_BLOCK(text_attr_hash, LO_TextAttr **, - state->top_state->text_attr_hash); - for (i=0; i < FONT_HASH_SIZE; i++) - { - attr_ptr = text_attr_hash[i]; - while (attr_ptr != NULL) - { - if (attr_ptr->FE_Data != NULL) - { - FE_ReleaseTextAttrFeData(context, attr_ptr); - } - attr_ptr->FE_Data = NULL; - attr_ptr = attr_ptr->next; - } - } -} - - -static char * -lo_find_face_in_array(char **face_list, intn len, char *face) -{ - intn i; - char *the_face; - - if (face == NULL) - { - return(NULL); - } - - the_face = NULL; - for (i=0; i<len; i++) - { - if ((face_list[i] != NULL)&& - (XP_STRCMP(face, face_list[i]) == 0)) - { - the_face = face_list[i]; - break; - } - } - - return(the_face); -} - - -Bool -lo_EvalTrueOrFalse(char *str, Bool default_val) -{ - Bool ret_val; - - ret_val = default_val; - - if (str == NULL) - { - return(ret_val); - } - - if (pa_TagEqual("true", str)) - { - ret_val = TRUE; - } - else if (pa_TagEqual("yes", str)) - { - ret_val = TRUE; - } - else if (pa_TagEqual("no", str)) - { - ret_val = FALSE; - } - else if (pa_TagEqual("false", str)) - { - ret_val = FALSE; - } - - return(ret_val); -} - -char * -lo_FetchFontFace(MWContext *context, lo_DocState *state, char *face) -{ - char **face_list; - char *new_face; - - /* - * If this is our first addition, allocate the array. - */ - if (state->top_state->font_face_array == NULL) - { - PA_Block buff; - - buff = PA_ALLOC(FONT_FACE_INC * sizeof(char *)); - if (buff == NULL) - { - state->top_state->out_of_memory = TRUE; - return(NULL); - } - state->top_state->font_face_array = buff; - state->top_state->font_face_array_size = FONT_FACE_INC; - state->top_state->font_face_array_len = 0; - } - /* - * Else if the list is full, grow the array. - */ - else if (state->top_state->font_face_array_len >= - state->top_state->font_face_array_size) - { - PA_Block buff; - intn new_size; - - if (state->top_state->font_face_array_size >= FONT_FACE_MAX) - { - return(NULL); - } - - new_size = state->top_state->font_face_array_size + - FONT_FACE_INC; - if (new_size > FONT_FACE_MAX) - { - new_size = FONT_FACE_MAX; - } - buff = XP_REALLOC_BLOCK(state->top_state->font_face_array, - (new_size * sizeof(char *))); - if (buff == NULL) - { - state->top_state->out_of_memory = TRUE; - return(NULL); - } - state->top_state->font_face_array = buff; - state->top_state->font_face_array_size = new_size; - } - - PA_LOCK(face_list, char **, state->top_state->font_face_array); - new_face = lo_find_face_in_array(face_list, - state->top_state->font_face_array_len, face); - if (new_face == NULL) - { - char *str; - - str = XP_STRDUP(face); - if (str == NULL) - { - PA_UNLOCK(state->top_state->font_face_array); - state->top_state->out_of_memory = TRUE; - return(NULL); - } - face_list[state->top_state->font_face_array_len] = str; - state->top_state->font_face_array_len++; - new_face = str; - } - PA_UNLOCK(state->top_state->font_face_array); - return(new_face); -} - - -Bool -lo_IsValidTarget(char *target) -{ - if (target == NULL) - { - return(FALSE); - } - if ((XP_IS_ALPHA(target[0]) != FALSE)|| - (XP_IS_DIGIT(target[0]) != FALSE)|| - (target[0] == '_')) - { - return(TRUE); - } - return(FALSE); -} - - -int32 -lo_StripTextNewlines(char *text, int32 text_len) -{ - char *from_ptr; - char *to_ptr; - int32 len; - - if ((text == NULL)||(text_len < 1)) - { - return(0); - } - - /* - * remove all non-space whitespace from the middle of the string. - */ - from_ptr = text; - len = text_len; - to_ptr = text; - while (*from_ptr != '\0') - { - if (XP_IS_SPACE(*from_ptr) && (*from_ptr != ' ')) - { - from_ptr++; - len--; - } - else - { - *to_ptr++ = *from_ptr++; - } - } - *to_ptr = '\0'; - - return(len); -} - - -PA_Block -lo_FEToNetLinebreaks(PA_Block text_block) -{ - PA_Block new_block; - char *new_text; - char *text; - char *from_ptr; - char *to_ptr; - char break_char; - int32 len, new_len; - int32 linebreak; - - if (text_block == NULL) - { - return(NULL); - } - PA_LOCK(text, char *, text_block); - - XP_BCOPY(LINEBREAK, (char *)(&break_char), 1); - len = 0; - linebreak = 0; - from_ptr = text; - while (*from_ptr != '\0') - { - if (*from_ptr == break_char) - { - if (strncmp(from_ptr, LINEBREAK, LINEBREAK_LEN) == 0) - { - linebreak++; - len += LINEBREAK_LEN; - from_ptr = (char *)(from_ptr + LINEBREAK_LEN); - } - else - { - len++; - from_ptr++; - } - } - else - { - len++; - from_ptr++; - } - } - - new_len = len - (LINEBREAK_LEN * linebreak) + (2 * linebreak); - new_block = PA_ALLOC(new_len + 1); - if (new_block == NULL) - { - PA_UNLOCK(text_block); - return(NULL); - } - PA_LOCK(new_text, char *, new_block); - from_ptr = text; - to_ptr = new_text; - while (*from_ptr != '\0') - { - if (*from_ptr == break_char) - { - if (strncmp(from_ptr, LINEBREAK, LINEBREAK_LEN) == 0) - { - from_ptr = (char *)(from_ptr + LINEBREAK_LEN); - *to_ptr++ = CR; - *to_ptr++ = LF; - } - else - { - *to_ptr++ = *from_ptr++; - } - } - else - { - *to_ptr++ = *from_ptr++; - } - } - *to_ptr = '\0'; - - new_text[new_len] = '\0'; - PA_UNLOCK(new_block); - PA_UNLOCK(text_block); - return(new_block); -} - - -PA_Block -lo_ConvertToFELinebreaks(char *text, int32 text_len, int32 *new_len_ptr) -{ - PA_Block new_block; - char *new_text; - char *from_ptr; - char *to_ptr; - char break_char; - int32 len, new_len; - int32 skip, linebreak; - - if (text == NULL) - { - return(NULL); - } - - break_char = '\0'; - len = 0; - skip = 0; - linebreak = 0; - from_ptr = text; - to_ptr = text; - while (len < text_len) - { - if ((*from_ptr == CR)||(*from_ptr == LF)) - { - if ((break_char != '\0')&&(break_char != *from_ptr)) - { - skip++; - break_char = '\0'; - } - else - { - skip++; - linebreak++; - break_char = *from_ptr; - } - } - from_ptr++; - len++; - } - - new_len = len - skip + (LINEBREAK_LEN * linebreak); - new_block = PA_ALLOC(new_len + 1); - if (new_block == NULL) - { - return(NULL); - } - PA_LOCK(new_text, char *, new_block); - break_char = '\0'; - len = 0; - from_ptr = text; - to_ptr = new_text; - while (len < text_len) - { - if ((*from_ptr == CR)||(*from_ptr == LF)) - { - if ((break_char != '\0')&&(break_char != *from_ptr)) - { - break_char = '\0'; - } - else - { - XP_BCOPY(LINEBREAK, to_ptr, LINEBREAK_LEN); - to_ptr = (char *)(to_ptr + LINEBREAK_LEN); - break_char = *from_ptr; - } - from_ptr++; - len++; - } - else - { - *to_ptr++ = *from_ptr++; - len++; - } - } - - new_text[new_len] = '\0'; - *new_len_ptr = new_len; - PA_UNLOCK(new_block); - return(new_block); -} - - -intn -lo_EvalVAlignParam(char *str) -{ - intn alignment; - - alignment = LO_ALIGN_TOP; - if (pa_TagEqual("top", str)) - { - alignment = LO_ALIGN_TOP; - } - else if (pa_TagEqual("bottom", str)) - { - alignment = LO_ALIGN_BOTTOM; - } - else if ((pa_TagEqual("middle", str))|| - (pa_TagEqual("center", str))) - { - alignment = LO_ALIGN_CENTER; - } - else if (pa_TagEqual("baseline", str)) - { - alignment = LO_ALIGN_BASELINE; - } - return(alignment); -} - - -intn -lo_EvalDivisionAlignParam(char *str) -{ - intn alignment; - - alignment = LO_ALIGN_LEFT; - if (pa_TagEqual("left", str)) - { - alignment = LO_ALIGN_LEFT; - } - else if (pa_TagEqual("right", str)) - { - alignment = LO_ALIGN_RIGHT; - } - else if (pa_TagEqual("center", str)) - { - alignment = LO_ALIGN_CENTER; - } - else if (pa_TagEqual("justify", str)) - { - alignment = LO_ALIGN_JUSTIFY; - } - return(alignment); -} - - -intn -lo_EvalCellAlignParam(char *str) -{ - intn alignment; - - alignment = LO_ALIGN_LEFT; - if (pa_TagEqual("left", str)) - { - alignment = LO_ALIGN_LEFT; - } - else if (pa_TagEqual("right", str)) - { - alignment = LO_ALIGN_RIGHT; - } - else if ((pa_TagEqual("middle", str))|| - (pa_TagEqual("center", str))) - { - alignment = LO_ALIGN_CENTER; - } - return(alignment); -} - -#if defined( EDITOR ) || !defined( MEMORY_ARENAS ) -/* this is a replacement routine for the non-editor version and should eventually - * replace the non-edit version. It uses an array of values. instead of an - * unrolled loop. -*/ - -/* - * Indexed by LO_ALIGN_ETC -*/ -char* lo_alignStrings[] = { - "abscenter", /* LO_ALIGN_CENTER */ - "left", /* LO_ALIGN_LEFT */ - "right", /* LO_ALIGN_RIGHT */ - "texttop", /* LO_ALIGN_TOP */ - "absbottom", /* LO_ALIGN_BOTTOM */ - "baseline", /* LO_ALIGN_BASELINE */ - "middle", /* LO_ALIGN_NCSA_CENTER */ - "bottom", /* LO_ALIGN_NCSA_BOTTOM */ - "top", /* LO_ALIGN_NCSA */ - 0 -}; - -intn -lo_EvalAlignParam(char *str, Bool *floating) -{ - intn alignment; - - *floating = FALSE; - alignment = LO_ALIGN_BASELINE; - if (pa_TagEqual("middle", str)) - { - alignment = LO_ALIGN_NCSA_CENTER; - } - else if (pa_TagEqual("absmiddle", str)) - { - alignment = LO_ALIGN_CENTER; - } - else - { - intn i = 0; - Bool bFound = FALSE; - - while( lo_alignStrings[i] != NULL && bFound == FALSE ) - { - if( pa_TagEqual( lo_alignStrings[i], str) ) - { - bFound = TRUE; - alignment = i; - } - i++; - } - } - if( alignment == LO_ALIGN_LEFT || alignment == LO_ALIGN_RIGHT) - { - *floating = TRUE; - } - return alignment; -} - -#else - -intn -lo_EvalAlignParam(char *str, Bool *floating) -{ - intn alignment; - - *floating = FALSE; - alignment = LO_ALIGN_BASELINE; - if (pa_TagEqual("top", str)) - { - alignment = LO_ALIGN_NCSA_TOP; - } - else if (pa_TagEqual("texttop", str)) - { - alignment = LO_ALIGN_TOP; - } - else if (pa_TagEqual("bottom", str)) - { - alignment = LO_ALIGN_NCSA_BOTTOM; - } - else if (pa_TagEqual("absbottom", str)) - { - alignment = LO_ALIGN_BOTTOM; - } - else if (pa_TagEqual("baseline", str)) - { - alignment = LO_ALIGN_BASELINE; - } - else if ((pa_TagEqual("middle", str))|| - (pa_TagEqual("center", str))) - { - alignment = LO_ALIGN_NCSA_CENTER; - } - else if ((pa_TagEqual("absmiddle", str))|| - (pa_TagEqual("abscenter", str))) - { - alignment = LO_ALIGN_CENTER; - } - else if (pa_TagEqual("left", str)) - { - alignment = LO_ALIGN_LEFT; - *floating = TRUE; - } - else if (pa_TagEqual("right", str)) - { - alignment = LO_ALIGN_RIGHT; - *floating = TRUE; - } - return(alignment); -} -#endif - -/* set *alignment and *floating iff there - * is a valid stylesheet alignment property. - */ -MODULE_PRIVATE void -lo_EvalStyleSheetAlignment(StyleStruct *style_struct, - intn *alignment, - Bool *floating) -{ - char *valign, *halign; - - if(!style_struct) - return; - - valign = STYLESTRUCT_GetString(style_struct,VERTICAL_ALIGN_STYLE); - halign = STYLESTRUCT_GetString(style_struct,HORIZONTAL_ALIGN_STYLE); - - if(valign) - { - if (pa_TagEqual("top", valign)) - { - *alignment = LO_ALIGN_NCSA_TOP; - *floating = FALSE; - } - else if (pa_TagEqual("texttop", valign) - || pa_TagEqual("text-top", valign)) - { - *alignment = LO_ALIGN_TOP; - *floating = FALSE; - } - else if (pa_TagEqual("bottom", valign)) - { - *alignment = LO_ALIGN_NCSA_BOTTOM; - *floating = FALSE; - } - else if (pa_TagEqual("absbottom", valign) - || pa_TagEqual("text-bottom", valign)) - { - *alignment = LO_ALIGN_BOTTOM; - *floating = FALSE; - } - else if (pa_TagEqual("baseline", valign)) - { - *alignment = LO_ALIGN_BASELINE; - *floating = FALSE; - } - else if ((pa_TagEqual("middle", valign))|| - (pa_TagEqual("center", valign))) - { - *alignment = LO_ALIGN_NCSA_CENTER; - *floating = FALSE; - } - else if ((pa_TagEqual("absmiddle", valign))|| - (pa_TagEqual("abscenter", valign))) - { - *alignment = LO_ALIGN_CENTER; - *floating = FALSE; - } - } - - if(halign) - { - if (pa_TagEqual("left", halign)) - { - *alignment = LO_ALIGN_LEFT; - *floating = TRUE; - } - else if (pa_TagEqual("right", halign)) - { - *alignment = LO_ALIGN_RIGHT; - *floating = TRUE; - } - } - - XP_FREEIF(valign); - XP_FREEIF(halign); - - return; -} - -void -lo_CalcAlignOffsets(lo_DocState *state, LO_TextInfo *text_info, intn alignment, - int32 width, int32 height, int16 *x_offset, int32 *y_offset, - int32 *line_inc, int32 *baseline_inc) -{ - *line_inc = 0; - *baseline_inc = 0; - switch (alignment) - { - case LO_ALIGN_CENTER: - *x_offset = 0; - /* - * Center after current text. - */ - /* - * If the image is shorter than the height - * of this line, just increase y_offset - * to get it centered. - */ - if (height < state->line_height) - { - *y_offset += ((state->line_height - height) - / 2); - } - /* - * Else for images taller than the line - * we will need to move all their - * baselines down, plus increase the rest - * of their lineheights to reflect the - * big centered image. - */ - else - { - *y_offset = 0; - *baseline_inc = (height - state->line_height) - / 2; - *line_inc = height - state->line_height - - *baseline_inc; - } - break; - case LO_ALIGN_NCSA_CENTER: - *x_offset = 0; - /* - * Center on baseline of current text. - */ - /* - * If the image centered on the baseline will not - * extend below or above the current line, - * just increase y_offset to get it centered. - */ - if (((height / 2) <= state->baseline)&& - ((height / 2) <= (state->line_height - - state->baseline))) - { - *y_offset = state->baseline - - (height / 2); - } - /* - * Else the image extends over the bottom, but - * not off the top. - */ - else if ((height / 2) <= state->baseline) - { - *y_offset = state->baseline - - (height / 2); - *line_inc = *y_offset + height - - state->line_height; - } - /* - * Else for images taller than the line - * we will need to move all their - * baselines down, plus and maybe increase the rest - * of their lineheights to reflect the - * big centered image. - */ - else - { - *y_offset = 0; - *baseline_inc = (height / 2) - state->baseline; - if ((state->baseline + (height / 2)) > - state->line_height) - { - *line_inc = state->baseline + - (height / 2) - - state->line_height; - } - } - break; - case LO_ALIGN_TOP: - *x_offset = 0; - /* - * Move the top of the image to the top of the - * last text placed. On negative offsets - * (such as at the start of a line) just - * start the image at the top. - */ - *y_offset = state->baseline - text_info->ascent; - if (*y_offset < 0) - { - *y_offset = 0; - } - - /* - * Top aligned images can easily hang down and make - * all the rest of the line taller. Set line_inc - * to properly increase the height of all previous - * elements. - */ - if ((*y_offset + height) > state->line_height) - { - *line_inc = *y_offset + height - - state->line_height; - } - break; - case LO_ALIGN_NCSA_TOP: - *x_offset = 0; - /* - * Move the top of the image to the top of the - * line. - */ - *y_offset = 0; - - /* - * Top aligned images can easily hang down and make - * all the rest of the line taller. Set line_inc - * to properly increase the height of all previous - * elements. - */ - if ((*y_offset + height) > state->line_height) - { - *line_inc = *y_offset + height - - state->line_height; - } - break; - case LO_ALIGN_BOTTOM: - *x_offset = 0; - /* - * Like centered images, images shorter than - * the line just get move with y_offset. - */ - if (height < state->line_height) - { - *y_offset = state->line_height - height; - } - /* - * Else since they are bottom aligned. - * they move everyone's baselines and can't - * change the height below the baseline. - */ - else - { - *y_offset = 0; - *baseline_inc = height - state->line_height; - } - break; - case LO_ALIGN_NCSA_BOTTOM: - case LO_ALIGN_BASELINE: - default: - *x_offset = 0; - /* - * Like centered images, images shorter than - * the baseline just get move with y_offset. - */ - if (height < state->baseline) - { - *y_offset = state->baseline - height; - } - /* - * Else since they are baseline aligned. - * they move everyone's baselines and can't - * change the height below the baseline. - */ - else - { - *y_offset = 0; - *baseline_inc = height - state->baseline; - } - break; - } -} - - -int32 -lo_ValueOrPercent(char *str, Bool *is_percent) -{ - int32 val; - char *tptr; - - *is_percent = FALSE; - - if (str == NULL) - { - return(0); - } - - tptr = str; - while (*tptr != '\0') - { - if (*tptr == '%') - { - *is_percent = TRUE; - *tptr = '\0'; - break; - } - tptr++; - } - val = XP_ATOI(str); - if (*is_percent) - *tptr = '%'; /* Restore original string */ - return(val); -} - - -void -lo_SetElementTextAttr(LO_Element *element, LO_TextAttr *attr) -{ - switch(element->type) - { - case LO_TEXT: - element->lo_text.text_attr = attr; - break; - - case LO_IMAGE: - element->lo_image.text_attr = attr; - break; - - case LO_SUBDOC: - element->lo_subdoc.text_attr = attr; - break; - - case LO_LINEFEED: - element->lo_linefeed.text_attr = attr; - break; - - case LO_FORM_ELE: - element->lo_form.text_attr = attr; - break; - - case LO_BULLET: - element->lo_bullet.text_attr = attr; - break; - - default: - XP_ASSERT(0); - } -} - -LO_TextAttr * -lo_GetElementTextAttr(LO_Element *element) -{ - switch(element->type) - { - case LO_TEXT: - return element->lo_text.text_attr; - - case LO_IMAGE: - return element->lo_image.text_attr; - - case LO_SUBDOC: - return element->lo_subdoc.text_attr; - - case LO_LINEFEED: - return element->lo_linefeed.text_attr; - - case LO_FORM_ELE: - return element->lo_form.text_attr; - - case LO_BULLET: - return element->lo_bullet.text_attr; - - default: - return NULL; - } -} - -void -lo_CopyTextAttr(LO_TextAttr *old_attr, LO_TextAttr *new_attr) -{ - if ((old_attr == NULL)||(new_attr == NULL)) - { - return; - } - - new_attr->size = old_attr->size; - new_attr->fontmask = old_attr->fontmask; - - new_attr->fg.red = old_attr->fg.red; - new_attr->fg.green = old_attr->fg.green; - new_attr->fg.blue = old_attr->fg.blue; - - new_attr->bg.red = old_attr->bg.red; - new_attr->bg.green = old_attr->bg.green; - new_attr->bg.blue = old_attr->bg.blue; - - new_attr->no_background = old_attr->no_background; - new_attr->attrmask = old_attr->attrmask; - new_attr->font_face = old_attr->font_face; - /* - * FE_Data is not copied, it belongs to the FE, - * And will need to be generated by the FE the first time this - * new TextAttr is used. - */ - new_attr->FE_Data = NULL; - - new_attr->charset = old_attr->charset; - new_attr->point_size = old_attr->point_size; - new_attr->font_weight = old_attr->font_weight; -} - -LO_TextAttr * -lo_NewCopyTextAttr(lo_DocState *state, LO_TextAttr *old_attr) -{ - LO_TextAttr *new_attr; - LO_TextAttr **text_attr_hash; - int32 hash_index; - - hash_index = (old_attr->fontmask & old_attr->attrmask) % FONT_HASH_SIZE; - - XP_LOCK_BLOCK(text_attr_hash, LO_TextAttr **, - state->top_state->text_attr_hash); - new_attr = XP_NEW_ZAP(LO_TextAttr); - if (new_attr != NULL) - { - lo_CopyTextAttr(old_attr, new_attr); - new_attr->next = text_attr_hash[hash_index]; - text_attr_hash[hash_index] = new_attr; - new_attr->refcnt = 1; - } - else - { - state->top_state->out_of_memory = TRUE; - } - XP_UNLOCK_BLOCK(state->top_state->text_attr_hash); - return new_attr; -} - -LO_TextAttr * -lo_FetchTextAttr(lo_DocState *state, LO_TextAttr *old_attr) -{ - LO_TextAttr **text_attr_hash; - LO_TextAttr *attr_ptr; - int32 hash_index; - - if (old_attr == NULL) - { - return(NULL); - } - - hash_index = (old_attr->fontmask & old_attr->attrmask) % FONT_HASH_SIZE; - - XP_LOCK_BLOCK(text_attr_hash, LO_TextAttr **, - state->top_state->text_attr_hash); - attr_ptr = text_attr_hash[hash_index]; - - while (attr_ptr != NULL) - { - if ((attr_ptr->size == old_attr->size)&& - (attr_ptr->fontmask == old_attr->fontmask)&& - (attr_ptr->attrmask == old_attr->attrmask)&& - (attr_ptr->fg.red == old_attr->fg.red)&& - (attr_ptr->fg.green == old_attr->fg.green)&& - (attr_ptr->fg.blue == old_attr->fg.blue)&& - (attr_ptr->bg.red == old_attr->bg.red)&& - (attr_ptr->bg.green == old_attr->bg.green)&& - (attr_ptr->bg.blue == old_attr->bg.blue)&& - (attr_ptr->font_face == old_attr->font_face)&& - (attr_ptr->charset == old_attr->charset)&& - (attr_ptr->point_size == old_attr->point_size)&& - (attr_ptr->font_weight == old_attr->font_weight) -#ifdef DOM - && (state->in_span == FALSE) /* Never reuse text attrs in SPANS */ -#endif - ) - { - attr_ptr->refcnt++; - break; - } - attr_ptr = attr_ptr->next; - } - if (attr_ptr == NULL) - { - LO_TextAttr *new_attr; - new_attr = lo_NewCopyTextAttr(state, old_attr); - attr_ptr = new_attr; - } - - XP_UNLOCK_BLOCK(state->top_state->text_attr_hash); - return(attr_ptr); -} - - -void -lo_AddMarginStack(lo_DocState *state, int32 x, int32 y, - int32 width, int32 height, - int32 border_width, - int32 border_vert_space, int32 border_horiz_space, - intn alignment) -{ - lo_MarginStack *mptr; - - mptr = XP_NEW(lo_MarginStack); - if (mptr == NULL) - { - state->top_state->out_of_memory = TRUE; - return; - } - - mptr->y_min = y; - if (y >= 0) - { - mptr->y_max = y + height + (2 * border_width) + - (2 * border_vert_space); - } - else - { - mptr->y_max = height + (2 * border_width) + - (2 * border_vert_space); - } - - if (alignment == LO_ALIGN_RIGHT) - { - if (state->right_margin_stack == NULL) - { - mptr->margin = state->right_margin - width - - (2 * border_width) - (2 * border_horiz_space); - } - else - { - mptr->margin = state->right_margin_stack->margin - - width - (2 * border_width) - - (2 * border_horiz_space); - } - mptr->next = state->right_margin_stack; - state->right_margin_stack = mptr; - } - else - { - mptr->margin = state->left_margin + width + - (2 * border_width) + (2 * border_horiz_space); - mptr->next = state->left_margin_stack; - state->left_margin_stack = mptr; - } -} - - -/* - * When clipping lines we have essentially scrolled the document up. - * Move the margin blocks up too. - */ -void -lo_ShiftMarginsUp(MWContext *context, lo_DocState *state, int32 dy) -{ - lo_MarginStack *mptr; - int32 y; - - mptr = state->left_margin_stack; - while (mptr != NULL) - { - y = mptr->y_min - dy; - if (y < 0) - { - y = 0; - } - mptr->y_min = y; - - y = mptr->y_max - dy; - if (y < 0) - { - y = 0; - } - mptr->y_max = y; - mptr = mptr->next; - } - - mptr = state->right_margin_stack; - while (mptr != NULL) - { - y = mptr->y_min - dy; - if (y < 0) - { - y = 0; - } - mptr->y_min = y; - - y = mptr->y_max - dy; - if (y < 0) - { - y = 0; - } - mptr->y_max = y; - mptr = mptr->next; - } -} - - -void -lo_ClearToLeftMargin(MWContext *context, lo_DocState *state) -{ - lo_MarginStack *mptr; - int32 y; - - mptr = state->left_margin_stack; - if (mptr == NULL) - { - return; - } - y = state->y; - - if (mptr->y_max > y) - { - y = mptr->y_max; - } - while (mptr->next != NULL) - { - lo_MarginStack *margin; - - if (mptr->y_max > y) - { - y = mptr->y_max; - } - margin = mptr; - mptr = mptr->next; - XP_DELETE(margin); - } - XP_DELETE(mptr); - state->y = y; - state->left_margin_stack = NULL; - state->left_margin = state->win_left; - state->x = state->left_margin; - - /* - * Find where we hit the right margin, popping old - * obsolete elements as we go. - */ - mptr = state->right_margin_stack; - while ((mptr != NULL)&&(state->y > mptr->y_max)) - { - lo_MarginStack *margin; - - margin = mptr; - mptr = mptr->next; - XP_DELETE(margin); - } - if (mptr != NULL) - { - state->right_margin_stack = mptr; - state->right_margin = mptr->margin; - } - else - { - state->right_margin_stack = NULL; - state->right_margin = (state->list_stack != NULL) - ? state->list_stack->old_right_margin - : 0; - } -} - - -void -lo_ClearToRightMargin(MWContext *context, lo_DocState *state) -{ - lo_MarginStack *mptr; - int32 y; - - mptr = state->right_margin_stack; - if (mptr == NULL) - { - return; - } - y = state->y; - - if (mptr->y_max > y) - { - y = mptr->y_max; - } - while (mptr->next != NULL) - { - lo_MarginStack *margin; - - if (mptr->y_max > y) - { - y = mptr->y_max; - } - margin = mptr; - mptr = mptr->next; - XP_DELETE(margin); - } - XP_DELETE(mptr); - state->y = y; - state->right_margin_stack = NULL; - state->right_margin = state->win_width - state->win_right; - - /* - * Find where we hit the left margin, popping old - * obsolete elements as we go. - */ - mptr = state->left_margin_stack; - while ((mptr != NULL)&&(state->y > mptr->y_max)) - { - lo_MarginStack *margin; - - margin = mptr; - mptr = mptr->next; - XP_DELETE(margin); - } - if (mptr != NULL) - { - state->left_margin_stack = mptr; - state->left_margin = mptr->margin; - } - else - { - state->left_margin_stack = NULL; - state->left_margin = (state->list_stack != NULL) - ? state->list_stack->old_left_margin - : 0; - } -} - - -void -lo_ClearToBothMargins(MWContext *context, lo_DocState *state) -{ - lo_MarginStack *mptr; - int32 y; - - y = state->y; - - mptr = state->right_margin_stack; - if (mptr != NULL) - { - if (mptr->y_max > y) - { - y = mptr->y_max; - } - while (mptr->next != NULL) - { - lo_MarginStack *margin; - - if (mptr->y_max > y) - { - y = mptr->y_max; - } - margin = mptr; - mptr = mptr->next; - XP_DELETE(margin); - } - XP_DELETE(mptr); - state->y = y; - state->right_margin_stack = NULL; - - state->right_margin = state->win_width - state->win_right; - } - - mptr = state->left_margin_stack; - if (mptr != NULL) - { - if (mptr->y_max > y) - { - y = mptr->y_max; - } - while (mptr->next != NULL) - { - lo_MarginStack *margin; - - if (mptr->y_max > y) - { - y = mptr->y_max; - } - margin = mptr; - mptr = mptr->next; - XP_DELETE(margin); - } - XP_DELETE(mptr); - if (y > state->y) - { - state->y = y; - } - state->left_margin_stack = NULL; - - state->left_margin = state->win_left; - state->x = state->left_margin; - } -} - - -void -lo_FindLineMargins(MWContext *context, lo_DocState *state, Bool updateFE) -{ - lo_MarginStack *mptr; - LO_Element *eptr; - - eptr = state->float_list; - /* - while ((eptr != NULL)&&(eptr->lo_any.y < 0)) - */ - while (eptr != NULL) - { - LO_Element *next_eptr = NULL; - - if (eptr->lo_any.y < 0) - { - int32 expose_y; - int32 expose_height; - /* LO_Element *next_eptr; */ - - next_eptr = NULL; - /* - * Float the y to our current position. - */ - eptr->lo_any.y = state->y; - - /* - * These get coppied into special variables because they - * may get changed by a table in the floating list. - */ - expose_y = eptr->lo_any.y; - expose_height = eptr->lo_any.height; - - /* - * Special case: If we have just placed a TABLE element, - * we need to properly offset all the CELLs inside it. - */ - if (eptr->type == LO_TABLE) - { - int32 y2; - int32 change_y; - LO_Element *tptr; - - /* - * We need to know the bottom and top extents of - * the table to know big an area to refresh. - */ - y2 = expose_y + eptr->lo_any.y_offset + expose_height; - - /* - * This is how far to move the cells based on - * where the table thought it was placed. - */ - change_y = state->y - eptr->lo_table.expected_y; - - /* - * set tptr to the start of the cell list. - */ - tptr = eptr->lo_any.next; - while ((tptr != NULL)&&(tptr->type == LO_CELL)) - { - /* - * Only do this work if the table has moved. - */ - if (change_y != 0) - { - tptr->lo_any.y += change_y; - lo_ShiftCell((LO_CellStruct *)tptr, - 0, change_y); - } - - /* - * Find upper and lower bounds of the - * cells. - */ - if (tptr->lo_any.y < expose_y) - { - expose_y = tptr->lo_any.y; - } - if ((tptr->lo_any.y + tptr->lo_any.y_offset + - tptr->lo_any.height) > y2) - { - y2 = tptr->lo_any.y + - tptr->lo_any.y_offset + - tptr->lo_any.height; - } - - tptr = tptr->lo_any.next; - } - - /* - * Whatever is after all the table cells will - * really be the next eptr. - */ - if (tptr != NULL) - { - next_eptr = tptr; - } - - /* - * Adjust exposed area height for lower bound. - * Upper bound already possibly moved. - */ - if ((y2 - expose_y - eptr->lo_any.y_offset) > - expose_height) - { - expose_height = y2 - expose_y - - eptr->lo_any.y_offset; - } - } - - if (updateFE) - { - /* - * We may have been blocking display on this floating image. - * If so deal with it here. - */ - if ((state->display_blocked != FALSE)&& - (state->is_a_subdoc == SUBDOC_NOT)&& - (state->display_blocking_element_y == 0)&& - (state->display_blocking_element_id != -1)&& - (eptr->lo_any.ele_id >= - state->display_blocking_element_id)) - { - state->display_blocking_element_y = - state->y; - /* - * Special case, if the blocking element - * is on the first line, no blocking - * at all needs to happen. - */ - if (state->y == state->win_top) - { - state->display_blocked = FALSE; - FE_SetDocPosition(context, - FE_VIEW, 0, state->base_y); - - if (context->compositor) - { - XP_Rect rect; - - rect.left = 0; - rect.top = 0; - rect.right = state->win_width; - rect.bottom = state->win_height; - CL_UpdateDocumentRect(context->compositor, - &rect, (PRBool)FALSE); - } - } - } - - } /* end if (updateFE) */ - - - - if (context->compositor) - { - XP_Rect rect; - - rect.left = eptr->lo_any.x + eptr->lo_any.x_offset; - rect.top = expose_y + eptr->lo_any.y_offset; - rect.right = rect.left + eptr->lo_any.width; - rect.bottom = rect.top + expose_height; - CL_UpdateDocumentRect(context->compositor, - &rect, (PRBool)FALSE); - - } - - /* - * In case these floating elements are the only thing in the - * doc (or subdoc) we need to set the state min and max widths - * when we place them. - */ - { - int32 width; - XP_Rect rect; - - rect.left = 0; - rect.right = 0; - lo_GetElementBbox(eptr, &rect); - width = rect.right - rect.left; - if (width > 0) - { - if (width > state->min_width) - { - state->min_width = width; - } - - /* - * Only do this if not in a table - */ - if (state->is_a_subdoc == SUBDOC_NOT) - { - width += rect.left; - } - if (width > state->max_width) - { - state->max_width = width; - } - } - - } - /* - eptr = eptr->lo_any.next; - */ - /* - * If we are skipping a table's cells, set eptr - * properly now. - */ - /* - if (next_eptr != NULL) - { - eptr = next_eptr; - } - */ - } /* End if (eptr->lo_any.y < 0) */ - - eptr = eptr->lo_any.next; - - /* - * If we are skipping a table's cells, set eptr - * properly now. - */ - if (next_eptr != NULL) - { - eptr = next_eptr; - } - } /* End while */ - - /* - * Find floating elements just added to the left margin stack - * from the last line, and set their absolute - * coordinates. - */ - mptr = state->left_margin_stack; - while ((mptr != NULL)&&(mptr->y_min < 0)) - { - mptr->y_min = state->y; - mptr->y_max = mptr->y_min + mptr->y_max; - mptr = mptr->next; - } - - /* - * Find where we hit the left margin, popping old - * obsolete elements as we go. - */ - mptr = state->left_margin_stack; - while ((mptr != NULL)&&(state->y > mptr->y_max)) - { - lo_MarginStack *margin; - - margin = mptr; - mptr = mptr->next; - XP_DELETE(margin); - } - if (mptr != NULL) - { - state->left_margin_stack = mptr; - state->left_margin = mptr->margin; - /* - * For a list wrapped around a floating image we may - * need to be indented from the image edge. - */ - if (state->list_stack->old_left_margin > mptr->margin) - { - state->left_margin = state->list_stack->old_left_margin; - } - } - else - { - state->left_margin_stack = NULL; - state->left_margin = (state->list_stack != NULL) - ? state->list_stack->old_left_margin - : 0; - } - - /* - * Find floating elements just added to the right margin stack - * from the last line, and set their absolute - * coordinates. - */ - mptr = state->right_margin_stack; - while ((mptr != NULL)&&(mptr->y_min < 0)) - { - mptr->y_min = state->y; - mptr->y_max = mptr->y_min + mptr->y_max; - mptr = mptr->next; - } - - /* - * Find where we hit the right margin, popping old - * obsolete elements as we go. - */ - mptr = state->right_margin_stack; - while ((mptr != NULL)&&(state->y > mptr->y_max)) - { - lo_MarginStack *margin; - - margin = mptr; - mptr = mptr->next; - XP_DELETE(margin); - } - if (mptr != NULL) - { - state->right_margin_stack = mptr; - state->right_margin = mptr->margin; - } - else - { - state->right_margin_stack = NULL; - state->right_margin = (state->list_stack != NULL) - ? state->list_stack->old_right_margin - : 0; - } -} - -void -lo_RecycleElements(MWContext *context, lo_DocState *state, LO_Element *elements) -{ - LO_Element *eptr; - - if (elements == NULL) - { - return; - } - - eptr = elements; - while(eptr->lo_any.next != NULL) - { - lo_ScrapeElement(context, eptr, TRUE); - eptr = eptr->lo_any.next; - } - lo_ScrapeElement(context, eptr, TRUE); -#ifdef MEMORY_ARENAS - if ( EDT_IS_EDITOR(context) ) { - eptr->lo_any.next = state->top_state->recycle_list; - state->top_state->recycle_list = elements; - } -#else - eptr->lo_any.next = state->top_state->recycle_list; - state->top_state->recycle_list = elements; -#endif /* MEMORY_ARENAS */ -} - - -LO_Element * -lo_NewElement(MWContext *context, lo_DocState *state, intn type, - ED_Element *edit_element, intn edit_offset) -{ - LO_Element *eptr; - -#ifdef MEMORY_ARENAS - int32 size; - - switch(type) - { - case LO_TEXT: - size = sizeof(LO_TextStruct); - break; - case LO_LINEFEED: - size = sizeof(LO_LinefeedStruct); - break; - case LO_HRULE: - size = sizeof(LO_HorizRuleStruct); - break; - case LO_IMAGE: - size = sizeof(LO_ImageStruct); - break; - case LO_BULLET: - size = sizeof(LO_BulletStruct); - break; - case LO_FORM_ELE: - size = sizeof(LO_FormElementStruct); - break; - case LO_SUBDOC: - size = sizeof(LO_SubDocStruct); - break; - case LO_TABLE: - size = sizeof(LO_TableStruct); - break; - case LO_BUILTIN: - size = sizeof(LO_BuiltinStruct); - break; - case LO_CELL: - size = sizeof(LO_CellStruct); - break; - case LO_EMBED: - size = sizeof(LO_EmbedStruct); - break; -#ifdef JAVA - case LO_JAVA: - size = sizeof(LO_JavaAppStruct); - break; -#endif - case LO_EDGE: - size = sizeof(LO_EdgeStruct); - break; - case LO_OBJECT: - size = sizeof(LO_ObjectStruct); - break; - case LO_PARAGRAPH: - size = sizeof(LO_ParagraphStruct); - break; - case LO_CENTER: - size = sizeof(LO_CenterStruct); - break; - case LO_MULTICOLUMN: - size = sizeof(LO_MulticolumnStruct); - break; - case LO_TEXTBLOCK: - size = sizeof(LO_TextBlock); - break; - case LO_LIST: - size = sizeof(LO_ListStruct); - break; - case LO_DESCTITLE: - size = sizeof(LO_DescTitleStruct); - break; - case LO_DESCTEXT: - size = sizeof(LO_DescTextStruct); - break; - case LO_BLOCKQUOTE: - size = sizeof(LO_BlockQuoteStruct); - break; - case LO_LAYER: - size = sizeof(LO_LayerStruct); - break; - case LO_HEADING: - size = sizeof(LO_HeadingStruct); - break; - case LO_SPAN: - size = sizeof(LO_SpanStruct); - break; - case LO_DIV: - size = sizeof(LO_DivStruct); - break; - case LO_SPACER: - size = sizeof(LO_SpacerStruct); - break; - case LO_FLOAT: - size = sizeof(LO_FloatStruct); - break; - case LO_SUPER: - size = sizeof(LO_SuperStruct); - break; - case LO_SUB: - size = sizeof(LO_SubStruct); - break; - default: - size = sizeof(LO_Any); - break; - } - if ( ! EDT_IS_EDITOR(context) ) { - eptr = (LO_Element *)lo_MemoryArenaAllocate(state->top_state, size); - } - else { - if (state->top_state->recycle_list != NULL) - { - eptr = state->top_state->recycle_list; - state->top_state->recycle_list = eptr->lo_any.next; - } - else - { - eptr = XP_NEW_ZAP(LO_Element); - } - } -#else - - /* sorry about all the asserts, in my debug version somehow state - * becomes nil after a malloc failure. */ -#ifdef DEBUG - assert (state); -#endif - - if (state->top_state->recycle_list != NULL) - { - eptr = state->top_state->recycle_list; - state->top_state->recycle_list = eptr->lo_any.next; - } - else - { - eptr = XP_NEW(LO_Element); -#ifdef DEBUG - assert (state); -#endif - } -#endif /* MEMORY_ARENAS */ - - if (eptr == NULL) - { -#ifdef DEBUG - assert (state); -#endif - state->top_state->out_of_memory = TRUE; - } - else - { -#ifdef DOM - eptr->lo_any.node = NULL; -#endif - eptr->lo_any.width = 0; - eptr->lo_any.height = 0; - eptr->lo_any.x_offset = 0; - eptr->lo_any.y_offset = 0; - eptr->lo_any.x = 0; - eptr->lo_any.y = 0; - eptr->lo_any.line_height = 0; - - eptr->lo_any.next = NULL; - eptr->lo_any.prev = NULL; -#ifdef EDITOR - eptr->lo_any.edit_element = NULL; - eptr->lo_any.edit_offset = 0; - - if( EDT_IS_EDITOR(context) ) - { - /* if( lo_EditableElement( type ) ) Change from toshok: */ - if( lo_EditableElement( type ) && type != LO_LINEFEED ) - { - if( edit_element == 0 ){ - edit_element = state->edit_current_element; - edit_offset = state->edit_current_offset; - } - EDT_SetLayoutElement( edit_element, - edit_offset, - type, - eptr ); - } - } - state->edit_force_offset = FALSE; -#endif - } - - return(eptr); -} - - -/* Add a named anchor to the global list of named anchors. This does not - associate the anchor with a layout element. lo_SetNamedAnchor should be - followed by a call to lo_BindNamedAnchorToElement in order to associate - the named anchor with a layout element. */ -Bool -lo_SetNamedAnchor(lo_DocState *state, PA_Block name) -{ - lo_NameList *name_rec = NULL; - lo_DocLists *doc_lists; - - /* - * No named anchors are allowed within a - * hacked scrolling content layout document. - */ - if (state->top_state->scrolling_doc != FALSE) - { - if (name != NULL) - { - PA_FREE(name); - } - return FALSE; - } - - doc_lists = lo_GetCurrentDocLists(state); - - if (state->in_relayout) { - /* Look for the old lo_NameList. Its mocha_object is still valid. */ - lo_NameList *name_list = doc_lists->name_list; - lo_NameList *prev; - Bool no_match; - char *s1, *s2; - - XP_ASSERT(name_list); /* If in relayout, this cannot be empty. */ - - prev = name_list; - name_rec = name_list; - while (name_rec != NULL) { - PA_LOCK(s1, char*, name); - PA_LOCK(s2, char*, name_rec->name); - no_match = XP_STRCMP(s1, s2); - PA_UNLOCK(name_rec->name); - PA_UNLOCK(name); - if (!no_match) { - if (name_rec == name_list) - doc_lists->name_list = name_list->next; - else - prev->next = name_rec->next; - PA_FREE(name_rec->name); /* No need for this, use new one. */ - break; - } - prev = name_rec; - name_rec = name_rec->next; - } - } - if (!name_rec || !state->in_relayout) { - name_rec = XP_NEW(lo_NameList); - if (name_rec == NULL) - { - state->top_state->out_of_memory = TRUE; - PA_FREE(name); - return FALSE; - } - name_rec->mocha_object = NULL; - } - name_rec->x = 0; - name_rec->y = 0; - name_rec->name = name; - name_rec->element = NULL; /* Set by lo_BindNamedAnchorToElement. */ - - name_rec->next = doc_lists->name_list; - doc_lists->name_list = name_rec; - return TRUE; -} - -/* Associate a named anchor with a layout element. The named anchor should - be the first one in the list of named anchors.*/ -Bool -lo_BindNamedAnchorToElement(lo_DocState *state, PA_Block name, - LO_Element *element) -{ - Bool no_match; - LO_Element *eptr; - lo_NameList *name_rec; - char *s1, *s2; - lo_DocLists *doc_lists; - - doc_lists = lo_GetCurrentDocLists(state); - - if (element == NULL) - { - if (state->line_list == NULL) - { - eptr = state->end_last_line; - } - else - { - eptr = state->line_list; - while (eptr->lo_any.next != NULL) - { - eptr = eptr->lo_any.next; - } - } - } - else - { - eptr = element; - } - - /* Find the matching name_rec in the name_list */ - name_rec = doc_lists->name_list; - PA_LOCK(s1, char*, name); - while (name_rec != NULL) - { - PA_LOCK(s2, char*, name_rec->name); - no_match = XP_STRCMP(s1, s2); - PA_UNLOCK(name_rec->name); - if (!no_match) - break; - name_rec = name_rec->next; - } - PA_UNLOCK(name); - if (name_rec == NULL) - return FALSE; - - if (eptr == NULL) - { - name_rec->x = 0; - name_rec->y = 0; - } - else - { - name_rec->x = eptr->lo_any.x; - name_rec->y = eptr->lo_any.y; - } - - name_rec->element = eptr; - return TRUE; -} - - -#ifdef DOM -/* Add a named span to the global list of named spans. This does not - associate the span with a layout element. lo_SetNamedSpan should be - followed by a call to lo_BindNamedSpanToElement in order to associate - the named span with a layout element. */ -Bool -lo_SetNamedSpan(lo_DocState *state, PA_Block id) -{ - lo_NameList *name_rec = NULL; - lo_DocLists *doc_lists; - - /* - * No named spans are allowed within a - * hacked scrolling content layout document. - */ - if (state->top_state->scrolling_doc != FALSE) - { - if (id != NULL) - { - PA_FREE(id); - } - return FALSE; - } - - doc_lists = lo_GetCurrentDocLists(state); - - if (state->in_relayout) { - /* Look for the old lo_NameList. Its mocha_object is still valid. */ - lo_NameList *span_list = doc_lists->span_list; - lo_NameList *prev; - Bool no_match; - char *s1, *s2; - - XP_ASSERT(span_list); /* If in relayout, this cannot be empty. */ - - prev = span_list; - name_rec = span_list; - while (name_rec != NULL) { - PA_LOCK(s1, char*, id); - PA_LOCK(s2, char*, name_rec->name); - no_match = XP_STRCMP(s1, s2); - PA_UNLOCK(name_rec->name); - PA_UNLOCK(id); - if (!no_match) { - if (name_rec == span_list) - doc_lists->span_list = span_list->next; - else - prev->next = name_rec->next; - PA_FREE(name_rec->name); /* No need for this, use new one. */ - break; - } - prev = name_rec; - name_rec = name_rec->next; - } - } - if (!name_rec || !state->in_relayout) { - name_rec = XP_NEW(lo_NameList); - if (name_rec == NULL) - { - state->top_state->out_of_memory = TRUE; - PA_FREE(id); - return FALSE; - } - name_rec->mocha_object = NULL; - } - name_rec->x = 0; - name_rec->y = 0; - name_rec->name = id; - name_rec->element = NULL; /* Set by lo_BindNamedSpanToElement. */ - - name_rec->next = doc_lists->span_list; - doc_lists->span_list = name_rec; - return TRUE; -} - -/* Associate a named span with a layout element. The named span should - be the first one in the list of named spans.*/ -Bool -lo_BindNamedSpanToElement(lo_DocState *state, PA_Block name, - LO_Element *element) -{ - Bool no_match; - LO_Element *eptr; - lo_NameList *name_rec; - char *s1, *s2; - lo_DocLists *doc_lists; - - doc_lists = lo_GetCurrentDocLists(state); - - if (element == NULL) - { - if (state->line_list == NULL) - { - eptr = state->end_last_line; - } - else - { - eptr = state->line_list; - while (eptr->lo_any.next != NULL) - { - eptr = eptr->lo_any.next; - } - } - } - else - { - eptr = element; - } - - /* Find the matching name_rec in the span_list */ - name_rec = doc_lists->span_list; - PA_LOCK(s1, char*, name); - while (name_rec != NULL) - { - PA_LOCK(s2, char*, name_rec->name); - no_match = XP_STRCMP(s1, s2); - PA_UNLOCK(name_rec->name); - if (!no_match) - break; - name_rec = name_rec->next; - } - PA_UNLOCK(name); - if (name_rec == NULL) - return FALSE; - - if (eptr == NULL) - { - name_rec->x = 0; - name_rec->y = 0; - } - else - { - name_rec->x = eptr->lo_any.x; - name_rec->y = eptr->lo_any.y; - } - - name_rec->element = eptr; - return TRUE; -} -#endif /* DOM */ - -void -lo_AddNameList(lo_DocState *state, lo_DocState *old_state) -{ -/* - * Now named anchors are added directly to the - * top_state (or layer's) name_list, so we don't have to push - * them up. We do, however, need to update their positions, - * though it seems like this is done at the end of table - * processing. Hence this code is no longer necessary. - */ -#if 0 - lo_NameList *name_list; - lo_NameList *nptr; - - name_list = old_state->name_list; - while (name_list != NULL) - { - /* - * Extract the current record from the list. - */ - nptr = name_list; - name_list = name_list->next; - - /* - * The element almost certainly has been moved - * from subdoc to main cell, correct its position. - */ - if (nptr->element != NULL) - { - nptr->x = nptr->element->lo_any.x; - nptr->y = nptr->element->lo_any.y; - } - - /* - * Stick it into the main name list. - */ - nptr->next = state->name_list; - state->name_list = nptr; - } - old_state->name_list = name_list; -#endif /* 0 */ -} - - -void -lo_CheckNameList(MWContext *context, lo_DocState *state, int32 min_id) -{ - lo_NameList *nptr; - lo_DocLists *doc_lists; - - /* - * Positions of named elements are only accurate if - * we are not in a nested subdoc. - */ - if (state->is_a_subdoc != SUBDOC_NOT) - { - return; - } - - doc_lists = lo_GetCurrentDocLists(state); - - nptr = doc_lists->name_list; - while (nptr != NULL) - { - /* - * If the element's id is greater - * than the passed minimum, then - * the element almost certainly has been moved - * during table processing, - * correct its position. - */ - if ((nptr->element != NULL)&& - (nptr->element->lo_any.ele_id > min_id)) - { - nptr->x = nptr->element->lo_any.x; - nptr->y = nptr->element->lo_any.y; - } - - /* - * If we are blocked on a named element. - * Check if this name is one we are waiting on. - */ - if ((state->display_blocking_element_id == -1)&& - (nptr->name != NULL)) - { - char *name; - - PA_LOCK(name, char *, nptr->name); - if (XP_STRCMP(name, - (char *)(state->top_state->name_target + 1)) == 0) - { - XP_FREE(state->top_state->name_target); - state->top_state->name_target = NULL; - if (nptr->element != NULL) - { - state->display_blocking_element_id = - nptr->element->lo_any.ele_id; - } - else - { - state->display_blocking_element_id = - state->top_state->element_id; - } - /* - * If the display is blocked for an element - * we havn't reached yet, check to see if - * it is in this line, and if so, save its - * y position. - */ - if ((state->display_blocked != FALSE)&& - (state->is_a_subdoc == SUBDOC_NOT)&& - (state->display_blocking_element_y == 0)&& - (state->display_blocking_element_id != -1)) - { - state->display_blocking_element_y = nptr->y; - } - PA_UNLOCK(nptr->name); - } - else - { - PA_UNLOCK(nptr->name); - } - } - - nptr = nptr->next; - } -} - -#if DOM -extern char *element_names[]; - -/* Wire the element to the DOM Node data for DOM-driven feedback. */ -void -lo_SetNodeElement(lo_DocState *state, LO_Element *element) -{ - LO_Element *eptr; - DOM_Node *node = ACTIVE_NODE(state); - -#ifdef DEBUG_shaver - if (!node) - fprintf(stderr, "NULL node\n"); - else if (node->type == NODE_TYPE_DOCUMENT) - fprintf(stderr, "NODE_TYPE_DOCUMENT node\n"); -#endif - if (!node || node->type == NODE_TYPE_DOCUMENT) - return; - XP_ASSERT(!ELEMENT_PRIV(node)->ele_end); -#ifdef DEBUG_shaver - if (ELEMENT_PRIV(node)->ele_end) { - fprintf(stderr, "lo_SetNodeElement: node %s has end already!\n", - node->type == NODE_TYPE_TEXT ? "text" : - ((DOM_Element *)node)->tagName); - } -#endif - eptr = ELEMENT_PRIV(node)->ele_start; - if (!eptr) { - /* this the first element for this node, so mark it */ - ELEMENT_PRIV(node)->ele_start = element; - } -#ifdef DEBUG_shaver_verbose - if (element->lo_any.node) - fprintf(stderr, "element %p (type %d) already has node %x\n", - element, element->lo_any.type, element->lo_any.node); -#endif - element->lo_any.node = node; -} -#endif - -void -lo_AppendToLineList(MWContext *context, lo_DocState *state, - LO_Element *element, int32 baseline_inc) -{ - LO_Element *eptr; - -#ifdef DOM - if (state->in_span) - { - lo_SetInSpanAttribute( element ); - } - - if (state->current_span != NULL) - { - if (!lo_BindNamedSpanToElement(state, state->current_span, - element)) - { - XP_ASSERT(FALSE); - } - state->current_span = NULL; - } - - lo_SetNodeElement(state, element); -#endif - - if (state->current_named_anchor != NULL) { - if (!lo_BindNamedAnchorToElement(state, state->current_named_anchor, - element)) { - XP_ASSERT(FALSE); - } - state->current_named_anchor = NULL; - } - else if (state->current_anchor) { - state->current_anchor->element = element; - } - - element->lo_any.next = NULL; - element->lo_any.prev = NULL; - eptr = state->line_list; - if (eptr == NULL) - { - state->line_list = element; - } - else - { - while (eptr->lo_any.next != NULL) - { - eptr->lo_any.y_offset += baseline_inc; - eptr = eptr->lo_any.next; - } - eptr->lo_any.y_offset += baseline_inc; - eptr->lo_any.next = element; - element->lo_any.prev = eptr; - } -} - -void -lo_SetLineArrayEntry(lo_DocState *state, LO_Element *eptr, int32 line) -{ - LO_Element **line_array; - -#ifdef XP_WIN16 - intn a_size; - intn a_indx; - intn a_line; - XP_Block *larray_array; -#endif /* XP_WIN16 */ - - if ((line < 0) || (line >= (state->line_num - 1))) - { - return; - } - -#ifdef XP_WIN16 - a_size = SIZE_LIMIT / sizeof(LO_Element *); - a_indx = (intn)(line / a_size); - a_line = (intn)(line - (a_indx * a_size)); - - XP_LOCK_BLOCK(larray_array, XP_Block *, state->larray_array); - state->line_array = larray_array[a_indx]; - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array); - line_array[a_line] = eptr; - - XP_UNLOCK_BLOCK(state->line_array); - XP_UNLOCK_BLOCK(state->larray_array); -#else - XP_LOCK_BLOCK(line_array, LO_Element **, state->line_array); - line_array[line] = eptr; - XP_UNLOCK_BLOCK(state->line_array); -#endif /* XP_WIN16 */ -} - -#define POSITIVE_SCALE_FACTOR 1.10 /* 10% */ -#define NEGATIVE_SCALE_FACTOR .90 /* 10% */ - - -/* - * Return the scaling percentage given a font scaler - * - */ -double -LO_GetScalingFactor(int32 scaler) -{ - double scale=1.0; - double mult; - int32 count; - - if(scaler < 0) - { - count = -scaler; - mult = NEGATIVE_SCALE_FACTOR; - } - else - { - count = scaler; - mult = POSITIVE_SCALE_FACTOR; - } - - /* use the percentage scaling factor to the power of the pref */ - while(count--) - scale *= mult; - - return scale; -} - - -/* - * Return the width of the window for this context in chars in the default - * fixed width font. Return -1 on error. - */ -int16 -LO_WindowWidthInFixedChars(MWContext *context) -{ - int32 doc_id; - lo_TopState *top_state; - lo_DocState *state; - LO_TextInfo tmp_info; - LO_TextAttr tmp_attr; - LO_TextStruct tmp_text; - PA_Block buff; - char *str; - int32 width; - int16 char_cnt; - - /* - * Get the unique document ID, and retreive this - * documents layout state. - */ - doc_id = XP_DOCID(context); - top_state = lo_FetchTopState(doc_id); - if ((top_state == NULL)||(top_state->doc_state == NULL)) - { - return((int16)-1); - } - state = top_state->doc_state; - - /* - * Create a fake text buffer to measure an 'M'. - */ - memset (&tmp_text, 0, sizeof (tmp_text)); - buff = PA_ALLOC(1); - if (buff == NULL) - { - return((int16)-1); - } - PA_LOCK(str, char *, buff); - str[0] = 'M'; - PA_UNLOCK(buff); - tmp_text.text = buff; - tmp_text.text_len = 1; - - /* - * Fill in default fixed font information. - */ - lo_SetDefaultFontAttr(state, &tmp_attr, context); - tmp_attr.fontmask |= LO_FONT_FIXED; - tmp_text.text_attr = &tmp_attr; - - /* - * Get the width of that 'M' - */ - FE_GetTextInfo(context, &tmp_text, &tmp_info); - PA_FREE(buff); - - /* - * Error if bad character width - */ - if (tmp_info.max_width <= 0) - { - return((int16)-1); - } - - width = state->win_width - state->win_left - state->win_right; - char_cnt = (int16)(width / tmp_info.max_width); - return(char_cnt); -} - - -LO_Element * -lo_FirstElementOfLine(MWContext *context, lo_DocState *state, int32 line) -{ - LO_Element *eptr; - LO_Element **line_array; - - if ((line < 0)||(line > (state->line_num - 2))) - { - return(NULL); - } - -#ifdef XP_WIN16 - { - intn a_size; - intn a_indx; - intn a_line; - XP_Block *larray_array; - - a_size = SIZE_LIMIT / sizeof(LO_Element *); - a_indx = (intn)(line / a_size); - a_line = (intn)(line - (a_indx * a_size)); - XP_LOCK_BLOCK(larray_array, XP_Block *, - state->larray_array); - state->line_array = larray_array[a_indx]; - XP_LOCK_BLOCK(line_array, LO_Element **, - state->line_array); - eptr = line_array[a_line]; - XP_UNLOCK_BLOCK(state->line_array); - XP_UNLOCK_BLOCK(state->larray_array); - } -#else - { - XP_LOCK_BLOCK(line_array, LO_Element **, - state->line_array); - eptr = line_array[line]; - XP_UNLOCK_BLOCK(state->line_array); - } -#endif /* XP_WIN16 */ - return(eptr); -} - - -Bool -lo_FindMochaExpr(char *str, char **expr_start, char **expr_end) -{ - char *tptr; - char *start; - char *end; - - if (str == NULL) - { - return(FALSE); - } - - start = NULL; - end = NULL; - tptr = str; - while (*tptr != '\0') - { - if ((*tptr == '&')&&(*(char *)(tptr + 1) == '{')) - { - start = tptr; - break; - } - tptr++; - } - - if (start == NULL) - { - return(FALSE); - } - - tptr = (char *)(start + 2); - while (*tptr != '\0') - { - if ((*tptr == '}')&&(*(char *)(tptr + 1) == ';')) - { - end = tptr; - break; - } - tptr++; - } - - if (end == NULL) - { - return(FALSE); - } - - end = (char *)(end + 1); - *expr_start = start; - *expr_end = end; - return(TRUE); -} - - -static char * -lo_add_string(char *base, char *add) -{ - char *new; - int32 base_len, add_len; - - if (add == NULL) - { - return(base); - } - - if (base == NULL) - { - new = XP_STRDUP(add); - return(new); - } - - base_len = XP_STRLEN(base); - add_len = XP_STRLEN(add); - new = (char *)XP_ALLOC(base_len + add_len + 1); - if (new == NULL) - { - return(base); - } - - XP_STRCPY(new, base); - XP_STRCAT(new, add); - XP_FREE(base); - return(new); -} - - -static char * -lo_eval_javascript_entities(MWContext *context, char *orig_value, - uint newline_count) -{ - char *tptr; - char *str; - char *new_str; - int32 len; - char tchar; - Bool has_mocha; - char *start, *end; - - if (orig_value == NULL) - { - return(NULL); - } - - str = orig_value; - len = XP_STRLEN(str); - - new_str = NULL; - tptr = str; - has_mocha = lo_FindMochaExpr(tptr, &start, &end); - while (has_mocha != FALSE) - { - char *expr_start, *expr_end; - - if (start > tptr) - { - tchar = *start; - *start = '\0'; - new_str = lo_add_string(new_str, tptr); - *start = tchar; - } - - expr_start = (char *)(start + 2); - expr_end = (char *)(end - 1); - if (expr_end > expr_start) - { - char *eval_str; - - tchar = *expr_end; - *expr_end = '\0'; - eval_str = LM_EvaluateAttribute(context, expr_start, - newline_count + 1); - *expr_end = tchar; - new_str = lo_add_string(new_str, eval_str); - if (eval_str != NULL) - { - XP_FREE(eval_str); - } - } - - tptr = (char *)(end + 1); - has_mocha = lo_FindMochaExpr(tptr, &start, &end); - } - if (tptr != str) - { - new_str = lo_add_string(new_str, tptr); - } - - if (new_str == NULL) - { - new_str = str; - } - - return(new_str); -} - - -void -lo_ConvertAllValues(MWContext *context, char **value_list, int32 list_len, - uint newline_count) -{ - int32 i; - - if (LM_CanDoJS(context) == FALSE) - { - return; - } - - for (i=0; i < list_len; i++) - { - char *str; - char *new_str; - - str = value_list[i]; - if (str != NULL) - { - new_str = lo_eval_javascript_entities(context, str, newline_count); - if (new_str != str) - { - XP_FREE(str); - value_list[i] = new_str; - } - } - } -} - - -PA_Block -lo_FetchParamValue(MWContext *context, PA_Tag *tag, char *param_name) -{ - PA_Block buff; - INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo(context); - buff = PA_FetchParamValue(tag, param_name, INTL_GetCSIWinCSID(c)); - return(buff); -} - -#include "prthread.h" -#include "prmon.h" - -static PRMonitor * layout_lock_monitor = NULL; -static PRThread * layout_lock_owner = NULL; -static int layout_lock_count = 0; - -/* - * Grab the lock around layout so that we can delete things / manipulate - * layout owned data structures in a separate thread - */ -void -LO_LockLayout() -{ - if(!layout_lock_monitor) - layout_lock_monitor = PR_NewNamedMonitor("layout-lock"); - - PR_EnterMonitor(layout_lock_monitor); - - while(TRUE) { - - /* no current owner or owned by this thread */ - if(layout_lock_owner == NULL || - layout_lock_owner == PR_CurrentThread()) { - layout_lock_owner = PR_CurrentThread(); - layout_lock_count++; - - PR_ExitMonitor(layout_lock_monitor); - return; - } - - /* owned by someone else -- wait till we can get it */ - PR_Wait(layout_lock_monitor, PR_INTERVAL_NO_TIMEOUT); - - } -} - -/* - * Release the lock and wake up anyone who was waiting to get it if - * we are the last release of the lock from this thread - */ -void -LO_UnlockLayout() -{ - - PR_EnterMonitor(layout_lock_monitor); - -#ifdef DEBUG - /* make sure someone doesn't try to free a lock they don't own */ - XP_ASSERT(layout_lock_owner == PR_CurrentThread()); -#endif - - layout_lock_count--; - - if(layout_lock_count == 0) { - layout_lock_owner = NULL; - PR_Notify(layout_lock_monitor); - } - PR_ExitMonitor(layout_lock_monitor); - -} - - -/* - * A (debugging) way to make sure the current thread doesn't have the - * layout lock - */ -Bool -LO_VerifyUnlockedLayout() -{ -#ifdef DEBUG - Bool bHolding = TRUE; - - if (layout_lock_monitor) { - PR_EnterMonitor(layout_lock_monitor); - bHolding = (layout_lock_owner != PR_CurrentThread()); - PR_ExitMonitor(layout_lock_monitor); - } - - return bHolding; - -#else - return TRUE; -#endif -} - - -/* - * The mocha lock has been released, flush the blockage to see if - * we can get our blocked entities evaluated now. - */ -static void -lo_JSLockReleased(void * data) -{ - MWContext * context = (MWContext *) data; - lo_TopState * top_state; - - top_state = lo_FetchTopState(XP_DOCID(context)); - if (!top_state) - return; - - /* free the fake element we created earlier */ - lo_FreeElement(context, top_state->layout_blocking_element, FALSE); - - /* flush the blockage */ - lo_UnblockLayout(context, top_state); -} - -/* - * see if there are any &{} constructs for this tag. If so, - * convert them now, if we can't convert them (since we couldn't - * get the mocha lock, for example) return FALSE - */ -Bool -lo_ConvertMochaEntities(MWContext * context, lo_DocState *state, PA_Tag * tag) -{ - - char *tptr; - char *str; - char *new_str; - int32 len; - char tchar; - Bool has_mocha; - char *start, *end; - int32 cur_layer_id; - - PA_LOCK(str, char *, tag->data); - len = tag->data_len; - - if (LM_CanDoJS(context) == FALSE) - return TRUE; - - new_str = NULL; - tptr = str; - has_mocha = lo_FindMochaExpr(tptr, &start, &end); - - if (has_mocha == FALSE) - return TRUE; - - /* attempt to lock JS */ - if (!LM_AttemptLockJS(context, lo_JSLockReleased, context)) - return FALSE; - - /* - * Make sure that the current layer and all its ancestors have - * been reflected and that the current layer has been set as the - * active layer, since we want to ensure correct scoping and there's - * no way to know that the reflect event has reached Mocha yet. - * Note that reflecting the object multiple times is safe, since the - * reflection code is idempotent. - */ - cur_layer_id = lo_CurrentLayerId(state); - if (cur_layer_id != LO_DOCUMENT_LAYER_ID) { - CL_Layer *layer, *parent; - int32 child_layer_id = cur_layer_id; - int32 parent_layer_id; - - do { - layer = LO_GetLayerFromId(context, child_layer_id); - parent = CL_GetLayerParent(layer); - parent_layer_id = LO_GetIdFromLayer(context, parent); - LM_ReflectLayer(context, cur_layer_id, parent_layer_id, NULL); - child_layer_id = parent_layer_id; - } while (child_layer_id != LO_DOCUMENT_LAYER_ID); - - } - LM_SetActiveLayer(context, cur_layer_id); - while (has_mocha != FALSE) - { - char *expr_start, *expr_end; - - if (start > tptr) - { - tchar = *start; - *start = '\0'; - new_str = lo_add_string(new_str, tptr); - *start = tchar; - } - - expr_start = (char *)(start + 2); - expr_end = (char *)(end - 1); - if (expr_end > expr_start) - { - char *eval_str; - - tchar = *expr_end; - *expr_end = '\0'; - if (state->top_state && state->top_state->nurl) { - LM_SetDecoderStream(context, NULL, - state->top_state->nurl, - JS_FALSE); - } - eval_str = LM_EvaluateAttribute(context, expr_start, - tag->newline_count + 1); - *expr_end = tchar; - new_str = lo_add_string(new_str, eval_str); - if (eval_str != NULL) - { - XP_FREE(eval_str); - } - } - - tptr = (char *)(end + 1); - has_mocha = lo_FindMochaExpr(tptr, &start, &end); - } - if (tptr != str) - { - new_str = lo_add_string(new_str, tptr); - } - - PA_FREE(tag->data); - tag->data = (PA_Block) new_str; - tag->data_len = XP_STRLEN((char *) tag->data); - PA_UNLOCK(tag->data); - - LM_UnlockJS(context); - - return TRUE; - -} - -/* Called from front ends as a threadsafe way to update values of text fields. */ -void -LO_UpdateTextData(lo_FormElementTextData * textData, const char * text) { - - LO_LockLayout(); - - if(textData->current_text) - XP_FREE(textData->current_text); - - textData->current_text = (PA_Block) XP_STRDUP(text); - - LO_UnlockLayout(); -} - -LO_TableStruct *lo_GetParentTable(MWContext *pContext, LO_Element *pElement) -{ - LO_Element *tptr; - if( !pElement ) - return NULL; - - if( pElement->lo_any.type == LO_CELL ) - { - /* Supplied element is already a cell, start table search with it */ - tptr = pElement; - } else { - if( !pContext ) - return NULL; - - /* First find the cell that contains the given element */ - tptr = (LO_Element*)lo_GetParentCell(pContext, pElement); - } - - /* Simply search back from current cell to find table element */ - while( tptr ) - { - if( tptr->lo_any.type == LO_TABLE ) - { - return (LO_TableStruct*)tptr; - } - tptr = tptr->lo_any.prev; - } - return NULL; -} - - -/* Recusively search for cell struct containing the given element - * If table is found, it searches into that as well - */ -LO_CellStruct *lo_GetCellContainingElement( LO_Element *pElement, LO_CellStruct *pFirstCell ) -{ - LO_CellStruct *pNestedCell = NULL; - LO_CellStruct *pFirstNestedCell; - LO_Element *cell_list_ptr; - LO_CellStruct *pLoCell; - - pLoCell = pFirstCell; - if( pLoCell == NULL ) - return NULL; - - do { - cell_list_ptr = pLoCell->cell_list; - while( cell_list_ptr ) - { - if( cell_list_ptr == pElement ) - { - /* We found the element - return cell containing it */ - return pLoCell; - } - if( cell_list_ptr->type == LO_TABLE ) - { - /* We found a nested table - * Get first cell in it and search through it - */ - pFirstNestedCell = (LO_CellStruct*)cell_list_ptr->lo_any.next; - XP_ASSERT(pFirstNestedCell->type == LO_CELL); - pNestedCell = lo_GetCellContainingElement(pElement, pFirstNestedCell); - if( pNestedCell ) - { - /* We found cell in nested table */ - return pNestedCell; - } - } - cell_list_ptr = cell_list_ptr->lo_any.next; - } - pLoCell = (LO_CellStruct*)pLoCell->next; - } /* End when there's no more cells or we hit linefeed at end of line (top-level table)*/ - while (pLoCell && pLoCell->type == LO_CELL); - - return NULL; -} - -/* Search algorithm is very similar to CEditBuffer::GetTableHitRegion() - * (which is similar to lo_XYtoDocumentElement except it finds only cells) - * Search for the Cell that contains pElement -*/ -LO_CellStruct *lo_GetParentCell(MWContext * pContext, LO_Element *pElement) -{ - LO_Element *tptr; - int32 doc_id; - lo_TopState *top_state; - lo_DocState *state; - XP_Bool in_table; - int32 line; - LO_Element *end_ptr; - LO_Element *tptrTable; - int32 x, y, t_width, t_height; - - doc_id = XP_DOCID(pContext); - top_state = lo_FetchTopState(doc_id); - - /* Supplied element is a cell - return it ??? */ - if( pElement && pElement->type == LO_CELL ) - return (LO_CellStruct*)pElement; - - if( pContext == NULL || pElement == NULL || top_state == NULL || top_state->doc_state == NULL ) - return NULL; - - state = top_state->doc_state; - tptrTable = NULL; - in_table = FALSE; - - /* Find the line that contains the supplied element - * This defines the top-level table - */ - x = pElement->lo_any.x+1; - y = pElement->lo_any.y+1; - - line = lo_PointToLine(pContext, state, x, y); - lo_GetLineEnds(pContext, state, line, &tptr, &end_ptr); - - while (tptr != end_ptr) - { - t_width = tptr->lo_any.width; - t_height = tptr->lo_any.height; - - if (t_width <= 0) - { - t_width = 1; - } - - if ((y >= tptr->lo_any.y) && - (y < tptr->lo_any.y + tptr->lo_any.y_offset + t_height) && - (x >= tptr->lo_any.x) && - (x < (tptr->lo_any.x + tptr->lo_any.x_offset + t_width))) - { - /* We are only interested in finding cells */ - if (tptr->type == LO_CELL) - { - /* Search through the cell's element list, - * Including all nested tables in that cell - */ - LO_CellStruct * pLoCell = lo_GetCellContainingElement(pElement, (LO_CellStruct*)tptr); - /* We found it - done */ - if( pLoCell ) - return pLoCell; - } - } - tptr = tptr->lo_any.next; - } - - /* Failed to find element */ - return NULL; -} - - -static int lo_iColumnX = 0; -static int lo_iRowY = 0; - -/* Find the first cell with with closest left border x-value <= than the given x - * value or, if bGetColumn=FALSE, find the cell with closest top border - * y-value <= than the given Y value. Also returns the pointer to the - * last LO element so we can search for other cells until pEndElement is reached. -*/ -LO_Element* lo_GetFirstCellInColumnOrRow(MWContext *pContext, LO_Element *pElement, int32 x, int32 y, XP_Bool bGetColumn, LO_Element **ppLastCellInTable) -{ - LO_Element *pFirstCell = NULL; - LO_Element *pLastCellInTable = NULL; - LO_Element *tptr = NULL; - int32 closest = 0; - - /* Save these values so future calls to lo_GetNextCellInColumnOrRow can use them */ - if( bGetColumn ) - lo_iColumnX = x; - else - lo_iRowY = y; - - if( pElement->type == LO_TABLE ) - { - /* Start at first element after the table */ - tptr = pElement->lo_any.next; - } else { - - if( pElement->type == LO_CELL ) - { - /* Element is a cell */ - tptr = pElement; - } else { - /* Get parent cell of supplied element */ - tptr = (LO_Element*)lo_GetParentCell(pContext, pElement); - } - if( !tptr ) - return NULL; - - /* Search back until we are at first cell in table */ - while ( (tptr->lo_any.prev)->type != LO_TABLE ) - { - tptr = tptr->lo_any.prev; - } - } - - /* Scan all cells to find first and last */ - do { - if( tptr->type == LO_CELL ) - { - if( bGetColumn && tptr->lo_any.x <= x && - tptr->lo_any.x > closest ) - { - /* We found a cell candidate */ - closest = tptr->lo_any.x; - pFirstCell = tptr; - } else if( !bGetColumn && tptr->lo_any.y <= y && - tptr->lo_any.y > closest ) - { - closest = tptr->lo_any.y; - pFirstCell = tptr; - } - pLastCellInTable = tptr; - } - tptr = tptr->lo_any.next; - - /* Table ends at linefeed (top level) or null element (nested table) */ - } while (tptr && tptr->type != LO_LINEFEED ); - - /* Return last cell element encountered */ - if( ppLastCellInTable ) - *ppLastCellInTable = pLastCellInTable; - - return pFirstCell; -} - -LO_Element* lo_GetNextCellInColumnOrRow(MWContext *pContext, int32 x, int32 y, LO_Element *pElement, XP_Bool bGetColumn) -{ - LO_Element *tptr; - - if(!pElement) - return NULL; - - /* Start with next element after the "current" one supplied */ - tptr = pElement->lo_any.next; - - /* Be sure we are a cell */ - /* (tptr = LO_LINEFEED if we were already on the last cell */ - while ( tptr && tptr->type != LO_LINEFEED && tptr->type != LO_CELL ) - tptr = tptr->lo_any.next; - - if(!tptr || tptr->type == LO_LINEFEED) - return NULL; - - /* Set column X or row Y values that define a col or row respectively */ - if( bGetColumn ) - { - if( x > 0 ) - lo_iColumnX = x; - } - else - { - if( y > 0 ) - lo_iRowY = y; - } - - do { - if( tptr->type == LO_CELL ) - { - /* Note that we return cell SPANNED by given ColumnX or RowY */ - if( ( bGetColumn && tptr->lo_any.x <= lo_iColumnX && - (tptr->lo_any.x + tptr->lo_any.width) > lo_iColumnX ) || - ( !bGetColumn && tptr->lo_any.y <= lo_iRowY && - (tptr->lo_any.y + tptr->lo_any.height) > lo_iRowY ) ) - { - return tptr; - } - } - tptr = tptr->lo_any.next; - - /* Table ends at linefeed (top level) or null element (nested table) */ - } while (tptr && tptr->type != LO_LINEFEED ); - - return NULL; -} - -/* Assumptions; - * Given a LO_CellStruct, the table element defines the begining of table - * and the last cell is that whose "next" pointer is NULL (nested table) - * or a linefeed element (top-level table) -*/ -LO_Element *lo_GetFirstAndLastCellsInTable(MWContext *pContext, LO_Element *pElement, LO_Element **ppLastCell) -{ - LO_Element *tptr = NULL; - LO_Element *pFirstCell = NULL; - LO_Element *pLastCell = NULL; - LO_Element *pCurrentCell = NULL; - - if(pContext == NULL || pElement == NULL ) - return NULL; - - if( pElement->type == LO_CELL ) - { - pCurrentCell = pElement; - } - else if( pElement->type == LO_TABLE ) - { - /* First cell SHOULD be next element, but let's be sure */ - pCurrentCell = pElement->lo_table.next; - while(pCurrentCell->type != LO_CELL) - { - pCurrentCell = pCurrentCell->lo_any.next; - } - } else { - pCurrentCell = (LO_Element*)lo_GetParentCell(pContext, pElement); - } - - if( pCurrentCell == NULL ) - return NULL; - - /* Scan backwards until we hit the table element - * that's before all the cells - */ - tptr = pCurrentCell; - while (tptr && (tptr->lo_any.prev)->type != LO_TABLE ) - { - tptr = tptr->lo_any.prev; - } - - /* Scan forward to find last cell -- next is null or line-feed element */ - do { - if( tptr->type == LO_CELL ) - { - if( !pFirstCell ) - pFirstCell = tptr; - - pLastCell = tptr; - } - tptr = tptr->lo_any.next; - } while (tptr && tptr->type != LO_LINEFEED); - - /* Return last cell element encountered */ - if( ppLastCell ) - *ppLastCell = pLastCell; - - return pFirstCell; -} - -LO_Element *lo_GetFirstAndLastCellsInColumnOrRow(LO_Element *pCellElement, LO_Element **ppLastCell, XP_Bool bInColumn ) -{ - LO_Element *tptr = NULL; - LO_Element *pFirstCell = NULL; - LO_Element *pLastCell = NULL; - - if(pCellElement == NULL || pCellElement->type != LO_CELL) - return NULL; - - /* Scan backwards until we hit the table element - * that's before all the cells - */ - tptr = pCellElement; - while (tptr && (tptr->lo_any.prev)->type != LO_TABLE ) - { - tptr = tptr->lo_any.prev; - } - - /* Scan forward to find first and last cells, - * based on sharing left edge (column) or top (row) - */ - do { - if( tptr->type == LO_CELL ) - { - if( (bInColumn && pCellElement->lo_any.x == tptr->lo_any.x) || - (!bInColumn && pCellElement->lo_any.y == tptr->lo_any.y) ) - { - if( !pFirstCell ) - pFirstCell = tptr; - - pLastCell = tptr; - } - } - tptr = tptr->lo_any.next; - } while (tptr && tptr->type != LO_LINEFEED); - - /* Return last cell element encountered */ - if( ppLastCell ) - *ppLastCell = pLastCell; - - return pFirstCell; -} - -XP_Bool lo_AllCellsSelectedInColumnOrRow( LO_CellStruct *pCell, XP_Bool bInColumn ) -{ - LO_Element *pFirstCell; - LO_Element *pLastCell = NULL; - LO_Element *tptr; - - /* Get first and last cells in row or column */ - pFirstCell = lo_GetFirstAndLastCellsInColumnOrRow( (LO_Element*)pCell, &pLastCell, bInColumn ); - if( !pFirstCell || !pLastCell ) - return FALSE; - - tptr = pFirstCell; - - while( TRUE ) - { - if( tptr->type == LO_CELL ) - { - if( (bInColumn && pCell->x == tptr->lo_any.x) || - (!bInColumn && pCell->y == tptr->lo_any.y) ) - { - /* If any cell is not selected, return FALSE */ - if( (tptr->lo_cell.ele_attrmask & LO_ELE_SELECTED) ? FALSE : TRUE ) - return FALSE; - } - } - /* Done when we checked the last cell */ - if( tptr == pLastCell ) - break; - - tptr = tptr->lo_any.next; - if( !tptr ) - break; - } - return TRUE; -} - -int32 lo_GetNumberOfCellsInTable(LO_TableStruct *pTable ) -{ - int32 iCount = 0; - if( pTable ) - { - LO_Element *tptr = (LO_Element*)pTable; - while( tptr && tptr->type != LO_LINEFEED ) - { - if( tptr->type == LO_CELL) - iCount++; - - tptr = tptr->lo_any.next; - } - } - return iCount; -} - -/* Subtract borders and inter-cell spacing to get the available table width - * to use when cell width in HTML is "percent of table" -*/ -int32 lo_CalcTableWidthForPercentMode(LO_Element *pCellElement) -{ - LO_Element *pLastCell; - LO_Element *pFirstCell; - LO_Element *pCell; - int32 iWidth; - XP_Bool bDone; - - /* Never return 0 to avoid divide by zero errors */ - if( !pCellElement || pCellElement->type != LO_CELL ) - return -1; - - iWidth = 0; - - /* We calculate the width by simply adding up widths of all cells in the row */ - pFirstCell = lo_GetFirstAndLastCellsInColumnOrRow(pCellElement, &pLastCell, FALSE ); - pCell = pFirstCell; - - if( pCell && pLastCell ) - { - bDone = FALSE; - while(!bDone) - { - if( pCell == pLastCell ) - bDone = TRUE; - - /* Add widths of all cells in the row (must have same top) */ - if( pCell->type == LO_CELL && - (pCell->lo_any.y == pFirstCell->lo_any.y) ) - { - iWidth += pCell->lo_cell.width; - } - pCell = pCell->lo_any.next; - } - } - return (iWidth > 0) ? iWidth : -1; -} - -XP_Bool LO_IsEmptyCell(LO_CellStruct *cell) -{ - if ( cell ) - { - LO_Element *element = cell->cell_list; - - /* Unlikely, but if nothing inside cell, we're empty! */ - if(element) - { - while(element) - { - /* Any non-text element except linefeed is not "empty" - * and check for text length - * Length of any element is 1. Length of text = real length, - * (but we don't want to consider linefeeds) - */ - if( element->type != LO_LINEFEED && lo_GetElementLength(element) > 0 ) - { - return FALSE; - } - element = element->lo_any.next; - } - } - } - return TRUE; -} - -/* The LO_CellStruct.width includes border, cell padding etc and is complicated - * by Column Span as well. Calculate the value to use for <TD WIDTH> param that - * would result in current pCellElement->lo_cell.width during the next layout -*/ -int32 lo_GetCellTagWidth(LO_Element *pCellElement) -{ - /* XP_ASSERT(pCellElement->type == LO_CELL); */ /* Why doesn't this compile! */ - int32 iColSpan = lo_GetColSpan(pCellElement); - int32 iPadding = iColSpan * 2 * (pCellElement->lo_cell.border_width + - lo_GetCellPadding(pCellElement)); - - /* Cells spanning across a border include the inter-cell space as well */ - if( iColSpan > 1 ) - iPadding += (iColSpan - 1) * pCellElement->lo_cell.inter_cell_space; - - return pCellElement->lo_cell.width - iPadding; -} - -/* Similar calculation for height. Unfortunately, there are differences from width. - * e.g., the cell border must be subtracted from width, but not height! (a bug???) -*/ -int32 lo_GetCellTagHeight(LO_Element *pCellElement) -{ - /*XP_ASSERT(pCellElement->type == LO_CELL);*/ - - int32 iRowSpan = lo_GetRowSpan(pCellElement); - int32 iPadding = iRowSpan * 2 * (/*pCellElement->lo_cell.border_width + */ - lo_GetCellPadding(pCellElement)); - - if( iRowSpan > 1 ) - iPadding += (iRowSpan - 1) * pCellElement->lo_cell.inter_cell_space; - - return pCellElement->lo_cell.height - iPadding; -} - -/* Helpers to access the lo_TableCell members now accessible through the LO_CellStruct */ -int32 lo_GetRowSpan(LO_Element *pCellElement) -{ - XP_ASSERT(pCellElement->type == LO_CELL); - - if( pCellElement && pCellElement->lo_any.type == LO_CELL && - pCellElement->lo_cell.table_cell ) - { - return ((lo_TableCell*)pCellElement->lo_cell.table_cell)->rowspan; - } - /* Should never fail, but since default value is 1, - this will tell caller we failed */ - return 0; -} - -int32 lo_GetColSpan(LO_Element *pCellElement) -{ - XP_ASSERT(pCellElement && pCellElement->type == LO_CELL); - if( pCellElement && pCellElement->lo_any.type == LO_CELL && - pCellElement->lo_cell.table_cell ) - { - return ((lo_TableCell*)pCellElement->lo_cell.table_cell)->colspan; - } - return 0; -} - -/* TODO: CHANGE THIS TO GET LEFT, TOP, RIGHT, OR BOTTOM SEPARATELY? */ -int32 lo_GetCellPadding(LO_Element *pCellElement) -{ - XP_ASSERT(pCellElement && pCellElement->type == LO_CELL); - - if( pCellElement && pCellElement->type == LO_CELL && - pCellElement->lo_cell.table ) - { - return ((lo_TableRec*)pCellElement->lo_cell.table)->inner_top_pad; - } - return 0; -} - -LO_Element * lo_GetLastElementInList( LO_Element *eleList ) -{ - LO_Element *retEle = NULL; - - if (eleList != NULL) - { - while (eleList->lo_any.next != NULL) - eleList = eleList->lo_any.next; - - retEle = eleList; - } - - return retEle; - -} - -#ifdef DOM -/* Checks the layout element to see if the element is enclosed within <SPAN> */ -Bool LO_IsWithinSpan( LO_Element *ele ) -{ - Bool isInSpan = FALSE; - - if (ele) - { - switch (ele->type) { - - case LO_TEXT: - isInSpan = ele->lo_text.ele_attrmask & LO_ELE_IN_SPAN ? TRUE : FALSE; - break; - case LO_IMAGE: - isInSpan = ele->lo_image.ele_attrmask & LO_ELE_IN_SPAN ? TRUE : FALSE; - break; - case LO_FORM_ELE: - isInSpan = ele->lo_form.ele_attrmask & LO_ELE_IN_SPAN ? TRUE : FALSE; - break; - case LO_EMBED: - isInSpan = ele->lo_embed.ele_attrmask & LO_ELE_IN_SPAN ? TRUE : FALSE; - break; - case LO_JAVA: - isInSpan = ele->lo_java.ele_attrmask & LO_ELE_IN_SPAN ? TRUE : FALSE; - break; - case LO_BUILTIN: - isInSpan = ele->lo_builtin.ele_attrmask & LO_ELE_IN_SPAN ? TRUE : FALSE; - break; - } - } - return isInSpan; -} - -static void lo_SetInSpanAttribute( LO_Element *ele ) -{ - switch (ele->type) { - - case LO_TEXT: - ele->lo_text.ele_attrmask |= LO_ELE_IN_SPAN; - break; - case LO_IMAGE: - ele->lo_image.ele_attrmask |= LO_ELE_IN_SPAN; - break; - case LO_FORM_ELE: - ele->lo_form.ele_attrmask |= LO_ELE_IN_SPAN; - break; - case LO_EMBED: - ele->lo_embed.ele_attrmask |= LO_ELE_IN_SPAN; - break; -#ifdef JAVA - case LO_JAVA: - ele->lo_java.ele_attrmask |= LO_ELE_IN_SPAN; - break; -#endif - } -} -#endif - -#ifdef PROFILE -#pragma profile off -#endif diff --git a/lib/libmocha/Makefile b/lib/libmocha/Makefile index edae4f428cc..42adc8ec3ac 100644 --- a/lib/libmocha/Makefile +++ b/lib/libmocha/Makefile @@ -57,10 +57,8 @@ CSRCS = et_mocha.c \ lm_nav.c \ lm_plgin.c \ lm_screen.c \ - lm_span.c \ lm_supdt.c \ lm_taint.c \ - lm_trans.c \ lm_tree.c \ lm_trggr.c \ lm_url.c \ diff --git a/lib/libmocha/Makefile.in b/lib/libmocha/Makefile.in index 37193b20aa9..b6a4fba9dc8 100644 --- a/lib/libmocha/Makefile.in +++ b/lib/libmocha/Makefile.in @@ -60,10 +60,8 @@ CSRCS = et_mocha.c \ lm_nav.c \ lm_plgin.c \ lm_screen.c \ - lm_span.c \ lm_supdt.c \ lm_taint.c \ - lm_trans.c \ lm_tree.c \ lm_trggr.c \ lm_url.c \ diff --git a/lib/libmocha/et_mocha.c b/lib/libmocha/et_mocha.c index c5ab4755756..7eb143430ff 100644 --- a/lib/libmocha/et_mocha.c +++ b/lib/libmocha/et_mocha.c @@ -908,15 +908,6 @@ et_reflect_handler(Reflect_Event * e) case LM_LAYERS: LM_ReflectLayer(e->ce.context, e->index, e->layer_id, e->pa_tag); break; -#ifdef DOM - case LM_SPANS: - LM_ReflectSpan(e->ce.context, e->lo_ele, e->pa_tag, - e->layer_id, e->index); - break; - case LM_TRANSCLUSIONS: - LM_ReflectTransclusion(e->ce.context, e->lo_ele, e->layer_id, e->index); - break; -#endif default: XP_ASSERT(0); break; diff --git a/lib/libmocha/et_moz.c b/lib/libmocha/et_moz.c index e80aabe3254..0fe042c7150 100644 --- a/lib/libmocha/et_moz.c +++ b/lib/libmocha/et_moz.c @@ -3063,157 +3063,8 @@ ET_PostSignedAppletPrivileges et_PostEvent(&event->ce, FALSE); } -#ifdef DOM - -/****************************************************************************/ - -typedef struct { - ETEvent ce; - lo_NameList *name_rec; - ETSpanOp op; - void *param_ptr; - int32 param_val; -} MozillaEvent_TweakSpan; - -PR_STATIC_CALLBACK(int) -et_HandleEvent_TweakSpan(MozillaEvent_TweakSpan* e) -{ - Bool ret = TRUE; - - /* check that the doc_id is valid */ - if(XP_DOCID(e->ce.context) != e->ce.doc_id) - return FALSE; - - switch(e->op) { - case SP_SetColor: - LO_SetSpanColor(e->ce.context, e->name_rec, (LO_Color*)e->param_ptr); - /* This call to reflow is just a temp hack */ - LO_RelayoutFromElement(e->ce.context, e->name_rec->element); - if (e->param_ptr) - XP_FREE((void*)e->param_ptr); - break; - case SP_SetBackground: - LO_SetSpanBackground(e->ce.context, e->name_rec, (LO_Color*)e->param_ptr); - /* This call to reflow is just a temp hack */ - LO_RelayoutFromElement(e->ce.context, e->name_rec->element); - if (e->param_ptr) - XP_FREE((void*)e->param_ptr); - break; - case SP_SetFontFamily: - LO_SetSpanFontFamily(e->ce.context, e->name_rec, (char*)e->param_ptr); - LO_RelayoutFromElement(e->ce.context, e->name_rec->element); - break; - case SP_SetFontWeight: - LO_SetSpanFontWeight(e->ce.context, e->name_rec, (char*)e->param_ptr); - LO_RelayoutFromElement(e->ce.context, e->name_rec->element); - break; - case SP_SetFontSize: - LO_SetSpanFontSize(e->ce.context, e->name_rec, e->param_val); - LO_RelayoutFromElement(e->ce.context, e->name_rec->element); - break; - case SP_SetFontSlant: - LO_SetSpanFontSlant(e->ce.context, e->name_rec, (char*)e->param_ptr); - LO_RelayoutFromElement(e->ce.context, e->name_rec->element); - break; - default: - XP_ASSERT(0); - } - - return (int)ret; -} - -PR_STATIC_CALLBACK(void) -et_DestroyEvent_TweakSpan(MozillaEvent_TweakSpan * event) -{ - XP_FREE(event); -} - -/* - * These need to be synchronous so that if we set this and then - * immediately look at it we get the correct (new) value - */ -int -ET_TweakSpan(MWContext * context, void *name_rec, void *param_ptr, - int32 param_val, ETSpanOp op, int32 doc_id) -{ - MozillaEvent_TweakSpan * event; - event = PR_NEW(MozillaEvent_TweakSpan); - if (event == NULL) - return 0; - - PR_InitEvent(&event->ce.event, context, - (PRHandleEventProc)et_HandleEvent_TweakSpan, - (PRDestroyEventProc)et_DestroyEvent_TweakSpan); - event->ce.context = context; - event->ce.doc_id = doc_id; - event->op = op; - event->name_rec = name_rec; - event->param_ptr = param_ptr; - event->param_val = param_val; - - return (int)et_PostEvent(&event->ce, TRUE); -} - -/* Tweak XML Transclusion stuff starts here */ -typedef struct { - ETEvent ce; - ETTransclusionOp op; - void *param_ptr; - int32 param_val; - void *xmlFile; -} MozillaEvent_TweakTransclusion; - -PR_STATIC_CALLBACK(int) -et_HandleEvent_TweakTransclusion(MozillaEvent_TweakTransclusion* e) -{ - Bool ret = TRUE; - - /* check that the doc_id is valid */ - if(XP_DOCID(e->ce.context) != e->ce.doc_id) - return FALSE; - - switch(e->op) { - case TR_SetHref: - XMLSetTransclusionProperty(e->xmlFile, e->param_val, "href", e->param_ptr); - if (e->param_ptr) - XP_FREE((void*)e->param_ptr); - break; - default: - XP_ASSERT(0); - } - - return (int)ret; -} - -PR_STATIC_CALLBACK(void) -et_DestroyEvent_TweakTransclusion(MozillaEvent_TweakTransclusion * event) -{ - XP_FREE(event); -} - - -int -ET_TweakTransclusion(MWContext * context, void *xmlFile, void *param_ptr, - int32 param_val, ETTransclusionOp op, int32 doc_id) -{ - MozillaEvent_TweakTransclusion * event; - event = PR_NEW(MozillaEvent_TweakTransclusion); - if (event == NULL) - return 0; - - PR_InitEvent(&event->ce.event, context, - (PRHandleEventProc)et_HandleEvent_TweakTransclusion, - (PRDestroyEventProc)et_DestroyEvent_TweakTransclusion); - event->ce.context = context; - event->ce.doc_id = doc_id; - event->op = op; - event->param_ptr = param_ptr; - event->param_val = param_val; - event->xmlFile = xmlFile; - - return (int)et_PostEvent(&event->ce, FALSE); -} +#if DOM /* Signal reflow from DOM alteration */ typedef struct { ETEvent ce; diff --git a/lib/libmocha/lm_doc.c b/lib/libmocha/lm_doc.c index 7aa89ed8226..35a06fd6c7a 100644 --- a/lib/libmocha/lm_doc.c +++ b/lib/libmocha/lm_doc.c @@ -85,27 +85,25 @@ enum doc_slot { DOC_ANCHORS = -5, DOC_APPLETS = -6, DOC_EMBEDS = -7, - DOC_SPANS = -8, /* Added for HTML SPAN DOM stuff */ - DOC_TRANSCLUSIONS = -9, /* Added for XML Transclusion DOM stuff */ - DOC_DOCELEMENT = -10, /* Added for W3C DOM stuff */ - DOC_TITLE = -11, - DOC_URL = -12, - DOC_REFERRER = -13, - DOC_LAST_MODIFIED = -14, - DOC_COOKIE = -15, - DOC_DOMAIN = -16, + DOC_DOCELEMENT = -8, /* Added for W3C DOM stuff */ + DOC_TITLE = -9, + DOC_URL = -10, + DOC_REFERRER = -11, + DOC_LAST_MODIFIED = -12, + DOC_COOKIE = -13, + DOC_DOMAIN = -14, /* slots below this line are not secured */ - DOC_IMAGES = -17, - DOC_LAYERS = -18, - DOC_LOADED_DATE = -19, - DOC_BG_COLOR = -20, - DOC_FG_COLOR = -21, - DOC_LINK_COLOR = -22, - DOC_VLINK_COLOR = -23, - DOC_ALINK_COLOR = -24, - DOC_WIDTH = -25, - DOC_HEIGHT = -26, - DOC_BUILTINS = -27 + DOC_IMAGES = -15, + DOC_LAYERS = -16, + DOC_LOADED_DATE = -17, + DOC_BG_COLOR = -18, + DOC_FG_COLOR = -19, + DOC_LINK_COLOR = -20, + DOC_VLINK_COLOR = -21, + DOC_ALINK_COLOR = -22, + DOC_WIDTH = -23, + DOC_HEIGHT = -24, + DOC_BUILTINS = -25 }; #endif @@ -123,8 +121,6 @@ static JSPropertySpec doc_props[] = { {lm_images_str, DOC_IMAGES, JSPROP_ENUMERATE|JSPROP_READONLY}, {lm_layers_str, DOC_LAYERS, JSPROP_ENUMERATE|JSPROP_READONLY}, #ifdef DOM - {lm_spans_str, DOC_SPANS, JSPROP_ENUMERATE|JSPROP_READONLY}, - {lm_transclusions_str, DOC_TRANSCLUSIONS, JSPROP_ENUMERATE|JSPROP_READONLY}, {"documentElement",DOC_DOCELEMENT, JSPROP_ENUMERATE|JSPROP_READONLY}, #endif {"title", DOC_TITLE, JSPROP_ENUMERATE|JSPROP_READONLY}, @@ -305,35 +301,7 @@ doc_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) return JS_TRUE; #ifdef DOM - case DOC_SPANS: - *vp = OBJECT_TO_JSVAL(lm_GetSpanArray(decoder, obj)); - active_layer_id = LM_GetActiveLayer(context); - LM_SetActiveLayer(context, doc->layer_id); - (void) LO_EnumerateSpans(context,doc->layer_id); - LM_SetActiveLayer(context, active_layer_id); - LO_UnlockLayout(); - return JS_TRUE; - - case DOC_TRANSCLUSIONS: - /* We are assuming that by the time any JS sees document.transclusions[] - all the transclusions have been reflected into JS. So - there is no need for the call to XMLEnumerateTransclusions that - reflects all Transclusions into JS. - */ - *vp = OBJECT_TO_JSVAL(lm_GetTransclusionArray(decoder, obj)); - active_layer_id = LM_GetActiveLayer(context); - LM_SetActiveLayer(context, doc->layer_id); - /* - (void) XMLEnumerateTransclusions(context,doc->layer_id); - */ - LM_SetActiveLayer(context, active_layer_id); - LO_UnlockLayout(); - return JS_TRUE; - case DOC_DOCELEMENT: -#ifdef DEBUG_shaver - fprintf(stderr, "getting document.documentElement\n"); -#endif *vp = OBJECT_TO_JSVAL(lm_DOMGetDocumentElement(decoder, obj)); LO_UnlockLayout(); return JS_TRUE; @@ -1700,12 +1668,7 @@ lm_DefineDocument(MochaDecoder *decoder, int32 layer_id) !JS_AddNamedRoot(cx, &doc->applets, lm_applets_str) || !JS_AddNamedRoot(cx, &doc->embeds, lm_embeds_str) || !JS_AddNamedRoot(cx, &doc->images, lm_images_str) || - !JS_AddNamedRoot(cx, &doc->layers, lm_layers_str) -#ifdef DOM - || !JS_AddNamedRoot(cx, &doc->spans, lm_spans_str) - || !JS_AddNamedRoot(cx, &doc->transclusions, lm_transclusions_str) -#endif - ) { + !JS_AddNamedRoot(cx, &doc->layers, lm_layers_str)) { /* doc_finalize will clean up the rest. */ return NULL; } @@ -1791,10 +1754,6 @@ lm_CleanUpDocumentRoots(MochaDecoder *decoder, JSObject *obj) doc->embeds = NULL; doc->images = NULL; doc->layers = NULL; -#ifdef DOM - doc->spans = NULL; - doc->transclusions = NULL; -#endif } /* diff --git a/lib/libmocha/lm_init.c b/lib/libmocha/lm_init.c index a3e5343b501..3b4e03cc69d 100644 --- a/lib/libmocha/lm_init.c +++ b/lib/libmocha/lm_init.c @@ -102,10 +102,6 @@ char lm_applets_str[] = "applets"; char lm_embeds_str[] = "embeds"; char lm_images_str[] = "images"; char lm_layers_str[] = "layers"; -#ifdef DOM -char lm_spans_str[] = "spans"; -char lm_transclusions_str[] = "transclusions"; -#endif char lm_builtins_str[] = "trees"; char lm_location_str[] = "location"; char lm_navigator_str[] = "navigator"; @@ -1212,11 +1208,6 @@ LM_PutMochaDecoder(MochaDecoder *decoder) CLEAR(decoder->rect_prototype); CLEAR(decoder->url_prototype); -#ifdef DOM - CLEAR(decoder->span_prototype); - CLEAR(decoder->transclusion_prototype); -#endif - /* Clear window sub-object refs. */ if (decoder->document) lm_CleanUpDocumentRoots(decoder, decoder->document); diff --git a/lib/libmocha/lm_input.c b/lib/libmocha/lm_input.c index 85140f60363..e1cc41f5d63 100644 --- a/lib/libmocha/lm_input.c +++ b/lib/libmocha/lm_input.c @@ -2383,14 +2383,6 @@ lm_InputEvent(MWContext *context, LO_Element *element, JSEvent *pEvent, case LO_TEXT: anchor = element->lo_text.text ? element->lo_text.anchor_href : 0; obj = anchor ? anchor->mocha_object : 0; -#ifdef DOM - /* If this layout element is within a span, set the mocha object to - the containing SPAN's mocha object */ - if (LO_IsWithinSpan( element )) - { - obj = LO_GetMochaObjectOfParentSpan( element ); - } -#endif if (!obj) { if (!LM_EventCaptureCheck(context, pEvent->type) || !anchor) { LO_UnlockLayout(); diff --git a/lib/libmocha/lm_span.c b/lib/libmocha/lm_span.c deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/lib/libmocha/lm_trans.c b/lib/libmocha/lm_trans.c deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/lib/libmocha/lm_win.c b/lib/libmocha/lm_win.c index 8f674d99dbc..2b6ea4ac300 100644 --- a/lib/libmocha/lm_win.c +++ b/lib/libmocha/lm_win.c @@ -3194,10 +3194,6 @@ lm_NewWindow(MWContext *context) HOLD(decoder->option_prototype); HOLD(decoder->rect_prototype); HOLD(decoder->url_prototype); -#ifdef DOM - HOLD(decoder->span_prototype); - HOLD(decoder->transclusion_prototype); -#endif /* Drop window sub-object refs. */ HOLD(decoder->document); @@ -3256,11 +3252,6 @@ lm_DestroyWindow(MochaDecoder *decoder) DROP(decoder->option_prototype); DROP(decoder->rect_prototype); DROP(decoder->url_prototype); -#ifdef DOM - DROP(decoder->span_prototype); - DROP(decoder->transclusion_prototype); -#endif - /* Drop window sub-object refs. */ DROP(decoder->document); @@ -3397,10 +3388,7 @@ lm_DefineWindowProps(JSContext *cx, MochaDecoder *decoder) lm_InitImageClass(decoder) && lm_InitAnchorClass(decoder) && #ifdef DOM - /* the order of lm_DOMInit* is significant -- be careful */ lm_DOMInit(decoder) && - lm_InitSpanClass(decoder) && - lm_InitTransclusionClass(decoder) && #endif lm_InitBuiltinClass(decoder) && lm_InitInputClasses(decoder) && @@ -3496,11 +3484,6 @@ lm_FreeWindowContent(MochaDecoder *decoder, JSBool fromDiscard) #endif CLEAR(decoder->pkcs11); -#ifdef DOM - CLEAR(decoder->span_prototype); - CLEAR(decoder->transclusion_prototype); -#endif - /* Drop ad-hoc GC roots, but not opener -- it survives unloads. */ CLEAR(decoder->event_receiver);