1 /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
2 
3 /* libstaroffice
4 * Version: MPL 2.0 / LGPLv2+
5 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 2.0 (the "License"); you may not use this file except in compliance with
8 * the License or as specified alternatively below. You may obtain a copy of
9 * the License at http://www.mozilla.org/MPL/
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 *
16 * Major Contributor(s):
17 * Copyright (C) 2002 William Lachance (wrlach@gmail.com)
18 * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net)
19 * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
20 * Copyright (C) 2006, 2007 Andrew Ziem
21 * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr)
22 *
23 *
24 * All Rights Reserved.
25 *
26 * For minor contributions see the git repository.
27 *
28 * Alternatively, the contents of this file may be used under the terms of
29 * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
30 * in which case the provisions of the LGPLv2+ are applicable
31 * instead of those above.
32 */
33 
34 #include <map>
35 #include <string>
36 
37 #include <librevenge/librevenge.h>
38 
39 #include "StarWriterStruct.hxx"
40 
41 #include "StarAttribute.hxx"
42 #include "StarFormatManager.hxx"
43 #include "StarObject.hxx"
44 #include "StarZone.hxx"
45 
46 #include "STOFFDebug.hxx"
47 
48 namespace StarWriterStruct
49 {
50 ////////////////////////////////////////////////////////////
51 //  Attribute
52 ////////////////////////////////////////////////////////////
~Attribute()53 Attribute::~Attribute()
54 {
55 }
56 
read(StarZone & zone,StarObject & object)57 bool Attribute::read(StarZone &zone, StarObject &object)
58 {
59   STOFFInputStreamPtr input=zone.input();
60   libstoff::DebugFile &ascFile=zone.ascii();
61   libstoff::DebugStream f;
62   long pos=input->tell();
63   unsigned char type;
64   if (input->peek()!='A' || !zone.openSWRecord(type)) {
65     input->seek(pos, librevenge::RVNG_SEEK_SET);
66     STOFF_DEBUG_MSG(("StarWriterStruct::Attribute::read: can not read a attribute\n"));
67     return false;
68   }
69   // sw_sw3fmts.cxx InAttr
70   f << "Entries(StarAttribute)[SW-" << zone.getRecordLevel() << "]:";
71   int fl=zone.openFlagZone();
72   uint16_t nWhich, nVers, nBegin=0xFFFF, nEnd=0xFFFF;
73   *input >> nWhich >> nVers;
74   if (fl&0x10) *input >> nBegin;
75   if (fl&0x20) *input >> nEnd;
76   m_position=STOFFVec2i(nBegin==0xFFFF ? -1 : int(nBegin), nEnd==0xFFFF ? -1 : int(nEnd));
77 
78   auto which=int(nWhich);
79   if (which>0x6001 && zone.getDocumentVersion()!=0x0219) // bug correction 0x95500
80     which+=15;
81   if (which>=0x1000 && which<=0x1024) which+=-0x1000+int(StarAttribute::ATTR_CHR_CASEMAP);
82   else if (which>=0x2000 && which<=0x2009) which+=-0x2000+int(StarAttribute::ATTR_TXT_INETFMT);
83   else if (which>=0x3000 && which<=0x3006) which+=-0x3000+int(StarAttribute::ATTR_TXT_FIELD);
84   else if (which>=0x4000 && which<=0x4013) which+=-0x4000+int(StarAttribute::ATTR_PARA_LINESPACING);
85   else if (which>=0x5000 && which<=0x5022) which+=-0x5000+int(StarAttribute::ATTR_FRM_FILL_ORDER);
86   else if (which>=0x6000 && which<=0x6013) which+=-0x6000+int(StarAttribute::ATTR_GRF_MIRRORGRF);
87   else {
88     STOFF_DEBUG_MSG(("StarWriterStruct::Attribute::read: find unexpected which value\n"));
89     which=-1;
90     f << "###";
91   }
92   f << "wh=" << which << "[" << std::hex << nWhich << std::dec << "],";
93   if (nVers) f << "nVers=" << nVers << ",";
94   if (nBegin!=0xFFFF) f << "nBgin=" << nBegin << ",";
95   if (nEnd!=0xFFFF) f << "nEnd=" << nEnd << ",";
96   zone.closeFlagZone();
97 
98   if (which<=0 || !object.getAttributeManager() ||
99       !(m_attribute=object.getAttributeManager()->readAttribute(zone, which, int(nVers), zone.getRecordLastPosition(), object)))
100     f << "###";
101   ascFile.addPos(pos);
102   ascFile.addNote(f.str().c_str());
103   zone.closeSWRecord(type, "StarAttribute");
104   return true;
105 }
106 
readList(StarZone & zone,std::vector<Attribute> & attribList,StarObject & object)107 bool Attribute::readList(StarZone &zone, std::vector<Attribute> &attribList, StarObject &object)
108 {
109   STOFFInputStreamPtr input=zone.input();
110   libstoff::DebugFile &ascFile=zone.ascii();
111   libstoff::DebugStream f;
112   long pos=input->tell();
113   unsigned char type;
114   if (input->peek()!='S') return false;
115   if (!zone.openSWRecord(type)) {
116     input->seek(pos, librevenge::RVNG_SEEK_SET);
117     STOFF_DEBUG_MSG(("StarWriterStruct::Attribute::readList: can not read a mark\n"));
118     return false;
119   }
120   f << "Entries(StarAttribute)[SWlist-" << zone.getRecordLevel() << "]:";
121   ascFile.addPos(pos);
122   ascFile.addNote(f.str().c_str());
123   while (input->tell()<zone.getRecordLastPosition()) {
124     pos=input->tell();
125     Attribute attrib;
126     if (!attrib.read(zone, object)) {
127       input->seek(pos, librevenge::RVNG_SEEK_SET);
128       break;
129     }
130     attribList.push_back(attrib);
131   }
132 
133   zone.closeSWRecord(type, "StarAttribute");
134   return true;
135 }
136 
operator <<(std::ostream & o,Attribute const & attrib)137 std::ostream &operator<<(std::ostream &o, Attribute const &attrib)
138 {
139   if (attrib.m_attribute) {
140     libstoff::DebugStream f;
141     attrib.m_attribute->printData(f);
142     o << "attrib=[" << f.str() << "],";
143   }
144   if (attrib.m_position[0]==0xFFFF) o << "pos=_,";
145   else if (attrib.m_position[1]==0xFFFF) o << "pos=" << attrib.m_position[0] << ",";
146   else o << "pos=" << attrib.m_position << ",";
147   return o;
148 }
149 
150 ////////////////////////////////////////////////////////////
151 //  Bookmark
152 ////////////////////////////////////////////////////////////
read(StarZone & zone)153 bool Bookmark::read(StarZone &zone)
154 {
155   STOFFInputStreamPtr input=zone.input();
156   libstoff::DebugFile &ascFile=zone.ascii();
157   libstoff::DebugStream f;
158   long pos=input->tell();
159   unsigned char type;
160   if (input->peek()!='B' || !zone.openSWRecord(type)) {
161     input->seek(pos, librevenge::RVNG_SEEK_SET);
162     STOFF_DEBUG_MSG(("StarWriterStruct::Bookmark::read: can not read a mark\n"));
163     return false;
164   }
165   // sw_sw3misc.cxx InBookmark
166   f << "Entries(StarBookmark)[" << type << "-" << zone.getRecordLevel() << "]:";
167   std::vector<uint32_t> text;
168   bool ok=true;
169   for (int i=0; i<2; ++i) {
170     if (!zone.readString(text)) {
171       ok=false;
172       STOFF_DEBUG_MSG(("StarWriterStruct::Bookmark::read: can not read a name\n"));
173       f << "###short";
174       break;
175     }
176     else if (i==0)
177       m_shortName=libstoff::getString(text);
178     else
179       m_name=libstoff::getString(text);
180   }
181   if (ok) {
182     zone.openFlagZone();
183     m_offset=int(input->readULong(2));
184     m_key=int(input->readULong(2));
185     m_modifier=int(input->readULong(2));
186     zone.closeFlagZone();
187   }
188   if (ok && input->tell()<zone.getRecordLastPosition()) {
189     for (auto &macroName : m_macroNames) {  // start[aMac:aLib],end[aMac:Alib]
190       if (!zone.readString(text)) {
191         STOFF_DEBUG_MSG(("StarWriterStruct::Bookmark::read: can not read macro name\n"));
192         f << "###macro";
193         break;
194       }
195       else
196         macroName=libstoff::getString(text);
197     }
198   }
199 
200   f << *this;
201   ascFile.addPos(pos);
202   ascFile.addNote(f.str().c_str());
203   zone.closeSWRecord(type, "StarBookmark");
204   return true;
205 }
206 
readList(StarZone & zone,std::vector<Bookmark> & markList)207 bool Bookmark::readList(StarZone &zone, std::vector<Bookmark> &markList)
208 {
209   STOFFInputStreamPtr input=zone.input();
210   libstoff::DebugFile &ascFile=zone.ascii();
211   libstoff::DebugStream f;
212   long pos=input->tell();
213   unsigned char type;
214   if (input->peek()!='a') return false;
215   if (!zone.openSWRecord(type)) {
216     input->seek(pos, librevenge::RVNG_SEEK_SET);
217     STOFF_DEBUG_MSG(("StarWriterStruct::Bookmark::readList: can not read a mark\n"));
218     return false;
219   }
220   // sw_sw3misc.cxx InBookmarks
221   f << "Entries(StarBookmark)[list-" << zone.getRecordLevel() << "]:";
222   ascFile.addPos(pos);
223   ascFile.addNote(f.str().c_str());
224   while (input->tell()<zone.getRecordLastPosition()) {
225     pos=input->tell();
226     Bookmark bookmark;
227     if (!bookmark.read(zone)) {
228       input->seek(pos, librevenge::RVNG_SEEK_SET);
229       break;
230     }
231     markList.push_back(bookmark);
232   }
233 
234   zone.closeSWRecord(type, "StarBookmark");
235   return true;
236 }
237 
operator <<(std::ostream & o,Bookmark const & mark)238 std::ostream &operator<<(std::ostream &o, Bookmark const &mark)
239 {
240   if (!mark.m_shortName.empty()) o << "shortName=" << mark.m_shortName.cstr() << ",";
241   if (!mark.m_name.empty()) o << "name=" << mark.m_name.cstr() << ",";
242   if (mark.m_offset) o << "offset=" << mark.m_offset << ",";
243   if (mark.m_key) o << "key=" << mark.m_key << ",";
244   if (mark.m_modifier) o << "modifier=" << mark.m_modifier << ",";
245   for (int i=0; i<4; i+=2) {
246     if (mark.m_macroNames[i].empty() && mark.m_macroNames[i+1].empty()) continue;
247     o << "macro[" << (i==0 ? "start" : "end") << "]=" << mark.m_macroNames[i].cstr() << ":" << mark.m_macroNames[i+1].cstr() << ",";
248   }
249   return o;
250 }
251 
252 ////////////////////////////////////////////////////////////
253 //  DatabaseName
254 ////////////////////////////////////////////////////////////
read(StarZone & zone)255 bool DatabaseName::read(StarZone &zone)
256 {
257   STOFFInputStreamPtr input=zone.input();
258   libstoff::DebugFile &ascFile=zone.ascii();
259   libstoff::DebugStream f;
260   long pos=input->tell();
261   unsigned char type;
262   if (input->peek()!='D' || !zone.openSWRecord(type)) {
263     input->seek(pos, librevenge::RVNG_SEEK_SET);
264     STOFF_DEBUG_MSG(("StarWriterStruct::DatabaseName::read: can not read a databaseName\n"));
265     return false;
266   }
267   // sw_sw3num.cxx: InDBName
268   f << "Entries(StarDatabaseName)[" << zone.getRecordLevel() << "]:";
269   std::vector<uint32_t> text;
270   if (!zone.readString(text)) {
271     STOFF_DEBUG_MSG(("StarWriterStruct::DatabaseName::read: can not read a string\n"));
272     f << "###string";
273     ascFile.addPos(pos);
274     ascFile.addNote(f.str().c_str());
275     zone.closeSWRecord('D', "StarDatabaseName");
276     return true;
277   }
278   librevenge::RVNGString delim, dbName, tableName;
279   libstoff::appendUnicode(0xff, delim);
280   libstoff::splitString(libstoff::getString(text),delim, dbName, tableName);
281   if (tableName.empty()) {
282     if (zone.isCompatibleWith(0x11,0x22))
283       m_names[0]=dbName;
284     else
285       m_names[1]=dbName;
286   }
287   else {
288     m_names[0]=dbName;
289     m_names[1]=tableName;
290   }
291   if (zone.isCompatibleWith(0xf,0x101)) {
292     if (!zone.readString(text)) {
293       STOFF_DEBUG_MSG(("StarWriterStruct::DatabaseName::read: can not read a SQL string\n"));
294       f << *this << "###SQL";
295       ascFile.addPos(pos);
296       ascFile.addNote(f.str().c_str());
297       zone.closeSWRecord('D', "StarDatabaseName");
298       return true;
299     }
300     m_sql=libstoff::getString(text);
301   }
302   if (zone.isCompatibleWith(0x11,0x22)) {
303     if (!zone.readString(text)) {
304       STOFF_DEBUG_MSG(("StarWriterStruct::DatabaseName::read: can not read a table name string\n"));
305       f << "###tableName";
306       ascFile.addPos(pos);
307       ascFile.addNote(f.str().c_str());
308       zone.closeSWRecord('D', "StarDatabaseName");
309       return true;
310     }
311     m_names[1]=libstoff::getString(text);
312   }
313   if (zone.isCompatibleWith(0x12,0x22, 0x101)) {
314     auto nCount=int(input->readULong(2));
315     if (nCount>0 && zone.isCompatibleWith(0x28)) {
316       for (int i=0; i<nCount; ++i) {
317         if (input->tell()>=zone.getRecordLastPosition()) {
318           STOFF_DEBUG_MSG(("StarWriterStruct::DatabaseName::read: can not read a DBData\n"));
319           f << "###";
320           break;
321         }
322         Data data;
323         if (!zone.readString(text)) {
324           STOFF_DEBUG_MSG(("StarWriterStruct::DatabaseName::read: can not read a table name string\n"));
325           f << "###dbDataName";
326           break;
327         }
328         data.m_name=libstoff::getString(text);
329         int positions[2];
330         for (int &position : positions) position=int(input->readULong(4));
331         data.m_selection=STOFFVec2i(positions[0],positions[1]);
332         m_dataList.push_back(data);
333       }
334     }
335   }
336   f << *this;
337   ascFile.addPos(pos);
338   ascFile.addNote(f.str().c_str());
339   zone.closeSWRecord(type, "StarDatabaseName");
340   return true;
341 }
342 
operator <<(std::ostream & o,DatabaseName const & dbase)343 std::ostream &operator<<(std::ostream &o, DatabaseName const &dbase)
344 {
345   for (int i=0; i<2; ++i) {
346     if (dbase.m_names[i].empty()) continue;
347     char const *wh[]= {"name[database]", "name[table]"};
348     o << wh[i] << "=" << dbase.m_names[i].cstr() << ",";
349   }
350   if (!dbase.m_sql.empty()) o << "sql=" << dbase.m_sql.cstr() << ",";
351   if (!dbase.m_dataList.empty()) {
352     o << "data=[";
353     for (auto const &data : dbase.m_dataList)
354       o << "[" << data << "],";
355     o << "],";
356   }
357   return o;
358 }
359 
360 ////////////////////////////////////////////////////////////
361 //  Dictionary
362 ////////////////////////////////////////////////////////////
read(StarZone & zone)363 bool Dictionary::read(StarZone &zone)
364 {
365   STOFFInputStreamPtr input=zone.input();
366   libstoff::DebugFile &ascFile=zone.ascii();
367   libstoff::DebugStream f;
368   long pos=input->tell();
369   unsigned char type;
370   if (input->peek()!='j' || !zone.openSWRecord(type)) {
371     input->seek(pos, librevenge::RVNG_SEEK_SET);
372     STOFF_DEBUG_MSG(("StarWriterStruct::Dictionary::read: can not read a dictionary\n"));
373     return false;
374   }
375   // sw_sw3misc.cxx: InDictionary
376   f << "Entries(StarDictionary)[" << zone.getRecordLevel() << "]:";
377   long lastPos=zone.getRecordLastPosition();
378   std::vector<uint32_t> string;
379   while (input->tell()<lastPos) {
380     pos=input->tell();
381     Data data;
382     if (!zone.readString(string)) {
383       STOFF_DEBUG_MSG(("StarObjectText::readSWDictionary: can not read a string\n"));
384       f << "###string,";
385       input->seek(pos, librevenge::RVNG_SEEK_SET);
386       break;
387     }
388     data.m_name=libstoff::getString(string);
389     data.m_language=int(input->readULong(2));
390     data.m_id=int(input->readULong(2));
391     *input>>data.m_spellWrong;
392     m_dataList.push_back(data);
393   }
394   f << *this;
395   ascFile.addPos(pos);
396   ascFile.addNote(f.str().c_str());
397   zone.closeSWRecord(type, "StarDictionary");
398   return true;
399 }
400 
operator <<(std::ostream & o,Dictionary const & dbase)401 std::ostream &operator<<(std::ostream &o, Dictionary const &dbase)
402 {
403   if (!dbase.m_dataList.empty()) {
404     o << "data=[";
405     for (auto const &data : dbase.m_dataList)
406       o << "[" << data << "],";
407     o << "],";
408   }
409   return o;
410 }
411 
412 ////////////////////////////////////////////////////////////
413 //  DocStats
414 ////////////////////////////////////////////////////////////
read(StarZone & zone)415 bool DocStats::read(StarZone &zone)
416 {
417   STOFFInputStreamPtr input=zone.input();
418   libstoff::DebugFile &ascFile=zone.ascii();
419   libstoff::DebugStream f;
420   long pos=input->tell();
421   unsigned char type;
422   if (input->peek()!='d' || !zone.openSWRecord(type)) {
423     input->seek(pos, librevenge::RVNG_SEEK_SET);
424     STOFF_DEBUG_MSG(("StarWriterStruct::DocStats::read: can not read a docStats\n"));
425     return false;
426   }
427   // sw_sw3misc.cxx: InDocStats
428   f << "Entries(StarDocStats)[" << zone.getRecordLevel() << "]:";
429   for (int i=0; i<3; ++i) m_numbers[i]=long(input->readULong(2));
430   if (zone.isCompatibleWith(0x201)) {
431     m_numbers[3]=long(input->readULong(4));
432     m_numbers[4]=long(input->readULong(4));
433   }
434   else {
435     m_numbers[3]=long(input->readULong(2));
436     m_numbers[4]=long(input->readULong(2));
437   }
438   for (int i=5; i<7; ++i) m_numbers[i]=long(input->readULong(4));
439   *input >> m_isModified;
440   f << *this;
441   ascFile.addPos(pos);
442   ascFile.addNote(f.str().c_str());
443   zone.closeSWRecord(type, "StarDocStats");
444   return true;
445 }
446 
operator <<(std::ostream & o,DocStats const & stats)447 std::ostream &operator<<(std::ostream &o, DocStats const &stats)
448 {
449   for (int i=0; i<7; ++i) {
450     if (!stats.m_numbers[i]) continue;
451     char const *wh[]= {"table", "graph", "ole", "page", "paragraph", "word", "char"};
452     o << "num[" << wh[i] << "]=" << stats.m_numbers[i] << ",";
453   }
454   if (stats.m_isModified) o << "modified,";
455   return o;
456 }
457 ////////////////////////////////////////////////////////////
458 //  Macro
459 ////////////////////////////////////////////////////////////
read(StarZone & zone)460 bool Macro::read(StarZone &zone)
461 {
462   STOFFInputStreamPtr input=zone.input();
463   libstoff::DebugFile &ascFile=zone.ascii();
464   libstoff::DebugStream f;
465   long pos=input->tell();
466   unsigned char type;
467   if (input->peek()!='m' || !zone.openSWRecord(type)) {
468     input->seek(pos, librevenge::RVNG_SEEK_SET);
469     STOFF_DEBUG_MSG(("StarWriterStruct::Macro::read: can not read a macro\n"));
470     return false;
471   }
472   // sw_sw3misc.cxx InMacroTable
473   f << "Entries(StarMacro)[" << zone.getRecordLevel() << "]:";
474   m_key=int(input->readULong(2));
475   bool ok=true;
476   for (auto &name : m_names) {
477     std::vector<uint32_t> string;
478     if (!zone.readString(string)) {
479       STOFF_DEBUG_MSG(("StarObjectText::readSWMacroTable: can not read a string\n"));
480       f << "###name,";
481       ok=false;
482       break;
483     }
484     name=libstoff::getString(string);
485   }
486   if (ok && zone.isCompatibleWith(0x102))
487     m_scriptType=int(input->readULong(2));
488   f << *this;
489   ascFile.addPos(pos);
490   ascFile.addNote(f.str().c_str());
491   zone.closeSWRecord(type, "StarMacro");
492   return true;
493 }
494 
readList(StarZone & zone,std::vector<Macro> & macroList)495 bool Macro::readList(StarZone &zone, std::vector<Macro> &macroList)
496 {
497   STOFFInputStreamPtr input=zone.input();
498   libstoff::DebugFile &ascFile=zone.ascii();
499   libstoff::DebugStream f;
500   long pos=input->tell();
501   unsigned char type;
502   if (input->peek()!='u') return false;
503   if (!zone.openSWRecord(type)) {
504     input->seek(pos, librevenge::RVNG_SEEK_SET);
505     STOFF_DEBUG_MSG(("StarWriterStruct::Macro::readList: can not read a macro\n"));
506     return false;
507   }
508   // sw_sw3misc.cxx InMacroTable
509   f << "Entries(StarMacro)[list-" << zone.getRecordLevel() << "]:";
510   ascFile.addPos(pos);
511   ascFile.addNote(f.str().c_str());
512   while (input->tell()<zone.getRecordLastPosition()) {
513     pos=input->tell();
514     Macro macro;
515     if (!macro.read(zone)) {
516       input->seek(pos, librevenge::RVNG_SEEK_SET);
517       break;
518     }
519     macroList.push_back(macro);
520   }
521 
522   zone.closeSWRecord(type, "StarMacro");
523   return true;
524 }
525 
operator <<(std::ostream & o,Macro const & macro)526 std::ostream &operator<<(std::ostream &o, Macro const &macro)
527 {
528   if (macro.m_key) o << "key=" << macro.m_key << ",";
529   for (int i=0; i<2; ++i) {
530     if (!macro.m_names[i].empty())
531       o << "name" << i << "=" << macro.m_names[i].cstr() << ",";
532   }
533   if (macro.m_scriptType) o << "type[script]=" << macro.m_scriptType << ",";
534   return o;
535 }
536 
537 ////////////////////////////////////////////////////////////
538 //  Mark
539 ////////////////////////////////////////////////////////////
read(StarZone & zone)540 bool Mark::read(StarZone &zone)
541 {
542   STOFFInputStreamPtr input=zone.input();
543   libstoff::DebugFile &ascFile=zone.ascii();
544   libstoff::DebugStream f;
545   long pos=input->tell();
546   unsigned char type;
547   if (input->peek()!='K' || !zone.openSWRecord(type)) {
548     input->seek(pos, librevenge::RVNG_SEEK_SET);
549     STOFF_DEBUG_MSG(("StarWriterStruct::Mark::read: can not read a mark\n"));
550     return false;
551   }
552   // sw_sw3misc.cxx InNodeMark
553   f << "Entries(StarMark)[" << type << "-" << zone.getRecordLevel() << "]:";
554   m_type=int(input->readULong(1));
555   m_id=int(input->readULong(2));
556   m_offset=int(input->readULong(2));
557   f << *this;
558   ascFile.addPos(pos);
559   ascFile.addNote(f.str().c_str());
560   zone.closeSWRecord(type, "StarMark");
561   return true;
562 }
563 
operator <<(std::ostream & o,Mark const & mark)564 std::ostream &operator<<(std::ostream &o, Mark const &mark)
565 {
566   o << "type=" << mark.m_type << ",";
567   o << "id=" << mark.m_id << ",";
568   o << "offset=" << mark.m_offset << ",";
569   return o;
570 }
571 
572 ////////////////////////////////////////////////////////////
573 //  NodeRedline
574 ////////////////////////////////////////////////////////////
read(StarZone & zone)575 bool NodeRedline::read(StarZone &zone)
576 {
577   STOFFInputStreamPtr input=zone.input();
578   libstoff::DebugFile &ascFile=zone.ascii();
579   libstoff::DebugStream f;
580   long pos=input->tell();
581   unsigned char type;
582   if (input->peek()!='v' || !zone.openSWRecord(type)) {
583     input->seek(pos, librevenge::RVNG_SEEK_SET);
584     STOFF_DEBUG_MSG(("StarWriterStruct::NodeRedline::read: can not read a nodeRedline\n"));
585     return false;
586   }
587   // sw_sw3misc.cxx InNodeNodeRedline
588   f << "Entries(StarNodeRedline)[" << type << "-" << zone.getRecordLevel() << "]:";
589   m_flags=zone.openFlagZone();
590   m_id=int(input->readULong(2));
591   m_offset=int(input->readULong(2));
592   zone.closeFlagZone();
593   f << *this;
594   ascFile.addPos(pos);
595   ascFile.addNote(f.str().c_str());
596   zone.closeSWRecord(type, "StarNodeRedline");
597   return true;
598 }
599 
operator <<(std::ostream & o,NodeRedline const & nodeRedline)600 std::ostream &operator<<(std::ostream &o, NodeRedline const &nodeRedline)
601 {
602   o << "id=" << nodeRedline.m_id << ",";
603   o << "offset=" << nodeRedline.m_offset << ",";
604   if (nodeRedline.m_flags)
605     o << "flags=" << std::hex << nodeRedline.m_flags << std::dec << ",";
606   return o;
607 }
608 
609 ////////////////////////////////////////////////////////////
610 //  NoteInfo
611 ////////////////////////////////////////////////////////////
read(StarZone & zone)612 bool NoteInfo::read(StarZone &zone)
613 {
614   STOFFInputStreamPtr input=zone.input();
615   libstoff::DebugFile &ascFile=zone.ascii();
616   libstoff::DebugStream f;
617   long pos=input->tell();
618   unsigned char type;
619   if (input->peek()!=(m_isFootnote ? '1' : '4') || !zone.openSWRecord(type)) {
620     input->seek(pos, librevenge::RVNG_SEEK_SET);
621     STOFF_DEBUG_MSG(("StarWriterStruct::NoteInfo::read: can not read a noteInfo\n"));
622     return false;
623   }
624   f << "Entries(StarNoteInfo)[" << (m_isFootnote ? "footnote" : "endnote") << "-" << zone.getRecordLevel() << "]:";
625   // sw_sw3num.cxx: InFtnInfo and InFntInfo40 InEndNoteInfo
626   bool oldFootnote=m_isFootnote && !zone.isCompatibleWith(0x201);
627   std::vector<uint32_t> text;
628   if (oldFootnote) {
629     for (int i=0; i<2; ++i) {
630       if (!zone.readString(text)) {
631         STOFF_DEBUG_MSG(("StarWriterStruct::NoteInfo::read: can not read a string\n"));
632         f << *this << "###string";
633         ascFile.addPos(pos);
634         ascFile.addNote(f.str().c_str());
635         zone.closeSWRecord(type, "StarNoteInfo");
636       }
637       m_strings[i+2]=libstoff::getString(text);
638     }
639   }
640   int fl=zone.openFlagZone();
641 
642   if (oldFootnote) {
643     m_posType=int(input->readULong(1));
644     m_numType=int(input->readULong(1));
645   }
646   m_type=int(input->readULong(1));
647   for (int i=0; i<2; ++i)
648     m_idx[i]=int(input->readULong(2));
649   if (zone.isCompatibleWith(0xc))
650     m_ftnOffset=int(input->readULong(2));
651   if (zone.isCompatibleWith(0x203))
652     m_idx[2]=int(input->readULong(2));
653   if (zone.isCompatibleWith(0x216) && (fl&0x10))
654     m_idx[3]=int(input->readULong(2));
655   zone.closeFlagZone();
656 
657   if (zone.isCompatibleWith(0x203)) {
658     for (int i=0; i<2; ++i) {
659       if (!zone.readString(text)) {
660         STOFF_DEBUG_MSG(("StarWriterStruct::NoteInfo::read: can not read a string\n"));
661         f << *this << "###string";
662         ascFile.addPos(pos);
663         ascFile.addNote(f.str().c_str());
664         zone.closeSWRecord(type, "StarNoteInfo");
665         return true;
666       }
667       m_strings[i]=libstoff::getString(text);
668     }
669   }
670 
671   if (m_isFootnote && !oldFootnote) {
672     zone.openFlagZone();
673     m_posType=int(input->readULong(1));
674     m_numType=int(input->readULong(1));
675     zone.closeFlagZone();
676     for (int i=0; i<2; ++i) {
677       if (!zone.readString(text)) {
678         STOFF_DEBUG_MSG(("StarWriterStruct::NoteInfo::read: can not read a string\n"));
679         f << *this << "###string";
680         ascFile.addPos(pos);
681         ascFile.addNote(f.str().c_str());
682         zone.closeSWRecord(type, "StarNoteInfo");
683         return true;
684       }
685       m_strings[i+2]=libstoff::getString(text);
686     }
687   }
688 
689   f << *this;
690   ascFile.addPos(pos);
691   ascFile.addNote(f.str().c_str());
692   zone.closeSWRecord(type, "StarNoteInfo");
693   return true;
694 }
695 
operator <<(std::ostream & o,NoteInfo const & info)696 std::ostream &operator<<(std::ostream &o, NoteInfo const &info)
697 {
698   o << (info.m_isFootnote ? "footnote" : "endnote") << ",";
699   if (info.m_type) o << "type=" << info.m_type << ",";
700   for (int i=0; i<4; ++i) {
701     if (info.m_idx[i]==0xFFFF) continue;
702     char const *wh[]= {"pageId", "collIdx", "charIdx", "anchorCharIdx"};
703     o << wh[i] << "=" << info.m_idx[i] << ",";
704   }
705   if (info.m_ftnOffset) o << "ftnOffset=" << info.m_ftnOffset << ",";
706   for (int i=0; i<4; ++i) {
707     if (info.m_strings[i].empty()) continue;
708     char const *wh[]= {"prefix", "suffix", "quoValis", "ergoSum"};
709     o << wh[i] << "=" << info.m_strings[i].cstr() << ",";
710   }
711   if (info.m_posType) o << "type[pos]=" << info.m_posType << ",";
712   if (info.m_numType) o << "type[number]=" << info.m_numType << ",";
713   return o;
714 }
715 
716 ////////////////////////////////////////////////////////////
717 //  PrintData
718 ////////////////////////////////////////////////////////////
read(StarZone & zone)719 bool PrintData::read(StarZone &zone)
720 {
721   STOFFInputStreamPtr input=zone.input();
722   libstoff::DebugFile &ascFile=zone.ascii();
723   libstoff::DebugStream f;
724   long pos=input->tell();
725   unsigned char type;
726   if (input->peek()!='8' || !zone.openSWRecord(type)) {
727     input->seek(pos, librevenge::RVNG_SEEK_SET);
728     STOFF_DEBUG_MSG(("StarWriterStruct::PrintData::read: can not read a printData\n"));
729     return false;
730   }
731   // sw_sw3misc.cxx: InPagePreviewPrintData
732   f << "Entries(StarPrintData)[" << zone.getRecordLevel() << "]:";
733   m_flags=int(input->readULong(1));
734   int dim[2];
735   for (int &i : dim) i=int(input->readULong(2));
736   m_colRow=STOFFVec2i(dim[1],dim[0]);
737   for (int &spacing : m_spacings) spacing=int(input->readULong(2));
738   f << *this;
739   ascFile.addPos(pos);
740   ascFile.addNote(f.str().c_str());
741   zone.closeSWRecord(type, "StarPrintData");
742   return true;
743 }
744 
operator <<(std::ostream & o,PrintData const & info)745 std::ostream &operator<<(std::ostream &o, PrintData const &info)
746 {
747   if (info.m_flags) o << "flags=" << std::hex << info.m_flags << std::dec;
748   if (info.m_colRow[0]!=1) o << "columns=" << info.m_colRow[0] << ",";
749   if (info.m_colRow[1]!=1) o << "rows=" << info.m_colRow[1] << ",";
750   for (int i=0; i<6; ++i) {
751     if (!info.m_spacings[i]) continue;
752     char const *wh[]= {"left", "right", "top", "bottom", "horizontal", "vertical"};
753     o << wh[i] << "=" << info.m_spacings[i] << ",";
754   }
755   return o;
756 }
757 ////////////////////////////////////////////////////////////
758 //  Redline
759 ////////////////////////////////////////////////////////////
read(StarZone & zone)760 bool Redline::read(StarZone &zone)
761 {
762   STOFFInputStreamPtr input=zone.input();
763   libstoff::DebugFile &ascFile=zone.ascii();
764   libstoff::DebugStream f;
765   long pos=input->tell();
766   unsigned char type;
767   if (input->peek()!='D' || !zone.openSWRecord(type)) {
768     input->seek(pos, librevenge::RVNG_SEEK_SET);
769     STOFF_DEBUG_MSG(("StarWriterStruct::Redline::read: can not read a redline\n"));
770     return false;
771   }
772   f << "Entries(StarRedline)[" << zone.getRecordLevel() << "]:";
773   // sw_sw3redline.cxx inRedline
774   zone.openFlagZone();
775   m_type=int(input->readULong(1));
776   m_stringId=int(input->readULong(2));
777   zone.closeFlagZone();
778   m_date=long(input->readULong(4));
779   m_time=long(input->readULong(4));
780   std::vector<uint32_t> text;
781   if (!zone.readString(text)) {
782     STOFF_DEBUG_MSG(("StarWriterStruct::Redline: can not read the comment\n"));
783     f << "###comment";
784   }
785   else
786     m_comment=libstoff::getString(text);
787   f << *this;
788   ascFile.addPos(pos);
789   ascFile.addNote(f.str().c_str());
790   zone.closeSWRecord(type, "StarRedline");
791   return true;
792 }
793 
readList(StarZone & zone,std::vector<Redline> & redlineList)794 bool Redline::readList(StarZone &zone, std::vector<Redline> &redlineList)
795 {
796   STOFFInputStreamPtr input=zone.input();
797   libstoff::DebugFile &ascFile=zone.ascii();
798   libstoff::DebugStream f;
799   long pos=input->tell();
800   unsigned char type;
801   if (input->peek()!='R') return false;
802   if (!zone.openSWRecord(type)) {
803     input->seek(pos, librevenge::RVNG_SEEK_SET);
804     STOFF_DEBUG_MSG(("StarWriterStruct::Redline::readList: can not read a mark\n"));
805     return false;
806   }
807   // sw_sw3misc.cxx InRedlines
808   f << "Entries(StarRedline)[list-" << zone.getRecordLevel() << "]:";
809   zone.openFlagZone();
810   auto N=int(input->readULong(2));
811   zone.closeFlagZone();
812   ascFile.addPos(pos);
813   ascFile.addNote(f.str().c_str());
814 
815   for (int i=0; i<N; ++i) {
816     pos=input->tell();
817     Redline redline;
818     if (!redline.read(zone)) {
819       input->seek(pos, librevenge::RVNG_SEEK_SET);
820       break;
821     }
822     redlineList.push_back(redline);
823   }
824 
825   zone.closeSWRecord(type, "StarRedline");
826   return true;
827 }
828 
readListList(StarZone & zone,std::vector<std::vector<Redline>> & redlineListList)829 bool Redline::readListList(StarZone &zone, std::vector<std::vector<Redline> > &redlineListList)
830 {
831   STOFFInputStreamPtr input=zone.input();
832   libstoff::DebugFile &ascFile=zone.ascii();
833   libstoff::DebugStream f;
834   long pos=input->tell();
835   unsigned char type;
836   if (input->peek()!='V') return false;
837   if (!zone.openSWRecord(type)) {
838     input->seek(pos, librevenge::RVNG_SEEK_SET);
839     STOFF_DEBUG_MSG(("StarWriterStruct::Redline::readListList: can not read a mark\n"));
840     return false;
841   }
842   // sw_sw3misc.cxx InRedlines
843   f << "Entries(StarRedline)[listList-" << zone.getRecordLevel() << "]:";
844   ascFile.addPos(pos);
845   ascFile.addNote(f.str().c_str());
846 
847   while (input->tell() < zone.getRecordLastPosition()) {
848     pos=input->tell();
849     std::vector<Redline> redlineList;
850     if (!readList(zone, redlineList)) {
851       input->seek(pos, librevenge::RVNG_SEEK_SET);
852       break;
853     }
854     redlineListList.push_back(redlineList);
855   }
856 
857   zone.closeSWRecord(type, "StarRedline");
858   return true;
859 }
860 
operator <<(std::ostream & o,Redline const & redline)861 std::ostream &operator<<(std::ostream &o, Redline const &redline)
862 {
863   if (redline.m_type) o << "type=" << redline.m_type << ",";
864   if (redline.m_stringId) o << "stringId=" << redline.m_stringId << ",";
865   if (redline.m_date) o << "date=" << redline.m_date << ",";
866   if (redline.m_time) o << "time=" << redline.m_time << ",";
867   if (!redline.m_comment.empty()) o << "comment=" << redline.m_comment.cstr() << ",";
868   return o;
869 }
870 
871 ////////////////////////////////////////////////////////////
872 //  TOX
873 ////////////////////////////////////////////////////////////
~TOX()874 TOX::~TOX()
875 {
876 }
877 
read(StarZone & zone,StarObject & object)878 bool TOX::read(StarZone &zone, StarObject &object)
879 {
880   STOFFInputStreamPtr input=zone.input();
881   libstoff::DebugFile &ascFile=zone.ascii();
882   libstoff::DebugStream f;
883   long pos=input->tell();
884   unsigned char type;
885   if (input->peek()!='x' || !zone.openSWRecord(type)) {
886     input->seek(pos, librevenge::RVNG_SEEK_SET);
887     STOFF_DEBUG_MSG(("StarWriterStruct::TOX::read::read: can not read a nodeRedline\n"));
888     return false;
889   }
890   long lastRecordPos=zone.getRecordLastPosition();
891   // sw_sw3misc.cxx: InTOX
892   f << "Entries(StarTOX)[" << zone.getRecordLevel() << "]:";
893   int fl=zone.openFlagZone();
894   if (fl&0xf0)
895     f << "fl=" << (fl>>4) << ",";
896   m_type=int(input->readULong(2));
897   m_createType=int(input->readULong(2));
898   m_captionDisplay=int(input->readULong(2));
899   for (int i=0; i<2; ++i) m_stringIds[i]=int(input->readULong(2));
900   m_data=int(input->readULong(2));
901   m_formFlags=int(input->readULong(1));
902   zone.closeFlagZone();
903   std::vector<uint32_t> string;
904   for (int i=0; i<2; ++i) {
905     if (!zone.readString(string)) {
906       STOFF_DEBUG_MSG(("StarWriterStruct::TOX::read: can not read aName\n"));
907       f << *this;
908       f << "###aName";
909       ascFile.addPos(pos);
910       ascFile.addNote(f.str().c_str());
911       zone.closeSWRecord(type, "StarTOX");
912       return true;
913     }
914     if (i==0)
915       m_name=libstoff::getString(string);
916     else
917       m_title=libstoff::getString(string);
918   }
919   if (zone.isCompatibleWith(0x215)) {
920     m_OLEOptions=int(input->readULong(2));
921     m_styleId=int(input->readULong(2));
922   }
923   else {
924     if (!zone.readString(string)) {
925       STOFF_DEBUG_MSG(("StarWriterStruct::TOX::read: can not read aDummy\n"));
926       f << "###aDummy";
927       ascFile.addPos(pos);
928       ascFile.addNote(f.str().c_str());
929       zone.closeSWRecord(type, "StarTOX");
930       return true;;
931     }
932     if (!string.empty())
933       f << "aDummy=" << libstoff::getString(string).cstr() << ",";
934   }
935 
936   auto N=int(input->readULong(1));
937   f << "nPatterns=" << N << ",";
938   bool ok=true;
939   for (int i=0; i<N; ++i) { // storeme
940     if (object.getFormatManager()->readSWPatternLCL(zone))
941       continue;
942     ok=false;
943     f << "###pat";
944     break;
945   }
946   if (!ok) {
947     f << *this;
948     ascFile.addPos(pos);
949     ascFile.addNote(f.str().c_str());
950     zone.closeSWRecord(type, "StarTOX");
951     return true;
952   }
953   N=int(input->readULong(1));
954   for (int i=0; i<N; ++i)
955     m_stringIdList.push_back(int(input->readULong(2)));
956   N=int(input->readULong(1));
957   for (int i=0; i<N; ++i) {
958     Style style;
959     style.m_level=int(input->readULong(1));
960     auto nCount=int(input->readULong(2));
961     f << "nCount=" << nCount << ",";
962     if (input->tell()+2*nCount>lastRecordPos) {
963       STOFF_DEBUG_MSG(("StarWriterStruct::TOX::read: can not read some string id\n"));
964       f << "###styleId";
965       ok=false;
966       break;
967     }
968     librevenge::RVNGString poolName;
969     for (int j=0; j<nCount; ++j) {
970       auto val=int(input->readULong(2));
971       if (!zone.getPoolName(val, poolName))
972         f << "###nPoolId=" << val << ",";
973       else
974         style.m_names.push_back(poolName);
975     }
976   }
977   if (!ok) {
978     f << *this;
979     ascFile.addPos(pos);
980     ascFile.addNote(f.str().c_str());
981     zone.closeSWRecord(type, "StarTOX");
982     return true;
983   }
984   fl=zone.openFlagZone();
985   m_stringIds[2]=int(input->readULong(2));
986   m_titleLength=long(input->readULong(4));
987   zone.closeFlagZone();
988 
989   if ((fl&0x10)) {
990     while (input->tell()<lastRecordPos && input->peek()=='s') {
991       std::shared_ptr<StarFormatManagerInternal::FormatDef> format;
992       if (!object.getFormatManager()->readSWFormatDef(zone,'s', format, object)) {
993         STOFF_DEBUG_MSG(("StarWriterStruct::TOX::read: can not read some format\n"));
994         f << "###format,";
995         break;
996       }
997       m_formatList.push_back(format);
998     }
999   }
1000 
1001   f << *this;
1002   ascFile.addPos(pos);
1003   ascFile.addNote(f.str().c_str());
1004   zone.closeSWRecord(type, "StarTOX");
1005   return true;
1006 }
1007 
readList(StarZone & zone,std::vector<TOX> & toxList,StarObject & object)1008 bool TOX::readList(StarZone &zone, std::vector<TOX> &toxList, StarObject &object)
1009 {
1010   STOFFInputStreamPtr input=zone.input();
1011   libstoff::DebugFile &ascFile=zone.ascii();
1012   libstoff::DebugStream f;
1013   long pos=input->tell();
1014   unsigned char type;
1015   if (input->peek()!='u') return false;
1016   if (!zone.openSWRecord(type)) {
1017     input->seek(pos, librevenge::RVNG_SEEK_SET);
1018     STOFF_DEBUG_MSG(("StarWriterStruct::TOX::readList: can not read a mark\n"));
1019     return false;
1020   }
1021   // sw_sw3misc.cxx InTOXs
1022   f << "Entries(StarTOX)[list-" << zone.getRecordLevel() << "]:";
1023   ascFile.addPos(pos);
1024   ascFile.addNote(f.str().c_str());
1025   while (input->tell()<zone.getRecordLastPosition()) {
1026     pos=input->tell();
1027     TOX tox;
1028     if (!tox.read(zone, object)) {
1029       input->seek(pos, librevenge::RVNG_SEEK_SET);
1030       break;
1031     }
1032     toxList.push_back(tox);
1033   }
1034 
1035   zone.closeSWRecord(type, "StarTOX");
1036   return true;
1037 }
1038 
operator <<(std::ostream & o,TOX const & tox)1039 std::ostream &operator<<(std::ostream &o, TOX const &tox)
1040 {
1041   if (tox.m_type) o << "type=" << tox.m_type << ",";
1042   if (tox.m_createType) o << "type[create]=" << tox.m_createType << ",";
1043   if (tox.m_captionDisplay) o << "captionDisplay=" << tox.m_captionDisplay << ",";
1044   for (int i=0; i<3; ++i) {
1045     if (tox.m_stringIds[i]==0xFFFF) continue;
1046     char const *wh[]= {"stringId", "seqStringId", "sectStringId"};
1047     o << wh[i] << "=" << tox.m_stringIds[i] << ",";
1048   }
1049   if (tox.m_styleId!=0xFFFF) o << "styleId=" << tox.m_styleId << ",";
1050   if (tox.m_data) o << "data=" << tox.m_data << ",";
1051   if (tox.m_formFlags) o << "formFlags=" << std::hex << tox.m_formFlags << std::dec << ",";
1052   if (!tox.m_title.empty()) o << "title=" << tox.m_title.cstr() << ",";
1053   if (!tox.m_name.empty()) o << "name=" << tox.m_name.cstr() << ",";
1054   if (tox.m_OLEOptions) o << "OLEOptions=" << tox.m_OLEOptions << ",";
1055   if (!tox.m_stringIdList.empty()) {
1056     o << "stringIdList=[";
1057     for (auto const &id : tox.m_stringIdList) {
1058       if (id==0xFFFF)
1059         o << "_,";
1060       else
1061         o << id << ",";
1062     }
1063     o << "],";
1064   }
1065   if (!tox.m_styleList.empty()) {
1066     o << "styleList=[";
1067     for (auto const &style : tox.m_styleList)
1068       o << "[" << style << "],";
1069     o << "],";
1070   }
1071   if (tox.m_titleLength) o << "titleLength=" << tox.m_titleLength << ",";
1072   if (!tox.m_formatList.empty()) o << "nFormat=" << tox.m_formatList.size() << ",";
1073   return o;
1074 }
1075 
1076 ////////////////////////////////////////////////////////////
1077 //  TOX51
1078 ////////////////////////////////////////////////////////////
~TOX51()1079 TOX51::~TOX51()
1080 {
1081 }
1082 
read(StarZone & zone,StarObject &)1083 bool TOX51::read(StarZone &zone, StarObject &/*object*/)
1084 {
1085   STOFFInputStreamPtr input=zone.input();
1086   libstoff::DebugFile &ascFile=zone.ascii();
1087   libstoff::DebugStream f;
1088   long pos=input->tell();
1089   unsigned char type;
1090   if (input->peek()!='x' || !zone.openSWRecord(type)) {
1091     input->seek(pos, librevenge::RVNG_SEEK_SET);
1092     STOFF_DEBUG_MSG(("StarWriterStruct::TOX51::read: can not read a tox51\n"));
1093     return false;
1094   }
1095   // sw_sw3misc.cxx InNodeTOX51
1096   f << "Entries(StarTox51)[" << type << "-" << zone.getRecordLevel() << "]:";
1097   std::vector<uint32_t> string;
1098   if (zone.isCompatibleWith(0x201)) {
1099     auto strId=int(input->readULong(2));
1100     if (strId!=0xFFFF && !zone.getPoolName(strId, m_typeName))
1101       f << "###nPoolId=" << strId << ",";
1102   }
1103   else {
1104     if (!zone.readString(string)) {
1105       STOFF_DEBUG_MSG(("StarWriterStruct::TOX51::read: can not read typeName\n"));
1106       f << *this << "###typeName";
1107       ascFile.addPos(pos);
1108       ascFile.addNote(f.str().c_str());
1109       zone.closeSWRecord(type, "StarTox51");
1110       return true;
1111     }
1112     m_typeName=libstoff::getString(string);
1113   }
1114   if (!zone.readString(string)) {
1115     STOFF_DEBUG_MSG(("StarWriterStruct::TOX51::read: can not read aTitle\n"));
1116     f << *this << "###aTitle";
1117     ascFile.addPos(pos);
1118     ascFile.addNote(f.str().c_str());
1119     zone.closeSWRecord(type, "StarTox51");
1120     return true;
1121   }
1122   m_title=libstoff::getString(string);
1123   int fl=zone.openFlagZone();
1124   m_createType=int(input->readULong(2));
1125   m_type=int(input->readULong(1));
1126   if (zone.isCompatibleWith(0x213) && (fl&0x10))
1127     m_firstTabPos=int(input->readULong(2));
1128 
1129   auto N=int(input->readULong(1));
1130   bool ok=true;
1131   for (int i=0; i<N; ++i) {
1132     if (!zone.readString(string)) {
1133       STOFF_DEBUG_MSG(("StarWriterStruct::TOX51::read: can not read a pattern name\n"));
1134       f << "###pat";
1135       ok=false;
1136       break;
1137     }
1138     m_patternList.push_back(libstoff::getString(string));
1139   }
1140   if (!ok) {
1141     f << *this;
1142     ascFile.addPos(pos);
1143     ascFile.addNote(f.str().c_str());
1144     zone.closeSWRecord(type, "StarTox51");
1145     return true;
1146   }
1147   N=int(input->readULong(1));
1148   for (int i=0; i<N; ++i)
1149     m_stringIdList.push_back(int(input->readULong(2)));
1150   m_infLevel=int(input->readULong(2));
1151 
1152   f << *this;
1153   ascFile.addPos(pos);
1154   ascFile.addNote(f.str().c_str());
1155   zone.closeSWRecord(type, "StarTox51");
1156   return true;
1157 }
1158 
1159 
readList(StarZone & zone,std::vector<TOX51> & toxList,StarObject & object)1160 bool TOX51::readList(StarZone &zone, std::vector<TOX51> &toxList, StarObject &object)
1161 {
1162   STOFFInputStreamPtr input=zone.input();
1163   libstoff::DebugFile &ascFile=zone.ascii();
1164   libstoff::DebugStream f;
1165   long pos=input->tell();
1166   unsigned char type;
1167   if (input->peek()!='y') return false;
1168   if (!zone.openSWRecord(type)) {
1169     input->seek(pos, librevenge::RVNG_SEEK_SET);
1170     STOFF_DEBUG_MSG(("StarWriterStruct::TOX51::readList: can not read a mark\n"));
1171     return false;
1172   }
1173   // sw_sw3misc.cxx InTOX51s
1174   f << "Entries(StarTox51)[list-" << zone.getRecordLevel() << "]:";
1175   ascFile.addPos(pos);
1176   ascFile.addNote(f.str().c_str());
1177   while (input->tell()<zone.getRecordLastPosition()) {
1178     pos=input->tell();
1179     TOX51 tox;
1180     if (!tox.read(zone, object)) {
1181       input->seek(pos, librevenge::RVNG_SEEK_SET);
1182       break;
1183     }
1184     toxList.push_back(tox);
1185   }
1186 
1187   zone.closeSWRecord(type, "StarTox51");
1188   return true;
1189 }
1190 
operator <<(std::ostream & o,TOX51 const & tox)1191 std::ostream &operator<<(std::ostream &o, TOX51 const &tox)
1192 {
1193   if (!tox.m_typeName.empty()) o << "type[name]=" << tox.m_typeName.cstr() << ",";
1194   if (tox.m_type) o << "type=" << tox.m_type << ",";
1195   if (tox.m_createType) o << "type[create]=" << tox.m_createType << ",";
1196   if (tox.m_firstTabPos) o << "firstTabPos=" << tox.m_firstTabPos << ",";
1197   if (!tox.m_title.empty()) o << "title=" << tox.m_title.cstr() << ",";
1198   if (!tox.m_patternList.empty()) {
1199     o << "patternList=[";
1200     for (auto const &pattern : tox.m_patternList)
1201       o << pattern.cstr() << ",";
1202     o << "],";
1203   }
1204   if (!tox.m_stringIdList.empty()) {
1205     o << "stringIdList=[";
1206     for (auto const &id : tox.m_stringIdList) {
1207       if (id==0xFFFF)
1208         o << "_,";
1209       else
1210         o << id << ",";
1211     }
1212     o << "],";
1213   }
1214   if (tox.m_infLevel) o << "infLevel=" << tox.m_infLevel << ",";
1215   return o;
1216 }
1217 }
1218 // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab:
1219