filters

wp6.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2002 Ariya Hidayat <ariya@kde.org>
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 <qtextcodec.h>
00027 #include <qfile.h>
00028 #include <qfileinfo.h>
00029 #include <qtextstream.h>
00030 #include <qvaluevector.h>
00031 
00032 #include <KWEFBaseWorker.h>
00033 #include <KWEFKWordLeader.h>
00034 #include <KWEFUtil.h>
00035 
00036 #include <wp6.h>
00037 
00038 bool WPSixWorker::doOpenFile(const QString& filenameOut, const QString& /*to*/)
00039 {
00040   filename = filenameOut;
00041   outfile.setName( filename );
00042   if( !outfile.open( IO_WriteOnly ) )
00043     return false;
00044 
00045   output.setDevice( &outfile );
00046   output.setByteOrder (QDataStream::LittleEndian);
00047   return true;
00048 }
00049 
00050 bool WPSixWorker::doCloseFile(void)
00051 {
00052   // asssume we're at the end of the file
00053   Q_UINT32 total_filesize = outfile.at();
00054 
00055   // close the file first
00056   outfile.close();
00057 
00058   // reopen for read and write
00059   if( !outfile.open( IO_ReadWrite ) )
00060     return false;
00061   output.setDevice( &outfile );
00062 
00063   // now it's time to fix-up some header fields
00064 
00065   // fix for offset 12, int32, filesize
00066   outfile.at( 20 );
00067   output << total_filesize;
00068 
00069   // offset 4, int32, pointer to document area
00070   outfile.at( 4 );
00071   output << document_area_ptr;
00072 
00073   outfile.close();
00074   return true;
00075 }
00076 
00077 bool WPSixWorker::doOpenDocument(void)
00078 {
00079   // write WP document header
00080   // note that some fields are still "dummy"
00081 
00082   // magic id: -1, "WPC"
00083   Q_UINT8 magic[] = { 0xff, 0x57, 0x50, 0x43 };
00084   for( int i=0; i<4; i++ ) output << magic[i];
00085 
00086   // pointer to document area (dummy, will be fixed later)
00087   Q_UINT8 docptr[] = { 0x0E, 0x02, 0x00, 0x00 } ;
00088   for( int i=0; i<4; i++ ) output << docptr[i];
00089 
00090   // write product type ( 1 = WordPerfect )
00091   Q_UINT8 product_type = 1;
00092   output << product_type;
00093 
00094   // write file type ( 10 = WordPerfect document )
00095   Q_UINT8 file_type = 10;
00096   output << file_type;
00097 
00098   // write version (TODO explain)
00099   Q_UINT16 version = 0x0202;
00100   output << version;
00101 
00102   // write encryption flag ( 0 = not encrypted )
00103   Q_UINT16 encrypt = 0;
00104   output << encrypt;
00105 
00106   // offset to index header (always 0x200?)
00107   Q_UINT16 index_header_ptr = 0x200;
00108   output << index_header_ptr;
00109 
00110   // beginning of extended file header (always 5)
00111   Q_UINT32 extheader = 5;
00112   output << extheader;
00113 
00114   // filesize (dummy, will be fixed later)
00115   Q_UINT32 filesize = 0;
00116   output << filesize;
00117 
00118   // filler 488 bytes
00119   Q_UINT8 dummy = 0;
00120   for( int i=0; i<488; i++ ) output << dummy;
00121 
00122   // index header (specified 0 index!)
00123   Q_UINT8 index_header[] = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00124     0, 0, 0, 0 };
00125   for( int i=0; i<14; i++ ) output << index_header[i];
00126 
00127   // document area starts, mark it for the header fields
00128   document_area_ptr = output.device()->at();
00129 
00130   return true;
00131 }
00132 
00133 bool WPSixWorker::doCloseDocument(void)
00134 {
00135   return true;
00136 }
00137 
00138 // this helper functions "escape" plain Unicode string to WP-compliance string
00139 // what it does: converting spaces and tabs to hard-spaces and hard-tabs
00140 // TODO handle Unicode characters using WP charsets
00141 static QCString WPSixEscape( const QString& text )
00142 {
00143   QCString result;
00144 
00145   for( unsigned int i=0; i < text.length(); i++ )
00146   {
00147     int c = text[i].unicode();
00148     if( c < 32 ) result += '.'; 
00149     else if ( c == 32 ) result += 0x80 ; // hard space
00150     else if ( c < 128 ) result += text[i].latin1();
00151     else result += '.';
00152   }
00153 
00154   return result;
00155 }
00156 
00157 bool WPSixWorker::doFullParagraph(const QString& paraText, 
00158   const LayoutData& layout, const ValueListFormatData& paraFormatDataList)
00159 {
00160   // handle paragraph alignment/justification (default to left)
00161   unsigned char wp_align[] = { 0xd3, 5, 12, 0, 0, 1, 0, 0, 2, 12, 0, 0xd3 };
00162   if( layout.alignment == "left" ) wp_align[7] = 0;
00163   if( layout.alignment == "justify" ) wp_align[7] = 1;
00164   if( layout.alignment == "center" ) wp_align[7] = 2;
00165   if( layout.alignment == "right" ) wp_align[7] = 3;
00166   output.writeRawBytes( (const char*)wp_align, 12 );
00167 
00168   ValueListFormatData::ConstIterator it;
00169   for( it = paraFormatDataList.begin(); it!=paraFormatDataList.end(); ++it )
00170   {
00171     const FormatData& formatData = *it;
00172 
00173     // only if the format is for text (id==1)
00174     if( formatData.id == 1 )
00175     {
00176 
00177        Q_UINT8 attr = 0; //invalid
00178        if( formatData.text.weight >= 75 ) attr = 12; // bold
00179        if( formatData.text.italic ) attr = 8; 
00180        if( formatData.text.underline )
00181        {
00182          if( formatData.text.underlineValue == "double" )
00183            attr = 11; // double underline
00184          else
00185            attr = 14; // single underline
00186        }
00187        if( formatData.text.verticalAlignment == 1 ) attr = 6; //subscript
00188        if( formatData.text.verticalAlignment == 2 ) attr = 5; //superscript
00189        if( formatData.text.strikeout ) attr = 13; 
00190 
00191        QColor fgColor = formatData.text.fgColor;
00192        QColor bgColor = formatData.text.bgColor;
00193 
00194        // due to the file format, before writing the text we must
00195        // write some refix-code (such as Bold On) and possibly appropriate suffix-code (Bold Off)
00196         
00197        // attribute on
00198        if( attr > 0 ) output << (Q_UINT8)0xf2 << attr << (Q_UINT8)0xf2;
00199 
00200        // set font color
00201        if( fgColor.isValid() )
00202        {
00203          Q_UINT8 wp_color[] = { 0xd4, 0x18, 16, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0xd4 }; 
00204          wp_color[7] = (Q_UINT8) fgColor.red();
00205          wp_color[8] = (Q_UINT8) fgColor.green();
00206          wp_color[9] = (Q_UINT8) fgColor.blue();
00207          output.writeRawBytes( (const char*)wp_color, 16 );
00208        }
00209 
00210        // highlight on (background color)
00211        if( bgColor.isValid() )
00212        {
00213          output << (Q_UINT8) 0xfb;
00214          output << (Q_UINT8)bgColor.red() << (Q_UINT8)bgColor.green() << (Q_UINT8)bgColor.blue();
00215          output << (Q_UINT8) 100 << (Q_UINT8) 0xfb;
00216        }
00217 
00218        // the text itself, "escape" it first 
00219        QCString out = WPSixEscape( paraText.mid( formatData.pos, formatData.len ) );
00220        output.writeRawBytes( (const char*)out, out.length() );
00221 
00222        // attribute off
00223        if( attr > 0 ) output << (Q_UINT8)0xf3 << attr << (Q_UINT8)0xf3;
00224 
00225        // highlight off
00226        if( bgColor.isValid() )
00227        {
00228          output << (Q_UINT8) 0xfc;
00229          output << (Q_UINT8)bgColor.red() << (Q_UINT8)bgColor.green() << (Q_UINT8)bgColor.blue();
00230          output << (Q_UINT8) 100 << (Q_UINT8) 0xfc;
00231        }
00232     }
00233 
00234   }
00235     
00236   // write hard-return
00237   output << (Q_UINT8) 0xcc;
00238  
00239   return true;
00240 }
00241 
KDE Home | KDE Accessibility Home | Description of Access Keys