~ubuntu-branches/ubuntu/breezy/koffice/breezy

« back to all changes in this revision

Viewing changes to filters/kspread/dbase/dbase.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ben Burton
  • Date: 2004-05-09 11:33:00 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040509113300-vfrdadqsvjfuhn3b
Tags: 1:1.3.1-1
* New upstream bugfix release.
* Built against newer imagemagick (closes: #246623).
* Made koffice-libs/kformula recommend/depend on latex-xft-fonts, which
  provides mathematical fonts that the formula editor can use.  Also
  patched the kformula part to make these fonts the default.
* Changed kword menu hint from "WordProcessors" to "Word processors"
  (closes: #246209).
* Spellchecker configuration is now fixed (closes: #221256, #227568).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of the KDE project
 
2
   Copyright (C) 2002 by Thomas Franke and Andreas Pietzowski <andreas@pietzowski.de>
 
3
                         Ariya Hidayat <ariyahidayat@yahoo.de>
 
4
 
 
5
   This library is free software; you can redistribute it and/or
 
6
   modify it under the terms of the GNU Library General Public
 
7
   License as published by the Free Software Foundation; either
 
8
   version 2 of the License, or (at your option) any later version.
 
9
 
 
10
   This library is distributed in the hope that it will be useful,
 
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
   Library General Public License for more details.
 
14
 
 
15
   You should have received a copy of the GNU Library General Public License
 
16
   along with this library; see the file COPYING.LIB.  If not, write to
 
17
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
18
   Boston, MA 02111-1307, USA.
 
19
*/
 
20
 
 
21
 
 
22
#include <qdatetime.h>
 
23
#include <qdatastream.h>
 
24
#include <qfile.h>
 
25
#include <qstring.h>
 
26
#include <qstringlist.h>
 
27
#include <qptrlist.h>
 
28
 
 
29
#include <dbase.h>
 
30
 
 
31
DBase::DBase(): m_recordCount( 0 )
 
32
{
 
33
  fields.setAutoDelete( true );
 
34
}
 
35
 
 
36
DBase::~DBase()
 
37
{
 
38
  fields.clear();
 
39
  close();
 
40
}
 
41
 
 
42
  // Headerdefinition in dBASE
 
43
  //
 
44
  //  Type                            char   Content
 
45
  //
 
46
  //  unsigned char version           0      dBASE-Version (3)
 
47
  //  unsigned char last_update[3]    1-3    Date of last update
 
48
  //  unsigned long records           4-7    Number of records
 
49
  //  unsigned short header_length    8-9    headerlength
 
50
  //  unsigned short record_length    10-11  recordlength
 
51
  //  unsigned char reserved[20]      12-31  reserverd info from dBase
 
52
  //
 
53
 
 
54
bool DBase::load( const QString& filename )
 
55
{
 
56
 
 
57
  m_file.setName( filename );
 
58
  if( !m_file.open(IO_ReadOnly) )
 
59
    return false;
 
60
 
 
61
  m_stream.setDevice( &m_file );
 
62
  m_stream.setByteOrder( QDataStream::LittleEndian );
 
63
 
 
64
  unsigned filesize = m_file.size();
 
65
 
 
66
  // read dBASE version
 
67
  Q_UINT8 ver;
 
68
  m_stream >> ver;
 
69
  m_version = ver & 0x7f; // bit 7: has memo ?
 
70
 
 
71
  // only dBASE V.3 is supported
 
72
  if ( m_version != 3 )
 
73
     return false;
 
74
 
 
75
  // date of last update
 
76
  Q_UINT8 y, m, d;
 
77
  m_stream >> y >> m >> d;
 
78
  // because dBASE saves 102 instead of 2002 (very Y2K-save ;-)
 
79
  m_lastUpdate.setYMD( y+1900, m, d );
 
80
 
 
81
  // check for valid date
 
82
  if( !m_lastUpdate.isValid() ) return false;
 
83
 
 
84
  // number of records
 
85
  Q_UINT32 norec;
 
86
  m_stream >> norec;
 
87
  m_recordCount = norec;
 
88
 
 
89
  // header-length
 
90
  Q_UINT16 header_length;
 
91
  m_stream >> header_length;
 
92
  m_headerLength = header_length;
 
93
 
 
94
  // record-length
 
95
  Q_UINT16 record_length;
 
96
  m_stream >> record_length;
 
97
  m_recordLength = record_length;
 
98
 
 
99
  // read the remaining chars
 
100
  Q_UINT8 dummy;
 
101
  for (int foo = 0; foo < 20; ++foo)
 
102
    m_stream >> dummy;
 
103
 
 
104
  // size of file must match
 
105
  if( filesize < m_headerLength + m_recordLength * m_recordCount )
 
106
    return false;
 
107
 
 
108
  // Now read the headers of the columns and their type
 
109
 
 
110
  // Type                              char     Content
 
111
  //
 
112
  // unsigned char field_name[11]      0-10     Fieldname
 
113
  // unsigned char field_type          11       Fieldtype
 
114
  // unsigned long field_address       12-15    Fielddataaddress
 
115
  // unsigned char field_length        16       Fieldlength
 
116
  // unsigned char field_decimals      17       decimals
 
117
  // unsigned char reserved[14]        18-31    reserved for internal dBASE-stuff
 
118
 
 
119
  fields.clear();
 
120
  for( unsigned i = 1; i < m_headerLength/32; ++i )
 
121
  {
 
122
    DBaseField* field = new DBaseField;
 
123
 
 
124
    // columnn-name
 
125
    Q_UINT8 colname[12];
 
126
    for ( int j = 0; j < 11; ++j)
 
127
       m_stream >> colname[j];
 
128
    colname[11] = '\0';
 
129
    field->name = QString( (const char*) &colname[0] );
 
130
      
 
131
    // type of column
 
132
    Q_UINT8 coltype;
 
133
    m_stream >> coltype;
 
134
    switch( coltype )
 
135
    {
 
136
      case 'C': field->type = DBaseField::Character; break;
 
137
      case 'N': field->type = DBaseField::Numeric; break;
 
138
      case 'D': field->type = DBaseField::Date; break;
 
139
      case 'M': field->type = DBaseField::Memo; break;
 
140
      case 'L': field->type = DBaseField::Logical; break;
 
141
      default: field->type = DBaseField::Unknown; break;
 
142
    }
 
143
      
 
144
    // fileddataaddress
 
145
    Q_UINT32 addr;
 
146
    m_stream >> addr;
 
147
 
 
148
    // columnlength
 
149
    Q_UINT8 colsize;
 
150
    m_stream >> colsize;
 
151
    field->length = colsize; 
 
152
 
 
153
    // decimals
 
154
    Q_UINT8 decimals;
 
155
    m_stream >> decimals;
 
156
    field->decimals = decimals;
 
157
 
 
158
    // read remaining chars
 
159
    Q_UINT8 dummy;
 
160
    for ( int foo = 0; foo < 14; ++foo )
 
161
      m_stream >> dummy;
 
162
 
 
163
    // now append 
 
164
    fields.append( field );
 
165
  }
 
166
 
 
167
  // set the index to the first record
 
168
  m_stream.device()->at( m_headerLength );
 
169
 
 
170
  return true;
 
171
}
 
172
 
 
173
QStringList DBase::readRecord( unsigned recno )
 
174
{
 
175
  QStringList result;
 
176
 
 
177
  // out of range ? return empty strings
 
178
  if( recno >= m_recordCount )
 
179
  {
 
180
    for( unsigned i=0; i<fields.count(); i++)
 
181
      result.append( "" );
 
182
    return result;
 
183
  }
 
184
 
 
185
  // seek to where the record is
 
186
  unsigned filepos = m_headerLength + recno * m_recordLength;
 
187
  m_stream.device()->at( filepos );
 
188
 
 
189
  // first char == '*' means the record is deleted
 
190
  // so we just skip it
 
191
  Q_UINT8 delmarker;
 
192
  m_stream >> delmarker;
 
193
  if( delmarker == 0x2a )
 
194
   return result;
 
195
 
 
196
  // load it
 
197
  for( unsigned i=0; i<fields.count(); i++ )
 
198
    switch( fields.at(i)->type )
 
199
    {
 
200
      // Numeric or Character
 
201
      case DBaseField::Numeric:
 
202
      case DBaseField::Character:
 
203
      {
 
204
        QString str;
 
205
        Q_UINT8 ch;
 
206
        for( unsigned j=0; j<fields.at(i)->length; j++ )
 
207
        {  m_stream >> ch; str += QChar(ch); }
 
208
        result.append( str );
 
209
      }  break;
 
210
 
 
211
      // Logical
 
212
      case DBaseField::Logical:
 
213
      {
 
214
        Q_UINT8 ch;
 
215
        m_stream >> ch;
 
216
        switch( ch )
 
217
        {
 
218
          case 'Y': case 'y': case 'T': case 't': result.append( "True" ); break;
 
219
          case 'N': case 'n': case 'F': case 'f': result.append( "False" ); break;
 
220
          default: result.append( "" ); break;
 
221
        }
 
222
      } break;
 
223
 
 
224
      // Date, stored as YYYYMMDD
 
225
      // Note: convert it to YYYY-MM-DD
 
226
      case DBaseField::Date:
 
227
      {
 
228
        QString str;
 
229
        Q_UINT8 ch;
 
230
        for( unsigned j=0; j<fields.at(i)->length; j++ )
 
231
        {  m_stream >> ch; str += QChar(ch); }
 
232
        str.insert( 6, '-' );
 
233
        str.insert( 4, '-' );
 
234
        result.append( str );
 
235
      } break;
 
236
 
 
237
      // Unknown/Unimplemented
 
238
      case DBaseField::Unknown:
 
239
      case DBaseField::Memo:
 
240
      default:
 
241
        result.append( "" ); // unknown
 
242
        break;
 
243
    }
 
244
 
 
245
  return result;
 
246
}
 
247
 
 
248
void DBase::close()
 
249
{
 
250
  if( m_file.isOpen() ) m_file.close();
 
251
}