diff --git a/lib/layout/Makefile b/lib/layout/Makefile index 55e39cf65fd..9f23bf24e7d 100644 --- a/lib/layout/Makefile +++ b/lib/layout/Makefile @@ -40,6 +40,7 @@ CSRCS = bullet.c \ layobj.c \ layscrip.c \ layspace.c \ + layspan.c \ laystyle.c \ laysub.c \ ptinpoly.c \ diff --git a/lib/layout/laymocha.c b/lib/layout/laymocha.c index 80e20017a69..cddd10a0a39 100644 --- a/lib/layout/laymocha.c +++ b/lib/layout/laymocha.c @@ -415,6 +415,83 @@ LO_EnumerateNamedAnchors(MWContext *context, int32 layer_id) return count; } +#ifdef DOM +void +lo_ReflectSpan(MWContext *context, lo_DocState *doc_state, PA_Tag *tag, + lo_NameList *name_rec, int32 layer_id) +{ + lo_DocLists *doc_lists; + + if (!doc_state->in_relayout) { + doc_lists = lo_GetDocListsById(doc_state, layer_id); + if (!doc_lists) + return; + name_rec->index = doc_lists->span_count++; + + if(!PA_HasMocha(tag)) + return; + + ET_ReflectObject(context, (void *) name_rec, tag, + layer_id, name_rec->index, LM_SPANS); + + } +} + +lo_NameList * +LO_GetSpanByIndex(MWContext *context, int32 layer_id, uint index) +{ + lo_TopState *top_state; + lo_NameList *name_rec, *nptr; + lo_DocLists *doc_lists; + + top_state = lo_GetTopState(context); + if (top_state == NULL) + return NULL; + + doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id); + if (!doc_lists) + return NULL; + + /* The list is not guaranteed to be in reverse-source order when nested + tables are involved, so search for matching index instead. */ + name_rec = NULL; + for (nptr = doc_lists->span_list; nptr != NULL; nptr = nptr->next) { + if (nptr->index == index) { + name_rec = nptr; + break; + } + } + return name_rec; +} + +uint +LO_EnumerateSpans(MWContext *context, int32 layer_id) +{ + lo_TopState *top_state; + lo_NameList *name_rec; + uint count; + lo_DocLists *doc_lists; + + top_state = lo_GetTopState(context); + if (top_state == NULL) + return 0; + + doc_lists = lo_GetDocListsById(top_state->doc_state, layer_id); + if (!doc_lists) + return 0; + + count = 0; + for (name_rec = doc_lists->span_list; name_rec != NULL; + name_rec = name_rec->next) { + if (name_rec->mocha_object == NULL) + LM_ReflectSpan(context, (void *) name_rec, NULL, + layer_id, name_rec->index); + count++; + } + return count; +} +#endif + void lo_ReflectLink(MWContext *context, lo_DocState *doc_state, PA_Tag *tag, LO_AnchorData *anchor_data, int32 layer_id, uint index) diff --git a/lib/layout/layout.c b/lib/layout/layout.c index 39476689aa6..644fe9d8f8b 100644 --- a/lib/layout/layout.c +++ b/lib/layout/layout.c @@ -537,7 +537,7 @@ lo_NewLayout(MWContext *context, int32 width, int32 height, return(NULL); } - state = XP_NEW(lo_DocState); + state = XP_NEW_ZAP(lo_DocState); if (state == NULL) { top_state->out_of_memory = TRUE; @@ -794,6 +794,11 @@ lo_InitDocState(lo_DocState *state, MWContext *context, state->old_break_pos = -1; state->old_break_width = 0; +#ifdef DOM + state->current_span = NULL; + state->in_span = FALSE; +#endif + state->current_named_anchor = NULL; state->current_anchor = NULL; @@ -3710,8 +3715,10 @@ lo_FinishLayout(MWContext *context, lo_DocState *state, int32 mocha_event) #endif /* OLD_MSGS */ /* Flush out layer callbacks so that document dimensions are correct. */ + /* if (context->compositor) CL_CompositeNow(context->compositor); + */ FE_FinishedLayout(context); return; @@ -3752,9 +3759,10 @@ lo_FinishLayout(MWContext *context, lo_DocState *state, int32 mocha_event) #endif /* OLD_MSGS */ /* Flush out layer callbacks so that document dimensions are correct. */ + /* if (context->compositor) CL_CompositeNow(context->compositor); - + */ FE_FinishedLayout(context); return; } @@ -3824,8 +3832,10 @@ lo_FinishLayout(MWContext *context, lo_DocState *state, int32 mocha_event) #endif /* OLD_MSGS */ /* Flush out layer callbacks so that document dimensions are correct. */ + /* if (context->compositor) CL_CompositeNow(context->compositor); + */ if (state->is_a_subdoc == SUBDOC_NOT && state->top_state && !state->top_state->have_title) { diff --git a/lib/layout/layout.h b/lib/layout/layout.h index 9c063111bb7..2e5ffc9656e 100644 --- a/lib/layout/layout.h +++ b/lib/layout/layout.h @@ -354,6 +354,11 @@ typedef struct lo_DocLists_struct { lo_NameList *name_list; /* list of positions of named anchors */ uint32 anchor_count; /* Count of named anchors in this document */ +#ifdef DOM + lo_NameList *span_list; /* list of positions of named spans*/ + uint32 span_count; /* Count of named spans in this document */ +#endif + lo_FormData *form_list; /* list of forms in doc */ intn current_form_num; /* The id of the next form to lay out */ @@ -643,6 +648,11 @@ typedef struct lo_DocState_struct { LO_TextBlock * cur_text_block; Bool need_min_width; uint32 src_text_offset; + +#ifdef DOM + Bool in_span; + PA_Block current_span; +#endif } lo_DocState; #ifdef TEST_16BIT @@ -1155,6 +1165,11 @@ extern PA_Block lo_ConvertToFELinebreaks(char *, int32, int32 *); extern PA_Block lo_FEToNetLinebreaks(PA_Block); extern void lo_CleanFormElementData(LO_FormElementData *); extern Bool lo_SetNamedAnchor(lo_DocState *, PA_Block); + +#ifdef DOM +extern Bool lo_SetNamedSpan(lo_DocState *, PA_Block); +#endif + extern void lo_AddNameList(lo_DocState *, lo_DocState *); extern void lo_CheckNameList(MWContext *, lo_DocState *, int32); extern int32 lo_StripTextWhitespace(char *, int32); @@ -1450,6 +1465,10 @@ extern void lo_ReflectNamedAnchor(MWContext *context, lo_DocState *state, PA_Tag *tag, lo_NameList *name_rec, int32 layer_id); +extern void +lo_ReflectSpan(MWContext *context, lo_DocState *doc_state, PA_Tag *tag, + lo_NameList *name_rec, int32 layer_id); + extern void lo_ReflectLink(MWContext *context, lo_DocState *state, PA_Tag *tag, LO_AnchorData *anchor_data, int32 layer_id, uint index); @@ -1561,6 +1580,14 @@ Bool lo_BindNamedAnchorToElement(lo_DocState *state, PA_Block name, LO_Element *element); +#ifdef DOM +Bool +lo_BindNamedSpanToElement(lo_DocState *state, PA_Block name, + LO_Element *element); + +LO_SpanStruct * lo_FindParentSpan( LO_Element *ele ); +#endif + /* Return the table element containing the given element (usually a LO_CELL type) */ LO_TableStruct *lo_GetParentTable(MWContext *pContext, LO_Element *pElement); diff --git a/lib/layout/layrelay.c b/lib/layout/layrelay.c index e079e03df4e..17b178119d2 100644 --- a/lib/layout/layrelay.c +++ b/lib/layout/layrelay.c @@ -555,6 +555,11 @@ lo_rl_InitDocState( MWContext *context, lo_DocState *state, int32 width, int32 h state->old_break_pos = -1; state->old_break_width = 0; +#ifdef DOM + state->current_span = NULL; + state->in_span = FALSE; +#endif + state->current_named_anchor = NULL; state->current_anchor = NULL; @@ -1519,9 +1524,29 @@ lo_rl_FitSpacer( lo_RelayoutState *relay_state, LO_Element *lo_ele ) } static LO_Element * lo_rl_FitSpan( lo_RelayoutState *relay_state, LO_Element *lo_ele ) -{ +{ +#ifndef DOM XP_ASSERT(0); return lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE); +#else + MWContext *context = relay_state->context; + lo_DocState *state = relay_state->doc_state; + LO_Element *next = lo_tv_GetNextLayoutElement( relay_state->doc_state, lo_ele, TRUE); + + /* Skip the SPAN element */ + if (lo_ele->lo_span.is_end == FALSE) + { + lo_AppendToLineList(context, state, lo_ele, 0); + state->in_span = TRUE; + } + else + { + state->in_span = FALSE; + lo_AppendToLineList(context, state, lo_ele, 0); + } + + return next; +#endif } static LO_Element * lo_rl_FitDiv( lo_RelayoutState *relay_state, LO_Element *lo_ele ) diff --git a/lib/layout/layspan.c b/lib/layout/layspan.c new file mode 100644 index 00000000000..80dd62016c7 --- /dev/null +++ b/lib/layout/layspan.c @@ -0,0 +1,413 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#ifdef DOM + +#include "xp.h" +#include "pa_parse.h" +#include "layout.h" +#include "laylayer.h" +#include "laystyle.h" +#include "libmocha.h" +#include "stystruc.h" +#include "stystack.h" +#include "layers.h" + + +/* Initial attempt at DOM by letting JS set style of SPAN contents */ +static void lo_SetColor( LO_Element *ele, LO_Color *color, Bool background); +static void lo_SetFontFamily( MWContext *context, LO_Element *ele, char *family); +static void lo_SetFontWeight( MWContext *context, LO_Element *ele, char *weight); +static void lo_SetFontSlant( MWContext *context, LO_Element *ele, char *weight); +static void lo_SetFontSize( MWContext *context, LO_Element *ele, int32 size); + +/* Public functions */ +JSObject * +LO_GetMochaObjectOfParentSpan( LO_Element *ele) +{ + LO_SpanStruct *span; + lo_NameList *name_rec; + JSObject *obj = NULL; + + if (LO_IsWithinSpan( ele )) + { + /* Go back in the layout element list until we find a SPAN element */ + span = lo_FindParentSpan(ele); + if ( span != NULL ) + { + name_rec = (lo_NameList *) span->name_rec; + if (name_rec != NULL) + obj = name_rec->mocha_object; + } + } + + return obj; +} + +/* Set the color of all layout elements contained within the span */ +void LO_SetSpanColor(MWContext* context, void *span, LO_Color *color) +{ + lo_NameList *name_rec = (lo_NameList *)span; + LO_SpanStruct *parent_span = lo_FindParentSpan(name_rec->element); + LO_Element *ele; + + ele = parent_span->lo_any.next; + while (ele != NULL && ele->lo_any.type != LO_SPAN) + { + lo_SetColor(ele, color, FALSE); + ele = ele->lo_any.next; + } +} + +/* Set the background color of all layout elements contained within the span */ +void LO_SetSpanBackground(MWContext* context, void *span, LO_Color *color) +{ + lo_NameList *name_rec = (lo_NameList *)span; + LO_SpanStruct *parent_span = lo_FindParentSpan(name_rec->element); + LO_Element *ele; + + ele = parent_span->lo_any.next; + while (ele != NULL && ele->lo_any.type != LO_SPAN) + { + lo_SetColor(ele, color, TRUE); + ele = ele->lo_any.next; + } +} + +/* Set the font family (Arial, Helvetica, Times) of all the layout + elements contained within the span */ +void +LO_SetSpanFontFamily(MWContext* context, void *span, char *family) +{ + lo_NameList *name_rec = (lo_NameList *)span; + LO_SpanStruct *parent_span = lo_FindParentSpan(name_rec->element); + LO_Element *ele; + + ele = parent_span->lo_any.next; + while (ele != NULL && ele->lo_any.type != LO_SPAN) + { + lo_SetFontFamily(context, ele, family); + ele = ele->lo_any.next; + } +} + +/* Set the font weight (medium, bold, heavy, etc.) of all the layout + elements contained within the span */ +void +LO_SetSpanFontWeight(MWContext* context, void *span, char *weight) +{ + lo_NameList *name_rec = (lo_NameList *)span; + LO_SpanStruct *parent_span = lo_FindParentSpan(name_rec->element); + LO_Element *ele; + + ele = parent_span->lo_any.next; + while (ele != NULL && ele->lo_any.type != LO_SPAN) + { + lo_SetFontWeight(context, ele, weight); + ele = ele->lo_any.next; + } +} + +/* Set the font size (in points) of all the layout elements contained + within the span */ +void +LO_SetSpanFontSize(MWContext* context, void *span, int32 size) +{ + lo_NameList *name_rec = (lo_NameList *)span; + LO_SpanStruct *parent_span = lo_FindParentSpan(name_rec->element); + LO_Element *ele; + + ele = parent_span->lo_any.next; + while (ele != NULL && ele->lo_any.type != LO_SPAN) + { + lo_SetFontSize(context, ele, size); + ele = ele->lo_any.next; + } +} + +/* Set the font slant (in points) of all the layout elements contained + within the span */ +void +LO_SetSpanFontSlant(MWContext* context, void *span, char *slant) +{ + lo_NameList *name_rec = (lo_NameList *)span; + LO_SpanStruct *parent_span = lo_FindParentSpan(name_rec->element); + LO_Element *ele; + + ele = parent_span->lo_any.next; + while (ele != NULL && ele->lo_any.type != LO_SPAN) + { + lo_SetFontSlant(context, ele, slant); + ele = ele->lo_any.next; + } +} + +/* Functions internal to layout */ +LO_SpanStruct * +lo_FindParentSpan( LO_Element *ele ) +{ + while (ele != NULL && ele->lo_any.type != LO_SPAN) + ele = ele->lo_any.prev; + + return (LO_SpanStruct *) ele; +} + +/* Functions internal to this file */ +static void lo_SetColor( LO_Element *ele, LO_Color *color, Bool background) +{ + switch (ele->lo_any.type) + { + case LO_TEXTBLOCK: + if (background) + { + ele->lo_textBlock.text_attr->bg = *color; + ele->lo_textBlock.text_attr->no_background = FALSE; + } + else + { + ele->lo_textBlock.text_attr->fg = *color; + } + break; + case LO_TEXT: + if (background) + { + ele->lo_text.text_attr->bg = *color; + ele->lo_text.text_attr->no_background = FALSE; + } + else + { + ele->lo_text.text_attr->fg = *color; + } + break; + case LO_BULLET: + if (background) + { + ele->lo_bullet.text_attr->bg = *color; + ele->lo_bullet.text_attr->no_background = FALSE; + } + else + { + ele->lo_bullet.text_attr->fg = *color; + } + break; + default: + break; + } +} + +static void +lo_SetFontFamily( MWContext *context, + LO_Element *ele, + char *new_face) +{ + LO_TextAttr *text_attr; + LO_TextInfo text_info; + + /* if the point size is different, tell the FE to release it's data, + set the point_size to the new value, and then have the FE + recompute it's information. */ + switch (ele->lo_any.type) + { + case LO_TEXTBLOCK: + text_attr = ele->lo_textBlock.text_attr; + break; + case LO_TEXT: + text_attr = ele->lo_text.text_attr; + break; + case LO_BULLET: + text_attr = ele->lo_bullet.text_attr; + break; + default: + /* we don't mess with any other type of element */ + return; + } + + if (ele->lo_any.type == LO_TEXT) + { + LO_TextInfo text_info; + LO_TextStruct tmp_text; + memset (&tmp_text, 0, sizeof (tmp_text)); + + FE_ReleaseTextAttrFeData(context, text_attr); + + /* XP_FREE(text_attr->font_face); */ + text_attr->font_face = strdup(new_face); + + tmp_text = ele->lo_text; + + FE_GetTextInfo(context, &tmp_text, &text_info); + } + else if (ele->lo_any.type == LO_TEXTBLOCK) + { + /* XP_FREE(text_attr->font_face); */ + text_attr->font_face = strdup(new_face); + } +} + +static void +lo_SetFontWeight( MWContext *context, + LO_Element *ele, + char *weight) +{ + LO_TextAttr *text_attr; + LO_TextInfo text_info; + int new_weight = atoi(weight); + + /* if the point size is different, tell the FE to release it's data, + set the point_size to the new value, and then have the FE + recompute it's information. */ + switch (ele->lo_any.type) + { + case LO_TEXTBLOCK: + text_attr = ele->lo_textBlock.text_attr; + break; + case LO_TEXT: + text_attr = ele->lo_text.text_attr; + break; + case LO_BULLET: + text_attr = ele->lo_bullet.text_attr; + break; + default: + /* we don't mess with any other type of element */ + return; + } + + if (ele->lo_any.type == LO_TEXT) + { + LO_TextInfo text_info; + LO_TextStruct tmp_text; + memset (&tmp_text, 0, sizeof (tmp_text)); + + FE_ReleaseTextAttrFeData(context, text_attr); + + text_attr->font_weight = new_weight; + if(text_attr->font_weight > 900) + text_attr->font_weight = 900; + + tmp_text = ele->lo_text; + + FE_GetTextInfo(context, &tmp_text, &text_info); + } + else if (ele->lo_any.type == LO_TEXTBLOCK) + { + text_attr->font_weight = new_weight; + if (text_attr->font_weight > 900) + text_attr->font_weight = 900; + } + +} + +static void +lo_SetFontSlant( MWContext *context, + LO_Element *ele, + char *slant) +{ + LO_TextAttr *text_attr; + LO_TextInfo text_info; + int flag; + + /* if the point size is different, tell the FE to release it's data, + set the point_size to the new value, and then have the FE + recompute it's information. */ + switch (ele->lo_any.type) + { + case LO_TEXTBLOCK: + text_attr = ele->lo_textBlock.text_attr; + break; + case LO_TEXT: + text_attr = ele->lo_text.text_attr; + break; + case LO_BULLET: + text_attr = ele->lo_bullet.text_attr; + break; + default: + /* we don't mess with any other type of element */ + return; + } + + if (!strcmp(slant, "italic")) + flag = LO_FONT_ITALIC; + else if (!strcmp(slant, "fixed")) + flag = LO_FONT_FIXED; + + if (ele->lo_any.type == LO_TEXTBLOCK + && !text_attr->fontmask & flag) + { + LO_TextInfo text_info; + LO_TextStruct tmp_text; + memset (&tmp_text, 0, sizeof (tmp_text)); + + FE_ReleaseTextAttrFeData(context, text_attr); + + text_attr->fontmask |= flag; + + tmp_text = ele->lo_text; + + FE_GetTextInfo(context, &tmp_text, &text_info); + } +} + +static void +lo_SetFontSize( MWContext *context, + LO_Element *ele, + int32 new_size) +{ + LO_TextAttr *text_attr; + LO_TextInfo text_info; + + /* if the point size is different, tell the FE to release it's data, + set the point_size to the new value, and then have the FE + recompute it's information. */ + switch (ele->lo_any.type) + { + case LO_TEXTBLOCK: + text_attr = ele->lo_textBlock.text_attr; + break; + case LO_TEXT: + text_attr = ele->lo_text.text_attr; + break; + case LO_BULLET: + text_attr = ele->lo_bullet.text_attr; + break; + default: + /* we don't mess with any other type of element */ + return; + } + + if (ele->lo_any.type == LO_TEXT) + { + LO_TextInfo text_info; + LO_TextStruct tmp_text; + memset (&tmp_text, 0, sizeof (tmp_text)); + + FE_ReleaseTextAttrFeData(context, text_attr); + + text_attr->point_size = new_size; + + tmp_text = ele->lo_text; + + FE_GetTextInfo(context, &tmp_text, &text_info); + } + else if (ele->lo_any.type == LO_TEXTBLOCK) + { + text_attr->point_size = new_size; + } + +} + +#endif diff --git a/lib/layout/laytable.c b/lib/layout/laytable.c index f6db7a53300..98b06060964 100644 --- a/lib/layout/laytable.c +++ b/lib/layout/laytable.c @@ -716,6 +716,11 @@ lo_reuse_current_state(MWContext *context, lo_DocState *state, state->old_break_pos = -1; state->old_break_width = 0; +#ifdef DOM + state->current_span = NULL; + state->in_span = FALSE; +#endif + state->current_named_anchor = NULL; state->current_anchor = NULL; @@ -2266,8 +2271,8 @@ lo_EndCellSubDoc(MWContext *context, lo_DocState *state, lo_DocState *old_state, * must be relayed out to take care of window * width and height dependencies. */ - /* case LO_HRULE: - */ + + /* case LO_HRULE: */ case LO_SUBDOC: case LO_TABLE: old_state->must_relayout_subdoc = TRUE; @@ -7923,9 +7928,12 @@ fprintf(stderr, "lo_EndTable called\n"); } } */ - + /* Decrement table nesting level (used for passing into lo_CreateCellBackGroundLayer() */ - state->top_state->table_nesting_level--; + if (!relayout) + { + state->top_state->table_nesting_level--; + } #ifdef XP_WIN16 _hfree(cell_array); diff --git a/lib/layout/laytags.c b/lib/layout/laytags.c index c6d42301187..4c39620c03a 100644 --- a/lib/layout/laytags.c +++ b/lib/layout/laytags.c @@ -1253,6 +1253,87 @@ lo_process_header_tag(MWContext *context, lo_DocState *state, PA_Tag *tag, int t } } +static void +lo_process_span_tag(MWContext *context, lo_DocState *state, PA_Tag *tag) +{ + LO_SpanStruct *span; + PA_Block buff; + lo_DocLists *doc_lists; + + doc_lists = lo_GetCurrentDocLists(state); + + span = (LO_SpanStruct*)lo_NewElement(context, state, LO_SPAN, NULL, 0); + XP_ASSERT(span); + if (!span) return; + + span->lo_any.type = LO_SPAN; + span->lo_any.ele_id = NEXT_ELEMENT; + span->is_end = tag->is_end; + + span->lo_any.x = state->x; + span->lo_any.y = state->y; + span->lo_any.x_offset = 0; + span->lo_any.y_offset = 0; + span->lo_any.width = 0; + span->lo_any.height = 0; + span->lo_any.line_height = 0; + +#ifdef DOM + span->name_rec = NULL; + if (tag->is_end == FALSE) + { + /* get the span's ID. */ + buff = lo_FetchParamValue(context, tag, PARAM_ID); + if (buff != NULL) + { + state->in_span = TRUE; + state->current_span = buff; + if (lo_SetNamedSpan(state, buff)) + { + lo_BindNamedSpanToElement(state, buff, NULL); + lo_ReflectSpan(context, state, tag, + doc_lists->span_list, + lo_CurrentLayerId(state)); + span->name_rec = doc_lists->span_list; + } + + PA_UNLOCK(buff); + } + lo_AppendToLineList(context, state, (LO_Element*)span, 0); + state->in_span = TRUE; + } + else + { + state->in_span = FALSE; + lo_AppendToLineList(context, state, (LO_Element*)span, 0); + } +#endif +} + +static void +lo_process_div_tag(MWContext *context, lo_DocState *state, PA_Tag *tag) +{ + LO_DivStruct *div; + + div = (LO_DivStruct*)lo_NewElement(context, state, LO_DIV, NULL, 0); + XP_ASSERT(div); + if (!div) return; + + div->lo_any.type = LO_DIV; + div->lo_any.ele_id = NEXT_ELEMENT; + div->is_end = tag->is_end; + + div->lo_any.x = state->x; + div->lo_any.y = state->y; + div->lo_any.x_offset = 0; + div->lo_any.y_offset = 0; + div->lo_any.width = 0; + div->lo_any.height = 0; + div->lo_any.line_height = 0; + + lo_AppendToLineList(context, state, (LO_Element*)div, 0); +} + PRIVATE Bool lo_do_underline = TRUE; #ifdef XP_MAC @@ -6823,7 +6904,12 @@ XP_TRACE(("lo_LayoutTag(%d)\n", tag->type)); * 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 diff --git a/lib/layout/layutil.c b/lib/layout/layutil.c index be5a19821a1..18e30af389a 100644 --- a/lib/layout/layutil.c +++ b/lib/layout/layutil.c @@ -50,6 +50,10 @@ #define FONT_FACE_INC 10 #define FONT_FACE_MAX 1000 +#ifdef DOM +static void lo_SetInSpanAttribute( LO_Element *ele ); +#endif + void lo_GetElementBbox(LO_Element *element, XP_Rect *rect) { @@ -1270,7 +1274,11 @@ lo_FetchTextAttr(lo_DocState *state, LO_TextAttr *old_attr) (attr_ptr->font_face == old_attr->font_face)&& (attr_ptr->charset == old_attr->charset)&& (attr_ptr->point_size == old_attr->point_size)&& - (attr_ptr->font_weight == old_attr->font_weight)) + (attr_ptr->font_weight == old_attr->font_weight) +#ifdef DOM + && (state->in_span == FALSE) /* Never reuse text attrs in SPANS */ +#endif + ) { break; } @@ -1280,7 +1288,7 @@ lo_FetchTextAttr(lo_DocState *state, LO_TextAttr *old_attr) { LO_TextAttr *new_attr; - new_attr = XP_NEW(LO_TextAttr); + new_attr = XP_NEW_ZAP(LO_TextAttr); if (new_attr != NULL) { lo_CopyTextAttr(old_attr, new_attr); @@ -2018,6 +2026,15 @@ lo_NewElement(MWContext *context, lo_DocState *state, intn type, case LO_LAYER: size = sizeof(LO_LayerStruct); break; + case LO_HEADING: + size = sizeof(LO_HeadingStruct); + break; + case LO_SPAN: + size = sizeof(LO_SpanStruct); + break; + case LO_DIV: + size = sizeof(LO_DivStruct); + break; case LO_SPACER: size = sizeof(LO_SpacerStruct); break; @@ -2036,7 +2053,7 @@ lo_NewElement(MWContext *context, lo_DocState *state, intn type, } else { - eptr = XP_NEW(LO_Element); + eptr = XP_NEW_ZAP(LO_Element); } } #else @@ -2247,6 +2264,151 @@ lo_BindNamedAnchorToElement(lo_DocState *state, PA_Block name, } +#ifdef DOM +/* Add a named span to the global list of named spans. This does not + associate the span with a layout element. lo_SetNamedSpan should be + followed by a call to lo_BindNamedSpanToElement in order to associate + the named span with a layout element. */ +Bool +lo_SetNamedSpan(lo_DocState *state, PA_Block id) +{ + lo_NameList *name_rec = NULL; + lo_DocLists *doc_lists; + + /* + * No named spans are allowed within a + * hacked scrolling content layout document. + */ + if (state->top_state->scrolling_doc != FALSE) + { + if (id != NULL) + { + PA_FREE(id); + } + return FALSE; + } + + doc_lists = lo_GetCurrentDocLists(state); + +#ifdef MOCHA + if (state->in_relayout) { + /* Look for the old lo_NameList. Its mocha_object is still valid. */ + lo_NameList *span_list = doc_lists->span_list; + lo_NameList *prev; + Bool no_match; + char *s1, *s2; + + XP_ASSERT(span_list); /* If in relayout, this cannot be empty. */ + + prev = span_list; + name_rec = span_list; + while (name_rec != NULL) { + PA_LOCK(s1, char*, id); + PA_LOCK(s2, char*, name_rec->name); + no_match = XP_STRCMP(s1, s2); + PA_UNLOCK(name_rec->name); + PA_UNLOCK(id); + if (!no_match) { + if (name_rec == span_list) + doc_lists->span_list = span_list->next; + else + prev->next = name_rec->next; + PA_FREE(name_rec->name); /* No need for this, use new one. */ + break; + } + prev = name_rec; + name_rec = name_rec->next; + } + } + if (!name_rec || !state->in_relayout) { +#endif /* MOCHA */ + name_rec = XP_NEW(lo_NameList); + if (name_rec == NULL) + { + state->top_state->out_of_memory = TRUE; + PA_FREE(id); + return FALSE; + } +#ifdef MOCHA + name_rec->mocha_object = NULL; + } +#endif /* MOCHA */ + name_rec->x = 0; + name_rec->y = 0; + name_rec->name = id; + name_rec->element = NULL; /* Set by lo_BindNamedSpanToElement. */ + + name_rec->next = doc_lists->span_list; + doc_lists->span_list = name_rec; + return TRUE; +} + +/* Associate a named span with a layout element. The named span should + be the first one in the list of named spans.*/ +Bool +lo_BindNamedSpanToElement(lo_DocState *state, PA_Block name, + LO_Element *element) +{ + Bool no_match; + LO_Element *eptr; + lo_NameList *name_rec; + char *s1, *s2; + lo_DocLists *doc_lists; + + doc_lists = lo_GetCurrentDocLists(state); + + if (element == NULL) + { + if (state->line_list == NULL) + { + eptr = state->end_last_line; + } + else + { + eptr = state->line_list; + while (eptr->lo_any.next != NULL) + { + eptr = eptr->lo_any.next; + } + } + } + else + { + eptr = element; + } + + /* Find the matching name_rec in the span_list */ + name_rec = doc_lists->span_list; + PA_LOCK(s1, char*, name); + while (name_rec != NULL) + { + PA_LOCK(s2, char*, name_rec->name); + no_match = XP_STRCMP(s1, s2); + PA_UNLOCK(name_rec->name); + if (!no_match) + break; + name_rec = name_rec->next; + } + PA_UNLOCK(name); + if (name_rec == NULL) + return FALSE; + + if (eptr == NULL) + { + name_rec->x = 0; + name_rec->y = 0; + } + else + { + name_rec->x = eptr->lo_any.x; + name_rec->y = eptr->lo_any.y; + } + + name_rec->element = eptr; + return TRUE; +} +#endif /* DOM */ + void lo_AddNameList(lo_DocState *state, lo_DocState *old_state) { @@ -2382,6 +2544,23 @@ lo_AppendToLineList(MWContext *context, lo_DocState *state, { LO_Element *eptr; +#ifdef DOM + if (state->in_span) + { + lo_SetInSpanAttribute( element ); + } + + if (state->current_span != NULL) + { + if (!lo_BindNamedSpanToElement(state, state->current_span, + element)) + { + XP_ASSERT(FALSE); + } + state->current_span = NULL; + } +#endif + if (state->current_named_anchor != NULL) { if (!lo_BindNamedAnchorToElement(state, state->current_named_anchor, element)) { @@ -3556,28 +3735,52 @@ Bool LO_IsWithinSpan( LO_Element *ele ) { Bool isInSpan = FALSE; + if (ele) + { + switch (ele->type) { + + case LO_TEXT: + isInSpan = ele->lo_text.ele_attrmask & LO_ELE_IN_SPAN ? TRUE : FALSE; + break; + case LO_IMAGE: + isInSpan = ele->lo_image.ele_attrmask & LO_ELE_IN_SPAN ? TRUE : FALSE; + break; + case LO_FORM_ELE: + isInSpan = ele->lo_form.ele_attrmask & LO_ELE_IN_SPAN ? TRUE : FALSE; + break; + case LO_EMBED: + isInSpan = ele->lo_embed.ele_attrmask & LO_ELE_IN_SPAN ? TRUE : FALSE; + break; + case LO_JAVA: + isInSpan = ele->lo_java.ele_attrmask & LO_ELE_IN_SPAN ? TRUE : FALSE; + break; + } + } + return isInSpan; +} + +static void lo_SetInSpanAttribute( LO_Element *ele ) +{ switch (ele->type) { case LO_TEXT: - isInSpan = ele->lo_text.ele_attrmask & LO_ELE_IN_SPAN ? TRUE : FALSE; + ele->lo_text.ele_attrmask |= LO_ELE_IN_SPAN; break; case LO_IMAGE: - isInSpan = ele->lo_image.ele_attrmask & LO_ELE_IN_SPAN ? TRUE : FALSE; + ele->lo_image.ele_attrmask |= LO_ELE_IN_SPAN; break; case LO_FORM_ELE: - isInSpan = ele->lo_form.ele_attrmask & LO_ELE_IN_SPAN ? TRUE : FALSE; + ele->lo_form.ele_attrmask |= LO_ELE_IN_SPAN; break; case LO_EMBED: - isInSpan = ele->lo_embed.ele_attrmask & LO_ELE_IN_SPAN ? TRUE : FALSE; + ele->lo_embed.ele_attrmask |= LO_ELE_IN_SPAN; break; #ifdef JAVA case LO_JAVA: - isInSpan = ele->lo_java.ele_attrmask & LO_ELE_IN_SPAN ? TRUE : FALSE; + ele->lo_java.ele_attrmask |= LO_ELE_IN_SPAN; break; #endif } - - return isInSpan; } #endif diff --git a/lib/libmocha/Makefile b/lib/libmocha/Makefile index eb0d0350149..15add99105a 100644 --- a/lib/libmocha/Makefile +++ b/lib/libmocha/Makefile @@ -47,6 +47,7 @@ CSRCS = et_mocha.c \ lm_nav.c \ lm_plgin.c \ lm_screen.c \ + lm_span.c \ lm_supdt.c \ lm_taint.c \ lm_trggr.c \ diff --git a/lib/libmocha/et_mocha.c b/lib/libmocha/et_mocha.c index ec794a8ac12..30cb879c7c1 100644 --- a/lib/libmocha/et_mocha.c +++ b/lib/libmocha/et_mocha.c @@ -781,6 +781,15 @@ et_reflect_handler(Reflect_Event * e) case LM_LAYERS: LM_ReflectLayer(e->ce.context, e->index, e->layer_id, e->pa_tag); break; +#ifdef DOM + case LM_SPANS: + LM_ReflectSpan(e->ce.context, e->lo_ele, e->pa_tag, + e->layer_id, e->index); + break; + case LM_TRANSCLUSIONS: + LM_ReflectTransclusion(e->ce.context, e->lo_ele, e->layer_id, e->index); + break; +#endif default: XP_ASSERT(0); break; diff --git a/lib/libmocha/et_moz.c b/lib/libmocha/et_moz.c index 82d9c7ec197..607d1df52f9 100644 --- a/lib/libmocha/et_moz.c +++ b/lib/libmocha/et_moz.c @@ -2873,3 +2873,156 @@ ET_moz_CompMethodFunction(ETCompMethodFunc fn, int32 argc, JSCompArg *argv) return (void *)et_PostEvent(&event->ce, TRUE); } + +#ifdef DOM + +/****************************************************************************/ + +typedef struct { + ETEvent ce; + lo_NameList *name_rec; + ETSpanOp op; + void *param_ptr; + int32 param_val; +} MozillaEvent_TweakSpan; + +PR_STATIC_CALLBACK(int) +et_HandleEvent_TweakSpan(MozillaEvent_TweakSpan* e) +{ + Bool ret = TRUE; + + /* check that the doc_id is valid */ + if(XP_DOCID(e->ce.context) != e->ce.doc_id) + return FALSE; + + switch(e->op) { + case SP_SetColor: + LO_SetSpanColor(e->ce.context, e->name_rec, (LO_Color*)e->param_ptr); + /* This call to reflow is just a temp hack */ + LO_RelayoutFromElement(e->ce.context, e->name_rec->element); + if (e->param_ptr) + XP_FREE((void*)e->param_ptr); + break; + case SP_SetBackground: + LO_SetSpanBackground(e->ce.context, e->name_rec, (LO_Color*)e->param_ptr); + /* This call to reflow is just a temp hack */ + LO_RelayoutFromElement(e->ce.context, e->name_rec->element); + if (e->param_ptr) + XP_FREE((void*)e->param_ptr); + break; + case SP_SetFontFamily: + LO_SetSpanFontFamily(e->ce.context, e->name_rec, (char*)e->param_ptr); + LO_RelayoutFromElement(e->ce.context, e->name_rec->element); + break; + case SP_SetFontWeight: + LO_SetSpanFontWeight(e->ce.context, e->name_rec, (char*)e->param_ptr); + LO_RelayoutFromElement(e->ce.context, e->name_rec->element); + break; + case SP_SetFontSize: + LO_SetSpanFontSize(e->ce.context, e->name_rec, e->param_val); + LO_RelayoutFromElement(e->ce.context, e->name_rec->element); + break; + case SP_SetFontSlant: + LO_SetSpanFontSlant(e->ce.context, e->name_rec, (char*)e->param_ptr); + LO_RelayoutFromElement(e->ce.context, e->name_rec->element); + break; + default: + XP_ASSERT(0); + } + + return (int)ret; +} + +PR_STATIC_CALLBACK(void) +et_DestroyEvent_TweakSpan(MozillaEvent_TweakSpan * event) +{ + XP_FREE(event); +} + +/* + * These need to be synchronous so that if we set this and then + * immediately look at it we get the correct (new) value + */ +int +ET_TweakSpan(MWContext * context, void *name_rec, void *param_ptr, + int32 param_val, ETSpanOp op, int32 doc_id) +{ + MozillaEvent_TweakSpan * event; + event = PR_NEW(MozillaEvent_TweakSpan); + if (event == NULL) + return NULL; + + PR_InitEvent(&event->ce.event, context, + (PRHandleEventProc)et_HandleEvent_TweakSpan, + (PRDestroyEventProc)et_DestroyEvent_TweakSpan); + event->ce.context = context; + event->ce.doc_id = doc_id; + event->op = op; + event->name_rec = name_rec; + event->param_ptr = param_ptr; + event->param_val = param_val; + + return (int)et_PostEvent(&event->ce, TRUE); +} + +/* Tweak XML Transclusion stuff starts here */ +typedef struct { + ETEvent ce; + ETTransclusionOp op; + void *param_ptr; + int32 param_val; + void *xmlFile; +} MozillaEvent_TweakTransclusion; + +PR_STATIC_CALLBACK(int) +et_HandleEvent_TweakTransclusion(MozillaEvent_TweakTransclusion* e) +{ + Bool ret = TRUE; + + /* check that the doc_id is valid */ + if(XP_DOCID(e->ce.context) != e->ce.doc_id) + return FALSE; + + switch(e->op) { + case TR_SetHref: + XMLSetTransclusionProperty(e->xmlFile, e->param_val, "href", e->param_ptr); + if (e->param_ptr) + XP_FREE((void*)e->param_ptr); + break; + default: + XP_ASSERT(0); + } + + return (int)ret; +} + +PR_STATIC_CALLBACK(void) +et_DestroyEvent_TweakTransclusion(MozillaEvent_TweakTransclusion * event) +{ + XP_FREE(event); +} + + +int +ET_TweakTransclusion(MWContext * context, void *xmlFile, void *param_ptr, + int32 param_val, ETTransclusionOp op, int32 doc_id) +{ + MozillaEvent_TweakTransclusion * event; + event = PR_NEW(MozillaEvent_TweakTransclusion); + if (event == NULL) + return NULL; + + PR_InitEvent(&event->ce.event, context, + (PRHandleEventProc)et_HandleEvent_TweakTransclusion, + (PRDestroyEventProc)et_DestroyEvent_TweakTransclusion); + event->ce.context = context; + event->ce.doc_id = doc_id; + event->op = op; + event->param_ptr = param_ptr; + event->param_val = param_val; + event->xmlFile = xmlFile; + + return (int)et_PostEvent(&event->ce, FALSE); +} + +#endif diff --git a/lib/libmocha/lm.h b/lib/libmocha/lm.h index c3605480482..bac8104f993 100644 --- a/lib/libmocha/lm.h +++ b/lib/libmocha/lm.h @@ -71,6 +71,11 @@ extern char lm_embeds_str[]; /* "embeds" */ extern char lm_plugins_str[]; /* "plugins" */ extern char lm_images_str[]; /* "images" */ extern char lm_layers_str[]; /* "layers" */ +#ifdef DOM +extern char lm_spans_str[]; /* "spans" */ +extern char lm_transclusions_str[]; /* "transclusions" */ +#endif + extern char lm_location_str[]; /* "location" */ extern char lm_navigator_str[]; /* "navigator" */ extern char lm_netcaster_str[]; /* "netcaster" */ @@ -226,6 +231,12 @@ extern JSObject *lm_GetLinkArray(MochaDecoder *decoder, JSObject *document); extern JSObject *lm_GetNameArray(MochaDecoder *decoder, JSObject *document); +#ifdef DOM +extern JSObject *lm_GetSpanArray(MochaDecoder *decoder, + JSObject *document); +extern JSObject *lm_GetTransclusionArray(MochaDecoder *decoder, + JSObject *document); +#endif extern JSObject *lm_GetAppletArray(MochaDecoder *decoder, JSObject *document); extern JSObject *lm_GetEmbedArray(MochaDecoder *decoder, @@ -326,6 +337,10 @@ typedef struct JSDocument { JSObject *embeds; JSObject *images; JSObject *layers; +#ifdef DOM + JSObject *spans; + JSObject *transclusions; +#endif } JSDocument; #define URL_NOT_INDEXED ((uint32)-1) @@ -501,6 +516,14 @@ lm_InitImageClass(MochaDecoder *decoder); extern JSBool lm_InitAnchorClass(MochaDecoder *decoder); +#ifdef DOM +extern JSBool +lm_InitSpanClass(MochaDecoder *decoder); + +extern JSBool +lm_InitTransclusionClass(MochaDecoder *decoder); +#endif + extern JSBool lm_InitLayerClass(MochaDecoder *decoder); diff --git a/lib/libmocha/lm_doc.c b/lib/libmocha/lm_doc.c index 4679f83b482..05eab1e33fb 100644 --- a/lib/libmocha/lm_doc.c +++ b/lib/libmocha/lm_doc.c @@ -42,6 +42,7 @@ #include "jsjava.h" #endif +#ifndef DOM enum doc_slot { DOC_LENGTH = -1, DOC_ELEMENTS = -2, @@ -68,7 +69,37 @@ enum doc_slot { DOC_WIDTH = -22, DOC_HEIGHT = -23 }; - +#else +enum doc_slot { + DOC_LENGTH = -1, + DOC_ELEMENTS = -2, + DOC_FORMS = -3, + DOC_LINKS = -4, + DOC_ANCHORS = -5, + DOC_APPLETS = -6, + DOC_EMBEDS = -7, + DOC_SPANS = -8, /* Added for HTML SPAN DOM stuff */ + DOC_TRANSCLUSIONS = -9, /* Added for XML Transclusion DOM stuff */ + DOC_TITLE = -10, + DOC_URL = -11, + DOC_REFERRER = -12, + DOC_LAST_MODIFIED = -13, + DOC_COOKIE = -14, + DOC_DOMAIN = -15, + /* slots below this line are not secured */ + DOC_IMAGES = -16, + DOC_LAYERS = -17, + DOC_LOADED_DATE = -18, + DOC_BG_COLOR = -19, + DOC_FG_COLOR = -20, + DOC_LINK_COLOR = -21, + DOC_VLINK_COLOR = -22, + DOC_ALINK_COLOR = -23, + DOC_WIDTH = -24, + DOC_HEIGHT = -25 +}; + +#endif #define IS_SECURE_DOC_SLOT(s) (DOC_DOMAIN <= (s) && (s) <= DOC_LENGTH) static JSPropertySpec doc_props[] = { @@ -82,6 +113,10 @@ static JSPropertySpec doc_props[] = { {lm_plugins_str, DOC_EMBEDS, JSPROP_READONLY}, {lm_images_str, DOC_IMAGES, JSPROP_ENUMERATE|JSPROP_READONLY}, {lm_layers_str, DOC_LAYERS, JSPROP_ENUMERATE|JSPROP_READONLY}, +#ifdef DOM + {lm_spans_str, DOC_SPANS, JSPROP_ENUMERATE|JSPROP_READONLY}, + {lm_transclusions_str, DOC_TRANSCLUSIONS, JSPROP_ENUMERATE|JSPROP_READONLY}, +#endif {"title", DOC_TITLE, JSPROP_ENUMERATE|JSPROP_READONLY}, {"URL", DOC_URL, JSPROP_ENUMERATE|JSPROP_READONLY}, {"referrer", DOC_REFERRER, JSPROP_ENUMERATE|JSPROP_READONLY}, @@ -249,6 +284,33 @@ doc_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) LO_UnlockLayout(); return JS_TRUE; +#ifdef DOM + case DOC_SPANS: + *vp = OBJECT_TO_JSVAL(lm_GetSpanArray(decoder, obj)); + active_layer_id = LM_GetActiveLayer(context); + LM_SetActiveLayer(context, doc->layer_id); + (void) LO_EnumerateSpans(context,doc->layer_id); + LM_SetActiveLayer(context, active_layer_id); + LO_UnlockLayout(); + return JS_TRUE; + + case DOC_TRANSCLUSIONS: + /* We are assuming that by the time any JS sees document.transclusions[] + all the transclusions have been reflected into JS. So + there is no need for the call to XMLEnumerateTransclusions that + reflects all Transclusions into JS. + */ + *vp = OBJECT_TO_JSVAL(lm_GetTransclusionArray(decoder, obj)); + active_layer_id = LM_GetActiveLayer(context); + LM_SetActiveLayer(context, doc->layer_id); + /* + (void) XMLEnumerateTransclusions(context,doc->layer_id); + */ + LM_SetActiveLayer(context, active_layer_id); + LO_UnlockLayout(); + return JS_TRUE; +#endif + /* XXX BUGBUG Need a story for some of these for a layer's document */ case DOC_TITLE: he = SHIST_GetCurrent(&context->hist); @@ -1578,7 +1640,12 @@ lm_DefineDocument(MochaDecoder *decoder, int32 layer_id) !JS_AddNamedRoot(cx, &doc->applets, lm_applets_str) || !JS_AddNamedRoot(cx, &doc->embeds, lm_embeds_str) || !JS_AddNamedRoot(cx, &doc->images, lm_images_str) || - !JS_AddNamedRoot(cx, &doc->layers, lm_layers_str)) { + !JS_AddNamedRoot(cx, &doc->layers, lm_layers_str) +#ifdef DOM + || !JS_AddNamedRoot(cx, &doc->spans, lm_spans_str) + || !JS_AddNamedRoot(cx, &doc->transclusions, lm_transclusions_str) +#endif + ) { /* doc_finalize will clean up the rest. */ return NULL; } @@ -1664,6 +1731,10 @@ lm_CleanUpDocumentRoots(MochaDecoder *decoder, JSObject *obj) doc->embeds = NULL; doc->images = NULL; doc->layers = NULL; +#ifdef DOM + doc->spans = NULL; + doc->transclusions = NULL; +#endif } /* diff --git a/lib/libmocha/lm_init.c b/lib/libmocha/lm_init.c index 6602b86b886..3905370be03 100644 --- a/lib/libmocha/lm_init.c +++ b/lib/libmocha/lm_init.c @@ -91,6 +91,10 @@ char lm_applets_str[] = "applets"; char lm_embeds_str[] = "embeds"; char lm_images_str[] = "images"; char lm_layers_str[] = "layers"; +#ifdef DOM +char lm_spans_str[] = "spans"; +char lm_transclusions_str[] = "transclusions"; +#endif char lm_location_str[] = "location"; char lm_navigator_str[] = "navigator"; char lm_netcaster_str[] = "netcaster"; diff --git a/lib/libmocha/lm_input.c b/lib/libmocha/lm_input.c index 1f10dd944f7..e1d26a2a901 100644 --- a/lib/libmocha/lm_input.c +++ b/lib/libmocha/lm_input.c @@ -2365,6 +2365,14 @@ lm_InputEvent(MWContext *context, LO_Element *element, JSEvent *pEvent, case LO_TEXT: anchor = element->lo_text.text ? element->lo_text.anchor_href : 0; obj = anchor ? anchor->mocha_object : 0; +#ifdef DOM + /* If this layout element is within a span, set the mocha object to + the containing SPAN's mocha object */ + if (LO_IsWithinSpan( element )) + { + obj = LO_GetMochaObjectOfParentSpan( element ); + } +#endif if (!obj) { if (!LM_EventCaptureCheck(context, pEvent->type) || !anchor) { LO_UnlockLayout(); diff --git a/lib/libmocha/lm_span.c b/lib/libmocha/lm_span.c new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/libmocha/lm_trans.c b/lib/libmocha/lm_trans.c new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/libmocha/lm_win.c b/lib/libmocha/lm_win.c index b8708ddcbe2..0b4db3aff5b 100644 --- a/lib/libmocha/lm_win.c +++ b/lib/libmocha/lm_win.c @@ -3326,6 +3326,10 @@ lm_DefineWindowProps(JSContext *cx, MochaDecoder *decoder) lm_InitRectClass(decoder) && lm_InitImageClass(decoder) && lm_InitAnchorClass(decoder) && +#ifdef DOM + lm_InitSpanClass(decoder) && + lm_InitTransclusionClass(decoder) && +#endif lm_InitInputClasses(decoder) && lm_DefinePkcs11(decoder)); } diff --git a/modules/xml/glue/makefile.win b/modules/xml/glue/makefile.win index 44074a1f3d7..80037c5971d 100644 --- a/modules/xml/glue/makefile.win +++ b/modules/xml/glue/makefile.win @@ -19,12 +19,12 @@ DEPTH = ..\..\.. - +MODULE = xmlglue CSRCS= xmlglue.c xmlss.c xmldom.c - +EXPORTS = xmlglue.h C_OBJS=.\$(OBJDIR)\xmlglue.obj .\$(OBJDIR)\xmlss.obj .\$(OBJDIR)\xmldom.obj -LINCS=-I$(XPDIST)\public\nspr -I$(XPDIST)\public\expat +LINCS=-I$(XPDIST)\public\nspr -I$(XPDIST)\public\expat -I$(XPDIST)\public\js include <$(DEPTH)\config\rules.mak> diff --git a/modules/xml/glue/xmldom.c b/modules/xml/glue/xmldom.c index a7afd92cbbf..644efccf5de 100644 --- a/modules/xml/glue/xmldom.c +++ b/modules/xml/glue/xmldom.c @@ -130,10 +130,95 @@ void XMLDOM_StartHandler (XMLFile f, const char* elementName, const char** attli xmle->content = (char*) incl; f->numOpenStreams++; readHTML(makeAbsoluteURL(f->address, hrefVal), incl); + if (f->numTransclusions == 0) { + f->transclusions = (XMLElement*)getMem(sizeof(XMLElement*) * 10); + } + f->transclusions[f->numTransclusions++] = xmle; +#ifdef DOM + ET_ReflectObject(f->mwcontext, f->transclusions[f->numTransclusions - 1], NULL, LO_DOCUMENT_LAYER_ID, + f->numTransclusions - 1, LM_TRANSCLUSIONS); +#endif } } } + +char** +setAttribute (char** attlist, char* elName, char* elValue) +{ + size_t n = 0; + char** nattlist; + if (!attlist) return NULL; + while ((n < 2*MAX_ATTRIBUTES) && (*(attlist + n) != NULL)) { + if (strcmp(*(attlist + n), elName) == 0) { + *(attlist + n + 1) = elValue; + return attlist; + } + n = n + 2; + } + + nattlist = getMem(n+2); + memcpy(nattlist, attlist, (n * sizeof(char**))); + *(nattlist + n) = elName; + *(nattlist + n + 1) = elValue; + freeMem(attlist); + return nattlist; +} + + +void XMLSetTransclusionProperty( XMLFile f, uint index, char* propName, char* propValue ) { + XMLElement el = f->transclusions[index]; + if (!el) return; + el->attributes = setAttribute(el->attributes, propName, propValue); + if (stringEquals(propName, "href")) { + XMLHTMLInclusion incl = (XMLHTMLInclusion) el->content; + freeMem(incl->content); + incl->content = (char**)getMem(400); + incl->n = 0; + readHTML (makeAbsoluteURL(f->address, propValue), (XMLHTMLInclusion)el->content); + } else if (stringEquals(propName, "visibility") + ||stringEquals(propName, "display")) { + xmlhtml_complete_int(f); + } +} + +void XMLDeleteMochaObjectReference(XMLFile f, uint index) +{ + XMLElement el = f->transclusions[index]; + if (el) el->mocha_object = NULL; +} + +int32 +XMLTransclusionCount(MWContext *context) +{ + if (!context) { + return 0; + } else { + XMLFile f = (XMLFile)context->xmlfile; + if (!f) { + return 0; + } else { + return f->numTransclusions; + } + } +} + +JSObject* XML_GetMochaObject (void* el) { + return ((XMLElement)el)->mocha_object; +} + +void XML_SetMochaObject (void* el, JSObject* jso) { + ((XMLElement)el)->mocha_object = jso; +} + + +void * /* XMLElement */ XMLGetTransclusionByIndex( MWContext *context, uint index ) +{ + XMLFile f = context->xmlfile; + if (!f) return 0; + return f->transclusions[index]; +} + void XMLDOM_PIHandler (XMLFile f, const char *elementName, const char *data) { if (startsWith("xml:stylesheet", elementName)) { char* url ; @@ -204,3 +289,4 @@ tokenizeXMLElement (char* attr, char** attlist) inAttrNamep = (inAttrNamep ? 0 : 1); } } + diff --git a/modules/xml/glue/xmlglue.c b/modules/xml/glue/xmlglue.c index 8fa7e229753..9b8972666ba 100644 --- a/modules/xml/glue/xmlglue.c +++ b/modules/xml/glue/xmlglue.c @@ -30,6 +30,7 @@ #include "xmlglue.h" #include "xmlparse.h" #include "xmlss.h" +#include "layers.h" @@ -73,7 +74,7 @@ xml_abort(NET_StreamClass *stream, int status) XML_ParserFree(obj->parser); } - + int xml_write(NET_StreamClass *stream, char* data, int32 len) { @@ -96,7 +97,7 @@ xml_complete (NET_StreamClass *stream) return; } XML_Parse(obj->parser, NULL, 0, 1); - XML_ParserFree(obj->parser); + XML_ParserFree(obj->parser); obj->numOpenStreams--; if (obj->numOpenStreams < 1) { @@ -107,25 +108,52 @@ xml_complete (NET_StreamClass *stream) newstream = NET_StreamBuilder(1, nurls, (MWContext*)obj->mwcontext); obj->stream = newstream; convertToHTML(obj); + outputToStream(obj, NULL); newstream->complete(newstream); NET_FreeURLStruct(nurls); } } - +#define OUTPUT_BUFFER_SIZE (4096*16) void outputToStream (XMLFile f, char* s) { int ans = 0; NET_StreamClass *stream = (NET_StreamClass*) f->stream; - char* buff = copyString(s); -#ifdef DEBUG -/* FE_Trace(s); */ -#endif - - if (buff) (*(stream->put_block))(stream, buff, strlen(s)); - freeMem(buff); + if (s == NULL) { + if (f->outputBuffer) { + XP_Rect rect; + CL_OffscreenMode save_offscreen_mode; + CL_Compositor *comp = ((MWContext*)f->mwcontext)->compositor; + rect.left = rect.top = 0; + rect.right = 1600; + rect.bottom = 16000; + /* CL_SetCompositorEnabled(comp, 0); */ + CL_SetCompositorOffscreenDrawing(comp, CL_OFFSCREEN_ENABLED); + (*(stream->put_block))(stream, f->outputBuffer, strlen(f->outputBuffer)); + /* CL_SetCompositorEnabled(comp, 1); + CL_SetCompositorOffscreenDrawing(comp, CL_OFFSCREEN_ENABLED); */ + CL_UpdateDocumentRect(comp,&rect, 0); + freeMem(f->outputBuffer); + f->outputBuffer = NULL; + } + return; + } + if (f->outputBuffer == NULL) f->outputBuffer = getMem(OUTPUT_BUFFER_SIZE+1); + if ((strlen(s) > OUTPUT_BUFFER_SIZE)) { + char* buff = copyString(s); + if (buff) (*(stream->put_block))(stream, buff, strlen(s)); + CL_CompositeNow(((MWContext*)f->mwcontext)->compositor); + freeMem(buff); + } else if (strlen(f->outputBuffer) + strlen(s) > OUTPUT_BUFFER_SIZE) { + (*(stream->put_block))(stream, f->outputBuffer, strlen(f->outputBuffer)); + CL_CompositeNow(((MWContext*)f->mwcontext)->compositor); + memset(f->outputBuffer, '\0', OUTPUT_BUFFER_SIZE); + sprintf(f->outputBuffer, s); + } else { + strcat(f->outputBuffer, s); + } } @@ -152,6 +180,7 @@ XML_XMLConverter(FO_Present_Types format_out, void *data_object, URL_Struct *UR xmlf->status = 1; xmlf->address = copyString(URL_s->address); xmlf->mwcontext = window_id; + window_id->xmlfile = xmlf; xmlf->numOpenStreams = 1; /* URL_s->fedata = xmlf; */ stream = NET_NewStream("XML", (MKStreamWriteFunc)xml_write, @@ -209,6 +238,7 @@ xmlcss_complete (NET_StreamClass *stream) newstream = NET_StreamBuilder(1, nurls, (MWContext*) xml->mwcontext); xml->stream = newstream; convertToHTML(xml); + outputToStream(xml, NULL); newstream->complete(newstream); NET_FreeURLStruct(nurls); } @@ -290,25 +320,47 @@ xmlhtml_abort(NET_StreamClass *stream, int status) -void -xmlhtml_complete (NET_StreamClass *stream) -{ - XMLHTMLInclusion ss =stream->data_object; - XMLFile xml = ss->xml; + +void xmlhtml_complete_int (XMLFile xml) { + MWContext *cx = (MWContext *)xml->mwcontext; + int16 save_offscreen_mode; + xml->numOpenStreams--; - if (xml->numOpenStreams == 0) { + if (xml->numOpenStreams < 1) { /* direct the stream to the html parser */ NET_StreamClass *newstream; URL_Struct *nurls = NET_CreateURLStruct(copyString(xml->address), NET_DONT_RELOAD); StrAllocCopy(nurls->content_type, TEXT_HTML); newstream = NET_StreamBuilder(1, nurls, (MWContext*) xml->mwcontext); xml->stream = newstream; + if (cx->compositor) + { + /* Temporarily force drawing to use the offscreen buffering area to reduce + flicker when outputing html. (If no offscreen store is allocated, this code will + have no effect, but it will do no harm.) */ + save_offscreen_mode = CL_GetCompositorOffscreenDrawing(cx->compositor); + CL_SetCompositorOffscreenDrawing(cx->compositor, CL_OFFSCREEN_ENABLED); + } convertToHTML(xml); + outputToStream(xml, NULL); + if (cx->compositor) + { +/* CL_CompositeNow(cx->compositor); + CL_SetCompositorOffscreenDrawing(cx->compositor, save_offscreen_mode); */ + } newstream->complete(newstream); NET_FreeURLStruct(nurls); } } +void +xmlhtml_complete (NET_StreamClass *stream) +{ + XMLHTMLInclusion ss =stream->data_object; + XMLFile xml = ss->xml; + xmlhtml_complete_int(xml); +} + #ifdef XP_MAC @@ -335,6 +387,8 @@ xmlhtml_GetUrlExitFunc (URL_Struct *urls, int status, MWContext *cx) } +void setTransclusionProp (XMLFile f, int32 n, char* prop, char* value) { +} void readHTML (char* url, XMLHTMLInclusion ss) diff --git a/modules/xml/glue/xmlglue.h b/modules/xml/glue/xmlglue.h index 158faae866e..d81d1fa1170 100644 --- a/modules/xml/glue/xmlglue.h +++ b/modules/xml/glue/xmlglue.h @@ -19,8 +19,18 @@ #ifndef _RDF_XMLGLUE_H_ #define _RDF_XMLGLUE_H_ +/* Make sure @#$%^&* LAYERS is defined for the Mac */ +#ifndef LAYERS +#define LAYERS +#endif + #include "xmlparse.h" +#include "jscompat.h" +#include "lo_ele.h" +#include "libevent.h" +#include "libmocha.h" + #ifdef XP_UNIX #include #elif defined(XP_MAC) @@ -78,9 +88,12 @@ typedef struct _XMLFileStruct { void* stream; int8 numOpenStreams; void* urls; - void* mwcontext; + MWContext* mwcontext; char* address; + char* outputBuffer; XML_Parser parser; + int32 numTransclusions; + struct _XMLElementStruct** transclusions; } XMLFileStruct; typedef XMLFileStruct* XMLFile; @@ -102,6 +115,7 @@ typedef struct _StyleElementStruct { char** tagStack; char* style; struct _StyleElementStruct* next; + int id; /* Unique identifier among all style elements in all style sheets */ } StyleElementStruct; typedef StyleElementStruct* StyleElement; @@ -111,6 +125,7 @@ typedef struct _XMLElementStruct { char* tag; char** attributes; char* content; + JSObject *mocha_object; struct _XMLElementStruct* parent; struct _XMLElementStruct* child; struct _XMLElementStruct* next; @@ -168,6 +183,7 @@ int xmlhtml_write(NET_StreamClass *stream, const char *str, int32 len); unsigned int xmlhtml_write_ready(NET_StreamClass *stream); void xmlhtml_abort(NET_StreamClass *stream, int status); void xmlhtml_complete (NET_StreamClass *stream); +void xmlhtml_complete_int (XMLFile xml); void xmlhtml_GetUrlExitFunc (URL_Struct *urls, int status, MWContext *cx); void readHTML (char* url, XMLHTMLInclusion ss); diff --git a/modules/xml/glue/xmlss.c b/modules/xml/glue/xmlss.c index ba486330bc3..84254ce7abd 100644 --- a/modules/xml/glue/xmlss.c +++ b/modules/xml/glue/xmlss.c @@ -83,7 +83,7 @@ parseNextXMLCSSBlob (NET_StreamClass *stream, char* blob, int32 size) return(size); } - +static int32 style_id_counter = 0; void parseNextXMLCSSElement (StyleSheet ss, char* ele) @@ -95,6 +95,7 @@ parseNextXMLCSSElement (StyleSheet ss, char* ele) } else { StyleElement se = (StyleElement) getMem(sizeof(StyleElementStruct)); size_t numTags, size, n, count; + se->id = ++style_id_counter; se->next = ss->el; ss->el = se; size = strlen(ele); @@ -263,7 +264,25 @@ outputAsHTML (XMLFile f, XMLElement el) } } - +void +outputAllStyles(XMLFile xf) +{ + char *ssline; + StyleSheet ss ; + StyleElement se; + outputToStream(xf, "\n"); +} void convertToHTML (XMLFile xf) { @@ -271,36 +290,40 @@ convertToHTML (XMLFile xf) { xf->numOpenStreams--; if (xf->numOpenStreams < 1) { outputToStream(xf, ""); + outputAllStyles(xf); outputAsHTML(xf, el); outputToStream(xf, ""); } } - void outputStyleSpan (XMLFile f, XMLElement el, PRBool endp) { + char *ssid; StyleSheet ss ; StyleElement se; for (ss = f->ss; (ss != NULL) ; ss = ss->next) { for (se = ss->el; (se != NULL) ; se = se->next) { - if (stringEquals((se->tagStack)[0], el->tag)) { + if (se->style && stringEquals((se->tagStack)[0], el->tag)) { + /* check for se->style from Steve Wingard */ PRBool divp = startsWith("Display:Block;", se->style); PRBool listp = startsWith("Display:List-item;", se->style); if (!endp) { if (divp) { - outputToStream(f, "
style)[14]); + outputToStream(f, "
  • style)[20]); + outputToStream(f, "
    • style); + outputToStream(f, "\n"); + ssid=PR_smprintf("class=xml%d>\n", se->id); + PR_ASSERT(ssid); + if (!ssid) + return; + outputToStream(f, ssid); + free(ssid); } else { if (divp) { outputToStream(f, "
  • ");