00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef NDEBUG
00020
00021 #endif
00022
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <stdarg.h>
00026
00027 #include <qfile.h>
00028 #include <qobject.h>
00029 #include <qstring.h>
00030 #include <qtextcodec.h>
00031 #include <qtextstream.h>
00032
00033 #include <kdebug.h>
00034 #include <kgenericfactory.h>
00035
00036 #include <KoFilterChain.h>
00037 #include <KoStore.h>
00038
00039 #include "list.h"
00040 #include "libmswrite.h"
00041
00042 #include "ImportDialog.h"
00043 #include "mswriteimport.h"
00044
00045
00046 class MSWriteImportFactory : KGenericFactory <MSWriteImport, KoFilter>
00047 {
00048 public:
00049 MSWriteImportFactory () : KGenericFactory <MSWriteImport, KoFilter> ("kwordmswriteimport")
00050 {
00051 }
00052
00053 protected:
00054 virtual void setupTranslations (void)
00055 {
00056 KGlobal::locale()->insertCatalogue ("kofficefilters");
00057 }
00058 };
00059
00060 K_EXPORT_COMPONENT_FACTORY (libmswriteimport, MSWriteImportFactory ())
00061
00062
00063
00064
00065
00066
00067 class WRIDevice : public MSWrite::Device
00068 {
00069 private:
00070 FILE *m_infp;
00071
00072 public:
00073 WRIDevice () : m_infp (NULL)
00074 {
00075 }
00076
00077 virtual ~WRIDevice ()
00078 {
00079 closeFile ();
00080 }
00081
00082 bool openFile (const char *fileName)
00083 {
00084 m_infp = fopen (fileName, "rb");
00085 if (!m_infp)
00086 {
00087 error (MSWrite::Error::FileError, "could not open file for reading\n");
00088 return false;
00089 }
00090
00091 return true;
00092 }
00093
00094 bool closeFile (void)
00095 {
00096 if (m_infp)
00097 {
00098 if (fclose (m_infp))
00099 {
00100 error (MSWrite::Error::FileError, "could not close input file\n");
00101 return false;
00102 }
00103
00104 m_infp = NULL;
00105 }
00106
00107 return true;
00108 }
00109
00110 bool read (MSWrite::Byte *buf, const MSWrite::DWord numBytes)
00111 {
00112 if (fread (buf, 1, (size_t) numBytes, m_infp) != (size_t) numBytes)
00113 {
00114 error (MSWrite::Error::FileError, "could not read from input file\n");
00115 return false;
00116 }
00117
00118 return true;
00119 }
00120
00121 bool write (const MSWrite::Byte *, const MSWrite::DWord)
00122 {
00123 error (MSWrite::Error::InternalError, "writing to an input file?\n");
00124 return false;
00125 }
00126
00127 bool seek (const long offset, const int whence)
00128 {
00129 if (fseek (m_infp, offset, whence))
00130 {
00131 error (MSWrite::Error::InternalError, "could not seek input file\n");
00132 return false;
00133 }
00134
00135 return true;
00136 }
00137
00138 long tell (void)
00139 {
00140 return ftell (m_infp);
00141 }
00142
00143 void debug (const char *s)
00144 {
00145 kdDebug (30509) << s;
00146 }
00147
00148 void debug (const int i)
00149 {
00150 kdDebug (30509) << i;
00151 }
00152
00153 void error (const int errorCode, const char *message,
00154 const char * = "", const int = 0,
00155 MSWrite::DWord = NoToken)
00156 {
00157 if (errorCode == MSWrite::Error::Warn)
00158 kdWarning (30509) << message;
00159 else
00160 {
00161 m_error = errorCode;
00162 kdError (30509) << message;
00163 }
00164 }
00165 };
00166
00167
00168
00169
00170
00171
00172 class KWordGenerator : public MSWrite::Generator, public MSWrite::NeedsDevice
00173 {
00174 private:
00175
00176
00177 class WRIObject
00178 {
00179 private:
00180 WRIObject (const WRIObject &rhs);
00181
00182 public:
00183 MSWrite::Byte *m_data;
00184 MSWrite::DWord m_dataLength;
00185 MSWrite::DWord m_dataUpto;
00186 QString m_nameInStore;
00187
00188 WRIObject () : m_data (NULL), m_dataLength (0), m_dataUpto (0)
00189 {
00190 }
00191
00192 ~WRIObject ()
00193 {
00194 delete [] m_data;
00195 }
00196
00197 WRIObject operator= (const WRIObject &rhs)
00198 {
00199 delete [] m_data;
00200
00201 m_dataLength = rhs.m_dataLength;
00202 m_dataUpto = rhs.m_dataUpto;
00203 m_nameInStore = rhs.m_nameInStore;
00204
00205 if (rhs.m_data)
00206 {
00207 m_data = new MSWrite::Byte [m_dataLength];
00208 if (m_data)
00209 memcpy (m_data, rhs.m_data, m_dataLength);
00210
00211 }
00212 else
00213 m_data = NULL;
00214
00215 return *this;
00216 }
00217 };
00218
00219
00220 int m_pageWidth, m_pageHeight;
00221 int m_left, m_right, m_top, m_bottom;
00222 int m_leftMargin, m_rightMargin, m_topMargin, m_bottomMargin;
00223 int m_headerFromTop, m_footerFromTop;
00224 bool m_hasHeader, m_isHeaderOnFirstPage;
00225 bool m_hasFooter, m_isFooterOnFirstPage;
00226 bool m_writeHeaderFirstTime, m_writeFooterFirstTime;
00227
00228 int inWhat;
00229
00230 enum inWhatPossiblities
00231 {
00232 Nothing,
00233 Header,
00234 Footer,
00235 Body
00236 };
00237
00238 int m_startingPageNumber;
00239
00240 KoFilterChain *m_chain;
00241 KoStoreDevice *m_outfile;
00242
00243
00244 QTextCodec *m_codec;
00245 QTextDecoder *m_decoder;
00246
00247
00248 bool m_simulateLineSpacing;
00249 bool m_simulateImageOffset;
00250
00251
00252 QString m_formatOutput;
00253 int m_charInfoCountStart, m_charInfoCountLen;
00254 bool m_pageBreak, m_needAnotherParagraph;
00255 int m_pageBreakOffset;
00256 int m_lineSpacingFromAbove;
00257
00258
00259 int m_numPictures;
00260 QString m_pictures;
00261
00262 QString m_objectFrameset;
00263
00264 MSWrite::List <WRIObject> m_objectList;
00265
00266 double m_objectHorizOffset;
00267 bool m_paraIsImage;
00268
00269 MSWriteImport *m_koLink;
00270
00271
00272
00273 bool m_delayOutput;
00274 QString m_heldOutput;
00275
00276 void delayOutput (const bool yes)
00277 {
00278 m_delayOutput = yes;
00279 }
00280
00281 bool delayOutputFlush (void)
00282 {
00283 QCString strUtf8 = m_heldOutput.utf8 ();
00284 int strLength = strUtf8.length ();
00285
00286 if (m_outfile->writeBlock (strUtf8, strLength) != strLength)
00287 ErrorAndQuit (MSWrite::Error::FileError, "could not write delayed output\n");
00288
00289 m_heldOutput = "";
00290 return true;
00291 }
00292
00293 public:
00294 KWordGenerator () : m_hasHeader (false), m_isHeaderOnFirstPage (false),
00295 m_hasFooter (false), m_isFooterOnFirstPage (false),
00296 m_writeHeaderFirstTime (true), m_writeFooterFirstTime (true),
00297 inWhat (Nothing),
00298 m_decoder (NULL),
00299 m_simulateLineSpacing (false),
00300 m_simulateImageOffset (true),
00301 m_pageBreak (false), m_needAnotherParagraph (false),
00302 m_lineSpacingFromAbove (0),
00303 m_numPictures (0)
00304 {
00305 delayOutput (false);
00306
00307
00308 m_codec = QTextCodec::codecForName ("CP 1252");
00309
00310 if (m_codec)
00311 m_decoder = m_codec->makeDecoder();
00312 else
00313 kdWarning (30509) << "Cannot convert from Win Charset!" << endl;
00314 }
00315
00316 virtual ~KWordGenerator ()
00317 {
00318 delete m_decoder;
00319 }
00320
00321 void setFilterChain (KoFilterChain *chain)
00322 {
00323 m_chain = chain;
00324 }
00325
00326 bool writeDocumentBegin (const MSWrite::Word,
00327 const MSWrite::PageLayout *pageLayout)
00328 {
00329 kdDebug (30509) << "writeDocumentBegin()" << endl;
00330
00331
00332 m_outfile = m_chain->storageFile ("root", KoStore::Write);
00333 if (!m_outfile)
00334 ErrorAndQuit (MSWrite::Error::FileError, "could not open root in store\n");
00335
00336
00337
00338
00339
00340
00341
00342 m_pageWidth = Twip2Point (pageLayout->getPageWidth ());
00343 m_pageHeight = Twip2Point (pageLayout->getPageHeight ());
00344
00345
00346 m_left = Twip2Point (pageLayout->getLeftMargin ());
00347 m_right = m_left + Twip2Point (pageLayout->getTextWidth ()) - 1;
00348 m_top = Twip2Point (pageLayout->getTopMargin ());
00349 m_bottom = m_top + Twip2Point (pageLayout->getTextHeight ()) - 1;
00350
00351
00352 m_leftMargin = m_left;
00353 m_rightMargin = Twip2Point (pageLayout->getRightMargin ());
00354 m_topMargin = m_top;
00355 m_bottomMargin = Twip2Point (pageLayout->getBottomMargin ());
00356
00357 kdDebug (30509) << "leftMargin: " << m_leftMargin << endl;
00358 kdDebug (30509) << "rightMargin: " << m_rightMargin << endl;
00359 kdDebug (30509) << "topMargin: " << m_topMargin << endl;
00360 kdDebug (30509) << "bottomMargin: " << m_bottomMargin << endl;
00361
00362
00363 m_headerFromTop = Twip2Point (pageLayout->getHeaderFromTop ());
00364 m_footerFromTop = Twip2Point (pageLayout->getFooterFromTop ());
00365
00366 kdDebug (30509) << "headerFromTop: " << m_headerFromTop
00367 << " footerFromTop: " << m_footerFromTop << endl;
00368
00369 m_startingPageNumber = pageLayout->getPageNumberStart ();
00370
00371 return true;
00372 }
00373
00374 bool writeDocumentBeginForReal (void)
00375 {
00376 kdDebug (30509) << "writeDocumentBeginForReal()" << endl;
00377
00378
00379
00380
00381
00382 if (m_hasHeader)
00383 if (m_headerFromTop < m_topMargin)
00384 m_topMargin = m_headerFromTop;
00385
00386 if (m_hasFooter)
00387 if (m_pageHeight - m_footerFromTop < m_bottomMargin)
00388 m_bottomMargin = m_pageHeight - m_footerFromTop;
00389
00390 kdDebug (30509) << "adjusted::: leftMargin: " << m_leftMargin
00391 << " rightMargin: " << m_rightMargin
00392 << " topMargin: " << m_topMargin
00393 << " bottomMargin: " << m_bottomMargin
00394 << endl;
00395
00396
00397
00398 writeTextInternal ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
00399 writeTextInternal ("<!DOCTYPE DOC PUBLIC \"-//KDE//DTD kword 1.3//EN\" "
00400 "\"http://www.koffice.org/DTD/kword-1.3.dtd\">");
00401 writeTextInternal ("<DOC xmlns=\"http://www.koffice.org/DTD/kword\" "
00402 "mime=\"application/x-kword\" "
00403 "syntaxVersion=\"3\" editor=\"KWord\">");
00404
00405 writeTextInternal ("<PAPER format=\"1\" "
00406 "width=\"%i\" height=\"%i\" "
00407 "orientation=\"0\" columns=\"1\" "
00408 "hType=\"%i\" fType=\"%i\">",
00409 m_pageWidth, m_pageHeight,
00410 m_isHeaderOnFirstPage ? 0 : 2,
00411 m_isFooterOnFirstPage ? 0 : 2);
00412
00413 writeTextInternal ("<PAPERBORDERS left=\"%i\" right=\"%i\" "
00414 "top=\"%i\" bottom=\"%i\"/>",
00415 m_leftMargin, m_rightMargin,
00416 m_topMargin, m_bottomMargin);
00417
00418 writeTextInternal ("</PAPER>");
00419
00420 writeTextInternal ("<ATTRIBUTES processing=\"0\" "
00421 "tabStopValue=\"%lf\" "
00422 "hasHeader=\"%i\" hasFooter=\"%i\"/>",
00423 Inch2Point (0.5),
00424 m_hasHeader ? 1 : 0, m_hasFooter ? 1 : 0);
00425
00426
00427 if (m_startingPageNumber != 1)
00428 writeTextInternal ("<VARIABLESETTINGS startingPageNumber=\"%i\"/>",
00429 m_startingPageNumber);
00430
00431 writeTextInternal ("<FRAMESETS>");
00432
00433 return true;
00434 }
00435
00436 bool writeDocumentEnd (const MSWrite::Word, const MSWrite::PageLayout *)
00437 {
00438 kdDebug (30509) << "writeDocumentEnd()" << endl;
00439
00440
00441 writeTextInternal (m_objectFrameset);
00442
00443 writeTextInternal ("</FRAMESETS>");
00444 writeTextInternal ("<STYLES>");
00445 writeTextInternal ("<STYLE>");
00446 writeTextInternal ("<NAME value=\"Standard\"/>");
00447 writeTextInternal ("<FLOW align=\"left\"/>");
00448 writeTextInternal ("<INDENTS first=\"0\" left=\"0\" right=\"0\"/>");
00449 writeTextInternal ("<OFFSETS before=\"0\" after=\"0\"/>");
00450
00451 writeTextInternal ("<FORMAT id=\"1\">");
00452 writeTextInternal ("<COLOR blue=\"0\" red=\"0\" green=\"0\"/>");
00453 writeTextInternal ("<FONT name=\"helvetica\"/>");
00454 writeTextInternal ("<SIZE value=\"12\"/>");
00455 writeTextInternal ("<WEIGHT value=\"50\"/>");
00456 writeTextInternal ("<ITALIC value=\"0\"/>");
00457 writeTextInternal ("<UNDERLINE value=\"0\"/>");
00458 writeTextInternal ("<STRIKEOUT value=\"0\"/>");
00459 writeTextInternal ("<VERTALIGN value=\"0\"/>");
00460 writeTextInternal ("</FORMAT>");
00461
00462 writeTextInternal ("<FOLLOWING name=\"Standard\"/>");
00463 writeTextInternal ("</STYLE>");
00464 writeTextInternal ("</STYLES>");
00465
00466
00467 writeTextInternal ("<PICTURES>");
00468 writeTextInternal (m_pictures);
00469 writeTextInternal ("</PICTURES>");
00470
00471
00472 writeTextInternal ("</DOC>");
00473
00474
00475 m_outfile->close ();
00476 m_outfile = (KoStoreDevice *) NULL;
00477
00478
00479
00480
00481
00482
00483
00484
00485 MSWrite::List <WRIObject>::Iterator it;
00486 MSWrite::List <WRIObject>::Iterator end(m_objectList.end ());
00487 for (it = m_objectList.begin (); it != end; ++it)
00488 {
00489 kdDebug (30509) << "outputting object \'" << (*it).m_nameInStore
00490 << "\' (length: " << (*it).m_dataLength << ")"
00491 << endl;
00492
00493 if (!(*it).m_data)
00494 ErrorAndQuit (MSWrite::Error::InternalError, "image data not initialised\n");
00495
00496
00497 m_outfile = m_chain->storageFile ((*it).m_nameInStore, KoStore::Write);
00498 if (!m_outfile)
00499 ErrorAndQuit (MSWrite::Error::FileError, "could not open image in store\n");
00500
00501 if (m_outfile->writeBlock ((const char *) (*it).m_data, (*it).m_dataLength)
00502 != (Q_LONG) (*it).m_dataLength)
00503 ErrorAndQuit (MSWrite::Error::FileError, "could not write image to store\n");
00504
00505
00506 m_outfile->close ();
00507 m_outfile = NULL;
00508 }
00509
00510 return true;
00511 }
00512
00513
00514 bool writeFooterBegin (void)
00515 {
00516 kdDebug (30509) << "writeFooterBegin()" << endl;
00517
00518 inWhat = Footer;
00519 m_hasFooter = true;
00520
00521
00522 delayOutput (true);
00523
00524
00525
00526 return true;
00527 }
00528
00529 bool writeFooterEnd (void)
00530 {
00531 kdDebug (30509) << "writeFooterEnd()" << endl;
00532
00533 inWhat = Nothing;
00534
00535 if (!m_writeFooterFirstTime)
00536 writeTextInternal ("</FRAMESET>");
00537 delayOutput (false);
00538
00539 return true;
00540 }
00541
00542 bool writeHeaderBegin (void)
00543 {
00544 kdDebug (30509) << "writeHeaderBegin()" << endl;
00545
00546 inWhat = Header;
00547 m_hasHeader = true;
00548
00549
00550 delayOutput (true);
00551
00552
00553
00554 return true;
00555 }
00556
00557 bool writeHeaderEnd (void)
00558 {
00559 kdDebug (30509) << "writeHeaderEnd()" << endl;
00560
00561 inWhat = Nothing;
00562
00563 if (!m_writeHeaderFirstTime)
00564 writeTextInternal ("</FRAMESET>");
00565 delayOutput (false);
00566
00567 return true;
00568 }
00569
00570 bool writeBodyBegin (void)
00571 {
00572 kdDebug (30509) << "writeBodyBegin()" << endl;
00573
00574 inWhat = Body;
00575
00576
00577
00578 writeDocumentBeginForReal ();
00579
00580 writeTextInternal ("<FRAMESET frameType=\"1\" frameInfo=\"0\" name=\"Text Frameset 1\" visible=\"1\">");
00581
00582 writeTextInternal ("<FRAME runaround=\"1\" autoCreateNewFrame=\"1\" newFrameBehavior=\"0\" copy=\"0\""
00583 " top=\"%i\" bottom=\"%i\" left=\"%i\" right=\"%i\"/>",
00584 m_top, m_bottom, m_left, m_right);
00585
00586 return true;
00587 }
00588
00589 bool writeBodyEnd (void)
00590 {
00591 kdDebug (30509) << "writeBodyEnd()" << endl;
00592
00593 inWhat = Nothing;
00594
00595
00596
00597 if (m_needAnotherParagraph)
00598 {
00599 kdDebug (30509) << "needAnotherParagraph in bodyEndWrite()" << endl;
00600 writeTextInternal ("<PARAGRAPH><TEXT></TEXT><LAYOUT></LAYOUT></PARAGRAPH>");
00601 m_needAnotherParagraph = false;
00602 }
00603
00604 writeTextInternal ("</FRAMESET>");
00605
00606
00607 delayOutputFlush ();
00608
00609 return true;
00610 }
00611
00612 bool writeParaInfoBegin (const MSWrite::FormatParaProperty *paraProperty,
00613 const MSWrite::OLE *ole,
00614 const MSWrite::Image *image)
00615 {
00616
00617
00618
00619 m_charInfoCountStart = 0;
00620 m_charInfoCountLen = 0;
00621
00622 if (inWhat == Header)
00623 {
00624 m_isHeaderOnFirstPage = paraProperty->getIsOnFirstPage ();
00625
00626 if (m_writeHeaderFirstTime)
00627 {
00628
00629
00630
00631
00632
00633 writeTextInternal ("<FRAMESET frameType=\"1\" frameInfo=\"1\" name=\"First Page Header\" visible=\"%i\">",
00634 m_isHeaderOnFirstPage ? 1 : 0);
00635 writeTextInternal ("<FRAME runaround=\"1\" copy=\"0\" newFrameBehavior=\"2\" autoCreateNewFrame=\"0\""
00636 " top=\"%i\" bottom=\"%i\" left=\"%i\" right=\"%i\"/>",
00637 m_headerFromTop, m_headerFromTop, m_left, m_right);
00638 writeTextInternal ("</FRAMESET>");
00639
00640 writeTextInternal ("<FRAMESET frameType=\"1\" frameInfo=\"2\" name=\"Even Pages Header\" visible=\"0\">");
00641 writeTextInternal ("<FRAME runaround=\"1\" copy=\"0\" newFrameBehavior=\"2\" autoCreateNewFrame=\"0\""
00642 " top=\"%i\" bottom=\"%i\" left=\"%i\" right=\"%i\"/>",
00643 m_headerFromTop, m_headerFromTop, m_left, m_right);
00644 writeTextInternal ("</FRAMESET>");
00645
00646
00647 writeTextInternal ("<FRAMESET frameType=\"1\" frameInfo=\"3\" name=\"Odd Pages Header\" visible=\"1\">");
00648 writeTextInternal ("<FRAME runaround=\"1\" copy=\"1\" newFrameBehavior=\"2\" autoCreateNewFrame=\"0\""
00649 " top=\"%i\" bottom=\"%i\" left=\"%i\" right=\"%i\"/>",
00650 m_headerFromTop, m_headerFromTop, m_left, m_right);
00651
00652 m_writeHeaderFirstTime = false;
00653 }
00654 }
00655 else if (inWhat == Footer)
00656 {
00657 m_isFooterOnFirstPage = paraProperty->getIsOnFirstPage ();
00658
00659 if (m_writeFooterFirstTime)
00660 {
00661
00662
00663
00664
00665
00666 writeTextInternal ("<FRAMESET frameType=\"1\" frameInfo=\"4\" name=\"First Page Footer\" visible=\"%i\">",
00667 m_isFooterOnFirstPage ? 1 : 0);
00668 writeTextInternal ("<FRAME runaround=\"1\" copy=\"0\" newFrameBehavior=\"2\" autoCreateNewFrame=\"0\""
00669 " top=\"%i\" bottom=\"%i\" left=\"%i\" right=\"%i\"/>",
00670 m_footerFromTop, m_footerFromTop, m_left, m_right);
00671 writeTextInternal ("</FRAMESET>");
00672
00673 writeTextInternal ("<FRAMESET frameType=\"1\" frameInfo=\"5\" name=\"Even Pages Footer\" visible=\"0\">");
00674 writeTextInternal ("<FRAME runaround=\"1\" copy=\"0\" newFrameBehavior=\"2\" autoCreateNewFrame=\"0\""
00675 " top=\"%i\" bottom=\"%i\" left=\"%i\" right=\"%i\"/>",
00676 m_footerFromTop, m_footerFromTop, m_left, m_right);
00677 writeTextInternal ("</FRAMESET>");
00678
00679
00680 writeTextInternal ("<FRAMESET frameType=\"1\" frameInfo=\"6\" name=\"Odd Pages Footer\" visible=\"1\">");
00681 writeTextInternal ("<FRAME runaround=\"1\" copy=\"1\" newFrameBehavior=\"2\" autoCreateNewFrame=\"0\""
00682 " top=\"%i\" bottom=\"%i\" left=\"%i\" right=\"%i\"/>",
00683 m_footerFromTop, m_footerFromTop, m_left, m_right);
00684
00685 m_writeFooterFirstTime = false;
00686 }
00687 }
00688
00689 if (!writeTextInternal ("<PARAGRAPH><TEXT>")) return false;
00690
00691 if (image)
00692 {
00693 kdDebug (30509) << "Paragraph is an image!" << endl;
00694
00695 QString imageName;
00696 QString fileInStore;
00697
00698
00699
00700
00701
00702 imageName = "Picture ";
00703 imageName += QString::number (m_numPictures + 1);
00704
00705
00706
00707
00708
00709 fileInStore = "pictures/picture" + QString::number (m_numPictures + 1);
00710
00711 kdDebug (30509) << "\tGetting type..." << endl;
00712
00713
00714 if (image->getIsBMP ())
00715 fileInStore += ".bmp";
00716 else if (image->getIsWMF () )
00717 fileInStore += ".wmf";
00718 else
00719 ErrorAndQuit (MSWrite::Error::InternalError, "unsupported picture type\n");
00720
00721
00722
00723
00724 kdDebug (30509) << "\tIndicating anchored image in formatting" << endl;
00725 if (!writeTextInternal ("#")) return false;
00726
00727 m_formatOutput += "<FORMAT id=\"6\" pos=\"0\" len=\"1\">";
00728 m_formatOutput += "<ANCHOR type=\"frameset\" instance=\"";
00729 m_formatOutput += imageName;
00730 m_formatOutput += "\"/>";
00731 m_formatOutput += "</FORMAT>";
00732
00733
00734
00735
00736 kdDebug (30509) << "\tWriting framesets!" << endl;
00737
00738 m_objectFrameset += "<FRAMESET frameType=\"2\" frameInfo=\"0\" name=\"";
00739 m_objectFrameset += imageName;
00740 m_objectFrameset += "\" visible=\"1\">";
00741
00742 m_objectFrameset += "<FRAME runaround=\"1\" copy=\"0\" newFrameBehavior=\"1\"";
00743
00744 const double imageLeft = double (m_left) + Twip2Point (double (image->getIndent ()));
00745 m_objectFrameset += " left=\"";
00746 m_objectFrameset += QString::number (imageLeft);
00747 m_objectFrameset += "\"";
00748
00749 const double imageWidth = Twip2Point (double (image->getDisplayedWidth ()));
00750 m_objectFrameset += " right=\"";
00751 m_objectFrameset += QString::number (imageLeft + imageWidth - 1);
00752 m_objectFrameset += "\"";
00753
00754 m_objectFrameset += " top=\"";
00755 m_objectFrameset += QString::number (m_top);
00756 m_objectFrameset += "\"";
00757
00758 const double imageHeight = Twip2Point (double (image->getDisplayedHeight ()));
00759 m_objectFrameset += " bottom=\"";
00760 m_objectFrameset += QString::number (double (m_top) + imageHeight - 1);
00761 m_objectFrameset += "\"/>";
00762
00763 m_objectFrameset += "<PICTURE keepAspectRatio=\"false\">";
00764 m_objectFrameset += "<KEY msec=\"0\" hour=\"0\" second=\"0\" minute=\"0\" day=\"1\" month=\"1\" year=\"1970\"";
00765 m_objectFrameset += " filename=\"";
00766 m_objectFrameset += fileInStore;
00767 m_objectFrameset += "\"/>";
00768 m_objectFrameset += "</PICTURE>";
00769
00770 m_objectFrameset += "</FRAMESET>";
00771 #ifdef DEBUG_XML_OUTPUT
00772 m_objectFrameset += "\n";
00773 #endif
00774
00775 m_pictures += "<KEY msec=\"0\" hour=\"0\" second=\"0\" minute=\"0\" day=\"1\" month=\"1\" year=\"1970\"";
00776 m_pictures += " name=\"";
00777 m_pictures += fileInStore;
00778 m_pictures += "\"";
00779 m_pictures += " filename=\"";
00780 m_pictures += fileInStore;
00781 m_pictures += "\"/>";
00782
00783 m_numPictures++;
00784
00785
00786
00787
00788 kdDebug (30509) << "\tStoring object" << endl;
00789
00790 if (!m_objectList.addToBack ())
00791 ErrorAndQuit (MSWrite::Error::OutOfMemory, "could not allocate memory for object\n");
00792
00793 WRIObject &obj = *m_objectList.begin (false);
00794 obj.m_nameInStore = fileInStore;
00795 obj.m_dataLength = image->getExternalImageSize ();
00796 obj.m_data = new MSWrite::Byte [obj.m_dataLength];
00797 if (!obj.m_data)
00798 ErrorAndQuit (MSWrite::Error::OutOfMemory, "could not allocate memory for object data\n");
00799
00800
00801 m_objectHorizOffset = double (Twip2Point (image->getIndent ()));
00802 m_paraIsImage = true;
00803 }
00804 else
00805 {
00806 if (ole)
00807 {
00808 if (!writeTextInternal ("[OLE unsupported]")) return false;
00809 }
00810
00811 m_paraIsImage = false;
00812 }
00813
00814
00815 return true;
00816 }
00817
00818 bool writeParaInfoEnd (const MSWrite::FormatParaProperty *paraProperty,
00819 const MSWrite::OLE * ,
00820 const MSWrite::Image *image)
00821
00822 {
00823
00824
00825 if (image)
00826 {
00827 WRIObject &obj = *m_objectList.begin (false);
00828
00829
00830 if (obj.m_dataUpto != obj.m_dataLength)
00831 kdWarning (30509) << "obj.dataUpto (" << obj.m_dataUpto
00832 << ") != obj.dataLength (" << obj.m_dataLength
00833 << ")" << endl;
00834 }
00835
00836 QString output;
00837 output += "</TEXT>";
00838
00839 output += "<LAYOUT>";
00840 output += "<NAME value=\"Standard\"/>";
00841
00842 int align = paraProperty->getAlignment ();
00843
00844 if (align != MSWrite::Alignment::Left)
00845 {
00846 output += "<FLOW align=\"";
00847 switch (align)
00848 {
00849
00850
00851
00852 case MSWrite::Alignment::Centre:
00853 output += "center";
00854 break;
00855 case MSWrite::Alignment::Right:
00856 output += "right";
00857 break;
00858 case MSWrite::Alignment::Justify:
00859 output += "justify";
00860 break;
00861 }
00862 output += "\"/>";
00863 }
00864
00865 double indentFirst = Twip2Point (double (paraProperty->getLeftIndentFirstLine ()));
00866 double indentLeft = Twip2Point (double (paraProperty->getLeftIndent ()));
00867 double indentRight = Twip2Point (double (paraProperty->getRightIndent ()));
00868
00869 #if 0
00870 debug ("raw indent: first: %i left: %i right: %i\n",
00871 indentFirst, indentLeft, indentRight);
00872 #endif
00873
00874 if (m_paraIsImage && m_objectHorizOffset)
00875 {
00876 if (align == MSWrite::Align::Center)
00877 {
00878
00879 kdDebug (30509) << "ignoring image offset with centred image" << endl;
00880 m_objectHorizOffset = 0;
00881 }
00882 else
00883 {
00884
00885
00886
00887 if (m_simulateImageOffset && m_objectHorizOffset > indentLeft)
00888 {
00889 kdDebug (30509) << "image is further away from left margin by itself, rather than using indentLeft ("
00890 << m_objectHorizOffset << " > " << indentLeft << ")" << endl;
00891 indentLeft = m_objectHorizOffset;
00892 }
00893 }
00894 }
00895
00896
00897 if (indentFirst || indentLeft || indentRight)
00898 {
00899 output += "<INDENTS";
00900 if (indentFirst) output += " first=\"" + QString::number (indentFirst) + "\"";
00901 if (indentLeft) output += " left=\"" + QString::number (indentLeft) + "\"";
00902 if (indentRight) output += " right=\"" + QString::number (indentRight) + "\"";
00903 output += "/>";
00904 }
00905
00906 MSWrite::Word lineSpacing = paraProperty->getLineSpacing ();
00907
00908 if (lineSpacing != MSWrite::LineSpacing::Single)
00909 {
00910 #if 1
00911 output += "<LINESPACING type=\"atleast\" spacingvalue=\"" + QString::number (Twip2Point (lineSpacing)) + "\"/>";
00912 #else // old way
00913 output += "<LINESPACING type=\"";
00914 switch (lineSpacing)
00915 {
00916
00917
00918 case MSWrite::LineSpacing::OneAndAHalf:
00919 output += "oneandhalf";
00920 break;
00921 case MSWrite::LineSpacing::Double:
00922 output += "double";
00923 break;
00924 default:
00925 kdWarning (30509) << "non-\"standard\" linespacing value: " << lineSpacing << endl;
00926 output += "atleast\" ";
00927 output += "spacingvalue=\"";
00928 output += QString::number (Twip2Point (lineSpacing));
00929 break;
00930 }
00931 output += "\"/>";
00932 #endif
00933 }
00934
00935
00936
00937 if (m_simulateLineSpacing)
00938 {
00939
00940
00941
00942 if (lineSpacing != MSWrite::LineSpacing::Single)
00943 {
00944 output += "<OFFSETS before=\"";
00945
00946 int amount = 0;
00947 switch (lineSpacing)
00948 {
00949
00950
00951 case MSWrite::LineSpacing::OneAndAHalf:
00952 amount = 7;
00953 break;
00954 case MSWrite::LineSpacing::Double:
00955 amount = 14;
00956 break;
00957 default:
00958 kdWarning (30509) << "unknown linespacing value: " << lineSpacing << endl;
00959 break;
00960 }
00961
00962
00963 amount -= m_lineSpacingFromAbove;
00964 if (amount <= 0) amount = 0;
00965
00966 output += QString::number (amount);
00967 output += "\" />";
00968 }
00969
00970
00971 switch (lineSpacing)
00972 {
00973 case MSWrite::LineSpacing::Single:
00974 m_lineSpacingFromAbove = 0;
00975 break;
00976 case MSWrite::LineSpacing::OneAndAHalf:
00977 m_lineSpacingFromAbove = 7;
00978 break;
00979 case MSWrite::LineSpacing::Double:
00980 m_lineSpacingFromAbove = 14;
00981 break;
00982 default:
00983 m_lineSpacingFromAbove = 0;
00984 break;
00985 }
00986 }
00987
00988 if (m_pageBreak)
00989 {
00990 #if 0
00991 debug ("\tpagebrk: output: offset: %i chars in paragraph: %i\n",
00992 m_pageBreakOffset, m_charInfoCountStart + m_charInfoCountLen);
00993 #endif
00994
00995
00996 if (m_pageBreakOffset == 0 && m_charInfoCountStart + m_charInfoCountLen > 0)
00997 {
00998 output += "<PAGEBREAKING hardFrameBreak=\"true\"/>";
00999 m_needAnotherParagraph = false;
01000 }
01001
01002 else
01003 {
01004 output += "<PAGEBREAKING hardFrameBreakAfter=\"true\"/>";
01005 m_needAnotherParagraph = true;
01006 }
01007
01008 m_pageBreak = false;
01009 }
01010 else
01011 m_needAnotherParagraph = false;
01012
01013
01014 for (int i = 0; i < paraProperty->getNumTabulator (); i++)
01015 {
01016 const MSWrite::FormatParaPropertyTabulator *tab = paraProperty->getTabulator (i);
01017 if (tab->getIsDummy ()) break;
01018
01019 output += "<TABULATOR";
01020
01021 if (tab->getIsDecimal ())
01022 output += " type=\"3\" alignchar=\".\"";
01023 else
01024 output += " type=\"0\"";
01025
01026 output += " ptpos=\"" + QString::number (Twip2Point (double (tab->getIndent ()))) + "\"/>";
01027
01028
01029
01030 }
01031
01032 output += "</LAYOUT>";
01033 #ifdef DEBUG_XML_OUTPUT
01034 output += "\n";
01035 #endif
01036
01037 output += "<FORMATS>";
01038 #ifdef DEBUG_XML_OUTPUT
01039 output += "\n";
01040 #endif
01041
01042 output += m_formatOutput; m_formatOutput = "";
01043 output += "</FORMATS>";
01044 #ifdef DEBUG_XML_OUTPUT
01045 output += "\n";
01046 #endif
01047
01048 output += "</PARAGRAPH>";
01049 #ifdef DEBUG_XML_OUTPUT
01050 output += "\n";
01051 #endif
01052
01053 if (!writeTextInternal (output)) return false;
01054
01055 return true;
01056 }
01057
01058 bool writeCharInfoBegin (const MSWrite::FormatCharProperty * )
01059 {
01060
01061
01062 return true;
01063 }
01064
01065
01066 bool writeCharInfoEnd (const MSWrite::FormatCharProperty *charProperty,
01067 const bool = false)
01068 {
01069
01070
01071
01072 m_formatOutput += "<FORMAT id=\"";
01073 if (charProperty->getIsPageNumber ())
01074 m_formatOutput += "4";
01075 else
01076 m_formatOutput += "1";
01077 m_formatOutput += "\" ";
01078
01079 m_formatOutput += "pos=\""; m_formatOutput += QString::number (m_charInfoCountStart); m_formatOutput += "\" ";
01080 m_formatOutput += "len=\""; m_formatOutput += QString::number (m_charInfoCountLen); m_formatOutput += "\">";
01081
01082 m_charInfoCountStart += m_charInfoCountLen;
01083 m_charInfoCountLen = 0;
01084
01085 if (charProperty->getIsPageNumber ())
01086 {
01087 m_formatOutput += "<VARIABLE>";
01088 m_formatOutput += "<TYPE key=\"NUMBER\" type=\"4\"/>";
01089 m_formatOutput += "<PGNUM subtype=\"0\" value=\"1\"/>";
01090 m_formatOutput += "</VARIABLE>";
01091 }
01092
01093 m_formatOutput += "<FONT name=\"";
01094 m_formatOutput += (const char *) (charProperty->getFont ()->getName ());
01095 m_formatOutput += "\"/>";
01096 m_formatOutput += "<SIZE value=\"";
01097 m_formatOutput += QString::number (charProperty->getFontSize ());
01098 m_formatOutput += "\"/>";
01099
01100 if (charProperty->getIsBold ())
01101 m_formatOutput += "<WEIGHT value=\"75\"/>";
01102
01103
01104
01105 if (charProperty->getIsItalic ())
01106 m_formatOutput += "<ITALIC value=\"1\"/>";
01107
01108
01109
01110 if (charProperty->getIsUnderlined ())
01111 m_formatOutput += "<UNDERLINE value=\"1\"/>";
01112
01113
01114
01115
01116
01117 if (charProperty->getIsSubscript ())
01118 m_formatOutput += "<VERTALIGN value=\"1\"/>";
01119 else if (charProperty->getIsSuperscript ())
01120 m_formatOutput += "<VERTALIGN value=\"2\"/>";
01121
01122
01123
01124 m_formatOutput += "</FORMAT>";
01125
01126 return true;
01127 }
01128
01129 bool writeBinary (const MSWrite::Byte *buffer, const MSWrite::DWord length)
01130 {
01131 kdDebug (30509) << "writeBinary()" << endl;
01132
01133
01134 if (!m_paraIsImage)
01135 return true;
01136
01137 WRIObject &obj = *m_objectList.begin (false);
01138
01139 if (!obj.m_data)
01140 ErrorAndQuit (MSWrite::Error::InternalError, "object data not initialised\n");
01141
01142
01143 if (obj.m_dataUpto + length > obj.m_dataLength)
01144 {
01145 kdDebug (30509) << "object image overrun: "
01146 << obj.m_dataUpto << " + " << length
01147 << " > " << obj.m_dataLength << endl;
01148 ErrorAndQuit (MSWrite::Error::InternalError, "object image overrun\n");
01149 }
01150
01151 memcpy (obj.m_data + obj.m_dataUpto, buffer, length);
01152 obj.m_dataUpto += length;
01153
01154 return true;
01155 }
01156
01157
01158
01159
01160
01161
01162
01163 bool writeText (const MSWrite::Byte *string)
01164 {
01165
01166 QString strUnicode;
01167
01168
01169 if (m_codec)
01170 {
01171
01172 strUnicode = m_decoder->toUnicode ((const char *) string, strlen ((const char *) string));
01173 }
01174 else
01175 {
01176
01177
01178 strUnicode = (const char *) string;
01179 }
01180
01181
01182 m_charInfoCountLen += strUnicode.length ();
01183
01184
01185 strUnicode.replace ('&', "&");
01186 strUnicode.replace ('<', "<");
01187 strUnicode.replace ('>', ">");
01188 strUnicode.replace ('\"', """);
01189 strUnicode.replace ('\'', "'");
01190
01191 return writeTextInternal (strUnicode);
01192 }
01193
01194 bool writeTextInternal (const MSWrite::Byte *str)
01195 {
01196 #if 0
01197 return textWrite_lowLevel (QString (str));
01198 #else // while this is code duplication (of below func), this ensures that no
01199
01200 if (m_delayOutput)
01201 {
01202
01203 m_heldOutput += (const char *) str;
01204 return true;
01205 }
01206 else
01207 {
01208 int strLength = strlen ((const char *) str);
01209
01210 if (m_outfile->writeBlock ((const char *) str, strLength) != strLength)
01211 {
01212 ErrorAndQuit (MSWrite::Error::FileError, "could not write to maindoc.xml\n");
01213 }
01214 else
01215 return true;
01216 }
01217 #endif
01218 }
01219
01220 bool writeTextInternal (const QString &str)
01221 {
01222 if (m_delayOutput)
01223 {
01224
01225 m_heldOutput += str;
01226 return true;
01227 }
01228 else
01229 {
01230 QCString strUtf8 = str.utf8 ();
01231 int strLength = strUtf8.length ();
01232
01233 if (m_outfile->writeBlock (strUtf8, strLength) != strLength)
01234 {
01235 ErrorAndQuit (MSWrite::Error::FileError, "could not write to maindoc.xml (2)\n");
01236 }
01237 else
01238 return true;
01239 }
01240 }
01241
01242 bool writeTextInternal (const int num)
01243 {
01244 return writeTextInternal (QString::number (num));
01245 }
01246
01247 bool writeTextInternal (const char *format, ...)
01248 {
01249 va_list list;
01250 va_start (list, format);
01251
01252 bool ret;
01253
01254
01255
01256
01257
01258 char string [1024];
01259
01260 vsnprintf (string, sizeof (string) - 1, format, list);
01261 string [sizeof (string) - 1] = '\0';
01262
01263 ret = writeTextInternal ((const MSWrite::Byte *) string);
01264
01265 va_end (list);
01266 return ret;
01267 }
01268
01269
01270
01271
01272 bool writePageNew (const int)
01273 {
01274 return true;
01275 }
01276
01277
01278 bool writePageBreak (void)
01279 {
01280
01281 m_pageBreak = true;
01282 m_pageBreakOffset = m_charInfoCountStart + m_charInfoCountLen;
01283
01284 return true;
01285 }
01286
01287
01288 bool writePageNumber (void)
01289 {
01290 m_charInfoCountLen++;
01291 return writeTextInternal ("#");
01292 }
01293
01294 bool writeCarriageReturn (void)
01295 {
01296 return true;
01297 }
01298
01299
01300
01301 bool writeNewLine (const bool endOfParagraph)
01302 {
01303 if (!endOfParagraph)
01304 {
01305 m_charInfoCountLen++;
01306 return writeTextInternal ("\n");
01307 }
01308 else
01309 return true;
01310 }
01311
01312
01313 bool writeOptionalHyphen (void)
01314 {
01315 m_charInfoCountLen++;
01316 return writeTextInternal ("\xC2\xAD");
01317 }
01318
01319 void setKOfficeLink (MSWriteImport *kofficeLink)
01320 {
01321 m_koLink = kofficeLink;
01322 }
01323
01324 void sigProgress (const int value)
01325 {
01326 m_koLink->sigProgress (value);
01327 }
01328 };
01329
01330
01331
01332
01333
01334
01335
01336 MSWriteImport::MSWriteImport (KoFilter *, const char *, const QStringList &)
01337 : m_device (NULL), m_parser (NULL), m_generator (NULL)
01338 {
01339 }
01340
01341 MSWriteImport::~MSWriteImport ()
01342 {
01343 delete m_generator;
01344 delete m_parser;
01345 delete m_device;
01346 }
01347
01348 KoFilter::ConversionStatus MSWriteImport::convert (const QCString &from, const QCString &to)
01349 {
01350 kdDebug (30509) << "MSWriteImport $Date: 2006-02-12 19:28:12 +0100 (dim, 12 fév 2006) $ using LibMSWrite "
01351 << MSWrite::Version << endl;
01352
01353 if (to != "application/x-kword" || from != "application/x-mswrite")
01354 {
01355 kdError (30509) << "Internal error! Filter not implemented?" << endl;
01356 return KoFilter::NotImplemented;
01357 }
01358
01359 #if 0
01360
01361 MSWriteImportDialog dialog;
01362
01363
01364
01365
01366
01367
01368
01369
01370 debug ("DIALOG EXEC!!!\n");
01371 if (!dialog.exec ())
01372 {
01373 error ("Dialog was aborted! Aborting filter!\n");
01374 return KoFilter::UserCancelled;
01375 }
01376
01377 debug ("DIALOG GET!!!\n");
01378
01379
01380 m_codec = dialog.getCodec ();
01381 m_simulateLinespacing = dialog.getSimulateLinespacing ();
01382 m_simulateImageOffset = dialog.getSimulateImageOffset ();
01383 debug ("Import options: simulateLinespacing: %i\tsimulateImageOffset: %i\n",
01384 m_simulateLinespacing, m_simulateImageOffset);
01385
01386 debug ("DIALOG DELETE\n");
01387
01388 #endif
01389
01390
01391 m_device = new WRIDevice;
01392 if (!m_device)
01393 {
01394 kdError (30509) << "Could not allocate memory for device" << endl;
01395 return KoFilter::OutOfMemory;
01396 }
01397
01398
01399 if (!m_device->openFile (QFile::encodeName (m_chain->inputFile ())))
01400 {
01401 kdError (30509) << "Could not open \'" << m_chain->inputFile () << "\'" << endl;
01402 return KoFilter::FileNotFound;
01403 }
01404
01405
01406
01407 m_parser = new MSWrite::InternalParser;
01408 if (!m_parser)
01409 {
01410 kdError (30509) << "Could not allocate memory for parser" << endl;
01411 return KoFilter::OutOfMemory;
01412 }
01413
01414
01415 m_parser->setDevice (m_device);
01416
01417
01418
01419 m_generator = new KWordGenerator;
01420 if (!m_generator)
01421 {
01422 kdError (30509) << "Could not allocate memory for generator" << endl;
01423 return KoFilter::OutOfMemory;
01424 }
01425
01426
01427 m_generator->setDevice (m_device);
01428
01429
01430 m_generator->setFilterChain (m_chain);
01431
01432
01433 m_generator->setKOfficeLink (this);
01434
01435
01436
01437 m_parser->setGenerator (m_generator);
01438
01439
01440
01441 if (!m_parser->parse ())
01442 {
01443
01444
01445 int errorCode = m_device->bad ();
01446 switch (errorCode)
01447 {
01448 case MSWrite::Error::Ok:
01449 kdDebug (30509) << "Error::Ok but aborted???" << endl;
01450 return KoFilter::InternalError;
01451
01452 case MSWrite::Error::Warn:
01453 kdDebug (30509) << "Error::Warn" << endl;
01454 return KoFilter::InternalError;
01455
01456 case MSWrite::Error::InvalidFormat:
01457 kdDebug (30509) << "Error::InvalidFormat" << endl;
01458 return KoFilter::WrongFormat;
01459
01460 case MSWrite::Error::OutOfMemory:
01461 kdDebug (30509) << "Error::OutOfMemory" << endl;
01462 return KoFilter::OutOfMemory;
01463
01464 case MSWrite::Error::InternalError:
01465 kdDebug (30509) << "Error::InternalError" << endl;
01466 return KoFilter::InternalError;
01467
01468 case MSWrite::Error::Unsupported:
01469 kdDebug (30509) << "Error::Unsupported" << endl;
01470 return KoFilter::InternalError;
01471
01472 case MSWrite::Error::FileError:
01473 kdDebug (30509) << "Error::FileError" << endl;
01474 return KoFilter::StupidError;
01475 }
01476
01477 kdWarning (30509) << "Unknown error: " << errorCode << endl;
01478 return KoFilter::StupidError;
01479 }
01480
01481 return KoFilter::OK;
01482 }
01483
01484 #include <mswriteimport.moc>