fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / writerperfect / source / writer / MWAWImportFilter.cxx
blob8e33dffb44357e4441e21959a5607fd88470a04c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* MWAWImportFilter: Sets up the filter, and calls DocumentCollector
3 * to do the actual filtering
5 * This file is part of the LibreOffice project.
7 * This Source Code Form is subject to the terms of the Mozilla Public
8 * License, v. 2.0. If a copy of the MPL was not distributed with this
9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
12 #include <osl/diagnose.h>
13 #include <rtl/tencinfo.h>
15 #include <com/sun/star/io/XInputStream.hpp>
16 #include <com/sun/star/xml/sax/XAttributeList.hpp>
17 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
18 #include <com/sun/star/xml/sax/InputSource.hpp>
19 #include <com/sun/star/xml/sax/XParser.hpp>
20 #include <com/sun/star/io/XSeekable.hpp>
21 #include <com/sun/star/uno/Reference.h>
23 #include <comphelper/componentcontext.hxx>
24 #include <xmloff/attrlist.hxx>
25 #include <ucbhelper/content.hxx>
27 #include <libmwaw/libmwaw.hxx>
28 #include <libodfgen/libodfgen.hxx>
30 #include "common/DocumentHandler.hxx"
31 #include "common/WPXSvStream.hxx"
32 #include "MWAWImportFilter.hxx"
34 #include <iostream>
36 using namespace ::com::sun::star::uno;
37 using com::sun::star::uno::Sequence;
38 using com::sun::star::uno::Reference;
39 using com::sun::star::uno::Any;
40 using com::sun::star::uno::UNO_QUERY;
41 using com::sun::star::uno::XInterface;
42 using com::sun::star::uno::Exception;
43 using com::sun::star::uno::RuntimeException;
44 using com::sun::star::beans::PropertyValue;
45 using com::sun::star::document::XFilter;
46 using com::sun::star::document::XExtendedFilterDetection;
47 using com::sun::star::ucb::XCommandEnvironment;
49 using com::sun::star::io::XInputStream;
50 using com::sun::star::document::XImporter;
51 using com::sun::star::xml::sax::InputSource;
52 using com::sun::star::xml::sax::XAttributeList;
53 using com::sun::star::xml::sax::XDocumentHandler;
54 using com::sun::star::xml::sax::XParser;
56 namespace
59 //! Internal: creates the string "f pt"
60 static std::string getStringPt(double f)
62 std::stringstream s;
63 s << float(f) << "pt";
64 return s.str();
67 static double getSizeInPt(WPXProperty const &prop)
69 WPXString str = prop.getStr();
70 if (!str.len()) return 0.0;
72 // we have a string, so we can not use getDouble
73 std::istringstream iss(str.cstr());
74 double res = 0.0;
75 iss >> res;
77 // try to guess the type
78 // point->pt, twip->*, inch -> in
79 char c = str.len() ? str.cstr()[str.len()-1] : ' ';
80 if (c == '*') res /= 1440.;
81 else if (c == 't') res /= 72.;
82 else if (c == 'n') ;
83 else if (c == '%')
85 SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::getSizeInPoint: called with a percent property");
87 return res *= 72.;
90 static std::string getStringSizeInPt(WPXProperty const &prop)
92 return getStringPt(getSizeInPt(prop));
95 static std::string getStyleName(int id)
97 std::stringstream s;
98 s.str("");
99 s << "bd" << id+1;
100 return s.str();
103 } // anonymous namespace
105 namespace MWAWObjectHandlerInternal
107 class Shape
109 public:
110 Shape() : m_type(BAD), m_styleId(-1), m_w(0), m_h(0), m_rw(0), m_rh(0),
111 m_x(), m_y(), m_angle(), m_path("")
114 bool read(const char *psName, WPXPropertyList const &xPropList, int styleId);
115 bool write(OdfDocumentHandler *output) const;
116 bool ok() const
118 return m_type != BAD;
121 protected:
122 bool drawLine(OdfDocumentHandler *output) const;
123 bool drawRectangle(OdfDocumentHandler *output) const;
124 bool drawCircle(OdfDocumentHandler *output) const;
125 bool drawArc(OdfDocumentHandler *output) const;
126 bool drawPath(OdfDocumentHandler *output) const;
127 bool drawPolygon(OdfDocumentHandler *output, bool is2D) const;
129 enum Type { LINE, RECTANGLE, CIRCLE, ARC, PATH, POLYLINE, POLYGON, BAD } m_type;
131 int m_styleId;
132 double m_w,m_h, m_rw, m_rh;
133 std::vector<double> m_x,m_y;
134 std::vector<double> m_angle;
135 std::string m_path;
138 class Document
140 public:
141 Document() : styles(), shapes(), m_w(0.0), m_h(0.0) {}
142 bool open(const char *psName, WPXPropertyList const &xPropList);
143 bool close(const char *psName);
145 void characters(WPXString const &sCharacters);
147 void write(OdfDocumentHandler *output);
149 protected:
150 static void writeStyle(OdfDocumentHandler *output,
151 WPXPropertyList const &style, int styleId);
153 std::vector<WPXPropertyList> styles;
154 std::vector<Shape> shapes;
156 protected:
157 double m_w, m_h;
162 class MWAWObjectHandler : public MWAWPropertyHandler
164 public:
165 MWAWObjectHandler(OdfDocumentHandler *output) : MWAWPropertyHandler(), m_document(), m_output(output) { }
166 ~MWAWObjectHandler() {};
168 void startDocument()
170 m_document= MWAWObjectHandlerInternal::Document();
172 void endDocument()
174 if (m_output) m_document.write(m_output);
177 void startElement(const char *psName, const WPXPropertyList &xPropList)
179 m_document.open(psName, xPropList);
181 void endElement(const char *psName)
183 m_document.close(psName);
185 void characters(const WPXString &sCharacters)
187 m_document.characters(sCharacters);
190 private:
191 MWAWObjectHandler(MWAWObjectHandler const &);
192 MWAWObjectHandler operator=(MWAWObjectHandler const &);
194 MWAWObjectHandlerInternal::Document m_document;
195 OdfDocumentHandler *m_output;
199 static bool handleEmbeddedMWAWObject(const WPXBinaryData &data, OdfDocumentHandler *pHandler, const OdfStreamType)
201 MWAWObjectHandler tmpHandler(pHandler);
202 tmpHandler.startDocument();
203 if (!tmpHandler.checkData(data) || !tmpHandler.readData(data)) return false;
204 tmpHandler.endDocument();
205 return true;
208 bool MWAWObjectHandlerInternal::Shape::read(const char *psName, WPXPropertyList const &xPropList, int stylId)
210 m_styleId = stylId;
211 m_type = BAD;
212 if (strcmp(psName,"drawLine")==0) m_type = LINE;
213 else if (strcmp(psName,"drawRectangle")==0) m_type = RECTANGLE;
214 else if (strcmp(psName,"drawCircle")==0) m_type = CIRCLE;
215 else if (strcmp(psName,"drawArc")==0) m_type = ARC;
216 else if (strcmp(psName,"drawPath")==0) m_type = PATH;
217 else if (strcmp(psName,"drawPolyline")==0) m_type = POLYLINE;
218 else if (strcmp(psName,"drawPolygon")==0) m_type = POLYGON;
219 else return false;
221 WPXPropertyList::Iter i(xPropList);
222 for (i .rewind(); i.next(); )
224 if (strcmp(i.key(), "w") == 0) m_w = getSizeInPt(*i());
225 else if (strcmp(i.key(), "h") == 0) m_h = getSizeInPt(*i());
226 else if (strcmp(i.key(), "rw") == 0) m_rw = getSizeInPt(*i());
227 else if (strcmp(i.key(), "rh") == 0) m_rh = getSizeInPt(*i());
228 else if (strcmp(i.key(), "path") == 0)
230 if (i()->getStr().len())
231 m_path = i()->getStr().cstr();
233 else
235 char const *key = i.key();
236 int len = (int) strlen(key);
237 bool readOk = len > 1, generic = false;
238 std::vector<double> *which = 0L;
239 if (readOk && strncmp(i.key(),"x",1)==0)
241 which = &m_x;
242 key++;
244 else if (readOk && strncmp(i.key(),"y",1)==0)
246 which = &m_y;
247 key++;
249 else if (readOk && strncmp(i.key(),"angle",5)==0)
251 which = &m_angle;
252 key+=5;
253 readOk = len>5;
254 generic=true;
256 else readOk = false;
258 long w(0);
259 if (readOk)
261 char *res;
262 w = strtol(key, &res, 10);
263 readOk = (*res=='\0') && (w >= 0);
265 if (readOk)
267 if (int(which->size()) < w+1) which->resize(size_t(w)+1,0.0);
268 double unit = generic ? 1./72.0 : 1.0;
269 (*which)[size_t(w)] = getSizeInPt(*i()) * unit;
271 if (!readOk)
273 SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Shape::read: find an unknown key '" << i.key() << "'");
278 return true;
281 bool MWAWObjectHandlerInternal::Shape::write(OdfDocumentHandler *output) const
283 if (!output) return true;
284 if (m_type == LINE) return drawLine(output);
285 else if (m_type == RECTANGLE) return drawRectangle(output);
286 else if (m_type == CIRCLE) return drawCircle(output);
287 else if (m_type == ARC) return drawArc(output);
288 else if (m_type == PATH) return drawPath(output);
289 else if (m_type == POLYLINE) return drawPolygon(output, false);
290 else if (m_type == POLYGON) return drawPolygon(output, true);
292 return false;
295 bool MWAWObjectHandlerInternal::Shape::drawLine(OdfDocumentHandler *output) const
297 if (m_x.size() < 2 || m_y.size() < 2)
299 SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Shape::drawLine: PB");
300 return false;
303 WPXPropertyList list;
304 list.insert("draw:text-style-name","P1");
305 list.insert("draw:layer","layout");
306 list.insert("draw:style-name",getStyleName(m_styleId).c_str());
307 list.insert("svg:x1",getStringPt(m_x[0]).c_str());
308 list.insert("svg:y1",getStringPt(m_y[0]).c_str());
309 list.insert("svg:x2",getStringPt(m_x[1]).c_str());
310 list.insert("svg:y2",getStringPt(m_y[1]).c_str());
311 output->startElement("draw:line", list);
312 output->endElement("draw:line");
313 return true;
316 bool MWAWObjectHandlerInternal::Shape::drawRectangle(OdfDocumentHandler *output) const
318 if (m_x.size() < 1 || m_y.size() < 1)
320 SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Shape::drawRectangle: PB");
321 return false;
324 WPXPropertyList list;
325 list.insert("draw:text-style-name","P1");
326 list.insert("draw:layer","layout");
327 list.insert("draw:style-name",getStyleName(m_styleId).c_str());
328 list.insert("svg:x",getStringPt(m_x[0]).c_str());
329 list.insert("svg:y",getStringPt(m_y[0]).c_str());
330 list.insert("svg:width",getStringPt(m_w).c_str());
331 list.insert("svg:height",getStringPt(m_h).c_str());
333 if (m_rw <= 0.0 || m_rh <= 0.0 || m_w < 2*m_rw || m_h < 2*m_rh)
335 if (m_rw > 0.0 || m_rh > 0.0)
337 SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Shape::drawRectangle:: can only create a rectangle");
339 output->startElement("draw:rect", list);
340 output->endElement("draw:rect");
341 return true;
344 // ok, we draw a rond rect
345 std::stringstream s;
346 float const unit = 1.0;//35.3;
347 s.str("");
349 double const minPt[] = { m_x[0] *unit, m_y[0] *unit };
350 double const maxPt[] = { (m_w+m_x[0]) *unit, (m_h+m_y[0]) *unit };
352 s << "0 0 " << int(maxPt[0]) << " " << int(maxPt[1]);
353 list.insert("svg:viewBox", s.str().c_str());
355 double const W[] = { m_rw *unit, m_rh *unit };
356 double const xPt[] = { minPt[0]+W[0], maxPt[0]-W[0], maxPt[0],
357 maxPt[0], maxPt[0], maxPt[0],
358 maxPt[0]-W[0], minPt[0]+W[0], minPt[0],
359 minPt[0], minPt[0], minPt[0],
360 minPt[0]+W[0]
362 double const yPt[] = { minPt[1], minPt[1], minPt[1],
363 minPt[1]+W[1], maxPt[1]-W[1], maxPt[1],
364 maxPt[1], maxPt[1], maxPt[1],
365 maxPt[1]-W[1], minPt[1]+W[1], minPt[1],
366 minPt[1]
368 s.str("");
369 for (int i = 0; i < 13; i++)
371 if (i) s << " ";
373 if (i == 0) s << "M";
374 else if ((i%3) == 2) s << "Q";
375 else if ((i%3) == 0);
376 else s << "L";
377 s << int(xPt[i]) << " " << int(yPt[i]);
379 s << "Z";
380 list.insert("svg:d", s.str().c_str());
382 output->startElement("draw:path", list);
383 output->endElement("draw:path");
384 return true;
387 bool MWAWObjectHandlerInternal::Shape::drawCircle(OdfDocumentHandler *output) const
389 if (m_x.size() < 1 || m_y.size() < 1)
391 SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Shape::drawCircle: PB");
392 return false;
395 WPXPropertyList list;
396 list.insert("draw:text-style-name","P1");
397 list.insert("draw:layer","layout");
398 list.insert("draw:style-name",getStyleName(m_styleId).c_str());
399 list.insert("svg:x",getStringPt(m_x[0]).c_str());
400 list.insert("svg:y",getStringPt(m_y[0]).c_str());
401 list.insert("svg:width",getStringPt(m_w).c_str());
402 list.insert("svg:height",getStringPt(m_h).c_str());
403 if (m_w < m_h || m_w > m_h)
405 output->startElement("draw:ellipse", list);
406 output->endElement("draw:ellipse");
408 else
410 output->startElement("draw:circle", list);
411 output->endElement("draw:circle");
413 return true;
416 bool MWAWObjectHandlerInternal::Shape::drawArc(OdfDocumentHandler *output) const
418 if (m_angle.size() < 2)
420 SAL_INFO("writerperfect", "MWAWObjectHandlerInternal::Shape::drawArc: angle are filled, call draw Circle");
421 return drawCircle(output);
423 if (m_x.size() < 1 || m_y.size() < 1)
425 SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Shape::drawArc: PB");
426 return false;
429 WPXPropertyList list;
430 list.insert("draw:text-style-name","P1");
431 list.insert("draw:layer","layout");
432 list.insert("draw:style-name",getStyleName(m_styleId).c_str());
433 list.insert("svg:x",getStringPt(m_x[0]).c_str());
434 list.insert("svg:y",getStringPt(m_y[0]).c_str());
435 list.insert("svg:width",getStringPt(m_w).c_str());
436 list.insert("svg:height",getStringPt(m_h).c_str());
437 list.insert("draw:kind","arc");
439 std::stringstream s;
440 // odg prefers angle between -360 and +360, ...
441 int minAngl = int(m_angle[0]), maxAngl = int(m_angle[1]);
442 if (minAngl >= 360 || maxAngl >= 360)
444 minAngl -= 360;
445 maxAngl -= 360;
447 s.str("");
448 s << minAngl;
449 list.insert("draw:start-angle", s.str().c_str());
450 s.str("");
451 s << maxAngl;
452 list.insert("draw:end-angle", s.str().c_str());
454 if (m_w < m_h || m_w > m_h)
456 output->startElement("draw:ellipse", list);
457 output->endElement("draw:ellipse");
459 else
461 output->startElement("draw:circle", list);
462 output->endElement("draw:circle");
464 return true;
467 bool MWAWObjectHandlerInternal::Shape::drawPolygon(OdfDocumentHandler *output, bool is2D) const
469 if (m_x.size() < 1 || m_y.size() != m_x.size())
471 SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Shape::drawPolygon: PB");
472 return false;
474 std::stringstream s;
475 WPXPropertyList list;
476 list.insert("draw:text-style-name","P1");
477 list.insert("draw:layer","layout");
478 list.insert("draw:style-name","bd1");
479 list.insert("svg:x","0pt");
480 list.insert("svg:y","0pt");
481 list.insert("svg:width",getStringPt(m_w).c_str());
482 list.insert("svg:height",getStringPt(m_h).c_str());
484 size_t numPt = m_x.size();
486 float const unit = 1; //35.2777; // convert in centimeters
487 s.str("");
488 s << "0 0 " << int(m_w*unit) << " " << int(m_h*unit);
489 list.insert("svg:viewBox", s.str().c_str());
491 s.str("");
492 for (size_t i = 0; i < numPt; i++)
494 if (i) s << " ";
495 s << int(m_x[i]*unit) << "," << int(m_y[i]*unit);
497 list.insert("draw:points", s.str().c_str());
498 if (!is2D)
500 output->startElement("draw:polyline", list);
501 output->endElement("draw:polyline");
503 else
505 output->startElement("draw:polygon", list);
506 output->endElement("draw:polygon");
508 return true;
511 bool MWAWObjectHandlerInternal::Shape::drawPath(OdfDocumentHandler *output) const
513 if (m_path.length()==0 || m_w <= 0 || m_h <= 0)
515 SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Shape::drawPath: PB");
516 return false;
519 WPXPropertyList list;
520 list.insert("draw:text-style-name","P1");
521 list.insert("draw:layer","layout");
522 list.insert("draw:style-name",getStyleName(m_styleId).c_str());
523 list.insert("svg:x","0pt");
524 list.insert("svg:y","0pt");
525 list.insert("svg:width",getStringPt(m_w).c_str());
526 list.insert("svg:height",getStringPt(m_h).c_str());
527 std::stringstream s;
528 s << "0 0 " << int(m_w) << " " << int(m_h);
529 list.insert("svg:viewBox", s.str().c_str());
530 list.insert("svg:d",m_path.c_str());
532 output->startElement("draw:path", list);
533 output->endElement("draw:path");
534 return true;
538 bool MWAWObjectHandlerInternal::Document::open(const char *psName, WPXPropertyList const &xPropList)
540 if (strncmp(psName,"libmwaw:", 8) == 0)
541 psName += 8;
542 else
544 SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Document::open Unknown tag '" << psName << "'.." );
545 return false;
547 if (strcmp(psName, "document") == 0)
549 m_w = m_h = 0.;
550 WPXPropertyList::Iter i(xPropList);
551 for (i .rewind(); i.next(); )
553 if (strcmp(i.key(), "w") == 0) m_w = getSizeInPt(*i());
554 else if (strcmp(i.key(), "h") == 0) m_h = getSizeInPt(*i());
555 else
557 SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Document::open: find an unknown key '" << i.key() << "'");
560 return true;
562 else if (strcmp(psName, "graphicStyle") == 0)
564 styles.push_back(xPropList);
565 return true;
567 else
569 int id = int(styles.size());
570 Shape shape;
571 if (shape.read(psName, xPropList, id ? id-1 : 0))
573 if (id == 0)
575 SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Document::open shape created without style..");
576 styles.push_back(WPXPropertyList());
578 shapes.push_back(shape);
579 return true;
582 SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Document::open Unknown tag '" << psName << "'..");
583 return false;
586 bool MWAWObjectHandlerInternal::Document::close(const char *)
588 return true;
591 void MWAWObjectHandlerInternal::Document::characters(WPXString const &)
593 SAL_WARN("writerperfect", "Document::characters must NOT be called..");
596 void MWAWObjectHandlerInternal::Document::write(OdfDocumentHandler *output)
598 if (!output) return;
599 WPXPropertyList list;
600 std::stringstream s;
602 list.clear();
603 list.insert("office:mimetype","application/vnd.oasis.opendocument.graphics");
604 list.insert("office:version", "1.0");
606 list.insert("xmlns:config", "urn:oasis:names:tc:opendocument:xmlns:config:1.0");
607 list.insert("xmlns:dc", "http://purl.org/dc/elements/1.1/");
608 list.insert("xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0");
609 list.insert("xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0");
610 list.insert("xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0");
611 list.insert("xmlns:ooo", "http://openoffice.org/2004/office");
612 list.insert("xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0");
613 list.insert("xmlns:svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0");
614 list.insert("xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0");
616 output->startElement("office:document", list);
618 // SETTINGS
620 list.clear();
621 output->startElement("office:settings", list);
622 list.clear();
623 list.insert("config:name","ooo:view-settings");
624 output->startElement("config:config-item-set", list);
626 // - Top
627 list.clear();
628 list.insert("config:name","VisibleAreaTop");
629 list.insert("config:type","int");
630 output->startElement("config:config-item", list);
631 output->characters("0");
633 output->endElement("config:config-item");
634 // - Left
635 list.clear();
636 list.insert("config:name","VisibleAreaLeft");
637 list.insert("config:type","int");
638 output->startElement("config:config-item", list);
639 output->characters("0");
640 output->endElement("config:config-item");
641 // - Width
642 list.clear();
643 list.insert("config:name","VisibleAreaWidth");
644 list.insert("config:type","int");
645 s.str("");
646 s << int(m_w*35.2777); // *2540/72. why ?
647 output->startElement("config:config-item", list);
648 output->characters(s.str().c_str());
649 output->endElement("config:config-item");
650 // - Height
651 list.clear();
652 list.insert("config:name","VisibleAreaHeight");
653 list.insert("config:type","int");
654 s.str("");
655 s << int(m_h*35.2777); // *2540/72. why ?
656 output->startElement("config:config-item", list);
657 output->characters(s.str().c_str());
658 output->endElement("config:config-item");
660 output->endElement("config:config-item-set");
661 output->endElement("office:settings");
664 // STYLES
666 list.clear();
667 output->startElement("office:styles", list);
668 // - a gradient
669 list.clear();
670 list.insert("draw:angle","0");
671 list.insert("draw:border","0%");
672 list.insert("draw:end-color","#000000");
673 list.insert("draw:end-intensity","100%");
674 list.insert("draw:name","Gradient_1");
675 list.insert("draw:start-color","#000000");
676 list.insert("draw:start-intensity","100%");
677 list.insert("draw:style","linear");
678 output->startElement("draw:gradient", list);
679 output->endElement("draw:gradient");
680 // - an arrow
681 list.clear();
682 list.insert("draw:name","Arrow");
683 list.insert("svg:viewBox","0 0 20 30");
684 list.insert("svg:d","m10 0-10 30h20z");
685 output->startElement("draw:marker", list);
686 output->endElement("draw:marker");
688 output->endElement("office:styles");
691 // AUTOMATIC STYLES
693 list.clear();
694 output->startElement("office:automatic-styles", list);
696 // - PM0
698 list.clear();
699 list.insert("style:name","PM0");
700 output->startElement("style:page-layout", list);
701 list.clear();
702 list.insert("fo:margin-bottom","0in");
703 list.insert("fo:margin-left","0in");
704 list.insert("fo:margin-right","0in");
705 list.insert("fo:margin-top","0in");
706 list.insert("fo:page-height",getStringPt(m_h).c_str());
707 list.insert("fo:page-width",getStringPt(m_w).c_str());
708 list.insert("style:print-orientation","portrait");
709 output->startElement("style:page-layout-properties", list);
710 output->endElement("style:page-layout-properties");
711 output->endElement("style:page-layout");
714 // - dp1
716 list.clear();
717 list.insert("style:family","drawing-page");
718 list.insert("style:name","dp1");
719 output->startElement("style:style", list);
720 list.clear();
721 list.insert("draw:fill","none");
722 output->startElement("style:drawing-page-properties", list);
723 output->endElement("style:drawing-page-properties");
724 output->endElement("style:style");
727 // -- the styles
728 for (size_t i = 0; i < styles.size() ; i++)
729 writeStyle(output, styles[i], int(i));
731 output->endElement("office:automatic-styles");
734 // MASTER STYLES
736 list.clear();
737 output->startElement("office:master-styles", list);
738 list.clear();
739 list.insert("draw:style-name","dp1");
740 list.insert("style:name","Default");
741 list.insert("style:page-layout-name","PM0");
742 output->startElement("style:master-page", list);
743 output->endElement("style:master-page");
744 output->endElement("office:master-styles");
747 // BODY
749 list.clear();
750 output->startElement("office:body", list);
751 output->startElement("office:drawing", list);
753 list.clear();
754 list.insert("draw:master-page-name","Default");
755 list.insert("draw:name","page1");
756 list.insert("draw:style-name","dp1");
758 output->startElement("draw:page", list);
760 for (size_t i = 0; i < shapes.size() ; i++)
761 shapes[i].write(output);
763 output->endElement("draw:page");
765 output->endElement("office:drawing");
766 output->endElement("office:body");
768 output->endElement("office:document");
771 void MWAWObjectHandlerInternal::Document::writeStyle (OdfDocumentHandler *output, WPXPropertyList const &style, int styleId)
773 if (!output) return;
775 WPXPropertyList list;
776 list.clear();
777 list.insert("style:family","graphic");
778 list.insert("style:name",getStyleName(styleId).c_str());
779 list.insert("style:parent-style-name","standard");
780 output->startElement("style:style", list);
782 list.clear();
784 WPXPropertyList::Iter i(style);
785 for (i .rewind(); i.next(); )
787 if (strcmp(i.key(), "lineColor") == 0)
788 list.insert("svg:stroke-color", i()->getStr().cstr());
789 else if (strcmp(i.key(), "lineWidth") == 0)
790 list.insert("svg:stroke-width", getStringSizeInPt(*i()).c_str());
791 else if (strcmp(i.key(), "lineFill") == 0)
792 list.insert("draw:stroke", i()->getStr().cstr());
793 else if (strcmp(i.key(), "surfaceColor") == 0)
794 list.insert("draw:fill-color", i()->getStr().cstr());
795 else if (strcmp(i.key(), "surfaceFill") == 0)
796 list.insert("draw:fill", i()->getStr().cstr());
797 else if (strcmp(i.key(), "startArrow") == 0)
799 if (strcmp(i()->getStr().cstr(), "true") == 0)
801 list.insert("draw:marker-start", "Arrow");
802 list.insert("draw:marker-start-center", "false");
805 else if (strcmp(i.key(), "startArrowWidth") == 0)
806 list.insert("draw:marker-start-width", getStringSizeInPt(*i()).c_str());
807 else if (strcmp(i.key(), "endArrow") == 0)
809 if (strcmp(i()->getStr().cstr(), "true") == 0)
811 list.insert("draw:marker-end", "Arrow");
812 list.insert("draw:marker-end-center", "false");
815 else if (strcmp(i.key(), "endArrowWidth") == 0)
816 list.insert("draw:marker-end-width", getStringSizeInPt(*i()).c_str());
817 else
819 SAL_WARN("writerperfect", "MWAWObjectHandlerInternal::Document::writeStyle: find an unknown key '" << i.key() << "'");
823 output->startElement("style:graphic-properties", list);
824 output->endElement("style:graphic-properties");
826 output->endElement("style:style");
830 sal_Bool SAL_CALL MWAWImportFilter::importImpl( const Sequence< ::com::sun::star::beans::PropertyValue > &aDescriptor )
831 throw (RuntimeException)
833 SAL_INFO("writerperfect", "MWAWImportFilter::importImpl");
835 sal_Int32 nLength = aDescriptor.getLength();
836 const PropertyValue *pValue = aDescriptor.getConstArray();
837 Reference < XInputStream > xInputStream;
838 for ( sal_Int32 i = 0 ; i < nLength; i++)
840 if ( pValue[i].Name == "InputStream" )
841 pValue[i].Value >>= xInputStream;
843 if ( !xInputStream.is() )
845 OSL_ASSERT( 0 );
846 return sal_False;
849 // An XML import service: what we push sax messages to..
850 OUString sXMLImportService ( "com.sun.star.comp.Writer.XMLOasisImporter" );
851 Reference < XDocumentHandler > xInternalHandler( comphelper::ComponentContext( mxContext ).createComponent( sXMLImportService ), UNO_QUERY );
853 // The XImporter sets up an empty target document for XDocumentHandler to write to..
854 Reference < XImporter > xImporter(xInternalHandler, UNO_QUERY);
855 xImporter->setTargetDocument(mxDoc);
857 // OO Document Handler: abstract class to handle document SAX messages, concrete implementation here
858 // writes to in-memory target doc
859 DocumentHandler xHandler(xInternalHandler);
861 WPXSvInputStream input( xInputStream );
863 OdtGenerator collector(&xHandler, ODF_FLAT_XML);
864 collector.registerEmbeddedObjectHandler("image/mwaw-odg", &handleEmbeddedMWAWObject);
865 if (MWAW_OK == MWAWDocument::parse(&input, &collector))
866 return sal_True;
867 return sal_False;
870 sal_Bool SAL_CALL MWAWImportFilter::filter( const Sequence< ::com::sun::star::beans::PropertyValue > &aDescriptor )
871 throw (RuntimeException)
873 SAL_INFO("writerperfect", "MWAWImportFilter::filter");
874 return importImpl ( aDescriptor );
876 void SAL_CALL MWAWImportFilter::cancel( )
877 throw (RuntimeException)
879 SAL_INFO("writerperfect", "MWAWImportFilter::cancel");
882 // XImporter
883 void SAL_CALL MWAWImportFilter::setTargetDocument( const Reference< ::com::sun::star::lang::XComponent > &xDoc )
884 throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException)
886 SAL_INFO("writerperfect", "MWAWImportFilter::getTargetDocument");
887 mxDoc = xDoc;
890 // XExtendedFilterDetection
891 OUString SAL_CALL MWAWImportFilter::detect( com::sun::star::uno::Sequence< PropertyValue > &Descriptor )
892 throw( com::sun::star::uno::RuntimeException )
894 SAL_INFO("writerperfect", "MWAWImportFilter::detect");
896 MWAWConfidence confidence = MWAW_CONFIDENCE_NONE;
897 MWAWDocument::DocumentType docType = MWAWDocument::UNKNOWN;
898 MWAWDocument::DocumentKind docKind = MWAWDocument::K_UNKNOWN;
899 OUString sTypeName;
900 sal_Int32 nLength = Descriptor.getLength();
901 sal_Int32 location = nLength;
902 const PropertyValue *pValue = Descriptor.getConstArray();
903 Reference < XInputStream > xInputStream;
904 for ( sal_Int32 i = 0 ; i < nLength; i++)
906 if ( pValue[i].Name == "TypeName" )
907 location=i;
908 else if ( pValue[i].Name == "InputStream" )
909 pValue[i].Value >>= xInputStream;
912 if (!xInputStream.is())
913 return OUString();
915 WPXSvInputStream input( xInputStream );
917 confidence = MWAWDocument::isFileFormatSupported(&input, docType, docKind);
919 if ((confidence == MWAW_CONFIDENCE_EXCELLENT) || (confidence == MWAW_CONFIDENCE_GOOD))
921 if ( docKind == MWAWDocument::K_TEXT )
923 switch (docType)
925 case MWAWDocument::ACT: // Acta (nothing done )
926 break;
927 case MWAWDocument::CW: // ClarisWorks/AppleWorks document (basic)
928 sTypeName = "writer_ClarisWorks";
929 break;
930 case MWAWDocument::DM: // DocMaker (v4)
931 sTypeName = "writer_DocMaker";
932 break;
933 case MWAWDocument::ED: // eDOC (v2)
934 sTypeName = "writer_eDoc_Document";
935 break;
936 case MWAWDocument::FULLW: // FullWrite Professional (basic)
937 sTypeName = "writer_FullWrite_Professional";
938 break;
939 case MWAWDocument::HMAC: // HanMac Word-K (basic done)
940 sTypeName = "writer_HanMac_Word_K";
941 break;
942 case MWAWDocument::HMACJ: // HanMac Word-J ( almost nothing done for J document)
943 // sTypeName = "writer_HanMac_Word_J";
944 break;
945 case MWAWDocument::LWTEXT: // LightWayText ( only v4.5 Mac format )
946 sTypeName = "writer_LightWayText";
947 break;
948 case MWAWDocument::MARIW: // Mariner Write ( only v1.6-v3.5 Mac Classic)
949 sTypeName = "writer_Mariner_Write";
950 break;
951 case MWAWDocument::MINDW: // MindWrite
952 sTypeName = "writer_MindWrite";
953 break;
954 case MWAWDocument::MW: // MacWrite document
955 sTypeName = "writer_MacWrite";
956 break;
957 case MWAWDocument::MWPRO: // MacWriteII or MacWritePro document
958 sTypeName = "writer_MacWritePro";
959 break;
960 case MWAWDocument::MSWORD: // MSWord document (v4 v5: basic done)
961 sTypeName = "writer_Mac_Word";
962 break;
963 case MWAWDocument::MSWORKS: // MSWorks document (v1 v2)
964 sTypeName = "writer_Mac_Works";
965 break;
966 case MWAWDocument::NISUSW: // Nisus Writer document: v3.4-v6.5
967 sTypeName = "writer_Nisus_Writer";
968 break;
969 case MWAWDocument::TEACH: // TeachText or SimpleText: v1
970 sTypeName = "writer_TeachText";
971 break;
972 case MWAWDocument::TEDIT: // Tex-Edit v2
973 sTypeName = "writer_TexEdit";
974 break;
975 case MWAWDocument::WNOW: // WriteNow
976 sTypeName = "writer_WriteNow";
977 break;
978 case MWAWDocument::WPLUS: // writerplus document
979 sTypeName = "writer_WriterPlus";
980 break;
981 case MWAWDocument::ZWRT: // Z-Write : v1.3
982 sTypeName = "writer_ZWrite";
983 break;
984 default:
985 break;
990 if (!sTypeName.isEmpty())
992 if ( location == nLength )
994 Descriptor.realloc(nLength+1);
995 Descriptor[location].Name = "TypeName";
998 Descriptor[location].Value <<=sTypeName;
1001 return sTypeName;
1005 // XInitialization
1006 void SAL_CALL MWAWImportFilter::initialize( const Sequence< Any > &aArguments )
1007 throw (Exception, RuntimeException)
1009 SAL_INFO("writerperfect", "MWAWImportFilter::initialize");
1010 Sequence < PropertyValue > aAnySeq;
1011 sal_Int32 nLength = aArguments.getLength();
1012 if ( nLength && ( aArguments[0] >>= aAnySeq ) )
1014 const PropertyValue *pValue = aAnySeq.getConstArray();
1015 nLength = aAnySeq.getLength();
1016 for ( sal_Int32 i = 0 ; i < nLength; i++)
1018 if ( pValue[i].Name == "Type" )
1020 pValue[i].Value >>= msFilterName;
1021 break;
1026 OUString MWAWImportFilter_getImplementationName ()
1027 throw (RuntimeException)
1029 return OUString ( "com.sun.star.comp.Writer.MWAWImportFilter" );
1032 #define SERVICE_NAME1 "com.sun.star.document.ImportFilter"
1033 #define SERVICE_NAME2 "com.sun.star.document.ExtendedTypeDetection"
1034 sal_Bool SAL_CALL MWAWImportFilter_supportsService( const OUString &ServiceName )
1035 throw (RuntimeException)
1037 return ( ServiceName == SERVICE_NAME1 || ServiceName == SERVICE_NAME2 );
1039 Sequence< OUString > SAL_CALL MWAWImportFilter_getSupportedServiceNames( )
1040 throw (RuntimeException)
1042 Sequence < OUString > aRet(2);
1043 OUString *pArray = aRet.getArray();
1044 pArray[0] = OUString ( SERVICE_NAME1 );
1045 pArray[1] = OUString ( SERVICE_NAME2 );
1046 return aRet;
1048 #undef SERVICE_NAME2
1049 #undef SERVICE_NAME1
1051 Reference< XInterface > SAL_CALL MWAWImportFilter_createInstance( const Reference< XComponentContext > &rContext)
1052 throw( Exception )
1054 return (cppu::OWeakObject *) new MWAWImportFilter( rContext );
1057 // XServiceInfo
1058 OUString SAL_CALL MWAWImportFilter::getImplementationName( )
1059 throw (RuntimeException)
1061 return MWAWImportFilter_getImplementationName();
1063 sal_Bool SAL_CALL MWAWImportFilter::supportsService( const OUString &rServiceName )
1064 throw (RuntimeException)
1066 return MWAWImportFilter_supportsService( rServiceName );
1068 Sequence< OUString > SAL_CALL MWAWImportFilter::getSupportedServiceNames( )
1069 throw (RuntimeException)
1071 return MWAWImportFilter_getSupportedServiceNames();
1074 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */