1 /*
2     generate_common.c - Part of psiconv, a PSION 5 file formats converter
3     Copyright (c) 2000-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 #include <stdlib.h>
23 #include <string.h>
24 
25 #include "generate_routines.h"
26 #include "error.h"
27 
28 #ifdef DMALLOC
29 #include <dmalloc.h>
30 #endif
31 
32 static int psiconv_write_layout_section(const psiconv_config config,
33                            psiconv_buffer buf, int lev,
34                            const psiconv_text_and_layout value,
35                            const psiconv_word_styles_section styles,
36                            int with_styles);
37 
38 /* Maybe use a psiconv_header_section variable instead? */
psiconv_write_header_section(const psiconv_config config,psiconv_buffer buf,int lev,psiconv_u32 uid1,psiconv_u32 uid2,psiconv_u32 uid3)39 int psiconv_write_header_section(const psiconv_config config,
40                                  psiconv_buffer buf,int lev,psiconv_u32 uid1,
41                                  psiconv_u32 uid2, psiconv_u32 uid3)
42 {
43   int res;
44   psiconv_progress(config,lev,0,"Writing header section");
45   if ((res = psiconv_write_u32(config,buf,lev+1,uid1)))
46     goto ERROR;
47   if ((res = psiconv_write_u32(config,buf,lev+1,uid2)))
48     goto ERROR;
49   if ((res = psiconv_write_u32(config,buf,lev+1,uid3)))
50     goto ERROR;
51   if ((res =  psiconv_write_u32(config,buf,lev+1,
52 	                        psiconv_checkuid(uid1,uid2,uid3))))
53     goto ERROR;
54   psiconv_progress(config,lev,0,"End of header section");
55   return 0;
56 
57 ERROR:
58   psiconv_error(config,lev,0,"Writing of header section failed");
59   return res;
60 }
61 
psiconv_write_section_table_section(const psiconv_config config,psiconv_buffer buf,int lev,const psiconv_section_table_section value)62 int psiconv_write_section_table_section(const psiconv_config config,
63                                     psiconv_buffer buf,int lev,
64                                     const psiconv_section_table_section value)
65 {
66   int res,i;
67   psiconv_section_table_entry entry;
68 
69   psiconv_progress(config,lev,0,"Writing section table section");
70   if (!value) {
71     psiconv_error(config,lev,0,"Null section table section");
72     res = -PSICONV_E_GENERATE;
73     goto ERROR;
74   }
75 
76   if ((res = psiconv_write_u8(config,buf,lev+1,2 * psiconv_list_length(value))))
77     goto ERROR;
78   for (i = 0; i < psiconv_list_length(value); i++) {
79     if (!(entry = psiconv_list_get(value,i))) {
80       psiconv_error(config,lev+1,0,"Data structure corruption");
81       res = -PSICONV_E_NOMEM;
82       goto ERROR;
83     }
84     if ((res = psiconv_write_u32(config,buf,lev+1,entry->id)))
85       goto ERROR;
86     if ((res = psiconv_write_offset(config,buf,lev+1,entry->offset)))
87       goto ERROR;
88   }
89   psiconv_progress(config,lev,0,"End of section table section");
90   return -PSICONV_E_OK;
91 
92 ERROR:
93   psiconv_error(config,lev,0,"Writing of section table section failed");
94   return res;
95 }
96 
psiconv_write_application_id_section(const psiconv_config config,psiconv_buffer buf,int lev,psiconv_u32 id,const psiconv_string_t text)97 int psiconv_write_application_id_section(const psiconv_config config,
98                                         psiconv_buffer buf,int lev,psiconv_u32 id,
99                                         const psiconv_string_t text)
100 {
101   int res;
102   psiconv_progress(config,lev,0,"Writing application id section");
103   if ((res = psiconv_write_u32(config,buf,lev+1,id)))
104     goto ERROR;
105   if ((res = psiconv_write_string(config,buf,lev+1,text)))
106     goto ERROR;
107   psiconv_progress(config,lev,0,"End of application id section");
108   return 0;
109 ERROR:
110   psiconv_error(config,lev,0,"Writing of application id section failed");
111   return res;
112 }
113 
psiconv_write_text_section(const psiconv_config config,psiconv_buffer buf,int lev,const psiconv_text_and_layout value)114 int psiconv_write_text_section(const psiconv_config config,
115                            psiconv_buffer buf,int lev,
116                            const psiconv_text_and_layout value)
117 {
118   int res;
119   psiconv_buffer extra_buf = NULL;
120   int i,j;
121   psiconv_paragraph paragraph;
122 
123   psiconv_progress(config,lev,0,"Writing text section");
124   if (!value) {
125     psiconv_error(config,lev+1,0,"Null text section");
126     res = -PSICONV_E_GENERATE;
127     goto ERROR;
128   }
129 
130   if (psiconv_list_length(value)) {
131     if (!(extra_buf = psiconv_buffer_new())) {
132       psiconv_error(config,lev+1,0,"Out of memory error");
133       res = -PSICONV_E_NOMEM;
134       goto ERROR;
135     }
136     for (i = 0; i < psiconv_list_length(value); i++) {
137       if (!(paragraph = psiconv_list_get(value,i))) {
138         psiconv_error(config,lev+1,0,"Data structure corruption");
139         res = -PSICONV_E_NOMEM;
140         goto ERROR;
141       }
142       for (j = 0; j < psiconv_unicode_strlen(paragraph->text); j++)
143 	if ((res = psiconv_unicode_write_char(config,extra_buf,lev+1,
144                                               paragraph->text[j])))
145           goto ERROR;
146       psiconv_unicode_write_char(config,extra_buf,lev+1,0x06);
147     }
148     if ((res = psiconv_write_X(config,buf,lev+1,psiconv_buffer_length(extra_buf))))
149       goto ERROR;
150     res = psiconv_buffer_concat(buf,extra_buf);
151   } else
152     /* Hack: empty text sections are just not allowed */
153     if ((res = psiconv_write_u16(config,buf,lev+1,0x0602)))
154       goto ERROR;
155 
156   psiconv_progress(config,lev,0,"End of text section");
157   return 0;
158 
159 ERROR:
160   if (extra_buf)
161     psiconv_buffer_free(extra_buf);
162   psiconv_error(config,lev,0,"Writing of text section failed");
163   return res;
164 }
165 
psiconv_write_layout_section(const psiconv_config config,psiconv_buffer buf,int lev,const psiconv_text_and_layout value,const psiconv_word_styles_section styles,int with_styles)166 int psiconv_write_layout_section(const psiconv_config config,
167                            psiconv_buffer buf,int lev,
168                            const psiconv_text_and_layout value,
169                            const psiconv_word_styles_section styles,
170                            int with_styles)
171 {
172   typedef struct psiconv_paragraph_type_list_s
173   {
174     psiconv_character_layout character;
175     psiconv_paragraph_layout paragraph;
176     psiconv_u8 style;
177     psiconv_u8 nr;
178   } *psiconv_paragraph_type_list;
179   psiconv_u32 obj_id;
180   psiconv_list paragraph_type_list; /* Of psiconv_paragraph_type_list_s */
181   psiconv_paragraph_type_list paragraph_type;
182   struct psiconv_paragraph_type_list_s new_type;
183   psiconv_buffer buf_types,buf_elements,buf_inlines,buf_objects;
184   psiconv_paragraph paragraph;
185   psiconv_in_line_layout in_line = NULL;
186   psiconv_word_style style;
187   psiconv_character_layout para_charlayout;
188   int i,j,para_type,nr_of_inlines=0,res,ptl_length,pel_length,thislen,paralen;
189 
190   psiconv_progress(config,lev,0,"Writing layout section");
191   if (!value) {
192     psiconv_error(config,lev,0,"Null text section");
193     res = -PSICONV_E_GENERATE;
194     goto ERROR1;
195   }
196 
197   if (!(paragraph_type_list = psiconv_list_new(sizeof(new_type)))) {
198     psiconv_error(config,lev+1,0,"Out of memory error");
199     res = -PSICONV_E_NOMEM;
200     goto ERROR1;
201   }
202 
203   if (!(buf_types = psiconv_buffer_new())) {
204     psiconv_error(config,lev+1,0,"Out of memory error");
205     res = -PSICONV_E_NOMEM;
206     goto ERROR2;
207   }
208 
209   if (!(buf_elements = psiconv_buffer_new())) {
210     psiconv_error(config,lev+1,0,"Out of memory error");
211     res = -PSICONV_E_NOMEM;
212     goto ERROR3;
213   }
214 
215   if (!(buf_inlines = psiconv_buffer_new())) {
216     psiconv_error(config,lev+1,0,"Out of memory error");
217     res = -PSICONV_E_NOMEM;
218     goto ERROR4;
219   }
220 
221   if (!(buf_objects = psiconv_buffer_new())) {
222     psiconv_error(config,lev+1,0,"Out of memory error");
223     res = -PSICONV_E_NOMEM;
224     goto ERROR5;
225   }
226 
227   for (i = 0; i < psiconv_list_length(value); i++) {
228     if (!(paragraph = psiconv_list_get(value,i))) {
229       psiconv_error(config,lev+1,0,"Data structure corruption");
230       res = -PSICONV_E_NOMEM;
231       goto ERROR6;
232     }
233     if ((res = psiconv_write_u32(config,buf_elements,lev+1,
234 	                         psiconv_unicode_strlen(paragraph->text)+1)))
235       goto ERROR6;
236 
237     /* We need it for the next if-statement */
238     if (psiconv_list_length(paragraph->in_lines) == 1)
239       if (!(in_line = psiconv_list_get(paragraph->in_lines,0))) {
240         psiconv_error(config,lev+1,0,"Data structure corruption");
241 	res = -PSICONV_E_NOMEM;
242 	goto ERROR6;
243       }
244 
245     if ((psiconv_list_length(paragraph->in_lines) > 1) ||
246 	((psiconv_list_length(paragraph->in_lines) == 1) &&
247 	 (in_line->object != NULL))) {
248       /* Inline layouts, or an object, so we generate a paragraph element
249          and inline elements */
250       if ((res = psiconv_write_u8(config,buf_elements,lev+1,0x00)))
251         goto ERROR6;
252       if (!(style = psiconv_get_style(styles,paragraph->base_style))) {
253         psiconv_error(config,lev+1,0,"Unknown style");
254         res = -PSICONV_E_GENERATE;
255         goto ERROR6;
256       }
257       if ((res = psiconv_write_paragraph_layout_list(config,buf_elements,lev+1,
258                                                      paragraph->base_paragraph,
259                                                      style->paragraph)))
260         goto ERROR6;
261       if (with_styles)
262         if ((res = psiconv_write_u8(config,buf_elements,lev+1,paragraph->base_style)))
263           goto ERROR6;
264       if ((res = psiconv_write_u32(config,buf_elements,lev+1,
265                                    psiconv_list_length(paragraph->in_lines))))
266          goto ERROR6;
267 
268       /* Generate the inlines. NB: Against what are all settings relative?!? */
269       paralen = 0;
270       for (j = 0; j < psiconv_list_length(paragraph->in_lines); j++) {
271         nr_of_inlines ++;
272         if (!(in_line = psiconv_list_get(paragraph->in_lines,j))) {
273           psiconv_error(config,lev,0,"Data structure corruption");
274           res = -PSICONV_E_NOMEM;
275           goto ERROR6;
276         }
277         if ((res = psiconv_write_u8(config,buf_inlines,lev+1,in_line->object?0x01:0x00)))
278           goto ERROR6;
279         thislen = in_line->length;
280         paralen += thislen;
281         /* If this is the last in_line, we need to make sure that the
282            complete length of all inlines equals the text length */
283         if (j == psiconv_list_length(paragraph->in_lines)-1) {
284           if (paralen > psiconv_unicode_strlen(paragraph->text)+1) {
285             psiconv_error(config,lev+1,0,"Inline formatting data length and line length are inconsistent");
286             res = -PSICONV_E_GENERATE;
287             goto ERROR6;
288           }
289           thislen += psiconv_unicode_strlen(paragraph->text)+1-paralen;
290         }
291         if ((res = psiconv_write_u32(config,buf_inlines,lev+1,thislen)))
292           goto ERROR6;
293         if ((res = psiconv_write_character_layout_list(config,buf_inlines,lev+1,
294                                                      in_line->layout,
295                                                      style->character)))
296           goto ERROR6;
297 	if (in_line->object) {
298 	  if ((res = psiconv_write_u32(config,buf_inlines,lev+1,PSICONV_ID_OBJECT)))
299 	    goto ERROR6;
300 	  obj_id = psiconv_buffer_unique_id();
301 	  if ((res = psiconv_buffer_add_reference(buf_inlines,obj_id))) {
302             psiconv_error(config,lev+1,0,"Out of memory error");
303 	    goto ERROR6;
304 	  }
305 	  if ((res = psiconv_buffer_add_target(buf_objects,obj_id))) {
306             psiconv_error(config,lev+1,0,"Out of memory error");
307 	    goto ERROR6;
308 	  }
309 	  if ((res = psiconv_write_embedded_object_section(config,buf_objects,lev+1,
310 		                                   in_line->object)))
311 	    goto ERROR6;
312 	  if ((res = psiconv_write_length(config,buf_inlines,lev+1,in_line->object_width)))
313 	    goto ERROR6;
314 	  if ((res = psiconv_write_length(config,buf_inlines,lev+1,in_line->object_height)))
315 	    goto ERROR6;
316 	}
317       }
318     } else {
319       /* No inline layouts (or only 1), so we generate a paragraph type list */
320       para_type = 0;
321       /* Set para_charlayout to the correct character-level layout */
322       if (psiconv_list_length(paragraph->in_lines) == 0)
323         para_charlayout = paragraph->base_character;
324       else {
325         if (!(in_line = psiconv_list_get(paragraph->in_lines,0))) {
326           psiconv_error(config,lev,0,"Data structure corruption");
327           res = -PSICONV_E_NOMEM;
328           goto ERROR6;
329         }
330         para_charlayout = in_line->layout;
331       }
332       for (j = 0; j < psiconv_list_length(paragraph_type_list); j++) {
333         if (!(paragraph_type = psiconv_list_get(paragraph_type_list,j))) {
334           psiconv_error(config,lev,0,"Data structure corruption");
335           res = -PSICONV_E_NOMEM;
336           goto ERROR6;
337         }
338         if ((paragraph->base_style == paragraph_type->style) &&
339             !psiconv_compare_character_layout(para_charlayout,
340                                               paragraph_type->character) &&
341             !psiconv_compare_paragraph_layout(paragraph->base_paragraph,
342                                               paragraph_type->paragraph)) {
343           para_type = paragraph_type->nr;
344           break;
345         }
346       }
347       if (!para_type) {
348         /* We need to add a new entry */
349         para_type = new_type.nr = j+1;
350         /* No need to copy them, we won't change them anyway */
351         new_type.paragraph = paragraph->base_paragraph;
352         new_type.character = para_charlayout;
353         new_type.style = paragraph->base_style;
354         paragraph_type = &new_type;
355         if ((res = psiconv_list_add(paragraph_type_list,paragraph_type))) {
356           psiconv_error(config,lev+1,0,"Out of memory error");
357           goto ERROR6;
358 	}
359         if ((res = psiconv_write_u32(config,buf_types,lev+1,paragraph_type->nr)))
360           goto ERROR6;
361         if (!(style = psiconv_get_style(styles,paragraph_type->style))) {
362           psiconv_error(config,lev,0,"Unknown style");
363           res = -PSICONV_E_GENERATE;
364           goto ERROR6;
365         }
366         if ((res = psiconv_write_paragraph_layout_list(config,buf_types,lev+1,
367                                 paragraph_type->paragraph,style->paragraph)))
368           goto ERROR6;
369         if (with_styles)
370           if ((res = psiconv_write_u8(config,buf_types,lev+1,paragraph_type->style)))
371             goto ERROR6;
372         if ((res = psiconv_write_character_layout_list(config,buf_types,lev+1,
373                                 paragraph_type->character,style->character)))
374           goto ERROR6;
375       }
376       if ((res = psiconv_write_u8(config,buf_elements,lev+1,para_type)))
377         goto ERROR6;
378     }
379   }
380 
381   /* HACK: special case: no paragraphs at all. We need to improvize. */
382   if (!psiconv_list_length(value)) {
383     if ((res = psiconv_write_u32(config,buf_types,lev+1,1)))
384       goto ERROR6;
385     if ((res = psiconv_write_u32(config,buf_types,lev+1,0)))
386       goto ERROR6;
387     if (with_styles)
388       if ((res = psiconv_write_u8(config,buf_types,lev+1,0)))
389         goto ERROR6;
390     if ((res = psiconv_write_u32(config,buf_types,lev+1,0)))
391       goto ERROR6;
392 
393     if ((res = psiconv_write_u32(config,buf_elements,lev+1,1)))
394       goto ERROR6;
395     if ((res = psiconv_write_u8(config,buf_elements,lev+1,1)))
396       goto ERROR6;
397     pel_length = 1;
398     ptl_length = 1;
399   } else  {
400     pel_length = psiconv_list_length(value);
401     ptl_length = psiconv_list_length(paragraph_type_list);
402   }
403 
404   /* Now append everything */
405   if ((res = psiconv_write_u16(config,buf,lev+1,with_styles?0x0001:0x0000)))
406     goto ERROR6;
407   if ((res = psiconv_write_u8(config,buf,lev+1, ptl_length)))
408     goto ERROR6;
409   if ((res = psiconv_buffer_concat(buf,buf_types))) {
410     psiconv_error(config,lev+1,0,"Out of memory error");
411     goto ERROR6;
412   }
413   if ((res = psiconv_write_u32(config,buf,lev+1,pel_length)))
414     goto ERROR6;
415   if ((res = psiconv_buffer_concat(buf,buf_elements))) {
416     psiconv_error(config,lev+1,0,"Out of memory error");
417     goto ERROR6;
418   }
419   if ((res = psiconv_write_u32(config,buf,lev+1,nr_of_inlines)))
420     goto ERROR6;
421   if ((res = psiconv_buffer_concat(buf,buf_inlines))) {
422     psiconv_error(config,lev+1,0,"Out of memory error");
423     goto ERROR6;
424   }
425   if ((res = psiconv_buffer_concat(buf,buf_objects))) {
426     psiconv_error(config,lev+1,0,"Out of memory error");
427     goto ERROR6;
428   }
429 
430 ERROR6:
431   psiconv_buffer_free(buf_objects);
432 ERROR5:
433   psiconv_buffer_free(buf_inlines);
434 ERROR4:
435   psiconv_buffer_free(buf_elements);
436 ERROR3:
437   psiconv_buffer_free(buf_types);
438 ERROR2:
439   psiconv_list_free(paragraph_type_list);
440 ERROR1:
441   if (res)
442     psiconv_error(config,lev,0,"Writing of layout section failed");
443   else
444     psiconv_progress(config,lev,0,"End of layout section");
445   return res;
446 }
447 
psiconv_write_styled_layout_section(const psiconv_config config,psiconv_buffer buf,int lev,psiconv_text_and_layout result,psiconv_word_styles_section styles)448 int psiconv_write_styled_layout_section(const psiconv_config config,
449                                     psiconv_buffer buf,int lev,
450                                     psiconv_text_and_layout result,
451                                     psiconv_word_styles_section styles)
452 {
453   int res;
454 
455   psiconv_progress(config,lev,0,"Writing styled layout section");
456   res = psiconv_write_layout_section(config,buf,lev+1,result,styles,1);
457   if (res)
458     psiconv_error(config,lev,0,"Writing of styles layout section failed");
459   else
460     psiconv_progress(config,lev,0,"End of styled layout section");
461   return res;
462 }
463 
psiconv_write_styleless_layout_section(const psiconv_config config,psiconv_buffer buf,int lev,const psiconv_text_and_layout value,const psiconv_character_layout base_char,const psiconv_paragraph_layout base_para)464 int psiconv_write_styleless_layout_section(const psiconv_config config,
465                                        psiconv_buffer buf,int lev,
466                                        const psiconv_text_and_layout value,
467                                        const psiconv_character_layout base_char,
468                                        const psiconv_paragraph_layout base_para)
469 {
470   int res = 0;
471   psiconv_word_styles_section styles_section;
472 
473   psiconv_progress(config,lev,0,"Writing styleless layout section");
474   if (!(styles_section = malloc(sizeof(*styles_section)))) {
475     psiconv_error(config,lev+1,0,"Out of memory error");
476     goto ERROR1;
477   }
478   if (!(styles_section->normal = malloc(sizeof(*styles_section->normal)))) {
479     psiconv_error(config,lev+1,0,"Out of memory error");
480     goto ERROR2;
481   }
482   if (!(styles_section->normal->character =
483                             psiconv_clone_character_layout(base_char))) {
484     psiconv_error(config,lev+1,0,"Out of memory error");
485     goto ERROR3;
486   }
487   if (!(styles_section->normal->paragraph =
488                             psiconv_clone_paragraph_layout(base_para))) {
489     psiconv_error(config,lev+1,0,"Out of memory error");
490     goto ERROR4;
491   }
492   styles_section->normal->hotkey = 0;
493   if (!(styles_section->normal->name = psiconv_unicode_empty_string())) {
494     psiconv_error(config,lev+1,0,"Out of memory error");
495     goto ERROR5;
496   }
497   if (!(styles_section->styles = psiconv_list_new(sizeof(
498                                         struct psiconv_word_style_s)))) {
499     psiconv_error(config,lev+1,0,"Out of memory error");
500     goto ERROR6;
501   }
502 
503   res = psiconv_write_layout_section(config,buf,lev+1,value,styles_section,0);
504   psiconv_free_word_styles_section(styles_section);
505   psiconv_progress(config,lev,0,"End of styleless layout section");
506   return res;
507 
508 ERROR6:
509   free(styles_section->normal->name);
510 ERROR5:
511   psiconv_free_paragraph_layout(styles_section->normal->paragraph);
512 ERROR4:
513   psiconv_free_character_layout(styles_section->normal->character);
514 ERROR3:
515   free(styles_section->normal);
516 ERROR2:
517   free(styles_section);
518 ERROR1:
519   psiconv_error(config,lev,0,"Writing of styleless layout section failed");
520   if (!res)
521     return -PSICONV_E_NOMEM;
522   else
523     return res;
524 }
525 
526 
psiconv_write_embedded_object_section(const psiconv_config config,psiconv_buffer buf,int lev,const psiconv_embedded_object_section value)527 int psiconv_write_embedded_object_section(const psiconv_config config,
528                                   psiconv_buffer buf,int lev,
529                                   const psiconv_embedded_object_section value)
530 {
531   int res;
532   psiconv_u32 display_id,icon_id,table_id;
533   psiconv_buffer extra_buf;
534 
535   psiconv_progress(config,lev,0,"Writing embedded object section");
536   if (!value) {
537     psiconv_error(config,lev,0,"Null Object");
538     res = -PSICONV_E_GENERATE;
539     goto ERROR1;
540   }
541 
542   if (!(extra_buf = psiconv_buffer_new())) {
543     psiconv_error(config,lev+1,0,"Out of memory error");
544     res = -PSICONV_E_NOMEM;
545     goto ERROR1;
546   }
547 
548   display_id = psiconv_buffer_unique_id();
549   icon_id = psiconv_buffer_unique_id();
550   table_id = psiconv_buffer_unique_id();
551   if ((res = psiconv_write_u8(config,buf,lev+1,0x06)))
552     goto ERROR2;
553   if ((res = psiconv_write_u32(config,buf,lev+1,PSICONV_ID_OBJECT_DISPLAY_SECTION)))
554     goto ERROR2;
555   if ((res = psiconv_buffer_add_reference(buf,display_id))) {
556     psiconv_error(config,lev+1,0,"Out of memory error");
557     goto ERROR2;
558   }
559   if ((res = psiconv_write_u32(config,buf,lev+1,PSICONV_ID_OBJECT_ICON_SECTION)))
560     goto ERROR2;
561   if ((res = psiconv_buffer_add_reference(buf,icon_id))) {
562     psiconv_error(config,lev+1,0,"Out of memory error");
563     goto ERROR2;
564   }
565   if ((res = psiconv_write_u32(config,buf,lev+1,PSICONV_ID_OBJECT_SECTION_TABLE_SECTION)))
566     goto ERROR2;
567   if ((res = psiconv_buffer_add_reference(buf,table_id))) {
568     psiconv_error(config,lev+1,0,"Out of memory error");
569     goto ERROR2;
570   }
571 
572   if ((res = psiconv_buffer_add_target(buf,display_id))) {
573     psiconv_error(config,lev+1,0,"Out of memory error");
574     goto ERROR2;
575   }
576   if ((res = psiconv_write_object_display_section(config,buf,lev+1,value->display)))
577     goto ERROR2;
578   if ((res = psiconv_buffer_add_target(buf,icon_id))) {
579     psiconv_error(config,lev+1,0,"Out of memory error");
580     goto ERROR2;
581   }
582   if ((res = psiconv_write_object_icon_section(config,buf,lev+1,value->icon)))
583     goto ERROR2;
584   if ((res = psiconv_buffer_add_target(buf,table_id))) {
585     psiconv_error(config,lev+1,0,"Out of memory error");
586     goto ERROR2;
587   }
588   switch(value->object->type) {
589     case psiconv_word_file:
590       if ((res = psiconv_write_word_file(config,extra_buf,lev+1,
591                                       (psiconv_word_f) value->object->file)))
592 	goto ERROR2;
593       break;
594     case psiconv_sketch_file:
595       if ((res = psiconv_write_sketch_file(config,extra_buf,lev+1,
596                                       (psiconv_sketch_f) value->object->file)))
597 	goto ERROR2;
598       break;
599 /*
600     case psiconv_sheet_file:
601       if ((res = psiconv_write_sheet_file(config,extra_buf,lev+1,
602                                       (psiconv_sheet_f) value->object->file)))
603 	goto ERROR2;
604       break;
605 */
606     default:
607       psiconv_error(config,lev,0,"Unknown or unsupported object type");
608       res = -PSICONV_E_GENERATE;
609       goto ERROR2;
610   }
611 
612   if ((res = psiconv_buffer_resolve(extra_buf))) {
613     psiconv_error(config,lev+1,0,"Internal error resolving buffer references");
614     goto ERROR2;
615   }
616   if ((res = psiconv_buffer_concat(buf,extra_buf))) {
617     psiconv_error(config,lev+1,0,"Out of memory error");
618     goto ERROR2;
619   }
620   psiconv_buffer_free(extra_buf);
621 
622   psiconv_progress(config,lev,0,"End of embedded object section");
623   return 0;
624 
625 ERROR2:
626   psiconv_buffer_free(extra_buf);
627 ERROR1:
628   psiconv_error(config,lev,0,"Writing of embedded object section failed");
629   return res;
630 }
631 
632 
psiconv_write_object_display_section(const psiconv_config config,psiconv_buffer buf,int lev,const psiconv_object_display_section value)633 int psiconv_write_object_display_section(const psiconv_config config,
634                                   psiconv_buffer buf,int lev,
635                                   const psiconv_object_display_section value)
636 {
637   int res;
638 
639   psiconv_progress(config,lev,0,"Writing object display section");
640 
641   if (!value) {
642     psiconv_error(config,lev,0,"Null Object Display Section");
643     res = -PSICONV_E_GENERATE;
644     goto ERROR1;
645   }
646 
647   if ((res = psiconv_write_u8(config,buf,lev+1,value->show_icon?0x00:0x01)))
648     goto ERROR1;
649   if ((res = psiconv_write_length(config,buf,lev+1,value->width)))
650     goto ERROR1;
651   if ((res = psiconv_write_length(config,buf,lev+1,value->height)))
652     goto ERROR1;
653   if ((res = psiconv_write_u32(config,buf,lev+1,0x00000000)))
654     goto ERROR1;
655 
656   psiconv_progress(config,lev,0,"End of object display section");
657 
658   return 0;
659 
660 ERROR1:
661   psiconv_error(config,lev,0,"Writing of object display section failed");
662   return res;
663 }
664 
psiconv_write_object_icon_section(const psiconv_config config,psiconv_buffer buf,int lev,const psiconv_object_icon_section value)665 int psiconv_write_object_icon_section(const psiconv_config config,
666                                   psiconv_buffer buf,int lev,
667                                   const psiconv_object_icon_section value)
668 {
669   int res;
670 
671   psiconv_progress(config,lev,0,"Writing object icon section");
672 
673   if (!value) {
674     psiconv_error(config,lev,0,"Null Object Icon Section");
675     res = -PSICONV_E_GENERATE;
676     goto ERROR1;
677   }
678 
679   if ((res = psiconv_write_string(config,buf,lev+1,value->icon_name)))
680     goto ERROR1;
681   if ((res = psiconv_write_length(config,buf,lev+1,value->icon_width)))
682     goto ERROR1;
683   if ((res = psiconv_write_length(config,buf,lev+1,value->icon_height)))
684     goto ERROR1;
685 
686   psiconv_progress(config,lev,0,"End of object icon section");
687   return 0;
688 
689 ERROR1:
690   psiconv_error(config,lev,0,"Writing of object icon section failed");
691   return res;
692 }
693