1 /*
2     parse_page.c - Part of psiconv, a PSION 5 file formats converter
3     Copyright (c) 1999-2014  Frodo Looijaard <frodo@frodo.looijaard.name>
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 
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include "parse_routines.h"
27 #include "error.h"
28 
29 #ifdef DMALLOC
30 #include <dmalloc.h>
31 #endif
32 
33 
psiconv_parse_page_header(const psiconv_config config,const psiconv_buffer buf,int lev,psiconv_u32 off,int * length,psiconv_page_header * result)34 int psiconv_parse_page_header(const psiconv_config config,
35                               const psiconv_buffer buf,int lev,psiconv_u32 off,
36                               int *length,psiconv_page_header *result)
37 {
38   int res = 0;
39   int len = 0;
40   int i,leng,has_content;
41   psiconv_u32 temp;
42 
43   psiconv_progress(config,lev+1,off,"Going to read a page header (or footer)");
44   if (!(*result = malloc(sizeof(**result))))
45     goto ERROR1;
46 
47   psiconv_progress(config,lev+2,off+len,
48                    "Going to read the has_content flag");
49   temp = psiconv_read_u8(config,buf,lev+2,off+len,&res);
50   if (res)
51     goto ERROR2;
52   if (temp == 0x00)
53     has_content = 0;
54   else if (temp == 0x01)
55     has_content = 1;
56   else {
57     psiconv_warn(config,lev+2,off+len,
58                "Page header has_content flag unknown value (assumed default)");
59     psiconv_debug(config,lev+2,off+len,"Flag: %02x",temp);
60     has_content = 1;
61   }
62   psiconv_debug(config,lev+2,off+len,"Has_content flag: %02x",has_content);
63   len += 1;
64 
65   psiconv_progress(config,lev+2,off+len,"Going to read displayed-on-first-page flag");
66   if ((res = psiconv_parse_bool(config,buf,lev+2,off+len,&leng,
67                                 &(*result)->on_first_page)))
68     goto ERROR2;
69   len += leng;
70 
71   psiconv_progress(config,lev+2,off+len,"Going to read three zero bytes");
72   for (i = 0; i < 0x03; i++,len++) {
73     temp = psiconv_read_u8(config,buf,lev+2,off+len,&res);
74     if (res)
75       goto ERROR2;
76     if (temp != 0x00) {
77       psiconv_warn(config,lev+2,off+len,
78                    "Page Header unknown value in zero bytes section");
79       psiconv_debug(config,lev+2,off+len,"Byte %d: read %02x, expected %02x",
80                     i,temp,0x00);
81     }
82   }
83 
84   psiconv_progress(config,lev+2,off+len,"Going to read base paragraph layout");
85   if (!((*result)->base_paragraph_layout = psiconv_basic_paragraph_layout()))
86     goto ERROR2;
87 
88   if (has_content) {
89     if ((res = psiconv_parse_paragraph_layout_list(config,buf,lev+2,off+len,&leng,
90                                              (*result)->base_paragraph_layout)))
91       goto ERROR3;
92     len += leng;
93   }
94 
95   psiconv_progress(config,lev+2,off+len,"Going to read base character layout");
96   if (!((*result)->base_character_layout = psiconv_basic_character_layout()))
97     goto ERROR3;
98   if (has_content) {
99     if ((res = psiconv_parse_character_layout_list(config,buf,lev+2,off+len,&leng,
100                                              (*result)->base_character_layout)))
101       goto ERROR4;
102   }
103   len += leng;
104 
105 
106   psiconv_progress(config,lev+2,off+len,"Going to read the TextEd section");
107   if (has_content) {
108     if ((res = psiconv_parse_texted_section(config,buf,lev+2,off+len,&leng,
109                                         &(*result)->text,
110                                         (*result)->base_character_layout,
111                                         (*result)->base_paragraph_layout)))
112       goto ERROR4;
113     len += leng;
114   } else {
115     (*result)->text = NULL;
116   }
117 
118   if (length)
119     *length = len;
120 
121   psiconv_progress(config,lev+1,off+len-1,"End of page header"
122                    "(total length: %08x", len);
123 
124   return res;
125 
126 ERROR4:
127   psiconv_free_character_layout((*result)->base_character_layout);
128 ERROR3:
129   psiconv_free_paragraph_layout((*result)->base_paragraph_layout);
130 ERROR2:
131   free (*result);
132 ERROR1:
133   psiconv_error(config,lev+1,off,"Reading of Page Header failed");
134   if (length)
135     *length = 0;
136   if (!res)
137     return -PSICONV_E_NOMEM;
138   else
139     return res;
140 }
141 
psiconv_parse_page_layout_section(const psiconv_config config,const psiconv_buffer buf,int lev,psiconv_u32 off,int * length,psiconv_page_layout_section * result)142 int psiconv_parse_page_layout_section(const psiconv_config config,
143                                       const psiconv_buffer buf,int lev,
144                                       psiconv_u32 off, int *length,
145                                       psiconv_page_layout_section *result)
146 {
147   int res = 0;
148   int len = 0;
149   int leng;
150   psiconv_u32 temp;
151 
152   psiconv_progress(config,lev+1,off,"Going to read the page layout section");
153   if (!(*result = malloc(sizeof(**result))))
154     goto ERROR1;
155 
156   psiconv_progress(config,lev+2,off+len,"Going to read first page number");
157   (*result)->first_page_nr = psiconv_read_u32(config,buf,lev+2,off+len,&res);
158   if (res)
159     goto ERROR2;
160   psiconv_debug(config,lev+2,off+len,"First page: %d",(*result)->first_page_nr);
161   len += 4;
162 
163   psiconv_progress(config,lev+2,off+len,"Going to read header distance");
164   (*result)->header_dist = psiconv_read_length(config,buf,lev+2,off+len,&leng,&res);
165   if (res)
166     goto ERROR2;
167   psiconv_debug(config,lev+2,off+len,"Header distance: %6.3f",(*result)->header_dist);
168   len += leng;
169 
170   psiconv_progress(config,lev+2,off+len,"Going to read footer distance");
171   (*result)->footer_dist = psiconv_read_length(config,buf,lev+2,off+len,&leng,&res);
172   if (res)
173     goto ERROR2;
174   psiconv_debug(config,lev+2,off+len,"Footer distance: %6.3f",(*result)->footer_dist);
175   len += leng;
176 
177   psiconv_progress(config,lev+2,off+len,"Going to read the left margin");
178   (*result)->left_margin = psiconv_read_length(config,buf,lev+2,off+len,&leng,&res);
179   if (res)
180     goto ERROR2;
181   psiconv_debug(config,lev+2,off+len,"Left margin: %6.3f",(*result)->left_margin);
182   len += leng;
183 
184   psiconv_progress(config,lev+2,off+len,"Going read the to right margin");
185   (*result)->right_margin = psiconv_read_length(config,buf,lev+2,off+len,&leng,&res);
186   if (res)
187     goto ERROR2;
188   psiconv_debug(config,lev+2,off+len,"Right margin: %6.3f",(*result)->right_margin);
189   len += leng;
190 
191   psiconv_progress(config,lev+2,off+len,"Going to read the top margin");
192   (*result)->top_margin = psiconv_read_length(config,buf,lev+2,off+len,&leng,&res);
193   if (res)
194     goto ERROR2;
195   psiconv_debug(config,lev+2,off+len,"Top margin: %6.3f",(*result)->top_margin);
196   len += leng;
197 
198   psiconv_progress(config,lev+2,off+len,"Going to read the bottom margin");
199   (*result)->bottom_margin = psiconv_read_length(config,buf,lev+2,off+len,&leng,&res);
200   if (res)
201     goto ERROR2;
202   psiconv_debug(config,lev+2,off+len,"Bottom margin: %6.3f",(*result)->bottom_margin);
203   len += leng;
204 
205   psiconv_progress(config,lev+2,off+len,"Going to read the header");
206   if ((res = psiconv_parse_page_header(config,buf,lev+2,off+len,&leng,
207                                        &(*result)->header)))
208     goto ERROR2;
209   len += leng;
210 
211   psiconv_progress(config,lev+2,off+len,"Going to read the footer");
212   if ((res = psiconv_parse_page_header(config,buf,lev+2,off+len,&leng,
213                                        &(*result)->footer)))
214     goto ERROR3;
215   len += leng;
216 
217   psiconv_progress(config,lev+2,off+len,"Going to read page dimensions id");
218   temp = psiconv_read_u32(config,buf,lev+2,off+len,&res);
219   if (res)
220     goto ERROR4;
221   if ((temp != PSICONV_ID_PAGE_DIMENSIONS1) &&
222        (temp != PSICONV_ID_PAGE_DIMENSIONS2)) {
223     psiconv_warn(config,lev+2,off+len,
224                  "Page layout section page dimensions marker not found");
225     psiconv_debug(config,lev+2,off+len,
226                   "Page dimensions marker: read %08x, expected %08x or %08x",
227                   temp, PSICONV_ID_PAGE_DIMENSIONS1,
228                   PSICONV_ID_PAGE_DIMENSIONS2);
229   }
230   len += 4;
231 
232   psiconv_progress(config,lev+2,off+len,"Going to read the page width");
233   (*result)->page_width = psiconv_read_length(config,buf,lev+2,off+len,&leng,&res);
234   if (res)
235     goto ERROR4;
236   psiconv_debug(config,lev+2,off+len,"Page width: %6.3f",(*result)->page_width);
237   len += leng;
238 
239   psiconv_progress(config,lev+2,off+len,"Going to read the page height");
240   (*result)->page_height = psiconv_read_length(config,buf,lev+2,off+len,&leng,&res);
241   if (res)
242     goto ERROR4;
243   psiconv_debug(config,lev+2,off+len,"Page height: %6.3f",(*result)->page_height);
244   len += leng;
245 
246   psiconv_progress(config,lev+2,off+len,"Going to read page portrait/landscape");
247   if ((res = psiconv_parse_bool(config,buf,lev+2,off+len,&leng,&(*result)->landscape)))
248     goto ERROR4;
249   psiconv_debug(config,lev+2,off+len,"Landscape: %d",(*result)->landscape);
250   len += leng;
251 
252 
253   if (length)
254     *length = len;
255 
256   psiconv_progress(config,lev,off+len-1,"End of page section (total length: %08x)",
257                    len);
258 
259   return res;
260 
261 ERROR4:
262   psiconv_free_page_header((*result)->footer);
263 ERROR3:
264   psiconv_free_page_header((*result)->header);
265 ERROR2:
266   free (*result);
267 ERROR1:
268   psiconv_error(config,lev+1,off,"Reading of Page Section failed");
269   if (length)
270     *length = 0;
271   if (!res)
272     return -PSICONV_E_NOMEM;
273   else
274     return res;
275 }
276