return;
goto out;
lo_LayoutTag(MWContext *context, lo_DocState *state, PA_Tag *tag){	char *tptr;	char *tptr2;#ifdef OJI	char* javaPlugin;#endif	LO_TextAttr tmp_attr;	StyleStruct *style_struct=NULL;	XP_Bool has_ss_bottom_margin=FALSE;    XP_Bool started_in_head=FALSE;	INTL_CharSetInfo c = LO_GetDocumentCharacterSetInfo(context);	XP_ASSERT(state);    if(state->top_state)        started_in_head = state->top_state->in_head;#ifdef LOCAL_DEBUGXP_TRACE(("lo_LayoutTag(%d)\n", tag->type));#endif /* LOCAL_DEBUG */	/* 	 * see if there are any &{} constructs for this tag.  If so,	 *   convert them now, if we can't convert them (since we couldn't	 *   get the mocha lock, for example) block layout and try to do 	 *   this tag convertion again later	 */	/*	 * Don't expand these inside XMP and PLAINTEXT or when the text	 *   is coming from a document.write()	 */	if (state->allow_amp_escapes != FALSE && tag->type != P_TEXT &&	    (state->top_state->input_write_level == 0 ||             state->top_state->tag_from_inline_stream == TRUE))	{		if (lo_ConvertMochaEntities(context, state, tag) == FALSE) {			state->top_state->wedged_on_mocha = TRUE;			lo_CloneTagAndBlockLayout(context, state, tag);			return;		} 	}	lo_PreLayoutTag(context, state, tag);	if ( state->top_state->out_of_memory )		return;			/* implicitly pop tags before we push a new one on the stack 	 * the call to this may alter the state variable due to	 * a table closure	 */	LO_ImplicitPop(context, &state, tag);	/* Call into the style sheet code to let it know	 * that we are starting a new tag	 *	 * Since we need to get the id and class out of	 * the tag->data call an LO function first 	 */	if(!tag->is_end)	{		PushTagStatus push_status;		 		push_status = LO_PushTagOnStyleStack(context, state, tag);		if(push_status == PUSH_TAG_SUCCESS) {			if(state->top_state->style_stack)				style_struct = STYLESTACK_GetStyleByIndex(state->top_state->style_stack, 0);			else				style_struct = NULL;		}		else if(push_status == PUSH_TAG_BLOCKED)			/* layout has been locked */			return;		else			style_struct = NULL;  /* push error */	} 	else	{		/* get has_bottom_margin flag for use in end P */		char *prop;        /* don't pop on unknown or empty tags.         * we have already pop'd empty tags.         */		if((tag->type != P_UNKNOWN || state->in_relayout)            && !lo_IsEmptyTag(tag->type))		{			if(state->top_state->style_stack)				style_struct = STYLESTACK_GetStyleByIndex(state->top_state->style_stack, 0);			else 				style_struct = NULL;			if(style_struct		   	&& (prop = STYLESTRUCT_GetString(style_struct, BOTTOMMARGIN_STYLE)) != NULL)			{				has_ss_bottom_margin = TRUE;				XP_FREE(prop);			}						/* pop the previous style tag, since this is an end tag */			LO_PopStyleTag(context, &state, tag);			/* if we have a pointer to the style struct it will			 * be dangling now since we just pop'd and detroyed the			 * top style struct.			 */			style_struct = NULL;		}	}	if(tag->type != P_TEXT && tag->type != P_UNKNOWN)	{		XP_ASSERT(state->top_state);		if(state->top_state)			state->top_state->tag_count++;	}	LO_LockLayout();#ifdef DOM    LM_ReflectTagNode(tag, state, context);#endif	if(!tag->is_end && lo_IsEmptyTag(tag->type))	{#ifdef DOM        lo_SetStyleSheetProperties(context, state, tag);#else        lo_SetStyleSheetProperties(context, style_struct, tag);#endif	}		switch(tag->type)	  {		case P_TEXT:			if(!state->hide_content)				lo_process_text_tag(context, state, tag);			break;		/*		 * Title text is special, it is not displayed, just		 * captured and sent to the front end.		 */		case P_TITLE:			lo_process_title_tag(context, state, tag);			break;		/*		 * Certificate text is special, it is not displayed,		 * but decoded and saved for later reference.		 */		case P_CERTIFICATE:#ifdef HTML_CERTIFICATE_SUPPORT			lo_process_certificate_tag(context, state, tag);#endif			break;		/*		 * All these tags just flip the fixed width font		 * bit, and push a new font on the font stack.		 */		case P_FIXED:		case P_CODE:		case P_SAMPLE:		case P_KEYBOARD:			lo_ProcessFontTag( state, context, tag, LO_FONT_FIXED, 0);			break;#ifdef EDITOR		process_server:		case P_SERVER:			if (tag->is_end == FALSE)			{				LO_TextAttr *old_attr;				LO_TextAttr *attr;				state->preformatted = PRE_TEXT_YES;				FE_BeginPreSection(context);#ifdef DOM                old_attr = lo_GetCurrentTextAttr(state, context);#else				old_attr = state->font_stack->text_attr;#endif				lo_CopyTextAttr(old_attr, &tmp_attr);				tmp_attr.fontmask |= LO_FONT_FIXED;				if( tag->type == P_SCRIPT ){					tmp_attr.fg.green = 0;				    tmp_attr.fg.red = 0xff;				    tmp_attr.fg.blue = 0;				}				else {					tmp_attr.fg.green = 0;				    tmp_attr.fg.red = 0;				    tmp_attr.fg.blue = 0xff;				}				tmp_attr.size = 3;				attr = lo_FetchTextAttr(state, &tmp_attr);				lo_PushFont(state, tag->type, attr);			}			else			{				LO_TextAttr *attr;				attr = lo_PopFont(state, tag->type);				state->preformatted = PRE_TEXT_NO;				FE_EndPreSection(context);			}			break;#endif		/*		 * All these tags just flip the bold font		 * bit, and push a new font on the font stack.		 */		case P_BOLD:		case P_STRONG:			lo_ProcessFontTag( state, context, tag, LO_FONT_BOLD, 0);			break;		/*		 * All these tags just flip the italic font		 * bit, and push a new font on the font stack.		 */		case P_ITALIC:		case P_EMPHASIZED:		case P_VARIABLE:		case P_CITATION:			lo_ProcessFontTag( state, context, tag, LO_FONT_ITALIC, 0);			break;		/*		 * All headers force whitespace, then set the bold		 * font bit and unset the fixed and/or italic if set.		 * In addition, they set the size attribute of the		 * new font they will push, like <font size=num>		 * Sizes are:		 * 	H1 -> 6		 * 	H2 -> 5		 * 	H3 -> 4		 * 	H4 -> 3		 * 	H5 -> 2		 * 	H6 -> 1		 */		case P_HEADER_1:			lo_process_header_tag(context, state, tag, 6);			break;		case P_HEADER_2:			lo_process_header_tag(context, state, tag, 5);			break;		case P_HEADER_3:			lo_process_header_tag(context, state, tag, 4);			break;		case P_HEADER_4:			lo_process_header_tag(context, state, tag, 3);			break;		case P_HEADER_5:			lo_process_header_tag(context, state, tag, 2);			break;		case P_HEADER_6:			lo_process_header_tag(context, state, tag, 1);			break;		/*		 * Description titles are just normal,		 * unless value > 1 and then they are outdented		 * the width of one list indention.		 */		case P_NSDT:			/*			 * The start of a list infers the end of			 * the HEAD section of the HTML and starts the BODY			 */			state->top_state->in_head = FALSE;			state->top_state->in_body = TRUE;			if (state->in_paragraph != FALSE)			{				lo_CloseParagraph(context, &state, tag, 2);			}			if (tag->is_end == FALSE)			{				/*				 * Undent to the left for a title if necessary.				 */				if ((state->list_stack->level != 0)&&				    (state->list_stack->type == P_DESC_LIST)&&				    (state->list_stack->value > 1))				{					state->list_stack->old_left_margin -=						LIST_MARGIN_INC;					state->list_stack->value = 1;				}				if (state->linefeed_state >= 1)				{					lo_FindLineMargins(context, state,FALSE);				}				else				{					lo_SetLineBreakState(context,state,FALSE,LO_LINEFEED_BREAK_HARD, 1, FALSE);				}				state->x = state->left_margin;			}			break;		case P_DESC_TITLE:			/*			 * The start of a list infers the end of			 * the HEAD section of the HTML and starts the BODY			 */			state->top_state->in_head = FALSE;			state->top_state->in_body = TRUE;			if (state->in_paragraph != FALSE)			{				lo_CloseParagraph(context, &state, tag, 2);			}			if (tag->is_end == FALSE)			{				LO_DescTitleStruct *title = (LO_DescTitleStruct*)lo_NewElement(context, state, LO_DESCTITLE, NULL, 0);				XP_ASSERT(title);				if (!title) 				{				    LO_UnlockLayout();				    return;				}				title->lo_any.type = LO_DESCTITLE;				title->lo_any.ele_id = NEXT_ELEMENT;								title->lo_any.x = state->x;				title->lo_any.y = state->y;				title->lo_any.x_offset = 0;				title->lo_any.y_offset = 0;				title->lo_any.width = 0;				title->lo_any.height = 0;				title->lo_any.line_height = 0;				lo_AppendToLineList(context, state, (LO_Element*)title, 0);				lo_ProcessDescTitleElement(context, state, title, FALSE);			}			break;		/*		 * Description text, is just normal text, but since there		 * is no ending <dd> tag, we need to put the		 * linebreak from the previous line in here.		 * Compact lists may not linebreak since they try to		 * put description text on the same line as title		 * text if there is room.		 * If value == 1 then we need to indent for the description		 * text, if it is > 1 then we are already indented.		 */		case P_DESC_TEXT:			/*			 * The start of a list infers the end of			 * the HEAD section of the HTML and starts the BODY			 */			state->top_state->in_head = FALSE;			state->top_state->in_body = TRUE;			if (state->in_paragraph != FALSE)			{				lo_CloseParagraph(context, &state, tag, 2);			}			if (tag->is_end == FALSE)			{				LO_DescTextStruct *text = (LO_DescTextStruct*)lo_NewElement(context, state, LO_DESCTEXT, NULL, 0);				XP_ASSERT(text);				if (!text) 				{				    LO_UnlockLayout();				    return;				}				text->lo_any.type = LO_DESCTEXT;				text->lo_any.ele_id = NEXT_ELEMENT;								text->lo_any.x = state->x;				text->lo_any.y = state->y;				text->lo_any.x_offset = 0;				text->lo_any.y_offset = 0;				text->lo_any.width = 0;				text->lo_any.height = 0;				text->lo_any.line_height = 0;				lo_AppendToLineList(context, state, (LO_Element*)text, 0);				lo_ProcessDescTextElement(context, state, text, FALSE);			}			break;		/*		 * A new list level, but don't move the		 * left margin in until you need to.		 * val is overloaded to tell us if we are		 * not indented (val=1) or indented (val > 1).		 * Push a new element on the list stack.		 */		case P_DESC_LIST:			/*			 * The start of a list infers the end of			 * the HEAD section of the HTML and starts the BODY			 */			state->top_state->in_head = FALSE;			state->top_state->in_body = TRUE;			if (tag->is_end == FALSE)			{				PA_Block buff;				char * t_ptr;				buff = lo_FetchParamValue(context, tag, PARAM_COMPACT);								PA_LOCK(t_ptr, char *, buff);				lo_setup_list(state,							  context,							  tag,							  NULL,							  NULL,							  t_ptr);								PA_UNLOCK(buff);				if (buff) PA_FREE(buff);			}			else /* tag->is_end is TRUE */			{				lo_TeardownList(context, state, tag);			}			break;		/*		 * Move the left margin in another indent step.		 * Push a new element on the list stack.		 */		case P_NUM_LIST:		case P_UNUM_LIST:		case P_MENU:		case P_DIRECTORY:    /*    case P_MQUOTE:  mquote tag disabled, replaced by  <blockquote mail> */			/*			 * The start of a list infers the end of			 * the HEAD section of the HTML and starts the BODY			 */			state->top_state->in_head = FALSE;			state->top_state->in_body = TRUE;			if (tag->is_end == FALSE)			{				char *bullet_type;				char *bullet_start;				char *compact_attr;				bullet_type = (char*)lo_FetchParamValue(context, 														tag, 														PARAM_TYPE);								bullet_start = (char*)lo_FetchParamValue(context, 														tag, 														PARAM_START);				compact_attr = (char*)lo_FetchParamValue(context, 														tag, 														PARAM_COMPACT);				lo_setup_list(state, 							  context,							  tag,							  bullet_type,							  bullet_start,							  compact_attr);				XP_FREEIF(bullet_type);				XP_FREEIF(bullet_start);				XP_FREEIF(compact_attr);			}			/* tag->is_end is TRUE */			else {				lo_TeardownList(context, state, tag);			}			break;		/*		 * Complex because we have to place one of many types		 * of bullet here, or one of several types of numbers.		 */		case P_LIST_ITEM:			/*			 * The start of a list infers the end of			 * the HEAD section of the HTML and starts the BODY			 */			state->top_state->in_head = FALSE;			state->top_state->in_body = TRUE;			if (state->in_paragraph != FALSE)			{				lo_CloseParagraph(context, &state, tag, 2);			}			if (tag->is_end == FALSE && !state->hide_content)			{				int type;				int bullet_type;				PA_Block buff;				/*				 * Reset fake linefeed state used to				 * fake out headers in lists.				 */				if (state->at_begin_line == FALSE)				{					state->linefeed_state = 0;				}				lo_SetLineBreakState(context, state, FALSE, LO_LINEFEED_BREAK_HARD, 1, FALSE);				/*				 * Artificially setting state to 2 here				 * allows us to put headers on list items				 * even if they aren't double spaced.				 */				state->linefeed_state = 2;				type = state->list_stack->bullet_type;				buff = lo_FetchParamValue(context, tag, PARAM_TYPE);				if ((buff != NULL)&&					(state->list_stack->type == P_NUM_LIST))				{					char *type_str;					PA_LOCK(type_str, char *, buff);					if (*type_str == 'A')					{						type = BULLET_ALPHA_L;					}					else if (*type_str == 'a')					{						type = BULLET_ALPHA_S;					}					else if (*type_str == 'I')					{						type = BULLET_NUM_L_ROMAN;					}					else if (*type_str == 'i')					{						type = BULLET_NUM_S_ROMAN;					}					else					{						type = BULLET_NUM;					}					PA_UNLOCK(buff);				}				else if ((buff != NULL)&&					(state->list_stack->type !=P_DESC_LIST))				{					char *type_str;					PA_LOCK(type_str, char *, buff);					if (pa_TagEqual("round", type_str))					{						type = BULLET_ROUND;					}					else if (pa_TagEqual("circle",type_str))					{						type = BULLET_ROUND;					}					else if (pa_TagEqual("square",type_str))					{						type = BULLET_SQUARE;					}					else					{						type = BULLET_BASIC;					}					PA_UNLOCK(buff);				}				state->list_stack->bullet_type = type;				if (buff != NULL) 				{					PA_FREE(buff);				}				buff = lo_FetchParamValue(context, tag, PARAM_VALUE);				if (buff != NULL)				{					int32 val;					char *val_str;					PA_LOCK(val_str, char *, buff);					val = XP_ATOI(val_str);					if (val < 1)					{						val = 1;					}					PA_UNLOCK(buff);					state->list_stack->value = val;					PA_FREE(buff);				}				bullet_type = state->list_stack->bullet_type;				if ((bullet_type == BULLET_NUM)||				    (bullet_type == BULLET_ALPHA_L)||				    (bullet_type == BULLET_ALPHA_S)||				    (bullet_type == BULLET_NUM_L_ROMAN)||				    (bullet_type == BULLET_NUM_S_ROMAN))				{					lo_PlaceBulletStr(context, state);					state->list_stack->value++;				}				else				{					lo_PlaceBullet(context, state);				}			}			break;		/*		 * Another font attribute, another font on the font stack		 */		case P_BLINK:            /*             * Blink is ignored in the editor.             */            if ( EDT_IS_EDITOR(context) ) {                break;            }			if (tag->is_end == FALSE)			{				LO_TextAttr *old_attr;				LO_TextAttr *attr;#ifdef DOM                old_attr = lo_GetCurrentTextAttr(state, context);#else				old_attr = state->font_stack->text_attr;#endif				lo_CopyTextAttr(old_attr, &tmp_attr);				tmp_attr.attrmask |= LO_ATTR_BLINK;				attr = lo_FetchTextAttr(state, &tmp_attr);				lo_PushFont(state, tag->type, attr);			}			else			{				LO_TextAttr *attr;				attr = lo_PopFont(state, tag->type);			}			break;		/*		 * Another font attribute, another font on the font stack		 * Because of spec mutation, two tags do the same thing.		 * <s> and <strike> are the same.		 */		case P_STRIKEOUT:		case P_STRIKE:			lo_ProcessFontTag( state, context, tag, 0, LO_ATTR_STRIKEOUT);			break;		case P_SPELL:			lo_ProcessFontTag( state, context, tag, 0, LO_ATTR_SPELL);			break;		case P_INLINEINPUT:			lo_ProcessFontTag( state, context, tag, 0, LO_ATTR_INLINEINPUT);			break;		case P_INLINEINPUTTHICK:			lo_ProcessFontTag( state, context, tag, 0,                               LO_ATTR_INLINEINPUTTHICK);			break;		case P_INLINEINPUTDOTTED:			lo_ProcessFontTag( state, context, tag, 0, LO_ATTR_INLINEINPUTDOTTED);			break;		/*		 * Another font attribute, another font on the font stack		 */		case P_UNDERLINE:			lo_ProcessFontTag( state, context, tag, 0, LO_ATTR_UNDERLINE);						break;		/*		 * Center all following lines.  Forces a single		 * line break to start and end the new centered lines.		 */		case P_CENTER:			lo_process_center_tag(context, state, tag);			break;		/*		 * For plaintext there is no endtag, so this is		 * really the last tag will we be parsing if this		 * is a plaintext tag.		 *		 * Difference between these three tags are		 * all based on what things the parser allows to		 * be tags while inside them.		 */		case P_PREFORMAT:		case P_PLAIN_PIECE:		case P_PLAIN_TEXT:			if (state->in_paragraph != FALSE)			{				lo_CloseParagraph(context, &state, tag, 2);			}			if (tag->is_end == FALSE)			{				LO_TextAttr *old_attr;				LO_TextAttr *attr;				PA_Block buff;                lo_SetLineBreakState(context, state, FALSE, LO_LINEFEED_BREAK_HARD,                                     2, FALSE);				if ((tag->type == P_PLAIN_PIECE)||					(tag->type == P_PLAIN_TEXT))				{					state->allow_amp_escapes = FALSE;				}				state->preformatted = PRE_TEXT_YES;				FE_BeginPreSection(context);				/*				 * Special WRAP attribute of the PRE tag				 * to make wrapped pre sections.				 */				if (tag->type == P_PREFORMAT)				{					buff = lo_FetchParamValue(context, tag,							PARAM_WRAP);					if (buff != NULL)					{						state->preformatted =							PRE_TEXT_WRAP;						PA_FREE(buff);					}					/*					 * Wrap at a certain column.					 */					buff = lo_FetchParamValue(context, tag,							PARAM_COLS);					if (buff != NULL)					{						char * str;						int32 val;												PA_LOCK(str, char *, buff);						val = XP_ATOI(str);						if (val < 0)						{							val = 0;						}						state->preformat_cols = val;						state->preformatted =							PRE_TEXT_COLS;						PA_FREE(buff);					}										/*					 * Special TABSTOP attribute of the PRE tag					 * to set the tab stop width.					 */					buff = lo_FetchParamValue(context, tag,							PARAM_TABSTOP);					if (buff != NULL)					{						char * str;						int32 val;												PA_LOCK(str, char *, buff);						val = XP_ATOI(str);												/*						 * Note that I made a tabwidth of 0 be an						 * illegal value. lo_PreformatedText divides						 * with tab_stop.						 */						if ( val <= 0 )						{							val = DEF_TAB_WIDTH;						}						state->tab_stop = val;						PA_FREE(buff);					}				}#ifdef DOM                old_attr = lo_GetCurrentTextAttr(state, context);#else				old_attr = state->font_stack->text_attr;#endif				lo_CopyTextAttr(old_attr, &tmp_attr);				/*				 * Allow <PRE VARIABLE> to create a variable				 * width font preformatted section.  This				 * is only to be used internally for 				 * mail and news in Netscape 2.0 and greater.				 */				buff = lo_FetchParamValue(context, tag, PARAM_VARIABLE);				if ((tag->type == P_PREFORMAT)&&(buff != NULL))				{					tmp_attr.fontmask &= (~(LO_FONT_FIXED));				}				else				{					tmp_attr.fontmask |= LO_FONT_FIXED;				}				/*				 * If VARIABLE attribute was there, free				 * the value buffer.				 */				if (buff != NULL)				{					PA_FREE(buff);				}				attr = lo_FetchTextAttr(state, &tmp_attr);				lo_PushFont(state, tag->type, attr);			}			else			{				LO_TextAttr *attr;				attr = lo_PopFont(state, tag->type);				state->preformat_cols = 0;				state->preformatted = PRE_TEXT_NO;				state->allow_amp_escapes = TRUE;                lo_SetLineBreakState(context, state, FALSE, LO_LINEFEED_BREAK_HARD,                                     2, FALSE);				FE_EndPreSection(context);			}			break;		/*		 * Historic text type.  Paragraph break, font size change		 * and font set to fixed.  Was supposed to support		 * lineprinter listings if you can believe that!		 */		case P_LISTING_TEXT:			if (state->in_paragraph != FALSE)			{				lo_CloseParagraph(context, &state, tag, 2);			}			if (tag->is_end == FALSE)			{				LO_TextAttr *old_attr;				LO_TextAttr *attr;				lo_SetSoftLineBreakState(context, state, FALSE, 2);				state->preformatted = PRE_TEXT_YES;				FE_BeginPreSection(context);#ifdef DOM                old_attr = lo_GetCurrentTextAttr(state, context);#else				old_attr = state->font_stack->text_attr;#endif				lo_CopyTextAttr(old_attr, &tmp_attr);				tmp_attr.fontmask |= LO_FONT_FIXED;				tmp_attr.size = DEFAULT_BASE_FONT_SIZE - 1;				attr = lo_FetchTextAttr(state, &tmp_attr);				lo_PushFont(state, tag->type, attr);			}			else			{				LO_TextAttr *attr;				attr = lo_PopFont(state, tag->type);				state->preformatted = PRE_TEXT_NO;				lo_SetSoftLineBreakState(context, state, FALSE, 2);				FE_EndPreSection(context);			}			break;		/*		 * Another historic tag.  Break a line, and switch to italic.		 */		case P_ADDRESS:			if (state->in_paragraph != FALSE)			{				lo_CloseParagraph(context, &state, tag, 2);			}			if (tag->is_end == FALSE)			{				LO_TextAttr *old_attr;				LO_TextAttr *attr;				lo_SetSoftLineBreakState(context, state, FALSE, 1);#ifdef DOM                old_attr = lo_GetCurrentTextAttr(state, context);#else				old_attr = state->font_stack->text_attr;#endif				lo_CopyTextAttr(old_attr, &tmp_attr);				tmp_attr.fontmask |= LO_FONT_ITALIC;				attr = lo_FetchTextAttr(state, &tmp_attr);				lo_PushFont(state, tag->type, attr);			}			else			{				LO_TextAttr *attr;				attr = lo_PopFont(state, tag->type);				lo_SetSoftLineBreakState(context, state, FALSE, 1);			}			break;		/*		 * Subscript.  Move down so the middle of the ascent		 * of the new text aligns with the baseline of the old.		 */		case P_SUB:			if (state->font_stack != NULL)			{				PA_Block buff;				char *str;				LO_TextStruct tmp_text;				LO_TextInfo text_info;				if (tag->is_end == FALSE)				{					LO_TextAttr *old_attr;					LO_TextAttr *attr;					intn new_size;#ifdef DOM                    old_attr = lo_GetCurrentTextAttr(state, context);#else					old_attr = state->font_stack->text_attr;#endif					lo_CopyTextAttr(old_attr, &tmp_attr);					new_size = LO_ChangeFontSize(tmp_attr.size,								"-1");					tmp_attr.size = new_size;					attr = lo_FetchTextAttr(state,						&tmp_attr);					lo_PushFont(state, tag->type, attr);				}				/*				 * 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;					LO_UnlockLayout();					return;				}				PA_LOCK(str, char *, buff);				str[0] = ' ';				PA_UNLOCK(buff);				tmp_text.text = buff;				tmp_text.text_len = 1;				tmp_text.text_attr =#ifdef DOM                  lo_GetCurrentTextAttr(state, context);#else                  state->font_stack->text_attr;#endif				FE_GetTextInfo(context, &tmp_text, &text_info);				PA_FREE(buff);                {                  LO_SubStruct *sub = (LO_SubStruct*)lo_NewElement(context, state, LO_SUB, NULL, 0);			                    XP_ASSERT(sub);                  if (!sub)                    {                      LO_UnlockLayout();                      return;                    }                  sub->lo_any.type = LO_SUB;                  sub->lo_any.ele_id = NEXT_ELEMENT;                  sub->is_end = tag->is_end;                  sub->baseline_adj = text_info.ascent / 2;                  lo_AppendToLineList(context, state, (LO_Element*)sub, 0);                  lo_ProcessSubElement(context, state, sub);                }                if (tag->is_end == TRUE)                  {					lo_PopFont(state, tag->type);                  }			}			break;		/*		 * Superscript.  Move up so the baseline of the new text		 * is raised above the baseline of the old by 1/2 the		 * ascent of the new text.		 */		case P_SUPER:			if (state->font_stack != NULL)			{				PA_Block buff;				char *str;				LO_TextStruct tmp_text;				LO_TextInfo text_info;				if (tag->is_end == FALSE)				{					LO_TextAttr *old_attr;					LO_TextAttr *attr;					intn new_size;#ifdef DOM                    old_attr = lo_GetCurrentTextAttr(state, context);#else					old_attr = state->font_stack->text_attr;#endif					lo_CopyTextAttr(old_attr, &tmp_attr);					new_size = LO_ChangeFontSize(tmp_attr.size,								"-1");					tmp_attr.size = new_size;					attr = lo_FetchTextAttr(state,						&tmp_attr);					lo_PushFont(state, tag->type, attr);				}				/*				 * 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;					LO_UnlockLayout();					return;				}				PA_LOCK(str, char *, buff);				str[0] = ' ';				PA_UNLOCK(buff);				tmp_text.text = buff;				tmp_text.text_len = 1;				tmp_text.text_attr =#ifdef DOM                  lo_GetCurrentTextAttr(state, context);#else                  state->font_stack->text_attr;#endif				FE_GetTextInfo(context, &tmp_text, &text_info);				PA_FREE(buff);                {                  LO_SuperStruct *super = (LO_SuperStruct*)lo_NewElement(context, state, LO_SUPER, NULL, 0);			                    XP_ASSERT(super);                  if (!super)                    {                      LO_UnlockLayout();                      return;                    }                  super->lo_any.type = LO_SUPER;                  super->lo_any.ele_id = NEXT_ELEMENT;                  super->is_end = tag->is_end;                  super->baseline_adj = text_info.ascent / 2;                  lo_AppendToLineList(context, state, (LO_Element*)super, 0);                  lo_ProcessSuperElement(context, state, super);                }                if (tag->is_end == TRUE)                  {					lo_PopFont(state, tag->type);                  }			}			break;		/*		 * Change the base font size that relative font size changes		 * are figured from.		 */		case P_BASEFONT:			{				LO_TextAttr *old_attr;				LO_TextAttr *attr;				PA_Block buff;				intn new_size;				char *size_str;				lo_FontStack *fptr;				buff = lo_FetchParamValue(context, tag, PARAM_SIZE);				if (buff != NULL)				{					PA_LOCK(size_str, char *, buff);					new_size = LO_ChangeFontSize(						state->base_font_size,						size_str);					PA_UNLOCK(buff);					PA_FREE(buff);				}				else				{					new_size = DEFAULT_BASE_FONT_SIZE;				}				state->base_font_size = new_size;				fptr = state->font_stack;				/*				 * If the current font is the basefont				 * we are changing the current font size.				 */				if (fptr->tag_type == P_UNKNOWN)				{					/*					 * Flush all current text before					 * changing the font size.					 */					lo_FlushTextBlock(context, state);				}				/*				 * Traverse the font stack to the base font				 * entry.				 */				while (fptr->tag_type != P_UNKNOWN)				{					fptr = fptr->next;				}				/*				 * Copy the old base entry, change its				 * size, and stuff the new one in its place				 */				old_attr = fptr->text_attr;				lo_CopyTextAttr(old_attr, &tmp_attr);				tmp_attr.size = state->base_font_size;				attr = lo_FetchTextAttr(state, &tmp_attr);				if (attr != NULL)				{					fptr->text_attr = attr;				}			}			break;		/*		 * Change font, currently only lets you change size.		 * Now let you change color.		 * Now let you change FACE.		 */		case P_FONT:			if (tag->is_end == FALSE)			{				LO_TextAttr *old_attr;				LO_TextAttr *attr;				PA_Block buff;				intn new_size;				uint16 new_point_size=0;				uint16 new_font_weight=0;				char *size_str;				char *str;				char *new_face=NULL;				Bool has_face;				Bool has_size;				Bool has_point_size;				Bool has_font_weight = FALSE;				Bool new_colors;				uint8 red, green, blue;				new_size = state->base_font_size;				has_size = FALSE;				has_point_size = FALSE;				has_font_weight = FALSE;				has_face = FALSE;				buff = lo_FetchParamValue(context, tag, PARAM_SIZE);				if (buff != NULL)				{					PA_LOCK(size_str, char *, buff);					new_size = LO_ChangeFontSize(						state->base_font_size,						size_str);					PA_UNLOCK(buff);					PA_FREE(buff);					has_size = TRUE;				}				buff = lo_FetchParamValue(context, tag, PARAM_POINT_SIZE);				if (buff != NULL)				{					PA_LOCK(size_str, char *, buff);					new_point_size = LO_ChangePointSize(						DEFAULT_BASE_POINT_SIZE,						size_str);					PA_UNLOCK(buff);					PA_FREE(buff);					has_point_size = TRUE;				}				buff = lo_FetchParamValue(context, tag, PARAM_FONT_WEIGHT);				if (buff != NULL)				{					PA_LOCK(size_str, char *, buff);					new_font_weight = LO_ChangeFontOrPointSize(						DEFAULT_BASE_FONT_WEIGHT,						size_str,						MIN_FONT_WEIGHT,						MAX_FONT_WEIGHT);					/* normalize 100, 200, ... 900 */					new_font_weight = new_font_weight - (new_font_weight % 100);					PA_UNLOCK(buff);					PA_FREE(buff);					has_font_weight = TRUE;				}				/*				 * For backwards compatibility, a font				 * tag with NO attributes will reset the				 * font size to the base size.				 */				if (PA_TagHasParams(tag) == FALSE)				{					new_size = state->base_font_size;					has_size = TRUE;				}				new_colors = FALSE;				buff = lo_FetchParamValue(context, tag, PARAM_COLOR);				if (buff != NULL)				{				    PA_LOCK(str, char *, buff);				    LO_ParseRGB(str, &red, &green, &blue);				    PA_UNLOCK(buff);				    PA_FREE(buff);				    new_colors = TRUE;				}				if (lo_face_attribute())				{					buff = lo_FetchParamValue(context, tag,							PARAM_FACE);					new_face = NULL;					if (buff != NULL)					{						PA_LOCK(str, char *, buff);						new_face = lo_FetchFontFace(context, state,								str);						PA_UNLOCK(buff);						PA_FREE(buff);						has_face = TRUE;					}				}#ifdef DOM                old_attr = lo_GetCurrentTextAttr(state, context);#else				old_attr = state->font_stack->text_attr;#endif				lo_CopyTextAttr(old_attr, &tmp_attr);				if (has_size != FALSE)				{					tmp_attr.size = new_size;				}				if (has_point_size)					tmp_attr.point_size = (double)new_point_size;				if (has_font_weight)					tmp_attr.font_weight = new_font_weight;				if (new_colors != FALSE)				{				    tmp_attr.fg.red = red;				    tmp_attr.fg.green = green;				    tmp_attr.fg.blue = blue;				}				if (has_face != FALSE)				{				    tmp_attr.font_face = new_face;				}				attr = lo_FetchTextAttr(state, &tmp_attr);				lo_PushFont(state, tag->type, attr);			}			else			{				LO_TextAttr *attr;				attr = lo_PopFont(state, tag->type);			}			break;		/*		 * Change font to bigger than current font.		 */		case P_BIG:			if (tag->is_end == FALSE)			{				LO_TextAttr *old_attr;				LO_TextAttr *attr;				intn new_size;#ifdef DOM                old_attr = lo_GetCurrentTextAttr(state, context);#else				old_attr = state->font_stack->text_attr;#endif				lo_CopyTextAttr(old_attr, &tmp_attr);				new_size = LO_ChangeFontSize(tmp_attr.size, "+1");				tmp_attr.size = new_size;				attr = lo_FetchTextAttr(state, &tmp_attr);				lo_PushFont(state, tag->type, attr);			}			else			{				LO_TextAttr *attr;				attr = lo_PopFont(state, tag->type);			}			break;		/*		 * Change font to smaller than current font.		 */		case P_SMALL:			if (tag->is_end == FALSE)			{				LO_TextAttr *old_attr;				LO_TextAttr *attr;				intn new_size;#ifdef DOM                old_attr = lo_GetCurrentTextAttr(state, context);#else				old_attr = state->font_stack->text_attr;#endif				lo_CopyTextAttr(old_attr, &tmp_attr);				new_size = LO_ChangeFontSize(tmp_attr.size, "-1");				tmp_attr.size = new_size;				attr = lo_FetchTextAttr(state, &tmp_attr);				lo_PushFont(state, tag->type, attr);			}			else			{				LO_TextAttr *attr;				attr = lo_PopFont(state, tag->type);			}			break;		/*		 * Change the absolute URL that describes where this		 * document came from for all following relative URLs.		 */		case P_BASE:			{				PA_Block buff;				char *url;				char *target;				buff = lo_FetchParamValue(context, tag, PARAM_HREF);				if (buff != NULL)				{					PA_LOCK(url, char *, buff);					if (url != NULL)					{					    int32 len;					    len = lo_StripTextWhitespace(							url, XP_STRLEN(url));					}                    lo_SetBaseUrl(state->top_state, url, FALSE);					PA_UNLOCK(buff);					PA_FREE(buff);				}				buff = lo_FetchParamValue(context, tag, PARAM_TARGET);				if (buff != NULL)				{					PA_LOCK(target, char *, buff);					if (target != NULL)					{					    int32 len;					    len = lo_StripTextWhitespace(						target, XP_STRLEN(target));					}				        if (lo_IsValidTarget(target) == FALSE)					{					    PA_UNLOCK(buff);					    PA_FREE(buff);#ifdef XP_OS2_FIX /*trap on double free of buff...*/						buff = NULL;#endif					    target = NULL;					}					if (state->top_state->base_target !=						NULL)					{					    XP_FREE(						state->top_state->base_target);					    state->top_state->base_target =NULL;					}					if (target != NULL)					{					    state->top_state->base_target =							XP_STRDUP(target);					}					PA_UNLOCK(buff);					PA_FREE(buff);				}			}			break;		/*		 * Begin an anchor.  Change font colors if		 * there is an HREF here.  Make the HREF absolute		 * based on the base url.  Check name in case we		 * are jumping to a named anchor inside this document.		 */		case P_ANCHOR:			lo_process_anchor_tag(context, state, tag);			if (state->top_state->out_of_memory != FALSE)			{				LO_UnlockLayout();				return;			}			break;		/*		 * Insert a wordbreak.  Allows layout to break a line		 * at this location in case it needs to.		 */		case P_WORDBREAK:			lo_InsertWordBreak(context, state);			break;		/*		 * All text inside these tags must be considered one		 * word, and not broken (unless there is a word break		 * in there).		 */		case P_NOBREAK:			if (tag->is_end == FALSE)			{				state->breakable = FALSE;			}			else			{				state->breakable = TRUE;			}			break;		/*		 * spacer element to move stuff around		 */		case P_SPACER:			if (tag->is_end == FALSE && !state->hide_content)			{				lo_ProcessSpacerTag(context, state, tag);			}			break;		case P_MULTICOLUMN:			lo_process_multicolumn_tag(context, state, tag);			break;		case P_LAYER:        case P_ILAYER:			if(state->hide_content)			{				break;  /* skip layer */            }			else if (tag->is_end == FALSE)			{                /* Can't have a layer inside a form */                if (state->top_state->in_form != FALSE)                {                    lo_EndForm(context, state);                    lo_SetSoftLineBreakState(context, state, FALSE, 2);                }				lo_BeginLayerTag(context, state, tag);			}			else			{   			    /* Don't close blocks unless they were opened in this scope. */				if (state->layer_nest_level > 0)				{					lo_EndLayerTag(context, state, tag);				}			}			break;		/*		 * Break the current line.		 * Optionally break further down to get past floating		 * elements in the margins.		 */		case P_LINEBREAK:		  		  {			uint8 clear_type = LO_CLEAR_NONE;			if(state->hide_content)				break;  /* skip the whole tag */			{			    PA_Block buff;			    buff = lo_FetchParamValue(context, tag, PARAM_CLEAR);			    if (buff != NULL)			    {				char *clear_str;				PA_LOCK(clear_str, char *, buff);				if (pa_TagEqual("left", clear_str))				{				  clear_type = LO_CLEAR_TO_LEFT;				}				else if (pa_TagEqual("right", clear_str))				{				  clear_type = LO_CLEAR_TO_RIGHT;				}				else if (pa_TagEqual("all", clear_str))				{				  clear_type = LO_CLEAR_TO_BOTH;				}				else if (pa_TagEqual("both", clear_str))				{				  clear_type = LO_CLEAR_TO_BOTH;				}				else if (pa_TagEqual("none", clear_str))			    {				  clear_type = LO_CLEAR_NONE;				}				else				{				  /* default to clear none  */				  clear_type = LO_CLEAR_NONE;				}				PA_UNLOCK(buff);				PA_FREE(buff);				/*				 * Reset the margins properly in case				 * we are inside a list.				 */				lo_FindLineMargins(context, state, TRUE);				state->x = state->left_margin;			    }			}			/*			 * <br> tag diabled in preformatted text			 */#ifdef EDITOR			if (state->preformatted != PRE_TEXT_NO && !EDT_IS_EDITOR(context))#else			if (state->preformatted != PRE_TEXT_NO)#endif			{				lo_SetSoftLineBreakState(context, state, FALSE, 1);				break;			}			lo_HardLineBreakWithClearType(context, state, clear_type, FALSE);#ifdef EDITOR			/* editor hack.  Make breaks always do something. */			if ( EDT_IS_EDITOR(context) ) {				state->linefeed_state = 0;            }#endif			switch(clear_type) 			  {			  case LO_CLEAR_TO_LEFT:				lo_ClearToLeftMargin(context, state);				break;			  case LO_CLEAR_TO_RIGHT:				lo_ClearToRightMargin(context, state);				break;			  case LO_CLEAR_TO_ALL:			  case LO_CLEAR_TO_BOTH:				lo_ClearToBothMargins(context, state);				break;			  case LO_CLEAR_NONE:			  default:				break;			}			/*			 * Reset the margins properly in case			 * we are inside a list.			 */			lo_FindLineMargins(context, state, TRUE);			state->x = state->left_margin;						break;		  }		/*		 * The head tag.  The tag is supposed to be a container		 * for the head of the HTML document.		 * We use it to try and detect when we should		 * suppress the content of unknown head tags.		 */		case P_HEAD:			/*			 * The end HEAD tags defines the end of			 * the HEAD section of the HTML			 */			if (tag->is_end != FALSE)			{				state->top_state->in_head = FALSE;			}			break;		/*		 * The body tag.  The tag is supposed to be a container		 * for the body of the HTML document.		 * Right now we are just using it to specify		 * the document qualities and colors.		 */		case P_BODY:			/*			 * The start of BODY definitely ends			 * the HEAD section of the HTML and starts the BODY			 * Only process this body tag if we aren't already			 * in a body.			 */			if (state->top_state->in_body == FALSE)			{				state->top_state->in_head = FALSE;				state->top_state->in_body = TRUE;				lo_ProcessBodyTag(context, state, tag);			}			else			{				state->top_state->in_head = FALSE;				state->top_state->in_body = TRUE;				/*				 * We now process later bodies just to				 * see if they set attributes not set by				 * the first body.				 */				lo_ProcessBodyTag(context, state, tag);			}			break;		/*		 * The colormap tag.  This is used to specify the colormap		 * to be used by all the images on this page.		 */		case P_COLORMAP:			if ((tag->is_end == FALSE)&&				(state->end_last_line == NULL))			{				PA_Block buff;				char *str;				char *image_url;				image_url = NULL;				buff = lo_FetchParamValue(context, tag, PARAM_SRC);				if (buff != NULL)				{					PA_LOCK(str, char *, buff);					if (str != NULL)					{						int32 len;						len = lo_StripTextWhitespace(							str, XP_STRLEN(str));					}					image_url = NET_MakeAbsoluteURL(						state->top_state->base_url,str);					PA_UNLOCK(buff);					PA_FREE(buff);				}#ifndef M12N                    /* XXXM12N Fix me.  Colormap tag has yet to                                   implemented. */				(void)IL_ColormapTag(image_url, context);#endif /* M12N */				if (image_url != NULL)				{					XP_FREE(image_url);				}			}			break;		/*		 * The meta tag.  This tag can only appear in the		 * head of the document.		 * It overrides HTTP headers sent by the		 * web server that served this document.		 * If URLStruct somehow became NULL, META must		 * be ignored.		 */		case P_META:			if ((tag->is_end == FALSE)&&				/* (state->end_last_line == NULL)&& allow in head */				(state->top_state->nurl != NULL))			{				PA_Block buff;				PA_Block buff2;				PA_Block buff3;				char *name;				char *value;				char *tptr;				buff = lo_FetchParamValue(context, tag, "rel");				if (buff != NULL)				{					char *rel_val = (char*)buff;										/* try and fetch the src */					buff2 = lo_FetchParamValue(context, tag, PARAM_SRC);					if (buff2 != NULL)					{						if(!strcasecomp(rel_val, "SMALL_BOOKMARK_ICON"))						{							state->top_state->small_bm_icon =								 NET_MakeAbsoluteURL(state->top_state->base_url, 												  rel_val);						}						else if(!strcasecomp(rel_val, "LARGE_BOOKMARK_ICON"))						{							state->top_state->large_bm_icon =								 NET_MakeAbsoluteURL(state->top_state->base_url, 												  rel_val);						}						PA_FREE(buff2);					}					PA_FREE(buff);					}				buff = lo_FetchParamValue(context, tag,					PARAM_HTTP_EQUIV);				if (buff != NULL)				{				    /*				     * Lou needs a colon on the end of				     * the name.				     */				    PA_LOCK(tptr, char *, buff);				    buff3 = PA_ALLOC(XP_STRLEN(tptr) + 2);				    if (buff3 != NULL)				    {					PA_LOCK(name, char *, buff3);					XP_STRCPY(name, tptr);					XP_STRCAT(name, ":");					PA_UNLOCK(buff);					PA_FREE(buff);					buff2 = lo_FetchParamValue(context, tag,						PARAM_CONTENT);					if (buff2 != NULL)					{						Bool ok;						PA_LOCK(value, char *, buff2);						ok = NET_ParseMimeHeader(							FO_PRESENT,							context,							state->top_state->nurl,							name, value, FALSE);						PA_UNLOCK(buff2);						PA_FREE(buff2);						if (INTL_GetCSIRelayoutFlag(c) == METACHARSET_REQUESTRELAYOUT)						{							INTL_SetCSIRelayoutFlag(c, METACHARSET_FORCERELAYOUT);							INTL_Relayout(context);						}					}					PA_UNLOCK(buff3);					PA_FREE(buff3);				    }				    else				    {					PA_UNLOCK(buff);					PA_FREE(buff);				    }				}			}						if (tag->is_end == FALSE && state && state->top_state)			{				/* Build up meta tags list for consumption by the RDF HT */				lo_TopState *top_state = state->top_state;				if ( top_state->metaTags == NULL )				{					top_state->metaTags = (TagList *) XP_NEW_ZAP( TagList );					top_state->metaTags->tagList = PA_CloneMDLTag( tag );					top_state->metaTags->lastTag = top_state->metaTags->tagList;				}				else 				{					top_state->metaTags->lastTag->next = PA_CloneMDLTag( tag );					top_state->metaTags->lastTag = top_state->metaTags->lastTag->next;				}			}			break;		/*		 * The hype tag is just for fun.		 * It only affects the UNIX version		 * which can afford to have a sound file		 * compiled into the binary.		 */		case P_HYPE:#if defined(XP_UNIX) || defined(XP_MAC)			if (tag->is_end == FALSE && !state->hide_content)			{			    PA_Tag tmp_tag;			    PA_Block buff;			    PA_Block abuff;			    LO_AnchorData *hold_current_anchor;			    LO_AnchorData *hype_anchor;			    char *str;			    /*			     * Try to allocate the hype anchor as if we			     * were inside:			     * <A HREF="HYPE_ANCHOR">			     * Save the real current anchor to restore later			     */			    hype_anchor = NULL;			    abuff = PA_ALLOC(XP_STRLEN(HYPE_ANCHOR) + 1);			    if (abuff != NULL)			    {				hype_anchor = lo_NewAnchor(state, NULL, NULL);				if (hype_anchor == NULL)				{				    PA_FREE(abuff);				    abuff = NULL;				}				else				{				    PA_LOCK(str, char *, abuff);				    XP_STRCPY(str, HYPE_ANCHOR);				    PA_UNLOCK(abuff);				    hype_anchor->anchor = abuff;				    hype_anchor->target = NULL;				    /*				     * Add this url's block to the list				     * of all allocated urls so we can free				     * it later.				     */				    lo_AddToUrlList(context, state, hype_anchor);				    if (state->top_state->out_of_memory !=FALSE)				    {					PA_FREE(abuff);					XP_DELETE(hype_anchor);					LO_UnlockLayout();					return;				    }				}			    }			    hold_current_anchor = state->current_anchor;			    state->current_anchor = hype_anchor;			    /*			     * If we have the memory, create a fake image			     * tag to replace the <HYPE> tag and process it.			     */			    buff = PA_ALLOC(XP_STRLEN(HYPE_TAG_BECOMES)+1);			    if (buff != NULL)			    {				PA_LOCK(str, char *, buff);				XP_STRCPY(str, HYPE_TAG_BECOMES);				PA_UNLOCK(buff);				tmp_tag.type = P_IMAGE;				tmp_tag.is_end = FALSE;				tmp_tag.newline_count = tag->newline_count;				tmp_tag.data = buff;				tmp_tag.data_len = XP_STRLEN(HYPE_TAG_BECOMES);				tmp_tag.true_len = 0;				tmp_tag.lo_data = NULL;				tmp_tag.next = NULL;				lo_FormatImage(context, state, &tmp_tag);				PA_FREE(buff);			    }			    /*			     * Restore the proper current_anchor.			     */			    state->current_anchor = hold_current_anchor;			}#endif /* XP_UNIX */			break;		/*		 * Insert a horizontal rule element.		 * They always take up an entire line.		 */		case P_HRULE:			if (state->in_paragraph != FALSE)			{				lo_CloseParagraph(context, &state, tag, 2);			}			/*			 * HR now does alignment the same as P, H?, and DIV.			 * Ignore </hr>.			 */			if (tag->is_end == FALSE && !state->hide_content)			{				lo_SetSoftLineBreakState(context, state, FALSE, 1);				lo_HorizontalRule(context, state, tag);			}			break;		/*		 * Experimental!  May be used to implement TABLES		 */		case P_CELL:			break;		/*		 * The start of a caption in a table		 */		case P_CAPTION:			if(!state->hide_content)				lo_process_caption_tag(context, state, tag);			break;		/*		 * The start of a header or data cell		 * in a row in a table		 */		case P_TABLE_HEADER:		case P_TABLE_DATA:			if(!state->hide_content)				lo_process_table_cell_tag(context, state, tag);			break;		/*		 * The start of a row in a table		 */		case P_TABLE_ROW:			if(!state->hide_content)				lo_process_table_row_tag(context, state, tag);			break;		/*		 * The start of a table.  Since this can cause the 		 *   destruction of elements that others may be holding		 *   pointers to, make sure they are out of their critical		 *   sections before starting to layout the table		 */		case P_TABLE:			if(!state->hide_content)				lo_process_table_tag(context, state, tag);			break;		/*		 * Experimental!  Everything in these tags is a complete		 * separate sub document, it should be formatted, and the		 * resulting entire document placed just like an image.		 */		case P_SUBDOC:			break;		/*		 * Begin a grid.  MUST be the very first thing inside		 * this HTML document.  After a grid is started, all non-grid		 * tags will be ignored!		 * Also, right now the text and postscript FEs can't		 * handle grids, so we block them.		 */		case P_GRID:			if ((context->type != MWContextText)&&			    (context->type != MWContextPostScript)&&				(EDT_IS_EDITOR(context) == FALSE)&&			    (state->top_state->nothing_displayed != FALSE)&&                !lo_InsideLayer(state) &&			    (state->top_state->in_body == FALSE)&&			    (state->end_last_line == NULL)&&			    /* (state->line_list == NULL)&& */    /* Can be non-null because we are putting TEXTBLOCK													     elements on there each time we get text tags*/			    (state->float_list == NULL)&&			    (state->top_state->the_grid == NULL))			{			    if (tag->is_end == FALSE)			    {				if (state->current_grid == NULL)				{					state->top_state->is_grid = TRUE;					/*					 * We may be restoring a grid from					 * history.  If so we recreate it					 * from saved data, and ignore all					 * the rest of the tags in this					 * document.  This happens because					 * we will set the_grid and not					 * set current_grid, so all					 * grid tags are ignored, and since					 * we have set is_grid, all non-grid					 * tags will be ignored.					 *					 * Only recreate if main window					 * size has not changed.					 */					if (state->top_state->savedData.Grid->the_grid != NULL)					{					    lo_SavedGridData *savedGridData;					    int32 width, height;					    width = state->win_width;					    height = state->win_height;					    FE_GetFullWindowSize(context,						&width, &height);					    savedGridData =					      state->top_state->savedData.Grid;					    if ((savedGridData->main_width ==							width)&&					        (savedGridData->main_height ==							height))					    {						lo_RecreateGrid(context, state,						    savedGridData->the_grid);						savedGridData->the_grid =NULL;					    }					    else					    {						/*						 * If window size has changed						 * on the grid we are restoring						 * we process normally, but						 * hang on to the old data so						 * we can restore the grid cell						 * contents once new sizes are						 * calculated.						 */						state->top_state->old_grid =						    savedGridData->the_grid;						savedGridData->the_grid =NULL;						lo_BeginGrid(context, state,								tag);					    }					}					else					{					    lo_BeginGrid(context, state, tag);					}				}				else				{					lo_BeginSubgrid(context, state, tag);				}			    }			    else if ((tag->is_end != FALSE)&&					(state->current_grid != NULL))			    {				lo_GridRec *grid;				grid = state->current_grid;				if (grid->subgrid == NULL)				{					state->current_grid = NULL;					lo_EndGrid(context, state, grid);				}				else				{					lo_EndSubgrid(context, state, grid);				}			    }			}			break;		/*		 * A grid cell can only happen inside a grid		 */		case P_GRID_CELL:			if ((state->top_state->nothing_displayed != FALSE)&&                !lo_InsideLayer(state) &&			    (state->top_state->in_body == FALSE)&&			    (state->end_last_line == NULL)&&			    /* state->line_list == NULL)&& */	/* Can be non-null because we are putting TEXTBLOCK													   elements on there each time we get text tags*/				    (state->float_list == NULL)&&			    (state->current_grid != NULL))			{				if (tag->is_end == FALSE)				{					lo_BeginGridCell(context, state, tag);				}			}			break;		/*		 * Begin a map.  Maps define area in client-side		 * image maps.		 */		case P_MAP:			if ((tag->is_end == FALSE)&&			    (state->top_state->current_map == NULL))			{				lo_BeginMap(context, state, tag);			}			else if ((tag->is_end != FALSE)&&				 (state->top_state->current_map != NULL))			{				lo_MapRec *map;				map = state->top_state->current_map;				state->top_state->current_map = NULL;				lo_EndMap(context, state, map);			}			break;		/*		 * An area definition, can only happen inside a MAP		 * definition for a client-side image map.		 */		case P_AREA:			if ((state->top_state->current_map != NULL)&&				(tag->is_end == FALSE))			{				lo_BeginMapArea(context, state, tag);			}			break;		/*		 * Shortcut and old historic tag to auto-place		 * a simple single item query form.		 */		case P_INDEX:			/*			 * No forms in the scrolling document			 * hack			 */			if (state->top_state->scrolling_doc != FALSE)			{				break;			}			if ((tag->is_end == FALSE)&&				(state->top_state->in_form == FALSE))			{				if (state->in_paragraph != FALSE)				{					lo_CloseParagraph(context, &state, tag, 2);				}				if(!state->hide_content)					lo_ProcessIsIndexTag(context, state, tag);			}			break;		/*		 * Begin a form.		 * Form cannot be nested!		 */		case P_FORM:#if defined(SingleSignon)            /* Notify the signon module of the new form */            SI_StartOfForm();#endif			/*			 * No forms in the scrolling document			 * hack			 */			if (state->top_state->scrolling_doc != FALSE)			{				break;			}			if (state->in_paragraph != FALSE)			{				lo_CloseParagraph(context, &state, tag, 2);			}			if (tag->is_end == FALSE)			{				/*				 * Sorry, no nested forms				 */				if (state->top_state->in_form == FALSE)				{					lo_SetLineBreakState(context, state, FALSE,										 LO_LINEFEED_BREAK_HARD, 2, FALSE);					lo_BeginForm(context, state, tag);				}			}			else if (state->top_state->in_form != FALSE)			{				lo_EndForm(context, state);				lo_SetLineBreakState(context, state, FALSE,									 LO_LINEFEED_BREAK_HARD, 2, FALSE);			}			break;		/*		 * Deceptive simple form element tag.  Can only be inside a		 * form.  Really multiplies into one of many possible		 * input elements.		 */		case P_INPUT:			/*			 * Input tags only inside an open form.			 */			if ((state->top_state->in_form != FALSE)&&				(tag->is_end == FALSE))			{				if (state->in_paragraph != FALSE)				{					lo_CloseParagraph(context, &state, tag, 2);				}				if(!state->hide_content)					lo_ProcessInputTag(context, state, tag);			}			break;		/*		 * A multi-line text input form element.  It encloses text		 * that will be its default text.		 */		case P_TEXTAREA:			/*			 * Textarea tags only inside an open form.			 */			if (state->top_state->in_form != FALSE				&& !state->hide_content)			{			    if (state->in_paragraph != FALSE)			    {				lo_CloseParagraph(context, &state, tag, 2);			    }			    if (tag->is_end == FALSE)			    {				lo_FlushTextBlock(context, state);				state->line_buf_len = 0;				state->text_divert = tag->type;				lo_BeginTextareaTag(context, state, tag);			    }			    else if (state->text_divert == tag->type)			    {				PA_Block buff;				int32 len;				int32 new_len;				if (state->line_buf_len != 0)				{				    PA_LOCK(tptr2, char *,					state->line_buf);				    /*				     * Don't do this, they were already				     * expanded by the parser.				    (void)pa_ExpandEscapes(tptr2,					state->line_buf_len, &len, TRUE);				     */				    len = state->line_buf_len;				    buff = lo_ConvertToFELinebreaks(tptr2, len,						&new_len);				    PA_UNLOCK(state->line_buf);				}				else				{				    buff = NULL;				    new_len = 0;				}				lo_EndTextareaTag(context, state, buff);				state->line_buf_len = 0;				state->text_divert = P_UNKNOWN;			    }			}			break;		/*		 * Option tag can only occur inside a select inside a form		 */		case P_OPTION:			/*			 * Select tags only inside an open select			 * in an open form.			 */			if ((state->top_state->in_form != FALSE)&&				(tag->is_end == FALSE)&&				(state->current_ele != NULL)&&				(!state->hide_content)&&				(state->current_ele->type == LO_FORM_ELE)&&                                ((state->current_ele->lo_form.element_data->type                                        == FORM_TYPE_SELECT_ONE)||                                 (state->current_ele->lo_form.element_data->type                                        == FORM_TYPE_SELECT_MULT)))			{			    if (state->in_paragraph != FALSE)			    {				lo_CloseParagraph(context, &state, tag, 2);			    }			    if (state->text_divert == P_OPTION)			    {				PA_Block buff;				int32 len;				if (state->line_buf_len != 0)				{				    PA_LOCK(tptr2, char *,					state->line_buf);				    /*  				     * Don't do this, they were already				     * expanded by the parser.				    (void)pa_ExpandEscapes(tptr2,					state->line_buf_len, &len, TRUE);				     */				    len = state->line_buf_len;				    len = lo_CleanTextWhitespace(tptr2, len);				    buff = PA_ALLOC(len + 1);				    if (buff != NULL)				    {					PA_LOCK(tptr, char *, buff);					XP_BCOPY(tptr2, tptr, len);					tptr[len] = '\0';					PA_UNLOCK(buff);				    }				    PA_UNLOCK(state->line_buf);				}				else				{				    buff = NULL;				    len = 0;				}				lo_EndOptionTag(context, state, buff);			    }			    state->line_buf_len = 0;			    lo_BeginOptionTag(context, state, tag);			    state->text_divert = tag->type;			}			break;		/*		 * Select tag, either an option menu or a scrolled		 * list inside a form.  Lets you chose N of Many.		 */		case P_SELECT:			/*			 * Select tags only inside an open form.			 */			if ((state->top_state->in_form != FALSE)&&				(!state->hide_content))			{			    /*			     * Because SELECT doesn't automatically flush,			     * we must do it here if this is the start of a			     * select.			     */			    if ((tag->is_end == FALSE)&&				(state->current_ele == NULL))			    {				lo_FlushTextBlock(context, state);			    }			    if (state->in_paragraph != FALSE)			    {				lo_CloseParagraph(context, &state, tag, 2);			    }			    if ((tag->is_end == FALSE)&&				(state->current_ele == NULL))			    {				/*				 * Don't allow text between beginning of select				 * and beginning of first option.				 */			        state->text_divert = tag->type;				lo_BeginSelectTag(context, state, tag);			    }			    else if ((state->current_ele != NULL)&&				(state->current_ele->type == LO_FORM_ELE)&&				((state->current_ele->lo_form.element_data->type					== FORM_TYPE_SELECT_ONE)||				 (state->current_ele->lo_form.element_data->type					== FORM_TYPE_SELECT_MULT)))			    {			        if (state->text_divert == P_OPTION)			        {				    PA_Block buff;				    int32 len;				    if (state->line_buf_len != 0)				    {				        PA_LOCK(tptr2, char *,					    state->line_buf);					/*  					 * Don't do this, they were already					 * expanded by the parser.				        (void)pa_ExpandEscapes(tptr2,					    state->line_buf_len, &len, TRUE);					 */					len = state->line_buf_len;				        len = lo_CleanTextWhitespace(tptr2,len);				        buff = PA_ALLOC(len + 1);				        if (buff != NULL)				        {					    PA_LOCK(tptr, char *, buff);					    XP_BCOPY(tptr2, tptr, len);					    tptr[len] = '\0';					    PA_UNLOCK(buff);				        }				        PA_UNLOCK(state->line_buf);				    }				    else				    {				        buff = NULL;				        len = 0;				    }				    lo_EndOptionTag(context, state, buff);			        }			        state->line_buf_len = 0;			        state->text_divert = P_UNKNOWN;				lo_EndSelectTag(context, state);			    }			}			break;		/*		 * Place an embedded object.		 * Just reserve an area of layout for that object		 * to use as it wishes.		 */		case P_EMBED:			if (tag->is_end == FALSE && !state->hide_content)			{#ifdef ANTHRAX				PA_Block buff;				NET_cinfo* fileInfo;				char* str;				char* appletName;#endif				/*				 * If we have started loading an EMBED we are				 * out if the HEAD section of the HTML				 * and into the BODY				 */				state->top_state->in_head = FALSE;				state->top_state->in_body = TRUE;				#ifdef ANTHRAX								/* determine the mimetype */				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);                    /*					//lo_AddParam(tag, "CODE", appletName);					//lo_RemoveParam(tag, "type");					//lo_AddParam(tag, "TYPE", "application/x-java-vm");					//lo_FormatEmbed(context, state, tag);                    */										lo_ProcessObjectTag(context, state, tag, FALSE);					tag->is_end = TRUE;					lo_ProcessObjectTag(context, state, tag, FALSE);					}				else					lo_FormatEmbed(context, state, tag);#else				lo_FormatEmbed(context, state, tag);#endif /* ANTHRAX */			}			break;		/*		 * Generate a public/private key pair.  The user sees		 * a selection of key sizes to choose from; an ascii		 * representation of the public key becomes the form		 * field value.		 */		case P_KEYGEN:			/*			 * Keygen tags only inside an open form.			 */			if ((state->top_state->in_form != FALSE)&&			    (tag->is_end == FALSE)&&				(!state->hide_content))			{				if (state->in_paragraph != FALSE)				{					lo_CloseParagraph(context, &state, tag, 2);				}				lo_ProcessKeygenTag(context, state, tag);			}			break;		/*		 * Process Mocha script source in a <SCRIPT LANGUAGE="Mocha">		 * ...</SCRIPT> container.  Drop all unknown language SCRIPT		 * contents on the floor.  Process SRC=<url> attributes for		 * known languages.		 */		case P_SCRIPT:#ifdef EDITOR			if( EDT_IS_EDITOR( context ) )			{				goto process_server;			}#endif			if(!state->hide_content)				lo_ProcessScriptTag(context, state, tag, NULL);			break;        case P_STYLE:			if(!state->hide_content)				lo_ProcessStyleTag(context, state, tag);			break;		case P_LINK:			/* link tag */            {				PA_Block buff = lo_FetchParamValue(context, tag, PARAM_REL);                if (buff != NULL)				{					if (strcasestr((char *)buff, "stylesheet"))					{						char *media = (char*)lo_FetchParamValue(context, tag, PARAM_MEDIA);						/* check for media=screen						 * don't load the style sheet if there 						 * is a media not equal to screen						 */						if(!media || !strcasecomp(media, "screen"))						{							if(LO_StyleSheetsEnabled(context))							{								/* set stylesheet tag stack on */								if(state->top_state && state->top_state->style_stack)								{									STYLESTACK_SetSaveOn(state->top_state->style_stack, TRUE);								}								lo_ProcessScriptTag(context, state, tag, NULL);								/* now end the script since								 * link is an empty tag 								 */								tag->is_end = TRUE;								lo_ProcessScriptTag(context, state, tag, NULL);								tag->is_end = FALSE;							}						}						XP_FREEIF(media);					}					else if (!strcasecomp((char *)buff, "fontdef") &&						!state->top_state->resize_reload)					{						/* Webfonts */						PA_Block buff2 = lo_FetchParamValue(context, tag, PARAM_SRC);						char *font_url = NULL;						char *str = NULL;						if (buff2 != NULL)						{							PA_LOCK(str, char *, buff2);							if (str != NULL)							{								(void) lo_StripTextWhitespace(str,									XP_STRLEN(str));							}							font_url = NET_MakeAbsoluteURL(								state->top_state->base_url, str);							PA_UNLOCK(buff2);							PA_FREE(buff2);						}						if (font_url)						{#ifdef WEBFONTS							if (WF_fbu)							{								/* Download the webfont */								nffbu_LoadWebfont(WF_fbu, context, font_url,									FORCE_RELOAD_FLAG(state->top_state), NULL);							}#endif /* WEBFONTS */							XP_FREE(font_url);						}					}					else if (!strcasecomp((char *)buff, "sitemap"))					{						/* RDF sitemaps */						PA_Block buff2 = lo_FetchParamValue(context, tag, PARAM_SRC);                        PA_Block buff3 = lo_FetchParamValue(context, tag, PARAM_NAME);						char *rdfURL = NULL;						char *str = NULL;						if (buff2 == NULL) buff2 = lo_FetchParamValue(context, tag, PARAM_HREF);						if (buff2 != NULL)						{							PA_LOCK(str, char *, buff2);							if (str != NULL)							{								(void) lo_StripTextWhitespace(str,									XP_STRLEN(str));							}							rdfURL = NET_MakeAbsoluteURL(								state->top_state->base_url, str);                            if (rdfURL)                              {                                XP_AddNavCenterSitemap(context, rdfURL, (char *)buff3);                              }							PA_UNLOCK(buff2);							PA_FREE(buff2);							PA_UNLOCK(buff3);							PA_FREE(buff3);						}					}					else if (!strcasecomp((char *)buff, "prefetch"))					{						char *prefetchURL=NULL;						char *str;						PA_Block buff2 = lo_FetchParamValue(context, tag, PARAM_SRC);						if (buff2)						{							PA_LOCK(str, char *, buff2);							if (str)							{								(void) lo_StripTextWhitespace(str, XP_STRLEN(str));							}							prefetchURL = NET_MakeAbsoluteURL(									state->top_state->base_url, str);							PA_UNLOCK(buff2);							PA_FREE(buff2);						}						if (prefetchURL)						{							PRE_AddToList(context, prefetchURL);						}					}											else if (!strcasecomp((char *)buff, "privacypolicy"))					{						char *policyURL=NULL;						char *str;						PA_Block buff2 = lo_FetchParamValue(context, tag, PARAM_SRC);						History_entry *hist;						if (buff2)						{							PA_LOCK(str, char *, buff2);							if (str)							{								(void) lo_StripTextWhitespace(str, XP_STRLEN(str));							}							policyURL = NET_MakeAbsoluteURL(								      state->top_state->base_url, str);							PA_UNLOCK(buff2);							PA_FREE(buff2);						}						if (policyURL)						{							hist = SHIST_GetCurrent(&context->hist);							if (hist)								hist->privacy_policy_url = policyURL;						}						}									PA_FREE(buff);				}			}			break;		/*		 * We were blocking on a <script> tag, while being processed		 *   it did a document.write("something that blocked us").		 * Now the elements in the above call are no longer blocking		 *   us but we need to continue to block on the script tag		 *   since it might have more output		 */		case P_NSCP_REBLOCK:		    if (state->in_relayout == FALSE) 		    {				state->top_state->layout_blocking_element = tag->lo_data;				XP_ASSERT(tag->newline_count == state->top_state->input_write_level);				state->top_state->input_write_level--;				ET_DocWriteAck(context, 0);		    }		    break;		/*		 * This is the NEW HTML-WG approved embedded JAVA		 * application.		 */#if defined(OJI)		case P_JAVA_APPLET:			javaPlugin = NPL_FindPluginEnabledForType(JAVA_PLUGIN_MIMETYPE);			/* If there is a JVM installed as a plugin, redirect to the object tag */			if(javaPlugin && !state->hide_content)			{				if(tag->is_end == FALSE)				{					PA_Block buff;					char* str;					buff = lo_FetchParamValue(context, tag, PARAM_CODE);					if(buff)					{						PA_LOCK(str, char *, buff);						lo_AddParam(tag, "TYPE", JAVA_PLUGIN_MIMETYPE);						PA_UNLOCK(buff);						XP_FREE(buff);						tag->type = P_OBJECT;						lo_ProcessObjectTag(context, state, tag, FALSE);					}				}				else				{					tag->type = P_OBJECT;					lo_ProcessObjectTag(context, state, tag, FALSE);				}								XP_FREE(javaPlugin);				}			break;#elif defined(JAVA)		case P_JAVA_APPLET:		    /*		     * If the user has disabled Java, act like it we don't		     * understand the APPLET tag.		     */		    if (!state->hide_content && LJ_GetJavaEnabled() != FALSE)		    {			if (tag->is_end == FALSE)			{			    /*			     * If we open a new java applet without closing			     * an old one, force a close of the old one			     * first.			     * Now open the new java applet.			     */			    if (state->current_java != NULL)			    {				lo_CloseJavaApp(context, state,						state->current_java);				state->current_java = NULL;				lo_FormatJavaApp(context, state, tag);			    }			    /*			     * Else this is a new java applet, open it.			     */			    else			    {				/*				 * If we have started loading an APPLET we are				 * out if the HEAD section of the HTML				 * and into the BODY				 */				state->top_state->in_head = FALSE;				state->top_state->in_body = TRUE;								lo_FormatJavaApp(context, state, tag);			    }			}			else			{			    /*			     * Only close a java app if it exists.			     */			    if (state->current_java != NULL)			    {				lo_CloseJavaApp(context, state,						state->current_java);				state->current_java = NULL;			    }			}		    }			break;#endif /* JAVA */		case P_OBJECT:			if(!state->hide_content)				lo_ProcessObjectTag(context, state, tag, FALSE);			break;		case P_PARAM:			if(!state->hide_content)				lo_ProcessParamTag(context, state, tag, FALSE);			break;		/*		 * Place an image.  Special because if layout of all		 * other tags was blocked, image tags are still		 * partially processed at that time.		 */		case P_IMAGE:		case P_NEW_IMAGE:			if (tag->is_end == FALSE && !state->hide_content)			{				/*				 * If we have started loading an IMAGE we are				 * out if the HEAD section of the HTML				 * and into the BODY				 */				state->top_state->in_head = FALSE;				state->top_state->in_body = TRUE;				if (tag->lo_data != NULL)				{					lo_PartialFormatImage(context, state,tag);				}				else				{					lo_FormatImage(context, state, tag);				}			}			break;		/*		 * Paragraph break, a single line of whitespace.		 */		case P_PARAGRAPH:			lo_process_paragraph_tag(context, state, tag, style_struct);			break;		/*		 * Division.  General alignment text block		 */		case P_DIVISION:			/*			 * The start of a division infers the end of			 * the HEAD section of the HTML and starts the BODY			 */			state->top_state->in_head = FALSE;			state->top_state->in_body = TRUE;			if (state->in_paragraph != FALSE)			{				lo_CloseParagraph(context, &state, tag, 2);			}			lo_SetLineBreakState(context, state, FALSE,								 LO_LINEFEED_BREAK_HARD, 1, FALSE);			if (tag->is_end == FALSE)			{				PA_Block buff;				char *str;				int32 alignment;				Bool is_multicol;				/*				 * By default inherit current alignment				 * for DIV tags that set COLS but not				 * ALIGN.				 */				if (state->align_stack != NULL)				{					alignment = state->align_stack->alignment;				}				else				{					alignment = LO_ALIGN_LEFT;				}				buff = lo_FetchParamValue(context, tag, PARAM_ALIGN);				if (buff != NULL)				{					PA_LOCK(str, char *, buff);					alignment =					  (int32)lo_EvalDivisionAlignParam(str);					PA_UNLOCK(buff);					PA_FREE(buff);				}				is_multicol = FALSE;				/*				 * If a DIV tag has a COLS attribute of				 * greater than 1, then treat it as a				 * MULTICOL tag.				 */				buff = lo_FetchParamValue(context, tag, PARAM_COLS);				if (buff != NULL)				{					int32 cols;					PA_LOCK(str, char *, buff);					cols = XP_ATOI(str);					PA_UNLOCK(buff);					PA_FREE(buff);					if (cols > 1)					{						is_multicol = TRUE;					}				}				if (is_multicol == FALSE)				{					lo_PushAlignment(state, tag->type, alignment);				}				else				{					lo_PushAlignment(state, P_MULTICOLUMN, alignment);					/*					lo_BeginMulticolumn(context, state, tag);					*/					lo_process_multicolumn_tag(context, state, tag);				}			}			else			{				lo_AlignStack *aptr;				Bool is_multicol;				is_multicol = FALSE;				aptr = lo_PopAlignment(state);				if (aptr != NULL)				{					if (aptr->type == P_MULTICOLUMN)					{						is_multicol = TRUE;					}					XP_DELETE(aptr);				}				/*				 * If this closing DIV closes a DIV that				 * was acting like a MULTICOL, then				 * we must close the fake MULTICOL tag				 * here.				 */				if ((is_multicol != FALSE)&&					(state->current_multicol != NULL))				{					/*					lo_EndMulticolumn(context, state, tag,						state->current_multicol);					*/					lo_process_multicolumn_tag(context, state, tag);				}			}			break;		/* added for stylesheet support		 *		 * a general container tag.  The default style is		 * inline.  It doesn't do anything without associated		 * stylesheet properties.		 * it's just ignored in normal layout		 */		case P_SPAN:		{#ifdef DOM			lo_process_span_tag(context, state, tag);#endif			break;		}		/*		 * Just move the left and right margins in for this paragraph		 * of text.		 */		case P_BLOCKQUOTE:		  {			int8 quote_type = QUOTE_NONE;			PA_Block buff;			/* 			 * Get the param to see if this is a mailing quote. <BLOCKQUOTE TYPE=CITE>			 */			buff = lo_FetchParamValue(context, tag, PARAM_TYPE);			if (buff != NULL) {			  char *str;			  PA_LOCK(str, char *, buff);			  /*			   * cite used to map to QUOTE_MQUOTE.			   * We now use QUOTE_CITE.			   */			  if (pa_TagEqual("cite",str)) {				quote_type = QUOTE_CITE;     			  }			  else if (pa_TagEqual("jwz",str)) {				quote_type = QUOTE_JWZ;     			  }			  PA_UNLOCK(buff);			  PA_FREE(buff);			}						/*			 * The start of a blockquote infers the end of			 * the HEAD section of the HTML and starts the BODY			 */			state->top_state->in_head = FALSE;			state->top_state->in_body = TRUE;						if (state->in_paragraph != FALSE)			  {				lo_CloseParagraph(context, &state, tag, 2);			  }			{			  LO_BlockQuoteStruct *quote = (LO_BlockQuoteStruct*)lo_NewElement(context, state, LO_BLOCKQUOTE, NULL, 0);			  			  XP_ASSERT(quote);			  if (!quote) 			  {				LO_UnlockLayout();				return;			  }			  			  quote->lo_any.type = LO_BLOCKQUOTE;			  quote->lo_any.ele_id = NEXT_ELEMENT;			  quote->lo_any.x = state->x;			  quote->lo_any.y = state->y;			  quote->lo_any.x_offset = 0;			  quote->lo_any.y_offset = 0;			  quote->lo_any.width = 0;			  quote->lo_any.height = 0;			  quote->lo_any.line_height = 0;			  			  quote->is_end = tag->is_end;			  quote->quote_type = quote_type;			  quote->tag = PA_CloneMDLTag(tag);			  lo_AppendToLineList(context, state, (LO_Element*)quote, 0);			  			  lo_ProcessBlockQuoteElement(context, state, quote, FALSE);			}		  }			break;		/*		 * An internal tag to allow libmocha/lm_doc.c's		 * doc_open_stream to get the new document's top		 * state struct early.		 */		case P_NSCP_OPEN:			break;		/*		 * An internal tag to allow us to merge two		 * possibly incomplete HTML docs as neatly		 * as possible.		 */		case P_NSCP_CLOSE:			if (tag->is_end == FALSE)			{				LO_CloseAllTags(context);				/* the previous function call				 * closes tags and free's the top				 * style struct				 */				style_struct = NULL;			}			break;		/*		 * Normally unknown tags are just ignored.		 * But if the unknown tag is in the head of a document, we		 * assume it is a tag that can contain content, and ignore		 * that content.		 * WARNING:  In special cases with omitted </head> tags,		 * this can result in the loss of body data!		 */		case P_UNKNOWN:			if (state->top_state->in_head != FALSE)			{			    char *tdata;			    char *tptr;			    char tchar;			    PA_LOCK(tdata, char *, tag->data);			    /*			     * Throw out non-tags like <!doctype>			     */			    if ((tag->data_len < 1)||(tdata[0] == '!'))			    {				PA_UNLOCK(tag->data);				break;			    }			    /*			     * Remove the unknown tag name from any attributes			     * it might have.			     */			    tptr = tdata;			    while ((!XP_IS_SPACE(*tptr))&&(*tptr != '>'))			    {				tptr++;			    }			    tchar = *tptr;			    *tptr = '\0';			    /*			     * Save the unknown tag name to match to its			     * end tag.			     */			    if (tag->is_end == FALSE)			    {				if (state->top_state->unknown_head_tag == NULL)				{				    state->top_state->unknown_head_tag =					XP_STRDUP(tdata);				}			    }			    /*			     * Else if we already have a saved start and this			     * is the matching end.  Clear the knowledge			     * that we are in an unknown head tag.			     */			    else			    {				if ((state->top_state->unknown_head_tag != NULL)				    &&(XP_STRCASECMP(state->top_state->unknown_head_tag, tdata) == 0))				{				    XP_FREE(state->top_state->unknown_head_tag);				    state->top_state->unknown_head_tag = NULL;				}			    }			    *tptr = tchar;			    PA_UNLOCK(tag->data);			}			break;		default:			break;	  }	if(!tag->is_end)	{		if(!lo_IsEmptyTag(tag->type))		{#ifdef DOM          lo_SetStyleSheetProperties(context, state, tag);#else			lo_SetStyleSheetProperties(context, style_struct, tag);#endif		}		else		{			/* get the new current state */			int32 doc_id = XP_DOCID(context);			lo_TopState *top_state = lo_FetchTopState(doc_id);			state = lo_TopSubState(top_state);							/* the tag is not a container so pop it off of		 	 * the style stack		 	 */			LO_PopStyleTag(context, &state, tag);			style_struct = NULL;		}	}    /* the last argument is TRUE if we started in the head      */	lo_PostLayoutTag( context, state, tag, started_in_head);#ifdef DOM    /*     * Ending the processing of a tag.     * Here we pop all the style state we need to, and wire up the     * Node->LO_Element end-element links.     */    if (tag->is_end) {        LO_Element *eptr;        DOM_Node *node;        /* find the last element on the line list and its node */#define FIND_LAST_ELEMENT(eptr)                                               \        eptr = state->line_list;                                              \        if (!eptr)                                                            \            eptr = state->end_last_line;                                      \        /* if there are no elements in state, try the currently active one */ \        if (!eptr)                                                            \            eptr = state->top_state->doc_state->line_list;                    \        if (!eptr)                                                            \            eptr = state->top_state->doc_state->end_last_line;                \        if (eptr) {                                                           \            while (eptr->lo_any.next != NULL) {                               \                eptr = eptr->lo_any.next;                                     \            }                                                                 \        }                FIND_LAST_ELEMENT(eptr);        if (!eptr)          return;        node = eptr->lo_any.node;        if (!node)          return;        if (node->type == NODE_TYPE_ELEMENT ||            node->type == NODE_TYPE_TEXT) {            PRBool resyncElements = PR_FALSE;            DOM_HTMLElementPrivate *priv = ELEMENT_PRIV(node);            XP_ASSERT(priv);                        if (priv->flags & STYLE_NODE_NEED_TO_POP_LAYER) {                resyncElements = PR_TRUE;                lo_EndLayer(context, state, PR_TRUE);                LM_ClearNodeFlags(node, STYLE_NODE_NEED_TO_POP_LAYER);            }            /* if we popped stuff, resync the end pointer */            if (resyncElements) {                FIND_LAST_ELEMENT(eptr);                if (!eptr) {#ifdef DEBUG_shaver                    fprintf(stderr, "can't find new eptr for resync!\n");#endif                    return;                }                XP_ASSERT(eptr->lo_any.node == node);            }            priv->ele_end = eptr;        } else {#ifdef DEBUG_shaver            fprintf(stderr, "node on LO_Element %d is type %d\n",                    eptr->lo_any.type, node->type);#endif        }#ifdef DEBUG_shaver_old            DumpNodeElements(last_node);#endif    }#endif /* DOM */	LO_UnlockLayout();}