Exemplo n.º 1
0
Bool
lo_CloneTagAndBlockLayout(MWContext *context, lo_DocState *state, PA_Tag *tag)
{

    PA_Tag *new_tag;
    lo_TopState * top_state = state->top_state;

    /*
     * 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);

    /* 
     * stick the current tag onto the front of the tag list
     */
    new_tag = PA_CloneMDLTag(tag);
    if (!new_tag) {
        top_state->out_of_memory = TRUE;
        return FALSE;
    }

    new_tag->next = top_state->tags;
    top_state->tags = new_tag;
    if (top_state->tags_end == &top_state->tags)
        top_state->tags_end = &new_tag->next;

    return lo_create_script_blockage(context, state, LO_UNKNOWN);
}
Exemplo n.º 2
0
PA_Tag *
LO_CreateHiddenEmbedTag(PA_Tag *old_tag, char * newTagStr)
{
	PA_Tag *new_tag = PA_CloneMDLTag(old_tag);
	if(new_tag)
	{
		char * buf = NULL;
		new_tag->type = P_EMBED;
		XP_FREE(new_tag->data);
		new_tag->data = NULL;
		StrAllocCopy(buf,newTagStr);
		XP_ASSERT(buf != NULL);
		new_tag->data = (PA_Block)buf;
		new_tag->data_len = XP_STRLEN((char*)new_tag->data);
		XP_ASSERT(new_tag->data_len != 0);
	}

	return(new_tag);
}
Exemplo n.º 3
0
void
lo_ProcessScriptTag(MWContext *context, lo_DocState *state, PA_Tag *tag, JSObject *obj)
{
    lo_TopState *top_state;
    pa_DocData *doc_data;
    XP_Bool type_explicitly_set=FALSE;
    XP_Bool saw_archive=FALSE;
#ifdef DEBUG_ScriptPlugin
	char * mimebuf = NULL;
#endif

    top_state = state->top_state;
    doc_data = (pa_DocData *)top_state->doc_data;
    XP_ASSERT(doc_data != NULL || state->in_relayout || tag->lo_data);

    if (tag->is_end == FALSE) {
        PA_Block buff;
        char *str, *url, *archiveSrc, *id, *codebase;

        /* Controversial default language value. */
        top_state->version = JSVERSION_DEFAULT;
        if (tag->type == P_STYLE || tag->type == P_LINK) {
            top_state->in_script = top_state->default_style_script_type;
        }
        else {
            /* in order to get old script behaviour, pretend
             * that the content-type is explicitly set for all scripts
             */
            type_explicitly_set = TRUE;
            top_state->in_script = SCRIPT_TYPE_MOCHA;
        }

        /* XXX account for HTML comment bytes and  "lost" newlines */
        if (lo_IsAnyCurrentAncestorSourced(state))
            top_state->script_bytes = top_state->layout_bytes;
        else
            top_state->script_bytes = top_state->layout_bytes - tag->true_len;
        if (tag->lo_data != NULL) {
            top_state->script_bytes += (int32)tag->lo_data - 1;
            tag->lo_data = NULL;
        } 
        else if (doc_data != NULL) {
            top_state->script_bytes += doc_data->comment_bytes;
        } 
        else {
            XP_ASSERT(state->in_relayout);
        }

	lo_ParseScriptLanguage(context, tag, &top_state->in_script,
			       &top_state->version);
#ifdef DEBUG_ScriptPlugin
		if (top_state->in_script == SCRIPT_TYPE_UNKNOWN)
		{
			mimebuf = npl_Script2mimeType(context,tag);
			if (mimebuf){
				if (NPL_FindPluginEnabledForType(mimebuf)){
					top_state->in_script = SCRIPT_TYPE_PLUGIN;
					XP_ASSERT(top_state->mimetype == NULL);
					StrAllocCopy((char *)top_state->mimetype,mimebuf);
					XP_FREE(mimebuf);
					mimebuf = NULL;
				}
				else{
					XP_FREE(mimebuf);
					mimebuf = NULL;
				}
			}
		}
#endif /* DEBUG_ScriptPlugin */

        buff = lo_FetchParamValue(context, tag, PARAM_TYPE);
        if (buff != NULL) {
            PA_LOCK(str, char *, buff);
            if ((XP_STRCASECMP(str, js_content_type) == 0) ||
                (!XP_STRCASECMP(str, "text/javascript"))) {
		if(tag->type == P_STYLE || tag->type == P_LINK)
		{
		    top_state->in_script = SCRIPT_TYPE_JSSS;
		    top_state->default_style_script_type = SCRIPT_TYPE_JSSS;
		}
		else
		{
		    top_state->in_script = SCRIPT_TYPE_MOCHA;                    
		}
                type_explicitly_set = TRUE;
            } 
            else if ((XP_STRCASECMP(str, TEXT_CSS) == 0)) {
                top_state->in_script = SCRIPT_TYPE_CSS;
                top_state->default_style_script_type = SCRIPT_TYPE_CSS;
                type_explicitly_set = TRUE;
            } 
            else {
                top_state->in_script = SCRIPT_TYPE_UNKNOWN;
                top_state->default_style_script_type = SCRIPT_TYPE_UNKNOWN;
            }
            PA_UNLOCK(buff);
            PA_FREE(buff);
        } 

	/* check for media=screen
	 * don't load the style sheet if there 
	 * is a media not equal to screen
	 */
	buff = lo_FetchParamValue(context, tag, PARAM_MEDIA);
	if (buff) {
	    if (strcasecomp((char*)buff, "screen")) {
		/* set the script type to UNKNOWN
		 * so that it will get thrown away
		 */
		top_state->in_script = SCRIPT_TYPE_UNKNOWN;
	    }
	    PA_FREE(buff);
	}

        /*
         * Flush the line buffer so we can start storing Mocha script
         * source lines in there.
         */
        lo_FlushLineBuffer(context, state);

        url = archiveSrc = id = codebase = NULL;
        if (top_state->in_script != SCRIPT_TYPE_NOT) {
            /*
             * Check for the archive parameter for known languages.
             */
            buff = lo_FetchParamValue(context, tag, PARAM_ARCHIVE);
            if (buff != NULL) {
                saw_archive = TRUE;
                PA_LOCK(str, char *, buff);
                url = NET_MakeAbsoluteURL(top_state->base_url, str);
                PA_UNLOCK(buff);
                PA_FREE(buff);
		if (url == NULL) {
                    top_state->out_of_memory = TRUE;
                    return;
		}
            }

            /* 
             * Look for ID attribute. If it's there we have may have
             * an inline signed script.
             */
            buff = lo_FetchParamValue(context, tag, PARAM_ID);
            if (buff != NULL) {
                PA_LOCK(str, char *, buff);
                StrAllocCopy(id, str);
                PA_UNLOCK(buff);
                PA_FREE(buff);
		if (id == NULL) {
                    top_state->out_of_memory = TRUE;
		    XP_FREEIF(url);
                    return;
		}
            }

            /*
             * Now look for a SRC="url" attribute for known languages.
             * If found, synchronously load the url.
             */
	    buff = lo_FetchParamValue(context, tag, PARAM_SRC);  /* XXX overloaded rv */
            if (buff != NULL) {
		XP_Bool allowFileSrc = FALSE;
                char *absUrl;

                PA_LOCK(str, char *, buff);

		PREF_GetBoolPref(lo_jsAllowFileSrcFromNonFile, &allowFileSrc);
                absUrl = NET_MakeAbsoluteURL(top_state->base_url, str);
		if (absUrl == NULL) {
		    top_state->out_of_memory = TRUE;
		    XP_FREEIF(id);
                } else if (allowFileSrc == FALSE &&
		           NET_URL_Type(absUrl) == FILE_TYPE_URL &&
		           NET_URL_Type(top_state->url) != FILE_TYPE_URL) {
		    /*
		     * Deny access from http: to file: via SCRIPT SRC=...
		     * XXX silently
		     */
                    top_state->in_script = SCRIPT_TYPE_UNKNOWN;
                    XP_FREE(absUrl);
                    XP_FREEIF(url);
		    XP_FREEIF(id);
		} else if (url != NULL) {
                    XP_FREE(absUrl);
                    StrAllocCopy(archiveSrc, str);
		    if (archiveSrc == NULL) {
			top_state->out_of_memory = TRUE;
			XP_FREE(url);
			XP_FREEIF(id);
		    }
                } else {
                    url = absUrl;
                }
                PA_UNLOCK(buff);
                PA_FREE(buff);
		if (top_state->out_of_memory)
		    return;

                /*
                 * If we are doing a <script src=""> mocha script but JS
                 *   is turned off just ignore the tag
                 */
		if (!LM_CanDoJS(context)) {
                    top_state->in_script = SCRIPT_TYPE_UNKNOWN;
                    XP_FREE(url);
		    XP_FREEIF(id);
		    XP_FREEIF(archiveSrc);
                    return;
                }
            }
        }

        /*
         * Set text_divert so we know to accumulate text in line_buf
         * without interpretation.
         */
        state->text_divert = tag->type;

        /*
         * XXX need to stack these to handle blocked SCRIPT tags
         */
        top_state->script_lineno = tag->newline_count + 1;

        /* if we got here as a result of a LINK tag
         * check to make sure rel=stylesheet and then
         * check for an HREF and if one does not exist
         * fail
         */
        if (tag->type == P_LINK) {
            char *cbuff = (char*)lo_FetchParamValue(context, tag, PARAM_REL);
                        
            if (cbuff && !strcasecomp(cbuff, "stylesheet")) {
                XP_FREE(cbuff);

                cbuff = (char*)lo_FetchParamValue(context, tag, PARAM_HREF);

                if (cbuff) {
                    if (saw_archive && url) {
                        archiveSrc = XP_STRDUP(cbuff);
                    } else {
		        XP_FREEIF(url);
                        url = NET_MakeAbsoluteURL(top_state->base_url, cbuff);
                    }
		}
            }

            XP_FREEIF(cbuff);
        }

        if (url != NULL || id != NULL || codebase != NULL) {
            if ((doc_data != NULL) &&
                (state->in_relayout == FALSE) &&
                SCRIPT_EXEC_OK(top_state, state, tag->type, P_SCRIPT)) {
                ScriptData *data;

                data = XP_ALLOC(sizeof(ScriptData));
                if (data == NULL) {
                    top_state->out_of_memory = TRUE;
                    return;
                }
                data->context = context;
                data->state = state;
                data->tag = PA_CloneMDLTag(tag);
                if (data->tag == NULL) {
                    top_state->out_of_memory = TRUE;
		    XP_FREE(data);
                    return;
                }
                data->url = url;
                data->archiveSrc = archiveSrc;
                data->id = id;
                if (codebase == NULL) {
                    StrAllocCopy(codebase, top_state->base_url);
                }
                data->codebase = codebase;
                data->buffer = NULL;
                data->bufferSize = 0;
                data->version = top_state->version;

		/*
		 * Only SCRIPT ARCHIVE= ID= without SRC= is an inline signed
		 * script -- if there is a SRC= attribute, archiveSrc will be
		 * non-null.
		 */
                data->inlineSigned = (JSBool)
		    (url != NULL && archiveSrc == NULL && id != NULL);

                /* Reset version accumulator */
                top_state->version = JSVERSION_UNKNOWN;

                XP_ASSERT (tag->type == P_SCRIPT || tag->type == P_STYLE || 
			   tag->type == P_LINK);

	        /* 
		 * Out-of-line included (by src=) or inline signed script.
		 * Save continuatation data on top_state.  If it's signed,
		 * we'll verify the signature once we see </script> and
		 * have the inline script to verify.
		 */
		top_state->scriptData = data;

            } 
	    else {
                XP_FREE(url);
		XP_FREEIF(id);
		XP_FREEIF(archiveSrc);
            }
        }
    } 
    else {

	/*
	 * We are in the </script> tag now...
	 */

        size_t line_buf_len;
        intn script_type;
        char *scope_to=NULL;
        char *untransformed = NULL;

        script_type = top_state->in_script;
        top_state->in_script = SCRIPT_TYPE_NOT;

	/* guard against superfluous end tags */
	if (script_type == SCRIPT_TYPE_NOT)
	    goto end_tag_out;

	/* convert from CSS to JavaScript here */
        if (tag->type != P_LINK && script_type == SCRIPT_TYPE_CSS) {
            char *new_buffer;
            int32 new_buffer_length;

            CSS_ConvertToJS((char *)state->line_buf, 
                            state->line_buf_len,
                            &new_buffer,
                            &new_buffer_length);

            if (!new_buffer) {
                /* css translator error, unblock layout and return */
                state->text_divert = P_UNKNOWN;
                state->line_buf_len = 0; /* clear script text */
                goto end_tag_out;
            }

            untransformed = (char *) state->line_buf;
            state->line_buf = (PA_Block) new_buffer;
            state->line_buf_len = new_buffer_length;
            state->line_buf_size = new_buffer_length;

            if (state->line_buf_len)
                state->line_buf_len--; /* hack: subtract one to remove final \n */

            script_type = SCRIPT_TYPE_JSSS;
        }

        if (tag->type == P_STYLE) {
            /* mocha scoped to document == jsss */
            scope_to = "document";
        }

        /*
         * Reset these before potentially recursing indirectly through
         * the document.write() built-in function, which writes to the
         * very same doc_data->parser_stream that this <SCRIPT> tag
         * came in on.
         */
        state->text_divert = P_UNKNOWN;
        line_buf_len = state->line_buf_len;
        state->line_buf_len = 0;

        if (script_type != SCRIPT_TYPE_UNKNOWN && 
	    script_type != SCRIPT_TYPE_NOT) {
            /*
             * If mocha is disabled or can't be done in this context we
             *   are going to just ignore the buffer contents
             */
            if (!LM_CanDoJS(context)) {
				top_state->in_script = SCRIPT_TYPE_UNKNOWN;
                goto end_tag_out;
            }

            if ((doc_data != NULL) &&
                (state->in_relayout == FALSE) &&
                SCRIPT_EXEC_OK(top_state, state, tag->type, P_SCRIPT)) {

                /*
                 * First off, make sure layout is blocking on us
                 */
                if (lo_create_script_blockage(context, state, 
					tag->type == P_SCRIPT ? LO_SCRIPT : LO_UNKNOWN)) 
				{
                    ScriptData *data;

                    /*
                     * Extreme hackery.  Hideous and shameful.  See the comment
						* in lo_BlockScriptTag before similar is_end/overflow code
						* and commence vomiting.
                     */
                    lo_BlockScriptTag(context, state, NULL);

		    if (tag->is_end == (PRPackedBool)1) {
			  PA_PushOverflow(doc_data);
			  doc_data->overflow_depth ++;
		    }

		    /*
		     * Set the document.write tag insertion point.
		     */
             top_state->input_write_point[top_state->input_write_level] = &top_state->tags;

		    data = top_state->scriptData;
                    top_state->scriptData = NULL;
                    if (data && data->url) {
			/*
			 * Three cases:
			 * 1.  SCRIPT SRC=: url non-null
			 * 2.  SCRIPT ARCHIVE= SRC=: url, archiveSrc non-null
			 * 3.  SCRIPT ARCHIVE= ID=: url, id non-null
			 * In the last case, we copy the inline script into
			 * data's buffer and let lo_script_archive_exit_fn do
			 * the eval.  We use an inlineSigned flag to avoid a
			 * bunch of (url != NULL && archiveSrc == NULL && id
			 * != NULL) tests.
			 */
			if (data->inlineSigned) {
                            StrAllocCopy(data->buffer, (char *) state->line_buf);
                            data->bufferSize = line_buf_len;
			}
			lo_GetScriptFromURL(data, script_type);
                    }
		    else {
                        JSPrincipals *principals = NULL;
			ETEvalStuff * stuff;
			
                        if (data) {
			    principals = LM_NewJSPrincipals(NULL, data->id, 
							    data->codebase);
                            if (untransformed &&
				!LM_SetUntransformedSource(principals, 
                                                           untransformed,
                                                           (char *) state->line_buf))
                            {
                                top_state->out_of_memory = TRUE;
                            }
                            lo_DestroyScriptData(data);
			}

                        /* 
                         * send the buffer off to be evaluated 
			 */
#ifdef DEBUG_ScriptPlugin
			 			if (script_type == SCRIPT_TYPE_PLUGIN)
						{
							XP_ASSERT(mimebuf == NULL);
							npl_ScriptPlugin(context, state, tag, line_buf_len,top_state->mimetype);
						    lo_unblock_script_tag(context, TRUE);
						}
						else
#endif /* DEBUG_ScriptPlugin */
 

			stuff = (ETEvalStuff *) XP_NEW_ZAP(ETEvalStuff);
			if (!stuff)
			    goto end_tag_out;

			stuff->len = line_buf_len;
			stuff->line_no = top_state->script_lineno;
			if (scope_to)
			    stuff->scope_to = XP_STRDUP(scope_to);
			else
			    stuff->scope_to = NULL;
			stuff->want_result = JS_FALSE;
			stuff->data = context;
			stuff->version = top_state->version;
			stuff->principals = principals;

                        ET_EvaluateScript(context, 
                                          (char *) state->line_buf,
					  stuff,
                                          lo_ScriptEvalExitFn);
                    }

                    /* Reset version accumulator */
                    top_state->version = JSVERSION_UNKNOWN;
                }
            }
        }
      end_tag_out:
	/*
	 * If we got a </SCRIPT> and still have scriptData set here, it must
	 *   be left over from an error case above, so we free it.
	 */
	if (top_state->scriptData) {
	    XP_ASSERT(!top_state->layout_blocking_element);
            lo_DestroyScriptData(top_state->scriptData);
	    top_state->scriptData = NULL;
	}
        XP_FREEIF(untransformed);
    }
}
Exemplo n.º 4
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);
		}
	}
}
Exemplo n.º 5
0
void
lo_BeginMulticolumn(MWContext *context, lo_DocState *state, PA_Tag *tag, LO_MulticolumnStruct *multicolEle)
{
	lo_MultiCol *multicol;
	PA_Block buff;
	char *str;
	int32 val;
	int32 doc_width;
	/* int32 width; */

	multicol = XP_NEW(lo_MultiCol);
	if (multicol == NULL)
	{
		state->top_state->out_of_memory = TRUE;
		return;
	}

	multicol->width = 0;
	multicol->isPercentWidth = FALSE;	

	/* Put a pointer to lo_multicol inside the MULTICOLUMN layout element that will be placed on the
	   line list */
	multicolEle->multicol = multicol;
    
	/*
     * If this multicol is within a layer, then we have to create an
     * artificial TABLE around it (since the multicol code depends on
     * the state's line array, which isn't in an updated state within
     * a layer). 
     */
    if (state->layer_nest_level > 0)
    {
        PA_Tag *tmp_tag;
        lo_TableRec *table;

        if (state->in_paragraph != FALSE)
        {
            lo_CloseParagraph(context, &state, tag, 2);
        }

        lo_BeginTableAttributes(context, state, NULL, NULL, NULL, NULL,
                                NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                                NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                                NULL, NULL, NULL);
        
        table = state->current_table;
        if (table) {
            lo_BeginTableRowAttributes(context, state, table,
                                       NULL, NULL, NULL, NULL);

            lo_BeginTableCellAttributes(context, state, table,
                                        NULL, NULL, NULL, NULL, NULL,
                                        LO_TILE_BOTH, NULL, NULL, NULL, NULL,
                                        FALSE, TRUE);

            /* 
             * If we've successfully created a subdoc, we need to clone
             * the MULTICOL tag and save it in the subdoc, since the code
             * above us doesn't realize we're now in a table.
             */
            if (state->sub_state) {
                state = state->sub_state;
                tmp_tag = PA_CloneMDLTag(tag);
                lo_SaveSubdocTags(context, state, tmp_tag);
            }
            multicol->close_table = TRUE;
        }
    }
    else {		
		/* 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_SetSoftLineBreakState(context, state, FALSE, 2);
        multicol->close_table = FALSE;		
    }

	/*
	 * Since we are going to block layout during multicol
	 * processing, we need to flush the compositor of any
	 * pending displays.
	 */
	if (context->compositor)
	{
		CL_CompositeNow(context->compositor);
	}

	lo_StartMultiColInit( state, multicol );

	/*
	multicol->end_last_line = state->end_last_line;
	multicol->start_ele = state->top_state->element_id;
	multicol->start_line = state->line_num;
	multicol->end_line = multicol->start_line;
	multicol->start_x = state->x;
	multicol->start_y = state->y;
	multicol->end_y = multicol->start_y;
	*/
	multicol->cols = 1;
	multicol->gutter = MULTICOL_GUTTER_WIDTH;

	/*	
     * Get the cols parameter.
     */
    buff = lo_FetchParamValue(context, tag, PARAM_COLS);
    if (buff != NULL)
    {
		PA_LOCK(str, char *, buff);
		multicol->cols = XP_ATOI(str);
		PA_UNLOCK(buff);
		PA_FREE(buff);
	}

	if (multicol->cols <= 1)
	{
		XP_DELETE(multicol);
		multicolEle->multicol = NULL;
		return;
	}

	/*
     * Get the gutter parameter.
     */
    buff = lo_FetchParamValue(context, tag, PARAM_GUTTER);
    if (buff != NULL)
    {
        PA_LOCK(str, char *, buff);
		multicol->gutter = XP_ATOI(str);
		if (multicol->gutter < 1)
		{
			multicol->gutter = 1;
		}
		PA_UNLOCK(buff);
		PA_FREE(buff);
	}

	multicol->gutter = FEUNITS_X(multicol->gutter, context);

	doc_width = state->right_margin - state->left_margin;
	/* width = doc_width; */

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

	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)
		{
			multicol->width = val;
			multicol->isPercentWidth = TRUE;
		}
		else
		{
			multicol->width = val;
			multicol->isPercentWidth = FALSE;
			val = FEUNITS_X(val, context);
			if (val < 1)
			{
				val = 1;
			}
		}
		PA_UNLOCK(buff);
		PA_FREE(buff);
	}

	/*
	width = width - ((multicol->cols - 1) * multicol->gutter);
	multicol->col_width = width / multicol->cols;
	if (multicol->col_width < MULTICOL_MIN_WIDTH)
	{
		multicol->col_width = MULTICOL_MIN_WIDTH;
	}

	multicol->orig_margin = state->right_margin;

	lo_PushList(state, tag, QUOTE_NONE);
*/

	lo_SetupStateForBeginMulticol( state, multicol, doc_width );
	
	/*
	state->right_margin = state->left_margin + multicol->col_width;
	state->x = state->left_margin;
	state->list_stack->old_left_margin = state->left_margin;
	state->list_stack->old_right_margin = state->right_margin;

	multicol->orig_min_width = state->min_width;
	state->min_width = 0;
	*/

	/*
	 * Don't display anything while processing the multicolumn text.
	 */
	/*
	multicol->orig_display_blocking_element_y = state->display_blocking_element_y;
	state->display_blocking_element_y = -1;
	multicol->orig_display_blocked = state->display_blocked;
	state->display_blocked = TRUE;

	multicol->next = state->current_multicol;
	state->current_multicol = multicol;
	*/
}