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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 14 - (show annotations)
Mon Oct 11 19:17:17 1999 UTC (24 years, 5 months ago) by frodo
File MIME type: text/plain
File size: 17033 byte(s)
(Frodo) Moved generation stuff out of the library into psiconv

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

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