/[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 142 - (hide annotations)
Tue Jan 29 18:38:38 2002 UTC (22 years, 2 months ago) by frodo
File MIME type: text/plain
File size: 17712 byte(s)
(Frodo) DMALLOC support

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

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