Annotation of libwww/Library/src/HTML.c, revision 1.4
1.2 timbl 1: /* Structured stream to Rich hypertext converter
2: ** ============================================
1.1 timbl 3: **
1.2 timbl 4: ** This generates of a hypertext object. It converts from the
5: ** structured stream interface fro HTMl events into the style-
6: ** oriented iunterface of the HText.h interface. This module is
7: ** only used in clients and shouldnot be linked into servers.
1.1 timbl 8: **
1.2 timbl 9: ** Override this module is making a new GUI browser.
1.1 timbl 10: **
11: */
12: #include "HTML.h"
13:
1.2 timbl 14: #define CAREFUL /* Check nesting here notreally necessary */
15:
1.1 timbl 16: #include <ctype.h>
17: #include <stdio.h>
18:
19: #include "HTAtom.h"
20: #include "HTChunk.h"
21: #include "HText.h"
22: #include "HTStyle.h"
23:
1.3 timbl 24: #include "HTAlert.h"
1.4 ! timbl 25: #include "HTMLGen.h"
1.1 timbl 26:
27: extern HTStyleSheet * styleSheet; /* Application-wide */
28:
29: /* Module-wide style cache
30: */
31: PRIVATE int got_styles = 0;
1.2 timbl 32: PRIVATE HTStyle *styles[HTML_ELEMENTS];
33: PRIVATE HTStyle *default_style;
1.1 timbl 34:
35:
36: /* HTML Object
37: ** -----------
38: */
1.2 timbl 39: #define MAX_NESTING 20 /* Should be checked by parser */
40:
41: typedef struct _stack_element {
42: HTStyle * style;
43: int tag_number;
44: } stack_element;
45:
46: struct _HTStructured {
47: CONST HTStructuredClass * isa;
48: HTParentAnchor * node_anchor;
49: HText * text;
50:
51: HTStream* target; /* Output stream */
52: HTStreamClass targetClass; /* Output routines */
53:
54: HTChunk title; /* Grow by 128 */
55:
56: char * comment_start; /* for literate programming */
57: char * comment_end;
58:
59: HTTag * current_tag;
60: BOOL style_change;
61: HTStyle * new_style;
62: HTStyle * old_style;
63: BOOL in_word; /* Have just had a non-white char */
64: stack_element stack[MAX_NESTING];
65: stack_element *sp; /* Style stack pointer */
1.1 timbl 66: };
67:
1.2 timbl 68: struct _HTStream {
69: CONST HTStreamClass * isa;
70: /* .... */
71: };
1.1 timbl 72:
73: /* Forward declarations of routines
74: */
75: PRIVATE void get_styles NOPARAMS;
76:
77:
1.4 ! timbl 78: PRIVATE void actually_set_style PARAMS((HTStructured * me));
! 79: PRIVATE void change_style PARAMS((HTStructured * me, HTStyle * style));
1.1 timbl 80:
81: /* Style buffering avoids dummy paragraph begin/ends.
82: */
1.4 ! timbl 83: #define UPDATE_STYLE if (me->style_change) { actually_set_style(me); }
1.1 timbl 84:
85:
1.2 timbl 86: #ifdef OLD_CODE
1.1 timbl 87: /* The following accented characters are from peter Flynn, curia project */
88:
89: /* these ifdefs don't solve the problem of a simple terminal emulator
90: ** with a different character set to the client machine. But nothing does,
91: ** except looking at the TERM setting */
92:
1.2 timbl 93:
1.1 timbl 94: { "ocus" , "&" }, /* for CURIA */
95: #ifdef IBMPC
96: { "aacute" , "\240" }, /* For PC display */
97: { "eacute" , "\202" },
98: { "iacute" , "\241" },
99: { "oacute" , "\242" },
100: { "uacute" , "\243" },
101: { "Aacute" , "\101" },
102: { "Eacute" , "\220" },
103: { "Iacute" , "\111" },
104: { "Oacute" , "\117" },
105: { "Uacute" , "\125" },
106: #else
107: { "aacute" , "\341" }, /* Works for openwindows -- Peter Flynn */
108: { "eacute" , "\351" },
109: { "iacute" , "\355" },
110: { "oacute" , "\363" },
111: { "uacute" , "\372" },
112: { "Aacute" , "\301" },
113: { "Eacute" , "\310" },
114: { "Iacute" , "\315" },
115: { "Oacute" , "\323" },
116: { "Uacute" , "\332" },
117: #endif
118: { 0, 0 } /* Terminate list */
119: };
1.2 timbl 120: #endif
1.1 timbl 121:
122:
1.2 timbl 123: /* Entity values -- for ISO Latin 1 local representation
124: **
125: ** This MUST match exactly the table referred to in the DTD!
126: */
127: static char * ISO_Latin1[] = {
128: "\306", /* capital AE diphthong (ligature) */
129: "\301", /* capital A, acute accent */
130: "\302", /* capital A, circumflex accent */
131: "\300", /* capital A, grave accent */
132: "\305", /* capital A, ring */
133: "\303", /* capital A, tilde */
134: "\304", /* capital A, dieresis or umlaut mark */
135: "\307", /* capital C, cedilla */
136: "\320", /* capital Eth, Icelandic */
137: "\311", /* capital E, acute accent */
138: "\312", /* capital E, circumflex accent */
139: "\310", /* capital E, grave accent */
140: "\313", /* capital E, dieresis or umlaut mark */
141: "\315", /* capital I, acute accent */
142: "\316", /* capital I, circumflex accent */
143: "\314", /* capital I, grave accent */
144: "\317", /* capital I, dieresis or umlaut mark */
145: "\321", /* capital N, tilde */
146: "\323", /* capital O, acute accent */
147: "\324", /* capital O, circumflex accent */
148: "\322", /* capital O, grave accent */
149: "\330", /* capital O, slash */
150: "\325", /* capital O, tilde */
151: "\326", /* capital O, dieresis or umlaut mark */
152: "\336", /* capital THORN, Icelandic */
153: "\332", /* capital U, acute accent */
154: "\333", /* capital U, circumflex accent */
155: "\331", /* capital U, grave accent */
156: "\334", /* capital U, dieresis or umlaut mark */
157: "\335", /* capital Y, acute accent */
158: "\341", /* small a, acute accent */
159: "\342", /* small a, circumflex accent */
160: "\346", /* small ae diphthong (ligature) */
161: "\340", /* small a, grave accent */
162: "\046", /* ampersand */
163: "\345", /* small a, ring */
164: "\343", /* small a, tilde */
165: "\344", /* small a, dieresis or umlaut mark */
166: "\347", /* small c, cedilla */
167: "\351", /* small e, acute accent */
168: "\352", /* small e, circumflex accent */
169: "\350", /* small e, grave accent */
170: "\360", /* small eth, Icelandic */
171: "\353", /* small e, dieresis or umlaut mark */
172: "\076", /* greater than */
173: "\355", /* small i, acute accent */
174: "\356", /* small i, circumflex accent */
175: "\354", /* small i, grave accent */
176: "\357", /* small i, dieresis or umlaut mark */
177: "\074", /* less than */
178: "\361", /* small n, tilde */
179: "\363", /* small o, acute accent */
180: "\364", /* small o, circumflex accent */
181: "\362", /* small o, grave accent */
182: "\370", /* small o, slash */
183: "\365", /* small o, tilde */
184: "\366", /* small o, dieresis or umlaut mark */
185: "\337", /* small sharp s, German (sz ligature) */
186: "\376", /* small thorn, Icelandic */
187: "\372", /* small u, acute accent */
188: "\373", /* small u, circumflex accent */
189: "\371", /* small u, grave accent */
190: "\374", /* small u, dieresis or umlaut mark */
191: "\375", /* small y, acute accent */
192: "\377", /* small y, dieresis or umlaut mark */
1.1 timbl 193: };
194:
1.2 timbl 195:
196: /* Entity values -- for NeXT local representation
197: **
198: ** This MUST match exactly the table referred to in the DTD!
199: **
200: */
201: static char * NeXTCharacters[] = {
202: "\341", /* capital AE diphthong (ligature) */
203: "\202", /* capital A, acute accent */
204: "\203", /* capital A, circumflex accent */
205: "\201", /* capital A, grave accent */
206: "\206", /* capital A, ring */
207: "\204", /* capital A, tilde */
208: "\205", /* capital A, dieresis or umlaut mark */
209: "\207", /* capital C, cedilla */
210: "\220", /* capital Eth, Icelandic */
211: "\211", /* capital E, acute accent */
212: "\212", /* capital E, circumflex accent */
213: "\210", /* capital E, grave accent */
214: "\213", /* capital E, dieresis or umlaut mark */
215: "\215", /* capital I, acute accent */
216: "\216", /* capital I, circumflex accent these are */
217: "\214", /* capital I, grave accent ISO -100 hex */
218: "\217", /* capital I, dieresis or umlaut mark */
219: "\221", /* capital N, tilde */
220: "\223", /* capital O, acute accent */
221: "\224", /* capital O, circumflex accent */
222: "\222", /* capital O, grave accent */
223: "\351", /* capital O, slash 'cept this */
224: "\225", /* capital O, tilde */
225: "\226", /* capital O, dieresis or umlaut mark */
226: "\234", /* capital THORN, Icelandic */
227: "\230", /* capital U, acute accent */
228: "\231", /* capital U, circumflex accent */
229: "\227", /* capital U, grave accent */
230: "\232", /* capital U, dieresis or umlaut mark */
231: "\233", /* capital Y, acute accent */
232: "\326", /* small a, acute accent */
233: "\327", /* small a, circumflex accent */
234: "\361", /* small ae diphthong (ligature) */
235: "\325", /* small a, grave accent */
236: "\046", /* ampersand */
237: "\332", /* small a, ring */
238: "\330", /* small a, tilde */
239: "\331", /* small a, dieresis or umlaut mark */
240: "\333", /* small c, cedilla */
241: "\335", /* small e, acute accent */
242: "\336", /* small e, circumflex accent */
243: "\334", /* small e, grave accent */
244: "\346", /* small eth, Icelandic */
245: "\337", /* small e, dieresis or umlaut mark */
246: "\076", /* greater than */
247: "\342", /* small i, acute accent */
248: "\344", /* small i, circumflex accent */
249: "\340", /* small i, grave accent */
250: "\345", /* small i, dieresis or umlaut mark */
251: "\074", /* less than */
252: "\347", /* small n, tilde */
253: "\355", /* small o, acute accent */
254: "\356", /* small o, circumflex accent */
255: "\354", /* small o, grave accent */
256: "\371", /* small o, slash */
257: "\357", /* small o, tilde */
258: "\360", /* small o, dieresis or umlaut mark */
259: "\373", /* small sharp s, German (sz ligature) */
260: "\374", /* small thorn, Icelandic */
261: "\363", /* small u, acute accent */
262: "\364", /* small u, circumflex accent */
263: "\362", /* small u, grave accent */
264: "\366", /* small u, dieresis or umlaut mark */
265: "\367", /* small y, acute accent */
266: "\375", /* small y, dieresis or umlaut mark */
1.1 timbl 267: };
268:
1.2 timbl 269: /* Entity values -- for IBM/PC Code Page 850 (International)
270: **
271: ** This MUST match exactly the table referred to in the DTD!
272: **
273: */
274: /* @@@@@@@@@@@@@@@@@ TBD */
275:
276:
277:
278: /* Set character set
279: ** ----------------
280: */
281:
282: PRIVATE char** p_entity_values = ISO_Latin1; /* Pointer to translation */
1.1 timbl 283:
1.2 timbl 284: PUBLIC void HTMLUseCharacterSet ARGS1(HTMLCharacterSet, i)
285: {
286: p_entity_values = (i == HTML_NEXT_CHARS) ? NeXTCharacters
287: : ISO_Latin1;
288: }
1.1 timbl 289:
290:
291: /* Flattening the style structure
292: ** ------------------------------
293: **
294: On the NeXT, and on any read-only browser, it is simpler for the text to have
295: a sequence of styles, rather than a nested tree of styles. In this
296: case we have to flatten the structure as it arrives from SGML tags into
297: a sequence of styles.
298: */
299:
300: /* If style really needs to be set, call this
301: */
1.4 ! timbl 302: PRIVATE void actually_set_style ARGS1(HTStructured *, me)
1.1 timbl 303: {
1.4 ! timbl 304: if (!me->text) { /* First time through */
! 305: me->text = HText_new2(me->node_anchor, me->target);
! 306: HText_beginAppend(me->text);
! 307: HText_setStyle(me->text, me->new_style);
! 308: me->in_word = NO;
1.1 timbl 309: } else {
1.4 ! timbl 310: HText_setStyle(me->text, me->new_style);
1.1 timbl 311: }
1.4 ! timbl 312: me->old_style = me->new_style;
! 313: me->style_change = NO;
1.1 timbl 314: }
315:
316: /* If you THINK you need to change style, call this
317: */
318:
1.4 ! timbl 319: PRIVATE void change_style ARGS2(HTStructured *, me, HTStyle *,style)
1.1 timbl 320: {
1.4 ! timbl 321: if (me->new_style!=style) {
! 322: me->style_change = YES;
! 323: me->new_style = style;
1.1 timbl 324: }
325: }
326:
1.2 timbl 327: /*_________________________________________________________________________
328: **
329: ** A C T I O N R O U T I N E S
330: */
331:
332: /* Character handling
333: ** ------------------
1.1 timbl 334: */
1.4 ! timbl 335: PRIVATE void HTML_put_character ARGS2(HTStructured *, me, char, c)
1.1 timbl 336: {
1.2 timbl 337:
1.4 ! timbl 338: switch (me->sp[0].tag_number) {
1.2 timbl 339: case HTML_COMMENT:
340: break; /* Do Nothing */
341:
342: case HTML_TITLE:
1.4 ! timbl 343: HTChunkPutc(&me->title, c);
1.2 timbl 344: break;
345:
346:
347: case HTML_LISTING: /* Litteral text */
348: case HTML_XMP:
349: case HTML_PLAINTEXT:
350: case HTML_PRE:
351: /* We guarrantee that the style is up-to-date in begin_litteral
352: */
1.4 ! timbl 353: HText_appendCharacter(me->text, c);
1.2 timbl 354: break;
355:
356: default: /* Free format text */
1.4 ! timbl 357: if (me->style_change) {
1.2 timbl 358: if ((c=='\n') || (c==' ')) return; /* Ignore it */
359: UPDATE_STYLE;
360: }
361: if (c=='\n') {
1.4 ! timbl 362: if (me->in_word) {
! 363: HText_appendCharacter(me->text, ' ');
! 364: me->in_word = NO;
1.2 timbl 365: }
366: } else {
1.4 ! timbl 367: HText_appendCharacter(me->text, c);
! 368: me->in_word = YES;
1.2 timbl 369: }
370: } /* end switch */
1.1 timbl 371: }
372:
1.2 timbl 373:
374:
375: /* String handling
376: ** ---------------
377: **
378: ** This is written separately from put_character becuase the loop can
379: ** in some cases be postponed to a lower level for speed.
380: */
1.4 ! timbl 381: PRIVATE void HTML_put_string ARGS2(HTStructured *, me, CONST char*, s)
1.1 timbl 382: {
1.2 timbl 383:
1.4 ! timbl 384: switch (me->sp[0].tag_number) {
1.2 timbl 385: case HTML_COMMENT:
386: break; /* Do Nothing */
387:
388: case HTML_TITLE:
1.4 ! timbl 389: HTChunkPuts(&me->title, s);
1.2 timbl 390: break;
391:
392:
393: case HTML_LISTING: /* Litteral text */
394: case HTML_XMP:
395: case HTML_PLAINTEXT:
396: case HTML_PRE:
397:
398: /* We guarrantee that the style is up-to-date in begin_litteral
399: */
1.4 ! timbl 400: HText_appendText(me->text, s);
1.2 timbl 401: break;
402:
403: default: /* Free format text */
404: {
405: CONST char *p = s;
1.4 ! timbl 406: if (me->style_change) {
1.2 timbl 407: for (; *p && ((*p=='\n') || (*p==' ')); p++) ; /* Ignore leaders */
408: if (!*p) return;
409: UPDATE_STYLE;
410: }
411: for(; *p; p++) {
1.4 ! timbl 412: if (me->style_change) {
1.2 timbl 413: if ((*p=='\n') || (*p==' ')) continue; /* Ignore it */
414: UPDATE_STYLE;
415: }
416: if (*p=='\n') {
1.4 ! timbl 417: if (me->in_word) {
! 418: HText_appendCharacter(me->text, ' ');
! 419: me->in_word = NO;
1.2 timbl 420: }
421: } else {
1.4 ! timbl 422: HText_appendCharacter(me->text, *p);
! 423: me->in_word = YES;
1.2 timbl 424: }
425: } /* for */
426: }
427: } /* end switch */
1.1 timbl 428: }
429:
430:
1.2 timbl 431: /* Buffer write
1.3 timbl 432: ** ------------
1.1 timbl 433: */
1.4 ! timbl 434: PRIVATE void HTML_write ARGS3(HTStructured *, me, CONST char*, s, int, l)
1.1 timbl 435: {
1.2 timbl 436: CONST char* p;
437: CONST char* e = s+l;
1.4 ! timbl 438: for (p=s; s<e; p++) HTML_put_character(me, *p);
1.1 timbl 439: }
1.2 timbl 440:
441:
442: /* Start Element
443: ** -------------
444: */
445: PRIVATE void HTML_start_element ARGS4(
1.4 ! timbl 446: HTStructured *, me,
1.2 timbl 447: int, element_number,
1.3 timbl 448: CONST BOOL*, present,
449: CONST char **, value)
1.2 timbl 450: {
451: switch (element_number) {
452: case HTML_A:
453: {
454: HTChildAnchor * source = HTAnchor_findChildAndLink(
1.4 ! timbl 455: me->node_anchor, /* parent */
1.2 timbl 456: present[HTML_A_NAME] ? value[HTML_A_NAME] : 0, /* Tag */
457: present[HTML_A_HREF] ? value[HTML_A_HREF] : 0, /* Addresss */
458: present[HTML_A_TYPE] && value[HTML_A_TYPE] ?
459: (HTLinkType*)HTAtom_for(value[HTML_A_TYPE])
460: : 0);
461:
462: if (present[HTML_A_TITLE] && value[HTML_A_TITLE]) {
463: HTParentAnchor * dest =
464: HTAnchor_parent(
465: HTAnchor_followMainLink((HTAnchor*)source)
466: );
467: if (!HTAnchor_title(dest))
468: HTAnchor_setTitle(dest, value[HTML_A_TITLE]);
469: }
470: UPDATE_STYLE;
1.4 ! timbl 471: HText_beginAnchor(me->text, source);
1.2 timbl 472: }
473: break;
474:
475: case HTML_TITLE:
1.4 ! timbl 476: HTChunkClear(&me->title);
1.2 timbl 477: break;
478:
479: case HTML_NEXTID:
480: /* if (present[NEXTID_N] && value[NEXTID_N])
1.4 ! timbl 481: HText_setNextId(me->text, atoi(value[NEXTID_N])); */
1.2 timbl 482: break;
483:
484: case HTML_ISINDEX:
1.4 ! timbl 485: HTAnchor_setIndex(me->node_anchor);
1.2 timbl 486: break;
487:
488: case HTML_P:
489: UPDATE_STYLE;
1.4 ! timbl 490: HText_appendParagraph(me->text);
! 491: me->in_word = NO;
1.2 timbl 492: break;
493:
494: case HTML_DL:
1.4 ! timbl 495: change_style(me, present && present[DL_COMPACT]
1.2 timbl 496: ? styles[HTML_DLC]
497: : styles[HTML_DL]);
1.4 ! timbl 498: me->in_word = NO;
1.2 timbl 499: break;
500:
501: case HTML_DT:
1.4 ! timbl 502: if (!me->style_change) {
! 503: HText_appendParagraph(me->text);
! 504: me->in_word = NO;
1.2 timbl 505: }
506: break;
507:
508: case HTML_DD:
509: UPDATE_STYLE;
1.4 ! timbl 510: HTML_put_character(me, '\t'); /* Just tab out one stop */
! 511: me->in_word = NO;
! 512: break;
1.2 timbl 513:
514: case HTML_UL:
515: case HTML_OL:
516: case HTML_MENU:
517: case HTML_DIR:
1.4 ! timbl 518: change_style(me, styles[element_number]);
! 519: me->in_word = NO;
1.2 timbl 520: break;
521:
522: case HTML_LI:
523: UPDATE_STYLE;
1.4 ! timbl 524: if (me->sp[1].tag_number != HTML_DIR)
! 525: HText_appendParagraph(me->text);
1.2 timbl 526: else
1.4 ! timbl 527: HText_appendCharacter(me->text, '\t'); /* Tab @@ nl for UL? */
! 528: me->in_word = NO;
1.2 timbl 529: break;
530:
531: case HTML_LISTING: /* Litteral text */
532: case HTML_XMP:
533: case HTML_PLAINTEXT:
534: case HTML_PRE:
1.4 ! timbl 535: change_style(me, styles[element_number]);
1.2 timbl 536: UPDATE_STYLE;
1.4 ! timbl 537: if (me->comment_end)
! 538: HText_appendText(me->text, me->comment_end);
1.2 timbl 539: break;
540:
541: default:
1.4 ! timbl 542: change_style(me, styles[element_number]); /* May be postponed */
1.2 timbl 543: break;
544:
545: } /* end switch */
546:
547: if (HTML_dtd.tags[element_number].contents!= SGML_EMPTY) {
1.4 ! timbl 548: --(me->sp);
! 549: me->sp[0].style = me->new_style; /* Stack new style */
! 550: me->sp[0].tag_number = element_number;
1.2 timbl 551: }
552:
1.1 timbl 553: }
1.2 timbl 554:
1.1 timbl 555: /* End Element
1.2 timbl 556: ** -----------
1.1 timbl 557: **
1.2 timbl 558: */
559: /* When we end an element, the style must be returned to that
1.1 timbl 560: ** in effect before that element. Note that anchors (etc?)
561: ** don't have an associated style, so that we must scan down the
562: ** stack for an element with a defined style. (In fact, the styles
563: ** should be linked to the whole stack not just the top one.)
564: ** TBL 921119
565: */
1.4 ! timbl 566: PRIVATE void HTML_end_element ARGS2(HTStructured *, me, int , element_number)
1.1 timbl 567: {
1.2 timbl 568: #ifdef CAREFUL /* parser assumed to produce good nesting */
1.4 ! timbl 569: if (element_number != me->sp[0].tag_number) {
1.2 timbl 570: fprintf(stderr, "HTMLText: end of element %s when expecting end of %s\n",
571: HTML_dtd.tags[element_number].name,
1.4 ! timbl 572: HTML_dtd.tags[me->sp->tag_number].name);
1.2 timbl 573: exit(-20);
1.1 timbl 574: }
1.2 timbl 575: #endif
576:
1.4 ! timbl 577: me->sp++; /* Pop state off stack */
1.2 timbl 578:
579: switch(element_number) {
580:
581: case HTML_A:
582: UPDATE_STYLE;
1.4 ! timbl 583: HText_endAnchor(me->text);
1.2 timbl 584: break;
585:
586: case HTML_TITLE:
1.4 ! timbl 587: HTChunkTerminate(&me->title);
! 588: HTAnchor_setTitle(me->node_anchor, me->title.data);
1.2 timbl 589: break;
590:
591: case HTML_LISTING: /* Litteral text */
592: case HTML_XMP:
593: case HTML_PLAINTEXT:
594: case HTML_PRE:
1.4 ! timbl 595: if (me->comment_start)
! 596: HText_appendText(me->text, me->comment_start);
1.2 timbl 597: /* Fall through */
598:
599: default:
600:
1.4 ! timbl 601: change_style(me, me->sp->style); /* Often won't really change */
! 602: me->in_word = NO; /* Paragraph styles only @@ */
1.2 timbl 603: break;
604:
605: } /* switch */
1.1 timbl 606: }
607:
1.2 timbl 608:
609: /* Expanding entities
610: ** ------------------
611: */
612: /* (In fact, they all shrink!)
1.1 timbl 613: */
1.2 timbl 614:
1.4 ! timbl 615: PRIVATE void HTML_put_entity ARGS2(HTStructured *, me, int, entity_number)
1.1 timbl 616: {
1.4 ! timbl 617: HTML_put_string(me, ISO_Latin1[entity_number]); /* @@ Other representations */
1.1 timbl 618: }
619:
1.2 timbl 620:
621:
622: /* Free an HTML object
623: ** -------------------
624: **
1.4 ! timbl 625: ** If the document is empty, the text object will not yet exist.
! 626: So we could in fact abandon creating the document and return
! 627: an error code. In fact an empty document is an important type
! 628: of document, so we don't.
! 629: **
! 630: ** If non-interactive, everything is freed off. No: crashes -listrefs
1.2 timbl 631: ** Otherwise, the interactive object is left.
632: */
1.4 ! timbl 633: PUBLIC void HTML_free ARGS1(HTStructured *, me)
1.1 timbl 634: {
1.4 ! timbl 635: UPDATE_STYLE; /* Creates empty document here! */
! 636: if (me->comment_end)
! 637: HTML_put_string(me,me->comment_end);
! 638: HText_endAppend(me->text);
! 639:
! 640: if (me->target) {
! 641: (*me->targetClass.end_document)(me->target);
! 642: (*me->targetClass.free)(me->target);
! 643: /* HText_free(me->text); */ /* @@@@@@@@@@@@@@@ */
1.2 timbl 644: }
1.4 ! timbl 645: free(me);
1.1 timbl 646: }
647:
648:
1.4 ! timbl 649: PRIVATE void HTML_end_document ARGS1(HTStructured *, me)
1.1 timbl 650:
1.4 ! timbl 651: { /* Obsolete */
1.1 timbl 652: }
653:
1.2 timbl 654:
655: /* Get Styles from style sheet
656: ** ---------------------------
657: */
658: PRIVATE void get_styles NOARGS
1.1 timbl 659: {
1.2 timbl 660: got_styles = YES;
661:
662: default_style = HTStyleNamed(styleSheet, "Normal");
1.1 timbl 663:
1.2 timbl 664: styles[HTML_H1] = HTStyleNamed(styleSheet, "Heading1");
665: styles[HTML_H2] = HTStyleNamed(styleSheet, "Heading2");
666: styles[HTML_H3] = HTStyleNamed(styleSheet, "Heading3");
667: styles[HTML_H4] = HTStyleNamed(styleSheet, "Heading4");
668: styles[HTML_H5] = HTStyleNamed(styleSheet, "Heading5");
669: styles[HTML_H6] = HTStyleNamed(styleSheet, "Heading6");
670: styles[HTML_H7] = HTStyleNamed(styleSheet, "Heading7");
671:
672: styles[HTML_DL] = HTStyleNamed(styleSheet, "Glossary");
673: styles[HTML_UL] =
674: styles[HTML_OL] = HTStyleNamed(styleSheet, "List");
675: styles[HTML_MENU] = HTStyleNamed(styleSheet, "Menu");
676: styles[HTML_DIR] = HTStyleNamed(styleSheet, "Dir");
677: styles[HTML_DLC] = HTStyleNamed(styleSheet, "GlossaryCompact");
678: styles[HTML_ADDRESS]= HTStyleNamed(styleSheet, "Address");
679: styles[HTML_BLOCKQUOTE]= HTStyleNamed(styleSheet, "BlockQuote");
680: styles[HTML_PLAINTEXT] =
681: styles[HTML_XMP] = HTStyleNamed(styleSheet, "Example");
682: styles[HTML_PRE] = HTStyleNamed(styleSheet, "Preformatted");
683: styles[HTML_LISTING] = HTStyleNamed(styleSheet, "Listing");
684: }
685: /* P U B L I C
686: */
687:
688: /* Structured Object Class
689: ** -----------------------
690: */
691: PUBLIC CONST HTStructuredClass HTMLPresentation = /* As opposed to print etc */
692: {
693: "text/html",
694: HTML_free,
695: HTML_end_document,
696: HTML_put_character, HTML_put_string, HTML_write,
697: HTML_start_element, HTML_end_element,
698: HTML_put_entity
699: };
1.1 timbl 700:
1.4 ! timbl 701:
1.2 timbl 702: /* New Structured Text object
703: ** --------------------------
704: **
1.4 ! timbl 705: ** The strutcured stream can generate either presentation,
! 706: ** or plain text, or HTML.
1.1 timbl 707: */
1.4 ! timbl 708: PUBLIC HTStructured* HTML_new ARGS3(
1.2 timbl 709: HTParentAnchor *, anchor,
1.4 ! timbl 710: HTFormat, format_out,
1.2 timbl 711: HTStream*, stream)
1.1 timbl 712: {
713:
1.4 ! timbl 714: HTStructured * me;
! 715:
! 716: if (format_out == WWW_HTML) return HTMLGenerator(stream);
! 717: if (format_out != WWW_PLAINTEXT && format_out != WWW_PRESENT) {
! 718: fprintf(stderr, "** Internal error: can't parse HTML to %s\n",
! 719: HTAtom_name(format_out));
! 720: exit (-99);
! 721: }
! 722:
! 723: me = (HTStructured*) malloc(sizeof(*me));
! 724: if (me == NULL) outofmem(__FILE__, "HTML_new");
1.1 timbl 725:
726: if (!got_styles) get_styles();
727:
1.4 ! timbl 728: me->isa = &HTMLPresentation;
! 729: me->node_anchor = anchor;
! 730: me->title.size = 0;
! 731: me->title.growby = 128;
! 732: me->title.allocated = 0;
! 733: me->title.data = 0;
! 734: me->text = 0;
! 735: me->style_change = YES; /* Force check leading to text creation */
! 736: me->new_style = default_style;
! 737: me->old_style = 0;
! 738: me->sp = me->stack + MAX_NESTING - 1;
! 739: me->sp->tag_number = -1; /* INVALID */
! 740: me->sp->style = default_style; /* INVALID */
1.1 timbl 741:
1.4 ! timbl 742: me->comment_start = NULL;
! 743: me->comment_end = NULL;
! 744: me->target = stream;
! 745: if (stream) me->targetClass = *stream->isa; /* Copy pointers */
1.1 timbl 746:
1.4 ! timbl 747: return (HTStructured*) me;
1.1 timbl 748: }
749:
750:
1.2 timbl 751: /* HTConverter for HTML to plain text
752: ** ----------------------------------
1.1 timbl 753: **
1.2 timbl 754: ** This will convert from HTML to presentation or plain text.
1.1 timbl 755: */
1.2 timbl 756: PUBLIC HTStream* HTMLToPlain ARGS3(
757: HTPresentation *, pres,
758: HTParentAnchor *, anchor,
759: HTStream *, sink)
1.1 timbl 760: {
1.4 ! timbl 761: return SGML_new(&HTML_dtd, HTML_new(anchor, pres->rep_out, sink));
1.1 timbl 762: }
763:
764:
1.2 timbl 765: /* HTConverter for HTML to C code
766: ** ------------------------------
767: **
768: ** C copde is like plain text but all non-preformatted code
769: ** is commented out.
770: ** This will convert from HTML to presentation or plain text.
771: */
772: PUBLIC HTStream* HTMLToC ARGS3(
773: HTPresentation *, pres,
774: HTParentAnchor *, anchor,
775: HTStream *, sink)
1.1 timbl 776: {
1.4 ! timbl 777:
! 778: HTStructured * html;
! 779:
! 780: (*sink->isa->put_string)(sink, "/* "); /* Before even title */
! 781: html = HTML_new(anchor, WWW_PLAINTEXT, sink);
1.2 timbl 782: html->comment_start = "/* ";
783: html->comment_end = " */\n"; /* Must start in col 1 for cpp */
1.4 ! timbl 784: /* HTML_put_string(html,html->comment_start); */
1.2 timbl 785: return SGML_new(&HTML_dtd, html);
1.1 timbl 786: }
787:
788:
1.2 timbl 789: /* Presenter for HTML
790: ** ------------------
791: **
792: ** This will convert from HTML to presentation or plain text.
793: **
794: ** Override this if you have a windows version
1.1 timbl 795: */
1.2 timbl 796: #ifndef GUI
797: PUBLIC HTStream* HTMLPresent ARGS3(
798: HTPresentation *, pres,
799: HTParentAnchor *, anchor,
800: HTStream *, sink)
1.1 timbl 801: {
1.4 ! timbl 802: return SGML_new(&HTML_dtd, HTML_new(anchor, WWW_PRESENT, NULL));
1.1 timbl 803: }
1.2 timbl 804: #endif
1.1 timbl 805:
806:
1.2 timbl 807: /* Record error message as a hypertext object
808: ** ------------------------------------------
809: **
810: ** The error message should be marked as an error so that
811: ** it can be reloaded later.
812: ** This implementation just throws up an error message
813: ** and leaves the document unloaded.
1.1 timbl 814: **
1.2 timbl 815: ** On entry,
816: ** sink is a stream to the output device if any
817: ** number is the HTTP error number
818: ** message is the human readable message.
1.1 timbl 819: */
1.2 timbl 820:
821: PUBLIC int HTLoadError ARGS3(
822: HTStream *, sink,
823: int, number,
824: CONST char *, message)
825: {
826: HTAlert(message); /* @@@@@@@@@@@@@@@@@@@ */
827: return -number;
828: }
829:
Webmaster