filters

amiproimport.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2002 Ariya Hidayat <ariyahidayat@yahoo.de>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include <config.h>
00021 
00022 #ifdef HAVE_UNISTD_H
00023 #include <unistd.h>
00024 #endif
00025 
00026 #include <qregexp.h>
00027 #include <qfileinfo.h>
00028 #include <qvaluelist.h>
00029 #include <qfont.h>
00030 
00031 #include <kdebug.h>
00032 #include <KoFilterChain.h>
00033 #include <kgenericfactory.h>
00034 #include <KoGlobal.h>
00035 
00036 #include <amiproimport.h>
00037 #include <amiproparser.h>
00038 
00039 typedef KGenericFactory<AmiProImport, KoFilter> AmiProImportFactory;
00040 K_EXPORT_COMPONENT_FACTORY( libamiproimport, AmiProImportFactory( "kofficefilters" ) )
00041 
00042 AmiProImport::AmiProImport( KoFilter *, const char *, const QStringList& ):
00043                      KoFilter()
00044 {
00045 }
00046 
00047 class AmiProConverter: public AmiProListener
00048 {
00049   public:
00050     AmiProConverter();
00051     QString root, documentInfo;
00052     virtual bool doOpenDocument();
00053     virtual bool doCloseDocument();
00054     virtual bool doDefineStyle( const AmiProStyle& style );
00055     virtual bool doParagraph( const QString& text, AmiProFormatList formatList,
00056       AmiProLayout& l );
00057   private:
00058     AmiProStyleList styleList;
00059 };
00060 
00061 // helper function to escape string for XML-ness
00062 static QString XMLEscape( const QString& str )
00063 {
00064   QString result;
00065 
00066   for( unsigned i=0; i<str.length(); i++ )
00067     if( str[i] == '&' ) result += "&amp;";
00068     else if( str[i] == '<' ) result += "&lt;";
00069     else if( str[i] == '>' ) result += "&gt;";
00070     else if( str[i] == '"' ) result += "&quot;";
00071     else if( str[i] == QChar(39) ) result += "&apos;";
00072     else result += str[i];
00073 
00074   return result;
00075 }
00076 
00077 // helper function to convert AmiPro format to KWord's FORMAT
00078 static QString AmiProFormatAsXML( AmiProFormat format )
00079 {
00080   QString result;
00081 
00082   QString fontname = format.fontFamily;
00083   if( fontname.isEmpty() ) fontname = KoGlobal::defaultFont().family();
00084   QString fontsize = QString::number( format.fontSize );
00085   QString boldness = format.bold ? "75" : "50";
00086   QString italic = format.italic ? "1" : "0";
00087   QString strikeout = format.strikethrough ? "1" : "0";
00088   QString vertalign = format.superscript ? "2" : format.subscript ? "1" : "0";
00089   QString underline = format.double_underline ? "double" :
00090     format.underline|format.word_underline ? "1" : "0";
00091 
00092   result = "<FORMAT id=\"1\" pos=\"" + QString::number(format.pos) +
00093      "\" len=\"" + QString::number(format.len) + "\">\n";
00094   result.append( "  <FONT name=\"" + fontname + "\" />\n" );
00095   result.append( "  <SIZE value=\"" + fontsize + "\" />\n" );
00096   result.append( "  <WEIGHT value=\"" + boldness + "\" />\n" );
00097   result.append( "  <ITALIC value=\"" + italic  + "\" />\n" );
00098   result.append( "  <STRIKEOUT value=\"" + strikeout + "\" />\n" );
00099   result.append( "  <VERTALIGN value=\"" + vertalign + "\" />\n" );
00100   result.append( "  <UNDERLINE value=\"" + underline + "\" />\n" );
00101   result.append( "</FORMAT>\n" );
00102 
00103   return result;
00104 }
00105 
00106 // helper function to convert AmiPro list of formats to KWord FORMATS
00107 static QString AmiProFormatListAsXML( AmiProFormatList& formatList )
00108 {
00109   QString result;
00110 
00111   AmiProFormatList::iterator it;
00112   for( it=formatList.begin(); it!=formatList.end(); ++it )
00113   {
00114     AmiProFormat& format = *it;
00115     result.append( AmiProFormatAsXML(format) );
00116   }
00117 
00118   if( !result.isEmpty() )
00119   {
00120     result.prepend( "<FORMATS>\n" );
00121     result.append( "</FORMATS>\n" );
00122   }
00123 
00124   return result;
00125 }
00126 
00127 // helper function to convert AmiPro paragraph layout to KWord's LAYOUT
00128 static QString AmiProLayoutAsXML( const AmiProLayout& layout )
00129 {
00130   QString result;
00131 
00132   QString referredStyle = layout.name;
00133   if( referredStyle.isEmpty() ) referredStyle = "Standard";
00134 
00135   QString fontname = layout.fontFamily;
00136   if( fontname.isEmpty() ) fontname = KoGlobal::defaultFont().family();
00137   QString fontsize = QString::number( layout.fontSize );
00138   QString fontcolor = "red=\"" + QString::number( layout.fontColor.red() ) +
00139     "\"  green=\"" +  QString::number( layout.fontColor.green() ) +
00140     "\"  blue=\"" + QString::number( layout.fontColor.blue() ) + "\"";
00141   QString boldness = layout.bold ? "75" : "50";
00142   QString italic = layout.italic ? "1" : "0";
00143   QString strikeout = layout.strikethrough ? "1" : "0";
00144   QString vertalign = layout.superscript ? "2" : layout.subscript ? "1" : "0";
00145   QString underline = layout.double_underline ? "double" :
00146     layout.underline|layout.word_underline ? "1" : "0";
00147 
00148   QString align;
00149   align = layout.align==Qt::AlignLeft ? "left" :
00150           layout.align==Qt::AlignRight ? "right" :
00151           layout.align==Qt::AlignCenter ? "center" :
00152           layout.align==Qt::AlignJustify ? "justify" :
00153           "left";
00154 
00155   QString offsets;
00156   offsets = "before=\"" + QString::number(layout.spaceBefore) +
00157             "\" after=\"" + QString::number(layout.spaceAfter) + "\"";
00158 
00159   QString linespacing;
00160   linespacing = layout.linespace==AmiPro::LS_Single ? QString::fromLatin1( "0" ) :
00161                 layout.linespace==AmiPro::LS_OneAndHalf ? QString::fromLatin1( "oneandhalf" ) :
00162                 layout.linespace==AmiPro::LS_Double ? QString::fromLatin1( "double" ) :
00163                   QString::number( layout.linespace );
00164 
00165   result.append( "<LAYOUT>\n" );
00166   result.append( "  <NAME value=\"" + XMLEscape( referredStyle ) + "\" />\n" );
00167   result.append( "  <FLOW align=\"" + align + "\" />\n" );
00168   result.append( "  <LINESPACING value=\"" + linespacing + "\" />\n" );
00169   result.append( "  <OFFSETS " + offsets + " />\n" );
00170   result.append( "  <LEFTBORDER width=\"0\" style=\"0\" />\n" );
00171   result.append( "  <RIGHTBORDER width=\"0\" style=\"0\" />\n" );
00172   result.append( "  <TOPBORDER width=\"0\" style=\"0\" />\n" );
00173   result.append( "  <BOTTOMBORDER width=\"0\" style=\"0\" />\n" );
00174   result.append( "  <INDENTS />\n" );
00175   result.append( "  <OFFSETS />\n" );
00176   result.append( "  <PAGEBREAKING />\n" );
00177   result.append( "  <COUNTER />\n" );
00178   result.append( "  <FORMAT id=\"1\">\n" );
00179   result.append( "    <FONT name=\"" + fontname + "\" />\n" );
00180   result.append( "    <SIZE value=\"" + fontsize + "\" />\n" );
00181   result.append( "    <COLOR " + fontcolor + " />\n" );
00182   result.append( "    <WEIGHT value=\"" + boldness + "\" />\n" );
00183   result.append( "    <ITALIC value=\"" + italic  + "\" />\n" );
00184   result.append( "    <STRIKEOUT value=\"" + strikeout + "\" />\n" );
00185   result.append( "    <VERTALIGN value=\"" + vertalign + "\" />\n" );
00186   result.append( "    <UNDERLINE value=\"" + underline + "\" />\n" );
00187   result.append( "  </FORMAT>\n" );
00188   result.append( "</LAYOUT>\n" );
00189 
00190   return result;
00191 }
00192 
00193 // helper function to convert AmiPro style to KWord STYLE
00194 static QString AmiProStyleAsXML( const AmiProStyle& style )
00195 {
00196   QString result;
00197 
00198   QString fontname = style.fontFamily;
00199   if( fontname.isEmpty() ) fontname = KoGlobal::defaultFont().family();
00200   QString fontsize = QString::number( style.fontSize );
00201   QString boldness = style.bold ? "75" : "50";
00202   QString italic = style.italic ? "1" : "0";
00203   QString strikeout = style.strikethrough ? "1" : "0";
00204   QString vertalign = style.superscript ? "2" : style.subscript ? "1" : "0";
00205   QString underline = style.double_underline ? "double" :
00206     style.underline|style.word_underline ? "1" : "0";
00207 
00208   QString align;
00209   align = style.align==Qt::AlignLeft ? "left" :
00210           style.align==Qt::AlignRight ? "right" :
00211           style.align==Qt::AlignCenter ? "center" :
00212           style.align==Qt::AlignJustify ? "justify" :
00213           "left";
00214 
00215   QString linespacing;
00216   linespacing = style.linespace==AmiPro::LS_Single ? QString::fromLatin1( "0" ) :
00217                 style.linespace==AmiPro::LS_OneAndHalf ? QString::fromLatin1( "oneandhalf" ) :
00218                 style.linespace==AmiPro::LS_Double ? QString::fromLatin1( "double" ) :
00219                   QString::number( style.linespace );
00220 
00221   QString offsets;
00222   offsets = "before=\"" + QString::number(style.spaceBefore) +
00223             "\" after=\"" + QString::number(style.spaceAfter) + "\"";
00224 
00225   result.append( "<STYLE>\n" );
00226   result.append( "  <NAME value=\"" + XMLEscape( style.name ) + "\" />\n" );
00227   result.append( "  <FOLLOWING name=\"Body Text\" />\n" );
00228   result.append( "  <FLOW align=\"" + align + "\" />\n" );
00229   result.append( "  <LINESPACING value=\"" + linespacing + "\" />\n" );
00230   result.append( "  <OFFSETS " + offsets + " />\n" );
00231   result.append( "  <LEFTBORDER width=\"0\" style=\"0\" />\n" );
00232   result.append( "  <RIGHTBORDER width=\"0\" style=\"0\" />\n" );
00233   result.append( "  <TOPBORDER width=\"0\" style=\"0\" />\n" );
00234   result.append( "  <BOTTOMBORDER width=\"0\" style=\"0\" />\n" );
00235   result.append( "  <FORMAT id=\"1\">\n" );
00236   result.append( "    <FONT name=\"" + fontname + "\" />\n" );
00237   result.append( "    <SIZE value=\"" + fontsize + "\" />\n" );
00238   result.append( "    <WEIGHT value=\"" + boldness + "\" />\n" );
00239   result.append( "    <ITALIC value=\"" + italic  + "\" />\n" );
00240   result.append( "    <STRIKEOUT value=\"" + strikeout + "\" />\n" );
00241   result.append( "    <VERTALIGN value=\"" + vertalign + "\" />\n" );
00242   result.append( "    <UNDERLINE value=\"" + underline + "\" />\n" );
00243   result.append( "  </FORMAT>\n" );
00244   result.append( "</STYLE>\n" );
00245 
00246   return result;
00247 }
00248 
00249 // helper function to convert AmiPro styles to KWord STYLES
00250 static QString AmiProStyleListAsXML( AmiProStyleList& styleList )
00251 {
00252   QString result;
00253 
00254   AmiProStyleList::iterator it;
00255   for( it=styleList.begin(); it!=styleList.end(); ++it )
00256   {
00257     AmiProStyle& style = *it;
00258     result.append( AmiProStyleAsXML( style ) );
00259   }
00260 
00261   if( !result.isEmpty() )
00262   {
00263     result.prepend ( "<STYLES>\n" );
00264     result.append( "</STYLES>\n" );
00265   }
00266 
00267   return result;
00268 }
00269 
00270 AmiProConverter::AmiProConverter()
00271 {
00272   root = "";
00273 }
00274 
00275 bool AmiProConverter::doOpenDocument()
00276 {
00277   QString prolog = "<!DOCTYPE DOC>\n";
00278 
00279   prolog.append( "<DOC mime=\"application/x-kword\" syntaxVersion=\"2\" editor=\"KWord\">\n");
00280   prolog.append( "<PAPER width=\"595\" height=\"841\" format=\"1\" fType=\"0\" orientation=\"0\" hType=\"0\" columns=\"1\">\n" );
00281   prolog.append( " <PAPERBORDERS left=\"36\" right=\"36\" top=\"36\" bottom=\"36\" />\n" );
00282   prolog.append( "</PAPER>\n" );
00283   prolog.append( "<ATTRIBUTES standardpage=\"1\" hasFooter=\"0\" hasHeader=\"0\" processing=\"0\" />\n" );
00284   prolog.append( "<FRAMESETS>\n" );
00285   prolog.append( "<FRAMESET removable=\"0\" frameType=\"1\" frameInfo=\"0\" autoCreateNewFrame=\"1\">\n" );
00286   prolog.append( "<FRAME right=\"567\" left=\"28\" top=\"42\" bottom=\"799\" />\n" );
00287   root = prolog;
00288 
00289   return true;
00290 }
00291 
00292 bool AmiProConverter::doCloseDocument()
00293 {
00294   QString epilog = "</FRAMESET>\n";
00295   epilog.append( "</FRAMESETS>\n" );
00296   epilog.append( AmiProStyleListAsXML( styleList ) );
00297   epilog.append( "</DOC>\n" );
00298 
00299   root.append( epilog );
00300 
00301   return true;
00302 }
00303 
00304 bool AmiProConverter::doDefineStyle( const AmiProStyle& style )
00305 {
00306   styleList.append( style );
00307   return true;
00308 }
00309 
00310 bool AmiProConverter::doParagraph( const QString& text, AmiProFormatList formatList,
00311   AmiProLayout& layout )
00312 {
00313   root.append( "<PARAGRAPH>\n" );
00314   root.append( "<TEXT>" + XMLEscape( text ) + "</TEXT>\n" );
00315   root.append( AmiProFormatListAsXML( formatList ) );
00316   root.append( AmiProLayoutAsXML( layout ) );
00317   root.append( "</PARAGRAPH>\n" );
00318 
00319   return true;
00320 }
00321 
00322 KoFilter::ConversionStatus AmiProImport::convert( const QCString& from, const QCString& to )
00323 {
00324   // check for proper conversion
00325   if( to!= "application/x-kword" || from != "application/x-amipro" )
00326      return KoFilter::NotImplemented;
00327 
00328   // parse/convert input file
00329   AmiProParser *parser = new AmiProParser;
00330   AmiProConverter *converter = new AmiProConverter;
00331   parser->setListener( converter );
00332 
00333   parser->process( m_chain->inputFile() );
00334 
00335   if( converter->root.isEmpty() )
00336     return KoFilter::StupidError;
00337 
00338   QString root = converter->root;
00339   QString documentInfo = converter->documentInfo;
00340 
00341   delete converter;
00342   delete parser;
00343 
00344   // prepare storage
00345   KoStoreDevice* out=m_chain->storageFile( "root", KoStore::Write );
00346 
00347   // store output document
00348   if( out )
00349     {
00350       QCString cstring = root.utf8();
00351       cstring.prepend( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
00352       out->writeBlock( (const char*) cstring, cstring.length() );
00353     }
00354 
00355   // store document info
00356   out = m_chain->storageFile( "documentinfo.xml", KoStore::Write );
00357   if ( out )
00358     {
00359        QCString cstring = documentInfo.utf8();
00360        cstring.prepend( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
00361 
00362        out->writeBlock( (const char*) cstring, cstring.length() );
00363      }
00364 
00365   return KoFilter::OK;
00366 }
00367 
00368 #include "amiproimport.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys