/* -*- 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 "net.h" #include "pa_parse.h" #include "layout.h" #include "laylayer.h" #include "np.h" #include "laystyle.h" #include "layers.h" #ifdef ANTHRAX /* 9.23.97 amusil */ #include "prefapi.h" #endif /* ANTHRAX */ #ifdef XP_WIN16 #define SIZE_LIMIT 32000 #endif /* XP_WIN16 */ #define EMBED_DEF_DIM 50 #define EMBED_DEF_BORDER 0 #define EMBED_DEF_VERTICAL_SPACE 0 #define EMBED_DEF_HORIZONTAL_SPACE 0 void lo_FinishEmbed(MWContext *, lo_DocState *, LO_EmbedStruct *); static void lo_FormatEmbedInternal(MWContext *, lo_DocState *, PA_Tag *, LO_EmbedStruct *, Bool, Bool); void lo_AddEmbedData(MWContext *context, void *session_data, lo_FreeProc freeProc, int32 indx) { int32 doc_id; lo_TopState *top_state; lo_DocState *state; lo_SavedEmbedListData *embed_list; lo_EmbedDataElement* embed_data_list; int32 old_count; /* * Get the state, so we can access the savedEmbedListData * list for this document. */ doc_id = XP_DOCID(context); top_state = lo_FetchTopState(doc_id); if ((top_state != NULL) && (top_state->doc_state != NULL)) state = top_state->doc_state; else return; embed_list = state->top_state->savedData.EmbedList; if (embed_list == NULL) return; /* * We may have to grow the list to fit this new data. */ if (indx >= embed_list->embed_count) { PA_Block old_embed_data_list; /* really a (lo_EmbedDataElement **) */ #ifdef XP_WIN16 /* * On 16 bit windows arrays can just get too big. */ if (((indx + 1) * sizeof(lo_EmbedDataElement)) > SIZE_LIMIT) return; #endif /* XP_WIN16 */ old_count = embed_list->embed_count; embed_list->embed_count = indx + 1; old_embed_data_list = NULL; if (old_count == 0) /* Allocate new array */ { embed_list->embed_data_list = PA_ALLOC( embed_list->embed_count * sizeof(lo_EmbedDataElement)); } else /* Enlarge existing array */ { old_embed_data_list = embed_list->embed_data_list; embed_list->embed_data_list = PA_REALLOC( embed_list->embed_data_list, (embed_list->embed_count * sizeof(lo_EmbedDataElement))); } /* * If we ran out of memory to grow the array. */ if (embed_list->embed_data_list == NULL) { embed_list->embed_data_list = old_embed_data_list; embed_list->embed_count = old_count; state->top_state->out_of_memory = TRUE; return; } /* * We enlarged the array, so make sure * the new slots are zero-filled. */ PA_LOCK(embed_data_list, lo_EmbedDataElement*, embed_list->embed_data_list); while (old_count < embed_list->embed_count) { embed_data_list[old_count].data = NULL; embed_data_list[old_count].freeProc = NULL; old_count++; } PA_UNLOCK(embed_list->embed_data_list); } /* * Store the new data into the list. */ PA_LOCK(embed_data_list, lo_EmbedDataElement*, embed_list->embed_data_list); embed_data_list[indx].data = session_data; embed_data_list[indx].freeProc = freeProc; PA_UNLOCK(embed_list->embed_data_list); } void LO_ClearEmbedBlock(MWContext *context, LO_EmbedStruct *embed) { int32 doc_id; lo_TopState *top_state; lo_DocState *main_doc_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; } if (top_state->layout_blocking_element == (LO_Element *)embed) { if (embed->width == 0) { embed->width = EMBED_DEF_DIM; } if (embed->height == 0) { embed->height = EMBED_DEF_DIM; } main_doc_state = top_state->doc_state; state = lo_CurrentSubState(main_doc_state); lo_FinishEmbed(context, state, embed); lo_FlushBlockage(context, state, main_doc_state); } } void lo_FormatEmbed(MWContext *context, lo_DocState *state, PA_Tag *tag) { LO_EmbedStruct *embed; #ifdef ANTHRAX LO_ObjectStruct* object; PA_Block buff; NET_cinfo* fileInfo; char* str; char* appletName; uint32 src_len; /* check to see if the type maps to an applet */ buff = lo_FetchParamValue(context, tag, PARAM_TYPE); if(buff == NULL) { /* get SRC */ buff = lo_FetchParamValue(context, tag, PARAM_SRC); PA_LOCK(str, char *, buff); /* if we didn't find a type param, look for an association in the SRC */ fileInfo = NET_cinfo_find_type(str); str = fileInfo->type; } else PA_LOCK(str, char *, buff); /* check to see if this mimetype has an applet handler */ if((appletName = NPL_FindAppletEnabledForMimetype(str)) != NULL) { PA_UNLOCK(buff); if(buff) XP_FREE(buff); /* just pass it to our object handler */ lo_FormatObject(context, state, tag); /* manually close the java app - this is normally done in lo_ProcessObjectTag */ lo_CloseJavaApp(context, state, state->current_java); XP_FREE(appletName); } else { PA_UNLOCK(buff); if(buff) XP_FREE(buff); #endif /* ANTHRAX */ embed = (LO_EmbedStruct *)lo_NewElement(context, state, LO_EMBED, NULL, 0); if (embed == NULL) { return; } embed->type = LO_EMBED; embed->ele_id = NEXT_ELEMENT; embed->x = state->x; embed->x_offset = 0; embed->y = state->y; embed->y_offset = 0; embed->width = 0; embed->height = 0; embed->next = NULL; embed->prev = NULL; embed->attribute_cnt = 0; embed->attribute_list = NULL; embed->value_list = NULL; embed->attribute_cnt = PA_FetchAllNameValues(tag, &(embed->attribute_list), &(embed->value_list), CS_FE_ASCII); lo_FormatEmbedInternal(context, state, tag, embed, FALSE, FALSE); #ifdef ANTHRAX } #endif /* ANTHRAX */ } void lo_FormatEmbedObject(MWContext* context, lo_DocState* state, PA_Tag* tag , LO_EmbedStruct* embed, Bool streamStarted, uint32 param_count, char** param_names, char** param_values) { uint32 count; int32 typeIndex = -1; int32 classidIndex = -1; embed->attribute_cnt = 0; embed->attribute_list = NULL; embed->value_list = NULL; embed->attribute_cnt = PA_FetchAllNameValues(tag, &(embed->attribute_list), &(embed->value_list), CS_FE_ASCII); /* * Look through the parameters and replace "id" * with "name" and "data" with "src", so that * other code that looks up parameters by name * can believe this is a normal EMBED. */ for (count = 0; count < (uint32)embed->attribute_cnt; count++) { if (XP_STRCASECMP(embed->attribute_list[count], PARAM_ID) == 0) StrAllocCopy(embed->attribute_list[count], PARAM_NAME); else if (XP_STRCASECMP(embed->attribute_list[count], PARAM_DATA) == 0) StrAllocCopy(embed->attribute_list[count], "src"); else if (XP_STRCASECMP(embed->attribute_list[count], PARAM_TYPE) == 0) typeIndex = count; else if (XP_STRCASECMP(embed->attribute_list[count], PARAM_CLASSID) == 0) classidIndex = count; } /* * If we have a CLASSID attribute, add the appropriate * TYPE attribute. */ if (classidIndex >= 0) { if (typeIndex >= 0) { /* Change current value of TYPE to application/oleobject */ if (XP_STRCASECMP(embed->value_list[typeIndex], APPLICATION_OLEOBJECT) != 0) StrAllocCopy(embed->value_list[typeIndex], APPLICATION_OLEOBJECT); } else { /* Add TYPE=application/oleobject to the attribute list */ char* names[1]; char* values[1]; names[0] = XP_STRDUP(PARAM_TYPE); values[0] = XP_STRDUP(APPLICATION_OLEOBJECT); lo_AppendParamList((uint32*) &(embed->attribute_cnt), &(embed->attribute_list), &(embed->value_list), 1, names, values); } /* Lop off the "clsid:" prefix from the CLASSID attribute */ if (XP_STRNCASECMP(embed->value_list[classidIndex], "clsid:", 6) == 0) { char* classID = &(embed->value_list[classidIndex][6]); XP_MEMMOVE(embed->value_list[classidIndex], classID, (XP_STRLEN(classID) + 1) * sizeof(char)); } } /* * Merge any parameters passed in with the ones in this tag. * Separate the merged tag attributes from the * tag attributes with an extra "PARAM" attribute. */ if (param_count > 0) { char* names[1]; char* values[1]; names[0] = XP_STRDUP(PT_PARAM); values[0] = NULL; /* Add "PARAM" to the list */ lo_AppendParamList((uint32*) &(embed->attribute_cnt), &(embed->attribute_list), &(embed->value_list), 1, names, values); /* Add all tag paramters to the list */ lo_AppendParamList((uint32*) &(embed->attribute_cnt), &(embed->attribute_list), &(embed->value_list), param_count, param_names, param_values); if (param_names != NULL) XP_FREE(param_names); if (param_values != NULL) XP_FREE(param_values); } lo_FormatEmbedInternal(context, state, tag, embed, TRUE, streamStarted); } static void lo_FormatEmbedInternal(MWContext *context, lo_DocState *state, PA_Tag *tag, LO_EmbedStruct *embed, Bool isObject, Bool streamStarted) { PA_Block buff; char *str; int32 val; int32 doc_width; XP_Bool widthSpecified = FALSE; XP_Bool heightSpecified = FALSE; lo_DocLists *doc_lists; embed->nextEmbed= NULL; #ifdef MOCHA embed->mocha_object = NULL; #endif embed->FE_Data = NULL; embed->session_data = NULL; embed->line_height = state->line_height; embed->embed_src = NULL; embed->alignment = LO_ALIGN_BASELINE; embed->border_width = EMBED_DEF_BORDER; embed->border_vert_space = EMBED_DEF_VERTICAL_SPACE; embed->border_horiz_space = EMBED_DEF_HORIZONTAL_SPACE; embed->tag = tag; embed->ele_attrmask = 0; if (streamStarted) embed->ele_attrmask |= LO_ELE_STREAM_STARTED; /* * Convert any javascript in the values */ lo_ConvertAllValues(context, embed->value_list, embed->attribute_cnt, tag->newline_count); /* don't double-count loading plugins due to table relayout */ if (!state->in_relayout) { state->top_state->mocha_loading_embeds_count++; } /* * Assign a unique index for this object * and increment the master index. */ embed->embed_index = state->top_state->embed_count++; /* * Check for the hidden attribute value. * HIDDEN embeds have no visible part. */ if (!isObject) /* OBJECT tag can't have "hidden" attribute */ { buff = lo_FetchParamValue(context, tag, PARAM_HIDDEN); if (buff != NULL) { Bool hidden; hidden = TRUE; PA_LOCK(str, char *, buff); if (pa_TagEqual("no", str)) { hidden = FALSE; } else if (pa_TagEqual("false", str)) { hidden = FALSE; } else if (pa_TagEqual("off", str)) { hidden = FALSE; } PA_UNLOCK(buff); PA_FREE(buff); if (hidden != FALSE) { embed->ele_attrmask |= LO_ELE_HIDDEN; /* marcb says: had to disable the printed hidden audio feature */ if (context->type==MWContextPrint){ return; } } } } /* * Check for an align parameter */ buff = lo_FetchParamValue(context, tag, PARAM_ALIGN); if (buff != NULL) { Bool floating; floating = FALSE; PA_LOCK(str, char *, buff); embed->alignment = lo_EvalAlignParam(str, &floating); if (floating != FALSE) { embed->ele_attrmask |= LO_ELE_FLOATING; } PA_UNLOCK(buff); PA_FREE(buff); } /* * Get the optional src parameter. */ if (isObject) buff = lo_FetchParamValue(context, tag, PARAM_DATA); else buff = lo_FetchParamValue(context, tag, PARAM_SRC); if (buff != NULL) { PA_Block new_buff; char *new_str; int32 len; len = 1; PA_LOCK(str, char *, buff); if (str != NULL) { len = lo_StripTextWhitespace(str, XP_STRLEN(str)); } if (str != NULL) { /* bing: make sure this deals with "data:" URLs */ new_str = NET_MakeAbsoluteURL( state->top_state->base_url, str); } else { new_str = NULL; } if ((new_str == NULL)||(len == 0)) { new_buff = NULL; } else { char *enbed_src; new_buff = PA_ALLOC(XP_STRLEN(new_str) + 1); if (new_buff != NULL) { PA_LOCK(enbed_src, char *, new_buff); XP_STRCPY(enbed_src, new_str); PA_UNLOCK(new_buff); } else { state->top_state->out_of_memory = TRUE; } XP_FREE(new_str); } PA_UNLOCK(buff); PA_FREE(buff); buff = new_buff; } embed->embed_src = buff; doc_width = state->right_margin - state->left_margin; /* * Get the width parameter, in absolute or percentage. * If percentage, make it absolute. If the height is * zero, make the embed hidden so the FE knows that the * size really is zero (zero size normally means that * we're blocking). */ 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) { embed->percent_width = val; } else { embed->percent_width = 0; embed->width = val; val = FEUNITS_X(val, context); } PA_UNLOCK(buff); PA_FREE(buff); widthSpecified = TRUE; } val = LO_GetWidthFromStyleSheet(context, state); if(val) { embed->width = val; embed->percent_width = 0; widthSpecified = TRUE; } /* * Get the height parameter, in absolute or percentage. * If percentage, make it absolute. If the height is * zero, make the embed hidden so the FE knows that the * size really is zero (zero size normally means that * we're blocking). */ 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) { embed->percent_height = val; } else { embed->percent_height = 0; val = FEUNITS_Y(val, context); } embed->height = val; PA_UNLOCK(buff); PA_FREE(buff); heightSpecified = TRUE; } val = LO_GetHeightFromStyleSheet(context, state); if(val) { embed->height = val; embed->percent_height = 0; heightSpecified = TRUE; } #ifndef XP_WIN /* * If they forgot to specify a width or height, make one up. * Don't do this for Windows, because they want to block * layout for unsized OLE objects. (Eventually all FEs will * want to support this behavior when there's a plug-in API * to specify the desired size of the object.) */ if (!widthSpecified) { if (heightSpecified) embed->width = embed->height; else embed->width = EMBED_DEF_DIM; } if (!heightSpecified) { if (widthSpecified) embed->height = embed->width; else embed->height = EMBED_DEF_DIM; } #endif /* ifndef XP_WIN */ lo_FillInEmbedGeometry(state, embed, FALSE); /* * Get the extra vertical space parameter. */ buff = lo_FetchParamValue(context, tag, PARAM_VSPACE); if (buff != NULL) { PA_LOCK(str, char *, buff); val = XP_ATOI(str); if (val < 0) { val = 0; } embed->border_vert_space = val; PA_UNLOCK(buff); PA_FREE(buff); } embed->border_vert_space = FEUNITS_Y(embed->border_vert_space, context); /* * Get the extra horizontal space parameter. */ buff = lo_FetchParamValue(context, tag, PARAM_HSPACE); if (buff != NULL) { PA_LOCK(str, char *, buff); val = XP_ATOI(str); if (val < 0) { val = 0; } embed->border_horiz_space = val; PA_UNLOCK(buff); PA_FREE(buff); } embed->border_horiz_space = FEUNITS_X(embed->border_horiz_space, context); /* * See if we have some saved embed session data to restore. */ if (state->top_state->savedData.EmbedList != NULL) { lo_SavedEmbedListData *embed_list; embed_list = state->top_state->savedData.EmbedList; /* * If there is still valid data to restore available. */ if (embed->embed_index < embed_list->embed_count) { lo_EmbedDataElement* embed_data_list; PA_LOCK(embed_data_list, lo_EmbedDataElement*, embed_list->embed_data_list); embed->session_data = embed_data_list[embed->embed_index].data; PA_UNLOCK(embed_list->embed_data_list); } } /* * Put the embed onto the embed list for later * possible reflection. */ doc_lists = lo_GetCurrentDocLists(state); if (state->in_relayout) { int32 i, count; LO_EmbedStruct *prev_embed, *cur_embed; /* * In the interest of changing as little as possible, I'm not * going to change the embed_list to be in the order of layout * (it is currently in reverse order). Instead, we do what * everybody else does - iterate till the end of the list to get * find an element with the correct index. * If we're in table relayout, we need to replace the element * of the same index in this list with the new layout element * to prevent multiple reflection. */ count = 0; cur_embed = doc_lists->embed_list; while (cur_embed) { cur_embed = cur_embed->nextEmbed; count++; } /* reverse order... */ prev_embed = NULL; cur_embed = doc_lists->embed_list; for (i = count-1; i >= 0; i--) { if (i == doc_lists->embed_list_count) { /* Copy over the mocha object (it might not exist) */ embed->mocha_object = cur_embed->mocha_object; embed->nextEmbed = cur_embed->nextEmbed; /* Replace the old embed with the new one */ if (prev_embed == NULL) doc_lists->embed_list = embed; else prev_embed->nextEmbed = embed; doc_lists->embed_list_count++; break; } prev_embed = cur_embed; cur_embed = cur_embed->nextEmbed; } } else { embed->nextEmbed = doc_lists->embed_list; doc_lists->embed_list = embed; doc_lists->embed_list_count++; } /* * Plug-ins won't be happy if we use a special colormap. */ #ifndef M12N /* XXXM12N Fix me, this has gone away. Sets cx->colorSpace->install_colormap_forbidden*/ IL_UseDefaultColormapThisPage(context); #endif /* M12N */ /* Create an initially hidden layer for this plugin to inhabit. If the plugin is a windowless plugin, this will later become a "normal" layer. If the plugin is a windowed plugin, the layer will become a cutout layer. */ embed->layer = lo_CreateEmbeddedObjectLayer(context, state, (LO_Element*)embed); /* * Have the front end fetch this embed data, and tell us * the embed's dimensions if it knows them. */ FE_GetEmbedSize(context, embed, state->top_state->force_reload); /* * Hidden embeds always have 0 width and height */ if (embed->ele_attrmask & LO_ELE_HIDDEN) { embed->width = 0; embed->height = 0; } /* * We may have to block on this embed until later * when the front end can give us the width and height. * Never block on hidden embeds. */ if (((embed->width == 0)||(embed->height == 0))&& ((embed->ele_attrmask & LO_ELE_HIDDEN) == 0)) { state->top_state->layout_blocking_element = (LO_Element *)embed; } else { lo_FinishEmbed(context, state, embed); } } void lo_FinishEmbed(MWContext *context, lo_DocState *state, LO_EmbedStruct *embed) { int32 baseline_inc; int32 line_inc; int32 embed_height, embed_width; /* * Eventually this will never happen since we always * have dims here from either the embed tag itself or the * front end. * Hidden embeds are supposed to have 0 width and height. */ if ((embed->ele_attrmask & LO_ELE_HIDDEN) == 0) { if (embed->width == 0) { embed->width = EMBED_DEF_DIM; } if (embed->height == 0) { embed->height = EMBED_DEF_DIM; } } embed_width = embed->width + (2 * embed->border_width) + (2 * embed->border_horiz_space); embed_height = embed->height + (2 * embed->border_width) + (2 * embed->border_vert_space); /* * SEVERE FLOW BREAK! This may be a floating embed, * which means at this point we go do something completely * different. */ if (embed->ele_attrmask & LO_ELE_FLOATING) { embed->x_offset += (int16)embed->border_horiz_space; embed->y_offset += (int32)embed->border_vert_space; /* * Insert this element into the float list. */ embed->next = state->float_list; state->float_list = (LO_Element *)embed; lo_AppendFloatInLineList(state, (LO_Element*)embed, NULL); lo_LayoutFloatEmbed(context, state, embed, TRUE); } else { /* * Figure out how to align this embed. * 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 embed. */ if (state->baseline == 0) { state->baseline = 0; } embed->x_offset += (int16)embed->border_horiz_space; embed->y_offset += (int32)embed->border_vert_space; lo_LayoutInflowEmbed(context, state, embed, FALSE, &line_inc, &baseline_inc); lo_AppendToLineList(context, state, (LO_Element *)embed, baseline_inc); lo_UpdateStateAfterEmbedLayout(state, embed, line_inc, baseline_inc); } } void lo_RelayoutEmbed ( MWContext *context, lo_DocState *state, LO_EmbedStruct * embed, PA_Tag * tag ) { lo_DocLists *doc_lists; lo_PreLayoutTag ( context, state, tag ); if (state->top_state->out_of_memory) { return; } LO_LockLayout(); /* * Fill in the embed structure with default data */ embed->type = LO_EMBED; embed->ele_id = NEXT_ELEMENT; embed->x = state->x; embed->x_offset = 0; embed->y = state->y; embed->y_offset = 0; embed->next = NULL; embed->prev = NULL; embed->line_height = state->line_height; /* * Assign a unique index for this object * and increment the master index. */ embed->embed_index = state->top_state->embed_count++; /* * Since we saved the embed_list_count during table relayout, * we increment it as if we were reprocessing the EMBED tag. */ doc_lists = lo_GetCurrentDocLists(state); doc_lists->embed_list_count++; /* * Plug-ins won't be happy if we use a special colormap. */ #ifndef M12N /* XXXM12N Fix me, this has gone away. Sets cx->colorSpace->install_colormap_forbidden*/ IL_UseDefaultColormapThisPage(context); #endif /* M12N */ /* * I don't think we need to worry about blocking at all since we're in * relayout, but I'd rather be safe. */ if (((embed->width == 0)||(embed->height == 0))&& ((embed->ele_attrmask & LO_ELE_HIDDEN) == 0)) { state->top_state->layout_blocking_element = (LO_Element *)embed; } else { lo_FinishEmbed(context, state, embed); } lo_PostLayoutTag ( context, state, tag, FALSE ); LO_UnlockLayout(); } void LO_CopySavedEmbedData(MWContext *context, SHIST_SavedData *saved_data) { int32 doc_id; lo_TopState *top_state; lo_DocState *state; lo_SavedEmbedListData *embed_list, *new_embed_list; lo_EmbedDataElement *embed_data_list, *new_embed_data_list; PA_Block old_embed_data_list = NULL; int32 old_count = 0; int32 index; /* * Get the state, so we can access the savedEmbedListData * list for this document. */ doc_id = XP_DOCID(context); top_state = lo_FetchTopState(doc_id); if ((top_state != NULL)&&(top_state->doc_state != NULL)) state = top_state->doc_state; else return; embed_list = state->top_state->savedData.EmbedList; if (embed_list == NULL || embed_list->embed_data_list == NULL) return; PA_LOCK(embed_data_list, lo_EmbedDataElement*, embed_list->embed_data_list); if (saved_data->EmbedList == NULL) saved_data->EmbedList = XP_NEW_ZAP(lo_SavedEmbedListData); new_embed_list = saved_data->EmbedList; if (new_embed_list->embed_data_list == NULL) { /* Allocate new array */ new_embed_list->embed_data_list = PA_ALLOC( embed_list->embed_count * sizeof(lo_EmbedDataElement)); } else if (new_embed_list->embed_count < embed_list->embed_count) { /* Enlarge existing array */ old_embed_data_list = new_embed_list->embed_data_list; old_count = new_embed_list->embed_count; new_embed_list->embed_data_list = PA_REALLOC( new_embed_list->embed_data_list, (embed_list->embed_count * sizeof(lo_EmbedDataElement))); } /* * If we ran out of memory to grow the array. */ if (new_embed_list->embed_data_list == NULL) { new_embed_list->embed_data_list = old_embed_data_list; new_embed_list->embed_count = old_count; state->top_state->out_of_memory = TRUE; return; } /* * Copy all the elements from the old array to the new one. */ PA_LOCK(new_embed_data_list, lo_EmbedDataElement*, new_embed_list->embed_data_list); for (index = 0; index < embed_list->embed_count; index++) new_embed_data_list[index] = embed_data_list[index]; new_embed_list->embed_count = embed_list->embed_count; PA_UNLOCK(new_embed_list->embed_data_list); PA_UNLOCK(embed_list->embed_data_list); } void LO_AddEmbedData(MWContext *context, LO_EmbedStruct* embed, void *session_data) { lo_AddEmbedData(context, session_data, NPL_DeleteSessionData, embed->embed_index); } void lo_FillInEmbedGeometry(lo_DocState *state, LO_EmbedStruct *embed, Bool relayout) { int32 doc_width; if (relayout == TRUE) { embed->ele_id = NEXT_ELEMENT; } embed->x = state->x; embed->y = state->y; doc_width = state->right_margin - state->left_margin; /* * Get the width parameter, in absolute or percentage. * If percentage, make it absolute. */ if (embed->percent_width > 0) { int32 val = embed->percent_width; if (state->allow_percent_width == FALSE) { val = 0; } else { val = doc_width * val / 100; } embed->width = val; } /* Set embed->height if embed has a % height specified */ if (embed->percent_height > 0) { int32 val = embed->percent_height; if (state->allow_percent_height == FALSE) { val = 0; } else { val = state->win_height * val / 100; } embed->height = val; } } void lo_LayoutInflowEmbed(MWContext *context, lo_DocState *state, LO_EmbedStruct *embed, Bool inRelayout, int32 *line_inc, int32 *baseline_inc) { int32 embed_width, embed_height; Bool line_break; PA_Block buff; char *str; LO_TextStruct tmp_text; LO_TextInfo text_info; lo_TopState *top_state; top_state = state->top_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) { 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); embed_width = embed->width + (2 * embed->border_width) + (2 * embed->border_horiz_space); embed_height = embed->height + (2 * embed->border_width) + (2 * embed->border_vert_space); /* * Will this embed make the line too wide. */ if ((state->x + embed_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 unwrapped 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 embed if we have * a break. */ if (line_break != FALSE) { /* * We need to make the elements sequential, linefeed * before embed. */ top_state->element_id = embed->ele_id; if (!inRelayout) { lo_SoftLineBreak(context, state, TRUE); } else { lo_rl_AddSoftBreakAndFlushLine(context, state); } embed->x = state->x; embed->y = state->y; embed->ele_id = NEXT_ELEMENT; } lo_CalcAlignOffsets(state, &text_info, (intn)embed->alignment, embed_width, embed_height, &embed->x_offset, &embed->y_offset, line_inc, baseline_inc); } void lo_LayoutFloatEmbed(MWContext *context, lo_DocState *state, LO_EmbedStruct *embed, Bool updateFE ) { int32 embed_width; embed_width = embed->width + (2 * embed->border_width) + (2 * embed->border_horiz_space); if (embed->alignment == LO_ALIGN_RIGHT) { if (state->right_margin_stack == NULL) { embed->x = state->right_margin - embed_width; } else { embed->x = state->right_margin_stack->margin - embed_width; } if (embed->x < 0) { embed->x = 0; } } else { embed->x = state->left_margin; } embed->y = -1; lo_AddMarginStack(state, embed->x, embed->y, embed->width, embed->height, embed->border_width, embed->border_vert_space, embed->border_horiz_space, (intn)embed->alignment); if (state->at_begin_line != FALSE) { lo_FindLineMargins(context, state, updateFE); state->x = state->left_margin; } } void lo_UpdateStateAfterEmbedLayout(lo_DocState *state, LO_EmbedStruct *embed, int32 line_inc, int32 baseline_inc ) { int32 embed_width; int32 x, y; embed_width = embed->width + (2 * embed->border_width) + (2 * embed->border_horiz_space); state->baseline += (intn) baseline_inc; state->line_height += (intn) (baseline_inc + line_inc); /* * Clean up state */ state->x = state->x + embed->x_offset + embed_width - embed->border_horiz_space; state->linefeed_state = 0; state->at_begin_line = FALSE; state->trailing_space = FALSE; state->cur_ele_type = LO_EMBED; /* Determine the new position of the layer. */ x = embed->x + embed->x_offset + embed->border_width; y = embed->y + embed->y_offset + embed->border_width; /* Move layer to new position */ CL_MoveLayer(embed->layer, x, y); } void LO_SetEmbedSize( MWContext *context, LO_EmbedStruct *embed, int32 width, int32 height ) { /* For now, just setting the embed's dimensions. Do we need to lock/unlock layout here? */ embed->width = width; embed->height = height; }