00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <kdebug.h>
00017 #include <qfontinfo.h>
00018 #include <stddef.h>
00019 #include <string.h>
00020 #include <KoFilterChain.h>
00021 #include <kgenericfactory.h>
00022
00023 #include <qcstring.h>
00024 #include <qstringlist.h>
00025 #include <qdir.h>
00026 #include <qfileinfo.h>
00027 #include <qregexp.h>
00028 #include <qvaluelist.h>
00029
00030 #include <kurl.h>
00031 #include <kmessagebox.h>
00032
00033 #include <KoPicture.h>
00034 #include <KoFilterManager.h>
00035
00036 #include "rtfimport.h"
00037 #include "rtfimport.moc"
00038
00039 typedef KGenericFactory<RTFImport, KoFilter> RTFImportFactory;
00040 K_EXPORT_COMPONENT_FACTORY( librtfimport, RTFImportFactory( "kofficefilters" ) )
00041
00042
00043 #define PROP(a,b,c,d,e) { a, b, &RTFImport::c, d, e }
00044
00045
00046 #define MEMBER(a,b,c,d,e) PROP(a,b,c,offsetof(RTFImport,d),e)
00047
00048 static RTFProperty destinationPropertyTable[] =
00049 {
00050
00051 PROP( 0L, "@*", skipGroup, 0L, false ),
00052 MEMBER( "@info", "@author", parsePlainText, author, false ),
00053 PROP( "@pict", "@blipuid", parseBlipUid, 0, 0 ),
00054 PROP( "@rtf", "@colortbl", parseColorTable, 0L, true ),
00055 MEMBER( "@info", "@company", parsePlainText, company, false ),
00056 MEMBER( "@info", "@doccomm", parsePlainText, doccomm, false ),
00057 PROP( "Text", "@field", parseField, 0L, false ),
00058 PROP( "@field", "@fldinst", parseFldinst, 0L, false ),
00059 PROP( "@field", "@fldrslt", parseFldrslt, 0L, false ),
00060 PROP( "@rtf", "@fonttbl", parseFontTable, 0L, true ),
00061 MEMBER( "@rtf", "@footer", parseRichText, oddPagesFooter, true ),
00062 PROP( "@rtf", "@footnote", parseFootNote, 0L, true ),
00063 MEMBER( "@rtf", "@footerf", parseRichText, firstPageFooter, true ),
00064 MEMBER( "@rtf", "@footerl", parseRichText, oddPagesFooter, true ),
00065 MEMBER( "@rtf", "@footerr", parseRichText, evenPagesFooter, true ),
00066 MEMBER( "@rtf", "@header", parseRichText, oddPagesHeader, true ),
00067 MEMBER( "@rtf", "@headerf", parseRichText, firstPageHeader, true ),
00068 MEMBER( "@rtf", "@headerl", parseRichText, oddPagesHeader, true ),
00069 MEMBER( "@rtf", "@headerr", parseRichText, evenPagesHeader, true ),
00070 PROP( "@rtf", "@info", parseGroup, 0L, true ),
00071 PROP( "Text", "@nonshppict", skipGroup, 0L, false ),
00072 PROP( 0L, "@panose", skipGroup, 0L, 0 ),
00073 PROP( "Text", "@pict", parsePicture, 0L, true ),
00074 MEMBER( "@", "@rtf", parseRichText, bodyText, true ),
00075 PROP( "Text", "@shpinst", skipGroup, 0L, true ),
00076 PROP( "Text", "@shppict", parseGroup, 0L, false ),
00077 PROP( "@rtf", "@stylesheet", parseStyleSheet, 0L, true ),
00078 MEMBER( "@info", "@title", parsePlainText, title, false ),
00079 };
00080
00081 static RTFProperty propertyTable[] =
00082
00083 {
00084
00085 PROP( "Text", "\n", insertParagraph, 0L, 0 ),
00086 PROP( "Text", "\r", insertParagraph, 0L, 0 ),
00087 PROP( 0L, "\'", insertHexSymbol, 0L, 0 ),
00088 PROP( 0L, "\\", insertSymbol, 0L, '\\' ),
00089 PROP( 0L, "_", insertSymbol, 0L, 0x2011 ),
00090 PROP( 0L, "{", insertSymbol, 0L, '{' ),
00091 PROP( 0L, "|", insertSymbol, 0L, 0x00b7 ),
00092 PROP( 0L, "}", insertSymbol, 0L, '}' ),
00093 PROP( 0L, "~", insertSymbol, 0L, 0x00a0 ),
00094 PROP( 0L, "-", insertSymbol, 0L, 0x00ad ),
00095 PROP( 0L, "adjustright", ignoreKeyword, 0L, 0 ),
00096 PROP( 0L, "ansi", setAnsiCodepage, 0L, 0 ),
00097 PROP( 0L, "ansicpg", setCodepage, 0L, 0 ),
00098 MEMBER( 0L, "b", setToggleProperty, state.format.bold, 0 ),
00099
00100 MEMBER( "@colortbl", "blue", setNumericProperty, blue, 0 ),
00101 MEMBER( 0L, "box", setEnumProperty, state.layout.border, 0 ),
00102 PROP( 0L, "brdrb", selectLayoutBorder, 0L, 3 ),
00103 PROP( 0L, "brdrcf", setBorderColor, 0L, 0 ),
00104 PROP( 0L, "brdrdash", setBorderStyle, 0L, RTFBorder::Dashes ),
00105 PROP( 0L, "brdrdashd", setBorderStyle, 0L, RTFBorder::DashDot ),
00106 PROP( 0L, "brdrdashdd", setBorderStyle, 0L, RTFBorder::DashDotDot ),
00107 PROP( 0L, "brdrdashsm", setBorderStyle, 0L, RTFBorder::Dashes ),
00108 PROP( 0L, "brdrdb", setBorderStyle, 0L, RTFBorder::Solid ),
00109 PROP( 0L, "brdrdot", setBorderStyle, 0L, RTFBorder::Dots ),
00110 PROP( 0L, "brdrhairline", setBorderStyle, 0L, RTFBorder::Solid ),
00111 PROP( 0L, "brdrl", selectLayoutBorder, 0L, 0 ),
00112 PROP( 0L, "brdrr", selectLayoutBorder, 0L, 1 ),
00113 PROP( 0L, "brdrs", setBorderStyle, 0L, RTFBorder::Solid ),
00114 PROP( 0L, "brdrsh", setBorderStyle, 0L, RTFBorder::Solid ),
00115 PROP( 0L, "brdrt", selectLayoutBorder, 0L, 2 ),
00116 PROP( 0L, "brdrth", setBorderStyle, 0L, RTFBorder::Solid ),
00117 PROP( 0L, "brdrw", setBorderProperty, offsetof(RTFBorder,width), 0 ),
00118 PROP( 0L, "bullet", insertSymbol, 0L, 0x2022 ),
00119 PROP( 0L, "brsp", setBorderProperty, offsetof(RTFBorder,space), 0 ),
00120 MEMBER( 0L, "caps", setToggleProperty, state.format.caps, 0 ),
00121 MEMBER( 0L, "cb", setNumericProperty, state.format.bgcolor, 0 ),
00122 MEMBER( 0L, "highlight", setNumericProperty, state.format.bgcolor, 0 ),
00123 PROP( "Text", "cell", insertTableCell, 0L, 0 ),
00124 PROP( 0L, "cellx", insertCellDef, 0L, 0 ),
00125 MEMBER( 0L, "cf", setNumericProperty, state.format.color, 0 ),
00126 PROP( 0L, "chdate", insertDateTime, 0L, TRUE ),
00127 PROP( 0L, "chpgn", insertPageNumber, 0L, 0 ),
00128 PROP( 0L, "chtime", insertDateTime, 0L, FALSE ),
00129 PROP( 0L, "clbrdrb", selectLayoutBorderFromCell, 0L, 3 ),
00130 PROP( 0L, "clbrdrl", selectLayoutBorderFromCell, 0L, 0 ),
00131 PROP( 0L, "clbrdrr", selectLayoutBorderFromCell, 0L, 1 ),
00132 PROP( 0L, "clbrdrt", selectLayoutBorderFromCell, 0L, 2 ),
00133 MEMBER( 0L, "clcbpat", setNumericProperty, state.tableCell.bgcolor, 0 ),
00134 PROP( 0L, "cs", ignoreKeyword, 0L, 0 ),
00135 PROP( 0L, "datafield", skipGroup, 0L, 0 ),
00136 MEMBER( "@rtf", "deff", setNumericProperty, defaultFont, 0 ),
00137 MEMBER( "@rtf", "deftab", setNumericProperty, defaultTab, 0 ),
00138 PROP( "@pict", "dibitmap", setPictureType, 0L, RTFPicture::BMP ),
00139 MEMBER( 0L, "dn", setNumericProperty, state.format.baseline, 6 ),
00140 PROP( 0L, "emdash", insertSymbol, 0L, 0x2014 ),
00141 PROP( "@pict", "emfblip", setPictureType, 0L, RTFPicture::EMF ),
00142 PROP( 0L, "emspace", insertSymbol, 0L, 0x2003 ),
00143 PROP( 0L, "endash", insertSymbol, 0L, 0x2013 ),
00144 PROP( 0L, "enspace", insertSymbol, 0L, 0x2002 ),
00145 PROP( 0L, "expnd", ignoreKeyword, 0L, 0 ),
00146 PROP( 0L, "expndtw", ignoreKeyword, 0L, 0 ),
00147 MEMBER( 0L, "f", setNumericProperty, state.format.font, 0 ),
00148 MEMBER( "@rtf", "facingp", setFlagProperty, facingPages, true ),
00149 PROP( 0L, "fcharset", setCharset, 0L, 0 ),
00150 PROP( "@fonttbl", "fdecor", setFontStyleHint, 0L, QFont::Decorative ),
00151 MEMBER( 0L, "fi", setNumericProperty, state.layout.firstIndent, 0 ),
00152 PROP( "@fonttbl", "fmodern", setFontStyleHint, 0L, QFont::TypeWriter ),
00153 PROP( "@fonttbl", "fnil", setFontStyleHint, 0L, QFont::AnyStyle ),
00154 MEMBER( 0L, "footery", setNumericProperty, state.section.footerMargin, 0 ),
00155 PROP( 0L, "formshade", ignoreKeyword, 0L, 0 ),
00156 MEMBER( "@fonttbl", "fprq", setNumericProperty, font.fixedPitch, 0 ),
00157 PROP( "@fonttbl", "froman", setFontStyleHint, 0L, QFont::Serif ),
00158 MEMBER( 0L, "fs", setNumericProperty, state.format.fontSize, 0 ),
00159 PROP( "@fonttbl", "fscript", setFontStyleHint, 0L, QFont::AnyStyle ),
00160 PROP( "@fonttbl", "fswiss", setFontStyleHint, 0L, QFont::SansSerif ),
00161 PROP( "@fonttbl", "ftech", setFontStyleHint, 0L, QFont::AnyStyle ),
00162 MEMBER( "@colortbl", "green", setNumericProperty, green, 0 ),
00163 MEMBER( 0L, "headery", setNumericProperty, state.section.headerMargin, 0 ),
00164 MEMBER( 0L, "i", setToggleProperty, state.format.italic, 0 ),
00165 MEMBER( 0L, "intbl", setFlagProperty, state.layout.inTable, true ),
00166 PROP( "@pict", "jpegblip", setPictureType, 0L, RTFPicture::JPEG ),
00167 MEMBER( 0L, "keep", setFlagProperty, state.layout.keep, true ),
00168 MEMBER( 0L, "keepn", setFlagProperty, state.layout.keepNext, true ),
00169 MEMBER( "@rtf", "landscape", setFlagProperty, landscape, true ),
00170 PROP( 0L, "ldblquote", insertSymbol, 0L, 0x201c ),
00171 MEMBER( 0L, "li", setNumericProperty, state.layout.leftIndent, 0 ),
00172 PROP( 0L, "line", insertSymbol, 0L, 0x000a ),
00173 PROP( 0L, "lquote", insertSymbol, 0L, 0x2018 ),
00174 PROP( 0L, "ltrmark", insertSymbol, 0L, 0x200e ),
00175 PROP( 0L, "mac", setMacCodepage, 0L, 0 ),
00176 PROP( "@pict", "macpict", setPictureType, 0L, RTFPicture::MacPict ),
00177 MEMBER( "@rtf", "margb", setNumericProperty, bottomMargin, 0 ),
00178 MEMBER( "@rtf", "margl", setNumericProperty, leftMargin, 0 ),
00179 MEMBER( "@rtf", "margr", setNumericProperty, rightMargin, 0 ),
00180 MEMBER( "@rtf", "margt", setNumericProperty, topMargin, 0 ),
00181 MEMBER( 0L, "nosupersub", setEnumProperty, state.format.vertAlign, RTFFormat::Normal ),
00182 PROP( "Text", "page", insertPageBreak, 0L, 0 ),
00183 MEMBER( 0L, "pagebb", setFlagProperty, state.layout.pageBB, true ),
00184 MEMBER( "@rtf", "paperh", setNumericProperty, paperHeight, 0 ),
00185 MEMBER( "@rtf", "paperw", setNumericProperty, paperWidth, 0 ),
00186 PROP( "Text", "par", insertParagraph, 0L, 0 ),
00187 PROP( 0L, "pard", setParagraphDefaults, 0L, 0 ),
00188 PROP( 0L, "pc", setPcCodepage, 0L, 0 ),
00189 PROP( 0L, "pca", setPcaCodepage, 0L, 0 ),
00190 MEMBER( 0L, "pgbrk", setToggleProperty, state.layout.pageBA, true ),
00191 MEMBER( "@pict", "piccropb", setNumericProperty, picture.cropBottom, 0 ),
00192 MEMBER( "@pict", "piccropl", setNumericProperty, picture.cropLeft, 0 ),
00193 MEMBER( "@pict", "piccropr", setNumericProperty, picture.cropRight, 0 ),
00194 MEMBER( "@pict", "piccropt", setNumericProperty, picture.cropTop, 0 ),
00195 MEMBER( "@pict", "pich", setNumericProperty, picture.height, 0 ),
00196 MEMBER( "@pict", "pichgoal", setNumericProperty, picture.desiredHeight, 0 ),
00197 MEMBER( "@pict", "picscaled", setFlagProperty, picture.scaled, true ),
00198 MEMBER( "@pict", "picscalex", setNumericProperty, picture.scalex, 0 ),
00199 MEMBER( "@pict", "picscaley", setNumericProperty, picture.scaley, 0 ),
00200 MEMBER( "@pict", "picw", setNumericProperty, picture.width, 0 ),
00201 MEMBER( "@pict", "picwgoal", setNumericProperty, picture.desiredWidth, 0 ),
00202 PROP( 0L, "plain", setPlainFormatting, 0L, 0 ),
00203 PROP( "@pict", "pmmetafile", setPictureType, 0L, RTFPicture::WMF ),
00204 PROP( "@pict", "pngblip", setPictureType, 0L, RTFPicture::PNG ),
00205 MEMBER( 0L, "qc", setEnumProperty, state.layout.alignment, RTFLayout::Centered ),
00206 MEMBER( 0L, "qj", setEnumProperty, state.layout.alignment, RTFLayout::Justified ),
00207 MEMBER( 0L, "ql", setEnumProperty, state.layout.alignment, RTFLayout::Left ),
00208 PROP( 0L, "qmspace", insertSymbol, 0L, 0x2004 ),
00209 MEMBER( 0L, "qr", setEnumProperty, state.layout.alignment, RTFLayout::Right ),
00210 PROP( 0L, "rdblquote", insertSymbol, 0L, 0x201d ),
00211 MEMBER( "@colortbl", "red", setNumericProperty, red, 0 ),
00212 MEMBER( 0L, "ri", setNumericProperty, state.layout.rightIndent, 0 ),
00213 PROP( "Text", "row", insertTableRow, 0L, 0 ),
00214 PROP( 0L, "rquote", insertSymbol, 0L, 0x2019 ),
00215 PROP( 0L, "rtlmark", insertSymbol, 0L, 0x200f ),
00216 MEMBER( 0L, "s", setNumericProperty, state.layout.style, 0 ),
00217 MEMBER( 0L, "sa", setNumericProperty, state.layout.spaceAfter, 0 ),
00218 MEMBER( 0L, "sb", setNumericProperty, state.layout.spaceBefore, 0 ),
00219 MEMBER( 0L, "scaps", setToggleProperty, state.format.smallCaps, 0 ),
00220 PROP( "Text", "sect", insertPageBreak, 0L, 0 ),
00221 PROP( 0L, "sectd", setSectionDefaults, 0L, 0 ),
00222 MEMBER( 0L, "sl", setNumericProperty, state.layout.spaceBetween, 0 ),
00223 MEMBER( 0L, "slmult", setToggleProperty, state.layout.spaceBetweenMultiple, 0 ),
00224 MEMBER( "@stylesheet", "snext", setNumericProperty, style.next, 0 ),
00225 MEMBER( 0L, "strike", setToggleProperty, state.format.strike, 0 ),
00226 MEMBER( 0L, "striked", setToggleProperty, state.format.striked, 0 ),
00227 MEMBER( 0L, "sub", setEnumProperty, state.format.vertAlign, RTFFormat::SubScript ),
00228 MEMBER( 0L, "super", setEnumProperty, state.format.vertAlign, RTFFormat::SuperScript ),
00229 PROP( 0L, "tab", insertSymbol, 0L, 0x0009 ),
00230 MEMBER( 0L, "titlepg", setFlagProperty, state.section.titlePage, true ),
00231 MEMBER( 0L, "tldot", setEnumProperty, state.layout.tab.leader, RTFTab::Dots ),
00232 MEMBER( 0L, "tlhyph", setEnumProperty, state.layout.tab.leader, RTFTab::Hyphens ),
00233 MEMBER( 0L, "tlth", setEnumProperty, state.layout.tab.leader, RTFTab::ThickLine ),
00234 MEMBER( 0L, "tlul", setEnumProperty, state.layout.tab.leader, RTFTab::Underline ),
00235 MEMBER( 0L, "tqc", setEnumProperty, state.layout.tab.type, RTFTab::Centered ),
00236 MEMBER( 0L, "tqdec", setEnumProperty, state.layout.tab.type, RTFTab::Decimal ),
00237 MEMBER( 0L, "tqr", setEnumProperty, state.layout.tab.type, RTFTab::FlushRight ),
00238 MEMBER( 0L, "trleft", setNumericProperty, state.tableRow.left, 0 ),
00239 MEMBER( 0L, "trowd", setTableRowDefaults, state.tableRow, 0 ),
00240 MEMBER( 0L, "trqc", setEnumProperty, state.tableRow.alignment, RTFLayout::Centered ),
00241 MEMBER( 0L, "trql", setEnumProperty, state.tableRow.alignment, RTFLayout::Left ),
00242 MEMBER( 0L, "trqr", setEnumProperty, state.tableRow.alignment, RTFLayout::Right ),
00243 MEMBER( 0L, "trrh", setNumericProperty, state.tableRow.height, 0 ),
00244 PROP( 0L, "tx", insertTabDef, 0L, 0 ),
00245 MEMBER( 0L, "u", insertUnicodeSymbol, state.format.uc, 0 ),
00246 MEMBER( 0L, "uc", setNumericProperty, state.format.uc, 0 ),
00247 PROP( 0L, "ul", setSimpleUnderlineProperty, 0L, 0 ),
00248 MEMBER( 0L, "ulc", setNumericProperty, state.format.underlinecolor, 0 ),
00249 PROP( 0L, "uld", setUnderlineProperty, 0L, RTFFormat::UnderlineDot ),
00250 PROP( 0L, "uldash", setUnderlineProperty, 0L, RTFFormat::UnderlineDash ),
00251 PROP( 0L, "uldashd", setUnderlineProperty, 0L, RTFFormat::UnderlineDashDot ),
00252 PROP( 0L, "uldashdd", setUnderlineProperty, 0L, RTFFormat::UnderlineDashDotDot ),
00253 PROP( 0L, "uldb", setUnderlineProperty, 0L, RTFFormat::UnderlineDouble ),
00254 PROP( 0L, "ulnone", setUnderlineProperty, 0L, RTFFormat::UnderlineNone ),
00255 PROP( 0L, "ulth", setUnderlineProperty, 0L, RTFFormat::UnderlineThick ),
00256 PROP( 0L, "ulw", setUnderlineProperty, 0L, RTFFormat::UnderlineWordByWord ),
00257 PROP( 0L, "ulwave", setUnderlineProperty, 0L, RTFFormat::UnderlineWave ),
00258 PROP( 0L, "ulhwave", setUnderlineProperty, 0L, RTFFormat::UnderlineWave ),
00259 PROP( 0L, "ululdbwave", setUnderlineProperty, 0L, RTFFormat::UnderlineWave ),
00260 MEMBER( 0L, "up", setUpProperty, state.format.baseline, 6 ),
00261 MEMBER( 0L, "v", setToggleProperty, state.format.hidden, 0 ),
00262
00263 PROP( "@pict", "wbitmap", setPictureType, 0L, RTFPicture::BMP ),
00264 PROP( "@pict", "wmetafile", setPictureType, 0L, RTFPicture::EMF ),
00265 PROP( 0L, "zwj", insertSymbol, 0L, 0x200d ),
00266 PROP( 0L, "zwnj", insertSymbol, 0L, 0x200c )
00267 };
00268
00269 static RTFField fieldTable[] =
00270 {
00271
00272 { "AUTHOR", 8, 2, "NO AUTHOR" },
00273 { "FILENAME", 8, 0, "NO FILENAME" },
00274 { "TITLE", 8, 10, "NO TITLE" },
00275 { "NUMPAGES", 4, 1, 0 },
00276 { "PAGE", 4, 0, 0 },
00277 { "TIME", -1, -1, 0 },
00278 { "DATE", -1, -1, 0 },
00279 { "HYPERLINK", 9, -1, 0 },
00280 { "SYMBOL", -1, -1, 0 },
00281 { "IMPORT", -1, -1, 0 }
00282 };
00283
00284
00285
00286 static const char *alignN[4] = { "left", "right", "justify", "center" };
00287 static const char *boolN[2] = { "false", "true" };
00288 static const char *borderN[4] = { "LEFTBORDER", "RIGHTBORDER", "TOPBORDER", "BOTTOMBORDER" };
00289
00290 RTFImport::RTFImport( KoFilter *, const char *, const QStringList& )
00291 : KoFilter(), properties(181), destinationProperties(29), textCodec(0), utf8TextCodec(0)
00292 {
00293 for (uint i=0; i < sizeof(propertyTable) / sizeof(propertyTable[0]); i++)
00294 {
00295 properties.insert( propertyTable[i].name, &propertyTable[i] );
00296 }
00297 for (uint i=0; i < sizeof(destinationPropertyTable) / sizeof(destinationPropertyTable[0]); i++)
00298 {
00299 destinationProperties.insert( destinationPropertyTable[i].name, &destinationPropertyTable[i] );
00300 }
00301
00302
00303 kdDebug(30515) << properties.count() << " normal and " << destinationProperties.count() << " destination keywords loaded" << endl;
00304 if (properties.size() < properties.count())
00305 kdWarning(30515) << "Hash size of properties too small: " << properties.size() << ". It should be at least " << properties.count() << " and be a prime number"<< endl;
00306 if (destinationProperties.size() < destinationProperties.count())
00307 kdWarning(30515) << "Hash size of destinationProperties too small: " << destinationProperties.size() << ". It should be at least " << destinationProperties.count() << " and be a prime number"<< endl;
00308
00309 fnnum=0;
00310 }
00311
00312 KoFilter::ConversionStatus RTFImport::convert( const QCString& from, const QCString& to )
00313 {
00314
00315 if ((from != "text/rtf") || (to != "application/x-kword"))
00316 return KoFilter::NotImplemented;
00317
00318 QTime debugTime;
00319 debugTime.start();
00320
00321
00322 m_batch=false;
00323 if ( m_chain->manager() )
00324 m_batch = m_chain->manager()->getBatchMode();
00325
00326
00327 inFileName = m_chain->inputFile();
00328 QFile in( inFileName );
00329
00330 if (!in.open( IO_ReadOnly ))
00331 {
00332 kdError(30515) << "Unable to open input file!" << endl;
00333 in.close();
00334 if ( !m_batch )
00335 {
00336 KMessageBox::error( 0L,
00337 i18n("The file cannot be loaded, as it cannot be opened."),
00338 i18n("KWord's RTF Import Filter"), 0 );
00339 }
00340 return KoFilter::FileNotFound;
00341 }
00342
00343
00344 token.open( &in );
00345 token.next();
00346
00347 if (token.type != RTFTokenizer::OpenGroup)
00348 {
00349 kdError(30515) << "Not an RTF file" << endl;
00350 in.close();
00351 if ( !m_batch )
00352 {
00353 KMessageBox::error( 0L,
00354 i18n("The file cannot be loaded, as it seems not to be an RTF document."),
00355 i18n("KWord's RTF Import Filter"), 0 );
00356 }
00357 return KoFilter::WrongFormat;
00358 }
00359
00360
00361
00362 token.next();
00363
00364 if (token.type != RTFTokenizer::ControlWord)
00365 {
00366 kdError(30515) << "Wrong document type" << endl;
00367 in.close();
00368 if ( !m_batch )
00369 {
00370 KMessageBox::error( 0L,
00371 i18n("The document cannot be loaded, as it seems not to follow the RTF syntax."),
00372 i18n("KWord's RTF Import Filter"), 0 );
00373 }
00374 return KoFilter::WrongFormat;
00375 }
00376
00377 bool force = false;
00378 if ( !qstrcmp( token.text, "rtf" ) )
00379 {
00380
00381 if ( token.value > 1 )
00382 {
00383 kdError(30515) << "Wrong RTF version (" << token.value << "); version 0 or 1 expected" << endl;
00384 if ( !m_batch )
00385 {
00386 force = ( KMessageBox::warningYesNo( 0L,
00387 i18n("The RTF (Rich Text Format) document has an unexpected version number: %1. Continuing might result in an erroneous conversion. Do you want to continue?").arg( token.value ),
00388 i18n("KWord's RTF Import Filter") ) == KMessageBox::Yes );
00389 }
00390 if ( !force )
00391 {
00392 in.close();
00393 return KoFilter::WrongFormat;
00394 }
00395 }
00396 }
00397 else if ( !qstrcmp( token.text, "pwd" ) )
00398 {
00399
00400 if ( token.value != 2 )
00401 {
00402 kdError(30515) << "Wrong PWD version (" << token.value << "); version 2 expected" << endl;
00403 if ( !m_batch )
00404 {
00405 force = ( KMessageBox::warningYesNo( 0L,
00406 i18n("The PWD (PocketWord's Rich Text Format) document has an unexpected version number: %1. Continuing might result in an erroneous conversion. Do you want to continue?").arg( token.value ),
00407 i18n("KWord's RTF Import Filter") ) == KMessageBox::Yes );
00408 }
00409 if ( !force )
00410 {
00411 in.close();
00412 return KoFilter::WrongFormat;
00413 }
00414 }
00415 }
00416 else if ( !qstrcmp( token.text, "urtf" ) )
00417 {
00418
00419 if ( token.value > 1 )
00420 {
00421 kdError(30515) << "Wrong URTF version (" << token.value << "); version 0 or 1 expected" << endl;
00422 if ( !m_batch )
00423 {
00424 force = ( KMessageBox::warningYesNo( 0L,
00425 i18n("The URTF (\"Unicode Rich Text Format\") document has an unexpected version number: %1. Continuing might result in an erroneous conversion. Do you want to continue?").arg( token.value ),
00426 i18n("KWord's RTF Import Filter") ) == KMessageBox::Yes );
00427 }
00428 if ( !force )
00429 {
00430 in.close();
00431 return KoFilter::WrongFormat;
00432 }
00433 }
00434 }
00435 else
00436 {
00437 kdError(30515) << "Wrong RTF document type (\\" << token.text << "); \\rtf, \\pwd or \\urtf expected" << endl;
00438 in.close();
00439 if ( !m_batch )
00440 {
00441 KMessageBox::error( 0L,
00442 i18n("The RTF document cannot be loaded, as it has an unexpected first keyword: \\%1.").arg( token.text ),
00443 i18n("KWord's RTF Import Filter"), 0 );
00444 }
00445 return KoFilter::WrongFormat;
00446 }
00447
00448 table = 0;
00449 pictureNumber = 0;
00450
00451
00452 paperWidth = 12240;
00453 paperHeight = 15840;
00454 leftMargin = 1800;
00455 topMargin = 1440;
00456 rightMargin = 1800;
00457 bottomMargin= 1440;
00458 defaultTab = 720;
00459 defaultFont = 0;
00460 landscape = false;
00461 facingPages = false;
00462
00463
00464 frameSets.clear( 2 );
00465 pictures.clear();
00466 bodyText.node.clear( 3 );
00467 firstPageHeader.node.clear( 3 );
00468 oddPagesHeader.node.clear( 3 );
00469 evenPagesHeader.node.clear( 3 );
00470 firstPageFooter.node.clear( 3 );
00471 oddPagesFooter.node.clear( 3 );
00472 evenPagesFooter.node.clear( 3 );
00473 author.clear();
00474 company.clear();
00475 title.clear();
00476 doccomm.clear();
00477
00478 stateStack.push( state );
00479
00480
00481 destination.name = "!stackbottom";
00482
00483 changeDestination( destinationProperties["@rtf"] );
00484
00485 flddst = -1;
00486 emptyCell = state.tableCell;
00487 state.format.uc=1;
00488 state.ignoreGroup = false;
00489
00490 utf8TextCodec=QTextCodec::codecForName("UTF-8");
00491 kdDebug(30515) << "UTF-8 asked, given: " << (utf8TextCodec?utf8TextCodec->name():QString("-none-")) << endl;
00492
00493
00494 textCodec=QTextCodec::codecForName("CP 1252");
00495 kdDebug(30515) << "CP 1252 asked, given: " << (textCodec?textCodec->name():QString("-none-")) << endl;
00496
00497
00498 while (true)
00499 {
00500 bool firstToken = false;
00501 bool ignoreUnknown = false;
00502
00503 token.next();
00504
00505 while (token.type == RTFTokenizer::OpenGroup)
00506 {
00507
00508 stateStack.push( state );
00509 state.brace0 = false;
00510 firstToken = true;
00511 ignoreUnknown = false;
00512
00513 token.next();
00514
00515 if (token.type == RTFTokenizer::ControlWord && !qstrcmp( token.text, "*" ))
00516 {
00517
00518 ignoreUnknown = true;
00519 token.next();
00520 }
00521 }
00522 if (token.type == RTFTokenizer::CloseGroup)
00523 {
00524 if (state.brace0)
00525 {
00526
00527 (this->*destination.destproc)(0L);
00528
00529 if (destinationStack.isEmpty())
00530 {
00531 kdWarning(30515) << "Destination stack is empty! Document might be buggy!" << endl;
00532
00533 }
00534 else
00535 {
00536 destination = destinationStack.pop();
00537 }
00538 }
00539
00540 if (stateStack.count() <= 1)
00541 {
00542
00543 stateStack.pop();
00544 break;
00545 }
00546 else
00547 {
00548
00549 state = stateStack.pop();
00550 }
00551 }
00552 else if (token.type == RTFTokenizer::ControlWord)
00553 {
00554 RTFProperty *property = properties[token.text];
00555
00556 if (property != 0L)
00557 {
00558 if (property->onlyValidIn == 0L ||
00559 property->onlyValidIn == destination.name ||
00560 property->onlyValidIn == destination.group)
00561 {
00562 (this->*property->cwproc)( property );
00563 }
00564 }
00565 else if (firstToken)
00566 {
00567
00568 *(--token.text) = '@';
00569 property = destinationProperties[token.text];
00570
00571 if ((property != 0L) &&
00572 (property->onlyValidIn == 0L ||
00573 property->onlyValidIn == destination.name ||
00574 property->onlyValidIn == destination.group))
00575 {
00576
00577 changeDestination( property );
00578 }
00579 else if (ignoreUnknown)
00580 {
00581
00582 changeDestination( destinationProperties["@*"] );
00583 debugUnknownKeywords[token.text]++;
00584 }
00585 else if ( !property )
00586 {
00587 kdWarning(30515) << "Unknown first non-ignorable token of a group: " << token.text << endl; kdDebug(30515) << "Destination: " << ( (void*) destination.name ) << " Destination stack depth: " << destinationStack.count() << endl;
00588
00589 kdWarning(30515) << " Assuming destination: " << destination.name << endl;
00590 debugUnknownKeywords[token.text]++;
00591 }
00592 }
00593 else
00594 {
00595 debugUnknownKeywords[token.text]++;
00596 }
00597 }
00598 else if (token.type == RTFTokenizer::PlainText || token.type == RTFTokenizer::BinaryData)
00599 {
00600 (this->*destination.destproc)(0L);
00601 }
00602 }
00603
00604
00605 const int hType = facingPages
00606 ? (state.section.titlePage ? 3 : 1) : (state.section.titlePage ? 2 : 0);
00607
00608 const bool hasHeader = !oddPagesHeader.node.isEmpty() ||
00609 (facingPages &&!evenPagesHeader.node.isEmpty()) ||
00610 (state.section.titlePage && !firstPageHeader.node.isEmpty());
00611 const bool hasFooter = !oddPagesFooter.node.isEmpty() ||
00612 (facingPages && !evenPagesFooter.node.isEmpty()) ||
00613 (state.section.titlePage && !firstPageFooter.node.isEmpty());
00614
00615 kdDebug(30515) << "hType " << hType << " hasHeader " << hasHeader << " hasFooter " << hasFooter << endl;
00616
00617
00618 DomNode mainDoc( "DOC" );
00619 mainDoc.setAttribute( "mime", "application/x-kword" );
00620 mainDoc.setAttribute( "syntaxVersion", "3" );
00621 mainDoc.setAttribute( "editor", "KWord's RTF Import Filter" );
00622 mainDoc.addNode( "PAPER" );
00623 mainDoc.setAttribute( "format", 6 );
00624 mainDoc.setAttribute( "columns", 1 );
00625 mainDoc.setAttribute( "columnspacing", 2 );
00626 mainDoc.setAttribute( "spHeadBody", 4 );
00627 mainDoc.setAttribute( "spFootBody", 4 );
00628 mainDoc.setAttribute( "zoom", 100 );
00629 mainDoc.setAttribute( "width", .05*paperWidth );
00630 mainDoc.setAttribute( "height", .05*paperHeight );
00631 mainDoc.setAttribute( "orientation", landscape );
00632 mainDoc.setAttribute( "hType", hType );
00633 mainDoc.setAttribute( "fType", hType );
00634 mainDoc.addNode( "PAPERBORDERS" );
00635 mainDoc.addRect( leftMargin,
00636 (hasHeader ? state.section.headerMargin : topMargin),
00637 rightMargin,
00638 (hasFooter ? state.section.footerMargin : bottomMargin) );
00639 mainDoc.closeNode( "PAPERBORDERS" );
00640 mainDoc.closeNode( "PAPER" );
00641 mainDoc.addNode( "ATTRIBUTES" );
00642 mainDoc.setAttribute( "standardpage", 1 );
00643 mainDoc.setAttribute( "processing", 0 );
00644
00645 mainDoc.setAttribute( "hasHeader", hasHeader );
00646 mainDoc.setAttribute( "hasFooter", hasFooter );
00647 mainDoc.closeNode( "ATTRIBUTES" );
00648 mainDoc.addNode( "FRAMESETS" );
00649 mainDoc.addFrameSet( "Frameset 1", 1, 0 );
00650 mainDoc.addFrame( leftMargin, topMargin, (paperWidth - rightMargin),
00651 (paperHeight - bottomMargin), 1, 0, 0 );
00652 mainDoc.closeNode( "FRAME" );
00653 mainDoc.appendNode( bodyText.node );
00654 mainDoc.closeNode( "FRAMESET" );
00655
00656 if (hasHeader)
00657 {
00658 mainDoc.addFrameSet( "First Page Header", 1, 1 );
00659 mainDoc.addFrame( leftMargin, state.section.headerMargin,
00660 (paperWidth - rightMargin), (topMargin - 80), 0, 2, 0 );
00661 mainDoc.closeNode( "FRAME" );
00662 mainDoc.appendNode( firstPageHeader.node );
00663 mainDoc.closeNode( "FRAMESET" );
00664 mainDoc.addFrameSet( "Odd Pages Header", 1, 2 );
00665 mainDoc.addFrame( leftMargin, state.section.headerMargin,
00666 (paperWidth - rightMargin), (topMargin - 80), 0, 2, 1 );
00667 mainDoc.closeNode( "FRAME" );
00668 mainDoc.appendNode( oddPagesHeader.node );
00669 mainDoc.closeNode( "FRAMESET" );
00670 mainDoc.addFrameSet( "Even Pages Header", 1, 3 );
00671 mainDoc.addFrame( leftMargin, state.section.headerMargin,
00672 (paperWidth - rightMargin), (topMargin - 80), 0, 2, 2 );
00673 mainDoc.closeNode( "FRAME" );
00674 mainDoc.appendNode( evenPagesHeader.node );
00675 mainDoc.closeNode( "FRAMESET" );
00676 }
00677
00678 if (hasFooter)
00679 {
00680 mainDoc.addFrameSet( "First Page Footer", 1, 4 );
00681 mainDoc.addFrame( leftMargin, state.section.headerMargin,
00682 (paperWidth - rightMargin), (topMargin - 80), 0, 2, 0 );
00683 mainDoc.closeNode( "FRAME" );
00684 mainDoc.appendNode( firstPageFooter.node );
00685 mainDoc.closeNode( "FRAMESET" );
00686 mainDoc.addFrameSet( "Odd Pages Footer", 1, 5 );
00687 mainDoc.addFrame( leftMargin, state.section.headerMargin,
00688 (paperWidth - rightMargin), (topMargin - 80), 0, 2, 1 );
00689 mainDoc.closeNode( "FRAME" );
00690 mainDoc.appendNode( oddPagesFooter.node );
00691 mainDoc.closeNode( "FRAMESET" );
00692 mainDoc.addFrameSet( "Even Pages Footer", 1, 6 );
00693 mainDoc.addFrame( leftMargin, state.section.headerMargin,
00694 (paperWidth - rightMargin), (topMargin - 80), 0, 2, 2 );
00695 mainDoc.closeNode( "FRAME" );
00696 mainDoc.appendNode( evenPagesFooter.node );
00697 mainDoc.closeNode( "FRAMESET" );
00698 }
00699
00700 int num=1;
00701 for(RTFTextState* i=footnotes.first();i;i=footnotes.next())
00702 {
00703 QCString str;
00704 str.setNum(num);
00705 str.prepend("Footnote ");
00706 num++;
00707 mainDoc.addFrameSet( str, 1, 7 );
00708 mainDoc.addFrame( leftMargin, paperHeight - bottomMargin-80,
00709 (paperWidth - rightMargin), paperHeight-bottomMargin, 0, 2, 0 );
00710 mainDoc.closeNode( "FRAME" );
00711 mainDoc.appendNode( i->node );
00712 mainDoc.closeNode( "FRAMESET" );
00713 }
00714 mainDoc.appendNode( frameSets );
00715 mainDoc.closeNode( "FRAMESETS" );
00716 mainDoc.addNode( "PICTURES" );
00717 mainDoc.appendNode( pictures );
00718 mainDoc.closeNode( "PICTURES" );
00719 mainDoc.addNode( "STYLES" );
00720 kwFormat.id = 1;
00721 kwFormat.pos = 0;
00722 kwFormat.len = 0;
00723
00724
00725 const QValueList<RTFStyle>::ConstIterator endStyleSheet=styleSheet.end();
00726 for (QValueList<RTFStyle>::ConstIterator it=styleSheet.begin();it!=endStyleSheet;++it)
00727 {
00728 mainDoc.addNode( "STYLE" );
00729 kwFormat.fmt = (*it).format;
00730
00731
00732 for (QValueList<RTFStyle>::ConstIterator it2=styleSheet.begin();it2!=endStyleSheet;++it2)
00733 {
00734 if ((*it2).layout.style == (*it).next)
00735 {
00736 mainDoc.addNode( "FOLLOWING" );
00737 mainDoc.setAttribute( "name", CheckAndEscapeXmlText( (*it2).name ));
00738 mainDoc.closeNode( "FOLLOWING");
00739 break;
00740 }
00741 }
00742 addLayout( mainDoc, (*it).name, (*it).layout, false );
00743 addFormat( mainDoc, kwFormat, 0L );
00744 mainDoc.closeNode( "STYLE" );
00745 }
00746 mainDoc.closeNode( "STYLES" );
00747 mainDoc.closeNode( "DOC" );
00748
00749
00750 DomNode docInfo( "document-info" );
00751 docInfo.addNode( "log" );
00752 docInfo.addNode( "text" );
00753 docInfo.closeNode( "text" );
00754 docInfo.closeNode( "log" );
00755 docInfo.addNode( "author" );
00756 docInfo.addNode( "company" );
00757 docInfo.appendNode( company );
00758 docInfo.closeNode( "company" );
00759 docInfo.addNode( "full-name" );
00760 docInfo.appendNode( author );
00761 docInfo.closeNode( "full-name" );
00762 docInfo.addNode( "email" );
00763 docInfo.closeNode( "email" );
00764 docInfo.addNode( "telephone" );
00765 docInfo.closeNode( "telephone" );
00766 docInfo.addNode( "fax" );
00767 docInfo.closeNode( "fax" );
00768 docInfo.addNode( "country" );
00769 docInfo.closeNode( "country" );
00770 docInfo.addNode( "postal-code" );
00771 docInfo.closeNode( "postal-code" );
00772 docInfo.addNode( "city" );
00773 docInfo.closeNode( "city" );
00774 docInfo.addNode( "street" );
00775 docInfo.closeNode( "street" );
00776 docInfo.closeNode( "author" );
00777 docInfo.addNode( "about" );
00778 docInfo.addNode( "abstract" );
00779 docInfo.appendNode( doccomm );
00780 docInfo.closeNode( "abstract" );
00781 docInfo.addNode( "title" );
00782 docInfo.appendNode( title );
00783 docInfo.closeNode( "title" );
00784 docInfo.closeNode( "about" );
00785 docInfo.closeNode( "document-info" );
00786
00787
00788 writeOutPart( "root", mainDoc );
00789 writeOutPart( "documentinfo.xml", docInfo );
00790 in.close();
00791
00792 kdDebug(30515) << "RTF FILTER TIME: " << debugTime.elapsed() << endl;
00793
00794 for (QMap<QString,int>::ConstIterator it=debugUnknownKeywords.begin();
00795 it!=debugUnknownKeywords.end();it++)
00796 kdDebug(30515) << "Unknown keyword: " << QString( "%1" ).arg( it.data(), 4 ) << " * " << it.key() << endl;
00797
00798 return KoFilter::OK;
00799 }
00800
00801 void RTFImport::ignoreKeyword( RTFProperty * )
00802 {
00803 }
00804
00805 void RTFImport::setCodepage( RTFProperty * )
00806 {
00807 QTextCodec* oldCodec = textCodec;
00808 QCString cp;
00809 if ( token.value == 10000 )
00810 {
00811 cp = "Apple Roman";
00812 }
00813 else
00814 {
00815 cp.setNum( token.value );
00816 cp.prepend("CP");
00817 }
00818 textCodec=QTextCodec::codecForName(cp);
00819 kdDebug(30515) << "\\ansicpg: codepage: " << token.value << "asked: "<< cp << " given: " << (textCodec?textCodec->name():QString("-none-")) << endl;
00820 if ( ! textCodec )
00821 textCodec = oldCodec;
00822 }
00823
00824 void RTFImport::setMacCodepage( RTFProperty * )
00825 {
00826 QTextCodec* oldCodec = textCodec;
00827 textCodec=QTextCodec::codecForName("Apple Roman");
00828 kdDebug(30515) << "\\mac " << (textCodec?textCodec->name():QString("-none-")) << endl;
00829 if ( ! textCodec )
00830 textCodec = oldCodec;
00831 }
00832
00833 void RTFImport::setAnsiCodepage( RTFProperty * )
00834 {
00835 QTextCodec* oldCodec = textCodec;
00836 textCodec=QTextCodec::codecForName("CP1252");
00837 kdDebug(30515) << "\\ansi " << (textCodec?textCodec->name():QString("-none-")) << endl;
00838 if ( ! textCodec )
00839 textCodec = oldCodec;
00840 }
00841
00842 void RTFImport::setPcaCodepage( RTFProperty * )
00843 {
00844 QTextCodec* oldCodec = textCodec;
00845 textCodec=QTextCodec::codecForName("IBM 850");
00846 kdDebug(30515) << "\\pca " << (textCodec?textCodec->name():QString("-none-")) << endl;
00847 if ( ! textCodec )
00848 textCodec = oldCodec;
00849 }
00850
00851 void RTFImport::setPcCodepage( RTFProperty * )
00852 {
00853 QTextCodec* oldCodec = textCodec;
00854 textCodec=QTextCodec::codecForName("IBM 850");
00855 kdDebug(30515) << "\\pc (approximation) " << (textCodec?textCodec->name():QString("-none-")) << endl;
00856 if ( ! textCodec )
00857 textCodec = oldCodec;
00858 }
00859
00860 void RTFImport::setToggleProperty( RTFProperty *property )
00861 {
00862 ((bool *)this)[property->offset] = (!token.hasParam || token.value != 0);
00863 }
00864
00865 void RTFImport::setFlagProperty( RTFProperty *property )
00866 {
00867 ((bool *)this)[property->offset] = property->value;
00868 }
00869
00870 void RTFImport::setCharset( RTFProperty *property )
00871 {
00872 QCString cp;
00873 switch(token.value) {
00874 case 0: cp = "CP1252"; break;
00875 case 1: cp = "CP1252"; break;
00876
00877 case 77: cp = "Apple Roman"; break;
00878 case 128: cp = "Shift-JIS"; break;
00879 case 129: cp = "eucKR"; break;
00880 case 130: cp = "CP1361"; break;
00881 case 134: cp = "GB2312"; break;
00882 case 136: cp = "Big5-HKSCS"; break;
00883 case 161: cp = "CP1253"; break;
00884 case 162: cp = "CP1254"; break;
00885 case 163: cp = "CP1258"; break;
00886 case 177: cp = "CP1255"; break;
00887 case 178: cp = "CP1256"; break;
00888 case 186: cp = "CP1257"; break;
00889 case 204: cp = "CP1251"; break;
00890 case 222: cp = "CP874"; break;
00891 case 238: cp = "CP1250"; break;
00892 case 255: cp = "CP850"; break;
00893 default: return;
00894 }
00895 QTextCodec* oldCodec = textCodec;
00896 textCodec=QTextCodec::codecForName(cp);
00897 kdDebug(30515) << "\\fcharset: charset: " << token.value << " codepage: "<< cp << " given: " << (textCodec?textCodec->name():QString("-none-")) << endl;
00898 if ( ! textCodec )
00899 textCodec = oldCodec;
00900 }
00901
00902 void RTFImport::setNumericProperty( RTFProperty *property )
00903 {
00904 *((int *)(((char *)this) + property->offset)) = token.hasParam ? token.value : property->value;
00905 }
00906
00907 void RTFImport::setEnumProperty( RTFProperty *property )
00908 {
00909 *((int *)(((char *)this) + property->offset)) = property->value;
00910 }
00911
00912 void RTFImport::setFontStyleHint( RTFProperty* property )
00913 {
00914 font.styleHint = QFont::StyleHint( property->value );
00915 }
00916
00917 void RTFImport::setPictureType( RTFProperty* property )
00918 {
00919 picture.type = RTFPicture::PictureType( property->value );
00920 }
00921
00922 void RTFImport::setSimpleUnderlineProperty( RTFProperty* )
00923 {
00924 state.format.underline
00925 = (!token.hasParam || token.value != 0)
00926 ? RTFFormat::UnderlineSimple : RTFFormat::UnderlineNone;
00927 }
00928
00929 void RTFImport::setUnderlineProperty( RTFProperty* property )
00930 {
00931 state.format.underline = RTFFormat::Underline( property->value );
00932 }
00933
00934 void RTFImport::setBorderStyle( RTFProperty *property )
00935 {
00936 if (state.layout.border)
00937 {
00938 state.layout.border->style = static_cast <RTFBorder::BorderStyle> ( property->value );
00939 }
00940 else
00941 {
00942 for (uint i=0; i < 4; i++)
00943 {
00944 state.layout.borders[i].style = static_cast <RTFBorder::BorderStyle> ( property->value );
00945 }
00946 }
00947 }
00948
00949 void RTFImport::setBorderProperty( RTFProperty *property )
00950 {
00951
00952 if (state.layout.border)
00953 {
00954 state.layout.border->width = token.value;
00955 }
00956 else
00957 {
00958 for (uint i=0; i < 4; i++)
00959 {
00960 state.layout.borders[i].width = token.value;
00961 }
00962 }
00963 }
00964
00965 void RTFImport::setBorderColor( RTFProperty * )
00966 {
00967 if (state.layout.border)
00968 {
00969 state.layout.border->color = token.value;
00970 }
00971 else
00972 {
00973 for (uint i=0; i < 4; i++)
00974 {
00975 state.layout.borders[i].color = token.value;
00976 }
00977 }
00978 }
00979
00980 void RTFImport::setUpProperty( RTFProperty * )
00981 {
00982 state.format.baseline = token.hasParam ? -token.value : -6;
00983 }
00984
00985 void RTFImport::setPlainFormatting( RTFProperty * )
00986 {
00987 RTFFormat &format = state.format;
00988
00989 format.font = defaultFont;
00990 format.fontSize = 24;
00991 format.baseline = 0;
00992 format.color = -1;
00993 format.bgcolor = -1;
00994 format.underlinecolor = -1;
00995 format.vertAlign = RTFFormat::Normal;
00996 format.bold = false;
00997 format.italic = false;
00998 format.strike = false;
00999 format.striked = false;
01000 format.hidden = false;
01001 format.caps = false;
01002 format.smallCaps = false;
01003
01004 format.underline = RTFFormat::UnderlineNone;
01005
01006
01007 }
01008
01009 void RTFImport::setParagraphDefaults( RTFProperty * )
01010 {
01011 RTFLayout &layout = state.layout;
01012
01013 layout.tablist.clear();
01014 layout.tab.type = RTFTab::Left;
01015 layout.tab.leader = RTFTab::None;
01016
01017 for (uint i=0; i < 4; i++)
01018 {
01019 RTFBorder &border = layout.borders[i];
01020 border.color = -1;
01021 border.width = 0;
01022 border.style = RTFBorder::None;
01023 }
01024 layout.firstIndent = 0;
01025 layout.leftIndent = 0;
01026 layout.rightIndent = 0;
01027 layout.spaceBefore = 0;
01028 layout.spaceAfter = 0;
01029 layout.spaceBetween = 0;
01030 layout.spaceBetweenMultiple = false;
01031 layout.style = 0;
01032 layout.alignment = RTFLayout::Left;
01033 layout.border = 0L;
01034 layout.inTable = false;
01035 layout.keep = false;
01036 layout.keepNext = false;
01037 layout.pageBB = false;
01038 layout.pageBA = false;
01039 }
01040
01041 void RTFImport::setSectionDefaults( RTFProperty * )
01042 {
01043 RTFSectionLayout §ion = state.section;
01044
01045 section.headerMargin = 720;
01046 section.footerMargin = 720;
01047 section.titlePage = false;
01048 }
01049
01050 void RTFImport::setTableRowDefaults( RTFProperty * )
01051 {
01052 RTFTableRow &tableRow = state.tableRow;
01053 RTFTableCell &tableCell = state.tableCell;
01054
01055 tableRow.height = 0;
01056 tableRow.left = 0;
01057 tableRow.alignment = RTFLayout::Left;
01058 tableRow.cells.clear();
01059 tableCell.bgcolor = -1;
01060
01061 for (uint i=0; i < 4; i++)
01062 {
01063 RTFBorder &border = tableCell.borders[i];
01064 border.color = -1;
01065 border.width = 0;
01066 border.style = RTFBorder::None;
01067 }
01068 }
01069
01070 void RTFImport::selectLayoutBorder( RTFProperty * property )
01071 {
01072 state.layout.border = & state.layout.borders [ property->value ];
01073 }
01074
01075 void RTFImport::selectLayoutBorderFromCell( RTFProperty * property )
01076 {
01077 state.layout.border = & state.tableCell.borders [ property->value ];
01078 }
01079
01080 void RTFImport::insertParagraph( RTFProperty * )
01081 {
01082 if (state.layout.inTable)
01083 {
01084 if (textState->table == 0)
01085 {
01086
01087 textState->table = ++table;
01088 }
01089 addParagraph( textState->cell, false );
01090 }
01091 else
01092 {
01093 if (textState->table)
01094 {
01095 finishTable();
01096 }
01097 addParagraph( textState->node, false );
01098 }
01099 }
01100
01101 void RTFImport::insertPageBreak( RTFProperty * )
01102 {
01103 if (textState->length > 0)
01104 {
01105 insertParagraph();
01106 }
01107 addParagraph( textState->node, true );
01108 }
01109
01110 void RTFImport::insertTableCell( RTFProperty * )
01111 {
01112
01113 bool b = state.layout.inTable;
01114 state.layout.inTable = true;
01115 insertParagraph();
01116 state.layout.inTable = b;
01117
01118 textState->frameSets << textState->cell.toString();
01119 textState->cell.clear( 3 );
01120 }
01121
01122 void RTFImport::insertTableRow( RTFProperty * )
01123 {
01124 if (!textState->frameSets.isEmpty())
01125 {
01126 RTFTableRow row = state.tableRow;
01127 row.frameSets = textState->frameSets;
01128
01129 if (textState->rows.isEmpty())
01130 {
01131 char buf[64];
01132 sprintf( buf, "Table %d", textState->table );
01133 RTFLayout::Alignment align = row.alignment;
01134
01135
01136 stateStack.push( state );
01137 resetState();
01138 state.layout.alignment = align;
01139
01140
01141 addAnchor( buf );
01142 addParagraph( textState->node, false );
01143
01144
01145 state = stateStack.pop();
01146 }
01147
01148
01149 while (row.cells.count() > row.frameSets.count())
01150 {
01151
01152 row.cells.pop_back();
01153 }
01154 while (row.cells.count() < row.frameSets.count())
01155 {
01156 row.cells << row.cells.last();
01157 }
01158 int lx = row.left;
01159
01160
01161 if (row.height == 0)
01162 {
01163 row.height = 1;
01164 }
01165
01166 for (uint k=0; k < row.cells.count(); k++)
01167 {
01168 if ((row.cells[k].x - lx) < 1)
01169 row.cells[k].x = ++lx;
01170 else
01171 lx = row.cells[k].x;
01172 }
01173 if (row.left < 0)
01174 {
01175
01176 for (uint k=0; k < row.cells.count(); k++)
01177 {
01178 row.cells[k].x -= row.left;
01179 }
01180 row.left = 0;
01181 }
01182 textState->rows << row;
01183 textState->frameSets.clear();
01184 }
01185 }
01186
01187 void RTFImport::insertCellDef( RTFProperty * )
01188 {
01189 RTFTableCell &cell = state.tableCell;
01190 cell.x = token.value;
01191 state.tableRow.cells << cell;
01192 cell.bgcolor = -1;
01193
01194 for (uint i=0; i < 4; i++)
01195 {
01196 RTFBorder &border = cell.borders[i];
01197 border.color = -1;
01198 border.width = 0;
01199 border.style = RTFBorder::None;
01200 }
01201 }
01202
01203 void RTFImport::insertTabDef( RTFProperty * )
01204 {
01205 RTFTab tab = state.layout.tab;
01206 tab.position = token.value;
01207 state.layout.tablist.push( tab );
01208 tab.type = RTFTab::Left;
01209 tab.leader = RTFTab::None;
01210 }
01211
01212 void RTFImport::insertUTF8( int ch )
01213 {
01214 kdDebug(30515) << "insertUTF8: " << ch << endl;
01215 char buf[4];
01216 char *text = buf;
01217 char *tk = token.text;
01218 token.type = RTFTokenizer::PlainText;
01219 token.text = buf;
01220
01221
01222
01223
01224
01225 if (ch > 0x007f)
01226 {
01227 if (ch > 0x07ff)
01228 {
01229 *text++ = 0xe0 | (ch >> 12);
01230 ch = (ch & 0xfff) | 0x1000;
01231 }
01232 *text++ = ((ch >> 6) | 0x80) ^ 0x40;
01233 ch = (ch & 0x3f) | 0x80;
01234 }
01235 *text++ = ch;
01236 *text++ = 0;
01237
01238 QTextCodec* oldCodec=textCodec;
01239
01240 if (utf8TextCodec)
01241 textCodec=utf8TextCodec;
01242 else
01243 kdError(30515) << "No UTF-8 QTextCodec available" << endl;
01244
01245 (this->*destination.destproc)(0L);
01246
01247 textCodec=oldCodec;
01248 token.text = tk;
01249 }
01250
01251 void RTFImport::insertSymbol( RTFProperty *property )
01252 {
01253 insertUTF8( property->value );
01254 }
01255
01256 void RTFImport::insertHexSymbol( RTFProperty * )
01257 {
01258
01259
01260
01261
01262
01263
01264
01265 if ( !token.value )
01266 {
01267 kdWarning(30515) << "Trying to insert NUL character!" << endl;
01268 return;
01269 }
01270
01271 char tmpch[2] = {token.value, '\0'};
01272
01273 char *tk = token.text;
01274 token.type = RTFTokenizer::PlainText;
01275 token.text = tmpch;
01276
01277 (this->*destination.destproc)(0L);
01278
01279 token.text = tk;
01280 }
01281
01282 void RTFImport::insertUnicodeSymbol( RTFProperty * )
01283 {
01284 const int ch = token.value;
01285
01286
01287 for (uint i=state.format.uc; i > 0; )
01288 {
01289 token.next();
01290
01291 if (token.type == RTFTokenizer::ControlWord)
01292 --i;
01293 else if (token.type == RTFTokenizer::OpenGroup ||
01294 token.type == RTFTokenizer::CloseGroup)
01295 {
01296 break;
01297 }
01298 else if (token.type == RTFTokenizer::PlainText)
01299 {
01300 const uint len = qstrlen( token.text );
01301 if ( len < i )
01302 i -= len;
01303 else
01304 {
01305 token.text += i;
01306 break;
01307 }
01308 }
01309 }
01310 if (token.type != RTFTokenizer::PlainText)
01311 {
01312 token.type = RTFTokenizer::PlainText;
01313 token.text[0] = 0;
01314 }
01315 insertUTF8( ch );
01316 (this->*destination.destproc)(0L);
01317 }
01318
01319 void RTFImport::parseFontTable( RTFProperty * )
01320 {
01321 if (token.type == RTFTokenizer::OpenGroup)
01322 {
01323 font.name = QString::null;
01324 font.styleHint = QFont::AnyStyle;
01325 font.fixedPitch = 0;
01326 }
01327 else if (token.type == RTFTokenizer::PlainText)
01328 {
01329 if (!textCodec)
01330 {
01331 kdError(30515) << "No text codec for font!" << endl;
01332 return;
01333 }
01334
01335
01336
01337 if (strchr( token.text, ';' ) == 0L)
01338 font.name += textCodec->toUnicode( token.text );
01339 else
01340 {
01341
01342 *strchr( token.text, ';' ) = 0;
01343 font.name += textCodec->toUnicode( token.text );
01344
01345 QFont qFont( font.name );
01346 qFont.setFixedPitch( (font.fixedPitch == 1) );
01347 qFont.setStyleHint( font.styleHint );
01348 for(;!qFont.exactMatch();)
01349 {
01350 int space=font.name.findRev(' ', font.name.length());
01351 if(space==-1)
01352 break;
01353 font.name.truncate(space);
01354 qFont.setFamily( font.name );
01355 }
01356 const QFontInfo info( qFont );
01357 const QString newFontName ( info.family() );
01358 kdDebug(30515) << "Font " << state.format.font << " asked: " << font.name << " given: " << newFontName << endl;
01359
01360 if ( newFontName.isEmpty() )
01361 fontTable.insert( state.format.font, font.name );
01362 else
01363 fontTable.insert( state.format.font, newFontName );
01364 font.name.truncate( 0 );
01365 font.styleHint = QFont::AnyStyle;
01366 font.fixedPitch = 0;
01367 }
01368 }
01369 }
01370
01371 void RTFImport::parseStyleSheet( RTFProperty * )
01372 {
01373 if (token.type == RTFTokenizer::OpenGroup)
01374 {
01375 style.name = "";
01376 style.next = -1;
01377 }
01378 else if (token.type == RTFTokenizer::PlainText)
01379 {
01380
01381 if (strchr( token.text, ';' ) == 0L)
01382 style.name += textCodec->toUnicode( token.text );
01383 else
01384 {
01385
01386 *strchr( token.text, ';' ) = 0;
01387 style.name += textCodec->toUnicode( token.text );
01388 style.format = state.format;
01389 style.layout = state.layout;
01390 style.next = (style.next == -1) ? style.layout.style : style.next;
01391 styleSheet << style;
01392 style.name.truncate( 0 );
01393 style.next = -1;
01394 }
01395 }
01396 }
01397
01398 void RTFImport::parseColorTable( RTFProperty * )
01399 {
01400 if (token.type == RTFTokenizer::OpenGroup)
01401 {
01402 red = 0;
01403 green = 0;
01404 blue = 0;
01405 }
01406 else if (token.type == RTFTokenizer::PlainText)
01407 {
01408
01409
01410 while ((token.text = strchr( token.text, ';' )))
01411 {
01412 colorTable << QColor( red, green, blue );
01413 red = green = blue = 0;
01414 ++token.text;
01415 }
01416 }
01417 }
01418
01419 void RTFImport::parseBlipUid( RTFProperty * )
01420 {
01421 if (token.type == RTFTokenizer::OpenGroup)
01422 {
01423 picture.identifier = QString::null;
01424 }
01425 else if (token.type == RTFTokenizer::PlainText)
01426 {
01427 picture.identifier += QString::fromUtf8( token.text );
01428 }
01429 else if (token.type == RTFTokenizer::CloseGroup)
01430 {
01431 kdDebug(30515) << "\\blipuid: " << picture.identifier << endl;
01432 }
01433 }
01434
01435 void RTFImport::parsePicture( RTFProperty * )
01436 {
01437 if (state.ignoreGroup)
01438 return;
01439
01440 if (token.type == RTFTokenizer::OpenGroup)
01441 {
01442 picture.type = RTFPicture::PNG;
01443 picture.width = 0;
01444 picture.height = 0;
01445 picture.desiredWidth = 0;
01446 picture.desiredHeight = 0;
01447 picture.scalex = 100;
01448 picture.scaley = 100;
01449 picture.cropLeft = 0;
01450 picture.cropTop = 0;
01451 picture.cropRight = 0;
01452 picture.cropBottom = 0;
01453 picture.nibble = 0;
01454 picture.bits.truncate( 0 );
01455 picture.identifier = QString::null;
01456 }
01457 else if (token.type == RTFTokenizer::PlainText)
01458 {
01459 if (picture.nibble)
01460 {
01461 *(--token.text) = picture.nibble;
01462 }
01463 uint n = qstrlen( token.text ) >> 1;
01464 picture.bits.resize( picture.bits.size() + n );
01465 char *src = token.text;
01466 char *dst = (picture.bits.data() + picture.bits.size() - n);
01467
01468
01469 while (n-- > 0)
01470 {
01471 int k = *src++;
01472 int l = *src++;
01473 *dst++ = (((k + ((k & 16) ? 0 : 9)) & 0xf) << 4) |
01474 ((l + ((l & 16) ? 0 : 9)) & 0xf);
01475 }
01476 picture.nibble = *src;
01477 }
01478 else if (token.type == RTFTokenizer::BinaryData)
01479 {
01480 picture.bits = token.binaryData;
01481 kdDebug(30515) << "Binary data of length: " << picture.bits.size() << endl;
01482 }
01483 else if (token.type == RTFTokenizer::CloseGroup)
01484 {
01485 const char *ext;
01486
01487
01488 switch (picture.type)
01489 {
01490 case RTFPicture::WMF:
01491 case RTFPicture::EMF:
01492 ext = ".wmf";
01493 break;
01494 case RTFPicture::BMP:
01495 ext = ".bmp";
01496 break;
01497 case RTFPicture::MacPict:
01498 ext = ".pict";
01499 break;
01500 case RTFPicture::JPEG:
01501 ext = ".jpg";
01502 break;
01503 case RTFPicture::PNG:
01504 default:
01505 ext = ".png";
01506 break;
01507 }
01508 const int id = ++pictureNumber;
01509 QString pictName("pictures/picture");
01510 pictName += QString::number(id);
01511 pictName += ext;
01512
01513 QCString frameName;
01514 frameName.setNum(id);
01515 frameName.prepend("Picture ");
01516
01517 QString idStr;
01518 if (picture.identifier.isEmpty())
01519 {
01520 idStr = pictName;
01521 }
01522 else
01523 {
01524 idStr += picture.identifier.stripWhiteSpace();
01525 idStr += ext;
01526 }
01527
01528 kdDebug(30515) << "Picture: " << pictName << " Frame: " << frameName << endl;
01529
01530
01531 KoStoreDevice* dev = m_chain->storageFile( pictName, KoStore::Write );
01532 if ( dev )
01533 dev->writeBlock(picture.bits.data(),picture.bits.size());
01534 else
01535 kdError(30515) << "Could not save: " << pictName << endl;
01536
01537
01538
01539 addAnchor( frameName );
01540
01541
01542 const QDateTime dt(QDateTime::currentDateTime());
01543
01544
01545 pictures.addKey( dt, idStr, pictName );
01546
01547
01548 frameSets.addFrameSet( frameName, 2, 0 );
01549
01550
01551 frameSets.addFrame( 0, 0,
01552 (picture.desiredWidth * picture.scalex) /100 ,
01553 (picture.desiredHeight * picture.scaley) /100 , 0, 1, 0 );
01554 frameSets.closeNode( "FRAME" );
01555 frameSets.addNode( "PICTURE" );
01556 frameSets.addKey( dt, idStr );
01557 frameSets.closeNode( "PICTURE" );
01558 frameSets.closeNode( "FRAMESET" );
01559 picture.identifier = QString::null;
01560 }
01561 }
01562
01563 void RTFImport::addImportedPicture( const QString& rawFileName )
01564 {
01565 kdDebug(30515) << "Import field: reading " << rawFileName << endl;
01566
01567 if (rawFileName=="\\*")
01568 {
01569 kdError(30515) << "Import field without file name!" << endl;
01570 return;
01571 }
01572
01573 QString slashPath( rawFileName );
01574 slashPath.replace('\\','/');
01575
01576 QFileInfo info;
01577 info.setFile( inFileName );
01578 QDir dir( info.dirPath() );
01579
01580 KURL url;
01581 url.setPath(dir.filePath( rawFileName ));
01582
01583 kdDebug(30515) << "Path: " << url.prettyURL() << endl;
01584
01585 KoPicture pic;
01586 pic.setKeyAndDownloadPicture(url, 0);
01587 if (pic.isNull())
01588 {
01589 kdError(30515) << "Import field: file is empty: " << rawFileName << endl;
01590 return;
01591 }
01592
01593 const uint id = ++pictureNumber;
01594
01595 QString pictName("pictures/picture");
01596 pictName += QString::number(id);
01597 pictName += '.';
01598 pictName += pic.getExtension();
01599
01600 QCString frameName;
01601 frameName.setNum(id);
01602 frameName.prepend("Picture ");
01603
01604
01605 kdDebug(30515) << "Imported picture: " << pictName << " Frame: " << frameName << endl;
01606
01607
01608 KoStoreDevice* dev = m_chain->storageFile( pictName, KoStore::Write );
01609 if ( dev )
01610 pic.save(dev);
01611 else
01612 kdError(30515) << "Could not save: " << pictName << endl;
01613
01614
01615 addAnchor( frameName );
01616
01617
01618 const QDateTime dt( pic.getKey().lastModified() );
01619
01620
01621 pictures.addKey( dt, rawFileName, pictName );
01622
01623
01624 const QSize size ( pic.getOriginalSize() * 20 );
01625 frameSets.addFrameSet( frameName, 2, 0 );
01626 frameSets.addFrame( 0, 0, size.width(), size.height(), 0, 1, 0 );
01627 frameSets.closeNode( "FRAME" );
01628 frameSets.addNode( "PICTURE" );
01629 frameSets.addKey( dt, rawFileName );
01630 frameSets.closeNode( "PICTURE" );
01631 frameSets.closeNode( "FRAMESET" );
01632 }
01633
01634 void RTFImport::insertPageNumber( RTFProperty * )
01635 {
01636 DomNode node;
01637 node.addNode( "PGNUM" );
01638 node.setAttribute( "subtype", 0 );
01639 node.setAttribute( "value", 0 );
01640 node.closeNode("PGNUM");
01641 addVariable( node, 4, "NUMBER", &state.format);
01642 }
01643
01644 void RTFImport::insertDateTime( RTFProperty *property )
01645 {
01646 kdDebug(30515) << "insertDateTime: " << property->value << endl;
01647 addDateTime( QString::null, bool(property->value), state.format );
01648 }
01649
01650 void RTFImport::addDateTime( const QString& format, const bool isDate, RTFFormat& fmt )
01651 {
01652 bool asDate=isDate;
01653 QString kwordFormat(format);
01654 if (format.isEmpty())
01655 {
01656 if (isDate)
01657 kwordFormat = "DATElocale";
01658 else
01659 kwordFormat = "TIMElocale";
01660 }
01661 else if (!isDate)
01662 {
01663
01664
01665 const QRegExp regexp ("[yMd]");
01666 asDate = (regexp.search(format)>-1);
01667 }
01668 DomNode node;
01669 if (asDate)
01670 {
01671 node.clear(7);
01672 node.addNode("DATE");
01673 node.setAttribute("year", 0);
01674 node.setAttribute("month", 0);
01675 node.setAttribute("day", 0);
01676 node.setAttribute("fix", 0);
01677 node.closeNode("DATE");
01678 addVariable(node, 0, kwordFormat, &fmt);
01679 }
01680 else
01681 {
01682 node.clear(7);
01683 node.addNode("TIME");
01684 node.setAttribute("hour", 0);
01685 node.setAttribute("minute", 0);
01686 node.setAttribute("second", 0);
01687 node.setAttribute("fix", 0);
01688 node.closeNode("TIME");
01689 addVariable(node, 2, kwordFormat, &fmt);
01690 }
01691 }
01692
01693 void RTFImport::parseField( RTFProperty * )
01694 {
01695 if (token.type == RTFTokenizer::OpenGroup)
01696 {
01697 if (flddst == -1)
01698 {
01699
01700 flddst = (destinationStack.count() - 1);
01701 }
01702 fldinst = "";
01703 fldrslt = "";
01704 destination.group = 0L;
01705 }
01706 else if (token.type == RTFTokenizer::CloseGroup)
01707 {
01708 if (!fldinst.isEmpty())
01709 {
01710 DomNode node;
01711 QStringList list ( QStringList::split( ' ', fldinst, false ) );
01712 kdDebug(30515) << "Field: " << list << endl;
01713 uint i;
01714
01715 QString fieldName ( list[0].upper() );
01716 fieldName.remove('\\');
01717 node.clear(7);
01718
01719 bool ok=false;
01720 for (i=0; i < sizeof(fieldTable) /sizeof(fieldTable[0]); i++)
01721 {
01722 if (fieldName == fieldTable[i].id)
01723 {
01724 kdDebug(30515) << "Field found: " << fieldTable[i].id << endl;
01725 ok=true;
01726 break;
01727 }
01728 }
01729 if (!ok)
01730 {
01731 kdWarning(30515) << "Field not supported: " << fieldName << endl;
01732 return;
01733 }
01734 if (fieldTable[i].type == 4)
01735 {
01736 node.addNode( "PGNUM" );
01737 node.setAttribute( "subtype", fieldTable[i].subtype );
01738 node.setAttribute( "value", 0 );
01739 node.closeNode("PGNUM");
01740 addVariable( node, 4, "NUMBER", &fldfmt);
01741 }
01742 else if (fieldTable[i].type == 8)
01743 {
01744 node.addNode( "FIELD" );
01745 node.setAttribute( "subtype", fieldTable[i].subtype );
01746 node.setAttribute( "value", fieldTable[i].value );
01747 node.closeNode("FIELD");
01748 addVariable( node, 8, "STRING", &fldfmt);
01749 }
01750 else if (fieldTable[i].type == 9)
01751 {
01752 QString hrefName = QString::null;
01753
01754
01755 for (uint i=1; i < list.count(); i++)
01756 {
01757 if (list[i] == "\\l")
01758 {
01759 hrefName += '#';
01760 }
01761 else if (list[i].startsWith( "\"" ) && list[i].endsWith( "\"" ))
01762 {
01763 hrefName += list[i].mid( 1, (list[i].length() - 2) );
01764 }
01765 else if (list[i].startsWith("http"))
01766 {
01767 hrefName += list[i];
01768 }
01769 }
01770 node.addNode( "LINK" );
01771 node.setAttribute( "linkName", fldrslt );
01772 node.setAttribute( "hrefName", hrefName );
01773 node.closeNode( "LINK" );
01774 addVariable( node, 9, "STRING", &fldfmt);
01775 }
01776 else if (fieldName == "SYMBOL")
01777 {
01778 if (list.count() >= 2)
01779 {
01780 int ch = list[1].toInt();
01781
01782 if (ch > 0)
01783 {
01784
01785 destination = destinationStack[flddst];
01786 state.format = fldfmt;
01787 insertUTF8( ch );
01788 }
01789 }
01790 }
01791 else if (fieldName == "TIME" || fieldName == "DATE")
01792 {
01793 QString strFldinst( QString::fromUtf8(fldinst) );
01794 QRegExp regexp("\\\\@\\s*\"(.+)\"");
01795 if (regexp.search(strFldinst)==-1)
01796 {
01797 kdWarning(30515) << "Date/time field format not in quotes!" << endl;
01798 strFldinst += ' ';
01799 regexp = QRegExp("\\\\@(\\S+)\\s+");
01800 regexp.search(strFldinst);
01801 }
01802 QString format(regexp.cap(1));
01803 kdDebug(30515) << "Date/time field format: " << format << endl;
01804 format.replace("am/pm", "ap");
01805 format.replace("a/p", "ap");
01806 format.replace("AM/PM", "AP");
01807 format.replace("A/P", "AP");
01808 format.remove("'");
01809 addDateTime( format, (fieldName == "DATE"), fldfmt );
01810 }
01811 else if (fieldName == "IMPORT")
01812 {
01813 addImportedPicture( list[1] );
01814 }
01815
01816 fldinst = "";
01817 }
01818
01819 if (flddst == (int) (destinationStack.count() - 1))
01820 {
01821
01822 flddst = -1;
01823 }
01824 }
01825 }
01826
01827 void RTFImport::parseFldinst( RTFProperty * )
01828 {
01829 if (token.type == RTFTokenizer::OpenGroup)
01830 {
01831 fldinst = "";
01832 }
01833 else if (token.type == RTFTokenizer::PlainText)
01834 {
01835 fldinst += token.text;
01836 }
01837 }
01838
01839 void RTFImport::parseFldrslt( RTFProperty * )
01840 {
01841 if (fldinst.isEmpty())
01842 {
01843 if (token.type == RTFTokenizer::OpenGroup)
01844 {
01845
01846 destination = destinationStack[flddst];
01847 destination.destproc = &RTFImport::parseFldrslt;
01848 }
01849 else if (token.type != RTFTokenizer::CloseGroup)
01850 {
01851 (this->*destinationStack[flddst].destproc)(0L);
01852 }
01853 }
01854 else if (token.type == RTFTokenizer::OpenGroup)
01855 {
01856 fldrslt = "";
01857 }
01858 else if (token.type == RTFTokenizer::PlainText)
01859 {
01860 fldrslt += token.text;
01861 }
01862 else if (token.type == RTFTokenizer::CloseGroup)
01863 {
01864 fldfmt = state.format;
01865 }
01866 }
01867
01868 void RTFImport::addVariable (const DomNode& spec, int type, const QString& key, const RTFFormat* fmt)
01869 {
01870 DomNode node;
01871
01872 node.clear( 6 );
01873 node.addNode( "VARIABLE" );
01874 node.closeTag(true);
01875 node.addNode("TYPE");
01876 node.setAttribute( "type", type );
01877 node.setAttribute( "key", CheckAndEscapeXmlText(key) );
01878 node.setAttribute( "text", 1 );
01879 node.closeNode("TYPE");
01880
01881 node.appendNode(spec);
01882 node.closeNode( "VARIABLE" );
01883 kwFormat.xmldata = node.toString();
01884 kwFormat.id = 4;
01885 kwFormat.pos = textState->length++;
01886 kwFormat.len = 1;
01887 if (fmt)
01888 kwFormat.fmt = *fmt;
01889 textState->text.append( '#' );
01890 textState->formats << kwFormat;
01891 }
01892
01893 void RTFImport::parseFootNote( RTFProperty * property)
01894 {
01895 if(token.type==RTFTokenizer::OpenGroup)
01896 {
01897 RTFTextState* newTextState=new RTFTextState;
01898 footnotes.append(newTextState);
01899 fnnum++;
01900 destination.target = newTextState;
01901
01902 QCString str;
01903 str.setNum(fnnum);
01904 str.prepend("Footnote ");
01905
01906 DomNode node;
01907
01908 node.clear( 7 );
01909 node.addNode("FOOTNOTE");
01910 node.setAttribute("numberingtype", "auto");
01911 node.setAttribute("notetype", "footnote");
01912 node.setAttribute("frameset", str);
01913 node.setAttribute("value", fnnum);
01914 node.closeNode("FOOTNOTE");
01915 addVariable(node, 11, "STRING");
01916 }
01917 parseRichText(property);
01918 }
01919
01920 void RTFImport::parseRichText( RTFProperty * )
01921 {
01922 if (token.type == RTFTokenizer::OpenGroup)
01923 {
01924
01925 RTFTextState *oldState = textState;
01926 textState = destination.target;
01927 destination.target = oldState;
01928 destination.group = "Text";
01929
01930
01931 textState->text.clear();
01932 textState->node.clear( 3 );
01933 textState->cell.clear( 3 );
01934 textState->formats.clear();
01935 textState->frameSets.clear();
01936 textState->rows.clear();
01937 textState->table = 0;
01938 textState->length = 0;
01939 }
01940 else if (token.type == RTFTokenizer::PlainText)
01941 {
01942
01943 if (!state.format.hidden)
01944 {
01945 const int len = (token.text[0] < 0) ? 1 : qstrlen( token.text );
01946
01947
01948 if ( textState->formats.isEmpty() ||
01949 textState->formats.last().fmt != state.format ||
01950 ( !textState->formats.last().xmldata.isEmpty() ) )
01951 {
01952 kwFormat.fmt = state.format;
01953 kwFormat.id = 1;
01954 kwFormat.pos = textState->length;
01955 kwFormat.len = len;
01956 textState->formats << kwFormat;
01957 kwFormat.xmldata = QString::null;
01958 }
01959 else
01960 {
01961 textState->formats.last().len += len;
01962 }
01963 textState->length += len;
01964 textState->text.addTextNode( token.text, textCodec );
01965 }
01966 }
01967 else if (token.type == RTFTokenizer::CloseGroup)
01968 {
01969 if (textState->length)
01970 insertParagraph();
01971 if (textState->table)
01972 finishTable();
01973
01974
01975 textState = destination.target;
01976 }
01977 }
01978
01979 void RTFImport::parsePlainText( RTFProperty * )
01980 {
01981 if (token.type == RTFTokenizer::OpenGroup)
01982 {
01983 destination.target->node.clear();
01984 }
01985 else if (token.type == RTFTokenizer::PlainText)
01986 {
01987 destination.target->node.addTextNode( token.text, textCodec );
01988 }
01989 }
01990
01991 void RTFImport::parseGroup( RTFProperty * )
01992 {
01993 }
01994
01995 void RTFImport::skipGroup( RTFProperty * )
01996 {
01997 kdDebug(30515) << "Skip Group: " << token.type << endl;
01998 state.ignoreGroup = true;
01999 }
02000
02001 void RTFImport::resetState()
02002 {
02003 setPlainFormatting();
02004 setParagraphDefaults();
02005 setSectionDefaults();
02006 setTableRowDefaults();
02007 }
02008
02009 void RTFImport::changeDestination( RTFProperty *property )
02010 {
02011 kdDebug(30515) << "changeDestination: " << property->name << endl;
02012 destinationStack.push( destination );
02013 destination.name = property->name;
02014 destination.destproc = property->cwproc;
02015 if ( property->offset )
02016 destination.target = (RTFTextState*) ( (char *)this + property->offset );
02017 else
02018 destination.target = &m_dummyTextState;
02019
02020 state.brace0 = true;
02021
02022 if (property->value)
02023 {
02024 resetState();
02025 destination.group = 0L;
02026 }
02027
02028
02029 token.type = RTFTokenizer::OpenGroup;
02030 (this->*destination.destproc)(0L);
02031 }
02032
02033 void RTFImport::addAnchor( const char *instance )
02034 {
02035 DomNode node;
02036
02037 node.clear( 6 );
02038 node.addNode( "ANCHOR" );
02039 node.setAttribute( "type", "frameset" );
02040 node.setAttribute( "instance", instance );
02041 node.closeNode( "ANCHOR" );
02042 kwFormat.xmldata = node.toString();
02043 kwFormat.id = 6;
02044 kwFormat.pos = textState->length++;
02045 kwFormat.len = 1;
02046 textState->text.append( '#' );
02047 textState->formats << kwFormat;
02048 }
02049
02050 void RTFImport::addFormat( DomNode &node, const KWFormat& format, const RTFFormat* baseFormat )
02051 {
02052
02053 int vertAlign = format.fmt.vertAlign;
02054 int fontSize = (format.fmt.fontSize >> 1);
02055 int vertAlign0 = ~vertAlign;
02056 int fontSize0 = ~fontSize;
02057
02058
02059 if (format.fmt.vertAlign == RTFFormat::Normal && format.fmt.baseline)
02060 {
02061 if (format.fmt.baseline < 0)
02062 vertAlign = RTFFormat::SuperScript;
02063 else
02064 vertAlign = RTFFormat::SubScript;
02065
02066 fontSize += (fontSize >> 1);
02067 }
02068 if (baseFormat)
02069 {
02070 vertAlign0 = baseFormat->vertAlign;
02071 fontSize0 = (baseFormat->fontSize >> 1);
02072
02073 if (vertAlign0 == RTFFormat::Normal && baseFormat->baseline)
02074 {
02075 if (baseFormat->baseline < 0)
02076 vertAlign0 = RTFFormat::SuperScript;
02077 else
02078 vertAlign0 = RTFFormat::SubScript;
02079
02080 fontSize0 += (fontSize0 >> 1);
02081 }
02082 }
02083 node.addNode( "FORMAT" );
02084 node.setAttribute( "id", (int)format.id );
02085
02086 if (format.len != 0)
02087 {
02088
02089 node.setAttribute( "pos", (int)format.pos );
02090 node.setAttribute( "len", (int)format.len );
02091 }
02092 if ((format.id == 1)||(format.id == 4))
02093 {
02094
02095 if (!baseFormat || format.fmt.color != baseFormat->color)
02096 {
02097 node.addNode( "COLOR" );
02098 node.addColor( ((uint)format.fmt.color >= colorTable.count())
02099 ? (QColor &)Qt::black : colorTable[format.fmt.color] );
02100 node.closeNode( "COLOR" );
02101 }
02102 if ((uint)format.fmt.bgcolor < colorTable.count() &&
02103 (!baseFormat || format.fmt.bgcolor != baseFormat->bgcolor))
02104 {
02105 node.addNode( "TEXTBACKGROUNDCOLOR" );
02106 node.addColor( colorTable[format.fmt.bgcolor] );
02107 node.closeNode( "TEXTBACKGROUNDCOLOR" );
02108 }
02109 if (!baseFormat || format.fmt.font != baseFormat->font)
02110 {
02111 node.addNode( "FONT" );
02112
02113 if (fontTable.contains( format.fmt.font ))
02114 {
02115 node.setAttribute( "name", fontTable[format.fmt.font] );
02116 }
02117 node.closeNode( "FONT" );
02118 }
02119 if (!baseFormat || format.fmt.bold != baseFormat->bold)
02120 {
02121 node.addNode( "WEIGHT" );
02122 node.setAttribute( "value", (format.fmt.bold ? 75 : 50) );
02123 node.closeNode( "WEIGHT" );
02124 }
02125 if (fontSize != fontSize0)
02126 {
02127 node.addNode( "SIZE" );
02128 node.setAttribute( "value", fontSize );
02129 node.closeNode( "SIZE" );
02130 }
02131 if (!baseFormat || format.fmt.italic != baseFormat->italic)
02132 {
02133 node.addNode( "ITALIC" );
02134 node.setAttribute( "value", format.fmt.italic );
02135 node.closeNode( "ITALIC" );
02136 }
02137 if (!baseFormat || format.fmt.underline != baseFormat->underline )
02138 {
02139 node.addNode( "UNDERLINE" );
02140 QCString st,styleline,wordbyword("0");
02141 st.setNum(format.fmt.underline);
02142 int underlinecolor = format.fmt.underlinecolor;
02143
02144 switch (format.fmt.underline)
02145 {
02146 case RTFFormat::UnderlineNone:
02147 default:
02148 {
02149 st="0";
02150 underlinecolor=-1;
02151 break;
02152 }
02153 case RTFFormat::UnderlineSimple:
02154 {
02155 st="single";
02156 break;
02157 }
02158 case RTFFormat::UnderlineDouble:
02159 {
02160 st="double";
02161 break;
02162 }
02163 case RTFFormat::UnderlineThick:
02164 {
02165 st="single-bold";
02166 styleline="solid";
02167 break;
02168 }
02169
02170 case RTFFormat::UnderlineWordByWord:
02171 {
02172 st="single";
02173 styleline="solid";
02174 wordbyword="1";
02175 break;
02176 }
02177 case RTFFormat::UnderlineDash:
02178 {
02179 st="single";
02180 styleline="dash";
02181 break;
02182 }
02183 case RTFFormat::UnderlineDot:
02184 {
02185 st="single";
02186 styleline="dot";
02187 break;
02188 }
02189 case RTFFormat::UnderlineDashDot:
02190 {
02191 st="single";
02192 styleline="dashdot";
02193 break;
02194 }
02195 case RTFFormat::UnderlineDashDotDot:
02196 {
02197 st="single";
02198 styleline="dashdotdot";
02199 break;
02200 }
02201 case RTFFormat::UnderlineWave:
02202 {
02203 st="single";
02204 styleline="wave";
02205 break;
02206 }
02207 }
02208 node.setAttribute( "value", st );
02209 node.setAttribute( "wordbyword", wordbyword );
02210 if ( !styleline.isEmpty() )
02211 node.setAttribute( "styleline", styleline );
02212 if ( underlinecolor >= 0 && uint(underlinecolor) < colorTable.count() )
02213 {
02214 node.setAttribute( "underlinecolor", colorTable[underlinecolor].name() );
02215 }
02216
02217 node.closeNode( "UNDERLINE" );
02218 }
02219 if (!baseFormat || format.fmt.strike != baseFormat->strike || format.fmt.striked != baseFormat->striked)
02220 {
02221 node.addNode( "STRIKEOUT" );
02222 QCString st;
02223 st.setNum(format.fmt.strike);
02224 if(format.fmt.striked)
02225 st="double";
02226 node.setAttribute( "value", st );
02227 node.closeNode( "STRIKEOUT" );
02228 }
02229 if (vertAlign != vertAlign0)
02230 {
02231 node.addNode( "VERTALIGN" );
02232 node.setAttribute( "value", vertAlign );
02233 node.closeNode( "VERTALIGN" );
02234 }
02235 if (!baseFormat || format.fmt.caps != baseFormat->caps || format.fmt.smallCaps != baseFormat->smallCaps)
02236 {
02237 node.addNode( "FONTATTRIBUTE" );
02238 QCString fontattr;
02239 if ( format.fmt.caps )
02240 fontattr="uppercase";
02241 else if ( format.fmt.smallCaps )
02242 fontattr="smallcaps";
02243 else
02244 fontattr="none";
02245 node.setAttribute( "value", fontattr );
02246 node.closeNode( "FONTATTRIBUTE" );
02247 }
02248 if (!baseFormat)
02249 {
02250 node.addNode( "CHARSET" );
02251 node.setAttribute( "value", (int)QFont::Unicode );
02252 node.closeNode( "CHARSET" );
02253 }
02254 }
02255 if (format.id == 4 || format.id == 6)
02256 {
02257
02258 node.closeTag( true );
02259 node.append( format.xmldata );
02260 }
02261 node.closeNode( "FORMAT" );
02262 }
02263
02264 void RTFImport::addLayout( DomNode &node, const QString &name, const RTFLayout &layout, bool frameBreak )
02265 {
02266
02267 node.addNode( "NAME" );
02268 node.setAttribute( "value", CheckAndEscapeXmlText(name) );
02269 node.closeNode( "NAME" );
02270 node.addNode( "FLOW" );
02271 node.setAttribute( "align", alignN[layout.alignment] );
02272 node.closeNode( "FLOW" );
02273
02274
02275 if (layout.firstIndent || layout.leftIndent || layout.rightIndent)
02276 {
02277 node.addNode( "INDENTS" );
02278
02279 if (layout.firstIndent)
02280 node.setAttribute( "first", .05*layout.firstIndent );
02281 if (layout.leftIndent)
02282 node.setAttribute( "left", .05*layout.leftIndent );
02283 if (layout.rightIndent)
02284 node.setAttribute( "right", .05*layout.rightIndent );
02285
02286 node.closeNode( "INDENTS" );
02287 }
02288
02289
02290 if (layout.spaceBefore || layout.spaceAfter)
02291 {
02292 node.addNode( "OFFSETS" );
02293
02294 if (layout.spaceBefore)
02295 node.setAttribute( "before", .05*layout.spaceBefore );
02296 if (layout.spaceAfter)
02297 node.setAttribute( "after", .05*layout.spaceAfter );
02298
02299 node.closeNode( "OFFSETS" );
02300 }
02301
02302
02303
02304
02305 QString lineSpacingType;
02306 QString lineSpacingValue;
02307 if ( layout.spaceBetweenMultiple )
02308 {
02309
02310 switch (layout.spaceBetween )
02311 {
02312 case 240:
02313 {
02314 lineSpacingType = "single";
02315 break;
02316 }
02317 case 360:
02318 {
02319 lineSpacingType = "oneandhalf";
02320 break;
02321 }
02322 case 480 :
02323 {
02324 lineSpacingType = "double";
02325 break;
02326 }
02327 default:
02328 {
02329 if ( layout.spaceBetween > 0 )
02330 {
02331 lineSpacingType = "multiple";
02332 lineSpacingValue.setNum( layout.spaceBetween / 240.0 );
02333 }
02334 break;
02335 }
02336 }
02337 }
02338 else
02339 {
02340 if (layout.spaceBetween > 0)
02341 {
02342 lineSpacingType = "atleast";
02343 lineSpacingValue.setNum( 0.05*layout.spaceBetween );
02344 }
02345 if (layout.spaceBetween < 0)
02346 {
02347
02348 lineSpacingType = "fixed" ;
02349 lineSpacingValue.setNum( -0.05*layout.spaceBetween );
02350 }
02351 }
02352
02353 if ( ! lineSpacingType.isEmpty() )
02354 {
02355 node.addNode( "LINESPACING" );
02356 node.setAttribute( "type", lineSpacingType );
02357 if ( ! lineSpacingValue.isEmpty() )
02358 node.setAttribute( "spacingvalue", lineSpacingValue );
02359 node.closeNode( "LINESPACING" );
02360 }
02361
02362 if (layout.keep || layout.pageBB || layout.pageBA || frameBreak || layout.keepNext)
02363 {
02364 node.addNode( "PAGEBREAKING" );
02365 node.setAttribute( "linesTogether", boolN[layout.keep] );
02366 node.setAttribute( "hardFrameBreak", boolN[layout.pageBB] );
02367 node.setAttribute( "hardFrameBreakAfter", boolN[layout.pageBA || frameBreak] );
02368 node.setAttribute( "keepWithNext", boolN[layout.keepNext] );
02369 node.closeNode( "PAGEBREAKING" );
02370 }
02371
02372
02373 for (uint i=0; i < 4; i++)
02374 {
02375 const RTFBorder &border = layout.borders[i];
02376
02377 if (border.style != RTFBorder::None || border.width > 0)
02378 {
02379 node.addNode( borderN[i] );
02380 node.addColor( ((uint)border.color >= colorTable.count())
02381 ? (QColor &)Qt::black : colorTable[border.color] );
02382 node.setAttribute( "style", (int)border.style & 0xf );
02383 node.setAttribute( "width", (border.width < 20) ? 1 : border.width /20 );
02384 node.closeNode( borderN[i] );
02385 }
02386 }
02387
02388
02389 if (layout.firstIndent < 0 && layout.leftIndent > 0)
02390 {
02391 node.addNode( "TABULATOR" );
02392 node.setAttribute( "type", 0 );
02393 node.setAttribute( "ptpos", .05*layout.leftIndent );
02394 node.closeNode( "TABULATOR" );
02395 }
02396
02397
02398 if (!layout.tablist.isEmpty())
02399 {
02400
02401 for (uint i=0; i < layout.tablist.count(); i++)
02402 {
02403 const RTFTab &tab = layout.tablist[i];
02404 int l = (int)tab.leader;
02405 node.addNode( "TABULATOR" );
02406 node.setAttribute( "type", tab.type );
02407 node.setAttribute( "ptpos", .05*tab.position );
02408 node.setAttribute( "filling", (l < 2) ? l : ((l == 2) ? 1 : 2) );
02409 node.setAttribute( "width", (l == 4) ? 1. : 0.5 );
02410 node.closeNode( "TABULATOR" );
02411 }
02412 }
02413 }
02414
02415 void RTFImport::addParagraph( DomNode &node, bool frameBreak )
02416 {
02417 node.addNode( "PARAGRAPH" );
02418 node.addNode( "TEXT" );
02419 node.appendNode( textState->text );
02420 node.closeNode( "TEXT" );
02421
02422
02423 QString name;
02424 const RTFFormat* format = &state.format;
02425 const int styleNum = state.layout.style;
02426
02427 const QValueList<RTFStyle>::ConstIterator endStyleSheet = styleSheet.end();
02428 for ( QValueList<RTFStyle>::ConstIterator it=styleSheet.begin(); it!=endStyleSheet; ++it )
02429 {
02430 if ( (*it).layout.style == styleNum )
02431 {
02432 if ( textState->length > 0 )
02433 {
02434 format = &(*it).format;
02435 }
02436 name = (*it).name;
02437 break;
02438 }
02439 }
02440 kwFormat.fmt = *format;
02441 kwFormat.id = 1;
02442 kwFormat.pos = 0;
02443 kwFormat.len = textState->length;
02444
02445 if ( name.isEmpty() )
02446 {
02447 kdWarning(30515) << "Style name empty! Assuming Standard!" << endl;
02448 name = "Standard";
02449 }
02450
02451
02452 bool hasFormats = false;
02453
02454 for ( QValueList<KWFormat>::ConstIterator it = textState->formats.begin(); it != textState->formats.end(); ++it )
02455 {
02456 if ( (*it).id != 1 || (*it).fmt != *format )
02457 {
02458 if (!hasFormats)
02459 {
02460 node.addNode( "FORMATS" );
02461 hasFormats = true;
02462 }
02463 addFormat( node, (*it), format );
02464 }
02465 }
02466 if (hasFormats)
02467 {
02468 node.closeNode( "FORMATS" );
02469 }
02470
02471
02472 node.addNode( "LAYOUT" );
02473 addLayout( node, name, state.layout, frameBreak );
02474 addFormat( node, kwFormat, 0L );
02475 node.closeNode( "LAYOUT" );
02476 node.closeNode( "PARAGRAPH" );
02477
02478
02479 textState->text.clear();
02480 textState->length = 0;
02481 textState->formats.clear();
02482 }
02483
02484 void RTFImport::finishTable()
02485 {
02486 kdDebug(30515) << "Starting TFImport::finishTable..." << endl;
02487 QCString emptyArray;
02488 QValueList<int> cellx;
02489 int left = 0, right = 0;
02490
02491 insertTableRow();
02492
02493
02494
02495 for (uint i=0; i < textState->rows.count(); i++)
02496 {
02497 RTFTableRow &row = textState->rows[i];
02498
02499 if (row.left < left || i == 0)
02500 left = row.left;
02501 if (row.cells.last().x > right || i == 0)
02502 right = row.cells.last().x;
02503 }
02504
02505
02506
02507 for (uint i=0; i < textState->rows.count(); i++)
02508 {
02509 RTFTableRow &row = textState->rows[i];
02510
02511 if (row.left > left)
02512 {
02513 row.frameSets.prepend( emptyArray );
02514 emptyCell.x = row.left;
02515 row.cells.prepend( emptyCell );
02516 row.left = left;
02517 }
02518 if (row.cells.last().x < right)
02519 {
02520 row.frameSets << emptyArray;
02521 emptyCell.x = right;
02522 row.cells << emptyCell;
02523 }
02524
02525 for (uint k=0; k < row.cells.count(); k++)
02526 {
02527 if (!cellx.contains( row.cells[k].x ))
02528 cellx << row.cells[k].x;
02529 }
02530 if (!cellx.contains( row.left ))
02531 {
02532 cellx << row.left;
02533 }
02534 }
02535
02536
02537
02538 for (uint k=0; k < cellx.count(); k++)
02539 {
02540 for (uint l=k+1; l < cellx.count(); l++)
02541 {
02542 if (cellx[l] < cellx[k])
02543 {
02544 int tmp = cellx[l];
02545 cellx[l] = cellx[k];
02546 cellx[k] = tmp;
02547 }
02548 }
02549 }
02550 int y1 = 0;
02551
02552
02553
02554 for (uint i=0; i < textState->rows.count(); i++)
02555 {
02556 RTFTableRow &row = textState->rows[i];
02557 int h = abs( row.height );
02558 int y2 = y1 + ((h < 400) ? 400 : h);
02559 int x1 = row.left;
02560
02561 for (uint k=0; k < row.cells.count(); k++)
02562 {
02563 char buf[64];
02564 int x2 = row.cells[k].x;
02565 int col = cellx.findIndex( x1 );
02566
02567 sprintf( buf, "Table %d Cell %d,%d", textState->table, i, col );
02568 frameSets.addFrameSet( buf, 1, 0 );
02569 sprintf( buf, "Table %d", textState->table );
02570 frameSets.setAttribute( "grpMgr", buf );
02571 frameSets.setAttribute( "row", (int)i );
02572 frameSets.setAttribute( "col", col );
02573 frameSets.setAttribute( "rows", 1 );
02574 frameSets.setAttribute( "cols", cellx.findIndex( x2 ) - col );
02575
02576 frameSets.addFrame( x1, y1, x2, y2, (row.height < 0) ? 2 : 0, 1, 0 );
02577
02578
02579 for (uint i=0; i < 4; i++)
02580 {
02581 RTFBorder &border = row.cells[k].borders[i];
02582
02583 if (border.style != RTFBorder::None || border.width > 0)
02584 {
02585 const char *id = "lrtb";
02586 QColor &c = ((uint)border.color >= colorTable.count())
02587 ? (QColor &)Qt::black : colorTable[border.color];
02588 frameSets.addBorder( (int)id[i], c, (int)border.style & 0x0f,
02589 .05*(!border.width ? 10 : border.width) );
02590 }
02591 }
02592
02593
02594 if ((uint)row.cells[k].bgcolor < colorTable.count())
02595 {
02596 QColor &color = colorTable[row.cells[k].bgcolor];
02597 frameSets.setAttribute( "bkRed", color.red() );
02598 frameSets.setAttribute( "bkGreen", color.green() );
02599 frameSets.setAttribute( "bkBlue", color.blue() );
02600 }
02601 frameSets.closeNode( "FRAME" );
02602 frameSets.append( row.frameSets[k] );
02603 frameSets.closeNode( "FRAMESET" );
02604 x1 = x2;
02605 }
02606 y1 = y2;
02607 }
02608 textState->table = 0;
02609 textState->rows.clear();
02610 kdDebug(30515) << "Quitting TFImport::finishTable..." << endl;
02611 }
02612
02613 void RTFImport::writeOutPart( const char *name, const DomNode& node )
02614 {
02615 KoStoreDevice* dev = m_chain->storageFile( name, KoStore::Write );
02616 if ( dev )
02617 {
02618 QTextStream stream( dev );
02619 stream.setEncoding( QTextStream::UnicodeUTF8 );
02620 stream << node.toString();
02621 }
02622 else
02623 kdError(30515) << "Could not write part " << name << endl;
02624 }