29#include <tqtextcodec.h>
30#include <tqvaluelist.h>
31#include <tqvaluestack.h>
34#include <kgenericfactory.h>
36#include <KoFilterChain.h>
37#include <kowmfpaint.h>
39#include <KWEFStructures.h>
40#include <KWEFBaseWorker.h>
41#include <KWEFKWordLeader.h>
43#include "libmswrite.h"
45#include "mswriteexport.h"
48class MSWriteExportFactory : KGenericFactory <MSWriteExport, KoFilter>
51 MSWriteExportFactory () : KGenericFactory <MSWriteExport, KoFilter> (
"kwordmswriteexport")
56 virtual void setupTranslations (
void)
58 TDEGlobal::locale()->insertCatalogue (
"kofficefilters");
62K_EXPORT_COMPONENT_FACTORY (libmswriteexport, MSWriteExportFactory ())
65class WRIDevice : public MSWrite::Device
69 long m_outfp_pos, m_outfp_eof;
72 WRIDevice () : m_outfp (NULL), m_outfp_pos (0), m_outfp_eof (0)
81 bool openFile (
const char *fileName)
83 m_outfp = fopen (fileName,
"wb");
86 error (MSWrite::Error::FileError,
"could not open file for writing\n");
99 error (MSWrite::Error::FileError,
"could not close output file\n");
109 bool read (MSWrite::Byte *,
const MSWrite::DWord)
111 error (MSWrite::Error::InternalError,
"reading from an output file?\n");
115 bool write (
const MSWrite::Byte *buf,
const MSWrite::DWord numBytes)
117 size_t cwrite = fwrite (buf, 1, numBytes, m_outfp);
118 if (cwrite != numBytes)
120 error (MSWrite::Error::FileError,
"could not write to output file\n");
125 m_outfp_pos += numBytes;
126 if (m_outfp_pos > m_outfp_eof)
127 m_outfp_eof = m_outfp_pos;
132 bool seek (
const long offset,
const int whence)
141 absloc = m_outfp_pos + offset;
144 absloc = m_outfp_eof + offset;
147 error (MSWrite::Error::InternalError,
"invalid whence passed to WRIDevice::seek\n");
151 if (absloc > m_outfp_eof)
153 kdDebug (30509) <<
"Want to seek to " << absloc
154 <<
" but EOF is at " << m_outfp_eof
155 <<
"; so writing " << absloc - m_outfp_eof
158 if (fseek (m_outfp, m_outfp_eof, SEEK_SET))
160 error (MSWrite::Error::FileError,
161 "could not seek to EOF in output file\n");
165 MSWrite::Byte *zero =
new MSWrite::Byte [absloc - m_outfp_eof];
168 error (MSWrite::Error::OutOfMemory,
169 "could not allocate memory for zeros\n");
172 memset (zero, 0, absloc - m_outfp_eof);
173 if (!write (zero, absloc - m_outfp_eof))
return false;
176 m_outfp_eof = absloc;
177 m_outfp_pos = absloc;
182 if (fseek (m_outfp, offset, whence) == 0)
184 m_outfp_pos = absloc;
189 error (MSWrite::Error::FileError,
"could not seek output file\n");
197 return ftell (m_outfp);
200 void debug (
const char *s)
202 kdDebug (30509) << s;
204 void debug (
const int i)
206 kdDebug (30509) << i;
208 void error (
const int errorCode,
const char *message,
209 const char * =
"",
const int = 0,
210 MSWrite::DWord = MSWrite::Device::NoToken)
212 if (errorCode == MSWrite::Error::Warn)
213 kdWarning (30509) << message;
217 kdError (30509) << message;
227 MSWrite::InternalGenerator *m_generator;
229 MSWrite::PageLayout m_pageLayout;
230 MSWrite::Word m_pageHeight, m_pageWidth,
231 m_topMargin, m_leftMargin, m_bottomMargin, m_rightMargin;
232 MSWrite::Word m_pageNumberStart;
235 TQTextCodec *m_codec;
236 TQTextEncoder *m_encoder;
238 TQValueList <HeaderData> m_headerData;
239 TQValueList <FooterData> m_footerData;
241 int m_headerType, m_footerType;
242 bool m_hasHeader, m_isHeaderOnFirstPage;
243 bool m_hasFooter, m_isFooterOnFirstPage;
245 enum inWhatPossiblities
254 KWordMSWriteWorker () : m_device (NULL), m_generator (NULL),
255 m_pageHeight (0xFFFF), m_pageWidth (0xFFFF),
256 m_topMargin (0xFFFF), m_leftMargin (0xFFFF),
257 m_bottomMargin (0xFFFF), m_rightMargin (0xFFFF),
259 m_hasHeader (false), m_hasFooter (false),
263 m_codec = TQTextCodec::codecForName (
"CP 1252");
266 m_encoder = m_codec->makeEncoder();
268 kdWarning (30509) <<
"Cannot convert to Win Charset!" << endl;
270 m_device =
new WRIDevice;
273 kdError (30509) <<
"Could not allocate memory for Device" << endl;
277 m_generator =
new MSWrite::InternalGenerator;
280 m_device->error (MSWrite::Error::OutOfMemory,
"could not allocate memory for InternalGenerator\n");
284 m_generator->setDevice (m_device);
287 virtual ~KWordMSWriteWorker ()
294 int getError (
void)
const
296 return m_device->bad ();
299 bool doOpenFile (
const TQString &outFileName,
const TQString &)
302 if (!m_device || !m_generator)
305 if (!m_device->openFile (TQFile::encodeName (outFileName)))
return false;
310 bool doCloseFile (
void)
312 if (!m_device->closeFile ())
return false;
316 bool doOpenDocument (
void)
318 kdDebug (30509) <<
"doOpenDocument ()" << endl;
330 bool doTrulyOpenDocument (
void)
334 m_pageLayout.setPageHeight (m_pageHeight);
335 m_pageLayout.setPageWidth (m_pageWidth);
336 m_pageLayout.setPageNumberStart (m_pageNumberStart);
337 m_pageLayout.setTopMargin (m_topMargin);
338 m_pageLayout.setLeftMargin (m_leftMargin);
339 m_pageLayout.setTextHeight (m_pageHeight - m_topMargin - m_bottomMargin);
340 m_pageLayout.setTextWidth (m_pageWidth - m_leftMargin - m_rightMargin);
346 if (!m_generator->writeDocumentBegin (MSWrite::Format::Write_3_0,
347 &m_pageLayout))
return false;
352 bool doCloseDocument (
void)
354 kdDebug (30509) <<
"doCloseDocument ()" << endl;
356 if (!m_generator->writeDocumentEnd (MSWrite::Format::Write_3_0,
357 &m_pageLayout))
return false;
362 bool doFullPaperFormat (
const int format,
363 const double width,
const double height,
364 const int orientation)
366 kdDebug (30509) <<
"doFullPaperFormat ("
370 << orientation <<
")" << endl;
374 m_pageHeight = MSWrite::Word (Point2Twip (height));
375 m_pageWidth = MSWrite::Word (Point2Twip (width));
380 bool doFullPaperBorders (
const double top,
const double left,
381 const double bottom,
const double right)
383 kdDebug (30509) <<
"doFullPaperBorders ("
387 << right <<
")" << endl;
389 m_topMargin = MSWrite::Word (Point2Twip (top));
390 m_leftMargin = MSWrite::Word (Point2Twip (left));
391 m_bottomMargin = MSWrite::Word (Point2Twip (bottom));
392 m_rightMargin = MSWrite::Word (Point2Twip (right));
397 bool doVariableSettings (
const VariableSettingsData &varSettings)
399 m_pageNumberStart = MSWrite::Word (varSettings.startingPageNumber);
401 kdDebug (30509) <<
"doVariableSettings pageNumberStart="
402 << m_pageNumberStart << endl;
416 bool doPageInfo (
int headerType,
int footerType)
418 kdDebug (30509) <<
"doPageInfo (headerType=" << headerType
419 <<
", footerType=" << footerType
422 m_headerType = headerType;
427 m_isHeaderOnFirstPage =
true;
431 m_isHeaderOnFirstPage =
false;
434 kdWarning (30509) <<
"Unknown headerType: " << headerType << endl;
435 m_isHeaderOnFirstPage =
false;
439 m_footerType = footerType;
444 m_isFooterOnFirstPage =
true;
448 m_isFooterOnFirstPage =
false;
451 kdWarning (30590) <<
"Unknown footerType: " << footerType << endl;
452 m_isFooterOnFirstPage =
false;
459 bool isParaListEmpty (
const TQValueList <ParaData> ¶)
461 if (para.count () == 1)
463 if (para.first ().text.isEmpty ())
470 bool doHeader (
const HeaderData &header)
472 kdDebug (30509) <<
"doHeader (header.page=" << header.page <<
")" << endl;
474 if (isParaListEmpty (header.para))
476 kdDebug (30509) <<
"\tEmpty, ignoring" << endl;
481 switch (m_headerType)
484 if (header.page != HeaderData::PAGE_ALL)
488 if (header.page != HeaderData::PAGE_ODD &&
489 header.page != HeaderData::PAGE_EVEN)
496 if (header.page != HeaderData::PAGE_FIRST &&
497 header.page != HeaderData::PAGE_ODD)
504 m_headerData.push_back (header);
508 bool doFooter (
const FooterData &footer)
510 kdDebug (30509) <<
"doFooter (footer.page=" << footer.page <<
")" << endl;
512 if (isParaListEmpty (footer.para))
514 kdDebug (30509) <<
"\tEmpty, ignoring" << endl;
519 switch (m_footerType)
522 if (footer.page != FooterData::PAGE_ALL)
526 if (footer.page != FooterData::PAGE_ODD &&
527 footer.page != FooterData::PAGE_EVEN)
534 if (footer.page != FooterData::PAGE_FIRST &&
535 footer.page != FooterData::PAGE_ODD)
542 m_footerData.push_back (footer);
548 kdDebug (30509) <<
"doOpenBody ()" << endl;
553 if (!doTrulyOpenDocument ())
return false;
560 bool wroteFooter =
false;
563 for (TQValueList <FooterData>::Iterator it = m_footerData.begin ();
564 it != m_footerData.end ();
567 if ((*it).page != FooterData::PAGE_FIRST)
571 if (!m_generator->writeFooterBegin ())
return false;
575 if (!doFullParagraphList ((*it).para))
return false;
576 it = --m_footerData.erase (it);
580 if (!m_generator->writeFooterEnd ())
return false;
582 bool wroteHeader =
false;
585 for (TQValueList <HeaderData>::Iterator it = m_headerData.begin ();
586 it != m_headerData.end ();
589 if ((*it).page != HeaderData::PAGE_FIRST)
593 if (!m_generator->writeHeaderBegin ())
return false;
597 if (!doFullParagraphList ((*it).para))
return false;
598 it = --m_headerData.erase (it);
602 if (!m_generator->writeHeaderEnd ())
return false;
610 if (!m_generator->writeBodyBegin ())
return false;
613 if (!m_generator->writePageNew ())
return false;
617 for (TQValueList <HeaderData>::Iterator it = m_headerData.begin ();
618 it != m_headerData.end ();
621 kdDebug (30509) <<
"BODY START ADDING HEADER: " << (*it).page << endl;
622 if (!doFullParagraphList ((*it).para))
return false;
623 it = --m_headerData.erase (it);
627 for (TQValueList <FooterData>::Iterator it = m_footerData.begin ();
628 it != m_footerData.end ();
631 kdDebug (30509) <<
"BODY START ADDING FOOTER: " << (*it).page << endl;
632 if (!doFullParagraphList ((*it).para))
return false;
633 it = --m_footerData.erase (it);
642 kdDebug (30509) <<
"doCloseBody ()" << endl;
644 if (!m_generator->writeBodyEnd ())
return false;
651 class TQBufferDevice :
public MSWrite::Device
657 TQBufferDevice (TQBuffer *buffer)
662 bool read (MSWrite::Byte *buf,
const MSWrite::DWord numBytes)
664 if (m_buffer->readBlock ((
char *) buf, (TQ_ULONG) numBytes) != TQ_LONG (numBytes))
666 error (MSWrite::Error::FileError,
"could not read from TQBuffer (not really a FileError)\n");
673 bool write (
const MSWrite::Byte *buf,
const MSWrite::DWord numBytes)
675 if (m_buffer->writeBlock ((
char *) buf, (TQ_ULONG) numBytes) != TQ_LONG (numBytes))
677 error (MSWrite::Error::FileError,
"could not write to TQBuffer (not really a FileError)\n");
686 bool seek (
const long offset,
const int whence)
695 absoffset = m_buffer->at () + offset;
698 absoffset = m_buffer->size () + offset;
701 error (MSWrite::Error::InternalError,
"unknown seek\n");
705 if (absoffset >
long (m_buffer->size ()))
707 error (MSWrite::Error::InternalError,
"seek past EOF unimplemented\n");
711 if (!m_buffer->at (absoffset))
713 error (MSWrite::Error::FileError,
"TQBuffer could not seek (not really a FileError)\n");
722 return long (m_buffer->at ());
725 void debug (
const char *s)
727 kdDebug (30509) << s;
729 void debug (
const int i)
731 kdDebug (30509) << i;
734 void error (
const int errorCode,
const char *message,
735 const char * =
"",
const int = 0,
736 MSWrite::DWord = MSWrite::Device::NoToken)
738 if (errorCode == MSWrite::Error::Warn)
739 kdWarning (30509) << message;
743 kdError (30509) << message;
748 class WMFRecord :
public MSWrite::NeedsDevice
751 static const int s_size = 6;
754 MSWrite::Byte m_data [s_size];
756 MSWrite::DWord m_size;
757 MSWrite::Word m_function;
759 MSWrite::Short m_args [100];
763 WMFRecord () : m_argUpto (0)
767 WMFRecord (
const MSWrite::DWord size,
const MSWrite::Word function, MSWrite::Device *device)
768 : MSWrite::NeedsDevice (device),
769 m_size (size), m_function (function),
774 MSWrite::DWord getSize (
void)
const {
return m_size; }
775 void setSize (
const MSWrite::DWord size) { m_size = size; }
777 MSWrite::Word getFunction (
void)
const {
return m_function; }
778 void setFunction (
const MSWrite::Word function) { m_function = function; }
780 void add (
const MSWrite::Short arg)
782 m_args [m_argUpto++] = arg;
785 bool readFromDevice (
void)
787 if (!m_device->readInternal (m_data, 6))
return false;
788 MSWrite::ReadDWord (m_size, m_data + 0);
789 MSWrite::ReadWord (m_function, m_data + 4);
790 printf (
"Size (Words): %i Size (Bytes): %i Function: %04X (func=%02X,numArgs=%i)\n",
791 m_size, m_size *
sizeof (MSWrite::Word), m_function, m_function & 255, m_function >> 8);
793 if (m_function == 0 && m_size == 3)
800 printf (
"\tSetMapMode\n");
803 printf (
"\tSetWindowExt\n");
806 printf (
"\tSetWindowOrg\n");
809 printf (
"\tDibStretchBlt\n");
812 printf (
"\tUnknown function\n");
815 long offset = m_device->tellInternal ();
817 for (
int i = 0; i < ((m_function == 0x0b41) ? 10 : (m_function >> 8)); i++)
819 MSWrite::Byte data [2];
820 if (!m_device->readInternal (data, 2))
return false;
821 MSWrite::ReadShort (m_args [i], data);
822 printf (
"\tArg (rev) #%i=%i\n", i, m_args [i]);
828 for (
int i = (m_function >> 8) - 1; i >= 0; i--, u++)
829 printf (
"\tArg #%i=%u\n", u, m_args [i]);
833 if (m_function == 0xb41)
836 MSWrite::BMP_BitmapInfoHeader bih;
837 bih.setDevice (m_device);
838 if (!bih.readFromDevice ())
return false;
842 m_size *=
sizeof (MSWrite::Word);
844 printf (
">>> At: %li Next: %li\n", m_device->tellInternal (), offset + m_size);
845 if (!m_device->seekInternal (offset + m_size, SEEK_SET))
return false;
849 bool writeToDevice (
void)
851 MSWrite::WriteDWord (m_size, m_data + 0);
852 MSWrite::WriteWord (m_function, m_data + 4);
853 if (!m_device->writeInternal (m_data, 6))
return false;
855 for (
int i = 0; i < ((m_function == 0x0B41) ? 10 : (m_function >> 8)); i++)
857 MSWrite::Byte data [2];
858 MSWrite::WriteShort (m_args [i], data);
859 if (!m_device->writeInternal (data, 2))
return false;
867 bool BMP2WMF (MSWrite::Device &readDevice, MSWrite::Device &writeDevice)
870 MSWrite::BMP_BitmapFileHeader bfh;
871 bfh.setDevice (&readDevice);
872 if (!bfh.readFromDevice ())
return false;
875 MSWrite::DWord totalBytes = bfh.getTotalBytes () - MSWrite::BMP_BitmapFileHeader::s_size;
878 MSWrite::BMP_BitmapInfoHeader bih;
879 bih.setDevice (&readDevice);
880 if (!bih.readFromDevice ())
return false;
883 MSWrite::Long width = bih.getWidth ();
884 MSWrite::Long height = bih.getHeight ();
888 kdDebug (30509) <<
"\t\tBIH: width(pt)=" << width
889 <<
" height(pt)=" << height
890 <<
" BPP=" << bih.getBitsPerPixel ()
892 kdDebug (30509) <<
"\t\tBIH: xPixelsPerMeter=" << bih.getXPixelsPerMeter ()
893 <<
" yPixelsPerMeter=" << bih.getYPixelsPerMeter ()
898 MSWrite::WMFHeader wmfHeader;
899 wmfHeader.setDevice (&writeDevice);
901 MSWrite::DWord maxRecordSizeBytes
903 + 10 *
sizeof (MSWrite::Word)
904 + WMFRecord::s_size);
905 wmfHeader.setFileSize ((MSWrite::WMFHeader::s_size
906 + WMFRecord::s_size + 1 *
sizeof (MSWrite::Word)
907 + WMFRecord::s_size + 2 *
sizeof (MSWrite::Word)
908 + WMFRecord::s_size + 2 *
sizeof (MSWrite::Word)
911 /
sizeof (MSWrite::Word));
912 wmfHeader.setMaxRecordSize (maxRecordSizeBytes /
sizeof (MSWrite::Word));
913 if (!wmfHeader.writeToDevice ())
return false;
915 WMFRecord wmfRecordSetMapMode (4, 0x0103, &writeDevice);
916 wmfRecordSetMapMode.add (8);
917 if (!wmfRecordSetMapMode.writeToDevice ())
return false;
919 WMFRecord wmfRecordSetWindowExt (5, 0x020C, &writeDevice);
920 wmfRecordSetWindowExt.add (-height);
921 wmfRecordSetWindowExt.add (width);
922 if (!wmfRecordSetWindowExt.writeToDevice ())
return false;
924 WMFRecord wmfRecordSetWindowOrg (5, 0x020B, &writeDevice);
925 wmfRecordSetWindowOrg.add (0);
926 wmfRecordSetWindowOrg.add (0);
927 if (!wmfRecordSetWindowOrg.writeToDevice ())
return false;
929 WMFRecord wmfRecordBMP (maxRecordSizeBytes /
sizeof (MSWrite::Word),
932 wmfRecordBMP.add (32);
933 wmfRecordBMP.add (204);
934 wmfRecordBMP.add (height);
935 wmfRecordBMP.add (width);
936 wmfRecordBMP.add (0);
937 wmfRecordBMP.add (0);
938 wmfRecordBMP.add (-height);
939 wmfRecordBMP.add (width);
940 wmfRecordBMP.add (0);
941 wmfRecordBMP.add (0);
942 if (!wmfRecordBMP.writeToDevice ())
return false;
945 bih.setDevice (&writeDevice);
946 if (!bih.writeToDevice ())
return false;
948 long left = totalBytes - MSWrite::BMP_BitmapInfoHeader::s_size;
951 MSWrite::Byte data [1024];
952 long amountToRead = left > 1024 ? 1024 : left;
953 if (!readDevice.readInternal (data, amountToRead))
return false;
954 if (!writeDevice.writeInternal (data, amountToRead))
return false;
956 left -= amountToRead;
959 WMFRecord wmfRecordSentinel (3, 0x0000, &writeDevice);
960 if (!wmfRecordSentinel.writeToDevice ())
return false;
964 MSWrite::Byte zero = 0;
965 if (!writeDevice.writeInternal (&zero, sizeof (MSWrite::Byte)))
return false;
972 static double getDimen72DPI (
const int measurement,
const int dotsPerMeter)
974 kdDebug (30509) <<
"\t\tgetDimen72DPI (measurement=" << measurement
975 <<
",dotsPerMeter=" << dotsPerMeter <<
")" << endl;
979 if (dotsPerMeter <= 0)
980 return double (measurement);
983 return double (measurement) * 2834.65 / double (dotsPerMeter);
1000 bool processImage (
const FrameAnchor &frameAnchor,
1001 const MSWrite::FormatParaProperty *paraPropIn,
1002 const MSWrite::FormatCharProperty *charPropIn,
1003 const bool ignoreIndent)
1005 kdDebug (30509) <<
"--------------------------" << endl
1006 <<
"processImage()" << endl;
1027 double imageActualWidth = -1, imageActualHeight = -1;
1028 MSWrite::DWord imageSize = 0;
1031 int pos = frameAnchor.picture.koStoreName.findRev (
'.');
1032 if (pos != -1) imageType = frameAnchor.picture.koStoreName.mid (pos).lower ();
1033 kdDebug (30509) <<
"\timageType: " << imageType << endl;
1035 TQByteArray imageData;
1036 kdDebug (30509) <<
"\tReading image: " << frameAnchor.picture.koStoreName << endl;
1037 if (!loadSubFile (frameAnchor.picture.koStoreName, imageData))
1038 ErrorAndQuit (MSWrite::Error::FileError,
"could not open image from store\n");
1043 if (imageType ==
".wmf")
1045 imageSize = imageData.size ();
1046 if (imageActualWidth == -1 && imageActualHeight == -1)
1050 if (!wmf.load (imageData))
1052 kdError (30509) <<
"Could not open WMF - Invalid Format!" << endl;
1057 TQRect dimen = wmf.boundingRect ();
1058 int width = abs (dimen.width ());
1059 int height = abs (dimen.height ());
1060 kdDebug (30509) <<
"\tRaw WMF dimensions: " << width <<
"x" << height << endl;
1062 if (wmf.isPlaceable ())
1064 kdDebug (30509) <<
"\tConverting Placeable WMF" << endl;
1067 int defaultDpi = wmf.defaultDpi ();
1068 if (defaultDpi <= 0)
1070 kdWarning (30509) <<
"Invalid defaultDPI: " << defaultDpi << endl;
1073 imageActualWidth = width * 1440 / defaultDpi;
1074 imageActualHeight = height * 1440 / defaultDpi;
1077 for (
int i = 0; i < int (imageSize) - 22; i++)
1078 imageData [i] = imageData [i + 22];
1080 imageData.resize (imageSize - 22);
1083 else if (wmf.isEnhanced ())
1085 kdError (30509) <<
"Enhanced WMF unsupported by TQWmf, internal error!" << endl;
1092 kdDebug (30509) <<
"\tStandard WMF - no conversion required" << endl;
1095 imageActualWidth = Point2Twip (width);
1096 imageActualHeight = Point2Twip (height);
1100 kdDebug (30509) <<
"\tNow WMF: width=" << imageActualWidth
1101 <<
" height=" << imageActualHeight
1102 <<
" size=" << imageSize
1109 else if (imageType ==
".bmp")
1111 TQImage image (imageData);
1112 if (image.isNull ())
1114 kdError (30509) <<
"TQImage IsNull: Line=" << __LINE__ << endl;
1118 if (imageActualWidth == -1 && imageActualHeight == -1)
1120 imageActualWidth = Point2Twip (getDimen72DPI (image.width (), image.dotsPerMeterX ()));
1121 imageActualHeight = Point2Twip (getDimen72DPI (image.height (), image.dotsPerMeterY ()));
1124 kdDebug (30509) <<
"\tNow BMP: width=" << imageActualWidth
1125 <<
" height=" << imageActualHeight
1126 <<
" size=" << imageSize
1129 TQByteArray imageWMF;
1131 TQBuffer inBuffer (imageData);
1132 inBuffer.open (IO_ReadOnly);
1133 TQBufferDevice inDevice (&inBuffer);
1136 TQBuffer outBuffer (imageWMF);
1137 outBuffer.open (IO_WriteOnly);
1138 TQBufferDevice outDevice (&outBuffer);
1141 if (!BMP2WMF (inDevice, outDevice))
1143 kdError (30509) <<
"BMP to WMF conversion error" << endl;
1149 imageData = imageWMF.copy ();
1155 if (imageActualWidth == -1 && imageActualHeight == -1)
1157 TQImage image (imageData);
1160 kdError (30509) <<
"TQImage isNull: Line=" << __LINE__ << endl;
1164 imageActualWidth = Point2Twip (getDimen72DPI (image.width (), image.dotsPerMeterX ()));
1165 imageActualHeight = Point2Twip (getDimen72DPI (image.height (), image.dotsPerMeterY ()));
1168 kdDebug (30509) <<
"\tForeign format: width=" << imageActualWidth
1169 <<
" height=" << imageActualHeight
1170 <<
" size=" << imageSize
1173 TQByteArray imageBMP;
1175 TQBuffer inBuffer (imageData);
1176 inBuffer.open (IO_ReadOnly);
1179 TQImageIO imageIO (&inBuffer, NULL);
1180 if (!imageIO.read ())
1182 kdError (30509) <<
"Could not read foreign format" << endl;
1187 TQBuffer outBuffer (imageBMP);
1188 outBuffer.open (IO_WriteOnly);
1191 imageIO.setIODevice (&outBuffer);
1192 imageIO.setFormat (
"BMP");
1193 if (!imageIO.write ())
1195 kdError (30509) <<
"Could not convert to BMP" << endl;
1201 imageData = imageBMP.copy ();
1208 kdDebug (30509) <<
"\tActual dimensions: width=" << imageActualWidth
1209 <<
" height=" << imageActualHeight << endl;
1211 kdDebug (30509) <<
"\tKOffice position: left=" << frameAnchor.frame.left
1212 <<
" right=" << frameAnchor.frame.right
1213 <<
" top=" << frameAnchor.frame.top
1214 <<
" bottom=" << frameAnchor.frame.bottom
1217 kdDebug (30509) <<
"\tIndent=" << MSWrite::Word (Point2Twip (frameAnchor.frame.left)) - m_leftMargin << endl;
1219 kdDebug (30509) <<
"\t\tIgnoring indent - already exported at least one image in a KWord paragraph" << endl;
1221 double displayedWidth = Point2Twip (frameAnchor.frame.right - frameAnchor.frame.left + 1);
1222 double displayedHeight = Point2Twip (frameAnchor.frame.bottom - frameAnchor.frame.top + 1);
1224 kdDebug (30509) <<
"\tdisplayedWidth=" << displayedWidth
1225 <<
" displayedHeight=" << displayedHeight
1236 MSWrite::Image image;
1237 image.setIsWMF (
true);
1240 if (paraPropIn->getAlignment () != MSWrite::Alignment::Centre)
1241 image.setIndent (MSWrite::Word (Point2Twip (frameAnchor.frame.left)) - m_leftMargin);
1245 kdDebug (30509) <<
"\tCentred paragraph, cannot position image" << endl;
1249 image.setOriginalWidth (imageActualWidth);
1250 image.setOriginalHeight (imageActualHeight);
1251 image.setDisplayedWidth (displayedWidth);
1252 image.setDisplayedHeight (displayedHeight);
1253 image.setExternalImageSize (imageSize);
1255 MSWrite::FormatParaProperty paraProp; paraProp = *paraPropIn;
1256 paraProp.setIsObject (
true);
1257 paraProp.setLeftIndent (0);
1258 if (!m_generator->writeParaInfoBegin (¶Prop, NULL, &image))
1264 MSWrite::FormatCharProperty charProp; charProp = *charPropIn;
1265 if (!m_generator->writeCharInfoBegin (&charProp))
1269 if (!m_generator->writeBinary ((
const MSWrite::Byte *) (
const char *) imageData.data (), imageSize))
return false;
1273 if (!m_generator->writeCharInfoEnd (&charProp,
true))
1276 if (!m_generator->writeParaInfoEnd (¶Prop, NULL, &image))
1280 kdDebug (30509) <<
"processImage() successful!" << endl
1281 <<
"==========================" << endl
1287 bool processTable (
const Table &table)
1290 for (TQValueList <TableCell>::ConstIterator it = table.cellList.begin ();
1291 it != table.cellList.end ();
1294 if (!doFullParagraphList (*(*it).paraList))
return false;
1300 bool processCounter (
const CounterData &counter)
1304 if (!counter.
text.isEmpty ())
1307 if (!processText (counter.
text))
return false;
1308 if (!processText (
" "))
return false;
1317 void processFormatData (MSWrite::FormatCharProperty &charProp,
1318 const TextFormatting &f)
1320 if (!f.fontName.isEmpty ())
1323 MSWrite::Font font ((
const MSWrite::Byte *) (
const char *) f.fontName.utf8 ());
1324 #ifdef KMF_DEBUG_FONT
1325 kdDebug (30509) <<
"FontName " << f.fontName << endl;
1329 TQFont TQTFontInfo (f.fontName);
1330 switch (TQTFontInfo.styleHint ())
1333 #ifdef KMF_DEBUG_FONT
1334 kdDebug (30509) <<
"FontFamily Serif" << endl;
1336 font.setFamily (MSWrite::Font::Roman);
1338 case TQFont::SansSerif:
1339 #ifdef KMF_DEBUG_FONT
1340 kdDebug (30509) <<
"FontFamily SansSerif" << endl;
1342 font.setFamily (MSWrite::Font::Swiss);
1344 case TQFont::Courier:
1345 #ifdef KMF_DEBUG_FONT
1346 kdDebug (30509) <<
"FontFamily Courier" << endl;
1348 font.setFamily (MSWrite::Font::Modern);
1350 case TQFont::OldEnglish:
1351 #ifdef KMF_DEBUG_FONT
1352 kdDebug (30509) <<
"FontFamily OldEnglish" << endl;
1354 font.setFamily (MSWrite::Font::Decorative);
1357 #ifdef KMF_DEBUG_FONT
1358 kdDebug (30509) <<
"FontFamily DontKnow" << endl;
1361 font.setFamily (MSWrite::Font::DontCare);
1365 charProp.setFont (&font);
1367 if (f.fontSize > 0) charProp.setFontSize (f.fontSize);
1369 charProp.setIsItalic (f.italic);
1371 charProp.setIsBold (f.weight > (50 + 75) / 2);
1373 switch (f.verticalAlignment)
1376 charProp.setIsNormalPosition ();
1379 charProp.setIsSubscript ();
1382 charProp.setIsSuperscript ();
1389 static MSWrite::Word getClosestLineSpacing (
const double points)
1391 const double twips = Point2Twip (points);
1394 if (twips <
double ((MSWrite::LineSpacing::Single + MSWrite::LineSpacing::OneAndAHalf) / 2))
1395 return MSWrite::LineSpacing::Single;
1396 else if (twips <
double ((MSWrite::LineSpacing::OneAndAHalf + MSWrite::LineSpacing::Double) / 2))
1397 return MSWrite::LineSpacing::OneAndAHalf;
1399 return MSWrite::LineSpacing::Double;
1401 return MSWrite::Word (twips);
1405 bool doFullParagraphList (
const TQValueList <ParaData> ¶List)
1407 for (TQValueList <ParaData>::ConstIterator it = paraList.begin ();
1408 it != paraList.end ();
1411 if (!doFullParagraph (*it))
return false;
1417 bool doFullParagraph (
const ParaData ¶Data)
1419 return doFullParagraph (paraData.text,
1421 paraData.formattingList);
1424 bool doFullParagraph (
const TQString ¶Text,
1425 const LayoutData &layout,
1426 const ValueListFormatData ¶FormatDataList)
1428 MSWrite::FormatParaProperty paraProp;
1430 if (m_inWhat == Body)
1431 paraProp.setIsNormalParagraph (
true);
1434 if (m_inWhat == Header)
1436 paraProp.setIsHeader (
true);
1437 paraProp.setIsOnFirstPage (m_isHeaderOnFirstPage);
1439 else if (m_inWhat == Footer)
1441 paraProp.setIsFooter (
true);
1442 paraProp.setIsOnFirstPage (m_isFooterOnFirstPage);
1446 paraProp.setIsText (
true);
1453 paraProp.setAlignment (MSWrite::Alignment::Left);
1455 paraProp.setAlignment (MSWrite::Alignment::Right);
1457 paraProp.setAlignment (MSWrite::Alignment::Center);
1459 paraProp.setAlignment (MSWrite::Alignment::Justify);
1461 kdWarning (30509) <<
"Unknown Alignment: " << layout.
alignment << endl;
1465 if (layout.
indentFirst) paraProp.setLeftIndentFirstLine (MSWrite::Short (Point2Twip (layout.
indentFirst)));
1466 if (layout.
indentLeft >= 0) paraProp.setLeftIndent (MSWrite::Word (Point2Twip (layout.
indentLeft)));
1469 kdDebug (30509) <<
"Indent: " << Point2Twip (layout.
indentFirst) <<
" "
1475 MSWrite::Word lineSpacing = MSWrite::LineSpacing::Normal;
1478 case LayoutData::LS_SINGLE:
1479 lineSpacing = MSWrite::LineSpacing::Normal;
1481 case LayoutData::LS_ONEANDHALF:
1482 lineSpacing = MSWrite::LineSpacing::OneAndAHalf;
1484 case LayoutData::LS_DOUBLE:
1485 lineSpacing = MSWrite::LineSpacing::Double;
1487 case LayoutData::LS_CUSTOM:
1488 case LayoutData::LS_FIXED:
1489 case LayoutData::LS_ATLEAST:
1490 lineSpacing = getClosestLineSpacing (layout.
lineSpacing);
1492 case LayoutData::LS_MULTIPLE:
1495 kdWarning (30509) <<
"unknown lineSpacingType \'" << layout.
lineSpacingType <<
"\'" << endl;
1497 paraProp.setLineSpacing (lineSpacing);
1503 for (TabulatorList::ConstIterator tabIt = layout.
tabulatorList.begin ();
1507 MSWrite::FormatParaPropertyTabulator tab;
1515 kdWarning (30509) <<
"Write does not support more 12 tabulators, not writing out all tabulators" << endl;
1521 if ((*tabIt).m_type == 3 )
1522 tab.setIsDecimal ();
1526 tab.setIndent (MSWrite::Word (Point2Twip ((*tabIt).m_ptpos)));
1530 if ((*tabIt).m_filling != TabulatorData::TF_NONE)
1531 kdWarning (30509) <<
"Write does not support Tabulator Filling" << endl;
1533 paraProp.addTabulator (&tab);
1543 if (!m_generator->writeParaInfoBegin (¶Prop))
return false;
1546 MSWrite::FormatCharProperty charPropDefault;
1547 processFormatData (charPropDefault, layout.formatData.text);
1549 MSWrite::DWord uptoByte = 0;
1550 MSWrite::DWord numBytes = paraText.length ();
1552 bool startOfWRIParagraph =
true;
1553 bool exportedAtLeastOneImage =
false;
1561 if (!m_generator->writeCharInfoBegin (&charPropDefault))
return false;
1564 if (layout.pageBreakBefore)
1565 if (!m_generator->writePageBreak ())
return false;
1568 processCounter (layout.counter);
1571 if (!m_generator->writeCarriageReturn ())
return false;
1572 if (!m_generator->writeNewLine (
true))
return false;
1575 if (layout.pageBreakAfter)
1576 if (!m_generator->writePageBreak ())
return false;
1579 if (!m_generator->writeCharInfoEnd (&charPropDefault,
true))
return false;
1583 for (ValueListFormatData::ConstIterator formatIt = paraFormatDataList.begin ();
1584 formatIt != paraFormatDataList.end ();
1587 bool textSegment =
true;
1590 MSWrite::FormatCharProperty charProp; charProp = charPropDefault;
1591 processFormatData (charProp, (*formatIt).text);
1593 if (!m_generator->writeCharInfoBegin (&charProp))
return false;
1598 if (layout.pageBreakBefore)
1599 if (!m_generator->writePageBreak ())
return false;
1602 processCounter (layout.counter);
1607 uptoByte += (*formatIt).len;
1609 switch ((*formatIt).id)
1612 ErrorAndQuit (MSWrite::Error::InternalError,
"Format ID = 0\n");
1614 if (!processText (paraText.mid ((*formatIt).pos, (*formatIt).len)))
1618 startOfWRIParagraph =
false;
1621 m_device->error (MSWrite::Error::Warn,
"Picture (deprecated) unsupported\n");
1624 m_device->error (MSWrite::Error::Warn,
"Tabulator (deprecated) unsupported\n");
1628 bool justPrintText =
true;
1631 if ((*formatIt).variable.m_type == 4 &&
1632 (*formatIt).variable.isPageNumber () &&
1635 if (!m_generator->writeCharInfoEnd (&charProp))
return false;
1636 charProp.setIsPageNumber (
true);
1638 if (!m_generator->writeCharInfoBegin (&charProp))
return false;
1643 if (!m_generator->writePageNumber ())
return false;
1645 if (!m_generator->writeCharInfoEnd (&charProp))
return false;
1646 charProp.setIsPageNumber (
false);
1647 if (!m_generator->writeCharInfoBegin (&charProp))
return false;
1649 justPrintText =
false;
1654 if (!processText ((*formatIt).variable.m_text))
1658 startOfWRIParagraph =
false;
1662 m_device->error (MSWrite::Error::Warn,
"Footnote unsupported\n");
1673 if (!startOfWRIParagraph)
1675 kdDebug (30509) <<
"Writing CRLF to end text paragraph" << endl;
1680 if (!m_generator->writeCarriageReturn ())
return false;
1681 if (!m_generator->writeNewLine (
true))
return false;
1684 kdDebug (30509) <<
"Inline frame is anchored at start of paragraph, no CRLF" << endl;
1686 if (!m_generator->writeCharInfoEnd (&charProp))
return false;
1687 if (!m_generator->writeParaInfoEnd (¶Prop))
return false;
1690 if ((*formatIt).frameAnchor.type == 6)
1692 kdDebug (30509) <<
"Table detected" << endl;
1695 processTable ((*formatIt).frameAnchor.table);
1700 kdDebug (30509) <<
"Table hack: resetting image-ignore-indent flag" << endl;
1701 exportedAtLeastOneImage =
false;
1703 else if ((*formatIt).frameAnchor.type == 2)
1705 kdDebug (30509) <<
"Image detected" << endl;
1708 if (!processImage ((*formatIt).frameAnchor, ¶Prop, &charProp,
1709 exportedAtLeastOneImage))
return false;
1711 exportedAtLeastOneImage =
true;
1714 kdWarning (30509) <<
"Unknown type of anchor: " << (*formatIt).frameAnchor.type << endl;
1718 if (!m_generator->writeParaInfoBegin (¶Prop))
return false;
1719 startOfWRIParagraph =
true;
1720 if (!m_generator->writeCharInfoBegin (&charProp))
return false;
1722 textSegment =
false;
1726 if (uptoByte == numBytes)
1731 if (!m_generator->writeCarriageReturn ())
return false;
1732 if (!m_generator->writeNewLine (
true))
return false;
1736 if (layout.pageBreakAfter)
1737 if (!m_generator->writePageBreak ())
return false;
1740 if (!m_generator->writeCharInfoEnd (&charProp, uptoByte == numBytes))
return false;
1744 if (!m_generator->writeParaInfoEnd (¶Prop))
return false;
1750 template <
class dtype>
1751 dtype min (
const dtype a,
const dtype b,
const dtype c)
1753 if (a <= b && a <= c)
return a;
1754 if (b <= a && b <= c)
return b;
1761 bool processText (
const TQString &stringUnicode)
1774 int softHyphen = -2, nonBreakingSpace = -2, newLine = -2;
1777 int stringUnicodeLength = stringUnicode.length ();
1778 while (upto < stringUnicodeLength)
1784 if (softHyphen == -2)
1786 softHyphen = stringUnicode.find (TQChar (0xAD), upto);
1787 if (softHyphen == -1) softHyphen = INT_MAX;
1790 if (nonBreakingSpace == -2)
1792 nonBreakingSpace = stringUnicode.find (TQChar (0xA0), upto);
1793 if (nonBreakingSpace == -1) nonBreakingSpace = INT_MAX;
1798 newLine = stringUnicode.find (TQChar (
'\n'), upto);
1799 if (newLine == -1) newLine = INT_MAX;
1803 int specialLocation = min (softHyphen, nonBreakingSpace, newLine);
1807 int length = stringUnicodeLength - upto;
1808 if (specialLocation != INT_MAX)
1809 length = specialLocation - upto;
1810 TQString substring = stringUnicode.mid (upto, length);
1812 #ifdef DEBUG_PROCESS_TEXT
1813 kdDebug (30509) <<
"Parent string: upto=" << upto
1814 <<
",length=" << stringUnicode.length () << endl;
1815 kdDebug (30509) <<
"Child string: length=" << length
1816 <<
" (specialLoc=" << specialLocation <<
")" << endl;
1823 TQCString stringWin;
1831 stringWin = m_encoder->fromUnicode (substring, len = length);
1837 stringWin = substring.utf8 ();
1842 if (!m_generator->writeText ((
const MSWrite::Byte *) (
const char *) stringWin))
1848 if (specialLocation != INT_MAX)
1850 #ifdef DEBUG_PROCESS_TEXT
1851 kdDebug (30509) <<
"Found special character!" << endl;
1855 if (specialLocation == softHyphen)
1857 #ifdef DEBUG_PROCESS_TEXT
1858 kdDebug (30509) <<
"\tSoft Hyphen" << endl;
1860 if (!m_generator->writeOptionalHyphen ())
return false;
1863 else if (specialLocation == nonBreakingSpace)
1865 #ifdef DEBUG_PROCESS_TEXT
1866 kdDebug (30509) <<
"\tNon-breaking Space" << endl;
1869 if (!m_generator->writeText ((
const MSWrite::Byte *)
" "))
return false;
1870 nonBreakingSpace = -2;
1872 else if (specialLocation == newLine)
1874 #ifdef DEBUG_PROCESS_TEXT
1875 kdDebug (30509) <<
"\tNew Line" << endl;
1878 if (!m_generator->writeCarriageReturn ())
return false;
1879 if (!m_generator->writeNewLine (
true))
return false;
1884 ErrorAndQuit (MSWrite::Error::InternalError,
"simply impossible specialLocation\n");
1897MSWriteExport::MSWriteExport (KoFilter *,
const char *,
const TQStringList &)
1902MSWriteExport::~MSWriteExport ()
1906KoFilter::ConversionStatus MSWriteExport::convert (
const TQCString &from,
const TQCString &to)
1908 kdDebug (30509) <<
"MSWriteExport $Date: 2006-02-12 19:28:12 +0100 (Sun, 12 Feb 2006) $ using LibMSWrite "
1909 << MSWrite::Version << endl;
1911 if (to !=
"application/x-mswrite" || from !=
"application/x-kword")
1913 kdError (30509) <<
"Internal error! Filter not implemented?" << endl;
1914 return KoFilter::NotImplemented;
1917 KWordMSWriteWorker *worker =
new KWordMSWriteWorker;
1920 kdError (30509) <<
"Could not allocate memory for worker" << endl;
1921 return KoFilter::OutOfMemory;
1924 KWEFKWordLeader *leader =
new KWEFKWordLeader (worker);
1927 kdError (30509) <<
"Could not allocate memory for leader" << endl;
1929 return KoFilter::OutOfMemory;
1932 KoFilter::ConversionStatus ret = leader->convert (m_chain, from, to);
1933 int errorCode = worker->getError ();
1942 case MSWrite::Error::Ok:
1943 kdDebug (30509) <<
"Returning error code " << ret << endl;
1946 case MSWrite::Error::Warn:
1947 kdDebug (30509) <<
"Error::Warn" << endl;
1948 return KoFilter::InternalError;
1950 case MSWrite::Error::InvalidFormat:
1951 kdDebug (30509) <<
"Error::InvalidFormat" << endl;
1952 return KoFilter::InternalError;
1954 case MSWrite::Error::OutOfMemory:
1955 kdDebug (30509) <<
"Error::OutOfMemory" << endl;
1956 return KoFilter::OutOfMemory;
1958 case MSWrite::Error::InternalError:
1959 kdDebug (30509) <<
"Error::InternalError" << endl;
1960 return KoFilter::InternalError;
1962 case MSWrite::Error::Unsupported:
1963 kdDebug (30509) <<
"Error::Unsupported" << endl;
1964 return KoFilter::InternalError;
1966 case MSWrite::Error::FileError:
1967 kdDebug (30509) <<
"Error::FileError" << endl;
1968 return KoFilter::CreationError;
1971 kdWarning (30509) <<
"Unknown error" << endl;
1972 return KoFilter::StupidError;
1975#include <mswriteexport.moc>
TQString text
text at the time of saving (no formatting info though)
Base worker of the libexport system.
virtual bool doCloseBody(void)
Like HTML's </BODY>.
virtual bool doOpenBody(void)
Like HTML's <BODY>.
double lineSpacing
Space between lines in pt, if lineSpacingType==0.
TabulatorList tabulatorList
List of tabulators.
double indentFirst
indentation correction of first line (can be negative!)
double indentRight
right indentation (a negative value means invalid)
double indentLeft
left indentation (a negative value means invalid)
TQString alignment
left, right, center, justify
int lineSpacingType
0=custom, 10=one line, 15=one and half lines, 20= 2 lines
bool underline
Any underline? (If true, we do not know if simple or double or what else).