are the same.
*/
case P_STRIKEOUT:
case P_STRIKE:
lo_ProcessFontTag( state, tag, 0, LO_ATTR_STRIKEOUT);
break;
case P_SPELL:
lo_ProcessFontTag( state, tag, 0, LO_ATTR_SPELL);
break;
case P_INLINEINPUT:
lo_ProcessFontTag( state, tag, 0, LO_ATTR_INLINEINPUT);
break;
case P_INLINEINPUTTHICK:
lo_ProcessFontTag( state, tag, 0, LO_ATTR_INLINEINPUTTHICK);
break;
case P_INLINEINPUTDOTTED:
lo_ProcessFontTag( state, tag, 0, LO_ATTR_INLINEINPUTDOTTED);
break;
/*
* Another font attribute, another font on the font stack
*/
case P_UNDERLINE:
lo_ProcessFontTag( state, 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);
}
}
old_attr = state->font_stack->text_attr;
lo_CopyTextAttr(old_attr, &tmp_attr);
/*
* Allow 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);
old_attr = state->font_stack->text_attr;
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);
old_attr = state->font_stack->text_attr;
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;
old_attr = state->font_stack->text_attr;
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 =
state->font_stack->text_attr;
FE_GetTextInfo(context, &tmp_text, &text_info);
PA_FREE(buff);
if (tag->is_end == FALSE)
{
state->baseline +=
(text_info.ascent / 2);
}
else
{
LO_TextAttr *attr;
state->baseline -=
(text_info.ascent / 2);
attr = 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;
old_attr = state->font_stack->text_attr;
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 =
state->font_stack->text_attr;
FE_GetTextInfo(context, &tmp_text, &text_info);
PA_FREE(buff);
if (tag->is_end == FALSE)
{
state->baseline -=
(text_info.ascent / 2);
}
else
{
LO_TextAttr *attr;
state->baseline +=
(text_info.ascent / 2);
attr = 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;
uint16 new_font_weight;
char *size_str;
char *str;
char *new_face;
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;
}
}
old_attr = state->font_stack->text_attr;
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;
old_attr = state->font_stack->text_attr;
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;
old_attr = state->font_stack->text_attr;
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
* docuemtn 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 furthur 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;
}
}
/*
*
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);
}
}
}
break;
/*
* The hype tag is just for fun.
* It only effects the UNIX version
* which can affor 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:
*
* 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 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 .
*/
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)
{
/*
* 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;
lo_FormatEmbed(context, state, tag);
}
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 container. Drop all unknown language SCRIPT
* contents on the floor. Process SRC= 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;
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;
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