예제 #1
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;
}
예제 #2
0
void
lo_EndMulticolumn(MWContext *context, lo_DocState *state, PA_Tag *tag,
			lo_MultiCol *multicol, Bool relayout)
{
	int32 i;
	lo_ListStack *lptr;
	int32 height;
	int32 col_height;
	int32 x, y;
	int32 line1, line2;
	int32 save_doc_min_width;
	int32 min_multi_width;
	LO_Element *cell_list;
	LO_Element *cell_list_end;
	LO_Element *cell_ele;
	LO_TableStruct *table_ele;
	LO_Element *ele;

	cell_ele = NULL;
	cell_list = NULL;
	cell_list_end = NULL;
	
	lo_SetLineBreakState (context, state, FALSE, LO_LINEFEED_BREAK_SOFT, 1, relayout);

	multicol->end_line = state->line_num;
	multicol->end_y = state->y;

	/*
	 * Break to clear all left and right margins.
	 */
	lo_ClearToBothMargins(context, state);

	/*
	 * Reset the margins properly in case
	 * we are inside a list.
	 */
	lo_FindLineMargins(context, state, !relayout);
	state->x = state->left_margin;

	height = multicol->end_y - multicol->start_y;
	col_height = height / multicol->cols;
	if (col_height < 1)
	{
		col_height = 1;
	}

	x = state->x;
	y = multicol->start_y;
	line1 = multicol->start_line - 1;
	for (i=0; i<multicol->cols; i++)
	{
		LO_CellStruct *cell;
		LO_Element *eptr;
		int32 line;
		int32 dx, dy;
		int32 move_height;

		eptr = lo_FirstElementOfLine(context, state, line1);
		if (eptr == NULL)
		{
			break;
		}
		y = eptr->lo_any.y + col_height;

		line = lo_PointToLine(context, state, x, y);
		eptr = lo_FirstElementOfLine(context, state, line);
		if (eptr->lo_any.x > multicol->start_x)
		{
			line = lo_find_breaking_line(context, state, line,
				multicol->start_x,
				(multicol->start_x + multicol->col_width));
		}

		line2 = line;
		if (line2 > (multicol->end_line - 2))
		{
			line2 = (multicol->end_line - 2);
		}
		cell = NULL;
		if (i > 0)
		{
			eptr = lo_FirstElementOfLine(context, state, line1);
			if (eptr != NULL)
			{
				dx = i * (multicol->col_width +
						multicol->gutter);
				dy = multicol->start_y - eptr->lo_any.y;
				cell = lo_CaptureLines(context, state,
					multicol->col_width,
					line1, line2, dx, dy);
				if (cell == NULL)
				{
					move_height = 0;
				}
				else
				{
					move_height = cell->height - 1;
				}
			}
			else
			{
				move_height = 0;
			}
		}
		else
		{
			cell = lo_CaptureLines(context, state,
				multicol->col_width,
				line1, line2, 0, 0);
			if (cell == NULL)
			{
				move_height = 0;
			}
			else
			{
				move_height = cell->height - 1;
			}
		}
		line1 = line2 + 1;
		if (move_height > col_height)
		{
			col_height = move_height;
		}

		if (cell != NULL)
		{
			if (cell_list_end == NULL)
			{
				cell_list = (LO_Element *)cell;
				cell_list_end = cell_list;
			}
			else
			{
				cell_list_end->lo_any.next = (LO_Element *)cell;
				cell_list_end = cell_list_end->lo_any.next;
			}
		}
	}

	lptr = lo_PopList(state, tag);
	if (lptr != NULL)
	{
		XP_DELETE(lptr);
	}
	state->left_margin = state->list_stack->old_left_margin;
	state->right_margin = state->list_stack->old_right_margin;

	state->top_state->element_id = multicol->start_ele;

	lo_SetLineArrayEntry(state, NULL, (multicol->start_line - 1));
	state->line_num = multicol->start_line;
	state->end_last_line = multicol->end_last_line;
	if (state->end_last_line != NULL)
	{
		state->end_last_line->lo_any.next = NULL;
	}
	state->line_list = NULL;
	state->y = multicol->start_y;

	state->display_blocked = multicol->orig_display_blocked;
	state->display_blocking_element_y = multicol->orig_display_blocking_element_y;

	table_ele = (LO_TableStruct *)lo_NewElement(context, state, LO_TABLE,
					NULL, 0);
	if (table_ele == NULL)
	{
		state->top_state->out_of_memory = TRUE;
        if (multicol->close_table)
            lo_CloseTable(context, state);
		return;
	}

	table_ele->type = LO_TABLE;
	table_ele->ele_id = NEXT_ELEMENT;
	table_ele->x = x;
	table_ele->x_offset = 0;
	table_ele->y = multicol->start_y;
	table_ele->y_offset = 0;
	table_ele->width = (multicol->cols * multicol->col_width) +
				((multicol->cols - 1) * multicol->gutter);
	table_ele->height = col_height + 1;
	table_ele->line_height = col_height + 1;
	table_ele->FE_Data = NULL;
	table_ele->anchor_href = NULL;
	table_ele->alignment = LO_ALIGN_LEFT;
	table_ele->border_width = 0;
	table_ele->border_vert_space = 0;
	table_ele->border_horiz_space = 0;
    table_ele->border_style = BORDER_NONE;
	table_ele->ele_attrmask = 0;
	table_ele->sel_start = -1;
	table_ele->sel_end = -1;
	table_ele->next = NULL;
	table_ele->prev = NULL;
	table_ele->table = NULL;
	lo_AppendToLineList(context, state, (LO_Element *)table_ele, 0);

	while (cell_list != NULL)
	{
		cell_ele = cell_list;
		cell_list = cell_list->lo_any.next;
		cell_ele->lo_any.next = NULL;
		cell_ele->lo_any.ele_id = NEXT_ELEMENT;
		lo_RenumberCell(state, (LO_CellStruct *)cell_ele);
		lo_AppendToLineList(context, state, cell_ele, 0);
	}

	if (cell_ele != NULL)
	{
		state->x = cell_ele->lo_any.x + multicol->col_width;
	}
	else
	{
		state->x = table_ele->x + table_ele->width;
	}
	state->baseline = 0;
	state->line_height = col_height + 1;
	state->linefeed_state = 0;
	state->at_begin_line = FALSE;
	state->trailing_space = FALSE;
	state->cur_ele_type = LO_SUBDOC;


	min_multi_width = (state->min_width * multicol->cols) +
				((multicol->cols - 1) * multicol->gutter);
	state->min_width = multicol->orig_min_width;
	save_doc_min_width = state->min_width;

	lo_SetLineBreakState (context, state, FALSE, LO_LINEFEED_BREAK_SOFT, 2, relayout);

	if (min_multi_width > save_doc_min_width)
	{
		save_doc_min_width = min_multi_width;
	}
	state->min_width = save_doc_min_width;

	state->current_multicol = multicol->next;

    if (!relayout)
	{
		if (multicol->close_table) {
			PA_Tag *tmp_tag;
			if (state->in_paragraph != FALSE)
			{
	            lo_CloseParagraph(context, &state, tag, 2);
			}
		    tmp_tag = PA_CloneMDLTag(tag); 
			lo_SaveSubdocTags(context, state, tmp_tag);
			lo_CloseTable(context, state);
		}
	}
}