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