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

Legend:
Removed from v.142  
changed lines
  Added in v.192

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