#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <dirent.h>
#include <ncurses.h>
#include <sys/utsname.h>
#include <sys/stat.h>
#include <linux/fcntl.h>
#include <vga.h>

#include "standard.h"
#include "gbm.h"
#include "gbmerr.h"

#define MAIN

#include "grav.h"

void Init();                                            /* Initialisierung */
void ReadDir();                                     /* Liest Directory ein */
void ReadConfig();                     /* Lesen der Config ($HOME/.gravrc) */
void SaveConfig();                 /* Speichern der Config ($HOME/.gravrc) */
int  GDIRVergleich (void *, void *);      /* Zum Vergleichen des Directory */

main()
{
   
   int Index;                                   /* Index fuer Fileselector */
   int Taste;                                        /* Taste fuer getch() */
   int local;

   StdScr=initscr();                             /* NCurses initialisieren */

   Farbe=has_colors();                  /* Koennen Farben verwendet werden */

   if(Farbe)
   {   
      start_color();                                  /* Farben aktivieren */
      init_pair(1, COLOR_WHITE,  COLOR_BLUE);          /* Farben festlegen */
      init_pair(2, COLOR_BLUE,   COLOR_CYAN); 
      init_pair(3, COLOR_YELLOW, COLOR_RED);
      init_pair(4, COLOR_BLACK,  COLOR_CYAN);
      init_pair(5, COLOR_WHITE,  COLOR_BLACK);
      init_pair(6, COLOR_YELLOW, COLOR_CYAN);
   }

   gbm_init();                           /* GBM-Schnittstelle initialisieren */
   vga_init();                                   /* SVGALIB initialisieren */

   Init();                                          /* GRAV initialisieren */
   InitNCurses();

   CardRC=0;                           /* Karte und Mode auf Standardwerte */
   ModeRC=0;

   ReadConfig();                                /* Lesen der Konfiguration */

   MakeScreen();                                          /* Menu aufbauen */

   vga_disabledriverreport();                       /* SVGALIB zaehmen ;-) */
   vga_runinbackground(FALSE);                      /* Nicht im Background */
   
   Quit=FALSE;
   SecondWin=FALSE;

   ShowCard();                                  /* Anzeigen der Videokarte */
   ShowMode();                                  /* Anzeigen des Videomodus */

   do
   {
      ClearWindow();
      ReadDir();                                     /* Directory einlesen */
      ShowDir(0);                                    /* Directory anzeigen */
      GetFile();                                           /* Fileselektor */
   }
   while(Quit==FALSE);

   SaveConfig();                                 /* Konfiguration sichern */

   gbm_deinit();                                  /* GBM deinitialisieren */

   ExitNCurses();                              /* Und weg mit den NCurses */
   
   GoodBye();                                      /* A word from Michael */
}
         
void Init(void)
{
   strcpy(GCARD[0].Adapter,"UNDEFINED   "); 
   strcpy(GCARD[1].Adapter,"NORMAL VGA  "); 
   strcpy(GCARD[2].Adapter,"ET4000      "); 
   strcpy(GCARD[3].Adapter,"CIRRUS      "); 
   strcpy(GCARD[4].Adapter,"TRIDENT 8900"); 
   strcpy(GCARD[5].Adapter,"OAK         "); 
   strcpy(GCARD[6].Adapter,"EGA         "); 
   strcpy(GCARD[7].Adapter,"S3          "); 


   strcpy(GMODE[0].Mode,"320x200x16   ");    GMODE[0].ModeIndex=1;
   strcpy(GMODE[1].Mode,"640x200x16   ");    GMODE[1].ModeIndex=2;
   strcpy(GMODE[2].Mode,"640x350x16   ");    GMODE[2].ModeIndex=3;   
   strcpy(GMODE[3].Mode,"640x480x16   ");    GMODE[3].ModeIndex=4;
   strcpy(GMODE[4].Mode,"320x200x256  ");    GMODE[4].ModeIndex=5;
   strcpy(GMODE[5].Mode,"320x240x256  ");    GMODE[5].ModeIndex=6;
   strcpy(GMODE[6].Mode,"320x400x256  ");    GMODE[6].ModeIndex=7;
   strcpy(GMODE[7].Mode,"360x480x256  ");    GMODE[7].ModeIndex=8;
   strcpy(GMODE[8].Mode,"640x480x256  ");    GMODE[8].ModeIndex=10;
   strcpy(GMODE[9].Mode,"800x600x256  ");    GMODE[9].ModeIndex=11;
   strcpy(GMODE[10].Mode,"1024x768x256 ");   GMODE[10].ModeIndex=12;
   strcpy(GMODE[11].Mode,"1280x1024x256");   GMODE[11].ModeIndex=13;
   

   GMODE[0].Width=320;    GMODE[0].Heigh=200;
   GMODE[1].Width=640;    GMODE[1].Heigh=200;
   GMODE[2].Width=640;    GMODE[2].Heigh=350;
   GMODE[3].Width=640;    GMODE[3].Heigh=480;
   GMODE[4].Width=320;    GMODE[4].Heigh=200;
   GMODE[5].Width=320;    GMODE[5].Heigh=240;
   GMODE[6].Width=320;    GMODE[6].Heigh=400;
   GMODE[7].Width=360;    GMODE[7].Heigh=480;
   GMODE[8].Width=640;    GMODE[8].Heigh=480;
   GMODE[9].Width=800;    GMODE[9].Heigh=600;
   GMODE[10].Width=1024;  GMODE[10].Heigh=768;
   GMODE[11].Width=1280;  GMODE[11].Heigh=1024;
}

void ReadDir()
{
   DIR    *DirFile;
   
   struct dirent *DirEintrag;
   struct stat   Buffer;
   
   char   CurrentDir[257];
   char   RootUpperDir;
   char   UpperDir;
   char   CurrDir;
   char   DirOrFile;
   char   Okay;
   int    local;
   int    Temp;

   local=0;
                       
   getcwd(CurrentDir,256);              /* Aktuelles Verzeichnis ermitteln */   
      
   DirFile=opendir(".");                              /* Directory oeffnen */
         
   while((DirEintrag=readdir(DirFile))!=NULL)   /* Bis keine Files mehr da */
   {
      Okay=FALSE; RootUpperDir=FALSE; CurrDir=FALSE; UpperDir=FALSE;
      
      if (strcmp(CurrentDir,"/")==0)               /* Wenn akt. Dir = ROOT */
        if (strcmp(DirEintrag->d_name,"..")==0)        /* und Eintrag = .. */
           RootUpperDir=TRUE;
                 
      if (strcmp(DirEintrag->d_name,".")==0)         /* Eintrag = CurrDir? */
         CurrDir=TRUE;           
         
      if (strcmp(DirEintrag->d_name,"..")==0)      /* Eintrag = UpperDir ? */
         UpperDir=TRUE;                      
      
      if ((stat(DirEintrag->d_name,&Buffer))==-1)
         Buffer.st_mode=0;
         
      if ((Buffer.st_mode & 0x7000)==0x4000) 
         DirOrFile=DIRECTORY;                 /* Eintrag ist ein Directory */ 
       else 
         DirOrFile=FILE;                         /* Eintrag ist eine Datei */
 
        Okay=TRUE;
           
      if (DirOrFile==FILE && gbm_guess_filetype(DirEintrag->d_name, &Temp)!=GBM_ERR_OK) 
         Okay=FALSE;                               /* KEINE GRAFIKDATEI!!! */
      
      if (Okay && !CurrDir && !RootUpperDir )               /* Alles klar? */
      {
         GRAVDIR[local].DirOrFile=DirOrFile; /* In globale Struct kopieren */
         GRAVDIR[local].Tagged=FALSE;
         strcpy(GRAVDIR[local].DirEintrag,DirEintrag->d_name);   
         local++;
      }    
      
   }
   
   GRAVDIREintraege=local;                     
   closedir(DirFile);                              /* Directory schliessen */

   qsort (&(GRAVDIR[1]),         /* Und jetzt noch das Directory sortieren */
          GRAVDIREintraege-1,
          sizeof(struct GDIR),
          (void *)GDIRVergleich);
}

int GDIRVergleich(void *GDIRZeiger1, void *GDIRZeiger2)
{
   struct GDIR *Eintrag1,*Eintrag2;
   
   char Buffer1[80],Buffer2[80];                      /* Puffer allocieren */
   
   Eintrag1=(struct GDIR *)GDIRZeiger1;                  /* Erster Eintrag */ 
   Eintrag2=(struct GDIR *)GDIRZeiger2;                 /* Zweiter Eintrag */
   
   if (Eintrag1->DirOrFile==DIRECTORY)         /* Wenn Eintrag = DIRECTORY */
   {
      strcpy(Buffer1,"<");        /* Dann in Zeichen < und > einschliessen */
      strcat(Buffer1,Eintrag1->DirEintrag);
      strcat(Buffer1,">");
   }
   else
   {  strcpy(Buffer1,Eintrag1->DirEintrag); }   

   if (Eintrag2->DirOrFile==DIRECTORY)
   {
      strcpy(Buffer2,"<");
      strcat(Buffer2,Eintrag2->DirEintrag);
      strcat(Buffer2,">");
   }
   else
   {  strcpy(Buffer2,Eintrag2->DirEintrag); }
   
   return(strcmp(Buffer1,Buffer2));         /* Beide Eintraege vergleichen */
}

void ReadConfig()
{
   int gravrc;
   int local;
   char InFile[80];
   char *HomeDir;
   
   unsigned char *Byte;
   
   HomeDir=getenv("HOME");
   sprintf(InFile,"%s/.gravrc",HomeDir);

   gravrc=open(InFile,O_RDONLY);
   
   if(gravrc!=-1)
   {
      read (gravrc,Byte,1);    CardRC=atoi(Byte);
      read (gravrc,Byte,1);    ModeRC=atoi(Byte);
      close(gravrc);   
   }   
   else
   {
      clear();                                       /* Bildschirm loeschen */
      attron(A_BOLD);
            
      DrawBox(10,68,7,6,3);                                      /* Fenster */

      attron(COLOR_PAIR(3));
      
      mvaddstr(7,8,"Welcome to GRAV 1.0.");
      mvaddstr(9,8,"This is the first time you run GRAV. Be sure that you set  the");
      mvaddstr(10,8,"correct Graphic-Card from the Main-Menu. If you  don't,  there");
      mvaddstr(11,8,"may be some trouble with your Text-Mode when getting back from");
      mvaddstr(12,8,"the VGA-Mode. So be careful!");
      mvaddstr(14,33,"Press any key");

      attroff(A_BOLD);
      attroff(COLOR_PAIR(3));
      
      refresh();
      getch();
   }
}

void SaveConfig()
{
   int gravrc;
   char OutFile[80];
   char *HomeDir;
   char Ausgabe [3];
   
   HomeDir=getenv("HOME");
   sprintf(OutFile,"%s/.gravrc",HomeDir);

   gravrc=open(OutFile,O_CREAT | O_WRONLY);
   
   if(gravrc!=-1)
   {
      sprintf(Ausgabe,"%d%d",CardRC,ModeRC);
      write(gravrc,Ausgabe,3);
      close(gravrc);   
   }   
}