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 <cstring>
35 #include <iomanip>
36 #include <iostream>
37 #include <limits>
38 #include <sstream>
39
40 #include <librevenge/librevenge.h>
41
42 #include "SWFieldManager.hxx"
43
44 #include "StarObject.hxx"
45 #include "StarState.hxx"
46 #include "StarZone.hxx"
47
48 #include "STOFFListener.hxx"
49 #include "STOFFSubDocument.hxx"
50
51 /** Internal: the structures of a SWFieldManager */
52 namespace SWFieldManagerInternal
53 {
updateDatabaseName(librevenge::RVNGString const & name,librevenge::RVNGPropertyList & pList)54 static void updateDatabaseName(librevenge::RVNGString const &name, librevenge::RVNGPropertyList &pList)
55 {
56 librevenge::RVNGString delim, dbName, tableName;
57 libstoff::appendUnicode(0xff, delim);
58 libstoff::splitString(name,delim, dbName, tableName);
59 if (tableName.empty()) {
60 if (!dbName.empty())
61 pList.insert("text:table-name", dbName);
62 }
63 else {
64 pList.insert("text:table-name", tableName);
65 if (!dbName.empty())
66 pList.insert("text:database-name", dbName);
67 }
68 // checkme: always table or is it a function of subtype
69 pList.insert("text:table-type", "table");
70 }
71
~Field()72 Field::~Field()
73 {
74 }
75
print(std::ostream & o) const76 void Field::print(std::ostream &o) const
77 {
78 if (m_type>=0 && m_type<40) {
79 char const *wh[]= {"db", "user", "filename", "dbName",
80 "inDate40", "inTime40", "pageNumber", "author",
81 "chapter", "docStat", "getExp", "setExp",
82 "getRef", "hiddenText", "postIt", "fixDate",
83 "fixTime", "reg", "varReg", "setRef", // checkme: 17-19
84 "input", "macro", "dde", "tbl",
85 "hiddenPara", "docInfo", "templName", "dbNextSet", // checkme: 27
86 "dbNumSet", "dbSetNumber", "extUser", "pageSet", // checkme: 29,31
87 "pageGet", "INet", "jumpEdit", "script", // checkme: 32-33,35
88 "dateTime", "authority", "combinedChar", "dropDown" // checkme: 36-39
89 };
90 o << wh[m_type];
91 if (m_subType>=0) o << "[" << m_subType << "]";
92 o << ",";
93 }
94 else if (m_type>=0)
95 o << "###field[type]=" << m_type << ",";
96 if (m_format>=0)
97 o << "format=" << m_format << ",";
98 if (!m_name.empty())
99 o << "name=" << m_name.cstr() << ",";
100 if (!m_content.empty())
101 o << "content=" << m_content.cstr() << ",";
102 if (!m_textValue.empty())
103 o << "val=" << m_textValue.cstr() << ",";
104 else if (m_doubleValue<0||m_doubleValue>0)
105 o << "val=" << m_doubleValue << ",";
106 if (m_level)
107 o << "level=" << m_level << ",";
108 }
109
send(STOFFListenerPtr & listener,StarState & state) const110 bool Field::send(STOFFListenerPtr &listener, StarState &state) const
111 {
112 if (!listener || !listener->canWriteText()) {
113 STOFF_DEBUG_MSG(("SWFieldManagerInternal::Field::send: can not find the listener\n"));
114 return false;
115 }
116 STOFFField field;
117 if (m_type==1) {
118 if (m_name.empty()) {
119 STOFF_DEBUG_MSG(("SWFieldManagerInternal::Field::send: can not find the user name\n"));
120 return false;
121 }
122 field.m_propertyList.insert("librevenge:field-type", "text:user-defined");
123 field.m_propertyList.insert("text:name", m_name);
124 if (!m_content.empty())
125 field.m_propertyList.insert("office:string-value", m_content);
126 else if (!m_textValue.empty())
127 field.m_propertyList.insert("office:string-value", m_textValue);
128 else if (m_doubleValue<0 || m_doubleValue>0)
129 field.m_propertyList.insert("office:value", m_doubleValue, librevenge::RVNG_GENERIC);
130 }
131 else if (m_type==2) {
132 field.m_propertyList.insert("librevenge:field-type", "text:file-name");
133 if (m_format>=0 && m_format<=5) {
134 char const *wh[]= {"name-and-extension", "full", "path", "name", "name"/*uiname*/, "area" /* range*/ };
135 field.m_propertyList.insert("text:display", wh[m_format]);
136 }
137 else {
138 STOFF_DEBUG_MSG(("SWFieldManagerInternal::Field::send: unknown filename type=%d\n", m_format));
139 }
140 }
141 else if (m_type==3) {
142 if (m_name.empty()) {
143 STOFF_DEBUG_MSG(("SWFieldManagerInternal::Field::send: can not find the dbName\n"));
144 return false;
145 }
146 field.m_propertyList.insert("librevenge:field-type", "text:database-name");
147 updateDatabaseName(m_name, field.m_propertyList);
148 field.m_propertyList.insert("librevenge:field-content", m_name);
149 }
150 else if (m_type==7)
151 field.m_propertyList.insert("librevenge:field-type", "text:author-name");
152 else if (m_type==8) {
153 field.m_propertyList.insert("librevenge:field-type", "text:chapter");
154 if (m_format>=0 && m_format<=2) {
155 char const *wh[]= {"number", "name", "number-and-name"};
156 field.m_propertyList.insert("text:display", wh[m_format]);
157 }
158 else {
159 STOFF_DEBUG_MSG(("SWFieldManagerInternal::Field::send: unknown chapter type=%d\n", m_format));
160 }
161 if (m_level>=0)
162 field.m_propertyList.insert("text:outline-level", m_level+1);
163 }
164 else if (m_type==9) {
165 if (m_subType>=0 && m_subType<=6) {
166 char const *wh[]= {
167 "text:page-count", "text:paragraph-count", "text:word-count", "text:character-count", "text:table-count",
168 "text:image-count","text:object-count"
169 };
170 field.m_propertyList.insert("librevenge:field-type", wh[m_subType]);
171 }
172 else {
173 STOFF_DEBUG_MSG(("SWFieldManagerInternal::Field::send: unknown doc type=%d\n", m_subType));
174 return false;
175 }
176 }
177 else if (m_type==10) {
178 if (m_name.empty() || m_content.empty()) {
179 STOFF_DEBUG_MSG(("SWFieldManagerInternal::Field::send: can not find the expression values\n"));
180 return false;
181 }
182 if (m_subType&0x10) {
183 field.m_propertyList.insert("librevenge:field-type", "text:expression");
184 field.m_propertyList.insert("text:formula", m_name);
185 field.m_propertyList.insert("office:string-value", m_content);
186 }
187 else {
188 field.m_propertyList.insert("librevenge:field-type", "text:variable-get");
189 field.m_propertyList.insert("text:name", m_name);
190 }
191 if (!m_content.empty())
192 field.m_propertyList.insert("librevenge:field-content", m_content);
193 }
194 else if (m_type==12) {
195 if (m_name.empty()) {
196 STOFF_DEBUG_MSG(("SWFieldManagerInternal::Field::send: can not find the getRef values\n"));
197 return false;
198 }
199 field.m_propertyList.insert("librevenge:field-type", "text:reference-ref");
200 field.m_propertyList.insert("text:ref-name", m_name);
201 if (m_format>=0 && m_format<=10) {
202 char const *wh[]= {"page", "chapter", "text", "direction",
203 "text"/* as page style*/, "category-and-value", "caption", "number",
204 "number"/* new ref*/, "number"/*no context*/, "number"/*full context*/
205 };
206 field.m_propertyList.insert("text:reference-format",wh[m_format]);
207 }
208 else {
209 STOFF_DEBUG_MSG(("SWFieldManagerInternal::Field::send: unknown getRef format=%d\n", m_format));
210 }
211 if (!m_content.empty())
212 field.m_propertyList.insert("librevenge:field-content", m_content);
213 }
214 else if (m_type==23) {
215 if (m_name.empty()) {
216 STOFF_DEBUG_MSG(("SWFieldManagerInternal::Field::send: can not find the expression values\n"));
217 return false;
218 }
219 field.m_propertyList.insert("librevenge:field-type", "text:expression");
220 field.m_propertyList.insert("text:formula", m_name);
221 if (!m_content.empty()) {
222 field.m_propertyList.insert("office:string-value", m_content);
223 field.m_propertyList.insert("librevenge:field-content", m_content);
224 }
225 }
226 else if (m_type==25) {
227 int subType=m_subType&0x7FF;
228 if (subType>=4 && subType<8) {
229 field.m_propertyList.insert("librevenge:field-type", "text:user-defined");
230 field.m_propertyList.insert("text:name", state.m_global->m_object.getUserNameMetaData(subType-4));
231 }
232 else if (subType==9) {
233 if (m_format>=0 && m_format<=2) {
234 char const *wh[]= {
235 "text:creator", "text:modification-time", "text:modification-date"
236 };
237 field.m_propertyList.insert("librevenge:field-type", wh[m_format]);
238 }
239 else {
240 STOFF_DEBUG_MSG(("SWFieldManagerInternal::Field::send: sending custom type %d is not implemented\n", m_format));
241 }
242 }
243 else if (subType==10) {
244 if (m_format>=0 && m_format<=2) {
245 char const *wh[]= {
246 "text:printed-by", "text:print-time", "text:print-date"
247 };
248 field.m_propertyList.insert("librevenge:field-type", wh[m_format]);
249 }
250 else {
251 STOFF_DEBUG_MSG(("SWFieldManagerInternal::Field::send: sending custom type %d is not implemented\n", m_format));
252 }
253 }
254 else if (subType>=0 && subType<=12) {
255 char const *wh[]= {
256 "text:title", "text:subject", "text:keywords", "text:description",
257 "text:Info1", "text:Info2", "text:Info3", "text:Info4",
258 "text:editing-cycles", "", "", "text:editing-cycles",
259 "text:editing-duration"
260 };
261 field.m_propertyList.insert("librevenge:field-type", wh[subType]);
262 }
263 else {
264 STOFF_DEBUG_MSG(("SWFieldManagerInternal::Field::send: sending docInfo %d is not implemented\n", subType));
265 return false;
266 }
267 }
268 else if (m_type==20) {
269 field.m_propertyList.insert("librevenge:field-type", "text:text-input");
270 field.m_propertyList.insert("text:description", m_name);
271 field.m_propertyList.insert("librevenge:field-content", m_content);
272 }
273 else if (m_type==21) {
274 static bool first=true;
275 if (first) {
276 STOFF_DEBUG_MSG(("SWFieldManagerInternal::Field::send: sending macros is not implemented\n"));
277 first=false;
278 }
279 return true;
280 }
281 else if (m_type==26) {
282 int subType=m_format&0x7FF;
283 if (subType>=0 && subType<=5) {
284 char const *wh[]= {"name-and-extension", "full", "path", "name", "title"/*uiname*/, "area" /* range*/ };
285 field.m_propertyList.insert("librevenge:field-type", "text:template-name");
286 field.m_propertyList.insert("text:display", wh[subType]);
287 }
288 else {
289 STOFF_DEBUG_MSG(("SWFieldManagerInternal::Field::send: unknown template type=%d\n", m_format));
290 return false;
291 }
292 }
293 else if (m_type==30) {
294 if (m_subType>=0 && m_subType<=16) {
295 char const *wh[]= {
296 "text:sender-company", "text:sender-firstname", "text:sender-lastname", "text:sender-initials", "text:sender-street",
297 "text:sender-country", "text:sender-postal-code", "text:sender-city", "text:sender-title", "text:sender-position",
298 "text:sender-phone-private", "text:sender-phone-work", "text:sender-fax", "text:sender-email", "text:sender-state-or-province",
299 "text:sender-lastname" /*father name*/, "text:sender-street" /* appartement*/
300 };
301 field.m_propertyList.insert("librevenge:field-type", wh[m_subType]);
302 }
303 else {
304 STOFF_DEBUG_MSG(("SWFieldManagerInternal::Field::send: unknown extUser type=%d\n", m_subType));
305 return false;
306 }
307 }
308 else {
309 STOFF_DEBUG_MSG(("SWFieldManagerInternal::Field::send: sending type=%d is not implemented\n", m_type));
310 return false;
311 }
312 listener->insertField(field);
313 return true;
314 }
315
316 //! Internal: a fixed date time field
317 struct FieldDateTime final : public Field {
318 //! constructor
FieldDateTimeSWFieldManagerInternal::FieldDateTime319 FieldDateTime() : Field(), m_dateTime(0), m_time(0), m_offset(0)
320 {
321 }
322 //! copy constructor
FieldDateTimeSWFieldManagerInternal::FieldDateTime323 explicit FieldDateTime(Field const &orig) : Field(orig), m_dateTime(0), m_time(0), m_offset(0)
324 {
325 }
326 //! destructor
327 ~FieldDateTime() final;
328 //! add to send the zone data
329 bool send(STOFFListenerPtr &listener, StarState &state) const final;
330 //! print a field
printSWFieldManagerInternal::FieldDateTime331 void print(std::ostream &o) const final
332 {
333 Field::print(o);
334 if (m_dateTime) o << "date/time=" << m_dateTime << ",";
335 if (m_offset) o << "offset=" << m_offset << ",";
336 }
337 //! the dateTime
338 long m_dateTime;
339 //! the time
340 long m_time;
341 //! the offset
342 long m_offset;
343 };
344
~FieldDateTime()345 FieldDateTime::~FieldDateTime()
346 {
347 }
348
send(STOFFListenerPtr & listener,StarState & state) const349 bool FieldDateTime::send(STOFFListenerPtr &listener, StarState &state) const
350 {
351 if (!listener || !listener->canWriteText()) {
352 STOFF_DEBUG_MSG(("SWFieldManagerInternal::FieldDateTime::send: can not find the listener\n"));
353 return false;
354 }
355 STOFFField field;
356
357 if (m_type==4 || m_type==36)
358 field.m_propertyList.insert("librevenge:field-type", "text:date");
359 else if (m_type==5)
360 field.m_propertyList.insert("librevenge:field-type", "text:time");
361 else if (m_type==15) {
362 field.m_propertyList.insert("librevenge:field-type", "text:date");
363 field.m_propertyList.insert("text:fixed", true);
364 if (m_dateTime) {
365 field.m_propertyList.insert("librevenge:year", int(m_dateTime/10000));
366 field.m_propertyList.insert("librevenge:month", int((m_dateTime/100)%100));
367 field.m_propertyList.insert("librevenge:day", int(m_dateTime%100));
368 }
369 }
370 else if (m_type==16) {
371 // FIXME: does not works because libodfgen does not regenerate the text zone...
372 field.m_propertyList.insert("librevenge:field-type", "text:time");
373 field.m_propertyList.insert("text:fixed", true);
374 if (m_dateTime) {
375 field.m_propertyList.insert("librevenge:hours", int(m_dateTime/1000000));
376 field.m_propertyList.insert("librevenge:minutes", int((m_dateTime/10000)%100));
377 field.m_propertyList.insert("librevenge:seconds", int((m_dateTime/100)%100));
378 }
379 }
380 else
381 return Field::send(listener, state);
382 //TODO: set the format
383 listener->insertField(field);
384 return true;
385 }
386
387 //! Internal: a DB field field
388 struct FieldDBField final : public Field {
389 //! constructor
FieldDBFieldSWFieldManagerInternal::FieldDBField390 FieldDBField()
391 : Field()
392 , m_dbName("")
393 , m_colName("")
394 , m_longNumber(0)
395 {
396 }
397 //! copy constructor
FieldDBFieldSWFieldManagerInternal::FieldDBField398 explicit FieldDBField(Field const &orig) : Field(orig), m_dbName(""), m_colName(""), m_longNumber(0)
399 {
400 }
401 //! destructor
402 ~FieldDBField() final;
403 //! add to send the zone data
404 bool send(STOFFListenerPtr &listener, StarState &state) const final;
405 //! print a field
printSWFieldManagerInternal::FieldDBField406 void print(std::ostream &o) const final
407 {
408 Field::print(o);
409 if (!m_dbName.empty()) o << "dbName=" << m_dbName.cstr() << ",";
410 if (!m_colName.empty()) o << "colName=" << m_colName.cstr() << ",";
411 else if (m_longNumber) o << "number=" << m_longNumber << ",";
412 }
413 //! the dbName
414 librevenge::RVNGString m_dbName;
415 //! the column name
416 librevenge::RVNGString m_colName;
417 //! the number as num
418 long m_longNumber;
419 };
420
~FieldDBField()421 FieldDBField::~FieldDBField()
422 {
423 }
424
send(STOFFListenerPtr & listener,StarState & state) const425 bool FieldDBField::send(STOFFListenerPtr &listener, StarState &state) const
426 {
427 if (!listener || !listener->canWriteText()) {
428 STOFF_DEBUG_MSG(("SWFieldManagerInternal::FieldDBField::send: can not find the listener\n"));
429 return false;
430 }
431 STOFFField field;
432
433 if (m_type==0) {
434 if (m_colName.empty()) {
435 STOFF_DEBUG_MSG(("SWFieldManagerInternal::FieldDBField::send: can not find the col value\n"));
436 return false;
437 }
438 field.m_propertyList.insert("librevenge:field-type", "text:database-display");
439 if (!m_dbName.empty())
440 updateDatabaseName(m_dbName, field.m_propertyList);
441 field.m_propertyList.insert("text:column-name", m_colName);
442 }
443 else
444 return Field::send(listener, state);
445 //TODO: set the format
446 listener->insertField(field);
447 return true;
448 }
449
450 //! Internal: a hidden text/para field
451 struct FieldHiddenText final : public Field {
452 //! constructor
FieldHiddenTextSWFieldManagerInternal::FieldHiddenText453 FieldHiddenText()
454 : Field()
455 , m_hidden(true)
456 , m_condition("")
457 {
458 }
459 //! copy constructor
FieldHiddenTextSWFieldManagerInternal::FieldHiddenText460 explicit FieldHiddenText(Field const &orig) : Field(orig), m_hidden(true), m_condition("")
461 {
462 }
463 //! destructor
464 ~FieldHiddenText() final;
465 //! add to send the zone data
466 bool send(STOFFListenerPtr &listener, StarState &state) const final;
467 //! print a field
printSWFieldManagerInternal::FieldHiddenText468 void print(std::ostream &o) const final
469 {
470 Field::print(o);
471 if (!m_condition.empty()) o << "condition=" << m_condition.cstr() << ",";
472 if (!m_hidden) o << "hidden=false,";
473 }
474 //! the hidden flag
475 bool m_hidden;
476 //! the condition
477 librevenge::RVNGString m_condition;
478 };
479
~FieldHiddenText()480 FieldHiddenText::~FieldHiddenText()
481 {
482 }
483
send(STOFFListenerPtr & listener,StarState & state) const484 bool FieldHiddenText::send(STOFFListenerPtr &listener, StarState &state) const
485 {
486 if (!listener || !listener->canWriteText()) {
487 STOFF_DEBUG_MSG(("SWFieldManagerInternal::FieldHiddenText::send: can not find the listener\n"));
488 return false;
489 }
490 STOFFField field;
491 if (m_type==13) {
492 if (m_condition.empty()) {
493 STOFF_DEBUG_MSG(("SWFieldManagerInternal::FieldHiddenText::send: can not find the condition\n"));
494 return false;
495 }
496 field.m_propertyList.insert("librevenge:field-type", "text:conditional-text");
497 field.m_propertyList.insert("text:condition", m_condition);
498 if (!m_content.empty()) {
499 librevenge::RVNGString trueValue, falseValue;
500 libstoff::splitString(m_content, "|", trueValue, falseValue);
501 if (!trueValue.empty())
502 field.m_propertyList.insert("text:string-value-if-true", trueValue);
503 if (!falseValue.empty())
504 field.m_propertyList.insert("text:string-value-if-false", falseValue);
505 }
506 }
507 else if (m_type==24) {
508 if (m_condition.empty()) {
509 STOFF_DEBUG_MSG(("SWFieldManagerInternal::FieldHiddenText::send: can not find the condition\n"));
510 return false;
511 }
512 field.m_propertyList.insert("librevenge:field-type", "text:hidden-paragraph");
513 field.m_propertyList.insert("text:condition", m_condition);
514 field.m_propertyList.insert("text:is-hidden", m_hidden);
515 }
516 else // also ....
517 return Field::send(listener, state);
518 //TODO: set the format
519 listener->insertField(field);
520 return true;
521 }
522
523 //! Internal: a set field field
524 struct FieldINet final : public Field {
525 //! constructor
FieldINetSWFieldManagerInternal::FieldINet526 FieldINet()
527 : Field()
528 , m_url("")
529 , m_target("")
530 , m_libNames()
531 {
532 }
533 //! copy constructor
FieldINetSWFieldManagerInternal::FieldINet534 explicit FieldINet(Field const &orig)
535 : Field(orig)
536 , m_url("")
537 , m_target("")
538 , m_libNames()
539 {
540 }
541 //! destructor
542 ~FieldINet() final;
543 //! add to send the zone data
544 bool send(STOFFListenerPtr &listener, StarState &state) const final;
545 //! print a field
printSWFieldManagerInternal::FieldINet546 void print(std::ostream &o) const final
547 {
548 Field::print(o);
549 if (!m_url.empty()) o << "url=" << m_url.cstr() << ",";
550 if (!m_target.empty()) o << "target=" << m_target.cstr() << ",";
551 if (!m_libNames.empty()) {
552 o << "libNames=[";
553 for (size_t i=0; i+1<m_libNames.size(); i+=2)
554 o << m_libNames[i].cstr() << ":" << m_libNames[i+1].cstr() << ",";
555 o << "],";
556 }
557 }
558 //! the url
559 librevenge::RVNGString m_url;
560 //! the target
561 librevenge::RVNGString m_target;
562 //! the lib names
563 std::vector<librevenge::RVNGString> m_libNames;
564 };
565
~FieldINet()566 FieldINet::~FieldINet()
567 {
568 }
569
send(STOFFListenerPtr & listener,StarState & state) const570 bool FieldINet::send(STOFFListenerPtr &listener, StarState &state) const
571 {
572 if (!listener || !listener->canWriteText()) {
573 STOFF_DEBUG_MSG(("SWFieldManagerInternal::FieldINet::send: can not find the listener\n"));
574 return false;
575 }
576 if (m_type!=33)
577 return Field::send(listener, state);
578 if (m_url.empty()) {
579 STOFF_DEBUG_MSG(("SWFieldManagerInternal::FieldINet::send: the url is empty\n"));
580 return false;
581 }
582 STOFFLink link;
583 link.m_HRef=m_url.cstr();
584 listener->openLink(link);
585 if (!m_target.empty())
586 listener->insertUnicodeString(m_target);
587 else {
588 STOFF_DEBUG_MSG(("SWFieldManagerInternal::FieldINet::send: can not find any representation\n"));
589 }
590 listener->closeLink();
591 return true;
592 }
593
594 //! Internal: a jump edit field
595 struct FieldJumpEdit final : public Field {
596 //! constructor
FieldJumpEditSWFieldManagerInternal::FieldJumpEdit597 FieldJumpEdit()
598 : Field()
599 , m_help("")
600 {
601 }
602 //! copy constructor
FieldJumpEditSWFieldManagerInternal::FieldJumpEdit603 explicit FieldJumpEdit(Field const &orig)
604 : Field(orig)
605 , m_help("")
606 {
607 }
608 //! destructor
609 ~FieldJumpEdit() final;
610 //! add to send the zone data
611 bool send(STOFFListenerPtr &listener, StarState &state) const final;
612 //! print a field
printSWFieldManagerInternal::FieldJumpEdit613 void print(std::ostream &o) const final
614 {
615 Field::print(o);
616 if (!m_help.empty()) o << "help=" << m_help.cstr() << ",";
617 }
618 //! the help
619 librevenge::RVNGString m_help;
620 };
621
~FieldJumpEdit()622 FieldJumpEdit::~FieldJumpEdit()
623 {
624 }
625
send(STOFFListenerPtr & listener,StarState & state) const626 bool FieldJumpEdit::send(STOFFListenerPtr &listener, StarState &state) const
627 {
628 if (!listener || !listener->canWriteText()) {
629 STOFF_DEBUG_MSG(("SWFieldManagerInternal::FieldJumpEdit::send: can not find the listener\n"));
630 return false;
631 }
632 STOFFField field;
633 if (m_type==34) {
634 field.m_propertyList.insert("librevenge:field-type", "text:placeholder");
635 field.m_propertyList.insert("librevenge:field-content", m_content);
636 if (m_format>=0 && m_format<=4) {
637 char const *wh[]= {"text", "table", "text-box", "image", "object"};
638 field.m_propertyList.insert("text:placeholder-type",wh[m_format]);
639 }
640 else {
641 STOFF_DEBUG_MSG(("SWFieldManagerInternal::FieldJumpEdit::send: unknown format=%d\n", m_format));
642 }
643 if (!m_help.empty())
644 field.m_propertyList.insert("text:description", m_help);
645 }
646 else
647 return Field::send(listener, state);
648 listener->insertField(field);
649 return true;
650 }
651
652 //! Internal: a pageNumber field
653 struct FieldPageNumber final : public Field {
654 //! constructor
FieldPageNumberSWFieldManagerInternal::FieldPageNumber655 FieldPageNumber()
656 : Field()
657 , m_userString("")
658 , m_offset(0)
659 , m_isOn(true)
660 {
661 }
662 //! copy constructor
FieldPageNumberSWFieldManagerInternal::FieldPageNumber663 explicit FieldPageNumber(Field const &orig) : Field(orig), m_userString(""), m_offset(0), m_isOn(true)
664 {
665 }
666 //! destructor
667 ~FieldPageNumber() final;
668 //! add to send the zone data
669 bool send(STOFFListenerPtr &listener, StarState &state) const final;
670 //! print a field
printSWFieldManagerInternal::FieldPageNumber671 void print(std::ostream &o) const final
672 {
673 Field::print(o);
674 if (!m_userString.empty())
675 o << "userString=" << m_userString.cstr() << ",";
676 if (m_offset) o << "offset=" << m_offset << ",";
677 if (!m_isOn) o << "off,";
678 }
679 //! the userString
680 librevenge::RVNGString m_userString;
681 //! the offset
682 int m_offset;
683 //! a flag to know if isOn
684 bool m_isOn;
685 };
686
~FieldPageNumber()687 FieldPageNumber::~FieldPageNumber()
688 {
689 }
690
send(STOFFListenerPtr & listener,StarState & state) const691 bool FieldPageNumber::send(STOFFListenerPtr &listener, StarState &state) const
692 {
693 if (!listener || !listener->canWriteText()) {
694 STOFF_DEBUG_MSG(("SWFieldManagerInternal::FieldPageNumber::send: can not find the listener\n"));
695 return false;
696 }
697 STOFFField field;
698 if (m_type==6) {
699 field.m_propertyList.insert("librevenge:field-type", "text:page-number");
700 if (m_offset<0)
701 field.m_propertyList.insert("text:select-page", "previous");
702 else if (m_offset>0)
703 field.m_propertyList.insert("text:select-page", "next");
704 }
705 else // also 31 which is setPageRef
706 return Field::send(listener, state);
707 //TODO: set the format
708 listener->insertField(field);
709 return true;
710 }
711
712 //! Internal: a postit field
713 struct FieldPostIt final : public Field {
714 //! constructor
FieldPostItSWFieldManagerInternal::FieldPostIt715 FieldPostIt()
716 : Field()
717 , m_author("")
718 , m_date(0)
719 {
720 }
721 //! copy constructor
FieldPostItSWFieldManagerInternal::FieldPostIt722 explicit FieldPostIt(Field const &orig)
723 : Field(orig)
724 , m_author("")
725 , m_date(0)
726 {
727 }
728 //! destructor
729 ~FieldPostIt() final;
730 //! add to send the zone data
731 bool send(STOFFListenerPtr &listener, StarState &state) const final;
732 //! print a field
printSWFieldManagerInternal::FieldPostIt733 void print(std::ostream &o) const final
734 {
735 Field::print(o);
736 if (!m_author.empty()) o << "author=" << m_author.cstr() << ",";
737 if (m_date) o << "date=" << m_date << ",";
738 }
739 //! the author
740 librevenge::RVNGString m_author;
741 //! the date
742 long m_date;
743 };
744
~FieldPostIt()745 FieldPostIt::~FieldPostIt()
746 {
747 }
748
749 //! Internal: a script field
750 struct FieldScript final : public Field {
751 //! constructor
FieldScriptSWFieldManagerInternal::FieldScript752 FieldScript()
753 : Field()
754 , m_code("")
755 , m_scriptType("")
756 {
757 }
758 //! copy constructor
FieldScriptSWFieldManagerInternal::FieldScript759 explicit FieldScript(Field const &orig)
760 : Field(orig)
761 , m_code("")
762 , m_scriptType("")
763 {
764 }
765 //! destructor
766 ~FieldScript() final;
767 //! print a field
printSWFieldManagerInternal::FieldScript768 void print(std::ostream &o) const final
769 {
770 Field::print(o);
771 if (!m_code.empty()) o << "code=" << m_code.cstr() << ",";
772 if (!m_scriptType.empty()) o << "script[type]=" << m_scriptType.cstr() << ",";
773 }
774 //! the code
775 librevenge::RVNGString m_code;
776 //! the scriptType
777 librevenge::RVNGString m_scriptType;
778 };
779
~FieldScript()780 FieldScript::~FieldScript()
781 {
782 }
783
784 //! Internal: a set expr field
785 struct FieldSetExp final : public Field {
786 //! constructor
FieldSetExpSWFieldManagerInternal::FieldSetExp787 FieldSetExp()
788 : Field()
789 , m_fieldType(0)
790 , m_formula("")
791 , m_prompt("")
792 , m_seqVal(0)
793 , m_seqNo(0)
794 , m_delim('.')
795 {
796 }
797 //! copy constructor
FieldSetExpSWFieldManagerInternal::FieldSetExp798 explicit FieldSetExp(Field const &orig)
799 : Field(orig)
800 , m_fieldType(0)
801 , m_formula("")
802 , m_prompt("")
803 , m_seqVal(0)
804 , m_seqNo(0)
805 , m_delim('.')
806 {
807 }
808 //! destructor
809 ~FieldSetExp() final;
810 //! add to send the zone data
811 bool send(STOFFListenerPtr &listener, StarState &state) const final;
812 //! print a field
printSWFieldManagerInternal::FieldSetExp813 void print(std::ostream &o) const final
814 {
815 Field::print(o);
816 if (m_fieldType) o << "fieldType=" << m_fieldType << ",";
817 if (!m_formula.empty()) o << "formula=" << m_formula.cstr() << ",";
818 if (!m_prompt.empty()) o << "prompt=" << m_prompt.cstr() << ",";
819 if (m_seqVal) o << "seqVal=" << m_seqVal << ",";
820 if (m_seqNo) o << "seqNo=" << m_seqNo << ",";
821 if (m_delim!='.') o << "delim=" << m_delim << ",";
822 }
823 //! the field type
824 int m_fieldType;
825 //! the formula
826 librevenge::RVNGString m_formula;
827 //! the prompt
828 librevenge::RVNGString m_prompt;
829 //! the seq value
830 int m_seqVal;
831 //! the seq number
832 int m_seqNo;
833 //! the deliminator
834 char m_delim;
835 };
836
~FieldSetExp()837 FieldSetExp::~FieldSetExp()
838 {
839 }
840
send(STOFFListenerPtr & listener,StarState & state) const841 bool FieldSetExp::send(STOFFListenerPtr &listener, StarState &state) const
842 {
843 if (!listener || !listener->canWriteText()) {
844 STOFF_DEBUG_MSG(("SWFieldManagerInternal::FieldSetExp::send: can not find the listener\n"));
845 return false;
846 }
847 //TODO: set the format
848 STOFFField field;
849 if (m_type==11) {
850 if (m_format&8) // we must also set text:ref-name
851 field.m_propertyList.insert("librevenge:field-type", "text:sequence");
852 else
853 field.m_propertyList.insert("librevenge:field-type", "text:variable-set");
854 if (!m_name.empty())
855 field.m_propertyList.insert("text:name", m_name);
856 if (!m_formula.empty()) {
857 if (m_format&8)
858 field.m_propertyList.insert("text:formula", m_formula);
859 else
860 field.m_propertyList.insert("office:string-value", m_formula);
861 }
862 if (!m_content.empty())
863 field.m_propertyList.insert("librevenge:field-content", m_content);
864 }
865 else
866 return Field::send(listener, state);
867 listener->insertField(field);
868 return true;
869 }
870
871 //! Internal: a set field field
872 struct FieldSetField final : public Field {
873 //! constructor
FieldSetFieldSWFieldManagerInternal::FieldSetField874 FieldSetField()
875 : Field()
876 , m_condition("")
877 , m_dbName("")
878 , m_textNumber("")
879 , m_longNumber(0)
880 {
881 }
882 //! copy constructor
FieldSetFieldSWFieldManagerInternal::FieldSetField883 explicit FieldSetField(Field const &orig)
884 : Field(orig)
885 , m_condition("")
886 , m_dbName("")
887 , m_textNumber("")
888 , m_longNumber(0)
889 {
890 }
891 //! destructor
892 ~FieldSetField() final;
893 //! add to send the zone data
894 bool send(STOFFListenerPtr &listener, StarState &state) const final;
895 //! print a field
printSWFieldManagerInternal::FieldSetField896 void print(std::ostream &o) const final
897 {
898 Field::print(o);
899 if (!m_condition.empty()) o << "condition=" << m_condition.cstr() << ",";
900 if (!m_dbName.empty()) o << "dbName=" << m_dbName.cstr() << ",";
901 if (!m_textNumber.empty()) o << "number=" << m_textNumber.cstr() << ",";
902 else if (m_longNumber) o << "number=" << m_longNumber << ",";
903 }
904 //! the condition
905 librevenge::RVNGString m_condition;
906 //! the dbName
907 librevenge::RVNGString m_dbName;
908 //! the number as text
909 librevenge::RVNGString m_textNumber;
910 //! the number as num
911 long m_longNumber;
912 };
913
~FieldSetField()914 FieldSetField::~FieldSetField()
915 {
916 }
917
send(STOFFListenerPtr & listener,StarState & state) const918 bool FieldSetField::send(STOFFListenerPtr &listener, StarState &state) const
919 {
920 if (!listener || !listener->canWriteText()) {
921 STOFF_DEBUG_MSG(("SWFieldManagerInternal::FieldSetField::send: can not find the listener\n"));
922 return false;
923 }
924 //TODO: set the format
925 STOFFField field;
926 if (m_type==28) {
927 field.m_propertyList.insert("librevenge:field-type", "text:database-row-select");
928 updateDatabaseName(m_dbName, field.m_propertyList);
929 if (!m_condition.empty())
930 field.m_propertyList.insert("text:condition", m_condition);
931 if (!m_textNumber.empty())
932 field.m_propertyList.insert("text:row-number", m_textNumber);
933 else
934 field.m_propertyList.insert("text:row-number", int(m_longNumber));
935 // CHECKME: we need to set also text:table-type
936 }
937 else // also 27,29...
938 return Field::send(listener, state);
939 listener->insertField(field);
940 return true;
941 }
942
943 ////////////////////////////////////////
944 //! Internal: the state of a SWFieldManager
945 struct State {
946 //! constructor
StateSWFieldManagerInternal::State947 State()
948 {
949 }
950 };
951
952 ////////////////////////////////////////
953 //! Internal: the subdocument of a SWFieldManger
954 class SubDocument final : public STOFFSubDocument
955 {
956 public:
SubDocument(librevenge::RVNGString const & text)957 explicit SubDocument(librevenge::RVNGString const &text)
958 : STOFFSubDocument(nullptr, STOFFInputStreamPtr(), STOFFEntry())
959 , m_text(text) {}
960
961 //! destructor
~SubDocument()962 ~SubDocument() override {}
963
964 //! operator!=
operator !=(STOFFSubDocument const & doc) const965 bool operator!=(STOFFSubDocument const &doc) const final
966 {
967 if (STOFFSubDocument::operator!=(doc)) return true;
968 auto const *sDoc = dynamic_cast<SubDocument const *>(&doc);
969 if (!sDoc) return true;
970 if (m_text != sDoc->m_text) return true;
971 return false;
972 }
973
974 //! the parser function
975 void parse(STOFFListenerPtr &listener, libstoff::SubDocumentType type) final;
976
977 protected:
978 //! the text
979 librevenge::RVNGString m_text;
980 };
981
parse(STOFFListenerPtr & listener,libstoff::SubDocumentType)982 void SubDocument::parse(STOFFListenerPtr &listener, libstoff::SubDocumentType /*type*/)
983 {
984 if (!listener.get()) {
985 STOFF_DEBUG_MSG(("SWFielManagerInternal::SubDocument::parse: no listener\n"));
986 return;
987 }
988 if (m_text.empty())
989 listener->insertChar(' ');
990 else
991 listener->insertUnicodeString(m_text);
992 }
993
send(STOFFListenerPtr & listener,StarState & state) const994 bool FieldPostIt::send(STOFFListenerPtr &listener, StarState &state) const
995 {
996 if (!listener || !listener->canWriteText()) {
997 STOFF_DEBUG_MSG(("SWFieldManagerInternal::FieldPostIt::send: can not find the listener\n"));
998 return false;
999 }
1000 if (m_type==14) {
1001 std::shared_ptr<STOFFSubDocument> doc(new SubDocument(m_content));
1002 librevenge::RVNGString date;
1003 if (m_date)
1004 date.sprintf("%d/%d/%d", int((m_date/100)%100), int(m_date%100), int(m_date/10000));
1005 listener->insertComment(doc, m_author, date);
1006 return true;
1007 }
1008 return Field::send(listener, state);
1009 }
1010
1011 }
1012
1013 ////////////////////////////////////////////////////////////
1014 // constructor/destructor, ...
1015 ////////////////////////////////////////////////////////////
SWFieldManager()1016 SWFieldManager::SWFieldManager()
1017 : m_state(new SWFieldManagerInternal::State)
1018 {
1019 }
1020
~SWFieldManager()1021 SWFieldManager::~SWFieldManager()
1022 {
1023 }
1024
readField(StarZone & zone,unsigned char cKind)1025 std::shared_ptr<SWFieldManagerInternal::Field> SWFieldManager::readField(StarZone &zone, unsigned char cKind)
1026 {
1027 STOFFInputStreamPtr input=zone.input();
1028 libstoff::DebugFile &ascFile=zone.ascii();
1029 unsigned char type;
1030 long pos=input->tell();
1031 std::shared_ptr<SWFieldManagerInternal::Field> field;
1032 if (cKind!='_' && (input->peek()!=cKind || !zone.openSWRecord(type))) {
1033 input->seek(pos, librevenge::RVNG_SEEK_SET);
1034 return field;
1035 }
1036
1037 // sw_sw3field.cxx inFieldType('Y') or inField('y' or '_')
1038 field.reset(new SWFieldManagerInternal::Field);
1039 libstoff::DebugStream f;
1040 if (cKind!='_')
1041 f << "Entries(SWFieldType)[" << cKind << "-" << zone.getRecordLevel() << "]:";
1042 else
1043 f << "Entries(SWFieldType)[" << zone.getRecordLevel() << "]:";
1044 field->m_type=int(input->readULong(cKind=='Y' ? 1 : 2));
1045 if (cKind!='Y') {
1046 if (zone.isCompatibleWith(0x202)) {
1047 field->m_format=int(input->readULong(4));
1048 field->m_subType=int(input->readULong(2));
1049 }
1050 else if (zone.isCompatibleWith(0x200))
1051 field->m_format=int(input->readULong(4));
1052 else
1053 field->m_format=int(input->readULong(2));
1054 }
1055 int val;
1056 std::vector<uint32_t> name;
1057 librevenge::RVNGString poolName;
1058 long lastPos=zone.getRecordLastPosition();
1059 switch (field->m_type) {
1060 case 0: { // dbfld: cKind=='Y' call lcl_sw3io_InDBFieldType
1061 std::shared_ptr<SWFieldManagerInternal::FieldDBField> dBField(new SWFieldManagerInternal::FieldDBField(*field));
1062 field=dBField;
1063 if (cKind=='Y' || !zone.isCompatibleWith(0x202)) {
1064 if (!zone.isCompatibleWith(0xa)) {
1065 if (!zone.readString(name)) {
1066 f << "###string,";
1067 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1068 break;
1069 }
1070 else
1071 dBField->m_colName=libstoff::getString(name);
1072 }
1073 else {
1074 val=int(input->readULong(2));
1075 if (!zone.getPoolName(val, dBField->m_colName))
1076 f << "###nPoolId=" << val << ",";
1077 }
1078 if (cKind=='Y') {
1079 if (zone.isCompatibleWith(0x10,0x22, 0x101)) {
1080 val=int(input->readULong(2));
1081 if (!zone.getPoolName(val, dBField->m_dbName)) // dbName
1082 f << "###nDbName=" << val << ",";
1083 }
1084 break;
1085 }
1086 // lcl_sw3io_InDBField40
1087 if (!zone.readString(name)) {
1088 f << "###expand,";
1089 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1090 break;
1091 }
1092 else if (!name.empty())
1093 field->m_content=libstoff::getString(name); // expand
1094 if (zone.isCompatibleWith(0xa))
1095 f << "cFlag=" << std::hex << input->readULong(1) << std::dec << ",";
1096 if (zone.isCompatibleWith(0x10,0x22, 0x101)) {
1097 val=int(input->readULong(2));
1098 if (!zone.getPoolName(val, dBField->m_dbName)) // dbName
1099 f << "###nDbName=" << val << ",";
1100 }
1101 break;
1102 }
1103 // lcl_sw3io_InDBField
1104 auto cFlag=int(input->readULong(1));
1105 if (cFlag)
1106 f << "cFlag=" << std::hex << cFlag << std::dec << ",";
1107 val=int(input->readULong(2));
1108 if (!zone.getPoolName(val, dBField->m_colName)) // colName
1109 f << "###nColNamePoolId=" << val << ",";
1110 val=int(input->readULong(2));
1111 if (!zone.getPoolName(val, dBField->m_dbName))
1112 f << "###dbNamePoolId=" << val << ",";
1113 if (cFlag&1) {
1114 bool isNan;
1115 if (!input->readDoubleReverted8(field->m_doubleValue, isNan)) {
1116 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a double\n"));
1117 f << "##value,";
1118 }
1119 }
1120 else if (!zone.readString(name)) {
1121 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string value\n"));
1122 f << "##value,";
1123 break;
1124 }
1125 else
1126 field->m_textValue=libstoff::getString(name);
1127 break;
1128 }
1129 case 1: {
1130 // userfld: cKind==Y lcl_sw3io_InUserFieldType|lcl_sw3io_InUserFieldType40
1131 if (!zone.isCompatibleWith(0xa)) {
1132 if (!zone.readString(name)) {
1133 f << "###string,";
1134 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1135 break;
1136 }
1137 else
1138 field->m_name=libstoff::getString(name);
1139 }
1140 else {
1141 val=int(input->readULong(2));
1142 if (!zone.getPoolName(val, field->m_name))
1143 f << "###name=" << val << ",";
1144 }
1145 if (cKind!='Y' && zone.isCompatibleWith(0xa)) break;
1146 std::vector<uint32_t> text;
1147 if (!zone.readString(text)) {
1148 f << "###aContent,";
1149 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a aContent\n"));
1150 break;
1151 }
1152 else
1153 field->m_content=libstoff::getString(text);
1154 if (!zone.isCompatibleWith(0x0202)) {
1155 if (!zone.readString(text)) {
1156 f << "###aValue,";
1157 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a aValue\n"));
1158 break;
1159 }
1160 else
1161 field->m_textValue=libstoff::getString(text);
1162 }
1163 else {
1164 bool isNan;
1165 if (!input->readDoubleReverted8(field->m_doubleValue, isNan)) {
1166 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a double\n"));
1167 f << "##value,";
1168 break;
1169 }
1170 }
1171 val=int(input->readULong(2)); // StoreMe
1172 f << "type=" << val << ",";
1173 break;
1174 }
1175 case 2:
1176 if (cKind=='Y') break;
1177 // lcl_sw3io_InFileNameField
1178 if (input->tell()>=lastPos) break;
1179 if (!zone.readString(name)) {
1180 f << "###string,";
1181 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1182 break;
1183 }
1184 else if (!name.empty())
1185 field->m_name=libstoff::getString(name);
1186 break;
1187 case 3:
1188 if (cKind=='Y') break;
1189 // lcl_sw3io_InDBNameField
1190 if (zone.isCompatibleWith(0x10,0x22, 0x101)) {
1191 val=int(input->readULong(2));
1192 if (!zone.getPoolName(val, field->m_name))
1193 f << "###nDbName=" << val << ",";
1194 }
1195 break;
1196 case 4:
1197 // lcl_sw3io_InDateField40
1198 case 5:
1199 // lcl_sw3io_InTimeField40
1200 field.reset(new SWFieldManagerInternal::FieldDateTime(*field));
1201 break;
1202 case 6: {
1203 std::shared_ptr<SWFieldManagerInternal::FieldPageNumber> pageNumber(new SWFieldManagerInternal::FieldPageNumber(*field));
1204 field=pageNumber;
1205 if (cKind=='Y') break;
1206 // lcl_sw3io_InPageNumberField40 && lcl_sw3io_InPageNumberField
1207 if (!zone.isCompatibleWith(0x202)) {
1208 pageNumber->m_offset=int(input->readLong(2));
1209 pageNumber->m_subType=int(input->readULong(2)); // 1: next, 2:prev
1210 if (!zone.isCompatibleWith(0x9)) break;
1211 if (!zone.readString(name)) {
1212 f << "###string,";
1213 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1214 break;
1215 }
1216 pageNumber->m_userString=libstoff::getString(name);
1217 if (zone.isCompatibleWith(0x14,0x22) && (pageNumber->m_subType==1 || pageNumber->m_subType==2))
1218 pageNumber->m_offset=int(input->readLong(2));
1219 break;
1220 }
1221 pageNumber->m_offset=int(input->readLong(2));
1222 if (!zone.readString(name)) {
1223 f << "###string,";
1224 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1225 break;
1226 }
1227 pageNumber->m_userString=libstoff::getString(name);
1228 break;
1229 }
1230 case 7:
1231 // lcl_sw3io_InAuthorField
1232 if (cKind=='Y') break;
1233 if (zone.isCompatibleWith(0x204)) {
1234 if (!zone.readString(name)) {
1235 f << "###string,";
1236 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1237 break;
1238 }
1239 field->m_content=libstoff::getString(name);
1240 }
1241 break;
1242 case 8:
1243 if (cKind=='Y') break;
1244 // lcl_sw3io_InChapterField
1245 if (zone.isCompatibleWith(0x9))
1246 field->m_level=int(input->readULong(1));
1247 break;
1248 case 9:
1249 if (cKind=='Y') break;
1250 // lcl_sw3io_InDocStatField40 or lcl_sw3io_InDocStatField
1251 if (!zone.isCompatibleWith(0x202))
1252 field->m_subType=int(input->readULong(2));
1253 break;
1254 case 10:
1255 if (cKind=='Y') break;
1256 // lcl_sw3io_InGetExpField40 or lcl_sw3io_InGetExpField
1257 if (!zone.readString(name)) {
1258 f << "###string,";
1259 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1260 break;
1261 }
1262 field->m_name=libstoff::getString(name);
1263 if (!zone.readString(name)) {
1264 f << "###string,";
1265 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1266 break;
1267 }
1268 field->m_content=libstoff::getString(name).cstr();
1269 if (!zone.isCompatibleWith(0x202)) {
1270 field->m_subType=int(input->readULong(2));
1271 }
1272 break;
1273 case 11: { // setexpfield: ckind=y call lcl_sw3io_InSetExpFieldType
1274 std::shared_ptr<SWFieldManagerInternal::FieldSetExp> setExp(new SWFieldManagerInternal::FieldSetExp(*field));
1275 field=setExp;
1276 if (cKind!='Y' && zone.isCompatibleWith(0x202)) {
1277 // lcl_sw3io_InSetExpField
1278 auto cFlags=int(input->readULong(1));
1279 if (cFlags) f << "flag=" << cFlags << ",";
1280 val=int(input->readULong(2));
1281 if (!zone.getPoolName(val, field->m_name)) // checkme
1282 f << "###nName=" << val << ",";
1283 if (!zone.readString(name)) {
1284 f << "###formula,";
1285 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1286 break;
1287 }
1288 else
1289 setExp->m_formula=libstoff::getString(name);
1290 if (cFlags & 0x10) {
1291 if (!zone.readString(name)) {
1292 f << "###prompt,";
1293 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1294 break;
1295 }
1296 else
1297 setExp->m_prompt=libstoff::getString(name);
1298 }
1299 if (cFlags & 0x20) {
1300 setExp->m_seqVal=int(input->readULong(2));
1301 setExp->m_seqNo=int(input->readULong(2));
1302 }
1303 if (cFlags & 0x40) {
1304 if (!zone.readString(name)) {
1305 f << "###expand,";
1306 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1307 break;
1308 }
1309 else
1310 field->m_content=libstoff::getString(name);
1311 }
1312 break;
1313 }
1314 if (cKind=='Y')
1315 setExp->m_fieldType=int(input->readULong(2));
1316 if (!zone.isCompatibleWith(0xa)) {
1317 if (!zone.readString(name)) {
1318 f << "###string,";
1319 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1320 break;
1321 }
1322 else
1323 field->m_name=libstoff::getString(name);
1324 }
1325 else {
1326 val=int(input->readULong(2));
1327 if (!zone.getPoolName(val, field->m_name))
1328 f << "###name=" << val << ",";
1329 }
1330 if (cKind=='Y') {
1331 if ((setExp->m_fieldType&8) && zone.isCompatibleWith(0x202)) {
1332 setExp->m_delim=char(input->readULong(1));
1333 setExp->m_level=int(input->readULong(1));
1334 }
1335 break;
1336 }
1337 // lcl_sw3io_InSetExpField40 end
1338 auto cFlags=int(input->readULong(1));
1339 if (cFlags)
1340 f << "cFlags=" << cFlags << ",";
1341 if (!zone.readString(name)) {
1342 f << "###formula,";
1343 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1344 break;
1345 }
1346 else
1347 setExp->m_formula=libstoff::getString(name);
1348 if (!zone.readString(name)) {
1349 f << "###expand,";
1350 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1351 break;
1352 }
1353 else
1354 setExp->m_content=libstoff::getString(name);
1355 if ((cFlags & 0x10) && zone.isCompatibleWith(0x10)) {
1356 if (!zone.readString(name)) {
1357 f << "###prompt,";
1358 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1359 break;
1360 }
1361 else
1362 setExp->m_prompt=libstoff::getString(name);
1363 }
1364 if (cFlags & 0x20)
1365 setExp->m_seqNo=int(input->readULong(2));
1366 break;
1367 }
1368 case 12:
1369 if (cKind=='Y') break;
1370 // lcl_sw3io_InGetRefField40 or lcl_sw3io_InGetRefField
1371 if (!zone.readString(name)) {
1372 f << "###string,";
1373 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1374 break;
1375 }
1376 else
1377 field->m_name=libstoff::getString(name);
1378 if (!zone.readString(name)) {
1379 f << "###string,";
1380 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1381 break;
1382 }
1383 else
1384 field->m_content=libstoff::getString(name);
1385 if (zone.isCompatibleWith(0x21,0x22)) {
1386 field->m_format=int(input->readULong(2));
1387 field->m_subType=int(input->readULong(2));
1388 }
1389 else if (zone.isCompatibleWith(0x101,0x202))
1390 field->m_subType=int(input->readULong(2));
1391 f << "nSeqNo=" << input->readULong(2) << ",";
1392 break;
1393 case 13: {
1394 std::shared_ptr<SWFieldManagerInternal::FieldHiddenText> hiddenText(new SWFieldManagerInternal::FieldHiddenText(*field));
1395 field=hiddenText;
1396 if (cKind=='Y') break;
1397 // lcl_sw3io_InHiddenTxtField40 or lcl_sw3io_InHiddenTxtField
1398 f << "cFlags=" << input->readULong(1) << ",";
1399 if (!zone.readString(name)) {
1400 f << "###string,";
1401 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1402 break;
1403 }
1404 else
1405 hiddenText->m_content=libstoff::getString(name);
1406 if (!zone.readString(name)) {
1407 f << "###string,";
1408 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1409 break;
1410 }
1411 else
1412 hiddenText->m_condition=libstoff::getString(name);
1413 if (!zone.isCompatibleWith(0x202))
1414 field->m_subType=int(input->readULong(2));
1415 break;
1416 }
1417 case 14: {
1418 std::shared_ptr<SWFieldManagerInternal::FieldPostIt> postIt(new SWFieldManagerInternal::FieldPostIt(*field));
1419 field=postIt;
1420 if (cKind=='Y') break;
1421 // lcl_sw3io_InPostItField
1422 postIt->m_date=long(input->readULong(4));
1423 if (!zone.readString(name)) {
1424 f << "###string,";
1425 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1426 break;
1427 }
1428 else
1429 postIt->m_author=libstoff::getString(name);
1430 if (!zone.readString(name)) {
1431 f << "###string,";
1432 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1433 break;
1434 }
1435 else if (!name.empty())
1436 postIt->m_content=libstoff::getString(name);
1437 break;
1438 }
1439 case 15: // date
1440 case 16: { // time
1441 std::shared_ptr<SWFieldManagerInternal::FieldDateTime> dateTime(new SWFieldManagerInternal::FieldDateTime(*field));
1442 field=dateTime;
1443 if (cKind=='Y' || zone.isCompatibleWith(0x202)) break;
1444 // lcl_sw3io_InFixDateField40 or lcl_sw3io_InFixTimeField40
1445 dateTime->m_dateTime=long(input->readULong(4));
1446 break;
1447 }
1448 case 17:
1449 // unknown code
1450 break;
1451 case 18:
1452 // unknown code
1453 break;
1454 case 19:
1455 // unknown code
1456 break;
1457 case 20:
1458 if (cKind=='Y') break;
1459 // lcl_sw3io_InInputField40 or lcl_sw3io_InInputField
1460 if (!zone.readString(name)) {
1461 f << "###string,";
1462 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1463 break;
1464 }
1465 field->m_content=libstoff::getString(name);
1466 if (!zone.readString(name)) {
1467 f << "###string,";
1468 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1469 break;
1470 }
1471 else
1472 field->m_name=libstoff::getString(name); // the prompt
1473 if (!zone.isCompatibleWith(0x202))
1474 field->m_subType=int(input->readULong(2));
1475 break;
1476 case 21:
1477 if (cKind=='Y') break;
1478 // lcl_sw3io_InMacroField
1479 if (!zone.readString(name)) {
1480 f << "###string,";
1481 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1482 break;
1483 }
1484 else
1485 field->m_name=libstoff::getString(name);
1486 if (!zone.readString(name)) {
1487 f << "###string,";
1488 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1489 break;
1490 }
1491 else
1492 field->m_content=libstoff::getString(name);
1493 break;
1494 case 22: { // ddefld: cKind=Y call lcl_sw3io_InDDEFieldType
1495 if (cKind!='Y' && !zone.isCompatibleWith(0xa)) {
1496 val=int(input->readULong(2));
1497 if (!zone.getPoolName(val, field->m_name))
1498 f << "###name=" << val << ",";
1499 break;
1500 }
1501 // lcl_sw3io_InDDEField
1502 val=int(input->readULong(2));
1503 f << "nType=" << val << ","; // linkAlway, onUpdate, ...
1504 if (!zone.isCompatibleWith(0xa)) {
1505 if (!zone.readString(name)) {
1506 f << "###string,";
1507 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1508 break;
1509 }
1510 else
1511 field->m_name=libstoff::getString(name);
1512 }
1513 else {
1514 val=int(input->readULong(2));
1515 if (!zone.getPoolName(val, field->m_name))
1516 f << "###name=" << val << ",";
1517 }
1518 std::vector<uint32_t> text;
1519 if (!zone.readString(text)) {
1520 f << "###text,";
1521 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a text\n"));
1522 break;
1523 }
1524 else
1525 field->m_content=libstoff::getString(text);
1526 break;
1527 }
1528 case 23:
1529 if (cKind=='Y') break;
1530 // lcl_sw3io_InTblField
1531 if (!zone.readString(name)) {
1532 f << "###string,";
1533 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1534 break;
1535 }
1536 else // formula
1537 field->m_name=libstoff::getString(name);
1538 if (!zone.readString(name)) {
1539 f << "###string,";
1540 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1541 break;
1542 }
1543 else
1544 field->m_content=libstoff::getString(name).cstr();
1545 if (!zone.isCompatibleWith(0x202))
1546 field->m_subType=int(input->readULong(2));
1547 break;
1548 case 24: {
1549 std::shared_ptr<SWFieldManagerInternal::FieldHiddenText> hiddenPara(new SWFieldManagerInternal::FieldHiddenText(*field));
1550 field=hiddenPara;
1551 if (cKind=='Y') break;
1552 // lcl_sw3io_InHiddenParaField
1553 *input >> hiddenPara->m_hidden;
1554 if (!zone.readString(name)) {
1555 f << "###string,";
1556 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1557 break;
1558 }
1559 else
1560 hiddenPara->m_condition=libstoff::getString(name);
1561 break;
1562 }
1563 case 25:
1564 if (cKind=='Y') break;
1565 // lcl_sw3io_InDocInfoField40 or lcl_sw3io_InDocInfoField
1566 if (!zone.isCompatibleWith(0x202))
1567 field->m_subType=int(input->readULong(2));
1568 else {
1569 auto flag=int(input->readULong(1));
1570 if (!zone.readString(name)) {
1571 f << "###string,";
1572 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1573 break;
1574 }
1575 else
1576 field->m_content=libstoff::getString(name);
1577 if (flag&1) {
1578 bool isNan;
1579 if (!input->readDoubleReverted8(field->m_doubleValue, isNan)) {
1580 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a double\n"));
1581 f << "##value,";
1582 break;
1583 }
1584 }
1585 }
1586 break;
1587 case 26:
1588 // lcl_sw3io_InTemplNameField
1589 break;
1590 case 27: {
1591 std::shared_ptr<SWFieldManagerInternal::FieldSetField> setField(new SWFieldManagerInternal::FieldSetField(*field));
1592 field=setField;
1593 if (cKind=='Y') break;
1594 // lcl_sw3io_InDBNextSetField
1595 if (!zone.readString(name)) {
1596 f << "###string,";
1597 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1598 break;
1599 }
1600 else
1601 setField->m_condition=libstoff::getString(name);
1602 if (!zone.readString(name)) {
1603 f << "###string,";
1604 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1605 break;
1606 }
1607 else
1608 setField->m_name=libstoff::getString(name).cstr();
1609 if (zone.isCompatibleWith(0x10,0x22, 0x101)) {
1610 val=int(input->readULong(2));
1611 if (!zone.getPoolName(val, setField->m_dbName))
1612 f << "###dbName=" << val << ",";
1613 }
1614 break;
1615 }
1616 case 28: {
1617 std::shared_ptr<SWFieldManagerInternal::FieldSetField> setField(new SWFieldManagerInternal::FieldSetField(*field));
1618 field=setField;
1619 if (cKind=='Y') break;
1620 // lcl_sw3io_InDBNumSetField
1621 bool inverted=(zone.isCompatibleWith(0x22,0x101));
1622 if (!zone.readString(name)) {
1623 f << "###string,";
1624 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1625 break;
1626 }
1627 else if (inverted)
1628 setField->m_textNumber=libstoff::getString(name);
1629 else
1630 setField->m_condition=libstoff::getString(name);
1631 if (!zone.readString(name)) {
1632 f << "###string,";
1633 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1634 break;
1635 }
1636 else if (!inverted)
1637 setField->m_textNumber=libstoff::getString(name);
1638 else
1639 setField->m_condition=libstoff::getString(name);
1640 if (zone.isCompatibleWith(0x10,0x22, 0x101)) {
1641 val=int(input->readULong(2));
1642 if (!zone.getPoolName(val, setField->m_dbName))
1643 f << "###dbName=" << val << ",";
1644 }
1645 break;
1646 }
1647 case 29: {
1648 std::shared_ptr<SWFieldManagerInternal::FieldSetField> setField(new SWFieldManagerInternal::FieldSetField(*field));
1649 field=setField;
1650 if (cKind=='Y') break;
1651 // lcl_sw3io_InDBSetNumberField
1652 setField->m_longNumber=long(input->readULong(4));
1653 if (zone.isCompatibleWith(0x10,0x22, 0x101)) {
1654 val=int(input->readULong(2));
1655 if (!zone.getPoolName(val, setField->m_dbName))
1656 f << "###dbName=" << val << ",";
1657 }
1658 break;
1659 }
1660 case 30:
1661 if (cKind=='Y') break;
1662 // lcl_sw3io_InExtUserField40 or lcl_sw3io_InExtUserField
1663 if (!zone.readString(name)) {
1664 f << "###string,";
1665 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1666 break;
1667 }
1668 else // data
1669 field->m_name=libstoff::getString(name);
1670 if (!zone.isCompatibleWith(0x202))
1671 field->m_subType=int(input->readULong(2));
1672 else if (zone.isCompatibleWith(0x204)) {
1673 if (!zone.readString(name)) {
1674 f << "###string,";
1675 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1676 break;
1677 }
1678 else
1679 field->m_content=libstoff::getString(name);
1680 }
1681 break;
1682 case 31: {
1683 std::shared_ptr<SWFieldManagerInternal::FieldPageNumber> pageNumber(new SWFieldManagerInternal::FieldPageNumber(*field));
1684 field=pageNumber;
1685 if (cKind=='Y') break;
1686 // lcl_sw3io_InRefPageSetField
1687 pageNumber->m_offset=int(input->readLong(2));
1688 *input >> pageNumber->m_isOn;
1689 break;
1690 }
1691 case 32:
1692 if (cKind=='Y') break;
1693 // lcl_sw3io_InRefPageGetField
1694 if (!zone.readString(name)) {
1695 f << "###string,";
1696 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1697 break;
1698 }
1699 else
1700 field->m_content=libstoff::getString(name);
1701 break;
1702 case 33: {
1703 std::shared_ptr<SWFieldManagerInternal::FieldINet> iNet(new SWFieldManagerInternal::FieldINet(*field));
1704 field=iNet;
1705 if (cKind=='Y' || zone.isCompatibleWith(0x202)) break;
1706 // lcl_sw3io_InINetField31
1707 if (!zone.readString(name)) {
1708 f << "###string,";
1709 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1710 break;
1711 }
1712 else
1713 iNet->m_url=libstoff::getString(name).cstr();
1714 if (!zone.readString(name)) {
1715 f << "###string,";
1716 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1717 break;
1718 }
1719 else // text
1720 iNet->m_content=libstoff::getString(name);
1721 if (zone.isCompatibleWith(0x11,0x22)) {
1722 if (!zone.readString(name)) {
1723 f << "###string,";
1724 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1725 break;
1726 }
1727 else
1728 iNet->m_target=libstoff::getString(name);
1729 }
1730 if (zone.isCompatibleWith(0x11,0x13)) {
1731 auto nCnt=int(input->readULong(2));
1732 for (int i=0; i<nCnt; ++i) {
1733 if (input->tell()>lastPos) {
1734 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a libmac name\n"));
1735 f << "###libname,";
1736 break;
1737 }
1738 if (!zone.readString(name)) {
1739 f << "###string,";
1740 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1741 break;
1742 }
1743 else
1744 iNet->m_libNames.push_back(libstoff::getString(name).cstr());
1745 if (!zone.readString(name)) {
1746 f << "###string,";
1747 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1748 break;
1749 }
1750 else
1751 iNet->m_libNames.push_back(libstoff::getString(name).cstr());
1752 }
1753 }
1754 break;
1755 }
1756 case 34: {
1757 std::shared_ptr<SWFieldManagerInternal::FieldJumpEdit> jumpEdit(new SWFieldManagerInternal::FieldJumpEdit(*field));
1758 field=jumpEdit;
1759 if (cKind=='Y') break;
1760 // lcl_sw3io_InJumpEditField
1761 if (!zone.readString(name)) {
1762 f << "###string,";
1763 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1764 break;
1765 }
1766 else
1767 field->m_content=libstoff::getString(name);
1768 if (!zone.readString(name)) {
1769 f << "###string,";
1770 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1771 break;
1772 }
1773 else
1774 jumpEdit->m_help=libstoff::getString(name);
1775 break;
1776 }
1777 case 35: {
1778 std::shared_ptr<SWFieldManagerInternal::FieldScript> script(new SWFieldManagerInternal::FieldScript(*field));
1779 field=script;
1780 if (cKind=='Y') break;
1781 // lcl_sw3io_InScriptField40 or lcl_sw3io_InScriptField
1782 if (!zone.readString(name)) {
1783 f << "###string,";
1784 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1785 break;
1786 }
1787 else
1788 script->m_scriptType=libstoff::getString(name);
1789 if (!zone.readString(name)) {
1790 f << "###string,";
1791 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a string\n"));
1792 break;
1793 }
1794 else
1795 script->m_code=libstoff::getString(name);
1796 if (zone.isCompatibleWith(0x200))
1797 f << "cFlags=" << input->readULong(1) << ",";
1798 break;
1799 }
1800 case 36: {
1801 std::shared_ptr<SWFieldManagerInternal::FieldDateTime> dateTime(new SWFieldManagerInternal::FieldDateTime(*field));
1802 field=dateTime;
1803 if (cKind=='Y' || !zone.isCompatibleWith(0x202)) break;
1804 // lcl_sw3io_InDateTimeField
1805 bool isNan;
1806 if (!input->readDoubleReverted8(dateTime->m_doubleValue, isNan)) {
1807 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read a double\n"));
1808 f << "##value,";
1809 break;
1810 }
1811 if (zone.isCompatibleWith(0x205))
1812 dateTime->m_offset=long(input->readULong(4));
1813 break;
1814 }
1815 case 37: { // cKind==Y call lcl_sw3io_InAuthorityFieldType
1816 // TODO: store me
1817 if (cKind!='Y' && zone.isCompatibleWith(0x202)) {
1818 // lcl_sw3io_InAuthorityField
1819 zone.openFlagZone();
1820 f << "nPos=" << input->readULong(2) << ",";
1821 zone.closeFlagZone();
1822 break;
1823 }
1824 if (cKind!='Y') break;
1825 val=int(zone.openFlagZone());
1826 if (val&0xf0) f << "flag=" << (val>>4) << ",";
1827 auto N=int(input->readULong(2));
1828 if (N) f << "N=" << N << ",";
1829 val=int(input->readULong(1));
1830 if (val) f << "cPrefix=" << val << ",";
1831 val=int(input->readULong(1));
1832 if (val) f << "cSuffix=" << val << ",";
1833 auto nSort=int(input->readULong(2));
1834 if (nSort) f << "cSortCount=" << nSort << ",";
1835 zone.closeFlagZone();
1836
1837 bool ok=true;
1838 for (int i=0; i<N; ++i) {
1839 long actPos=input->tell();
1840 input->seek(actPos, librevenge::RVNG_SEEK_SET);
1841
1842 unsigned char authType;
1843 libstoff::DebugStream f2;
1844 f2<<"SWFieldType[auth-A" << i << "]:";
1845 if (input->peek()!='E' || !zone.openSWRecord(authType)) {
1846 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read an authority zone\n"));
1847
1848 f2<< "###";
1849 ascFile.addPos(actPos);
1850 ascFile.addNote(f2.str().c_str());
1851 ok=false;
1852 break;
1853 }
1854 ascFile.addPos(actPos);
1855 ascFile.addNote(f2.str().c_str());
1856 zone.closeSWRecord(authType, "SWFieldType");
1857 }
1858 if (!ok || !nSort) break;
1859 long actPos=input->tell();
1860 libstoff::DebugStream f2;
1861 f2<<"SWFieldType[auth-B]:";
1862 if (input->tell()+3*nSort>zone.getRecordLastPosition()) {
1863 STOFF_DEBUG_MSG(("SWFieldManager::readField: can not read sort data\n"));
1864 f2 << "###";
1865 ascFile.addPos(actPos);
1866 ascFile.addNote(f2.str().c_str());
1867 break;
1868 }
1869 f2 << "sort[flag:type]=[";
1870 for (int i=0; i<nSort; ++i) {
1871 f2 << std::hex << input->readULong(1) << std::dec << ":" << input->readULong(2) << ",";
1872 }
1873 f2 << "],";
1874 ascFile.addPos(actPos);
1875 ascFile.addNote(f2.str().c_str());
1876 break;
1877 }
1878 case 38: // combinedChar
1879 break;
1880 case 39: // dropdown108791
1881 break;
1882 default:
1883 STOFF_DEBUG_MSG(("SWFieldManager::readField: find unexpected flag\n"));
1884 break;
1885 }
1886 f << *field;
1887
1888 if (input->tell()!=zone.getRecordLastPosition() && cKind=='_') {
1889 STOFF_DEBUG_MSG(("SWFieldManager::readField: find extra data\n"));
1890 f << "###extra";
1891 ascFile.addDelimiter(input->tell(),'|');
1892 }
1893 ascFile.addPos(pos);
1894 ascFile.addNote(f.str().c_str());
1895
1896 if (cKind!='_')
1897 zone.closeSWRecord(cKind, "SWFieldType");
1898 return field;
1899 }
1900
readPersistField(StarZone & zone,long lastPos)1901 std::shared_ptr<SWFieldManagerInternal::Field> SWFieldManager::readPersistField(StarZone &zone, long lastPos)
1902 {
1903 std::shared_ptr<SWFieldManagerInternal::Field> field;
1904 // pstm.cxx SvPersistStream::ReadObj
1905 STOFFInputStreamPtr input=zone.input();
1906 long pos=input->tell();
1907 libstoff::DebugFile &ascii=zone.ascii();
1908 libstoff::DebugStream f;
1909 f << "Entries(PersistField)["<< zone.getRecordLevel() << "]:";
1910 // SvPersistStream::ReadId
1911 uint8_t hdr;
1912 *input >> hdr;
1913 long id=0, classId=0;
1914 bool ok=true;
1915 if (hdr&0x80) // nId=0
1916 ;
1917 else {
1918 if ((hdr&0xf)==0) {
1919 if ((hdr&0x20) || !(hdr&0x40))
1920 ok=input->readCompressedLong(id);
1921 }
1922 else if (hdr&0x10)
1923 ok=input->readCompressedLong(id);
1924 if (hdr&0x60)
1925 ok=input->readCompressedLong(classId);
1926 }
1927 if (id) f << "id=" << id << ",";
1928 if (classId) f << "id[class]=" << classId << ",";
1929 if (!ok || !hdr || input->tell()>lastPos) {
1930 STOFF_DEBUG_MSG(("SWFieldManager::readPersistField: find unexpected header\n"));
1931 f << "###header";
1932 ascii.addPos(pos);
1933 ascii.addNote(f.str().c_str());
1934 return field;
1935 }
1936 if (hdr&0x80 || (hdr&0x40)==0) {
1937 ascii.addPos(pos);
1938 ascii.addNote(f.str().c_str());
1939 return std::make_shared<SWFieldManagerInternal::Field>();
1940 }
1941 if (hdr&0x20) {
1942 ok=zone.openSCRecord();
1943 if (!ok || zone.getRecordLastPosition()>lastPos) {
1944 STOFF_DEBUG_MSG(("SWFieldManager::readPersistField: can not open main zone\n"));
1945 if (ok) zone.closeSCRecord("PersistField");
1946 f << "###,";
1947 ascii.addPos(pos);
1948 ascii.addNote(f.str().c_str());
1949 return field;
1950 }
1951 lastPos=zone.getRecordLastPosition();
1952 }
1953 if (hdr&0x40) {
1954 switch (classId) {
1955 // case 1 SvxFieldData::
1956 case 2: {
1957 // SvxDateField::Load
1958 if (input->tell()+8>lastPos) {
1959 STOFF_DEBUG_MSG(("SWFieldManager::readPersistField: can not read date field\n"));
1960 f << "###,";
1961 break;
1962 }
1963 auto dateTime=std::make_shared<SWFieldManagerInternal::FieldDateTime>();
1964 field=dateTime;
1965 dateTime->m_type=15;
1966 dateTime->m_dateTime=long(input->readULong(4));
1967 dateTime->m_subType=int(input->readULong(2));
1968 dateTime->m_format=int(input->readULong(2));
1969 if (dateTime->m_dateTime && dateTime->m_subType==1) // type==0: mean fixed
1970 dateTime->m_type=4;
1971 f << "date[field],";
1972 f << "date=" << dateTime->m_dateTime << ",";
1973 f << "type=" << dateTime->m_subType << ",";
1974 f << "format=" << dateTime->m_format << ",";
1975 break;
1976 }
1977 case 3: { // flditem.cxx:void SvxURLField::Load
1978 f << "urlData,";
1979 auto inet=std::make_shared<SWFieldManagerInternal::FieldINet>();
1980 field=inet;
1981 field->m_type=33;
1982 field->m_format=int(input->readULong(2));
1983 if (field->m_format) f << "format=" << field->m_format << ",";
1984 for (int i=0; i<2; ++i) {
1985 std::vector<uint32_t> text;
1986 if (!zone.readString(text) || input->tell()>lastPos) {
1987 STOFF_DEBUG_MSG(("SWFieldManager::readPersistField: can not read a string\n"));
1988 f << "##string";
1989 break;
1990 }
1991 else if (!text.empty()) {
1992 if (i==0)
1993 inet->m_url=libstoff::getString(text);
1994 else
1995 inet->m_target=libstoff::getString(text);
1996 f << (i==0 ? "url" : "representation") << "=" << libstoff::getString(text).cstr() << ",";
1997 }
1998 }
1999 if (input->tell()==lastPos)
2000 break;
2001 uint32_t nFrameMarker;
2002 *input>>nFrameMarker;
2003 uint16_t val;
2004 switch (nFrameMarker) {
2005 case 0x21981357:
2006 *input>>val;
2007 if (val) f << "char[set]=" << val << ",";
2008 break;
2009 case 0x21981358:
2010 for (int i=0; i<2; ++i) {
2011 *input>>val;
2012 if (val) f << "f" << i << "=" << val << ",";
2013 }
2014 break;
2015 default:
2016 input->seek(-4, librevenge::RVNG_SEEK_CUR);
2017 break;
2018 }
2019 break;
2020 }
2021 case 50: // SdrMeasureField(unsure)
2022 f << "measureField,";
2023 if (input->tell()+2>lastPos) {
2024 STOFF_DEBUG_MSG(("SWFieldManager::readPersistField: can not read measure field\n"));
2025 f << "###,";
2026 break;
2027 }
2028 f << "kind=" << input->readULong(2) << ",";
2029 break;
2030 case 100: // flditem.cxx
2031 field=std::make_shared<SWFieldManagerInternal::FieldPageNumber>();
2032 field->m_type=6;
2033 f << "pageField,";
2034 break;
2035 case 101:
2036 field=std::make_shared<SWFieldManagerInternal::Field>();
2037 field->m_type=9;
2038 field->m_subType=0;
2039 f << "pagesField,";
2040 break;
2041 case 102:
2042 field=std::make_shared<SWFieldManagerInternal::FieldDateTime>();
2043 field->m_type=5;
2044 f << "timeField,";
2045 break;
2046 case 103:
2047 field=std::make_shared<SWFieldManagerInternal::Field>();
2048 field->m_type=2;
2049 f << "fileField,";
2050 break;
2051 case 104:
2052 f << "tableField,";
2053 break;
2054 case 105: {
2055 f << "timeField[extended],";
2056 if (input->tell()+8>lastPos) {
2057 STOFF_DEBUG_MSG(("SWFieldManager::readPersistField: can not read extended time field\n"));
2058 f << "###,";
2059 break;
2060 }
2061 auto dateTime=std::make_shared<SWFieldManagerInternal::FieldDateTime>();
2062 field=dateTime;
2063 dateTime->m_type=16;
2064 dateTime->m_dateTime=long(input->readULong(4));
2065 dateTime->m_subType=int(input->readULong(2));
2066 dateTime->m_format=int(input->readULong(2));
2067 if (dateTime->m_dateTime && dateTime->m_subType==1) // type==0: mean fixed
2068 dateTime->m_type=5;
2069
2070 f << "date[field],";
2071 if (dateTime->m_dateTime)
2072 f << "time=" << dateTime->m_dateTime << ",";
2073 f << "type=" << dateTime->m_subType << ",";
2074 f << "format=" << dateTime->m_format << ",";
2075 break;
2076 }
2077 case 106: {
2078 f << "fileField[extended],";
2079 field=std::make_shared<SWFieldManagerInternal::Field>();
2080 field->m_type=2;
2081 std::vector<uint32_t> text;
2082 if (!zone.readString(text) || input->tell()+4>lastPos) {
2083 STOFF_DEBUG_MSG(("SWFieldManager::readPersistField: can not read a string\n"));
2084 f << "##string";
2085 break;
2086 }
2087 else if (!text.empty())
2088 f << libstoff::getString(text).cstr() << ",";
2089 f << "type=" << input->readULong(2) << ",";
2090 field->m_format=int(input->readULong(2));
2091 f << "format=" << field->m_format << ",";
2092 break;
2093 }
2094 case 107: {
2095 field=std::make_shared<SWFieldManagerInternal::Field>();
2096 field->m_type=7;
2097 f << "authorField,";
2098 bool fieldOk=true;
2099 for (int i=0; i<3; ++i) {
2100 std::vector<uint32_t> text;
2101 if (!zone.readString(text) || input->tell()>lastPos) {
2102 STOFF_DEBUG_MSG(("SWFieldManager::readPersistField: can not read a string\n"));
2103 f << "##string";
2104 fieldOk=false;
2105 break;
2106 }
2107 else if (!text.empty())
2108 f << (i==0 ? "name" : i==1 ? "first[name]": "last[name]") << "=" << libstoff::getString(text).cstr() << ",";
2109 }
2110 if (!fieldOk) break;
2111 if (input->tell()+4>lastPos) {
2112 STOFF_DEBUG_MSG(("SWFieldManager::readPersistField: can not read author field\n"));
2113 f << "###,";
2114 break;
2115 }
2116 f << "type=" << input->readULong(2) << ",";
2117 field->m_format=int(input->readULong(2));
2118 f << "format=" << field->m_format << ",";
2119 break;
2120 }
2121 default:
2122 STOFF_DEBUG_MSG(("SWFieldManager::readPersistField: unknown class id\n"));
2123 f << "##classId";
2124 break;
2125 }
2126 }
2127 if (input->tell()!=lastPos)
2128 ascii.addDelimiter(input->tell(),'|');
2129 input->seek(lastPos, librevenge::RVNG_SEEK_SET);
2130 if (hdr&0x20)
2131 zone.closeSCRecord("PersistField");
2132
2133 ascii.addPos(pos);
2134 ascii.addNote(f.str().c_str());
2135 if (field) return field;
2136 return std::make_shared<SWFieldManagerInternal::Field>(); // create a dummy field
2137 }
2138
2139 // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab:
2140