1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2
3 /* AbiWord
4 * Copyright (C) 2001 AbiSource, Inc.
5 * Copyright (C) 2002-2004 Marc Maurer (uwog@uwog.net)
6 * Copyright (C) 2002-2005 William Lachance (william.lachance@sympatico.ca)
7 * Copyright (C) 2006 Fridrich Strba (fridrich.strba@bluewin.ch)
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301 USA.
23 */
24
25 /* See bug 1764
26 * "This product is not manufactured, approved, or supported by
27 * Corel Corporation or Corel Corporation Limited."
28 */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <math.h>
34 #include <map>
35 #include <string>
36 #include <gsf/gsf-utils.h>
37 #include <gsf/gsf-input-memory.h>
38 #include <gsf/gsf-input-stdio.h>
39
40 #include "ut_types.h"
41 #include "ut_string.h"
42 #include "ut_string_class.h"
43 #include "ut_units.h"
44 #include "ut_growbuf.h"
45 #include "ut_assert.h"
46 #include "ut_debugmsg.h"
47 #include "ut_math.h" // for rint (font size)
48 #include "ut_rand.h"
49 #include "ut_locale.h"
50
51 #include "xap_Frame.h"
52 #include "xap_EncodingManager.h"
53
54 #include "pd_Document.h"
55 #include "pt_Types.h"
56
57 #include "fl_AutoLists.h"
58 #include "fl_AutoNum.h"
59
60 #include "ie_imp_WordPerfect.h"
61 #include "ie_impexp_WordPerfect.h"
62
63 // Stream class
64
65 #include <librevenge-stream/librevenge-stream.h>
66 #include <libwpd/libwpd.h>
67
68 #include <gsf/gsf-input.h>
69 #include <gsf/gsf-infile.h>
70 #include <gsf/gsf-infile-msole.h>
71 #include <gsf/gsf-infile-zip.h>
72
73 #ifdef HAVE_LIBWPS
74 #include <libwps/libwps.h>
75 #endif
76
77 class AbiWordperfectInputStream : public librevenge::RVNGInputStream
78 {
79 public:
80 AbiWordperfectInputStream(GsfInput *input);
81 ~AbiWordperfectInputStream();
82
83 virtual bool isStructured();
84 virtual unsigned subStreamCount();
85 virtual const char* subStreamName(unsigned);
86 bool existsSubStream(const char*);
87 virtual librevenge::RVNGInputStream* getSubStreamByName(const char*);
88 virtual librevenge::RVNGInputStream* getSubStreamById(unsigned);
89 virtual const unsigned char *read(unsigned long numBytes, unsigned long &numBytesRead);
90 virtual int seek(long offset, librevenge::RVNG_SEEK_TYPE seekType);
91 virtual long tell();
92 virtual bool isEnd();
93
94 private:
95
96 GsfInput *m_input;
97 GsfInfile *m_ole;
98 std::map<unsigned, std::string> m_substreams;
99 };
100
AbiWordperfectInputStream(GsfInput * input)101 AbiWordperfectInputStream::AbiWordperfectInputStream(GsfInput *input) :
102 librevenge::RVNGInputStream(),
103 m_input(input),
104 m_ole(NULL),
105 m_substreams()
106 {
107 g_object_ref(G_OBJECT(input));
108 }
109
~AbiWordperfectInputStream()110 AbiWordperfectInputStream::~AbiWordperfectInputStream()
111 {
112 if (m_ole)
113 g_object_unref(G_OBJECT(m_ole));
114
115 g_object_unref(G_OBJECT(m_input));
116 }
117
read(unsigned long numBytes,unsigned long & numBytesRead)118 const unsigned char * AbiWordperfectInputStream::read(unsigned long numBytes, unsigned long &numBytesRead)
119 {
120 const unsigned char *buf = gsf_input_read(m_input, numBytes, NULL);
121
122 if (buf == NULL)
123 numBytesRead = 0;
124 else
125 numBytesRead = numBytes;
126
127 return buf;
128 }
129
seek(long offset,librevenge::RVNG_SEEK_TYPE seekType)130 int AbiWordperfectInputStream::seek(long offset, librevenge::RVNG_SEEK_TYPE seekType)
131 {
132 GSeekType gsfSeekType = G_SEEK_SET;
133 switch(seekType)
134 {
135 case librevenge::RVNG_SEEK_CUR:
136 gsfSeekType = G_SEEK_CUR;
137 break;
138 case librevenge::RVNG_SEEK_SET:
139 gsfSeekType = G_SEEK_SET;
140 break;
141 case librevenge::RVNG_SEEK_END:
142 gsfSeekType = G_SEEK_END;
143 break;
144 }
145
146 return gsf_input_seek(m_input, offset, gsfSeekType);
147 }
148
isStructured()149 bool AbiWordperfectInputStream::isStructured()
150 {
151 if (!m_ole)
152 m_ole = GSF_INFILE(gsf_infile_msole_new (m_input, NULL));
153
154 if (!m_ole)
155 m_ole = GSF_INFILE(gsf_infile_zip_new (m_input, NULL));
156
157 if (m_ole)
158 return true;
159
160 return false;
161 }
162
subStreamCount()163 unsigned AbiWordperfectInputStream::subStreamCount()
164 {
165 if (!m_ole)
166 m_ole = GSF_INFILE(gsf_infile_msole_new (m_input, NULL));
167
168 if (!m_ole)
169 m_ole = GSF_INFILE(gsf_infile_zip_new (m_input, NULL));
170
171 if (m_ole)
172 {
173 int numChildren = gsf_infile_num_children(m_ole);
174 if (numChildren > 0)
175 return numChildren;
176 return 0;
177 }
178
179 return 0;
180 }
181
subStreamName(unsigned id)182 const char * AbiWordperfectInputStream::subStreamName(unsigned id)
183 {
184 if (!m_ole)
185 m_ole = GSF_INFILE(gsf_infile_msole_new (m_input, NULL));
186
187 if (!m_ole)
188 m_ole = GSF_INFILE(gsf_infile_zip_new (m_input, NULL));
189
190 if (m_ole)
191 {
192 if ((int)id >= gsf_infile_num_children(m_ole))
193 {
194 return 0;
195 }
196 std::map<unsigned, std::string>::iterator i = m_substreams.lower_bound(id);
197 if (i == m_substreams.end() || m_substreams.key_comp()(id, i->first))
198 {
199 std::string name = gsf_infile_name_by_index(m_ole, (int)id);
200 i = m_substreams.insert(i, std::map<unsigned, std::string>::value_type(id, name));
201 }
202 return i->second.c_str();
203 }
204
205 return 0;
206 }
207
existsSubStream(const char * name)208 bool AbiWordperfectInputStream::existsSubStream(const char * name)
209 {
210 if (!m_ole)
211 m_ole = GSF_INFILE(gsf_infile_msole_new (m_input, NULL));
212
213 if (!m_ole)
214 m_ole = GSF_INFILE(gsf_infile_zip_new (m_input, NULL));
215
216 if (m_ole)
217 {
218 GsfInput *document = gsf_infile_child_by_name(m_ole, name);
219 if (document)
220 {
221 g_object_unref(G_OBJECT (document));
222 return true;
223 }
224 }
225
226 return false;
227 }
228
getSubStreamByName(const char * name)229 librevenge::RVNGInputStream * AbiWordperfectInputStream::getSubStreamByName(const char * name)
230 {
231 librevenge::RVNGInputStream *documentStream = NULL;
232
233 if (!m_ole)
234 m_ole = GSF_INFILE(gsf_infile_msole_new (m_input, NULL));
235
236 if (!m_ole)
237 m_ole = GSF_INFILE(gsf_infile_zip_new (m_input, NULL));
238
239 if (m_ole)
240 {
241 GsfInput *document = gsf_infile_child_by_name(m_ole, name);
242 if (document)
243 {
244 documentStream = new AbiWordperfectInputStream(document);
245 g_object_unref(G_OBJECT (document)); // the only reference should be encapsulated within the new stream
246 }
247 }
248
249 return documentStream;
250 }
251
getSubStreamById(unsigned id)252 librevenge::RVNGInputStream * AbiWordperfectInputStream::getSubStreamById(unsigned id)
253 {
254 librevenge::RVNGInputStream *documentStream = NULL;
255
256 if (!m_ole)
257 m_ole = GSF_INFILE(gsf_infile_msole_new (m_input, NULL));
258
259 if (!m_ole)
260 m_ole = GSF_INFILE(gsf_infile_zip_new (m_input, NULL));
261
262 if (m_ole)
263 {
264 GsfInput *document = gsf_infile_child_by_index(m_ole, (int)id);
265 if (document)
266 {
267 documentStream = new AbiWordperfectInputStream(document);
268 g_object_unref(G_OBJECT (document)); // the only reference should be encapsulated within the new stream
269 }
270 }
271
272 return documentStream;
273 }
274
tell()275 long AbiWordperfectInputStream::tell()
276 {
277 return gsf_input_tell(m_input);
278 }
279
isEnd()280 bool AbiWordperfectInputStream::isEnd()
281 {
282 return gsf_input_eof(m_input);
283 }
284
285 // This should probably be defined in pt_Types.h
286 static const UT_uint32 PT_MAX_ATTRIBUTES = 8;
287
ABI_ListDefinition(int iOutlineHash)288 ABI_ListDefinition::ABI_ListDefinition(int iOutlineHash) :
289 m_iOutlineHash(iOutlineHash)
290 {
291 for(int i=0; i<WP6_NUM_LIST_LEVELS; i++)
292 {
293 m_iListIDs[i] = 0;
294 m_listTypes[i] = BULLETED_LIST;
295 m_iListNumbers[i] = 0;
296 m_listLeftOffset[i] = 0.0f;
297 m_listMinLabelWidth[i] = 0.0f;
298 }
299 }
300
setListType(const int level,const char type)301 void ABI_ListDefinition::setListType(const int level, const char type)
302 {
303 switch (type)
304 {
305 case '1':
306 m_listTypes[level-1] = NUMBERED_LIST;
307 break;
308 case 'a':
309 m_listTypes[level-1] = LOWERCASE_LIST;
310 break;
311 case 'A':
312 m_listTypes[level-1] = UPPERCASE_LIST;
313 break;
314 case 'i':
315 m_listTypes[level-1] = LOWERROMAN_LIST;
316 break;
317 case 'I':
318 m_listTypes[level-1] = UPPERROMAN_LIST;
319 break;
320 }
321 }
322
323 #define X_CheckDocumentError(v) if (!v) { UT_DEBUGMSG(("X_CheckDocumentError: %d\n", __LINE__)); }
324
IE_Imp_WordPerfect_Sniffer()325 IE_Imp_WordPerfect_Sniffer::IE_Imp_WordPerfect_Sniffer()
326 : IE_ImpSniffer(IE_MIMETYPE_WP_6)
327 {
328 }
329
~IE_Imp_WordPerfect_Sniffer()330 IE_Imp_WordPerfect_Sniffer::~IE_Imp_WordPerfect_Sniffer()
331 {
332 }
333
334 // supported suffixes
335 static IE_SuffixConfidence IE_Imp_WordPerfect_Sniffer__SuffixConfidence[] = {
336 { "wpd", UT_CONFIDENCE_PERFECT },
337 { "wp", UT_CONFIDENCE_PERFECT },
338 { "", UT_CONFIDENCE_ZILCH }
339 };
340
getSuffixConfidence()341 const IE_SuffixConfidence * IE_Imp_WordPerfect_Sniffer::getSuffixConfidence ()
342 {
343 return IE_Imp_WordPerfect_Sniffer__SuffixConfidence;
344 }
345
recognizeContents(GsfInput * input)346 UT_Confidence_t IE_Imp_WordPerfect_Sniffer::recognizeContents (GsfInput * input)
347 {
348 AbiWordperfectInputStream gsfInput(input);
349
350 libwpd::WPDConfidence confidence = libwpd::WPDocument::isFileFormatSupported(&gsfInput);
351
352 switch (confidence)
353 {
354 case libwpd::WPD_CONFIDENCE_NONE:
355 return UT_CONFIDENCE_ZILCH;
356 case libwpd::WPD_CONFIDENCE_EXCELLENT:
357 return UT_CONFIDENCE_PERFECT;
358 default:
359 return UT_CONFIDENCE_ZILCH;
360 }
361 }
362
constructImporter(PD_Document * pDocument,IE_Imp ** ppie)363 UT_Error IE_Imp_WordPerfect_Sniffer::constructImporter (PD_Document * pDocument,
364 IE_Imp ** ppie)
365 {
366 *ppie = new IE_Imp_WordPerfect(pDocument);
367 return UT_OK;
368 }
369
getDlgLabels(const char ** pszDesc,const char ** pszSuffixList,IEFileType * ft)370 bool IE_Imp_WordPerfect_Sniffer::getDlgLabels (const char ** pszDesc,
371 const char ** pszSuffixList,
372 IEFileType * ft)
373 {
374 *pszDesc = "WordPerfect (.wpd, .wp)";
375 *pszSuffixList = "*.wpd; *.wp";
376 *ft = getFileType();
377 return true;
378 }
379
380 /****************************************************************************/
381 /****************************************************************************/
382
IE_Imp_WordPerfect(PD_Document * pDocument)383 IE_Imp_WordPerfect::IE_Imp_WordPerfect(PD_Document * pDocument)
384 : IE_Imp (pDocument),
385 m_leftPageMargin(1.0f),
386 m_rightPageMargin(1.0f),
387 m_leftSectionMargin(0.0f),
388 m_rightSectionMargin(0.0f),
389 m_sectionColumnsCount(0),
390 m_headerId(-1),
391 m_footerId(-1),
392 m_nextFreeId(0),
393 m_leftMarginOffset(0.0f),
394 m_rightMarginOffset(0.0f),
395 m_pCurrentListDefinition(NULL),
396 m_bParagraphChanged(false),
397 m_bParagraphInSection(false),
398 m_bInSection(false),
399 m_bSectionChanged(false),
400 m_bRequireBlock(false),
401 m_iCurrentListLevel(0),
402 m_bInCell(false),
403 m_bHdrFtrOpenCount(0)
404 {
405 }
406
~IE_Imp_WordPerfect()407 IE_Imp_WordPerfect::~IE_Imp_WordPerfect()
408 {
409 //UT_HASH_PURGEDATA(ABI_ListDefinition *,&m_listStylesHash,delete);
410 }
411
_loadFile(GsfInput * input)412 UT_Error IE_Imp_WordPerfect::_loadFile(GsfInput * input)
413 {
414 AbiWordperfectInputStream gsfInput(input);
415 libwpd::WPDResult error = libwpd::WPDocument::parse(&gsfInput, static_cast<librevenge::RVNGTextInterface *>(this), NULL);
416
417 if (error != libwpd::WPD_OK)
418 {
419 UT_DEBUGMSG(("AbiWordPerfect: ERROR: %i!\n", (int)error));
420 return UT_IE_IMPORTERROR;
421 }
422
423 return UT_OK;
424 }
425
pasteFromBuffer(PD_DocumentRange *,unsigned char *,unsigned int,const char *)426 void IE_Imp_WordPerfect::pasteFromBuffer (PD_DocumentRange *,
427 unsigned char *, unsigned int, const char *)
428 {
429 // nada
430 }
431
setDocumentMetaData(const librevenge::RVNGPropertyList & propList)432 void IE_Imp_WordPerfect::setDocumentMetaData(const librevenge::RVNGPropertyList &propList)
433 {
434 if (propList["dc:author"])
435 getDoc()->setMetaDataProp(PD_META_KEY_CREATOR, propList["dc:author"]->getStr().cstr());
436 if (propList["dc:subject"])
437 getDoc()->setMetaDataProp(PD_META_KEY_SUBJECT, propList["dc:subject"]->getStr().cstr());
438 if (propList["dc:publisher"])
439 getDoc()->setMetaDataProp(PD_META_KEY_PUBLISHER, propList["dc:publisher"]->getStr().cstr());
440 if (propList["dc:type"])
441 getDoc()->setMetaDataProp(PD_META_KEY_TYPE, propList["dc:category"]->getStr().cstr());
442 if (propList["librevenge:keywords"])
443 getDoc()->setMetaDataProp(PD_META_KEY_KEYWORDS, propList["librevenge:keywords"]->getStr().cstr());
444 if (propList["dc:language"])
445 getDoc()->setMetaDataProp(PD_META_KEY_LANGUAGE, propList["dc:language"]->getStr().cstr());
446 if (propList["librevenge:abstract"])
447 getDoc()->setMetaDataProp(PD_META_KEY_DESCRIPTION, propList["librevenge:abstract"]->getStr().cstr());
448 }
449
startDocument(const librevenge::RVNGPropertyList &)450 void IE_Imp_WordPerfect::startDocument(const librevenge::RVNGPropertyList & /* propList */)
451 {
452 UT_DEBUGMSG(("AbiWordPerfect: startDocument\n"));
453 }
454
endDocument()455 void IE_Imp_WordPerfect::endDocument()
456 {
457 UT_DEBUGMSG(("AbiWordPerfect: endDocument\n"));
458 }
459
openPageSpan(const librevenge::RVNGPropertyList & propList)460 void IE_Imp_WordPerfect::openPageSpan(const librevenge::RVNGPropertyList &propList)
461 {
462 if (m_bHdrFtrOpenCount) return; // HACK
463 UT_DEBUGMSG(("AbiWordPerfect: openPageSpan\n"));
464
465 float marginLeft = 1.0f, marginRight = 1.0f;
466
467 if (propList["fo:margin-left"])
468 marginLeft = propList["fo:margin-left"]->getDouble();
469 if (propList["fo:margin-right"])
470 marginRight = propList["fo:margin-right"]->getDouble();
471
472 if (marginLeft != m_leftPageMargin || marginRight != m_rightPageMargin /* || */
473 /* marginTop != m_marginBottom || marginBottom != m_marginBottom */ )
474 m_bSectionChanged = true; // margin properties are section properties in AbiWord
475
476 m_leftPageMargin = marginLeft;
477 m_rightPageMargin = marginRight;
478
479 }
480
openHeader(const librevenge::RVNGPropertyList &)481 void IE_Imp_WordPerfect::openHeader(const librevenge::RVNGPropertyList & /*propList*/)
482 {
483 m_bHdrFtrOpenCount++;
484
485 /*
486 TODO: THIS CODE IS NOT!!!! USEFULL! - DON'T TOUCH IT - MARCM
487 UT_String propBuffer;
488
489 switch (headerFooterType)
490 {
491 case HEADER:
492 m_headerId = m_nextFreeId;
493 UT_String_sprintf(propBuffer,"id:%d; listid:0; parentid=0; type=header", m_headerId);
494 break;
495 case FOOTER:
496 m_footerId = m_nextFreeId;
497 UT_String_sprintf(propBuffer,"id:%d; listid:0; parentid=0; type=footer", m_footerId);
498 break;
499 default:
500 UT_ASSERT(SHOULD_NOT_HAPPEN);
501 break;
502 }
503
504 const gchar* propsArray[3];
505 propsArray[0] = "props";
506 propsArray[1] = propBuffer.c_str();
507 propsArray[2] = NULL;
508
509 X_CheckDocumentError(appendStrux(PTX_Section, propsArray));
510 m_bInSection = true;
511 m_bSectionChanged = false;*/
512 }
513
closeHeader()514 void IE_Imp_WordPerfect::closeHeader()
515 {
516 m_bHdrFtrOpenCount--;
517 /*
518 TODO: THIS CODE IS NOT!!!! USEFULL! - DON'T TOUCH IT - MARCM
519 m_nextFreeId++;
520 */
521 }
522
openFooter(const librevenge::RVNGPropertyList &)523 void IE_Imp_WordPerfect::openFooter(const librevenge::RVNGPropertyList & /*propList*/)
524 {
525 m_bHdrFtrOpenCount++;
526 // see above comments re: openHeader
527 }
528
closeFooter()529 void IE_Imp_WordPerfect::closeFooter()
530 {
531 m_bHdrFtrOpenCount--;
532 // see above comments re: closeHeader
533 }
534
openParagraph(const librevenge::RVNGPropertyList & propList)535 void IE_Imp_WordPerfect::openParagraph(const librevenge::RVNGPropertyList &propList)
536 {
537 if (m_bHdrFtrOpenCount) return; // HACK
538 UT_DEBUGMSG(("AbiWordPerfect: openParagraph()\n"));
539 // for now, we always append these options
540 float marginTop = 0.0f, marginBottom = 0.0f;
541 float marginLeft = 0.0f, marginRight = 0.0f, textIndent = 0.0f;
542 if (propList["fo:margin-top"])
543 marginTop = propList["fo:margin-top"]->getDouble();
544 if (propList["fo:margin-bottom"])
545 marginBottom = propList["fo:margin-bottom"]->getDouble();
546 if (propList["fo:margin-left"])
547 marginLeft = propList["fo:margin-left"]->getDouble();
548 if (propList["fo:margin-right"])
549 marginRight = propList["fo:margin-right"]->getDouble();
550 if (propList["fo:text-indent"])
551 textIndent = propList["fo:text-indent"]->getDouble();
552
553 m_topMargin = marginTop;
554 m_bottomMargin = marginBottom;
555 m_leftMarginOffset = marginLeft;
556 m_rightMarginOffset = marginRight;
557 m_textIndent = textIndent;
558
559 UT_String propBuffer;
560 propBuffer += "text-align:";
561 if (propList["fo:text-align"])
562 {
563 // AbiWord follows xsl:fo, except here, for some reason..
564 if (propList["fo:text-align"]->getStr() == "end")
565 propBuffer += "right";
566 else
567 propBuffer += propList["fo:text-align"]->getStr().cstr();
568 }
569 else
570 propBuffer += "left";
571
572 float lineSpacing = 1.0f;
573 if (propList["fo:line-height"])
574 lineSpacing = propList["fo:line-height"]->getDouble();
575
576 UT_String tmpBuffer;
577 UT_String_sprintf(tmpBuffer, "; margin-top:%dpt; margin-bottom:%dpt; margin-left:%.4fin; margin-right:%.4fin; text-indent:%.4fin; line-height:%.4f",
578 (int)(m_topMargin*72), (int)(m_bottomMargin*72), m_leftMarginOffset, m_rightMarginOffset, m_textIndent, lineSpacing);
579 propBuffer += tmpBuffer;
580
581 const librevenge::RVNGPropertyListVector *tabStops = propList.child("style:tab-stops");
582
583 if (tabStops && tabStops->count()) // Append the tabstop information
584 {
585 propBuffer += "; tabstops:";
586 tmpBuffer = "";
587 librevenge::RVNGPropertyListVector::Iter i(*tabStops);
588 for (i.rewind(); i.next();)
589 {
590 propBuffer += tmpBuffer;
591 if (i()["style:position"])
592 {
593 UT_String_sprintf(tmpBuffer, "%.4fin", i()["style:position"]->getDouble());
594 propBuffer += tmpBuffer;
595 }
596
597 if (i()["style:type"])
598 if (i()["style:type"]->getStr() == "right")
599 propBuffer += "/R";
600 else if (i()["style:type"]->getStr() == "center")
601 propBuffer += "/C";
602 else if (i()["style:type"]->getStr() == "char")
603 propBuffer += "/D";
604 else
605 propBuffer += "/L";
606 else // Left aligned is default
607 propBuffer += "/L";
608
609 if (i()["style:leader-text"])
610 if (i()["style:leader-text"]->getStr() == "-")
611 propBuffer += "2";
612 else if (i()["style:leader-text"]->getStr() == "_")
613 propBuffer += "3";
614 else // default to dot leader if the given leader is dot or is not supported by AbiWord
615 propBuffer += "1";
616 else
617 propBuffer += "0";
618
619 tmpBuffer = ",";
620 }
621 }
622
623
624
625 UT_DEBUGMSG(("AbiWordPerfect: Appending paragraph properties: %s\n", propBuffer.c_str()));
626 const gchar* propsArray[3];
627 propsArray[0] = "props";
628 propsArray[1] = propBuffer.c_str();
629 propsArray[2] = NULL;
630 X_CheckDocumentError(appendStrux(PTX_Block, propsArray));
631 m_bRequireBlock = false;
632
633 if (propList["fo:break-before"])
634 {
635 if (strcmp(propList["fo:break-before"]->getStr().cstr(), "page") == 0)
636 {
637 UT_UCS4Char ucs = UCS_FF;
638 X_CheckDocumentError(appendSpan(&ucs,1));
639 }
640 else if (strcmp(propList["fo:break-before"]->getStr().cstr(), "column") == 0)
641 {
642 UT_UCS4Char ucs = UCS_VTAB;
643 X_CheckDocumentError(appendSpan(&ucs,1));
644 }
645 }
646 }
647
openSpan(const librevenge::RVNGPropertyList & propList)648 void IE_Imp_WordPerfect::openSpan(const librevenge::RVNGPropertyList &propList)
649 {
650 if (m_bHdrFtrOpenCount) return; // HACK
651 UT_DEBUGMSG(("AbiWordPerfect: Appending current text properties\n"));
652
653 const gchar* pProps = "props";
654 UT_String propBuffer;
655 UT_String tempBuffer;
656
657 // bold
658 propBuffer += "font-weight:";
659 propBuffer += (propList["fo:font-weight"] ? propList["fo:font-weight"]->getStr().cstr() : "normal");
660
661 // italic
662 propBuffer += "; font-style:";
663 propBuffer += (propList["fo:font-style"] ? propList["fo:font-style"]->getStr().cstr() : "normal");
664
665 // superscript or subscript
666 if (propList["style:text-position"])
667 {
668 propBuffer += "; text-position:";
669 if (strncmp(propList["style:text-position"]->getStr().cstr(), "super", 5) == 0)
670 propBuffer += "superscript";
671 else
672 propBuffer += "subscript";
673 }
674
675 if (propList["style:text-underline-type"] || propList["style:text-line-through-type"])
676 {
677 propBuffer += "; text-decoration:";
678 if (propList["style:text-underline-type"])
679 propBuffer += "underline ";
680 if (propList["style:text-line-through-type"])
681 propBuffer += "line-through";
682
683 }
684
685 if (propList["style:font-name"])
686 {
687 propBuffer += "; font-family:";
688 propBuffer += propList["style:font-name"]->getStr().cstr();
689 }
690
691 // font face
692 if (propList["fo:font-size"])
693 {
694 propBuffer += "; font-size:";
695 propBuffer += propList["fo:font-size"]->getStr().cstr();
696 }
697
698 if (propList["fo:color"])
699 {
700 propBuffer += "; color:";
701 propBuffer += propList["fo:color"]->getStr().cstr();
702 }
703
704 if (propList["fo:background-color"])
705 {
706 propBuffer += "; bgcolor:";
707 propBuffer += propList["fo:background-color"]->getStr().cstr();
708 }
709
710 UT_DEBUGMSG(("AbiWordPerfect: Appending span format: %s\n", propBuffer.c_str()));
711 const gchar* propsArray[5];
712
713 propsArray[0] = pProps;
714 propsArray[1] = propBuffer.c_str();
715 propsArray[2] = NULL;
716 X_CheckDocumentError(appendFmt(propsArray));
717 }
718
openSection(const librevenge::RVNGPropertyList & propList)719 void IE_Imp_WordPerfect::openSection(const librevenge::RVNGPropertyList &propList)
720 {
721 if (m_bHdrFtrOpenCount) return; // HACK
722 UT_DEBUGMSG(("AbiWordPerfect: openSection\n"));
723
724 float marginLeft = 0.0f, marginRight = 0.0f;
725 const librevenge::RVNGPropertyListVector *columns = propList.child("style:columns");
726 int columnsCount = ((!columns || !columns->count()) ? 1 : columns->count());
727
728 // TODO: support spaceAfter
729 if (propList["fo:start-indent"])
730 marginLeft = propList["fo:start-indent"]->getDouble();
731 if (propList["fo:end-indent"])
732 marginRight = propList["fo:end-indent"]->getDouble();
733
734 if (marginLeft != m_leftSectionMargin || marginRight != m_rightSectionMargin || m_sectionColumnsCount != columnsCount)
735 m_bSectionChanged = true;
736
737 m_leftSectionMargin = marginLeft;
738 m_rightSectionMargin = marginRight;
739 m_sectionColumnsCount = columnsCount;
740
741 _appendSection(columnsCount, m_leftPageMargin + m_leftSectionMargin, m_rightPageMargin + m_rightSectionMargin);
742 }
743
insertTab()744 void IE_Imp_WordPerfect::insertTab()
745 {
746 if (m_bHdrFtrOpenCount) return; // HACK
747 UT_DEBUGMSG(("AbiWordPerfect: insertTab\n"));
748
749 UT_UCS4Char ucs = UCS_TAB;
750 X_CheckDocumentError(appendSpan(&ucs,1));
751 }
752
insertText(const librevenge::RVNGString & text)753 void IE_Imp_WordPerfect::insertText(const librevenge::RVNGString &text)
754 {
755 if (m_bHdrFtrOpenCount) return; // HACK
756 if (text.len())
757 {
758 UT_DEBUGMSG(("AbiWordPerfect: insertText\n"));
759 UT_UCS4String ucs4(text.cstr());
760 X_CheckDocumentError(appendSpan(ucs4.ucs4_str(), ucs4.length()));
761 }
762 }
763
insertSpace()764 void IE_Imp_WordPerfect::insertSpace()
765 {
766 if (m_bHdrFtrOpenCount) return; // HACK
767 UT_DEBUGMSG(("AbiWordPerfect: insertSpace\n"));
768
769 UT_UCS4Char ucs = UCS_SPACE;
770 X_CheckDocumentError(appendSpan(&ucs,1));
771 }
772
insertLineBreak()773 void IE_Imp_WordPerfect::insertLineBreak()
774 {
775 if (m_bHdrFtrOpenCount) return; // HACK
776 UT_DEBUGMSG(("AbiWordPerfect: insertLineBreak\n"));
777
778 UT_UCSChar ucs = UCS_LF;
779 X_CheckDocumentError(appendSpan(&ucs,1));
780 }
781
782
openOrderedListLevel(const librevenge::RVNGPropertyList & propList)783 void IE_Imp_WordPerfect::openOrderedListLevel(const librevenge::RVNGPropertyList &propList)
784 {
785 if (m_bHdrFtrOpenCount) return; // HACK
786 UT_DEBUGMSG(("AbiWordPerfect: openOrderedListLevel\n"));
787
788 int listID = 0, startingNumber = 0, level = 1;
789 char listType = '1';
790 UT_UTF8String textBeforeNumber, textAfterNumber;
791 float listLeftOffset = 0.0f;
792 float listMinLabelWidth = 0.0f;
793
794 if (propList["librevenge:id"])
795 listID = propList["librevenge:id"]->getInt();
796 if (propList["text:start-value"])
797 startingNumber = propList["text:start-value"]->getInt();
798 if (propList["librevenge:level"])
799 level = propList["librevenge:level"]->getInt();
800 if (propList["style:num-prefix"])
801 textBeforeNumber += propList["style:num-prefix"]->getStr().cstr();
802 if (propList["style:num-suffix"])
803 textAfterNumber += propList["style:num-suffix"]->getStr().cstr();
804 if (propList["style:num-format"])
805 listType = propList["style:num-format"]->getStr().cstr()[0];
806 if (propList["text:space-before"])
807 listLeftOffset = propList["text:space-before"]->getDouble();
808 if (propList["text:min-label-width"])
809 listMinLabelWidth = propList["text:min-label-width"]->getDouble();
810
811 if (!m_pCurrentListDefinition ||
812 m_pCurrentListDefinition->getOutlineHash() != listID ||
813 (m_pCurrentListDefinition->getLevelNumber(level) != startingNumber &&
814 level == 1))
815 {
816 if (m_pCurrentListDefinition)
817 delete (m_pCurrentListDefinition);
818
819 m_pCurrentListDefinition = new ABI_ListDefinition(listID);
820 }
821
822 if (!m_pCurrentListDefinition->getListID(level))
823 {
824 m_pCurrentListDefinition->setListType(level, listType);
825 m_pCurrentListDefinition->setListID(level, UT_rand());
826 m_pCurrentListDefinition->setListLeftOffset(level, listLeftOffset);
827 m_pCurrentListDefinition->setListMinLabelWidth(level, listMinLabelWidth);
828 _updateDocumentOrderedListDefinition(m_pCurrentListDefinition, level, listType, textBeforeNumber, textAfterNumber, startingNumber);
829 }
830
831 m_iCurrentListLevel++;
832 }
833
closeOrderedListLevel()834 void IE_Imp_WordPerfect::closeOrderedListLevel()
835 {
836 if (m_bHdrFtrOpenCount) return; // HACK
837 UT_DEBUGMSG(("AbiWordPerfect: closeOrderedListLevel (level: %i)\n", m_iCurrentListLevel));
838 UT_ASSERT(m_iCurrentListLevel > 0);
839
840 // every time we close a list level, the level above it is normally renumbered to start at "1"
841 // again. this code takes care of that.
842 if (m_iCurrentListLevel < (WP6_NUM_LIST_LEVELS-1))
843 m_pCurrentListDefinition->setLevelNumber(m_iCurrentListLevel + 1, 0);
844
845 m_iCurrentListLevel--;
846 }
847
openUnorderedListLevel(const librevenge::RVNGPropertyList & propList)848 void IE_Imp_WordPerfect::openUnorderedListLevel(const librevenge::RVNGPropertyList &propList)
849 {
850 if (m_bHdrFtrOpenCount) return; // HACK
851 UT_DEBUGMSG(("AbiWordPerfect: openUNorderedListLevel\n"));
852
853 int listID = 0, level = 1;
854 librevenge::RVNGString textBeforeNumber, textAfterNumber;
855 float listLeftOffset = 0.0f;
856 float listMinLabelWidth = 0.0f;
857
858 if (propList["librevenge:id"])
859 listID = propList["librevenge:id"]->getInt();
860 if (propList["librevenge:level"])
861 level = propList["librevenge:level"]->getInt();
862 if (propList["text:space-before"])
863 listLeftOffset = propList["text:space-before"]->getDouble();
864 if (propList["text:min-label-width"])
865 listMinLabelWidth = propList["text:min-label-width"]->getDouble();
866
867 if (!m_pCurrentListDefinition || m_pCurrentListDefinition->getOutlineHash() != listID)
868 {
869 if (m_pCurrentListDefinition)
870 delete (m_pCurrentListDefinition);
871
872 m_pCurrentListDefinition = new ABI_ListDefinition(listID);
873 }
874
875 if (!m_pCurrentListDefinition->getListID(level))
876 {
877 m_pCurrentListDefinition->setListID(level, UT_rand());
878 m_pCurrentListDefinition->setListLeftOffset(level, listLeftOffset);
879 m_pCurrentListDefinition->setListMinLabelWidth(level, listMinLabelWidth);
880 _updateDocumentUnorderedListDefinition(m_pCurrentListDefinition, level);
881 }
882
883 m_iCurrentListLevel++;
884 }
885
closeUnorderedListLevel()886 void IE_Imp_WordPerfect::closeUnorderedListLevel()
887 {
888 if (m_bHdrFtrOpenCount) return; // HACK
889 UT_DEBUGMSG(("AbiWordPerfect: closeUnorderedListLevel (level: %i)\n", m_iCurrentListLevel));
890 UT_ASSERT(m_iCurrentListLevel > 0);
891
892 m_iCurrentListLevel--;
893 }
894
895 // ASSUMPTION: We assume that unordered lists will always pass a number of "0". unpredictable behaviour
896 // may result otherwise
openListElement(const librevenge::RVNGPropertyList & propList)897 void IE_Imp_WordPerfect::openListElement(const librevenge::RVNGPropertyList &propList)
898 {
899 if (m_bHdrFtrOpenCount) return; // HACK
900 UT_DEBUGMSG(("AbiWordPerfect: openListElement\n"));
901
902 UT_ASSERT(m_pCurrentListDefinition); // FIXME: ABI_LISTS_IMPORT throw an exception back to libwpd, if this fails
903
904 // Paragraph properties for our list element
905 UT_String szListID;
906 UT_String szParentID;
907 UT_String szLevel;
908 UT_String_sprintf(szListID,"%d",m_pCurrentListDefinition->getListID(m_iCurrentListLevel));
909 if (m_iCurrentListLevel > 1)
910 UT_String_sprintf(szParentID,"%d", m_pCurrentListDefinition->getListID((m_iCurrentListLevel-1)));
911 else
912 UT_String_sprintf(szParentID,"0");
913 UT_String_sprintf(szLevel,"%d", m_iCurrentListLevel);
914
915 const gchar* listAttribs[PT_MAX_ATTRIBUTES*2 + 1];
916 UT_uint32 attribsCount=0;
917
918 listAttribs[attribsCount++] = PT_LISTID_ATTRIBUTE_NAME;
919 listAttribs[attribsCount++] = szListID.c_str();
920 listAttribs[attribsCount++] = PT_PARENTID_ATTRIBUTE_NAME;
921 listAttribs[attribsCount++] = szParentID.c_str();
922 listAttribs[attribsCount++] = PT_LEVEL_ATTRIBUTE_NAME;
923 listAttribs[attribsCount++] = szLevel.c_str();
924
925 // Now handle the Abi List properties
926 UT_String propBuffer;
927 UT_String tempBuffer;
928 UT_String_sprintf(tempBuffer,"list-style:%i;", m_pCurrentListDefinition->getListType(m_iCurrentListLevel));
929 propBuffer += tempBuffer;
930
931 #if 0
932 // FIXME: writing the list delimiter is kind of tricky and silly (because wordperfect wants to define
933 // it within the document, while abi wants to (sensibly probably) define it in the list definition)
934 // (we reset it each time but only for numbered lists)
935 if (listDefinition->isLevelNumbered(m_iCurrentListLevel))
936 {
937 UT_DEBUGMSG(("WordPerfect: Appending this list delim: %s\n", m_rightListDelim.c_str()));
938 listDefinition->setListRightDelimText(m_iCurrentListLevel, m_rightListDelim.c_str());
939 X_CheckWordPerfectError(_updateDocumentListDefinition(listDefinition, m_iCurrentListLevel));
940 }
941 #endif
942
943 if (m_pCurrentListDefinition->getListType(m_iCurrentListLevel) == BULLETED_LIST)
944 UT_String_sprintf(tempBuffer, "field-font:Symbol; ");
945 else
946 UT_String_sprintf(tempBuffer, "field-font:NULL; ");
947
948 m_pCurrentListDefinition->incrementLevelNumber(m_iCurrentListLevel);
949
950 propBuffer += tempBuffer;
951 UT_String_sprintf(tempBuffer, "start-value:%i; ", 1);
952 propBuffer += tempBuffer;
953
954 UT_String_sprintf(tempBuffer, "margin-left:%.4fin; ", m_pCurrentListDefinition->getListLeftOffset(m_iCurrentListLevel)
955 + m_pCurrentListDefinition->getListMinLabelWidth(m_iCurrentListLevel)
956 - (propList["fo:text-indent"] ? propList["fo:text-indent"]->getDouble() : 0.0f));
957 propBuffer += tempBuffer;
958 UT_String_sprintf(tempBuffer, "text-indent:%.4fin", - m_pCurrentListDefinition->getListMinLabelWidth(m_iCurrentListLevel)
959 + (propList["fo:text-indent"] ? propList["fo:text-indent"]->getDouble() : 0.0f));
960 propBuffer += tempBuffer;
961
962 listAttribs[attribsCount++] = PT_PROPS_ATTRIBUTE_NAME;
963 listAttribs[attribsCount++] = propBuffer.c_str();
964 listAttribs[attribsCount++] = NULL;
965
966 X_CheckDocumentError(appendStrux(PTX_Block, listAttribs));
967 m_bRequireBlock = false;
968
969 // hang text off of a list label
970 getDoc()->appendFmtMark();
971 UT_DEBUGMSG(("WordPerfect: LISTS - Appended a list tag def'n (character props)\n"));
972
973 // append a list field label
974 const gchar* fielddef[5];
975 fielddef[0] ="type";
976 fielddef[1] = "list_label";
977 fielddef[2] = NULL;
978 X_CheckDocumentError(appendObject(PTO_Field,fielddef));
979 UT_DEBUGMSG(("WordPerfect: LISTS - Appended a field def'n\n"));
980
981 // insert a tab
982 UT_UCS4Char ucs = UCS_TAB;
983 X_CheckDocumentError(appendSpan(&ucs,1));
984 }
985
openFootnote(const librevenge::RVNGPropertyList &)986 void IE_Imp_WordPerfect::openFootnote(const librevenge::RVNGPropertyList & /*propList*/)
987 {
988 if (m_bHdrFtrOpenCount) return; // HACK
989
990 if (!m_bInSection)
991 {
992 X_CheckDocumentError(appendStrux(PTX_Section, NULL));
993 X_CheckDocumentError(appendStrux(PTX_Block,NULL));
994 m_bInSection = true;
995 }
996
997 const gchar** propsArray = NULL;
998
999 UT_String footnoteId;
1000 UT_String_sprintf(footnoteId,"%i",UT_rand());
1001
1002 propsArray = static_cast<const gchar **>(UT_calloc(7, sizeof(gchar *)));
1003 propsArray [0] = "type";
1004 propsArray [1] = "footnote_ref";
1005 propsArray [2] = "footnote-id";
1006 propsArray [3] = footnoteId.c_str();
1007 propsArray [4] = NULL;
1008 propsArray [5] = NULL;
1009 propsArray [6] = NULL;
1010 X_CheckDocumentError(appendObject(PTO_Field, propsArray));
1011
1012 const gchar * attribs[3] ={"footnote-id", footnoteId.c_str(), NULL};
1013 X_CheckDocumentError(appendStrux(PTX_SectionFootnote,attribs));
1014
1015 X_CheckDocumentError(appendStrux(PTX_Block,NULL));
1016 m_bRequireBlock = false;
1017
1018 propsArray = static_cast<const gchar **>(UT_calloc(7, sizeof(gchar *)));
1019 propsArray [0] = "type";
1020 propsArray [1] = "footnote_anchor";
1021 propsArray [2] = "footnote-id";
1022 propsArray [3] = footnoteId.c_str();
1023 propsArray [4] = NULL;
1024 propsArray [5] = NULL;
1025 propsArray [6] = NULL;
1026 X_CheckDocumentError(appendObject(PTO_Field, propsArray));
1027 }
1028
closeFootnote()1029 void IE_Imp_WordPerfect::closeFootnote()
1030 {
1031 if (m_bHdrFtrOpenCount) return; // HACK
1032 X_CheckDocumentError(appendStrux(PTX_EndFootnote,NULL));
1033 }
1034
openEndnote(const librevenge::RVNGPropertyList &)1035 void IE_Imp_WordPerfect::openEndnote(const librevenge::RVNGPropertyList & /*propList*/)
1036 {
1037 if (m_bHdrFtrOpenCount) return; // HACK
1038 const gchar** propsArray = NULL;
1039
1040 UT_String endnoteId;
1041 UT_String_sprintf(endnoteId,"%i",UT_rand());
1042
1043 propsArray = static_cast<const gchar **>(UT_calloc(7, sizeof(gchar *)));
1044 propsArray [0] = "type";
1045 propsArray [1] = "endnote_ref";
1046 propsArray [2] = "endnote-id";
1047 propsArray [3] = endnoteId.c_str();
1048 propsArray [4] = NULL;
1049 propsArray [5] = NULL;
1050 propsArray [6] = NULL;
1051 X_CheckDocumentError(appendObject(PTO_Field, propsArray));
1052
1053 const gchar * attribs[3] ={"endnote-id", endnoteId.c_str(), NULL};
1054 X_CheckDocumentError(appendStrux(PTX_SectionEndnote,attribs));
1055
1056 X_CheckDocumentError(appendStrux(PTX_Block,NULL));
1057 m_bRequireBlock = false;
1058
1059 propsArray = static_cast<const gchar **>(UT_calloc(7, sizeof(gchar *)));
1060 propsArray [0] = "type";
1061 propsArray [1] = "endnote_anchor";
1062 propsArray [2] = "endnote-id";
1063 propsArray [3] = endnoteId.c_str();
1064 propsArray [4] = NULL;
1065 propsArray [5] = NULL;
1066 propsArray [6] = NULL;
1067 X_CheckDocumentError(appendObject(PTO_Field, propsArray));
1068 }
1069
closeEndnote()1070 void IE_Imp_WordPerfect::closeEndnote()
1071 {
1072 if (m_bHdrFtrOpenCount) return; // HACK
1073 X_CheckDocumentError(appendStrux(PTX_EndEndnote,NULL));
1074 }
1075
openTable(const librevenge::RVNGPropertyList & propList)1076 void IE_Imp_WordPerfect::openTable(const librevenge::RVNGPropertyList &propList)
1077 {
1078 if (m_bHdrFtrOpenCount) return; // HACK
1079 // TODO: handle 'marginLeftOffset' and 'marginRightOffset'
1080 UT_DEBUGMSG(("AbiWordPerfect: openTable\n"));
1081
1082 UT_String propBuffer;
1083
1084 if (propList["table:align"])
1085 {
1086 // no need to support left: default behaviour
1087
1088 //if (strcmp(propList["table:align"]->getStr().cstr(), "right"))
1089 // abiword does not support this I think
1090 //if (strcmp(propList["table:align"]->getStr().cstr(), "center"))
1091 // abiword does not support this I think
1092 //if (strcmp(propList["table:align"]->getStr().cstr(), "margins"))
1093 // abiword does not support this I think
1094 if (strcmp(propList["table:align"]->getStr().cstr(), "margins"))
1095 {
1096 if (propList["fo:margin-left"])
1097 UT_String_sprintf(propBuffer, "table-column-leftpos:%s; ", propList["fo:margin-left"]->getStr().cstr());
1098 }
1099 }
1100
1101 const librevenge::RVNGPropertyListVector *columns = propList.child("librevenge:table-columns");
1102 if (columns)
1103 {
1104 propBuffer += "table-column-props:";
1105 librevenge::RVNGPropertyListVector::Iter i(*columns);
1106 for (i.rewind(); i.next();)
1107 {
1108 UT_String tmpBuffer;
1109 if (i()["style:column-width"])
1110 UT_String_sprintf(tmpBuffer, "%s/", i()["style:column-width"]->getStr().cstr());
1111 propBuffer += tmpBuffer;
1112 }
1113 }
1114
1115 const gchar* propsArray[3];
1116 propsArray[0] = "props";
1117 propsArray[1] = propBuffer.c_str();
1118 propsArray[2] = NULL;
1119
1120 X_CheckDocumentError(appendStrux(PTX_SectionTable, propsArray));
1121 }
1122
openTableRow(const librevenge::RVNGPropertyList &)1123 void IE_Imp_WordPerfect::openTableRow(const librevenge::RVNGPropertyList & /*propList*/)
1124 {
1125 if (m_bHdrFtrOpenCount) return; // HACK
1126 UT_DEBUGMSG(("AbiWordPerfect: openRow\n"));
1127 if (m_bInCell)
1128 {
1129 X_CheckDocumentError(appendStrux(PTX_EndCell, NULL));
1130 }
1131
1132 m_bInCell = false;
1133 }
1134
openTableCell(const librevenge::RVNGPropertyList & propList)1135 void IE_Imp_WordPerfect::openTableCell(const librevenge::RVNGPropertyList &propList)
1136 {
1137 if (m_bHdrFtrOpenCount) return; // HACK
1138 int col =0, row = 0, colSpan = 0, rowSpan = 0;
1139 if (propList["librevenge:column"])
1140 col = propList["librevenge:column"]->getInt();
1141 if (propList["librevenge:row"])
1142 row = propList["librevenge:row"]->getInt();
1143 if (propList["table:number-columns-spanned"])
1144 colSpan = propList["table:number-columns-spanned"]->getInt();
1145 if (propList["table:number-rows-spanned"])
1146 rowSpan = propList["table:number-rows-spanned"]->getInt();
1147
1148 UT_DEBUGMSG(("AbiWordPerfect: openCell(col: %d, row: %d, colSpan: %d, rowSpan: %d\n", col, row, colSpan, rowSpan));
1149 if (m_bInCell)
1150 {
1151 X_CheckDocumentError(appendStrux(PTX_EndCell, NULL));
1152 }
1153
1154 UT_String propBuffer;
1155 UT_String_sprintf(propBuffer, "left-attach:%d; right-attach:%d; top-attach:%d; bot-attach:%d",
1156 col, col+colSpan, row, row+rowSpan);
1157
1158 UT_String borderStyle;
1159 // we only support bg-style:1 for now
1160 bool borderLeftSolid = false;
1161 bool borderRightSolid = false;
1162 bool borderTopSolid = false;
1163 bool borderBottomSolid = false;
1164 if (propList["fo:border-left"])
1165 borderLeftSolid = strncmp(propList["fo:border-left"]->getStr().cstr(), "0.0inch", 7);
1166 if (propList["fo:border-right"])
1167 borderRightSolid = strncmp(propList["fo:border-right"]->getStr().cstr(), "0.0inch", 7);
1168 if (propList["fo:border-top"])
1169 borderTopSolid = strncmp(propList["fo:border-top"]->getStr().cstr(), "0.0inch", 7);
1170 if (propList["fo:border-bottom"])
1171 borderBottomSolid = strncmp(propList["fo:border-bottom"]->getStr().cstr(), "0.0inch", 7);
1172
1173 UT_String_sprintf(borderStyle, "; left-style:%s; right-style:%s; top-style:%s; bot-style:%s",
1174 (borderLeftSolid ? "solid" : "none"),
1175 (borderRightSolid ? "solid" : "none"),
1176 (borderTopSolid ? "solid" : "none"),
1177 (borderBottomSolid ? "solid" : "none"));
1178 propBuffer += borderStyle;
1179
1180 // we only support bg-style:1 for now
1181 if (propList["fo:background-color"])
1182 {
1183 UT_String bgCol;
1184 UT_String_sprintf(bgCol, "; bg-style:1; background-color:%s", &(propList["fo:background-color"]->getStr().cstr()[1]));
1185 propBuffer += bgCol;
1186 }
1187
1188 UT_DEBUGMSG(("AbiWordPerfect: Inserting a Cell definition: %s\n", propBuffer.c_str()));
1189
1190 const gchar* propsArray[3];
1191 propsArray[0] = "props";
1192 propsArray[1] = propBuffer.c_str();
1193 propsArray[2] = NULL;
1194
1195 X_CheckDocumentError(appendStrux(PTX_SectionCell, propsArray));
1196 m_bInCell = true;
1197 }
1198
closeTable()1199 void IE_Imp_WordPerfect::closeTable()
1200 {
1201 if (m_bHdrFtrOpenCount) return; // HACK
1202 UT_DEBUGMSG(("AbiWordPerfect: Closing table\n"));
1203
1204 if (m_bInCell)
1205 {
1206 X_CheckDocumentError(appendStrux(PTX_EndCell, NULL));
1207 }
1208 X_CheckDocumentError(appendStrux(PTX_EndTable, NULL));
1209 m_bInCell = false;
1210
1211 // we need to open a new paragraph after a table, since libwpd does NOT do it
1212 // FIXME: NEED TO PASS THE CURRENT PROPERTIES INSTEAD OF NULL
1213 // NOTE: THIS SUCKS.........
1214 X_CheckDocumentError(appendStrux(PTX_Block, NULL));
1215 m_bRequireBlock = false;
1216 }
1217
_appendSection(int numColumns,const float marginLeft,const float marginRight)1218 UT_Error IE_Imp_WordPerfect::_appendSection(int numColumns, const float marginLeft, const float marginRight)
1219 {
1220 UT_DEBUGMSG(("AbiWordPerfect: Appending section\n"));
1221
1222 UT_String myProps("") ;
1223 UT_LocaleTransactor lt(LC_NUMERIC, "C");
1224 myProps += UT_String_sprintf("columns:%d; page-margin-left:%.4fin; page-margin-right:%.4fin", numColumns, marginLeft, marginRight);
1225
1226 if(m_bInSection && m_bRequireBlock) // AbiWord will hang on an empty <section>
1227 {
1228 X_CheckDocumentError(appendStrux(PTX_Block,NULL));
1229 }
1230
1231 const gchar * propsArray[3];
1232 propsArray[0] = "props";
1233 propsArray[1] = myProps.c_str();
1234 propsArray[2] = NULL ;
1235 X_CheckDocumentError(appendStrux(PTX_Section, propsArray));
1236
1237 m_bInSection = true;
1238 m_bRequireBlock = true;
1239
1240 m_bSectionChanged = false;
1241
1242 return UT_OK;
1243 }
1244
1245 // NB: AbiWord-2.0 doesn't properly support nested lists with different nested styles: only "1" style
1246 // really looks proper. We hack around this be only using the style given at level "1"
1247 // NB: AbiWord-2.0 doesn't properly support setting list delimeters at levels greater than 1,
1248 // we hack around this by using only "plain" (e.g.: NULL) list delimeters on levels greater than 1.
_updateDocumentOrderedListDefinition(ABI_ListDefinition * pListDefinition,int iLevel,const char,const UT_UTF8String & sTextBeforeNumber,const UT_UTF8String & sTextAfterNumber,int iStartingNumber)1249 UT_Error IE_Imp_WordPerfect::_updateDocumentOrderedListDefinition(ABI_ListDefinition *pListDefinition, int iLevel,
1250 const char /*listType*/, const UT_UTF8String &sTextBeforeNumber,
1251 const UT_UTF8String &sTextAfterNumber, int iStartingNumber)
1252 {
1253 UT_DEBUGMSG(("AbiWordPerfect: Updating document list definition (iLevel: %i)\n", iLevel));
1254
1255 if (iLevel > 1) {
1256 UT_DEBUGMSG(("WLACH: Parent's list id is.. %i\n", pListDefinition->getListID((iLevel-1))));
1257 }
1258
1259 // finally, set the document's list identification info..
1260 fl_AutoNum * pAuto = getDoc()->getListByID(pListDefinition->getListID(iLevel));
1261 // not in document yet, we should create a list for it
1262 if (pAuto == NULL)
1263 {
1264 UT_DEBUGMSG(("AbiWordPerfect: pAuto is NULL: creating a list\n"));
1265 if (iLevel > 1)
1266 {
1267 pAuto = new fl_AutoNum(pListDefinition->getListID(iLevel),
1268 pListDefinition->getListID((iLevel-1)),
1269 pListDefinition->getListType(1),
1270 iStartingNumber,
1271 const_cast<gchar*>(reinterpret_cast<const gchar*>("%L")),
1272 ".",
1273 getDoc(),
1274 NULL);
1275 }
1276 else
1277 {
1278 UT_UTF8String sNumberingString;
1279 UT_UTF8String sNumber("%L", (size_t)0);
1280
1281 sNumberingString += sTextBeforeNumber;
1282 sNumberingString += sNumber;
1283 sNumberingString += sTextAfterNumber;
1284
1285 pAuto = new fl_AutoNum(pListDefinition->getListID(iLevel), 0, pListDefinition->getListType(iLevel), iStartingNumber,
1286 const_cast<gchar*>(reinterpret_cast<const gchar*>(sNumberingString.utf8_str())), ".", getDoc(), NULL);
1287 }
1288 getDoc()->addList(pAuto);
1289 }
1290 // we should update what we have
1291 else
1292 {
1293 UT_DEBUGMSG(("AbiWordPerfect: pAuto already exists\n"));
1294 }
1295
1296 pAuto->fixHierarchy();
1297
1298 return UT_OK;
1299 }
1300
_updateDocumentUnorderedListDefinition(ABI_ListDefinition * pListDefinition,int iLevel)1301 UT_Error IE_Imp_WordPerfect::_updateDocumentUnorderedListDefinition(ABI_ListDefinition *pListDefinition, int iLevel)
1302 {
1303 UT_DEBUGMSG(("AbiWordPerfect: Updating document list definition (iLevel: %i)\n", iLevel));
1304
1305 // finally, set the document's list identification info..
1306 fl_AutoNum * pAuto = getDoc()->getListByID(pListDefinition->getListID(iLevel));
1307 // not in document yet, we should create a list for it
1308 if (pAuto == NULL)
1309 {
1310 UT_DEBUGMSG(("AbiWordPerfect: pAuto is NULL: creating a list\n"));
1311 if (iLevel > 1)
1312 {
1313 pAuto = new fl_AutoNum(pListDefinition->getListID(iLevel), pListDefinition->getListID((iLevel-1)),
1314 pListDefinition->getListType(1), 0, const_cast<gchar*>(reinterpret_cast<const gchar*>("%L")), ".", getDoc(), NULL);
1315 }
1316 else
1317 pAuto = new fl_AutoNum(pListDefinition->getListID(iLevel), 0, pListDefinition->getListType(iLevel), 0,
1318 const_cast<gchar*>(reinterpret_cast<const gchar*>("%L")), ".", getDoc(), NULL);
1319
1320 getDoc()->addList(pAuto);
1321 }
1322 // we should update what we have
1323 else
1324 {
1325 UT_DEBUGMSG(("AbiWordPerfect: pAuto already exists\n"));
1326 }
1327
1328 pAuto->fixHierarchy();
1329
1330 return UT_OK;
1331 }
1332
1333 #ifdef HAVE_LIBWPS
1334
1335 class IE_Imp_MSWorks : public IE_Imp_WordPerfect
1336 {
1337 public:
1338
IE_Imp_MSWorks(PD_Document * pDocument)1339 IE_Imp_MSWorks(PD_Document * pDocument)
1340 : IE_Imp_WordPerfect(pDocument)
1341 {
1342 }
1343
~IE_Imp_MSWorks()1344 ~IE_Imp_MSWorks()
1345 {
1346 }
1347
1348 protected:
_loadFile(GsfInput * input)1349 virtual UT_Error _loadFile(GsfInput * input)
1350 {
1351 AbiWordperfectInputStream gsfInput(input);
1352 libwps::WPSResult error = libwps::WPSDocument::parse(&gsfInput, static_cast<librevenge::RVNGTextInterface *>(this), NULL, NULL);
1353
1354 if (error != libwps::WPS_OK)
1355 {
1356 UT_DEBUGMSG(("AbiMSWorks: ERROR: %i!\n", (int)error));
1357 return UT_IE_IMPORTERROR;
1358 }
1359
1360 return UT_OK;
1361 }
1362 };
1363
1364 /****************************************************************************************/
1365 /****************************************************************************************/
1366
IE_Imp_MSWorks_Sniffer()1367 IE_Imp_MSWorks_Sniffer::IE_Imp_MSWorks_Sniffer()
1368 : IE_ImpSniffer("application/vnd.ms-works")
1369 {
1370 }
1371
~IE_Imp_MSWorks_Sniffer()1372 IE_Imp_MSWorks_Sniffer::~IE_Imp_MSWorks_Sniffer()
1373 {
1374 }
1375
1376 // supported suffixes
1377 static IE_SuffixConfidence IE_Imp_MSWorks_Sniffer__SuffixConfidence[] = {
1378 { "wps", UT_CONFIDENCE_PERFECT },
1379 { "", UT_CONFIDENCE_ZILCH }
1380 };
1381
getSuffixConfidence()1382 const IE_SuffixConfidence * IE_Imp_MSWorks_Sniffer::getSuffixConfidence ()
1383 {
1384 return IE_Imp_MSWorks_Sniffer__SuffixConfidence;
1385 }
1386
recognizeContents(GsfInput * input)1387 UT_Confidence_t IE_Imp_MSWorks_Sniffer::recognizeContents (GsfInput * input)
1388 {
1389 AbiWordperfectInputStream gsfInput(input);
1390
1391 libwps::WPSCreator creator;
1392 libwps::WPSKind kind;
1393 bool needEncoding;
1394 libwps::WPSConfidence confidence = libwps::WPSDocument::isFileFormatSupported(&gsfInput, kind, creator, needEncoding);
1395
1396 if (kind != libwps::WPS_TEXT)
1397 confidence = libwps::WPS_CONFIDENCE_NONE;
1398
1399 switch (confidence)
1400 {
1401 case libwps::WPS_CONFIDENCE_NONE:
1402 return UT_CONFIDENCE_ZILCH;
1403 case libwps::WPS_CONFIDENCE_EXCELLENT:
1404 return UT_CONFIDENCE_PERFECT;
1405 default:
1406 return UT_CONFIDENCE_ZILCH;
1407 }
1408 }
1409
constructImporter(PD_Document * pDocument,IE_Imp ** ppie)1410 UT_Error IE_Imp_MSWorks_Sniffer::constructImporter (PD_Document * pDocument,
1411 IE_Imp ** ppie)
1412 {
1413 *ppie = new IE_Imp_MSWorks(pDocument);
1414 return UT_OK;
1415 }
1416
getDlgLabels(const char ** pszDesc,const char ** pszSuffixList,IEFileType * ft)1417 bool IE_Imp_MSWorks_Sniffer::getDlgLabels (const char ** pszDesc,
1418 const char ** pszSuffixList,
1419 IEFileType * ft)
1420 {
1421 *pszDesc = "Microsoft Works (.wps)";
1422 *pszSuffixList = "*.wps";
1423 *ft = getFileType();
1424 return true;
1425 }
1426
1427 #endif
1428