Annotation of libwww/Library/src/HTMLGen.c, revision 2.7

2.1       timbl       1: /*             HTML Generator
                      2: **             ==============
                      3: **
                      4: **     This version of the HTML object sends HTML markup to the output stream.
                      5: **
                      6: ** Bugs:       Line wrapping is not done at all.
                      7: **             All data handled as PCDATA.
                      8: **             Should convert old XMP, LISTING and PLAINTEXT to PRE.
                      9: **
                     10: **     It is not obvious to me right now whether the HEAD should be generated
2.7     ! timbl      11: **     from the incomming data or the anchor.  Currently it is from the former
2.1       timbl      12: **     which is cleanest.
                     13: */
                     14: 
2.7     ! timbl      15: #define BUFFER_SIZE    80      /* Line buffer attempts to make neat breaks */
        !            16: 
2.1       timbl      17: /* Implements:
                     18: */
                     19: #include "HTMLGen.h"
                     20: 
                     21: #include <stdio.h>
                     22: #include "HTMLDTD.h"
                     23: #include "HTStream.h"
                     24: #include "SGML.h"
                     25: #include "HTFormat.h"
                     26: 
2.3       timbl      27: #define PUTC(c) (*me->targetClass.put_character)(me->target, c)
2.7     ! timbl      28: /* #define PUTS(s) (*me->targetClass.put_string)(me->target, s) */
2.4       timbl      29: #define PUTB(s,l) (*me->targetClass.put_block)(me->target, s, l)
2.1       timbl      30: 
                     31: /*             HTML Object
                     32: **             -----------
                     33: */
                     34: 
                     35: struct _HTStream {
                     36:        CONST HTStreamClass *           isa;    
                     37:        HTStream *                      target;
                     38:        HTStreamClass                   targetClass;    /* COPY for speed */
                     39: };
                     40: 
                     41: struct _HTStructured {
                     42:        CONST HTStructuredClass *       isa;
                     43:        HTStream *                      target;
                     44:        HTStreamClass                   targetClass;    /* COPY for speed */
2.7     ! timbl      45:        
        !            46:        char                            buffer[BUFFER_SIZE];
        !            47:        char *                          write_pointer;
        !            48:        char *                          line_break;
        !            49:        int                             cleanness;
        !            50:        BOOL                            preformatted;
2.1       timbl      51: };
                     52: 
                     53: 
2.7     ! timbl      54: /*     Flush Buffer
        !            55: **     ------------
        !            56: */
        !            57: PRIVATE void HTMLGen_flush ARGS1(HTStructured *, me)
        !            58: {
        !            59:     (*me->targetClass.put_block)(me->target, 
        !            60:                                me->buffer,
        !            61:                                me->write_pointer - me->buffer);
        !            62:     me->write_pointer = me->buffer;
        !            63:     me->line_break = me->buffer;
        !            64:     me->cleanness = 0;
        !            65: }
        !            66: 
        !            67: 
2.1       timbl      68: /*     Character handling
                     69: **     ------------------
                     70: */
2.3       timbl      71: PRIVATE void HTMLGen_put_character ARGS2(HTStructured *, me, char, c)
2.1       timbl      72: {
2.7     ! timbl      73: 
        !            74:     *me->write_pointer++ = c;
        !            75:     
        !            76:     if (c=='\n') {
        !            77:         HTMLGen_flush(me);
        !            78:        return;
        !            79:     }
        !            80:     
        !            81:     if ((!me->preformatted  && c==' ')) {
        !            82:        me->line_break = me->write_pointer;
        !            83:        me->cleanness = 1;
        !            84:     }
        !            85:     
        !            86:     /* Flush buffer out when full */
        !            87:     if (me->write_pointer == me->buffer + BUFFER_SIZE) {
        !            88:        if (me->cleanness) {
        !            89:            me->line_break[-1] = '\n';
        !            90:            (*me->targetClass.put_block)(me->target,
        !            91:                                        me->buffer,
        !            92:                                        me->line_break - me->buffer);
        !            93:            {  /* move next line in */
        !            94:                char * p,*q;
        !            95:                for(q=me->buffer, p=me->line_break; p < me->write_pointer; )
        !            96:                        *q++ = *p++;
        !            97:            }
        !            98:            me->cleanness = 0;
        !            99:        } else {
        !           100:            (*me->targetClass.put_block)(me->target,
        !           101:                me->buffer,
        !           102:                BUFFER_SIZE);
        !           103:        }
        !           104:        me->write_pointer = me->buffer;
        !           105:        me->line_break = me->buffer;
        !           106:     }
2.1       timbl     107: }
                    108: 
                    109: 
                    110: 
                    111: /*     String handling
                    112: **     ---------------
                    113: */
2.3       timbl     114: PRIVATE void HTMLGen_put_string ARGS2(HTStructured *, me, CONST char*, s)
2.1       timbl     115: {
2.7     ! timbl     116:     CONST char * p;
        !           117:     for(p=s; *p; p++) HTMLGen_put_character(me, *p);
2.1       timbl     118: }
                    119: 
2.3       timbl     120: PRIVATE void HTMLGen_write ARGS3(HTStructured *, me, CONST char*, s, int, l)
2.1       timbl     121: {
2.7     ! timbl     122:     CONST char * p;
        !           123:     for(p=s; p<s+l; p++) HTMLGen_put_character(me, *p);
2.1       timbl     124: }
                    125: 
                    126: 
                    127: /*     Start Element
                    128: **     -------------
2.7     ! timbl     129: **
        !           130: **     Within the opening tag, there may be spaces
        !           131: **     and the line may be broken at these spaces.
2.1       timbl     132: */
                    133: PRIVATE void HTMLGen_start_element ARGS4(
2.3       timbl     134:        HTStructured *,         me,
2.2       timbl     135:        int,                    element_number,
                    136:        CONST BOOL*,            present,
                    137:        CONST char **,          value)
2.1       timbl     138: {
                    139:     int i;
2.7     ! timbl     140:     
        !           141:     BOOL was_preformatted = me->preformatted;
        !           142:     HTTag * tag = &HTML_dtd.tags[element_number];
2.1       timbl     143: 
2.7     ! timbl     144:     me->preformatted = NO;
        !           145:     HTMLGen_put_character(me, '<');
        !           146:     HTMLGen_put_string(me, tag->name);
2.1       timbl     147:     if (present) for (i=0; i< tag->number_of_attributes; i++) {
                    148:         if (present[i]) {
2.7     ! timbl     149:            HTMLGen_put_character(me, ' ');
        !           150:            HTMLGen_put_string(me, tag->attributes[i].name);
2.1       timbl     151:            if (value[i]) {
2.7     ! timbl     152:                HTMLGen_put_string(me, "=\"");
        !           153:                HTMLGen_put_string(me, value[i]);
        !           154:                HTMLGen_put_character(me, '"');
2.1       timbl     155:            }
                    156:        }
                    157:     }
2.7     ! timbl     158:     HTMLGen_put_string(me, ">\n");
        !           159:     
        !           160:     /* Make very specific HTML assumption that PRE can't be
        !           161:        nested! */
        !           162:        
        !           163:     me->preformatted = (element_number == HTML_PRE)  ? YES : was_preformatted;
2.1       timbl     164: }
                    165: 
                    166: 
                    167: /*             End Element
                    168: **             -----------
                    169: **
                    170: */
                    171: /*     When we end an element, the style must be returned to that
                    172: **     in effect before that element.  Note that anchors (etc?)
                    173: **     don't have an associated style, so that we must scan down the
                    174: **     stack for an element with a defined style. (In fact, the styles
                    175: **     should be linked to the whole stack not just the top one.)
                    176: **     TBL 921119
                    177: */
2.3       timbl     178: PRIVATE void HTMLGen_end_element ARGS2(HTStructured *, me,
2.1       timbl     179:                        int , element_number)
                    180: {
2.7     ! timbl     181:     HTMLGen_put_string(me, "</");
        !           182:     HTMLGen_put_string(me, HTML_dtd.tags[element_number].name);
        !           183:     HTMLGen_put_character(me, '>');
        !           184:     if (element_number == HTML_PRE) me->preformatted = NO;
2.1       timbl     185: }
                    186: 
                    187: 
                    188: /*             Expanding entities
                    189: **             ------------------
                    190: **
                    191: */
                    192: 
2.3       timbl     193: PRIVATE void HTMLGen_put_entity ARGS2(HTStructured *, me, int, entity_number)
2.1       timbl     194: {
2.7     ! timbl     195:     HTMLGen_put_character(me, '&');
        !           196:     HTMLGen_put_string(me, HTML_dtd.entity_names[entity_number]);
        !           197:     HTMLGen_put_character(me, ';');
2.1       timbl     198: }
                    199: 
                    200: 
                    201: 
                    202: /*     Free an HTML object
                    203: **     -------------------
                    204: **
                    205: */
2.3       timbl     206: PRIVATE void HTMLGen_free ARGS1(HTStructured *, me)
2.1       timbl     207: {
2.7     ! timbl     208:     (*me->targetClass.put_character)(me->target, '\n');
        !           209:     HTMLGen_flush(me);
2.3       timbl     210:     (*me->targetClass.free)(me->target);       /* ripple through */
                    211:     free(me);
2.1       timbl     212: }
                    213: 
                    214: 
2.7     ! timbl     215: PRIVATE void PlainToHTML_free ARGS1(HTStructured *, me)
        !           216: {
        !           217:     HTMLGen_end_element(me, HTML_PRE);
        !           218:     HTMLGen_end_element(me, HTML_BODY);
        !           219:     HTMLGen_end_element(me, HTML_HTML);
        !           220:     HTMLGen_free(me);
        !           221: }
        !           222: 
        !           223: 
2.1       timbl     224: 
2.6       timbl     225: PRIVATE void HTMLGen_abort ARGS2(HTStructured *, me, HTError, e)
2.1       timbl     226: {
2.6       timbl     227:     HTMLGen_free(me);
2.1       timbl     228: }
                    229: 
                    230: 
2.6       timbl     231: PRIVATE void PlainToHTML_abort ARGS2(HTStructured *, me, HTError, e)
2.1       timbl     232: {
2.7     ! timbl     233:     PlainToHTML_free(me);
2.1       timbl     234: }
                    235: 
                    236: 
                    237: 
                    238: /*     Structured Object Class
                    239: **     -----------------------
                    240: */
2.5       timbl     241: PRIVATE CONST HTStructuredClass HTMLGeneration = /* As opposed to print etc */
2.1       timbl     242: {              
                    243:        "text/html",
                    244:        HTMLGen_free,
2.6       timbl     245:        HTMLGen_abort,
2.1       timbl     246:        HTMLGen_put_character,  HTMLGen_put_string, HTMLGen_write,
                    247:        HTMLGen_start_element,  HTMLGen_end_element,
                    248:        HTMLGen_put_entity
                    249: }; 
                    250: 
                    251: 
                    252: /*     Subclass-specific Methods
                    253: **     -------------------------
                    254: */
                    255: 
                    256: PUBLIC HTStructured * HTMLGenerator ARGS1(HTStream *, output)
                    257: {
2.3       timbl     258:     HTStructured* me = (HTStructured*)malloc(sizeof(*me));
                    259:     if (me == NULL) outofmem(__FILE__, "HTMLGenerator");
                    260:     me->isa = &HTMLGeneration;       
2.1       timbl     261: 
2.3       timbl     262:     me->target = output;
                    263:     me->targetClass = *me->target->isa; /* Copy pointers to routines for speed*/
2.7     ! timbl     264:     
        !           265:     me->write_pointer = me->buffer;
        !           266:     me->line_break =   me->buffer;
        !           267:     me->cleanness =    0;
        !           268:     me->preformatted =         NO;
2.3       timbl     269:     return me;
2.1       timbl     270: }
                    271: 
                    272: /*     Stream Object Class
                    273: **     -------------------
                    274: **
2.2       timbl     275: **     This object just converts a plain text stream into HTML
                    276: **     It is officially a structured strem but only the stream bits exist.
                    277: **     This is just the easiest way of typecasting all the routines.
2.1       timbl     278: */
2.2       timbl     279: PRIVATE CONST HTStructuredClass PlainToHTMLConversion =
2.1       timbl     280: {              
                    281:        "plaintexttoHTML",
                    282:        HTMLGen_free,   
2.6       timbl     283:        PlainToHTML_abort,      
2.1       timbl     284:        HTMLGen_put_character,
                    285:        HTMLGen_put_string,
                    286:        HTMLGen_write,
2.2       timbl     287:        NULL,           /* Structured stuff */
                    288:        NULL,
                    289:        NULL
2.1       timbl     290: }; 
                    291: 
                    292: 
                    293: /*     HTConverter from plain text to HTML Stream
                    294: **     ------------------------------------------
                    295: */
                    296: 
                    297: PUBLIC HTStream* HTPlainToHTML ARGS3(
                    298:        HTPresentation *,       pres,
                    299:        HTParentAnchor *,       anchor, 
                    300:        HTStream *,             sink)
                    301: {
2.7     ! timbl     302:     HTStructured* me = (HTStructured*)malloc(sizeof(*me));
2.3       timbl     303:     if (me == NULL) outofmem(__FILE__, "PlainToHTML");
2.7     ! timbl     304:     me->isa = (HTStructuredClass*) &PlainToHTMLConversion;       
2.1       timbl     305: 
2.3       timbl     306:     me->target = sink;
                    307:     me->targetClass = *me->target->isa;
2.1       timbl     308:        /* Copy pointers to routines for speed*/
                    309:        
2.7     ! timbl     310:     HTMLGen_put_string(me, "<HTML>\n<BODY>\n<PRE>\n");
        !           311:     me->preformatted = YES;
        !           312:     return (HTStream*) me;
2.1       timbl     313: }
                    314: 
                    315: 

Webmaster