Annotation of libwww/Library/src/HTML.c, revision 1.75

1.39      frystyk     1: /*                                                                      HTML.c
1.75    ! frystyk     2: **     SIMPLE HTML PARSER WITHOUT ANY PRESENTATION CODE
1.39      frystyk     3: **
1.43      frystyk     4: **     (c) COPYRIGHT MIT 1995.
1.39      frystyk     5: **     Please first read the full copyright statement in the file COPYRIGH.
1.75    ! frystyk     6: **     @(#) $Id: HTML.c,v 1.74 1998/10/15 20:07:55 frystyk Exp $
1.1       timbl       7: **
1.2       timbl       8: **     This generates of a hypertext object.  It converts from the
1.75    ! frystyk     9: **     structured stream interface foo HTML events into the style-
        !            10: **     oriented interface of the HText interface.
1.1       timbl      11: **
1.35      duns       12: ** HISTORY:
                     13: **      8 Jul 94  FM   Insulate free() from _free structure element.
1.1       timbl      14: */
1.16      timbl      15: 
1.41      frystyk    16: /* Library include files */
1.72      frystyk    17: #include "wwwsys.h"
1.63      frystyk    18: #include "WWWUtil.h"
                     19: #include "WWWCore.h"
                     20: #include "WWWHTML.h"
1.73      frystyk    21: #include "HTML.h"
1.75    ! frystyk    22: #include "HTextImp.h"
1.73      frystyk    23: 
1.75    ! frystyk    24: #define PUTC(t,c)      (*(t)->target->isa->put_character)((t)->target, (c))
        !            25: #define PUTS(t,s)      (*(t)->target->isa->put_string)((t)->target, (s))
        !            26: #define PUTB(s,b,l)    (*(t)->target->isa->put_block)((t)->target, (b), (l))
        !            27: #define FLUSH_TARGET(t)        (*(t)->target->isa->flush)((t)->target)
        !            28: #define FREE_TARGET(t) (*(t)->target->isa->_free)((t)->target)
        !            29: #define ABORT_TARGET(t)        (*(t)->target->isa->abort)((t)->target, e)
1.1       timbl      30: 
1.75    ! frystyk    31: #define MAX_NESTING 40
1.1       timbl      32: 
1.75    ! frystyk    33: struct _HTStream {
        !            34:     const HTStreamClass *      isa;
        !            35:     /* .... */
        !            36: };
1.2       timbl      37: 
                     38: struct _HTStructured {
1.60      frystyk    39:     const HTStructuredClass *  isa;
1.54      frystyk    40:     HTRequest *                        request;
1.2       timbl      41:     HTParentAnchor *           node_anchor;
1.75    ! frystyk    42:     HTextImp *                         text;
        !            43:     HTStream *                 target;
        !            44:     HTChunk *                  title;
        !            45:     BOOL                       in_word;
        !            46:     SGML_dtd *                 dtd;
1.2       timbl      47:     char *                     comment_start;  /* for literate programming */
                     48:     char *                     comment_end;
1.75    ! frystyk    49:     BOOL                       started;
1.1       timbl      50: 
1.75    ! frystyk    51:     int                                overflow;
        !            52:     int *                      sp;
        !            53:     int                                stack[MAX_NESTING];
1.2       timbl      54: };
1.1       timbl      55: 
1.75    ! frystyk    56: /*
        !            57: **     Entity values -- for ISO Latin 1 local representation
1.2       timbl      58: **     This MUST match exactly the table referred to in the DTD!
                     59: */
1.75    ! frystyk    60: #define ENTITY_SIZE    67
        !            61: static char * ISO_Latin1[ENTITY_SIZE] = {
1.2       timbl      62:        "\306", /* capital AE diphthong (ligature) */ 
                     63:        "\301", /* capital A, acute accent */ 
                     64:        "\302", /* capital A, circumflex accent */ 
                     65:        "\300", /* capital A, grave accent */ 
                     66:        "\305", /* capital A, ring */ 
                     67:        "\303", /* capital A, tilde */ 
                     68:        "\304", /* capital A, dieresis or umlaut mark */ 
                     69:        "\307", /* capital C, cedilla */ 
                     70:        "\320", /* capital Eth, Icelandic */ 
                     71:        "\311", /* capital E, acute accent */ 
                     72:        "\312", /* capital E, circumflex accent */ 
                     73:        "\310", /* capital E, grave accent */ 
                     74:        "\313", /* capital E, dieresis or umlaut mark */ 
                     75:        "\315", /* capital I, acute accent */ 
                     76:        "\316", /* capital I, circumflex accent */ 
                     77:        "\314", /* capital I, grave accent */ 
                     78:        "\317", /* capital I, dieresis or umlaut mark */ 
                     79:        "\321", /* capital N, tilde */ 
                     80:        "\323", /* capital O, acute accent */ 
                     81:        "\324", /* capital O, circumflex accent */ 
                     82:        "\322", /* capital O, grave accent */ 
                     83:        "\330", /* capital O, slash */ 
                     84:        "\325", /* capital O, tilde */ 
                     85:        "\326", /* capital O, dieresis or umlaut mark */ 
                     86:        "\336", /* capital THORN, Icelandic */ 
                     87:        "\332", /* capital U, acute accent */ 
                     88:        "\333", /* capital U, circumflex accent */ 
                     89:        "\331", /* capital U, grave accent */ 
                     90:        "\334", /* capital U, dieresis or umlaut mark */ 
                     91:        "\335", /* capital Y, acute accent */ 
                     92:        "\341", /* small a, acute accent */ 
                     93:        "\342", /* small a, circumflex accent */ 
                     94:        "\346", /* small ae diphthong (ligature) */ 
                     95:        "\340", /* small a, grave accent */ 
                     96:        "\046", /* ampersand */ 
                     97:        "\345", /* small a, ring */ 
                     98:        "\343", /* small a, tilde */ 
                     99:        "\344", /* small a, dieresis or umlaut mark */ 
                    100:        "\347", /* small c, cedilla */ 
                    101:        "\351", /* small e, acute accent */ 
                    102:        "\352", /* small e, circumflex accent */ 
                    103:        "\350", /* small e, grave accent */ 
                    104:        "\360", /* small eth, Icelandic */ 
                    105:        "\353", /* small e, dieresis or umlaut mark */ 
                    106:        "\076", /* greater than */ 
                    107:        "\355", /* small i, acute accent */ 
                    108:        "\356", /* small i, circumflex accent */ 
                    109:        "\354", /* small i, grave accent */ 
                    110:        "\357", /* small i, dieresis or umlaut mark */ 
                    111:        "\074", /* less than */ 
1.62      frystyk   112:        "\040", /* non-breaking space */
1.2       timbl     113:        "\361", /* small n, tilde */ 
                    114:        "\363", /* small o, acute accent */ 
                    115:        "\364", /* small o, circumflex accent */ 
                    116:        "\362", /* small o, grave accent */ 
                    117:        "\370", /* small o, slash */ 
                    118:        "\365", /* small o, tilde */ 
                    119:        "\366", /* small o, dieresis or umlaut mark */ 
1.36      frystyk   120:         "\042", /* double quote sign - June 94 */
1.2       timbl     121:        "\337", /* small sharp s, German (sz ligature) */ 
                    122:        "\376", /* small thorn, Icelandic */ 
                    123:        "\372", /* small u, acute accent */ 
                    124:        "\373", /* small u, circumflex accent */ 
                    125:        "\371", /* small u, grave accent */ 
                    126:        "\374", /* small u, dieresis or umlaut mark */ 
                    127:        "\375", /* small y, acute accent */ 
                    128:        "\377", /* small y, dieresis or umlaut mark */ 
1.1       timbl     129: };
                    130: 
1.75    ! frystyk   131: PRIVATE char ** CurrentEntityValues = ISO_Latin1;
1.2       timbl     132: 
1.75    ! frystyk   133: PUBLIC BOOL HTMLUseCharacterSet (HTMLCharacterSet i)
1.1       timbl     134: {
1.75    ! frystyk   135:     if (i == HTML_ISO_LATIN1) {
        !           136:        CurrentEntityValues = ISO_Latin1;
        !           137:        return YES;
1.1       timbl     138:     } else {
1.75    ! frystyk   139:        if (SGML_TRACE) HTTrace("HTML Parser. Doesn't support this character set\n");
        !           140:        return NO;
1.1       timbl     141:     }
                    142: }
                    143: 
1.75    ! frystyk   144: PRIVATE int HTML_write (HTStructured * me, const char * b, int l)
1.1       timbl     145: {
1.75    ! frystyk   146:     if (!me->started) {
        !           147:        HTextImp_build(me->text, HTEXT_BEGIN);
        !           148:        me->started = YES;
1.1       timbl     149:     }
                    150: 
1.75    ! frystyk   151:     /* Look at what we got */
        !           152:     switch (me->sp[0]) {
1.2       timbl     153: 
1.75    ! frystyk   154:     case HTML_COMMENT:
        !           155:        break;                                  /* Do Nothing */
        !           156:                
        !           157:     case HTML_TITLE:
        !           158:        HTChunk_putb(me->title, b, l);
        !           159:        /* Fall through */
1.71      frystyk   160:        
1.75    ! frystyk   161:     default:
        !           162:        HTextImp_addText(me->text, b, l);
1.71      frystyk   163:     }
1.42      frystyk   164:     return HT_OK;
1.1       timbl     165: }
                    166: 
1.71      frystyk   167: PRIVATE int HTML_put_character (HTStructured * me, char c)
1.1       timbl     168: {
1.71      frystyk   169:     return HTML_write(me, &c, sizeof(char));
1.1       timbl     170: }
                    171: 
1.64      frystyk   172: PRIVATE int HTML_put_string (HTStructured * me, const char* s)
1.1       timbl     173: {
1.71      frystyk   174:     return HTML_write(me, s, (int) strlen(s));
1.1       timbl     175: }
1.2       timbl     176: 
1.75    ! frystyk   177: PRIVATE void HTML_start_element (HTStructured *        me,
        !           178:                                 int            element_number,
        !           179:                                 const BOOL *   present,
        !           180:                                 const char **  value)
        !           181: {
        !           182:     HTChildAnchor * address = NULL;
        !           183:     if (!me->started) {
        !           184:        HTextImp_build(me->text, HTEXT_BEGIN);
        !           185:        me->started = YES;
1.73      frystyk   186:     }
                    187: 
1.75    ! frystyk   188:     /* Look at what element was started */
        !           189:     switch (element_number) {
1.2       timbl     190:     case HTML_A:
1.75    ! frystyk   191:        if (present[HTML_A_HREF] && value[HTML_A_HREF]) {
        !           192:            address = HTAnchor_findChildAndLink(
        !           193:                me->node_anchor,                                        /* parent */
        !           194:                present[HTML_A_NAME] ? value[HTML_A_NAME] : NULL,       /* Tag */
        !           195:                value[HTML_A_HREF],                                     /* Addresss */
        !           196:                present[HTML_A_REL] && value[HTML_A_REL] ? 
        !           197:                (HTLinkType) HTAtom_caseFor(value[HTML_A_REL]) : NULL);
1.2       timbl     198:            
1.75    ! frystyk   199:            if (present[HTML_A_TITLE] && value[HTML_A_TITLE]) {
        !           200:                HTLink * link = HTAnchor_mainLink((HTAnchor *) address);
        !           201:                HTParentAnchor * dest = HTAnchor_parent(HTLink_destination(link));
        !           202:                if (!HTAnchor_title(dest)) HTAnchor_setTitle(dest, value[HTML_A_TITLE]);
        !           203:            }
        !           204:            HTextImp_foundLink(me->text, element_number, HTML_A_HREF,
        !           205:                               address, present, value);
        !           206:            if (SGML_TRACE)
        !           207:                HTTrace("HTML Parser. Anchor `%s\'\n", value[HTML_A_HREF]);
        !           208:        }
        !           209:        break;
        !           210: 
        !           211:     case HTML_AREA:
        !           212:        if (present[HTML_AREA_HREF] && value[HTML_AREA_HREF]) {
        !           213:            address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
        !           214:                                                value[HTML_AREA_HREF], NULL);
        !           215:            HTextImp_foundLink(me->text, element_number, HTML_AREA_HREF,
        !           216:                               address, present, value);
        !           217:            if (SGML_TRACE)
        !           218:                HTTrace("HTML Parser. Image map area `%s\'\n", value[HTML_AREA_HREF]);
1.2       timbl     219:        }
1.75    ! frystyk   220:        break;
        !           221: 
        !           222:     case HTML_BASE:
        !           223:        if (present[HTML_BASE_HREF] && value[HTML_BASE_HREF]) {
        !           224:            HTAnchor_setBase(me->node_anchor, (char *) value[HTML_BASE_HREF]);
        !           225:            if (SGML_TRACE)
        !           226:                HTTrace("HTML Parser. New base `%s\'\n", value[HTML_BASE_HREF]);
        !           227:        }
        !           228:        break;
        !           229: 
        !           230:     case HTML_BODY:
        !           231:        if (present[HTML_BODY_BACKGROUND] && value[HTML_BODY_BACKGROUND]) {
        !           232:            address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
        !           233:                                                value[HTML_BODY_BACKGROUND], NULL);
        !           234:            HTextImp_foundLink(me->text, element_number, HTML_BODY_BACKGROUND,
        !           235:                               address, present, value);
        !           236:            if (SGML_TRACE)
        !           237:                HTTrace("HTML Parser. Background `%s\'\n", value[HTML_BODY_BACKGROUND]);
        !           238:        }
        !           239:        break;
        !           240: 
        !           241:     case HTML_FRAME:
        !           242:        if (present[HTML_FRAME_SRC] && value[HTML_FRAME_SRC]) {
        !           243:            address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
        !           244:                                                value[HTML_FRAME_SRC], NULL);
        !           245:            HTextImp_foundLink(me->text, element_number, HTML_FRAME_SRC,
        !           246:                               address, present, value);
        !           247:            if (SGML_TRACE)
        !           248:                HTTrace("HTML Parser. Frame `%s\'\n", value[HTML_FRAME_SRC]);
        !           249:        }
        !           250:        break;
        !           251:        
        !           252:     case HTML_IMG:
        !           253:        if (present[HTML_IMG_SRC] && value[HTML_IMG_SRC]) {
        !           254:            address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
        !           255:                                                value[HTML_IMG_SRC], NULL);
        !           256:            HTextImp_foundLink(me->text, element_number, HTML_IMG_SRC,
        !           257:                               address, present, value);
        !           258:        }
        !           259:        break;
        !           260: 
        !           261:     case HTML_ISINDEX:
        !           262:        HTAnchor_setIndex(me->node_anchor);
        !           263:        break;
1.2       timbl     264:        
1.63      frystyk   265:     case HTML_LINK:
1.69      frystyk   266:        if (present[HTML_LINK_HREF] && value[HTML_LINK_HREF]) {
1.75    ! frystyk   267:            HTParentAnchor * dest = NULL;
        !           268:            address = HTAnchor_findChildAndLink(
1.73      frystyk   269:                me->node_anchor,                                        /* parent */
                    270:                present[HTML_A_NAME] ? value[HTML_A_NAME] : NULL,       /* Tag */
                    271:                present[HTML_A_HREF] ? value[HTML_A_HREF] : NULL,       /* Addresss */
                    272:                NULL);                                                  /* Rels */
1.75    ! frystyk   273:            dest = HTAnchor_parent(HTAnchor_followMainLink((HTAnchor *) address));
1.69      frystyk   274: 
                    275:            /* If forward reference */
                    276:            if ((present[HTML_LINK_REL] && value[HTML_LINK_REL])) {
                    277:                char * strval = NULL;
                    278:                char * ptr = NULL;
                    279:                char * relation = NULL;
                    280:                StrAllocCopy(strval, value[HTML_LINK_REL]);
                    281:                ptr = strval;
                    282:                while ((relation = HTNextLWSToken(&ptr)) != NULL) {
                    283:                    HTLink_add((HTAnchor *) me->node_anchor, (HTAnchor *) dest,
                    284:                               (HTLinkType) HTAtom_caseFor(relation),
                    285:                               METHOD_INVALID);
                    286:                }
                    287:                HT_FREE(strval);
                    288:            }
                    289: 
                    290:            /* If reverse reference */
                    291:            if ((present[HTML_LINK_REV] && value[HTML_LINK_REV])) {
                    292:                char * strval = NULL;
                    293:                char * ptr = NULL;
                    294:                char * relation = NULL;
                    295:                StrAllocCopy(strval, value[HTML_LINK_REV]);
                    296:                ptr = strval;
                    297:                while ((relation = HTNextLWSToken(&ptr)) != NULL) {
                    298:                    HTLink_add((HTAnchor *) dest, (HTAnchor *) me->node_anchor,
                    299:                               (HTLinkType) HTAtom_caseFor(relation),
                    300:                               METHOD_INVALID);
                    301:                }
                    302:                HT_FREE(strval);
                    303:            }
1.63      frystyk   304: 
1.69      frystyk   305:            /* If we got any type information as well */
                    306:            if (present[HTML_LINK_TYPE] && value[HTML_LINK_TYPE]) {
                    307:                if (HTAnchor_format(dest) == WWW_UNKNOWN)
                    308:                    HTAnchor_setFormat(dest,
                    309:                                       (HTFormat) HTAtom_caseFor(value[HTML_LINK_TYPE]));
                    310:            }
1.63      frystyk   311: 
1.75    ! frystyk   312:            /* Call out to the layout engine */
        !           313:            HTextImp_foundLink(me->text, element_number, HTML_LINK_HREF,
        !           314:                               address, present, value);
1.70      frystyk   315:        }
1.75    ! frystyk   316:        break;
1.70      frystyk   317: 
                    318:     case HTML_META:
                    319:        if (present[HTML_META_NAME] && value[HTML_META_NAME]) {
                    320:            HTAnchor_addMeta (me->node_anchor,
                    321:                              value[HTML_META_NAME],
                    322:                              (present[HTML_META_CONTENT] && value[HTML_META_CONTENT]) ?
                    323:                              value[HTML_META_CONTENT] : "");
1.69      frystyk   324:        }
1.75    ! frystyk   325:        break;
        !           326: 
        !           327:     case HTML_OBJECT:
        !           328:        if (present[HTML_OBJECT_CLASSID] && value[HTML_OBJECT_CLASSID]) {
        !           329:            address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
        !           330:                                                value[HTML_OBJECT_CLASSID], NULL);
        !           331:            HTextImp_foundLink(me->text, element_number, HTML_OBJECT_CLASSID,
        !           332:                               address, present, value);
        !           333:        }
        !           334: 
        !           335:        if (present[HTML_OBJECT_CODEBASE] && value[HTML_OBJECT_CODEBASE]) {
        !           336:            address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
        !           337:                                                value[HTML_OBJECT_CODEBASE], NULL);
        !           338:            HTextImp_foundLink(me->text, element_number, HTML_OBJECT_CODEBASE,
        !           339:                               address, present, value);
        !           340:        }
        !           341: 
        !           342:        if (present[HTML_OBJECT_DATA] && value[HTML_OBJECT_DATA]) {
        !           343:            address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
        !           344:                                                value[HTML_OBJECT_DATA], NULL);
        !           345:            HTextImp_foundLink(me->text, element_number, HTML_OBJECT_DATA,
        !           346:                               address, present, value);
        !           347:        }
1.63      frystyk   348: 
1.75    ! frystyk   349:        if (present[HTML_OBJECT_ARCHIVE] && value[HTML_OBJECT_ARCHIVE]) {
        !           350:            address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
        !           351:                                                value[HTML_OBJECT_ARCHIVE], NULL);
        !           352:            HTextImp_foundLink(me->text, element_number, HTML_OBJECT_ARCHIVE,
        !           353:                               address, present, value);
        !           354:        }
1.2       timbl     355: 
1.75    ! frystyk   356:        if (present[HTML_OBJECT_USEMAP] && value[HTML_OBJECT_USEMAP]) {
        !           357:            address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
        !           358:                                                value[HTML_OBJECT_USEMAP], NULL);
        !           359:            HTextImp_foundLink(me->text, element_number, HTML_OBJECT_USEMAP,
        !           360:                               address, present, value);
1.2       timbl     361:        }
                    362:        break;
                    363: 
                    364:     case HTML_PRE:
1.4       timbl     365:        if (me->comment_end)
1.75    ! frystyk   366:            HTextImp_addText(me->text, me->comment_end, strlen(me->comment_end));
1.2       timbl     367:        break;
1.11      timbl     368: 
1.75    ! frystyk   369:     case HTML_TITLE:
        !           370:         HTChunk_clear(me->title);
1.2       timbl     371:        break;
1.75    ! frystyk   372:     }
1.2       timbl     373: 
1.75    ! frystyk   374:     /* Update our parse stack */
        !           375:     if (SGML_findTagContents(me->dtd, element_number) != SGML_EMPTY) {
1.13      timbl     376:         if (me->sp == me->stack) {
1.44      frystyk   377:            if (SGML_TRACE)
1.75    ! frystyk   378:                HTTrace("HTML Parser. Maximum nesting of %d exceded!\n", MAX_NESTING); 
1.44      frystyk   379:            me->overflow++;
1.12      timbl     380:            return;
                    381:        }
1.4       timbl     382:        --(me->sp);
1.75    ! frystyk   383:        me->sp[0] = element_number;
1.10      timbl     384:     }  
1.75    ! frystyk   385: 
        !           386:     /* Call out to the layout engine */
        !           387:     HTextImp_beginElement(me->text, element_number, present, value);
1.1       timbl     388: }
1.10      timbl     389: 
1.53      frystyk   390: PRIVATE void HTML_end_element (HTStructured * me, int element_number)
1.1       timbl     391: {
1.75    ! frystyk   392:     if (!me->started) {
        !           393:        HTextImp_build(me->text, HTEXT_BEGIN);
        !           394:        me->started = YES;
1.1       timbl     395:     }
1.44      frystyk   396: 
1.75    ! frystyk   397:     /* Update our parse stack */
1.44      frystyk   398:     if (me->overflow > 0) {
                    399:        me->overflow--;
                    400:        return;
                    401:     }
1.75    ! frystyk   402:     me->sp++;
1.67      frystyk   403:     if (me->sp > me->stack + MAX_NESTING - 1) {
1.75    ! frystyk   404:        if (SGML_TRACE) HTTrace("HTML Parser. Bottom of parse stack reached\n");
1.67      frystyk   405:        me->sp = me->stack + MAX_NESTING - 1;
                    406:     }
1.44      frystyk   407: 
1.75    ! frystyk   408:     /* Look at what element was closed */
1.2       timbl     409:     switch(element_number) {
                    410:     case HTML_TITLE:
1.56      frystyk   411:        HTAnchor_setTitle(me->node_anchor, HTChunk_data(me->title));
1.2       timbl     412:        break;
                    413:        
                    414:     case HTML_PRE:
1.4       timbl     415:        if (me->comment_start)
1.75    ! frystyk   416:            HTextImp_addText(me->text, me->comment_start, strlen(me->comment_start));
        !           417:        break;
        !           418:     }
1.44      frystyk   419: 
1.75    ! frystyk   420:     /* Call out to the layout engine */
        !           421:     HTextImp_endElement(me->text, element_number);
1.1       timbl     422: }
                    423: 
1.53      frystyk   424: PRIVATE void HTML_put_entity (HTStructured * me, int entity_number)
1.1       timbl     425: {
1.75    ! frystyk   426:     if (!me->started) {
        !           427:        HTextImp_build(me->text, HTEXT_BEGIN);
        !           428:        me->started = YES;
        !           429:     }
        !           430:     if (entity_number>=0 && entity_number<ENTITY_SIZE)
        !           431:        HTML_put_string(me, *(CurrentEntityValues+entity_number));
1.1       timbl     432: }
1.2       timbl     433: 
1.53      frystyk   434: PUBLIC int HTML_flush (HTStructured * me)
1.42      frystyk   435: {
1.75    ! frystyk   436:     if (!me->started) {
        !           437:        HTextImp_build(me->text, HTEXT_BEGIN);
        !           438:        me->started = YES;
        !           439:     }
        !           440:     if (me->comment_end) HTML_put_string(me, me->comment_end);
        !           441:     return me->target ? FLUSH_TARGET(me) : HT_OK;
        !           442: }
        !           443: 
        !           444: PRIVATE int HTML_unparsedBeginElement (HTStructured * me, const char * b, int l)
        !           445: {
        !           446:     if (!me->started) {
        !           447:        HTextImp_build(me->text, HTEXT_BEGIN);
        !           448:        me->started = YES;
        !           449:     }
        !           450:     HTextImp_unparsedBeginElement(me->text, b, l);
        !           451:     return HT_OK;
1.42      frystyk   452: }
1.2       timbl     453: 
1.75    ! frystyk   454: PRIVATE int HTML_unparsedEndElement (HTStructured * me, const char * b, int l)
1.1       timbl     455: {
1.75    ! frystyk   456:     if (!me->started) {
        !           457:        HTextImp_build(me->text, HTEXT_BEGIN);
        !           458:        me->started = YES;
        !           459:     }
        !           460:     HTextImp_unparsedEndElement(me->text, b, l);
        !           461:     return HT_OK;
        !           462: }
1.4       timbl     463: 
1.75    ! frystyk   464: PRIVATE int HTML_unparsedEntity (HTStructured * me, const char * b, int l)
        !           465: {
        !           466:     if (!me->started) {
        !           467:        HTextImp_build(me->text, HTEXT_BEGIN);
        !           468:        me->started = YES;
1.2       timbl     469:     }
1.75    ! frystyk   470:     HTextImp_unparsedEntity(me->text, b, l);
        !           471:     return HT_OK;
        !           472: }
        !           473: 
        !           474: PUBLIC int HTML_free (HTStructured * me)
        !           475: {
        !           476:     if (!me->started) HTextImp_build(me->text, HTEXT_BEGIN);
        !           477:     if (me->comment_end) HTML_put_string(me, me->comment_end);
        !           478:     HTextImp_build(me->text, HTEXT_END);
1.56      frystyk   479:     HTChunk_delete(me->title);
1.75    ! frystyk   480:     if (me->target) FREE_TARGET(me);
1.58      frystyk   481:     HT_FREE(me);
1.42      frystyk   482:     return HT_OK;
1.1       timbl     483: }
                    484: 
1.53      frystyk   485: PRIVATE int HTML_abort (HTStructured * me, HTList * e)
1.14      timbl     486: {
1.75    ! frystyk   487:     if (!me->started) HTextImp_build(me->text, HTEXT_BEGIN);
        !           488:     HTextImp_build(me->text, HTEXT_ABORT);
1.56      frystyk   489:     HTChunk_delete(me->title);
1.75    ! frystyk   490:     if (me->target) ABORT_TARGET(me);
1.58      frystyk   491:     HT_FREE(me);
1.42      frystyk   492:     return HT_ERROR;
1.1       timbl     493: }
                    494: 
1.2       timbl     495: /*     Structured Object Class
                    496: **     -----------------------
                    497: */
1.60      frystyk   498: PRIVATE const HTStructuredClass HTMLPresentation = /* As opposed to print etc */
1.2       timbl     499: {              
1.75    ! frystyk   500:     "text/html",
        !           501:     HTML_flush,
        !           502:     HTML_free,
        !           503:     HTML_abort,
        !           504:     HTML_put_character,
        !           505:     HTML_put_string,
        !           506:     HTML_write,
        !           507:     HTML_start_element,
        !           508:     HTML_end_element,
        !           509:     HTML_put_entity,
        !           510:     HTML_unparsedBeginElement,
        !           511:     HTML_unparsedEndElement,
        !           512:     HTML_unparsedEntity
        !           513: };
1.4       timbl     514: 
1.75    ! frystyk   515: /*     Structured Text object
        !           516: **     ----------------------
1.2       timbl     517: **
1.16      timbl     518: **     The structured stream can generate either presentation,
1.4       timbl     519: **     or plain text, or HTML.
1.1       timbl     520: */
1.75    ! frystyk   521: PRIVATE HTStructured * HTML_new (HTRequest *   request,
        !           522:                                 void *         param,
        !           523:                                 HTFormat       input_format,
        !           524:                                 HTFormat       output_format,
        !           525:                                 HTStream *     output_stream)
        !           526: {
        !           527:     HTStructured * me = NULL;
        !           528:     if (request) {
        !           529:        if ((me = (HTStructured *) HT_CALLOC(1, sizeof(HTStructured))) == NULL)
        !           530:            HT_OUTOFMEM("HTML_new");
        !           531:        me->isa = &HTMLPresentation;
        !           532:        me->dtd = HTML_dtd();
        !           533:        me->request = request;
        !           534:        me->node_anchor =  HTRequest_anchor(request);
        !           535:        me->title = HTChunk_new(128);
        !           536:        me->comment_start = NULL;
        !           537:        me->comment_end = NULL;
        !           538:        me->target = output_stream;
        !           539:        me->sp = me->stack + MAX_NESTING - 1;
        !           540: 
        !           541:        /* Create the text object */
        !           542:        me->text = HTextImp_new(me->request, me->node_anchor, me->target);
        !           543:     }
        !           544:     return me;
1.1       timbl     545: }
                    546: 
1.2       timbl     547: /*     HTConverter for HTML to plain text
                    548: **     ----------------------------------
1.1       timbl     549: **
1.2       timbl     550: **     This will convert from HTML to presentation or plain text.
1.1       timbl     551: */
1.75    ! frystyk   552: PUBLIC HTStream * HTMLToPlain (HTRequest *     request,
        !           553:                               void *           param,
        !           554:                               HTFormat         input_format,
        !           555:                               HTFormat         output_format,
        !           556:                               HTStream *       output_stream)
1.1       timbl     557: {
1.75    ! frystyk   558:     return SGML_new(HTML_dtd(), HTML_new(
1.16      timbl     559:        request, NULL, input_format, output_format, output_stream));
1.1       timbl     560: }
                    561: 
                    562: 
1.2       timbl     563: /*     HTConverter for HTML to C code
                    564: **     ------------------------------
                    565: **
1.36      frystyk   566: **     C code is like plain text but all non-preformatted code
1.2       timbl     567: **     is commented out.
                    568: **     This will convert from HTML to presentation or plain text.
                    569: */
1.75    ! frystyk   570: PUBLIC HTStream * HTMLToC (HTRequest * request,
        !           571:                           void *       param,
        !           572:                           HTFormat     input_format,
        !           573:                           HTFormat     output_format,
        !           574:                           HTStream *   output_stream)
        !           575: {
        !           576:     if (output_stream) {
        !           577:        HTStructured * html = NULL;
        !           578:        (*output_stream->isa->put_string)(output_stream, "/* "); /* Before title */
        !           579:        html = HTML_new(request, NULL, input_format, output_format, output_stream);
        !           580:        html->comment_start = "\n/* ";
        !           581:        html->dtd = HTML_dtd();
        !           582:        html->comment_end = " */\n";    /* Must start in col 1 for cpp */
        !           583:        return SGML_new(HTML_dtd(), html);
        !           584:     } else
        !           585:        return HTErrorStream();
1.1       timbl     586: }
                    587: 
                    588: 
1.2       timbl     589: /*     Presenter for HTML
                    590: **     ------------------
                    591: **
                    592: **     This will convert from HTML to presentation or plain text.
                    593: **
                    594: **     Override this if you have a windows version
1.1       timbl     595: */
1.75    ! frystyk   596: PUBLIC HTStream * HTMLPresent (HTRequest *     request,
        !           597:                               void *           param,
        !           598:                               HTFormat         input_format,
        !           599:                               HTFormat         output_format,
        !           600:                               HTStream *       output_stream)
1.1       timbl     601: {
1.75    ! frystyk   602:     return SGML_new(HTML_dtd(), HTML_new(
1.16      timbl     603:        request, NULL, input_format, output_format, output_stream));
1.1       timbl     604: }
1.29      frystyk   605: 

Webmaster