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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 24 - (show 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 /*
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 #include "compat.h"
22 #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 } 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 } 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 }
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