1 |
/* |
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 |
/* |
22 |
2002/Apr. Keita KAWABE |
23 |
A: <META HTTP-EQUIV="Content-Type" CONTENT="text/html"> header |
24 |
was added. |
25 |
|
26 |
B: Support for narrow build Asian Psions added. |
27 |
If the encoding_type is PSICONV_ENCODING_UTF8, |
28 |
B-1: use utf8_table for character conversion. |
29 |
B-2: add the "Charset=UTF-8" in the Content-Type header. |
30 |
Otherwise proceed as normal. |
31 |
*/ |
32 |
|
33 |
#include "config.h" |
34 |
#include <stdio.h> |
35 |
#include <string.h> |
36 |
#include <ctype.h> |
37 |
#include <stdlib.h> |
38 |
#include "psiconv/data.h" |
39 |
#include "psiconv/list.h" |
40 |
#include "gen.h" |
41 |
#include "psiconv.h" |
42 |
|
43 |
#ifndef TRUE |
44 |
#define TRUE (0==0) |
45 |
#endif |
46 |
|
47 |
#ifdef DMALLOC |
48 |
#include "dmalloc.h" |
49 |
#endif |
50 |
|
51 |
/* |
52 |
* Various string tables for HTML4 settings |
53 |
*/ |
54 |
|
55 |
/* How to display each character */ |
56 |
static const char *char_table[0x100] = { |
57 |
/* 0x00 */ "", "", "", "", "", "", "<BR>\n", "<BR>\n", |
58 |
/* 0x08 */ "\n<HR>\n", "\t", "", "", "", "", "", "", |
59 |
/* 0x10 */ " ", "", "", "", "", "", "", "", |
60 |
/* 0x18 */ "", "", "", "", "", "", "", "", |
61 |
/* 0x20 */ " ", "!", """, "#", "$", "%", "&", "'", |
62 |
/* 0x28 */ "(", ")", "*", "+", ",", "-", ".", "/", |
63 |
/* 0x30 */ "0", "1", "2", "3", "4", "5", "6", "7", |
64 |
/* 0x38 */ "8", "9", ":", ";", "<", "=", ">", "?", |
65 |
/* 0x40 */ "@", "A", "B", "C", "D", "E", "F", "G", |
66 |
/* 0x48 */ "H", "I", "J", "K", "L", "M", "N", "O", |
67 |
/* 0x50 */ "P", "Q", "R", "S", "T", "U", "V", "W", |
68 |
/* 0x58 */ "X", "Y", "Z", "[", "\\", "]", "^", "_", |
69 |
/* 0x60 */ "`", "a", "b", "c", "d", "e", "f", "g", |
70 |
/* 0x68 */ "h", "i", "j", "k", "l", "m", "n", "o", |
71 |
/* 0x70 */ "p", "q", "r", "s", "t", "u", "v", "w", |
72 |
/* 0x78 */ "x", "y", "z", "{", "|", "}", "~", "", |
73 |
/* 0x80 */ "", "", "‚", "ƒ", |
74 |
"„", "…", "†", "‡", |
75 |
/* 0x88 */ "ˆ", "‰", "Š", "<", |
76 |
"Œ", "", "", "", |
77 |
/* 0x90 */ "", "‘", "’", "“", |
78 |
"”","•", "–", "—", |
79 |
/* 0x98 */ "˜", "™", "š", ">", |
80 |
"œ", "", "", "Ÿ", |
81 |
/* 0xa0 */ " ", "¡", "¢", "£", |
82 |
"¤", "¥", "¦", "§", |
83 |
/* 0xa8 */ "¨", "©", "ª", "«", |
84 |
"¬", "­", "®", "¯", |
85 |
/* 0xb0 */ "°", "±", "²", "³", |
86 |
"´", "µ", "¶", "·", |
87 |
/* 0xb8 */ "¸", "¹", "º", "»", |
88 |
"¼", "½", "¾", "¿", |
89 |
/* 0xc0 */ "À", "Á", "Â", "Ã", |
90 |
"Ä", "Å", "Æ", "Ç", |
91 |
/* 0xc8 */ "È", "É", "Ê", "Ë", |
92 |
"Ì", "Í", "Î", "Ï", |
93 |
/* 0xd0 */ "Ð", "Ñ", "Ò", "Ó", |
94 |
"Ô", "Õ", "Ö", "×", |
95 |
/* 0xd8 */ "Ø", "Ù", "Ú", "Û", |
96 |
"Ü", "Ý", "Þ", "ß", |
97 |
/* 0xe0 */ "à", "á", "â", "ã", |
98 |
"ä", "å", "æ", "ç", |
99 |
/* 0xe8 */ "è", "é", "ê", "ë", |
100 |
"ì", "í", "î", "ï", |
101 |
/* 0xf0 */ "ð", "ñ", "ò", "ó", |
102 |
"ô", "õ", "ö", "÷", |
103 |
/* 0xf8 */ "ø", "ù", "ú", "û", |
104 |
"ü", "ý", "þ", "ÿ" |
105 |
}; |
106 |
|
107 |
static const char *utf_table[0x100] = { |
108 |
/* 0x00 */ "", "", "", "", "", "", "<BR>\n", "<BR>\n", |
109 |
/* 0x08 */ "\n<HR>\n", "\t", "", "", "", "", "", "", |
110 |
/* 0x10 */ " ", "", "", "", "", "", "", "", |
111 |
/* 0x18 */ "", "", "", "", "", "", "", "", |
112 |
/* 0x20 */ " ", "!", """, "#", "$", "%", "&", "'", |
113 |
/* 0x28 */ "(", ")", "*", "+", ",", "-", ".", "/", |
114 |
/* 0x30 */ "0", "1", "2", "3", "4", "5", "6", "7", |
115 |
/* 0x38 */ "8", "9", ":", ";", "<", "=", ">", "?", |
116 |
/* 0x40 */ "@", "A", "B", "C", "D", "E", "F", "G", |
117 |
/* 0x48 */ "H", "I", "J", "K", "L", "M", "N", "O", |
118 |
/* 0x50 */ "P", "Q", "R", "S", "T", "U", "V", "W", |
119 |
/* 0x58 */ "X", "Y", "Z", "[", "\\", "]", "^", "_", |
120 |
/* 0x60 */ "`", "a", "b", "c", "d", "e", "f", "g", |
121 |
/* 0x68 */ "h", "i", "j", "k", "l", "m", "n", "o", |
122 |
/* 0x70 */ "p", "q", "r", "s", "t", "u", "v", "w", |
123 |
/* 0x78 */ "x", "y", "z", "{", "|", "}", "~", "", |
124 |
/* 0x80 */ "\x80", "\x81", "\x82", "\x83", "\x84", "\x85", "\x86", "\x87", |
125 |
/* 0x88 */ "\x88", "\x89", "\x8a", "\x8b", "\x8c", "\x8d", "\x8e", "\x8f", |
126 |
/* 0x90 */ "\x90", "\x91", "\x92", "\x93", "\x94", "\x95", "\x96", "\x97", |
127 |
/* 0x98 */ "\x98", "\x99", "\x9a", "\x9b", "\x9c", "\x9d", "\x9e", "\x9f", |
128 |
/* 0xa0 */ "\xa0", "\xa1", "\xa2", "\xa3", "\xa4", "\xa5", "\xa6", "\xa7", |
129 |
/* 0xa8 */ "\xa8", "\xa9", "\xaa", "\xab", "\xac", "\xad", "\xae", "\xaf", |
130 |
/* 0xb0 */ "\xb0", "\xb1", "\xb2", "\xb3", "\xb4", "\xb5", "\xb6", "\xb7", |
131 |
/* 0xb8 */ "\xb8", "\xb9", "\xba", "\xbb", "\xbc", "\xbd", "\xbe", "\xbf", |
132 |
/* 0xc0 */ "\xc0", "\xc1", "\xc2", "\xc3", "\xc4", "\xc5", "\xc6", "\xc7", |
133 |
/* 0xc8 */ "\xc8", "\xc9", "\xca", "\xcb", "\xcc", "\xcd", "\xce", "\xcf", |
134 |
/* 0xd0 */ "\xd0", "\xd1", "\xd2", "\xd3", "\xd4", "\xd5", "\xd6", "\xd7", |
135 |
/* 0xd8 */ "\xd8", "\xd9", "\xda", "\xdb", "\xdc", "\xdd", "\xde", "\xdf", |
136 |
/* 0xe0 */ "\xe0", "\xe1", "\xe2", "\xe3", "\xe4", "\xe5", "\xe6", "\xe7", |
137 |
/* 0xe8 */ "\xe8", "\xe9", "\xea", "\xeb", "\xec", "\xed", "\xee", "\xef", |
138 |
/* 0xf0 */ "\xf0", "\xf1", "\xf2", "\xf3", "\xf4", "\xf5", "\xf6", "\xf7", |
139 |
/* 0xf8 */ "\xf8", "\xf9", "\xfa", "\xfb", "\xfc", "\xfd", "\xfe", "\xff", |
140 |
}; |
141 |
|
142 |
/* a flag to indicate the use of UTF8 */ |
143 |
static psiconv_encoding encoding=PSICONV_ENCODING_CP1252; |
144 |
|
145 |
|
146 |
/* The order of these must match the enum psiconv_border_kind (data.h) */ |
147 |
static const char *border_strings[] = { |
148 |
"none", "solid", "double", "dotted", "dashed", "dashed", "dotted" |
149 |
}; |
150 |
|
151 |
/* The order of these must match the enum psiconv_justify (data.h) */ |
152 |
static const char *justify_strings[] = { |
153 |
"left", "center", "right", "justify" |
154 |
}; |
155 |
|
156 |
/* The order of these must match the enum psiconv_super_sub (data.h) */ |
157 |
static const char *vertical_strings[] = { |
158 |
"baseline", "super", "sub" |
159 |
}; |
160 |
|
161 |
|
162 |
/* |
163 |
* Support routines for particular formatting structures |
164 |
*/ |
165 |
|
166 |
static void fput_name(FILE * of, const char *string) { |
167 |
int i; |
168 |
|
169 |
for (i = 0; i < strlen(string); i++) |
170 |
if (isalnum(string[i])) |
171 |
putc(string[i], of); |
172 |
} |
173 |
|
174 |
static void fput_text(FILE * of, const char *text, int length, int *pwasspace) { |
175 |
int j; |
176 |
int space; |
177 |
char ** table; |
178 |
if (encoding == PSICONV_ENCODING_UTF8){ |
179 |
table = (char**) utf_table; |
180 |
}else{ |
181 |
table=(char**) char_table; |
182 |
} |
183 |
|
184 |
for (j = 0; j < length; j++) { |
185 |
space = (text[j] == ' '); |
186 |
if (*pwasspace && space) |
187 |
fputs(" ", of); |
188 |
else |
189 |
fputs(table[(unsigned char) (text[j])], of); |
190 |
*pwasspace = space; |
191 |
} |
192 |
} |
193 |
|
194 |
static const char *screenfont_name(psiconv_u8 screenfont) |
195 |
{ |
196 |
if (screenfont == psiconv_font_sansserif) |
197 |
return "sans-serif"; |
198 |
else if (screenfont == psiconv_font_nonprop) |
199 |
return "monospace"; |
200 |
else if (screenfont == psiconv_font_serif) |
201 |
return "serif"; |
202 |
else |
203 |
return "serif"; |
204 |
} |
205 |
|
206 |
static const char *generic_font_family(const char *font_name) { |
207 |
static const char *sans_font_names[] = { |
208 |
"Arial", "Univers", "Sans Serif" |
209 |
}; |
210 |
static const char *mono_font_names[] = { |
211 |
"Courier New", "Courier", "Mono", "Lineprinter", "Elite", "Swiss", |
212 |
"Courier (compressed)", "Courier (expanded)", "Letter Gothic" |
213 |
}; |
214 |
int i; |
215 |
|
216 |
for (i=0; i < sizeof(sans_font_names) / sizeof(sans_font_names[0]); i++) |
217 |
if (!strcmp(font_name, sans_font_names[i])) |
218 |
return "sans-serif"; |
219 |
|
220 |
for (i=0; i < sizeof(mono_font_names) / sizeof(mono_font_names[0]); i++) |
221 |
if (!strcmp(font_name, mono_font_names[i])) |
222 |
return "monospace"; |
223 |
|
224 |
return "serif"; |
225 |
} |
226 |
|
227 |
static int colors_different( |
228 |
const psiconv_color old, |
229 |
const psiconv_color new) |
230 |
{ |
231 |
return ((old->red != new->red) || |
232 |
(old->green != new->green) || |
233 |
(old->blue != new->blue)); |
234 |
} |
235 |
|
236 |
|
237 |
/* Borders */ |
238 |
static int borders_different( |
239 |
const psiconv_border old, |
240 |
const psiconv_border new) |
241 |
{ |
242 |
return (!old || |
243 |
(old->kind != new->kind) || |
244 |
colors_different(old->color, new->color) || |
245 |
(old->thickness != new->thickness)); |
246 |
} |
247 |
|
248 |
static void fput_border(FILE * of, |
249 |
const char *which, |
250 |
const psiconv_border old, |
251 |
const psiconv_border new) |
252 |
{ |
253 |
/* If the border changed at all we'll set all parameters, as they're |
254 |
* fairly closely linked and it's much easier to do it this way */ |
255 |
if (borders_different(old, new)) { |
256 |
fprintf(of, "border-%s-style:%s;", |
257 |
which, border_strings[new->kind]); |
258 |
if ((new->kind != psiconv_border_none) && |
259 |
(new->color->red || new->color->green || new->color->blue)) |
260 |
fprintf(of, "border-%s-color:#%02x%02x%02x;", which, |
261 |
new->color->red, new->color->green, new->color->blue); |
262 |
if ((new->kind == psiconv_border_solid) || |
263 |
(new->kind == psiconv_border_double)) |
264 |
fprintf(of, "border-%s-width:%.0fpx;", |
265 |
which, (new->thickness / 10.0) - 1); |
266 |
else if (new->kind != psiconv_border_none) |
267 |
fprintf(of, "border-%s-width:1px;", which); |
268 |
} |
269 |
} |
270 |
|
271 |
/* Paragraph formats */ |
272 |
static int paragraph_layouts_different( |
273 |
const psiconv_paragraph_layout old, |
274 |
const psiconv_paragraph_layout new) |
275 |
{ |
276 |
return ((old->space_above != new->space_above) || |
277 |
(old->indent_right != new->indent_right) || |
278 |
(old->space_below != new->space_below) || |
279 |
(old->indent_left != new->indent_left) || |
280 |
(old->indent_first != new->indent_first) || |
281 |
(old->justify_hor != new->justify_hor) || |
282 |
(old->linespacing_exact != new->linespacing_exact) || |
283 |
borders_different(old->left_border, new->left_border) || |
284 |
borders_different(old->right_border, new->right_border) || |
285 |
borders_different(old->top_border, new->top_border) || |
286 |
borders_different(old->bottom_border, new->bottom_border)); |
287 |
} |
288 |
|
289 |
static void fput_paragraph_layout(FILE * of, |
290 |
const psiconv_paragraph_layout old, |
291 |
const psiconv_paragraph_layout new) |
292 |
{ |
293 |
if (!old || (old->space_above != new->space_above)) |
294 |
fprintf(of, "margin-top:%.1fpt;", new->space_above); |
295 |
if (!old || (old->indent_right != new->indent_right)) |
296 |
fprintf(of, "margin-right:%.2fcm;", new->indent_right); |
297 |
if (!old || (old->space_below != new->space_below)) |
298 |
fprintf(of, "margin-bottom:%.1fpt;", new->space_below); |
299 |
if (!old || |
300 |
(old->bullet->on != new->bullet->on) || |
301 |
(old->bullet->indent != new->bullet->indent) || |
302 |
(old->indent_left != new->indent_left) || |
303 |
(old->indent_first != new->indent_first)) { |
304 |
psiconv_length_t indent = new->indent_first; |
305 |
psiconv_length_t margin = new->indent_left; |
306 |
/* Bullets with indent set cause strange margin behaviour: */ |
307 |
if (new->bullet->on && new->bullet->indent) { |
308 |
if (indent > 0.0) { |
309 |
margin += indent; |
310 |
indent = new->indent_left - indent; |
311 |
} |
312 |
} |
313 |
fprintf(of, "margin-left:%.2fcm;", margin); |
314 |
fprintf(of, "text-indent:%.2fcm;", indent); |
315 |
} |
316 |
if (!old || (old->justify_hor != new->justify_hor)) |
317 |
fprintf(of, "text-align:%s;", justify_strings[new->justify_hor]); |
318 |
if (!old || (old->linespacing_exact != new->linespacing_exact)) { |
319 |
if (!old || old->linespacing_exact) |
320 |
fputs("line-height:normal;", of); |
321 |
else |
322 |
fprintf(of, "line-height:%.1fpt;", new->linespacing); |
323 |
} |
324 |
fput_border(of, "left", old ? old->left_border : NULL, |
325 |
new->left_border); |
326 |
fput_border(of, "right", old ? old->right_border : NULL, |
327 |
new->right_border); |
328 |
fput_border(of, "top", old ? old->top_border : NULL, |
329 |
new->top_border); |
330 |
fput_border(of, "bottom", old ? old->bottom_border : NULL, |
331 |
new->bottom_border); |
332 |
} |
333 |
|
334 |
/* Character formats */ |
335 |
static int character_layouts_different( |
336 |
const psiconv_character_layout old, |
337 |
const psiconv_character_layout new) |
338 |
{ |
339 |
return ((old->font->screenfont != new->font->screenfont) || |
340 |
(strcmp(old->font->name,new->font->name)) || |
341 |
(old->font_size != new->font_size) || |
342 |
(old->color->red != new->color->red) || |
343 |
(old->color->green != new->color->green) || |
344 |
(old->color->blue != new->color->blue) || |
345 |
(old->back_color->red != new->back_color->red) || |
346 |
(old->back_color->green != new->back_color->green) || |
347 |
(old->back_color->blue != new->back_color->blue) || |
348 |
(old->italic != new->italic) || |
349 |
(old->bold != new->bold) || |
350 |
(old->super_sub != new->super_sub) || |
351 |
(old->underline != new->underline) || |
352 |
(old->strikethrough != new->strikethrough)); |
353 |
} |
354 |
|
355 |
static void fput_character_layout(FILE * of, |
356 |
const psiconv_character_layout old, |
357 |
const psiconv_character_layout new, |
358 |
psiconv_word_f wf) |
359 |
{ |
360 |
if (!old || (old->font->screenfont != new->font->screenfont) || |
361 |
strcmp(old->font->name,new->font->name)) { |
362 |
fprintf(of, "font-family:%s,%s,%s;", new->font->name, |
363 |
generic_font_family(new->font->name), |
364 |
screenfont_name(new->font->screenfont)); |
365 |
} |
366 |
if (!old || (old->font_size != new->font_size)) |
367 |
fprintf(of, "font-size:%.1f%%;", 100.0 * new->font_size / 10.0); |
368 |
if (!old || (old->bold != new->bold)) |
369 |
fprintf(of, "font-weight:%s;", new->bold ? "bold" : "normal"); |
370 |
if (!old || (old->italic != new->italic)) |
371 |
fprintf(of, "font-style:%s;", new->italic ? "italic" : "normal"); |
372 |
if (!old || (colors_different(old->color, new->color))) |
373 |
fprintf(of, "color:#%02x%02x%02x;", |
374 |
new->color->red, new->color->green, new->color->blue); |
375 |
if (!old || (colors_different(old->back_color, new->back_color))) |
376 |
fprintf(of, "background-color:#%02x%02x%02x;", |
377 |
new->back_color->red, new->back_color->green, new->back_color->blue); |
378 |
if (!old || (old->super_sub != new->super_sub)) |
379 |
fprintf(of, "vertical-align:%s;", vertical_strings[new->super_sub]); |
380 |
if (!old || (old->underline != new->underline) || |
381 |
(old->strikethrough != new->strikethrough)) { |
382 |
fputs("text-decoration:", of); |
383 |
if (new->strikethrough) |
384 |
fputs("line-through ", of); |
385 |
if (new->underline) |
386 |
fputs("underline", of); |
387 |
else if (!new->strikethrough) |
388 |
fputs("none", of); |
389 |
fputs(";", of); |
390 |
} |
391 |
} |
392 |
|
393 |
|
394 |
/* Formatted paragraphs */ |
395 |
static void fput_para(FILE * of, |
396 |
const psiconv_paragraph para, |
397 |
psiconv_word_f wf) |
398 |
{ |
399 |
psiconv_paragraph_layout base_para = para->base_paragraph; |
400 |
psiconv_character_layout base_char = para->base_character; |
401 |
psiconv_character_layout cur_char; |
402 |
psiconv_character_layout *layout_stack; |
403 |
psiconv_in_line_layout inl; |
404 |
psiconv_word_style sty; |
405 |
int spans = 0; |
406 |
int wasspace = 0; |
407 |
int i, j, loc; |
408 |
char ** table; |
409 |
|
410 |
if (encoding == PSICONV_ENCODING_UTF8){ |
411 |
table= (char**) utf_table; |
412 |
}else{ |
413 |
table= (char**) char_table; |
414 |
} |
415 |
|
416 |
layout_stack = calloc(psiconv_list_length(para->in_lines), |
417 |
sizeof(*layout_stack)); |
418 |
fputs("<P", of); |
419 |
sty = psiconv_get_style(wf->styles_sec, para->base_style); |
420 |
cur_char = sty->character; |
421 |
|
422 |
if (sty->name) { |
423 |
fputs(" CLASS=\"", of); |
424 |
fput_name(of, sty->name); |
425 |
putc('"', of); |
426 |
} |
427 |
|
428 |
if (paragraph_layouts_different(sty->paragraph, base_para) || |
429 |
character_layouts_different(cur_char, base_char)) { |
430 |
fputs(" STYLE=\"", of); |
431 |
fput_paragraph_layout(of, sty->paragraph, base_para); |
432 |
fput_character_layout(of, cur_char, base_char, wf); |
433 |
cur_char = base_char; |
434 |
putc('"', of); |
435 |
} |
436 |
putc('>', of); |
437 |
|
438 |
if (base_para->bullet->on) { |
439 |
fputs("<SPAN STYLE=\"", of); |
440 |
if (base_para->bullet->font != base_char->font) { |
441 |
fprintf(of, "font-family:%s,%s,%s;", |
442 |
base_para->bullet->font->name, |
443 |
generic_font_family(base_para->bullet->font->name), |
444 |
screenfont_name(base_para->bullet->font->screenfont)); |
445 |
} |
446 |
if (base_para->bullet->font_size != base_char->font_size) |
447 |
fprintf(of, "font-size:%.1f%%;", |
448 |
100.0 * base_para->bullet->font_size / 10.0); |
449 |
if ((base_para->bullet->color->red != base_char->color->red) || |
450 |
(base_para->bullet->color->green != base_char->color->green) || |
451 |
(base_para->bullet->color->blue != base_char->color->blue)) |
452 |
fprintf(of, "color:#%02x%02x%02x;", |
453 |
base_para->bullet->color->red, |
454 |
base_para->bullet->color->green, |
455 |
base_para->bullet->color->blue); |
456 |
fprintf(of, "\">%s </SPAN>", |
457 |
table[base_para->bullet->character]); |
458 |
wasspace = TRUE; |
459 |
} |
460 |
|
461 |
loc = 0; |
462 |
for (i = 0; i < psiconv_list_length(para->in_lines); i++) { |
463 |
inl = psiconv_list_get(para->in_lines, i); |
464 |
if (character_layouts_different(cur_char, inl->layout)) { |
465 |
for (j = 0; j < spans; j++) |
466 |
if (!character_layouts_different(inl->layout, layout_stack[j])) |
467 |
break; |
468 |
if (j < spans) { |
469 |
while (spans > j) { |
470 |
fputs("</SPAN>",of); |
471 |
spans--; |
472 |
} |
473 |
} else { |
474 |
fputs("<SPAN STYLE=\"", of); |
475 |
fput_character_layout(of, cur_char, inl->layout, wf); |
476 |
fputs("\">",of); |
477 |
layout_stack[spans++] = cur_char; |
478 |
} |
479 |
cur_char = inl->layout; |
480 |
} |
481 |
fput_text(of, ¶->text[loc], inl->length, &wasspace); |
482 |
loc += inl->length; |
483 |
} |
484 |
|
485 |
while (spans > 0) { |
486 |
fputs("</SPAN>",of); |
487 |
spans--; |
488 |
} |
489 |
|
490 |
if (loc < strlen(para->text)) { |
491 |
fput_text(of, ¶->text[loc], strlen(para->text) - loc, &wasspace); |
492 |
} |
493 |
|
494 |
if (strlen(para->text) == 0) |
495 |
fputs(" ", of); |
496 |
|
497 |
fputs("</P>\n", of); |
498 |
free(layout_stack); |
499 |
} |
500 |
|
501 |
static void fput_style(FILE * of, |
502 |
const psiconv_word_style normal, |
503 |
const psiconv_word_style sty, |
504 |
psiconv_word_f wf) |
505 |
{ |
506 |
if (sty->name == NULL) |
507 |
fputs(" P {", of); |
508 |
else { |
509 |
fputs(" P.", of); |
510 |
fput_name(of, sty->name); |
511 |
fputs(" {", of); |
512 |
} |
513 |
fput_paragraph_layout(of, normal ? normal->paragraph : NULL, sty->paragraph); |
514 |
fput_character_layout(of, normal ? normal->character : NULL, sty->character, wf); |
515 |
fputs("}\n", of); |
516 |
} |
517 |
|
518 |
static int psiconv_gen_html4(const char *filename, const psiconv_file file, |
519 |
const char *dest, const psiconv_encoding encoding_type) |
520 |
{ |
521 |
FILE * of; |
522 |
int i; |
523 |
psiconv_paragraph para; |
524 |
psiconv_word_style normal, sty; |
525 |
psiconv_word_f wf; |
526 |
|
527 |
encoding=encoding_type; |
528 |
|
529 |
if (file->type == psiconv_word_file) |
530 |
wf = file->file; |
531 |
else { |
532 |
/* Fall back on the normal HTML generator */ |
533 |
return psiconv_gen_html(filename,file,dest,encoding_type); |
534 |
} |
535 |
|
536 |
if (! (of = fopen(filename,"w"))) |
537 |
return -1; |
538 |
|
539 |
fputs("<!doctype html public \"-//W3C//DTD HTML 4.0 STRICT//EN\">", of); |
540 |
fputs("\n<HTML>\n<HEAD>\n <META NAME=\"GENERATOR\"", of); |
541 |
fputs(" CONTENT=\"psiconv-" VERSION "\">\n", of); |
542 |
|
543 |
fputs(" <META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html", of); |
544 |
if (encoding == PSICONV_ENCODING_UTF8) |
545 |
fputs("; CHARSET=UTF-8", of); |
546 |
fputs("\">\n", of); |
547 |
|
548 |
if (wf->page_sec->header->text) { |
549 |
if (psiconv_list_length(wf->page_sec->header->text->paragraphs) > 0) { |
550 |
fputs(" <TITLE>", of); |
551 |
para = psiconv_list_get(wf->page_sec->header->text->paragraphs, 0); |
552 |
i = 0; |
553 |
fput_text(of, para->text, strlen(para->text), &i); |
554 |
fputs("</TITLE>\n", of); |
555 |
} |
556 |
} |
557 |
|
558 |
normal = wf->styles_sec->normal; |
559 |
fputs(" <STYLE TYPE=\"text/css\"><!--\n", of); |
560 |
fprintf(of," BODY { background-color: #%02x%02x%02x }\n", |
561 |
normal->paragraph->back_color->red, |
562 |
normal->paragraph->back_color->green, |
563 |
normal->paragraph->back_color->blue); |
564 |
fput_style(of, NULL, normal, wf); |
565 |
for (i = 0; i < psiconv_list_length(wf->styles_sec->styles); i++) { |
566 |
sty = psiconv_list_get(wf->styles_sec->styles, i); |
567 |
fput_style(of, normal, sty, wf); |
568 |
} |
569 |
fputs(" --></STYLE>\n</HEAD>\n<BODY>\n", of); |
570 |
if (wf->page_sec->header->text) { |
571 |
for (i = 0; i < psiconv_list_length(wf->paragraphs); i++) { |
572 |
para = psiconv_list_get(wf->paragraphs, i); |
573 |
fput_para(of, para, wf); |
574 |
} |
575 |
} |
576 |
fputs("</BODY>\n</HTML>\n", of); |
577 |
|
578 |
return fclose(of); |
579 |
} |
580 |
|
581 |
static struct psiconv_fileformat_s ff = |
582 |
{ |
583 |
"HTML4", |
584 |
"HTML 4.0 with cascading style sheets", |
585 |
psiconv_gen_html4 |
586 |
}; |
587 |
|
588 |
void init_html4(void) |
589 |
{ |
590 |
psiconv_list_add(fileformat_list,&ff); |
591 |
} |
592 |
|