/[public]/psiconv/trunk/lib/psiconv/gen_rtf.c
ViewVC logotype

Contents of /psiconv/trunk/lib/psiconv/gen_rtf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9 - (show annotations)
Tue Oct 5 15:33:38 1999 UTC (24 years, 5 months ago) by frodo
File MIME type: text/plain
File size: 17157 byte(s)
(Frodo) Perhaps even slightly functional RTF generator

Most stubs are in, and it should even do something. The generated code is
not validated yet, so it will probably not work. Still many things to do.

1 /*
2 * gen_rtf.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>
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 "data.h"
25 #include "list.h"
26 #include "gen.h"
27
28
29 /*
30 * Various string tables for RTF settings
31 */
32
33 /* Character conversion table */
34 /* TO BE ADJUSTED FOR RTF! */
35 static const char *char_table[0x100] = {
36 /* 0x00 */ "", "", "", "", "", "", "\n", "\n",
37 /* 0x08 */ "\n", "\t", "", "", "", "", "", "",
38 /* 0x10 */ " ", "", "", "", "", "", "", "",
39 /* 0x18 */ "", "", "", "", "", "", "", "",
40 /* 0x20 */ " ", "!", "\"", "#", "$", "%", "&", "'",
41 /* 0x28 */ "(", ")", "*", "+", ",", "-", ".", "/",
42 /* 0x30 */ "0", "1", "2", "3", "4", "5", "6", "7",
43 /* 0x38 */ "8", "9", ":", ";", "<", "=", ">", "?",
44 /* 0x40 */ "@", "A", "B", "C", "D", "E", "F", "G",
45 /* 0x48 */ "H", "I", "J", "K", "L", "M", "N", "O",
46 /* 0x50 */ "P", "Q", "R", "S", "T", "U", "V", "W",
47 /* 0x58 */ "X", "Y", "Z", "[", "\\", "]", "^", "_",
48 /* 0x60 */ "`", "a", "b", "c", "d", "e", "f", "g",
49 /* 0x68 */ "h", "i", "j", "k", "l", "m", "n", "o",
50 /* 0x70 */ "p", "q", "r", "s", "t", "u", "v", "w",
51 /* 0x78 */ "x", "y", "z", "{", "|", "}", "~", "",
52 /* 0x80 */ "", "", ",", "f", ",,", "...", "+", "#",
53 /* 0x88 */ "^", "\176/oo","S", "<", "OE", "", "", "",
54 /* 0x90 */ "", "`", "'", "``", "''", "*", "-", "--",
55 /* 0x98 */ "~", "(TM)", "s", ">", "oe", "", "", "Y",
56 /* 0xa0 */ "\xa0", "\xa1", "\xa2", "\xa3", "\xa4", "\xa5", "\xa6", "\xa7",
57 /* 0xa8 */ "\xa8", "\xa9", "\xaa", "\xab", "\xac", "\xad", "\xae", "\xaf",
58 /* 0xb0 */ "\xb0", "\xb1", "\xb2", "\xb3", "\xb4", "\xb5", "\xb6", "\xb7",
59 /* 0xb8 */ "\xb8", "\xb9", "\xba", "\xbb", "\xbc", "\xbd", "\xbe", "\xbf",
60 /* 0xc0 */ "\xc0", "\xc1", "\xc2", "\xc3", "\xc4", "\xc5", "\xc6", "\xc7",
61 /* 0xc8 */ "\xc8", "\xc9", "\xca", "\xcb", "\xcc", "\xcd", "\xce", "\xcf",
62 /* 0xd0 */ "\xd0", "\xd1", "\xd2", "\xd3", "\xd4", "\xd5", "\xd6", "\xd7",
63 /* 0xd8 */ "\xd8", "\xd9", "\xda", "\xdb", "\xdc", "\xdd", "\xde", "\xdf",
64 /* 0xe0 */ "\xe0", "\xe1", "\xe2", "\xe3", "\xe4", "\xe5", "\xe6", "\xe7",
65 /* 0xe8 */ "\xe8", "\xe9", "\xea", "\xeb", "\xec", "\xed", "\xee", "\xef",
66 /* 0xf0 */ "\xf0", "\xf1", "\xf2", "\xf3", "\xf4", "\xf5", "\xf6", "\xf7",
67 /* 0xf8 */ "\xf8", "\xf9", "\xfa", "\xfb", "\xfc", "\xfd", "\xfe", "\xff",
68 };
69
70
71
72 static void fput_text(FILE * of, const char *text, int length) {
73 int j;
74
75 for (j = 0; j < length; j++) {
76 fputs(char_table[(unsigned char) (text[j])], of);
77 }
78 }
79
80 static int length_to_twips(psiconv_length_t len)
81 {
82 return 1440.0 / 2.54 * len;
83 }
84
85 static int lookup_color(psiconv_list colors,psiconv_color color)
86 {
87 int i;
88 psiconv_color comp;
89 for (i = 0; i < psiconv_list_length(colors); i ++) {
90 comp = * (psiconv_color *) psiconv_list_get(colors,i);
91 if ((comp->red == color->red) && (comp->green == color->green) &&
92 (comp->blue == color->blue))
93 return i;
94 }
95 return -1;
96 }
97
98 static void add_color(psiconv_list colors, psiconv_color color)
99 {
100 if (color)
101 if (lookup_color(colors,color) < 0)
102 psiconv_list_add(colors,&color);
103 }
104
105 static int lookup_font(psiconv_list fonts,psiconv_font font)
106 {
107 int i;
108 psiconv_font comp;
109 for (i = 0; i < psiconv_list_length(fonts); i ++) {
110 comp = *(psiconv_font *) psiconv_list_get(fonts,i);
111 if ((comp->screenfont == font->screenfont) &&
112 ! strcmp(comp->name,font->name))
113 return i;
114 }
115 return -1;
116 }
117
118 static void add_font(psiconv_list fonts, psiconv_font font)
119 {
120 if (font)
121 if (lookup_font(fonts,font) < 0)
122 psiconv_list_add(fonts,&font);
123 }
124
125 static void scan_border(psiconv_list colors,psiconv_list fonts,
126 psiconv_border sec)
127 {
128 if (sec) {
129 add_color(colors,sec->color);
130 }
131 }
132
133 static void scan_bullet(psiconv_list colors,psiconv_list fonts,
134 psiconv_bullet sec)
135 {
136 if (sec) {
137 add_color(colors,sec->color);
138 add_font(fonts,sec->font);
139 }
140 }
141
142 static void scan_paragraph_layout(psiconv_list colors,psiconv_list fonts,
143 psiconv_paragraph_layout sec)
144 {
145 if (sec) {
146 add_color(colors,sec->back_color);
147 scan_bullet(colors,fonts,sec->bullet);
148 scan_border(colors,fonts,sec->left_border);
149 scan_border(colors,fonts,sec->right_border);
150 scan_border(colors,fonts,sec->top_border);
151 scan_border(colors,fonts,sec->bottom_border);
152 }
153 }
154
155 static void scan_character_layout(psiconv_list colors,psiconv_list fonts,
156 psiconv_character_layout sec)
157 {
158 if (sec) {
159 add_color(colors,sec->color);
160 add_color(colors,sec->back_color);
161 add_font(fonts,sec->font);
162 }
163 }
164
165 static void scan_in_line_layout(psiconv_list colors,psiconv_list fonts,
166 psiconv_in_line_layout sec)
167 {
168 if (sec) {
169 scan_character_layout(colors,fonts,sec->layout);
170 }
171 }
172
173 static void scan_in_line_layouts(psiconv_list colors,psiconv_list fonts,
174 psiconv_in_line_layouts sec)
175 {
176 int i;
177 psiconv_in_line_layout layout;
178 if (sec) {
179 for (i = 0; i < psiconv_list_length(sec); i++) {
180 layout = psiconv_list_get(sec,i);
181 scan_in_line_layout(colors,fonts,layout);
182 }
183 }
184 }
185
186 static void scan_paragraph(psiconv_list colors,psiconv_list fonts,
187 psiconv_paragraph sec)
188 {
189 if (sec) {
190 scan_paragraph_layout(colors,fonts,sec->base_paragraph);
191 scan_character_layout(colors,fonts,sec->base_character);
192 scan_in_line_layouts(colors,fonts,sec->in_lines);
193 }
194 }
195
196 static void scan_text_and_layout(psiconv_list colors,psiconv_list fonts,
197 psiconv_text_and_layout sec)
198 {
199 int i;
200 psiconv_paragraph para;
201 if (sec) {
202 for (i = 0; i < psiconv_list_length(sec); i++) {
203 para = psiconv_list_get(sec,i);
204 scan_paragraph(colors,fonts,para);
205 }
206 }
207 }
208
209 static void scan_texted_section(psiconv_list colors,psiconv_list fonts,
210 psiconv_texted_section sec)
211 {
212 if (sec) {
213 scan_text_and_layout(colors,fonts,sec->paragraphs);
214 }
215 }
216
217 static void scan_page_header(psiconv_list colors,psiconv_list fonts,
218 psiconv_page_header sec)
219 {
220 if (sec) {
221 scan_paragraph_layout(colors,fonts,sec->base_paragraph_layout);
222 scan_character_layout(colors,fonts,sec->base_character_layout);
223 scan_texted_section(colors,fonts,sec->text);
224 }
225 }
226
227 static void scan_page_layout_section(psiconv_list colors,psiconv_list fonts,
228 psiconv_page_layout_section sec)
229 {
230 if (sec) {
231 scan_page_header(colors,fonts,sec->header);
232 scan_page_header(colors,fonts,sec->footer);
233 }
234 }
235
236 static void scan_word_style(psiconv_list colors,psiconv_list fonts,
237 psiconv_word_style sec)
238 {
239 if (sec) {
240 scan_character_layout(colors,fonts,sec->character);
241 scan_paragraph_layout(colors,fonts,sec->paragraph);
242 }
243 }
244
245 static void scan_word_style_list(psiconv_list colors,psiconv_list fonts,
246 psiconv_word_style_list sec)
247 {
248 int i;
249 psiconv_word_style style;
250 if (sec) {
251 for (i = 0; i < psiconv_list_length(sec); i++) {
252 style = psiconv_list_get(sec,i);
253 scan_word_style(colors,fonts,style);
254 }
255 }
256 }
257
258 static void scan_word_styles_section(psiconv_list colors,psiconv_list fonts,
259 psiconv_word_styles_section sec)
260 {
261 if (sec) {
262 scan_word_style(colors,fonts,sec->normal);
263 scan_word_style_list(colors,fonts,sec->styles);
264 }
265 }
266
267
268 static void scan_word_f(psiconv_list colors,psiconv_list fonts,
269 psiconv_word_f sec)
270 {
271 if (sec) {
272 scan_page_layout_section(colors,fonts,sec->page_sec);
273 scan_text_and_layout(colors,fonts,sec->paragraphs);
274 scan_word_styles_section(colors,fonts,sec->styles_sec);
275 }
276 }
277
278 static void scan_texted_f(psiconv_list colors,psiconv_list fonts,
279 psiconv_texted_f sec)
280 {
281 if (sec) {
282 scan_page_layout_section(colors,fonts,sec->page_sec);
283 scan_texted_section(colors,fonts,sec->texted_sec);
284 }
285 }
286
287 static void gen_font_table(FILE *of,psiconv_list fonts)
288 {
289 int i;
290 psiconv_font *font;
291
292 fprintf(of,"{\\fonttbl");
293 for (i = 0; i < psiconv_list_length(fonts); i++) {
294 font = psiconv_list_get(fonts,i);
295 fprintf(of,"{\\f%d",i);
296 if ((*font)->screenfont == 1)
297 fprintf(of,"\\fswiss");
298 else if ((*font)->screenfont == 2)
299 fprintf(of,"\\fmodern");
300 else if ((*font)->screenfont == 3)
301 fprintf(of,"\\froman");
302 else
303 fprintf(of,"\\fnil");
304 fprintf(of,"\\cpg1252\\f%s;}",(*font)->name);
305 }
306 fprintf(of,"}\n");
307 }
308
309 static void gen_color_table(FILE *of, psiconv_list colors)
310 {
311 int i;
312 psiconv_color *color;
313
314 fprintf(of,"{\\colortbl");
315 for (i = 0; i < psiconv_list_length(colors); i++) {
316 color = psiconv_list_get(colors,i);
317 fprintf(of,"\\red%d\\green%d\\blue%d;",(*color)->red,
318 (*color)->green, (*color)->blue);
319 }
320 fprintf(of,"}\n");
321 }
322
323 /* This is not necessarily the same as returned by basic_character_layout_status
324 This one is specific for the base point of RTF */
325 static psiconv_character_layout
326 gen_base_char(psiconv_list colors, psiconv_list fonts)
327 {
328 struct psiconv_color white = { 0,0,0 };
329 struct psiconv_color black = { 0xff,0xff,0xff };
330 struct psiconv_font font = { strdup(""),-1 }; /* Pseudo - not added! */
331
332 struct psiconv_character_layout base_char_struct =
333 {
334 &black, /* color */
335 &white, /* back_color */
336 13.0, /* font_size */
337 psiconv_bool_false, /* italic */
338 psiconv_bool_false, /* bold */
339 psiconv_normalscript, /* super_sub */
340 psiconv_bool_false, /* underline */
341 psiconv_bool_false, /* strike_out */
342 &font, /* font */
343 };
344
345 add_color(colors,&white);
346 add_color(colors,&black);
347
348 return psiconv_clone_character_layout(&base_char_struct);
349 }
350
351 void diff_char(FILE *of,psiconv_list colors, psiconv_list fonts,
352 const psiconv_character_layout old,
353 const psiconv_character_layout new)
354 {
355 if ((old->font->screenfont != new->font->screenfont) ||
356 strcmp(old->font->name,new->font->name))
357 fprintf(of,"\\f%d",lookup_font(fonts,new->font));
358 if (old->font_size != new->font_size)
359 fprintf(of,"\\fs%d",(int) (new->font_size * 2));
360 if (old->super_sub != new->super_sub) {
361 if (new->super_sub == psiconv_normalscript)
362 fprintf(of,"\\nosupersub");
363 else if (new->super_sub == psiconv_superscript)
364 fprintf(of,"\\super");
365 else if (new->super_sub == psiconv_subscript)
366 fprintf(of,"\\sub");
367 }
368 if (old->bold != new->bold)
369 fprintf(of,"\\b%s",new->bold?"":"0");
370 if (old->italic != new->italic)
371 fprintf(of,"\\i%s",new->italic?"":"0");
372 if (old->underline != new->underline)
373 fprintf(of,"\\ul%s",new->underline?"":"0");
374 if (old->strike_out != new->strike_out)
375 fprintf(of,"\\strike%s",new->strike_out?"":"0");
376 if ((old->color->red != new->color->red) ||
377 (old->color->green != new->color->green) ||
378 (old->color->blue != new->color->blue))
379 fprintf(of,"\\cf%d",lookup_color(colors,new->color));
380 if ((old->back_color->red != new->back_color->red) ||
381 (old->back_color->green != new->back_color->green) ||
382 (old->back_color->blue != new->back_color->blue))
383 fprintf(of,"\\cb%d",lookup_color(colors,new->back_color));
384 }
385
386
387 /* Note: this generates also some character formatting; Psion Word and
388 RTF do not agree on what is paragraph-level formatting and what is
389 character-level formatting. The character-level formatting is put
390 at the end. This should work out. */
391 static void gen_paragraph_codes(FILE *of, psiconv_list colors,
392 psiconv_list fonts,
393 psiconv_paragraph_layout para)
394 {
395 if (para->indent_first != 0.0)
396 fprintf(of,"\\fl%d",length_to_twips( para->indent_first));
397 if (para->indent_left != 0.0)
398 fprintf(of,"\\ll%d",length_to_twips(para->indent_left));
399 if (para->indent_right != 0.0)
400 fprintf(of,"\\rl%d",length_to_twips(para->indent_right));
401 if (para->justify_hor != psiconv_justify_left) {
402 if (para->justify_hor == psiconv_justify_right)
403 fprintf(of,"\\qr");
404 else if (para->justify_hor == psiconv_justify_centre)
405 fprintf(of,"\\qc");
406 else if (para->justify_hor == psiconv_justify_full)
407 fprintf(of,"\\qj");
408 /*
409 else if (para->justify_hor == psiconv_justify_left)
410 fprintf(of,"\\ql");
411 */
412 }
413 if (para->interline != 0.0)
414 fprintf(of,"\\sl%d",(para->interline_exact?-1:1) *
415 length_to_twips(para->interline));
416 if (para->top_space != 0.0)
417 fprintf(of,"\\sb%d",length_to_twips(para->top_space));
418 if (para->bottom_space != 0.0)
419 fprintf(of,"\\sa%d",length_to_twips(para->bottom_space));
420 if (para->on_one_page)
421 fprintf(of,"\\keep");
422 if (para->together_with)
423 fprintf(of,"\\keepn");
424 if (!para->on_next_page)
425 fprintf(of,"pagebb");
426 if (!para->no_widow_protection)
427 fprintf(of,"\\nowidctlpar");
428 }
429
430
431 static void gen_para(FILE *of, psiconv_list colors, psiconv_list fonts,
432 psiconv_paragraph para)
433 {
434 psiconv_character_layout cur_char,base_char;
435 psiconv_in_line_layout inl;
436 int loc,i,j;
437
438 fprintf(of,"\\par\\pard");
439 gen_paragraph_codes(of,colors,fonts,para->base_paragraph);
440
441 base_char = gen_base_char(colors,fonts);
442 cur_char = base_char;
443
444 if (psiconv_list_length(para->in_lines) == 0) {
445 diff_char(of,colors,fonts,cur_char,para->base_character);
446 cur_char = para->base_character;
447 }
448 loc = 0;
449
450 for (i = 0; i < psiconv_list_length(para->in_lines); i++) {
451 inl = psiconv_list_get(para->in_lines,i);
452 diff_char(of,colors,fonts,cur_char,inl->layout);
453 cur_char = inl->layout;
454 for (j = loc; j < inl->length + loc; j ++) {
455 fputs(char_table[(unsigned char) (para->text[j])],of);
456 }
457 loc = j;
458 }
459
460 if (loc < strlen(para->text)) {
461 diff_char(of,colors,fonts,cur_char,para->base_character);
462 cur_char = para->base_character;
463 for (j = loc; j < strlen(para->text); j ++) {
464 fputs(char_table[(unsigned char) (para->text[j])],of);
465 }
466 }
467
468 psiconv_free_character_layout(base_char);
469 }
470
471 static void gen_text(FILE *of, psiconv_list colors, psiconv_list fonts,
472 psiconv_text_and_layout paragraphs)
473 {
474 int i;
475 psiconv_paragraph para;
476 fprintf(of,"\\sect");
477 for (i = 0; i < psiconv_list_length(paragraphs); i++) {
478 para = psiconv_list_get(paragraphs,i);
479 gen_para(of,colors,fonts,para);
480 }
481 }
482
483 static void psiconv_gen_rtf_word(FILE * of, psiconv_word_f wf)
484 {
485 psiconv_list fonts;
486 psiconv_list colors;
487
488 fonts = psiconv_list_new(sizeof(psiconv_font));
489 colors = psiconv_list_new(sizeof(psiconv_color));
490 scan_word_f(colors,fonts,wf);
491
492 fputs("{\\rtf1\\ansi\n",of);
493 gen_font_table(of,fonts);
494 gen_color_table(of,colors);
495 gen_text(of,colors,fonts,wf->paragraphs);
496 fputs("}\n",of);
497
498 psiconv_list_free(fonts);
499 psiconv_list_free(colors);
500
501 }
502
503 static void psiconv_gen_rtf_texted(FILE * of, psiconv_texted_f tf)
504 {
505 psiconv_list fonts;
506 psiconv_list colors;
507
508 fonts = psiconv_list_new(sizeof(psiconv_font));
509 colors = psiconv_list_new(sizeof(psiconv_color));
510 scan_texted_f(colors,fonts,tf);
511
512 fputs("{\\rtf1\\ansi\n",of);
513 gen_font_table(of,fonts);
514 gen_color_table(of,colors);
515 gen_text(of,colors,fonts,tf->texted_sec->paragraphs);
516 fputs("}\n",of);
517
518 psiconv_list_free(fonts);
519 psiconv_list_free(colors);
520 }
521
522 void psiconv_gen_rtf(FILE * of, psiconv_file file)
523 {
524 if (file->type == psiconv_word_file)
525 psiconv_gen_rtf_word(of,(psiconv_word_f) file->file);
526 else if (file->type == psiconv_texted_file)
527 psiconv_gen_rtf_texted(of,(psiconv_texted_f) file->file);
528 else
529 return;
530 }
531

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