// callbase.c

#include "dbase.h"
#include "secmem.h"

#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <dos.h>


#define CB_FILENAME "CALLBASE.DBF"

#define HEADER_SIZE sizeof(struct header)
#define QSO_SIZE sizeof(struct qso)


typedef struct header
{
  unsigned char magic[5];
  unsigned char owncall[14];
  unsigned char ownloc[7];
  unsigned char desc[60];
  unsigned qso_cnt;
  unsigned invalid;
  unsigned ODX;
  unsigned char ODX_call[14];
  unsigned average;
  unsigned char countries;
  unsigned char unknown_pref;
  unsigned char squares;
  unsigned long points;
};


typedef struct qso
{
  struct qso *next, *prev;

  unsigned hour, min;
  unsigned nr;
  unsigned char barecall[13];
  unsigned char call[14];
  unsigned char locator[7];
  unsigned char rst_RX[8];
  unsigned char rst_TX[4];
  unsigned points;
  unsigned direction;
};


typedef struct callinfo
{
   unsigned char call[13];
   unsigned qrv_on;
   unsigned char loc1[7];
   unsigned long loc1_date;
   unsigned char loc2[7];
   unsigned long loc2_date;
   unsigned char loc3[7];
   unsigned long loc3_date;
   
   struct callinfo *prev;
   struct callinfo *next;
};


struct callinfo *root;

void free_call_list()
{
   struct callinfo *node;
   
   while(root)
   {
      node = root;
      root = root->next;
      sec_free(node);
   };
   
   root = NULL;
};


void read_cnt_file(FILE *f,unsigned long date,unsigned band)
{
   struct qso q;
   struct callinfo *new_node;
   struct callinfo *insert_node;
   char *cp;
   unsigned i;
   char ch;
   

   root = NULL;
   fseek(f,HEADER_SIZE,SEEK_SET);
   
   while(!feof(f))
   {
      memset((void *)&q,0,QSO_SIZE);
      fread((void *)&q.hour,1,2,f);
      fread((void *)&q.min,1,2,f);
      fread((void *)&q.nr,1,2,f);
      fread((void *)q.barecall,1,13,f);
      fread((void *)q.call,1,14,f);
      fread((void *)q.locator,1,7,f);
      fread((void *)q.rst_RX,1,8,f);
      fread((void *)q.rst_TX,1,4,f);
      fread((void *)&q.points,1,2,f);
      fread((void *)&q.direction,1,2,f);
   
      if(q.points)
      {
         new_node = sec_alloc(sizeof(struct callinfo));   
         memset(new_node,0,sizeof(struct callinfo));
            
         cp = q.call+strlen(q.call)-4;
         while(*cp && (*cp!='/')) cp++;
         *cp = 0;
         strcpy(new_node->call,q.call);

         new_node->qrv_on = band;
         strcpy(new_node->loc1,q.locator);
         new_node->loc1_date = date;

         insert_node = root;
         while(insert_node)
         {
            if(strcmp(insert_node->call,new_node->call)<0) insert_node = insert_node->next;
            else
            {
               insert_node = insert_node->prev;
               if(!insert_node)
               {
                  new_node->next = root;
                  root->prev = new_node;
                  root = new_node;
               }
               else
               {
                  insert_node->next->prev = new_node;
                  new_node->next = insert_node->next;
                  insert_node->next = new_node;
               };
               new_node->prev = insert_node;
               insert_node = NULL;
               new_node = NULL;
            };
         };
         
         if(new_node)
         {
            if(!root)
            {
               root = new_node;
               new_node->prev = NULL;
            }
            else
            {
               insert_node = root;
               while(insert_node->next) insert_node = insert_node->next;
               insert_node->next = new_node;
               new_node->prev = insert_node;
            };   
            new_node->next = NULL;
            
         };
      };
   };
   
   insert_node = root;
   i = 0;
   while(insert_node)
   {
      printf("%s - %s\n",insert_node->call,insert_node->loc1);
      i++;
      if(!(i%25)) ch = getch();
      insert_node = insert_node->next;
   };
   
   return;
};
               
      
void dbf_read(struct callinfo *ci,FILE *f)
{
   char s[10];
   char i;

   fread(&i,1,1,f);
   
   fread(&ci->call,1,12,f);
   ci->call[12] = 0;
   
   fread(s,1,5,f);
   s[5] = 0;
   ci->qrv_on = atoi(s);
   
   fread(&ci->loc1,1,6,f);                    
   ci->loc1[6] = 0;
   
   fread(s,1,8,f);
   s[8] = 0;
   ci->loc1_date = atol(s);

   fread(&ci->loc2,1,6,f);                    
   ci->loc2[6] = 0;
   
   fread(s,1,8,f);
   s[8] = 0;
   ci->loc2_date = atol(s);
   
   fread(&ci->loc3,1,6,f);                    
   ci->loc3[6] = 0;
   
   fread(s,1,8,f);
   s[8] = 0;
   ci->loc3_date = atol(s);
};

void dbf_write(struct callinfo *ci, FILE *f)
{
   char s[10];
   char i;

   i = 32;
   fwrite(&i,1,1,f);  
 
   fwrite(ci->call,1,12,f);
   sprintf(s,"%05d",ci->qrv_on);
   fwrite(s,1,5,f);
   
   fwrite(ci->loc1,1,6,f);
   sprintf(s,"%08ld",ci->loc1_date);
   fwrite(s,1,8,f);
   
   fwrite(ci->loc2,1,6,f);
   sprintf(s,"%08ld",ci->loc2_date);
   fwrite(s,1,8,f);

   fwrite(ci->loc3,1,6,f);
   sprintf(s,"%08ld",ci->loc3_date);
   fwrite(s,1,8,f);
};


void mix_write()
{
   struct callinfo *ci_list;
   struct callinfo ci_file;
   char file_end = 0;
   
   FILE *f, *newf;
   struct db_header h;
   struct db_rec_def rec;

   unsigned long written = 0;
   char compare, i,j;
   
   char loc[6][8];
   unsigned long date[6];
   
   unsigned max_index;
   unsigned long max_date;
   
   
   f = fopen(CB_FILENAME,"rb");
   if(!f) file_end = 1;
   
   newf = fopen("CALLBASE.$$$","wb");
   
   fread(&h,1,sizeof(h),f);
   fwrite(&h,1,sizeof(h),newf);
   
   for(i=1;i<9;i++)
   {
      fread(&rec,1,sizeof(rec),f);
      fwrite(&rec,1,sizeof(rec),newf);
   }
   
   fread(&i,1,1,f);
   fwrite(&i,1,1,newf);
   
   dbf_read(&ci_file,f);
   file_end = feof(f);

   ci_list = root;
   
   while(ci_list && (!file_end))
   {
      if(!ci_list)
      {
         while(!feof(f))
         {
            dbf_write(&ci_file,newf);
            written++;
            dbf_read(&ci_file,f);
         };
         dbf_write(&ci_file,newf);
         written++;
         file_end = 1;
      };
       
      if(file_end && ci_list)
      {
         while(ci_list)
         {
            dbf_write(ci_list,newf);
            written++;
            ci_list = ci_list->next;
         };
      };
       
      if(ci_list && (!file_end))
      {
         compare = strcmp(ci_list->call,ci_file.call);
         
         if(compare>0)
         {
            dbf_write(&ci_file,newf);
            written++;
            dbf_read(&ci_file,f);
            file_end = feof(f);
         };
          
         if(compare<0)
         {
            dbf_write(ci_list,newf);
            written++;
            ci_list = ci_list->next;
         }
          
         if(!compare)
         {
            ci_file.qrv_on = ci_file.qrv_on | ci_list->qrv_on;
            
            strcpy(loc[0],ci_file.loc1);  date[0] = ci_file.loc1_date;
            strcpy(loc[1],ci_file.loc2);  date[1] = ci_file.loc2_date;
            strcpy(loc[2],ci_file.loc3);  date[2] = ci_file.loc3_date;
            strcpy(loc[3],ci_list->loc1); date[3] = ci_list->loc1_date;
            strcpy(loc[4],ci_list->loc2); date[4] = ci_list->loc2_date;
            strcpy(loc[5],ci_list->loc3); date[5] = ci_list->loc3_date;
   
            for(i=0;i<6;i++)
            {
               if(loc[i][0])
               {
                  for(j=i+1;j<6;j++)
                  {
                     if(!strcmp(loc[i],loc[j]))  // Gleiche Locator!
                     {
                        loc[j][0] = 0;
                        if(date[j]>date[i]) date[i]=date[j];
                        date[j] = 0L;
                     };
                  };
               };
            };
            
            
            memset(&ci_file.loc1,0,6);
            memset(&ci_file.loc1_date,0,sizeof(unsigned long));
            max_date = 0;
            max_index = 100;
            for(i=0;i<6;i++)
            {
               if(date[i]>max_date)
               {
                  max_date = date[i];
                  max_index = i;
               };
            };
            if(max_index<6)
            {
               strcpy(ci_file.loc1,loc[max_index]);
               loc[max_index][0] = 0;
               ci_file.loc1_date = date[max_index];
               date[max_index] = 0;
            };

            
            memset(&ci_file.loc2,0,6);
            memset(&ci_file.loc2_date,0,sizeof(unsigned long));
            max_date = 0;
            max_index = 100;
            for(i=0;i<6;i++)
            {
               if(date[i]>max_date)
               {
                  max_date = date[i];
                  max_index = i;
               };
            };
            if(max_index<6)
            {
               strcpy(ci_file.loc2,loc[max_index]);
               loc[max_index][0] = 0;
               ci_file.loc2_date = date[max_index];
               date[max_index] = 0;
            };
         
         
            memset(&ci_file.loc3,0,6);
            memset(&ci_file.loc3_date,0,sizeof(unsigned long));
            max_date = 0;
            max_index = 100;
            for(i=0;i<6;i++)
            {
               if(date[i]>max_date)
               {
                  max_date = date[i];
                  max_index = i;
               };
            };
            if(max_index<6)
            {
               strcpy(ci_file.loc3,loc[max_index]);
               loc[max_index][0] = 0;
               ci_file.loc3_date = date[max_index];
               date[max_index] = 0;
            };
            
            dbf_write(&ci_file,newf);
            written++;
            ci_list = ci_list->next;
            dbf_read(&ci_file,f);
         };
      };
   };            

   if(!ci_list && (!file_end))
   {
      while(!feof(f))
      {
         dbf_write(&ci_file,newf);
         written++;
         dbf_read(&ci_file,f);
      };
      file_end = 1;
   };
       
   if(file_end && ci_list)
   {
      while(ci_list)
      {
         dbf_write(ci_list,newf);
         written++;
         ci_list = ci_list->next;
      };
   };

   fclose(f);

   fseek(newf,4,SEEK_SET);
   fwrite(&written,1,4,newf);
   fclose(newf);

   unlink("CALLBASE.BAK");
   rename(CB_FILENAME,"CALLBASE.BAK");
   rename("CALLBASE.$$$",CB_FILENAME);
};



FILE *write_dbf_file(char *name)
{
   struct db_header h;
   struct db_rec_def rec;
   FILE *f;
   unsigned char i;

   struct date d;
   
      
   f = fopen(name,"wb");
  
   memset(&h,0,sizeof(h)); 
   h.version = 0x03;

   getdate(&d);
   
   h.last_access[0] = (char)(d.da_year%100);
   h.last_access[1] = d.da_mon;
   h.last_access[2] = d.da_day;
   h.rec_count = 0l;
   h.header_len = 289;
   h.rec_len = 60;
   
   fwrite(&h,1,sizeof(h),f);
   
   memset(&rec,0,sizeof(rec));
   strcpy(rec.name,"CALLSIGN");
   rec.type = 'C';
   rec.address = 0l;
   rec.len = 12;
   rec.decimals = 0;
   fwrite(&rec,1,sizeof(rec),f);
   
   memset(&rec,0,sizeof(rec));
   strcpy(rec.name,"QRV_ON");
   rec.type = 'N';
   rec.address = 0l;
   rec.len = 5;
   rec.decimals = 0;
   fwrite(&rec,1,sizeof(rec),f);

   for(i=1;i<4;i++)
   {   
      memset(&rec,0,sizeof(rec));
      sprintf(&rec.name,"LOCATOR%d",i);
      rec.type = 'C';
      rec.address = 0l;
      rec.len = 6;
      rec.decimals = 0;
      fwrite(&rec,1,sizeof(rec),f);
   
      memset(&rec,0,sizeof(rec));
      sprintf(&rec.name,"LOC_DATE%d",i);
      rec.type = 'D';
      rec.address = 0l;
      rec.len = 8;
      rec.decimals = 0;
      fwrite(&rec,1,sizeof(rec),f);
   };

   i = 0x0D;
   fwrite(&i,1,1,f);
   
   fclose(f);
   
   f = fopen(name,"rb+");
   return(f);
};   


void find_call(FILE *f, char *arg)
{
};


   
void main(int argc, char **argv)
{
   FILE *f;
   FILE *addf;
   char argument[128];
   char fname[128];
   char date_str[32];
   unsigned long date;
   char band_str[32];
   int band;
   char *cp;
   
   
   printf("Callbase v1.00, (C) 1997 by Stefan Pfeiffer, DL1ELY\n");
   f = fopen(CB_FILENAME,"rb");
   if(!f)
   {
      f = write_dbf_file(CB_FILENAME);
      printf("\nFile %s written!\n",CB_FILENAME);
   };

   if(argc<2)
   {
      printf("\nSyntax:\n");
      printf("CALLBASE <call>\n");
   }
   else
   {
      strcpy(argument,argv[1]);
      if((argument[0] == '-')||(argument[0] == '/'))
      {
         switch(argument[1])
         {
            case 'a':
            case 'A':
               strcpy(fname,argv[2]);
               if(!fname[0])
               {
                  printf("No file given!\n");
                  fclose(f);
                  return;
               };
               
               addf = fopen(fname,"rb");
   	         if(!addf)
   	         {
   	            printf("File %s not found!\n",fname);
   	            fclose(f);
   	            return;
   	         };

	            strcpy(date_str,argv[3]);
	            date = atol(date_str);
               if(!date)
               {
                  printf("Date of contest is missing!\n");
            	   printf("Usage: CALLBASE -a <filename> <date> <band>\n\n");
                  printf("  filename = for example C:\LOGS\MAY97\DL0ABC01.CNT\n");
		            printf("  date = YYMMDD, for example 970501\n");
		            printf("  band = {144MHz,2m,432MHz,70cm,1296MHz,23cm,2300MHz,13cm,3400MHz,9cm,5700MHz,\n         6cm,10GHz,3cm,24GHz,47GHz\n");
		            printf("Example: CALLBASE -a C:\LOGS\MAY97\DL1ELY01.CNT 970501 2m\n");
	               fclose(f);
                  fclose(addf);
                  return;
   	         };

	            strcpy(band_str,argv[4]);
	            cp = band_str+strlen(band_str);
	            while((cp > band) && (!isdigit(*cp))) cp--;
	            cp++;
	            *cp = 0;
	            
               band = 0;
               band = atoi(band_str);
               switch(band)
               {
                  case 2:
                  case 144:
                     band = 1;
                     break;
                  case 70:
		            case 432:
                     band = 2;
                     break;
                  case 23:
                  case 1296:
                     band = 4;
                     break;
                  case 13:
                  case 2300:
                     band = 8;
                     break;
                  case 9:
                  case 3400:
                     band = 16;
                     break;
                  case 6:
                  case 5700:
                     band = 32;
                     break;
                  case 3:
                  case 10:
                     band = 64;
                     break;
                  case 24:
                     band = 128;
                     break;
                  case 47:
                     band = 256;
                     break;
               };

               if(!band)
               {
                  printf("Band is missing!\n");
		            printf("Usage: CALLBASE -a <filename> <date> <band>\n\n");
                  printf("  filename = for example C:\LOGS\MAY97\DL0ABC01.CNT\n");
		            printf("  date = YYMMDD, for example 970501\n");
		            printf("  band = {144MHz,2m,432MHz,70cm,1296MHz,23cm,2300MHz,13cm,3400MHz,9cm,5700MHz,\n         6cm,10GHz,3cm,24GHz,47GHz\n");
		            printf("Example: CALLBASE -a C:\LOGS\MAY97\DL1ELY01.CNT 970501 2m\n");
	               fclose(f);
                  fclose(addf);
                  return;
               };
 
     	         read_cnt_file(addf,date,band);
   	         fclose(addf);
   	         fclose(f);
   	       
   	         mix_write();
   	       
   	         free_call_list();
   	         break;
   	      default:
   	         printf("Unknown argument!\n");
   	         fclose(f);
   	         return;
   	   };
      }
      else find_call(f,argument);
   };
      
   fclose(f);
};

   
      
      
