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

Annotation of /psiconv/trunk/program/psiconv/gen_rtf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 58 - (hide annotations)
Sun Dec 10 16:49:40 2000 UTC (23 years, 3 months ago) by frodo
File MIME type: text/plain
File size: 17623 byte(s)
(Frodo) Revamped directory structure, rescues a few files from CVS limbo

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

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