00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #ifdef HAVE_UNISTD_H
00023 #include <unistd.h>
00024 #endif
00025
00026 #include <qmap.h>
00027 #include <qbuffer.h>
00028 #include <qpicture.h>
00029 #include <qxml.h>
00030 #include <qdom.h>
00031 #include <qdatetime.h>
00032
00033 #include <kdebug.h>
00034 #include <kmdcodec.h>
00035 #include <kfilterdev.h>
00036 #include <kgenericfactory.h>
00037 #include <kmessagebox.h>
00038
00039 #include <KoPageLayout.h>
00040 #include <KoStore.h>
00041 #include <KoFilterChain.h>
00042
00043 #include "ImportHelpers.h"
00044 #include "ImportFormatting.h"
00045 #include "ImportStyle.h"
00046 #include "ImportField.h"
00047
00048 #include "abiwordimport.h"
00049
00050 class ABIWORDImportFactory : KGenericFactory<ABIWORDImport, KoFilter>
00051 {
00052 public:
00053 ABIWORDImportFactory(void) : KGenericFactory<ABIWORDImport, KoFilter> ("kwordabiwordimport")
00054 {}
00055 protected:
00056 virtual void setupTranslations( void )
00057 {
00058 KGlobal::locale()->insertCatalogue( "kofficefilters" );
00059 }
00060 };
00061
00062 K_EXPORT_COMPONENT_FACTORY( libabiwordimport, ABIWORDImportFactory() )
00063
00064
00065
00066
00067
00068
00069
00070 class StructureParser : public QXmlDefaultHandler
00071 {
00072 public:
00073 StructureParser(KoFilterChain* chain)
00074 : m_chain(chain), m_pictureNumber(0), m_pictureFrameNumber(0), m_tableGroupNumber(0),
00075 m_timepoint(QDateTime::currentDateTime(Qt::UTC)), m_fatalerror(false)
00076 {
00077 createDocument();
00078 structureStack.setAutoDelete(true);
00079 StackItem *stackItem=new(StackItem);
00080 stackItem->elementType=ElementTypeBottom;
00081 stackItem->m_frameset=mainFramesetElement;
00082 stackItem->stackElementText=mainFramesetElement;
00083 structureStack.push(stackItem);
00084 }
00085 virtual ~StructureParser()
00086 {
00087 structureStack.clear();
00088 }
00089 public:
00090 virtual bool startDocument(void);
00091 virtual bool endDocument(void);
00092 virtual bool startElement( const QString&, const QString&, const QString& name, const QXmlAttributes& attributes);
00093 virtual bool endElement( const QString&, const QString& , const QString& qName);
00094 virtual bool characters ( const QString & ch );
00095 virtual bool warning(const QXmlParseException& exception);
00096 virtual bool error(const QXmlParseException& exception);
00097 virtual bool fatalError(const QXmlParseException& exception);
00098 public:
00099 inline QDomDocument getDocInfo(void) const { return m_info; }
00100 inline QDomDocument getDocument(void) const { return mainDocument; }
00101 inline bool wasFatalError(void) const { return m_fatalerror; }
00102 protected:
00103 bool clearStackUntilParagraph(StackItemStack& auxilaryStack);
00104 bool complexForcedPageBreak(StackItem* stackItem);
00105 private:
00106
00107 bool StartElementC(StackItem* stackItem, StackItem* stackCurrent,
00108 const QXmlAttributes& attributes);
00109 bool StartElementA(StackItem* stackItem, StackItem* stackCurrent,
00110 const QXmlAttributes& attributes);
00111 bool StartElementImage(StackItem* stackItem, StackItem* stackCurrent,
00112 const QXmlAttributes& attributes);
00113 bool EndElementD (StackItem* stackItem);
00114 bool EndElementM (StackItem* stackItem);
00115 bool StartElementSection(StackItem* stackItem, StackItem* stackCurrent,
00116 const QXmlAttributes& attributes);
00117 bool StartElementFoot(StackItem* stackItem, StackItem* stackCurrent,
00118 const QXmlAttributes& attributes);
00119 bool StartElementTable(StackItem* stackItem, StackItem* stackCurrent, const QXmlAttributes& attributes);
00120 bool StartElementCell(StackItem* stackItem, StackItem* stackCurrent,const QXmlAttributes& attributes);
00121 private:
00122 void createDocument(void);
00123 void createDocInfo(void);
00124 QString indent;
00125 StackItemStack structureStack;
00126 QDomDocument mainDocument;
00127 QDomDocument m_info;
00128 QDomElement framesetsPluralElement;
00129 QDomElement mainFramesetElement;
00130 QDomElement m_picturesElement;
00131 QDomElement m_paperElement;
00132 QDomElement m_paperBordersElement;
00133 QDomElement m_ignoreWordsElement;
00134 StyleDataMap styleDataMap;
00135 KoFilterChain* m_chain;
00136 uint m_pictureNumber;
00137 uint m_pictureFrameNumber;
00138 uint m_tableGroupNumber;
00139 QMap<QString,QString> m_metadataMap;
00140 QDateTime m_timepoint;
00141 bool m_fatalerror;
00142 };
00143
00144
00145
00146 bool StructureParser::StartElementC(StackItem* stackItem, StackItem* stackCurrent, const QXmlAttributes& attributes)
00147 {
00148
00149
00150
00151
00152 if ((stackCurrent->elementType==ElementTypeParagraph)||(stackCurrent->elementType==ElementTypeContent))
00153 {
00154
00155
00156 QString strStyleProps;
00157 QString strStyleName=attributes.value("style").stripWhiteSpace();
00158 if (!strStyleName.isEmpty())
00159 {
00160 StyleDataMap::Iterator it=styleDataMap.find(strStyleName);
00161 if (it!=styleDataMap.end())
00162 {
00163 strStyleProps=it.data().m_props;
00164 }
00165 }
00166
00167 AbiPropsMap abiPropsMap;
00168 PopulateProperties(stackItem,strStyleProps,attributes,abiPropsMap,true);
00169
00170 stackItem->elementType=ElementTypeContent;
00171 stackItem->stackElementParagraph=stackCurrent->stackElementParagraph;
00172 stackItem->stackElementText=stackCurrent->stackElementText;
00173 stackItem->stackElementFormatsPlural=stackCurrent->stackElementFormatsPlural;
00174 stackItem->pos=stackCurrent->pos;
00175 }
00176
00177 else if ((stackCurrent->elementType==ElementTypeAnchor)||(stackCurrent->elementType==ElementTypeAnchorContent))
00178 {
00179 stackItem->elementType=ElementTypeAnchorContent;
00180 }
00181 else
00182 {
00183 kdError(30506) << "parse error <c> tag nested neither in <p> nor in <c> nor in <a> but in "
00184 << stackCurrent->itemName << endl;
00185 return false;
00186 }
00187 return true;
00188 }
00189
00190 bool charactersElementC (StackItem* stackItem, QDomDocument& mainDocument, const QString & ch)
00191 {
00192 if (stackItem->elementType==ElementTypeContent)
00193 {
00194 QDomElement elementText=stackItem->stackElementText;
00195 QDomElement elementFormatsPlural=stackItem->stackElementFormatsPlural;
00196 elementText.appendChild(mainDocument.createTextNode(ch));
00197
00198 QDomElement formatElementOut=mainDocument.createElement("FORMAT");
00199 formatElementOut.setAttribute("id",1);
00200 formatElementOut.setAttribute("pos",stackItem->pos);
00201 formatElementOut.setAttribute("len",ch.length());
00202 elementFormatsPlural.appendChild(formatElementOut);
00203 stackItem->pos+=ch.length();
00204
00205 AddFormat(formatElementOut, stackItem, mainDocument);
00206 }
00207 else if (stackItem->elementType==ElementTypeAnchorContent)
00208 {
00209
00210 stackItem->strTemp2+=ch;
00211
00212 }
00213 else
00214 {
00215 kdError(30506) << "Internal error (in charactersElementC)" << endl;
00216 }
00217
00218 return true;
00219 }
00220
00221 bool EndElementC (StackItem* stackItem, StackItem* stackCurrent)
00222 {
00223 if (stackItem->elementType==ElementTypeContent)
00224 {
00225 stackItem->stackElementText.normalize();
00226 stackCurrent->pos=stackItem->pos;
00227 }
00228 else if (stackItem->elementType==ElementTypeAnchorContent)
00229 {
00230 stackCurrent->strTemp2+=stackItem->strTemp2;
00231 }
00232 else
00233 {
00234 kdError(30506) << "Wrong element type!! Aborting! (</c> in StructureParser::endElement)" << endl;
00235 return false;
00236 }
00237 return true;
00238 }
00239
00240
00241 bool StructureParser::StartElementA(StackItem* stackItem, StackItem* stackCurrent, const QXmlAttributes& attributes)
00242 {
00243
00244 if (stackCurrent->elementType==ElementTypeParagraph)
00245 {
00246
00247
00248
00249
00250 stackItem->elementType=ElementTypeAnchor;
00251 stackItem->stackElementParagraph=stackCurrent->stackElementParagraph;
00252 stackItem->stackElementText=stackCurrent->stackElementText;
00253 stackItem->stackElementFormatsPlural=stackCurrent->stackElementFormatsPlural;
00254 stackItem->pos=stackCurrent->pos;
00255 stackItem->strTemp1=attributes.value("xlink:href").stripWhiteSpace();
00256 stackItem->strTemp2=QString::null;
00257
00258
00259
00260 if (stackItem->strTemp1[0]=='#')
00261 {
00262 kdWarning(30506) << "Anchor <a> to bookmark: " << stackItem->strTemp1 << endl
00263 << " Processing <a> like <c>" << endl;
00264
00265 return StartElementC(stackItem, stackCurrent, attributes);
00266 }
00267 }
00268 else
00269 {
00270 kdError(30506) << "parse error <a> tag not a child of <p> but of "
00271 << stackCurrent->itemName << endl;
00272 return false;
00273 }
00274 return true;
00275 }
00276
00277 static bool charactersElementA (StackItem* stackItem, const QString & ch)
00278 {
00279
00280 stackItem->strTemp2+=ch;
00281 return true;
00282 }
00283
00284 static bool EndElementA (StackItem* stackItem, StackItem* stackCurrent, QDomDocument& mainDocument)
00285 {
00286 if (!stackItem->elementType==ElementTypeAnchor)
00287 {
00288 kdError(30506) << "Wrong element type!! Aborting! (</a> in StructureParser::endElement)" << endl;
00289 return false;
00290 }
00291
00292 QDomElement elementText=stackItem->stackElementText;
00293 elementText.appendChild(mainDocument.createTextNode("#"));
00294
00295 QDomElement formatElement=mainDocument.createElement("FORMAT");
00296 formatElement.setAttribute("id",4);
00297 formatElement.setAttribute("pos",stackItem->pos);
00298 formatElement.setAttribute("len",1);
00299
00300 QDomElement variableElement=mainDocument.createElement("VARIABLE");
00301 formatElement.appendChild(variableElement);
00302
00303 QDomElement typeElement=mainDocument.createElement("TYPE");
00304 typeElement.setAttribute("key","STRING");
00305 typeElement.setAttribute("type",9);
00306 typeElement.setAttribute("text",stackItem->strTemp2);
00307 variableElement.appendChild(typeElement);
00308
00309 QDomElement linkElement=mainDocument.createElement("LINK");
00310 linkElement.setAttribute("hrefName",stackItem->strTemp1);
00311 linkElement.setAttribute("linkName",stackItem->strTemp2);
00312 variableElement.appendChild(linkElement);
00313
00314
00315 stackCurrent->stackElementFormatsPlural.appendChild(formatElement);
00316 stackCurrent->pos++;
00317
00318 return true;
00319 }
00320
00321
00322
00323 bool StartElementP(StackItem* stackItem, StackItem* stackCurrent,
00324 QDomDocument& mainDocument,
00325 StyleDataMap& styleDataMap, const QXmlAttributes& attributes)
00326 {
00327
00328 QString strStyle=attributes.value("style");
00329 if (strStyle.isEmpty())
00330 {
00331 strStyle="Normal";
00332 }
00333 StyleDataMap::ConstIterator it=styleDataMap.useOrCreateStyle(strStyle);
00334
00335 QString strLevel=attributes.value("level");
00336 int level;
00337 if (strLevel.isEmpty())
00338 {
00339
00340 level=it.data().m_level;
00341 }
00342 else
00343 {
00344
00345 level=strStyle.toInt();
00346 }
00347
00348 QDomElement elementText=stackCurrent->stackElementText;
00349 QDomElement paragraphElementOut=mainDocument.createElement("PARAGRAPH");
00350 stackCurrent->m_frameset.appendChild(paragraphElementOut);
00351
00352 QDomElement textElementOut=mainDocument.createElement("TEXT");
00353 paragraphElementOut.appendChild(textElementOut);
00354 QDomElement formatsPluralElementOut=mainDocument.createElement("FORMATS");
00355 paragraphElementOut.appendChild(formatsPluralElementOut);
00356
00357 AbiPropsMap abiPropsMap;
00358 PopulateProperties(stackItem,it.data().m_props,attributes,abiPropsMap,false);
00359
00360 stackItem->elementType=ElementTypeParagraph;
00361 stackItem->stackElementParagraph=paragraphElementOut;
00362 stackItem->stackElementText=textElementOut;
00363 stackItem->stackElementFormatsPlural=formatsPluralElementOut;
00364 stackItem->pos=0;
00365
00366
00367 QDomElement layoutElement=mainDocument.createElement("LAYOUT");
00368 paragraphElementOut.appendChild(layoutElement);
00369
00370 AddLayout(strStyle,layoutElement, stackItem, mainDocument, abiPropsMap, level, false);
00371
00372 return true;
00373 }
00374
00375 bool charactersElementP (StackItem* stackItem, QDomDocument& mainDocument, const QString & ch)
00376 {
00377 QDomElement elementText=stackItem->stackElementText;
00378
00379 elementText.appendChild(mainDocument.createTextNode(ch));
00380
00381 stackItem->pos+=ch.length();
00382
00383 return true;
00384 }
00385
00386 bool EndElementP (StackItem* stackItem)
00387 {
00388 if (!stackItem->elementType==ElementTypeParagraph)
00389 {
00390 kdError(30506) << "Wrong element type!! Aborting! (in endElementP)" << endl;
00391 return false;
00392 }
00393 stackItem->stackElementText.normalize();
00394 return true;
00395 }
00396
00397 static bool StartElementField(StackItem* stackItem, StackItem* stackCurrent,
00398 QDomDocument& mainDocument, const QXmlAttributes& attributes)
00399 {
00400
00401 if (stackCurrent->elementType==ElementTypeParagraph)
00402 {
00403 QString strType=attributes.value("type").stripWhiteSpace();
00404 kdDebug(30506)<<"<field> type:"<<strType<<endl;
00405
00406 AbiPropsMap abiPropsMap;
00407 PopulateProperties(stackItem,QString::null,attributes,abiPropsMap,true);
00408
00409 stackItem->elementType=ElementTypeEmpty;
00410
00411
00412 QDomElement variableElement=mainDocument.createElement("VARIABLE");
00413
00414 if (!ProcessField(mainDocument, variableElement, strType, attributes))
00415 {
00416
00417
00418 kdWarning(30506) << "Unknown <field> type: " << strType << endl;
00419 QDomElement formatElement=mainDocument.createElement("FORMAT");
00420 formatElement.setAttribute("id",1);
00421 formatElement.setAttribute("pos",stackItem->pos);
00422 formatElement.setAttribute("len",strType.length());
00423
00424 formatElement.appendChild(variableElement);
00425
00426
00427 stackCurrent->stackElementFormatsPlural.appendChild(formatElement);
00428 stackCurrent->stackElementText.appendChild(mainDocument.createTextNode(strType));
00429 stackCurrent->pos+=strType.length();
00430
00431
00432 stackItem->fgColor.setRgb(255,0,0);
00433 AddFormat(formatElement, stackItem, mainDocument);
00434 return true;
00435 }
00436
00437
00438 QDomElement formatElement=mainDocument.createElement("FORMAT");
00439 formatElement.setAttribute("id",4);
00440 formatElement.setAttribute("pos",stackItem->pos);
00441 formatElement.setAttribute("len",1);
00442
00443 formatElement.appendChild(variableElement);
00444
00445
00446 stackCurrent->stackElementFormatsPlural.appendChild(formatElement);
00447 stackCurrent->stackElementText.appendChild(mainDocument.createTextNode("#"));
00448 stackCurrent->pos++;
00449
00450
00451 AddFormat(formatElement, stackItem, mainDocument);
00452
00453 }
00454 else
00455 {
00456 kdError(30506) << "parse error <field> tag not nested in <p> but in "
00457 << stackCurrent->itemName << endl;
00458 return false;
00459 }
00460 return true;
00461 }
00462
00463
00464 static bool StartElementS(StackItem* stackItem, StackItem* ,
00465 const QXmlAttributes& attributes, StyleDataMap& styleDataMap)
00466 {
00467
00468
00469 stackItem->elementType=ElementTypeEmpty;
00470
00471 QString strStyleName=attributes.value("name").stripWhiteSpace();
00472
00473 if (strStyleName.isEmpty())
00474 {
00475 kdWarning(30506) << "Style has no name!" << endl;
00476 }
00477 else
00478 {
00479 QString strLevel=attributes.value("level");
00480 int level;
00481 if (strLevel.isEmpty())
00482 level=-1;
00483 else
00484 level=strLevel.toInt();
00485 QString strBasedOn=attributes.value("basedon").simplifyWhiteSpace();
00486 styleDataMap.defineNewStyleFromOld(strStyleName,strBasedOn,level,attributes.value("props"));
00487 kdDebug(30506) << " Style name: " << strStyleName << endl
00488 << " Based on: " << strBasedOn << endl
00489 << " Level: " << level << endl
00490 << " Props: " << attributes.value("props") << endl;
00491 }
00492
00493 return true;
00494 }
00495
00496
00497 bool StructureParser::StartElementImage(StackItem* stackItem, StackItem* stackCurrent,
00498 const QXmlAttributes& attributes)
00499 {
00500
00501 if ((stackCurrent->elementType!=ElementTypeParagraph) && (stackCurrent->elementType!=ElementTypeContent))
00502 {
00503 kdError(30506) << "parse error <image> tag nested neither in <p> nor in <c> but in "
00504 << stackCurrent->itemName << endl;
00505 return false;
00506 }
00507 stackItem->elementType=ElementTypeEmpty;
00508
00509 QString strDataId=attributes.value("dataid").stripWhiteSpace();
00510
00511 AbiPropsMap abiPropsMap;
00512 abiPropsMap.splitAndAddAbiProps(attributes.value("props"));
00513
00514 double height=ValueWithLengthUnit(abiPropsMap["height"].getValue());
00515 double width =ValueWithLengthUnit(abiPropsMap["width" ].getValue());
00516
00517 kdDebug(30506) << "Image: " << strDataId << " height: " << height << " width: " << width << endl;
00518
00519
00520
00521 if (strDataId.isEmpty())
00522 {
00523 kdWarning(30506) << "Image has no data id!" << endl;
00524 }
00525 else
00526 {
00527 kdDebug(30506) << "Image: " << strDataId << endl;
00528 }
00529
00530 QString strPictureFrameName(i18n("Frameset name","Picture %1").arg(++m_pictureFrameNumber));
00531
00532
00533
00534 QDomElement framesetElement=mainDocument.createElement("FRAMESET");
00535 framesetElement.setAttribute("frameType",2);
00536 framesetElement.setAttribute("frameInfo",0);
00537 framesetElement.setAttribute("visible",1);
00538 framesetElement.setAttribute("name",strPictureFrameName);
00539 framesetsPluralElement.appendChild(framesetElement);
00540
00541 QDomElement frameElementOut=mainDocument.createElement("FRAME");
00542 frameElementOut.setAttribute("left",0);
00543 frameElementOut.setAttribute("top",0);
00544 frameElementOut.setAttribute("bottom",height);
00545 frameElementOut.setAttribute("right" ,width );
00546 frameElementOut.setAttribute("runaround",1);
00547
00548 framesetElement.appendChild(frameElementOut);
00549
00550 QDomElement element=mainDocument.createElement("PICTURE");
00551 element.setAttribute("keepAspectRatio","true");
00552 framesetElement.setAttribute("frameType",2);
00553 framesetElement.appendChild(element);
00554
00555 QDomElement key=mainDocument.createElement("KEY");
00556 key.setAttribute("filename",strDataId);
00557 key.setAttribute("year",m_timepoint.date().year());
00558 key.setAttribute("month",m_timepoint.date().month());
00559 key.setAttribute("day",m_timepoint.date().day());
00560 key.setAttribute("hour",m_timepoint.time().hour());
00561 key.setAttribute("minute",m_timepoint.time().minute());
00562 key.setAttribute("second",m_timepoint.time().second());
00563 key.setAttribute("msec",m_timepoint.time().msec());
00564 element.appendChild(key);
00565
00566
00567 QDomElement elementText=stackItem->stackElementText;
00568 QDomElement elementFormatsPlural=stackItem->stackElementFormatsPlural;
00569 elementText.appendChild(mainDocument.createTextNode("#"));
00570
00571 QDomElement formatElementOut=mainDocument.createElement("FORMAT");
00572 formatElementOut.setAttribute("id",6);
00573 formatElementOut.setAttribute("pos",stackItem->pos);
00574 formatElementOut.setAttribute("len",1);
00575 elementFormatsPlural.appendChild(formatElementOut);
00576
00577
00578 stackCurrent->pos++;
00579
00580 QDomElement anchor=mainDocument.createElement("ANCHOR");
00581
00582 anchor.setAttribute("type","frameset");
00583 anchor.setAttribute("instance",strPictureFrameName);
00584 formatElementOut.appendChild(anchor);
00585
00586 return true;
00587 }
00588
00589
00590 static bool StartElementD(StackItem* stackItem, StackItem* ,
00591 const QXmlAttributes& attributes)
00592 {
00593
00594
00595 stackItem->elementType=ElementTypeRealData;
00596
00597 QString strName=attributes.value("name").stripWhiteSpace();
00598 kdDebug(30506) << "Data: " << strName << endl;
00599
00600 QString strBase64=attributes.value("base64").stripWhiteSpace();
00601 QString strMime=attributes.value("mime").stripWhiteSpace();
00602
00603 if (strName.isEmpty())
00604 {
00605 kdWarning(30506) << "Data has no name!" << endl;
00606 stackItem->elementType=ElementTypeEmpty;
00607 return true;
00608 }
00609
00610 if (strMime.isEmpty())
00611 {
00612
00613 strMime="image/png";
00614 strBase64="yes";
00615 }
00616
00617 stackItem->fontName=strName;
00618 stackItem->bold=(strBase64=="yes");
00619 stackItem->strTemp1=strMime;
00620 stackItem->strTemp2=QString::null;
00621
00622 return true;
00623 }
00624
00625 static bool CharactersElementD (StackItem* stackItem, QDomDocument& , const QString & ch)
00626 {
00627
00628 stackItem->strTemp2+=ch;
00629 return true;
00630 }
00631
00632 bool StructureParser::EndElementD (StackItem* stackItem)
00633 {
00634 if (!stackItem->elementType==ElementTypeRealData)
00635 {
00636 kdError(30506) << "Wrong element type!! Aborting! (in endElementD)" << endl;
00637 return false;
00638 }
00639 if (!m_chain)
00640 {
00641 kdError(30506) << "No filter chain! Aborting! (in endElementD)" << endl;
00642 return false;
00643 }
00644
00645 bool isSvg=false;
00646
00647 QString extension;
00648
00649
00650 if (stackItem->strTemp1=="image/png")
00651 {
00652 extension=".png";
00653 }
00654 else if (stackItem->strTemp1=="image/jpeg")
00655 {
00656 extension=".jpeg";
00657 }
00658 else if (stackItem->strTemp1=="image/svg-xml")
00659 {
00660 extension=".svg";
00661 isSvg=true;
00662 }
00663 else
00664 {
00665 kdWarning(30506) << "Unknown or unsupported mime type: "
00666 << stackItem->strTemp1 << endl;
00667 return true;
00668 }
00669
00670 QString strStoreName;
00671 strStoreName="pictures/picture";
00672 strStoreName+=QString::number(++m_pictureNumber);
00673 strStoreName+=extension;
00674
00675 QString strDataId=stackItem->fontName;
00676 QDomElement key=mainDocument.createElement("KEY");
00677 key.setAttribute("filename",strDataId);
00678 key.setAttribute("year",m_timepoint.date().year());
00679 key.setAttribute("month",m_timepoint.date().month());
00680 key.setAttribute("day",m_timepoint.date().day());
00681 key.setAttribute("hour",m_timepoint.time().hour());
00682 key.setAttribute("minute",m_timepoint.time().minute());
00683 key.setAttribute("second",m_timepoint.time().second());
00684 key.setAttribute("msec",m_timepoint.time().msec());
00685 key.setAttribute("name",strStoreName);
00686 m_picturesElement.appendChild(key);
00687
00688 KoStoreDevice* out=m_chain->storageFile(strStoreName, KoStore::Write);
00689 if(!out)
00690 {
00691 kdError(30506) << "Unable to open output file for: " << stackItem->fontName << " Storage: " << strStoreName << endl;
00692 return false;
00693 }
00694
00695 if (stackItem->bold)
00696 {
00697 kdDebug(30506) << "Decode and write base64 stream: " << stackItem->fontName << endl;
00698
00699
00700 QByteArray base64Stream=stackItem->strTemp2.utf8();
00701 QByteArray binaryStream;
00702 KCodecs::base64Decode(base64Stream, binaryStream);
00703 out->writeBlock(binaryStream, binaryStream.count());
00704 }
00705 else
00706 {
00707
00708 kdDebug(30506) << "Write character stream: " << stackItem->fontName << endl;
00709
00710 QCString strOut=stackItem->strTemp2.stripWhiteSpace().utf8();
00711 out->writeBlock(strOut,strOut.length());
00712 }
00713
00714 return true;
00715 }
00716
00717
00718 static bool StartElementM(StackItem* stackItem, StackItem* ,
00719 const QXmlAttributes& attributes)
00720 {
00721
00722 stackItem->elementType=ElementTypeRealMetaData;
00723
00724 QString strKey=attributes.value("key").stripWhiteSpace();
00725 kdDebug(30506) << "Metadata key: " << strKey << endl;
00726
00727 if (strKey.isEmpty())
00728 {
00729 kdWarning(30506) << "Metadata has no key!" << endl;
00730 stackItem->elementType=ElementTypeIgnore;
00731 return true;
00732 }
00733
00734 stackItem->strTemp1=strKey;
00735 stackItem->strTemp2=QString::null;
00736
00737 return true;
00738 }
00739
00740 static bool CharactersElementM (StackItem* stackItem, const QString & ch)
00741 {
00742
00743 stackItem->strTemp2+=ch;
00744 return true;
00745 }
00746
00747 bool StructureParser::EndElementM (StackItem* stackItem)
00748 {
00749 if (!stackItem->elementType==ElementTypeRealData)
00750 {
00751 kdError(30506) << "Wrong element type!! Aborting! (in endElementM)" << endl;
00752 return false;
00753 }
00754
00755 if (stackItem->strTemp1.isEmpty())
00756 {
00757
00758 kdError(30506) << "Key name was erased! Aborting! (in endElementM)" << endl;
00759 return false;
00760 }
00761
00762
00763 m_metadataMap[stackItem->strTemp1]=stackItem->strTemp2;
00764
00765 return true;
00766 }
00767
00768
00769 static bool StartElementBR(StackItem* stackItem, StackItem* stackCurrent,
00770 QDomDocument& mainDocument)
00771 {
00772
00773 if ((stackCurrent->elementType==ElementTypeParagraph)
00774 || (stackCurrent->elementType==ElementTypeContent))
00775 {
00776 stackItem->elementType=ElementTypeEmpty;
00777
00778
00779
00780 if (stackCurrent->elementType==ElementTypeContent)
00781 {
00782
00783 QDomElement formatElement=mainDocument.createElement("FORMAT");
00784 formatElement.setAttribute("id",1);
00785 formatElement.setAttribute("pos",stackCurrent->pos);
00786 formatElement.setAttribute("len",1);
00787 AddFormat(formatElement, stackCurrent, mainDocument);
00788 stackCurrent->stackElementFormatsPlural.appendChild(formatElement);
00789 }
00790
00791 stackCurrent->stackElementText.appendChild(mainDocument.createTextNode(QChar(10)));
00792 stackCurrent->pos++;
00793
00794 }
00795 else
00796 {
00797 kdError(30506) << "parse error <br> tag not nested in <p> or <c> but in "
00798 << stackCurrent->itemName << endl;
00799 return false;
00800 }
00801 return true;
00802 }
00803
00804
00805
00806 static bool StartElementPBR(StackItem* , StackItem* stackCurrent,
00807 QDomDocument& mainDocument)
00808 {
00809
00810
00811
00812
00813 QDomElement paragraphElementOut=mainDocument.createElement("PARAGRAPH");
00814 stackCurrent->m_frameset.appendChild(paragraphElementOut);
00815 QDomElement textElementOut=mainDocument.createElement("TEXT");
00816 paragraphElementOut.appendChild(textElementOut);
00817 QDomElement formatsPluralElementOut=mainDocument.createElement("FORMATS");
00818 paragraphElementOut.appendChild(formatsPluralElementOut);
00819
00820
00821
00822 QDomNodeList nodeList=stackCurrent->stackElementParagraph.elementsByTagName("LAYOUT");
00823
00824 if (!nodeList.count())
00825 {
00826 kdError(30506) << "Unable to find <LAYOUT> element! Aborting! (in StartElementPBR)" <<endl;
00827 return false;
00828 }
00829
00830
00831 QDomNode newNode=nodeList.item(0).cloneNode(true);
00832 if (newNode.isNull())
00833 {
00834 kdError(30506) << "Unable to clone <LAYOUT> element! Aborting! (in StartElementPBR)" <<endl;
00835 return false;
00836 }
00837 paragraphElementOut.appendChild(newNode);
00838
00839
00840 QDomElement oldLayoutElement=nodeList.item(0).toElement();
00841 if (oldLayoutElement.isNull())
00842 {
00843 kdError(30506) << "Cannot find old <LAYOUT> element! Aborting! (in StartElementPBR)" <<endl;
00844 return false;
00845 }
00846
00847
00848 QDomElement pagebreakingElement=mainDocument.createElement("PAGEBREAKING");
00849 pagebreakingElement.setAttribute("linesTogether","false");
00850 pagebreakingElement.setAttribute("hardFrameBreak","false");
00851 pagebreakingElement.setAttribute("hardFrameBreakAfter","true");
00852 oldLayoutElement.appendChild(pagebreakingElement);
00853
00854
00855
00856
00857 stackCurrent->elementType=ElementTypeParagraph;
00858 stackCurrent->stackElementParagraph=paragraphElementOut;
00859 stackCurrent->stackElementText=textElementOut;
00860 stackCurrent->stackElementFormatsPlural=formatsPluralElementOut;
00861 stackCurrent->pos=0;
00862
00863 return true;
00864 }
00865
00866
00867 static bool StartElementPageSize(QDomElement& paperElement, const QXmlAttributes& attributes)
00868 {
00869 if (attributes.value("page-scale").toDouble()!=1.0)
00870 {
00871 kdWarning(30506) << "Ignoring unsupported page scale: " << attributes.value("page-scale") << endl;
00872 }
00873
00874 int kwordOrientation;
00875 QString strOrientation=attributes.value("orientation").stripWhiteSpace();
00876
00877 if (strOrientation=="portrait")
00878 {
00879 kwordOrientation=0;
00880 }
00881 else if (strOrientation=="landscape")
00882 {
00883 kwordOrientation=1;
00884 }
00885 else
00886 {
00887 kdWarning(30506) << "Unknown page orientation: " << strOrientation << "! Ignoring! " << endl;
00888 kwordOrientation=0;
00889 }
00890
00891 double kwordHeight;
00892 double kwordWidth;
00893
00894 QString strPageType=attributes.value("pagetype").stripWhiteSpace();
00895
00896
00897
00898
00899 KoFormat kwordFormat = KoPageFormat::formatFromString(strPageType);
00900
00901 if (kwordFormat==PG_CUSTOM)
00902 {
00903 kdDebug(30506) << "Custom or other page format found: " << strPageType << endl;
00904
00905 double height = attributes.value("height").toDouble();
00906 double width = attributes.value("width" ).toDouble();
00907
00908 QString strUnits = attributes.value("units").stripWhiteSpace();
00909
00910 kdDebug(30506) << "Explicit page size: "
00911 << height << " " << strUnits << " x " << width << " " << strUnits
00912 << endl;
00913
00914 if (strUnits=="cm")
00915 {
00916 kwordHeight = CentimetresToPoints(height);
00917 kwordWidth = CentimetresToPoints(width);
00918 }
00919 else if (strUnits=="inch")
00920 {
00921 kwordHeight = InchesToPoints(height);
00922 kwordWidth = InchesToPoints(width);
00923 }
00924 else if (strUnits=="mm")
00925 {
00926 kwordHeight = MillimetresToPoints(height);
00927 kwordWidth = MillimetresToPoints(width);
00928 }
00929 else
00930 {
00931 kwordHeight = 0.0;
00932 kwordWidth = 0.0;
00933 kdWarning(30506) << "Unknown unit type: " << strUnits << endl;
00934 }
00935 }
00936 else
00937 {
00938
00939 kwordHeight = MillimetresToPoints(KoPageFormat::height(kwordFormat,PG_PORTRAIT));
00940 kwordWidth = MillimetresToPoints(KoPageFormat::width (kwordFormat,PG_PORTRAIT));
00941 }
00942
00943 if ((kwordHeight <= 1.0) || (kwordWidth <= 1.0))
00944
00945 {
00946 kdWarning(30506) << "Page width or height is too small: "
00947 << kwordHeight << "x" << kwordWidth << endl;
00948
00949 kwordFormat = PG_DIN_A4;
00950 kwordHeight = CentimetresToPoints(29.7);
00951 kwordWidth = CentimetresToPoints(21.0);
00952 }
00953
00954
00955
00956 if (paperElement.isNull())
00957 {
00958 kdError(30506) << "<PAPER> element cannot be accessed! Aborting!" << endl;
00959 return false;
00960 }
00961
00962 paperElement.setAttribute("format",kwordFormat);
00963 paperElement.setAttribute("width",kwordWidth);
00964 paperElement.setAttribute("height",kwordHeight);
00965 paperElement.setAttribute("orientation",kwordOrientation);
00966
00967 return true;
00968 }
00969
00970
00971 bool StructureParser::complexForcedPageBreak(StackItem* stackItem)
00972 {
00973
00974
00975 StackItemStack auxilaryStack;
00976
00977 if (!clearStackUntilParagraph(auxilaryStack))
00978 {
00979 kdError(30506) << "Could not clear stack until a paragraph!" << endl;
00980 return false;
00981 }
00982
00983
00984
00985 bool success=StartElementPBR(stackItem,structureStack.current(),mainDocument);
00986
00987
00988
00989 StackItem* stackCurrent=structureStack.current();
00990 StackItem* item;
00991 while (auxilaryStack.count()>0)
00992 {
00993 item=auxilaryStack.pop();
00994
00995
00996 item->pos=0;
00997 item->stackElementParagraph=stackCurrent->stackElementParagraph;
00998 item->stackElementText=stackCurrent->stackElementText;
00999 item->stackElementFormatsPlural=stackCurrent->stackElementFormatsPlural;
01000 structureStack.push(item);
01001 }
01002
01003 return success;
01004 }
01005
01006
01007
01008 bool StructureParser::StartElementSection(StackItem* stackItem, StackItem* ,
01009 const QXmlAttributes& attributes)
01010 {
01011
01012 stackItem->elementType=ElementTypeSection;
01013
01014 AbiPropsMap abiPropsMap;
01015
01016 kdDebug(30506)<< "========== props=\"" << attributes.value("props") << "\"" << endl;
01017 abiPropsMap.splitAndAddAbiProps(attributes.value("props"));
01018 abiPropsMap.splitAndAddAbiProps(attributes.value("PROPS"));
01019
01020
01021
01022 if (true && (!m_paperBordersElement.isNull()))
01023 {
01024 QString str;
01025 str=abiPropsMap["page-margin-top"].getValue();
01026 if (!str.isEmpty())
01027 {
01028 m_paperBordersElement.setAttribute("top",ValueWithLengthUnit(str));
01029 }
01030 str=abiPropsMap["page-margin-left"].getValue();
01031 if (!str.isEmpty())
01032 {
01033 m_paperBordersElement.setAttribute("left",ValueWithLengthUnit(str));
01034 }
01035 str=abiPropsMap["page-margin-bottom"].getValue();
01036 if (!str.isEmpty())
01037 {
01038 m_paperBordersElement.setAttribute("bottom",ValueWithLengthUnit(str));
01039 }
01040 str=abiPropsMap["page-margin-right"].getValue();
01041 if (!str.isEmpty())
01042 {
01043 m_paperBordersElement.setAttribute("right",ValueWithLengthUnit(str));
01044 }
01045 }
01046 return true;
01047 }
01048
01049
01050
01051 static bool EndElementIW(StackItem* stackItem, StackItem* ,
01052 QDomDocument& mainDocument, QDomElement& m_ignoreWordsElement)
01053 {
01054 if (!stackItem->elementType==ElementTypeIgnoreWord)
01055 {
01056 kdError(30506) << "Wrong element type!! Aborting! (in endElementIW)" << endl;
01057 return false;
01058 }
01059 QDomElement wordElement=mainDocument.createElement("SPELLCHECKIGNOREWORD");
01060 wordElement.setAttribute("word",stackItem->strTemp2.stripWhiteSpace());
01061 m_ignoreWordsElement.appendChild(wordElement);
01062 return true;
01063 }
01064
01065
01066 bool StructureParser::StartElementFoot(StackItem* stackItem, StackItem* ,
01067 const QXmlAttributes& )
01068 {
01069 #if 0
01070 stackItem->elementType=ElementTypeFoot;
01071
01072 const QString id(attributes.value("endnote-id").stripWhiteSpace());
01073 kdDebug(30506) << "Foot note id: " << id << endl;
01074
01075 if (id.isEmpty())
01076 {
01077 kdWarning(30506) << "Footnote has no id!" << endl;
01078 stackItem->elementType=ElementTypeIgnore;
01079 return true;
01080 }
01081
01082
01083 QDomElement framesetElement(mainDocument.createElement("FRAMESET"));
01084 framesetElement.setAttribute("frameType",1);
01085 framesetElement.setAttribute("frameInfo",7);
01086 framesetElement.setAttribute("visible",1);
01087 framesetElement.setAttribute("name",getFootnoteFramesetName(id));
01088 framesetsPluralElement.appendChild(framesetElement);
01089
01090 QDomElement frameElementOut(mainDocument.createElement("FRAME"));
01091
01092
01093
01094
01095 frameElementOut.setAttribute("runaround",1);
01096
01097 framesetElement.appendChild(frameElementOut);
01098
01099 stackItem->m_frameset=framesetElement;
01100 #else
01101 stackItem->elementType=ElementTypeIgnore;
01102 #endif
01103 return true;
01104 }
01105
01106
01107 bool StructureParser::StartElementTable(StackItem* stackItem, StackItem* stackCurrent,
01108 const QXmlAttributes& attributes)
01109 {
01110 #if 1
01111
01112
01113
01114 QStringList widthList;
01115 widthList.split('/', attributes.value("table-column-props"), false);
01116 const uint columns = widthList.size();
01117 stackItem->m_doubleArray.detach();
01118 stackItem->m_doubleArray.resize(columns+1);
01119 stackItem->m_doubleArray[0] = 0.0;
01120 QStringList::ConstIterator it;
01121 uint i;
01122 for ( i=0, it=widthList.begin(); i<columns; ++i, ++it )
01123 {
01124 kdDebug(30506) << "Column width: " << (*it) << " cooked " << ValueWithLengthUnit(*it) << endl;
01125 stackItem->m_doubleArray[i+1] = ValueWithLengthUnit(*it) + stackItem->m_doubleArray[i];
01126 }
01127
01128
01129 const uint tableNumber(++m_tableGroupNumber);
01130 const QString tableName(i18n("Table %1").arg(tableNumber));
01131
01132 QDomElement elementText=stackCurrent->stackElementText;
01133 QDomElement paragraphElementOut=mainDocument.createElement("PARAGRAPH");
01134 stackCurrent->m_frameset.appendChild(paragraphElementOut);
01135
01136 QDomElement textElementOut(mainDocument.createElement("TEXT"));
01137 textElementOut.appendChild(mainDocument.createTextNode("#"));
01138 paragraphElementOut.appendChild(textElementOut);
01139
01140 QDomElement formatsPluralElementOut=mainDocument.createElement("FORMATS");
01141 paragraphElementOut.appendChild(formatsPluralElementOut);
01142
01143 QDomElement elementFormat(mainDocument.createElement("FORMAT"));
01144 elementFormat.setAttribute("id",6);
01145 elementFormat.setAttribute("pos",0);
01146 elementFormat.setAttribute("len",1);
01147 formatsPluralElementOut.appendChild(elementFormat);
01148
01149 QDomElement elementAnchor(mainDocument.createElement("ANCHOR"));
01150 elementAnchor.setAttribute("type","frameset");
01151 elementAnchor.setAttribute("instance",tableName);
01152 elementFormat.appendChild(elementAnchor);
01153
01154 stackItem->elementType=ElementTypeTable;
01155 stackItem->stackElementParagraph=paragraphElementOut;
01156 stackItem->stackElementText=textElementOut;
01157 stackItem->stackElementFormatsPlural=formatsPluralElementOut;
01158 stackItem->strTemp1=tableName;
01159 stackItem->strTemp2=QString::number(tableNumber);
01160 stackItem->pos=1;
01161
01162
01163 QDomElement layoutElement=mainDocument.createElement("LAYOUT");
01164 paragraphElementOut.appendChild(layoutElement);
01165
01166 AbiPropsMap abiPropsMap;
01167 styleDataMap.useOrCreateStyle("Normal");
01168 AddLayout("Normal", layoutElement, stackItem, mainDocument, abiPropsMap, 0, false);
01169 #else
01170 stackItem->elementType=ElementTypeIgnore;
01171 #endif
01172 return true;
01173 }
01174
01175
01176 bool StructureParser::StartElementCell(StackItem* stackItem, StackItem* stackCurrent,
01177 const QXmlAttributes& attributes)
01178 {
01179 #if 1
01180 if (stackCurrent->elementType!=ElementTypeTable)
01181 {
01182 kdError(30506) << "Wrong element type!! Aborting! (in StructureParser::endElementCell)" << endl;
01183 return false;
01184 }
01185
01186 stackItem->elementType=ElementTypeCell;
01187
01188 const QString tableName(stackCurrent->strTemp1);
01189 kdDebug(30506) << "Table name: " << tableName << endl;
01190
01191 if (tableName.isEmpty())
01192 {
01193 kdError(30506) << "Table name is empty! Aborting!" << endl;
01194 return false;
01195 }
01196
01197 AbiPropsMap abiPropsMap;
01198 abiPropsMap.splitAndAddAbiProps(attributes.value("props"));
01199
01200
01201 const uint row=abiPropsMap["top-attach"].getValue().toUInt();
01202 const uint col=abiPropsMap["left-attach"].getValue().toUInt();
01203
01204 if ( col >= stackItem->m_doubleArray.size() )
01205 {
01206
01207
01208
01209 stackItem->m_doubleArray.resize( stackItem->m_doubleArray.size() + 1, QGArray::SpeedOptim );
01210 stackItem->m_doubleArray[col+1] = stackItem->m_doubleArray[col] + 72;
01211 }
01212
01213 const QString frameName(i18n("Frameset name","Table %3, row %1, column %2")
01214 .arg(row).arg(col).arg(stackCurrent->strTemp2));
01215
01216
01217 QDomElement framesetElement(mainDocument.createElement("FRAMESET"));
01218 framesetElement.setAttribute("frameType",1);
01219 framesetElement.setAttribute("frameInfo",0);
01220 framesetElement.setAttribute("visible",1);
01221 framesetElement.setAttribute("name",frameName);
01222 framesetElement.setAttribute("row",row);
01223 framesetElement.setAttribute("col",col);
01224 framesetElement.setAttribute("rows",1);
01225 framesetElement.setAttribute("cols",1);
01226 framesetElement.setAttribute("grpMgr",tableName);
01227 framesetsPluralElement.appendChild(framesetElement);
01228
01229 QDomElement frameElementOut(mainDocument.createElement("FRAME"));
01230 frameElementOut.setAttribute( "left", stackItem->m_doubleArray[col] );
01231 frameElementOut.setAttribute( "right", stackItem->m_doubleArray[col+1] );
01232 frameElementOut.setAttribute("top",0);
01233 frameElementOut.setAttribute("bottom",0);
01234 frameElementOut.setAttribute("runaround",1);
01235 frameElementOut.setAttribute("autoCreateNewFrame",0);
01236
01237 framesetElement.appendChild(frameElementOut);
01238
01239 stackItem->m_frameset=framesetElement;
01240 QDomElement nullDummy;
01241 stackItem->stackElementParagraph=nullDummy;
01242 stackItem->stackElementText=nullDummy;
01243 stackItem->stackElementFormatsPlural=nullDummy;
01244
01245 #else
01246 stackItem->elementType=ElementTypeIgnore;
01247 #endif
01248 return true;
01249 }
01250
01251
01252
01253 bool StructureParser :: startElement( const QString&, const QString&, const QString& name, const QXmlAttributes& attributes)
01254 {
01255
01256 kdDebug(30506) << indent << " <" << name << ">" << endl;
01257 indent += "*";
01258
01259 if (structureStack.isEmpty())
01260 {
01261 kdError(30506) << "Stack is empty!! Aborting! (in StructureParser::startElement)" << endl;
01262 return false;
01263 }
01264
01265
01266 StackItem *stackItem=new StackItem(*structureStack.current());
01267
01268 if (!stackItem)
01269 {
01270 kdError(30506) << "Could not create Stack Item! Aborting! (in StructureParser::startElement)" << endl;
01271 return false;
01272 }
01273
01274 stackItem->itemName=name;
01275
01276 bool success=false;
01277
01278 if ((name=="c")||(name=="C"))
01279 {
01280 success=StartElementC(stackItem,structureStack.current(),attributes);
01281 }
01282 else if ((name=="p")||(name=="P"))
01283 {
01284 success=StartElementP(stackItem,structureStack.current(),mainDocument,
01285 styleDataMap,attributes);
01286 }
01287 else if ((name=="section")||(name=="SECTION"))
01288 {
01289 success=StartElementSection(stackItem,structureStack.current(),attributes);
01290 }
01291 else if (name=="a")
01292 {
01293 success=StartElementA(stackItem,structureStack.current(),attributes);
01294 }
01295 else if (name=="br")
01296 {
01297
01298 StackItem* stackCurrent=structureStack.current();
01299 success=StartElementBR(stackItem,stackCurrent,mainDocument);
01300 }
01301 else if (name=="cbr")
01302 {
01303
01304 stackItem->elementType=ElementTypeEmpty;
01305 StackItem* stackCurrent=structureStack.current();
01306 if (stackCurrent->elementType==ElementTypeContent)
01307 {
01308 kdWarning(30506) << "Forced column break found! Transforming to forced page break" << endl;
01309 success=complexForcedPageBreak(stackItem);
01310 }
01311 else if (stackCurrent->elementType==ElementTypeParagraph)
01312 {
01313 kdWarning(30506) << "Forced column break found! Transforming to forced page break" << endl;
01314 success=StartElementPBR(stackItem,stackCurrent,mainDocument);
01315 }
01316 else
01317 {
01318 kdError(30506) << "Forced column break found out of turn! Aborting! Parent: "
01319 << stackCurrent->itemName <<endl;
01320 success=false;
01321 }
01322 }
01323 else if (name=="pbr")
01324 {
01325
01326 stackItem->elementType=ElementTypeEmpty;
01327 StackItem* stackCurrent=structureStack.current();
01328 if (stackCurrent->elementType==ElementTypeContent)
01329 {
01330 success=complexForcedPageBreak(stackItem);
01331 }
01332 else if (stackCurrent->elementType==ElementTypeParagraph)
01333 {
01334 success=StartElementPBR(stackItem,stackCurrent,mainDocument);
01335 }
01336 else
01337 {
01338 kdError(30506) << "Forced page break found out of turn! Aborting! Parent: "
01339 << stackCurrent->itemName <<endl;
01340 success=false;
01341 }
01342 }
01343 else if (name=="pagesize")
01344
01345 {
01346 stackItem->elementType=ElementTypeEmpty;
01347 stackItem->stackElementText=structureStack.current()->stackElementText;
01348 success=StartElementPageSize(m_paperElement,attributes);
01349 }
01350 else if ((name=="field")
01351 || (name=="f"))
01352 {
01353 success=StartElementField(stackItem,structureStack.current(),mainDocument,attributes);
01354 }
01355 else if (name=="s")
01356 {
01357 success=StartElementS(stackItem,structureStack.current(),attributes,styleDataMap);
01358 }
01359 else if ((name=="image")
01360 || (name=="i"))
01361 {
01362 success=StartElementImage(stackItem,structureStack.current(),attributes);
01363 }
01364 else if (name=="d")
01365 {
01366 success=StartElementD(stackItem,structureStack.current(),attributes);
01367 }
01368 else if (name=="iw")
01369 {
01370 stackItem->elementType=ElementTypeIgnoreWord;
01371 success=true;
01372 }
01373 else if (name=="m")
01374 {
01375 success=StartElementM(stackItem,structureStack.current(),attributes);
01376 }
01377 else if (name=="foot")
01378 {
01379 success=StartElementFoot(stackItem,structureStack.current(),attributes);
01380 }
01381 else if (name=="table")
01382 {
01383 success=StartElementTable(stackItem,structureStack.current(), attributes);
01384 }
01385 else if (name=="cell")
01386 {
01387 success=StartElementCell(stackItem,structureStack.current(),attributes);
01388 }
01389 else
01390 {
01391 stackItem->elementType=ElementTypeUnknown;
01392 stackItem->stackElementText=structureStack.current()->stackElementText;
01393 success=true;
01394 }
01395 if (success)
01396 {
01397 structureStack.push(stackItem);
01398 }
01399 else
01400 {
01401 delete stackItem;
01402 }
01403 return success;
01404 }
01405
01406 bool StructureParser :: endElement( const QString&, const QString& , const QString& name)
01407 {
01408 indent.remove( 0, 1 );
01409 kdDebug(30506) << indent << " </" << name << ">" << endl;
01410
01411 if (structureStack.isEmpty())
01412 {
01413 kdError(30506) << "Stack is empty!! Aborting! (in StructureParser::endElement)" << endl;
01414 return false;
01415 }
01416
01417 bool success=false;
01418
01419 StackItem *stackItem=structureStack.pop();
01420 if ((name=="c")||(name=="C"))
01421 {
01422 success=EndElementC(stackItem,structureStack.current());
01423 }
01424 else if ((name=="p")||(name=="P"))
01425 {
01426 success=EndElementP(stackItem);
01427 }
01428 else if (name=="a")
01429 {
01430 if (stackItem->elementType==ElementTypeContent)
01431 {
01432
01433 success=EndElementC(stackItem,structureStack.current());
01434 }
01435 else
01436 {
01437
01438 success=EndElementA(stackItem,structureStack.current(), mainDocument);
01439 }
01440 }
01441 else if (name=="d")
01442 {
01443 success=EndElementD(stackItem);
01444 }
01445 else if (name=="iw")
01446 {
01447 success=EndElementIW(stackItem,structureStack.current(), mainDocument, m_ignoreWordsElement);
01448 }
01449 else if (name=="m")
01450 {
01451 success=EndElementM(stackItem);
01452 }
01453 else
01454 {
01455 success=true;
01456 }
01457 if (!success)
01458 {
01459
01460 kdError(30506) << "Found tag name: " << name
01461 << " expected: " << stackItem->itemName << endl;
01462 }
01463 delete stackItem;
01464 return success;
01465 }
01466
01467 bool StructureParser :: characters ( const QString & ch )
01468 {
01469
01470 if (ch=="\n")
01471 {
01472 kdDebug(30506) << indent << " (LINEFEED)" << endl;
01473 }
01474 else if (ch.length()> 40)
01475 {
01476 kdDebug(30506) << indent << " :" << ch.left(40) << "..." << endl;
01477 }
01478 else
01479 {
01480 kdDebug(30506) << indent << " :" << ch << ":" << endl;
01481 }
01482
01483 if (structureStack.isEmpty())
01484 {
01485 kdError(30506) << "Stack is empty!! Aborting! (in StructureParser::characters)" << endl;
01486 return false;
01487 }
01488
01489 bool success=false;
01490
01491 StackItem *stackItem=structureStack.current();
01492
01493 if ((stackItem->elementType==ElementTypeContent)
01494 || (stackItem->elementType==ElementTypeAnchorContent))
01495 {
01496 success=charactersElementC(stackItem,mainDocument,ch);
01497 }
01498 else if (stackItem->elementType==ElementTypeParagraph)
01499 {
01500 success=charactersElementP(stackItem,mainDocument,ch);
01501 }
01502 else if (stackItem->elementType==ElementTypeAnchor)
01503 {
01504 success=charactersElementA(stackItem,ch);
01505 }
01506 else if (stackItem->elementType==ElementTypeEmpty)
01507 {
01508 success=ch.stripWhiteSpace().isEmpty();
01509 if (!success)
01510 {
01511
01512 kdError(30506) << "Empty element "<< stackItem->itemName
01513 <<" is not empty! Aborting! (in StructureParser::characters)" << endl;
01514 }
01515 }
01516 else if (stackItem->elementType==ElementTypeRealData)
01517 {
01518 success=CharactersElementD(stackItem,mainDocument,ch);
01519 }
01520 else if (stackItem->elementType==ElementTypeIgnoreWord)
01521 {
01522 stackItem->strTemp2+=ch;
01523 success=true;
01524 }
01525 else if (stackItem->elementType==ElementTypeRealMetaData)
01526 {
01527 success=CharactersElementM(stackItem,ch);
01528 }
01529 else
01530 {
01531 success=true;
01532 }
01533
01534 return success;
01535 }
01536
01537 bool StructureParser::startDocument(void)
01538 {
01539 indent = QString::null;
01540 styleDataMap.defineDefaultStyles();
01541 return true;
01542 }
01543
01544 void StructureParser::createDocInfo(void)
01545 {
01546 QDomImplementation implementation;
01547 QDomDocument doc(implementation.createDocumentType("document-info",
01548 "-//KDE//DTD document-info 1.2//EN", "http://www.koffice.org/DTD/document-info-1.2.dtd"));
01549
01550 m_info=doc;
01551
01552 m_info.appendChild(
01553 mainDocument.createProcessingInstruction(
01554 "xml","version=\"1.0\" encoding=\"UTF-8\""));
01555
01556 QDomElement elementDoc(mainDocument.createElement("document-info"));
01557 elementDoc.setAttribute("xmlns","http://www.koffice.org/DTD/document-info");
01558 m_info.appendChild(elementDoc);
01559
01560 QDomElement about(mainDocument.createElement("about"));
01561 elementDoc.appendChild(about);
01562
01563 QDomElement abstract(mainDocument.createElement("abstract"));
01564 about.appendChild(abstract);
01565 abstract.appendChild(mainDocument.createTextNode(m_metadataMap["dc.description"]));
01566
01567 QDomElement title(mainDocument.createElement("title"));
01568 about.appendChild(title);
01569 title.appendChild(mainDocument.createTextNode(m_metadataMap["dc.title"]));
01570
01571 QDomElement keyword(mainDocument.createElement("keyword"));
01572 about.appendChild(keyword);
01573 keyword.appendChild(mainDocument.createTextNode(m_metadataMap["abiword.keywords"]));
01574
01575 QDomElement subject(mainDocument.createElement("subject"));
01576 about.appendChild(subject);
01577 subject.appendChild(mainDocument.createTextNode(m_metadataMap["dc.subject"]));
01578 }
01579
01580 bool StructureParser::endDocument(void)
01581 {
01582 QDomElement stylesPluralElement=mainDocument.createElement("STYLES");
01583
01584 mainDocument.documentElement().insertBefore(stylesPluralElement,m_picturesElement);
01585
01586 kdDebug(30506) << "###### Start Style List ######" << endl;
01587 StyleDataMap::ConstIterator it;
01588
01589
01590 it=styleDataMap.find("Normal");
01591 if (it!=styleDataMap.end())
01592 {
01593 kdDebug(30506) << "\"" << it.key() << "\" => " << it.data().m_props << endl;
01594 QDomElement styleElement=mainDocument.createElement("STYLE");
01595 stylesPluralElement.appendChild(styleElement);
01596 AddStyle(styleElement, it.key(),it.data(),mainDocument);
01597 }
01598 else
01599 kdWarning(30506) << "No 'Normal' style" << endl;
01600
01601 for (it=styleDataMap.begin();it!=styleDataMap.end();++it)
01602 {
01603 if (it.key()=="Normal")
01604 continue;
01605
01606 kdDebug(30506) << "\"" << it.key() << "\" => " << it.data().m_props << endl;
01607
01608 QDomElement styleElement=mainDocument.createElement("STYLE");
01609 stylesPluralElement.appendChild(styleElement);
01610
01611 AddStyle(styleElement, it.key(),it.data(),mainDocument);
01612 }
01613 kdDebug(30506) << "###### End Style List ######" << endl;
01614
01615 createDocInfo();
01616
01617 return true;
01618 }
01619
01620 bool StructureParser::warning(const QXmlParseException& exception)
01621 {
01622 kdWarning(30506) << "XML parsing warning: line " << exception.lineNumber()
01623 << " col " << exception.columnNumber() << " message: " << exception.message() << endl;
01624 return true;
01625 }
01626
01627 bool StructureParser::error(const QXmlParseException& exception)
01628 {
01629
01630 kdWarning(30506) << "XML parsing error: line " << exception.lineNumber()
01631 << " col " << exception.columnNumber() << " message: " << exception.message() << endl;
01632 return true;
01633 }
01634
01635 bool StructureParser::fatalError (const QXmlParseException& exception)
01636 {
01637 kdError(30506) << "XML parsing fatal error: line " << exception.lineNumber()
01638 << " col " << exception.columnNumber() << " message: " << exception.message() << endl;
01639 m_fatalerror=true;
01640 KMessageBox::error(NULL, i18n("An error has occurred while parsing the AbiWord file.\nAt line: %1, column %2\nError message: %3")
01641 .arg(exception.lineNumber()).arg(exception.columnNumber())
01642 .arg( i18n( "QXml", exception.message().utf8() ) ),
01643 i18n("AbiWord Import Filter"),0);
01644 return false;
01645 }
01646
01647 void StructureParser :: createDocument(void)
01648 {
01649 QDomImplementation implementation;
01650 QDomDocument doc(implementation.createDocumentType("DOC",
01651 "-//KDE//DTD kword 1.2//EN", "http://www.koffice.org/DTD/kword-1.2.dtd"));
01652
01653 mainDocument=doc;
01654
01655 mainDocument.appendChild(
01656 mainDocument.createProcessingInstruction(
01657 "xml","version=\"1.0\" encoding=\"UTF-8\""));
01658
01659 QDomElement elementDoc;
01660 elementDoc=mainDocument.createElement("DOC");
01661 elementDoc.setAttribute("xmlns","http://www.koffice.org/DTD/kword");
01662 elementDoc.setAttribute("editor","AbiWord Import Filter");
01663 elementDoc.setAttribute("mime","application/x-kword");
01664 elementDoc.setAttribute( "syntaxVersion", 3 );
01665 mainDocument.appendChild(elementDoc);
01666
01667 QDomElement element;
01668 element=mainDocument.createElement("ATTRIBUTES");
01669 element.setAttribute("processing",0);
01670 element.setAttribute("standardpage",1);
01671 element.setAttribute("hasHeader",0);
01672 element.setAttribute("hasFooter",0);
01673
01674 element.setAttribute("tabStopValue",36);
01675 elementDoc.appendChild(element);
01676
01677
01678
01679 m_paperElement=mainDocument.createElement("PAPER");
01680 m_paperElement.setAttribute("format",PG_US_LETTER);
01681 m_paperElement.setAttribute("width",MillimetresToPoints(KoPageFormat::width (PG_US_LETTER,PG_PORTRAIT)));
01682 m_paperElement.setAttribute("height",MillimetresToPoints(KoPageFormat::height(PG_US_LETTER,PG_PORTRAIT)));
01683 m_paperElement.setAttribute("orientation",PG_PORTRAIT);
01684 m_paperElement.setAttribute("columns",1);
01685 m_paperElement.setAttribute("columnspacing",2);
01686 m_paperElement.setAttribute("hType",0);
01687 m_paperElement.setAttribute("fType",0);
01688 m_paperElement.setAttribute("spHeadBody",9);
01689 m_paperElement.setAttribute("spFootBody",9);
01690 m_paperElement.setAttribute("zoom",100);
01691 elementDoc.appendChild(m_paperElement);
01692
01693 m_paperBordersElement=mainDocument.createElement("PAPERBORDERS");
01694 m_paperBordersElement.setAttribute("left",28);
01695 m_paperBordersElement.setAttribute("top",42);
01696 m_paperBordersElement.setAttribute("right",28);
01697 m_paperBordersElement.setAttribute("bottom",42);
01698 m_paperElement.appendChild(m_paperBordersElement);
01699
01700 framesetsPluralElement=mainDocument.createElement("FRAMESETS");
01701 mainDocument.documentElement().appendChild(framesetsPluralElement);
01702
01703 mainFramesetElement=mainDocument.createElement("FRAMESET");
01704 mainFramesetElement.setAttribute("frameType",1);
01705 mainFramesetElement.setAttribute("frameInfo",0);
01706 mainFramesetElement.setAttribute("visible",1);
01707 mainFramesetElement.setAttribute("name",i18n("Frameset name","Main Text Frameset"));
01708 framesetsPluralElement.appendChild(mainFramesetElement);
01709
01710 QDomElement frameElementOut=mainDocument.createElement("FRAME");
01711 frameElementOut.setAttribute("left",28);
01712 frameElementOut.setAttribute("top",42);
01713 frameElementOut.setAttribute("bottom",566);
01714 frameElementOut.setAttribute("right",798);
01715 frameElementOut.setAttribute("runaround",1);
01716
01717 mainFramesetElement.appendChild(frameElementOut);
01718
01719
01720 m_ignoreWordsElement=mainDocument.createElement("SPELLCHECKIGNORELIST");
01721 mainDocument.documentElement().appendChild(m_ignoreWordsElement);
01722 m_picturesElement=mainDocument.createElement("PICTURES");
01723 mainDocument.documentElement().appendChild(m_picturesElement);
01724 }
01725
01726 bool StructureParser::clearStackUntilParagraph(StackItemStack& auxilaryStack)
01727 {
01728 for (;;)
01729 {
01730 StackItem* item=structureStack.pop();
01731 switch (item->elementType)
01732 {
01733 case ElementTypeContent:
01734 {
01735
01736 auxilaryStack.push(item);
01737 break;
01738 }
01739 case ElementTypeParagraph:
01740 {
01741
01742 structureStack.push(item);
01743 return true;
01744 }
01745 default:
01746 {
01747
01748 kdError(30506) << "Cannot clear this element: "
01749 << item->itemName << endl;
01750 return false;
01751 }
01752 }
01753 }
01754 }
01755
01756 ABIWORDImport::ABIWORDImport(KoFilter *, const char *, const QStringList &) :
01757 KoFilter() {
01758 }
01759
01760 KoFilter::ConversionStatus ABIWORDImport::convert( const QCString& from, const QCString& to )
01761 {
01762 if ((to != "application/x-kword") || (from != "application/x-abiword"))
01763 return KoFilter::NotImplemented;
01764
01765 kdDebug(30506)<<"AbiWord to KWord Import filter"<<endl;
01766
01767 StructureParser handler(m_chain);
01768
01769
01770 QXmlSimpleReader reader;
01771 reader.setContentHandler( &handler );
01772 reader.setErrorHandler( &handler );
01773
01774
01775 QString strExt;
01776 QString fileIn = m_chain->inputFile();
01777 const int result=fileIn.findRev('.');
01778 if (result>=0)
01779 {
01780 strExt=fileIn.mid(result);
01781 }
01782
01783 kdDebug(30506) << "File extension: -" << strExt << "-" << endl;
01784
01785 QString strMime;
01786
01787 if ((strExt==".gz")||(strExt==".GZ")
01788 ||(strExt==".zabw")||(strExt==".ZABW"))
01789 {
01790
01791 strMime="application/x-gzip";
01792 kdDebug(30506) << "Compression: gzip" << endl;
01793 }
01794 else if ((strExt==".bz2")||(strExt==".BZ2")
01795 ||(strExt==".bzabw")||(strExt==".BZABW"))
01796 {
01797
01798 strMime="application/x-bzip2";
01799 kdDebug(30506) << "Compression: bzip2" << endl;
01800 }
01801
01802 QIODevice* in = KFilterDev::deviceForFile(fileIn,strMime);
01803
01804 if ( !in )
01805 {
01806 kdError(30506) << "Cannot create device for uncompressing! Aborting!" << endl;
01807 return KoFilter::FileNotFound;
01808 }
01809
01810 if (!in->open(IO_ReadOnly))
01811 {
01812 kdError(30506) << "Cannot open file for uncompressing! Aborting!" << endl;
01813 delete in;
01814 return KoFilter::FileNotFound;
01815 }
01816
01817 QXmlInputSource source(in);
01818
01819 in->close();
01820
01821 if (!reader.parse( source ))
01822 {
01823 kdError(30506) << "Import: Parsing unsuccessful. Aborting!" << endl;
01824 delete in;
01825 if (!handler.wasFatalError())
01826 {
01827
01828 KMessageBox::error(NULL, i18n("An error occurred during the load of the AbiWord file: %1").arg(from),
01829 i18n("AbiWord Import Filter"),0);
01830 }
01831 return KoFilter::ParsingError;
01832 }
01833 delete in;
01834
01835 QCString strOut;
01836 KoStoreDevice* out;
01837
01838 kdDebug(30506) << "Creating documentinfo.xml" << endl;
01839 out=m_chain->storageFile( "documentinfo.xml", KoStore::Write );
01840 if(!out)
01841 {
01842 kdError(30506) << "AbiWord Import unable to open output file! (Documentinfo)" << endl;
01843 KMessageBox::error(NULL, i18n("Unable to save document information."),i18n("AbiWord Import Filter"),0);
01844 return KoFilter::StorageCreationError;
01845 }
01846
01847
01848 strOut=handler.getDocInfo().toCString();
01849
01850 out->writeBlock(strOut,strOut.length());
01851
01852 kdDebug(30506) << "Creating maindoc.xml" << endl;
01853 out=m_chain->storageFile( "root", KoStore::Write );
01854 if(!out)
01855 {
01856 kdError(30506) << "AbiWord Import unable to open output file! (Root)" << endl;
01857 KMessageBox::error(NULL, i18n("Unable to save main document."),i18n("AbiWord Import Filter"),0);
01858 return KoFilter::StorageCreationError;
01859 }
01860
01861
01862 strOut=handler.getDocument().toCString();
01863
01864 out->writeBlock(strOut,strOut.length());
01865
01866 #if 0
01867 kdDebug(30506) << documentOut.toString();
01868 #endif
01869
01870 kdDebug(30506) << "Now importing to KWord!" << endl;
01871
01872 return KoFilter::OK;
01873 }
01874
01875 #include "abiwordimport.moc"