Annotation of libwww/Library/src/HTML.c, revision 1.76
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.76 ! frystyk 6: ** @(#) $Id: HTML.c,v 1.75 1999/01/06 15:38:47 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.76 ! frystyk 479: HTextImp_delete(me->text);
1.56 frystyk 480: HTChunk_delete(me->title);
1.75 frystyk 481: if (me->target) FREE_TARGET(me);
1.58 frystyk 482: HT_FREE(me);
1.42 frystyk 483: return HT_OK;
1.1 timbl 484: }
485:
1.53 frystyk 486: PRIVATE int HTML_abort (HTStructured * me, HTList * e)
1.14 timbl 487: {
1.75 frystyk 488: if (!me->started) HTextImp_build(me->text, HTEXT_BEGIN);
489: HTextImp_build(me->text, HTEXT_ABORT);
1.76 ! frystyk 490: HTextImp_delete(me->text);
1.56 frystyk 491: HTChunk_delete(me->title);
1.75 frystyk 492: if (me->target) ABORT_TARGET(me);
1.58 frystyk 493: HT_FREE(me);
1.42 frystyk 494: return HT_ERROR;
1.1 timbl 495: }
496:
1.2 timbl 497: /* Structured Object Class
498: ** -----------------------
499: */
1.60 frystyk 500: PRIVATE const HTStructuredClass HTMLPresentation = /* As opposed to print etc */
1.2 timbl 501: {
1.75 frystyk 502: "text/html",
503: HTML_flush,
504: HTML_free,
505: HTML_abort,
506: HTML_put_character,
507: HTML_put_string,
508: HTML_write,
509: HTML_start_element,
510: HTML_end_element,
511: HTML_put_entity,
512: HTML_unparsedBeginElement,
513: HTML_unparsedEndElement,
514: HTML_unparsedEntity
515: };
1.4 timbl 516:
1.75 frystyk 517: /* Structured Text object
518: ** ----------------------
1.2 timbl 519: **
1.16 timbl 520: ** The structured stream can generate either presentation,
1.4 timbl 521: ** or plain text, or HTML.
1.1 timbl 522: */
1.75 frystyk 523: PRIVATE HTStructured * HTML_new (HTRequest * request,
524: void * param,
525: HTFormat input_format,
526: HTFormat output_format,
527: HTStream * output_stream)
528: {
529: HTStructured * me = NULL;
530: if (request) {
531: if ((me = (HTStructured *) HT_CALLOC(1, sizeof(HTStructured))) == NULL)
532: HT_OUTOFMEM("HTML_new");
533: me->isa = &HTMLPresentation;
534: me->dtd = HTML_dtd();
535: me->request = request;
536: me->node_anchor = HTRequest_anchor(request);
537: me->title = HTChunk_new(128);
538: me->comment_start = NULL;
539: me->comment_end = NULL;
540: me->target = output_stream;
541: me->sp = me->stack + MAX_NESTING - 1;
542:
543: /* Create the text object */
544: me->text = HTextImp_new(me->request, me->node_anchor, me->target);
545: }
546: return me;
1.1 timbl 547: }
548:
1.2 timbl 549: /* HTConverter for HTML to plain text
550: ** ----------------------------------
1.1 timbl 551: **
1.2 timbl 552: ** This will convert from HTML to presentation or plain text.
1.1 timbl 553: */
1.75 frystyk 554: PUBLIC HTStream * HTMLToPlain (HTRequest * request,
555: void * param,
556: HTFormat input_format,
557: HTFormat output_format,
558: HTStream * output_stream)
1.1 timbl 559: {
1.75 frystyk 560: return SGML_new(HTML_dtd(), HTML_new(
1.16 timbl 561: request, NULL, input_format, output_format, output_stream));
1.1 timbl 562: }
563:
564:
1.2 timbl 565: /* HTConverter for HTML to C code
566: ** ------------------------------
567: **
1.36 frystyk 568: ** C code is like plain text but all non-preformatted code
1.2 timbl 569: ** is commented out.
570: ** This will convert from HTML to presentation or plain text.
571: */
1.75 frystyk 572: PUBLIC HTStream * HTMLToC (HTRequest * request,
573: void * param,
574: HTFormat input_format,
575: HTFormat output_format,
576: HTStream * output_stream)
577: {
578: if (output_stream) {
579: HTStructured * html = NULL;
580: (*output_stream->isa->put_string)(output_stream, "/* "); /* Before title */
581: html = HTML_new(request, NULL, input_format, output_format, output_stream);
582: html->comment_start = "\n/* ";
583: html->dtd = HTML_dtd();
584: html->comment_end = " */\n"; /* Must start in col 1 for cpp */
585: return SGML_new(HTML_dtd(), html);
586: } else
587: return HTErrorStream();
1.1 timbl 588: }
589:
590:
1.2 timbl 591: /* Presenter for HTML
592: ** ------------------
593: **
594: ** This will convert from HTML to presentation or plain text.
595: **
596: ** Override this if you have a windows version
1.1 timbl 597: */
1.75 frystyk 598: PUBLIC HTStream * HTMLPresent (HTRequest * request,
599: void * param,
600: HTFormat input_format,
601: HTFormat output_format,
602: HTStream * output_stream)
1.1 timbl 603: {
1.75 frystyk 604: return SGML_new(HTML_dtd(), HTML_new(
1.16 timbl 605: request, NULL, input_format, output_format, output_stream));
1.1 timbl 606: }
1.29 frystyk 607:
Webmaster