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

Annotation of /psiconv/trunk/lib/psiconv/parse_common.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 24 - (hide annotations)
Fri Oct 29 21:14:58 1999 UTC (24 years, 5 months ago) by frodo
File MIME type: text/plain
File size: 22075 byte(s)
(Frodo) Sketch files are now supported. That is, they are parsed, and
        generated, but generating still needs a lot of work. Untested.

1 frodo 2 /*
2     parse_common.c - Part of psiconv, a PSION 5 file formats converter
3     Copyright (c) 1999 Frodo Looijaard <frodol@dds.nl>
4    
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9    
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13     GNU General Public License for more details.
14    
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18     */
19    
20     #include "config.h"
21 frodo 20 #include "compat.h"
22 frodo 2 #include <stdlib.h>
23     #include <string.h>
24    
25     #include "data.h"
26     #include "parse_routines.h"
27    
28     static int psiconv_parse_layout_section(const psiconv_buffer buf,
29     int lev,psiconv_u32 off,
30     int *length,
31     psiconv_text_and_layout result,
32     psiconv_word_styles_section styles,
33     int with_styles);
34    
35     int psiconv_parse_header_section(const psiconv_buffer buf,int lev,
36     psiconv_u32 off, int *length,
37     psiconv_header_section *result)
38     {
39     int res=0;
40     int len=0;
41     psiconv_u32 temp;
42    
43     psiconv_progress(lev+1,off+len,"Going to read the header section");
44     (*result) = malloc(sizeof(**result));
45    
46     psiconv_progress(lev+2,off+len,"Going to read UID1 to UID3");
47     (*result)->uid1 = psiconv_read_u32(buf,lev+2,off+len);
48     psiconv_debug(lev+2,off+len,"UID1: %08x",(*result)->uid1);
49     if ((*result)->uid1 != PSICONV_ID_PSION5) {
50     psiconv_warn(lev+2,off+len,"UID1 has unknown value. This is probably "
51     "not a (parsable) Psion 5 file");
52     res = -1;
53     }
54     len += 4;
55     (*result)->uid2 = psiconv_read_u32(buf,lev+2,off+len);
56     psiconv_debug(lev+2,off+len,"UID2: %08x",(*result)->uid2);
57     len += 4;
58     (*result)->uid3 = psiconv_read_u32(buf,lev+2,off+len);
59     psiconv_debug(lev+2,off+len,"UID3: %08x",(*result)->uid3);
60     len += 4;
61    
62     (*result)->file = psiconv_unknown_file;
63     if ((*result)->uid1 == PSICONV_ID_PSION5) {
64     if ((*result)->uid2 == PSICONV_ID_DATA_FILE) {
65     if ((*result)->uid3 == PSICONV_ID_WORD) {
66     (*result)->file = psiconv_word_file;
67     psiconv_debug(lev+2,off+len,"File is a Word file");
68     } else if ((*result)->uid3 == PSICONV_ID_TEXTED) {
69     (*result)->file = psiconv_texted_file;
70     psiconv_debug(lev+2,off+len,"File is a TextEd file");
71 frodo 24 } else if ((*result)->uid3 == PSICONV_ID_SKETCH) {
72     (*result)->file = psiconv_sketch_file;
73     psiconv_debug(lev+2,off+len,"File is a Sketch file");
74     }
75 frodo 12 } else if ((*result)->uid2 == PSICONV_ID_MBM_FILE) {
76     (*result)->file = psiconv_mbm_file;
77     if ((*result)->uid3 != 0x00)
78     psiconv_warn(lev+2,off+len,"UID3 set in MBM file?!?");
79     psiconv_debug(lev+2,off+len,"File is a MBM file");
80     }
81 frodo 2 }
82     if ((*result)->file == psiconv_unknown_file) {
83     psiconv_warn(lev+2,off+len,"Unknown file type");
84     (*result)->file = psiconv_unknown_file;
85     }
86    
87     psiconv_progress(lev+2,off+len,"Checking UID4");
88     temp = psiconv_read_u32(buf,lev+2,off+len);
89     if (temp == psiconv_checkuid((*result)->uid1,(*result)->uid2,
90     (*result)->uid3))
91     psiconv_debug(lev+2,off+len,"Checksum %08x is correct",temp);
92     else {
93     psiconv_warn(lev+2,off+len,"Checksum failed, file corrupted!");
94     psiconv_debug(lev+2,off+len,"Expected checksum %08x, found %08x",
95     psiconv_checkuid((*result)->uid1,(*result)->uid2,
96     (*result)->uid3),temp);
97     res = -1;
98     }
99     len += 4;
100    
101     if (length)
102     *length = len;
103    
104     psiconv_progress(lev+1,off+len-1,
105     "End of Header Section (total length: %08x)",len);
106    
107     return res;
108     }
109    
110     int psiconv_parse_section_table_section(const psiconv_buffer buf, int lev,
111     psiconv_u32 off, int *length,
112     psiconv_section_table_section *result)
113     {
114     int res=0;
115     int len=0;
116     psiconv_section_table_entry entry;
117    
118     int i;
119     psiconv_u8 nr;
120    
121     psiconv_progress(lev+1,off+len,"Going to read the section table section");
122     *result = psiconv_list_new(sizeof(*entry));
123    
124     psiconv_progress(lev+2,off+len,"Going to read the section table length");
125     nr = psiconv_read_u8(buf,lev+2,off+len);
126     psiconv_debug(lev+2,off+len,"Length: %08x",nr);
127     if (nr & 0x01) {
128     psiconv_warn(lev+2,off+len,
129     "Section table length odd - ignoring last entry");
130     res = -1;
131     }
132     len ++;
133    
134     psiconv_progress(lev+2,off+len,"Going to read the section table entries");
135     entry = malloc(sizeof(*entry));
136     for (i = 0; i < nr / 2; i++) {
137     entry->id = psiconv_read_u32(buf,lev+2,off + len);
138     psiconv_debug(lev+2,off + len,"Entry %d: ID = %08x",i,entry->id);
139     len += 0x04;
140     entry->offset = psiconv_read_u32(buf,lev+2,off + len);
141     psiconv_debug(lev+2,off +len,"Entry %d: Offset = %08x",i,entry->offset);
142     len += 0x04;
143     psiconv_list_add(*result,entry);
144     }
145    
146     free(entry);
147    
148     if (length)
149     *length = len;
150    
151     psiconv_progress(lev+1,off+len-1,"End of section table section "
152     "(total length: %08x", len);
153    
154     return res;
155     }
156    
157     int psiconv_parse_application_id_section(const psiconv_buffer buf, int lev,
158     psiconv_u32 off, int *length,
159     psiconv_application_id_section *result)
160     {
161     int res=0;
162     int len=0;
163     int leng;
164    
165     psiconv_progress(lev+1,off,"Going to read the application id section");
166     (*result) = malloc(sizeof(**result));
167    
168     psiconv_progress(lev+2,off+len,"Going to read the type identifier");
169     (*result)->id = psiconv_read_u32(buf,lev+2,off+len);
170     psiconv_debug(lev+2,off+len,"Identifier: %08x",(*result)->id);
171     len += 4;
172    
173     psiconv_progress(lev+2,off+len,"Going to read the application id string");
174     (*result)->name = psiconv_read_string(buf,lev+2,off+len,&leng);
175     len += leng;
176    
177     if (length)
178     *length = len;
179    
180     psiconv_progress(lev+1,off+len-1,"End of application id section "
181     "(total length: %08x", len);
182    
183     return res;
184     }
185    
186     int psiconv_parse_text_section(const psiconv_buffer buf,int lev,psiconv_u32 off,
187     int *length,psiconv_text_and_layout *result)
188     {
189    
190     int res = 0;
191     int len=0;
192    
193     psiconv_u32 text_len;
194     psiconv_paragraph para;
195    
196     int nr;
197     int i,j,start,leng;
198     char *str_copy;
199    
200     psiconv_progress(lev+1,off,"Going to parse the text section");
201     psiconv_progress(lev+2,off,"Reading the text length");
202     text_len = psiconv_read_X(buf,lev+2,off,&leng);
203     psiconv_debug(lev+2,off,"Length: %08x",text_len);
204     len += leng;
205    
206     *result = psiconv_list_new(sizeof(*para));
207     para = malloc(sizeof(*para));
208    
209     psiconv_progress(lev+2,off+len,"Going to read all paragraph text");
210     nr = 0;
211     start = 0;
212     for (i = 0; i < text_len; i++)
213     if (psiconv_read_u8(buf,lev+2,off+len+i) == 0x06) {
214     para->text = malloc(i - start + 1);
215     for (j = 0; j < i - start; j++)
216     para->text[j] = psiconv_read_u8(buf,lev+1,off + len + start + j);
217     para->text[j] = 0;
218    
219     psiconv_list_add(*result,para);
220    
221     str_copy = psiconv_make_printable(para->text);
222     psiconv_debug(lev+2,off+i+len,"Line %d: %d characters",nr,
223     strlen(str_copy) +1);
224     psiconv_debug(lev+2,off+i+len,"Line %d: `%s'",nr,str_copy);
225     free(str_copy);
226    
227     start = i + 1;
228     nr ++;
229     }
230    
231     if (start != text_len) {
232     res = -1;
233     psiconv_warn(lev+2,off+start+len,
234     "Last line does not end on EOL (%d characters left)", len - start);
235     para->text = malloc(text_len - start + 1);
236     for (j = 0; j < text_len - start; j++)
237     para->text[j] = psiconv_read_u8(buf,lev+2,off + start + j + len);
238     para->text[text_len - start] = 0;
239     psiconv_list_add(*result,para);
240     str_copy = psiconv_make_printable(para->text);
241     psiconv_debug(lev+2,off+start+len,"Last line: %d characters",nr,
242     strlen(str_copy)+1);
243     psiconv_debug(lev+2,off+start+len,"Last line: `%s'",str_copy);
244     free(str_copy);
245     }
246    
247     free(para);
248    
249     /* Initialize the remaining parts of each paragraph */
250     for (i = 0; i < psiconv_list_length(*result); i ++) {
251     para = psiconv_list_get(*result,i);
252     para->in_lines = psiconv_list_new(sizeof(struct psiconv_in_line_layout));
253     para->replacements = psiconv_list_new(sizeof(struct psiconv_replacement));
254     para->base_style = 0;
255     para->base_character = psiconv_basic_character_layout();
256     para->base_paragraph = psiconv_basic_paragraph_layout();
257     }
258    
259    
260     len += text_len;
261    
262     if (length)
263     *length = len;
264    
265     psiconv_progress(lev+1,off+len-1,"End of text section (total length: %08x",
266     len);
267    
268     return res;
269     }
270    
271     /* First do a parse_text_section, or you will get into trouble here */
272     int psiconv_parse_layout_section(const psiconv_buffer buf,
273     int lev,psiconv_u32 off,
274     int *length,
275     psiconv_text_and_layout result,
276     psiconv_word_styles_section styles,
277     int with_styles)
278     {
279     int res = 0;
280     int len = 0;
281     psiconv_u32 temp;
282     int parse_styles,nr,i,j,total,leng,line_length;
283    
284     typedef struct anon_style
285     {
286     int nr;
287     psiconv_s16 base_style;
288     psiconv_character_layout character;
289     psiconv_paragraph_layout paragraph;
290     } *anon_style;
291    
292     typedef psiconv_list anon_style_list; /* of struct anon_style */
293    
294     anon_style_list anon_styles;
295     struct anon_style anon;
296     anon_style anon_ptr=NULL;
297    
298     psiconv_paragraph para;
299     struct psiconv_in_line_layout in_line;
300    
301     int *inline_count;
302    
303    
304     psiconv_progress(lev+1,off,"Going to read the layout section");
305    
306     psiconv_progress(lev+2,off,"Going to read the section type");
307     temp = psiconv_read_u16(buf,lev+2,off+len);
308     psiconv_debug(lev+2,off+len,"Type: %02x",temp);
309     parse_styles = with_styles;
310     if ((temp == 0x0001) && !with_styles) {
311     psiconv_warn(lev+2,off+len,"Styleless layout section expected, "
312     "but styled section found!");
313     parse_styles = 1;
314     res = -1;
315     } else if ((temp == 0x0000) && (with_styles)) {
316     psiconv_warn(lev+2,off+len,"Styled layout section expected, "
317     "but styleless section found!");
318     parse_styles = 0;
319     res = -1;
320     } else if ((temp != 0x0000) && (temp != 0x0001)) {
321     psiconv_warn(lev+2,off+len,
322     "Layout section type indicator has unknown value!");
323     res = -1;
324     }
325     len += 0x02;
326    
327     psiconv_progress(lev+2,off+len,"Going to read paragraph type list");
328     anon_styles = psiconv_list_new(sizeof(anon));
329     psiconv_progress(lev+3,off+len,"Going to read paragraph type list length");
330     nr = psiconv_read_u8(buf,lev+3,off+len);
331     psiconv_debug(lev+3,off+len,"Length: %02x",nr);
332     len ++;
333    
334     psiconv_progress(lev+3,off+len,
335     "Going to read the paragraph type list elements");
336     for (i = 0; i < nr; i ++) {
337     psiconv_progress(lev+3,off+len,"Element %d",i);
338     anon.nr = psiconv_read_u32(buf,lev+4,off+len);
339     psiconv_debug(lev+4,off+len,"Number: %08x",anon.nr);
340     len += 0x04;
341    
342     psiconv_progress(lev+4,off,"Going to determine the base style");
343     if (parse_styles) {
344     anon.base_style = psiconv_read_u8(buf,lev+3,
345     off+len+4+psiconv_read_u32(buf,lev+4,
346     off+len));
347     psiconv_debug(lev+4,off+len+psiconv_read_u32(buf,lev+4,off+len),
348     "Style indicator: %02x",anon.base_style);
349     } else
350     anon.base_style = 0;
351     anon.paragraph = psiconv_clone_paragraph_layout(psiconv_get_style
352     (styles,anon.base_style)->paragraph);
353     anon.character = psiconv_clone_character_layout(psiconv_get_style
354     (styles,anon.base_style)->character);
355    
356     psiconv_progress(lev+4,off+len,"Going to read the paragraph layout");
357     res |= psiconv_parse_paragraph_layout_list(buf,lev+4,off+len,&leng,
358     anon.paragraph);
359     len += leng;
360     if (parse_styles)
361     len ++;
362    
363     psiconv_progress(lev+4,off+len,"Going to read the character layout");
364     res |= psiconv_parse_character_layout_list(buf,lev+4,off+len,&leng,
365     anon.character);
366     len += leng;
367     psiconv_list_add(anon_styles,&anon);
368     }
369    
370     psiconv_progress(lev+2,off+len,"Going to parse the paragraph element list");
371     psiconv_progress(lev+3,off+len,"Going to read the number of paragraphs");
372     nr = psiconv_read_u32(buf,lev+3,off+len);
373     if (nr != psiconv_list_length(result)) {
374     psiconv_warn(lev+3,off+len,
375     "Number of text paragraphs and paragraph elements does not match");
376     psiconv_debug(lev+3,off+len,
377     "%d text paragraphs, %d paragraph elements",
378     psiconv_list_length(result),nr);
379     }
380     psiconv_debug(lev+3,off+len,"Number of paragraphs: %d",nr);
381     len += 4;
382     inline_count = malloc(nr * sizeof(*inline_count));
383    
384     psiconv_progress(lev+3,off+len,"Going to read the paragraph elements");
385     for (i = 0; i < nr; i ++) {
386     psiconv_progress(lev+3,off+len,"Element %d",i);
387     if (i >= psiconv_list_length(result)) {
388     psiconv_debug(lev+4,off+len,"Going to allocate a new element");
389     para = malloc(sizeof(*para));
390     para->in_lines = psiconv_list_new(sizeof(struct psiconv_in_line_layout));
391     para->base_style = 0;
392     para->base_character = psiconv_basic_character_layout();
393     para->base_paragraph = psiconv_basic_paragraph_layout();
394     free(para);
395     }
396     para = psiconv_list_get(result,i);
397    
398     psiconv_progress(lev+4,off+len,"Going to read the paragraph length");
399     temp = psiconv_read_u32(buf,lev+4,off+len);
400     if (temp != strlen(para->text)+1) {
401     res = -1;
402     psiconv_warn(lev+4,off+len,
403     "Disagreement of the length of paragraph in layout section");
404     psiconv_debug(lev+4,off+len,
405     "Paragraph length: layout section says %d, counted %d",
406     temp,strlen(para->text)+1);
407     } else
408     psiconv_debug(lev+4,off+len,"Paragraph length: %d",temp);
409     len += 4;
410    
411     psiconv_progress(lev+4,off+len,"Going to read the paragraph type");
412     temp = psiconv_read_u8(buf,lev+4,off+len);
413     if (temp != 0x00) {
414     psiconv_debug(lev+4,off+len,"Type: %02x",temp);
415     for (j = 0; j < psiconv_list_length(anon_styles); j++) {
416     anon_ptr = psiconv_list_get(anon_styles,j);
417     if (temp == anon_ptr->nr)
418     break;
419     }
420     if (j == psiconv_list_length(anon_styles)) {
421     psiconv_warn(lev+4,off+len,"Layout section paragraph type unknown");
422     psiconv_debug(lev+4,off+len,"Unknown type - using base styles instead");
423     para->base_style = 0;
424     psiconv_free_paragraph_layout(para->base_paragraph);
425     psiconv_free_character_layout(para->base_character);
426     para->base_paragraph = psiconv_clone_paragraph_layout(psiconv_get_style
427     (styles,0)->paragraph);
428     para->base_character = psiconv_clone_character_layout(psiconv_get_style
429     (styles,0)->character);
430     } else {
431     para->base_style = anon_ptr->base_style;
432     psiconv_free_paragraph_layout(para->base_paragraph);
433     psiconv_free_character_layout(para->base_character);
434     para->base_paragraph = psiconv_clone_paragraph_layout
435     (anon_ptr->paragraph);
436     para->base_character = psiconv_clone_character_layout
437     (anon_ptr->character);
438     }
439     inline_count[i] = 0;
440     len += 0x01;
441     } else {
442     psiconv_debug(lev+4,off+len,"Type: %02x (not based on a paragraph type)"
443     ,temp);
444     len += 0x01;
445     if (parse_styles) {
446     psiconv_progress(lev+4,off+len+psiconv_read_u32(buf,lev+4,off+len),
447     "Going to read the paragraph element base style");
448     temp = psiconv_read_u8(buf,lev+4,
449     off+len+psiconv_read_u32(buf,lev+4,off+len));
450     psiconv_debug(lev+4,off+len+psiconv_read_u32(buf,lev+4,off+len),
451     "Style: %02x",temp);
452     } else
453     temp = 0x00;
454     psiconv_free_paragraph_layout(para->base_paragraph);
455     psiconv_free_character_layout(para->base_character);
456     para->base_paragraph = psiconv_clone_paragraph_layout(psiconv_get_style
457     (styles,temp)->paragraph);
458     para->base_character = psiconv_clone_character_layout(psiconv_get_style
459     (styles,temp)->character);
460     para->base_style = temp;
461     psiconv_progress(lev+4,off+len,"Going to read paragraph layout");
462     psiconv_parse_paragraph_layout_list(buf,lev+4,off+len,&leng,
463     para->base_paragraph);
464     len += leng;
465     if (parse_styles)
466     len += 1;
467     psiconv_progress(lev+4,off+len,"Going to read number of in-line "
468     "layout elements");
469     inline_count[i] = psiconv_read_u32(buf,lev+4,off+len);
470     psiconv_debug(lev+4,off+len,"Nr: %08x",inline_count[i]);
471     len += 4;
472     }
473     }
474    
475     psiconv_progress(lev+2,off+len,"Going to read the text layout inline list");
476    
477     psiconv_progress(lev+3,off+len,"Going to read the number of elements");
478     nr = psiconv_read_u32(buf,lev+3,off+len);
479     psiconv_debug(lev+3,off,"Elements: %08x",nr);
480     len += 0x04;
481    
482     psiconv_progress(lev+3,off+len,
483     "Going to read the text layout inline elements");
484     total = 0;
485     for (i = 0; i < psiconv_list_length(result); i++) {
486     para = psiconv_list_get(result,i);
487     line_length = -1;
488     for (j = 0; j < inline_count[i]; j++) {
489     psiconv_progress(lev+3,off+len,"Element %d: Paragraph %d, element %d",
490     total,i,j);
491     if (total >= nr) {
492     psiconv_warn(lev+3,off+len,
493     "Layout section inlines: not enough element");
494     res = -1;
495     psiconv_debug(lev+3,off+len,"Can't read element!");
496     } else {
497     total ++;
498     in_line.layout = psiconv_clone_character_layout(para->base_character);
499     psiconv_progress(lev+4,off+len,"Going to read the element type");
500     temp = psiconv_read_u8(buf,lev+4,len+off);
501     len += 1;
502     psiconv_debug(lev+4,off,"Type: %02x",temp);
503     psiconv_progress(lev+4,off,
504     "Going to read the number of characters it applies to");
505     in_line.length = psiconv_read_u32(buf,lev+4,len+off);
506     psiconv_debug(lev+4,off+len,"Length: %02x",in_line.length);
507     len += 4;
508     psiconv_progress(lev+4,off+len,"Going to read the character layout");
509     res |= psiconv_parse_character_layout_list(buf,lev+4,off+len,&leng,
510     in_line.layout);
511     len += leng;
512    
513     if (temp == 0x01) {
514     psiconv_debug(lev+4,off+len,"Skipping object data");
515     len += 0x10;
516     } else if (temp != 0x00) {
517     psiconv_warn(lev+4,off+len,"Layout section unknown inline type");
518     res = -1;
519     }
520     if (line_length + in_line.length > strlen(para->text)) {
521     psiconv_warn(lev+4,off+len,
522     "Layout section inlines: line length mismatch");
523     res = -1;
524     in_line.length = strlen(para->text) - line_length;
525     }
526     line_length += in_line.length;
527     psiconv_list_add(para->in_lines,&in_line);
528     }
529     }
530     }
531    
532     if (total != nr) {
533     psiconv_warn(lev+4,off+len,
534     "Layout section too many inlines, skipping remaining");
535     }
536    
537     free(inline_count);
538    
539     for (i = 0 ; i < psiconv_list_length(anon_styles); i ++) {
540     anon_ptr = psiconv_list_get(anon_styles,i);
541     psiconv_free_character_layout(anon_ptr->character);
542     psiconv_free_paragraph_layout(anon_ptr->paragraph);
543     }
544     psiconv_list_free(anon_styles);
545    
546     if (length)
547     *length = len;
548    
549     psiconv_progress(lev+1,off+len-1,"End of layout section (total length: %08x",
550     len);
551    
552     return res;
553     }
554    
555     int psiconv_parse_styled_layout_section(const psiconv_buffer buf,
556     int lev,psiconv_u32 off,
557     int *length,
558     psiconv_text_and_layout result,
559     psiconv_word_styles_section styles)
560     {
561     return psiconv_parse_layout_section(buf,lev,off,length,result,styles,1);
562     }
563    
564     int psiconv_parse_styleless_layout_section(const psiconv_buffer buf,
565     int lev,psiconv_u32 off,
566     int *length,
567     psiconv_text_and_layout result,
568     psiconv_character_layout base_char,
569     psiconv_paragraph_layout base_para)
570     {
571     int res;
572     psiconv_word_styles_section styles_section;
573    
574     styles_section = malloc(sizeof(*styles_section));
575     styles_section->normal = malloc(sizeof(*styles_section->normal));
576     styles_section->normal->character = psiconv_clone_character_layout(base_char);
577     styles_section->normal->paragraph = psiconv_clone_paragraph_layout(base_para);
578     styles_section->normal->hotkey = 0;
579     styles_section->normal->name = strdup("");
580     styles_section->styles = psiconv_list_new(sizeof(struct psiconv_word_style));
581    
582     res = psiconv_parse_layout_section(buf,lev,off,length,result,
583     styles_section,0);
584    
585     psiconv_free_word_styles_section(styles_section);
586     return res;
587     }
588    

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