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; }
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); } } }