1 | /* |
1 | /* |
2 | * gen_rtf.c - Part of psiconv, a PSION 5 file formats converter |
2 | * gen_rtf.c - Part of psiconv, a PSION 5 file formats converter |
3 | * Copyright (c) 1999 Andrew Johnson <anjohnson@iee.org> |
3 | * Copyright (c) 1999 Andrew Johnson <anjohnson@iee.org> |
4 | * Portions Copyright (c) 1999 Frodo Looijaard <frodol@dds.nl> |
4 | * Portions Copyright (c) 1999-2014 Frodo Looijaard <frodo@frodo.looijaard.name> |
5 | * |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
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 |
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 |
8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. |
9 | * (at your option) any later version. |
… | |
… | |
20 | |
20 | |
21 | #include "config.h" |
21 | #include "config.h" |
22 | #include "compat.h" |
22 | #include "compat.h" |
23 | #include <stdio.h> |
23 | #include <stdio.h> |
24 | #include <string.h> |
24 | #include <string.h> |
25 | #include "data.h" |
25 | #include "psiconv/data.h" |
26 | #include "list.h" |
26 | #include "psiconv/list.h" |
27 | #include "gen.h" |
27 | #include "gen.h" |
|
|
28 | #include "psiconv.h" |
|
|
29 | |
|
|
30 | #ifdef DMALLOC |
|
|
31 | #include "dmalloc.h" |
|
|
32 | #endif |
|
|
33 | |
28 | |
34 | |
29 | |
35 | |
30 | /* |
36 | /* |
31 | * Various string tables for RTF settings |
37 | * Various string tables for RTF settings |
32 | */ |
38 | */ |
… | |
… | |
66 | /* 0xe8 */ "\xe8", "\xe9", "\xea", "\xeb", "\xec", "\xed", "\xee", "\xef", |
72 | /* 0xe8 */ "\xe8", "\xe9", "\xea", "\xeb", "\xec", "\xed", "\xee", "\xef", |
67 | /* 0xf0 */ "\xf0", "\xf1", "\xf2", "\xf3", "\xf4", "\xf5", "\xf6", "\xf7", |
73 | /* 0xf0 */ "\xf0", "\xf1", "\xf2", "\xf3", "\xf4", "\xf5", "\xf6", "\xf7", |
68 | /* 0xf8 */ "\xf8", "\xf9", "\xfa", "\xfb", "\xfc", "\xfd", "\xfe", "\xff", |
74 | /* 0xf8 */ "\xf8", "\xf9", "\xfa", "\xfb", "\xfc", "\xfd", "\xfe", "\xff", |
69 | }; |
75 | }; |
70 | |
76 | |
|
|
77 | static const char *utf_table[0x100] = { |
|
|
78 | /* 0x00 */ "", "", "", "", "", "", "\n", "\n", |
|
|
79 | /* 0x08 */ "\n", "\t", "", "", "", "", "", "", |
|
|
80 | /* 0x10 */ " ", "", "", "", "", "", "", "", |
|
|
81 | /* 0x18 */ "", "", "", "", "", "", "", "", |
|
|
82 | /* 0x20 */ " ", "!", "\"", "#", "$", "%", "&", "'", |
|
|
83 | /* 0x28 */ "(", ")", "*", "+", ",", "-", ".", "/", |
|
|
84 | /* 0x30 */ "0", "1", "2", "3", "4", "5", "6", "7", |
|
|
85 | /* 0x38 */ "8", "9", ":", ";", "<", "=", ">", "?", |
|
|
86 | /* 0x40 */ "@", "A", "B", "C", "D", "E", "F", "G", |
|
|
87 | /* 0x48 */ "H", "I", "J", "K", "L", "M", "N", "O", |
|
|
88 | /* 0x50 */ "P", "Q", "R", "S", "T", "U", "V", "W", |
|
|
89 | /* 0x58 */ "X", "Y", "Z", "[", "\\", "]", "^", "_", |
|
|
90 | /* 0x60 */ "`", "a", "b", "c", "d", "e", "f", "g", |
|
|
91 | /* 0x68 */ "h", "i", "j", "k", "l", "m", "n", "o", |
|
|
92 | /* 0x70 */ "p", "q", "r", "s", "t", "u", "v", "w", |
|
|
93 | /* 0x78 */ "x", "y", "z", "{", "|", "}", "~", "", |
|
|
94 | /* 0x80 */ "\x80", "\x81", "\x82", "\x83", "\x84", "\x85", "\x86", "\x87", |
|
|
95 | /* 0x88 */ "\x88", "\x89", "\x8a", "\x8b", "\x8c", "\x8d", "\x8e", "\x8f", |
|
|
96 | /* 0x90 */ "\x90", "\x91", "\x92", "\x93", "\x94", "\x95", "\x96", "\x97", |
|
|
97 | /* 0x98 */ "\x98", "\x99", "\x9a", "\x9b", "\x9c", "\x9d", "\x9e", "\x9f", |
|
|
98 | /* 0xa0 */ "\xa0", "\xa1", "\xa2", "\xa3", "\xa4", "\xa5", "\xa6", "\xa7", |
|
|
99 | /* 0xa8 */ "\xa8", "\xa9", "\xaa", "\xab", "\xac", "\xad", "\xae", "\xaf", |
|
|
100 | /* 0xb0 */ "\xb0", "\xb1", "\xb2", "\xb3", "\xb4", "\xb5", "\xb6", "\xb7", |
|
|
101 | /* 0xb8 */ "\xb8", "\xb9", "\xba", "\xbb", "\xbc", "\xbd", "\xbe", "\xbf", |
|
|
102 | /* 0xc0 */ "\xc0", "\xc1", "\xc2", "\xc3", "\xc4", "\xc5", "\xc6", "\xc7", |
|
|
103 | /* 0xc8 */ "\xc8", "\xc9", "\xca", "\xcb", "\xcc", "\xcd", "\xce", "\xcf", |
|
|
104 | /* 0xd0 */ "\xd0", "\xd1", "\xd2", "\xd3", "\xd4", "\xd5", "\xd6", "\xd7", |
|
|
105 | /* 0xd8 */ "\xd8", "\xd9", "\xda", "\xdb", "\xdc", "\xdd", "\xde", "\xdf", |
|
|
106 | /* 0xe0 */ "\xe0", "\xe1", "\xe2", "\xe3", "\xe4", "\xe5", "\xe6", "\xe7", |
|
|
107 | /* 0xe8 */ "\xe8", "\xe9", "\xea", "\xeb", "\xec", "\xed", "\xee", "\xef", |
|
|
108 | /* 0xf0 */ "\xf0", "\xf1", "\xf2", "\xf3", "\xf4", "\xf5", "\xf6", "\xf7", |
|
|
109 | /* 0xf8 */ "\xf8", "\xf9", "\xfa", "\xfb", "\xfc", "\xfd", "\xfe", "\xff", |
|
|
110 | }; |
71 | |
111 | |
|
|
112 | /* a flag to indicate the use of UTF8 */ |
|
|
113 | static psiconv_encoding encoding= PSICONV_ENCODING_CP1252; |
72 | |
114 | |
73 | static void fput_text(FILE * of, const char *text, int length) { |
115 | static void fput_text(FILE * of, const char *text, int length) { |
74 | int j; |
116 | int j; |
|
|
117 | char ** table; |
|
|
118 | if (encoding == PSICONV_ENCODING_UTF8){ |
|
|
119 | table = (char**) utf_table; |
|
|
120 | }else{ |
|
|
121 | table = (char**) char_table; |
75 | |
122 | } |
76 | for (j = 0; j < length; j++) { |
123 | for (j = 0; j < length; j++) { |
77 | fputs(char_table[(unsigned char) (text[j])], of); |
124 | fputs(table[(unsigned char) (text[j])], of); |
78 | } |
125 | } |
79 | } |
126 | } |
80 | |
127 | |
81 | static int length_to_twips(psiconv_length_t len) |
128 | static int length_to_twips(psiconv_length_t len) |
82 | { |
129 | { |
… | |
… | |
292 | |
339 | |
293 | fprintf(of,"{\\fonttbl"); |
340 | fprintf(of,"{\\fonttbl"); |
294 | for (i = 0; i < psiconv_list_length(fonts); i++) { |
341 | for (i = 0; i < psiconv_list_length(fonts); i++) { |
295 | font = psiconv_list_get(fonts,i); |
342 | font = psiconv_list_get(fonts,i); |
296 | fprintf(of,"{\\f%d",i); |
343 | fprintf(of,"{\\f%d",i); |
297 | if ((*font)->screenfont == 1) |
344 | if ((*font)->screenfont == psiconv_font_sansserif) |
298 | fprintf(of,"\\fswiss"); |
345 | fprintf(of,"\\fswiss"); |
299 | else if ((*font)->screenfont == 2) |
346 | else if ((*font)->screenfont == psiconv_font_nonprop) |
300 | fprintf(of,"\\fmodern"); |
347 | fprintf(of,"\\fmodern"); |
301 | else if ((*font)->screenfont == 3) |
348 | else if ((*font)->screenfont == psiconv_font_serif) |
302 | fprintf(of,"\\froman"); |
349 | fprintf(of,"\\froman"); |
303 | else |
350 | else |
304 | fprintf(of,"\\fnil"); |
351 | fprintf(of,"\\fnil"); |
305 | fprintf(of,"\\cpg1252\\f%s;}",(*font)->name); |
352 | fprintf(of,"\\cpg1252\\f%s;}",(*font)->name); |
306 | } |
353 | } |
… | |
… | |
324 | /* This is not necessarily the same as returned by basic_character_layout_status |
371 | /* This is not necessarily the same as returned by basic_character_layout_status |
325 | This one is specific for the base point of RTF */ |
372 | This one is specific for the base point of RTF */ |
326 | static psiconv_character_layout |
373 | static psiconv_character_layout |
327 | gen_base_char(psiconv_list colors, psiconv_list fonts) |
374 | gen_base_char(psiconv_list colors, psiconv_list fonts) |
328 | { |
375 | { |
329 | struct psiconv_color white = { 0,0,0 }; |
376 | struct psiconv_color_s white = { 0,0,0 }; |
330 | struct psiconv_color black = { 0xff,0xff,0xff }; |
377 | struct psiconv_color_s black = { 0xff,0xff,0xff }; |
331 | struct psiconv_font font = { NULL,-1 }; /* Pseudo - not added! */ |
378 | struct psiconv_font_s font = { NULL,-1 }; /* Pseudo - not added! */ |
332 | |
379 | |
333 | struct psiconv_character_layout base_char_struct = |
380 | struct psiconv_character_layout_s base_char_struct = |
334 | { |
381 | { |
335 | &black, /* color */ |
382 | &black, /* color */ |
336 | &white, /* back_color */ |
383 | &white, /* back_color */ |
337 | 13.0, /* font_size */ |
384 | 13.0, /* font_size */ |
338 | psiconv_bool_false, /* italic */ |
385 | psiconv_bool_false, /* italic */ |
339 | psiconv_bool_false, /* bold */ |
386 | psiconv_bool_false, /* bold */ |
340 | psiconv_normalscript, /* super_sub */ |
387 | psiconv_normalscript, /* super_sub */ |
341 | psiconv_bool_false, /* underline */ |
388 | psiconv_bool_false, /* underline */ |
342 | psiconv_bool_false, /* strike_out */ |
389 | psiconv_bool_false, /* strikethrough */ |
343 | &font, /* font */ |
390 | &font, /* font */ |
344 | }; |
391 | }; |
345 | |
392 | |
346 | font.name = strdup(""); |
393 | font.name = strdup(""); |
347 | add_color(colors,&white); |
394 | add_color(colors,&white); |
… | |
… | |
371 | fprintf(of,"\\b%s",new->bold?"":"0"); |
418 | fprintf(of,"\\b%s",new->bold?"":"0"); |
372 | if (old->italic != new->italic) |
419 | if (old->italic != new->italic) |
373 | fprintf(of,"\\i%s",new->italic?"":"0"); |
420 | fprintf(of,"\\i%s",new->italic?"":"0"); |
374 | if (old->underline != new->underline) |
421 | if (old->underline != new->underline) |
375 | fprintf(of,"\\ul%s",new->underline?"":"0"); |
422 | fprintf(of,"\\ul%s",new->underline?"":"0"); |
376 | if (old->strike_out != new->strike_out) |
423 | if (old->strikethrough != new->strikethrough) |
377 | fprintf(of,"\\strike%s",new->strike_out?"":"0"); |
424 | fprintf(of,"\\strike%s",new->strikethrough?"":"0"); |
378 | if ((old->color->red != new->color->red) || |
425 | if ((old->color->red != new->color->red) || |
379 | (old->color->green != new->color->green) || |
426 | (old->color->green != new->color->green) || |
380 | (old->color->blue != new->color->blue)) |
427 | (old->color->blue != new->color->blue)) |
381 | fprintf(of,"\\cf%d",lookup_color(colors,new->color)); |
428 | fprintf(of,"\\cf%d",lookup_color(colors,new->color)); |
382 | if ((old->back_color->red != new->back_color->red) || |
429 | if ((old->back_color->red != new->back_color->red) || |
… | |
… | |
410 | /* |
457 | /* |
411 | else if (para->justify_hor == psiconv_justify_left) |
458 | else if (para->justify_hor == psiconv_justify_left) |
412 | fprintf(of,"\\ql"); |
459 | fprintf(of,"\\ql"); |
413 | */ |
460 | */ |
414 | } |
461 | } |
415 | if (para->interline != 0.0) |
462 | if (para->linespacing != 0.0) |
416 | fprintf(of,"\\sl%d",(para->interline_exact?-1:1) * |
463 | fprintf(of,"\\sl%d",(para->linespacing_exact?-1:1) * |
417 | length_to_twips(para->interline)); |
464 | length_to_twips(para->linespacing)); |
418 | if (para->top_space != 0.0) |
465 | if (para->space_above != 0.0) |
419 | fprintf(of,"\\sb%d",length_to_twips(para->top_space)); |
466 | fprintf(of,"\\sb%d",length_to_twips(para->space_above)); |
420 | if (para->bottom_space != 0.0) |
467 | if (para->space_below != 0.0) |
421 | fprintf(of,"\\sa%d",length_to_twips(para->bottom_space)); |
468 | fprintf(of,"\\sa%d",length_to_twips(para->space_below)); |
422 | if (para->on_one_page) |
469 | if (para->keep_together) |
423 | fprintf(of,"\\keep"); |
470 | fprintf(of,"\\keep"); |
424 | if (para->together_with) |
471 | if (para->keep_with_next) |
425 | fprintf(of,"\\keepn"); |
472 | fprintf(of,"\\keepn"); |
426 | if (!para->on_next_page) |
473 | if (!para->on_next_page) |
427 | fprintf(of,"pagebb"); |
474 | fprintf(of,"pagebb"); |
428 | if (!para->no_widow_protection) |
475 | if (!para->no_widow_protection) |
429 | fprintf(of,"\\nowidctlpar"); |
476 | fprintf(of,"\\nowidctlpar"); |
… | |
… | |
435 | { |
482 | { |
436 | psiconv_character_layout cur_char,base_char; |
483 | psiconv_character_layout cur_char,base_char; |
437 | psiconv_in_line_layout inl; |
484 | psiconv_in_line_layout inl; |
438 | int loc,i,j; |
485 | int loc,i,j; |
439 | |
486 | |
|
|
487 | char ** table; |
|
|
488 | if (encoding == PSICONV_ENCODING_UTF8){ |
|
|
489 | table = (char**) utf_table; |
|
|
490 | }else{ |
|
|
491 | table = (char**) char_table; |
|
|
492 | } |
|
|
493 | |
440 | fprintf(of,"\\par\\pard"); |
494 | fprintf(of,"\\par\\pard"); |
441 | gen_paragraph_codes(of,colors,fonts,para->base_paragraph); |
495 | gen_paragraph_codes(of,colors,fonts,para->base_paragraph); |
442 | |
496 | |
443 | base_char = gen_base_char(colors,fonts); |
497 | base_char = gen_base_char(colors,fonts); |
444 | cur_char = base_char; |
498 | cur_char = base_char; |
… | |
… | |
452 | for (i = 0; i < psiconv_list_length(para->in_lines); i++) { |
506 | for (i = 0; i < psiconv_list_length(para->in_lines); i++) { |
453 | inl = psiconv_list_get(para->in_lines,i); |
507 | inl = psiconv_list_get(para->in_lines,i); |
454 | diff_char(of,colors,fonts,cur_char,inl->layout); |
508 | diff_char(of,colors,fonts,cur_char,inl->layout); |
455 | cur_char = inl->layout; |
509 | cur_char = inl->layout; |
456 | for (j = loc; j < inl->length + loc; j ++) { |
510 | for (j = loc; j < inl->length + loc; j ++) { |
457 | fputs(char_table[(unsigned char) (para->text[j])],of); |
511 | fputs(table[(unsigned char) (para->text[j])],of); |
458 | } |
512 | } |
459 | loc = j; |
513 | loc = j; |
460 | } |
514 | } |
461 | |
515 | |
462 | if (loc < strlen(para->text)) { |
516 | if (loc < strlen(para->text)) { |
463 | diff_char(of,colors,fonts,cur_char,para->base_character); |
517 | diff_char(of,colors,fonts,cur_char,para->base_character); |
464 | cur_char = para->base_character; |
518 | cur_char = para->base_character; |
465 | for (j = loc; j < strlen(para->text); j ++) { |
519 | for (j = loc; j < strlen(para->text); j ++) { |
466 | fputs(char_table[(unsigned char) (para->text[j])],of); |
520 | fputs(table[(unsigned char) (para->text[j])],of); |
467 | } |
521 | } |
468 | } |
522 | } |
469 | |
523 | |
470 | psiconv_free_character_layout(base_char); |
524 | psiconv_free_character_layout(base_char); |
471 | } |
525 | } |
… | |
… | |
519 | |
573 | |
520 | psiconv_list_free(fonts); |
574 | psiconv_list_free(fonts); |
521 | psiconv_list_free(colors); |
575 | psiconv_list_free(colors); |
522 | } |
576 | } |
523 | |
577 | |
524 | void psiconv_gen_rtf(FILE * of, psiconv_file file) |
578 | static int psiconv_gen_rtf(const char *filename, const psiconv_file file, |
|
|
579 | const char *dest, const psiconv_encoding encoding_type) |
525 | { |
580 | { |
|
|
581 | FILE *of = fopen(filename,"w"); |
|
|
582 | if (! of) |
|
|
583 | return -1; |
|
|
584 | |
|
|
585 | encoding = encoding_type; |
526 | if (file->type == psiconv_word_file) |
586 | if (file->type == psiconv_word_file) { |
527 | psiconv_gen_rtf_word(of,(psiconv_word_f) file->file); |
587 | psiconv_gen_rtf_word(of,(psiconv_word_f) file->file); |
528 | else if (file->type == psiconv_texted_file) |
588 | } else if (file->type == psiconv_texted_file) { |
529 | psiconv_gen_rtf_texted(of,(psiconv_texted_f) file->file); |
589 | psiconv_gen_rtf_texted(of,(psiconv_texted_f) file->file); |
530 | else |
590 | } else { |
|
|
591 | fclose(of); |
531 | return; |
592 | return -1; |
|
|
593 | } |
|
|
594 | return fclose(of); |
532 | } |
595 | } |
533 | |
596 | |
|
|
597 | static struct psiconv_fileformat_s ff = |
|
|
598 | { |
|
|
599 | "RTF", |
|
|
600 | "Rich Text Format (not functional yet!)", |
|
|
601 | psiconv_gen_rtf |
|
|
602 | }; |
|
|
603 | |
|
|
604 | void init_rtf(void) |
|
|
605 | { |
|
|
606 | /* psiconv_list_add(fileformat_list,&ff); */ |
|
|
607 | } |
|
|
608 | |