/* $Revision Header *** Header built automatically - do not edit! ***********
 *
 *	(C) Copyright 1991 by Metalworx
 *
 *	Name .....: chemest.c
 *	Created ..: Sun 06-Oct-91 20:51
 *	Revision .: 4
 *
 *	Date		Author		Comment
 *	=========	========	====================
 *	26-Apr-92	Mtwx		Anpassungen f. Default-Gadget (Prefs)
 *	22-Jan-92	Mtwx		Auslagerung der Programmroutinen in control.c
 *	23-Oct-91	Mtwx		FileRequest-Struktur jetzt über ArpAlloc()
 *	18-Oct-91	Mtwx		Zeit-Info hinzugefügt
 *	     1989	Mtwx		Created this file!
 *
 * $Revision Header ********************************************************/
 #define REVISION 4

/***************************************************************************
* chemest.c : Hauptprogramm von Chemesthetics				   *
***************************************************************************/

/* ------------------------------- includes ----------------------------- */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <intuition/intuitionbase.h>
#include <graphics/view.h>
#include <graphics/gfxbase.h>
#include <libraries/dosextens.h>
#include "mathlibs.h"
#include <libraries/arpbase.h>
#include <libraries/reqbase.h>
#include <clib/req_protos.h>
#include <req.h>
#include <time.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>

#include <mtwx_defs.h>

#include "messages.h"
#include "chem_defs.h"
#include "chemest.h"

/* ------------------------------- defines ------------------------------ */

/* ------------------------------- global references -------------------- */

double	  VERGRFAKTOR = 0.3;	       /* Umrechnungsfaktor pm -> Pixels   */

int	  HEIGHT = 256; 	       /* Default, wird bei NTSC-Screen geaendert */
BOOL	  reqlib_used = FALSE;
int	  koordmx, koordmy;
int	  aktfarb;

double	  aspect , vergr;

long	  conwin;
char	  dn[DSIZE+FCHARS+2]="";
char	  Dateiname[FCHARS+1]="", IFFDateiname[FCHARS+1];
char	  Pfadname[DSIZE+1],Titel[80];

struct ChemPrefs ChemPrefs= { "",0,0,1.5,TRUE,TRUE,FALSE,TRUE,
			      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2 };
struct ChemPrefs DefaultPrefs= { "",0,0,1.5,TRUE,TRUE,FALSE,TRUE,
			      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2 };

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct ArpBase *ArpBase;
struct ReqLib *ReqBase;
struct Screen *FirstScreen;
struct Window *Window1;
struct Process *MyProcess;
struct ReqFileRequester *FileStr; /* kommt aus reqbase.h */
APTR OldErrorWin;	      /* Windowstruktur vor dem Starten des Tasks */

/* ------------------------------- external references ------------------ */

extern char ProgId[], Version[];
extern char	 Konfigdn[];
extern struct Window *timewin;
extern int	 atomanz;		      /*Anzahl der Atome    */
extern USHORT	 code;
extern USHORT	 GadgetID;
extern struct IntuiMessage *message;
extern struct Gadget *GadgetPtr;
extern ATOMTYP	 *a[MAXATOM];	/* Atome */

/* ------------------------------- prototypes --------------------------- */

/* Prototypes for functions defined in chemest.c */

#ifndef __NOPROTO
#ifndef __PROTO
#define __PROTO(a) a
#endif
#else
#ifndef __PROTO
#define __PROTO(a) ()
#endif
#endif

void Open_All __PROTO((void));
void Menu_Auswertung __PROTO((USHORT Menu_Nr));
void Close_All __PROTO((BOOL status));

/* ------------------------------ external references ------------------- */

extern void Werte_loeschen __PROTO((void));
extern void license __PROTO((void));
extern void set_screenmode __PROTO((int height));
extern void Credits __PROTO((void));
extern void Prepare __PROTO((void));
extern void dateispeichern __PROTO((BOOL));
extern void Bild_speichern __PROTO((void));
extern void SysInfo __PROTO((void));
extern void Farben __PROTO((void));
extern void Logo __PROTO((void));
extern void atomskizze __PROTO((ATOMTYP *v_m));
extern void PrintName __PROTO((void));
extern void zeit_angabe __PROTO((int,long,long));
extern void StatRequest __PROTO((struct Window *,int,int));
extern void prefs __PROTO((struct ChemPrefs *));
extern void Load_Datafile __PROTO((void));
extern void Titelbild __PROTO((void));
extern void PrepareLogo __PROTO((void));
extern void FreeLogo __PROTO((void));
extern void PrepareEGadgets __PROTO((void));
extern void FreeEGadgets __PROTO((void));
extern void PreparePrefs __PROTO((struct ChemPrefs *));
extern int dateieinlesen __PROTO((void));
extern int farbnr __PROTO((ATOMTYP *v_atom));
extern int __regargs atomzeichnen __PROTO((ATOMTYP *v_m,int));
extern BOOL Eingabe __PROTO((void));
extern BOOL prepare_zeitinfo __PROTO((int));
extern BOOL Metalworx __PROTO((struct Screen *));
extern BOOL PrefsLaden __PROTO((struct ChemPrefs *,struct Window *));

extern void SimpleRequest __PROTO((char *,...));
extern short TwoGadRequest __PROTO((char *,...));

/* ------------------------------- routines ----------------------------- */

void	  main()                       /* Hauptprogramm            */
{
  Open_All();
  koordmx = round(RESX / 2.0);
  koordmy = round(((double) HEIGHT - 26.0) / 2.0);
  if(HEIGHT<256)
    ChemPrefs.bv=2.0;
  aspect = ((double) HEIGHT - 26.0) / RESX * ChemPrefs.bv;

  vergr = VERGRFAKTOR;
  Werte_loeschen();                    /* sicherheitshalber loeschen, damit nicht irgend-
					  welcher Muell vorhanden ist */
  FOREVER
  {
    switch (Nachricht(Window1))
    {
      case MENUPICK:
	Menu_Auswertung(code);
	break;
      case VANILLAKEY:	  /* alle diese Features sind nicht dokumentiert,
			     da sie nur für mich interessant sind! */
	switch(code)
	{
	  case 'l':
	  case 'L':
	    license();
	    break;
	  case 'N':
	    set_screenmode(200);
	    break;
	  case 'P':
	    set_screenmode(256);
	    break;
	 }
	 break;
    }
  }
}

/*--------------------------- Unterroutinen ------------------------------*/

void Menu_Auswertung(Menu_Nr)
USHORT	  Menu_Nr;
{
  USHORT    Menu, MenuItem;
  int n;
  long stime,etime;
  BYTE oldpri;
  BOOL timewindow_on=FALSE;

  Menu = MENUNUM(Menu_Nr);
  MenuItem = ITEMNUM(Menu_Nr);
/*  SubItem = SUBNUM(Menu_Nr); */  /* fuer spaeteren Gebrauch */

  switch (Menu)
  {
    case 0:			       /* Copyright, Credits */
      switch (MenuItem)
      {
	case 3:
	  Credits();
	  break;
      }
      break;
    case 1:			       /* Projekt */
      switch (MenuItem)
      {
	case 0:
	  if(atomanz)
	  {
	    if(TwoGadRequest(CONFIRM_DELETION))
	    {
	      Werte_loeschen();
	      atomanz=0;
	      strcpy(Dateiname,"");
	      strcpy(IFFDateiname,"");
	      SimpleRequest(VALUES_DELETED);
	    }
	  }
	  break;
	case 1:
	  if (dateieinlesen())
	    Prepare();
	  break;
	case 2:
	  dateispeichern(ChemPrefs.IconCreaCDM);
	  break;
	case 3:
	  Bild_speichern();
	  break;
	case 4:
	  SysInfo();
	  break;
	case 5:
	  SimpleRequest(NO_MENU_ITEM);
	  break;
	case 6:
	  if(TwoGadRequest(CONFIRM_QUIT))
	    Close_All(OK);
	  break;
      }
      break;
    case 2:			       /* Edit */
      switch (MenuItem)
      {
	case 0:
	  if (Eingabe())
	    Prepare();                 /* bei OK */
	  break;
	case 1:
	  Farben();
	  break;
      }
      break;
    case 3:			       /* Zeichnen */
      switch (MenuItem)
      {
	case 0:
	  Cls(Window1, 0);
	  for (n = 1; n <= atomanz; n++)
	  {
	    aktfarb = farbnr(a[n]);
	    atomskizze(a[n]);
	  }
	  PrintName();
	  break;
	case 1:
	  oldpri=SetTaskPri(FindTask(NULL),ChemPrefs.Priority);
	  Block(Window1, 0, 20, HEIGHT - 12, 280, 11);
	  Print(Window1, PRESS_MB, 1, 0, 20, HEIGHT - 6);
	  if(ChemPrefs.TimeWindow==TRUE)
	    timewindow_on=prepare_zeitinfo(atomanz); /* Zeit-Fenster öffnen */
	  else
	    timewindow_on=FALSE;
	  stime=time(&stime);
	  for (n = 1; n <= atomanz; n++)
	  {
	    aktfarb = farbnr(a[n]);
	    if (atomzeichnen(a[n],n))   /* solange FALSE, bis Maustaste gedr. */
	      break;
	    if(timewindow_on)
	      zeit_angabe(n,stime,time(NULL));
	  }
	  etime=time(&etime);
	  Block(Window1, 0, 20, HEIGHT - 12, 280, 11);
	  PrintName();
	  if(timewindow_on)
	  {
	    CloseWindowSafely(timewin,NULL);
	    timewindow_on=FALSE;
	  }
	  SetTaskPri(FindTask(NULL),oldpri);
	  StatRequest(Window1,etime-stime,n-1);
	  break;
      }
      break;
    case 4:			       /* Einstellungen */
      switch (MenuItem)
      {
	case 0:
	  prefs(&ChemPrefs);
	  if(ChemPrefs.bv<1.0)
	    ChemPrefs.bv=1.0;
	  aspect = ((double) HEIGHT - 26.0) / RESX * ChemPrefs.bv;
	  break;
      }
      break;
  }
}

void Open_All()
{
#ifdef FPU81
  struct CPU CPU;
#endif

  conwin = OpenRevWin("CON:120/88/400/80/Chemesthetics");
  if (conwin == -1)
  {
    printf(NO_CONSOLE);
    Close_All(NOK);
  }

  if (!(TestFile("libs:req.library")))
  {
    WrConWin(conwin, NO_REQ_LIB);
    Close_All(NOK);
  }
  else
  {
    if (!(ReqBase = (struct ReqLib *) OpenLibrary("req.library",0L)))
    {
      WrConWin(conwin, ERROR_NO_REQ);
      Close_All(NOK);
    }
  }

  if (!(IntuitionBase = (struct IntuitionBase *) ReqBase->IntuiLib))
  {
    WrConWin(conwin, NO_INTUI);
    Close_All(NOK);
  }

  if (!(GfxBase = (struct GfxBase *) ReqBase->GfxLib))
  {
    WrConWin(conwin, NO_GFX);
    Close_All(NOK);
  }

  if (!(TestFile("libs:arp.library")))
  {
    WrConWin(conwin, NO_ARP);
    Close_All(NOK);
  }

  if (!(ArpBase = (struct ArpBase *) OpenLibrary(ArpName, ArpVersion)))
  {
    WrConWin(conwin, ERROR_NO_ARP);
    Close_All(NOK);
  }

#if defined(FFP)
  if(!(TestFile("libs:mathtrans.library")))
  {
    WrConWin(conwin, NO_MATHTRANS);
    Close_All(NOK);
  }
#elif defined(IEEE)
  if(!(TestFile("libs:mathieeedoubbas.library")))
  {
    WrConWin(conwin, NO_MATHDOUBBAS);
    Close_All(NOK);
  }
  if(!(TestFile("libs:mathieeedoubtrans.library")))
  {
    WrConWin(conwin, NO_MATHDOUBTRANS);
    Close_All(NOK);
  }
#endif

#if defined(GERMAN)
  if (!(TestFile("chems_g.dat")))
#elif defined(ENGLISH)
  if (!(TestFile("chems_e.dat")))
#else
#error Specify either GERMAN or ENGLISH as define!!
#endif
  {
      WrConWin(conwin, NO_DATA);
      Close_All(NOK);
  }

  Load_Datafile();
  sprintf(Ver, "%s V%s", ProgId, Version);
#if defined(IEEE)
  strcat(Ver,"i");
#elif defined(FPU81)
  strcat(Ver,"fpu");
#endif

/*##########################################################################
# Einstellungen setzen							   #
##########################################################################*/
  memcpy(ChemPrefs.Pal,Def_Pal,16*sizeof(UWORD));
  stccpy(ChemPrefs.ProgId,ProgId,11);
  sscanf(Version,"%d.%d",&ChemPrefs.Version,&ChemPrefs.Revision);

  memcpy(DefaultPrefs.Pal,Def_Pal,16*sizeof(UWORD));
  stccpy(DefaultPrefs.ProgId,ProgId,11);
  DefaultPrefs.Version=ChemPrefs.Version;
  DefaultPrefs.Revision=ChemPrefs.Revision;
  strcpy(Konfigdn,"s:chemest.knf");

/*##########################################################################
# Demografik anzeigen							   #
##########################################################################*/
/*  Titelbild(); */

/*##########################################################################
# Screen öffnen, Höhe und Farben setzten, Fenster öffnen, Menü anhängen    #
##########################################################################*/
  if(GfxBase->DisplayFlags & (UWORD)NTSC)
    HEIGHT=200;
  FirstNewScreen.Height = HEIGHT;
  if (!(FirstScreen = (struct Screen *) OpenScreen(&FirstNewScreen)))
  {
    WrConWin(conwin, NO_SCREEN);
    Close_All(NOK);
  }

  LoadRGB4(&FirstScreen->ViewPort, ChemPrefs.Pal, 16);

  if (Metalworx(FirstScreen))
    WrConWin(conwin, NO_METAL_WIN);

  HauptFenster.Height = HEIGHT;
  HauptFenster.Screen = FirstScreen;

  if (!(Window1 = (struct Window *) OpenWindow(&HauptFenster)))
  {
    WrConWin(conwin, NO_MAIN_WIN);
    Close_All(NOK);
  }

  SetMenuStrip(Window1, &Menu1);
  MyProcess = (struct Process *)FindTask((char *)0);
  OldErrorWin = MyProcess->pr_WindowPtr; /* alten Window-Pointer sichern */
  MyProcess->pr_WindowPtr=(APTR) Window1; /* Requests auf neuen Screen */

#ifdef FPU81
  CPU=CheckCPU();
  if(strcmp(CPU.MaC_Id,"68881"))
  {
    WrConWin(conwin,NO_FPU_INSTALLED);
    if(!TwoGadRequest("%s%s%s%s%s%s",NO_FPU_TEXT1,NO_FPU_TEXT2,NO_FPU_TEXT3,
		     NO_FPU_TEXT4,NO_FPU_TEXT5,NO_FPU_TEXT6))
      Close_All(NOK);
  }
#endif

/*##########################################################################
# Strukturen für den FileRequester vorbereiten				   #
##########################################################################*/
  FileStr=(struct ReqFileRequester *)ArpAlloc(2048);
  if(!FileStr)
  {
    DispAlert(RECOVERY_ALERT,ERROR_ALLOC,MB_TO_CONTINUE);
    Close_All(NOK);
  }
  FileStr->VersionNumber=REQVERSION;
  FileStr->Title= Titel;
  FileStr->PathName = dn;
  FileStr->Dir = Pfadname;
  FileStr->File = Dateiname;
  FileStr->Flags = FRQCACHINGM|FRQCACHEPURGEM;
  FileStr->dirnamescolor = 8;
  FileStr->devicenamescolor = 4;
  strcpy(Pfadname,"Examples");

  license();
  ShowTitle(FirstScreen,ChemPrefs.Title);
  PrepareEGadgets();

  if(PrefsLaden(&ChemPrefs,NULL)==OK)
  {
    SimpleRequest(PREFS_LOADED);
    sscanf(Version,"%d.%d",&ChemPrefs.Version,&ChemPrefs.Revision);
  }
  PreparePrefs(&ChemPrefs); /* Gadgets f. Schatten- und Reflexionsfarbe
			       vorbereiten */
}

/****************************************
* Funktion: Alles geoeffnete schliessen *
****************************************/

void Close_All(status)
BOOL status;
{
  MyProcess->pr_WindowPtr=OldErrorWin;	/* alten Window-Pointer wieder
					   herstellen */
  if(reqlib_used)
    PurgeFiles(FileStr);           /* Speicher f. FileListe freigeben */
  FreeEGadgets();
  if (Window1)
  {
    ClearMenuStrip(Window1);
    CloseWindowSafely(Window1, NULL);
  }
  if (FirstScreen)
    CloseScreen(FirstScreen);
  if (ArpBase)                   /* Arp-Library schliessen und vorher alle */
    CloseLibrary((struct Library *)ArpBase);   /* Tracked_Items freigeben  */
  if (ReqBase)
    CloseLibrary((struct Library *)ReqBase);
  if (conwin != -1)
  {
    WrConWin(conwin, "Thanx! Have a nice day!");
    Delay(150L);
    close(conwin);
  }
  exit(status);
}
