Annotation of libwww/Library/src/HTML.c, revision 1.79
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.79 ! frystyk 6: ** @(#) $Id: HTML.c,v 1.78 1999/02/22 22:10:11 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.78 frystyk 139: HTTRACE(SGML_TRACE, "HTML Parser. Doesn't support this character set\n");
1.75 frystyk 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_TITLE:
155: HTChunk_putb(me->title, b, l);
156: /* Fall through */
1.71 frystyk 157:
1.75 frystyk 158: default:
159: HTextImp_addText(me->text, b, l);
1.71 frystyk 160: }
1.42 frystyk 161: return HT_OK;
1.1 timbl 162: }
163:
1.71 frystyk 164: PRIVATE int HTML_put_character (HTStructured * me, char c)
1.1 timbl 165: {
1.71 frystyk 166: return HTML_write(me, &c, sizeof(char));
1.1 timbl 167: }
168:
1.64 frystyk 169: PRIVATE int HTML_put_string (HTStructured * me, const char* s)
1.1 timbl 170: {
1.71 frystyk 171: return HTML_write(me, s, (int) strlen(s));
1.1 timbl 172: }
1.2 timbl 173:
1.75 frystyk 174: PRIVATE void HTML_start_element (HTStructured * me,
175: int element_number,
176: const BOOL * present,
177: const char ** value)
178: {
179: HTChildAnchor * address = NULL;
180: if (!me->started) {
181: HTextImp_build(me->text, HTEXT_BEGIN);
182: me->started = YES;
1.73 frystyk 183: }
184:
1.75 frystyk 185: /* Look at what element was started */
186: switch (element_number) {
1.2 timbl 187: case HTML_A:
1.75 frystyk 188: if (present[HTML_A_HREF] && value[HTML_A_HREF]) {
189: address = HTAnchor_findChildAndLink(
190: me->node_anchor, /* parent */
191: present[HTML_A_NAME] ? value[HTML_A_NAME] : NULL, /* Tag */
192: value[HTML_A_HREF], /* Addresss */
193: present[HTML_A_REL] && value[HTML_A_REL] ?
194: (HTLinkType) HTAtom_caseFor(value[HTML_A_REL]) : NULL);
1.2 timbl 195:
1.75 frystyk 196: if (present[HTML_A_TITLE] && value[HTML_A_TITLE]) {
197: HTLink * link = HTAnchor_mainLink((HTAnchor *) address);
198: HTParentAnchor * dest = HTAnchor_parent(HTLink_destination(link));
199: if (!HTAnchor_title(dest)) HTAnchor_setTitle(dest, value[HTML_A_TITLE]);
200: }
201: HTextImp_foundLink(me->text, element_number, HTML_A_HREF,
202: address, present, value);
1.78 frystyk 203: HTTRACE(SGML_TRACE, "HTML Parser. Anchor `%s\'\n" _ value[HTML_A_HREF]);
1.75 frystyk 204: }
205: break;
206:
207: case HTML_AREA:
208: if (present[HTML_AREA_HREF] && value[HTML_AREA_HREF]) {
209: address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
210: value[HTML_AREA_HREF], NULL);
211: HTextImp_foundLink(me->text, element_number, HTML_AREA_HREF,
212: address, present, value);
1.78 frystyk 213: HTTRACE(SGML_TRACE, "HTML Parser. Image map area `%s\'\n" _ value[HTML_AREA_HREF]);
1.2 timbl 214: }
1.75 frystyk 215: break;
216:
217: case HTML_BASE:
218: if (present[HTML_BASE_HREF] && value[HTML_BASE_HREF]) {
219: HTAnchor_setBase(me->node_anchor, (char *) value[HTML_BASE_HREF]);
1.78 frystyk 220: HTTRACE(SGML_TRACE, "HTML Parser. New base `%s\'\n" _ value[HTML_BASE_HREF]);
1.75 frystyk 221: }
222: break;
223:
224: case HTML_BODY:
225: if (present[HTML_BODY_BACKGROUND] && value[HTML_BODY_BACKGROUND]) {
226: address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
227: value[HTML_BODY_BACKGROUND], NULL);
228: HTextImp_foundLink(me->text, element_number, HTML_BODY_BACKGROUND,
229: address, present, value);
1.78 frystyk 230: HTTRACE(SGML_TRACE, "HTML Parser. Background `%s\'\n" _ value[HTML_BODY_BACKGROUND]);
1.75 frystyk 231: }
232: break;
233:
1.77 frystyk 234: case HTML_FORM:
235: if (present[HTML_FORM_ACTION] && value[HTML_FORM_ACTION]) {
236: address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
237: value[HTML_FORM_ACTION], NULL);
238: HTextImp_foundLink(me->text, element_number, HTML_FORM_ACTION,
239: address, present, value);
240: }
241: break;
242:
1.75 frystyk 243: case HTML_FRAME:
244: if (present[HTML_FRAME_SRC] && value[HTML_FRAME_SRC]) {
245: address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
246: value[HTML_FRAME_SRC], NULL);
247: HTextImp_foundLink(me->text, element_number, HTML_FRAME_SRC,
248: address, present, value);
1.78 frystyk 249: HTTRACE(SGML_TRACE, "HTML Parser. Frame `%s\'\n" _ value[HTML_FRAME_SRC]);
1.75 frystyk 250: }
251: break;
252:
1.77 frystyk 253: case HTML_INPUT:
254: if (present[HTML_INPUT_SRC] && value[HTML_INPUT_SRC]) {
255: address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
256: value[HTML_INPUT_SRC], NULL);
257: HTextImp_foundLink(me->text, element_number, HTML_INPUT_SRC,
258: address, present, value);
259: }
260: break;
261:
1.75 frystyk 262: case HTML_IMG:
263: if (present[HTML_IMG_SRC] && value[HTML_IMG_SRC]) {
264: address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
265: value[HTML_IMG_SRC], NULL);
266: HTextImp_foundLink(me->text, element_number, HTML_IMG_SRC,
267: address, present, value);
268: }
269: break;
270:
271: case HTML_ISINDEX:
272: HTAnchor_setIndex(me->node_anchor);
273: break;
1.2 timbl 274:
1.63 frystyk 275: case HTML_LINK:
1.69 frystyk 276: if (present[HTML_LINK_HREF] && value[HTML_LINK_HREF]) {
1.75 frystyk 277: HTParentAnchor * dest = NULL;
278: address = HTAnchor_findChildAndLink(
1.73 frystyk 279: me->node_anchor, /* parent */
280: present[HTML_A_NAME] ? value[HTML_A_NAME] : NULL, /* Tag */
281: present[HTML_A_HREF] ? value[HTML_A_HREF] : NULL, /* Addresss */
282: NULL); /* Rels */
1.75 frystyk 283: dest = HTAnchor_parent(HTAnchor_followMainLink((HTAnchor *) address));
1.69 frystyk 284:
285: /* If forward reference */
286: if ((present[HTML_LINK_REL] && value[HTML_LINK_REL])) {
287: char * strval = NULL;
288: char * ptr = NULL;
289: char * relation = NULL;
290: StrAllocCopy(strval, value[HTML_LINK_REL]);
291: ptr = strval;
292: while ((relation = HTNextLWSToken(&ptr)) != NULL) {
293: HTLink_add((HTAnchor *) me->node_anchor, (HTAnchor *) dest,
294: (HTLinkType) HTAtom_caseFor(relation),
295: METHOD_INVALID);
296: }
297: HT_FREE(strval);
298: }
299:
300: /* If reverse reference */
301: if ((present[HTML_LINK_REV] && value[HTML_LINK_REV])) {
302: char * strval = NULL;
303: char * ptr = NULL;
304: char * relation = NULL;
305: StrAllocCopy(strval, value[HTML_LINK_REV]);
306: ptr = strval;
307: while ((relation = HTNextLWSToken(&ptr)) != NULL) {
308: HTLink_add((HTAnchor *) dest, (HTAnchor *) me->node_anchor,
309: (HTLinkType) HTAtom_caseFor(relation),
310: METHOD_INVALID);
311: }
312: HT_FREE(strval);
313: }
1.63 frystyk 314:
1.69 frystyk 315: /* If we got any type information as well */
316: if (present[HTML_LINK_TYPE] && value[HTML_LINK_TYPE]) {
317: if (HTAnchor_format(dest) == WWW_UNKNOWN)
318: HTAnchor_setFormat(dest,
319: (HTFormat) HTAtom_caseFor(value[HTML_LINK_TYPE]));
320: }
1.63 frystyk 321:
1.75 frystyk 322: /* Call out to the layout engine */
323: HTextImp_foundLink(me->text, element_number, HTML_LINK_HREF,
324: address, present, value);
1.70 frystyk 325: }
1.75 frystyk 326: break;
1.70 frystyk 327:
328: case HTML_META:
329: if (present[HTML_META_NAME] && value[HTML_META_NAME]) {
330: HTAnchor_addMeta (me->node_anchor,
331: value[HTML_META_NAME],
332: (present[HTML_META_CONTENT] && value[HTML_META_CONTENT]) ?
333: value[HTML_META_CONTENT] : "");
1.69 frystyk 334: }
1.75 frystyk 335: break;
336:
337: case HTML_OBJECT:
338: if (present[HTML_OBJECT_CLASSID] && value[HTML_OBJECT_CLASSID]) {
339: address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
340: value[HTML_OBJECT_CLASSID], NULL);
341: HTextImp_foundLink(me->text, element_number, HTML_OBJECT_CLASSID,
342: address, present, value);
343: }
344:
345: if (present[HTML_OBJECT_CODEBASE] && value[HTML_OBJECT_CODEBASE]) {
346: address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
347: value[HTML_OBJECT_CODEBASE], NULL);
348: HTextImp_foundLink(me->text, element_number, HTML_OBJECT_CODEBASE,
349: address, present, value);
350: }
351:
352: if (present[HTML_OBJECT_DATA] && value[HTML_OBJECT_DATA]) {
353: address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
354: value[HTML_OBJECT_DATA], NULL);
355: HTextImp_foundLink(me->text, element_number, HTML_OBJECT_DATA,
356: address, present, value);
357: }
1.63 frystyk 358:
1.75 frystyk 359: if (present[HTML_OBJECT_ARCHIVE] && value[HTML_OBJECT_ARCHIVE]) {
360: address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
361: value[HTML_OBJECT_ARCHIVE], NULL);
362: HTextImp_foundLink(me->text, element_number, HTML_OBJECT_ARCHIVE,
363: address, present, value);
364: }
1.2 timbl 365:
1.75 frystyk 366: if (present[HTML_OBJECT_USEMAP] && value[HTML_OBJECT_USEMAP]) {
367: address = HTAnchor_findChildAndLink(me->node_anchor, NULL,
368: value[HTML_OBJECT_USEMAP], NULL);
369: HTextImp_foundLink(me->text, element_number, HTML_OBJECT_USEMAP,
370: address, present, value);
1.2 timbl 371: }
372: break;
373:
374: case HTML_PRE:
1.4 timbl 375: if (me->comment_end)
1.75 frystyk 376: HTextImp_addText(me->text, me->comment_end, strlen(me->comment_end));
1.2 timbl 377: break;
1.11 timbl 378:
1.75 frystyk 379: case HTML_TITLE:
380: HTChunk_clear(me->title);
1.2 timbl 381: break;
1.75 frystyk 382: }
1.2 timbl 383:
1.75 frystyk 384: /* Update our parse stack */
385: if (SGML_findTagContents(me->dtd, element_number) != SGML_EMPTY) {
1.13 timbl 386: if (me->sp == me->stack) {
1.78 frystyk 387: HTTRACE(SGML_TRACE, "HTML Parser. Maximum nesting of %d exceded!\n" _ MAX_NESTING);
1.44 frystyk 388: me->overflow++;
1.12 timbl 389: return;
390: }
1.4 timbl 391: --(me->sp);
1.75 frystyk 392: me->sp[0] = element_number;
1.10 timbl 393: }
1.75 frystyk 394:
395: /* Call out to the layout engine */
396: HTextImp_beginElement(me->text, element_number, present, value);
1.1 timbl 397: }
1.10 timbl 398:
1.53 frystyk 399: PRIVATE void HTML_end_element (HTStructured * me, int element_number)
1.1 timbl 400: {
1.75 frystyk 401: if (!me->started) {
402: HTextImp_build(me->text, HTEXT_BEGIN);
403: me->started = YES;
1.1 timbl 404: }
1.44 frystyk 405:
1.75 frystyk 406: /* Update our parse stack */
1.44 frystyk 407: if (me->overflow > 0) {
408: me->overflow--;
409: return;
410: }
1.75 frystyk 411: me->sp++;
1.67 frystyk 412: if (me->sp > me->stack + MAX_NESTING - 1) {
1.78 frystyk 413: HTTRACE(SGML_TRACE, "HTML Parser. Bottom of parse stack reached\n");
1.67 frystyk 414: me->sp = me->stack + MAX_NESTING - 1;
415: }
1.44 frystyk 416:
1.75 frystyk 417: /* Look at what element was closed */
1.2 timbl 418: switch(element_number) {
419: case HTML_TITLE:
1.56 frystyk 420: HTAnchor_setTitle(me->node_anchor, HTChunk_data(me->title));
1.2 timbl 421: break;
422:
423: case HTML_PRE:
1.4 timbl 424: if (me->comment_start)
1.75 frystyk 425: HTextImp_addText(me->text, me->comment_start, strlen(me->comment_start));
426: break;
427: }
1.44 frystyk 428:
1.75 frystyk 429: /* Call out to the layout engine */
430: HTextImp_endElement(me->text, element_number);
1.1 timbl 431: }
432:
1.53 frystyk 433: PRIVATE void HTML_put_entity (HTStructured * me, int entity_number)
1.1 timbl 434: {
1.75 frystyk 435: if (!me->started) {
436: HTextImp_build(me->text, HTEXT_BEGIN);
437: me->started = YES;
438: }
439: if (entity_number>=0 && entity_number<ENTITY_SIZE)
440: HTML_put_string(me, *(CurrentEntityValues+entity_number));
1.1 timbl 441: }
1.2 timbl 442:
1.53 frystyk 443: PUBLIC int HTML_flush (HTStructured * me)
1.42 frystyk 444: {
1.75 frystyk 445: if (!me->started) {
446: HTextImp_build(me->text, HTEXT_BEGIN);
447: me->started = YES;
448: }
449: if (me->comment_end) HTML_put_string(me, me->comment_end);
450: return me->target ? FLUSH_TARGET(me) : HT_OK;
451: }
452:
453: PRIVATE int HTML_unparsedBeginElement (HTStructured * me, const char * b, int l)
454: {
455: if (!me->started) {
456: HTextImp_build(me->text, HTEXT_BEGIN);
457: me->started = YES;
458: }
459: HTextImp_unparsedBeginElement(me->text, b, l);
460: return HT_OK;
1.42 frystyk 461: }
1.2 timbl 462:
1.75 frystyk 463: PRIVATE int HTML_unparsedEndElement (HTStructured * me, const char * b, int l)
1.1 timbl 464: {
1.75 frystyk 465: if (!me->started) {
466: HTextImp_build(me->text, HTEXT_BEGIN);
467: me->started = YES;
468: }
469: HTextImp_unparsedEndElement(me->text, b, l);
470: return HT_OK;
471: }
1.4 timbl 472:
1.75 frystyk 473: PRIVATE int HTML_unparsedEntity (HTStructured * me, const char * b, int l)
474: {
475: if (!me->started) {
476: HTextImp_build(me->text, HTEXT_BEGIN);
477: me->started = YES;
1.2 timbl 478: }
1.75 frystyk 479: HTextImp_unparsedEntity(me->text, b, l);
480: return HT_OK;
481: }
482:
483: PUBLIC int HTML_free (HTStructured * me)
484: {
485: if (!me->started) HTextImp_build(me->text, HTEXT_BEGIN);
486: if (me->comment_end) HTML_put_string(me, me->comment_end);
487: HTextImp_build(me->text, HTEXT_END);
1.76 frystyk 488: HTextImp_delete(me->text);
1.56 frystyk 489: HTChunk_delete(me->title);
1.75 frystyk 490: if (me->target) FREE_TARGET(me);
1.58 frystyk 491: HT_FREE(me);
1.42 frystyk 492: return HT_OK;
1.1 timbl 493: }
494:
1.53 frystyk 495: PRIVATE int HTML_abort (HTStructured * me, HTList * e)
1.14 timbl 496: {
1.75 frystyk 497: if (!me->started) HTextImp_build(me->text, HTEXT_BEGIN);
498: HTextImp_build(me->text, HTEXT_ABORT);
1.76 frystyk 499: HTextImp_delete(me->text);
1.56 frystyk 500: HTChunk_delete(me->title);
1.75 frystyk 501: if (me->target) ABORT_TARGET(me);
1.58 frystyk 502: HT_FREE(me);
1.42 frystyk 503: return HT_ERROR;
1.1 timbl 504: }
505:
1.2 timbl 506: /* Structured Object Class
507: ** -----------------------
508: */
1.60 frystyk 509: PRIVATE const HTStructuredClass HTMLPresentation = /* As opposed to print etc */
1.2 timbl 510: {
1.75 frystyk 511: "text/html",
512: HTML_flush,
513: HTML_free,
514: HTML_abort,
515: HTML_put_character,
516: HTML_put_string,
517: HTML_write,
518: HTML_start_element,
519: HTML_end_element,
520: HTML_put_entity,
521: HTML_unparsedBeginElement,
522: HTML_unparsedEndElement,
523: HTML_unparsedEntity
524: };
1.4 timbl 525:
1.75 frystyk 526: /* Structured Text object
527: ** ----------------------
1.2 timbl 528: **
1.16 timbl 529: ** The structured stream can generate either presentation,
1.4 timbl 530: ** or plain text, or HTML.
1.1 timbl 531: */
1.75 frystyk 532: PRIVATE HTStructured * HTML_new (HTRequest * request,
533: void * param,
534: HTFormat input_format,
535: HTFormat output_format,
536: HTStream * output_stream)
537: {
538: HTStructured * me = NULL;
539: if (request) {
540: if ((me = (HTStructured *) HT_CALLOC(1, sizeof(HTStructured))) == NULL)
541: HT_OUTOFMEM("HTML_new");
542: me->isa = &HTMLPresentation;
543: me->dtd = HTML_dtd();
544: me->request = request;
545: me->node_anchor = HTRequest_anchor(request);
546: me->title = HTChunk_new(128);
547: me->comment_start = NULL;
548: me->comment_end = NULL;
549: me->target = output_stream;
550: me->sp = me->stack + MAX_NESTING - 1;
551:
552: /* Create the text object */
553: me->text = HTextImp_new(me->request, me->node_anchor, me->target);
554: }
555: return me;
1.1 timbl 556: }
557:
1.2 timbl 558: /* HTConverter for HTML to plain text
559: ** ----------------------------------
1.1 timbl 560: **
1.2 timbl 561: ** This will convert from HTML to presentation or plain text.
1.1 timbl 562: */
1.75 frystyk 563: PUBLIC HTStream * HTMLToPlain (HTRequest * request,
564: void * param,
565: HTFormat input_format,
566: HTFormat output_format,
567: HTStream * output_stream)
1.1 timbl 568: {
1.75 frystyk 569: return SGML_new(HTML_dtd(), HTML_new(
1.16 timbl 570: request, NULL, input_format, output_format, output_stream));
1.1 timbl 571: }
572:
573:
1.2 timbl 574: /* HTConverter for HTML to C code
575: ** ------------------------------
576: **
1.36 frystyk 577: ** C code is like plain text but all non-preformatted code
1.2 timbl 578: ** is commented out.
579: ** This will convert from HTML to presentation or plain text.
580: */
1.75 frystyk 581: PUBLIC HTStream * HTMLToC (HTRequest * request,
582: void * param,
583: HTFormat input_format,
584: HTFormat output_format,
585: HTStream * output_stream)
586: {
587: if (output_stream) {
588: HTStructured * html = NULL;
589: (*output_stream->isa->put_string)(output_stream, "/* "); /* Before title */
590: html = HTML_new(request, NULL, input_format, output_format, output_stream);
591: html->comment_start = "\n/* ";
592: html->dtd = HTML_dtd();
593: html->comment_end = " */\n"; /* Must start in col 1 for cpp */
594: return SGML_new(HTML_dtd(), html);
595: } else
596: return HTErrorStream();
1.1 timbl 597: }
598:
599:
1.2 timbl 600: /* Presenter for HTML
601: ** ------------------
602: **
603: ** This will convert from HTML to presentation or plain text.
604: **
605: ** Override this if you have a windows version
1.1 timbl 606: */
1.75 frystyk 607: PUBLIC HTStream * HTMLPresent (HTRequest * request,
608: void * param,
609: HTFormat input_format,
610: HTFormat output_format,
611: HTStream * output_stream)
1.1 timbl 612: {
1.75 frystyk 613: return SGML_new(HTML_dtd(), HTML_new(
1.16 timbl 614: request, NULL, input_format, output_format, output_stream));
1.1 timbl 615: }
1.29 frystyk 616:
Webmaster