#include <stdio.h>
#include <strings.h>
#include <dirent.h>
#include <ncurses.h>
#include <sys/utsname.h>
#include <sys/stat.h>

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

#define SUBPROG

#include "grav.h"
#include "screen.h"

void DrawBox (Lines, Cols, StartY, StartX, Color)
{
   int local;
   int DL;

   Lines--;                              /* Jeden Parameter dekrementieren */
   Cols--;
   StartX--;
   StartY--;

   attron(COLOR_PAIR(Color));
         
   move(StartY,StartX);                                 /* Ecke oben links */
   addch(ACS_ULCORNER);
   
   for (local=1;local<Cols;local++)             /* Obere waagerechte Linie */
   {
      move(StartY,StartX+local);
      addch(ACS_HLINE);
   }

   addch(ACS_URCORNER);                                /* Ecke oben rechts */
   
   for(DL=1;DL<Lines;DL++)                   /* Schleife ueber alle Zeilen */
   {
      move(StartY+DL,StartX);                /* Strich an linken der Seite */
      addch(ACS_VLINE);
   
      for (local=1;local<Cols;local++)
      {
         move(StartY+DL,StartX+local);             /* Innenraum mit Blanks */
         addch(' ');
      }
   
      addch(ACS_VLINE);                     /* Strich an der rechten Seite */
   }
   
   move(StartY+Lines,StartX);
   addch(ACS_LLCORNER);                               /* Untere linke Ecke */
   
   for (local=1;local<Cols;local++)
   {
      move(StartY+Lines,StartX+local);
      addch(ACS_HLINE);                        /* Untere waagerechte Linie */
   }

   addch(ACS_LRCORNER);                               /* Ecke unten rechts */

   attroff(COLOR_PAIR(Color));   
}


void MakeScreen(void)
{
   struct utsname uts;          
   char System[20];                             /* Name und Release des OS */
   int local;
   
   uname(&uts);                            /* System und Release ermitteln */

   sprintf(System," %s %s \0",uts.sysname,uts.release);
   
   attron(COLOR_PAIR(1));                                /* Weiss auf blau */
   clear();                                     /* Und Bildschirm loeschen */
   
   DrawBox(3,80,1,1,2);                                  /* Oberes Fenster */
   DrawBox(22,80,4,1,1);                                 /* Blaues Fenster */
   DrawBox(16,47,8,5,4);                                   /* Dateifenster */
   
   attron(COLOR_PAIR(4));
   mvaddstr (0,(80-strlen(System))/2,System);    /* OS und Relese ausgeben */
   mvaddstr(1,2,"GRAphic View 1.0");          /* Und Text im Kopf ausgeben */
   mvaddstr(1,55,"by Michael Knigge, 1994");
   attroff(COLOR_PAIR(4));
   attron (COLOR_PAIR(1));
   mvaddstr(5,5,"Directory of");

   mvaddstr(7,53,"Graphic Card:");
   mvaddstr(10,53,"Graphic Mode:");
   mvaddstr(14,53,"Press F1 or H for Help");
}

void ShowDir(int Start)
{
   int local;
   int Taste;
   int Position=LINKS;
   int Zeile;

   char Temp[21];                               /* Fuer Ausgabe im Fenster */
   char CurrentDir[61];                        /* Fuer aktuelles Directory */
   
   MaxRechts=0;                     /* Anzahl der Eintrage auf Null setzen */
   MaxLinks=0;
   DirEntry=Start;                                     /* Position sichern */

   DrawBox(16,47,8,5,4);                                   /* Dateifenster */

   attron(COLOR_PAIR(4));
   
   for(local=8;local<22;local++)        /* Senkrechten Strich in der Mitte */
   {
      move(local,27);
      addch(ACS_VLINE);
   } 

   Zeile=1;
   
   for(local=Start;local<GRAVDIREintraege;local++)     /* Jeden Eintrag listen */
   {
       move(Zeile+7,Position);
       
       if(GRAVDIR[local].DirOrFile==DIRECTORY)   /* Ist es ein Directory ? */
       {
          strcpy(Temp,"<");                   /* Dann in < und > einfuegen */
          strncat(Temp,GRAVDIR[local].DirEintrag,18);    /* Max 18 Stellen */
          strcat(Temp,">");
       }
       else
       {  strncpy(Temp,GRAVDIR[local].DirEintrag,20); }    /* Sonst max 20 */

       addstr(Temp);                          /* File / Directory ausgeben */
       
       if(Position==RECHTS)                 /* Wenn letzer Eintrag rechts, */
       {                                       /* dann nach links wechseln */
          Position=LINKS;
          MaxRechts++;
          Zeile++;
       }
       else                              /* ansonsten nach rechts wechseln */
       {  
          Position=RECHTS; 
          MaxLinks++;
       }
          
       if (Zeile==15) local=999;           /* Hier ist das Fenster zuende! */
   }

   getcwd(CurrentDir,60);                       /* Aktuelles Dir ermitteln */
   
   strncat(CurrentDir,BLANK60,60-strlen(CurrentDir));        /* Auffuellen */
   
   move(5,18);
   attron(COLOR_PAIR(1));
   addstr(CurrentDir);                          /* Akt. Directory ausgeben */
   refresh();
}

void GetFile()
{
   int local;
   int PosX=LINKS;
   int PosY=1;
   int Index=0;
   int Taste;
   int STOP;
   int RetCode;
   int CurrentColor;
   
   char Temp[21];
   
   STOP=FALSE;
   
   do
   {
      strcpy(Temp," ");
   
      if (GRAVDIR[Index].DirOrFile==DIRECTORY)/* Wenn Eintrag = DIRECTORY */
      {
         strcat(Temp,"<");       /* Dann in Zeichen < und > einschliessen */
         strncat(Temp,GRAVDIR[Index].DirEintrag,18);
         strcat(Temp,">");
      }
      else
      {  strncat(Temp,GRAVDIR[Index].DirEintrag,20); }

      if(strlen(Temp)<20)
        strncat(Temp,BLANK60,21-strlen(Temp));   /* Auffuellen mit Blanks */
                               
      strcat(Temp," ");                         
                                 
      attron(COLOR_PAIR(5));
      move(PosY+7,PosX-1);
      addstr(Temp);                                    /* Balken ausgeben */
      refresh();                                        /* Screen-Refresh */
      
      Taste=getch();                                       /* Taste holen */
      
      if(SecondWin==TRUE)
         ClearWindow();

      attron(COLOR_PAIR(4));
      move(PosY+7,PosX-1);
      addstr(Temp);                                    /* Balken loeschen */
      
      switch (Taste)                    /* Welche Taste wurde gedrueckt ? */
      {
      case 67:        CardRC++;                            /* Taste = 'C' */
                      ShowCard();
                      break;
                      
      case 99:        CardRC++;                            /* Taste = 'c' */
                      ShowCard();
                      break;
                      
      case 45:        ModeRC--;                            /* Taste = '-' */
                      ShowMode();
                      break;                
                      
      case 43:        ModeRC++;                            /* Taste = '+' */
                      ShowMode();
                      break;
                      
      case 77:        ModeRC++;                            /* Taste = 'M' */
                      ShowMode();
                      break;
                      
      case 109:       ModeRC++;                            /* Taste = 'm' */
                      ShowMode();
                      break;
                      
      case 72:        ShowHelp();                          /* Taste = 'H' */
                      break;
                      
      case 104:       ShowHelp();                          /* Taste = 'h' */
                      break;
                      
      case 81:        Quit=TRUE; STOP=TRUE; break;         /* Taste = 'Q' */
      
      case 113:       Quit=TRUE; STOP=TRUE; break;         /* Taste = 'q' */
      
      case 73:        RetCode=ProcessFile(Index);          /* Taste = 'I' */
                      close(GBM_File);
                      if (RetCode==NO_ERROR)
                      {
                         ShowInfo(Index);                /* Info anzeigen */
                         ShowDir(DirEntry);     /* Und Directory anzeigen */
                      }
                      else
                         ShowErrorWindow(RetCode);       /* Oh, Mist! ;-) */
                      break;
                      
      case 105:       RetCode=ProcessFile(Index);          /* Taste = 'i' */
                      close (GBM_File);
                      if (RetCode==NO_ERROR)
                      {  
                         ShowInfo(Index);                /* Info anzeigen */
                         ShowDir(DirEntry);     /* Und Directory anzeigen */
                      }
                      else
                         ShowErrorWindow(RetCode);               /* SHIT! */
                      break;
      
      case KEY_F(1):  ShowHelp();
                      break;
      
      case KEY_DOWN:  Index=Index+2;
                      PosY++;
                      
                      if( (PosX==RECHTS && PosY>MaxRechts) ||
                           (PosX==LINKS && PosY>MaxLinks) )
              
                         if (Index<GRAVDIREintraege)
                         {
                            if (PosX==RECHTS)
                               ShowDir(Index-1);
                            else
                               ShowDir(Index);
                            PosY=1;
                         }
                         else                         
                         { 
                            Index=Index-2; 
                            PosY--; 
                         }
                      
                      break;
                      
     case KEY_UP:     Index=Index-2; PosY--;

                      if (PosY<1)
                      {
                         if (Index>1)
                         {
                            if (PosX==RECHTS)
                               ShowDir(Index-27);
                            else
                               ShowDir(Index-26);
                            PosY=14;
                         }
                         else                         
                         { 
                            Index=Index+2; 
                            PosY++; 
                         }                      
                      }
                      break;
                      
     case KEY_RIGHT:  if(PosX==LINKS)
                      {
                         if (MaxRechts!=0)
                         {
                            Index++;
                            PosX=RECHTS;
                            if(PosY>MaxRechts)
                            {
                                PosY=MaxRechts;
                                Index=GRAVDIREintraege-2;
                            }    
                         }
                      }
                      break;
                      
     case KEY_LEFT:   if(PosX==RECHTS) 
                      { 
                         Index--;
                         PosX=LINKS;
                      }
                      break;
      
     case KEY_F(10):  Quit=TRUE; STOP=TRUE; break;      /* Nu aber Schluss */
      
     case KEY_ENTER:  if (GRAVDIR[Index].DirOrFile==DIRECTORY)
                      {
                         move(8,50);
                         chdir(GRAVDIR[Index].DirEintrag); /* Dir wechseln */
                         STOP=TRUE;  
                      } 
                      else 
                      { 
                         RetCode=CheckMode();
                         if(RetCode==NO_ERROR)
                         {
                            RetCode=ProcessFile(Index);
                            if(RetCode==NO_ERROR)
                            {
                               RetCode=ViewFile(Index);
                               StdScr=initscr();
                               InitNCurses();
                               MakeScreen();
                               ShowDir(DirEntry);
                               ShowMode();
                               ShowCard();
                               if (RetCode!=NO_ERROR)
                                  ShowErrorWindow(RetCode);
                            }
                            else
                            {   ShowErrorWindow(RetCode);   }
                         }
                         else
                         {   ShowErrorWindow(RetCode);   }
                      } 
                      break;  
     }
   }
   while(!STOP); } 

void ShowCard()
{
   if (CardRC>MAX_CARDS)
      CardRC=0;
   
   attron(COLOR_PAIR(1));
   mvaddstr(8,53,GCARD[CardRC].Adapter);
}

void ShowMode()
{
   if (ModeRC < 0)
      ModeRC=MAX_MODES;

   if (ModeRC>MAX_MODES)
      ModeRC=0;
   
   attron(COLOR_PAIR(1));
   mvaddstr(11,53,GMODE[ModeRC].Mode);
}

void InitNCurses(void)
{
   curs_set(CURSOR_INVISIBLE);                       /* Cursor ausschalten */
   keypad(stdscr,TRUE);                /* KEY-defines aus ncurses.h nutzen */
   noecho();                                            /* Kein Local-Echo */
   raw();                                           /* Raw-Mode aktivieren */
   nl();                                         /* Eingaben gemaess icrnl */
   cbreak();                                      /* Zeichen nicht puffern */
   clear();                                         /* Bildschirm loeschen */
}

void ExitNCurses(void)
{
   curs_set(CURSOR_NORMAL);                       /* Cursor wieder normal */
   attron(A_NORMAL);
   attron(COLOR_PAIR(5));                           /* Farben setzen (BW) */
   clear();                                        /* Bildschirm loeschen */
   refresh();                                           /* Screen-Refresh */
   endwin();                                           /* NCurses beenden */
   VT100_CLS();
}                      

void GoodBye(void)
{
   printf("GRAphic View 1.0\t\t\t   (C) Copyright by Michael Knigge, 1994\n");
   printf("----------------------------------------");
   printf("----------------------------------------\n\n");
   printf("If you like (and more important if you use) this program, please send me a mail.\n");
   printf("My eMail-Address is knick@harlie.han.de. Please write what you think about GRAV\n");
   printf("and what features would be nice in further releases. And excuse my poor english.\n\n");
   printf("Happy linuxing\n   Michael\n\n"); 

#ifdef BETA
   printf("\n\t      THIS IS A BETA-RELEASE - PLEASE DO NOT DISTRIBUTE!\n\n");
#endif
}
void ClearWindow()
{
   int local;
   
   attron(COLOR_PAIR(1));
   
   for(local=13;local<24;local++)
      mvaddstr(local,53,"                        ");
         
  mvaddstr(14,53,"Press F1 or H for Help");
  
  SecondWin=FALSE;
}

void ShowHelp()
{
  attron(A_BOLD);
  DrawBox(10,24,14,54,3);
  attron(COLOR_PAIR(3));
  
  mvaddstr(14,55,"The following keys");
  mvaddstr(15,55,"are active:");
  mvaddstr(17,55,"'C'   Change Adapter");
  mvaddstr(18,55,"'M'   Change Mode   ");
  mvaddstr(19,55,"'I'   File Info     ");
  mvaddstr(21,55,"   Press any key    ");

  refresh();
  getch();
  
  mvaddstr(17,55,"'+'   Inc Resolution");
  mvaddstr(18,55,"'-'   Dec Resolution");
  mvaddstr(19,55,"'Q'   Quit          ");
  mvaddstr(20,55,"'F10' Quit too      ");
  mvaddstr(21,55,"                    ");
  
  
  attroff(A_BOLD);
  attroff(COLOR_PAIR(3));
  
  SecondWin=TRUE;
}

void ShowErrorWindow(int ErrCode)
{
   
   attron(A_BOLD);
   DrawBox(5,24,18,54,3);
   attron(COLOR_PAIR(3));
   
   switch(ErrCode)
   {
   case ERROR_TYP:     mvaddstr(18,58,"This Filetype");
                       mvaddstr(20,57,"isn't supported");
                       break;
   
   case ERROR_OPEN:    mvaddstr(19,57,"Can't open File");
                       break;                   
   
   case ERROR_HEADER:  mvaddstr(19,56,"Can't read Header");
                       break;                   
   
   case ERROR_PALETTE: mvaddstr(19,56,"Can't read Palette");
                       break;
   
   case ERROR_ALLOC:   mvaddstr(19,58,"Out of Memory");
                       break;

   case ERROR_SUPPORT: mvaddstr(19,56,"Mode not supported");
                       break;
   }
   
   attroff(COLOR_PAIR(3));
   attroff(A_BOLD);
   SecondWin=TRUE;   
}

int ShowInfo(int Index)
{
  
  char Zeile[40];
  long colors;
  
  DrawBox(16,47,8,5,4);                                /* Dateifenster neu */
  
  attron(COLOR_PAIR(4));                                  /* Farben setzen */


  if (GBM_Typ==3)                                           /* TIFF-Format */
  {   strncpy(Zeile,gbmft.long_name,24);      /* Nur die ersten 24 Zeichen */
      Zeile[24]=0;                                      /* Nullterminieren */
  }
  else
    strcpy(Zeile,gbmft.long_name);                  /* Sonst alle Zeichen */
     
  mvaddstr(9,7,Zeile);
  
  sprintf(Zeile,"Filename      : %s",GRAVDIR[Index].DirEintrag);
  mvaddstr(11,7,Zeile);  
  
  sprintf(Zeile,"Resolution    : %d x %d",gbm.w,gbm.h);
  mvaddstr(13,7,Zeile);
  
  sprintf(Zeile,"Bit per pixel : %d",gbm.bpp);
  mvaddstr(15,7,Zeile);
  
  colors = ( (1 << gbm.bpp) & 0x1ff );
  sprintf(Zeile,"Colors        : %ld",colors);
  mvaddstr(17,7,Zeile);
  
  mvaddstr(21,20,"Press any key");
  
  refresh();
  getch();
}