16#include <tqfontinfo.h>
19#include <KoFilterChain.h>
20#include <kgenericfactory.h>
23#include <tqstringlist.h>
25#include <tqfileinfo.h>
27#include <tqvaluelist.h>
30#include <tdemessagebox.h>
33#include <KoFilterManager.h>
36#include "rtfimport.moc"
38typedef KGenericFactory<RTFImport, KoFilter> RTFImportFactory;
39K_EXPORT_COMPONENT_FACTORY( librtfimport, RTFImportFactory( "kofficefilters" ) )
42#define PROP(a,b,c,d,e) { a, b, &RTFImport::c, d, e }
45#define MEMBER(a,b,c,d,e) PROP(a,b,c,offsetof(RTFImport,d),e)
50 PROP( 0L, "@*", skipGroup, 0L, false ),
51 MEMBER( "@info", "@author", parsePlainText, author, false ),
52 PROP( "@pict", "@blipuid", parseBlipUid, 0, 0 ),
53 PROP( "@rtf", "@colortbl", parseColorTable, 0L, true ),
54 MEMBER( "@info", "@company", parsePlainText, company, false ),
55 MEMBER( "@info", "@doccomm", parsePlainText, doccomm, false ),
56 PROP( "Text", "@field", parseField, 0L, false ),
57 PROP( "@field", "@fldinst", parseFldinst, 0L, false ),
58 PROP( "@field", "@fldrslt", parseFldrslt, 0L, false ),
59 PROP( "@rtf", "@fonttbl", parseFontTable, 0L, true ),
60 MEMBER( "@rtf", "@footer", parseRichText, oddPagesFooter, true ),
61 PROP( "@rtf", "@footnote", parseFootNote, 0L, true ),
62 MEMBER( "@rtf", "@footerf", parseRichText, firstPageFooter, true ),
63 MEMBER( "@rtf", "@footerl", parseRichText, oddPagesFooter, true ),
64 MEMBER( "@rtf", "@footerr", parseRichText, evenPagesFooter, true ),
65 MEMBER( "@rtf", "@header", parseRichText, oddPagesHeader, true ),
66 MEMBER( "@rtf", "@headerf", parseRichText, firstPageHeader, true ),
67 MEMBER( "@rtf", "@headerl", parseRichText, oddPagesHeader, true ),
68 MEMBER( "@rtf", "@headerr", parseRichText, evenPagesHeader, true ),
69 PROP( "@rtf", "@info", parseGroup, 0L, true ),
70 PROP( "Text", "@nonshppict", skipGroup, 0L, false ),
71 PROP( 0L, "@panose", skipGroup, 0L, 0 ),
72 PROP( "Text", "@pict", parsePicture, 0L, true ),
73 MEMBER( "@", "@rtf", parseRichText, bodyText, true ),
74 PROP( "Text", "@shpinst", skipGroup, 0L, true ),
75 PROP( "Text", "@shppict", parseGroup, 0L, false ),
76 PROP( "@rtf", "@stylesheet", parseStyleSheet, 0L, true ),
77 MEMBER( "@info", "@title", parsePlainText, title, false ),
84 PROP( "Text", "\n", insertParagraph, 0L, 0 ),
85 PROP( "Text", "\r", insertParagraph, 0L, 0 ),
86 PROP( 0L, "\'", insertHexSymbol, 0L, 0 ),
87 PROP( 0L, "\\", insertSymbol, 0L, '\\' ),
88 PROP( 0L, "_", insertSymbol, 0L, 0x2011 ),
89 PROP( 0L, "{", insertSymbol, 0L, '{' ),
90 PROP( 0L, "|", insertSymbol, 0L, 0x00b7 ),
91 PROP( 0L, "}", insertSymbol, 0L, '}' ),
92 PROP( 0L, "~", insertSymbol, 0L, 0x00a0 ),
93 PROP( 0L, "-", insertSymbol, 0L, 0x00ad ),
94 PROP( 0L, "adjustright", ignoreKeyword, 0L, 0 ),
95 PROP( 0L, "ansi", setAnsiCodepage, 0L, 0 ),
96 PROP( 0L, "ansicpg", setCodepage, 0L, 0 ),
97 MEMBER( 0L, "b", setToggleProperty, state.format.bold, 0 ),
99 MEMBER( "@colortbl", "blue", setNumericProperty, blue, 0 ),
100 MEMBER( 0L, "box", setEnumProperty, state.layout.border, 0 ),
101 PROP( 0L, "brdrb", selectLayoutBorder, 0L, 3 ),
102 PROP( 0L, "brdrcf", setBorderColor, 0L, 0 ),
103 PROP( 0L, "brdrdash", setBorderStyle, 0L, RTFBorder::Dashes ),
104 PROP( 0L, "brdrdashd", setBorderStyle, 0L, RTFBorder::DashDot ),
105 PROP( 0L, "brdrdashdd", setBorderStyle, 0L, RTFBorder::DashDotDot ),
106 PROP( 0L, "brdrdashsm", setBorderStyle, 0L, RTFBorder::Dashes ),
107 PROP( 0L, "brdrdb", setBorderStyle, 0L, RTFBorder::Solid ),
108 PROP( 0L, "brdrdot", setBorderStyle, 0L, RTFBorder::Dots ),
109 PROP( 0L, "brdrhairline", setBorderStyle, 0L, RTFBorder::Solid ),
110 PROP( 0L, "brdrl", selectLayoutBorder, 0L, 0 ),
111 PROP( 0L, "brdrr", selectLayoutBorder, 0L, 1 ),
112 PROP( 0L, "brdrs", setBorderStyle, 0L, RTFBorder::Solid ),
113 PROP( 0L, "brdrsh", setBorderStyle, 0L, RTFBorder::Solid ),
114 PROP( 0L, "brdrt", selectLayoutBorder, 0L, 2 ),
115 PROP( 0L, "brdrth", setBorderStyle, 0L, RTFBorder::Solid ),
116 PROP( 0L, "brdrw", setBorderProperty, offsetof( RTFBorder,width), 0 ),
117 PROP( 0L, "bullet", insertSymbol, 0L, 0x2022 ),
118 PROP( 0L, "brsp", setBorderProperty, offsetof( RTFBorder,space), 0 ),
119 MEMBER( 0L, "caps", setToggleProperty, state.format.caps, 0 ),
120 MEMBER( 0L, "cb", setNumericProperty, state.format.bgcolor, 0 ),
121 MEMBER( 0L, "highlight", setNumericProperty, state.format.bgcolor, 0 ),
122 PROP( "Text", "cell", insertTableCell, 0L, 0 ),
123 PROP( 0L, "cellx", insertCellDef, 0L, 0 ),
124 MEMBER( 0L, "cf", setNumericProperty, state.format.color, 0 ),
125 PROP( 0L, "chdate", insertDateTime, 0L, TRUE ),
126 PROP( 0L, "chpgn", insertPageNumber, 0L, 0 ),
127 PROP( 0L, "chtime", insertDateTime, 0L, FALSE ),
128 PROP( 0L, "clbrdrb", selectLayoutBorderFromCell, 0L, 3 ),
129 PROP( 0L, "clbrdrl", selectLayoutBorderFromCell, 0L, 0 ),
130 PROP( 0L, "clbrdrr", selectLayoutBorderFromCell, 0L, 1 ),
131 PROP( 0L, "clbrdrt", selectLayoutBorderFromCell, 0L, 2 ),
132 MEMBER( 0L, "clcbpat", setNumericProperty, state.tableCell.bgcolor, 0 ),
133 PROP( 0L, "cs", ignoreKeyword, 0L, 0 ),
134 PROP( 0L, "datafield", skipGroup, 0L, 0 ),
135 MEMBER( "@rtf", "deff", setNumericProperty, defaultFont, 0 ),
136 MEMBER( "@rtf", "deftab", setNumericProperty, defaultTab, 0 ),
137 PROP( "@pict", "dibitmap", setPictureType, 0L, RTFPicture::BMP ),
138 MEMBER( 0L, "dn", setNumericProperty, state.format.baseline, 6 ),
139 PROP( 0L, "emdash", insertSymbol, 0L, 0x2014 ),
140 PROP( "@pict", "emfblip", setPictureType, 0L, RTFPicture::EMF ),
141 PROP( 0L, "emspace", insertSymbol, 0L, 0x2003 ),
142 PROP( 0L, "endash", insertSymbol, 0L, 0x2013 ),
143 PROP( 0L, "enspace", insertSymbol, 0L, 0x2002 ),
144 PROP( 0L, "expnd", ignoreKeyword, 0L, 0 ),
145 PROP( 0L, "expndtw", ignoreKeyword, 0L, 0 ),
146 MEMBER( 0L, "f", setNumericProperty, state.format.font, 0 ),
147 MEMBER( "@rtf", "facingp", setFlagProperty, facingPages, true ),
148 PROP( 0L, "fcharset", setCharset, 0L, 0 ),
149 PROP( "@fonttbl", "fdecor", setFontStyleHint, 0L, TQFont::Decorative ),
150 MEMBER( 0L, "fi", setNumericProperty, state.layout.firstIndent, 0 ),
151 PROP( "@fonttbl", "fmodern", setFontStyleHint, 0L, TQFont::TypeWriter ),
152 PROP( "@fonttbl", "fnil", setFontStyleHint, 0L, TQFont::AnyStyle ),
153 MEMBER( 0L, "footery", setNumericProperty, state.section.footerMargin, 0 ),
154 PROP( 0L, "formshade", ignoreKeyword, 0L, 0 ),
155 MEMBER( "@fonttbl", "fprq", setNumericProperty, font.fixedPitch, 0 ),
156 PROP( "@fonttbl", "froman", setFontStyleHint, 0L, TQFont::Serif ),
157 MEMBER( 0L, "fs", setNumericProperty, state.format.fontSize, 0 ),
158 PROP( "@fonttbl", "fscript", setFontStyleHint, 0L, TQFont::AnyStyle ),
159 PROP( "@fonttbl", "fswiss", setFontStyleHint, 0L, TQFont::SansSerif ),
160 PROP( "@fonttbl", "ftech", setFontStyleHint, 0L, TQFont::AnyStyle ),
161 MEMBER( "@colortbl", "green", setNumericProperty, green, 0 ),
162 MEMBER( 0L, "headery", setNumericProperty, state.section.headerMargin, 0 ),
163 MEMBER( 0L, "i", setToggleProperty, state.format.italic, 0 ),
164 MEMBER( 0L, "intbl", setFlagProperty, state.layout.inTable, true ),
165 PROP( "@pict", "jpegblip", setPictureType, 0L, RTFPicture::JPEG ),
166 MEMBER( 0L, "keep", setFlagProperty, state.layout.keep, true ),
167 MEMBER( 0L, "keepn", setFlagProperty, state.layout.keepNext, true ),
168 MEMBER( "@rtf", "landscape", setFlagProperty, landscape, true ),
169 PROP( 0L, "ldblquote", insertSymbol, 0L, 0x201c ),
170 MEMBER( 0L, "li", setNumericProperty, state.layout.leftIndent, 0 ),
171 PROP( 0L, "line", insertSymbol, 0L, 0x000a ),
172 PROP( 0L, "lquote", insertSymbol, 0L, 0x2018 ),
173 PROP( 0L, "ltrmark", insertSymbol, 0L, 0x200e ),
174 PROP( 0L, "mac", setMacCodepage, 0L, 0 ),
175 PROP( "@pict", "macpict", setPictureType, 0L, RTFPicture::MacPict ),
176 MEMBER( "@rtf", "margb", setNumericProperty, bottomMargin, 0 ),
177 MEMBER( "@rtf", "margl", setNumericProperty, leftMargin, 0 ),
178 MEMBER( "@rtf", "margr", setNumericProperty, rightMargin, 0 ),
179 MEMBER( "@rtf", "margt", setNumericProperty, topMargin, 0 ),
180 MEMBER( 0L, "nosupersub", setEnumProperty, state.format.vertAlign, RTFFormat::Normal ),
181 PROP( "Text", "page", insertPageBreak, 0L, 0 ),
182 MEMBER( 0L, "pagebb", setFlagProperty, state.layout.pageBB, true ),
183 MEMBER( "@rtf", "paperh", setNumericProperty, paperHeight, 0 ),
184 MEMBER( "@rtf", "paperw", setNumericProperty, paperWidth, 0 ),
185 PROP( "Text", "par", insertParagraph, 0L, 0 ),
186 PROP( 0L, "pard", setParagraphDefaults, 0L, 0 ),
187 PROP( 0L, "pc", setPcCodepage, 0L, 0 ),
188 PROP( 0L, "pca", setPcaCodepage, 0L, 0 ),
189 MEMBER( 0L, "pgbrk", setToggleProperty, state.layout.pageBA, true ),
190 MEMBER( "@pict", "piccropb", setNumericProperty, picture.cropBottom, 0 ),
191 MEMBER( "@pict", "piccropl", setNumericProperty, picture.cropLeft, 0 ),
192 MEMBER( "@pict", "piccropr", setNumericProperty, picture.cropRight, 0 ),
193 MEMBER( "@pict", "piccropt", setNumericProperty, picture.cropTop, 0 ),
194 MEMBER( "@pict", "pich", setNumericProperty, picture.height, 0 ),
195 MEMBER( "@pict", "pichgoal", setNumericProperty, picture.desiredHeight, 0 ),
196 MEMBER( "@pict", "picscaled", setFlagProperty, picture.scaled, true ),
197 MEMBER( "@pict", "picscalex", setNumericProperty, picture.scalex, 0 ),
198 MEMBER( "@pict", "picscaley", setNumericProperty, picture.scaley, 0 ),
199 MEMBER( "@pict", "picw", setNumericProperty, picture.width, 0 ),
200 MEMBER( "@pict", "picwgoal", setNumericProperty, picture.desiredWidth, 0 ),
201 PROP( 0L, "plain", setPlainFormatting, 0L, 0 ),
202 PROP( "@pict", "pmmetafile", setPictureType, 0L, RTFPicture::WMF ),
203 PROP( "@pict", "pngblip", setPictureType, 0L, RTFPicture::PNG ),
204 MEMBER( 0L, "qc", setEnumProperty, state.layout.alignment, RTFLayout::Centered ),
205 MEMBER( 0L, "qj", setEnumProperty, state.layout.alignment, RTFLayout::Justified ),
206 MEMBER( 0L, "ql", setEnumProperty, state.layout.alignment, RTFLayout::Left ),
207 PROP( 0L, "qmspace", insertSymbol, 0L, 0x2004 ),
208 MEMBER( 0L, "qr", setEnumProperty, state.layout.alignment, RTFLayout::Right ),
209 PROP( 0L, "rdblquote", insertSymbol, 0L, 0x201d ),
210 MEMBER( "@colortbl", "red", setNumericProperty, red, 0 ),
211 MEMBER( 0L, "ri", setNumericProperty, state.layout.rightIndent, 0 ),
212 PROP( "Text", "row", insertTableRow, 0L, 0 ),
213 PROP( 0L, "rquote", insertSymbol, 0L, 0x2019 ),
214 PROP( 0L, "rtlmark", insertSymbol, 0L, 0x200f ),
215 MEMBER( 0L, "s", setNumericProperty, state.layout.style, 0 ),
216 MEMBER( 0L, "sa", setNumericProperty, state.layout.spaceAfter, 0 ),
217 MEMBER( 0L, "sb", setNumericProperty, state.layout.spaceBefore, 0 ),
218 MEMBER( 0L, "scaps", setToggleProperty, state.format.smallCaps, 0 ),
219 PROP( "Text", "sect", insertPageBreak, 0L, 0 ),
220 PROP( 0L, "sectd", setSectionDefaults, 0L, 0 ),
221 MEMBER( 0L, "sl", setNumericProperty, state.layout.spaceBetween, 0 ),
222 MEMBER( 0L, "slmult", setToggleProperty, state.layout.spaceBetweenMultiple, 0 ),
223 MEMBER( "@stylesheet", "snext", setNumericProperty, style.next, 0 ),
224 MEMBER( 0L, "strike", setToggleProperty, state.format.strike, 0 ),
225 MEMBER( 0L, "striked", setToggleProperty, state.format.striked, 0 ),
226 MEMBER( 0L, "sub", setEnumProperty, state.format.vertAlign, RTFFormat::SubScript ),
227 MEMBER( 0L, "super", setEnumProperty, state.format.vertAlign, RTFFormat::SuperScript ),
228 PROP( 0L, "tab", insertSymbol, 0L, 0x0009 ),
229 MEMBER( 0L, "titlepg", setFlagProperty, state.section.titlePage, true ),
230 MEMBER( 0L, "tldot", setEnumProperty, state.layout.tab.leader, RTFTab::Dots ),
231 MEMBER( 0L, "tlhyph", setEnumProperty, state.layout.tab.leader, RTFTab::Hyphens ),
232 MEMBER( 0L, "tlth", setEnumProperty, state.layout.tab.leader, RTFTab::ThickLine ),
233 MEMBER( 0L, "tlul", setEnumProperty, state.layout.tab.leader, RTFTab::Underline ),
234 MEMBER( 0L, "tqc", setEnumProperty, state.layout.tab.type, RTFTab::Centered ),
235 MEMBER( 0L, "tqdec", setEnumProperty, state.layout.tab.type, RTFTab::Decimal ),
236 MEMBER( 0L, "tqr", setEnumProperty, state.layout.tab.type, RTFTab::FlushRight ),
237 MEMBER( 0L, "trleft", setNumericProperty, state.tableRow.left, 0 ),
238 MEMBER( 0L, "trowd", setTableRowDefaults, state.tableRow, 0 ),
239 MEMBER( 0L, "trqc", setEnumProperty, state.tableRow.alignment, RTFLayout::Centered ),
240 MEMBER( 0L, "trql", setEnumProperty, state.tableRow.alignment, RTFLayout::Left ),
241 MEMBER( 0L, "trqr", setEnumProperty, state.tableRow.alignment, RTFLayout::Right ),
242 MEMBER( 0L, "trrh", setNumericProperty, state.tableRow.height, 0 ),
243 PROP( 0L, "tx", insertTabDef, 0L, 0 ),
244 MEMBER( 0L, "u", insertUnicodeSymbol, state.format.uc, 0 ),
245 MEMBER( 0L, "uc", setNumericProperty, state.format.uc, 0 ),
246 PROP( 0L, "ul", setSimpleUnderlineProperty, 0L, 0 ),
247 MEMBER( 0L, "ulc", setNumericProperty, state.format.underlinecolor, 0 ),
248 PROP( 0L, "uld", setUnderlineProperty, 0L, RTFFormat::UnderlineDot ),
249 PROP( 0L, "uldash", setUnderlineProperty, 0L, RTFFormat::UnderlineDash ),
250 PROP( 0L, "uldashd", setUnderlineProperty, 0L, RTFFormat::UnderlineDashDot ),
251 PROP( 0L, "uldashdd", setUnderlineProperty, 0L, RTFFormat::UnderlineDashDotDot ),
252 PROP( 0L, "uldb", setUnderlineProperty, 0L, RTFFormat::UnderlineDouble ),
253 PROP( 0L, "ulnone", setUnderlineProperty, 0L, RTFFormat::UnderlineNone ),
254 PROP( 0L, "ulth", setUnderlineProperty, 0L, RTFFormat::UnderlineThick ),
255 PROP( 0L, "ulw", setUnderlineProperty, 0L, RTFFormat::UnderlineWordByWord ),
256 PROP( 0L, "ulwave", setUnderlineProperty, 0L, RTFFormat::UnderlineWave ),
257 PROP( 0L, "ulhwave", setUnderlineProperty, 0L, RTFFormat::UnderlineWave ),
258 PROP( 0L, "ululdbwave", setUnderlineProperty, 0L, RTFFormat::UnderlineWave ),
259 MEMBER( 0L, "up", setUpProperty, state.format.baseline, 6 ),
260 MEMBER( 0L, "v", setToggleProperty, state.format.hidden, 0 ),
262 PROP( "@pict", "wbitmap", setPictureType, 0L, RTFPicture::BMP ),
263 PROP( "@pict", "wmetafile", setPictureType, 0L, RTFPicture::EMF ),
264 PROP( 0L, "zwj", insertSymbol, 0L, 0x200d ),
265 PROP( 0L, "zwnj", insertSymbol, 0L, 0x200c )
271 { "AUTHOR", 8, 2, "NO AUTHOR" },
272 { "FILENAME", 8, 0, "NO FILENAME" },
273 { "TITLE", 8, 10, "NO TITLE" },
274 { "NUMPAGES", 4, 1, 0 },
276 { "TIME", -1, -1, 0 },
277 { "DATE", -1, -1, 0 },
278 { "HYPERLINK", 9, -1, 0 },
279 { "SYMBOL", -1, -1, 0 },
280 { "IMPORT", -1, -1, 0 }
285static const char *alignN[4] = { "left", "right", "justify", "center" };
286static const char *boolN[2] = { "false", "true" };
287static const char *borderN[4] = { "LEFTBORDER", "RIGHTBORDER", "TOPBORDER", "BOTTOMBORDER" };
289RTFImport::RTFImport( KoFilter *, const char *, const TQStringList& )
290 : KoFilter(), properties(181), destinationProperties(29), textCodec(0), utf8TextCodec(0)
292 for (uint i=0; i < sizeof(propertyTable) / sizeof(propertyTable[0]); i++)
294 properties.insert( propertyTable[i].name, &propertyTable[i] );
296 for (uint i=0; i < sizeof(destinationPropertyTable) / sizeof(destinationPropertyTable[0]); i++)
298 destinationProperties.insert( destinationPropertyTable[i].name, &destinationPropertyTable[i] );
302 kdDebug(30515) << properties.count() << " normal and " << destinationProperties.count() << " destination keywords loaded" << endl;
303 if (properties.size() < properties.count())
304 kdWarning(30515) << "Hash size of properties too small: " << properties.size() << ". It should be at least " << properties.count() << " and be a prime number"<< endl;
305 if (destinationProperties.size() < destinationProperties.count())
306 kdWarning(30515) << "Hash size of destinationProperties too small: " << destinationProperties.size() << ". It should be at least " << destinationProperties.count() << " and be a prime number"<< endl;
311KoFilter::ConversionStatus RTFImport::convert( const TQCString& from, const TQCString& to )
314 if ((from != "text/rtf") || (to != "application/x-kword"))
315 return KoFilter::NotImplemented;
322 if ( m_chain->manager() )
323 m_batch = m_chain->manager()->getBatchMode();
326 inFileName = m_chain->inputFile();
327 TQFile in( inFileName );
329 if (!in.open( IO_ReadOnly ))
331 kdError(30515) << "Unable to open input file!" << endl;
335 KMessageBox::error( 0L,
336 i18n( "The file cannot be loaded, as it cannot be opened."),
337 i18n( "KWord's RTF Import Filter"), 0 );
339 return KoFilter::FileNotFound;
346 if (token.type != RTFTokenizer::OpenGroup)
348 kdError(30515) << "Not an RTF file" << endl;
352 KMessageBox::error( 0L,
353 i18n( "The file cannot be loaded, as it seems not to be an RTF document."),
354 i18n( "KWord's RTF Import Filter"), 0 );
356 return KoFilter::WrongFormat;
363 if (token.type != RTFTokenizer::ControlWord)
365 kdError(30515) << "Wrong document type" << endl;
369 KMessageBox::error( 0L,
370 i18n( "The document cannot be loaded, as it seems not to follow the RTF syntax."),
371 i18n( "KWord's RTF Import Filter"), 0 );
373 return KoFilter::WrongFormat;
377 if ( !qstrcmp( token.text, "rtf" ) )
380 if ( token.value > 1 )
382 kdError(30515) << "Wrong RTF version (" << token.value << "); version 0 or 1 expected" << endl;
385 force = ( KMessageBox::warningYesNo( 0L,
386 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 ),
387 i18n( "KWord's RTF Import Filter") ) == KMessageBox::Yes );
392 return KoFilter::WrongFormat;
396 else if ( !qstrcmp( token.text, "pwd" ) )
399 if ( token.value != 2 )
401 kdError(30515) << "Wrong PWD version (" << token.value << "); version 2 expected" << endl;
404 force = ( KMessageBox::warningYesNo( 0L,
405 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 ),
406 i18n( "KWord's RTF Import Filter") ) == KMessageBox::Yes );
411 return KoFilter::WrongFormat;
415 else if ( !qstrcmp( token.text, "urtf" ) )
418 if ( token.value > 1 )
420 kdError(30515) << "Wrong URTF version (" << token.value << "); version 0 or 1 expected" << endl;
423 force = ( KMessageBox::warningYesNo( 0L,
424 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 ),
425 i18n( "KWord's RTF Import Filter") ) == KMessageBox::Yes );
430 return KoFilter::WrongFormat;
436 kdError(30515) << "Wrong RTF document type (\\" << token.text << "); \\rtf, \\pwd or \\urtf expected" << endl;
440 KMessageBox::error( 0L,
441 i18n( "The RTF document cannot be loaded, as it has an unexpected first keyword: \\%1.").arg( token.text ),
442 i18n( "KWord's RTF Import Filter"), 0 );
444 return KoFilter::WrongFormat;
463 frameSets.clear( 2 );
465 bodyText.node.clear( 3 );
466 firstPageHeader.node.clear( 3 );
467 oddPagesHeader.node.clear( 3 );
468 evenPagesHeader.node.clear( 3 );
469 firstPageFooter.node.clear( 3 );
470 oddPagesFooter.node.clear( 3 );
471 evenPagesFooter.node.clear( 3 );
477 stateStack.push( state );
480 destination.name = "!stackbottom";
482 changeDestination( destinationProperties[ "@rtf"] );
485 emptyCell = state.tableCell;
487 state.ignoreGroup = false;
489 utf8TextCodec=TQTextCodec::codecForName( "UTF-8");
490 kdDebug(30515) << "UTF-8 asked, given: " << (utf8TextCodec?TQString(utf8TextCodec->name()):TQString( "-none-")) << endl;
493 textCodec=TQTextCodec::codecForName( "CP 1252");
494 kdDebug(30515) << "CP 1252 asked, given: " << (textCodec?TQString(textCodec->name()):TQString( "-none-")) << endl;
499 bool firstToken = false;
500 bool ignoreUnknown = false;
504 while (token.type == RTFTokenizer::OpenGroup)
507 stateStack.push( state );
508 state.brace0 = false;
510 ignoreUnknown = false;
514 if (token.type == RTFTokenizer::ControlWord && !qstrcmp( token.text, "*" ))
517 ignoreUnknown = true;
521 if (token.type == RTFTokenizer::CloseGroup)
526 (this->*destination.destproc)(0L);
528 if (destinationStack.isEmpty())
530 kdWarning(30515) << "Destination stack is empty! Document might be buggy!" << endl;
535 destination = destinationStack.pop();
539 if (stateStack.count() <= 1)
548 state = stateStack.pop();
551 else if (token.type == RTFTokenizer::ControlWord)
557 if (property->onlyValidIn == 0L ||
558 property->onlyValidIn == destination.name ||
559 property->onlyValidIn == destination.group)
561 (this->* property->cwproc)( property );
567 *(--token.text) = '@';
568 property = destinationProperties[token.text];
570 if ((property != 0L) &&
571 ( property->onlyValidIn == 0L ||
572 property->onlyValidIn == destination.name ||
573 property->onlyValidIn == destination.group))
576 changeDestination( property );
578 else if (ignoreUnknown)
581 changeDestination( destinationProperties[ "@*"] );
582 debugUnknownKeywords[token.text]++;
584 else if ( !property )
586 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;
588 kdWarning(30515) << " Assuming destination: " << destination.name << endl;
589 debugUnknownKeywords[token.text]++;
594 debugUnknownKeywords[token.text]++;
597 else if (token.type == RTFTokenizer::PlainText || token.type == RTFTokenizer::BinaryData)
599 (this->*destination.destproc)(0L);
604 const int hType = facingPages
605 ? (state.section.titlePage ? 3 : 1) : (state.section.titlePage ? 2 : 0);
607 const bool hasHeader = !oddPagesHeader.node.isEmpty() ||
608 (facingPages &&!evenPagesHeader.node.isEmpty()) ||
609 (state.section.titlePage && !firstPageHeader.node.isEmpty());
610 const bool hasFooter = !oddPagesFooter.node.isEmpty() ||
611 (facingPages && !evenPagesFooter.node.isEmpty()) ||
612 (state.section.titlePage && !firstPageFooter.node.isEmpty());
614 kdDebug(30515) << "hType " << hType << " hasHeader " << hasHeader << " hasFooter " << hasFooter << endl;
617 DomNode mainDoc( "DOC" );
618 mainDoc.setAttribute( "mime", "application/x-kword" );
619 mainDoc.setAttribute( "syntaxVersion", "3" );
620 mainDoc.setAttribute( "editor", "KWord's RTF Import Filter" );
621 mainDoc.addNode( "PAPER" );
622 mainDoc.setAttribute( "format", 6 );
623 mainDoc.setAttribute( "columns", 1 );
624 mainDoc.setAttribute( "columnspacing", 2 );
625 mainDoc.setAttribute( "spHeadBody", 4 );
626 mainDoc.setAttribute( "spFootBody", 4 );
627 mainDoc.setAttribute( "zoom", 100 );
628 mainDoc.setAttribute( "width", .05*paperWidth );
629 mainDoc.setAttribute( "height", .05*paperHeight );
630 mainDoc.setAttribute( "orientation", landscape );
631 mainDoc.setAttribute( "hType", hType );
632 mainDoc.setAttribute( "fType", hType );
633 mainDoc.addNode( "PAPERBORDERS" );
634 mainDoc.addRect( leftMargin,
635 (hasHeader ? state.section.headerMargin : topMargin),
637 (hasFooter ? state.section.footerMargin : bottomMargin) );
638 mainDoc.closeNode( "PAPERBORDERS" );
639 mainDoc.closeNode( "PAPER" );
640 mainDoc.addNode( "ATTRIBUTES" );
641 mainDoc.setAttribute( "standardpage", 1 );
642 mainDoc.setAttribute( "processing", 0 );
644 mainDoc.setAttribute( "hasHeader", hasHeader );
645 mainDoc.setAttribute( "hasFooter", hasFooter );
646 mainDoc.closeNode( "ATTRIBUTES" );
647 mainDoc.addNode( "FRAMESETS" );
648 mainDoc.addFrameSet( "Frameset 1", 1, 0 );
649 mainDoc.addFrame( leftMargin, topMargin, (paperWidth - rightMargin),
650 (paperHeight - bottomMargin), 1, 0, 0 );
651 mainDoc.closeNode( "FRAME" );
652 mainDoc.appendNode( bodyText.node );
653 mainDoc.closeNode( "FRAMESET" );
657 mainDoc.addFrameSet( "First Page Header", 1, 1 );
658 mainDoc.addFrame( leftMargin, state.section.headerMargin,
659 (paperWidth - rightMargin), (topMargin - 80), 0, 2, 0 );
660 mainDoc.closeNode( "FRAME" );
661 mainDoc.appendNode( firstPageHeader.node );
662 mainDoc.closeNode( "FRAMESET" );
663 mainDoc.addFrameSet( "Odd Pages Header", 1, 2 );
664 mainDoc.addFrame( leftMargin, state.section.headerMargin,
665 (paperWidth - rightMargin), (topMargin - 80), 0, 2, 1 );
666 mainDoc.closeNode( "FRAME" );
667 mainDoc.appendNode( oddPagesHeader.node );
668 mainDoc.closeNode( "FRAMESET" );
669 mainDoc.addFrameSet( "Even Pages Header", 1, 3 );
670 mainDoc.addFrame( leftMargin, state.section.headerMargin,
671 (paperWidth - rightMargin), (topMargin - 80), 0, 2, 2 );
672 mainDoc.closeNode( "FRAME" );
673 mainDoc.appendNode( evenPagesHeader.node );
674 mainDoc.closeNode( "FRAMESET" );
679 mainDoc.addFrameSet( "First Page Footer", 1, 4 );
680 mainDoc.addFrame( leftMargin, state.section.headerMargin,
681 (paperWidth - rightMargin), (topMargin - 80), 0, 2, 0 );
682 mainDoc.closeNode( "FRAME" );
683 mainDoc.appendNode( firstPageFooter.node );
684 mainDoc.closeNode( "FRAMESET" );
685 mainDoc.addFrameSet( "Odd Pages Footer", 1, 5 );
686 mainDoc.addFrame( leftMargin, state.section.headerMargin,
687 (paperWidth - rightMargin), (topMargin - 80), 0, 2, 1 );
688 mainDoc.closeNode( "FRAME" );
689 mainDoc.appendNode( oddPagesFooter.node );
690 mainDoc.closeNode( "FRAMESET" );
691 mainDoc.addFrameSet( "Even Pages Footer", 1, 6 );
692 mainDoc.addFrame( leftMargin, state.section.headerMargin,
693 (paperWidth - rightMargin), (topMargin - 80), 0, 2, 2 );
694 mainDoc.closeNode( "FRAME" );
695 mainDoc.appendNode( evenPagesFooter.node );
696 mainDoc.closeNode( "FRAMESET" );
700 for( RTFTextState* i=footnotes.first();i;i=footnotes.next())
704 str.prepend( "Footnote ");
706 mainDoc.addFrameSet( str, 1, 7 );
707 mainDoc.addFrame( leftMargin, paperHeight - bottomMargin-80,
708 (paperWidth - rightMargin), paperHeight-bottomMargin, 0, 2, 0 );
709 mainDoc.closeNode( "FRAME" );
710 mainDoc.appendNode( i->node );
711 mainDoc.closeNode( "FRAMESET" );
713 mainDoc.appendNode( frameSets );
714 mainDoc.closeNode( "FRAMESETS" );
715 mainDoc.addNode( "PICTURES" );
716 mainDoc.appendNode( pictures );
717 mainDoc.closeNode( "PICTURES" );
718 mainDoc.addNode( "STYLES" );
724 const TQValueList<RTFStyle>::ConstIterator endStyleSheet=styleSheet.end();
725 for (TQValueList<RTFStyle>::ConstIterator it=styleSheet.begin();it!=endStyleSheet;++it)
727 mainDoc.addNode( "STYLE" );
728 kwFormat.fmt = (*it).format;
731 for (TQValueList<RTFStyle>::ConstIterator it2=styleSheet.begin();it2!=endStyleSheet;++it2)
733 if ((*it2).layout.style == (*it).next)
735 mainDoc.addNode( "FOLLOWING" );
736 mainDoc.setAttribute( "name", CheckAndEscapeXmlText( (*it2).name ));
737 mainDoc.closeNode( "FOLLOWING");
741 addLayout( mainDoc, (*it).name, (*it).layout, false );
742 addFormat( mainDoc, kwFormat, 0L );
743 mainDoc.closeNode( "STYLE" );
745 mainDoc.closeNode( "STYLES" );
746 mainDoc.closeNode( "DOC" );
749 DomNode docInfo( "document-info" );
750 docInfo.addNode( "log" );
751 docInfo.addNode( "text" );
752 docInfo.closeNode( "text" );
753 docInfo.closeNode( "log" );
754 docInfo.addNode( "author" );
755 docInfo.addNode( "company" );
756 docInfo.appendNode( company );
757 docInfo.closeNode( "company" );
758 docInfo.addNode( "full-name" );
759 docInfo.appendNode( author );
760 docInfo.closeNode( "full-name" );
761 docInfo.addNode( "email" );
762 docInfo.closeNode( "email" );
763 docInfo.addNode( "telephone" );
764 docInfo.closeNode( "telephone" );
765 docInfo.addNode( "fax" );
766 docInfo.closeNode( "fax" );
767 docInfo.addNode( "country" );
768 docInfo.closeNode( "country" );
769 docInfo.addNode( "postal-code" );
770 docInfo.closeNode( "postal-code" );
771 docInfo.addNode( "city" );
772 docInfo.closeNode( "city" );
773 docInfo.addNode( "street" );
774 docInfo.closeNode( "street" );
775 docInfo.closeNode( "author" );
776 docInfo.addNode( "about" );
777 docInfo.addNode( "abstract" );
778 docInfo.appendNode( doccomm );
779 docInfo.closeNode( "abstract" );
780 docInfo.addNode( "title" );
781 docInfo.appendNode( title );
782 docInfo.closeNode( "title" );
783 docInfo.closeNode( "about" );
784 docInfo.closeNode( "document-info" );
787 writeOutPart( "root", mainDoc );
788 writeOutPart( "documentinfo.xml", docInfo );
791 kdDebug(30515) << "RTF FILTER TIME: " << debugTime.elapsed() << endl;
793 for (TQMap<TQString,int>::ConstIterator it=debugUnknownKeywords.begin();
794 it!=debugUnknownKeywords.end();it++)
795 kdDebug(30515) << "Unknown keyword: " << TQString( "%1" ).arg( it.data(), 4 ) << " * " << it.key() << endl;
806 TQTextCodec* oldCodec = textCodec;
808 if ( token.value == 10000 )
814 cp.setNum( token.value );
817 textCodec=TQTextCodec::codecForName(cp);
818 kdDebug(30515) << "\\ansicpg: codepage: " << token.value << "asked: "<< cp << " given: " << (textCodec?TQString(textCodec->name()):TQString( "-none-")) << endl;
820 textCodec = oldCodec;
825 TQTextCodec* oldCodec = textCodec;
826 textCodec=TQTextCodec::codecForName( "Apple Roman");
827 kdDebug(30515) << "\\mac " << (textCodec?TQString(textCodec->name()):TQString( "-none-")) << endl;
829 textCodec = oldCodec;
834 TQTextCodec* oldCodec = textCodec;
835 textCodec=TQTextCodec::codecForName( "CP1252");
836 kdDebug(30515) << "\\ansi " << (textCodec?TQString(textCodec->name()):TQString( "-none-")) << endl;
838 textCodec = oldCodec;
843 TQTextCodec* oldCodec = textCodec;
844 textCodec=TQTextCodec::codecForName( "IBM 850");
845 kdDebug(30515) << "\\pca " << (textCodec?TQString(textCodec->name()):TQString( "-none-")) << endl;
847 textCodec = oldCodec;
852 TQTextCodec* oldCodec = textCodec;
853 textCodec=TQTextCodec::codecForName( "IBM 850");
854 kdDebug(30515) << "\\pc (approximation) " << (textCodec?TQString(textCodec->name()):TQString( "-none-")) << endl;
856 textCodec = oldCodec;
859void RTFImport::setToggleProperty( RTFProperty *property )
861 (( bool *) this)[ property->offset] = (!token.hasParam || token.value != 0);
864void RTFImport::setFlagProperty( RTFProperty *property )
866 (( bool *) this)[ property->offset] = property->value;
872 switch(token.value) {
873 case 0: cp = "CP1252"; break;
874 case 1: cp = "CP1252"; break;
876 case 77: cp = "Apple Roman"; break;
877 case 128: cp = "Shift-JIS"; break;
878 case 129: cp = "eucKR"; break;
879 case 130: cp = "CP1361"; break;
880 case 134: cp = "GB2312"; break;
881 case 136: cp = "Big5-HKSCS"; break;
882 case 161: cp = "CP1253"; break;
883 case 162: cp = "CP1254"; break;
884 case 163: cp = "CP1258"; break;
885 case 177: cp = "CP1255"; break;
886 case 178: cp = "CP1256"; break;
887 case 186: cp = "CP1257"; break;
888 case 204: cp = "CP1251"; break;
889 case 222: cp = "CP874"; break;
890 case 238: cp = "CP1250"; break;
891 case 255: cp = "CP850"; break;
894 TQTextCodec* oldCodec = textCodec;
895 textCodec=TQTextCodec::codecForName(cp);
896 kdDebug(30515) << "\\fcharset: charset: " << token.value << " codepage: "<< cp << " given: " << (textCodec?TQString(textCodec->name()):TQString( "-none-")) << endl;
898 textCodec = oldCodec;
901void RTFImport::setNumericProperty( RTFProperty *property )
903 *(( int *)((( char *) this) + property->offset)) = token.hasParam ? token.value : property->value;
906void RTFImport::setEnumProperty( RTFProperty *property )
908 *(( int *)((( char *) this) + property->offset)) = property->value;
911void RTFImport::setFontStyleHint( RTFProperty* property )
913 font.styleHint = TQFont::StyleHint( property-> value );
916void RTFImport::setPictureType( RTFProperty* property )
918 picture.type = RTFPicture::PictureType( property-> value );
921void RTFImport::setSimpleUnderlineProperty( RTFProperty* )
923 state.format.underline
924 = (!token.hasParam || token.value != 0)
925 ? RTFFormat::UnderlineSimple : RTFFormat::UnderlineNone;
928void RTFImport::setUnderlineProperty( RTFProperty* property )
930 state.format.underline = RTFFormat::Underline( property-> value );
933void RTFImport::setBorderStyle( RTFProperty *property )
935 if (state.layout.border)
937 state.layout.border->style = static_cast <RTFBorder::BorderStyle > ( property->value );
941 for (uint i=0; i < 4; i++)
943 state.layout.borders[i].style = static_cast <RTFBorder::BorderStyle > ( property->value );
948void RTFImport::setBorderProperty( RTFProperty *property )
951 if (state.layout.border)
953 state.layout.border->width = token.value;
957 for (uint i=0; i < 4; i++)
959 state.layout.borders[i].width = token.value;
966 if (state.layout.border)
968 state.layout.border->color = token.value;
972 for (uint i=0; i < 4; i++)
974 state.layout.borders[i].color = token.value;
981 state.format.baseline = token.hasParam ? -token.value : -6;
988 format.font = defaultFont;
989 format.fontSize = 24;
993 format.underlinecolor = -1;
994 format.vertAlign = RTFFormat::Normal;
996 format.italic = false;
997 format.strike = false;
998 format.striked = false;
999 format.hidden = false;
1000 format.caps = false;
1001 format.smallCaps = false;
1003 format.underline = RTFFormat::UnderlineNone;
1008void RTFImport::setParagraphDefaults( RTFProperty * )
1012 layout.tablist.clear();
1013 layout.tab.type = RTFTab::Left;
1014 layout.tab.leader = RTFTab::None;
1016 for (uint i=0; i < 4; i++)
1021 border.style = RTFBorder::None;
1023 layout.firstIndent = 0;
1024 layout.leftIndent = 0;
1025 layout.rightIndent = 0;
1026 layout.spaceBefore = 0;
1027 layout.spaceAfter = 0;
1031 layout.alignment = RTFLayout::Left;
1033 layout.inTable = false;
1034 layout.keep = false;
1035 layout.keepNext = false;
1036 layout.pageBB = false;
1037 layout.pageBA = false;
1040void RTFImport::setSectionDefaults( RTFProperty * )
1044 section.headerMargin = 720;
1045 section.footerMargin = 720;
1046 section.titlePage = false;
1049void RTFImport::setTableRowDefaults( RTFProperty * )
1054 tableRow.height = 0;
1056 tableRow.alignment = RTFLayout::Left;
1057 tableRow.cells.clear();
1058 tableCell.bgcolor = -1;
1060 for (uint i=0; i < 4; i++)
1062 RTFBorder &border = tableCell.borders[i];
1065 border.style = RTFBorder::None;
1069void RTFImport::selectLayoutBorder( RTFProperty * property )
1071 state.layout.border = & state.layout.borders [ property->value ];
1074void RTFImport::selectLayoutBorderFromCell( RTFProperty * property )
1076 state.layout.border = & state.tableCell.borders [ property->value ];
1081 if (state.layout.inTable)
1083 if (textState->table == 0)
1086 textState->table = ++table;
1088 addParagraph( textState->cell, false );
1092 if (textState->table)
1096 addParagraph( textState->node, false );
1102 if (textState->length > 0)
1106 addParagraph( textState->node, true );
1112 bool b = state.layout.inTable;
1113 state.layout.inTable = true;
1115 state.layout.inTable = b;
1117 textState->frameSets << textState->cell.toString();
1118 textState->cell.clear( 3 );
1123 if (!textState->frameSets.isEmpty())
1126 row.frameSets = textState->frameSets;
1128 if (textState->rows.isEmpty())
1131 sprintf( buf, "Table %d", textState->table );
1132 RTFLayout::Alignment align = row.alignment;
1135 stateStack.push( state );
1137 state.layout.alignment = align;
1141 addParagraph( textState->node, false );
1144 state = stateStack.pop();
1148 while (row.cells.count() > row.frameSets.count())
1151 row.cells.pop_back();
1153 while (row.cells.count() < row.frameSets.count())
1155 row.cells << row.cells.last();
1160 if (row.height == 0)
1165 for (uint k=0; k < row.cells.count(); k++)
1167 if ((row.cells[k].x - lx) < 1)
1168 row.cells[k].x = ++lx;
1170 lx = row.cells[k].x;
1175 for (uint k=0; k < row.cells.count(); k++)
1177 row.cells[k].x -= row.left;
1181 textState->rows << row;
1182 textState->frameSets.clear();
1189 cell.x = token.value;
1190 state.tableRow.cells << cell;
1193 for (uint i=0; i < 4; i++)
1198 border.style = RTFBorder::None;
1204 RTFTab tab = state.layout.tab;
1205 tab.position = token.value;
1206 state.layout.tablist.push( tab );
1207 tab.type = RTFTab::Left;
1208 tab.leader = RTFTab::None;
1211void RTFImport::insertUTF8( int ch )
1213 kdDebug(30515) << "insertUTF8: " << ch << endl;
1216 char *tk = token.text;
1217 token.type = RTFTokenizer::PlainText;
1228 *text++ = 0xe0 | (ch >> 12);
1229 ch = (ch & 0xfff) | 0x1000;
1231 *text++ = ((ch >> 6) | 0x80) ^ 0x40;
1232 ch = (ch & 0x3f) | 0x80;
1237 TQTextCodec* oldCodec=textCodec;
1240 textCodec=utf8TextCodec;
1242 kdError(30515) << "No UTF-8 TQTextCodec available" << endl;
1244 (this->*destination.destproc)(0L);
1250void RTFImport::insertSymbol( RTFProperty *property )
1252 insertUTF8( property-> value );
1266 kdWarning(30515) << "Trying to insert NUL character!" << endl;
1270 char tmpch[2] = {(char)(token.value), '\0'};
1272 char *tk = token.text;
1273 token.type = RTFTokenizer::PlainText;
1276 (this->*destination.destproc)(0L);
1281void RTFImport::insertUnicodeSymbol( RTFProperty * )
1283 const int ch = token.value;
1286 for (uint i=state.format.uc; i > 0; )
1290 if (token.type == RTFTokenizer::ControlWord)
1292 else if (token.type == RTFTokenizer::OpenGroup ||
1293 token.type == RTFTokenizer::CloseGroup)
1297 else if (token.type == RTFTokenizer::PlainText)
1299 const uint len = tqstrlen( token.text );
1309 if (token.type != RTFTokenizer::PlainText)
1311 token.type = RTFTokenizer::PlainText;
1315 (this->*destination.destproc)(0L);
1320 if (token.type == RTFTokenizer::OpenGroup)
1322 font.name = TQString();
1323 font.styleHint = TQFont::AnyStyle;
1324 font.fixedPitch = 0;
1326 else if (token.type == RTFTokenizer::PlainText)
1330 kdError(30515) << "No text codec for font!" << endl;
1336 if (strchr( token.text, ';' ) == 0L)
1337 font.name += textCodec->toUnicode( token.text );
1341 *strchr( token.text, ';' ) = 0;
1342 font.name += textCodec->toUnicode( token.text );
1344 TQFont qFont( font.name );
1345 qFont.setFixedPitch( (font.fixedPitch == 1) );
1346 qFont.setStyleHint( font.styleHint );
1347 for(;!qFont.exactMatch();)
1349 int space=font.name.findRev( ' ', font.name.length());
1352 font.name.truncate(space);
1353 qFont.setFamily( font.name );
1355 const TQFontInfo info( qFont );
1356 const TQString newFontName ( info.family() );
1357 kdDebug(30515) << "Font " << state.format.font << " asked: " << font.name << " given: " << newFontName << endl;
1359 if ( newFontName.isEmpty() )
1360 fontTable.insert( state.format.font, font.name );
1362 fontTable.insert( state.format.font, newFontName );
1363 font.name.truncate( 0 );
1364 font.styleHint = TQFont::AnyStyle;
1365 font.fixedPitch = 0;
1372 if (token.type == RTFTokenizer::OpenGroup)
1377 else if (token.type == RTFTokenizer::PlainText)
1380 if (strchr( token.text, ';' ) == 0L)
1381 style.name += textCodec->toUnicode( token.text );
1385 *strchr( token.text, ';' ) = 0;
1386 style.name += textCodec->toUnicode( token.text );
1387 style.format = state.format;
1388 style.layout = state.layout;
1389 style.next = (style.next == -1) ? style.layout.style : style.next;
1390 styleSheet << style;
1391 style.name.truncate( 0 );
1399 if (token.type == RTFTokenizer::OpenGroup)
1405 else if (token.type == RTFTokenizer::PlainText)
1409 while ((token.text = strchr( token.text, ';' )))
1411 colorTable << TQColor( red, green, blue );
1412 red = green = blue = 0;
1420 if (token.type == RTFTokenizer::OpenGroup)
1422 picture.identifier = TQString();
1424 else if (token.type == RTFTokenizer::PlainText)
1426 picture.identifier += TQString::fromUtf8( token.text );
1428 else if (token.type == RTFTokenizer::CloseGroup)
1430 kdDebug(30515) << "\\blipuid: " << picture.identifier << endl;
1436 if (state.ignoreGroup)
1439 if (token.type == RTFTokenizer::OpenGroup)
1441 picture.type = RTFPicture::PNG;
1444 picture.desiredWidth = 0;
1445 picture.desiredHeight = 0;
1446 picture.scalex = 100;
1447 picture.scaley = 100;
1448 picture.cropLeft = 0;
1449 picture.cropTop = 0;
1450 picture.cropRight = 0;
1451 picture.cropBottom = 0;
1453 picture.bits.truncate( 0 );
1454 picture.identifier = TQString();
1456 else if (token.type == RTFTokenizer::PlainText)
1460 *(--token.text) = picture.nibble;
1462 uint n = tqstrlen( token.text ) >> 1;
1463 picture.bits.resize( picture.bits.size() + n );
1464 char *src = token.text;
1465 char *dst = (picture.bits.data() + picture.bits.size() - n);
1472 *dst++ = (((k + ((k & 16) ? 0 : 9)) & 0xf) << 4) |
1473 ((l + ((l & 16) ? 0 : 9)) & 0xf);
1475 picture.nibble = *src;
1477 else if (token.type == RTFTokenizer::BinaryData)
1479 picture.bits = token.binaryData;
1480 kdDebug(30515) << "Binary data of length: " << picture.bits.size() << endl;
1482 else if (token.type == RTFTokenizer::CloseGroup)
1487 switch (picture.type)
1489 case RTFPicture::WMF:
1490 case RTFPicture::EMF:
1493 case RTFPicture::BMP:
1496 case RTFPicture::MacPict:
1499 case RTFPicture::JPEG:
1502 case RTFPicture::PNG:
1507 const int id = ++pictureNumber;
1508 TQString pictName( "pictures/picture");
1509 pictName += TQString::number( id);
1512 TQCString frameName;
1513 frameName.setNum( id);
1514 frameName.prepend( "Picture ");
1517 if (picture.identifier.isEmpty())
1523 idStr += picture.identifier.stripWhiteSpace();
1527 kdDebug(30515) << "Picture: " << pictName << " Frame: " << frameName << endl;
1530 KoStoreDevice* dev = m_chain->storageFile( pictName, KoStore::Write );
1532 dev->writeBlock(picture.bits.data(),picture.bits.size());
1534 kdError(30515) << "Could not save: " << pictName << endl;
1538 addAnchor( frameName );
1541 const TQDateTime dt(TQDateTime::currentDateTime());
1544 pictures.addKey( dt, idStr, pictName );
1547 frameSets.addFrameSet( frameName, 2, 0 );
1550 frameSets.addFrame( 0, 0,
1551 (picture.desiredWidth * picture.scalex) /100 ,
1552 (picture.desiredHeight * picture.scaley) /100 , 0, 1, 0 );
1553 frameSets.closeNode( "FRAME" );
1554 frameSets.addNode( "PICTURE" );
1555 frameSets.addKey( dt, idStr );
1556 frameSets.closeNode( "PICTURE" );
1557 frameSets.closeNode( "FRAMESET" );
1558 picture.identifier = TQString();
1562void RTFImport::addImportedPicture( const TQString& rawFileName )
1564 kdDebug(30515) << "Import field: reading " << rawFileName << endl;
1566 if (rawFileName== "\\*")
1568 kdError(30515) << "Import field without file name!" << endl;
1572 TQString slashPath( rawFileName );
1573 slashPath.replace( '\\', '/');
1576 info.setFile( inFileName );
1577 TQDir dir( info.dirPath() );
1580 url.setPath(dir.filePath( rawFileName ));
1582 kdDebug(30515) << "Path: " << url.prettyURL() << endl;
1585 pic.setKeyAndDownloadPicture(url, 0);
1588 kdError(30515) << "Import field: file is empty: " << rawFileName << endl;
1592 const uint id = ++pictureNumber;
1594 TQString pictName( "pictures/picture");
1595 pictName += TQString::number( id);
1597 pictName += pic.getExtension();
1599 TQCString frameName;
1600 frameName.setNum( id);
1601 frameName.prepend( "Picture ");
1604 kdDebug(30515) << "Imported picture: " << pictName << " Frame: " << frameName << endl;
1607 KoStoreDevice* dev = m_chain->storageFile( pictName, KoStore::Write );
1611 kdError(30515) << "Could not save: " << pictName << endl;
1614 addAnchor( frameName );
1617 const TQDateTime dt( pic.getKey().lastModified() );
1620 pictures.addKey( dt, rawFileName, pictName );
1623 const TQSize size ( pic.getOriginalSize() * 20 );
1624 frameSets.addFrameSet( frameName, 2, 0 );
1625 frameSets.addFrame( 0, 0, size.width(), size.height(), 0, 1, 0 );
1626 frameSets.closeNode( "FRAME" );
1627 frameSets.addNode( "PICTURE" );
1628 frameSets.addKey( dt, rawFileName );
1629 frameSets.closeNode( "PICTURE" );
1630 frameSets.closeNode( "FRAMESET" );
1636 node.addNode( "PGNUM" );
1637 node.setAttribute( "subtype", 0 );
1638 node.setAttribute( "value", 0 );
1639 node.closeNode( "PGNUM");
1640 addVariable( node, 4, "NUMBER", &state.format);
1643void RTFImport::insertDateTime( RTFProperty *property )
1645 kdDebug(30515) << "insertDateTime: " << property->value << endl;
1646 addDateTime( TQString(), bool(property-> value), state.format );
1649void RTFImport::addDateTime( const TQString& format, const bool isDate, RTFFormat& fmt )
1652 TQString kwordFormat(format);
1653 if (format.isEmpty())
1656 kwordFormat = "DATElocale";
1658 kwordFormat = "TIMElocale";
1664 const TQRegExp regexp ( "[yMd]");
1665 asDate = (regexp.search(format)>-1);
1671 node.addNode( "DATE");
1672 node.setAttribute( "year", 0);
1673 node.setAttribute( "month", 0);
1674 node.setAttribute( "day", 0);
1675 node.setAttribute( "fix", 0);
1676 node.closeNode( "DATE");
1677 addVariable(node, 0, kwordFormat, &fmt);
1682 node.addNode( "TIME");
1683 node.setAttribute( "hour", 0);
1684 node.setAttribute( "minute", 0);
1685 node.setAttribute( "second", 0);
1686 node.setAttribute( "fix", 0);
1687 node.closeNode( "TIME");
1688 addVariable(node, 2, kwordFormat, &fmt);
1694 if (token.type == RTFTokenizer::OpenGroup)
1699 flddst = (destinationStack.count() - 1);
1703 destination.group = 0L;
1705 else if (token.type == RTFTokenizer::CloseGroup)
1707 if (!fldinst.isEmpty())
1710 TQStringList list ( TQStringList::split( ' ', fldinst, false ) );
1711 kdDebug(30515) << "Field: " << list << endl;
1714 TQString fieldName ( list[0].upper() );
1715 fieldName.remove( '\\');
1719 for (i=0; i < sizeof(fieldTable) / sizeof(fieldTable[0]); i++)
1721 if (fieldName == fieldTable[i]. id)
1723 kdDebug(30515) << "Field found: " << fieldTable[i].id << endl;
1730 kdWarning(30515) << "Field not supported: " << fieldName << endl;
1733 if (fieldTable[i].type == 4)
1735 node.addNode( "PGNUM" );
1736 node.setAttribute( "subtype", fieldTable[i].subtype );
1737 node.setAttribute( "value", 0 );
1738 node.closeNode( "PGNUM");
1739 addVariable( node, 4, "NUMBER", &fldfmt);
1741 else if (fieldTable[i].type == 8)
1743 node.addNode( "FIELD" );
1744 node.setAttribute( "subtype", fieldTable[i].subtype );
1745 node.setAttribute( "value", fieldTable[i].value );
1746 node.closeNode( "FIELD");
1747 addVariable( node, 8, "STRING", &fldfmt);
1749 else if (fieldTable[i].type == 9)
1751 TQString hrefName = TQString();
1754 for (uint i=1; i < list.count(); i++)
1756 if (list[i] == "\\l")
1760 else if (list[i].startsWith( "\"" ) && list[i].endsWith( "\"" ))
1762 hrefName += list[i].mid( 1, (list[i].length() - 2) );
1764 else if (list[i].startsWith( "http"))
1766 hrefName += list[i];
1769 node.addNode( "LINK" );
1770 node.setAttribute( "linkName", !fldrslt.isNull() );
1771 node.setAttribute( "hrefName", hrefName );
1772 node.closeNode( "LINK" );
1773 addVariable( node, 9, "STRING", &fldfmt);
1775 else if (fieldName == "SYMBOL")
1777 if (list.count() >= 2)
1779 int ch = list[1].toInt();
1784 destination = destinationStack[flddst];
1785 state.format = fldfmt;
1790 else if (fieldName == "TIME" || fieldName == "DATE")
1792 TQString strFldinst( TQString::fromUtf8(fldinst) );
1793 TQRegExp regexp( "\\\\@\\s*\"(.+)\"");
1794 if (regexp.search(strFldinst)==-1)
1796 kdWarning(30515) << "Date/time field format not in quotes!" << endl;
1798 regexp = TQRegExp( "\\\\@(\\S+)\\s+");
1799 regexp.search(strFldinst);
1801 TQString format(regexp.cap(1));
1802 kdDebug(30515) << "Date/time field format: " << format << endl;
1803 format.replace( "am/pm", "ap");
1804 format.replace( "a/p", "ap");
1805 format.replace( "AM/PM", "AP");
1806 format.replace( "A/P", "AP");
1808 addDateTime( format, (fieldName == "DATE"), fldfmt );
1810 else if (fieldName == "IMPORT")
1812 addImportedPicture( list[1] );
1818 if (flddst == ( int) (destinationStack.count() - 1))
1828 if (token.type == RTFTokenizer::OpenGroup)
1832 else if (token.type == RTFTokenizer::PlainText)
1834 fldinst += token.text;
1840 if (fldinst.isEmpty())
1842 if (token.type == RTFTokenizer::OpenGroup)
1845 destination = destinationStack[flddst];
1846 destination.destproc = &RTFImport::parseFldrslt;
1848 else if (token.type != RTFTokenizer::CloseGroup)
1850 (this->*destinationStack[flddst].destproc)(0L);
1853 else if (token.type == RTFTokenizer::OpenGroup)
1857 else if (token.type == RTFTokenizer::PlainText)
1859 fldrslt += token.text;
1861 else if (token.type == RTFTokenizer::CloseGroup)
1863 fldfmt = state.format;
1867void RTFImport::addVariable ( const DomNode& spec, int type, const TQString& key, const RTFFormat* fmt)
1872 node.addNode( "VARIABLE" );
1873 node.closeTag( true);
1874 node.addNode( "TYPE");
1875 node.setAttribute( "type", type );
1876 node.setAttribute( "key", CheckAndEscapeXmlText(key) );
1877 node.setAttribute( "text", 1 );
1878 node.closeNode( "TYPE");
1880 node.appendNode(spec);
1881 node.closeNode( "VARIABLE" );
1882 kwFormat.xmldata = node.toString();
1884 kwFormat.pos = textState->length++;
1887 kwFormat.fmt = *fmt;
1888 textState->text.append( '#' );
1889 textState->formats << kwFormat;
1892void RTFImport::parseFootNote( RTFProperty * property)
1894 if(token.type==RTFTokenizer::OpenGroup)
1897 footnotes.append(newTextState);
1899 destination.target = newTextState;
1903 str.prepend( "Footnote ");
1908 node.addNode( "FOOTNOTE");
1909 node.setAttribute( "numberingtype", "auto");
1910 node.setAttribute( "notetype", "footnote");
1911 node.setAttribute( "frameset", !str.isNull());
1912 node.setAttribute( "value", fnnum);
1913 node.closeNode( "FOOTNOTE");
1914 addVariable(node, 11, "STRING");
1916 parseRichText(property);
1921 if (token.type == RTFTokenizer::OpenGroup)
1925 textState = destination.target;
1926 destination.target = oldState;
1927 destination.group = "Text";
1930 textState-> text.clear();
1931 textState->node.clear( 3 );
1932 textState->cell.clear( 3 );
1933 textState->formats.clear();
1934 textState->frameSets.clear();
1935 textState->rows.clear();
1936 textState->table = 0;
1937 textState->length = 0;
1939 else if (token.type == RTFTokenizer::PlainText)
1942 if (!state.format.hidden)
1944 const int len = (token.text[0] < 0) ? 1 : tqstrlen( token.text );
1947 if ( textState->formats.isEmpty() ||
1948 textState->formats.last().fmt != state.format ||
1949 ( !textState->formats.last().xmldata.isEmpty() ) )
1951 kwFormat.fmt = state.format;
1953 kwFormat.pos = textState->length;
1955 textState->formats << kwFormat;
1956 kwFormat.xmldata = TQString();
1960 textState->formats.last().len += len;
1962 textState->length += len;
1963 textState->text.addTextNode( token.text, textCodec );
1966 else if (token.type == RTFTokenizer::CloseGroup)
1968 if (textState->length)
1970 if (textState->table)
1974 textState = destination.target;
1980 if (token.type == RTFTokenizer::OpenGroup)
1982 destination.target->node.clear();
1984 else if (token.type == RTFTokenizer::PlainText)
1986 destination.target->node.addTextNode( token.text, textCodec );
1996 kdDebug(30515) << "Skip Group: " << token.type << endl;
1997 state.ignoreGroup = true;
2000void RTFImport::resetState()
2002 setPlainFormatting();
2003 setParagraphDefaults();
2004 setSectionDefaults();
2005 setTableRowDefaults();
2008void RTFImport::changeDestination( RTFProperty *property )
2010 kdDebug(30515) << "changeDestination: " << property->name << endl;
2011 destinationStack.push( destination );
2012 destination.name = property->name;
2013 destination.destproc = property->cwproc;
2015 destination.target = ( RTFTextState*) ( ( char *) this + property->offset );
2017 destination.target = &m_dummyTextState;
2019 state.brace0 = true;
2021 if (property-> value)
2024 destination.group = 0L;
2028 token.type = RTFTokenizer::OpenGroup;
2029 (this->*destination.destproc)(0L);
2032void RTFImport::addAnchor( const char *instance )
2037 node.addNode( "ANCHOR" );
2038 node.setAttribute( "type", "frameset" );
2039 node.setAttribute( "instance", instance );
2040 node.closeNode( "ANCHOR" );
2041 kwFormat.xmldata = node.toString();
2043 kwFormat.pos = textState->length++;
2045 textState->text.append( '#' );
2046 textState->formats << kwFormat;
2049void RTFImport::addFormat( DomNode &node, const KWFormat& format, const RTFFormat* baseFormat )
2052 int vertAlign = format.fmt.vertAlign;
2053 int fontSize = (format.fmt.fontSize >> 1);
2054 int vertAlign0 = ~vertAlign;
2055 int fontSize0 = ~fontSize;
2058 if (format.fmt.vertAlign == RTFFormat::Normal && format.fmt.baseline)
2060 if (format.fmt.baseline < 0)
2061 vertAlign = RTFFormat::SuperScript;
2063 vertAlign = RTFFormat::SubScript;
2065 fontSize += (fontSize >> 1);
2069 vertAlign0 = baseFormat->vertAlign;
2070 fontSize0 = (baseFormat->fontSize >> 1);
2072 if (vertAlign0 == RTFFormat::Normal && baseFormat->baseline)
2074 if (baseFormat->baseline < 0)
2075 vertAlign0 = RTFFormat::SuperScript;
2077 vertAlign0 = RTFFormat::SubScript;
2079 fontSize0 += (fontSize0 >> 1);
2082 node.addNode( "FORMAT" );
2083 node.setAttribute( "id", ( int)format.id );
2085 if (format.len != 0)
2088 node.setAttribute( "pos", ( int)format.pos );
2089 node.setAttribute( "len", ( int)format.len );
2091 if ((format.id == 1)||(format.id == 4))
2094 if (!baseFormat || format.fmt.color != baseFormat->color)
2096 node.addNode( "COLOR" );
2097 node.addColor( ((uint)format.fmt.color >= colorTable.count())
2098 ? (TQColor &)TQt::black : colorTable[format.fmt.color] );
2099 node.closeNode( "COLOR" );
2101 if ((uint)format.fmt.bgcolor < colorTable.count() &&
2102 (!baseFormat || format.fmt.bgcolor != baseFormat->bgcolor))
2104 node.addNode( "TEXTBACKGROUNDCOLOR" );
2105 node.addColor( colorTable[format.fmt.bgcolor] );
2106 node.closeNode( "TEXTBACKGROUNDCOLOR" );
2108 if (!baseFormat || format.fmt.font != baseFormat->font)
2110 node.addNode( "FONT" );
2112 if (fontTable.contains( format.fmt.font ))
2114 node.setAttribute( "name", fontTable[format.fmt.font] );
2116 node.closeNode( "FONT" );
2118 if (!baseFormat || format.fmt.bold != baseFormat->bold)
2120 node.addNode( "WEIGHT" );
2121 node.setAttribute( "value", (format.fmt.bold ? 75 : 50) );
2122 node.closeNode( "WEIGHT" );
2124 if (fontSize != fontSize0)
2126 node.addNode( "SIZE" );
2127 node.setAttribute( "value", fontSize );
2128 node.closeNode( "SIZE" );
2130 if (!baseFormat || format.fmt.italic != baseFormat->italic)
2132 node.addNode( "ITALIC" );
2133 node.setAttribute( "value", format.fmt.italic );
2134 node.closeNode( "ITALIC" );
2136 if (!baseFormat || format.fmt.underline != baseFormat->underline )
2138 node.addNode( "UNDERLINE" );
2139 TQCString st,styleline,wordbyword( "0");
2140 st.setNum(format.fmt.underline);
2141 int underlinecolor = format.fmt.underlinecolor;
2143 switch (format.fmt.underline)
2145 case RTFFormat::UnderlineNone:
2152 case RTFFormat::UnderlineSimple:
2157 case RTFFormat::UnderlineDouble:
2162 case RTFFormat::UnderlineThick:
2169 case RTFFormat::UnderlineWordByWord:
2176 case RTFFormat::UnderlineDash:
2182 case RTFFormat::UnderlineDot:
2188 case RTFFormat::UnderlineDashDot:
2191 styleline= "dashdot";
2194 case RTFFormat::UnderlineDashDotDot:
2197 styleline= "dashdotdot";
2200 case RTFFormat::UnderlineWave:
2207 node.setAttribute( "value", !st.isNull() );
2208 node.setAttribute( "wordbyword", !wordbyword.isNull() );
2209 if ( !styleline.isEmpty() )
2210 node.setAttribute( "styleline", !styleline.isNull() );
2211 if ( underlinecolor >= 0 && uint(underlinecolor) < colorTable.count() )
2213 node.setAttribute( "underlinecolor", colorTable[underlinecolor].name() );
2216 node.closeNode( "UNDERLINE" );
2218 if (!baseFormat || format.fmt.strike != baseFormat->strike || format.fmt.striked != baseFormat->striked)
2220 node.addNode( "STRIKEOUT" );
2222 st.setNum(format.fmt.strike);
2223 if(format.fmt.striked)
2225 node.setAttribute( "value", !st.isNull() );
2226 node.closeNode( "STRIKEOUT" );
2228 if (vertAlign != vertAlign0)
2230 node.addNode( "VERTALIGN" );
2231 node.setAttribute( "value", vertAlign );
2232 node.closeNode( "VERTALIGN" );
2234 if (!baseFormat || format.fmt.caps != baseFormat->caps || format.fmt.smallCaps != baseFormat->smallCaps)
2236 node.addNode( "FONTATTRIBUTE" );
2238 if ( format.fmt.caps )
2239 fontattr= "uppercase";
2240 else if ( format.fmt.smallCaps )
2241 fontattr= "smallcaps";
2244 node.setAttribute( "value", !fontattr.isNull() );
2245 node.closeNode( "FONTATTRIBUTE" );
2249 node.addNode( "CHARSET" );
2250 node.setAttribute( "value", ( int)TQFont::Unicode );
2251 node.closeNode( "CHARSET" );
2254 if (format.id == 4 || format.id == 6)
2257 node.closeTag( true );
2258 node.append( format.xmldata );
2260 node.closeNode( "FORMAT" );
2263void RTFImport::addLayout( DomNode &node, const TQString &name, const RTFLayout &layout, bool frameBreak )
2266 node.addNode( "NAME" );
2267 node.setAttribute( "value", CheckAndEscapeXmlText(name) );
2268 node.closeNode( "NAME" );
2269 node.addNode( "FLOW" );
2270 node.setAttribute( "align", alignN[layout.alignment] );
2271 node.closeNode( "FLOW" );
2274 if (layout.firstIndent || layout.leftIndent || layout.rightIndent)
2276 node.addNode( "INDENTS" );
2278 if (layout.firstIndent)
2279 node.setAttribute( "first", .05*layout.firstIndent );
2280 if (layout.leftIndent)
2281 node.setAttribute( "left", .05*layout.leftIndent );
2282 if (layout.rightIndent)
2283 node.setAttribute( "right", .05*layout.rightIndent );
2285 node.closeNode( "INDENTS" );
2289 if (layout.spaceBefore || layout.spaceAfter)
2291 node.addNode( "OFFSETS" );
2293 if (layout.spaceBefore)
2294 node.setAttribute( "before", .05*layout.spaceBefore );
2295 if (layout.spaceAfter)
2296 node.setAttribute( "after", .05*layout.spaceAfter );
2298 node.closeNode( "OFFSETS" );
2304 TQString lineSpacingType;
2305 TQString lineSpacingValue;
2313 lineSpacingType = "single";
2318 lineSpacingType = "oneandhalf";
2323 lineSpacingType = "double";
2330 lineSpacingType = "multiple";
2331 lineSpacingValue.setNum( layout. spaceBetween / 240.0 );
2341 lineSpacingType = "atleast";
2347 lineSpacingType = "fixed" ;
2352 if ( ! lineSpacingType.isEmpty() )
2354 node.addNode( "LINESPACING" );
2355 node.setAttribute( "type", lineSpacingType );
2356 if ( ! lineSpacingValue.isEmpty() )
2357 node.setAttribute( "spacingvalue", lineSpacingValue );
2358 node.closeNode( "LINESPACING" );
2361 if (layout.keep || layout.pageBB || layout.pageBA || frameBreak || layout.keepNext)
2363 node.addNode( "PAGEBREAKING" );
2364 node.setAttribute( "linesTogether", boolN[layout.keep] );
2365 node.setAttribute( "hardFrameBreak", boolN[layout.pageBB] );
2366 node.setAttribute( "hardFrameBreakAfter", boolN[layout.pageBA || frameBreak] );
2367 node.setAttribute( "keepWithNext", boolN[layout.keepNext] );
2368 node.closeNode( "PAGEBREAKING" );
2372 for (uint i=0; i < 4; i++)
2374 const RTFBorder &border = layout.borders[i];
2376 if (border.style != RTFBorder::None || border.width > 0)
2378 node.addNode( borderN[i] );
2379 node.addColor( ((uint)border.color >= colorTable.count())
2380 ? (TQColor &)TQt::black : colorTable[border.color] );
2381 node.setAttribute( "style", ( int)border.style & 0xf );
2382 node.setAttribute( "width", (border.width < 20) ? 1 : border.width /20 );
2383 node.closeNode( borderN[i] );
2388 if (layout.firstIndent < 0 && layout.leftIndent > 0)
2390 node.addNode( "TABULATOR" );
2391 node.setAttribute( "type", 0 );
2392 node.setAttribute( "ptpos", .05*layout.leftIndent );
2393 node.closeNode( "TABULATOR" );
2397 if (!layout.tablist.isEmpty())
2400 for (uint i=0; i < layout.tablist.count(); i++)
2402 const RTFTab &tab = layout.tablist[i];
2403 int l = (int)tab.leader;
2404 node.addNode( "TABULATOR" );
2405 node.setAttribute( "type", tab.type );
2406 node.setAttribute( "ptpos", .05*tab.position );
2407 node.setAttribute( "filling", (l < 2) ? l : ((l == 2) ? 1 : 2) );
2408 node.setAttribute( "width", (l == 4) ? 1. : 0.5 );
2409 node.closeNode( "TABULATOR" );
2414void RTFImport::addParagraph( DomNode &node, bool frameBreak )
2416 node.addNode( "PARAGRAPH" );
2417 node.addNode( "TEXT" );
2418 node.appendNode( textState->text );
2419 node.closeNode( "TEXT" );
2423 const RTFFormat* format = &state.format;
2424 const int styleNum = state.layout.style;
2426 const TQValueList<RTFStyle>::ConstIterator endStyleSheet = styleSheet.end();
2427 for ( TQValueList<RTFStyle>::ConstIterator it=styleSheet.begin(); it!=endStyleSheet; ++it )
2429 if ( (*it).layout.style == styleNum )
2431 if ( textState->length > 0 )
2433 format = &(*it).format;
2439 kwFormat.fmt = *format;
2442 kwFormat.len = textState->length;
2444 if ( name.isEmpty() )
2446 kdWarning(30515) << "Style name empty! Assuming Standard!" << endl;
2451 bool hasFormats = false;
2453 for ( TQValueList<KWFormat>::ConstIterator it = textState->formats.begin(); it != textState->formats.end(); ++it )
2455 if ( (*it).id != 1 || (*it).fmt != *format )
2459 node.addNode( "FORMATS" );
2462 addFormat( node, (*it), format );
2467 node.closeNode( "FORMATS" );
2471 node.addNode( "LAYOUT" );
2472 addLayout( node, name, state.layout, frameBreak );
2473 addFormat( node, kwFormat, 0L );
2474 node.closeNode( "LAYOUT" );
2475 node.closeNode( "PARAGRAPH" );
2478 textState->text.clear();
2479 textState->length = 0;
2480 textState->formats.clear();
2483void RTFImport::finishTable()
2485 kdDebug(30515) << "Starting TFImport::finishTable..." << endl;
2486 TQCString emptyArray;
2487 TQValueList<int> cellx;
2488 int left = 0, right = 0;
2494 for (uint i=0; i < textState->rows.count(); i++)
2498 if (row.left < left || i == 0)
2500 if (row.cells.last().x > right || i == 0)
2501 right = row.cells.last().x;
2506 for (uint i=0; i < textState->rows.count(); i++)
2510 if (row.left > left)
2512 row.frameSets.prepend( emptyArray );
2513 emptyCell.x = row.left;
2514 row.cells.prepend( emptyCell );
2517 if (row.cells.last().x < right)
2519 row.frameSets << emptyArray;
2520 emptyCell.x = right;
2521 row.cells << emptyCell;
2524 for (uint k=0; k < row.cells.count(); k++)
2526 if (!cellx.contains( row.cells[k].x ))
2527 cellx << row.cells[k].x;
2529 if (!cellx.contains( row.left ))
2537 for (uint k=0; k < cellx.count(); k++)
2539 for (uint l=k+1; l < cellx.count(); l++)
2541 if (cellx[l] < cellx[k])
2544 cellx[l] = cellx[k];
2553 for (uint i=0; i < textState->rows.count(); i++)
2556 int h = abs( row.height );
2557 int y2 = y1 + ((h < 400) ? 400 : h);
2560 for (uint k=0; k < row.cells.count(); k++)
2563 int x2 = row.cells[k].x;
2564 int col = cellx.findIndex( x1 );
2566 sprintf( buf, "Table %d Cell %d,%d", textState->table, i, col );
2567 frameSets.addFrameSet( buf, 1, 0 );
2568 sprintf( buf, "Table %d", textState->table );
2569 frameSets.setAttribute( "grpMgr", buf );
2570 frameSets.setAttribute( "row", ( int)i );
2571 frameSets.setAttribute( "col", col );
2572 frameSets.setAttribute( "rows", 1 );
2573 frameSets.setAttribute( "cols", cellx.findIndex( x2 ) - col );
2575 frameSets.addFrame( x1, y1, x2, y2, (row.height < 0) ? 2 : 0, 1, 0 );
2578 for (uint i=0; i < 4; i++)
2580 RTFBorder &border = row.cells[k].borders[i];
2582 if (border.style != RTFBorder::None || border.width > 0)
2584 const char * id = "lrtb";
2585 TQColor &c = ((uint)border.color >= colorTable.count())
2586 ? (TQColor &)TQt::black : colorTable[border.color];
2587 frameSets.addBorder( ( int) id[i], c, (int)border.style & 0x0f,
2588 .05*(!border.width ? 10 : border.width) );
2593 if ((uint)row.cells[k].bgcolor < colorTable.count())
2595 TQColor &color = colorTable[row.cells[k].bgcolor];
2596 frameSets.setAttribute( "bkRed", color.red() );
2597 frameSets.setAttribute( "bkGreen", color.green() );
2598 frameSets.setAttribute( "bkBlue", color.blue() );
2600 frameSets.closeNode( "FRAME" );
2601 frameSets.append( row.frameSets[k] );
2602 frameSets.closeNode( "FRAMESET" );
2607 textState->table = 0;
2608 textState->rows.clear();
2609 kdDebug(30515) << "Quitting TFImport::finishTable..." << endl;
2612void RTFImport::writeOutPart( const char *name, const DomNode& node )
2614 KoStoreDevice* dev = m_chain->storageFile( name, KoStore::Write );
2617 TQTextStream stream( dev );
2618 stream.setEncoding( TQTextStream::UnicodeUTF8 );
2619 stream << node.toString();
2622 kdError(30515) << "Could not write part " << name << endl;
Paragraph-formatting properties.
bool spaceBetweenMultiple Is the linespacing defined as multiple of line height (true) or by a height in 1/20 pt (false)?
int spaceBetween Line spacing.
RTF property (control word table entry)
int offset offset of formatting property
Section-formatting properties.
Table-formatting properties.
RTF rich text state (text and tables)
DomNode text plain text (for paragraph or table cell)
|