/[public]/psiconv/trunk/program/psiconv/gen_html4.c
ViewVC logotype

Annotation of /psiconv/trunk/program/psiconv/gen_html4.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 140 - (hide annotations)
Tue Jan 22 21:45:45 2002 UTC (22 years, 2 months ago) by frodo
File MIME type: text/plain
File size: 17668 byte(s)
(Frodo) Fixed possible dangling pointers when no header/footer text was
        present, and added test to see whether any is present.

1 frodo 14 /*
2     * gen_html4.c - Part of psiconv, a PSION 5 data formats converter
3     * Copyright (c) 1999 Andrew Johnson <anjohnson@iee.org>
4     * Portions Copyright (c) 1999 Frodo Looijaard <frodol@dds.nl>
5     *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19     */
20    
21     #include "config.h"
22     #include <stdio.h>
23     #include <string.h>
24     #include <ctype.h>
25     #include <stdlib.h>
26 frodo 58 #include "psiconv/data.h"
27     #include "psiconv/list.h"
28 frodo 14 #include "gen.h"
29 frodo 34 #include "psiconv.h"
30 frodo 14
31     #ifndef TRUE
32     #define TRUE (0==0)
33     #endif
34    
35     /*
36     * Various string tables for HTML4 settings
37     */
38    
39     /* How to display each character */
40     static const char *char_table[0x100] = {
41     /* 0x00 */ "", "", "", "", "", "", "<BR>\n", "<BR>\n",
42     /* 0x08 */ "\n<HR>\n", "\t", "", "", "", "", "", "",
43     /* 0x10 */ " ", "", "", "", "", "", "", "",
44     /* 0x18 */ "", "", "", "", "", "", "", "",
45     /* 0x20 */ " ", "!", "&quot;", "#", "$", "%", "&amp;", "'",
46     /* 0x28 */ "(", ")", "*", "+", ",", "-", ".", "/",
47     /* 0x30 */ "0", "1", "2", "3", "4", "5", "6", "7",
48     /* 0x38 */ "8", "9", ":", ";", "&lt;", "=", "&gt;", "?",
49     /* 0x40 */ "@", "A", "B", "C", "D", "E", "F", "G",
50     /* 0x48 */ "H", "I", "J", "K", "L", "M", "N", "O",
51     /* 0x50 */ "P", "Q", "R", "S", "T", "U", "V", "W",
52     /* 0x58 */ "X", "Y", "Z", "[", "\\", "]", "^", "_",
53     /* 0x60 */ "`", "a", "b", "c", "d", "e", "f", "g",
54     /* 0x68 */ "h", "i", "j", "k", "l", "m", "n", "o",
55     /* 0x70 */ "p", "q", "r", "s", "t", "u", "v", "w",
56     /* 0x78 */ "x", "y", "z", "{", "|", "}", "~", "",
57     /* 0x80 */ "", "", "&#8218;", "&#402;",
58     "&#8222;", "&#8230;", "&#8224;", "&#8225;",
59     /* 0x88 */ "&#136;", "&#8240;", "&#352;", "<",
60     "&#338;", "", "", "",
61     /* 0x90 */ "", "&#8216;", "&#8217;", "&#8220;",
62     "&#8221;","&#8226;", "&#8211;", "&#8212;",
63     /* 0x98 */ "&#732;", "&#8482;", "&#353;", ">",
64     "&#339;", "", "", "&#376;",
65     /* 0xa0 */ "&nbsp;", "&iexcl;", "&cent;", "&pound;",
66     "&curren;", "&yen;", "&brvbar;", "&sect;",
67     /* 0xa8 */ "&uml;", "&copy;", "&ordf;", "&laquo;",
68     "&not;", "&shy;", "&reg;", "&#175;",
69     /* 0xb0 */ "&deg;", "&plusmn;", "&sup2;", "&sup3;",
70     "&acute;", "&micro;", "&para;", "&middot;",
71     /* 0xb8 */ "&cedil;", "&sup1;", "&ordm;", "&raquo;",
72     "&frac14;", "&frac12;", "&frac34;", "&iquest;",
73     /* 0xc0 */ "&Agrave;", "&Aacute;", "&Acirc;", "&Atilde;",
74     "&Auml;", "&Aring;", "&AElig;", "&Ccedil;",
75     /* 0xc8 */ "&Egrave;", "&Eacute;", "&Ecirc;", "&Euml;",
76     "&Igrave;", "&Iacute;", "&Icirc;", "&Iuml;",
77     /* 0xd0 */ "&ETH;", "&Ntilde;", "&Ograve;", "&Oacute;",
78     "&Ocirc;", "&Otilde;", "&Ouml;", "&times;",
79     /* 0xd8 */ "&Oslash;", "&Ugrave;", "&Uacute;", "&Ucirc;",
80     "&Uuml;", "&Yacute;", "&THORN;", "&szlig;",
81     /* 0xe0 */ "&agrave;", "&aacute;", "&acirc;", "&atilde;",
82     "&auml;", "&aring;", "&aelig;", "&ccedil;",
83     /* 0xe8 */ "&egrave;", "&eacute;", "&ecirc;", "&euml;",
84     "&igrave;", "&iacute;", "&icirc;", "&iuml;",
85     /* 0xf0 */ "&eth;", "&ntilde;", "&ograve;", "&oacute;",
86     "&ocirc;", "&otilde;", "&ouml;", "&divide;",
87     /* 0xf8 */ "&oslash;", "&ugrave;", "&uacute;", "&ucirc;",
88     "&uuml;", "&yacute;", "&thorn;", "&yuml;"
89     };
90    
91     /* The order of these must match the enum psiconv_border_kind (data.h) */
92     static const char *border_strings[] = {
93     "none", "solid", "double", "dotted", "dashed", "dashed", "dotted"
94     };
95    
96     /* The order of these must match the enum psiconv_justify (data.h) */
97     static const char *justify_strings[] = {
98     "left", "center", "right", "justify"
99     };
100    
101     /* The order of these must match the enum psiconv_super_sub (data.h) */
102     static const char *vertical_strings[] = {
103     "baseline", "super", "sub"
104     };
105    
106    
107     /*
108     * Support routines for particular formatting structures
109     */
110    
111     static void fput_name(FILE * of, const char *string) {
112     int i;
113    
114     for (i = 0; i < strlen(string); i++)
115     if (isalnum(string[i]))
116     putc(string[i], of);
117     }
118    
119     static void fput_text(FILE * of, const char *text, int length, int *pwasspace) {
120     int j;
121     int space;
122    
123     for (j = 0; j < length; j++) {
124     space = (text[j] == ' ');
125     if (*pwasspace && space)
126     fputs("&nbsp;", of);
127     else
128     fputs(char_table[(unsigned char) (text[j])], of);
129     *pwasspace = space;
130     }
131     }
132    
133     static const char *screenfont_name(psiconv_u8 screenfont)
134     {
135 frodo 90 if (screenfont == psiconv_font_sansserif)
136 frodo 14 return "sans-serif";
137 frodo 90 else if (screenfont == psiconv_font_nonprop)
138 frodo 14 return "monospace";
139 frodo 90 else if (screenfont == psiconv_font_serif)
140 frodo 14 return "serif";
141     else
142     return "serif";
143     }
144    
145     static const char *generic_font_family(const char *font_name) {
146     static const char *sans_font_names[] = {
147     "Arial", "Univers", "Sans Serif"
148     };
149     static const char *mono_font_names[] = {
150     "Courier New", "Courier", "Mono", "Lineprinter", "Elite", "Swiss",
151     "Courier (compressed)", "Courier (expanded)", "Letter Gothic"
152     };
153     int i;
154    
155     for (i=0; i < sizeof(sans_font_names) / sizeof(sans_font_names[0]); i++)
156     if (!strcmp(font_name, sans_font_names[i]))
157     return "sans-serif";
158    
159     for (i=0; i < sizeof(mono_font_names) / sizeof(mono_font_names[0]); i++)
160     if (!strcmp(font_name, mono_font_names[i]))
161     return "monospace";
162    
163     return "serif";
164     }
165    
166     static int colors_different(
167     const psiconv_color old,
168     const psiconv_color new)
169     {
170     return ((old->red != new->red) ||
171     (old->green != new->green) ||
172     (old->blue != new->blue));
173     }
174    
175    
176     /* Borders */
177     static int borders_different(
178     const psiconv_border old,
179     const psiconv_border new)
180     {
181     return (!old ||
182     (old->kind != new->kind) ||
183     colors_different(old->color, new->color) ||
184     (old->thickness != new->thickness));
185     }
186    
187     static void fput_border(FILE * of,
188     const char *which,
189     const psiconv_border old,
190     const psiconv_border new)
191     {
192     /* If the border changed at all we'll set all parameters, as they're
193     * fairly closely linked and it's much easier to do it this way */
194     if (borders_different(old, new)) {
195     fprintf(of, "border-%s-style:%s;",
196     which, border_strings[new->kind]);
197     if ((new->kind != psiconv_border_none) &&
198     (new->color->red || new->color->green || new->color->blue))
199     fprintf(of, "border-%s-color:#%02x%02x%02x;", which,
200     new->color->red, new->color->green, new->color->blue);
201     if ((new->kind == psiconv_border_solid) ||
202     (new->kind == psiconv_border_double))
203     fprintf(of, "border-%s-width:%.0fpx;",
204     which, (new->thickness / 10.0) - 1);
205     else if (new->kind != psiconv_border_none)
206     fprintf(of, "border-%s-width:1px;", which);
207     }
208     }
209    
210     /* Paragraph formats */
211     static int paragraph_layouts_different(
212     const psiconv_paragraph_layout old,
213     const psiconv_paragraph_layout new)
214     {
215 frodo 67 return ((old->space_above != new->space_above) ||
216 frodo 14 (old->indent_right != new->indent_right) ||
217 frodo 67 (old->space_below != new->space_below) ||
218 frodo 14 (old->indent_left != new->indent_left) ||
219     (old->indent_first != new->indent_first) ||
220     (old->justify_hor != new->justify_hor) ||
221 frodo 67 (old->linespacing_exact != new->linespacing_exact) ||
222 frodo 14 borders_different(old->left_border, new->left_border) ||
223     borders_different(old->right_border, new->right_border) ||
224     borders_different(old->top_border, new->top_border) ||
225     borders_different(old->bottom_border, new->bottom_border));
226     }
227    
228     static void fput_paragraph_layout(FILE * of,
229     const psiconv_paragraph_layout old,
230     const psiconv_paragraph_layout new)
231     {
232 frodo 67 if (!old || (old->space_above != new->space_above))
233     fprintf(of, "margin-top:%.1fpt;", new->space_above);
234 frodo 14 if (!old || (old->indent_right != new->indent_right))
235     fprintf(of, "margin-right:%.2fcm;", new->indent_right);
236 frodo 67 if (!old || (old->space_below != new->space_below))
237     fprintf(of, "margin-bottom:%.1fpt;", new->space_below);
238 frodo 14 if (!old ||
239     (old->bullet->on != new->bullet->on) ||
240     (old->bullet->indent != new->bullet->indent) ||
241     (old->indent_left != new->indent_left) ||
242     (old->indent_first != new->indent_first)) {
243     psiconv_length_t indent = new->indent_first;
244     psiconv_length_t margin = new->indent_left;
245     /* Bullets with indent set cause strange margin behaviour: */
246     if (new->bullet->on && new->bullet->indent) {
247     if (indent > 0.0) {
248     margin += indent;
249     indent = new->indent_left - indent;
250     }
251     }
252     fprintf(of, "margin-left:%.2fcm;", margin);
253     fprintf(of, "text-indent:%.2fcm;", indent);
254     }
255     if (!old || (old->justify_hor != new->justify_hor))
256     fprintf(of, "text-align:%s;", justify_strings[new->justify_hor]);
257 frodo 67 if (!old || (old->linespacing_exact != new->linespacing_exact)) {
258     if (!old || old->linespacing_exact)
259 frodo 14 fputs("line-height:normal;", of);
260     else
261 frodo 67 fprintf(of, "line-height:%.1fpt;", new->linespacing);
262 frodo 14 }
263     fput_border(of, "left", old ? old->left_border : NULL,
264     new->left_border);
265     fput_border(of, "right", old ? old->right_border : NULL,
266     new->right_border);
267     fput_border(of, "top", old ? old->top_border : NULL,
268     new->top_border);
269     fput_border(of, "bottom", old ? old->bottom_border : NULL,
270     new->bottom_border);
271     }
272    
273     /* Character formats */
274     static int character_layouts_different(
275     const psiconv_character_layout old,
276     const psiconv_character_layout new)
277     {
278     return ((old->font->screenfont != new->font->screenfont) ||
279     (strcmp(old->font->name,new->font->name)) ||
280     (old->font_size != new->font_size) ||
281     (old->color->red != new->color->red) ||
282     (old->color->green != new->color->green) ||
283     (old->color->blue != new->color->blue) ||
284     (old->back_color->red != new->back_color->red) ||
285     (old->back_color->green != new->back_color->green) ||
286     (old->back_color->blue != new->back_color->blue) ||
287     (old->italic != new->italic) ||
288     (old->bold != new->bold) ||
289     (old->super_sub != new->super_sub) ||
290     (old->underline != new->underline) ||
291 frodo 67 (old->strikethrough != new->strikethrough));
292 frodo 14 }
293    
294     static void fput_character_layout(FILE * of,
295     const psiconv_character_layout old,
296     const psiconv_character_layout new,
297     psiconv_word_f wf)
298     {
299     if (!old || (old->font->screenfont != new->font->screenfont) ||
300     strcmp(old->font->name,new->font->name)) {
301     fprintf(of, "font-family:%s,%s,%s;", new->font->name,
302     generic_font_family(new->font->name),
303     screenfont_name(new->font->screenfont));
304     }
305     if (!old || (old->font_size != new->font_size))
306     fprintf(of, "font-size:%.1f%%;", 100.0 * new->font_size / 10.0);
307     if (!old || (old->bold != new->bold))
308     fprintf(of, "font-weight:%s;", new->bold ? "bold" : "normal");
309     if (!old || (old->italic != new->italic))
310     fprintf(of, "font-style:%s;", new->italic ? "italic" : "normal");
311     if (!old || (colors_different(old->color, new->color)))
312     fprintf(of, "color:#%02x%02x%02x;",
313     new->color->red, new->color->green, new->color->blue);
314     if (!old || (colors_different(old->back_color, new->back_color)))
315     fprintf(of, "background-color:#%02x%02x%02x;",
316     new->back_color->red, new->back_color->green, new->back_color->blue);
317     if (!old || (old->super_sub != new->super_sub))
318     fprintf(of, "vertical-align:%s;", vertical_strings[new->super_sub]);
319     if (!old || (old->underline != new->underline) ||
320 frodo 67 (old->strikethrough != new->strikethrough)) {
321 frodo 14 fputs("text-decoration:", of);
322 frodo 67 if (new->strikethrough)
323 frodo 14 fputs("line-through ", of);
324     if (new->underline)
325     fputs("underline", of);
326 frodo 67 else if (!new->strikethrough)
327 frodo 14 fputs("none", of);
328     fputs(";", of);
329     }
330     }
331    
332    
333     /* Formatted paragraphs */
334     static void fput_para(FILE * of,
335     const psiconv_paragraph para,
336     psiconv_word_f wf)
337     {
338     psiconv_paragraph_layout base_para = para->base_paragraph;
339     psiconv_character_layout base_char = para->base_character;
340     psiconv_character_layout cur_char;
341     psiconv_character_layout *layout_stack;
342     psiconv_in_line_layout inl;
343     psiconv_word_style sty;
344     int spans = 0;
345     int wasspace = 0;
346     int i, j, loc;
347    
348     layout_stack = calloc(psiconv_list_length(para->in_lines),
349     sizeof(*layout_stack));
350     fputs("<P", of);
351     sty = psiconv_get_style(wf->styles_sec, para->base_style);
352     cur_char = sty->character;
353    
354     if (sty->name) {
355     fputs(" CLASS=\"", of);
356     fput_name(of, sty->name);
357     putc('"', of);
358     }
359    
360     if (paragraph_layouts_different(sty->paragraph, base_para) ||
361     character_layouts_different(cur_char, base_char)) {
362     fputs(" STYLE=\"", of);
363     fput_paragraph_layout(of, sty->paragraph, base_para);
364     fput_character_layout(of, cur_char, base_char, wf);
365     cur_char = base_char;
366     putc('"', of);
367     }
368     putc('>', of);
369    
370     if (base_para->bullet->on) {
371     fputs("<SPAN STYLE=\"", of);
372     if (base_para->bullet->font != base_char->font) {
373     fprintf(of, "font-family:%s,%s,%s;",
374     base_para->bullet->font->name,
375     generic_font_family(base_para->bullet->font->name),
376     screenfont_name(base_para->bullet->font->screenfont));
377     }
378     if (base_para->bullet->font_size != base_char->font_size)
379     fprintf(of, "font-size:%.1f%%;",
380     100.0 * base_para->bullet->font_size / 10.0);
381     if ((base_para->bullet->color->red != base_char->color->red) ||
382     (base_para->bullet->color->green != base_char->color->green) ||
383     (base_para->bullet->color->blue != base_char->color->blue))
384     fprintf(of, "color:#%02x%02x%02x;",
385     base_para->bullet->color->red,
386     base_para->bullet->color->green,
387     base_para->bullet->color->blue);
388     fprintf(of, "\">%s </SPAN>",
389     char_table[base_para->bullet->character]);
390     wasspace = TRUE;
391     }
392    
393     loc = 0;
394     for (i = 0; i < psiconv_list_length(para->in_lines); i++) {
395     inl = psiconv_list_get(para->in_lines, i);
396     if (character_layouts_different(cur_char, inl->layout)) {
397     for (j = 0; j < spans; j++)
398     if (!character_layouts_different(inl->layout, layout_stack[j]))
399     break;
400     if (j < spans) {
401     while (spans > j) {
402     fputs("</SPAN>",of);
403     spans--;
404     }
405     } else {
406     fputs("<SPAN STYLE=\"", of);
407     fput_character_layout(of, cur_char, inl->layout, wf);
408     fputs("\">",of);
409     layout_stack[spans++] = cur_char;
410     }
411     cur_char = inl->layout;
412     }
413     fput_text(of, &para->text[loc], inl->length, &wasspace);
414     loc += inl->length;
415     }
416    
417     while (spans > 0) {
418     fputs("</SPAN>",of);
419     spans--;
420     }
421    
422     if (loc < strlen(para->text)) {
423     fput_text(of, &para->text[loc], strlen(para->text) - loc, &wasspace);
424     }
425    
426     if (strlen(para->text) == 0)
427     fputs("&nbsp;", of);
428    
429     fputs("</P>\n", of);
430     free(layout_stack);
431     }
432    
433     static void fput_style(FILE * of,
434     const psiconv_word_style normal,
435     const psiconv_word_style sty,
436     psiconv_word_f wf)
437     {
438     if (sty->name == NULL)
439     fputs(" P {", of);
440     else {
441     fputs(" P.", of);
442     fput_name(of, sty->name);
443     fputs(" {", of);
444     }
445     fput_paragraph_layout(of, normal ? normal->paragraph : NULL, sty->paragraph);
446     fput_character_layout(of, normal ? normal->character : NULL, sty->character, wf);
447     fputs("}\n", of);
448     }
449    
450 frodo 53 static int psiconv_gen_html4(const char *filename, const psiconv_file file,
451 frodo 34 const char *dest)
452 frodo 14 {
453 frodo 53 FILE * of;
454 frodo 14 int i;
455     psiconv_paragraph para;
456     psiconv_word_style normal, sty;
457     psiconv_word_f wf;
458    
459     if (file->type == psiconv_word_file)
460     wf = file->file;
461     else {
462     /* Fall back on the normal HTML generator */
463 frodo 53 return psiconv_gen_html(filename,file,dest);
464 frodo 14 }
465    
466 frodo 53 if (! (of = fopen(filename,"w")))
467     return -1;
468    
469 frodo 14 fputs("<!doctype html public \"-//W3C//DTD HTML 4.0 STRICT//EN\">", of);
470     fputs("\n<HTML>\n<HEAD>\n <META NAME=\"GENERATOR\"", of);
471     fputs(" CONTENT=\"psiconv-" VERSION "\">\n", of);
472    
473 frodo 140 if (wf->page_sec->header->text) {
474     if (psiconv_list_length(wf->page_sec->header->text->paragraphs) > 0) {
475     fputs(" <TITLE>", of);
476     para = psiconv_list_get(wf->page_sec->header->text->paragraphs, 0);
477     i = 0;
478     fput_text(of, para->text, strlen(para->text), &i);
479     fputs("</TITLE>\n", of);
480     }
481 frodo 14 }
482    
483     normal = wf->styles_sec->normal;
484     fputs(" <STYLE TYPE=\"text/css\"><!--\n", of);
485     fprintf(of," BODY { background-color: #%02x%02x%02x }\n",
486     normal->paragraph->back_color->red,
487     normal->paragraph->back_color->green,
488     normal->paragraph->back_color->blue);
489     fput_style(of, NULL, normal, wf);
490     for (i = 0; i < psiconv_list_length(wf->styles_sec->styles); i++) {
491     sty = psiconv_list_get(wf->styles_sec->styles, i);
492     fput_style(of, normal, sty, wf);
493     }
494     fputs(" --></STYLE>\n</HEAD>\n<BODY>\n", of);
495 frodo 140 if (wf->page_sec->header->text) {
496     for (i = 0; i < psiconv_list_length(wf->paragraphs); i++) {
497     para = psiconv_list_get(wf->paragraphs, i);
498     fput_para(of, para, wf);
499     }
500 frodo 14 }
501     fputs("</BODY>\n</HTML>\n", of);
502 frodo 53
503     return fclose(of);
504 frodo 14 }
505    
506 frodo 56 static struct psiconv_fileformat_s ff =
507 frodo 34 {
508     "HTML4",
509     "HTML 4.0 with cascading style sheets",
510     psiconv_gen_html4
511     };
512    
513     void init_html4(void)
514     {
515     psiconv_list_add(fileformat_list,&ff);
516     }
517    

frodo@frodo.looijaard.name
ViewVC Help
Powered by ViewVC 1.1.26