/*
FILE:     pdb_to_ndb.C
*/
/*
VERSION:  1.600
*/
/*
DATE:     2/3/2005
*/
/*
  Comments and Questions to: sw-help@rcsb.rutgers.edu
*/
/*
COPYRIGHT 1999-2005 Rutgers - The State University of New Jersey

This software is provided WITHOUT WARRANTY OF MERCHANTABILITY OR
FITNESS FOR A PARTICULAR PURPOSE OR ANY OTHER WARRANTY, EXPRESS OR
IMPLIED.  RUTGERS MAKE NO REPRESENTATION OR WARRANTY THAT THE
SOFTWARE WILL NOT INFRINGE ANY PATENT, COPYRIGHT OR OTHER
PROPRIETARY RIGHT.

The user of this software shall indemnify, hold harmless and defend
Rutgers, its governors, trustees, officers, employees, students,
agents and the authors against any and all claims, suits,
losses, liabilities, damages, costs, fees, and expenses including
reasonable attorneys' fees resulting from or arising out of the
use of this software.  This indemnification shall include, but is
not limited to, any and all claims alleging products liability.
*/
/*
               PDB SOFTWARE LICENSE AGREEMENT

BY CLICKING THE ACCEPTANCE BUTTON OR INSTALLING OR USING 
THIS "SOFTWARE, THE INDIVIDUAL OR ENTITY LICENSING THE  
SOFTWARE ("LICENSEE") IS CONSENTING TO BE BOUND BY AND IS 
BECOMING A PARTY TO THIS AGREEMENT.  IF LICENSEE DOES NOT 
AGREE TO ALL OF THE TERMS OF THIS AGREEMENT
THE LICENSEE MUST NOT INSTALL OR USE THE SOFTWARE.

1. LICENSE AGREEMENT

This is a license between you ("Licensee") and the Protein Data Bank (PDB) 
at Rutgers, The State University of New Jersey (hereafter referred to 
as "RUTGERS").   The software is owned by RUTGERS and protected by 
copyright laws, and some elements are protected by laws governing 
trademarks, trade dress and trade secrets, and may be protected by 
patent laws. 

2. LICENSE GRANT

RUTGERS grants you, and you hereby accept, non-exclusive, royalty-free 
perpetual license to install, use, modify, prepare derivative works, 
incorporate into other computer software, and distribute in binary 
and source code format, or any derivative work thereof, together with 
any associated media, printed materials, and on-line or electronic 
documentation (if any) provided by RUTGERS (collectively, the "SOFTWARE"), 
subject to the following terms and conditions: (i) any distribution 
of the SOFTWARE shall bind the receiver to the terms and conditions 
of this Agreement; (ii) any distribution of the SOFTWARE in modified 
form shall clearly state that the SOFTWARE has been modified from 
the version originally obtained from RUTGERS.  

2. COPYRIGHT; RETENTION OF RIGHTS.  

The above license grant is conditioned on the following: (i) you must 
reproduce all copyright notices and other proprietary notices on any 
copies of the SOFTWARE and you must not remove such notices; (ii) in 
the event you compile the SOFTWARE, you will include the copyright 
notice with the binary in such a manner as to allow it to be easily 
viewable; (iii) if you incorporate the SOFTWARE into other code, you 
must provide notice that the code contains the SOFTWARE and include 
a copy of the copyright notices and other proprietary notices.  All 
copies of the SOFTWARE shall be subject to the terms of this Agreement.  

3. NO MAINTENANCE OR SUPPORT; TREATMENT OF ENHANCEMENTS 

RUTGERS is under no obligation whatsoever to: (i) provide maintenance 
or support for the SOFTWARE; or (ii) to notify you of bug fixes, patches, 
or upgrades to the features, functionality or performance of the 
SOFTWARE ("Enhancements") (if any), whether developed by RUTGERS 
or third parties.  If, in its sole discretion, RUTGERS makes an 
Enhancement available to you and RUTGERS does not separately enter 
into a written license agreement with you relating to such bug fix, 
patch or upgrade, then it shall be deemed incorporated into the SOFTWARE 
and subject to this Agreement. You are under no obligation whatsoever 
to provide any Enhancements to RUTGERS or the public that you may 
develop over time; however, if you choose to provide your Enhancements 
to RUTGERS, or if you choose to otherwise publish or distribute your 
Enhancements, in source code form without contemporaneously requiring 
end users or RUTGERS to enter into a separate written license agreement 
for such Enhancements, then you hereby grant RUTGERS a non-exclusive,
royalty-free perpetual license to install, use, modify, prepare
derivative works, incorporate into the SOFTWARE or other computer
software, distribute, and sublicense your Enhancements or derivative
works thereof, in binary and source code form.

4. FEES.  There is no license fee for the SOFTWARE.  If Licensee
wishes to receive the SOFTWARE on media, there may be a small charge
for the media and for shipping and handling.  Licensee is
responsible for any and all taxes.

5. TERMINATION.  Without prejudice to any other rights, Licensor
may terminate this Agreement if Licensee breaches any of its terms
and conditions.  Upon termination, Licensee shall destroy all
copies of the SOFTWARE.

6. PROPRIETARY RIGHTS.  Title, ownership rights, and intellectual
property rights in the Product shall remain with RUTGERS.  Licensee 
acknowledges such ownership and intellectual property rights and will 
not take any action to jeopardize, limit or interfere in any manner 
with RUTGERS' ownership of or rights with respect to the SOFTWARE.  
The SOFTWARE is protected by copyright and other intellectual 
property laws and by international treaties.  Title and related 
rights in the content accessed through the SOFTWARE is the property 
of the applicable content owner and is protected by applicable law.  
The license granted under this Agreement gives Licensee no rights to such
content.

7. DISCLAIMER OF WARRANTY.  THE SOFTWARE IS PROVIDED FREE OF 
CHARGE, AND, THEREFORE, ON AN "AS IS" BASIS, WITHOUT WARRANTY OF 
ANY KIND, INCLUDING WITHOUT LIMITATION THE WARRANTIES THAT IT 
IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE 
OR NON-INFRINGING.  THE ENTIRE RISK AS TO THE QUALITY AND 
PERFORMANCE OF THE SOFTWARE IS BORNE BY LICENSEE.  SHOULD THE 
SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, THE LICENSEE AND NOT 
LICENSOR ASSUMES THE ENTIRE COST OF ANY SERVICE AND REPAIR.  
THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF 
THIS AGREEMENT.  NO USE OF THE PRODUCT IS AUTHORIZED HEREUNDER 
EXCEPT UNDER THIS DISCLAIMER.

8. LIMITATION OF LIABILITY.  TO THE MAXIMUM EXTENT PERMITTED BY
APPLICABLE LAW,  IN NO EVENT WILL LICENSOR BE LIABLE FOR ANY 
INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 
OUT OF THE USE OF OR INABILITY TO USE THE SOFTWARE, INCLUDING, 
WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK 
STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL 
OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF ADVISED OF THE
POSSIBILITY THEREOF. 
*/
#include <stdio.h>
#include <string.h>
#include <math.h>

#include "_maxit.h"
#include "erf_util.h"
#include "ndb_misclib.h"
#include "util.h"

#include "remark_100s.h"
#include "remark_200s.h"
#include "remark_300s.h"
#include "remark_general.h"
#include "remark_3_prolsqs.h"
#include "remark_3_refmac5.h"
#include "remark_3_shelxl.h"
#include "remark_3_tnt.h"
#include "remark_3_xplors.h"
#include "remark_cryoem.h"
#include "remark_solution.h"
#include "remark_olds.h"

#define NUM_REMARK  17

static int remark_nums[NUM_REMARK] = { 2, 3, 18, 200, 210, 215, 220, 225, 230, 240,
                245, 250, 265, 280, 300, 350, 800
};

static REMARKS *old_remarks[8] = { Remark_3_xplor_old, Remark_3_xplor_old,
                Remark_3_nuclsq_old, Remark_3_prolsq_old, Remark_3_prolsq_old,
                Remark_3_prolsq_old, Remark_3_tnt_old, Remark_3_shelx_old
};

static int num_old_remarks[8] = { Num_Remark_3_xplor_old, Num_Remark_3_xplor_old,
                Num_Remark_3_nuclsq_old, Num_Remark_3_prolsq_old, Num_Remark_3_prolsq_old,
                Num_Remark_3_prolsq_old, Num_Remark_3_tnt_old, Num_Remark_3_shelx_old 
};

static int find_a_match(const char *context, REMARKS *remark);
static void clean_middle_space(char *string);
static int string_compare(const char *remark, const char *string,
                 const int pos, const int len);
static void get_remark_answer(char *answer, One_Card_Info_Format *remarkCard,
                 REMARKS *remark, int field_no);
static void get_name_and_version(char *name, char *version, char *program);
static void clean_author_name(char *authors, char *name);

void _MAXIT::pdb_to_ndb_general(const char *ndb_sid, const int is_encapsulated)
{
       pdb_to_ndb_proc_header(ndb_sid);
       pdb_to_ndb_proc_compnd_and_source(is_encapsulated);
       pdb_to_ndb_proc_remarks();
       pdb_to_ndb_postprocessing();
}

void _MAXIT::pdb_to_ndb_proc_header(const char *ndb_sid)
{
       char buffer[50];
       One_Card_Info_Format *pCard = NULL, *qCard = NULL;
       pCard = _CardInfo[HEADER_TOKEN-1].Head();
       if (pCard == NULL) pCard = _CardInfo[HEADER_TOKEN-1].
               add_a_new_card(NdbToken[HEADER_TOKEN-1], 0);

       if (_num_mol && !strcmp(pCard->Field(1), "")) {
            if (_molecules[0]->type() == ATOMN_TYPE_DNA_RNA) {
                 pCard->AddElementToField(NDB_HYBRID_TEXT, 1);
            } else if (_molecules[0]->type() == ATOM_TYPE_TRNA) {
                 pCard->AddElementToField(NDB_T_RNA_TEXT, 1);
            } else if (_molecules[0]->type() & ATOMN_TYPE_RNA_ONLY) {
                 if (_molecules[0]->type() & ATOM_TYPE_PROTEIN) {
                      sprintf(buffer, "PROTEIN/%s", NDB_RNA_TEXT);
                      pCard->AddElementToField(buffer, 1);
                 } else pCard->AddElementToField(NDB_RNA_TEXT, 1);
            } else if (_molecules[0]->type() & ATOM_TYPE_DNA_ONLY) {
                 if (_molecules[0]->type() & ATOM_TYPE_PROTEIN) {
                      sprintf(buffer, "PROTEIN/%s", NDB_DNA_TEXT);
                      pCard->AddElementToField(buffer, 1);
                 } else pCard->AddElementToField(NDB_DNA_TEXT, 1);
            }
       }

       if (!strcmp(pCard->Field(1), "DEOXYRIBONUCLEIC ACID"))
            pCard->AddElementToField(NDB_DNA_TEXT, 1);
       else if (!strcmp(pCard->Field(1), "RIBONUCLEIC ACID"))
            pCard->AddElementToField(NDB_RNA_TEXT, 1);
       else if (!strcmp(pCard->Field(1), "AMINO-ACID TRANSPORT"))
            pCard->AddElementToField(NDB_T_RNA_TEXT, 1);

       if (strcmp(pCard->Field(3), "")) {
            qCard = _CardInfo[PDBFIL_TOKEN-1].Head();
            if (qCard == NULL) qCard = _CardInfo[PDBFIL_TOKEN-1].
                   add_a_new_card(NdbToken[PDBFIL_TOKEN-1], 0);
            qCard->AddElementToField(pCard->Field(3), 1);
       }

       qCard = _CardInfo[NDBFIL_TOKEN-1].Head();
       if (qCard == NULL) qCard = _CardInfo[NDBFIL_TOKEN-1].
                  add_a_new_card(NdbToken[NDBFIL_TOKEN-1], 0);
  
       if (!strcmp(qCard->Field(1), "")) {
            if (ndb_sid != NULL && strcmp(ndb_sid, "")) {
                 qCard->AddElementToField(ndb_sid, 1);
                 pCard->AddElementToField(ndb_sid, 3);
            } else qCard->AddElementToField(pCard->Field(3), 1);
       } else pCard->AddElementToField(qCard->Field(1), 3);
       qCard->UpperCaseField(1);
  
       qCard = _CardInfo[STATUS_TOKEN-1].Head();
       if (qCard == NULL) qCard = _CardInfo[STATUS_TOKEN-1].
                 add_a_new_card(NdbToken[STATUS_TOKEN-1], 0);

       if (strcmp(pCard->Field(2), "") && !strcmp(qCard->Field(6), ""))
            qCard->AddElementToField(pCard->Field(2), 6);
}

void _MAXIT::pdb_to_ndb_proc_compnd_and_source(const int is_encapsulated)
{
       typedef struct {
               int mol_id;
               int num_entity;
               int *entity;
               char *molecule;
               char *chains;
               char *fragment;
               char *synonym;
               char *ec_number;
               char *engineered;
               char *mutation;
               char *biol_unit;
               char *details;
       } MOL_COMPND;

       MOL_COMPND *mol_compnd = NULL;
       int n_mol = 0, found, i, j, k, len, entity;
       int nsource_Nat = 0, nsource_Gen = 0, nsource_Syn = 0;
       int mol_id = -1, nsource = 0;
       PDB_Source_Format *PdbSource = NULL;
       char source[800], match[100], pdb_chnid[10], *p;
       One_Card_Info_Format *pCard = NULL, *qCard = NULL, *rCard = NULL;

       pCard = _CardInfo[COMPND_TOKEN-1].Head();
       if (!pCard) return;
       while (pCard) {
            qCard = _CardInfo[PCOMPN_TOKEN-1].
                    add_a_new_card(NdbToken[PCOMPN_TOKEN-1], 0);
            for (i = 1; i < NdbToken[PCOMPN_TOKEN-1].NumField; i++) {
                 qCard->AddElementToField(pCard->Field(i), i);
            }

            if (!strncmp(pCard->Field(2), "MOL_ID:", 7)) {
                 if (mol_compnd == NULL) {
                      n_mol = 1;
                      mol_compnd = (MOL_COMPND *) malloc(sizeof(MOL_COMPND));
                 } else {
                      n_mol++;
                      mol_compnd = (MOL_COMPND *) realloc(mol_compnd,
                             n_mol * sizeof(MOL_COMPND));
                 }
                 mol_compnd[n_mol-1].mol_id = atoi(&(pCard->Field(2)[7]));
                 mol_compnd[n_mol-1].num_entity = 0;
                 mol_compnd[n_mol-1].entity = NULL;
                 mol_compnd[n_mol-1].molecule = NULL;
                 mol_compnd[n_mol-1].chains = NULL;
                 mol_compnd[n_mol-1].fragment = NULL;
                 mol_compnd[n_mol-1].synonym = NULL;
                 mol_compnd[n_mol-1].ec_number = NULL;
                 mol_compnd[n_mol-1].engineered = NULL;
                 mol_compnd[n_mol-1].mutation = NULL;
                 mol_compnd[n_mol-1].biol_unit = NULL;
                 mol_compnd[n_mol-1].details = NULL;
            } else if (!strncmp(pCard->Field(2), "MOLECULE:", 9)) {
                 if (mol_compnd == NULL) {
                      n_mol = 1;
                      mol_compnd = (MOL_COMPND *) malloc(sizeof(MOL_COMPND));
                      mol_compnd[n_mol-1].num_entity = 0;
                      mol_compnd[n_mol-1].entity = NULL;
                      mol_compnd[n_mol-1].molecule = NULL;
                      mol_compnd[n_mol-1].chains = NULL;
                      mol_compnd[n_mol-1].fragment = NULL;
                      mol_compnd[n_mol-1].synonym = NULL;
                      mol_compnd[n_mol-1].ec_number = NULL;
                      mol_compnd[n_mol-1].engineered = NULL;
                      mol_compnd[n_mol-1].mutation = NULL;
                      mol_compnd[n_mol-1].biol_unit = NULL;
                      mol_compnd[n_mol-1].details = NULL;
                 }
                 len = strlen(&(pCard->Field(2)[9]));
                 mol_compnd[n_mol-1].molecule = (char *) calloc(len + 1,
                               sizeof(char));
                 strcpy(mol_compnd[n_mol-1].molecule, &(pCard->Field(2)[9]));
                 len = strlen(mol_compnd[n_mol-1].molecule);
                 if (mol_compnd[n_mol-1].molecule[len-1] == ';')
                      mol_compnd[n_mol-1].molecule[len-1] = '\0';
                 ndb_clean_string(mol_compnd[n_mol-1].molecule);
            } else if (!strncmp(pCard->Field(2), "CHAIN:", 6)) {
                 if (mol_compnd == NULL) {
                      n_mol = 1;
                      mol_compnd = (MOL_COMPND *) malloc(sizeof(MOL_COMPND));
                      mol_compnd[n_mol-1].num_entity = 0;
                      mol_compnd[n_mol-1].entity = NULL;
                      mol_compnd[n_mol-1].molecule = NULL;
                      mol_compnd[n_mol-1].chains = NULL;
                      mol_compnd[n_mol-1].fragment = NULL;
                      mol_compnd[n_mol-1].synonym = NULL;
                      mol_compnd[n_mol-1].ec_number = NULL;
                      mol_compnd[n_mol-1].engineered = NULL;
                      mol_compnd[n_mol-1].mutation = NULL;
                      mol_compnd[n_mol-1].biol_unit = NULL;
                      mol_compnd[n_mol-1].details = NULL;
                 }
                 len = strlen(&(pCard->Field(2)[6]));
                 mol_compnd[n_mol-1].chains = (char *) calloc(len + 1,
                               sizeof(char));
                 strcpy(mol_compnd[n_mol-1].chains, &(pCard->Field(2)[6]));
                 len = strlen(mol_compnd[n_mol-1].chains);
                 if (mol_compnd[n_mol-1].chains[len-1] == ';')
                      mol_compnd[n_mol-1].chains[len-1] = '\0';
                 len = strlen(mol_compnd[n_mol-1].chains);
                 for (i = 0; i < len; i++)
                      if (mol_compnd[n_mol-1].chains[i] == ',')
                           mol_compnd[n_mol-1].chains[i] = ' ';
                 ndb_clean_string(mol_compnd[n_mol-1].chains);
                 if (!strcmp(mol_compnd[n_mol-1].chains, "NULL") ||
                     !strcmp(mol_compnd[n_mol-1].chains, "N/A") ||
                     !strcmp(mol_compnd[n_mol-1].chains, "NONE"))
                      mol_compnd[n_mol-1].chains[0] = '\0';
            } else if (!strncmp(pCard->Field(2), "FRAGMENT:", 9)) {
                 if (mol_compnd == NULL) {
                      n_mol = 1;
                      mol_compnd = (MOL_COMPND *) malloc(sizeof(MOL_COMPND));
                      mol_compnd[n_mol-1].num_entity = 0;
                      mol_compnd[n_mol-1].entity = NULL;
                      mol_compnd[n_mol-1].molecule = NULL;
                      mol_compnd[n_mol-1].chains = NULL;
                      mol_compnd[n_mol-1].fragment = NULL;
                      mol_compnd[n_mol-1].synonym = NULL;
                      mol_compnd[n_mol-1].ec_number = NULL;
                      mol_compnd[n_mol-1].engineered = NULL;
                      mol_compnd[n_mol-1].mutation = NULL;
                      mol_compnd[n_mol-1].biol_unit = NULL;
                      mol_compnd[n_mol-1].details = NULL;
                 }
                 len = strlen(&(pCard->Field(2)[9]));
                 mol_compnd[n_mol-1].fragment = (char *) calloc(len + 1,
                               sizeof(char));
                 strcpy(mol_compnd[n_mol-1].fragment, &(pCard->Field(2)[9]));
                 len = strlen(mol_compnd[n_mol-1].fragment);
                 if (mol_compnd[n_mol-1].fragment[len-1] == ';')
                      mol_compnd[n_mol-1].fragment[len-1] = '\0';
                 ndb_clean_string(mol_compnd[n_mol-1].fragment);
            } else if (!strncmp(pCard->Field(2), "SYNONYM:", 8)) {
                 if (mol_compnd == NULL) {
                      n_mol = 1;
                      mol_compnd = (MOL_COMPND *) malloc(sizeof(MOL_COMPND));
                      mol_compnd[n_mol-1].num_entity = 0;
                      mol_compnd[n_mol-1].entity = NULL;
                      mol_compnd[n_mol-1].molecule = NULL;
                      mol_compnd[n_mol-1].chains = NULL;
                      mol_compnd[n_mol-1].fragment = NULL;
                      mol_compnd[n_mol-1].synonym = NULL;
                      mol_compnd[n_mol-1].ec_number = NULL;
                      mol_compnd[n_mol-1].engineered = NULL;
                      mol_compnd[n_mol-1].mutation = NULL;
                      mol_compnd[n_mol-1].biol_unit = NULL;
                      mol_compnd[n_mol-1].details = NULL;
                 }
                 len = strlen(&(pCard->Field(2)[8]));
                 mol_compnd[n_mol-1].synonym = (char *) calloc(len + 1,
                               sizeof(char));
                 strcpy(mol_compnd[n_mol-1].synonym, &(pCard->Field(2)[8]));
                 len = strlen(mol_compnd[n_mol-1].synonym);
                 if (mol_compnd[n_mol-1].synonym[len-1] == ';')
                      mol_compnd[n_mol-1].synonym[len-1] = '\0';
                 ndb_clean_string(mol_compnd[n_mol-1].synonym);
            } else if (!strncmp(pCard->Field(2), "EC:", 3)) {
                 if (mol_compnd == NULL) {
                      n_mol = 1;
                      mol_compnd = (MOL_COMPND *) malloc(sizeof(MOL_COMPND));
                      mol_compnd[n_mol-1].num_entity = 0;
                      mol_compnd[n_mol-1].entity = NULL;
                      mol_compnd[n_mol-1].molecule = NULL;
                      mol_compnd[n_mol-1].chains = NULL;
                      mol_compnd[n_mol-1].fragment = NULL;
                      mol_compnd[n_mol-1].synonym = NULL;
                      mol_compnd[n_mol-1].ec_number = NULL;
                      mol_compnd[n_mol-1].engineered = NULL;
                      mol_compnd[n_mol-1].mutation = NULL;
                      mol_compnd[n_mol-1].biol_unit = NULL;
                      mol_compnd[n_mol-1].details = NULL;
                 }
                 len = strlen(&(pCard->Field(2)[3]));
                 mol_compnd[n_mol-1].ec_number = (char *) calloc(len + 1,
                               sizeof(char));
                 strcpy(mol_compnd[n_mol-1].ec_number, &(pCard->Field(2)[3]));
                 len = strlen(mol_compnd[n_mol-1].ec_number);
                 if (mol_compnd[n_mol-1].ec_number[len-1] == ';')
                      mol_compnd[n_mol-1].ec_number[len-1] = '\0';
                 ndb_clean_string(mol_compnd[n_mol-1].ec_number);
            } else if (!strncmp(pCard->Field(2), "ENGINEERED:", 11)) {
                 if (mol_compnd == NULL) {
                      n_mol = 1;
                      mol_compnd = (MOL_COMPND *) malloc(sizeof(MOL_COMPND));
                      mol_compnd[n_mol-1].num_entity = 0;
                      mol_compnd[n_mol-1].entity = NULL;
                      mol_compnd[n_mol-1].molecule = NULL;
                      mol_compnd[n_mol-1].chains = NULL;
                      mol_compnd[n_mol-1].fragment = NULL;
                      mol_compnd[n_mol-1].synonym = NULL;
                      mol_compnd[n_mol-1].ec_number = NULL;
                      mol_compnd[n_mol-1].engineered = NULL;
                      mol_compnd[n_mol-1].mutation = NULL;
                      mol_compnd[n_mol-1].biol_unit = NULL;
                      mol_compnd[n_mol-1].details = NULL;
                 }
                 len = strlen(&(pCard->Field(2)[11]));
                 mol_compnd[n_mol-1].engineered = (char *) calloc(len + 1,
                               sizeof(char));
                 strcpy(mol_compnd[n_mol-1].engineered, &(pCard->Field(2)[11]));
                 len = strlen(mol_compnd[n_mol-1].engineered);
                 if (mol_compnd[n_mol-1].engineered[len-1] == ';')
                      mol_compnd[n_mol-1].engineered[len-1] = '\0';
                 ndb_clean_string(mol_compnd[n_mol-1].engineered);
            } else if (!strncmp(pCard->Field(2), "MUTATION:", 9)) {
                 if (mol_compnd == NULL) {
                      n_mol = 1;
                      mol_compnd = (MOL_COMPND *) malloc(sizeof(MOL_COMPND));
                      mol_compnd[n_mol-1].num_entity = 0;
                      mol_compnd[n_mol-1].entity = NULL;
                      mol_compnd[n_mol-1].molecule = NULL;
                      mol_compnd[n_mol-1].chains = NULL;
                      mol_compnd[n_mol-1].fragment = NULL;
                      mol_compnd[n_mol-1].synonym = NULL;
                      mol_compnd[n_mol-1].ec_number = NULL;
                      mol_compnd[n_mol-1].engineered = NULL;
                      mol_compnd[n_mol-1].mutation = NULL;
                      mol_compnd[n_mol-1].biol_unit = NULL;
                      mol_compnd[n_mol-1].details = NULL;
                 }
                 len = strlen(&(pCard->Field(2)[9]));
                 mol_compnd[n_mol-1].mutation = (char *) calloc(len + 1,
                               sizeof(char));
                 strcpy(mol_compnd[n_mol-1].mutation, &(pCard->Field(2)[9]));
                 len = strlen(mol_compnd[n_mol-1].mutation);
                 if (mol_compnd[n_mol-1].mutation[len-1] == ';')
                      mol_compnd[n_mol-1].mutation[len-1] = '\0';
                 ndb_clean_string(mol_compnd[n_mol-1].mutation);
            } else if (!strncmp(pCard->Field(2), "BIOLOGICAL_UNIT:", 16)) {
                 if (mol_compnd == NULL) {
                      n_mol = 1;
                      mol_compnd = (MOL_COMPND *) malloc(sizeof(MOL_COMPND));
                      mol_compnd[n_mol-1].num_entity = 0;
                      mol_compnd[n_mol-1].entity = NULL;
                      mol_compnd[n_mol-1].molecule = NULL;
                      mol_compnd[n_mol-1].chains = NULL;
                      mol_compnd[n_mol-1].fragment = NULL;
                      mol_compnd[n_mol-1].synonym = NULL;
                      mol_compnd[n_mol-1].ec_number = NULL;
                      mol_compnd[n_mol-1].engineered = NULL;
                      mol_compnd[n_mol-1].mutation = NULL;
                      mol_compnd[n_mol-1].biol_unit = NULL;
                      mol_compnd[n_mol-1].details = NULL;
                 }
                 len = strlen(&(pCard->Field(2)[16]));
                 mol_compnd[n_mol-1].biol_unit = (char *) calloc(len + 1,
                               sizeof(char));
                 strcpy(mol_compnd[n_mol-1].biol_unit, &(pCard->Field(2)[16]));
                 len = strlen(mol_compnd[n_mol-1].biol_unit);
                 if (mol_compnd[n_mol-1].biol_unit[len-1] == ';')
                      mol_compnd[n_mol-1].biol_unit[len-1] = '\0';
                 ndb_clean_string(mol_compnd[n_mol-1].biol_unit);
            } else if (!strncmp(pCard->Field(2), "OTHER_DETAILS:", 14)) {
                 if (mol_compnd == NULL) {
                      n_mol = 1;
                      mol_compnd = (MOL_COMPND *) malloc(sizeof(MOL_COMPND));
                      mol_compnd[n_mol-1].num_entity = 0;
                      mol_compnd[n_mol-1].entity = NULL;
                      mol_compnd[n_mol-1].molecule = NULL;
                      mol_compnd[n_mol-1].chains = NULL;
                      mol_compnd[n_mol-1].fragment = NULL;
                      mol_compnd[n_mol-1].synonym = NULL;
                      mol_compnd[n_mol-1].ec_number = NULL;
                      mol_compnd[n_mol-1].engineered = NULL;
                      mol_compnd[n_mol-1].mutation = NULL;
                      mol_compnd[n_mol-1].biol_unit = NULL;
                      mol_compnd[n_mol-1].details = NULL;
                 }
                 len = strlen(&(pCard->Field(2)[14]));
                 mol_compnd[n_mol-1].details = (char *) calloc(len + 1,
                               sizeof(char));
                 strcpy(mol_compnd[n_mol-1].details, &(pCard->Field(2)[14]));
                 len = strlen(mol_compnd[n_mol-1].details);
                 if (mol_compnd[n_mol-1].details[len-1] == ';')
                      mol_compnd[n_mol-1].details[len-1] = '\0';
                 ndb_clean_string(mol_compnd[n_mol-1].details);
            }
            pCard = pCard->Next();
       }

       pCard = _CardInfo[COMPND_TOKEN-1].Head();
       while (pCard) pCard = _CardInfo[COMPND_TOKEN-1].delete_a_card(pCard);

       for (i = 0; i < n_mol; i++) {
            if (mol_compnd[i].chains == NULL) {
                 pdb_chnid[0] = '\0';
                 entity = get_entity_index(pdb_chnid, is_encapsulated);
                 if (entity != -1) {
                      mol_compnd[i].num_entity = 1;
                      mol_compnd[i].entity = (int *) malloc(sizeof(int));
                      mol_compnd[i].entity[0] = entity;
                 }
            } else {
                 p = mol_compnd[i].chains;
                 while (p) {
                      p = get_word(p, pdb_chnid);
                      if (!strcmp(pdb_chnid, "NULL") || !strcmp(pdb_chnid, "N/A") ||
                          !strcmp(pdb_chnid, "NONE")) pdb_chnid[0] = '\0';
                      entity = get_entity_index(pdb_chnid, is_encapsulated);
                      if (entity != -1) {
                           found = 0;
                           for (j = 0; j < mol_compnd[i].num_entity; j++) {
                                if (entity == mol_compnd[i].entity[j]) {
                                     found = 1; break;
                                }
                           }
                           if (!found) {
                                mol_compnd[i].num_entity++;
                                mol_compnd[i].entity = (int *)
                                   realloc(mol_compnd[i].entity,
                                    mol_compnd[i].num_entity * sizeof(int));
                                mol_compnd[i].entity[mol_compnd[i].num_entity-1] = entity;
                           }
                      }
                 }
            }

            for (j = 0; j < mol_compnd[i].num_entity; j++) {
                 if (is_entity_a_protein(mol_compnd[i].entity[j])) {
                      if (mol_compnd[i].molecule) {
                           insert_a_card(mol_compnd[i].entity[j], PROTEI_TOKEN-1, 3,
                                       mol_compnd[i].molecule);
                      }
                      strcpy(source, "nat");
                      if (mol_compnd[i].engineered &&
                         !strcmp(mol_compnd[i].engineered, "YES")) strcpy(source, "man");
                      pCard = _CardInfo[ENTITY_TOKEN-1].Head();
                      while (pCard) {
                           if (atoi(pCard->Field(1)) == mol_compnd[i].entity[j]) {
                                if (strcasecmp(pCard->Field(3), "nat") && !strcasecmp(source, "nat") ||
                                    !strcasecmp(pCard->Field(3), "nat") && strcasecmp(source, "nat"))
                                     pCard->AddElementToField(source, 3);
                                break;
                           }
                           pCard = pCard->Next();
                      }
                 }
                 if (mol_compnd[i].molecule)
                      insert_a_card(mol_compnd[i].entity[j], ENTDES_TOKEN-1, 3,
                                       mol_compnd[i].molecule);
                 if (mol_compnd[i].fragment)
                      insert_a_card(mol_compnd[i].entity[j], FRAGMT_TOKEN-1, 3,
                                       mol_compnd[i].fragment);
                 if (mol_compnd[i].synonym)
                      insert_a_card(mol_compnd[i].entity[j], ENTNAM_TOKEN-1, 3,
                                       mol_compnd[i].synonym);
                 if (mol_compnd[i].ec_number)
                      insert_a_card(mol_compnd[i].entity[j], ECNUM_TOKEN-1, 2,
                                       mol_compnd[i].ec_number);
                 if (mol_compnd[i].mutation)
                      insert_a_card(mol_compnd[i].entity[j], ENTMUT_TOKEN-1, 3,
                                       mol_compnd[i].mutation);
                 if (mol_compnd[i].biol_unit)
                      insert_a_card(mol_compnd[i].entity[j], BIOUNI_TOKEN-1, 3,
                                       mol_compnd[i].biol_unit);
                 if (mol_compnd[i].details)
                      insert_a_card(mol_compnd[i].entity[j], ENTAIL_TOKEN-1, 3,
                                       mol_compnd[i].details);
            }
       }

       while (PdbSource_Nat[nsource_Nat].pdbname &&
              strcmp(PdbSource_Nat[nsource_Nat].pdbname, "")) {
            if (PdbSource_Nat[nsource_Nat].NdbTokenId <= 0)
                 PdbSource_Nat[nsource_Nat].NdbTokenId =
                    find_card_id(PdbSource_Nat[nsource_Nat].NdbTokenName)+1;
            nsource_Nat++;
       }

       while (PdbSource_Gen[nsource_Gen].pdbname &&
              strcmp(PdbSource_Gen[nsource_Gen].pdbname, "")) {
            if (PdbSource_Gen[nsource_Gen].NdbTokenId <= 0)
                 PdbSource_Gen[nsource_Gen].NdbTokenId =
                    find_card_id(PdbSource_Gen[nsource_Gen].NdbTokenName)+1;
            nsource_Gen++;
       }

       while (PdbSource_Syn[nsource_Syn].pdbname &&
              strcmp(PdbSource_Syn[nsource_Syn].pdbname, "")) {
            if (PdbSource_Syn[nsource_Syn].NdbTokenId <= 0)
                 PdbSource_Syn[nsource_Syn].NdbTokenId =
                    find_card_id(PdbSource_Syn[nsource_Syn].NdbTokenName)+1;
            nsource_Syn++;
       }

       pCard = _CardInfo[SOURCE_TOKEN-1].Head();
       while (pCard) {
            qCard = _CardInfo[PSOURC_TOKEN-1].
                   add_a_new_card(NdbToken[PSOURC_TOKEN-1], 0);
            for (i = 1; i < NdbToken[PSOURC_TOKEN-1].NumField; i++) {
                 qCard->AddElementToField(pCard->Field(i), i);
            }

            if (!strncmp(pCard->Field(2), "MOL_ID:", 7)) {
                 mol_id = atoi(&(pCard->Field(2)[7]));
                 PdbSource = NULL;
                 nsource = 0;
                 for (i = 0; i < n_mol; i++) {
                      if (mol_compnd[i].mol_id == mol_id) {
                           mol_id = i;
                           if (mol_compnd[i].engineered &&
                              !strcmp(mol_compnd[i].engineered, "YES")) {
                                PdbSource = PdbSource_Gen;
                                nsource = nsource_Gen;
                           } else {
                                PdbSource = PdbSource_Nat;
                                nsource = nsource_Nat;
                           }
                           break;
                      }
                 }
            } else if (!strncmp(pCard->Field(2), "SYNTHETIC:", 10)) {
                 PdbSource = PdbSource_Syn;
                 nsource = nsource_Syn;
                 if (mol_id == -1 && n_mol) mol_id = 0;

                 if (mol_id >= 0) {
                      for (k = 0; k < mol_compnd[mol_id].num_entity; k++) {
                           rCard = _CardInfo[ENTITY_TOKEN-1].Head();
                           while (rCard) {
                                if (atoi(rCard->Field(1)) == mol_compnd[mol_id].entity[k]) {
                                     rCard->AddElementToField("syn", 3);
                                     break;
                                }
                                rCard = rCard->Next();
                           }
                      }
                 }
            } else {
                 if (mol_id == -1 && n_mol) {
                      if (mol_compnd[0].engineered &&
                          !strcmp(mol_compnd[0].engineered, "YES")) {
                           PdbSource = PdbSource_Gen;
                           nsource = nsource_Gen;
                      } else {
                           PdbSource = PdbSource_Nat;
                           nsource = nsource_Nat;
                      }
                      mol_id = 0;
                 }

                 if (mol_id >= 0) {
                      if (!strncmp(pCard->Field(2), "SYNTHETIC: YES", 14)) {
                           for (k = 0; k < mol_compnd[mol_id].num_entity; k++) {
                                rCard = _CardInfo[ENTITY_TOKEN-1].Head();
                                while (rCard) {
                                     if (atoi(rCard->Field(1)) == mol_compnd[mol_id].entity[k]) {
                                          rCard->AddElementToField("syn", 3);
                                          break;
                                     }
                                     rCard = rCard->Next();
                                }
                           }
                      } else {
                           for (i = 0; i < nsource; i++) {
                                sprintf(match, "%s: ", PdbSource[i].pdbname);
                                len = strlen(match);
                                if (!strncmp(pCard->Field(2), match, len) &&
                                    PdbSource[i].NdbTokenId > 0 &&
                                    PdbSource[i].NdbFieldNo > 0) {
                                     strcpy(source, &(pCard->Field(2)[len]));
                                     ndb_clean_string(source);
                                     len = strlen(source);
                                     if (len && source[len - 1] == ';')
                                          source[len-1] = '\0';
                                     if (source[0] == '\0' || !strcmp(source, "NULL") ||
                                         !strcmp(source, "N/A") || !strcmp(source, "NONE")) break;
                                     for (k = 0; k < mol_compnd[mol_id].num_entity; k++) {
                                          insert_a_card(mol_compnd[mol_id].entity[k],  
                                                 PdbSource[i].NdbTokenId - 1,
                                                 PdbSource[i].NdbFieldNo - 1, source);
                                     }
                                }
                           }
                      }
                 }
            }
            pCard = pCard->Next();
       }
       pCard = _CardInfo[SOURCE_TOKEN-1].Head();
       while (pCard) pCard = _CardInfo[SOURCE_TOKEN-1].delete_a_card(pCard);

       for (i = 0; i < n_mol; i++) {
            if (mol_compnd[i].entity) free((void *) mol_compnd[i].entity);
            if (mol_compnd[i].molecule) free((void *) mol_compnd[i].molecule);
            if (mol_compnd[i].chains) free((void *) mol_compnd[i].chains);
            if (mol_compnd[i].fragment) free((void *) mol_compnd[i].fragment);
            if (mol_compnd[i].synonym) free((void *) mol_compnd[i].synonym);
            if (mol_compnd[i].ec_number) free((void *) mol_compnd[i].ec_number);
            if (mol_compnd[i].engineered) free((void *) mol_compnd[i].engineered);
            if (mol_compnd[i].mutation) free((void *) mol_compnd[i].mutation);
            if (mol_compnd[i].biol_unit) free((void *) mol_compnd[i].biol_unit);
            if (mol_compnd[i].details) free((void *) mol_compnd[i].details);
       }
       if (mol_compnd) free ((void *) mol_compnd);
}

void _MAXIT::pdb_to_ndb_proc_remarks()
{
       int  i, j, k, group_index = 0, nRemarkCard = 0, num_block = 0, *block = NULL;
       int  num_remark = 0, num_old_remark = 0, found = 0, found_any = 0, *used_index = NULL;
       int  SOLEXP_TOKEN, SOLMDL_TOKEN;
       One_Card_Info_Format *pCard = NULL, *rCard = NULL, **pRemarkCard = NULL;
       REMARKS *old_remark = NULL;
       GROUP_REMARKS *group_remark = NULL;

       SOLEXP_TOKEN = find_card_id("SOLEXP");
       SOLMDL_TOKEN = find_card_id("SOLMDL");

       pCard = _CardInfo[REMARK_TOKEN-1].Head();
       while (pCard) {
            rCard = _CardInfo[PREMRK_TOKEN-1].
                   add_a_new_card(NdbToken[PREMRK_TOKEN-1], 0);
            rCard->AddElementToField(pCard->Field(1), 1);
            rCard->AddElementToField(pCard->Field(2), 2);
            pCard = pCard->Next();
       }

       for (i = 0; i < NUM_REMARK; i++) {
            pRemarkCard = get_remarks(remark_nums[i], nRemarkCard);
            if (!nRemarkCard) continue;

            if (remark_nums[i] == 2)
                 pdb_to_ndb_proc_remark(nRemarkCard, pRemarkCard, 1, &Remark_2, 0);
            else if (remark_nums[i] == 3) {
                 if (_experiment_type & EXPERIMENT_TYPE_NMR ||
                     _experiment_type & EXPERIMENT_TYPE_MODEL) {
                      pdb_to_ndb_proc_remark(nRemarkCard, pRemarkCard,
                                Num_Remark_3_NMR, Remark_3_NMR, 0);
                 } else if (_experiment_type & EXPERIMENT_TYPE_CRYO_EM) {
                      pdb_to_ndb_proc_remark(nRemarkCard, pRemarkCard,
                                Num_Remark_3_Cryo_Em, Remark_3_Cryo_Em, 0);
                 } else if (_experiment_type & EXPERIMENT_TYPE_SOLN_SCT) {
                      block = get_blocks_of_remarks(nRemarkCard, num_block, pRemarkCard);
                      if (num_block) {
                           k = 0;
                           for (j = 0; j < num_block; j++) {
                                num_remark = block[2 * j + 1] - block[2 * j] + 1;
                                found = 0;
                                while (k < Remark_3_Solution.Remarks_No) {
                                     found = pdb_to_ndb_proc_remark(num_remark,
                                          &pRemarkCard[block[2 * j]],
                                          Remark_3_Solution.num_remarks[k],
                                          Remark_3_Solution.remarks[k],
                                          Remark_3_Solution.repeat[k]);
                                     if (found) break;
                                     k++;
                                }
                                if (found) {
                                     if (k < Remark_3_Solution.Remarks_No &&
                                         !Remark_3_Solution.repeat[k]) k++;
                                } else k = 0;
                           }
                      }
                      if (block) {
                           delete [] block;
                           block = NULL;
                      }
                 } else {
                      block = get_blocks_of_remarks(nRemarkCard, num_block, pRemarkCard);
                      if (num_block) {
                           num_remark = block[1] - block[0] + 1;
                           if (!pdb_to_ndb_proc_remark(num_remark, &pRemarkCard[block[0]],
                                 Num_Remark_3_1, Remark_3_1, 0)) {
                                if (!pdb_to_ndb_proc_remark(num_remark, &pRemarkCard[block[0]],
                                 Num_Remark_3_2, Remark_3_2, 0))
                                     pdb_to_ndb_proc_remark(num_remark, &pRemarkCard[block[0]],
                                          Num_Remark_3_3, Remark_3_3, 0);

                           }
                           group_index = 0;
                           rCard = _CardInfo[REFMET_TOKEN-1].Head();
                           if (rCard) {
                                if (!strncmp(rCard->Field(3), "CNS", 3) ||
                                    !strncmp(rCard->Field(3), "CNX", 3))
                                     group_index = 1;
                                else if (!strncmp(rCard->Field(3),"NUCLSQ", 6))
                                     group_index = 2;
                                else if (!strncmp(rCard->Field(3), "PROLSQ", 6) ||
                                           !strncmp(rCard->Field(3), "PROFFT", 6) ||
                                           !strncmp(rCard->Field(3), "CCP4", 4) ||
                                           !strncmp(rCard->Field(3), "PROTEIN", 7) ||
                                           !strncmp(rCard->Field(3), "RESTRAIN", 8) ||
                                           !strncmp(rCard->Field(3), "GPRLSA", 6))
                                     group_index = 3;
                                else if (!strncmp(rCard->Field(3), "REFMAC 5", 8))
                                     group_index = 5;
                                else if (!strncmp(rCard->Field(3), "REFMAC", 6))
                                     group_index = 4;
                                else if (!strncmp(rCard->Field(3),"TNT", 3))
                                     group_index = 6;
                                else if (!strncmp(rCard->Field(3),"SHELX", 5))
                                     group_index = 7;
                           }
                           group_remark = group_remarks_in[group_index];
                           num_old_remark = num_old_remarks[group_index];
                           old_remark = old_remarks[group_index];

                           k = 0;
                           found_any = 0;
                           used_index = new int[group_remark->Remarks_No];
                           for (j = 0; j < group_remark->Remarks_No; j++) used_index[j] = 0;
                           for (j = 1; j < num_block; j++) {
                                num_remark = block[2 * j + 1] - block[2 * j] + 1;
                                found = 0;
                                while (k < group_remark->Remarks_No) {
                                     found = pdb_to_ndb_proc_remark(num_remark,
                                          &pRemarkCard[block[2 * j]],
                                          group_remark->num_remarks[k],
                                          group_remark->remarks[k],
                                          group_remark->repeat[k]);
                                     if (found) {
                                          used_index[k] = 1;
                                          break;
                                     }
                                     k++;
                                }
                                if (found) {
                                     found_any = 1;
                                     for (k = 0; k < group_remark->Remarks_No; k++) {
                                          if (!used_index[k]) break;
                                     }
/*
                                     if (k < group_remark->Remarks_No &&
                                         !group_remark->repeat[k]) k++;
*/
                                } else k = 0;
                           }
                           delete [] used_index;
                           if (!found_any) {
                                for (j = 0; j < nRemarkCard; j++) {
                                     if (pdb_to_ndb_proc_remark_special(pRemarkCard[j],
                                              num_old_remark, old_remark))
                                          found_any = 1;
                                }
                           }
                           if (!found_any) {
                                FILE *fp = fopen("MAXIT.ERROR", "a");
                                fprintf(fp, "%s: maxit failed to pick up the correct value in REMARK 3\n", 
                                           _StructureId);
                                for (j = 0; j < nRemarkCard; j++) {
                                     fprintf(fp, "\tREMARK   3 %s\n", pRemarkCard[j]->Field(2));
                                }
                                fprintf(fp, "\n");
                                fclose (fp);
                           }
                      }
                      if (block) {
                           delete [] block;
                           block = NULL;
                      }
                 }
            } else if (remark_nums[i] == 18)
                 pdb_to_ndb_proc_remark(nRemarkCard, pRemarkCard, Num_Remark_18, Remark_18, 0);
            else if (remark_nums[i] == 200) {
                 pdb_to_ndb_proc_remark(nRemarkCard, pRemarkCard, Num_Remark_200, Remark_200, 0);
                 if (_experiment_type == EXPERIMENT_TYPE_BASIC)
                      _experiment_type = EXPERIMENT_TYPE_XRAY;
            } else if (remark_nums[i] == 210) {
                 pdb_to_ndb_proc_remark(nRemarkCard, pRemarkCard, Num_Remark_210, Remark_210, 0);
                 if (_experiment_type == EXPERIMENT_TYPE_BASIC)
                      _experiment_type = EXPERIMENT_TYPE_NMR;
            } else if (remark_nums[i] == 215) {
                 if (_experiment_type == EXPERIMENT_TYPE_BASIC)
                      _experiment_type = EXPERIMENT_TYPE_NMR;
            } else if (remark_nums[i] == 220) {
                 pdb_to_ndb_proc_remark(nRemarkCard, pRemarkCard, Num_Remark_220, Remark_220, 0);
                 if (_experiment_type == EXPERIMENT_TYPE_BASIC)
                      _experiment_type = EXPERIMENT_TYPE_MODEL;
            } else if (remark_nums[i] == 225) {
                 if (_experiment_type == EXPERIMENT_TYPE_BASIC)
                       _experiment_type = EXPERIMENT_TYPE_MODEL;
            } else if (remark_nums[i] == 230) {
                 pdb_to_ndb_proc_remark(nRemarkCard, pRemarkCard, Num_Remark_230, Remark_230, 0);
                 if (_experiment_type == EXPERIMENT_TYPE_BASIC)
                      _experiment_type = EXPERIMENT_TYPE_NEUTRON;
            } else if (remark_nums[i] == 240) {
                 pdb_to_ndb_proc_remark(nRemarkCard, pRemarkCard, Num_Remark_240, Remark_240, 0);
                 if (_experiment_type == EXPERIMENT_TYPE_BASIC)
                      _experiment_type = EXPERIMENT_TYPE_ELECTRON;
            } else if (remark_nums[i] == 245) {
                 if (_experiment_type == EXPERIMENT_TYPE_CRYO_EM)
                      pdb_to_ndb_proc_remark(nRemarkCard, pRemarkCard, Num_Remark_245, Remark_245, 0);
            } else if (remark_nums[i] == 250)
                 pdb_to_ndb_proc_remark(nRemarkCard, pRemarkCard, Num_Remark_250, Remark_250, 0);
            else if (remark_nums[i] == 265) {
                 if (_experiment_type == EXPERIMENT_TYPE_SOLN_SCT) {
                      block = get_blocks_of_remarks(nRemarkCard, num_block, pRemarkCard);
                      if (num_block) {
                           k = 0;
                           for (j = 0; j < num_block; j++) {
                                num_remark = block[2 * j + 1] - block[2 * j] + 1;
                                found = 0;
                                while (k < Remark_265.Remarks_No) {
                                     found = pdb_to_ndb_proc_remark(num_remark,
                                          &pRemarkCard[block[2 * j]],
                                          Remark_265.num_remarks[k],
                                          Remark_265.remarks[k],
                                          Remark_265.repeat[k]);
                                     if (found) break;
                                     k++;
                                }
                                if (found) {
                                     if (k < Remark_265.Remarks_No &&
                                         !Remark_265.repeat[k]) k++;
                                } else k = 0;
                           }
                      }
                      if (block) {
                           delete [] block;
                           block = NULL;
                      }
                      num_block = 0;
                      if (SOLEXP_TOKEN >= 0) {
                           pCard = _CardInfo[SOLEXP_TOKEN].Head();
                           while (pCard) {
                                pCard->AddElementToField(++num_block, 1);
                                rCard = pCard->Next();
                                if (rCard && !strcmp(rCard->Field(2), "") &&
                                    strcmp(pCard->Field(2), ""))
                                     rCard->AddElementToField(pCard->Field(2), 2); 
                                pCard = pCard->Next();
                           }
                      }
                      if (SOLMDL_TOKEN >= 0 && SOLEXP_TOKEN >= 0) {
                           rCard = _CardInfo[SOLMDL_TOKEN].Head();
                           j = 0;
                           while (rCard) {
                                pCard = _CardInfo[SOLEXP_TOKEN].
                                   add_a_new_card(NdbToken[SOLEXP_TOKEN], 0);
                                pCard->AddElementToField("THEORETICAL MODELLING", 2);
                                pCard->AddElementToField(++num_block, 1);
                                rCard->AddElementToField(num_block, 9);
                                rCard->AddElementToField(++j, 10);
                                rCard = rCard->Next();
                           }
                      }
                 }
            } else if (remark_nums[i] == 280)
                 pdb_to_ndb_proc_remark(nRemarkCard, pRemarkCard, Num_Remark_280, Remark_280, 0);
            else if (remark_nums[i] == 300) {
                 if (_experiment_type == EXPERIMENT_TYPE_CRYO_EM) {
                      block = get_blocks_of_remarks(nRemarkCard, num_block, pRemarkCard);
                      if (num_block) {
                           k = 0;
                           for (j = 1; j < num_block; j++) {
                                num_remark = block[2 * j + 1] - block[2 * j] + 1;
                                found = 0;
                                while (k < Remark_Cryo_Em_300.Remarks_No) {
                                     found = pdb_to_ndb_proc_remark(num_remark,
                                          &pRemarkCard[block[2 * j]],
                                          Remark_Cryo_Em_300.num_remarks[k],
                                          Remark_Cryo_Em_300.remarks[k],
                                          Remark_Cryo_Em_300.repeat[k]);
                                     if (found) break;
                                     k++;
                                }
                                if (found) {
                                     if (k < Remark_Cryo_Em_300.Remarks_No &&
                                         !Remark_Cryo_Em_300.repeat[k]) k++;
                                } else k = 0;
                           }
                      }
                      if (block) {
                           delete [] block;
                           block = NULL;
                      }
                 }
            } else if (remark_nums[i] == 800)
                 pdb_to_ndb_proc_remark(nRemarkCard, pRemarkCard, Num_Remark_800, Remark_800, 0);

            if (pRemarkCard) delete [] pRemarkCard;
       }

       pCard = _CardInfo[REMARK_TOKEN-1].Head();
       while (pCard) pCard = _CardInfo[REMARK_TOKEN-1].delete_a_card(pCard);

       if (_CardInfo[EXPDTA_TOKEN-1].Head() == NULL) {
            pCard = _CardInfo[EXPDTA_TOKEN-1].add_a_new_card(NdbToken[EXPDTA_TOKEN-1], 0);
            if (_experiment_type == EXPERIMENT_TYPE_XRAY)
                 pCard->AddElementToField("X-RAY DIFFRACTION", 2);
            else if (_experiment_type == EXPERIMENT_TYPE_NMR)
                 pCard->AddElementToField("NMR", 2);
            else if (_experiment_type == EXPERIMENT_TYPE_MODEL)
                 pCard->AddElementToField("THEORETICAL MODEL", 2);
            else if (_experiment_type == EXPERIMENT_TYPE_NEUTRON)
                 pCard->AddElementToField("NEUTRON DIFFRACTION", 2);
            else if (_experiment_type == EXPERIMENT_TYPE_ELECTRON)
                 pCard->AddElementToField("ELECTRON DIFFRACTION", 2);
            else pCard->AddElementToField("X-RAY DIFFRACTION", 2);
       }
       if (_experiment_type == EXPERIMENT_TYPE_NMR)
            pdb_to_ndb_postprocessing_remarks();
}

One_Card_Info_Format** _MAXIT::get_remarks(const int remarkNo, int &nRemarkCard)
{
       int i;
       One_Card_Info_Format *pCard = NULL, **pRemarkCard = NULL, **tmp = NULL;

       nRemarkCard = 0;
       pCard = _CardInfo[REMARK_TOKEN-1].Head();
       while (pCard) {
            if (atoi(pCard->Field(1)) == remarkNo) {
                 tmp = pRemarkCard;
                 pRemarkCard = new One_Card_Info_Format*[nRemarkCard+1];
                 for (i = 0; i < nRemarkCard; i++) pRemarkCard[i] = tmp[i];
                 pRemarkCard[nRemarkCard] = pCard;
                 if (tmp) delete [] tmp;
                 nRemarkCard++;
            }
            pCard = pCard->Next();
       }
       return pRemarkCard;
}

int* _MAXIT::get_blocks_of_remarks(const int nRemarkCard, int &num_block,
                 One_Card_Info_Format **pRemarkCard)
{
       int i, j, *index = NULL, flag = 0;

       num_block = 0;
       for (i = 0; i < nRemarkCard; i++) {
            if (strcmp(pRemarkCard[i]->Field(2), ""))
                 flag = 1;
            else {
                 if (flag) num_block++;
                 flag = 0;
            }
       }
       if (flag) num_block++;
       if (num_block) {
            index = new int[2 * num_block];
            j = 0; flag = 0;
            for (i = 0; i < nRemarkCard; i++) {
                 if (strcmp(pRemarkCard[i]->Field(2), "")) {
                      if (!flag) index[2 * j] = i;
                      index[2 * j + 1] = i;
                      flag = 1;
                 } else {
                      if (flag) j++;
                      flag = 0;
                 }
            }
       }
       return index;
}

void _MAXIT::pdb_to_ndb_postprocessing()
{
       int i = 0, jrnl_id = -1, RNOCUT_TOKEN = -1;
       char temp_string[800];
       One_Card_Info_Format *pJrnlCard = NULL, *pCard = NULL;
       One_Card_Info_Format *qCard = NULL, *rCard = NULL, *tCard = NULL;

       jrnl_id = find_jrnl_id("REF");
       pJrnlCard = _JrnlCardInfo[jrnl_id].Head();
       while (pJrnlCard) {
            pJrnlCard->MixCaseField(4);
            pJrnlCard = pJrnlCard->Next();
       }
       jrnl_id = find_jrnl_id("AUTH");
       pJrnlCard = _JrnlCardInfo[jrnl_id].Head();
       while (pJrnlCard) {
            pJrnlCard->MixCaseField(4);
            pJrnlCard = pJrnlCard->Next();
       }
       jrnl_id = find_jrnl_id("TITL");
       pJrnlCard = _JrnlCardInfo[jrnl_id].Head();
       while (pJrnlCard) {
            pJrnlCard->MixCaseField(4);
            pJrnlCard = pJrnlCard->Next();
       }
       jrnl_id = find_jrnl_id("PUBL");
       pJrnlCard = _JrnlCardInfo[jrnl_id].Head();
       while (pJrnlCard) {
            pJrnlCard->MixCaseField(4);
            pJrnlCard = pJrnlCard->Next();
       }
       jrnl_id = find_jrnl_id("EDIT");
       pJrnlCard = _JrnlCardInfo[jrnl_id].Head();
       while (pJrnlCard) {
            pJrnlCard->MixCaseField(4);
            pJrnlCard = pJrnlCard->Next();
       }
       pJrnlCard = _CardInfo[AUTHOR_TOKEN-1].Head();
       while (pJrnlCard) {
            pJrnlCard->MixCaseField(2);
            pJrnlCard = pJrnlCard->Next();
       }

       RNOCUT_TOKEN = find_card_id("RNOCUT");
       pCard = _CardInfo[REFMET_TOKEN-1].Head();
       if (pCard) {
            if (!strncasecmp(pCard->Field(3), "SHELX", 5)) {
                 qCard = _CardInfo[RFACTR_TOKEN-1].Head();
                 if (qCard) {
                      if ((rCard = _CardInfo[RNOCUT_TOKEN].Head())) {
                           qCard->AddElementToField(rCard->Field(1), 8);
                           qCard->AddElementToField(rCard->Field(2), 7);
                           tCard = _CardInfo[FREERF_TOKEN-1].Head();
                           if (tCard == NULL) tCard = _CardInfo[FREERF_TOKEN-1].
                                   add_a_new_card(NdbToken[FREERF_TOKEN-1], 0);
                           tCard->AddElementToField(rCard->Field(3), 1);
                           tCard->AddElementToField(rCard->Field(4), 3);
                           tCard->AddElementToField(rCard->Field(5), 4);
                     }
                 } else {
                     if ((rCard = _CardInfo[RNOCUT_TOKEN].Head())) {
                          qCard = _CardInfo[RFACTR_TOKEN-1].
                                    add_a_new_card(NdbToken[RFACTR_TOKEN-1], 0);
                          qCard->AddElementToField("0.000", 4);
                          qCard->AddElementToField(rCard->Field(1), 8);
                          qCard->AddElementToField(rCard->Field(2), 7);

                          tCard = _CardInfo[FREERF_TOKEN-1].Head();
                          if (tCard == NULL) tCard = _CardInfo[FREERF_TOKEN-1].
                                     add_a_new_card(NdbToken[FREERF_TOKEN-1], 0);
                          tCard->AddElementToField(rCard->Field(3), 1);
                          tCard->AddElementToField(rCard->Field(4), 3);
                          tCard->AddElementToField(rCard->Field(5), 4);
                     } 
                 }
            } else if ((!strncasecmp(pCard->Field(3), "TNT", 3) ||
                        !strncasecmp(pCard->Field(3), "NUCLSQ", 6) ||
                        !strncasecmp(pCard->Field(3), "PROLSQ", 6)) &&
                        (rCard = _CardInfo[RNOCUT_TOKEN].Head())) {
                 qCard = _CardInfo[RFACTR_TOKEN-1].Head();
                 if (qCard) {
                      if (!strcmp(qCard->Field(4),"") || strcmp(qCard->Field(4),"") &&
                           fabs(atof(qCard->Field(4))) < 0.1) {
                           if (!strcmp(qCard->Field(8), ""))
                                qCard->AddElementToField(rCard->Field(1), 8);
                      }
                 } else {
                      qCard = _CardInfo[RFACTR_TOKEN-1].
                             add_a_new_card(NdbToken[RFACTR_TOKEN-1], 0);
                      qCard->AddElementToField("0.000", 4);
                      qCard->AddElementToField(rCard->Field(1), 8);
                 }
            } else if (!strncasecmp(pCard->Field(3), "CNS", 3) ||
                       !strncasecmp(pCard->Field(3), "X-PLOR", 6)) {
                 qCard = _CardInfo[RFACTR_TOKEN-1].Head();
                 if (qCard && strcmp(qCard->Field(10), ""))
                      qCard->AddElementToField(qCard->Field(10), 7);
            }
       }
       update_tokens(NDB_FILE_FORMAT_NDB);

       pCard = _CardInfo[XFILES_TOKEN-1].Head();
       while (pCard) {
            for (i = 2; i < pCard->NumField(); i++) {
                 if (strcmp(pCard->Field(i), "")) break;
            }
            if (i < pCard->NumField())
                 pCard = pCard->Next();
            else pCard = _CardInfo[XFILES_TOKEN-1].delete_a_card(pCard);
       }

       pCard = _CardInfo[DTMETH_TOKEN-1].Head();
       if (pCard && !strcmp(pCard->Field(1), "Y")) {
            rCard = _CardInfo[DTMEAS_TOKEN-1].Head();
            if (rCard == NULL) rCard = _CardInfo[DTMEAS_TOKEN-1].
                           add_a_new_card(NdbToken[DTMEAS_TOKEN-1], 0);
            rCard->AddElementToField(pCard->Field(4), 2);
            pCard->AddElementToField("SYNCHROTRON", 4);

            temp_string[0] = '\0';
            if (strcmp(rCard->Field(2), "") && strcmp(rCard->Field(3), "")) 
                 sprintf(temp_string, "%s BEAMLINE %s", rCard->Field(2), rCard->Field(3));
            else if (strcmp(rCard->Field(2), ""))
                 sprintf(temp_string, "%s", rCard->Field(2));
            else if (strcmp(rCard->Field(3), ""))
                 sprintf(temp_string, "BEAMLINE %s", rCard->Field(3));
            ndb_clean_string(temp_string);
            if (temp_string[0] != '\0') {
                 rCard = _CardInfo[RADIAT_TOKEN-1].Head();
                 if (rCard == NULL) rCard = _CardInfo[RADIAT_TOKEN-1].
                        add_a_new_card(NdbToken[RADIAT_TOKEN-1], 0);
                 rCard->AddElementToField(temp_string, 5);
            }
       }

       pCard = _CardInfo[DTWAVE_TOKEN-1].Head();
       while (pCard) {
            pCard->AddElementToField(1, 1);
            pCard->AddElementToField(1, 2);
            pCard = pCard->Next();
       }

       pCard = _CardInfo[WAVLEN_TOKEN-1].Head();
       if (pCard && (strstr(pCard->Field(2), ",") ||
                     strstr(pCard->Field(2), ";"))) {
            pCard->AddElementToField(pCard->Field(2), 3);
            pCard->AddElementToField("", 2);
       }

       RNOCUT_TOKEN = find_card_id("TLSRNG");
       int count = 1;
       pCard = _CardInfo[RNOCUT_TOKEN].Head();
       while (pCard) {
            pCard->AddElementToField(count, 6);
            count++;
            pCard = pCard->Next();
       }

       RNOCUT_TOKEN = find_card_id("TLSGRO");
       pCard = _CardInfo[RNOCUT_TOKEN].Head();
       while (pCard) {
            pCard->AddElementToField("refined", 6);
            pCard = pCard->Next();
       }
}

int _MAXIT::get_entity_index(const char *pdb_chnid, const int is_encapsulated)
{
       if (is_encapsulated) {
            if (_CifObj) {
                 int i, rowNo, entity_id, chain_id;
                 CifString string;
                 ISTable *Table = _CifObj->GetTablePtr(_StructureId, "entity_poly");
                 if (is_empty_table(Table)) return -1;
                 rowNo = Table->GetNumRows();
                 entity_id = Table->GetColumnIndex("entity_id");
                 chain_id = Table->GetColumnIndex("ndb_chain_id");
                 for (i = 0; i < rowNo; i++) {
                      Table->GetCell(string, chain_id, i);
                      if ((!strcmp(pdb_chnid, "") && (string == "" || string == "?" ||
                           string == ".")) || strstr(string.Text(), pdb_chnid)) {
                           Table->GetCell(string, entity_id, i);
                           return (atoi(string.Text()));
                      }
                 }
            }
            return -1;
       } else {
            if (_num_mol == 0) return -1;
            _CHAIN *chain = _molecules[0]->GetFirstChain();
            while (chain) {
                 if (chain->chain_type() != ATOMN_TOKEN &&
                     chain->chain_type() != ATOMP_TOKEN) {
                      chain = _molecules[0]->GetNextChain();
                      continue;
                 }
                 if (!strcmp(chain->PDB_ChainID(), pdb_chnid))
                      return chain->entity_id();
                 chain = _molecules[0]->GetNextChain();
            }
            return -1;
       }
}

int _MAXIT::is_entity_a_protein(const int entity_id)
{
       if (_num_mol == 0) return 0;

       _CHAIN *chain = _molecules[0]->GetFirstChain();
       while (chain) {
            if (chain->entity_id() == entity_id) {
                 if (chain->chain_type() == ATOMP_TOKEN)
                      return 1;
                 else return 0;
            }
            chain = _molecules[0]->GetNextChain();
       }
       return 0;
}

void _MAXIT::insert_a_card(const int entity_id, const int card_id,
                    const int fieldno, char *value)
{
       One_Card_Info_Format *pCard = _CardInfo[card_id].Head();
       while (pCard) {
            if (atoi(pCard->Field(1)) == entity_id) break;
            pCard = pCard->Next();
       }
       if (pCard == NULL)
            pCard = _CardInfo[card_id].add_a_new_card(NdbToken[card_id], 0);
       pCard->AddElementToField(entity_id, 1);
       pCard->AddElementToField(value, fieldno);
}

int _MAXIT::pdb_to_ndb_proc_remark(const int nRemarkCard, One_Card_Info_Format **pRemarkCard,
              const int remark_num, REMARKS *remark, const int repeat)
{
       int i, j, k, count = 0, card_id, field_no, *index = 0;
       char temp_string[MxStrLen], temp_string1[MxStrLen];
       double temp_double;
       BTreeObj<_IIndex> OrderIndex;
       _IIndex idx;
       One_Card_Info_Format *newCard = NULL, *pCard = NULL;

       index = new int[nRemarkCard];
       for (i = 0; i < nRemarkCard; i++) index[i] = 0;
       j = 0;
       for (i = 0; i < nRemarkCard; i++) {
            while (j < remark_num) {
                 if (find_a_match(pRemarkCard[i]->Field(2), &remark[j])) {
                      index[i] = j + 1;
                      count++;
                      break;
                 }
                 j++;
            }
            if (index[i]) {
                 // if (repeat == -1) j = 0;
                 if (repeat) j = 0;
                 else if (j < remark_num && !remark[j].Multiple_Treatment) j++;
            } else j = 0;
       }
       card_id = 0;
       for (i = 0; i < remark_num; i++) {
            if (remark[i].NumField > 1) card_id++;
            else if (strcmp(remark[i].FieldList[0].TokenName, "") ||
                     strcmp(remark[i].FieldList[0].Text, "")) card_id++;
       }
       if (!count || (count < nRemarkCard && nRemarkCard < 8 ||
          count < 4 * nRemarkCard / 5 && nRemarkCard >= 8)  && count < 2 * card_id / 3) {
            delete [] index;
            return 0;
       }

       OrderIndex.Clear();
       newCard = NULL;
       card_id = -1;
       field_no = -1;
       for (k = 0; k < nRemarkCard; k++) {
            if (index[k]) {
                 newCard = NULL;
                 card_id = -1;
                 field_no = -1;
                 j = index[k] - 1;
                 for (i = 0; i < remark[j].NumField; i++) {
                      card_id = find_card_id(remark[j].FieldList[i].TokenName);
                      field_no = remark[j].FieldList[i].FieldId - 1;
                      temp_string[0] = '\0';
                      if (strcmp(remark[j].FieldList[i].TokenName,"") && 
                                 remark[j].FieldList[i].FieldId) {
                           if ((int) strlen(pRemarkCard[k]->Field(2)) >
                                 remark[j].FieldList[i].FieldStCol -
                                 remark[j].FieldList[0].FieldStCol)
                                get_remark_answer(temp_string, pRemarkCard[k], &remark[j], i);
                      }

                      ndb_clean_string(temp_string);
                      ndb_set_string_to_upper(temp_string);
     
                      if (strcmp(temp_string, "NULL") && strcmp(temp_string, "NONE") &&
                          strcmp(temp_string, "N/A") && strcmp(temp_string,"") &&
                          card_id != -1 && strcmp(remark[j].FieldList[i].TokenName,"") &&
                          remark[j].FieldList[i].FieldId) {
                           if (!newCard) {
                                if (remark[j].Multiple_Treatment < 0) {
                                     newCard = _CardInfo[card_id].
                                                      add_a_new_card(NdbToken[card_id], 0);
                                     pCard = NULL;
                                     if (!strcmp(remark[j].FieldList[i].TokenName, "CCPNCS"))
                                          pCard = _CardInfo[NCSGRO_TOKEN-1].Tail();
                                     else if (!strcmp(remark[j].FieldList[i].TokenName, "TLSRNG"))
                                          pCard = _CardInfo[TLSGRO_TOKEN-1].Tail();
                                     if (pCard) newCard->AddElementToField(pCard->Field(1), 1);
                                } else if (repeat > 0) {
                                     idx.set_value(card_id);
                                     if (OrderIndex.Seek(idx) < 0) {
                                          OrderIndex.Add(idx);
                                          newCard = _CardInfo[card_id].
                                                     add_a_new_card(NdbToken[card_id], 0);
                                          if (!strcmp(remark[j].FieldList[i].TokenName, "TTENSR") ||
                                              !strcmp(remark[j].FieldList[i].TokenName, "LTENSR") ||
                                              !strcmp(remark[j].FieldList[i].TokenName, "STENSR")) {
                                               pCard = _CardInfo[TLSGRO_TOKEN-1].Tail();
                                               if (pCard) newCard->AddElementToField(pCard->Field(1), 1);
                                          }
                                     } else if ((!strcmp(remark[j].FieldList[i].TokenName, "ASSEMB") ||
                                                 !strcmp(remark[j].FieldList[i].TokenName, "VIRPAR")) &&
                                                  field_no == 1)
                                          newCard = _CardInfo[card_id].
                                                     add_a_new_card(NdbToken[card_id], 0);
                                     newCard = _CardInfo[card_id].Tail();
                                } else if (remark[j].Multiple_Treatment ==
                                           remark[j].FieldList[i].FieldId) {
                                     newCard = _CardInfo[card_id].Head();
                                     while (newCard) {
                                          if (!strcmp(newCard->Field(field_no), temp_string)) break;
                                          newCard = newCard->Next();
                                     }
                                     if (card_id == XFILES_TOKEN-1 && field_no == 1 && !strcmp(temp_string, "1"))
                                          newCard = _CardInfo[card_id].Head();
                                } else newCard = _CardInfo[card_id].Head();
                                if (!newCard) newCard = _CardInfo[card_id].
                                               add_a_new_card(NdbToken[card_id], 0);
                           }
                           if (remark[j].Special_Treatment == PDB_REMARK_R_VALUE) {
                                temp_double = atof(temp_string) * 100.0;
                                sprintf(temp_string, "%lf", temp_double);
                                newCard->AddElementToField(temp_string, field_no);
                           } else newCard->AddElementToField(temp_string, field_no);
                      }
                 }
            } else if (card_id >= 0 && field_no > 0) {
                 strcpy(temp_string1, pRemarkCard[k]->Field(2));
                 if (strstr(temp_string1, "):") || strstr(temp_string1, " :")) continue; 
                 ndb_clean_string(temp_string1);
                 if (strcmp(temp_string1, "")) {
                      if (!newCard) newCard = _CardInfo[card_id].
                               add_a_new_card(NdbToken[card_id], 0);
                      if (strcmp(newCard->Field(field_no), "")) {
                           newCard->AttachToField(" ", field_no);
                           newCard->AttachToField(temp_string1, field_no);
                      } else newCard->AddElementToField(temp_string1, field_no);
                 }
            }
       }
       delete [] index;
       return 1;
}

int _MAXIT::pdb_to_ndb_proc_remark_special(One_Card_Info_Format *remarkCard,
                  const int remark_no, REMARKS *remark)
{
       if (remarkCard == NULL) return 1;

       int i, j, label, len, pos, card_id, field_no;
       char temp_string[80], temp_string1[80];
       double temp_double;
       One_Card_Info_Format *newCard = NULL;

       for (j = 0; j < remark_no; j++) {
            strcpy(temp_string1, remarkCard->Field(2));
            ndb_set_string_to_upper(temp_string1);
            ndb_strip_leading_blanks(temp_string1);

            label = 0;
            for (i = 0; i < remark[j].NumField; i++) {
                 if (!strcmp(remark[j].FieldList[i].TokenName, "")) {
                      strcpy(temp_string, remark[j].FieldList[i].Text);
                      ndb_set_string_to_upper(temp_string);
                      ndb_strip_leading_blanks(temp_string);
                      len = strlen(temp_string);
                      pos = remark[j].FieldList[i].FieldStCol
                              - remark[j].FieldList[0].FieldStCol;
                      if (string_compare(&temp_string1[pos], temp_string, pos, len)) {
                           label = 1; break;
                      }
                 }
            }
            if (label) continue;

            for (i = 0; i < remark[j].NumField; i++) {
                 card_id = find_card_id(remark[j].FieldList[i].TokenName);
                 field_no = remark[j].FieldList[i].FieldId -1;
                 temp_string[0] = '\0';
                 if (strcmp(remark[j].FieldList[i].TokenName, "") &&
                            remark[j].FieldList[i].FieldId) {
                      get_remark_answer(temp_string, remarkCard, &remark[j], i);
                 }
                 ndb_clean_string(temp_string);
                 ndb_set_string_to_upper(temp_string);

                 if (strcmp(temp_string, "NULL") && strcmp(temp_string, "NONE") &&
                     strcmp(temp_string, "N/A") && strcmp(temp_string,"") &&
                     card_id != -1 && strcmp(remark[j].FieldList[i].TokenName,"") &&
                     remark[j].FieldList[i].FieldId) {
                      newCard = _CardInfo[card_id].Head();
                      if (newCard == NULL) newCard = _CardInfo[card_id].
                            add_a_new_card(NdbToken[card_id], 0);
                      if (remark[j].Special_Treatment == PDB_REMARK_R_VALUE) {
                           temp_double = atof(temp_string) * 100.0;
                           sprintf(temp_string, "%lf", temp_double);
                           newCard->AddElementToField(temp_string, field_no);
                      } else newCard->AddElementToField(temp_string, field_no);
                 }
            }
            return 1;
       }
       return 0;
}

void _MAXIT::pdb_to_ndb_postprocessing_remarks()
{
       int i, j, serial_no;
       char program[1000], authors[200], version[80], name[80], *p, *a;
       One_Card_Info_Format *pCard = NULL, *qCard = NULL;

       pCard = _CardInfo[REFMET_TOKEN-1].Head();
       if (pCard) {
            p = pCard->Field(3);
            a = pCard->Field(4);
            while (p && a) {
                 p = get_words_separate_by_AND(p, program);
                 a = get_words_separate_by_AND(a, authors);
                 get_name_and_version(name, version, program);
                 clean_author_name(authors, name);
                 if (strcmp(name, "") || strcmp(authors, "")) {
                      qCard = _CardInfo[SFTWAR_TOKEN-1].
                              add_a_new_card(NdbToken[SFTWAR_TOKEN-1], 0);
                      qCard->AddElementToField("refinement", 2);
                      if (strcmp(name, ""))
                           qCard->AddElementToField(name, 3);
                      if (strcmp(version, ""))
                           qCard->AddElementToField(version, 4);
                      if (strcmp(authors, ""))
                           qCard->AddElementToField(authors, 5);
                 }
            }
            while (pCard) pCard = _CardInfo[REFMET_TOKEN-1].delete_a_card(pCard);
       }

       pCard = _CardInfo[NMRECD_TOKEN-1].Head();
       if (pCard) {
            p = pCard->Field(2);
            serial_no = 1;
            while (p) {
                 p = get_words(p, program);
                 One_Card_Info_Format *qCard = _CardInfo[NMREXP_TOKEN-1].
                          add_a_new_card(NdbToken[NMREXP_TOKEN-1], 0);
                 qCard->AddElementToField(serial_no, 1);
                 qCard->AddElementToField(1, 2);
                 qCard->AddElementToField(program, 3);
                 qCard->AddElementToField(1, 4);
                 serial_no++;
            }
            while (pCard) pCard = _CardInfo[NMRECD_TOKEN-1].delete_a_card(pCard);
       }

       pCard = _CardInfo[NMRSFT_TOKEN-1].Head();
       if (pCard) {
            p = pCard->Field(2);
            while (p) {
                 p = get_words(p, program);
                 get_name_and_version(name, version, program);
                 if (strcmp(name, "")) {
                      One_Card_Info_Format *qCard = _CardInfo[SFTWAR_TOKEN-1].
                               add_a_new_card(NdbToken[SFTWAR_TOKEN-1], 0);
                      qCard->AddElementToField("structure solution", 2);
                      qCard->AddElementToField(name, 3);
                      if (strcmp(version, ""))
                           qCard->AddElementToField(version, 4);
                 }
            }
            while (pCard) pCard = _CardInfo[NMRSFT_TOKEN-1].delete_a_card(pCard);
       }

       pCard = _CardInfo[NMRSPM_TOKEN-1].Head();
       if (pCard) {
            typedef struct {
                   char buf[100];
            } BUF;
            BUF strengh[10], model[10], maker[10];
            int n_strengh = 0, n_model = 0, n_maker = 0;
            char buffer[100];
            p = pCard->Field(2);
            while (p) {
                 p = get_words(p, buffer);
                 if (strcmp(buffer, "")) {
                      strcpy(model[n_model].buf, buffer);
                      n_model++;
                 }
            }
            p = pCard->Field(3);
            while (p) {
                 p = get_words(p, buffer);
                 if (strcmp(buffer, "")) {
                      strcpy(maker[n_maker].buf, buffer);
                      n_maker++;
                 }
            }
            p = pCard->Field(4);
            while (p) {
                 p = get_words(p, buffer);
                 if (strcmp(buffer, "")) {
                      strcpy(strengh[n_strengh].buf, buffer);
                      n_strengh++;
                 }
            }

            int max_number = n_model;
            if (n_maker > max_number) max_number = n_maker;
            if (n_strengh > max_number) max_number = n_strengh;
            for (i = 0; i < n_strengh; i++) {
                 p = strstr(strengh[i].buf, "MHZ");
                 if (p) *p = '\0';
            }

            while (pCard) pCard = _CardInfo[NMRSPM_TOKEN-1].delete_a_card(pCard);
            
            for (i = 0; i < max_number; i++) {
                 pCard = _CardInfo[NMRSPM_TOKEN-1].
                            add_a_new_card(NdbToken[NMRSPM_TOKEN-1], 0);
                 pCard->AddElementToField(i+1, 1);
                 if (n_model) {
                      j = i;
                      if (j >= n_model) j = n_model - 1;
                      pCard->AddElementToField(model[j].buf, 2);
                 }
                 if (n_maker) {
                      j = i;
                      if (j >= n_maker) j = n_maker - 1;
                      pCard->AddElementToField(maker[j].buf, 3);
                 }
                 if (n_strengh) {
                      j = i;
                      if (j >= n_strengh) j = n_strengh - 1;
                      pCard->AddElementToField(strengh[j].buf, 4);
                 }
            }
       }
       
       pCard = _CardInfo[NMRSMP_TOKEN-1].Head();
       if (pCard) {
            pCard->AddElementToField(1, 1);
            pCard->AddElementToField(1, 2);
       }

       int NMRSDT_TOKEN = find_card_id("NMRSDT");
       pCard = _CardInfo[NMRSDT_TOKEN].Head();
       if (pCard) pCard->AddElementToField(1, 1);
}

void _MAXIT::delete_atom_count()
{
       int card_id = find_card_id("ATNUMS");
       _CardInfo[card_id].clear_Cards();
}

static int find_a_match(const char *context, REMARKS *remark)
{
       char temp_string[80], temp_string1[80], string[80];
       int  label = 0, i, strip_blanks, not_empty, len, pos;

       strcpy(temp_string1, context);
       strip_blanks = 1;
       for (i = 0; i < remark->NumField; i++) {
            if (!strcmp(remark->FieldList[i].TokenName, "") &&
                 strcmp(remark->FieldList[i].Text, "")) {
                 strcpy(temp_string, remark->FieldList[i].Text);
                 ndb_set_string_to_upper(temp_string);
                 ndb_strip_leading_blanks(temp_string);
                 len = strlen(temp_string);
                 if (!len) strip_blanks = 0;
                 break;
            }
       }
       if (strip_blanks) ndb_strip_leading_blanks(temp_string1);

       for (i = 0; i < remark->NumField; i++) {
            if (!strcmp(remark->FieldList[i].TokenName, "") &&
                 strcmp(remark->FieldList[i].Text, "")) {
                 label = 1;
                 strcpy(temp_string, remark->FieldList[i].Text);
                 ndb_set_string_to_upper(temp_string);
                 ndb_strip_leading_blanks(temp_string);
                 len = strlen(temp_string);
                 not_empty = 1;
                 if (!len) {
                      strcpy(temp_string, remark->FieldList[i].Text);
                      not_empty = 0;
                      len = strlen(temp_string);
                 }
                 if (strip_blanks)
                      pos = remark->FieldList[i].FieldStCol
                          - remark->FieldList[0].FieldStCol;
                 else pos = remark->FieldList[i].FieldStCol;
                 if (strncmp(&temp_string1[pos], temp_string, len)) {
                      if (!not_empty) {
                           label = 0;
                           break;
                      }
                      ndb_clean_string(temp_string);
                      strcpy(string, temp_string1);
                      ndb_clean_string(string);
                      len = strlen(temp_string);
                      if (strncmp(string, temp_string, len)) {
                           label = 0;
                           break;
                      }
                 }
            }
       }
       return label;
}

static void clean_middle_space(char *string)
{
       int i, j = 0, k, length;
    
       length = strlen(string);
       for (i = 0; i < length; i++) if (string[i] != ' ') j = i;

       for (i = 0; i < j; i++) {
            if (string[i] == ' ') {
                 for (k = i; k < length - 1; k++)
                      string[k] = string[k+1];
                 length--;
                 j--;
            }
       }
       string[length] = '\0';
}

static int string_compare(const char *remark, const char *string, 
                          const int pos, const int len)
{
       char tmp_remark[80], tmp_tpt[80];
       int  i = 0, j = 0;
       while (i < pos && remark[j - 1] != ' ') {
            i++; j--;
       }
       strncpy(tmp_remark, &remark[j], len);
       strncpy(tmp_tpt, string, len);
       tmp_remark[len] = '\0';
       tmp_tpt[len]    = '\0';
       ndb_strip_leading_blanks(tmp_remark);
       ndb_strip_leading_blanks(tmp_tpt);
       clean_middle_space(tmp_remark);
       clean_middle_space(tmp_tpt);
       return (strcmp(tmp_remark, tmp_tpt));
}

static void get_remark_answer(char *answer, One_Card_Info_Format *remarkCard, 
		REMARKS *remark, int field_no)
{
       int i, k, tmp, end, width, strip_blanks;
       char temp_string[80];

       strcpy(answer, "");
       if (remarkCard == NULL) return;

       strip_blanks = 1;
       strcpy(temp_string, remark->FieldList[0].Text);
       ndb_set_string_to_upper(temp_string);
       ndb_strip_leading_blanks(temp_string);
       k = strlen(temp_string);
       if (!k) strip_blanks = 0;

       strcpy(temp_string, remarkCard->Field(2));
       if (strip_blanks) ndb_strip_leading_blanks(temp_string);

       if (field_no == 0) {
            if (strcmp(temp_string,"NULL") && strcmp(temp_string,"NONE") &&
                strcmp(temp_string,"N/A")) 
                 strncpy(answer, temp_string, remark->FieldList[field_no].FieldWidth);
            else strcpy(answer,  "NULL");
       } else {
            if (strip_blanks) {
                 tmp = remark->FieldList[field_no].FieldStCol
                     - remark->FieldList[0].FieldStCol;
                 end = remark->FieldList[field_no].FieldStCol 
                     - remark->FieldList[0].FieldStCol
                     + remark->FieldList[field_no].FieldWidth;
            } else {
                 tmp = remark->FieldList[field_no].FieldStCol;
                 end = remark->FieldList[field_no].FieldStCol
                     + remark->FieldList[field_no].FieldWidth;
            }
            if (field_no == remark->NumField - 1) {
                if (strip_blanks)
                     k = 67 - remark->FieldList[0].FieldStCol;
                else k = 67;
                if (k > end) end = k;
            }
            if (end > (int) strlen(temp_string)) end = strlen(temp_string);
            for (i = tmp; i < end; i++)
                 if (temp_string[i] != ' ' && temp_string[i] != ':' &&
                     temp_string[i] != ';' && temp_string[i] != '(' &&
                     temp_string[i] != ')') break;
            while (i && temp_string[i-1] != ' ' && temp_string[i-1] != ':' &&
                        temp_string[i-1] != ';' && temp_string[i-1] != '(' &&
                        temp_string[i] != ')') i--;
            width = 0;
            for (k = i; k < end; k++) {
                 if (temp_string[k] == ';') break;
                 if ((remark->FieldList[field_no].FieldType == 1 ||
                      remark->FieldList[field_no].FieldType == 2) &&
                     (temp_string[k] == ' ' || temp_string[k] == '(' ||
                      temp_string[k] == ')')) break;
                 answer[width] = temp_string[k];
                 width++;
            }
            answer[width] = '\0';
       }
}

static void get_name_and_version(char *name, char *version, char *program)
{
       unsigned int i;
       name[0] = '\0'; version[0] = '\0';

       char *p = get_word(program, name);
       while (p) {
            p = get_word(p, version);
       }
       if (strcmp(version, "")) {
            for (i = 0; i < strlen(version); i++)
                 if (!isdigit(version[i]) && version[i] != '.') break;
            if (i == strlen(version)) {
                 p = strstr(program, version);
                 *p = '\0';
            }
       }
       strcpy(name, program);
       ndb_clean_string(name);
}

static void clean_author_name(char *authors, char *name)
{
       char *buff = new char[strlen(name)+3];
       sprintf(buff, "(%s)", name);
       char *p = strstr(authors, buff);
       delete buff;
       if (p) {
            *p = '\0';
            ndb_clean_string(authors);
            return;
       }
       p = strstr(authors, name);
       if (p) {
            *p = '\0';
            ndb_clean_string(authors);
       }
}

