home *** CD-ROM | disk | FTP | other *** search
- /* -*- 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"
-
-
- #define SPACE_WORD 1
- #define SPACE_LINE 2
- #define SPACE_BLOCK 3
-
- static void lo_AppendSpacerElementToLineList( MWContext *context, lo_DocState *state,
- LO_SpacerStruct *spacer );
- static void lo_ParseAttributesForBlockSpacer( MWContext *context, lo_DocState *state,
- LO_SpacerStruct *spacer );
- static void lo_LayoutBlockSpacer(MWContext *context, lo_DocState *state,
- LO_SpacerStruct *spacer, Bool relayout);
-
- void
- lo_ProcessSpacerTag(MWContext *context, lo_DocState *state, PA_Tag *tag)
- {
- int32 type;
- int32 size;
- PA_Block buff;
- LO_SpacerStruct *spacer;
-
- spacer = (LO_SpacerStruct*)lo_NewElement(context, state, LO_SPACER, NULL, 0);
- XP_ASSERT(spacer);
- if (!spacer)
- {
- state->top_state->out_of_memory = TRUE;
- return;
- }
-
- type = SPACE_WORD;
- buff = lo_FetchParamValue(context, tag, PARAM_TYPE);
- if (buff != NULL)
- {
- char *type_str;
-
- PA_LOCK(type_str, char *, buff);
- if (pa_TagEqual("line", type_str))
- {
- type = SPACE_LINE;
- }
- else if (pa_TagEqual("vert", type_str))
- {
- type = SPACE_LINE;
- }
- else if (pa_TagEqual("vertical", type_str))
- {
- type = SPACE_LINE;
- }
- else if (pa_TagEqual("block", type_str))
- {
- type = SPACE_BLOCK;
- }
- PA_UNLOCK(buff);
- PA_FREE(buff);
- }
-
- size = 0;
- buff = lo_FetchParamValue(context, tag, PARAM_SIZE);
- if (buff != NULL)
- {
- char *str;
-
- PA_LOCK(str, char *, buff);
- size = XP_ATOI(str);
- PA_UNLOCK(buff);
- PA_FREE(buff);
- if (size < 1)
- {
- size = 0;
- }
- }
-
- spacer->size = size;
- spacer->type = (int8) type;
- spacer->tag = tag;
-
- lo_AppendSpacerElementToLineList( context, state, spacer );
- lo_LayoutSpacerElement(context, state, spacer, FALSE);
-
- /*
- * Spacers of size 0 do nothing.
- * Unless they are block spacers that use WIDTH and HEIGHT.
- */
- /*
- if ((size == 0)&&(type != SPACE_BLOCK))
- {
- return;
- }
-
- if (type == SPACE_WORD)
- {
- lo_InsertWordBreak(context, state);
- size = FEUNITS_X(size, context);
- state->x += size;
- }
- else if (type == SPACE_LINE)
- {
- lo_SetSoftLineBreakState(context, state, FALSE, 1);
- size = FEUNITS_Y(size, context);
- state->y += size;
- }
- else if (type == SPACE_BLOCK)
- {
- lo_format_block_spacer(context, state, tag);
- }
- */
- }
-
- static void lo_AppendSpacerElementToLineList( MWContext *context, lo_DocState *state, LO_SpacerStruct *spacer )
- {
- spacer->lo_any.type = LO_SPACER;
- spacer->lo_any.x = state->x;
- spacer->lo_any.y = state->y;
- spacer->lo_any.x_offset = 0;
- spacer->lo_any.y_offset = 0;
- spacer->lo_any.width = 0;
- spacer->lo_any.height = 0;
- spacer->lo_any.line_height = 0;
- spacer->lo_any.ele_id = NEXT_ELEMENT;
-
- lo_AppendToLineList(context, state, (LO_Element*)spacer, 0);
- }
-
-
- void lo_LayoutSpacerElement(MWContext *context, lo_DocState *state, LO_SpacerStruct *spacer, Bool relayout)
- {
- int32 size = spacer->size;
- int8 type = spacer->type;
-
- /*
- * Spacers of size 0 do nothing.
- * Unless they are block spacers that use WIDTH and HEIGHT.
- */
- if ((size == 0)&&(type != SPACE_BLOCK))
- {
- return;
- }
-
- if (type == SPACE_WORD)
- {
- if (!relayout)
- lo_InsertWordBreak(context, state);
-
- size = FEUNITS_X(size, context);
- state->x += size;
- }
- else if (type == SPACE_LINE)
- {
- /* lo_SetSoftLineBreakState(context, state, FALSE, 1); */
- lo_SetLineBreakState(context, state, FALSE, LO_LINEFEED_BREAK_SOFT, 1, relayout);
- size = FEUNITS_Y(size, context);
- state->y += size;
- }
- else if (type == SPACE_BLOCK)
- {
- if (!relayout)
- {
- lo_ParseAttributesForBlockSpacer(context, state, spacer);
- }
-
- lo_LayoutBlockSpacer(context, state, spacer, relayout);
- }
-
- if (!relayout)
- {
- /* We do not want to keep a pointer to the tag around for relayout
- because we have all the information we need in the LO_SPACER
- layout element */
- spacer->tag = NULL;
- }
- }
-
-
- static void lo_ParseAttributesForBlockSpacer( MWContext *context, lo_DocState *state, LO_SpacerStruct *spacer )
- {
- Bool floating;
- int32 alignment;
- int32 val;
- PA_Block buff;
- PA_Tag *tag = spacer->tag;
- char *str;
-
- alignment = LO_ALIGN_BASELINE;
- floating = FALSE;
-
- /*
- * Check for an align parameter
- */
- buff = lo_FetchParamValue(context, tag, PARAM_ALIGN);
- if (buff != NULL)
- {
- PA_LOCK(str, char *, buff);
- alignment = lo_EvalAlignParam(str, &floating);
- PA_UNLOCK(buff);
- PA_FREE(buff);
- }
- spacer->alignment = alignment;
- spacer->floating = floating;
-
- /*
- * Get the width parameter, in absolute or percentage.
- * If percentage, make it absolute.
- */
- buff = lo_FetchParamValue(context, tag, PARAM_WIDTH);
- if (buff != NULL)
- {
- Bool is_percent;
-
- PA_LOCK(str, char *, buff);
- val = lo_ValueOrPercent(str, &is_percent);
- if (is_percent != FALSE)
- {
- spacer->is_percent_width = TRUE;
- spacer->width = val;
- }
- else
- {
- spacer->is_percent_width = FALSE;
- val = FEUNITS_X(val, context);
- if (val < 1)
- {
- val = 1;
- }
- spacer->width = val;
- }
- PA_UNLOCK(buff);
- PA_FREE(buff);
- }
-
- /*
- * Get the height parameter, in absolute or percentage.
- * If percentage, make it absolute.
- */
- buff = lo_FetchParamValue(context, tag, PARAM_HEIGHT);
- if (buff != NULL)
- {
- Bool is_percent;
-
- PA_LOCK(str, char *, buff);
- val = lo_ValueOrPercent(str, &is_percent);
- if (is_percent != FALSE)
- {
- spacer->is_percent_height = TRUE;
- spacer->height = val;
- }
- else
- {
- spacer->is_percent_height = FALSE;
- val = FEUNITS_Y(val, context);
- if (val < 1)
- {
- val = 1;
- }
- spacer->height = val;
- }
- PA_UNLOCK(buff);
- PA_FREE(buff);
- }
- }
-
- static void lo_LayoutBlockSpacer(MWContext *context, lo_DocState *state, LO_SpacerStruct *spacer, Bool relayout)
- {
- int32 width = 0;
- int32 height = 0;
- int32 doc_width;
- int32 alignment = spacer->alignment;
- Bool floating = spacer->floating;
- Bool line_break;
- char *str;
- int32 x, y;
- int16 x_offset;
- int32 y_offset;
- int32 baseline_inc, line_inc;
- LO_TextStruct tmp_text;
- LO_TextInfo text_info;
- LO_Element *eptr;
- PA_Block buff;
-
- x = state->x;
- y = state->y;
- doc_width = state->right_margin - state->left_margin;
-
- if (spacer->is_percent_width)
- {
- int32 val;
-
- if (state->allow_percent_width == FALSE)
- {
- val = 0;
- }
- else
- {
- val = spacer->width;
- val = doc_width * val / 100;
- if (val < 1)
- {
- val = 1;
- }
- }
-
- width = val;
- }
- else
- {
- width = spacer->width;
- }
-
- if (spacer->is_percent_height)
- {
- int32 val;
-
- if (state->allow_percent_height == FALSE)
- {
- val = 0;
- }
- else
- {
- val = state->win_height * val / 100;
- if (val < 1)
- {
- val = 1;
- }
- }
- height = val;
- }
- else
- {
- height = spacer->height;
- }
-
-
- /*
- * 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;
- }
- PA_LOCK(str, char *, buff);
- str[0] = ' ';
- PA_UNLOCK(buff);
- tmp_text.text = buff;
- tmp_text.text_len = 1;
- tmp_text.text_attr = state->font_stack->text_attr;
- FE_GetTextInfo(context, &tmp_text, &text_info);
- PA_FREE(buff);
-
- /*
- * If both dimentions are bogus, no spacer.
- * If only one dimension bogus, then make it 1.
- */
- if ((width < 1)&&(height < 1))
- {
- return;
- }
- else if (width < 1)
- {
- width = 1;
- }
- else if (height < 1)
- {
- height = 1;
- }
-
-
- /*
- * SEVERE FLOW BREAK! This may be a floating image,
- * which means at this point we go do something completely
- * different.
- */
- if (floating != FALSE)
- {
- if (alignment == LO_ALIGN_RIGHT)
- {
- if (state->right_margin_stack == NULL)
- {
- x = state->right_margin - width;
- }
- else
- {
- x = state->right_margin_stack->margin - width;
- }
- if (x < 0)
- {
- x = 0;
- }
- }
- else
- {
- x = state->left_margin;
- }
-
- y = -1;
-
- lo_AddMarginStack(state, x, y,
- width, height, 0, 0, 0, alignment);
-
- if (state->at_begin_line != FALSE)
- {
- lo_FindLineMargins(context, state, !relayout);
- state->x = state->left_margin;
- }
-
- return;
- }
-
- /*
- * Will this spacer make the line too wide.
- */
- if ((state->x + 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 unmapped preformatted 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 spacer if we have
- * a break.
- */
- if (line_break != FALSE)
- {
- if (!relayout)
- lo_SoftLineBreak(context, state, TRUE);
- else
- lo_rl_AddSoftBreakAndFlushLine(context, state);
-
- x = state->x;
- y = state->y;
- }
-
- /*
- * Figure out how to align this spacer.
- * 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;
- x_offset = 0;
- y_offset = 0;
-
- lo_CalcAlignOffsets(state, &text_info, alignment,
- width, height,
- &x_offset, &y_offset, &line_inc, &baseline_inc);
-
- width += x_offset;
- height += y_offset;
-
- /*
- * Change the rest of the line the way lo_AppendToLineList()
- * would if we were adding a real element.
- */
- eptr = state->line_list;
- if (eptr != NULL)
- {
- 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;
- }
-
- state->baseline += (intn) baseline_inc;
- state->line_height += (intn) (baseline_inc + line_inc);
-
- /*
- * Clean up state
- */
- state->x = state->x + width;
- state->linefeed_state = 0;
- state->at_begin_line = FALSE;
- state->trailing_space = FALSE;
- state->cur_ele_type = LO_NONE;
- }
-
- #if 0
- void
- lo_format_block_spacer(MWContext *context, lo_DocState *state, PA_Tag *tag, Bool relayout)
- {
- Bool line_break;
- Bool floating;
- int32 baseline_inc, line_inc;
- int32 alignment;
- int16 x_offset;
- int32 y_offset;
- int32 x, y;
- int32 width, height;
- int32 doc_width;
- int32 val;
- PA_Block buff;
- char *str;
- LO_TextStruct tmp_text;
- LO_TextInfo text_info;
- LO_Element *eptr;
-
- x = state->x;
- y = state->y;
- width = 0;
- height = 0;
- alignment = LO_ALIGN_BASELINE;
- floating = FALSE;
-
- /*
- * Check for an align parameter
- */
- buff = lo_FetchParamValue(context, tag, PARAM_ALIGN);
- if (buff != NULL)
- {
-
- PA_LOCK(str, char *, buff);
- alignment = lo_EvalAlignParam(str, &floating);
- PA_UNLOCK(buff);
- PA_FREE(buff);
- }
-
- doc_width = state->right_margin - state->left_margin;
-
- /*
- * Get the width parameter, in absolute or percentage.
- * If percentage, make it absolute.
- */
- buff = lo_FetchParamValue(context, tag, PARAM_WIDTH);
- if (buff != NULL)
- {
- Bool is_percent;
-
- PA_LOCK(str, char *, buff);
- val = lo_ValueOrPercent(str, &is_percent);
- if (is_percent != FALSE)
- {
- if (state->allow_percent_width == FALSE)
- {
- val = 0;
- }
- else
- {
- val = doc_width * val / 100;
- if (val < 1)
- {
- val = 1;
- }
- }
- }
- else
- {
- val = FEUNITS_X(val, context);
- if (val < 1)
- {
- val = 1;
- }
- }
- width = val;
- PA_UNLOCK(buff);
- PA_FREE(buff);
- }
-
- /*
- * Get the height parameter, in absolute or percentage.
- * If percentage, make it absolute.
- */
- buff = lo_FetchParamValue(context, tag, PARAM_HEIGHT);
- if (buff != NULL)
- {
- Bool is_percent;
-
- PA_LOCK(str, char *, buff);
- val = lo_ValueOrPercent(str, &is_percent);
- if (is_percent != FALSE)
- {
- if (state->allow_percent_height == FALSE)
- {
- val = 0;
- }
- else
- {
- val = state->win_height * val / 100;
- if (val < 1)
- {
- val = 1;
- }
- }
- }
- else
- {
- val = FEUNITS_Y(val, context);
- if (val < 1)
- {
- val = 1;
- }
- }
- height = val;
- PA_UNLOCK(buff);
- PA_FREE(buff);
- }
-
- /*
- * 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;
- }
- PA_LOCK(str, char *, buff);
- str[0] = ' ';
- PA_UNLOCK(buff);
- tmp_text.text = buff;
- tmp_text.text_len = 1;
- tmp_text.text_attr = state->font_stack->text_attr;
- FE_GetTextInfo(context, &tmp_text, &text_info);
- PA_FREE(buff);
-
- /*
- * If both dimentions are bogus, no spacer.
- * If only one dimension bogus, then make it 1.
- */
- if ((width < 1)&&(height < 1))
- {
- return;
- }
- else if (width < 1)
- {
- width = 1;
- }
- else if (height < 1)
- {
- height = 1;
- }
-
-
- /*
- * SEVERE FLOW BREAK! This may be a floating image,
- * which means at this point we go do something completely
- * different.
- */
- if (floating != FALSE)
- {
- if (alignment == LO_ALIGN_RIGHT)
- {
- if (state->right_margin_stack == NULL)
- {
- x = state->right_margin - width;
- }
- else
- {
- x = state->right_margin_stack->margin - width;
- }
- if (x < 0)
- {
- x = 0;
- }
- }
- else
- {
- x = state->left_margin;
- }
-
- y = -1;
-
- lo_AddMarginStack(state, x, y,
- width, height, 0, 0, 0, alignment);
-
- if (state->at_begin_line != FALSE)
- {
- lo_FindLineMargins(context, state, TRUE);
- state->x = state->left_margin;
- }
-
- return;
- }
-
- /*
- * Will this spacer make the line too wide.
- */
- if ((state->x + 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 unmapped preformatted 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 spacer if we have
- * a break.
- */
- if (line_break != FALSE)
- {
- lo_SoftLineBreak(context, state, TRUE);
- x = state->x;
- y = state->y;
- }
-
- /*
- * Figure out how to align this spacer.
- * 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;
- x_offset = 0;
- y_offset = 0;
-
- lo_CalcAlignOffsets(state, &text_info, alignment,
- width, height,
- &x_offset, &y_offset, &line_inc, &baseline_inc);
-
- width += x_offset;
- height += y_offset;
-
- /*
- * Change the rest of the line the way lo_AppendToLineList()
- * would if we were adding a real element.
- */
- eptr = state->line_list;
- if (eptr != NULL)
- {
- 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;
- }
-
- state->baseline += (intn) baseline_inc;
- state->line_height += (intn) (baseline_inc + line_inc);
-
- /*
- * Clean up state
- */
- state->x = state->x + width;
- state->linefeed_state = 0;
- state->at_begin_line = FALSE;
- state->trailing_space = FALSE;
- state->cur_ele_type = LO_NONE;
- }
- #endif
-