dtd->tags[element_number];
/* Control line breaks allowed within tag! */
int was_preformatted = me->preformatted; /* save state */
me->preformatted = 1; /* Can break between attributes */
HTMLGen_output_character(me, '<');
HTMLGen_output_string(me, tag->name);
if (present) for (i=0; i< tag->number_of_attributes; i++) {
if (present[i]) {
HTMLGen_output_character(me, ' ');
allow_break(me, 1, YES);
HTMLGen_output_string(me, tag->attributes[i].name);
if (value[i]) {
HTMLGen_output_string(me, "=\"");
HTMLGen_output_string(me, value[i]);
HTMLGen_output_character(me, '"');
}
}
}
me->preformatted = was_preformatted; /* Restore state */
/* Nested PRE is no more a problem! */
if (element_number == HTML_PRE)
me->preformatted++;
HTMLGen_output_character(me, '>');
/* Here is a funny one. In PRE, newlines are significant, except of
course for one after the which is ignored. This means that
we MUST put in a dummy one after the to protect any real newline
within the pre section.
However, *within* a PRE section, although we can break after
(for example) emphasis start tags, it will probably confuse some
parsers so we won't.*/
if (element_number == HTML_PRE) {
HTMLGen_output_character(me, '\n');
} else if (!me->preformatted &&
tag->contents != SGML_EMPTY) { /* can break after element start */
allow_break(me, 3, NO);
}
}
/* End Element
** -----------
**
** The rules for insertring CR LF into SGML are weird, strict, and
** nonintitive.
** See comment also about PRE above.
*/
PRIVATE void HTMLGen_end_element ARGS2(HTStructured *, me,
int , element_number)
{
if (element_number == HTML_PRE) {
HTMLGen_output_character(me, '\n');
} else if (!me->preformatted) { /* can break before element end */
allow_break(me, 1, NO);
}
HTMLGen_output_string(me, "");
HTMLGen_output_string(me, me->dtd->tags[element_number].name);
HTMLGen_output_character(me, '>'); /* NO break after. TBL 940501 */
if (element_number == HTML_PRE && me->preformatted)
me->preformatted--;
}
/* Expanding entities
** ------------------
**
*/
PRIVATE void HTMLGen_put_entity ARGS2(HTStructured *, me, int, entity_number)
{
HTMLGen_output_character(me, '&');
HTMLGen_output_string(me, me->dtd->entity_names[entity_number]);
HTMLGen_output_character(me, ';');
}
/* Free an object
** --------------
**
*/
PRIVATE void HTMLGen_free ARGS1(HTStructured *, me)
{
HTMLGen_flush(me);
(*me->targetClass.put_character)(me->target, '\n');
(*me->targetClass._free)(me->target); /* ripple through */
free(me);
}
PRIVATE void PlainToHTML_free ARGS1(HTStructured *, me)
{
HTMLGen_end_element(me, HTML_PRE);
HTMLGen_end_element(me, HTML_BODY);
HTMLGen_end_element(me, HTML_HTML);
HTMLGen_free(me);
}
PRIVATE void HTMLGen_abort ARGS2(HTStructured *, me, HTError, e)
{
HTMLGen_free(me);
}
PRIVATE void PlainToHTML_abort ARGS2(HTStructured *, me, HTError, e)
{
PlainToHTML_free(me);
}
/* Structured Object Class
** -----------------------
*/
PRIVATE CONST HTStructuredClass HTMLGeneration = /* As opposed to print etc */
{
"text/html",
HTMLGen_free,
HTMLGen_abort,
HTMLGen_put_character, HTMLGen_put_string, HTMLGen_write,
HTMLGen_start_element, HTMLGen_end_element,
HTMLGen_put_entity
};
/* Subclass-specific Methods
** -------------------------
*/
PUBLIC HTStructured * HTMLGenerator ARGS1(HTStream *, output)
{
HTStructured* me = (HTStructured*)calloc(1,sizeof(*me));
if (me == NULL) outofmem(__FILE__, "HTMLGenerator");
me->isa = &HTMLGeneration;
me->dtd = &HTMLP_dtd;
me->target = output;
me->targetClass = *me->target->isa; /* Copy pointers to routines for speed*/
me->write_pointer = me->buffer;
flush_breaks(me);
return me;
}
/* Stream Object Class
** -------------------
**
** This object just converts a plain text stream into HTML
** It is officially a structured stream but only the stream bits exist.
** This is just the easiest way of typecasting all the routines.
*/
PRIVATE CONST HTStructuredClass PlainToHTMLConversion =
{
"plaintexttoHTML",
PlainToHTML_free, /* HTMLGen_free, Henrik 03/03-94 */
PlainToHTML_abort,
HTMLGen_put_character,
HTMLGen_put_string,
HTMLGen_write,
NULL, /* Structured stuff */
NULL,
NULL
};
/* HTConverter from plain text to HTML Stream
** ------------------------------------------
**
** Changed by henrik 03/03-94, so no more core dumps etc. (I hope!!!)
*/
PUBLIC HTStream* HTPlainToHTML ARGS5(
HTRequest *, request,
void *, param,
HTFormat, input_format,
HTFormat, output_format,
HTStream *, output_stream)
{
BOOL present[MAX_ATTRIBUTES]; /* Flags: attribute is present? */
CONST char *value[MAX_ATTRIBUTES]; /* malloc'd strings or NULL if none */
HTStructured* me = (HTStructured*)calloc(1,sizeof(*me));
if (me == NULL) outofmem(__FILE__, "PlainToHTML");
memset(present, '\0', MAX_ATTRIBUTES);
memset(value, '\0', MAX_ATTRIBUTES*sizeof(char *));
me->isa = (HTStructuredClass*) &PlainToHTMLConversion;
me->dtd = &HTMLP_dtd;
me->target = output_stream;
me->targetClass = *me->target->isa;/* Copy pointers to routines for speed*/
me->write_pointer = me->buffer;
flush_breaks(me);
HTMLGen_start_element(me, HTML_HTML, present, value);
HTMLGen_start_element(me, HTML_BODY, present, value);
HTMLGen_start_element(me, HTML_PRE, present, value);
return (HTStream*) me;
}
/* A safe version for making 7-bit restricted HTML
** Beware that thsi makes it horrible for the Scandinavians
** to actually read it.
*/
PUBLIC HTStream* HTPlainTo7BitHTML ARGS5(
HTRequest *, request,
void *, param,
HTFormat, input_format,
HTFormat, output_format,
HTStream *, output_stream)
{
HTStream* me = HTPlainToHTML(request,param,input_format,
output_format, output_stream);
((HTStructured*)me)->seven_bit = YES;
return me;
}