1 /* This file is part of the wvWare 2 project
2    Copyright (C) 2003 Werner Trobin <trobin@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 version 2 as published by the Free Software Foundation.
7 
8    This library is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11    Library General Public License for more details.
12 
13    You should have received a copy of the GNU Library General Public License
14    along with this library; see the file COPYING.LIB.  If not, write to
15    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16    Boston, MA 02111-1307, USA.
17 */
18 
19 #include "word_helper.h"
20 #include "olestream.h"
21 #include "textconverter.h"
22 #include "ustring.h"
23 
24 namespace wvWare
25 {
26 
STTBF(U16 lid,OLEStreamReader * reader,bool preservePos)27     STTBF::STTBF( U16 lid, OLEStreamReader* reader, bool preservePos )
28     {
29         if ( preservePos )
30             reader->push();
31         init( lid, reader, 0 );
32         if ( preservePos )
33             reader->pop();
34     }
35 
STTBF(U16 lid,const U8 * ptr)36     STTBF::STTBF( U16 lid, const U8* ptr )
37     {
38         init( lid, 0, ptr );
39     }
40 
STTBF(const STTBF & rhs)41     STTBF::STTBF( const STTBF& rhs ) : m_strings( rhs.m_strings ), m_extraDataLength( rhs.m_extraDataLength )
42     {
43         std::vector<U8*>::const_iterator it = rhs.m_extraData.begin();
44         std::vector<U8*>::const_iterator end = rhs.m_extraData.end();
45         for ( ; it != end; ++it ) {
46             U8* tmp = new U8[ m_extraDataLength ];
47             memcpy( tmp, *it, m_extraDataLength );
48             m_extraData.push_back( tmp );
49         }
50     }
51 
~STTBF()52     STTBF::~STTBF()
53     {
54         std::vector<U8*>::const_iterator it = m_extraData.begin();
55         for ( ; it != m_extraData.end(); ++it )
56             delete [] *it;
57     }
58 
count() const59     unsigned int STTBF::count() const
60     {
61         return m_strings.size();
62     }
63 
firstString() const64     UString STTBF::firstString() const
65     {
66         m_stringIt = m_strings.begin();
67         if ( m_stringIt != m_strings.end() )
68             return *m_stringIt;
69         return UString::null;
70     }
71 
nextString() const72     UString STTBF::nextString() const
73     {
74         if ( m_stringIt == m_strings.end() )
75             return UString::null;
76         ++m_stringIt;
77         if ( m_stringIt != m_strings.end() )
78             return *m_stringIt;
79         return UString::null;
80     }
81 
prevString() const82     UString STTBF::prevString() const
83     {
84         if ( m_strings.size() == 0 )
85             return UString::null;
86         if ( m_stringIt != m_strings.begin() )
87             --m_stringIt;
88         return *m_stringIt;
89     }
90 
lastString() const91     UString STTBF::lastString() const
92     {
93         m_stringIt = m_strings.end();
94         if ( m_stringIt == m_strings.begin() )
95             return UString::null;
96         --m_stringIt;
97         return *m_stringIt;
98     }
99 
stringAt(unsigned int index) const100     UString STTBF::stringAt( unsigned int index ) const
101     {
102         if ( index < m_strings.size() )
103             return m_strings[ index ];
104         return UString::null;
105     }
106 
firstExtra() const107     const U8* STTBF::firstExtra() const
108     {
109         m_extraIt = m_extraData.begin();
110         if ( m_extraIt != m_extraData.end() )
111             return *m_extraIt;
112         return 0;
113     }
114 
nextExtra() const115     const U8* STTBF::nextExtra() const
116     {
117         if ( m_extraIt == m_extraData.end() )
118             return 0;
119         ++m_extraIt;
120         if ( m_extraIt != m_extraData.end() )
121             return *m_extraIt;
122         return 0;
123     }
124 
prevExtra() const125     const U8* STTBF::prevExtra() const
126     {
127         if ( m_extraData.size() == 0 )
128             return 0;
129         if ( m_extraIt != m_extraData.begin() )
130             --m_extraIt;
131         return *m_extraIt;
132     }
133 
lastExtra() const134     const U8* STTBF::lastExtra() const
135     {
136         m_extraIt = m_extraData.end();
137         if ( m_extraIt == m_extraData.begin() )
138             return 0;
139         --m_extraIt;
140         return *m_extraIt;
141     }
142 
extraAt(unsigned int index) const143     const U8* STTBF::extraAt( unsigned int index ) const
144     {
145         if ( index < m_extraData.size() )
146             return m_extraData[ index ];
147         return 0;
148     }
149 
dumpStrings() const150     void STTBF::dumpStrings() const
151     {
152         wvlog << "STTBF::dumpStrings(): count=" << count() << " extraDataLength="
153               << extraDataLength() << std::endl;
154         std::vector<UString>::const_iterator it = m_strings.begin();
155         std::vector<UString>::const_iterator end = m_strings.end();
156         for ( ; it != end; ++it )
157             wvlog << "   '" << ( *it ).ascii() << "'" << std::endl;
158     }
159 
init(U16 lid,OLEStreamReader * reader,const U8 * ptr)160     void STTBF::init( U16 lid, OLEStreamReader* reader, const U8* ptr )
161     {
162         bool extended = false;
163         U16 count = readU16( reader, &ptr );
164         // "extended" characters?
165         if ( count == 0xffff ) {
166             extended = true;
167             // read the real size
168             count = readU16( reader, &ptr );
169         }
170         m_extraDataLength = readU16( reader, &ptr );
171 
172         // If we don't read unicode strings we have to set up a text converter
173         TextConverter* textconverter = 0;
174         if ( !extended )
175             textconverter = new TextConverter( lid );
176 
177         // read one string after the other
178         for ( U16 i = 0; i < count; ++i ) {
179             U16 len = 0;
180             if ( extended ) // double byte count!
181                 len = readU16( reader, &ptr );
182             else
183                 len = readU8( reader, &ptr );
184 
185             if ( len != 0 ) {
186                 if ( extended ) {
187                     XCHAR* string = new XCHAR[ len ];
188                     for ( U16 j = 0; j < len; ++j )
189                         string[ j ] = readU16( reader, &ptr );
190                     UString ustring( reinterpret_cast<const wvWare::UChar *>( string ), len );
191                     delete [] string;
192                     m_strings.push_back( ustring );
193                 }
194                 else {
195                     U8* string = new U8[ len ];
196                     read( reader, &ptr, string, len );
197                     UString ustring( textconverter->convert( reinterpret_cast<char*>( string ),
198                                                              static_cast<unsigned int>( len ) ) );
199                     delete [] string;
200                     m_strings.push_back( ustring );
201                 }
202             }
203             else
204                 m_strings.push_back( UString("") );
205             if ( m_extraDataLength != 0 ) {
206                 U8* extra = new U8[ m_extraDataLength ];
207                 read( reader, &ptr, extra, m_extraDataLength );
208                 m_extraData.push_back( extra );
209             }
210         }
211         delete textconverter;
212     }
213 
readU16(OLEStreamReader * reader,const U8 ** ptr) const214     U16 STTBF::readU16( OLEStreamReader* reader, const U8** ptr ) const
215     {
216         if ( reader )
217             return reader->readU16();
218         else if ( *ptr ) {
219             U16 ret = wvWare::readU16( *ptr );
220             *ptr += 2;
221             return ret;
222         }
223         else {
224             wvlog << "Warning: Internal error while reading STTBF" << std::endl;
225             return 0;
226         }
227     }
228 
readU8(OLEStreamReader * reader,const U8 ** ptr) const229     U8 STTBF::readU8( OLEStreamReader* reader, const U8** ptr ) const
230     {
231         if ( reader )
232             return reader->readU8();
233         else if ( *ptr ) {
234             U8 ret = **ptr;
235             *ptr += 1;
236             return ret;
237         }
238         else {
239             wvlog << "Warning: Internal error while reading STTBF" << std::endl;
240             return 0;
241         }
242     }
243 
read(OLEStreamReader * reader,const U8 ** ptr,U8 * buffer,size_t length) const244     bool STTBF::read( OLEStreamReader* reader, const U8** ptr, U8* buffer, size_t length ) const
245     {
246         if ( reader )
247             return reader->read( buffer, length );
248         else if ( *ptr ) {
249             memcpy( buffer, *ptr, length );
250             *ptr += length;
251             return true;
252         }
253         else {
254             wvlog << "Warning: Internal error while reading STTBF" << std::endl;
255             return false;
256         }
257     }
258 
259 
CHPFKP_BX()260     CHPFKP_BX::CHPFKP_BX()
261     {
262         clear();
263     }
264 
CHPFKP_BX(OLEStreamReader * stream,bool preservePos)265     CHPFKP_BX::CHPFKP_BX( OLEStreamReader* stream, bool preservePos )
266     {
267         clear();
268         read( stream, preservePos );
269     }
270 
CHPFKP_BX(const U8 * ptr)271     CHPFKP_BX::CHPFKP_BX( const U8* ptr )
272     {
273         clear();
274         readPtr( ptr );
275     }
276 
read(OLEStreamReader * stream,bool preservePos)277     bool CHPFKP_BX::read( OLEStreamReader* stream, bool preservePos )
278     {
279         if ( preservePos )
280             stream->push();
281         offset = stream->readU8();
282         if ( preservePos )
283             stream->pop();
284         return true;
285     }
286 
readPtr(const U8 * ptr)287     void CHPFKP_BX::readPtr( const U8* ptr )
288     {
289         offset = *ptr;
290     }
291 
write(OLEStreamWriter * stream,bool preservePos) const292     bool CHPFKP_BX::write( OLEStreamWriter* stream, bool preservePos ) const
293     {
294         if ( preservePos )
295             stream->push();
296         stream->write( offset );
297         if ( preservePos )
298             stream->pop();
299         return true;
300     }
301 
clear()302     void CHPFKP_BX::clear()
303     {
304         offset = 0;
305     }
306 
operator ==(const CHPFKP_BX & lhs,const CHPFKP_BX & rhs)307     bool operator==( const CHPFKP_BX& lhs, const CHPFKP_BX& rhs )
308     {
309         return lhs.offset == rhs.offset;
310     }
311 
operator !=(const CHPFKP_BX & lhs,const CHPFKP_BX & rhs)312     bool operator!=( const CHPFKP_BX& lhs, const CHPFKP_BX& rhs )
313     {
314         return !( lhs == rhs );
315     }
316 
317     const unsigned int CHPFKP_BX::sizeOf = 1;
318 
319 } // namespace wvWare
320