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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 140 Revision 267
1/* 1/*
2 * gen_html4.c - Part of psiconv, a PSION 5 data formats converter 2 gen_html.c - Part of psiconv, a PSION 5 file formats converter
3 * Copyright (c) 1999 Andrew Johnson <anjohnson@iee.org>
4 * Portions Copyright (c) 1999 Frodo Looijaard <frodol@dds.nl> 3 Copyright (c) 1999-2004 Frodo Looijaard <frodol@dds.nl>
5 * 4
6 * This program is free software; you can redistribute it and/or modify 5 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 6 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 7 the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version. 8 (at your option) any later version.
10 * 9
11 * This program is distributed in the hope that it will be useful, 10 This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details. 13 GNU General Public License for more details.
15 * 14
16 * You should have received a copy of the GNU General Public License 15 You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software 16 along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */ 18*/
20 19
21#include "config.h" 20#include "config.h"
22#include <stdio.h> 21
22#include <psiconv/configuration.h>
23#include <psiconv/data.h>
24#include "general.h"
25
23#include <string.h> 26#include <string.h>
24#include <ctype.h>
25#include <stdlib.h> 27#include <stdlib.h>
26#include "psiconv/data.h"
27#include "psiconv/list.h"
28#include "gen.h"
29#include "psiconv.h"
30 28
31#ifndef TRUE 29#ifdef DMALLOC
32#define TRUE (0==0) 30#include "dmalloc.h"
33#endif 31#endif
34 32
35/* 33#define TEMPSTR_LEN 100
36 * Various string tables for HTML4 settings
37 */
38 34
39/* How to display each character */ 35static void text(const psiconv_config config,psiconv_list list,
40static const char *char_table[0x100] = { 36 psiconv_string_t data,const encoding enc);
41 /* 0x00 */ "", "", "", "", "", "", "<BR>\n", "<BR>\n", 37static void header(const psiconv_config config, psiconv_list list,
42 /* 0x08 */ "\n<HR>\n", "\t", "", "", "", "", "", "", 38 const encoding enc);
43 /* 0x10 */ " ", "", "", "", "", "", "", "", 39static void footer(const psiconv_config config, psiconv_list list,
44 /* 0x18 */ "", "", "", "", "", "", "", "", 40 const encoding enc);
45 /* 0x20 */ " ", "!", "&quot;", "#", "$", "%", "&amp;", "'", 41static void characters(const psiconv_config config, psiconv_list list,
46 /* 0x28 */ "(", ")", "*", "+", ",", "-", ".", "/", 42 const psiconv_string_t textstr,
47 /* 0x30 */ "0", "1", "2", "3", "4", "5", "6", "7", 43 const psiconv_character_layout layout,const encoding enc);
48 /* 0x38 */ "8", "9", ":", ";", "&lt;", "=", "&gt;", "?", 44static void paragraph(const psiconv_config config, psiconv_list list,
49 /* 0x40 */ "@", "A", "B", "C", "D", "E", "F", "G", 45 psiconv_paragraph para, const encoding enc);
50 /* 0x48 */ "H", "I", "J", "K", "L", "M", "N", "O", 46static void paragraphs(const psiconv_config config, psiconv_list list,
51 /* 0x50 */ "P", "Q", "R", "S", "T", "U", "V", "W", 47 psiconv_text_and_layout paragraphs, const encoding enc);
52 /* 0x58 */ "X", "Y", "Z", "[", "\\", "]", "^", "_", 48static void gen_word(const psiconv_config config, psiconv_list list,
53 /* 0x60 */ "`", "a", "b", "c", "d", "e", "f", "g", 49 const psiconv_word_f file, const encoding enc);
54 /* 0x68 */ "h", "i", "j", "k", "l", "m", "n", "o", 50static void gen_texted(const psiconv_config config, psiconv_list list,
55 /* 0x70 */ "p", "q", "r", "s", "t", "u", "v", "w", 51 const psiconv_texted_f file, const encoding enc);
56 /* 0x78 */ "x", "y", "z", "{", "|", "}", "~", "", 52static int gen_html4(const psiconv_config config, psiconv_list list,
57 /* 0x80 */ "", "", "&#8218;", "&#402;", 53 const psiconv_file file, const char *dest,
58 "&#8222;", "&#8230;", "&#8224;", "&#8225;", 54 const encoding enc);
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 55
91/* The order of these must match the enum psiconv_border_kind (data.h) */
92static const char *border_strings[] = {
93 "none", "solid", "double", "dotted", "dashed", "dashed", "dotted"
94};
95 56
96/* The order of these must match the enum psiconv_justify (data.h) */ 57void text(const psiconv_config config,psiconv_list list,
97static const char *justify_strings[] = { 58 psiconv_string_t data,const encoding enc)
98 "left", "center", "right", "justify" 59{
99};
100
101/* The order of these must match the enum psiconv_super_sub (data.h) */
102static const char *vertical_strings[] = {
103 "baseline", "super", "sub"
104};
105
106
107/*
108 * Support routines for particular formatting structures
109 */
110
111static void fput_name(FILE * of, const char *string) {
112 int i; 60 int i;
113 61 for (i = 0; i < psiconv_unicode_strlen(data); i++) {
114 for (i = 0; i < strlen(string); i++) 62 if ((data[i] == 0x06) || (data[i] == 0x07) || (data[i] == 0x08))
115 if (isalnum(string[i])) 63 output_simple_chars(config,list,"<BR>",enc);
116 putc(string[i], of); 64 else if ((data[i] == 0x0b) || (data[i] == 0x0c))
65 output_simple_chars(config,list,"-",enc);
66 else if ((data[i] == 0x0f) || (data[i] == 0x09) || (data[i] == 0x0a))
67 output_simple_chars(config,list," ",enc);
68 else if (data[i] >= 0x20)
69 output_char(config,list,data[i],enc);
70 }
117} 71}
118 72
119static void fput_text(FILE * of, const char *text, int length, int *pwasspace) { 73void header(const psiconv_config config, psiconv_list list, const encoding enc)
120 int j; 74{
121 int space; 75 output_simple_chars(config,list,"<!DOCTYPE html PUBLIC "
122 76 "\"-//W3C//DTD HTML 4.01 Transitional//EN\" "
123 for (j = 0; j < length; j++) { 77 "\"http://www.w3.org/TR/html4/loose.dtd\">\n",
124 space = (text[j] == ' '); 78 enc);
125 if (*pwasspace && space) 79 output_simple_chars(config,list,"<HTML>\n",enc);
126 fputs("&nbsp;", of); 80 output_simple_chars(config,list,"<HEAD>\n",enc);
127 else 81 output_simple_chars(config,list,"<META HTTP-EQUIV=\"Content-Type\" "
128 fputs(char_table[(unsigned char) (text[j])], of); 82 "CONTENT=\"text/html; charset=",enc);
129 *pwasspace = space; 83 output_simple_chars(config,list,enc==ENCODING_UTF8?"UTF-8":
84 enc==ENCODING_UCS2?"UTF-16BE":
85 enc==ENCODING_ASCII?"US-ASCII":
86 "",enc);
87 output_simple_chars(config,list,"\">\n",enc);
88 output_simple_chars(config,list,"<TITLE>EPOC32 file "
89 "converted by psiconv</TITLE>\n",enc);
90 output_simple_chars(config,list,"</HEAD>\n",enc);
91 output_simple_chars(config,list,"<BODY>\n",enc);
92}
93
94void footer(const psiconv_config config, psiconv_list list, const encoding enc)
95{
96 output_simple_chars(config,list,"</BODY>\n",enc);
97 output_simple_chars(config,list,"</HTML>\n",enc);
98}
99
100int character_layout_equal(const psiconv_character_layout l1,
101 const psiconv_character_layout l2)
102{
103 int font_size1,font_size2;
104
105 font_size1 = l1->font_size < 8 ?1:
106 l1->font_size < 10 ?2:
107 l1->font_size < 13 ?3:
108 l1->font_size < 17 ?4:
109 l1->font_size < 24 ?5:
110 l1->font_size < 36 ?6:7;
111 font_size2 = l2->font_size < 8 ?1:
112 l2->font_size < 10 ?2:
113 l2->font_size < 13 ?3:
114 l2->font_size < 17 ?4:
115 l2->font_size < 24 ?5:
116 l2->font_size < 36 ?6:7;
117
118 return (l1 && l2 &&
119 (l1->color->red == l2->color->red) &&
120 (l1->color->green == l2->color->green) &&
121 (l1->color->blue == l2->color->blue) &&
122 (font_size1 == font_size2) &&
123 (l1->italic == l2->italic) &&
124 (l1->bold == l2->bold) &&
125 (l1->super_sub == l2->super_sub) &&
126 (l1->underline == l2->underline) &&
127 (l1->strikethrough == l2->strikethrough) &&
128 (l1->font->screenfont == l2->font->screenfont));
129}
130
131void characters(const psiconv_config config, psiconv_list list,
132 const psiconv_string_t textstr,
133 const psiconv_character_layout layout,const encoding enc)
134{
135 char tempstr[TEMPSTR_LEN];
136
137 output_simple_chars(config,list,"<FONT face=\"",enc);
138 output_simple_chars(config,list,
139 layout->font->screenfont == psiconv_font_serif?"serif":
140 layout->font->screenfont == psiconv_font_sansserif?"sans-serif":
141 layout->font->screenfont == psiconv_font_nonprop?"monospace":
142 layout->font->screenfont == psiconv_font_misc?"fantasy":"",
143 enc);
144 output_simple_chars(config,list,"\"",enc);
145
146 if ((layout->font_size < 10) || (layout->font_size >= 13)) {
147 output_simple_chars(config,list," size=",enc);
148 output_simple_chars(config,list,
149 layout->font_size < 8 ?"1":
150 layout->font_size < 10 ?"2":
151 layout->font_size < 13 ?"3":
152 layout->font_size < 17 ?"4":
153 layout->font_size < 24 ?"5":
154 layout->font_size < 36 ?"6":"7",enc);
155 }
156 if ((layout->color->red != 0) || (layout->color->green != 0) ||
157 (layout->color->blue != 0)) {
158 snprintf(tempstr,TEMPSTR_LEN,"%02x%02x%02x",
159 layout->color->red,layout->color->green,layout->color->blue);
160 output_simple_chars(config,list," color=#",enc);
161 output_simple_chars(config,list,tempstr,enc);
162 }
163 output_simple_chars(config,list,">",enc);
164
165
166 if (layout->italic)
167 output_simple_chars(config,list,"<I>",enc);
168 if (layout->bold)
169 output_simple_chars(config,list,"<B>",enc);
170 if (layout->super_sub != psiconv_normalscript)
171 output_simple_chars(config,list,
172 layout->super_sub == psiconv_superscript?"<SUP>":
173 layout->super_sub == psiconv_subscript?"<SUB>":
174 "",enc);
175 if (layout->strikethrough)
176 output_simple_chars(config,list,"<S>",enc);
177 if (layout->underline)
178 output_simple_chars(config,list,"<U>",enc);
179
180 text(config,list,textstr,enc);
181
182 if (layout->underline)
183 output_simple_chars(config,list,"</U>",enc);
184 if (layout->strikethrough)
185 output_simple_chars(config,list,"</S>",enc);
186 if (layout->super_sub != psiconv_normalscript)
187 output_simple_chars(config,list,
188 layout->super_sub == psiconv_superscript?"</SUP>":
189 layout->super_sub == psiconv_subscript?"</SUB>":
190 "",enc);
191 if (layout->bold)
192 output_simple_chars(config,list,"</B>",enc);
193 if (layout->italic)
194 output_simple_chars(config,list,"</I>",enc);
195 output_simple_chars(config,list,"</FONT>",enc);
196}
197
198void paragraph(const psiconv_config config, psiconv_list list,
199 psiconv_paragraph para, const encoding enc)
200{
201 int i,charnr,start,len;
202 psiconv_string_t text;
203 psiconv_in_line_layout layout,next_layout;
204
205
206 output_simple_chars(config,list,
207 para->base_paragraph->bullet->on?"<UL><LI":"<P",enc);
208
209 if (para->base_paragraph->justify_hor == psiconv_justify_centre)
210 output_simple_chars(config,list," align=center",enc);
211 else if (para->base_paragraph->justify_hor == psiconv_justify_right)
212 output_simple_chars(config,list," align=right",enc);
213 else if (para->base_paragraph->justify_hor == psiconv_justify_full)
214 output_simple_chars(config,list," align=justify",enc);
215
216 output_simple_chars(config,list,">",enc);
217
218 if (psiconv_list_length(para->in_lines) == 0) {
219 if (psiconv_unicode_strlen(para->text))
220 characters(config,list,para->text,para->base_character,enc);
221 } else {
222 charnr = 0;
223 start = -1;
224 for (i = 0; i < psiconv_list_length(para->in_lines); i++) {
225 if (start < 0)
226 start = charnr;
227 if (!(layout = psiconv_list_get(para->in_lines,i))) {
228 fputs("Internal data structures corruption\n",stderr);
229 exit(1);
230 }
231 if (i+1 < psiconv_list_length(para->in_lines)) {
232 if (!(next_layout = psiconv_list_get(para->in_lines,i+1))) {
233 fputs("Internal data structures corruption\n",stderr);
234 exit(1);
235 }
236 } else {
237 next_layout = NULL;
238 }
239 if (next_layout &&
240 character_layout_equal(layout->layout,next_layout->layout)) {
241 charnr += layout->length;
242 continue;
243 }
244 len = charnr - start + layout->length;
245 if (len) {
246 if (!(text = malloc(sizeof (*text) * (len + 1)))) {
247 fputs("Out of memory error\n",stderr);
248 exit(1);
249 }
250 memcpy(text,para->text+charnr,len * sizeof(*text));
251 text[len] = 0;
252 characters(config,list,text,layout->layout,enc);
253 free(text);
254 }
255 charnr += layout->length;
256 start = -1;
130 } 257 }
258 }
259 output_simple_chars(config, list,
260 para->base_paragraph->bullet->on?"</UL>\n":"\n",enc);
131} 261}
132 262
133static const char *screenfont_name(psiconv_u8 screenfont) 263void paragraphs(const psiconv_config config, psiconv_list list,
264 psiconv_text_and_layout paragraphs, const encoding enc)
134{ 265{
135 if (screenfont == psiconv_font_sansserif)
136 return "sans-serif";
137 else if (screenfont == psiconv_font_nonprop)
138 return "monospace";
139 else if (screenfont == psiconv_font_serif)
140 return "serif";
141 else
142 return "serif";
143}
144
145static 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; 266 int i;
154 267 psiconv_paragraph para;
155 for (i=0; i < sizeof(sans_font_names) / sizeof(sans_font_names[0]); i++) 268 for (i = 0; i < psiconv_list_length(paragraphs); i++) {
156 if (!strcmp(font_name, sans_font_names[i])) 269 if (!(para = psiconv_list_get(paragraphs,i))) {
157 return "sans-serif"; 270 fputs("Internal datastructure corruption\n",stderr);
158 271 exit(1);
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
166static 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 */
177static 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
187static 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 } 272 }
273 paragraph(config,list,para,enc);
274 }
208} 275}
209 276
210/* Paragraph formats */ 277void gen_word(const psiconv_config config, psiconv_list list,
211static int paragraph_layouts_different( 278 const psiconv_word_f file, const encoding enc)
212 const psiconv_paragraph_layout old,
213 const psiconv_paragraph_layout new)
214{ 279{
215 return ((old->space_above != new->space_above) || 280 if (!file)
216 (old->indent_right != new->indent_right) || 281 return;
217 (old->space_below != new->space_below) ||
218 (old->indent_left != new->indent_left) ||
219 (old->indent_first != new->indent_first) ||
220 (old->justify_hor != new->justify_hor) ||
221 (old->linespacing_exact != new->linespacing_exact) ||
222 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 282
228static void fput_paragraph_layout(FILE * of, 283 header(config,list,enc);
229 const psiconv_paragraph_layout old, 284 paragraphs(config,list,file->paragraphs,enc);
230 const psiconv_paragraph_layout new) 285 footer(config,list,enc);
286}
287
288
289void gen_texted(const psiconv_config config, psiconv_list list,
290 const psiconv_texted_f file, const encoding enc)
231{ 291{
232 if (!old || (old->space_above != new->space_above)) 292 header(config,list,enc);
233 fprintf(of, "margin-top:%.1fpt;", new->space_above); 293 paragraphs(config,list,file->texted_sec->paragraphs,enc);
234 if (!old || (old->indent_right != new->indent_right)) 294 footer(config,list,enc);
235 fprintf(of, "margin-right:%.2fcm;", new->indent_right); 295}
236 if (!old || (old->space_below != new->space_below)) 296
237 fprintf(of, "margin-bottom:%.1fpt;", new->space_below); 297int gen_html4(const psiconv_config config, psiconv_list list,
238 if (!old || 298 const psiconv_file file, const char *dest,
239 (old->bullet->on != new->bullet->on) || 299 const encoding enc)
240 (old->bullet->indent != new->bullet->indent) || 300{
241 (old->indent_left != new->indent_left) || 301 encoding enc1 = enc;
242 (old->indent_first != new->indent_first)) { 302
243 psiconv_length_t indent = new->indent_first; 303 if (enc == ENCODING_PSION) {
244 psiconv_length_t margin = new->indent_left; 304 fputs("Unsupported encoding\n",stderr);
245 /* Bullets with indent set cause strange margin behaviour: */ 305 return -1;
246 if (new->bullet->on && new->bullet->indent) { 306 } else if (enc == ENCODING_ASCII)
247 if (indent > 0.0) { 307 enc1 = ENCODING_ASCII_HTML;
248 margin += indent; 308
249 indent = new->indent_left - indent; 309 if (file->type == psiconv_word_file) {
310 gen_word(config,list,(psiconv_word_f) file->file,enc1);
311 return 0;
312 } else if (file->type == psiconv_texted_file) {
313 gen_texted(config,list,(psiconv_texted_f) file->file,enc1);
314 return 0;
315 } else
316 return -1;
317}
318
319
320static struct fileformat_s fileformats[] =
321 {
322 {
323 "HTML4",
324 "HTML 4.01 Transitional, without CSS",
325 FORMAT_WORD | FORMAT_TEXTED,
326 gen_html4
250 } 327 },
251 } 328 {
252 fprintf(of, "margin-left:%.2fcm;", margin); 329 NULL,
253 fprintf(of, "text-indent:%.2fcm;", indent); 330 NULL,
331 0,
332 NULL
254 } 333 }
255 if (!old || (old->justify_hor != new->justify_hor))
256 fprintf(of, "text-align:%s;", justify_strings[new->justify_hor]);
257 if (!old || (old->linespacing_exact != new->linespacing_exact)) {
258 if (!old || old->linespacing_exact)
259 fputs("line-height:normal;", of);
260 else
261 fprintf(of, "line-height:%.1fpt;", new->linespacing);
262 }
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 */
274static 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 (old->strikethrough != new->strikethrough));
292}
293
294static 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 (old->strikethrough != new->strikethrough)) {
321 fputs("text-decoration:", of);
322 if (new->strikethrough)
323 fputs("line-through ", of);
324 if (new->underline)
325 fputs("underline", of);
326 else if (!new->strikethrough)
327 fputs("none", of);
328 fputs(";", of);
329 }
330}
331
332
333/* Formatted paragraphs */
334static 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
433static 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
450static int psiconv_gen_html4(const char *filename, const psiconv_file file,
451 const char *dest)
452{
453 FILE * of;
454 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 return psiconv_gen_html(filename,file,dest);
464 }
465
466 if (! (of = fopen(filename,"w")))
467 return -1;
468
469 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 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 }
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 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 }
501 fputs("</BODY>\n</HTML>\n", of);
502
503 return fclose(of);
504}
505
506static struct psiconv_fileformat_s ff =
507 {
508 "HTML4",
509 "HTML 4.0 with cascading style sheets",
510 psiconv_gen_html4
511 }; 334 };
512 335
336
513void init_html4(void) 337void init_html4(void)
514{ 338{
339 int i;
340 for (i = 0; fileformats[i].name; i++)
515 psiconv_list_add(fileformat_list,&ff); 341 psiconv_list_add(fileformat_list,fileformats+i);
516} 342}
517

Legend:
Removed from v.140  
changed lines
  Added in v.267

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