
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "util.h"

/* the utilities for both pdb_extract and pdb_extract_sf */


int str_cmp(const char *str, const char *str1, int n1, char *tmp1);
int str_comp(const char *str, const char *str1,  char *tmp1);


void token_str(char *str, const char *token, long *nstr, char **line)

/* token the string and put them into line[][] */
{
    char *tokenPtr;
    long k=0,i=0;

    k= strlen(str);
    if(strstr(str, "\n")){ /*rid of \n */
        str[k-1]=' ';
    }
    
    tokenPtr = strtok(str, token);
    i = 0;
    while(tokenPtr != NULL){
        strcpy(line[i], tokenPtr);
        tokenPtr = strtok(NULL, token);
        i++;
    }
    *nstr = i;
        
}


char ** string_token(char *str, const char *token, int *nstr)

/* token the string return **line */
{
    char *tokenPtr, **line=NULL, *tmp=NULL;
    int i=0;


    delete_return(str);
    
    tmp = new char [strlen(str) +1];
    strcpy(tmp,str);

    tokenPtr = strtok(tmp, token); //get number of token
    i = 0;
    while(tokenPtr != NULL){
        tokenPtr = strtok(NULL, token);
        i++;
    }
    delete [] tmp;

    line = new char *[i+1];
    
    tokenPtr = strtok(str, token);
    i = 0;
    while(tokenPtr != NULL){
        line[i] = new char [strlen(tokenPtr) +1];
        
        strcpy(line[i], tokenPtr);
        tokenPtr = strtok(NULL, token);
        i++;
    }
    *nstr = i;
    return (line);
    
}



long upperstr(char *a)
/* change to upper case, and return string length */
{
    long nlen = 0;

    while (*a) {
        nlen++;
        if (islower((int) *a))
            *a = toupper(*a);
        a++;
    }
    return nlen;
}

long lowerstr( char *a)
/* change to upper case, and return string length */
{
    long nlen = 0;

    while (*a) {
        nlen++;
        if (isupper((int) *a))
            *a = tolower(*a);
        a++;
    }
    return nlen;
}


long num_of_line(const char *inpfile)
{
    char str[512];
    long n=0;    
    FILE *fp;
    
    if((fp = fopen(inpfile, "r"))==NULL) {        
        printf("Can not open the file %s (routine:num_of_line)\n",inpfile);
        return 0;
    }
    
    n=0;    
    while (fgets(str, sizeof str, fp) != NULL) {
        n++;
    }
    fclose(fp);    
    return n;
}
    

void get_data_set_id(const char *str, const char *start, const char *end,
                     char *substr)
/* return the substr between the first start and the first end of the str */
{
    char str_start[512];
    long n1=0, len=0;
    
    
    if(!strstr_case(str, start) || !strstr_case(str, end) ) {
        strcpy(substr,"");
//        printf("There is no start (%s) or end (%s) \n", start,end);
        return;
    }
    
    len = strlen(start);
    strcpy(str_start, strstr_case(str, start)+len );
    rid_of_front_space(str_start);
    if(!strstr_case(str_start, end) ){ /*end is not after start*/
//        printf("End (%s) is not after start (%s) \n", end, start);
        strcpy(substr,"");
        return;
    }

    n1 = strstr_case(str_start, end) - str_start;
    strncpy(substr,str_start, n1);
    substr[n1]='\0';
    if(iscntrl(substr[n1-1]))substr[n1-1]='\0';
    if(iscntrl(substr[n1-2]))substr[n1-2]='\0';
         
}



void char2space(char *str, char charact)
/* subsitute the charact by a space */
{
    int i=0, len=0;

    len=strlen(str);
    for(i=0; i<len; i++){
        if(str[i]==charact) str[i]=' ';
    }
}

void rid_of_char(char *str, char ch)
/* get rid of space*/
{
    int i=0, j=0, len=0;

    len=strlen(str);
    for(i=0; i<len; i++){
        if(str[i]==ch) continue;
        str[j++]= str[i];
    }
    str[j]='\0';
    if(iscntrl(str[j-1]))str[j-1]='\0';
}

void rid_of_space(char *str)
/* get rid of space*/
{
    int i=0, j=0, len=0;

    len=strlen(str);
    for(i=0; i<len; i++){
        if(isspace(str[i])) continue;
        str[j++]= str[i];
    }
    str[j]='\0';
    if(iscntrl(str[j-1]))str[j-1]='\0';
}

void rid_of_front_end_space(char *str)
{
    int i=0, j=0, len=0, n=0;

    len=strlen(str);  
    for(i=0; i<len; i++){  //front space
        if(isspace(str[i]))
            continue;
        else{
            j=i;
            break;
        }
    }
    n=0;
    for(i=j; i<len; i++){
        str[n++]=str[i];
    }
    str[n]='\0';

    if(str[0]=='\0') return;
    
    n=0;
    len=strlen(str);
    for(i=len-1; i>=0; i--){ //end space
        if(isspace(str[i]))
            n++;
        else
            break;
    }
    str[len-n]='\0';
    if(iscntrl(str[len-n-1]))str[len-n-1]='\0';
}


void rid_of_front_space(char *str)
/* get rid of first space*/
{
    int i=0, j=0, len=0, n=0;

    len=strlen(str);
    for(i=0; i<len; i++){
        if(isspace(str[i]))
            continue;
        else{
            j=i;
            break;
        }
    }
    
    for(i=j; i<len; i++){
        str[n++]=str[i];
    }
    str[n]='\0';
}

void rid_of_end_space(char *str)
/* get rid of space after last word */
{
    int i=0,  n=0, len;

    len=strlen(str);
    for(i=len-1; i>=0; i--){
        if(isspace(str[i]))
            n++;
        else
            break;
    }
    str[len-n]='\0';
    if(iscntrl(str[len-n-1]))str[len-n-1]='\0';
}



int strstr_space( const char *str, const char *str1)
/* see if str1 is in str regardless of the spaces in str and str1
 (case insensitive!)
*/
{
    int i=0, j=0, n=0, n1=0, key=0;
    char *tmp=NULL, *tmp1=NULL;
    
    tmp=(char *) calloc(strlen(str)+1, sizeof(char)+1);
    tmp1=(char *) calloc(strlen(str1)+1, sizeof(char)+1);
    
   
    strcpy(tmp, str);
    strcpy(tmp1, str1);

    n=strlen(tmp);
    n1=strlen(tmp1);

    tmp1[0] = toupper(str1[0]);
    j=1;
    for(i=1;i<n1;i++){
        if ( isspace(str1[i-1]) && isspace(str1[i]) ) continue;
        tmp1[j] = toupper(str1[i]);
        j++;
    }
    tmp1[j]='\0';

    tmp[0] = toupper(str[0]);
    j=1;
    for(i=0;i<n;i++){
        if ( isspace(str[i]) &&  isspace(str[i+1]) ) continue;
        tmp[j++] = toupper(str[i]);
    }
    tmp[j]='\0';

    if(strstr(tmp, tmp1))
        key = 1;
    else
        key = 0;

    free (tmp);
    free (tmp1);
    
    return key;
    
}


int pattern5(const char *str,const char *str1,const char *str2,
             const char *str3, const char *str4,const char *str5)
{
    char *tmp1=NULL,*tmp2=NULL,*tmp3=NULL,*tmp4=NULL,*tmp5=NULL;
    
    if(strlen(str)==0) return 0;
    
    tmp1= new char [strlen(str)+1];
    tmp2= new char [strlen(str)+1];
    tmp3= new char [strlen(str)+1];
    tmp4= new char [strlen(str)+1];
    tmp5= new char [strlen(str)+1];

    if(!str_comp(str, str1, tmp1)){
        delete []tmp1; delete []tmp2; delete []tmp3; delete []tmp4; delete []tmp5;
        return 0;
    }
    if(!str_comp(tmp1, str2, tmp2)){
        delete []tmp1; delete []tmp2; delete []tmp3; delete []tmp4; delete []tmp5;
        return 0;
    }
    if(!str_comp(tmp2, str3, tmp3)){
        delete []tmp1; delete []tmp2; delete []tmp3; delete []tmp4; delete []tmp5;
        return 0;
    }
    if(!str_comp(tmp3, str4, tmp4)){
        delete []tmp1; delete []tmp2; delete []tmp3; delete []tmp4; delete []tmp5;
        return 0;
    }
    if(!str_comp(tmp4, str5, tmp5)){
        delete []tmp1; delete []tmp2; delete []tmp3; delete []tmp4; delete []tmp5;
        return 0;
    }
     
    delete []tmp1; delete []tmp2; delete []tmp3; delete []tmp4; delete []tmp5;
    return 1;
}


int str_comp(const char *str, const char *str1,  char *tmp1)
{

    int n;

    if((n=strlen(str1)) <= 0){
        strcpy(tmp1, str);
        return 1;
        
    }
    
    if(strstr_case(str, str1)){
        strcpy(tmp1, strstr_case(str, str1) + n);
        return 1;
    }else{
        strcpy(tmp1, str);
        return 0;
    }
}


int str_cmp(const char *str, const char *str1, int n1, char *tmp1)
// compare str and str1, return new char after str1
{
    
    if(strstr_case(str, str1)){
        strcpy(tmp1 , strstr_case(str, str1) + n1);
        return 1;
    }else
        return 0;
}
/*
int pattern5(const char *str,const char *str1,const char *str2,
             const char *str3, const char *str4,const char *str5)
{
    char *tmp1=NULL,*tmp2=NULL,*tmp3=NULL,*tmp4=NULL;
    int n1,n2,n3,n4;
    
    if(strlen(str)==0) return 0;
    
    if((n1 = strlen(str1)) > 0){
        
        if(strstr_case(str, str1)){
            if((n2 = strlen(str2)) > 0){
                tmp1 = strstr_case(str, str1) + n1; //after str1

                if( strstr(tmp1, str2) ){ //test str2
                    
                    if((n3 = strlen(str3)) > 0){  
                        tmp2= strstr_case(tmp1, str2) + n2; //after str2
                        if( strstr_case(tmp2, str3) ){
                                
                            if((n4 = strlen(str4)) > 0){
                                tmp3= strstr_case(tmp2, str3) + n3;//after str3

                                if( strstr_case(tmp3, str4) ){
                                    
                                    if(strlen(str5) > 0){ //after str4
                                        tmp4= strstr_case(tmp3, str4) + n4;
                                        if( strstr_case(tmp4, str5) ){
                                            return 1;
                                        }else {
                                            return 0; //str5
                                        }
                                        
                                    }else{
                                        return 1;
                                    }
                                    
                                }else{
                                    return 0; //str4
                                }
                                
                                
                            }else {
                                return 1;
                            }

                            
                        }else {
                            return 0; //str3
                        }
                        
                    }else{
                        return 1;
                    }
                    
                }else{  
                    return 0; //str2
                }
                
            }else{
                return 1;
            }

        }else{
            return 0; //str1
        }

    }else{
        return 0;
    }
}
*/

int strcmp_case (const char *s1, const char *s2){
  int same =0;
  char a1, a2;

  while (s1[0]!='\0' && s2[0]!='\0' && !same) {
    a1 = tolower(s1[0]);
    a2 = tolower(s2[0]);
    if (a1!=a2)
      if (a1<a2)
	same = 1;
      else
	same = -1;
    s1++; s2++;
  }
  if ((s1[0]!='\0'|| s2[0]!='\0')&& same==0)
    if (s1[0]!='\0')
      same = 1;
    else
      same = -1;
  return same;
}

int strncmp_case (const char *s1, const char *s2, int n){

  int same =0;
  char a1, a2;
  int i=0;
  
  i=0;
  while (s1[0]!='\0' && s2[0]!='\0' && !same && i<n) {
    a1 = tolower(s1[0]);
    a2 = tolower(s2[0]);
    if (a1!=a2)
      if (a1<a2)
	same = 1;
      else
	same = -1;
    s1++; s2++;
    i++;
  }
  if ((s1[0]!='\0'|| s2[0]!='\0')&& same==0)
    if (i<n) {
      if (s1[0]!='\0')
	same = 1;
      else
	same = -1;
    }
  return same;
}

char* strstr_case(const char *s1, const char *s2) 
{ 
    int i,j,k; 

    for(i=0;s1[i];i++) 
        for(j=i,k=0;tolower(s1[j])==tolower(s2[k]);j++,k++) 
            if(!s2[k+1]) 
                return (char*) (s1+i); 

    return NULL; 
}


void replace_first_str(const char *str_old, const char *str1, const char *str2,
                       char *str_new)
/*
  str_old is the old string and str_new is the new string after replace
  str1 is the first occurrence in str_old.
  str2 is the given string for replace.
*/
    
{
    char *tmp=NULL, *tmp1=NULL;
    int n1;

    if(strlen(str_old)<=0) return;
    if(strstr_case(str_old, str1) <=0){
        printf("String=%s is not in the string=%s\n", str1, str_old);
        return;
    }
    tmp= new char[strlen(str_old)+1];;
    tmp1=new char[strlen(str_old)+1];
        
    strcpy(tmp, strstr_case(str_old,str1) + strlen(str1));
    
    n1 = strstr_case(str_old,str1) - str_old;
    strncpy(tmp1, str_old, n1);
    tmp1[n1]='\0';

    sprintf(str_new, "%s%s%s", tmp1, str2,tmp);
    delete tmp;
    delete tmp1;
    
}

int is_space_line(const char *str)
// n=0, is a space line; n!=0 NOT.    
{
    int i, n=0, len;

    len = strlen(str);
    for(i=0; i<len; i++){
        if(isspace(str[i])) continue;
        n++;
    }
    return n;
}

void delete_return(char *line)
/* rid of \n */
{
    long len=0, i=0;
    
    len = strlen(line);
    for(i=0; i<len; i++)  
        if(line[i]=='\n')
            line[i]=' ';
    if(iscntrl(line[i-1]))line[i-1]='\0';
}

void get_string(const char *str_in, int start, int end, char *str_out)
{

    int len=0, i=0, n, stop;
    
    len = strlen(str_in);
    if(len<=start || start>=end){ 
        strcpy(str_out, "?");
//        printf("The input (%s)\n string length (%d) < start position!(%d)\n",str_in,len,start );
        return ;
    }
    if(end<=len) {
        stop = end;
    }else{
        stop = len;
    }
    
    
//    (end<=len) ? stop = end: stop = len; //why it does not work for SGI? 
    n=0;
    for(i=start; i<=stop; i++){
        str_out[n++]=str_in[i];
    }
    str_out[n] = '\0';
    if(iscntrl(str_out[n-1])) str_out[n-1]='\0';
    if(is_space_line(str_out)==0) strcpy(str_out, "?");
    
}

void get_last_string(const char *str_in, int length,  char *str_out)
        // length = length of last string
{
    char *tmp=NULL;
    long len=0,len1=0, i=0, n;

    
    len = strlen(str_in);
    tmp = new char[len+1];
    strcpy(tmp, str_in);
    
    if(len<=length){
        strcpy(str_out, "?");
//        printf("The number (length=%d ) is out of line\n", length);
        delete [] tmp;
        
        return;
    }
    
    rid_of_end_space(tmp);
    len1=strlen(tmp);
    
    n=0;
    for(i=len1-length; i<len1; i++){
        str_out[n++]=tmp[i];
    }
    str_out[n] = '\0';
    if(iscntrl(str_out[n-1])) str_out[n-1]='\0';
    if(is_space_line(str_out)==0) strcpy(str_out, "?");
    delete [] tmp;
   
}


void open_file_error(const char *inpfile, const char *message)
{
    printf("Can not open the file = (%s)\n",inpfile);
    printf("Program stoped at subroutine = (%s)\n",message);
    exit(0);
}

void write_data_message(const char *program, const char *filename)
{
    printf("\nWarning! No data was extracted from file (%s).\n", filename);
    printf("Please check the %s format!\n", program);
    printf("or send your file (%s) to 'sw-help@rcsb.rutgers.edu'.\n\n",
           filename);
}

char *get_substr(const char *str,  const char *start,  const char *end)
{
    char *str_start=NULL, *substr=NULL;
    long n1=0, len=0;
    
    len = strlen(str);
    str_start = new char [len+1];
    substr = new char [len+1];
    
    if(!strstr_case(str, start) || !strstr_case(str, end) ) {
        strcpy(substr,"?");
//        printf("There is no start (%s) or end (%s) \n", start,end);
        delete [] str_start;
        
        return substr ;
    }
    
    len = strlen(start);
    strcpy(str_start, strstr_case(str, start)+len );
    if(!strstr_case(str_start, end) ){ /*end is not after start*/
        strcpy(substr,"?");
//        printf("End (%s) is not after start (%s) \n", end, start);
        delete [] str_start;
        
        return substr;
    }else{
        
        n1 = strstr_case(str_start, end) - str_start;
//        printf("nn1=%d\n", n1);
           
        strncpy(substr,str_start, n1);
        substr[n1]='\0';
        if(iscntrl(substr[n1-1]))substr[n1-1]='\0';
        if(iscntrl(substr[n1-2]))substr[n1-2]='\0';
        delete []str_start;
        rid_of_front_space(substr);
        rid_of_end_space(substr);
        if(is_space_line(substr)==0) strcpy(substr, "?");
        return substr;
    }
}

char *get_string_after_id_number(const char *str,  const char *id,  int num)
// get string after id by the giving string number (spaced).    
{
    char *str_tmp=NULL, *substr=NULL, **line=NULL;
    int i, len=0, len_id=0, nstr=0, number;
    
    len = strlen(str);
    len_id = strlen(id);
    if (!strstr_case(str, id) || len<len_id){
        printf("The id =(%s) is not in the string (%s)\n", id, str);
        return  substr ;
    }
    
        
    str_tmp = new char [len+1];
    substr = new char [len+1];
    
    strcpy(str_tmp, strstr_case(str, id) + len_id);

    line = string_token(str_tmp," ", &nstr);
    (nstr>num)? number = num: number = nstr;
    
    strcpy(substr, "");
    for(i=0; i<number;i++){
        strcat(substr, line[i]);
        strcat(substr, " ");
    }
    delete [] line;
    delete [] str_tmp;
    return substr;
}

void  get_one_string_after_id(const char *str,  const char *id,  char *str_out)
// get string after id by the giving string number (spaced).    
{
    char *str_tmp=NULL;
    int  len=0;
    
    len = strlen(str);
    if (!strstr_case(str, id)){
        printf("The id =(%s) is not in the string (%s)\n", id, str);
        return ;
    }
        
    str_tmp = new char [len+1];
    strcpy(str_tmp, strstr_case(str, id) + strlen(id));
    if(sscanf(str_tmp, "%s", str_out) !=1){
        printf("Nothing exists after string (%s)\n", id);
        return;
    }
    delete [] str_tmp;
}

int get_int_after_id(const char *str,  const char *id)
// get string after id by the giving string number (spaced).    
{
    char *str_tmp=NULL;
    int i, len=0;
    
    len = strlen(str);
    if (!strstr_case(str, id)){
        printf("The id =(%s) is not in the string (%s)\n", id, str);
        return -9999;
    }
        
    str_tmp = new char [len+1];
    strcpy(str_tmp, strstr_case(str, id) + strlen(id));
    if(sscanf(str_tmp, "%d", &i) !=1){
        printf("Nothing exists after string (%s)\n", id);
    delete [] str_tmp;
        return 0;
    }
    delete [] str_tmp;
    return i;
}

float get_float_after_id(const char *str,  const char *id)
// get string after id by the giving string number (spaced).    
{
    char *str_tmp=NULL;
    int len=0;
    float a;
    
    
    len = strlen(str);
    if (!strstr_case(str, id)){
        printf("The id =(%s) is not in the string (%s)\n", id, str);
        return 0;
    }
        
    str_tmp = new char [len+1];
    strcpy(str_tmp, strstr_case(str, id) + strlen(id));
    if(sscanf(str_tmp, "%f", &a) !=1){
        printf("Nothing exists after string (%s)\n", id);
    delete [] str_tmp;
        return  0;
    }
    delete [] str_tmp;
    return a;
    
}


char *get_string_after_id_length(const char *str,  const char *id,  int leng)
// get string after id by the giving length.    
{
    char *str_tmp=NULL, *substr=NULL;
    int  len=0, len_id=0,len_tmp=0,length ;
    
    len = strlen(str);
    len_id = strlen(id);
    if (!strstr_case(str, id) || len<len_id){
        printf("The id =(%s) is not in the string (%s)\n", id, str);
        return  substr ;
    }
    
        
    str_tmp = new char [len+1];
    substr = new char [len+1];
    
    strcpy(str_tmp, strstr_case(str, id) + len_id);
    len_tmp =  strlen(str_tmp);

    (len_tmp>leng)? length = leng : length =len_tmp;
    
    strncpy(substr, str_tmp, length);
    substr[length] = '\0';
   
    delete [] str_tmp;
    return substr;
}


char *get_string_by_length(const char *str,  int start,   int end)
{
    char *str_tmp=NULL, *str_out=NULL;
    
    int len=0,  n;

    len = strlen(str);
    if(len<=start || start>end){
        return  (char*)"?";
    }
    if(end>len) end = len;
   
    n=end-start+1;
    str_tmp=new char [len+1];
    str_out = new char [n+1];
    
    strcpy(str_tmp, str + start);
    strncpy(str_out, str_tmp, n);
    str_out[n]='\0';
    delete [] str_tmp;
    if(iscntrl(str_out[n-1])) str_out[n-1]='\0';
    rid_of_end_space(str_out);
    if(is_space_line(str_out)==0) strcpy(str_out, "?");
    return str_out; 
}

void get_string_with_length(const char *str, int start,int end, char *substr)
{
    int i, j, len;
    
    len = strlen(str);
    if(len<=start || start>end){
        strcpy(substr,"?");
        printf("Warning! The given integers(start=%d; end=%d)\n",start, end);
        printf("are beyond string (%s) scope\n",str);
        return;
    }
    if(end>len) end = len;
    j=0;
    for(i=start;i<=end;i++){
        substr[j++] = str[i];
    }
    substr[j] = '\0';
}


float get_float(const char *str, const char *start,  const char *end)
{
    char *tmp=NULL;
    int n;
    float a;
    tmp=get_substr(str,start,end);
    n=sscanf(tmp, "%f", &a);
    delete tmp;
    
    if (n==1) return a;
    else return -99999;
}

int get_int(const char *str,  const char *start,   const char *end)
{
    int n, k;
    char *tmp=NULL;
    
    tmp = get_substr(str,start,end);
    n=sscanf(tmp, "%d", &k);
    
    delete [] tmp;
    if (n==1) return k;
    else return -99999;
}

float get_float_by_length(const char *str,  int start,   int end) 
{
    char *str_out=NULL;
    int n;
    float a;
    
    str_out=new char[strlen(str)+1];

    get_string(str, start,  end, str_out) ;

    n=sscanf(str_out, "%f", &a);
    
    delete [] str_out;
    
    if (n==1) return a;
    else return -99999.0;
}

int get_int_by_length(const char *str,  int start,   int end) 
{
    char *str_out=NULL;
    int n, a;
    
    str_out=new char[strlen(str)+1];

    get_string(str, start,  end, str_out) ;

    n=sscanf(str_out, "%d", &a);
    delete [] str_out;
    
    if (n==1) return a;
    else return -99999;
}

char *get_attribute_value(CifFileObj *fobj, const char *blockId,
                          const char *category, const char *attribute)
{
  ISTable *t=NULL;

  ReVarCifArray<CifString> *col=NULL;
  int nRow, iCol;
  char *string=NULL;


  if (fobj->IsTablePresent(blockId,category)) {
    t=fobj->GetTablePtr(blockId,category);
    nRow = t->GetNumRows();

    if (nRow > 0) {
      iCol = t->GetColumnIndex(attribute);
      if (iCol >= 0) {
	col=t->GetColumn(iCol);
	if (col && ((*col)[0].Length() > 0) ) {
	  string = new char[(*col)[0].Length() + 1];
	  strcpy(string,(*col)[0].Text());

	}
      }
    }
  }
  return(string);
}

char **get_attribute_values(CifFileObj *fobj, const char *blockId,
                            const char *category,const char *attribute,
                            long *nrow)
{
  ISTable *t = NULL;
  ReVarCifArray<CifString> *col=NULL;
  int nRow, iCol, ncol;
  char **strings=NULL;


  if (fobj->IsTablePresent(blockId,category)) {
      t=fobj->GetTablePtr(blockId,category);
      nRow = t->GetNumRows();
//      printf("nRow= %d\n", nRow);
    
      if (nRow > 0) {
          iCol = t->GetColumnIndex(attribute);

          if (iCol >= 0) {
              col=t->GetColumn(iCol);
              if (col && (col->Length() > 0) ) {
                  strings = new char *[ col->Length() + 1];
                  *nrow = col->Length();
//                  printf("HERE %5d %5d  %5d\n",iCol, nRow, col->Length());
                  ncol = col->Length();
                  for (int i=0;  i < ncol; i++) {
                      strings[i] = new char[(*col)[i].Length() + 1];
                      strcpy(strings[i],(*col)[i].Text());
            
                  }
//                  nValues = col->Length();
              }
          }
      }
  }
  return(strings);
}

int is_cif(const char *inpfile)
/* all the possible categories are seperated by a space */
{
    char str[512], tmp[512], category[100], item[100];
    int ncat=0,  n;
    FILE *fp;
    
    if((fp = fopen(inpfile, "r"))==NULL) {
        open_file_error(inpfile, "is_cif");
    }

    while(fgets(str, sizeof str, fp)!= NULL){
        rid_of_front_end_space(str);
        
        n=sscanf(str,"%s",tmp);
        
        if(n!=1 || tmp[0] != '_' || !strchr(tmp,'.')
           || strlen(tmp)<=1 || strlen(tmp)>100) continue;
        
        
        strcpy(item, strchr(tmp,'.')+1);
        get_data_set_id(tmp,"_", ".", category);
        
        if(strlen(category)<1 || strchr(category,'.')) continue;
        if(strlen(item)<1 || strchr(item,'.')) continue;
        
        
            
//        printf("str=%s; category=%s; item=%s\n",str, category, item); 
        
        ncat++;
        if(ncat>60) break;
    
    }
    
    fclose(fp);
    return ncat;
}


int is_pdb(const char *inpfile)
{
    char str[256],tmp[256], atom[5], res[5], xyz[30];
    int  nline=0, len, chain=0;
    FILE *fp;
    
    if((fp = fopen(inpfile, "r"))==NULL) {
        open_file_error(inpfile, "is_pdb");
    }

    while(fgets(str, sizeof str, fp)!= NULL){
        strcpy(tmp,str);
        rid_of_front_end_space(tmp);
        len = strlen(tmp);
        
        if ((!strncmp_case(str, "ATOM  ", 6)|| !strncmp_case(str, "HETATM", 6))
            && len>54 && len< 82) {
            strncpy(atom, str+12,4);
            atom[4]='\0';
            strncpy(res, str+17,3);
            res[4]='\0';
            strncpy(xyz, str+28,24);
            xyz[24]='\0';

            if(strlen(atom)>0 && strlen(res)>0 &&
               pattern5(xyz, ".",".",".","","")){
                nline++;
                if(isalnum(str[21])) chain++;
                if(nline >50) break;  
            }
        }
    }
    fclose(fp);
//    printf("hello chain, nline = %d %d\n", chain, nline );
    
    if(nline>0 && chain != nline){
        printf("Severe warning! The PDB file (%s) do not have the right chain ID.\n",inpfile);
        printf("Chain ID should be either letter or number.\n");
        printf("Please give the right chain ID before continuing!\n");
    }
    
    return nline;
}

int  check_category(const char *str, char *category, char *item)
// get possible category between _ and . (no space in between)     
{
    int  n=0, i=0;
    char  *tmp=NULL;

    tmp = new char[strlen(str)+1];
    
    n=sscanf(str,"%s",tmp);
        
    if(n!=1 || tmp[0] != '_' || !strchr(tmp,'.')
       || strlen(tmp)<=1 || strlen(tmp)>100) {
        strcpy(category, "");
        strcpy(item, "");
        delete []tmp;
        return 0;
    }
    
        
    strcpy(item, strchr(tmp,'.')+1);
    
    for(i=0; tmp[i]!='.'; i++){
        category[i]=tmp[i];
    }
    category[i] = '\0';
        
    if((strlen(category)<1 || strchr(category,'.')) ||
      (strlen(item)<1 || strchr(item,'.')) ) {
        strcpy(category, "");
        strcpy(item, "");
        delete []tmp;
        return 0;
    }

    delete []tmp;

    return 1;
    
}


/*
int  check_category(const char *str, char *category, char *item)
// get possible category between _ and . (no space in between)     
{
    int i, j=0, k, n,m, ndot=0, nspace=0, len=0;
    char *tokenPtr=NULL, *tmp;

    tmp = (char *) calloc(strlen(str), sizeof(char)+1);
    printf("str=%s; category=%s; item=%s\n",str, category, item); 
    strcpy(tmp, str);
    tokenPtr = strtok(tmp," ");
    strcpy(tmp, tokenPtr);
    strcpy(category, "");
    len=strlen(tmp);
    
    for(i=0; i<len-1; i++){
        if(isspace(tmp[i]))continue;
        if(!isspace(tmp[i]) && tmp[i] != '_'){
            strcpy(category, "");
            return 0;
        }else{
            j=i;
            break;
        }
    }

    for(i=j; i<len; i++){
        if(isspace(tmp[i]) )nspace++;
        if(tmp[i]=='.') ndot++;
        
        if( nspace==0 && ndot==0 ) continue;
        if( nspace>0 && ndot==0 ){
            strcpy(category, "");            
            return 0;
        }else if(i<=len-1 && nspace==0 && ndot==1 && !isspace(tmp[i+1])){
                
            n=0;
            for(k=j; k<i; k++){
                category[n++]=tmp[k];
            }
            category[n]='\0';
            
            n=0;
            for(m=k+1; m<len; m++){
            if(isspace(tmp[m])) continue;  // rid of return charactor
                item[n++]=tmp[m];
            }
            item[n]='\0';
            if(n<2){
                return 0;
            }else            
//            printf("!!! %s.%s\n", category, item);
                return 1;            
        }
    }
    return 0;
    
}
*/
void write_cif(FILE *fout,  const char *inpfile,const  char *method)
/* Note: if CIF, write everythings after check;.*/
{
    int n=0;
    char  str[512], tmp[512];
    FILE *fp;

    if((fp = fopen(inpfile, "r"))==NULL) {
        open_file_error(inpfile, "write_cif");
    }
 
    n=is_cif(inpfile);
    if(n<=1){
        printf("Error! File (%s) is not in CIF format\n", inpfile);
        fclose(fp);
        return;
    }
    n=0;
    while(fgets(str, sizeof str, fp)!= NULL){
        strcpy(tmp,str);
        rid_of_front_space(tmp);
        if(tmp[0] !='#') n++;
        if(n==1 && !strncmp_case(tmp,"data_",5)) continue;
        fprintf(fout,"%s", str);
    }
    
    fclose(fp);
}

int  write_mmcif_sf(FILE *fout, char *iFile, int write)
{
    char *diags=NULL,  *fnx=(char*)"cif2cif_from_cifparse";
    char  *blockId=NULL,  **tmp=NULL;
    long n1=0;
    FILE *fp;
    
    CifFileObj * fobjR = NULL;


    if((fp = fopen(iFile, "r"))==NULL){
        open_file_error(iFile, "write_mmcif_sf");
    }
    fclose(fp);
    
    if(is_cif(iFile)<3){
        return 0;
    }
    
    fobjR = new CifFileObj(fnx, WRITE_MODE, 80, "?", 1);
    fobjR->Read(iFile,diags);
    if (diags != NULL) fprintf(stderr, "Diags for file %s: %s\n",iFile,diags);
    fobjR->CloseFile();
    if (fobjR) delete fobjR;

    fobjR = new CifFileObj(fnx, READ_MODE);

    blockId = fobjR->GetBlockName(0);
    
    tmp = get_attribute_values(fobjR, blockId, "refln", "index_h", &n1);
    
    if(n1<10 ){
        delete_file("cif2cif_from_cifparse");
        return 0;
    }else{
        if(write>0) write_cif(fout, iFile, "");
        if(tmp) free_memory_2d(tmp, n1);
        delete_file("cif2cif_from_cifparse");
        return 1;
    }
    
}

void change_file_name(const char *inpfile, char *outfile)
{
    char str[512];
    FILE *fp=NULL, *fout=NULL;

    if((fp=fopen(inpfile, "r"))==NULL){
        open_file_error(inpfile, "change_file_name");
    }
    fout=fopen(outfile, "w");
    
    while(fgets(str, sizeof str,fp)!=NULL){
        fprintf(fout, "%s", str);
    }
    fclose(fp);
    fclose(fout);
    
}

    

void delete_file(const char *file)
{
    char command[512];
    
    strcpy(command,"");
    strcpy(command, "rm -f  ");
    strcat(command, file);
    system(command);
}
    

char *make_string(const char *str1, const char *str2, const char *str3)
{
    int m;
    char *string=NULL;
    

    m = strlen(str1) + strlen(str2) + strlen(str3);
    string = new char[m+1];
    strcpy(string, "");
    strcat(string, str1);
    strcat(string, str2);
    strcat(string, str3);

    return string;
}

void array_sort(char ** str, int max)
 /* str 2D array; max array length*/
{
    int i, j;
    char *tmp;
    

    for(j = 0; j <max-1 ; j++){
        for (i=j+1; i<max; i++){
            if(strcmp(str[i], str[j])>0){
                tmp = str[j];
                str[j]= str[i];
                str[i]= tmp;
            }
        }
    }
    
}

void replace_char(char *str, char find, char replace)
/* replace the find by replace in the string str*/
{
    int i,  len;

    len =strlen(str);

    if(!strchr(str,find)){
        printf("Sorry, the character (%c) is not in the string.\n(%s)\n", find ,str);
        return;
    }
    
    for(i = 0; i <len ; i++){
        if(str[i] == find ) str[i] = replace;
    }
    
}

     
void print_mmcif_head(FILE *fout, const char *category, const char **items, int nitems)
{
    int i;
    
    fprintf(fout, "#\nloop_\n");
    for(i=0; i<nitems;i++) {
        fprintf(fout, "%s.%s\n", category, items[i]);
//        printf( "%s.%s\n", category, items[i]);
    }
}

char **get_lines_from_file(char *inpfile, int *nline)
        //there is no space between lines
{
    char str[512], **all_line=NULL;
    int m;
    FILE *fp=NULL;

    
    if((fp=fopen(inpfile, "r"))==NULL)
       open_file_error(inpfile, "get_lines_from_file");
    
    
    m=0;
    while (fgets(str, sizeof str, fp) != NULL) {
        if(is_space_line(str)<=0)continue;
        m++;
    }
    rewind(fp);
    all_line=new char *[m+1];

    m=0;
    while (fgets(str, sizeof str, fp) != NULL) {
        if(is_space_line(str)<=0)continue;
         all_line[m] = new char [strlen(str) +1];
        strcpy(all_line[m],str);
        m++;
    }
    *nline =m;
    fclose(fp);
    return (all_line);
}

char **set_memory_2d( int nptr, int length)
{
    char **var=NULL;
    int i;

    if(nptr<=0 || length<=0) return (var);
    
    var = new char *[nptr];
    if(var == NULL){
        printf("Too many points (%d) were assigned\n",nptr);
        return(NULL);
    }
    for(i=0; i<nptr; i++){
        var[i] =  new char[length];
            
        if(var[i] == NULL){
            printf("Too many points (nptr=%d; length=%d) were assigned\n",nptr,i);
            return(NULL);
        }
            
    }
    
    return (var);
    
}


void free_memory_2d(char **var, int nptr)
{
    int i;
    if(nptr<=0) return;
    
    for(i=0; i<nptr; i++){
        if(var[i]) delete [] var[i];
    }
    if (var) delete [] var;
}

void file_handle(char *inpfile,char *outfile)
/* uncompress *.Z or gunzip *.gz file.
   If the extension is *.Z or *.gz, the outfile is still generated without ext.
 */    
{
    
    char *pchar;
    char command[512];
    int len=0, i=0;

    pchar = strrchr(inpfile, '.');
    if (pchar == NULL){
        strcpy(outfile, inpfile);
        return;
    }else {
        i = pchar - inpfile;
        len = strlen(inpfile) - i;
        
        if(len != 2 &&  len != 3  ) {
            strcpy(outfile, inpfile);
            return;
        }else if(len==2){
            if(inpfile[i+1] == 'Z'){
                sprintf(command,"/usr/bin/uncompress -f %s", inpfile);
                system(command);
                strncpy(outfile, inpfile, i);
                outfile[i] = '\0';
                return;
            }else{    
                strcpy(outfile, inpfile);
                return;
            }
        }else if(len==3){
//         printf("hello len=%d; %c, %c\n",len,inpfile[i+1], inpfile[i+2]);
           if(inpfile[i+1] == 'g' && inpfile[i+2]=='z'){
                sprintf(command,"/usr/bin/gunzip -f %s", inpfile);
                system(command);
                strncpy(outfile, inpfile, i);
                outfile[i] = '\0';
                return;
            }else{    
                strcpy(outfile, inpfile);
                return;
            }
            
        }
    }
}
  

/*
void open_CifFileObj_error(char *routine)
{
    printf("Can not create a new CifFileObj in (routine:%s)!\n", routine);
    printf("Did you do 'make binary' during compilation?\n");
    return;
}
*/
