/*
FILE:     cif_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 <ctype.h>
#include <unistd.h>

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

#define N_SWITCH_CATEGORY   3
#define N_R_MERGE           4
#define N_ENTITY           46

typedef struct {
        const char *category;
        const char *high_item;
        const char *low_item;
} _Switch_Category;

typedef struct {
        const char *catetory;
        const char *item;
} _R_Merge;

static _Switch_Category _switch_category[N_SWITCH_CATEGORY] =
{
       { "refine",       "ls_d_res_high",     "ls_d_res_low" },
       { "reflns",       "d_resolution_high", "d_resolution_low" },
       { "reflns_shell", "d_res_high",        "d_res_low" }
};

static _R_Merge _r_merge[N_R_MERGE] =
{
        { "reflns",          "ndb_Rmerge_I_obs" },
        { "reflns",          "ndb_Rsym_value" },
        { "reflns_shell",    "Rmerge_I_obs" },
        { "reflns_shell",    "ndb_Rsym_value" }
};

static const char entity_token[N_ENTITY][7] = {
            "ENTAIL", "ENTKEY", "ENTMUT", "FRAGMT", "ISOTYP", "ECNUM",
            "BINEMD", "BIOUNI", "ENTNAM", "ENTSYS", "PROTEI", "SRCNNM",
            "SRCNSP", "SRCNTS", "SRCNSE", "SRCNDS", "SRCNFR", "SRCNSC",
            "SRCNCC", "SRCNOR", "SRCNPL", "SRCGFR", "SRCGNM", "SRCNN1",
            "SRCGST", "SRCGSP", "SRCGCC", "SRCGTS", "SRCGTI", "SRCGDS",
            "SRCSYN", "SRCGE1", "SRCGE2", "SRCGE3", "SRCGE4", "SRCGE5",
            "SRCGHN", "SRCGHS", "SRCGH1", "SRCGHT", "SRCGHV", "SRCGHC",
            "SRCGVE", "SRCGHD", "SRCGPL", "TARGET"
};

#define NUM_CENTER  20

static const int is_psi_center[NUM_CENTER] = { 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1 };

static const char *_full_name_of_center[NUM_CENTER] = {
       "Bacterial targets at IGS-CNRS, France",
       "Berkeley Structural Genomics Center",
       "Center for Eukaryotic Structural Genomics",
       "Israel Structural Proteomics Center", 
       "Joint Center for Structural Genomics",
       "Marseilles Structural Genomics Program @ AFMB",
       "Midwest Center for Structural Genomics",
       "Montreal-Kingston Bacterial Structural Genomics Initiative",
       "Mycobacterium Tuberculosis Structural Proteomics Project",
       "New York Structural Genomics Research Consortium",
       "Northeast Structural Genomics Consortium",
       "Oxford Protein Production Facility",
       "Paris-Sud Yeast Structural Genomics",
       "Protein Structure Factory",
       "RIKEN Structural Genomics/Proteomics Initiative",
       "Southeast Collaboratory for Structural Genomics",
       "Structural Genomics of Pathogenic Protozoa Consortium",
       "Structural Proteomics in Europe",
       "Structure 2 Function Project",
       "TB Structural Genomics Consortium"
};

static const char *_initials_of_center[NUM_CENTER] = {
       "BIGS",
       "BSGC",
       "CESG",
       "ISPC",
       "JCSG",
       "MSGP",
       "MCSG",
       "BSGI",
       "XMTB",
       "NYSGRC",
       "NESG",
       "OPPF",
       "YSG",
       "PSF", 
       "RSGI",
       "SECSG",
       "SGPP",
       "SPINE",
       "S2F",
       "TBSGC"
};

static int get_number_strands(ISTable *Table, const char *sheet_id);
static int get_sense(ISTable *Table, const char *sheet_id, const char *id_1, const char *id_2);
static void get_hbond(_MOLECULE *mol, ISTable *Table, const int chain_index,
                 const char *sheet_id, const char *range_id, CifString &curAtom, int &curIndex,
                 int &curRes, CifString &prevAtom, int &prevIndex, int &prevRes);
static void cif_to_ndb_find_serial_no(ISTable *Table, const int id, const int irow,
         const int tokenid, int *idfield, char idvalue[10][82], char SerialNo[10][82]);

void _MAXIT::cif_to_ndb_general(const int transfer, const int flag, const int special,
       const int recover_asym, const int exchange, const int together,
       const int short_version, const int symmetry_flag, const int is_nmr_view)
{
       int fd, i, k, is_same, card_id, rowNo, entity_id, full_index, initial_index;
       int is_PSI_entry = 0, is_SG_entry = 0, name_index, db_name_index, db_id_index;
       int project_index, rowNo1, target_index, len;
       char buffer[5000], buffer1[100], *p = NULL;
       CifString cifstring, cifstring1, target, project, full_name, initials;
       ISTable *Struct_Ref = NULL, *Table = NULL;
       One_Card_Info_Format *pCard = NULL;
       ReVarCifArray<CifString> colData;

       int input_format = NDB_FILE_FORMAT_PDB;
       read_mmcif_file(input_format, special, exchange, short_version, symmetry_flag, 0, is_nmr_view);

       ndb_processing_requests();
       ndb_processing_em_software();
       ndb_processing_struct_category();
       ndb_processing_struct_sheet_hbond();
       ndb_processing_ndb_database_PDB_obs_spr_category();
       ndb_processing_struct_ref_seq_and_diff();

       if (transfer != 2) seq_alignment(1);
       if (_file_status == FILE_STATUS_MMCIF_PLUS_MOL) {
            char filename[100], line[200];
            char templateFileName[9] = "./XXXXXX";
            strcpy(filename, templateFileName);
            fd = mkstemp(filename);
            close (fd);
            FILE *tlog = fopen(filename, "w");
            ndb_check_file(tlog, NUM_TOKEN, Check_Format, NUM_CHECK_CATEGORY,
                     check_category, 1, 0);
            input_structural_features(NDB_FILE_FORMAT_PDB);
            fclose (tlog);
            tlog = fopen(filename, "r");
            CifString message("");
            while (!feof(tlog)) {
                 fgets(line, 199, tlog);
                 if (feof(tlog)) break;
                 message += line;
            }
            fclose (tlog);
            sprintf(line, "rm -f %s", filename);
            system(line);
            if (message != "") ndb_log_message(NDB_MSG_WARN, "%s\n", message.Text());
       }
       if (flag) processing_r_factor(100.0);

       Table = _CifObj->GetTablePtr(_StructureId, "pdbx_SG_project");
       if (!is_empty_table(Table)) {
            project_index = Table->GetColumnIndex("project_name");
            full_index = Table->GetColumnIndex("full_name_of_center");
            initial_index = Table->GetColumnIndex("initial_of_center");
            rowNo1 = Table->GetNumRows();
            for (k = 0; k < rowNo1; k++) {
                 cifstring.Clear();
                 Table->GetCell(cifstring, full_index, k);
                 for (i = 0; i < NUM_CENTER; i++) {
                      if (!strcasecmp(cifstring.Text(), _full_name_of_center[i])) {
                           cifstring.Copy(_full_name_of_center[i]);
                           Table->UpdateCell(cifstring, full_index, k);
                           cifstring.Copy(_initials_of_center[i]);
                           Table->UpdateCell(cifstring, initial_index, k);
                           _CifObj->WriteTable(Table, _StructureId, "pdbx_SG_project");
                           is_SG_entry = 1;
                           if (is_psi_center[i]) is_PSI_entry = 1;
                           break;
                      }
                 }
            }

            if (is_SG_entry) {
                 Struct_Ref = _CifObj->GetTablePtr(_StructureId, "ndb_database_status");
                 if (!is_empty_table(Struct_Ref)) {
                      cifstring.Copy("Y");
                      name_index = Struct_Ref->GetColumnIndex("SG_entry");
                      if (name_index < 0) {
                           Struct_Ref->AddColumn("SG_entry");
                           name_index = Struct_Ref->GetColumnIndex("SG_entry");
                           colData.Clear();
                           colData.Add(cifstring);
                           Struct_Ref->FillColumn(colData, name_index);
                      }
                      Struct_Ref->UpdateCell(cifstring, name_index, 0);
                      _CifObj->WriteTable(Struct_Ref, _StructureId, "ndb_database_status");
                 }

                 for (k = 0; k < rowNo1; k++) {
                      Table->GetCell(project, project_index, k);
                      if (project == "?" || project == ".") project.Copy("");
                      Table->GetCell(full_name, full_index, k);
                      if (full_name == "?" || full_name == ".") full_name.Copy("");
                      Table->GetCell(initials, initial_index, k);
                      if (initials == "?" || initials == ".") initials.Copy("");
     
                      if (full_name != "") {
                           Struct_Ref = _CifObj->GetTablePtr(_StructureId, "audit_author");
                           if (is_empty_table(Struct_Ref)) {
                                _CifObj->DeleteTable(_StructureId, "audit_author");
                                Struct_Ref = new ISTable("audit_author");
                                Struct_Ref->AddColumn("name");
                                _CifObj->WriteTable(Struct_Ref, _StructureId, "audit_author");
                           }
                           name_index = Struct_Ref->GetColumnIndex("name");
                           rowNo = Struct_Ref->GetNumRows();
                           for (i = 0; i < rowNo; i++) {
                                Struct_Ref->GetCell(cifstring, name_index, i);
                                if (strstr(cifstring.Text(), full_name.Text()) &&
                                    strstr(cifstring.Text(), initials.Text())) break;
                           }
                           if (i == rowNo) {
                                Struct_Ref->AddRow();
                                cifstring.Copy(full_name.Text());
                                if (initials != "") {
                                     cifstring += " (";
                                     cifstring += initials.Text();
                                     cifstring += ")";
                                }
                                Struct_Ref->UpdateCell(cifstring, name_index, rowNo);
                                _CifObj->WriteTable(Struct_Ref, _StructureId, "audit_author");
                           }
                      }
     
                      Struct_Ref = _CifObj->GetTablePtr(_StructureId, "struct_keywords");
                      if (is_empty_table(Struct_Ref)) {
                           _CifObj->DeleteTable(_StructureId, "struct_keywords");
                           Struct_Ref = new ISTable("struct_keywords");
                           Struct_Ref->AddColumn("entry_id");
                           Struct_Ref->AddColumn("ndb_keywords");
                           Struct_Ref->AddColumn("text");
                           Struct_Ref->AddRow();
                           cifstring.Copy(_StructureId);
                           Struct_Ref->UpdateCell(cifstring, 0, 0);
                           _CifObj->WriteTable(Struct_Ref, _StructureId, "struct_keywords");
                      }
                      name_index = Struct_Ref->GetColumnIndex("text");
                      cifstring.Clear();
                      Struct_Ref->GetCell(cifstring, name_index, 0);
                      if (cifstring == "?" || cifstring == ".") cifstring.Clear();
                      strcpy(buffer, cifstring.Text());
                      ndb_set_string_to_upper(buffer);
                      if (!strstr(buffer, "STRUCTURAL GENOMICS")) {
                           if (cifstring != "") cifstring += ", ";
                           cifstring += "Structural Genomics";
                      }
                      if (is_PSI_entry) {
                           if (!strstr(buffer, "PSI")) {
                                if (cifstring != "") cifstring += ", ";
                                cifstring += "PSI";
                           }
                           if (!strstr(buffer, "PROTEIN STRUCTURE INITIATIVE")) {
                                if (cifstring != "") cifstring += ", ";
                                cifstring += "Protein Structure Initiative"; 
                           }
                      } else {
                           strcpy(buffer1, project.Text());
                           ndb_set_string_to_upper(buffer1);
                           if (strcmp(buffer1, "") && !strstr(buffer, buffer1)) {
                                if (cifstring != "") cifstring += ", ";
                                cifstring += project.Text();
                           }
                      }
                      strcpy(buffer1, full_name.Text());
                      ndb_set_string_to_upper(buffer1);
                      if (strcmp(buffer1, "") && !strstr(buffer, buffer1)) {
                           if (cifstring != "") cifstring += ", ";
                           cifstring += full_name.Text();
                      }
                      strcpy(buffer1, initials.Text());
                      ndb_set_string_to_upper(buffer1);
                      if (strcmp(buffer1, "") && !strstr(buffer, buffer1)) {
                           if (cifstring != "") cifstring += ", ";
                           cifstring += initials.Text();
                      }
                      Struct_Ref->UpdateCell(cifstring, name_index, 0);
                      _CifObj->WriteTable(Struct_Ref, _StructureId, "struct_keywords");
                 }
           
                 Table = _CifObj->GetTablePtr(_StructureId, "entity_poly"); 
                 if (!is_empty_table(Table)) {
                      target_index = Table->GetColumnIndex("pdbx_target_identifier");
                      rowNo1 = Table->GetNumRows();
                      for (i = 0; i < rowNo1; i++) {
                           cifstring.Clear();
                           Table->GetCell(cifstring, target_index, i);
                           if (cifstring == "." || cifstring == "?") cifstring.Clear();
                           if (cifstring != "") break;
                      }
                      if (i < rowNo1) {
                           Struct_Ref = _CifObj->GetTablePtr(_StructureId, "rcsb_database_related");
                           if (is_empty_table(Struct_Ref)) {
                                _CifObj->DeleteTable(_StructureId, "rcsb_database_related");
                                Struct_Ref = new ISTable("rcsb_database_related");
                                Struct_Ref->AddColumn("db_name");
                                Struct_Ref->AddColumn("db_id");
                                _CifObj->WriteTable(Struct_Ref, _StructureId, "rcsb_database_related");
                           }
                           db_name_index = Struct_Ref->GetColumnIndex("db_name");
                           db_id_index = Struct_Ref->GetColumnIndex("db_id");
                           rowNo = Struct_Ref->GetNumRows();
                           for (k = 0; k < rowNo1; k++) {
                                target.Clear();
                                Table->GetCell(target, target_index, k);
                                if (target == "." || target == "?" || target == "") continue; 

                                strcpy(buffer, target.Text());
                                len = strlen(buffer);
                                for (i = 0; i < len; i++) {
                                     if (buffer[i] == ',' || buffer[i] == ';') buffer[i] = ' ';
                                }
                                ndb_clean_string(buffer);

                                p = buffer;
                                while (p) {
                                     p = get_word(p, buffer1);
                                     if (!strcmp(buffer1, "")) continue;

                                     for (i = 0; i < rowNo; i++) {
                                          Struct_Ref->GetCell(cifstring, db_name_index, i);
                                          Struct_Ref->GetCell(cifstring1, db_id_index, i);
                                          if (!strcasecmp(cifstring.Text(), "TargetDB") &&
                                              !strcasecmp(cifstring1.Text(), buffer1)) break;
                                     }
                                     if (i == rowNo) {
                                          Struct_Ref->AddRow();
                                          cifstring.Copy("TargetDB");
                                          Struct_Ref->UpdateCell(cifstring, db_name_index, rowNo);
                                          cifstring.Copy(buffer1);
                                          Struct_Ref->UpdateCell(cifstring, db_id_index, rowNo);
                                          _CifObj->WriteTable(Struct_Ref, _StructureId, "rcsb_database_related");
                                          rowNo++;
                                     }
                                }
                           }
                      }
                 }
            }
       }

       ndb_processing_categories_mapping(transfer);

       if (transfer != 2) {
            find_missing_residues();
            // update_pdb_and_pub_numbers();
            // Input_Stbiol();
            if (!recover_asym) Get_Stbiol(exchange);
            Reorder_Stbiol();
            Input_Entity();
            get_seqifo(0, together);
            match_entity_with_molecules();
            match_stbiol_with_molecules();
            if (_file_status == FILE_STATUS_MMCIF_PLUS_MOL) {
                 is_same = 1;
                 for (i = 0; i < _n_entity; i++) {
                      if (_entity[i].Entity_ID != _entity[i].Old_Entity_ID) {
                           is_same = 0; break;
                      }
                 }
                 if (!is_same) {
                      for (i = 0; i < N_ENTITY; i++) {
                           card_id = find_card_id(entity_token[i]);
                           if (card_id == -1) continue;
                           pCard = _CardInfo[card_id].Head();
                           while (pCard) {
                                for (k = 0; k < _n_entity; k++) {
                                     if (!strcmp(entity_token[i], "BINEMD")) {
                                          if (atoi(pCard->Field(3)) == _entity[k].Old_Entity_ID) {
                                               pCard->AddElementToField(_entity[k].Entity_ID, 3);
                                               break;
                                          }
                                     } else {
                                          if (atoi(pCard->Field(1)) == _entity[k].Old_Entity_ID) {
                                               pCard->AddElementToField(_entity[k].Entity_ID, 1);
                                               break;
                                          }
                                     }
                                }
                                pCard = pCard->Next();
                           }
                           _CardInfo[card_id].reorder_cards(1, INTEGER_COMPARE, ASCENT);
                      }

                      Table = _CifObj->GetTablePtr(_StructureId, "rcsb_entity_name");
                      if (!is_empty_table(Table)) {
                           rowNo = Table->GetNumRows();
                           entity_id = Table->GetColumnIndex("entity_id");
                           if (entity_id >= 0) {
                                for (i = 0; i < rowNo; i++) {
                                     get_value(cifstring, Table, entity_id, i);
                                     if (cifstring != "") {
                                          for (k = 0; _n_entity; k++) {
                                               if (atoi(cifstring.Text()) == _entity[k].Old_Entity_ID) {
                                                    sprintf(buffer, "%d", _entity[k].Entity_ID);
                                                    cifstring.Copy(buffer);
                                                    Table->UpdateCell(cifstring, entity_id, i);
                                                    break;
                                               }
                                          }
                                     }
                                }
                           }
                           _CifObj->WriteTable(Table, _StructureId, "rcsb_entity_name");
                      }

                      Struct_Ref = _CifObj->GetTablePtr(_StructureId, "struct_ref");
                      if (!is_empty_table(Struct_Ref)) {
                           rowNo = Struct_Ref->GetNumRows();
                           entity_id = Struct_Ref->GetColumnIndex("entity_id");
                           if (entity_id >= 0) {
                                for (i = 0; i < rowNo; i++) {
                                     get_value(cifstring, Struct_Ref, entity_id, i);
                                     if (cifstring != "") {
                                          for (k = 0; _n_entity; k++) {
                                               if (atoi(cifstring.Text()) == _entity[k].Old_Entity_ID) {
                                                    sprintf(buffer, "%d", _entity[k].Entity_ID);
                                                    cifstring.Copy(buffer);
                                                    Struct_Ref->UpdateCell(cifstring, entity_id, i);
                                                    break;
                                               }
                                          }
                                     }
                                }
                           }
                           _CifObj->WriteTable(Struct_Ref, _StructureId, "struct_ref");
                      }
                 }
            }
            Table = _CifObj->GetTablePtr(_StructureId, "rcsb_struct_link");
            if (!is_empty_table(Table)) cifndb_process_rcsb_link(Table);

            get_entity_card();
            get_compnd_card();
       }

       check_terminal_atoms(cifstring);
       if (strcmp(cifstring.Text(), "")) ndb_log_message(NDB_MSG_WARN, "%s\n", cifstring.Text());

       post_processing_from_cif_to_ndb();
}

void _MAXIT::cif_to_ndb_exchange(const int exchange, const int is_nmr_view)
{
       int input_format = NDB_FILE_FORMAT_PDB;

       read_mmcif_file(input_format, 0, exchange, 0, 0, 0, is_nmr_view);
       seq_alignment(0);
       ndb_processing_em_software();
       ndb_processing_struct_category();
       ndb_processing_struct_sheet_hbond();
       ndb_processing_ndb_database_PDB_obs_spr_category();
       ndb_processing_struct_ref_seq_and_diff();
       processing_r_factor(100.0);
       ndb_processing_categories_mapping(0);
       Get_Stbiol(exchange);
}

void _MAXIT::ndb_processing_categories_mapping(const int transfer)
{
       int i, card_id, struct_ref_id = -1;
       ISTable *Struct_Ref = NULL, *Table = NULL;

       for (i = 0; i < MxCategory; i++) {
            if (transfer && !(transfer & CifCategory[i].transfer)) continue;
            if (!strcmp(CifCategory[i].category, "struct_conf_type") ||
                !strcmp(CifCategory[i].category, "struct_conn_type") ||
                !strcmp(CifCategory[i].category, "struct_sheet_order") ||
                !strcmp(CifCategory[i].category, "struct_sheet_range") ||
                !strcmp(CifCategory[i].category, "struct_sheet_hbond") ||
                !strcmp(CifCategory[i].category, "rcsb_struct_sheet_hbond") ||
                !strcmp(CifCategory[i].category, "atom_site") ||
                !strcmp(CifCategory[i].category, "atom_site_anisotrop") ||
                !strcmp(CifCategory[i].category, "struct_asym") ||
                !strcmp(CifCategory[i].category, "entity_poly_seq") ||
                !strcmp(CifCategory[i].category, "ndb_nonstandard_list") ||
                !strcmp(CifCategory[i].category, "ndb_poly_seq_scheme") ||
                !strcmp(CifCategory[i].category, "database_PDB_rev_record"))
                 continue;

            Table = _CifObj->GetTablePtr(_StructureId, CifCategory[i].category);
            if (is_empty_table(Table)) continue;

            if (!strcmp(CifCategory[i].category, "struct_ref")) {
                 Struct_Ref = Table;
                 struct_ref_id = i;
                 continue;
            } if (!strcmp(CifCategory[i].category, "struct_conf"))
                 cifndb_process_struct_conf(Table);
            else if (!strcmp(CifCategory[i].category, "struct_sheet"))
                 cifndb_process_sheet();
            else if (!strcmp(CifCategory[i].category, "struct_conn"))
                 cifndb_process_struct_conn(Table);
            else if (!strcmp(CifCategory[i].category, "refine_ls_restr")) 
                 cifndb_process_refine_ls_restr(Table);
            else if (!strcmp(CifCategory[i].category, "struct_site_gen")) 
                 cifndb_process_struct_site_gen(Table);
            else if (!strcmp(CifCategory[i].category, "rcsb_struct_link"))
                 cifndb_process_rcsb_link(Table);
            else if (!strcmp(CifCategory[i].category, "database_PDB_rev"))
                 cifndb_process_database_pdb_rev(Table);
            else if (!strcmp(CifCategory[i].category, "database_PDB_remark") ||
                     !strcmp(CifCategory[i].category, "rcsb_database_PDB_remark")) {
                 if (!strcmp(CifCategory[i].category, "database_PDB_remark"))
                      cifndb_process_remark(Table, PREMRK_TOKEN-1, 2);
                 else {
                      card_id = find_card_id("PDBRMK");
                      cifndb_process_remark(Table, card_id, 3);
                 }
            } else if (!strcmp(CifCategory[i].category, "ndb_database_remark") ||
                     !strcmp(CifCategory[i].category, "ndb_pdb_compnd") ||
                     !strcmp(CifCategory[i].category, "ndb_pdb_source")) {
                 cifndb_process_general_category(Table, i, 1);
            } else if (CifCategory[i].general)
                 cifndb_process_general_category(Table, i, 0);
            else if (CifCategory[i].xray_or_nmr & 4)
                 cifndb_process_matrix(Table, i);
            else cifndb_process_category(Table, i, 0);
       }
       if (Struct_Ref) cifndb_process_category(Struct_Ref, struct_ref_id, 1);
}

void _MAXIT::cifndb_process_category(ISTable *Table, const int id, const int is_special)
{
       int  i, j, k, irow, icol, tokenid, jrnlid, fieldno;
       int  idfield[10], SerialNoField[10], cols[200];
       char SerialNo[10][82], idValue[10][82];
       CifString string;

       int colNo = Table->GetNumColumns();
       int rowNo = Table->GetNumRows();
       ReVarCifArray<CifString> *ColumnNames = Table->GetColumnNames();

       for (i = 0; i < 10; i++) idfield[i] = -1;
       for (i = 0; i < colNo; i++) {
            for (j = 0; j < CifCategory[id].nkeywords; j++) {
                 if (!strcasecmp((*ColumnNames)[i].Text(),
                        CifCategory[id].keywords[j].name)) break;
            }
            if (j == CifCategory[id].nkeywords) cols[i] = -1;
            else                                cols[i] = j;
            for (k = 0; k < CifCategory[id].nCifKeyField; k++) {
                 if (j == CifCategory[id].CifKeyField[k]) idfield[k] = i;
            }
       }
       if (ColumnNames) delete ColumnNames;

       for (irow = 0; irow < rowNo; irow++) {
            for (icol = 0; icol < colNo; icol++) {
                 j = cols[icol];
                 if (j < 0 || j > CifCategory[id].nkeywords) continue;
                 Table->GetCell(string, icol, irow);
                 if (string == "" || string == "." || string == "?") continue;

                 for (i = 0; i < CifCategory[id].keywords[j].numNdbInfo; i++) {
                      tokenid = CifCategory[id].keywords[j].NdbInfo[i].NdbTokenId-1;
                      jrnlid  = CifCategory[id].keywords[j].NdbInfo[i].JrnlTokenId-1;
                      fieldno = CifCategory[id].keywords[j].NdbInfo[i].NdbFieldNo-1;
                      for (k = 0; k < CifCategory[id].nCifKeyField; k++)
                           SerialNoField[k] = CifCategory[id].keywords[j].
                                       NdbInfo[i].NdbTokenKeyFieldNo[k];

                      if (tokenid < 0 || tokenid >= MxTokens || fieldno <= 0) continue;
                      cif_to_ndb_find_serial_no(Table, id, irow, tokenid, idfield,
                                       idValue, SerialNo);

                      if (CifCategory[id].nCifKeyField) {
                           for (k = 0; k < CifCategory[id].nCifKeyField; k++) {
                                if (strcmp(idValue[k], "") && strcasecmp(idValue[k],
                                    CifCategory[id].keywords[j].NdbInfo[i].
                                       JrnlTokenName_Type)) break;
                           }
                           if (k < CifCategory[id].nCifKeyField) continue;
                      }
        
                      if (tokenid == JRNL_TOKEN - 1) {
                           if (!strcasecmp(JrnlToken[jrnlid].TokenName, "AUTH") &&
                               !strcasecmp(CifCategory[id].category, "citation"))
                                continue;

                           cifndb_process_general(jrnlid, fieldno, 
                              CifCategory[id].nCifKeyField, SerialNoField, 
                                 SerialNo, string.Text(), TRUE);
                      } else if (is_special)
                           cifndb_process_special(tokenid, fieldno,
                                   CifCategory[id].nCifKeyField,
                                   SerialNoField, SerialNo, string.Text());
                      else cifndb_process_general(tokenid, fieldno, 
                                   CifCategory[id].nCifKeyField, 
                                   SerialNoField, SerialNo, string.Text(), FALSE);
                 }
            }
       }
}

void _MAXIT::cifndb_process_general(const int tokenid, const int fieldno, 
	      const int NumKey, int *SerialNoField, char SerialNo[10][82], 
              char *value, const int IsJrnl)
{
       One_Card_Info_Format *pCard = NULL;
       int i, vField = 5, logical = FALSE, jrnl_id;
       char buffer[1000];

       if (tokenid == NDBFIL_TOKEN - 1 &&
          !strcasecmp(value, "DEPOSIT-0")) {
            pCard = _CardInfo[tokenid].Head();
            if (pCard && strcmp(pCard->Field(fieldno), "")) return;
       }

       if (IsJrnl) {
            pCard = _JrnlCardInfo[tokenid].Head();
            while (pCard) {
                 if (NumKey) {
                      for (i = 0; i < NumKey; i++) {
                           if (SerialNoField[i] > 0 && strcasecmp(SerialNo[i],
                               pCard->Field(SerialNoField[i]))) break;
                      }
                      if (i == NumKey) break;
                 } else if (JrnlToken[tokenid].SeqField != 0 && !strcasecmp(SerialNo[0],
                   pCard->Field(JrnlToken[tokenid].SeqField-1)))
                      break;
                 else if (!strcmp(pCard->Field(fieldno), "")) break;
                 pCard = pCard->Next();
            }
       } else if (tokenid == AUTHOR_TOKEN-1)
            pCard = _CardInfo[tokenid].Tail();
       else {
            pCard = _CardInfo[tokenid].Head();
            while (pCard) {
                 if (NumKey) {
                      for (i = 0; i < NumKey; i++) {
                           if (SerialNoField[i] > 0 && strcasecmp(SerialNo[i], 
                               pCard->Field(SerialNoField[i]))) break;
                      }
                      if (i == NumKey) break;
                 } else if (NdbToken[tokenid].SeqField != 0 && !strcasecmp(SerialNo[0],
                   pCard->Field(NdbToken[tokenid].SeqField-1)))
                      break;
                 else if ((tokenid == HEADER_TOKEN - 1 ||
                           tokenid == PDBFIL_TOKEN - 1 ||
                           tokenid == NDBFIL_TOKEN - 1) &&
                          !strcasecmp(value, pCard->Field(fieldno))) break;
                 else if (!strcmp(pCard->Field(fieldno), "")) break;
                 pCard = pCard->Next();
            }
       }

       if (IsJrnl && pCard == NULL) {
            pCard = _JrnlCardInfo[tokenid].add_a_new_card(JrnlToken[tokenid], 1);
            if (NumKey) {
                 for (i = 0; i < NumKey; i++) {
                      if (SerialNoField[i] > 0)
                           pCard->AddElementToField(SerialNo[i], SerialNoField[i]);
                 }
            } else if (atoi(SerialNo[0]) != 0 && JrnlToken[tokenid].SeqField != 0)
                 pCard->AddElementToField(SerialNo[0], JrnlToken[tokenid].SeqField-1);
       } else if (!IsJrnl && pCard == NULL) {
            pCard = _CardInfo[tokenid].add_a_new_card(NdbToken[tokenid], 0);
            if (NumKey) {
                 for (i = 0; i < NumKey; i++) {
                      if (SerialNoField[i] > 0) 
                           pCard->AddElementToField(SerialNo[i], SerialNoField[i]);
                 }
            } else if (strcmp(SerialNo[0], "") && NdbToken[tokenid].SeqField != 0)
                 pCard->AddElementToField(SerialNo[0], NdbToken[tokenid].SeqField-1);
       }

       for (i = 0; i < NumKey; i++) {
            if (fieldno == SerialNoField[i]) logical = TRUE;
       }
       if (!IsJrnl && (logical || fieldno == NdbToken[tokenid].SeqField - 1) ||
           IsJrnl && fieldno == JrnlToken[tokenid].SeqField -1) {}
       else if (!IsJrnl && !strcmp(NdbToken[tokenid].TokenName, "AUTHOR")) {
            ndb_name_conversion_first_last(value);
            if (!strcmp(pCard->Field(fieldno), ""))
                 strcpy(buffer, value);
            else sprintf(buffer, "%s, %s", pCard->Field(fieldno), value);
            pCard->AddElementToField(buffer, fieldno);
       } else if (!IsJrnl || IsJrnl && (!strcmp(pCard->Field(fieldno), "") ||
            strcmp(JrnlToken[tokenid].TokenName, "AUTH") &&
            strcmp(JrnlToken[tokenid].TokenName, "EDIT"))) {
            if (IsJrnl) {
                 jrnl_id = find_jrnl_id("REF");
                 if (jrnl_id == tokenid &&  fieldno == vField + 1)
                      pCard->AddElementToField("V.", vField);
                 if (!strcmp(JrnlToken[tokenid].TokenName, "AUTH") ||
                     !strcmp(JrnlToken[tokenid].TokenName, "EDIT"))
                      ndb_name_conversion_first_last(value);
            }
            pCard->AddElementToField(value, fieldno);
       } else if (atoi(SerialNo[0]) == 
           atoi(pCard->Field(JrnlToken[tokenid].SeqField-1))) {
            ndb_name_conversion_first_last(value);
            sprintf(buffer, "%s, %s", pCard->Field(fieldno), value);
            pCard->AddElementToField(buffer, fieldno);
       }
}

void _MAXIT::cifndb_process_special(const int tokenid, const int fieldno,
              const int NumKey, int *SerialNoField, char SerialNo[10][82],
              const char *value)
{
       int i;
       One_Card_Info_Format *pCard = _CardInfo[tokenid].Head();
       while (pCard) {
            for (i = 0; i < NumKey; i++) {
                 if (SerialNoField[i] > 0 && strcmp(SerialNo[i],
                       pCard->Field(SerialNoField[i]))) break;
            }
            if (i == NumKey) pCard->AddElementToField(value, fieldno);
            pCard = pCard->Next();
       }
}

void _MAXIT::cifndb_process_general_category(ISTable *Table, const int id, 
             const int is_remark)
{
       int ndb_tokenid = -1, ndb_fieldno, i, j, tmp_id, row, col;
       char value[10000], buffer[62], *p;
       CifString string;
       One_Card_Info_Format *pCard = NULL, *qCard = NULL;

       int colNo = Table->GetNumColumns();
       int rowNo = Table->GetNumRows();

       ReVarCifArray<CifString> *ColumnNames = Table->GetColumnNames();
       int *cols = new int[colNo];

       for (i = 0; i < colNo; i++) {
            for (j = 0; j < CifCategory[id].nkeywords; j++) {
                 if (!strcasecmp((*ColumnNames)[i].Text(),
                        CifCategory[id].keywords[j].name)) {
                      tmp_id = CifCategory[id].keywords[j].NdbInfo[0].NdbTokenId-1;
                      if (tmp_id != HEADER_TOKEN-1 && tmp_id >= 0)
                              ndb_tokenid = tmp_id;
                      break;
                 }
            }
            if (j == CifCategory[id].nkeywords) cols[i] = -1;
            else                                cols[i] = j;
       }
       if (ColumnNames) delete ColumnNames;
       if (ndb_tokenid == -1) {
            delete cols;
            return;
       }

       for (row = 0; row < rowNo; row++) {
            pCard = _CardInfo[ndb_tokenid].add_a_new_card(NdbToken[ndb_tokenid], 0);
            for (col = 0; col < colNo; col++) {
                 j = cols[col];
                 if (j < 0 || j > CifCategory[id].nkeywords) continue;

                 string.Clear();
                 Table->GetCell(string, col, row);
                 if (string == "?" || string == "." ||
                     string == "" || string == "@") continue;

                 ndb_fieldno = CifCategory[id].keywords[j].
                            NdbInfo[0].NdbFieldNo - 1;
                 if (ndb_fieldno < 0) continue;

                 strcpy(value, string.Text());
                 if (is_remark) {
                      if (strstr(value, "'") && value[0] == '\n')
                           strcpy(value, &value[1]);
                 } else ndb_clean_string(value);
                 if (is_remark && ndb_tokenid == PREMRK_TOKEN-1 &&
                     strlen(value) > 60) {
                      ndb_clean_string(value);
                      p = get_max_length_word(value, buffer, 60);
                      pCard->AddElementToField(buffer, ndb_fieldno);
                      while (p) {
                           p = get_max_length_word(p, buffer, 60);
                           ndb_clean_string(buffer);
                           if (!strcmp(buffer, "")) break;
                           qCard = _CardInfo[ndb_tokenid].
                                add_a_new_card(NdbToken[ndb_tokenid], 0);
                           qCard->AddElementToField(pCard->Field(1), 1);
                           qCard->AddElementToField(buffer, ndb_fieldno);
                      }
                 } else pCard->AddElementToField(value, ndb_fieldno);
            }
       }
       delete [] cols;

       if (ndb_tokenid == REMARK_TOKEN-1 ||
           ndb_tokenid == PCOMPN_TOKEN-1 ||
           ndb_tokenid == PSOURC_TOKEN-1) {
            pCard = _CardInfo[ndb_tokenid].Head();
            while (pCard) {
                 if (!strcmp(pCard->Field(2), "") ||
                     !strcmp(pCard->Field(2), "@") ||
                     !strcmp(pCard->Field(2), "?"))
                      pCard = _CardInfo[ndb_tokenid].delete_a_card(pCard);
                 else pCard = pCard->Next();
            }
       }
}

void _MAXIT::cifndb_process_remark(ISTable *Table, const int card_id, const int field_no)
{
       CifString id, text, old_id;
       char buffer[62], *value, *p;
       int irow, count, length, i, first = 1;
       One_Card_Info_Format *pCard = NULL;

       int rowNo = Table->GetNumRows();
       int id_idx = Table->GetColumnIndex("id");
       int txt_idx = Table->GetColumnIndex("text");
       if (id_idx < 0 || txt_idx < 0) return;

       old_id.Copy("-1");
       for (irow = 0; irow < rowNo; irow++) {
            Table->GetCell(id, id_idx, irow);
            Table->GetCell(text, txt_idx, irow);
            if (id != old_id) {
                 old_id.Copy(id);
                 first = 1;
            } else first = 0;
            count = 0;
            length = strlen(text.Text());
            for (i = 0; i < length; i++) {
                 if (text.Text()[i] != '\n') count++;
                 else {
                      if (count > 60) break;
                      count = 0;
                 }
            }
            if (count > 60) {
                 value = new char[length + 1];
                 strcpy(value, text.Text());
                 ndb_clean_string(value);
                 p = value;
                 while (p) {
                      p = get_max_length_word(p, buffer, 60);
                      ndb_clean_string(buffer);
                      if (!strcmp(buffer, "")) break;
                      pCard = _CardInfo[card_id].
                               add_a_new_card(NdbToken[card_id], 0);
                      pCard->AddElementToField(id.Text(), 1);
                      pCard->AddElementToField(buffer, field_no);
                 }
                 delete [] value;
            } else {
                 count = 0;
                 for (i = 0; i < length; i++) {
                      if (text.Text()[i] != '\n') {
                           buffer[count++] = text.Text()[i];
                      } else {
                           buffer[count] = '\0';
                           if (!strcmp(buffer, "?")) strcpy(buffer, "");
                           if (strcmp(buffer, "") || !strcmp(buffer, "") && !first) {
                                pCard = _CardInfo[card_id].
                                        add_a_new_card(NdbToken[card_id], 0);
                                pCard->AddElementToField(id.Text(), 1);
                                pCard->AddElementToField(buffer, field_no);
                                first = 0;
                           }
                           count = 0;
                      }
                 }
                 if (count) {
                      buffer[count] = '\0';
                      if (!strcmp(buffer, "?")) strcpy(buffer, "");
                      if (strcmp(buffer, "") || !strcmp(buffer, "") && !first) {
                           pCard = _CardInfo[card_id].
                                    add_a_new_card(NdbToken[card_id], 0);
                           pCard->AddElementToField(id.Text(), 1);
                           pCard->AddElementToField(buffer, field_no);
                      }
                 }
            }
       }
}

void _MAXIT::cifndb_process_refine_ls_restr(ISTable *Table)
{
       int rowNo = Table->GetNumRows();

       int type_index = Table->GetColumnIndex("type");
       if (type_index < 0) return;

       int ave_index  = Table->GetColumnIndex("dev_ideal");
       int std_index  = Table->GetColumnIndex("dev_ideal_target");
       int weight_index = Table->GetColumnIndex("weight");
       int number_index = Table->GetColumnIndex("number");

       int ndb_tokenid, ndb_fieldno, irow, i;
       CifString value;
       for (irow = 0; irow < rowNo; irow++) {
            get_value(value, Table, type_index, irow);
            for (i = 0; i < mxRmsRecords; i++) {
                 if (!strcasecmp(value.Text(), rmsRecords[i].type)) break;
            }
            if (i == mxRmsRecords) continue;

            if (ave_index >= 0 && get_value(value, Table, ave_index, irow)) {
                 ndb_tokenid = rmsRecords[i].tokens[0];
                 ndb_fieldno = rmsRecords[i].fields[0];
                 put_into_card(value.Text(), ndb_tokenid, ndb_fieldno);
            }

            if (std_index >= 0 && get_value(value, Table, std_index, irow)) {
                 ndb_tokenid = rmsRecords[i].tokens[1];
                 ndb_fieldno = rmsRecords[i].fields[1];
                 put_into_card(value.Text(), ndb_tokenid, ndb_fieldno);
            }

            if (weight_index >= 0 && get_value(value, Table, weight_index, irow)) {
                 ndb_tokenid = rmsRecords[i].tokens[2];
                 ndb_fieldno = rmsRecords[i].fields[2];
                 put_into_card(value.Text(), ndb_tokenid, ndb_fieldno);
            }

            if (number_index >= 0 && get_value(value, Table, number_index, irow)) {
                 ndb_tokenid = rmsRecords[i].tokens[3];
                 ndb_fieldno = rmsRecords[i].fields[3];
                 put_into_card(value.Text(), ndb_tokenid, ndb_fieldno);
            }
       }
}

void _MAXIT::cifndb_process_matrix(ISTable *Table, const int id)
{
       int colNo = Table->GetNumColumns();
       int rowNo = Table->GetNumRows();

       ReVarCifArray<CifString> *ColumnNames = Table->GetColumnNames();
       int *cols = new int[colNo];

       int ndb_tokenid = -1, i, j, tokenid, fieldno, tmp_id, row;
       CifString value;
       One_Card_Info_Format *pCard1 = NULL, *pCard2 = NULL, *pCard3 = NULL;

       for (i = 0; i < colNo; i++) {
            for (j = 0; j < CifCategory[id].nkeywords; j++) {
                 if (!strcasecmp((*ColumnNames)[i].Text(),
                        CifCategory[id].keywords[j].name)) {
                         tmp_id = CifCategory[id].keywords[j].
                                      NdbInfo[0].NdbTokenId - 1;
                         if (tmp_id != HEADER_TOKEN-1 && tmp_id >= 0)
                              ndb_tokenid = tmp_id;
                      break;
                 }
            }
            if (j == CifCategory[id].nkeywords) cols[i] = -1;
            else                                cols[i] = j;
       }
       if (ndb_tokenid == -1) {
            if (ColumnNames) delete ColumnNames;
            delete cols;
            return;
       }

       for (row = 0; row < rowNo; row++) {
            pCard1 = _CardInfo[ndb_tokenid].add_a_new_card(NdbToken[ndb_tokenid], 0);
            pCard2 = _CardInfo[ndb_tokenid].add_a_new_card(NdbToken[ndb_tokenid], 0);
            pCard3 = _CardInfo[ndb_tokenid].add_a_new_card(NdbToken[ndb_tokenid], 0);
            for (i = 0; i < colNo; i++) {
                 j = cols[i];
                 if (j < 0 || j > CifCategory[id].nkeywords) continue;

                 if (!get_value(value, Table, i, row)) continue;

                 tokenid = CifCategory[id].keywords[j].NdbInfo[0].NdbTokenId-1;
                 fieldno = CifCategory[id].keywords[j].NdbInfo[0].NdbFieldNo-1;
                 if (fieldno < 0 || tokenid != ndb_tokenid) continue;

                 if (strstr((*ColumnNames)[i].Text(), "x[1]") ||
                     strstr((*ColumnNames)[i].Text(), "vector[1]")) {
                      pCard1->AddElementToField(value.Text(), fieldno);
                 } else if (strstr((*ColumnNames)[i].Text(), "x[2]") ||
                            strstr((*ColumnNames)[i].Text(), "vector[2]")) {
                      pCard2->AddElementToField(value.Text(), fieldno);
                 } else if (strstr((*ColumnNames)[i].Text(), "x[3]") ||
                            strstr((*ColumnNames)[i].Text(), "vector[3]")) {
                      pCard3->AddElementToField(value.Text(), fieldno);
                 } else {
                      if (value == "given") value.Copy("1");
                      else if (value == "generate") value.Copy("");
                      pCard1->AddElementToField(value.Text(), fieldno);
                      pCard2->AddElementToField(value.Text(), fieldno);
                      pCard3->AddElementToField(value.Text(), fieldno);
                 }
            }
       }
       if (ColumnNames) delete ColumnNames;
       delete [] cols;
}

void _MAXIT::cifndb_process_struct_site_gen(ISTable *Table)
{
       if (_num_mol == 0 || _molecules == NULL) return;

       int rowNo = Table->GetNumRows();

       int site_id_index = Table->GetColumnIndex("site_id");
       int label_comp_id = Table->GetColumnIndex("label_comp_id");
       int label_asym_id = Table->GetColumnIndex("label_asym_id");
       int label_seq_id  = Table->GetColumnIndex("label_seq_id");
       int auth_comp_id  = Table->GetColumnIndex("auth_comp_id");
       int auth_asym_id  = Table->GetColumnIndex("auth_asym_id");
       int auth_seq_id   = Table->GetColumnIndex("auth_seq_id");
       int ndb_ins_code  = Table->GetColumnIndex("ndb_label_ins_code");
 
       CifString site_id;
       int irow, FstIndex, FstRes;
       for (irow = 0; irow < rowNo; irow++) {
            get_value(site_id, Table, site_id_index, irow);
            if (get_residue_index(_molecules[0], Table, irow, label_comp_id,
                      label_asym_id, label_seq_id, auth_comp_id, auth_asym_id,
                      auth_seq_id, ndb_ins_code, FstIndex, FstRes)) {
                 Insert_a_Site(site_id.Text(), FstIndex, FstRes);
            }
       }
}

void _MAXIT::cifndb_process_rcsb_link(ISTable *Table)
{
       int rowNo, irow, BegIndex, BegRes, EndIndex, EndRes, beg, end;
       int ptnr1_label_alt_id, ptnr1_label_asym_id, ptnr1_label_atom_id;
       int ptnr1_label_comp_id, ptnr1_label_seq_id, ptnr1_label_ins_code;
       int ptnr1_symmetry, ptnr2_label_alt_id, ptnr2_label_asym_id;
       int ptnr2_label_atom_id, ptnr2_label_comp_id, ptnr2_label_seq_id;
       int ptnr2_label_ins_code, ptnr2_symmetry, details;
       CifString comment, atom1, loc1, atom2, loc2, symm1, symm2;

       if (_num_mol == 0 || _molecules == NULL) return;

       rowNo = Table->GetNumRows();
       ptnr1_label_alt_id = Table->GetColumnIndex("ptnr1_label_alt_id");
       ptnr1_label_asym_id = Table->GetColumnIndex("ptnr1_label_asym_id");
       ptnr1_label_atom_id = Table->GetColumnIndex("ptnr1_label_atom_id");
       ptnr1_label_comp_id = Table->GetColumnIndex("ptnr1_label_comp_id");
       ptnr1_label_seq_id = Table->GetColumnIndex("ptnr1_label_seq_id");
       ptnr1_label_ins_code = Table->GetColumnIndex("ptnr1_label_ins_code");
       ptnr1_symmetry = Table->GetColumnIndex("ptnr1_symmetry");
       ptnr2_label_alt_id = Table->GetColumnIndex("ptnr2_label_alt_id");
       ptnr2_label_asym_id = Table->GetColumnIndex("ptnr2_label_asym_id");
       ptnr2_label_atom_id = Table->GetColumnIndex("ptnr2_label_atom_id");
       ptnr2_label_comp_id = Table->GetColumnIndex("ptnr2_label_comp_id");
       ptnr2_label_seq_id = Table->GetColumnIndex("ptnr2_label_seq_id");
       ptnr2_label_ins_code = Table->GetColumnIndex("ptnr2_label_ins_code");
       ptnr2_symmetry = Table->GetColumnIndex("ptnr2_symmetry");
       details = Table->GetColumnIndex("details");

       for (irow = 0; irow < rowNo; irow++) {
            get_value(comment, Table, details, irow);
            get_value(loc1, Table, ptnr1_label_alt_id, irow);
            get_value(atom1, Table, ptnr1_label_atom_id, irow);
            get_value(symm1, Table, ptnr1_symmetry, irow);
            get_value(loc2, Table, ptnr2_label_alt_id, irow);
            get_value(atom2, Table, ptnr2_label_atom_id, irow);
            get_value(symm2, Table, ptnr2_symmetry, irow);
            beg = get_residue_index(_molecules[0], Table, irow, -1, -1, -1,
                   ptnr1_label_comp_id, ptnr1_label_asym_id,
                   ptnr1_label_seq_id, ptnr1_label_ins_code,
                   BegIndex, BegRes);
            end = get_residue_index(_molecules[0], Table, irow, -1, -1, -1,
                   ptnr2_label_comp_id, ptnr2_label_asym_id,
                   ptnr2_label_seq_id, ptnr2_label_ins_code,
                   EndIndex, EndRes);
            if (!beg || !end) continue;
            if (symm1 == "1_555") symm1.Clear();
            if (symm2 == "1_555") symm2.Clear();
            Insert_a_Link(atom1.Text(), loc1.Text(), BegIndex, BegRes,
                          atom2.Text(), loc2.Text(), EndIndex, EndRes,
                          symm1.Text(), symm2.Text(), comment.Text());
       }
}

void _MAXIT::cifndb_process_struct_conf(ISTable *Table)
{
       int BegIndex = -1, BegRes = -1, EndIndex = -1, EndRes = -1, beg = -1, end = -1;
       int irow, rowNo, id_index, pdb_index, beg_label_comp_id, beg_label_asym_id;
       int beg_label_seq_id, beg_label_ins_code, beg_auth_comp_id, beg_auth_asym_id;
       int beg_auth_seq_id, end_label_comp_id, end_label_asym_id, end_label_seq_id;
       int end_label_ins_code, end_auth_comp_id, end_auth_asym_id, end_auth_seq_id;
       int class_index, details_index;
       CifString pdb_id, type, comment, class_type;
       _CHAIN *chain = NULL;

       if (_num_mol == 0 || _molecules == NULL) return;

       rowNo = Table->GetNumRows();
       id_index = Table->GetColumnIndex("conf_type_id");
       pdb_index = Table->GetColumnIndex("pdb_id");
       beg_label_comp_id = Table->GetColumnIndex("beg_label_comp_id");
       beg_label_asym_id = Table->GetColumnIndex("beg_label_asym_id");
       beg_label_seq_id = Table->GetColumnIndex("beg_label_seq_id");
       beg_label_ins_code = Table->GetColumnIndex("ndb_beg_label_ins_code_pdb");
       beg_auth_comp_id = Table->GetColumnIndex("beg_auth_comp_id");
       beg_auth_asym_id = Table->GetColumnIndex("beg_auth_asym_id");
       beg_auth_seq_id = Table->GetColumnIndex("beg_auth_seq_id");
       end_label_comp_id = Table->GetColumnIndex("end_label_comp_id");
       end_label_asym_id = Table->GetColumnIndex("end_label_asym_id");
       end_label_seq_id = Table->GetColumnIndex("end_label_seq_id");
       end_label_ins_code = Table->GetColumnIndex("ndb_end_label_ins_code_pdb");
       end_auth_comp_id = Table->GetColumnIndex("end_auth_comp_id");
       end_auth_asym_id = Table->GetColumnIndex("end_auth_asym_id");
       end_auth_seq_id = Table->GetColumnIndex("end_auth_seq_id");
       class_index = Table->GetColumnIndex("ndb_helix_class_pdb");
       details_index = Table->GetColumnIndex("details");

       for (irow = 0; irow < rowNo; irow++) {
            beg = get_residue_index(_molecules[0], Table, irow, beg_label_comp_id,
                  beg_label_asym_id, beg_label_seq_id, beg_auth_comp_id,
                  beg_auth_asym_id, beg_auth_seq_id, beg_label_ins_code,
                  BegIndex, BegRes);
            end = get_residue_index(_molecules[0], Table, irow, end_label_comp_id,
                  end_label_asym_id, end_label_seq_id, end_auth_comp_id,
                  end_auth_asym_id, end_auth_seq_id, end_label_ins_code,
                  EndIndex, EndRes);
            if (beg && end && BegIndex == EndIndex) {
                 chain = _molecules[0]->GetIndexChain(BegIndex);
                 if (chain) {
                      get_value(type, Table, id_index, irow);
                      get_value(pdb_id, Table, pdb_index, irow);
                      get_value(comment, Table, details_index, irow);
                      if (!strcasecmp(type.Text(), "HELX_P")) {
                           get_value(class_type, Table, class_index, irow);
                           chain->Insert_a_Helix(pdb_id.Text(), BegRes, EndRes,
                                 atoi(class_type.Text()), comment.Text());
                           _exist_helix = 1;
                      } else if (!strcasecmp(type.Text(), "TURN_P")) {
                           chain->Insert_a_Turn(pdb_id.Text(), BegRes, EndRes, comment.Text());
                      }
                 }
            }
       }
}

void _MAXIT::cifndb_process_sheet()
{
       if (_num_mol == 0 || _molecules == NULL) return;

       ISTable *Table = _CifObj->GetTablePtr(_StructureId, "struct_sheet_range");
       if (is_empty_table(Table)) return;

       ISTable *Table1 = _CifObj->GetTablePtr(_StructureId, "rcsb_struct_sheet_hbond");
       ISTable *Table2 = _CifObj->GetTablePtr(_StructureId, "struct_sheet_order");
       ISTable *Table3 = _CifObj->GetTablePtr(_StructureId, "struct_sheet");

       int rowNo = Table->GetNumRows();
       int sheet_id_index = Table->GetColumnIndex("sheet_id");
       int id_index = Table->GetColumnIndex("id");
       int beg_label_comp_id = Table->GetColumnIndex("beg_label_comp_id");
       int beg_label_asym_id = Table->GetColumnIndex("beg_label_asym_id");
       int beg_label_seq_id = Table->GetColumnIndex("beg_label_seq_id");
       int ndb_beg_label_ins_code_pdb = Table->GetColumnIndex("ndb_beg_label_ins_code_pdb");
       int end_label_comp_id = Table->GetColumnIndex("end_label_comp_id");
       int end_label_asym_id = Table->GetColumnIndex("end_label_asym_id");
       int end_label_seq_id = Table->GetColumnIndex("end_label_seq_id");
       int ndb_end_label_ins_code_pdb = Table->GetColumnIndex("ndb_end_label_ins_code_pdb");
       int beg_auth_comp_id = Table->GetColumnIndex("beg_auth_comp_id");
       int beg_auth_asym_id = Table->GetColumnIndex("beg_auth_asym_id");
       int beg_auth_seq_id = Table->GetColumnIndex("beg_auth_seq_id");
       int end_auth_comp_id = Table->GetColumnIndex("end_auth_comp_id");
       int end_auth_asym_id = Table->GetColumnIndex("end_auth_asym_id");
       int end_auth_seq_id = Table->GetColumnIndex("end_auth_seq_id");

       int row, BegIndex, BegRes, EndIndex, EndRes, beg, end, number_strands;
       int sense = 0, curIndex = -1, curRes = -1, prevIndex = -1, prevRes = -1;
       CifString sheet_id, id, prev_id, curAtom, prevAtom;
       prev_id[0] = '\0';
       prev_id.Clear();
       id.Clear();
       for (row = 0; row < rowNo; row++) {
            prev_id.Copy(id);
            sheet_id.Clear();
            id.Clear();
            get_value(sheet_id, Table, sheet_id_index, row);
            get_value(id, Table, id_index, row);

            beg = get_residue_index(_molecules[0], Table, row, beg_label_comp_id,
                  beg_label_asym_id, beg_label_seq_id, beg_auth_comp_id,
                  beg_auth_asym_id, beg_auth_seq_id, ndb_beg_label_ins_code_pdb,
                  BegIndex, BegRes);
            end = get_residue_index(_molecules[0], Table, row, end_label_comp_id,
                  end_label_asym_id, end_label_seq_id, end_auth_comp_id,
                  end_auth_asym_id, end_auth_seq_id, ndb_end_label_ins_code_pdb,
                  EndIndex, EndRes);
            if (beg && end && BegIndex == EndIndex) {
                 sense = 0; curIndex = -1; curRes = -1; prevIndex = -1; prevRes = -1;
                 curAtom.Clear(); prevAtom.Clear();
                 number_strands = get_number_strands(Table3, sheet_id.Text());
                 if (row) {
                      get_hbond(_molecules[0], Table1, BegIndex, sheet_id.Text(), id.Text(),
                         curAtom, curIndex, curRes, prevAtom, prevIndex, prevRes);
                      sense = get_sense(Table2, sheet_id.Text(), prev_id.Text(), id.Text());
                 }
                 Insert_a_Sheet(sheet_id.Text(), number_strands, BegIndex, BegRes, EndIndex,
                       EndRes, sense, curAtom.Text(), curIndex, curRes,
                       prevAtom.Text(), prevIndex, prevRes);
                 _exist_sheet = 1;
            }
       }
}

#ifdef SUN_OS
#ifdef __cplusplus
extern "C" {
#endif
#endif
static int pdb_rev_compare(const void *a, const void *b)
{
       return (((PDB_REV *) b)->num - ((PDB_REV *) a)->num);
}
#ifdef SUN_OS
#ifdef __cplusplus
}
#endif
#endif

void _MAXIT::cifndb_process_database_pdb_rev(ISTable *Table)
{
       int rowNo = Table->GetNumRows();
       PDB_REV *pdb_rev = (PDB_REV *) calloc(rowNo, sizeof(PDB_REV));
       int n_rev = rowNo;
       int num_index = Table->GetColumnIndex("num");
       int date_index = Table->GetColumnIndex("date");
       int original_index = Table->GetColumnIndex("date_original");
       int replaces_index = Table->GetColumnIndex("replaces");
       int type_index = Table->GetColumnIndex("mod_type");
       int revised_index[4];
       revised_index[0] = Table->GetColumnIndex("rcsb_record_revised_1");
       revised_index[1] = Table->GetColumnIndex("rcsb_record_revised_2");
       revised_index[2] = Table->GetColumnIndex("rcsb_record_revised_3");
       revised_index[3] = Table->GetColumnIndex("rcsb_record_revised_4");

       int irow, i, len, serial_no, pos;
       CifString cifstring, value;
       char buffer[20], *p;
       One_Card_Info_Format *pCard = NULL;
       for (irow = 0; irow < rowNo; irow++) {
            pdb_rev[irow].num = 0;
            pdb_rev[irow].date[0] = '\0';
            pdb_rev[irow].replaces[0] = '\0';
            pdb_rev[irow].mod_type = 0;
            pdb_rev[irow].record = NULL;
            if (num_index >= 0) {
                 get_value(cifstring, Table, num_index, irow);
                 pdb_rev[irow].num = atoi(cifstring.Text());
            }
            if (date_index >= 0) {
                 get_value(cifstring, Table, date_index, irow);
                 strcpy(pdb_rev[irow].date, cifstring.Text());
            }
            if (replaces_index >= 0) {
                 get_value(cifstring, Table, replaces_index, irow);
                 strcpy(pdb_rev[irow].replaces, cifstring.Text());
            }
            if (type_index >= 0) {
                 get_value(cifstring, Table, type_index, irow);
                 pdb_rev[irow].mod_type = atoi(cifstring.Text());
            }
            if (original_index >= 0 && !pdb_rev[irow].mod_type) {
                 get_value(cifstring, Table, original_index, irow);
                 if (cifstring != "") {
                      pCard = _CardInfo[HEADER_TOKEN-1].Head();
                      if (!pCard) pCard = _CardInfo[HEADER_TOKEN-1].
                           add_a_new_card(NdbToken[HEADER_TOKEN-1], 0);
                      pCard->AddElementToField(cifstring.Text(), 2);
                 }
            }
            for (i = 0; i < 4; i++) {
                 if (revised_index[i] < 0) continue;
                 get_value(cifstring, Table, revised_index[i], irow);
                 if (cifstring == "") continue;

                 if (pdb_rev[irow].record == NULL) {
                      len = strlen(cifstring.Text())+1;
                      pdb_rev[irow].record = (char *) calloc(len, sizeof(char));
                      strcpy(pdb_rev[irow].record, cifstring.Text());
                 } else if (!strstr(pdb_rev[irow].record, cifstring.Text())) {
                      len = strlen(cifstring.Text()) + 2 +
                                strlen(pdb_rev[irow].record);
                      pdb_rev[irow].record = (char *) realloc(pdb_rev[irow].record,
                                            len * sizeof(char));
                      strcat(pdb_rev[irow].record, " ");
                      strcat(pdb_rev[irow].record, cifstring.Text());
                 }
            }
       }

       Table = _CifObj->GetTablePtr(_StructureId, "database_PDB_rev_record");
       if (!is_empty_table(Table)) {
            rowNo = Table->GetNumRows();
            num_index = Table->GetColumnIndex("rev_num");
            type_index = Table->GetColumnIndex("type");
            for (irow = 0; irow < rowNo; irow++) {
                 get_value(cifstring, Table, num_index, irow);
                 get_value(value, Table, type_index, irow);
                 if (cifstring == "" || value == "") continue;

                 for (i = 0; i < n_rev; i++)
                      if (pdb_rev[i].num == atoi(cifstring.Text())) break;
                 if (i < n_rev) {
                      if (pdb_rev[i].record == NULL) {
                           len = strlen(value.Text())+1;
                           pdb_rev[i].record = (char *) calloc(len, sizeof(char));
                           strcpy(pdb_rev[i].record, value.Text());
                      } else if (!strstr(pdb_rev[i].record, value.Text())) {
                           len = strlen(value.Text()) + 2 +
                                     strlen(pdb_rev[i].record);
                           pdb_rev[i].record = (char *) realloc(pdb_rev[i].record,
                                                 len * sizeof(char));
                           strcat(pdb_rev[i].record, " ");
                           strcat(pdb_rev[i].record, value.Text());
                      }
                 }
            }
       }
       if (n_rev > 1) qsort((void *) pdb_rev, n_rev, sizeof(PDB_REV), pdb_rev_compare);

       for (i = 0; i < n_rev; i++) {
            if (!pdb_rev[i].num) continue;
            pCard = _CardInfo[REVDAT_TOKEN-1].
                        add_a_new_card(NdbToken[REVDAT_TOKEN-1], 0);
            pCard->AddElementToField(pdb_rev[i].num, 1);
            pCard->AddElementToField(pdb_rev[i].date, 3);
            pCard->AddElementToField(pdb_rev[i].replaces, 4);
            pCard->AddElementToField(pdb_rev[i].mod_type, 5);
            p = pdb_rev[i].record;
            serial_no = 2;
            pos = 6;
            while (p) {
                 if (pos > 9) {
                      pCard = _CardInfo[REVDAT_TOKEN-1].
                              add_a_new_card(NdbToken[REVDAT_TOKEN-1], 0);
                      pCard->AddElementToField(pdb_rev[i].num, 1);
                      pCard->AddElementToField(serial_no, 2);
                      pCard->AddElementToField(pdb_rev[i].mod_type, 5);
                      serial_no++;
                      pos = 6;
                 }
                 p = get_word(p, buffer);
                 pCard->AddElementToField(buffer, pos);
                 pos++;
            }
       }
       for (i = 0; i < n_rev; i++) {
            if (pdb_rev[i].record) free ((void *) pdb_rev[i].record);
       }
       free ((void *) pdb_rev);
}

void _MAXIT::cifndb_process_struct_conn(ISTable *Table)
{
       if (_num_mol == 0 || _molecules == NULL) return;

       int rowNo = Table->GetNumRows();

       int id_index = Table->GetColumnIndex("conn_type_id");
       int pdb_index = Table->GetColumnIndex("ndb_PDB_id");
       int name_index = Table->GetColumnIndex("ndb_ptnr1_mod_name");
       int sugar_index = Table->GetColumnIndex("ndb_ptnr1_sugar_name");
       int replaced_index = Table->GetColumnIndex("ndb_ptnr1_replaced_atom");
       int standard_index = Table->GetColumnIndex("ndb_ptnr1_standard_comp_id");
       int ptnr1_label_comp_id = Table->GetColumnIndex("ptnr1_label_comp_id");
       int ptnr1_label_asym_id = Table->GetColumnIndex("ptnr1_label_asym_id");
       int ptnr1_label_seq_id = Table->GetColumnIndex("ptnr1_label_seq_id");
       int ptnr1_label_atom_id = Table->GetColumnIndex("ptnr1_label_atom_id");
       int ndb_ptnr1_label_alt_loc = Table->GetColumnIndex("ndb_ptnr1_label_alt_loc");
       int ptnr1_label_ins_code = Table->GetColumnIndex("ndb_ptnr1_label_ins_code");
       int ptnr1_symmetry = Table->GetColumnIndex("ptnr1_symmetry");
       int ptnr2_label_comp_id = Table->GetColumnIndex("ptnr2_label_comp_id");
       int ptnr2_label_asym_id = Table->GetColumnIndex("ptnr2_label_asym_id");
       int ptnr2_label_seq_id = Table->GetColumnIndex("ptnr2_label_seq_id");
       int ptnr2_label_atom_id = Table->GetColumnIndex("ptnr2_label_atom_id");
       int ndb_ptnr2_label_alt_loc = Table->GetColumnIndex("ndb_ptnr2_label_alt_loc");
       int ptnr2_label_ins_code = Table->GetColumnIndex("ndb_ptnr2_label_ins_code");
       int ptnr2_symmetry = Table->GetColumnIndex("ptnr2_symmetry");
       int ptnr1_auth_comp_id = Table->GetColumnIndex("ptnr1_auth_comp_id");
       int ptnr1_auth_asym_id = Table->GetColumnIndex("ptnr1_auth_asym_id");
       int ptnr1_auth_seq_id = Table->GetColumnIndex("ptnr1_auth_seq_id");
       int ptnr2_auth_comp_id = Table->GetColumnIndex("ptnr2_auth_comp_id");
       int ptnr2_auth_asym_id = Table->GetColumnIndex("ptnr2_auth_asym_id");
       int ptnr2_auth_seq_id = Table->GetColumnIndex("ptnr2_auth_seq_id");
       int ndb_ptnr3_label_atom_id = Table->GetColumnIndex("ndb_ptnr3_label_atom_id");
       int ndb_ptnr3_label_seq_id = Table->GetColumnIndex("ndb_ptnr3_label_seq_id");
       int ndb_ptnr3_label_asym_id = Table->GetColumnIndex("ndb_ptnr3_label_asym_id");
       int ndb_ptnr3_label_alt_loc = Table->GetColumnIndex("ndb_ptnr3_label_alt_loc");
       int details_index = Table->GetColumnIndex("details");

       int irow, BegIndex, BegRes, EndIndex, EndRes, beg, end, H_Index, H_Res;
       CifString type, atom1, loc1, atom2, loc2, symm1, symm2, comment, name;
       CifString Replaced_Atom, atom3, loc3, standard, pdb_id, sugar;
       CifString seq_id1, seq_id2, seq_id3, chain_id1, chain_id2, chain_id3;
       for (irow = 0; irow < rowNo; irow++) {
            get_value(type, Table, id_index, irow);
            if (type == "") continue;

            get_value(atom1, Table, ptnr1_label_atom_id, irow);
            get_value(loc1, Table, ndb_ptnr1_label_alt_loc, irow);
            get_value(symm1, Table, ptnr1_symmetry, irow);
            get_value(atom2, Table, ptnr2_label_atom_id, irow);
            get_value(loc2, Table, ndb_ptnr2_label_alt_loc, irow);
            get_value(symm2, Table, ptnr2_symmetry, irow);
            get_value(comment, Table, details_index, irow);
            get_value(name, Table, name_index, irow);
            get_value(Replaced_Atom, Table, replaced_index, irow);
            if (symm1 == "1_555") symm1.Clear();
            if (symm2 == "1_555") symm2.Clear();

            beg = get_residue_index(_molecules[0], Table, irow, ptnr1_label_comp_id,
                  ptnr1_label_asym_id, ptnr1_label_seq_id, ptnr1_auth_comp_id,
                  ptnr1_auth_asym_id, ptnr1_auth_seq_id, ptnr1_label_ins_code,
                  BegIndex, BegRes);
            end = get_residue_index(_molecules[0], Table, irow, ptnr2_label_comp_id,
                  ptnr2_label_asym_id, ptnr2_label_seq_id, ptnr2_auth_comp_id,
                  ptnr2_auth_asym_id, ptnr2_auth_seq_id, ptnr2_label_ins_code,
                  EndIndex, EndRes);
            if (!beg) continue;

            if (!strcasecmp(type.Text(), "hydrog")) {
                 if (end) {
                      if (!strcasecmp(comment.Text(), "WATSON-CRICK") ||
                          !strcasecmp(comment.Text(), "REVERSED WATSON-CRICK") ||
                          !strcasecmp(comment.Text(), "HOOGSTEEN") ||
                          !strcasecmp(comment.Text(), "REVERSED HOOGSTEEN") ||
                          strstr(comment.Text(), "PAIR") || strstr(comment.Text(), "pair"))
                           Insert_a_Bspair(atom1.Text(), BegIndex, BegRes, atom2.Text(),
                                 EndIndex, EndRes, symm2.Text(), comment.Text());
                      else {
                           seq_id3.Copy("ZZZ"); chain_id3.Copy("ZZZ");
                           get_value(atom3, Table, ndb_ptnr3_label_atom_id, irow);
                           get_value(loc3, Table, ndb_ptnr3_label_alt_loc, irow);
                           get_value(seq_id1, Table, ptnr1_label_seq_id, irow);
                           get_value(chain_id1, Table, ptnr1_label_asym_id, irow);
                           get_value(seq_id2, Table, ptnr2_label_seq_id, irow);
                           get_value(chain_id2, Table, ptnr2_label_asym_id, irow);
                           if (ndb_ptnr3_label_seq_id >= 0)
                                get_value(seq_id3, Table, ndb_ptnr3_label_seq_id, irow);
                           if (ndb_ptnr3_label_asym_id >= 0)
                                get_value(chain_id3, Table, ndb_ptnr3_label_asym_id, irow);
                           H_Index = -1; H_Res = -1;
                           if (seq_id1 == seq_id3 && chain_id1 == chain_id3) {
                                H_Index = BegIndex; H_Res = BegRes;
                           } else if (seq_id2 == seq_id3 && chain_id2 == chain_id3) {
                                H_Index = EndIndex; H_Res = EndRes;
                           }
                           Insert_a_Hydbnd(atom1.Text(), loc1.Text(), BegIndex, BegRes,
                                 atom3.Text(), loc3.Text(), H_Index, H_Res, atom2.Text(),
                                 loc2.Text(), EndIndex, EndRes, symm1.Text(), symm2.Text());
                      }
                 }
            } else if (!strcasecmp(type.Text(), "hydbnd")) {
                 if (end) {
                      seq_id3.Copy("ZZZ"); chain_id3.Copy("ZZZ");
                      get_value(atom3, Table, ndb_ptnr3_label_atom_id, irow);
                      get_value(loc3, Table, ndb_ptnr3_label_alt_loc, irow);
                      get_value(seq_id1, Table, ptnr1_label_seq_id, irow);
                      get_value(chain_id1, Table, ptnr1_label_asym_id, irow);
                      get_value(seq_id2, Table, ptnr2_label_seq_id, irow);
                      get_value(chain_id2, Table, ptnr2_label_asym_id, irow);
                      if (ndb_ptnr3_label_seq_id >= 0)
                           get_value(seq_id3, Table, ndb_ptnr3_label_seq_id, irow);
                      if (ndb_ptnr3_label_asym_id >= 0)
                           get_value(chain_id3, Table, ndb_ptnr3_label_asym_id, irow);
                      H_Index = -1; H_Res = -1;
                      if (seq_id1 == seq_id3 && chain_id1 == chain_id3) {
                           H_Index = BegIndex; H_Res = BegRes;
                      } else if (seq_id2 == seq_id3 && chain_id2 == chain_id3) {
                           H_Index = EndIndex; H_Res = EndRes;
                      }
                      Insert_a_Hydbnd(atom1.Text(), loc1.Text(), BegIndex, BegRes,
                             atom3.Text(), loc3.Text(), H_Index, H_Res, atom2.Text(),
                             loc2.Text(), EndIndex, EndRes, symm1.Text(), symm2.Text());
                 }
            } else if (!strcasecmp(type.Text(), "link") || !strcasecmp(type.Text(), "covale")) {
                 if (end) Insert_a_Link(atom1.Text(), loc1.Text(), BegIndex, BegRes, atom2.Text(),
                       loc2.Text(), EndIndex, EndRes, symm1.Text(), symm2.Text(), comment.Text());
            } else if (!strcasecmp(type.Text(), "modres")) {
                 get_value(pdb_id, Table, pdb_index, irow);
                 get_value(standard, Table, standard_index, irow);
                 Insert_a_Modres(pdb_id.Text(), BegIndex, BegRes, standard.Text(), comment.Text());
            } else if (!strcasecmp(type.Text(), "sltbrg") || !strcasecmp(type.Text(), "saltbr")) {
                 if (end) Insert_a_Sltbrg(atom1.Text(), loc1.Text(), BegIndex, BegRes, atom2.Text(),
                        loc2.Text(), EndIndex, EndRes, symm1.Text(), symm2.Text());
            } else if (!strcasecmp(type.Text(), "disulf")) {
                 if (end) {
                      Insert_a_SSbond(BegIndex, BegRes, EndIndex, EndRes, symm1.Text(), symm2.Text());
                      _exist_ssbond = 1;
                 }
            } else if (!strcasecmp(type.Text(), "mismat")) {
                 if (end) Insert_a_Mismat(BegIndex, BegRes, EndIndex, EndRes);
            } else if (!strcasecmp(type.Text(), "covale_base")) {
                 if (end) Insert_a_Modifb(name.Text(), atom1.Text(), BegIndex, BegRes, atom2.Text(),
                                EndIndex, EndRes, Replaced_Atom.Text());
            } else if (!strcasecmp(type.Text(), "covale_sugar")) {
                 if (end) {
                      get_value(sugar, Table, sugar_index, irow);
                      Insert_a_Modifs(name.Text(), atom1.Text(), BegIndex, BegRes, atom2.Text(), EndIndex,
                                   EndRes, Replaced_Atom.Text(), sugar.Text());
                 }
            } else if (!strcasecmp(type.Text(), "covale_phosphate")) {
                 if (end) Insert_a_Modifp(name.Text(), atom1.Text(), BegIndex, BegRes, atom2.Text(),
                                EndIndex, EndRes, Replaced_Atom.Text());
            }
       }
}

void _MAXIT::put_into_card(const char *value, const int tokenid, const int fieldno)
{
       if (tokenid < 0 || tokenid >= MxTokens || fieldno < 0 ||
           fieldno >= NdbToken[tokenid].NumField) return;

       One_Card_Info_Format *pCard = _CardInfo[tokenid].Tail();
       if (pCard == NULL || strcmp(pCard->Field(fieldno), ""))
            pCard = _CardInfo[tokenid].add_a_new_card(NdbToken[tokenid], 0);
       pCard->AddElementToField(value, fieldno);
}

void _MAXIT::ndb_processing_em_software()
{
       int idx;
       CifString string, string1;
       ISTable *Table = NULL;

       Table = _CifObj->GetTablePtr(_StructureId, "em_3d_fitting");
       if (is_empty_table(Table)) return;

       idx = Table->GetColumnIndex("software_name");
       if (idx < 0) return;

       Table->GetCell(string, idx, 0);
       if (string == "" || string == "." || string == "?") return;

       Table = _CifObj->GetTablePtr(_StructureId, "em_2d_projection_selection");
       if (!Table) {
            Table = new ISTable("em_2d_projection_selection");
            Table->AddColumn("entry_id");
            Table->AddColumn("software_name");
            Table->AddColumn("num_particles");
            Table->AddRow();
            _CifObj->WriteTable(Table, _StructureId, "em_2d_projection_selection");
       }
       idx = Table->GetColumnIndex("software_name");
       Table->GetCell(string1, idx, 0);
       if (string1 == "" || string1 == "." || string1 == "?")
            Table->UpdateCell(string, idx, 0);
}

void _MAXIT::ndb_processing_struct_category()
{
       ISTable *Table = _CifObj->GetTablePtr(_StructureId, "struct");
       if (is_empty_table(Table)) return;

       int ndb_descriptor = Table->GetColumnIndex("ndb_descriptor");
       int ndb_title_text = Table->GetColumnIndex("ndb_title_text");
       int title_index    = Table->GetColumnIndex("title");
       
       if (ndb_title_text >= 0 && title_index >= 0 && ndb_descriptor < 0) {
            ISTable *Table1 = new ISTable("struct");
            Table1->AddColumn("entry_id");
            Table1->AddColumn("title");
            Table1->AddColumn("ndb_descriptor");
            Table1->AddColumn("rcsb_model_details");
            Table1->AddColumn("ndb_details");
            Table1->AddRow();
            CifString string(_StructureId);
            Table1->UpdateCell(string, 0, 0);
            Table->GetCell(string, ndb_title_text, 0);
            Table1->UpdateCell(string, 1, 0);
            Table->GetCell(string, title_index, 0);
            Table1->UpdateCell(string, 2, 0);
            int detail_index = Table->GetColumnIndex("rcsb_model_details");
            if (detail_index >= 0) {
                 Table->GetCell(string, detail_index, 0);
                 Table1->UpdateCell(string, 3, 0);
            }
            detail_index = Table->GetColumnIndex("ndb_details");
            if (detail_index >= 0) {
                 Table->GetCell(string, detail_index, 0);
                 Table1->UpdateCell(string, 4, 0);
            }
            _CifObj->DeleteTable(_StructureId, "struct");
            _CifObj->WriteTable(Table1, _StructureId, "struct");
       }
}

void _MAXIT::ndb_processing_struct_sheet_hbond()
{
       ISTable *Table = _CifObj->GetTablePtr(_StructureId, "struct_sheet_hbond");
       if (is_empty_table(Table)) return;

       ISTable *Table1 = new ISTable("rcsb_struct_sheet_hbond");

       Table1->AddColumn("sheet_id");
       Table1->AddColumn("range_id_2");
       Table1->AddColumn("range_1_label_atom_id");
       Table1->AddColumn("range_1_label_comp_id");
       Table1->AddColumn("range_1_label_asym_id");
       Table1->AddColumn("range_1_label_seq_id");
       Table1->AddColumn("range_1_PDB_ins_code");
       Table1->AddColumn("range_1_auth_comp_id");
       Table1->AddColumn("range_1_auth_asym_id");
       Table1->AddColumn("range_1_auth_seq_id");
       Table1->AddColumn("range_2_label_atom_id");
       Table1->AddColumn("range_2_label_comp_id");
       Table1->AddColumn("range_2_label_asym_id");
       Table1->AddColumn("range_2_label_seq_id");
       Table1->AddColumn("range_2_PDB_ins_code");
       Table1->AddColumn("range_2_auth_comp_id");
       Table1->AddColumn("range_2_auth_asym_id");
       Table1->AddColumn("range_2_auth_seq_id");

       int rowNo = Table->GetNumRows();
       int sheet_id = Table->GetColumnIndex("sheet_id");
       int range_id_1 = Table->GetColumnIndex("range_id_1");
       int beg_label_atom_id = Table->GetColumnIndex("range_1_beg_label_atom_id");
       int beg_label_comp_id = Table->GetColumnIndex("ndb_range_1_beg_label_comp_id");
       int beg_label_asym_id = Table->GetColumnIndex("ndb_range_1_beg_label_asym_id");
       int beg_label_seq_id = Table->GetColumnIndex("range_1_beg_label_seq_id");
       int beg_label_ins_code = Table->GetColumnIndex("ndb_range_1_beg_label_ins_code");
       int beg_auth_comp_id = Table->GetColumnIndex("ndb_range_1_beg_auth_comp_id");
       int beg_auth_asym_id = Table->GetColumnIndex("ndb_range_1_beg_auth_asym_id");
       int beg_auth_seq_id = Table->GetColumnIndex("range_1_beg_auth_seq_id");
       int end_label_atom_id = Table->GetColumnIndex("range_1_end_label_atom_id");
       int end_label_comp_id = Table->GetColumnIndex("ndb_range_1_end_label_comp_id");
       int end_label_asym_id = Table->GetColumnIndex("ndb_range_1_end_label_asym_id");
       int end_label_seq_id = Table->GetColumnIndex("range_1_end_label_seq_id");
       int end_label_ins_code = Table->GetColumnIndex("ndb_range_1_end_label_ins_code");
       int end_auth_comp_id = Table->GetColumnIndex("ndb_range_1_end_auth_comp_id");
       int end_auth_asym_id = Table->GetColumnIndex("ndb_range_1_end_auth_asym_id");
       int end_auth_seq_id = Table->GetColumnIndex("range_1_end_auth_seq_id");
       CifString string;
       for (int i = 0; i < rowNo; i++) {
            Table1->AddRow();
            if (sheet_id >= 0) {
                 Table->GetCell(string, sheet_id, i);
                 Table1->UpdateCell(string, 0, i);
            }
            if (range_id_1 >= 0) {
                 Table->GetCell(string, range_id_1, i);
                 Table1->UpdateCell(string, 1, i);
            }
            if (end_label_atom_id >= 0) {
                 Table->GetCell(string, end_label_atom_id, i);
                 Table1->UpdateCell(string, 2, i);
            }
            if (end_label_comp_id >= 0) {
                 Table->GetCell(string, end_label_comp_id, i);
                 Table1->UpdateCell(string, 3, i);
            }
            if (end_label_asym_id >= 0) {
                 Table->GetCell(string, end_label_asym_id, i);
                 Table1->UpdateCell(string, 4, i);
            }
            if (end_label_seq_id >= 0) {
                 Table->GetCell(string, end_label_seq_id, i);
                 Table1->UpdateCell(string, 5, i);
            }
            if (end_label_ins_code >= 0) {
                 Table->GetCell(string, end_label_ins_code, i);
                 Table1->UpdateCell(string, 6, i);
            }
            if (end_auth_comp_id >= 0) {
                 Table->GetCell(string, end_auth_comp_id, i);
                 Table1->UpdateCell(string, 7, i);
            }
            if (end_auth_asym_id >= 0) {
                 Table->GetCell(string, end_auth_asym_id, i);
                 Table1->UpdateCell(string, 8, i);
            }
            if (end_auth_seq_id >= 0) {
                 Table->GetCell(string, end_auth_seq_id, i);
                 Table1->UpdateCell(string, 9, i);
            }
            if (beg_label_atom_id >= 0) {
                 Table->GetCell(string, beg_label_atom_id, i);
                 Table1->UpdateCell(string, 10, i);
            }
            if (beg_label_comp_id >= 0) {
                 Table->GetCell(string, beg_label_comp_id, i);
                 Table1->UpdateCell(string, 11, i);
            }
            if (beg_label_asym_id >= 0) {
                 Table->GetCell(string, beg_label_asym_id, i);
                 Table1->UpdateCell(string, 12, i);
            }
            if (beg_label_seq_id >= 0) {
                 Table->GetCell(string, beg_label_seq_id, i);
                 Table1->UpdateCell(string, 13, i);
            }
            if (beg_label_ins_code >= 0) {
                 Table->GetCell(string, beg_label_ins_code, i);
                 Table1->UpdateCell(string, 14, i);
            }
            if (beg_auth_comp_id >= 0) {
                 Table->GetCell(string, beg_auth_comp_id, i);
                 Table1->UpdateCell(string, 15, i);
            }
            if (beg_auth_asym_id >= 0) {
                 Table->GetCell(string, beg_auth_asym_id, i);
                 Table1->UpdateCell(string, 16, i);
            }
            if (beg_auth_seq_id >= 0) {
                 Table->GetCell(string, beg_auth_seq_id, i);
                 Table1->UpdateCell(string, 17, i);
            }
       }
       _CifObj->DeleteTable(_StructureId, "struct_sheet_hbond");
       _CifObj->WriteTable(Table1, _StructureId, "rcsb_struct_sheet_hbond");
}

void _MAXIT::ndb_processing_ndb_database_PDB_obs_spr_category()
{
       ISTable *Table = _CifObj->GetTablePtr(_StructureId, "ndb_database_PDB_obs_spr");
       if (is_empty_table(Table)) return;

       int id, nrow, i;
       CifString value;

       id = Table->GetColumnIndex("id");
       if (id >= 0) {
            nrow = Table->GetNumRows();
            for (i = 0; i < nrow; i++) {
                 value.Clear();
                 Table->GetCell(value, id, i);
                 if (strcmp(value.Text(), "SPRSDE") &&
                     strcmp(value.Text(), "OBSLTE")) {
                      value.Copy("SPRSDE");
                      Table->UpdateCell(value, id, i);
                 }
            }
       }
       _CifObj->WriteTable(Table, _StructureId, "ndb_database_PDB_obs_spr");
}

void _MAXIT::ndb_processing_struct_ref_seq_and_diff()
{
       int i, rowNo, auth_beg_idx, auth_end_idx, beg_idx, end_idx;
       CifString string;
       ISTable *Table = NULL;

       Table = _CifObj->GetTablePtr(_StructureId, "struct_ref_seq");
       if (!is_empty_table(Table)) {
            rowNo = Table->GetNumRows();
            auth_beg_idx = Table->GetColumnIndex("ndb_auth_seq_align_beg");
            auth_end_idx = Table->GetColumnIndex("ndb_auth_seq_align_end");
            beg_idx = Table->GetColumnIndex("seq_align_beg");
            end_idx = Table->GetColumnIndex("seq_align_end");
            if (auth_beg_idx >= 0 && auth_end_idx >= 0 && beg_idx >= 0 &&
                end_idx >= 0) {
                 for (i = 0; i < rowNo; i++) {
                      Table->GetCell(string, auth_beg_idx, i);
                      if (string != "?" && string != "" && string != ".")
                           Table->UpdateCell(string, beg_idx, i);
                      Table->GetCell(string, auth_end_idx, i);
                      if (string != "?" && string != "" && string != ".")
                           Table->UpdateCell(string, end_idx, i);
                 }
            }
       }
       Table = _CifObj->GetTablePtr(_StructureId, "struct_ref_seq_dif");
       if (!is_empty_table(Table)) {
            rowNo = Table->GetNumRows();
            auth_beg_idx = Table->GetColumnIndex("ndb_auth_seq_num");
            beg_idx = Table->GetColumnIndex("seq_num");
            if (auth_beg_idx >= 0 && beg_idx >= 0) {
                 for (i = 0; i < rowNo; i++) {
                      Table->GetCell(string, auth_beg_idx, i);
                      if (string != "?" && string != "" && string != ".")
                           Table->UpdateCell(string, beg_idx, i);
                 }
            }
       }
}

void _MAXIT::post_processing_from_cif_to_ndb()
{
       int Auth_Token;
       One_Card_Info_Format *pCard = NULL;

       Auth_Token = find_jrnl_id("AUTH");
       if (_JrnlCardInfo[Auth_Token].Head() && _CardInfo[AUTHOR_TOKEN-1].Head() == NULL && 
           strcmp(_JrnlCardInfo[Auth_Token].Head()->Field(4), "")) {
            pCard = _CardInfo[AUTHOR_TOKEN-1].add_a_new_card(NdbToken[AUTHOR_TOKEN-1], 0);
            pCard->AddElementToField(_JrnlCardInfo[Auth_Token].Head()->Field(4), 2);
       }

       get_refn_card();
       _JrnlCardInfo[Auth_Token].reorder_cards(1, INTEGER_COMPARE, ASCENT);
       Auth_Token = find_jrnl_id("TITL");
       _JrnlCardInfo[Auth_Token].reorder_cards(1, INTEGER_COMPARE, ASCENT);
       Auth_Token = find_jrnl_id("EDIT");
       _JrnlCardInfo[Auth_Token].reorder_cards(1, INTEGER_COMPARE, ASCENT);
       Auth_Token = find_jrnl_id("REF");
       _JrnlCardInfo[Auth_Token].reorder_cards(1, INTEGER_COMPARE, ASCENT);
       Auth_Token = find_jrnl_id("PUBL");
       _JrnlCardInfo[Auth_Token].reorder_cards(1, INTEGER_COMPARE, ASCENT);
       Auth_Token = find_jrnl_id("REFN");
       _JrnlCardInfo[Auth_Token].reorder_cards(1, INTEGER_COMPARE, ASCENT);

       Auth_Token = find_card_id("TITLE");
       pCard = _CardInfo[Auth_Token].Head();
       while (pCard) {
            pCard->CleanStringDash(2);
            pCard = pCard->Next();
       }

       if ((_CardInfo[STATUS_TOKEN-1].Head() == NULL ||
           !strcmp(_CardInfo[STATUS_TOKEN-1].Head()->Field(6), "")) &&
            _CardInfo[HEADER_TOKEN-1].Head() &&
            strcmp(_CardInfo[HEADER_TOKEN-1].Head()->Field(2), "")) {
             pCard = _CardInfo[STATUS_TOKEN-1].Head();
             if (pCard == NULL) pCard = _CardInfo[STATUS_TOKEN-1].
                         add_a_new_card(NdbToken[STATUS_TOKEN-1], 0);
             pCard->AddElementToField(_CardInfo[HEADER_TOKEN-1].Head()->Field(2), 6);
       }

       pCard = _CardInfo[PROCES_TOKEN-1].Head();
       if (pCard == NULL) pCard = _CardInfo[PROCES_TOKEN-1].
                       add_a_new_card(NdbToken[PROCES_TOKEN-1], 0);
       if (!strcmp(pCard->Field(5), "")) pCard->AddElementToField("RCSB", 5);
 
       _CardInfo[RADIAT_TOKEN-1].reorder_cards(1, INTEGER_COMPARE, ASCENT);

       pCard = _CardInfo[REFMET_TOKEN-1].Head();
       if (pCard && (!strncasecmp(pCard->Field(3), "CNS", 3) ||
           !strncasecmp(pCard->Field(3), "X-PLOR", 6))) {
            pCard = _CardInfo[RFACTR_TOKEN-1].Head();
            if (pCard) {
                 if (!strcmp(pCard->Field(10), "") && strcmp(pCard->Field(7), ""))
                      pCard->AddElementToField(pCard->Field(7), 10);
                 else if (strcmp(pCard->Field(10), "") && !strcmp(pCard->Field(7), ""))
                      pCard->AddElementToField(pCard->Field(10), 7);
            }
       }
       delete_null_cards();
}

void _MAXIT::update_encapsulated_cif()
{
       int count = 0;
       One_Card_Info_Format *pCard = NULL;
       if (_file_status == FILE_STATUS_MMCIF_PLUS_MOL) {
            pCard = _CardInfo[COMPND_TOKEN-1].Head();
            while (pCard) {
                 count++;
                 pCard = pCard->Next();
            }
            pCard = _CardInfo[SOURCE_TOKEN-1].Head();
            if (pCard && count > 2)
                 pdb_to_ndb_proc_compnd_and_source(0);
       }
}

static int get_number_strands(ISTable *Table, const char *sheet_id)
{
       int  id_index, num_index, rowNo, irow;
       CifString id, number;
       if (is_empty_table(Table)) return 1;

       id_index = Table->GetColumnIndex("id");
       num_index = Table->GetColumnIndex("number_strands");
       if (id_index < 0 || num_index < 0) return 1;
       rowNo = Table->GetNumRows();
       for (irow = 0; irow < rowNo; irow++) {
            get_value(id, Table, id_index, irow);
            get_value(number, Table, num_index, irow);
            if (!strcasecmp(sheet_id, id.Text())) {
                 return (atoi(number.Text()));
            }
       }
       return 1;
}

static int get_sense(ISTable *Table, const char *sheet_id, const char *id_1, const char *id_2)
{
       int id_index, range_id_1, range_id_2, sense_index, rowNo, irow;
       char sense[50];
       CifString id, range_1, range_2, cifstring;

       if (is_empty_table(Table)) return 0;
       id_index = Table->GetColumnIndex("sheet_id");
       range_id_1 = Table->GetColumnIndex("range_id_1");
       range_id_2 = Table->GetColumnIndex("range_id_2");
       sense_index  = Table->GetColumnIndex("sense");
       if (id_index < 0 || range_id_1 < 0 || range_id_2 < 0 || sense_index < 0) return 0;
       rowNo = Table->GetNumRows();
       for (irow = 0; irow < rowNo; irow++) {
            get_value(id, Table, id_index, irow);
            get_value(range_1, Table, range_id_1, irow);
            get_value(range_2, Table, range_id_2, irow);
            get_value(cifstring, Table, sense_index, irow);
            if (!strcasecmp(sheet_id, id.Text()) && !strcasecmp(id_1, range_1.Text()) &&
                !strcasecmp(id_2, range_2.Text())) {
                 strcpy(sense, cifstring.Text());
                 ndb_clean_string(sense);
                 if (sense[0] == '-' || isdigit(sense[0])) return (atoi(sense));
                 else if (!strcasecmp(sense, "anti-parallel")) return (-1);
                 else if (!strcasecmp(sense, "parallel")) return (1);
            }
       }
       return 0;
}

static void get_hbond(_MOLECULE *mol, ISTable *Table, const int chain_index,
            const char *sheet_id, const char *range_id, CifString &curAtom, int &curIndex,
            int &curRes, CifString &prevAtom, int &prevIndex, int &prevRes)
{
       if (is_empty_table(Table)) return;
       int id_index = Table->GetColumnIndex("sheet_id");
       int range_id_2 = Table->GetColumnIndex("range_id_2");
       int beg_label_atom_id = Table->GetColumnIndex("range_2_label_atom_id");
       int beg_label_comp_id = Table->GetColumnIndex("range_2_label_comp_id");
       int beg_label_asym_id = Table->GetColumnIndex("range_2_label_asym_id");
       int beg_label_seq_id = Table->GetColumnIndex("range_2_label_seq_id");
       int beg_label_ins_code = Table->GetColumnIndex("range_2_PDB_ins_code");
       int beg_auth_comp_id = Table->GetColumnIndex("range_2_auth_comp_id");
       int beg_auth_asym_id = Table->GetColumnIndex("range_2_auth_asym_id");
       int beg_auth_seq_id = Table->GetColumnIndex("range_2_auth_seq_id");
       int end_label_atom_id = Table->GetColumnIndex("range_1_label_atom_id");
       int end_label_comp_id = Table->GetColumnIndex("range_1_label_comp_id");
       int end_label_asym_id = Table->GetColumnIndex("range_1_label_asym_id");
       int end_label_seq_id = Table->GetColumnIndex("range_1_label_seq_id");
       int end_label_ins_code = Table->GetColumnIndex("range_1_PDB_ins_code");
       int end_auth_comp_id = Table->GetColumnIndex("range_1_auth_comp_id");
       int end_auth_asym_id = Table->GetColumnIndex("range_1_auth_asym_id");
       int end_auth_seq_id = Table->GetColumnIndex("range_1_auth_seq_id");
       int rowNo = Table->GetNumRows();

       int irow, BegIndex, BegRes, EndIndex, EndRes, beg, end;
       CifString id, range_2;
       for (irow = 0; irow < rowNo; irow++) {
            get_value(id, Table, id_index, irow);
            get_value(range_2, Table, range_id_2, irow);
            if (!strcasecmp(sheet_id, id.Text()) && !strcasecmp(range_id, range_2.Text())) {
                 beg = get_residue_index(mol, Table, irow, beg_label_comp_id,
                       beg_label_asym_id, beg_label_seq_id, beg_auth_comp_id,
                       beg_auth_asym_id, beg_auth_seq_id, beg_label_ins_code,
                       BegIndex, BegRes);
                 end = get_residue_index(mol, Table, irow, end_label_comp_id,
                       end_label_asym_id, end_label_seq_id, end_auth_comp_id,
                       end_auth_asym_id, end_auth_seq_id, end_label_ins_code,
                       EndIndex, EndRes);
                 if (beg && end && (BegIndex == chain_index || EndIndex == chain_index)) {
                      curIndex = BegIndex; curRes = BegRes;
                      prevIndex = EndIndex; prevRes = EndRes;
                      get_value(curAtom, Table, beg_label_atom_id, irow);
                      get_value(prevAtom, Table, end_label_atom_id, irow);
                 }
                 return;
            }
       }
}

static void cif_to_ndb_find_serial_no(ISTable *Table, const int id, const int irow,
         const int tokenid, int *idfield, char idvalue[10][82], char SerialNo[10][82])
{
       int i, j, k;
       unsigned int str_len;
       CifString value;

       for (j = 0; j < 10; j++) {
            SerialNo[j][0] = '\0';
            idvalue[j][0] = '\0';
       }

       if (CifCategory[id].nCifKeyField) {
            for (i = 0; i < CifCategory[id].nCifKeyField; i++) {
                 j =  CifCategory[id].CifKeyField[i];
                 get_value(value, Table, idfield[i], irow);
                 if (tokenid == JRNL_TOKEN-1) {
                      if (value == "primary")
                           strcpy(SerialNo[i], "0");
                      else if (value != "")
                           strcpy(SerialNo[i], value.Text());
                      else sprintf(SerialNo[i], "%d", irow);
                 } else if (value != "") {
                      strcpy(SerialNo[i], value.Text());
                      for (k = 0; k < CifCategory[id].keywords[j].numNdbInfo; k++) {
                           str_len = strlen(CifCategory[id].keywords[j].NdbInfo[k].
                                   JrnlTokenName_Type);
                           if (str_len != 0 && strlen(value.Text()) >= str_len &&
                              !strncmp(value.Text(), CifCategory[id].keywords[j].NdbInfo[k].
                                   JrnlTokenName_Type, str_len)) {
                                strcpy(SerialNo[i], &value.Text()[str_len]);
                                strcpy(idvalue[i], CifCategory[id].keywords[j].
                                      NdbInfo[k].JrnlTokenName_Type);
                                break;
                           }
                      }
                 } else sprintf(SerialNo[i], "%d", irow + 1);
            }
       } else sprintf(SerialNo[0], "%d", irow + 1);
}

void _MAXIT::ndb_processing_requests() 
{
       int i, j, k, ph_idx, mtd_idx, tmp_idx, det_idx, rowNo;
       char buffer[1000];
       ISTable *Table = NULL, *Table1 = NULL;
       CifString pH, method, temp, rcsb_details;

       if (_experiment_type == EXPERIMENT_TYPE_NMR) {
            Table = _CifObj->GetTablePtr(_StructureId, "exptl");
            if (!is_empty_table(Table)) {
                 mtd_idx = Table->GetColumnIndex("method");
                 method.Clear();
                 Table->GetCell(method, mtd_idx, 0);
                 // if (strcasecmp(method.Text(), "NMR, RESTRAINED REGULARIZED MEAN STRUCTURE")) {
                 if (!strstr(method.Text(), "REGULARIZED MEAN STRUCTURE")) {
                      if (_num_mol > 1)
                           sprintf(buffer, "NMR, %d STRUCTURES", _num_mol);
                      else if (_num_mol == 1) {
                           strcpy(buffer, "NMR");
                           Table1 = _CifObj->GetTablePtr(_StructureId, "rcsb_nmr_representative");
                           if (!is_empty_table(Table1)) {
                                tmp_idx = Table1->GetColumnIndex("selection_criteria");
                                temp.Clear();
                                Table1->GetCell(temp, tmp_idx, 0);
                                if (!strcasecmp(temp.Text(), "minimized average structure")) {
                                     strcpy(buffer, "NMR, minimized average structure");
                                }
                           }
                      } else strcpy(buffer, "NMR");
                      method.Copy(buffer);
                      Table->UpdateCell(method, mtd_idx, 0);
                      _CifObj->WriteTable(Table, _StructureId, "exptl");
                 }
            }
            Table = _CifObj->GetTablePtr(_StructureId, "rcsb_nmr_software");
            if (!is_empty_table(Table)) {
                 mtd_idx = Table->GetColumnIndex("classification");
                 rowNo = Table->GetNumRows();
                 tmp_idx = -1; det_idx = -1;
                 for (i = 0; i < rowNo; i++) {
                      Table->GetCell(method, mtd_idx, i);
                      if (!strcasecmp(method.Text(), "structure solution")) tmp_idx = i;
                      if (!strcasecmp(method.Text(), "refinement")) det_idx = i;
                 }
                 if (tmp_idx >= 0 && det_idx < 0) {
                      ph_idx = Table->GetNumColumns();
                      Table->AddRow();
                      for (i = 0; i < ph_idx; i++) {
                           if (i == mtd_idx)
                                method.Copy("refinement");
                           else Table->GetCell(method, i, tmp_idx);
                           Table->UpdateCell(method, i, rowNo);
                      }
                      _CifObj->WriteTable(Table, _StructureId, "rcsb_nmr_software");
                 }
            }
       }

       for (i = 0; i < N_R_MERGE; i++) {
            Table = _CifObj->GetTablePtr(_StructureId, _r_merge[i].catetory);
            if (is_empty_table(Table)) continue;
            mtd_idx = Table->GetColumnIndex(_r_merge[i].item);
            if (mtd_idx < 0) continue;
            rowNo = Table->GetNumRows();
            for (j = 0; j < rowNo; j++) {
                 Table->GetCell(method, mtd_idx, j);
                 if (method == "" || method == "?" || method == ".") continue;
                 if (atof(method.Text()) > 0.99) {
                      sprintf(buffer, "%.7f", atof(method.Text()) / 100.0);
                      for (k = strlen(buffer) - 1; k >= 0; k--) {
                           if (buffer[k] == '0') buffer[k] = '\0';
                           else break;
                      }
                      method.Copy(buffer);
                      Table->UpdateCell(method, mtd_idx, j);
                 }
            }
            _CifObj->WriteTable(Table, _StructureId, _r_merge[i].catetory);
       }

       for (i = 0; i < N_SWITCH_CATEGORY; i++) {
            Table = _CifObj->GetTablePtr(_StructureId, _switch_category[i].category);
            if (is_empty_table(Table)) continue;
            mtd_idx = Table->GetColumnIndex(_switch_category[i].high_item);
            tmp_idx = Table->GetColumnIndex(_switch_category[i].low_item);
            if (mtd_idx < 0 || tmp_idx < 0) continue;
            Table->GetCell(method, mtd_idx, 0);
            Table->GetCell(temp, tmp_idx, 0);
            if (method == "" || method == "?" || method == "." ||
                temp == "" || temp == "?" || temp == ".") continue;
            if (atof(method.Text()) > atof(temp.Text())) {
                 Table->UpdateCell(temp, mtd_idx, 0);
                 Table->UpdateCell(method, tmp_idx, 0);
                 _CifObj->WriteTable(Table, _StructureId, _switch_category[i].category);
            }
       }

       Table = _CifObj->GetTablePtr(_StructureId, "struct_keywords");
       if (!is_empty_table(Table)) {
            ph_idx = Table->GetColumnIndex("ndb_keywords");
            mtd_idx = Table->GetColumnIndex("text");
            pH.Clear();
            Table->GetCell(pH, ph_idx, 0);
            if (pH == "" || pH == "?" || pH == ".") pH.Clear();
            method.Clear();
            Table->GetCell(method, mtd_idx, 0);
            if (method == "" || method == "?" || method == ".") method.Clear();
            if (pH != "" && method == "") {
                 Table->UpdateCell(pH, mtd_idx, 0);
                 _CifObj->WriteTable(Table, _StructureId, "struct_keywords");
            }
       }

       Table = _CifObj->GetTablePtr(_StructureId, "exptl_crystal_grow");
       if (!is_empty_table(Table)) {
            rowNo = Table->GetNumRows();
            ph_idx = Table->GetColumnIndex("pH");
            mtd_idx = Table->GetColumnIndex("method");
            tmp_idx = Table->GetColumnIndex("temp");
            det_idx = Table->GetColumnIndex("rcsb_details");
            for (i = 0; i < rowNo; i++) {
                 rcsb_details.Clear();
                 Table->GetCell(rcsb_details, det_idx, i);
                 if (rcsb_details == "" || rcsb_details == "?" || rcsb_details == ".")
                      rcsb_details.Clear();

                 pH.Clear();
                 Table->GetCell(pH, ph_idx, i);
                 if (pH == "" || pH == "?" || pH == ".") pH.Clear();
                 if (pH != "" && !strstr(rcsb_details.Text(), pH.Text())) {
                      if (rcsb_details != "") rcsb_details += ", ";
                      rcsb_details += "pH ";
                      rcsb_details += pH;
                 }
                 method.Clear();
                 Table->GetCell(method, mtd_idx, i);
                 if (method == "" || method == "?" || method == ".") method.Clear();
                 if (method != "" && !strstr(rcsb_details.Text(), method.Text())) {
                      if (rcsb_details != "") rcsb_details += ", ";
                      rcsb_details += method;
                 }
                 temp.Clear();
                 Table->GetCell(temp, tmp_idx, i);
                 if (temp == "" || temp == "?" || temp == ".") temp.Clear();
                 if (temp != "" && !strstr(rcsb_details.Text(), temp.Text())) {
                      if (rcsb_details != "") rcsb_details += ", temperature ";
                      rcsb_details += temp;
                      rcsb_details += "K";
                 }
                 Table->UpdateCell(rcsb_details, det_idx, i);
            }
            _CifObj->WriteTable(Table, _StructureId, "exptl_crystal_grow");
       }

       Table = _CifObj->GetTablePtr(_StructureId, "ndb_xplor_file");
       if (!is_empty_table(Table)) {
            rowNo = Table->GetNumRows();
            mtd_idx = Table->GetColumnIndex("param_file");
            tmp_idx = Table->GetColumnIndex("topol_file");
            for (i = 0; i < rowNo; i++) {
                 Table->GetCell(method, mtd_idx, i);
                 if (method != "" && method != "?" && method != ".") {
                      strcpy(buffer, method.Text());
                      for (j = strlen(buffer) - 1; j >= 0; j--) {
                           if (buffer[j] == '/') break;
                      }
                      method.Copy(&buffer[j + 1]);
                      Table->UpdateCell(method, mtd_idx, i);
                 }
                 Table->GetCell(method, tmp_idx, i);
                 if (method != "" && method != "?" && method != ".") {
                      strcpy(buffer, method.Text());
                      for (j = strlen(buffer) - 1; j >= 0; j--) {
                           if (buffer[j] == '/') break;
                      }
                      method.Copy(&buffer[j + 1]);
                      Table->UpdateCell(method, tmp_idx, i);
                 }
            }
            _CifObj->WriteTable(Table, _StructureId, "ndb_xplor_file");
       }

       Table = _CifObj->GetTablePtr(_StructureId, "database_PDB_remark");
       if (!is_empty_table(Table)) {
            rowNo = Table->GetNumRows();
            mtd_idx = Table->GetColumnIndex("id");
            if (mtd_idx >= 0) {
                 for (i = 0; i < rowNo; i++) {
                      Table->GetCell(method, mtd_idx, i);
                      if (method != "" && method != "?" && method != ".") {
                           strcpy(buffer, method.Text());
                           k = strlen(buffer);
                           for (j = 0; j < k; j++) {
                                if (!isdigit(buffer[j])) break;
                           }
                           if (j < k) {
                                Table->DeleteRow(i);
/*
                                Table->RemoveRow(i);
                                i--;
                                rowNo--;
*/
                           }
                      }
                 }
                 Table->CompressTable();
                 _CifObj->WriteTable(Table, _StructureId, "database_PDB_remark");
            }
       }
}
