~ubuntu-branches/debian/stretch/openbabel/stretch

« back to all changes in this revision

Viewing changes to src/formats/chemdrawcdx.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Banck
  • Date: 2008-07-22 23:54:58 UTC
  • mfrom: (3.1.10 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080722235458-3o606czluviz4akx
Tags: 2.2.0-2
* Upload to unstable.
* debian/control: Updated descriptions.
* debian/patches/gauss_cube_format.patch: New patch, makes the 
  gaussian cube format available again.
* debian/rules (DEB_DH_MAKESHLIBS_ARGS_libopenbabel3): Removed.
* debian/rules (DEB_CONFIGURE_EXTRA_FLAGS): Likewise.
* debian/libopenbabel3.install: Adjust formats directory to single 
  version hierarchy.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**********************************************************************
 
2
Copyright (C) 2006 by Fredrik Wallner
 
3
Some portions Copyright (C) 2006-2007 by Geoffrey Hutchsion
 
4
Some portions Copyright (C) 2004 by Chris Morley
 
5
 
 
6
This program is free software; you can redistribute it and/or modify
 
7
it under the terms of the GNU General Public License as published by
 
8
the Free Software Foundation version 2 of the License.
 
9
 
 
10
This program 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
 
13
GNU General Public License for more details.
 
14
***********************************************************************/
 
15
 
 
16
#include <openbabel/babelconfig.h>
 
17
#include <openbabel/obmolecformat.h>
 
18
#include <openbabel/reaction.h>
 
19
#include "chemdrawcdx.h"
 
20
 
 
21
#include <iostream>
 
22
#include <fstream>
 
23
#include <map>
 
24
#include <list>
 
25
 
 
26
//#define debug
 
27
 
 
28
static inline unsigned short bswap_16(unsigned short x) {
 
29
  return (x>>8) | (x<<8);
 
30
}
 
31
 
 
32
static inline unsigned int bswap_32(unsigned int x) {
 
33
  return (bswap_16(x&0xffff)<<16) | (bswap_16(x>>16));
 
34
}
 
35
 
 
36
static inline unsigned long long bswap_64(unsigned long long x) {
 
37
  return (((unsigned long long)bswap_32(x&0xffffffffull))<<32) | (bswap_32(x>>32));
 
38
}
 
39
 
 
40
// Macs -- need to use Apple macros to deal with Universal binaries correctly
 
41
#ifdef __APPLE__
 
42
#include <machine/endian.h>
 
43
#if BYTE_ORDER == BIG_ENDIAN
 
44
#    define READ_INT16(stream,data) \
 
45
(stream).read ((char*)&data, sizeof(data)); \
 
46
data = bswap_16 (data);
 
47
#    define READ_INT32(stream,data) \
 
48
(stream).read ((char*)&data, sizeof(data)); \
 
49
data = bswap_32 (data);
 
50
#else BYTE_ORDER == LITTLE_ENDIAN
 
51
#    define READ_INT16(stream,data) \
 
52
(stream).read ((char*)&data, sizeof(data));
 
53
#    define READ_INT32(stream,data) \
 
54
(stream).read ((char*)&data, sizeof(data));
 
55
#endif
 
56
#else
 
57
 
 
58
// Non-Apple systems
 
59
// defined in babelconfig.h by autoconf (portable to Solaris, BSD, Linux)
 
60
#ifdef WORDS_BIGENDIAN
 
61
#    define READ_INT16(stream,data) \
 
62
(stream).read ((char*)&data, sizeof(data)); \
 
63
data = bswap_16 (data);
 
64
#    define READ_INT32(stream,data) \
 
65
(stream).read ((char*)&data, sizeof(data)); \
 
66
data = bswap_32 (data);
 
67
#else
 
68
#    define READ_INT16(stream,data) \
 
69
(stream).read ((char*)&data, sizeof(data));
 
70
#    define READ_INT32(stream,data) \
 
71
(stream).read ((char*)&data, sizeof(data));
 
72
#endif
 
73
// end endian / bigendian issues (on non-Mac systems)
 
74
#endif 
 
75
// end Apple/non-Apple systems
 
76
 
 
77
using namespace std;
 
78
namespace OpenBabel
 
79
{
 
80
 
 
81
  class ChemDrawBinaryFormat : public OBMoleculeFormat
 
82
  {
 
83
  public:
 
84
    //Register this format type ID in the constructor
 
85
    ChemDrawBinaryFormat()
 
86
    {
 
87
      OBConversion::RegisterFormat("cdx",this, "chemical/x-cdx");
 
88
    }
 
89
 
 
90
    virtual const char* Description() //required
 
91
    {
 
92
      return
 
93
        "ChemDraw binary format\n"
 
94
        "Read only.\n";
 
95
    };
 
96
 
 
97
    //Optional URL where the file format is specified
 
98
    virtual const char* SpecificationURL()
 
99
    {return "http://www.cambridgesoft.com/services/documentation/sdk/chemdraw/cdx/IntroCDX.htm";};
 
100
 
 
101
    virtual const char* GetMIMEType() 
 
102
    { return "chemical/x-cdx"; };
 
103
 
 
104
    /* Flags() can return be any of the following combined by | 
 
105
       or be omitted if none apply
 
106
       NOTREADABLE  READONEONLY  NOTWRITABLE  WRITEONEONLY */
 
107
    virtual unsigned int Flags()
 
108
    {
 
109
      return READBINARY|NOTWRITABLE;
 
110
    };
 
111
 
 
112
    ////////////////////////////////////////////////////
 
113
    /// Declarations for the "API" interface functions. Definitions are below
 
114
    virtual bool ReadMolecule(OBBase* pOb, OBConversion* pConv);
 
115
    OBBase* ReadObject(OBConversion* pConv);
 
116
    //  virtual bool WriteMolecule(OBBase* pOb, OBConversion* pConv);
 
117
  private:
 
118
    struct cdBond
 
119
    {
 
120
      UINT32    begin;
 
121
      UINT32    end;
 
122
      int       order;
 
123
      int stereo;
 
124
 
 
125
                        cdBond() {}
 
126
                        cdBond(UINT32 bgn, UINT32 e, int ord, int st = 0) : begin(bgn), end (e), order(ord), stereo(st) {}
 
127
                        ~cdBond() {}
 
128
    };
 
129
 
 
130
 
 
131
    int readFragment(istream *ifs, UINT32 fragmentId, 
 
132
                     OBMol *pmol, map<UINT32, int> &atoms, list<cdBond> &bonds);
 
133
    int readNode(istream *ifs, UINT32 nodeId, OBMol *pmol, 
 
134
                 map<UINT32, int> &atoms, list<cdBond> &bonds, 
 
135
                 UINT32 fragmentID);
 
136
    int readBond(istream *ifs, UINT32 nodeId, OBMol *pmol, list<cdBond> &bonds);
 
137
    int readGeneric(istream *ifs, UINT32 objId);
 
138
    const char* getName(istream *ifs, UINT32 size);
 
139
 
 
140
  };  
 
141
        ////////////////////////////////////////////////////
 
142
 
 
143
  //Make an instance of the format class
 
144
  ChemDrawBinaryFormat theChemDrawBinaryFormat;
 
145
 
 
146
  /////////////////////////////////////////////////////////////////
 
147
  bool ChemDrawBinaryFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
 
148
  {
 
149
    OBMol* pmol = pOb->CastAndClear<OBMol>();
 
150
    if(pmol==NULL)
 
151
      return false;
 
152
 
 
153
    istream& ifs = *pConv->GetInStream();
 
154
    char buffer[BUFF_SIZE];
 
155
    char errorMsg[BUFF_SIZE];
 
156
    UINT16 tag;
 
157
    UINT16 size;
 
158
    UINT32 id;
 
159
    map<UINT32, int> atoms;
 
160
    list<cdBond> bonds;
 
161
    list<cdBond>::const_iterator bondsIter;
 
162
    cdBond prevBond;
 
163
    cdBond oneBond;
 
164
    //    OBPairData *pd;
 
165
    int iInt=0, depth=1;
 
166
 
 
167
    if (!ifs.good() || ifs.peek() == EOF)
 
168
      return false;
 
169
 
 
170
    pmol->BeginModify();
 
171
 
 
172
    pmol->SetTitle(pConv->GetTitle());
 
173
        
 
174
    if((int)ifs.tellg() == 0)   // Beginning of file
 
175
      {
 
176
        ifs.read(buffer,kCDX_HeaderStringLen);
 
177
        if(strncmp(buffer, kCDX_HeaderString, kCDX_HeaderStringLen) == 0)  // File header
 
178
          {
 
179
            ifs.seekg (kCDX_HeaderLength - kCDX_HeaderStringLen, ios_base::cur);        // Discard rest of header.
 
180
          }
 
181
        else
 
182
          {
 
183
            cout << "Invalid file, no ChemDraw Header" << endl; // No header, error.
 
184
            ifs.seekg(0, ios_base::end);
 
185
            return false;
 
186
          }
 
187
      }
 
188
    while(ifs.good())
 
189
      {
 
190
        READ_INT16 (ifs, tag);
 
191
        if(tag & kCDXTag_Object)        // Object
 
192
          {
 
193
            READ_INT32 (ifs, id);
 
194
            snprintf(errorMsg, BUFF_SIZE, "Object ID: %08X in root has type: %04X\n", id, tag);
 
195
            obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
196
 
 
197
            if(tag == kCDXObj_Fragment)
 
198
              {
 
199
                if(readFragment(&ifs, id, pmol, atoms, bonds) != 0)
 
200
                  {
 
201
                    obErrorLog.ThrowError(__FUNCTION__, "Error reading fragment", obWarning);
 
202
                    return false;
 
203
                  }
 
204
                iInt = 0;
 
205
                prevBond = cdBond(0,0,0);
 
206
                for (bondsIter=bonds.begin(); bondsIter != bonds.end(); bondsIter++)
 
207
                  {
 
208
                    // printf("Bond between %08X (%d) and %08x (%d)\n", bondsIter->begin, atoms[bondsIter->begin], bondsIter->end, atoms[bondsIter->end]);
 
209
                    if(atoms[bondsIter->begin] == -1)
 
210
                      {
 
211
                        //                                              printf("Bond starts at a non-atom\n");
 
212
                        if(atoms[bondsIter->end] == -1)
 
213
                          {
 
214
                            //                                                  printf("Bond between two non-atoms pushed back\n");
 
215
                            if((prevBond.begin == bondsIter->begin) && (prevBond.end == bondsIter->end))
 
216
                              {
 
217
                                obErrorLog.ThrowError(__FUNCTION__, "Can't assign all bonds!", obDebug);
 
218
                                break;
 
219
                              } 
 
220
                            bonds.push_back(*bondsIter);
 
221
                          }
 
222
                        else
 
223
                          atoms[bondsIter->begin] = atoms[bondsIter->end];
 
224
                      }
 
225
                    else if(atoms[bondsIter->end] == -1)
 
226
                      atoms[bondsIter->end] = atoms[bondsIter->begin];
 
227
                    else
 
228
                      {
 
229
                        int flags = 0;
 
230
                        switch (bondsIter->stereo)
 
231
                          {
 
232
                          case kCDXBondDisplay_WedgedHashBegin:
 
233
                          case kCDXBondDisplay_WedgeEnd:
 
234
                            flags = OB_HASH_BOND;
 
235
                            break;
 
236
                          case kCDXBondDisplay_WedgedHashEnd:
 
237
                          case kCDXBondDisplay_WedgeBegin:
 
238
                            flags = OB_WEDGE_BOND;
 
239
                            break;
 
240
                          default:;
 
241
                          }
 
242
                        pmol->AddBond(atoms[bondsIter->begin], atoms[bondsIter->end], bondsIter->order, flags);
 
243
                      }
 
244
                    prevBond = *bondsIter;
 
245
                  }
 
246
                break;
 
247
              }
 
248
            else if ((tag == kCDXObj_Graphic) || (tag == kCDXObj_Text)
 
249
                     || (tag == kCDXObj_BracketedGroup) 
 
250
                     || (tag == kCDXObj_BracketAttachment) 
 
251
                     || (tag == kCDXObj_CrossingBond) 
 
252
                     || (tag == kCDXObj_ReactionStep) 
 
253
                     || (tag == kCDXObj_Curve) 
 
254
                     || (tag == kCDXObj_EmbeddedObject)) 
 
255
              { // Objects that can be ignored
 
256
                readGeneric(&ifs, id);
 
257
              }
 
258
            else if((tag == kCDXObj_Page) || ( tag == kCDXObj_Group))
 
259
              { // Objects where the header can be ignored
 
260
              }
 
261
            else
 
262
              {
 
263
                depth++;
 
264
                snprintf(errorMsg, BUFF_SIZE, "New object in root, type %04X\n", tag);
 
265
                obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
266
              }
 
267
          }
 
268
        else if(tag == 0)       // End of object
 
269
          {
 
270
            if(depth > 1)
 
271
              {
 
272
                obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
273
                depth--;
 
274
              }
 
275
          }
 
276
        else    // Property
 
277
          {
 
278
            READ_INT16 (ifs ,size);
 
279
            switch(tag)
 
280
              {
 
281
              case kCDXProp_Name: 
 
282
                pmol->SetTitle(getName(&ifs, size)); 
 
283
                break;
 
284
              case kCDXProp_FontTable: 
 
285
              case kCDXProp_BoundingBox:
 
286
              case kCDXProp_Window_Position:
 
287
              case kCDXProp_Window_Size:
 
288
              case kCDXProp_Atom_ShowQuery:
 
289
              case kCDXProp_Atom_ShowStereo:
 
290
              case kCDXProp_Atom_ShowAtomNumber:
 
291
              case kCDXProp_Bond_ShowQuery:
 
292
              case kCDXProp_Bond_ShowStereo:
 
293
              case kCDXProp_MacPrintInfo:
 
294
              case kCDXProp_DrawingSpaceType:
 
295
              case kCDXProp_Width:
 
296
              case kCDXProp_Height:
 
297
              case kCDXProp_PageOverlap:
 
298
              case kCDXProp_Magnification:
 
299
              case kCDXProp_ChainAngle:
 
300
              case kCDXProp_BondSpacing:
 
301
              case kCDXProp_BondSpacingAbs:
 
302
              case kCDXProp_BondLength:
 
303
              case kCDXProp_BoldWidth:
 
304
              case kCDXProp_LineWidth:
 
305
              case kCDXProp_MarginWidth:
 
306
              case kCDXProp_HashSpacing:
 
307
              case kCDXProp_LabelStyle:
 
308
              case kCDXProp_CaptionStyle:
 
309
              case kCDXProp_CaptionJustification:
 
310
              case kCDXProp_LabelJustification:
 
311
              case kCDXProp_FractionalWidths:
 
312
              case kCDXProp_LabelLineHeight:
 
313
              case kCDXProp_CaptionLineHeight:
 
314
              case kCDXProp_Window_IsZoomed:
 
315
              case kCDXProp_WidthPages:
 
316
              case kCDXProp_HeightPages:
 
317
              case kCDXProp_HeaderPosition:
 
318
              case kCDXProp_FooterPosition:
 
319
              case kCDXProp_PrintTrimMarks:
 
320
              case kCDXProp_PrintMargins:
 
321
              case kCDXProp_ColorTable:
 
322
              case kCDXProp_CreationProgram:
 
323
              case kCDXProp_Group_Integral:
 
324
                ifs.seekg(size, ios_base::cur); 
 
325
                break;
 
326
              default: // some unknown tag
 
327
                ifs.seekg(size, ios_base::cur); 
 
328
                snprintf(errorMsg, BUFF_SIZE, "Root Tag: %04X\tSize: %04X\n", tag, size); 
 
329
                obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
330
                break;
 
331
              }
 
332
          }
 
333
      }
 
334
 
 
335
    pmol->SetDimension(2);
 
336
    pmol->EndModify();
 
337
 
 
338
    return true;
 
339
  }
 
340
 
 
341
  OBBase* ChemDrawBinaryFormat::ReadObject(OBConversion* pConv)
 
342
  {
 
343
    istream& ifs = *pConv->GetInStream();
 
344
    char buffer[BUFF_SIZE];
 
345
    char errorMsg[BUFF_SIZE];
 
346
    UINT16 tag;
 
347
    UINT16 size;
 
348
    UINT32 id;
 
349
    map<UINT32, int> atoms;
 
350
    list<cdBond> bonds;
 
351
    list<cdBond>::const_iterator bondsIter;
 
352
    cdBond prevBond;
 
353
    cdBond oneBond;
 
354
    //    OBPairData *pd;
 
355
    int iInt=0, depth=1;
 
356
        
 
357
    if((int)ifs.tellg() == 0)   // Beginning of file
 
358
      {
 
359
        ifs.read(buffer,kCDX_HeaderStringLen);
 
360
        if(strncmp(buffer, kCDX_HeaderString, kCDX_HeaderStringLen) == 0)  // File header
 
361
          {
 
362
            ifs.seekg (kCDX_HeaderLength - kCDX_HeaderStringLen, ios_base::cur);        // Discard rest of header.
 
363
          }
 
364
        else
 
365
          {
 
366
            cout << "Invalid file, no ChemDraw Header" << endl; // No header, error.
 
367
            ifs.seekg(0, ios_base::end);
 
368
            return false;
 
369
          }
 
370
      }
 
371
    while(ifs.good())
 
372
      {
 
373
        READ_INT16 (ifs, tag);
 
374
        if(tag & kCDXTag_Object)        // Object
 
375
          {
 
376
            READ_INT32 (ifs, id);
 
377
            snprintf(errorMsg, BUFF_SIZE, "Object ID: %08X in root has type: %04X\n", id, tag);
 
378
            obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
379
 
 
380
            if(tag == kCDXObj_Fragment)
 
381
              {
 
382
                OBMol *pmol = new OBMol();
 
383
                if(pmol==NULL)
 
384
                  {
 
385
                        return NULL;
 
386
                  }
 
387
 
 
388
                pmol->BeginModify();
 
389
 
 
390
                    pmol->SetTitle(pConv->GetTitle());
 
391
                if(readFragment(&ifs, id, pmol, atoms, bonds) != 0)
 
392
                  {
 
393
                    obErrorLog.ThrowError(__FUNCTION__, "Error reading fragment", obWarning);
 
394
                    delete pmol;
 
395
                    return NULL;
 
396
                  }
 
397
                iInt = 0;
 
398
                prevBond = cdBond(0,0,0);
 
399
                for (bondsIter=bonds.begin(); bondsIter != bonds.end(); bondsIter++)
 
400
                  {
 
401
                    // printf("Bond between %08X (%d) and %08x (%d)\n", bondsIter->begin, atoms[bondsIter->begin], bondsIter->end, atoms[bondsIter->end]);
 
402
                    if(atoms[bondsIter->begin] == -1)
 
403
                      {
 
404
                        //                                              printf("Bond starts at a non-atom\n");
 
405
                        if(atoms[bondsIter->end] == -1)
 
406
                          {
 
407
                            //                                                  printf("Bond between two non-atoms pushed back\n");
 
408
                            if((prevBond.begin == bondsIter->begin) && (prevBond.end == bondsIter->end))
 
409
                              {
 
410
                                obErrorLog.ThrowError(__FUNCTION__, "Can't assign all bonds!", obDebug);
 
411
                                break;
 
412
                              } 
 
413
                            bonds.push_back(*bondsIter);
 
414
                          }
 
415
                        else
 
416
                          atoms[bondsIter->begin] = atoms[bondsIter->end];
 
417
                      }
 
418
                    else if(atoms[bondsIter->end] == -1)
 
419
                      atoms[bondsIter->end] = atoms[bondsIter->begin];
 
420
                    else
 
421
                      {
 
422
                        int flags = 0;
 
423
                        switch (bondsIter->stereo)
 
424
                          {
 
425
                          case kCDXBondDisplay_WedgedHashBegin:
 
426
                          case kCDXBondDisplay_WedgeEnd:
 
427
                            flags = OB_HASH_BOND;
 
428
                            break;
 
429
                          case kCDXBondDisplay_WedgedHashEnd:
 
430
                          case kCDXBondDisplay_WedgeBegin:
 
431
                            flags = OB_WEDGE_BOND;
 
432
                            break;
 
433
                          default:;
 
434
                          }
 
435
                        pmol->AddBond(atoms[bondsIter->begin], atoms[bondsIter->end], bondsIter->order, flags);
 
436
                      }
 
437
                    prevBond = *bondsIter;
 
438
                  }
 
439
                pmol->SetDimension(2);
 
440
                pmol->EndModify();
 
441
                return pmol;
 
442
              }
 
443
            else if (tag == kCDXObj_ReactionScheme)
 
444
              {
 
445
                readGeneric(&ifs, id);
 
446
puts("found a reaction");
 
447
                return new OBReaction();
 
448
              }
 
449
           else if ((tag == kCDXObj_Graphic) || (tag == kCDXObj_Text)
 
450
                     || (tag == kCDXObj_BracketedGroup) 
 
451
                     || (tag == kCDXObj_BracketAttachment) 
 
452
                     || (tag == kCDXObj_CrossingBond) 
 
453
                     || (tag == kCDXObj_Curve) 
 
454
                     || (tag == kCDXObj_EmbeddedObject)) 
 
455
              { // Objects that can be ignored
 
456
                readGeneric(&ifs, id);
 
457
              }
 
458
            else if((tag == kCDXObj_Page) || ( tag == kCDXObj_Group))
 
459
              { // Objects where the header can be ignored
 
460
              }
 
461
            else
 
462
              {
 
463
                depth++;
 
464
                snprintf(errorMsg, BUFF_SIZE, "New object in root, type %04X\n", tag);
 
465
                obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
466
              }
 
467
          }
 
468
        else if(tag == 0)       // End of object
 
469
          {
 
470
            if(depth > 1)
 
471
              {
 
472
                obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
473
                depth--;
 
474
              }
 
475
          }
 
476
        else    // Property
 
477
          {
 
478
            READ_INT16 (ifs ,size);
 
479
            switch(tag)
 
480
              {
 
481
              case kCDXProp_Name:
 
482
puts("found name");
 
483
                /*pmol->SetTitle(*/puts(getName(&ifs, size));//); 
 
484
                break;
 
485
              case kCDXProp_FontTable: 
 
486
              case kCDXProp_BoundingBox:
 
487
              case kCDXProp_Window_Position:
 
488
              case kCDXProp_Window_Size:
 
489
              case kCDXProp_Atom_ShowQuery:
 
490
              case kCDXProp_Atom_ShowStereo:
 
491
              case kCDXProp_Atom_ShowAtomNumber:
 
492
              case kCDXProp_Bond_ShowQuery:
 
493
              case kCDXProp_Bond_ShowStereo:
 
494
              case kCDXProp_MacPrintInfo:
 
495
              case kCDXProp_DrawingSpaceType:
 
496
              case kCDXProp_Width:
 
497
              case kCDXProp_Height:
 
498
              case kCDXProp_PageOverlap:
 
499
              case kCDXProp_Magnification:
 
500
              case kCDXProp_ChainAngle:
 
501
              case kCDXProp_BondSpacing:
 
502
              case kCDXProp_BondSpacingAbs:
 
503
              case kCDXProp_BondLength:
 
504
              case kCDXProp_BoldWidth:
 
505
              case kCDXProp_LineWidth:
 
506
              case kCDXProp_MarginWidth:
 
507
              case kCDXProp_HashSpacing:
 
508
              case kCDXProp_LabelStyle:
 
509
              case kCDXProp_CaptionStyle:
 
510
              case kCDXProp_CaptionJustification:
 
511
              case kCDXProp_LabelJustification:
 
512
              case kCDXProp_FractionalWidths:
 
513
              case kCDXProp_LabelLineHeight:
 
514
              case kCDXProp_CaptionLineHeight:
 
515
              case kCDXProp_Window_IsZoomed:
 
516
              case kCDXProp_WidthPages:
 
517
              case kCDXProp_HeightPages:
 
518
              case kCDXProp_HeaderPosition:
 
519
              case kCDXProp_FooterPosition:
 
520
              case kCDXProp_PrintTrimMarks:
 
521
              case kCDXProp_PrintMargins:
 
522
              case kCDXProp_ColorTable:
 
523
              case kCDXProp_CreationProgram:
 
524
              case kCDXProp_Group_Integral:
 
525
                ifs.seekg(size, ios_base::cur); 
 
526
                break;
 
527
              default: // some unknown tag
 
528
                ifs.seekg(size, ios_base::cur); 
 
529
                snprintf(errorMsg, BUFF_SIZE, "Root Tag: %04X\tSize: %04X\n", tag, size); 
 
530
                obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
531
                break;
 
532
              }
 
533
          }
 
534
      }
 
535
 
 
536
    return NULL;
 
537
  }
 
538
 
 
539
  const char* ChemDrawBinaryFormat::getName(istream *ifs, UINT32 size)
 
540
  {
 
541
    char *buff;
 
542
    UINT16 temp;
 
543
    UINT32 skipsize;
 
544
                
 
545
    //  buff = new char[size];
 
546
    READ_INT16 ((*ifs), temp);
 
547
    if(temp == 0)
 
548
      {
 
549
        buff = new char[size-1];
 
550
        ifs->read(buff, size-2);
 
551
        buff[size-2] = 0;
 
552
      }
 
553
    else
 
554
      {
 
555
        skipsize = temp * 10;
 
556
        ifs->seekg(skipsize, ios_base::cur);
 
557
        buff = new char[size-skipsize-1];
 
558
        ifs->read(buff, size-skipsize-2);
 
559
        buff[size-skipsize-2] = 0;
 
560
      }
 
561
    return buff;
 
562
  }
 
563
 
 
564
 
 
565
  int get2DPosition(istream *ifs, UINT32 size, INT32 &x, INT32 &y)
 
566
  {
 
567
    if(size != 8) {
 
568
      return -1; }
 
569
 
 
570
    READ_INT32 (*ifs, y);
 
571
    READ_INT32 (*ifs, x);
 
572
    
 
573
    //  printf("2D coordinates - x: %d, y: %d\n", x, y);
 
574
    return 0;
 
575
  }
 
576
 
 
577
  UINT32 getBondStart(istream *ifs, UINT32 size)
 
578
  {
 
579
    UINT32 atomID;
 
580
        
 
581
    if(size != 4)
 
582
      return -1;
 
583
        
 
584
    READ_INT32 (*ifs, atomID);
 
585
    //  printf("Bond starts at atom nr: %08X\n", atomID);
 
586
    return atomID;
 
587
  }
 
588
 
 
589
  UINT32 getBondEnd(istream *ifs, UINT32 size)
 
590
  {
 
591
    UINT32 atomID;
 
592
        
 
593
    if(size != 4)
 
594
      return -1;
 
595
        
 
596
    READ_INT32 (*ifs, atomID);
 
597
    //  printf("Bond ends at atom nr: %08X\n", atomID);
 
598
    return atomID;
 
599
  }
 
600
 
 
601
  int getBondOrder(istream *ifs, UINT32 size)
 
602
  {
 
603
    UINT16 order;
 
604
        
 
605
    if(size != 2)
 
606
      return -1;
 
607
        
 
608
    READ_INT16 (*ifs, order);
 
609
    //  printf("Bond order is: %d\n", order);
 
610
    return (int) order;
 
611
  }
 
612
 
 
613
  int getBondDisplay(istream *ifs, UINT32 size)
 
614
  {
 
615
    UINT16 stereo;
 
616
        
 
617
    if(size != 2)
 
618
      return -1;
 
619
        
 
620
    READ_INT16 (*ifs, stereo);
 
621
    //    printf("Bond stereo is: %d\n", stereo);
 
622
    return (int) stereo;
 
623
  }
 
624
 
 
625
  int getNodeType(istream *ifs, UINT32 size)
 
626
  {
 
627
    UINT16 nodeType;
 
628
        
 
629
    if(size != 2)
 
630
      return -1;
 
631
        
 
632
    READ_INT16 (*ifs, nodeType);
 
633
    //  printf("Node type is: %d\n", nodeType);
 
634
    return (int) nodeType;
 
635
  }
 
636
 
 
637
  int getElement(istream *ifs, UINT32 size, OBAtom &atom)
 
638
  {
 
639
    UINT16 element;
 
640
        
 
641
    if(size != 2)
 
642
      return -1;
 
643
        
 
644
    READ_INT16 (*ifs, element);
 
645
    atom.SetAtomicNum(element);
 
646
    //  printf("Atomic number: %d\n", element);
 
647
    return 0;
 
648
  }
 
649
 
 
650
  int getIsotope(istream *ifs, UINT32 size, OBAtom &atom)
 
651
  {
 
652
    UINT16 isotope;
 
653
        
 
654
    if(size != 2)
 
655
      return -1;
 
656
        
 
657
    READ_INT16 (*ifs, isotope);
 
658
    atom.SetIsotope(isotope);
 
659
    return 0;
 
660
  }
 
661
 
 
662
  int getRadical(istream *ifs, UINT32 size, OBAtom &atom)
 
663
  {
 
664
    int radical;
 
665
 
 
666
    ifs->read((char *)&radical, size);
 
667
#if __BYTE_ORDER == __BIG_ENDIAN
 
668
    radical = radical >> 24;
 
669
#endif
 
670
        
 
671
    //    cout << " Atomic radical " << size << " " << radical << endl;
 
672
    switch (radical)
 
673
      {
 
674
      case 2:
 
675
        atom.SetSpinMultiplicity(2);
 
676
        break;
 
677
      case 3:
 
678
        atom.SetSpinMultiplicity(3);
 
679
        break;
 
680
      case 1:
 
681
      case 0:
 
682
      default:
 
683
        break; // all singlets (current no way in OB to set diradical singlet)
 
684
      }
 
685
 
 
686
    return 0;
 
687
  }
 
688
 
 
689
  int getCharge(istream *ifs, UINT32 size)
 
690
  {
 
691
    int charge;
 
692
        
 
693
    if(size == 4)               // Bug in ChemDraw 8.0, see http://www.cambridgesoft.com/services/documentation/sdk/chemdraw/cdx/properties/Atom_Charge.htm
 
694
      {
 
695
        READ_INT32 (*ifs, charge);
 
696
      }
 
697
    else
 
698
      if(size == 1)
 
699
        {
 
700
          ifs->read((char *)&charge, size);
 
701
#if __BYTE_ORDER == __BIG_ENDIAN
 
702
          charge = charge >> 24;
 
703
#endif
 
704
        }
 
705
      else
 
706
        return 0;
 
707
        
 
708
    //  printf("Charge: %d\n",charge);
 
709
    return charge;
 
710
  }
 
711
 
 
712
  int getAtomHydrogens(istream *ifs, UINT32 size)
 
713
  {
 
714
    UINT16 hydrogens;
 
715
        
 
716
    if(size != 2)
 
717
      return -1;
 
718
        
 
719
    READ_INT16 (*ifs, hydrogens);
 
720
    //  printf("Number of explicit hydrogens: %d\n", hydrogens);
 
721
    return 0;
 
722
  }
 
723
 
 
724
  int readText(istream *ifs, UINT32 textId)
 
725
  {
 
726
    char errorMsg[BUFF_SIZE];
 
727
    UINT16 tag;
 
728
    UINT16 size;
 
729
    UINT32 id;
 
730
    int depth = 1;
 
731
 
 
732
    while(ifs->good())
 
733
      {
 
734
        READ_INT16 (*ifs, tag);
 
735
        if(tag & kCDXTag_Object)        // Object
 
736
          {
 
737
            depth++;
 
738
            READ_INT32 (*ifs, id);
 
739
            //                  printf("Object ID (in text-object %08X): %08X has type: %04X\n", textId, id, tag);
 
740
            snprintf(errorMsg, BUFF_SIZE, "New object in text, type %04X\n", tag);
 
741
            obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
742
          }
 
743
        else if(tag == 0)       // End of object
 
744
          {
 
745
            depth--;
 
746
            //                  printf("End of textobject %08X\n", textId);
 
747
          }
 
748
        else    // Property
 
749
          {
 
750
            READ_INT16 (*ifs, size);
 
751
            //                  printf("Tag: %04X\tSize: %04X\n", tag, size);
 
752
            switch(tag)
 
753
              {
 
754
              default: ifs->seekg(size, ios_base::cur); break;
 
755
              }
 
756
          }
 
757
        if(depth < 1)
 
758
          return 0;
 
759
      }
 
760
    return -1;
 
761
  }
 
762
 
 
763
                
 
764
  int ChemDrawBinaryFormat::readNode(istream *ifs, UINT32 nodeId,
 
765
                                     OBMol *pmol, map<UINT32, int> &atoms,
 
766
                                     list<cdBond> &bonds, UINT32 fragmentID)
 
767
  {
 
768
    char errorMsg[BUFF_SIZE];
 
769
    UINT16 tag;
 
770
    UINT16 size;
 
771
    UINT32 id;
 
772
    int depth = 1;
 
773
    OBAtom atom;
 
774
    OBAtom *atom2;
 
775
    //  OBPairData *data = new OBPairData;   // To hold ChemDraw's indexnr
 
776
    INT32 x, y;
 
777
    int nodeType = 1;
 
778
    //    char strNodeId[20];
 
779
 
 
780
    atom.SetAtomicNum(6);
 
781
    //  data->SetAttribute("nodeId");
 
782
    //  snprintf(strNodeId, 20, "%d", nodeId);
 
783
    //  data->SetValue(strNodeId);
 
784
    //  atom.SetData(data);     
 
785
    //  if(atom.HasData("nodeId"))
 
786
    //  {
 
787
    //          printf("Adding data to atom - attr: %s\tvalue: %s\n", dynamic_cast<OBPairData *> (atom.GetData("nodeId"))->GetAttribute().c_str(), dynamic_cast<OBPairData *> (atom.GetData("nodeId"))->GetValue().c_str());
 
788
    //  }
 
789
    //  else
 
790
    //          printf("No data added\n");
 
791
                
 
792
    while(ifs->good())
 
793
      {
 
794
        READ_INT16 (*ifs, tag);
 
795
        if(tag & kCDXTag_Object)        // Object
 
796
          {
 
797
            depth++;
 
798
            READ_INT32 (*ifs, id);
 
799
 
 
800
            snprintf(errorMsg, BUFF_SIZE, "Object ID (in node %08X): %08X has type: %04X\n", nodeId, id, tag);
 
801
            obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
802
 
 
803
            if(tag == kCDXObj_Fragment)
 
804
              {
 
805
                if(readFragment(ifs, id, pmol, atoms, bonds) != 0)
 
806
                  {
 
807
                    obErrorLog.ThrowError(__FUNCTION__, "Error reading fragment", obWarning);
 
808
                    return false;
 
809
                  }
 
810
                bonds.push_back(cdBond(nodeId, id, 1));
 
811
                depth--;
 
812
              }
 
813
            else if(tag == kCDXObj_Text)
 
814
              {
 
815
                readText(ifs, id);
 
816
                depth--;
 
817
              }
 
818
            else if((tag == kCDXObj_ObjectTag))
 
819
              { // Objects to ignore
 
820
                readGeneric(ifs, id);
 
821
                depth--;
 
822
              }
 
823
            else if(tag == kCDXObj_Group)
 
824
              { // Objects where we can ignore the header
 
825
              }                 
 
826
            else
 
827
              {
 
828
                snprintf(errorMsg, BUFF_SIZE, "New object in node, type %04X\n", tag);
 
829
                obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
830
              }                 
 
831
          }
 
832
        else if(tag == 0)       // End of object
 
833
          {
 
834
            depth--;
 
835
            //                  printf("End of Object, depth=%d\n", depth);
 
836
          }
 
837
        else    // Property
 
838
          {
 
839
            READ_INT16 (*ifs, size);
 
840
            snprintf(errorMsg, BUFF_SIZE, "Node Tag: %04X\tSize: %04X\n", tag, size);
 
841
            obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
842
 
 
843
            switch(tag)
 
844
              {
 
845
              case kCDXProp_Atom_NumHydrogens:
 
846
                getAtomHydrogens(ifs, size); 
 
847
                break;
 
848
              case kCDXProp_2DPosition:
 
849
                get2DPosition(ifs, size, x, y); 
 
850
                atom.SetVector((double) x / 500000., (double) y / -500000.0, (double) 0.0);
 
851
                break;
 
852
              case kCDXProp_Node_Element:
 
853
                getElement(ifs, size, atom); 
 
854
                break;
 
855
              case kCDXProp_Atom_Charge:
 
856
                atom.SetFormalCharge(getCharge(ifs, size)); 
 
857
                break;
 
858
              case kCDXProp_Node_Type:
 
859
                nodeType = getNodeType(ifs, size); 
 
860
                break;
 
861
              case kCDXProp_Atom_Isotope:
 
862
                getIsotope(ifs, size, atom);
 
863
                break;
 
864
              case kCDXProp_Atom_Radical:
 
865
                getRadical(ifs, size, atom);
 
866
                break;
 
867
              case kCDXProp_Atom_ElementList:
 
868
              case kCDXProp_Atom_AbnormalValence:
 
869
              case kCDXProp_Name:
 
870
              case kCDXProp_IgnoreWarnings:
 
871
              case kCDXProp_ChemicalWarning:
 
872
                ifs->seekg(size, ios_base::cur); 
 
873
                break;  // Maybe use? (any of the above properties)
 
874
              case kCDXProp_MarginWidth:
 
875
              case kCDXProp_ZOrder:
 
876
              case kCDXProp_Atom_GenericNickname:
 
877
              case kCDXProp_Atom_CIPStereochemistry: // maybe use for chirality
 
878
              case kCDXProp_Atom_Geometry:
 
879
              case kCDXProp_Atom_BondOrdering:
 
880
              case kCDXProp_Node_LabelDisplay:
 
881
              case kCDXProp_LabelStyle:
 
882
              case kCDXProp_ForegroundColor:
 
883
              case kCDXProp_BackgroundColor:
 
884
                ifs->seekg(size, ios_base::cur); 
 
885
                break;
 
886
              default: // some unknown node tag
 
887
                ifs->seekg(size, ios_base::cur); 
 
888
                snprintf(errorMsg, BUFF_SIZE, "Node Tag: %04X\tSize: %04X\n", tag, size); 
 
889
                obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
890
                break;
 
891
              }
 
892
          }
 
893
        if(depth < 1)
 
894
          {
 
895
                                                // Check the data before returning...
 
896
            switch(nodeType)
 
897
              {
 
898
              case kCDXNodeType_Fragment:
 
899
                atoms[nodeId] = -1; 
 
900
                break;
 
901
              case kCDXNodeType_ExternalConnectionPoint:
 
902
                atoms[nodeId] = -1;
 
903
                bonds.push_back(cdBond(nodeId,fragmentID,1)); 
 
904
                break;
 
905
              default:
 
906
                atom2 = pmol->NewAtom();
 
907
                atom2->SetVector(atom.GetVector());
 
908
                atom2->SetFormalCharge(atom.GetFormalCharge());
 
909
                atom2->SetAtomicNum(atom.GetAtomicNum());
 
910
                if (atom.IsClockwise())
 
911
                  atom2->SetClockwiseStereo();
 
912
                else if (atom.IsAntiClockwise())
 
913
                  atom2->SetAntiClockwiseStereo();
 
914
                atoms[nodeId] = atom2->GetIdx();
 
915
                break;
 
916
              }
 
917
            return 0; // everything worked correctly
 
918
          }
 
919
      } // end while(ifs.good())
 
920
    return -1; // file ended early
 
921
  }
 
922
 
 
923
  int ChemDrawBinaryFormat::readBond(istream *ifs, UINT32 bondId, 
 
924
                                     OBMol *pmol, list<cdBond> &bonds)
 
925
  {
 
926
    char errorMsg[BUFF_SIZE];
 
927
    UINT16 tag;
 
928
    UINT16 size;
 
929
    UINT32 id, bgnID, endID;
 
930
    int depth = 1, order=1, stereo = 0;
 
931
 
 
932
    while(ifs->good())
 
933
      {
 
934
        READ_INT16 (*ifs, tag);
 
935
        if(tag & kCDXTag_Object)        // Object
 
936
          {
 
937
            depth++;
 
938
            READ_INT32 (*ifs, id);
 
939
            snprintf(errorMsg, BUFF_SIZE, "Object ID (in bond %08X): %08X has type: %04X\n", bondId, id, tag);
 
940
            obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
941
 
 
942
            if(tag == kCDXObj_Text)
 
943
              {
 
944
                readText(ifs, id);
 
945
                depth--;
 
946
              }
 
947
            else
 
948
              {
 
949
                snprintf(errorMsg, BUFF_SIZE, "New object in bond, type %04X\n", tag);
 
950
                obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
951
              }
 
952
          }
 
953
        else if(tag == 0)       // End of object
 
954
          {
 
955
            depth--;
 
956
            //                  printf("End of Object\n");
 
957
          }
 
958
        else    // Property
 
959
          {
 
960
            READ_INT16 (*ifs, size);
 
961
 
 
962
            snprintf(errorMsg, BUFF_SIZE, "Bond Tag: %04X\tSize: %04X\n", tag, size);
 
963
            obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
964
 
 
965
            switch(tag)
 
966
              {
 
967
              case kCDXProp_Bond_Begin:
 
968
                bgnID = getBondStart(ifs, size); 
 
969
                break;
 
970
              case kCDXProp_Bond_End:
 
971
                endID = getBondEnd(ifs, size); 
 
972
                break;
 
973
              case kCDXProp_Bond_Order:
 
974
                order = getBondOrder(ifs, size);
 
975
                switch (order)
 
976
                  {
 
977
                  case 0xFFFF: // undefined, keep 1 for now
 
978
                    order = 1;
 
979
                  case 0x0001:
 
980
                  case 0x0002:
 
981
                    break;
 
982
                  case 0x0004:
 
983
                    order = 3;
 
984
                    break;
 
985
                  case 0x0080: // aromatic bond
 
986
                    order = 5;
 
987
                    break;
 
988
                  default: // other cases are just not supported, keep 1
 
989
                    order = 1;
 
990
                    break;
 
991
                  }
 
992
                break;
 
993
              case kCDXProp_Bond_Display:
 
994
                stereo = getBondDisplay(ifs, size); 
 
995
                break; // Stereo info
 
996
 
 
997
              case kCDXProp_BondLength:
 
998
              case kCDXProp_Bond_CIPStereochemistry:
 
999
              case kCDXProp_Bond_BeginAttach:
 
1000
              case kCDXProp_Bond_EndAttach:
 
1001
              case kCDXProp_ChemicalWarning:
 
1002
                ifs->seekg(size, ios_base::cur); 
 
1003
                break; // Maybe use? (any of the above cases)
 
1004
 
 
1005
              case kCDXProp_IgnoreWarnings:
 
1006
              case kCDXProp_MarginWidth:
 
1007
              case kCDXProp_Bond_Display2:
 
1008
              case kCDXProp_Bond_DoublePosition:
 
1009
              case kCDXProp_Bond_BondOrdering:
 
1010
              case kCDXProp_BondSpacing:
 
1011
              case kCDXProp_LineWidth:
 
1012
              case kCDXProp_BoldWidth:
 
1013
              case kCDXProp_HashSpacing:
 
1014
              case kCDXProp_ZOrder:
 
1015
              case kCDXProp_ForegroundColor:
 
1016
              case kCDXProp_BackgroundColor:
 
1017
              case kCDXProp_LabelStyle:
 
1018
                ifs->seekg(size, ios_base::cur); 
 
1019
                break;
 
1020
 
 
1021
              default: // some unknown, undocumented property
 
1022
                ifs->seekg(size, ios_base::cur);
 
1023
                snprintf(errorMsg, BUFF_SIZE, "Bond Tag: %04X\tSize: %04X\n", tag, size);
 
1024
                obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
1025
                break;
 
1026
              }
 
1027
          }
 
1028
        if(depth < 1)
 
1029
          {
 
1030
            bonds.push_back(cdBond(bgnID,endID,order,stereo));
 
1031
            return 0;
 
1032
          }
 
1033
      }
 
1034
    return -1;
 
1035
  }
 
1036
 
 
1037
  int ChemDrawBinaryFormat::readGeneric(istream *ifs, UINT32 objId)
 
1038
  {
 
1039
    char errorMsg[BUFF_SIZE];
 
1040
    UINT16 tag;
 
1041
    UINT16 size;
 
1042
    UINT32 id;
 
1043
    int depth = 1;
 
1044
 
 
1045
    while(ifs->good())
 
1046
      {
 
1047
        READ_INT16 (*ifs, tag);
 
1048
        if(tag & kCDXTag_Object)        // Object
 
1049
          {
 
1050
            depth++;
 
1051
            READ_INT32 (*ifs, id);
 
1052
 
 
1053
            snprintf(errorMsg, BUFF_SIZE, "Object ID (in generic %08X): %08X has type: %04X\n", objId, id, tag);
 
1054
            obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
1055
 
 
1056
            if ((tag == kCDXObj_BracketAttachment) 
 
1057
                || (tag == kCDXObj_CrossingBond) 
 
1058
                || (tag == kCDXObj_BracketedGroup) 
 
1059
                || (tag == kCDXObj_Text)
 
1060
                || (tag == kCDXObj_Fragment))
 
1061
              { // Objects to ignore (Fragment might be worth parsing)
 
1062
                readGeneric(ifs, id);
 
1063
                depth--;
 
1064
              }
 
1065
            else {
 
1066
              snprintf(errorMsg, BUFF_SIZE, "New object in generic, type %04X\n", tag);
 
1067
              obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
1068
            }
 
1069
          }
 
1070
        else if(tag == 0)       // End of object
 
1071
          {
 
1072
            depth--;
 
1073
            snprintf(errorMsg, BUFF_SIZE, "End of Object in generic %08X\n", objId);
 
1074
            obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
1075
          }
 
1076
        else    // Property
 
1077
          {
 
1078
            READ_INT16 (*ifs, size);
 
1079
 
 
1080
            snprintf(errorMsg, BUFF_SIZE, "Generic Tag: %04X\tSize: %04X\n", tag, size);
 
1081
            obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
1082
            switch(tag)
 
1083
              {
 
1084
              default:
 
1085
                ifs->seekg(size, ios_base::cur); 
 
1086
                break;
 
1087
              }
 
1088
          }
 
1089
        if(depth < 1) // matched begin and end tags, so we're good
 
1090
          {
 
1091
            return 0;
 
1092
          }
 
1093
      } // while reading
 
1094
    return -1; // file ended while reading
 
1095
  }
 
1096
 
 
1097
  int ChemDrawBinaryFormat::readFragment(istream *ifs, UINT32 fragmentId,
 
1098
                                         OBMol *pmol, map<UINT32, int> &atoms,
 
1099
                                         list<cdBond> &bonds)
 
1100
  {
 
1101
    char errorMsg[BUFF_SIZE];
 
1102
    UINT16 tag;
 
1103
    UINT16 size;
 
1104
    UINT32 id;
 
1105
    //char u32[4];
 
1106
    int depth = 1;
 
1107
 
 
1108
 cerr<<"Reading "<<pmol<<endl;
 
1109
   atoms[fragmentId] = -1;
 
1110
    while(ifs->good())
 
1111
      {
 
1112
        READ_INT16 ((*ifs), tag);
 
1113
        if(tag & kCDXTag_Object)        // Object
 
1114
          {
 
1115
            depth++;
 
1116
            READ_INT32 (*ifs, id);
 
1117
 
 
1118
            snprintf(errorMsg, BUFF_SIZE, "Object ID (in fragment %08X): %08X has type: %04X\n", fragmentId, id, tag);
 
1119
            obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
1120
 
 
1121
            if(tag == kCDXObj_Fragment)
 
1122
              {
 
1123
                if(readFragment(ifs, id, pmol, atoms, bonds) != 0)
 
1124
                  {
 
1125
                    obErrorLog.ThrowError(__FUNCTION__, "Error reading fragment", obWarning);
 
1126
                    return false;
 
1127
                  }
 
1128
              }
 
1129
            else if(tag == kCDXObj_Node)
 
1130
              {
 
1131
                readNode(ifs, id, pmol, atoms, bonds, fragmentId);
 
1132
                depth--;
 
1133
              }
 
1134
            else if(tag == kCDXObj_Bond)
 
1135
              {
 
1136
                readBond(ifs, id, pmol, bonds);
 
1137
                depth--;
 
1138
              }
 
1139
            else if((tag == kCDXObj_Graphic) || (tag == kCDXObj_Text))
 
1140
              { // Objects that can be ignored
 
1141
                readGeneric(ifs, id);
 
1142
                depth--;
 
1143
              }
 
1144
            //                  else if((tag == kCDXObj_Page) || ( tag == kCDXObj_Group))
 
1145
            //                  {       // Objects where the header can be ignored
 
1146
            //                  }
 
1147
            else
 
1148
              {
 
1149
                snprintf(errorMsg, BUFF_SIZE, "New object in fragment, type %04X\n", tag);
 
1150
                obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
1151
              }
 
1152
 
 
1153
          }
 
1154
        else if(tag == 0)       // End of object
 
1155
          {
 
1156
            depth--;
 
1157
          }
 
1158
        else    // Property
 
1159
          {
 
1160
            READ_INT16 ((*ifs), size);
 
1161
            switch(tag)
 
1162
              {
 
1163
              case kCDXProp_Frag_ConnectionOrder:
 
1164
                ifs->seekg(size, ios_base::cur); 
 
1165
                break;  // Should use
 
1166
              case kCDXProp_BoundingBox:
 
1167
                ifs->seekg(size, ios_base::cur); 
 
1168
                break;
 
1169
              default:
 
1170
                ifs->seekg(size, ios_base::cur); 
 
1171
                snprintf(errorMsg, BUFF_SIZE, "Fragment Tag: %04X\tSize: %04X\n", tag, size);
 
1172
                obErrorLog.ThrowError(__FUNCTION__, errorMsg, obDebug);
 
1173
 
 
1174
                break;
 
1175
              }
 
1176
          }
 
1177
        if(depth < 1)
 
1178
          {
 
1179
cerr<<"Done reading "<<pmol<<endl;
 
1180
            return 0; // all begin and end tags matched -- everything good 
 
1181
          }
 
1182
      } // while reading
 
1183
    return -1; // file ended before reading was finished
 
1184
  }
 
1185
 
 
1186
} //namespace OpenBabel