summaryrefslogtreecommitdiffstats
path: root/kfile-plugins/dvi/kfile_dvi.cpp
blob: b449ad1e1bcf98c57c87280c60816f9caf4706ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/* This file is part of the KDE project
 * Copyright (C) 2002 Matthias Witzgall <witzi@gmx.net>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation version 2.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */


/* further informations about the dvi file format could be downloaded from: http://www.rpi.edu/~sofkam/DVI/archive/standards/dvistd0.dvi */

#include "kfile_dvi.h"

#include <kgenericfactory.h>
#include <kdebug.h>
#include <klocale.h>
#include <kfilemetainfo.h>

#include <tqstring.h>
#include <tqvariant.h>
#include <tqdatetime.h>
#include <tqfile.h>
#include <tqfileinfo.h>
#include <tqregexp.h>


// preprocessormacro K_EXPORT_COMPONENT_FACTORY loads shared library 'kfile_dvi.so' dynamic if necessary
typedef KGenericFactory<KDviPlugin> DviFactory;
K_EXPORT_COMPONENT_FACTORY(kfile_dvi, DviFactory("kfile_dvi"))

KDviPlugin::KDviPlugin (TQObject * parent, const char * name, const TQStringList & preferredItems)
  : KFilePlugin(parent, name, preferredItems)
{
  kdDebug(7034) << "dvi plugin" << endl;
  
  // set up our mime type
  KFileMimeTypeInfo * info = this->addMimeTypeInfo("application/x-dvi");
  
  
  KFileMimeTypeInfo::GroupInfo * group = this->addGroupInfo(info, "General", "General");
  
  this->addItemInfo(group, "3_Created", i18n("Created"), TQVariant::String);
  this->addItemInfo(group, "6_Comment", i18n("Comment"), TQVariant::String);
  this->addItemInfo(group, "7_Pages", i18n("Pages"), TQVariant::UInt);
}

bool KDviPlugin::readInfo (KFileMetaInfo & info, uint /* what (unused in this plugin) */)
{
  if ( info.path().isEmpty() )
    return false;
  KFileMetaInfoGroup GeneralGroup = appendGroup(info, "General");
  TQFile f(info.path());
  TQFileInfo f_info;
  TQ_UINT16 bytes_to_read;
  TQ_UINT8 comment_length;
  TQString comment;
  TQ_UINT16 pages;
  TQ_UINT8 buffer[270]; // buffer for reading data; no data is read with more than 270 bytes
  TQ_UINT32 ptr;
  int i; // running index
  
  // open file and try to get the comment
  f.open(IO_ReadOnly);
  
  if ( f.isOpen() == false ){
    kdDebug(7034) << "cannot open file" << endl;
    return false;
  }
  
  f_info.setFile(f); // create fileinfoobject
  bytes_to_read = TQMIN(f_info.size(), 270); // check, if the file size is smaller than 270 bytes
  // (if the comment is as large as possible, we don't have to
  // read more than 270 bytes)
  
  if ( f.readBlock((char *)buffer, bytes_to_read) != bytes_to_read ){ // cast to (char *) is necessary
    kdDebug(7034) << "read error (1)" << endl;
    return false;
  }
  
  if ( (buffer[0] != 247)  ||  (buffer[1] != 2) ){
    // magic numbers are not right
    kdDebug(7034) << "wrong file format" << endl;;
    return false;
  }
  
  comment_length = buffer[14]; // set up length of comment
  comment.setLength(comment_length); // used to avoid permanent reallocation when extracting the comment from buffer
  
  for ( i = 15; i <= 14+comment_length; ++i ) // extract comment from buffer
    comment[i-15] = (char)buffer[i];

  appendItem(GeneralGroup, "6_Comment", comment.simplifyWhiteSpace() );
  
  // comment is ok, now get total number of pages
  f.at( f.size() - 13);
  if ( f.readBlock((char *)buffer, 13) != 13 ){
    kdDebug(7034) << "read error (2)" << endl;
    return false;
  }
  
  i = 12; // reset running index i
  while ( buffer[i] == 223 ){ --i; } // skip all trailing bytes
  
  if ( (buffer[i] != 2) || (i > 8) || (i < 5) ){
    kdDebug(7034) << "wrong file formatx" << endl;
    return false;
  }
  
  // now we know the position of the pointer to the beginning of the postamble and we can read it
  ptr = buffer[i-4];
  ptr = (ptr << 8) | buffer[i-3];
  ptr = (ptr << 8) | buffer[i-2];
  ptr = (ptr << 8) | buffer[i-1];
  
  // bytes for total number of pages have a offset of 27 to the beginning of the postamble
  f.at(ptr + 27);
  
  // now read total number of pages from file
  if ( f.readBlock((char *)buffer, 2) != 2 ){
    kdDebug(7034) << "read error (3)" << endl;
    return false;
  }
  pages = buffer[0];
  pages = (pages << 8) | buffer[1];
  
  appendItem(GeneralGroup, "7_Pages", TQVariant(pages) );
  
  f.close();
  
  // now get and set up some basic informations about the file (same informations would be displayed, if there is no dvi-plugin)
  appendItem(GeneralGroup, "1_Type", TQVariant( i18n("TeX Device Independent file") ) ); // set up type of file
  
  appendItem(GeneralGroup, "4_Modified", TQVariant(f_info.lastModified().toString("yyyy-MM-dd hh:mm")) );
  // ISO 8601 date format (without seconds)
  
  return true;
}

#include "kfile_dvi.moc"