/****************************************************************
***                        Woerterbuch                        ***
***                                                           ***
*** Es wird ein HASHING, bezueglich der Wortlaenge            ***
*** durchgefuehrt. Dann wird das Wort mit einem AVL-BAUM      ***
*** einsortiert bzw, gesucht. Dadurch kann mit LOG-TIME       ***
*** auf ein Element zugegriffen werden.                       ***
***                                                           ***
****************************************************************/
/*

   Zum Initialisieren muss BaseInit() aufgerufen werden ! 

   Eintrag ins Woerterbuch mit            :  ElementEinfuegen("any text");
   Suche im Woerterbuch mit               :  SucheElement    ("any text");    (Ergebnis  =0 oder =1)
   DatenStruktur im SPEICHER loeschen mit :  LoescheDatenStruktur():

*/   

#include <stdio.h>
#include <stdlib.h>
#include "baum.h"
#ifdef TEXT2
#else
#include "german.h"
#endif


#define MAXREAD 60

struct Baum
{
 short int    bal;
 struct Baum *Links;
 struct Baum *Rechts;
 unsigned char        *Daten;
};

void ElementEinfuegen(); 
struct Baum  *StartBaum[MAXREAD];

short int up,ttt;
char DatenWort[MAXREAD];
long LaengeVonDatenWort,startpos;
short int init = 0;
FILE *aktuell_fd,*aktuell_text_fd;
short int dirty[MAXREAD+1];

unsigned long Konvert(Zeichen)
unsigned char *Zeichen;
{
 long wert;  
 wert=0;
 wert=(*(Zeichen+3)) + ((*(Zeichen+2))<<8) + ((*(Zeichen+1))<<16) + ((*(Zeichen+0))<<24);
 return(wert);
}

void ToKonvert(Zeichen,wert)
unsigned char *Zeichen;
unsigned long wert;
{
 short int w,w1,w2,w3;
 w3=wert & 255;
 w2=(wert>>8) & 255;
 w1=(wert>>16) & 255;
 w=(wert>>24) & 255;
 *Zeichen=w; Zeichen++; 
 *Zeichen=w1; Zeichen++; 
 *Zeichen=w2; Zeichen++; 
 *Zeichen=w3; 
}


void kill_it(Ptr)
struct Baum *Ptr;
{
 if (Ptr!=NULL)
 {
  kill_it(Ptr->Links);
  kill_it(Ptr->Rechts);
  free(Ptr->Daten);
  free(Ptr);
 }
}

void LoescheDatenStruktur()
{
 long t;
 for (t=0;t<MAXREAD;t++) { kill_it(StartBaum[t]); StartBaum[t]=NULL; dirty[t]=0; }
 init=0;
}

struct Baum *RRotation(Ptr)
struct Baum *Ptr;
{
 struct Baum *Ptr1;

 Ptr1 = Ptr->Links;
 Ptr->Links=Ptr1->Rechts;
 Ptr1->Rechts = Ptr;
 Ptr->bal=0;
 return(Ptr1);
}

struct Baum *LRRotation(Ptr)
struct Baum *Ptr;
{
 struct Baum *Ptr1,*Ptr2;
 
 Ptr1=Ptr->Links;
 Ptr2=Ptr1->Rechts;
 Ptr1->Rechts=Ptr2->Links;
 Ptr2->Links=Ptr1;
 Ptr->Links=Ptr2->Rechts;
 Ptr2->Rechts=Ptr;
 if (Ptr2->bal==2)
 {
  Ptr->bal=1;
 } else
 {
  Ptr->bal=0;
 }  
 if (Ptr2->bal==1)
 {
  Ptr1->bal=2;
 } else
 {
  Ptr1->bal=0;
 }
 return(Ptr2);
}

struct Baum *LRotation(Ptr)
struct Baum *Ptr;
{
 struct Baum *Ptr1;
 
 Ptr1= Ptr->Rechts;
 Ptr->Rechts=Ptr1->Links;
 Ptr1->Links=Ptr;
 Ptr->bal=0;
 return(Ptr1);
}

struct Baum *RLRotation(Ptr)
struct Baum *Ptr;
{
 struct Baum *Ptr1,*Ptr2;
 Ptr1=Ptr->Rechts;
 Ptr2=Ptr1->Links;
 Ptr1->Links=Ptr2->Rechts;
 Ptr2->Rechts=Ptr1;
 Ptr->Rechts=Ptr2->Links;
 Ptr2->Links=Ptr;
 if (Ptr2->bal==1)
 {
  Ptr->bal=2;
 } else
 {
  Ptr->bal=0;
 }
 if (Ptr2->bal==2)
 {
  Ptr1->bal=1;
 }
 else
 {
  Ptr1->bal=0;
 }
 return(Ptr2);
}

void rek(Ptr)
struct Baum *Ptr;
{
 if (Ptr!=NULL)
 {
  printf("Element: %s [%d]  ",Ptr->Daten,Ptr->bal);
  if (Ptr->Links!=NULL) printf(" LKind: %s",Ptr->Links->Daten);
  if (Ptr->Rechts!=NULL) printf("  RKind: %s",Ptr->Rechts->Daten);
  printf("\n");
  rek(Ptr->Links);
  rek(Ptr->Rechts);
}
}

struct Baum *Insert(Ptr)
struct Baum *Ptr;
{
 short int erg;

 if (Ptr==NULL)
 {
  struct Baum *Ptr1;
  
  up=1;  /* TRUE */
  Ptr1=(struct Baum *)calloc(1,sizeof(struct Baum)); 
  if (Ptr1==NULL) { printf("No Memory ! \n"); exit(-1); }
  Ptr1->Links=NULL;
  Ptr1->Rechts=NULL;
  Ptr1->bal=0;
  dirty[ttt]=1;
  Ptr1->Daten=(unsigned char *)calloc(1,1+LaengeVonDatenWort);  
  strcpy(Ptr1->Daten,DatenWort);  
  /* Neuer Eintrag */ 
 return(Ptr1);
 } else
 { 
  erg=strcmp(Ptr->Daten,DatenWort);
  if (erg>0)
  {
   Ptr->Links=Insert(Ptr->Links);
   if (up)
   {
    switch(Ptr->bal)
    { 
     case 1 :   
                Ptr->bal=0;
                up=0;
                break;  

     case 0 :   Ptr->bal=2;
                break;

     case 2:   up=0;
                if (Ptr->Links->bal==2)
                {
  
                 Ptr=RRotation(Ptr);
                } else
                {
   
                 Ptr=LRRotation(Ptr);
                }
                Ptr->bal=0;
                break;   

    }  /* end switch */
   } /* end if up */
  } /* end if erg>0 */

  if (erg<0)
  {
   Ptr->Rechts=Insert(Ptr->Rechts);
   if (up)
   {
    switch(Ptr->bal)
    { 
     case 2 :   
                Ptr->bal=0;
                up=0;
                break;  

     case 0 :   Ptr->bal=1;
                break;

     case 1:    up=0;
                if (Ptr->Rechts->bal==1)
                {
               
  Ptr=LRotation(Ptr);
                } else
                {
                           Ptr=RLRotation(Ptr);
                }
                Ptr->bal=0;
                break;   
    } /* end switch */
   } /*  end if up */
  } /* end if erg<0 */
  if (erg==0)
  {
   /* Doppleter Eintrag */
  }
  return(Ptr);
 }
}

short int Suche(Ptr)
struct Baum *Ptr;
{
 short int erg;
 if (Ptr==NULL)
 {
  /* nicht gefunden ! */
  return(0);
 } else
 { 
  erg=strcmp(Ptr->Daten,DatenWort);
  if (erg>0)
  {
   return(Suche(Ptr->Links));
  }
  if (erg<0)
  {
   return(Suche(Ptr->Rechts));
  }
  if (erg==0) return(1);
  return(0); 
 }
}


short int SucheElement(Puffer)
unsigned char *Puffer;
{
 LaengeVonDatenWort=strlen(Puffer);
 strcpy(DatenWort,Puffer);
 ttt=LaengeVonDatenWort;
 return(Suche(StartBaum[LaengeVonDatenWort]));
}

void ElementEinfuegen(Puffer)
char *Puffer;
{
 LaengeVonDatenWort=strlen(Puffer);
 strcpy(DatenWort,Puffer);
 up=0;
 ttt=LaengeVonDatenWort;
 StartBaum[LaengeVonDatenWort]=Insert(StartBaum[LaengeVonDatenWort]);
 }

void BaseInit()
{
 long t;
 for (t=0;t<MAXREAD;t++) { StartBaum[t]=NULL; dirty[t]=0; }
 init=1;
}


void RohDateiVerarbeiten(DateiName)
char *DateiName;
{
 long pos,t,big,ok,ok1; 
 unsigned char Puffer[MAXREAD];
 FILE *file;
 unsigned char kk;
 ok=0;
 ok1=1;
 init=1;
 file=fopen(DateiName,"r");
 if (file==NULL) return;
 pos=0;
 fseek(file,0,2);
 big=ftell(file);
 for (;;)  
 {
  fseek(file,pos,0);
  if (0==fread(Puffer,1,MAXREAD,file)) break; 
  Puffer[MAXREAD-2]=0; 
  kk=Puffer[0];
 if (((kk>='A') && (kk<='Z')) || (kk>='a'))
 {  
  for (t=0;;t++)
  {
   pos++;   
   if ((Puffer[t]<'0') || ((Puffer[t]>'9') && (Puffer[t]<'A') ) || (  (Puffer[t]>'Z') && (Puffer[t]<'a') ))  { Puffer[t]=0; break; }
  } 
  if (t>1) 
  {
   if (0==SucheElement(Puffer)) 
   { 
    ElementEinfuegen(Puffer);
   } 
  }
 } else
 {
  pos++;
 }
 }
 fclose(file);
}

void makeBaum (text)
char *text;
{
  BaseInit();
  RohDateiVerarbeiten(text);
} 
  
