hancomwordimport.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2002,2006 Ariya Hidayat <ariya@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include <config.h>
21
22#ifdef HAVE_UNISTD_H
23#include <unistd.h>
24#endif
25
26#include <hancomwordimport.h>
27#include <hancomwordimport.moc>
28
29#include <tqbuffer.h>
30#include <tqcstring.h>
31#include <tqfile.h>
32#include <tqstring.h>
33#include <tqstringlist.h>
34#include <tqtextstream.h>
35
36#include <kdebug.h>
37#include <KoFilterChain.h>
38#include <KoGlobal.h>
39#include <KoUnit.h>
40#include <kgenericfactory.h>
41
42#include <KoXmlWriter.h>
43
44#include <iostream>
45#include "pole.h"
46
47typedef KGenericFactory<HancomWordImport, KoFilter> HancomWordImportFactory;
48K_EXPORT_COMPONENT_FACTORY( libhancomwordimport, HancomWordImportFactory( "kofficefilters" ) )
49
50class HancomWordImport::Private
51{
52public:
53 TQString inputFile;
54 TQString outputFile;
55
56 TQStringList paragraphs;
57
58 TQByteArray createStyles();
59 TQByteArray createContent();
60 TQByteArray createManifest();
61};
62
63HancomWordImport::HancomWordImport ( TQObject*, const char*, const TQStringList& )
64 : KoFilter()
65{
66 d = new Private;
67}
68
69HancomWordImport::~HancomWordImport()
70{
71 delete d;
72}
73
74namespace
75{
76
77static inline unsigned long readU16( const void* p )
78{
79 const unsigned char* ptr = (const unsigned char*) p;
80 return ptr[0]+(ptr[1]<<8);
81}
82
83}
84
85KoFilter::ConversionStatus HancomWordImport::convert( const TQCString& from, const TQCString& to )
86{
87 if ( from != "application/x-hancomword" )
88 return KoFilter::NotImplemented;
89
90 if ( to != "application/vnd.oasis.opendocument.text" )
91 return KoFilter::NotImplemented;
92
93 d->inputFile = m_chain->inputFile();
94 d->outputFile = m_chain->outputFile();
95 d->paragraphs.clear();
96
97 POLE::Storage storage( d->inputFile.latin1() );
98 if( !storage.open() )
99 return KoFilter::WrongFormat;
100
101 POLE::Stream* stream;
102 stream = new POLE::Stream( &storage, "/PrvText" );
103 if( stream->fail() || (stream->size() == 0) )
104 {
105 delete stream;
106 return KoFilter::WrongFormat;
107 }
108
109 int len = stream->size() / 2;
110 TQString plaindoc;
111 plaindoc.reserve( len );
112
113 unsigned char* buf = new unsigned char [stream->size()];
114 stream->read( buf, stream->size());
115 for(int i = 0; i < len; i++ )
116 plaindoc.append( TQChar((int)readU16(buf + i*2) ) );
117 delete[] buf;
118 delete stream;
119
120 // split into paragraphs
121 d->paragraphs = TQStringList::split( "\n", plaindoc, true );
122
123 // create output store
124 KoStore* storeout;
125 storeout = KoStore::createStore( d->outputFile, KoStore::Write,
126 "application/vnd.oasis.opendocument.text", KoStore::Zip );
127
128 if ( !storeout )
129 {
130 kdWarning() << "Couldn't open the requested file." << endl;
131 return KoFilter::FileNotFound;
132 }
133
134 if ( !storeout->open( "styles.xml" ) )
135 {
136 kdWarning() << "Couldn't open the file 'styles.xml'." << endl;
137 return KoFilter::CreationError;
138 }
139 storeout->write( d->createStyles() );
140 storeout->close();
141
142 if ( !storeout->open( "content.xml" ) )
143 {
144 kdWarning() << "Couldn't open the file 'content.xml'." << endl;
145 return KoFilter::CreationError;
146 }
147 storeout->write( d->createContent() );
148 storeout->close();
149
150 // store document manifest
151 storeout->enterDirectory( "META-INF" );
152 if ( !storeout->open( "manifest.xml" ) )
153 {
154 kdWarning() << "Couldn't open the file 'META-INF/manifest.xml'." << endl;
155 return KoFilter::CreationError;
156 }
157 storeout->write( d->createManifest() );
158 storeout->close();
159
160 // we are done!
161 d->inputFile = TQString();
162 d->outputFile = TQString();
163 delete storeout;
164
165 return KoFilter::OK;
166}
167
168TQByteArray HancomWordImport::Private::createContent()
169{
170 KoXmlWriter* contentWriter;
171 TQByteArray contentData;
172 TQBuffer contentBuffer( contentData );
173
174 contentBuffer.open( IO_WriteOnly );
175 contentWriter = new KoXmlWriter( &contentBuffer );
176
177 contentWriter->startDocument( "office:document-content" );
178 contentWriter->startElement( "office:document-content" );
179
180 contentWriter->addAttribute( "xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0" );
181 contentWriter->addAttribute( "xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0" );
182 contentWriter->addAttribute( "xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0" );
183 contentWriter->addAttribute( "xmlns:table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0" );
184 contentWriter->addAttribute( "xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" );
185 contentWriter->addAttribute( "xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" );
186 contentWriter->addAttribute( "xmlns:svg","urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" );
187 contentWriter->addAttribute( "office:version","1.0" );
188
189 contentWriter->startElement( "office:automatic-styles" );
190 contentWriter->endElement(); // office:automatic-style
191
192 // office:body
193 contentWriter->startElement( "office:body" );
194
195 contentWriter->startElement( "office:text" );
196
197 contentWriter->startElement( "text:sequence-decls" );
198 contentWriter->endElement(); // text:sequence-decls
199
200 for( uint i = 0; i < paragraphs.count(); i++ )
201 {
202 TQString text = paragraphs[i];
203 text.replace( '\r', ' ' );
204 contentWriter->startElement( "text:p" );
205 contentWriter->addTextNode( text );
206 contentWriter->endElement(); // text:p
207 }
208
209 contentWriter->endElement(); //office:text
210 contentWriter->endElement(); // office:body
211
212 contentWriter->endElement(); // office:document-content
213 contentWriter->endDocument();
214
215 delete contentWriter;
216
217 return contentData;
218}
219
220TQByteArray HancomWordImport::Private::createStyles()
221{
222 KoXmlWriter* stylesWriter;
223 TQByteArray stylesData;
224 TQBuffer stylesBuffer( stylesData );
225
226 stylesBuffer.open( IO_WriteOnly );
227 stylesWriter = new KoXmlWriter( &stylesBuffer );
228
229 stylesWriter->startDocument( "office:document-styles" );
230 stylesWriter->startElement( "office:document-styles" );
231 stylesWriter->addAttribute( "xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0" );
232 stylesWriter->addAttribute( "xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0" );
233 stylesWriter->addAttribute( "xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0" );
234 stylesWriter->addAttribute( "xmlns:table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0" );
235 stylesWriter->addAttribute( "xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" );
236 stylesWriter->addAttribute( "xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" );
237 stylesWriter->addAttribute( "xmlns:svg","urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" );
238 stylesWriter->addAttribute( "office:version","1.0" );
239 stylesWriter->startElement( "office:styles" );
240
241 // dummy default paragraph style
242 stylesWriter->startElement( "style:default-style" );
243 stylesWriter->addAttribute( "style:family", "paragraph" );
244
245 stylesWriter->startElement( "style:paragraph-properties" );
246 stylesWriter->addAttribute( "fo:hyphenation-ladder-count", "no-limit" );
247 stylesWriter->addAttribute( "style:text-autospace", "ideograph-alpha" );
248 stylesWriter->addAttribute( "style:punctuation-wrap", "hanging" );
249 stylesWriter->addAttribute( "style:line-break", "strict" );
250 stylesWriter->addAttribute( "tyle:tab-stop-distance", "0.5in" );
251 stylesWriter->addAttribute( "style:writing-mode", "page" );
252 stylesWriter->endElement(); // style:paragraph-properties
253
254 stylesWriter->startElement( "style:text-properties" );
255 stylesWriter->addAttribute( "style:use-window-font-color", "true" );
256 stylesWriter->addAttribute( "style:font-name", "Sans Serif" );
257 stylesWriter->addAttribute( "fo:font-size", "12pt" );
258 stylesWriter->addAttribute( "fo:hyphenate", "false" );
259 stylesWriter->endElement(); // style:text-properties
260
261 stylesWriter->endElement(); // style:default-style
262 stylesWriter->endElement(); // office:styles
263
264 // office:automatic-styles
265 stylesWriter->startElement( "office:automatic-styles" );
266 stylesWriter->endElement(); // office:automatic-styles
267
268 stylesWriter->endElement(); // office:document-styles
269 stylesWriter->endDocument();
270
271 delete stylesWriter;
272
273 return stylesData;
274}
275
276TQByteArray HancomWordImport::Private::createManifest()
277{
278 KoXmlWriter* manifestWriter;
279 TQByteArray manifestData;
280 TQBuffer manifestBuffer( manifestData );
281
282 manifestBuffer.open( IO_WriteOnly );
283 manifestWriter = new KoXmlWriter( &manifestBuffer );
284
285 manifestWriter->startDocument( "manifest:manifest" );
286 manifestWriter->startElement( "manifest:manifest" );
287 manifestWriter->addAttribute( "xmlns:manifest", "urn:oasis:names:tc:openoffice:xmlns:manifest:1.0" );
288 manifestWriter->addManifestEntry( "/", "application/vnd.oasis.opendocument.text" );
289 manifestWriter->addManifestEntry( "styles.xml", "text/xml" );
290 manifestWriter->addManifestEntry( "content.xml", "text/xml" );
291 manifestWriter->endElement();
292 manifestWriter->endDocument();
293 delete manifestWriter;
294
295 return manifestData;
296}