00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <limits.h>
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023
00024 #include <qbuffer.h>
00025 #include <qcstring.h>
00026 #include <qfile.h>
00027 #include <qfont.h>
00028 #include <qimage.h>
00029 #include <qtextcodec.h>
00030 #include <qvaluelist.h>
00031 #include <qvaluestack.h>
00032
00033 #include <kdebug.h>
00034 #include <kgenericfactory.h>
00035
00036 #include <KoFilterChain.h>
00037 #include <kowmfpaint.h>
00038
00039 #include <KWEFStructures.h>
00040 #include <KWEFBaseWorker.h>
00041 #include <KWEFKWordLeader.h>
00042
00043 #include "libmswrite.h"
00044
00045 #include "mswriteexport.h"
00046
00047
00048 class MSWriteExportFactory : KGenericFactory <MSWriteExport, KoFilter>
00049 {
00050 public:
00051 MSWriteExportFactory () : KGenericFactory <MSWriteExport, KoFilter> ("kwordmswriteexport")
00052 {
00053 }
00054
00055 protected:
00056 virtual void setupTranslations (void)
00057 {
00058 KGlobal::locale()->insertCatalogue ("kofficefilters");
00059 }
00060 };
00061
00062 K_EXPORT_COMPONENT_FACTORY (libmswriteexport, MSWriteExportFactory ())
00063
00064
00065 class WRIDevice : public MSWrite::Device
00066 {
00067 private:
00068 FILE *m_outfp;
00069 long m_outfp_pos, m_outfp_eof;
00070
00071 public:
00072 WRIDevice () : m_outfp (NULL), m_outfp_pos (0), m_outfp_eof (0)
00073 {
00074 }
00075
00076 virtual ~WRIDevice ()
00077 {
00078 closeFile ();
00079 }
00080
00081 bool openFile (const char *fileName)
00082 {
00083 m_outfp = fopen (fileName, "wb");
00084 if (!m_outfp)
00085 {
00086 error (MSWrite::Error::FileError, "could not open file for writing\n");
00087 return false;
00088 }
00089
00090 return true;
00091 }
00092
00093 bool closeFile (void)
00094 {
00095 if (m_outfp)
00096 {
00097 if (fclose (m_outfp))
00098 {
00099 error (MSWrite::Error::FileError, "could not close output file\n");
00100 return false;
00101 }
00102
00103 m_outfp = NULL;
00104 }
00105
00106 return true;
00107 }
00108
00109 bool read (MSWrite::Byte *, const MSWrite::DWord)
00110 {
00111 error (MSWrite::Error::InternalError, "reading from an output file?\n");
00112 return false;
00113 }
00114
00115 bool write (const MSWrite::Byte *buf, const MSWrite::DWord numBytes)
00116 {
00117 size_t cwrite = fwrite (buf, 1, numBytes, m_outfp);
00118 if (cwrite != numBytes)
00119 {
00120 error (MSWrite::Error::FileError, "could not write to output file\n");
00121 return false;
00122 }
00123
00124
00125 m_outfp_pos += numBytes;
00126 if (m_outfp_pos > m_outfp_eof)
00127 m_outfp_eof = m_outfp_pos;
00128
00129 return true;
00130 }
00131
00132 bool seek (const long offset, const int whence)
00133 {
00134 long absloc;
00135 switch (whence)
00136 {
00137 case SEEK_SET:
00138 absloc = offset;
00139 break;
00140 case SEEK_CUR:
00141 absloc = m_outfp_pos + offset;
00142 break;
00143 case SEEK_END:
00144 absloc = m_outfp_eof + offset;
00145 break;
00146 default:
00147 error (MSWrite::Error::InternalError, "invalid whence passed to WRIDevice::seek\n");
00148 return false;
00149 }
00150
00151 if (absloc > m_outfp_eof)
00152 {
00153 kdDebug (30509) << "Want to seek to " << absloc
00154 << " but EOF is at " << m_outfp_eof
00155 << "; so writing " << absloc - m_outfp_eof
00156 << " zeros" << endl;
00157
00158 if (fseek (m_outfp, m_outfp_eof, SEEK_SET))
00159 {
00160 error (MSWrite::Error::FileError,
00161 "could not seek to EOF in output file\n");
00162 return false;
00163 }
00164
00165 MSWrite::Byte *zero = new MSWrite::Byte [absloc - m_outfp_eof];
00166 if (!zero)
00167 {
00168 error (MSWrite::Error::OutOfMemory,
00169 "could not allocate memory for zeros\n");
00170 return false;
00171 }
00172 memset (zero, 0, absloc - m_outfp_eof);
00173 if (!write (zero, absloc - m_outfp_eof)) return false;
00174 delete [] zero;
00175
00176 m_outfp_eof = absloc;
00177 m_outfp_pos = absloc;
00178 return true;
00179 }
00180 else
00181 {
00182 if (fseek (m_outfp, offset, whence) == 0)
00183 {
00184 m_outfp_pos = absloc;
00185 return true;
00186 }
00187 else
00188 {
00189 error (MSWrite::Error::FileError, "could not seek output file\n");
00190 return false;
00191 }
00192 }
00193 }
00194
00195 long tell (void)
00196 {
00197 return ftell (m_outfp);
00198 }
00199
00200 void debug (const char *s)
00201 {
00202 kdDebug (30509) << s;
00203 }
00204 void debug (const int i)
00205 {
00206 kdDebug (30509) << i;
00207 }
00208 void error (const int errorCode, const char *message,
00209 const char * = "", const int = 0,
00210 MSWrite::DWord = MSWrite::Device::NoToken)
00211 {
00212 if (errorCode == MSWrite::Error::Warn)
00213 kdWarning (30509) << message;
00214 else
00215 {
00216 m_error = errorCode;
00217 kdError (30509) << message;
00218 }
00219 }
00220 };
00221
00222
00223 class KWordMSWriteWorker : public KWEFBaseWorker
00224 {
00225 private:
00226 WRIDevice *m_device;
00227 MSWrite::InternalGenerator *m_generator;
00228
00229 MSWrite::PageLayout m_pageLayout;
00230 MSWrite::Word m_pageHeight, m_pageWidth,
00231 m_topMargin, m_leftMargin, m_bottomMargin, m_rightMargin;
00232 MSWrite::Word m_pageNumberStart;
00233
00234
00235 QTextCodec *m_codec;
00236 QTextEncoder *m_encoder;
00237
00238 QValueList <HeaderData> m_headerData;
00239 QValueList <FooterData> m_footerData;
00240
00241 int m_headerType, m_footerType;
00242 bool m_hasHeader, m_isHeaderOnFirstPage;
00243 bool m_hasFooter, m_isFooterOnFirstPage;
00244
00245 enum inWhatPossiblities
00246 {
00247 Nothing,
00248 Header,
00249 Footer,
00250 Body
00251 } m_inWhat;
00252
00253 public:
00254 KWordMSWriteWorker () : m_device (NULL), m_generator (NULL),
00255 m_pageHeight (0xFFFF), m_pageWidth (0xFFFF),
00256 m_topMargin (0xFFFF), m_leftMargin (0xFFFF),
00257 m_bottomMargin (0xFFFF), m_rightMargin (0xFFFF),
00258 m_encoder (NULL),
00259 m_hasHeader (false), m_hasFooter (false),
00260 m_inWhat (Nothing)
00261 {
00262
00263 m_codec = QTextCodec::codecForName ("CP 1252");
00264
00265 if (m_codec)
00266 m_encoder = m_codec->makeEncoder();
00267 else
00268 kdWarning (30509) << "Cannot convert to Win Charset!" << endl;
00269
00270 m_device = new WRIDevice;
00271 if (!m_device)
00272 {
00273 kdError (30509) << "Could not allocate memory for Device" << endl;
00274 return;
00275 }
00276
00277 m_generator = new MSWrite::InternalGenerator;
00278 if (!m_generator)
00279 {
00280 m_device->error (MSWrite::Error::OutOfMemory, "could not allocate memory for InternalGenerator\n");
00281 return;
00282 }
00283
00284 m_generator->setDevice (m_device);
00285 }
00286
00287 virtual ~KWordMSWriteWorker ()
00288 {
00289 delete m_generator;
00290 delete m_device;
00291 delete m_encoder;
00292 }
00293
00294 int getError (void) const
00295 {
00296 return m_device->bad ();
00297 }
00298
00299 bool doOpenFile (const QString &outFileName, const QString &)
00300 {
00301
00302 if (!m_device || !m_generator)
00303 return false;
00304
00305 if (!m_device->openFile (QFile::encodeName (outFileName))) return false;
00306
00307 return true;
00308 }
00309
00310 bool doCloseFile (void)
00311 {
00312 if (!m_device->closeFile ()) return false;
00313 return true;
00314 }
00315
00316 bool doOpenDocument (void)
00317 {
00318 kdDebug (30509) << "doOpenDocument ()" << endl;
00319
00320
00321
00322
00323
00324
00325
00326
00327 return true;
00328 }
00329
00330 bool doTrulyOpenDocument (void)
00331 {
00332
00333
00334 m_pageLayout.setPageHeight (m_pageHeight);
00335 m_pageLayout.setPageWidth (m_pageWidth);
00336 m_pageLayout.setPageNumberStart (m_pageNumberStart);
00337 m_pageLayout.setTopMargin (m_topMargin);
00338 m_pageLayout.setLeftMargin (m_leftMargin);
00339 m_pageLayout.setTextHeight (m_pageHeight - m_topMargin - m_bottomMargin);
00340 m_pageLayout.setTextWidth (m_pageWidth - m_leftMargin - m_rightMargin);
00341
00342
00343
00344
00345
00346 if (!m_generator->writeDocumentBegin (MSWrite::Format::Write_3_0,
00347 &m_pageLayout)) return false;
00348
00349 return true;
00350 }
00351
00352 bool doCloseDocument (void)
00353 {
00354 kdDebug (30509) << "doCloseDocument ()" << endl;
00355
00356 if (!m_generator->writeDocumentEnd (MSWrite::Format::Write_3_0,
00357 &m_pageLayout)) return false;
00358
00359 return true;
00360 }
00361
00362 bool doFullPaperFormat (const int format,
00363 const double width, const double height,
00364 const int orientation)
00365 {
00366 kdDebug (30509) << "doFullPaperFormat ("
00367 << format << ", "
00368 << width << ", "
00369 << height << ", "
00370 << orientation << ")" << endl;
00371
00372
00373
00374 m_pageHeight = MSWrite::Word (Point2Twip (height));
00375 m_pageWidth = MSWrite::Word (Point2Twip (width));
00376
00377 return true;
00378 }
00379
00380 bool doFullPaperBorders (const double top, const double left,
00381 const double bottom, const double right)
00382 {
00383 kdDebug (30509) << "doFullPaperBorders ("
00384 << top << ", "
00385 << left << ", "
00386 << bottom << ", "
00387 << right << ")" << endl;
00388
00389 m_topMargin = MSWrite::Word (Point2Twip (top));
00390 m_leftMargin = MSWrite::Word (Point2Twip (left));
00391 m_bottomMargin = MSWrite::Word (Point2Twip (bottom));
00392 m_rightMargin = MSWrite::Word (Point2Twip (right));
00393
00394 return true;
00395 }
00396
00397 bool doVariableSettings (const VariableSettingsData &varSettings)
00398 {
00399 m_pageNumberStart = MSWrite::Word (varSettings.startingPageNumber);
00400
00401 kdDebug (30509) << "doVariableSettings pageNumberStart="
00402 << m_pageNumberStart << endl;
00403 return true;
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 bool doPageInfo (int headerType, int footerType)
00417 {
00418 kdDebug (30509) << "doPageInfo (headerType=" << headerType
00419 << ", footerType=" << footerType
00420 << ")" << endl;
00421
00422 m_headerType = headerType;
00423 switch (headerType)
00424 {
00425 case 0:
00426 case 3:
00427 m_isHeaderOnFirstPage = true;
00428 break;
00429 case 1:
00430 case 2:
00431 m_isHeaderOnFirstPage = false;
00432 break;
00433 default:
00434 kdWarning (30509) << "Unknown headerType: " << headerType << endl;
00435 m_isHeaderOnFirstPage = false;
00436 break;
00437 }
00438
00439 m_footerType = footerType;
00440 switch (footerType)
00441 {
00442 case 0:
00443 case 3:
00444 m_isFooterOnFirstPage = true;
00445 break;
00446 case 1:
00447 case 2:
00448 m_isFooterOnFirstPage = false;
00449 break;
00450 default:
00451 kdWarning (30590) << "Unknown footerType: " << footerType << endl;
00452 m_isFooterOnFirstPage = false;
00453 break;
00454 }
00455
00456 return true;
00457 }
00458
00459 bool isParaListEmpty (const QValueList <ParaData> ¶)
00460 {
00461 if (para.count () == 1)
00462 {
00463 if (para.first ().text.isEmpty ())
00464 return true;
00465 }
00466
00467 return false;
00468 }
00469
00470 bool doHeader (const HeaderData &header)
00471 {
00472 kdDebug (30509) << "doHeader (header.page=" << header.page << ")" << endl;
00473
00474 if (isParaListEmpty (header.para))
00475 {
00476 kdDebug (30509) << "\tEmpty, ignoring" << endl;
00477 return true;
00478 }
00479
00480 #if 0
00481 switch (m_headerType)
00482 {
00483 case 0:
00484 if (header.page != HeaderData::PAGE_ALL)
00485 return true;
00486 break;
00487 case 3:
00488 if (header.page != HeaderData::PAGE_ODD &&
00489 header.page != HeaderData::PAGE_EVEN)
00490 return true;
00491 break;
00492 case 1:
00493
00494 break;
00495 case 2:
00496 if (header.page != HeaderData::PAGE_FIRST &&
00497 header.page != HeaderData::PAGE_ODD)
00498 return true;
00499 break;
00500 }
00501 #endif
00502
00503 m_hasHeader = true;
00504 m_headerData.push_back (header);
00505 return true;
00506 }
00507
00508 bool doFooter (const FooterData &footer)
00509 {
00510 kdDebug (30509) << "doFooter (footer.page=" << footer.page << ")" << endl;
00511
00512 if (isParaListEmpty (footer.para))
00513 {
00514 kdDebug (30509) << "\tEmpty, ignoring" << endl;
00515 return true;
00516 }
00517
00518 #if 0
00519 switch (m_footerType)
00520 {
00521 case 0:
00522 if (footer.page != FooterData::PAGE_ALL)
00523 return true;
00524 break;
00525 case 3:
00526 if (footer.page != FooterData::PAGE_ODD &&
00527 footer.page != FooterData::PAGE_EVEN)
00528 return true;
00529 break;
00530 case 1:
00531
00532 break;
00533 case 2:
00534 if (footer.page != FooterData::PAGE_FIRST &&
00535 footer.page != FooterData::PAGE_ODD)
00536 return true;
00537 break;
00538 }
00539 #endif
00540
00541 m_hasFooter = true;
00542 m_footerData.push_back (footer);
00543 return true;
00544 }
00545
00546 bool doOpenBody (void)
00547 {
00548 kdDebug (30509) << "doOpenBody ()" << endl;
00549
00550
00551
00552
00553 if (!doTrulyOpenDocument ()) return false;
00554
00555
00556
00557
00558
00559
00560 bool wroteFooter = false;
00561 m_inWhat = Footer;
00562
00563 for (QValueList <FooterData>::Iterator it = m_footerData.begin ();
00564 it != m_footerData.end ();
00565 it++)
00566 {
00567 if ((*it).page != FooterData::PAGE_FIRST)
00568 {
00569 if (!wroteFooter)
00570 {
00571 if (!m_generator->writeFooterBegin ()) return false;
00572 wroteFooter = true;
00573 }
00574
00575 if (!doFullParagraphList ((*it).para)) return false;
00576 it = --m_footerData.erase (it);
00577 }
00578 }
00579 if (wroteFooter)
00580 if (!m_generator->writeFooterEnd ()) return false;
00581
00582 bool wroteHeader = false;
00583 m_inWhat = Header;
00584
00585 for (QValueList <HeaderData>::Iterator it = m_headerData.begin ();
00586 it != m_headerData.end ();
00587 it++)
00588 {
00589 if ((*it).page != HeaderData::PAGE_FIRST)
00590 {
00591 if (!wroteHeader)
00592 {
00593 if (!m_generator->writeHeaderBegin ()) return false;
00594 wroteHeader = true;
00595 }
00596
00597 if (!doFullParagraphList ((*it).para)) return false;
00598 it = --m_headerData.erase (it);
00599 }
00600 }
00601 if (wroteHeader)
00602 if (!m_generator->writeHeaderEnd ()) return false;
00603
00604
00605
00606
00607
00608
00609 m_inWhat = Body;
00610 if (!m_generator->writeBodyBegin ()) return false;
00611
00612
00613 if (!m_generator->writePageNew ()) return false;
00614
00615 #if 0
00616
00617 for (QValueList <HeaderData>::Iterator it = m_headerData.begin ();
00618 it != m_headerData.end ();
00619 it++)
00620 {
00621 kdDebug (30509) << "BODY START ADDING HEADER: " << (*it).page << endl;
00622 if (!doFullParagraphList ((*it).para)) return false;
00623 it = --m_headerData.erase (it);
00624 }
00625
00626
00627 for (QValueList <FooterData>::Iterator it = m_footerData.begin ();
00628 it != m_footerData.end ();
00629 it++)
00630 {
00631 kdDebug (30509) << "BODY START ADDING FOOTER: " << (*it).page << endl;
00632 if (!doFullParagraphList ((*it).para)) return false;
00633 it = --m_footerData.erase (it);
00634 }
00635 #endif
00636
00637 return true;
00638 }
00639
00640 bool doCloseBody (void)
00641 {
00642 kdDebug (30509) << "doCloseBody ()" << endl;
00643
00644 if (!m_generator->writeBodyEnd ()) return false;
00645
00646 return true;
00647 }
00648
00649
00650
00651 class QBufferDevice : public MSWrite::Device
00652 {
00653 private:
00654 QBuffer *m_buffer;
00655
00656 public:
00657 QBufferDevice (QBuffer *buffer)
00658 {
00659 m_buffer = buffer;
00660 }
00661
00662 bool read (MSWrite::Byte *buf, const MSWrite::DWord numBytes)
00663 {
00664 if (m_buffer->readBlock ((char *) buf, (Q_ULONG) numBytes) != Q_LONG (numBytes))
00665 {
00666 error (MSWrite::Error::FileError, "could not read from QBuffer (not really a FileError)\n");
00667 return false;
00668 }
00669 else
00670 return true;
00671 }
00672
00673 bool write (const MSWrite::Byte *buf, const MSWrite::DWord numBytes)
00674 {
00675 if (m_buffer->writeBlock ((char *) buf, (Q_ULONG) numBytes) != Q_LONG (numBytes))
00676 {
00677 error (MSWrite::Error::FileError, "could not write to QBuffer (not really a FileError)\n");
00678 return false;
00679 }
00680 else
00681 return true;
00682 }
00683
00684
00685
00686 bool seek (const long offset, const int whence)
00687 {
00688 long absoffset;
00689 switch (whence)
00690 {
00691 case SEEK_SET:
00692 absoffset = offset;
00693 break;
00694 case SEEK_CUR:
00695 absoffset = m_buffer->at () + offset;
00696 break;
00697 case SEEK_END:
00698 absoffset = m_buffer->size () + offset;
00699 break;
00700 default:
00701 error (MSWrite::Error::InternalError, "unknown seek\n");
00702 return false;
00703 }
00704
00705 if (absoffset > long (m_buffer->size ()))
00706 {
00707 error (MSWrite::Error::InternalError, "seek past EOF unimplemented\n");
00708 return false;
00709 }
00710
00711 if (!m_buffer->at (absoffset))
00712 {
00713 error (MSWrite::Error::FileError, "QBuffer could not seek (not really a FileError)\n");
00714 return false;
00715 }
00716
00717 return true;
00718 }
00719
00720 long tell (void)
00721 {
00722 return long (m_buffer->at ());
00723 }
00724
00725 void debug (const char *s)
00726 {
00727 kdDebug (30509) << s;
00728 }
00729 void debug (const int i)
00730 {
00731 kdDebug (30509) << i;
00732 }
00733
00734 void error (const int errorCode, const char *message,
00735 const char * = "", const int = 0,
00736 MSWrite::DWord = MSWrite::Device::NoToken)
00737 {
00738 if (errorCode == MSWrite::Error::Warn)
00739 kdWarning (30509) << message;
00740 else
00741 {
00742 m_error = errorCode;
00743 kdError (30509) << message;
00744 }
00745 }
00746 };
00747
00748 class WMFRecord : public MSWrite::NeedsDevice
00749 {
00750 public:
00751 static const int s_size = 6;
00752
00753 protected:
00754 MSWrite::Byte m_data [s_size];
00755
00756 MSWrite::DWord m_size;
00757 MSWrite::Word m_function;
00758
00759 MSWrite::Short m_args [100];
00760 int m_argUpto;
00761
00762 public:
00763 WMFRecord () : m_argUpto (0)
00764 {
00765 }
00766
00767 WMFRecord (const MSWrite::DWord size, const MSWrite::Word function, MSWrite::Device *device)
00768 : MSWrite::NeedsDevice (device),
00769 m_size (size), m_function (function),
00770 m_argUpto (0)
00771 {
00772 }
00773
00774 MSWrite::DWord getSize (void) const { return m_size; }
00775 void setSize (const MSWrite::DWord size) { m_size = size; }
00776
00777 MSWrite::Word getFunction (void) const { return m_function; }
00778 void setFunction (const MSWrite::Word function) { m_function = function; }
00779
00780 void add (const MSWrite::Short arg)
00781 {
00782 m_args [m_argUpto++] = arg;
00783 }
00784
00785 bool readFromDevice (void)
00786 {
00787 if (!m_device->readInternal (m_data, 6)) return false;
00788 MSWrite::ReadDWord (m_size, m_data + 0);
00789 MSWrite::ReadWord (m_function, m_data + 4);
00790 printf ("Size (Words): %i Size (Bytes): %i Function: %04X (func=%02X,numArgs=%i)\n",
00791 m_size, m_size * sizeof (MSWrite::Word), m_function, m_function & 255, m_function >> 8);
00792 #if 1
00793 if (m_function == 0 && m_size == 3)
00794 return false;
00795 #endif
00796
00797 switch (m_function)
00798 {
00799 case 0x0103:
00800 printf ("\tSetMapMode\n");
00801 break;
00802 case 0x020c:
00803 printf ("\tSetWindowExt\n");
00804 break;
00805 case 0x020b:
00806 printf ("\tSetWindowOrg\n");
00807 break;
00808 case 0x0b41:
00809 printf ("\tDibStretchBlt\n");
00810 break;
00811 default:
00812 printf ("\tUnknown function\n");
00813 }
00814
00815 long offset = m_device->tellInternal ();
00816
00817 for (int i = 0; i < ((m_function == 0x0b41) ? 10 : (m_function >> 8)); i++)
00818 {
00819 MSWrite::Byte data [2];
00820 if (!m_device->readInternal (data, 2)) return false;
00821 MSWrite::ReadShort (m_args [i], data);
00822 printf ("\tArg (rev) #%i=%i\n", i, m_args [i]);
00823 }
00824
00825 #if 0
00826
00827 int u = 0;
00828 for (int i = (m_function >> 8) - 1; i >= 0; i--, u++)
00829 printf ("\tArg #%i=%u\n", u, m_args [i]);
00830 #endif
00831
00832 #if 1
00833 if (m_function == 0xb41)
00834 {
00835
00836 MSWrite::BMP_BitmapInfoHeader bih;
00837 bih.setDevice (m_device);
00838 if (!bih.readFromDevice ()) return false;
00839 }
00840 #endif
00841
00842 m_size *= sizeof (MSWrite::Word);
00843 m_size -= 6;
00844 printf (">>> At: %li Next: %li\n", m_device->tellInternal (), offset + m_size);
00845 if (!m_device->seekInternal (offset + m_size, SEEK_SET)) return false;
00846 return true;
00847 }
00848
00849 bool writeToDevice (void)
00850 {
00851 MSWrite::WriteDWord (m_size, m_data + 0);
00852 MSWrite::WriteWord (m_function, m_data + 4);
00853 if (!m_device->writeInternal (m_data, 6)) return false;
00854
00855 for (int i = 0; i < ((m_function == 0x0B41) ? 10 : (m_function >> 8)); i++)
00856 {
00857 MSWrite::Byte data [2];
00858 MSWrite::WriteShort (m_args [i], data);
00859 if (!m_device->writeInternal (data, 2)) return false;
00860 }
00861
00862 return true;
00863 }
00864 };
00865
00866
00867 bool BMP2WMF (MSWrite::Device &readDevice, MSWrite::Device &writeDevice)
00868 {
00869
00870 MSWrite::BMP_BitmapFileHeader bfh;
00871 bfh.setDevice (&readDevice);
00872 if (!bfh.readFromDevice ()) return false;
00873
00874
00875 MSWrite::DWord totalBytes = bfh.getTotalBytes () - MSWrite::BMP_BitmapFileHeader::s_size;
00876
00877
00878 MSWrite::BMP_BitmapInfoHeader bih;
00879 bih.setDevice (&readDevice);
00880 if (!bih.readFromDevice ()) return false;
00881
00882
00883 MSWrite::Long width = bih.getWidth ();
00884 MSWrite::Long height = bih.getHeight ();
00885
00886
00887
00888 kdDebug (30509) << "\t\tBIH: width(pt)=" << width
00889 << " height(pt)=" << height
00890 << " BPP=" << bih.getBitsPerPixel ()
00891 << endl;
00892 kdDebug (30509) << "\t\tBIH: xPixelsPerMeter=" << bih.getXPixelsPerMeter ()
00893 << " yPixelsPerMeter=" << bih.getYPixelsPerMeter ()
00894 << endl;
00895
00896
00897
00898 MSWrite::WMFHeader wmfHeader;
00899 wmfHeader.setDevice (&writeDevice);
00900
00901 MSWrite::DWord maxRecordSizeBytes
00902 = (totalBytes
00903 + 10 * sizeof (MSWrite::Word)
00904 + WMFRecord::s_size);
00905 wmfHeader.setFileSize ((MSWrite::WMFHeader::s_size
00906 + WMFRecord::s_size + 1 * sizeof (MSWrite::Word)
00907 + WMFRecord::s_size + 2 * sizeof (MSWrite::Word)
00908 + WMFRecord::s_size + 2 * sizeof (MSWrite::Word)
00909 + maxRecordSizeBytes
00910 + WMFRecord::s_size)
00911 / sizeof (MSWrite::Word));
00912 wmfHeader.setMaxRecordSize (maxRecordSizeBytes / sizeof (MSWrite::Word));
00913 if (!wmfHeader.writeToDevice ()) return false;
00914
00915 WMFRecord wmfRecordSetMapMode (4, 0x0103, &writeDevice);
00916 wmfRecordSetMapMode.add (8);
00917 if (!wmfRecordSetMapMode.writeToDevice ()) return false;
00918
00919 WMFRecord wmfRecordSetWindowExt (5, 0x020C, &writeDevice);
00920 wmfRecordSetWindowExt.add (-height);
00921 wmfRecordSetWindowExt.add (width);
00922 if (!wmfRecordSetWindowExt.writeToDevice ()) return false;
00923
00924 WMFRecord wmfRecordSetWindowOrg (5, 0x020B, &writeDevice);
00925 wmfRecordSetWindowOrg.add (0);
00926 wmfRecordSetWindowOrg.add (0);
00927 if (!wmfRecordSetWindowOrg.writeToDevice ()) return false;
00928
00929 WMFRecord wmfRecordBMP (maxRecordSizeBytes / sizeof (MSWrite::Word),
00930 0x0B41,
00931 &writeDevice);
00932 wmfRecordBMP.add (32);
00933 wmfRecordBMP.add (204);
00934 wmfRecordBMP.add (height);
00935 wmfRecordBMP.add (width);
00936 wmfRecordBMP.add (0);
00937 wmfRecordBMP.add (0);
00938 wmfRecordBMP.add (-height);
00939 wmfRecordBMP.add (width);
00940 wmfRecordBMP.add (0);
00941 wmfRecordBMP.add (0);
00942 if (!wmfRecordBMP.writeToDevice ()) return false;
00943
00944
00945 bih.setDevice (&writeDevice);
00946 if (!bih.writeToDevice ()) return false;
00947
00948 long left = totalBytes - MSWrite::BMP_BitmapInfoHeader::s_size;
00949 while (left)
00950 {
00951 MSWrite::Byte data [1024];
00952 long amountToRead = left > 1024 ? 1024 : left;
00953 if (!readDevice.readInternal (data, amountToRead)) return false;
00954 if (!writeDevice.writeInternal (data, amountToRead)) return false;
00955
00956 left -= amountToRead;
00957 }
00958
00959 WMFRecord wmfRecordSentinel (3, 0x0000, &writeDevice);
00960 if (!wmfRecordSentinel.writeToDevice ()) return false;
00961
00962 #if 1
00963
00964 MSWrite::Byte zero = 0;
00965 if (!writeDevice.writeInternal (&zero, sizeof (MSWrite::Byte))) return false;
00966 #endif
00967
00968 return true;
00969 }
00970
00971
00972 static double getDimen72DPI (const int measurement, const int dotsPerMeter)
00973 {
00974 kdDebug (30509) << "\t\tgetDimen72DPI (measurement=" << measurement
00975 << ",dotsPerMeter=" << dotsPerMeter << ")" << endl;
00976
00977
00978
00979 if (dotsPerMeter <= 0)
00980 return double (measurement);
00981
00982
00983 return double (measurement) * 2834.65 / double (dotsPerMeter);
00984 }
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000 bool processImage (const FrameAnchor &frameAnchor,
01001 const MSWrite::FormatParaProperty *paraPropIn,
01002 const MSWrite::FormatCharProperty *charPropIn,
01003 const bool ignoreIndent)
01004 {
01005 kdDebug (30509) << "--------------------------" << endl
01006 << "processImage()" << endl;
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027 double imageActualWidth = -1, imageActualHeight = -1;
01028 MSWrite::DWord imageSize = 0;
01029
01030 QString imageType;
01031 int pos = frameAnchor.picture.koStoreName.findRev ('.');
01032 if (pos != -1) imageType = frameAnchor.picture.koStoreName.mid (pos).lower ();
01033 kdDebug (30509) << "\timageType: " << imageType << endl;
01034
01035 QByteArray imageData;
01036 kdDebug (30509) << "\tReading image: " << frameAnchor.picture.koStoreName << endl;
01037 if (!loadSubFile (frameAnchor.picture.koStoreName, imageData))
01038 ErrorAndQuit (MSWrite::Error::FileError, "could not open image from store\n");
01039
01040
01041 for (;;)
01042 {
01043 if (imageType == ".wmf")
01044 {
01045 imageSize = imageData.size ();
01046 if (imageActualWidth == -1 && imageActualHeight == -1)
01047 {
01048
01049 KoWmfPaint wmf;
01050 if (!wmf.load (imageData))
01051 {
01052 kdError (30509) << "Could not open WMF - Invalid Format!" << endl;
01053 return true;
01054 }
01055
01056
01057 QRect dimen = wmf.boundingRect ();
01058 int width = abs (dimen.width ());
01059 int height = abs (dimen.height ());
01060 kdDebug (30509) << "\tRaw WMF dimensions: " << width << "x" << height << endl;
01061
01062 if (wmf.isPlaceable ())
01063 {
01064 kdDebug (30509) << "\tConverting Placeable WMF" << endl;
01065
01066
01067 int defaultDpi = wmf.defaultDpi ();
01068 if (defaultDpi <= 0)
01069 {
01070 kdWarning (30509) << "Invalid defaultDPI: " << defaultDpi << endl;
01071 defaultDpi = 1440;
01072 }
01073 imageActualWidth = width * 1440 / defaultDpi;
01074 imageActualHeight = height * 1440 / defaultDpi;
01075
01076
01077 for (int i = 0; i < int (imageSize) - 22; i++)
01078 imageData [i] = imageData [i + 22];
01079
01080 imageData.resize (imageSize - 22);
01081 imageSize -= 22;
01082 }
01083 else if (wmf.isEnhanced ())
01084 {
01085 kdError (30509) << "Enhanced WMF unsupported by QWmf, internal error!" << endl;
01086
01087 return true;
01088 }
01089
01090 else
01091 {
01092 kdDebug (30509) << "\tStandard WMF - no conversion required" << endl;
01093
01094
01095 imageActualWidth = Point2Twip (width);
01096 imageActualHeight = Point2Twip (height);
01097 }
01098 }
01099
01100 kdDebug (30509) << "\tNow WMF: width=" << imageActualWidth
01101 << " height=" << imageActualHeight
01102 << " size=" << imageSize
01103 << endl;
01104
01105
01106 break;
01107 }
01108
01109 else if (imageType == ".bmp")
01110 {
01111 QImage image (imageData);
01112 if (image.isNull ())
01113 {
01114 kdError (30509) << "QImage IsNull: Line=" << __LINE__ << endl;
01115 return true;
01116 }
01117
01118 if (imageActualWidth == -1 && imageActualHeight == -1)
01119 {
01120 imageActualWidth = Point2Twip (getDimen72DPI (image.width (), image.dotsPerMeterX ()));
01121 imageActualHeight = Point2Twip (getDimen72DPI (image.height (), image.dotsPerMeterY ()));
01122 }
01123
01124 kdDebug (30509) << "\tNow BMP: width=" << imageActualWidth
01125 << " height=" << imageActualHeight
01126 << " size=" << imageSize
01127 << endl;
01128
01129 QByteArray imageWMF;
01130
01131 QBuffer inBuffer (imageData);
01132 inBuffer.open (IO_ReadOnly);
01133 QBufferDevice inDevice (&inBuffer);
01134
01135
01136 QBuffer outBuffer (imageWMF);
01137 outBuffer.open (IO_WriteOnly);
01138 QBufferDevice outDevice (&outBuffer);
01139
01140
01141 if (!BMP2WMF (inDevice, outDevice))
01142 {
01143 kdError (30509) << "BMP to WMF conversion error" << endl;
01144 return true;
01145 }
01146
01147 outBuffer.close ();
01148 inBuffer.close ();
01149 imageData = imageWMF.copy ();
01150
01151 imageType = ".wmf";
01152 }
01153 else
01154 {
01155 if (imageActualWidth == -1 && imageActualHeight == -1)
01156 {
01157 QImage image (imageData);
01158 if (image.isNull())
01159 {
01160 kdError (30509) << "QImage isNull: Line=" << __LINE__ << endl;
01161 return true;
01162 }
01163
01164 imageActualWidth = Point2Twip (getDimen72DPI (image.width (), image.dotsPerMeterX ()));
01165 imageActualHeight = Point2Twip (getDimen72DPI (image.height (), image.dotsPerMeterY ()));
01166 }
01167
01168 kdDebug (30509) << "\tForeign format: width=" << imageActualWidth
01169 << " height=" << imageActualHeight
01170 << " size=" << imageSize
01171 << endl;
01172
01173 QByteArray imageBMP;
01174
01175 QBuffer inBuffer (imageData);
01176 inBuffer.open (IO_ReadOnly);
01177
01178
01179 QImageIO imageIO (&inBuffer, NULL);
01180 if (!imageIO.read ())
01181 {
01182 kdError (30509) << "Could not read foreign format" << endl;
01183 return true;
01184 }
01185
01186
01187 QBuffer outBuffer (imageBMP);
01188 outBuffer.open (IO_WriteOnly);
01189
01190
01191 imageIO.setIODevice (&outBuffer);
01192 imageIO.setFormat ("BMP");
01193 if (!imageIO.write ())
01194 {
01195 kdError (30509) << "Could not convert to BMP" << endl;
01196 return true;
01197 }
01198
01199 outBuffer.close ();
01200 inBuffer.close ();
01201 imageData = imageBMP.copy ();
01202
01203 imageType = ".bmp";
01204 }
01205 }
01206
01207
01208 kdDebug (30509) << "\tActual dimensions: width=" << imageActualWidth
01209 << " height=" << imageActualHeight << endl;
01210
01211 kdDebug (30509) << "\tKOffice position: left=" << frameAnchor.frame.left
01212 << " right=" << frameAnchor.frame.right
01213 << " top=" << frameAnchor.frame.top
01214 << " bottom=" << frameAnchor.frame.bottom
01215 << endl;
01216
01217 kdDebug (30509) << "\tIndent=" << MSWrite::Word (Point2Twip (frameAnchor.frame.left)) - m_leftMargin << endl;
01218 if (ignoreIndent)
01219 kdDebug (30509) << "\t\tIgnoring indent - already exported at least one image in a KWord paragraph" << endl;
01220
01221 double displayedWidth = Point2Twip (frameAnchor.frame.right - frameAnchor.frame.left + 1);
01222 double displayedHeight = Point2Twip (frameAnchor.frame.bottom - frameAnchor.frame.top + 1);
01223
01224 kdDebug (30509) << "\tdisplayedWidth=" << displayedWidth
01225 << " displayedHeight=" << displayedHeight
01226 << endl;
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236 MSWrite::Image image;
01237 image.setIsWMF (true);
01238 if (!ignoreIndent)
01239 {
01240 if (paraPropIn->getAlignment () != MSWrite::Alignment::Centre)
01241 image.setIndent (MSWrite::Word (Point2Twip (frameAnchor.frame.left)) - m_leftMargin);
01242 else
01243 {
01244
01245 kdDebug (30509) << "\tCentred paragraph, cannot position image" << endl;
01246 }
01247 }
01248
01249 image.setOriginalWidth (imageActualWidth);
01250 image.setOriginalHeight (imageActualHeight);
01251 image.setDisplayedWidth (displayedWidth);
01252 image.setDisplayedHeight (displayedHeight);
01253 image.setExternalImageSize (imageSize);
01254
01255 MSWrite::FormatParaProperty paraProp; paraProp = *paraPropIn;
01256 paraProp.setIsObject (true);
01257 paraProp.setLeftIndent (0);
01258 if (!m_generator->writeParaInfoBegin (¶Prop, NULL, &image))
01259 return false;
01260
01261
01262
01263
01264 MSWrite::FormatCharProperty charProp; charProp = *charPropIn;
01265 if (!m_generator->writeCharInfoBegin (&charProp))
01266 return false;
01267
01268
01269 if (!m_generator->writeBinary ((const MSWrite::Byte *) (const char *) imageData.data (), imageSize)) return false;
01270
01271
01272
01273 if (!m_generator->writeCharInfoEnd (&charProp, true))
01274 return false;
01275 ;
01276 if (!m_generator->writeParaInfoEnd (¶Prop, NULL, &image))
01277 return false;
01278
01279
01280 kdDebug (30509) << "processImage() successful!" << endl
01281 << "==========================" << endl
01282 << endl
01283 << endl;
01284 return true;
01285 }
01286
01287 bool processTable (const Table &table)
01288 {
01289
01290 for (QValueList <TableCell>::ConstIterator it = table.cellList.begin ();
01291 it != table.cellList.end ();
01292 it++)
01293 {
01294 if (!doFullParagraphList (*(*it).paraList)) return false;
01295 }
01296
01297 return true;
01298 }
01299
01300 bool processCounter (const CounterData &counter)
01301 {
01302
01303
01304 if (!counter.text.isEmpty ())
01305 {
01306
01307 if (!processText (counter.text)) return false;
01308 if (!processText (" ")) return false;
01309 }
01310
01311 return true;
01312 }
01313
01314 #ifndef NDEBUG
01315
01316 #endif
01317 void processFormatData (MSWrite::FormatCharProperty &charProp,
01318 const TextFormatting &f)
01319 {
01320 if (!f.fontName.isEmpty ())
01321 {
01322
01323 MSWrite::Font font ((const MSWrite::Byte *) (const char *) f.fontName.utf8 ());
01324 #ifdef KMF_DEBUG_FONT
01325 kdDebug (30509) << "FontName " << f.fontName << endl;
01326 #endif
01327
01328
01329 QFont QTFontInfo (f.fontName);
01330 switch (QTFontInfo.styleHint ())
01331 {
01332 case QFont::Serif:
01333 #ifdef KMF_DEBUG_FONT
01334 kdDebug (30509) << "FontFamily Serif" << endl;
01335 #endif
01336 font.setFamily (MSWrite::Font::Roman);
01337 break;
01338 case QFont::SansSerif:
01339 #ifdef KMF_DEBUG_FONT
01340 kdDebug (30509) << "FontFamily SansSerif" << endl;
01341 #endif
01342 font.setFamily (MSWrite::Font::Swiss);
01343 break;
01344 case QFont::Courier:
01345 #ifdef KMF_DEBUG_FONT
01346 kdDebug (30509) << "FontFamily Courier" << endl;
01347 #endif
01348 font.setFamily (MSWrite::Font::Modern);
01349 break;
01350 case QFont::OldEnglish:
01351 #ifdef KMF_DEBUG_FONT
01352 kdDebug (30509) << "FontFamily OldEnglish" << endl;
01353 #endif
01354 font.setFamily (MSWrite::Font::Decorative);
01355 break;
01356 default:
01357 #ifdef KMF_DEBUG_FONT
01358 kdDebug (30509) << "FontFamily DontKnow" << endl;
01359 #endif
01360
01361 font.setFamily (MSWrite::Font::DontCare);
01362 break;
01363 }
01364
01365 charProp.setFont (&font);
01366 }
01367 if (f.fontSize > 0) charProp.setFontSize (f.fontSize);
01368
01369 charProp.setIsItalic (f.italic);
01370 charProp.setIsUnderlined (f.underline);
01371 charProp.setIsBold (f.weight > (50 + 75) / 2);
01372
01373 switch (f.verticalAlignment)
01374 {
01375 case 0:
01376 charProp.setIsNormalPosition ();
01377 break;
01378 case 1:
01379 charProp.setIsSubscript ();
01380 break;
01381 case 2:
01382 charProp.setIsSuperscript ();
01383 break;
01384 }
01385
01386
01387 }
01388
01389 static MSWrite::Word getClosestLineSpacing (const double points)
01390 {
01391 const double twips = Point2Twip (points);
01392
01393 #if 1
01394 if (twips < double ((MSWrite::LineSpacing::Single + MSWrite::LineSpacing::OneAndAHalf) / 2))
01395 return MSWrite::LineSpacing::Single;
01396 else if (twips < double ((MSWrite::LineSpacing::OneAndAHalf + MSWrite::LineSpacing::Double) / 2))
01397 return MSWrite::LineSpacing::OneAndAHalf;
01398 else
01399 return MSWrite::LineSpacing::Double;
01400 #else // or do we want a non-"standard" linespacing?
01401 return MSWrite::Word (twips);
01402 #endif
01403 }
01404
01405 bool doFullParagraphList (const QValueList <ParaData> ¶List)
01406 {
01407 for (QValueList <ParaData>::ConstIterator it = paraList.begin ();
01408 it != paraList.end ();
01409 it ++)
01410 {
01411 if (!doFullParagraph (*it)) return false;
01412 }
01413
01414 return true;
01415 }
01416
01417 bool doFullParagraph (const ParaData ¶Data)
01418 {
01419 return doFullParagraph (paraData.text,
01420 paraData.layout,
01421 paraData.formattingList);
01422 }
01423
01424 bool doFullParagraph (const QString ¶Text,
01425 const LayoutData &layout,
01426 const ValueListFormatData ¶FormatDataList)
01427 {
01428 MSWrite::FormatParaProperty paraProp;
01429
01430 if (m_inWhat == Body)
01431 paraProp.setIsNormalParagraph (true);
01432 else
01433 {
01434 if (m_inWhat == Header)
01435 {
01436 paraProp.setIsHeader (true);
01437 paraProp.setIsOnFirstPage (m_isHeaderOnFirstPage);
01438 }
01439 else if (m_inWhat == Footer)
01440 {
01441 paraProp.setIsFooter (true);
01442 paraProp.setIsOnFirstPage (m_isFooterOnFirstPage);
01443 }
01444 }
01445
01446 paraProp.setIsText (true);
01447
01448
01449 if (!layout.alignment.isEmpty ())
01450 {
01451 if (layout.alignment == "left")
01452
01453 paraProp.setAlignment (MSWrite::Alignment::Left);
01454 else if (layout.alignment == "right")
01455 paraProp.setAlignment (MSWrite::Alignment::Right);
01456 else if (layout.alignment == "center")
01457 paraProp.setAlignment (MSWrite::Alignment::Center);
01458 else if (layout.alignment == "justify")
01459 paraProp.setAlignment (MSWrite::Alignment::Justify);
01460 else
01461 kdWarning (30509) << "Unknown Alignment: " << layout.alignment << endl;
01462 }
01463
01464
01465 if (layout.indentFirst) paraProp.setLeftIndentFirstLine (MSWrite::Short (Point2Twip (layout.indentFirst)));
01466 if (layout.indentLeft >= 0) paraProp.setLeftIndent (MSWrite::Word (Point2Twip (layout.indentLeft)));
01467 if (layout.indentRight >= 0) paraProp.setRightIndent (MSWrite::Word (Point2Twip (layout.indentRight)));
01468 #if 0
01469 kdDebug (30509) << "Indent: " << Point2Twip (layout.indentFirst) << " "
01470 << Point2Twip (layout.indentLeft) << " "
01471 << Point2Twip (layout.indentRight) << endl;
01472 #endif
01473
01474
01475 MSWrite::Word lineSpacing = MSWrite::LineSpacing::Normal;
01476 switch (layout.lineSpacingType)
01477 {
01478 case LayoutData::LS_SINGLE:
01479 lineSpacing = MSWrite::LineSpacing::Normal;
01480 break;
01481 case LayoutData::LS_ONEANDHALF:
01482 lineSpacing = MSWrite::LineSpacing::OneAndAHalf;
01483 break;
01484 case LayoutData::LS_DOUBLE:
01485 lineSpacing = MSWrite::LineSpacing::Double;
01486 break;
01487 case LayoutData::LS_CUSTOM:
01488 case LayoutData::LS_FIXED:
01489 case LayoutData::LS_ATLEAST:
01490 lineSpacing = getClosestLineSpacing (layout.lineSpacing);
01491 break;
01492 case LayoutData::LS_MULTIPLE:
01493 break;
01494 default:
01495 kdWarning (30509) << "unknown lineSpacingType \'" << layout.lineSpacingType << "\'" << endl;
01496 }
01497 paraProp.setLineSpacing (lineSpacing);
01498
01499
01500
01501
01502 int numTabs = 0;
01503 for (TabulatorList::ConstIterator tabIt = layout.tabulatorList.begin ();
01504 tabIt != layout.tabulatorList.end ();
01505 tabIt++)
01506 {
01507 MSWrite::FormatParaPropertyTabulator tab;
01508
01509
01510
01511
01512
01513 if (numTabs >= 12)
01514 {
01515 kdWarning (30509) << "Write does not support more 12 tabulators, not writing out all tabulators" << endl;
01516 break;
01517 }
01518
01519
01520
01521 if ((*tabIt).m_type == 3 )
01522 tab.setIsDecimal ();
01523 else
01524 tab.setIsNormal ();
01525
01526 tab.setIndent (MSWrite::Word (Point2Twip ((*tabIt).m_ptpos)));
01527
01528
01529
01530 if ((*tabIt).m_filling != TabulatorData::TF_NONE)
01531 kdWarning (30509) << "Write does not support Tabulator Filling" << endl;
01532
01533 paraProp.addTabulator (&tab);
01534 numTabs++;
01535 }
01536
01537
01538
01539
01540
01541
01542
01543 if (!m_generator->writeParaInfoBegin (¶Prop)) return false;
01544
01545
01546 MSWrite::FormatCharProperty charPropDefault;
01547 processFormatData (charPropDefault, layout.formatData.text);
01548
01549 MSWrite::DWord uptoByte = 0;
01550 MSWrite::DWord numBytes = paraText.length ();
01551
01552 bool startOfWRIParagraph = true;
01553 bool exportedAtLeastOneImage = false;
01554
01555
01556 if (numBytes == 0)
01557 {
01558
01559
01560
01561 if (!m_generator->writeCharInfoBegin (&charPropDefault)) return false;
01562
01563
01564 if (layout.pageBreakBefore)
01565 if (!m_generator->writePageBreak ()) return false;
01566
01567
01568 processCounter (layout.counter);
01569
01570
01571 if (!m_generator->writeCarriageReturn ()) return false;
01572 if (!m_generator->writeNewLine (true)) return false;
01573
01574
01575 if (layout.pageBreakAfter)
01576 if (!m_generator->writePageBreak ()) return false;
01577
01578
01579 if (!m_generator->writeCharInfoEnd (&charPropDefault, true)) return false;
01580 }
01581 else
01582 {
01583 for (ValueListFormatData::ConstIterator formatIt = paraFormatDataList.begin ();
01584 formatIt != paraFormatDataList.end ();
01585 formatIt++)
01586 {
01587 bool textSegment = true;
01588
01589
01590 MSWrite::FormatCharProperty charProp; charProp = charPropDefault;
01591 processFormatData (charProp, (*formatIt).text);
01592
01593 if (!m_generator->writeCharInfoBegin (&charProp)) return false;
01594
01595 if (uptoByte == 0)
01596 {
01597
01598 if (layout.pageBreakBefore)
01599 if (!m_generator->writePageBreak ()) return false;
01600
01601
01602 processCounter (layout.counter);
01603 }
01604
01605
01606
01607 uptoByte += (*formatIt).len;
01608
01609 switch ((*formatIt).id)
01610 {
01611 case 0:
01612 ErrorAndQuit (MSWrite::Error::InternalError, "Format ID = 0\n");
01613 case 1:
01614 if (!processText (paraText.mid ((*formatIt).pos, (*formatIt).len)))
01615
01616 return false;
01617
01618 startOfWRIParagraph = false;
01619 break;
01620 case 2:
01621 m_device->error (MSWrite::Error::Warn, "Picture (deprecated) unsupported\n");
01622 break;
01623 case 3:
01624 m_device->error (MSWrite::Error::Warn, "Tabulator (deprecated) unsupported\n");
01625 break;
01626 case 4:
01627 {
01628 bool justPrintText = true;
01629
01630
01631 if ((*formatIt).variable.m_type == 4 &&
01632 (*formatIt).variable.isPageNumber () &&
01633 m_inWhat != Body)
01634 {
01635 if (!m_generator->writeCharInfoEnd (&charProp)) return false;
01636 charProp.setIsPageNumber (true);
01637
01638 if (!m_generator->writeCharInfoBegin (&charProp)) return false;
01639
01640
01641
01642
01643 if (!m_generator->writePageNumber ()) return false;
01644
01645 if (!m_generator->writeCharInfoEnd (&charProp)) return false;
01646 charProp.setIsPageNumber (false);
01647 if (!m_generator->writeCharInfoBegin (&charProp)) return false;
01648
01649 justPrintText = false;
01650 }
01651
01652 if (justPrintText)
01653 {
01654 if (!processText ((*formatIt).variable.m_text))
01655 return false;
01656 }
01657
01658 startOfWRIParagraph = false;
01659 break;
01660 }
01661 case 5:
01662 m_device->error (MSWrite::Error::Warn, "Footnote unsupported\n");
01663 break;
01664 case 6:
01665
01666
01667
01668
01669
01670
01671
01672
01673 if (!startOfWRIParagraph)
01674 {
01675 kdDebug (30509) << "Writing CRLF to end text paragraph" << endl;
01676
01677
01678
01679
01680 if (!m_generator->writeCarriageReturn ()) return false;
01681 if (!m_generator->writeNewLine (true)) return false;
01682 }
01683 else
01684 kdDebug (30509) << "Inline frame is anchored at start of paragraph, no CRLF" << endl;
01685
01686 if (!m_generator->writeCharInfoEnd (&charProp)) return false;
01687 if (!m_generator->writeParaInfoEnd (¶Prop)) return false;
01688
01689
01690 if ((*formatIt).frameAnchor.type == 6)
01691 {
01692 kdDebug (30509) << "Table detected" << endl;
01693
01694
01695 processTable ((*formatIt).frameAnchor.table);
01696
01697
01698
01699
01700 kdDebug (30509) << "Table hack: resetting image-ignore-indent flag" << endl;
01701 exportedAtLeastOneImage = false;
01702 }
01703 else if ((*formatIt).frameAnchor.type == 2)
01704 {
01705 kdDebug (30509) << "Image detected" << endl;
01706
01707
01708 if (!processImage ((*formatIt).frameAnchor, ¶Prop, &charProp,
01709 exportedAtLeastOneImage)) return false;
01710
01711 exportedAtLeastOneImage = true;
01712 }
01713 else
01714 kdWarning (30509) << "Unknown type of anchor: " << (*formatIt).frameAnchor.type << endl;
01715
01716
01717
01718 if (!m_generator->writeParaInfoBegin (¶Prop)) return false;
01719 startOfWRIParagraph = true;
01720 if (!m_generator->writeCharInfoBegin (&charProp)) return false;
01721
01722 textSegment = false;
01723 break;
01724 }
01725
01726 if (uptoByte == numBytes)
01727 {
01728 if (textSegment)
01729 {
01730
01731 if (!m_generator->writeCarriageReturn ()) return false;
01732 if (!m_generator->writeNewLine (true)) return false;
01733 }
01734
01735
01736 if (layout.pageBreakAfter)
01737 if (!m_generator->writePageBreak ()) return false;
01738 }
01739
01740 if (!m_generator->writeCharInfoEnd (&charProp, uptoByte == numBytes)) return false;
01741 }
01742 }
01743
01744 if (!m_generator->writeParaInfoEnd (¶Prop)) return false;
01745
01746
01747 return true;
01748 }
01749
01750 template <class dtype>
01751 dtype min (const dtype a, const dtype b, const dtype c)
01752 {
01753 if (a <= b && a <= c) return a;
01754 if (b <= a && b <= c) return b;
01755 return c;
01756 }
01757
01758 #ifndef NDEBUG
01759
01760 #endif
01761 bool processText (const QString &stringUnicode)
01762 {
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774 int softHyphen = -2, nonBreakingSpace = -2, newLine = -2;
01775
01776 int upto = 0;
01777 int stringUnicodeLength = stringUnicode.length ();
01778 while (upto < stringUnicodeLength)
01779 {
01780
01781
01782
01783
01784 if (softHyphen == -2)
01785 {
01786 softHyphen = stringUnicode.find (QChar (0xAD), upto);
01787 if (softHyphen == -1) softHyphen = INT_MAX;
01788 }
01789
01790 if (nonBreakingSpace == -2)
01791 {
01792 nonBreakingSpace = stringUnicode.find (QChar (0xA0), upto);
01793 if (nonBreakingSpace == -1) nonBreakingSpace = INT_MAX;
01794 }
01795
01796 if (newLine == -2)
01797 {
01798 newLine = stringUnicode.find (QChar ('\n'), upto);
01799 if (newLine == -1) newLine = INT_MAX;
01800 }
01801
01802
01803 int specialLocation = min (softHyphen, nonBreakingSpace, newLine);
01804
01805
01806
01807 int length = stringUnicodeLength - upto;
01808 if (specialLocation != INT_MAX)
01809 length = specialLocation - upto;
01810 QString substring = stringUnicode.mid (upto, length);
01811
01812 #ifdef DEBUG_PROCESS_TEXT
01813 kdDebug (30509) << "Parent string: upto=" << upto
01814 << ",length=" << stringUnicode.length () << endl;
01815 kdDebug (30509) << "Child string: length=" << length
01816 << " (specialLoc=" << specialLocation << ")" << endl;
01817 #endif
01818
01819
01820
01821
01822
01823 QCString stringWin;
01824
01825
01826 if (m_codec)
01827 {
01828 int len;
01829
01830
01831 stringWin = m_encoder->fromUnicode (substring, len = length);
01832 }
01833 else
01834 {
01835
01836
01837 stringWin = substring.utf8 ();
01838 }
01839
01840
01841
01842 if (!m_generator->writeText ((const MSWrite::Byte *) (const char *) stringWin))
01843 return false;
01844
01845 upto += length;
01846
01847
01848 if (specialLocation != INT_MAX)
01849 {
01850 #ifdef DEBUG_PROCESS_TEXT
01851 kdDebug (30509) << "Found special character!" << endl;
01852 #endif
01853
01854
01855 if (specialLocation == softHyphen)
01856 {
01857 #ifdef DEBUG_PROCESS_TEXT
01858 kdDebug (30509) << "\tSoft Hyphen" << endl;
01859 #endif
01860 if (!m_generator->writeOptionalHyphen ()) return false;
01861 softHyphen = -2;
01862 }
01863 else if (specialLocation == nonBreakingSpace)
01864 {
01865 #ifdef DEBUG_PROCESS_TEXT
01866 kdDebug (30509) << "\tNon-breaking Space" << endl;
01867 #endif
01868
01869 if (!m_generator->writeText ((const MSWrite::Byte *) " ")) return false;
01870 nonBreakingSpace = -2;
01871 }
01872 else if (specialLocation == newLine)
01873 {
01874 #ifdef DEBUG_PROCESS_TEXT
01875 kdDebug (30509) << "\tNew Line" << endl;
01876 #endif
01877
01878 if (!m_generator->writeCarriageReturn ()) return false;
01879 if (!m_generator->writeNewLine (true)) return false;
01880 newLine = -2;
01881 }
01882 else
01883 {
01884 ErrorAndQuit (MSWrite::Error::InternalError, "simply impossible specialLocation\n");
01885 }
01886
01887
01888 upto++;
01889 }
01890 }
01891
01892 return true;
01893 }
01894 };
01895
01896
01897 MSWriteExport::MSWriteExport (KoFilter *, const char *, const QStringList &)
01898 : KoFilter()
01899 {
01900 }
01901
01902 MSWriteExport::~MSWriteExport ()
01903 {
01904 }
01905
01906 KoFilter::ConversionStatus MSWriteExport::convert (const QCString &from, const QCString &to)
01907 {
01908 kdDebug (30509) << "MSWriteExport $Date: 2006-02-12 19:28:12 +0100 (Sun, 12 Feb 2006) $ using LibMSWrite "
01909 << MSWrite::Version << endl;
01910
01911 if (to != "application/x-mswrite" || from != "application/x-kword")
01912 {
01913 kdError (30509) << "Internal error! Filter not implemented?" << endl;
01914 return KoFilter::NotImplemented;
01915 }
01916
01917 KWordMSWriteWorker *worker = new KWordMSWriteWorker;
01918 if (!worker)
01919 {
01920 kdError (30509) << "Could not allocate memory for worker" << endl;
01921 return KoFilter::OutOfMemory;
01922 }
01923
01924 KWEFKWordLeader *leader = new KWEFKWordLeader (worker);
01925 if (!leader)
01926 {
01927 kdError (30509) << "Could not allocate memory for leader" << endl;
01928 delete worker;
01929 return KoFilter::OutOfMemory;
01930 }
01931
01932 KoFilter::ConversionStatus ret = leader->convert (m_chain, from, to);
01933 int errorCode = worker->getError ();
01934
01935 delete leader;
01936 delete worker;
01937
01938
01939
01940 switch (errorCode)
01941 {
01942 case MSWrite::Error::Ok:
01943 kdDebug (30509) << "Returning error code " << ret << endl;
01944 return ret;
01945
01946 case MSWrite::Error::Warn:
01947 kdDebug (30509) << "Error::Warn" << endl;
01948 return KoFilter::InternalError;
01949
01950 case MSWrite::Error::InvalidFormat:
01951 kdDebug (30509) << "Error::InvalidFormat" << endl;
01952 return KoFilter::InternalError;
01953
01954 case MSWrite::Error::OutOfMemory:
01955 kdDebug (30509) << "Error::OutOfMemory" << endl;
01956 return KoFilter::OutOfMemory;
01957
01958 case MSWrite::Error::InternalError:
01959 kdDebug (30509) << "Error::InternalError" << endl;
01960 return KoFilter::InternalError;
01961
01962 case MSWrite::Error::Unsupported:
01963 kdDebug (30509) << "Error::Unsupported" << endl;
01964 return KoFilter::InternalError;
01965
01966 case MSWrite::Error::FileError:
01967 kdDebug (30509) << "Error::FileError" << endl;
01968 return KoFilter::CreationError;
01969 }
01970
01971 kdWarning (30509) << "Unknown error" << endl;
01972 return KoFilter::StupidError;
01973 }
01974
01975 #include <mswriteexport.moc>