/* $Revision Header *** Header built automatically - do not edit! ***********
 *
 *	(C) Copyright 1991 by Metalworx
 *
 *	Name .....: eingabe.c
 *	Created ..: Sun 06-Oct-91 21:43
 *	Revision .: 3
 *
 *	Date		Author		Comment
 *	=========	========	====================
 *	27-Jun-92	Mtwx		Einbau des 'Molekül-Erzeuger'-Gadgets
 *	26-Apr-92	Mtwx		Anpassungen an diverse Mathe-Modelle
 *	19-Oct-91	Mtwx		Fehler i. Speicherverwaltung behoben
 *	06-Oct-91	Mtwx		Created this file!
 *
 * $Revision Header ********************************************************/
 #define REVISION 3

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <exec/types.h>
#include <exec/memory.h>
#include "mathlibs.h"
#include <intuition/intuitionbase.h>
#include <libraries/arpbase.h>
#include <libraries/reqbase.h>
#include <clib/req_protos.h>
#include <req.h>		     /* enthält #pragmas für req.library */
#include <proto/exec.h>
#include <proto/intuition.h>

#include <mtwx_defs.h>

#include "messages.h"
#include "chem_defs.h"
#include "eingabe.h"

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

#ifndef __SASC
static USHORT *AddBuffer=NULL;	       /* MemoryBuffer f. Gadget-Grafik */
static USHORT *EditBuffer=NULL;
static USHORT *UpBuffer=NULL;
static USHORT *DnBuffer=NULL;
#endif
static struct Window *Window2;

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

extern int atomanz, drehx, drehy, drehz, ref, geladene_Atome;
extern long conwin;
extern double mattheit, matthm1, abstand, vergr, zf, VERGRFAKTOR;
extern ATOMTYP *a[];
extern ATOMTYP *alt[];	      /* enthaelt Original-Werte, nicht gedreht etc. */
extern VEKTOR l, b;
extern USHORT GadgetID;
extern BOOL reflexion;
extern char Dateiname[];
extern struct Atom *GAtom[];
extern struct Screen *FirstScreen;
extern struct ReqLib *ReqBase;
extern struct Border StringGBorder1;
extern struct Border StringGBorder2;

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

void	  uebertragen(void), anzeigen(), Prepare();
void	  FlushStrGadget(struct StringInfo *);

extern void SimpleRequest(char *,...);

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

int	  Eingabe()
{
  register int i, j;
  int	    ende = 0, anfang = 1, nummer = atomanz + 1, pos, mx, my, rwert,
	    atomanz_alt, a_name;
  char	    dummy[81];
  char	    CreaNameBufOld[21];

  SHORT SGVec2[]={ 0,11,171,11,171,0 };
  SHORT SGVec1[]={ 0,10,0,0,170,0 };
  struct Border LocalSGBorder1, LocalSGBorder2;

/* Border für das 'Molekül-Erzeuger' einrichten */
  LocalSGBorder1=StringGBorder1;
  LocalSGBorder2=StringGBorder2;
  LocalSGBorder1.NextBorder=&LocalSGBorder2;
  LocalSGBorder1.XY=SGVec1;
  LocalSGBorder2.XY=SGVec2;
  CreaNameGadget.GadgetRender=(APTR)&LocalSGBorder1;
  CreaNameInfo.NumChars=strlen(CreaNameBuf);
  strcpy(CreaNameBufOld,CreaNameBuf);    /* alten Namen sichern */

/* Fenster öffnen und Texte ausgeben */
  EingabeFenster.Screen = FirstScreen;
  if (!(Window2 = OpenWindow(&EingabeFenster)))
    return 0;
  Print(Window2, Dateiname, 7, 0, 5, 32);
  Print(Window2, CREANAMETEXT, 1,0,312-strlen(CREANAMETEXT)*8,24);
  Print(Window2, "Atom                         X      Y      Z    Radius",
	9, 0, 62, 127);
  Box(Window2, 1, 6, 4, 35, 608, 86);
  sprintf(dummy, "%s    %s               %s               %s             ",
	  MAGNF, TURN, LIGHT, REFLEX);
  Print(Window2, dummy, 13, 2, 4, 158);

/* Speicher holen, Werte sichern etc. */
  atomanz_alt = atomanz;	       /* Sichern, falls Abbr. gedrueckt wird */
  a[nummer]=(ATOMTYP *)ArpAlloc(sizeof(ATOMTYP)); /* für das erste neue Atom */
  alt[nummer]=(ATOMTYP *)ArpAlloc(sizeof(ATOMTYP)); /* für die erste
						       Sicherheitskopie */
  for (i = 1; i <= atomanz; i++)
  {
    *a[i] = *alt[i];	/* Original-Werte zurückschreiben, (enthält Molekül
			   im 'Ursprungszustand', d.h. nicht gedreht und
			   sortiert!!) */
  }
  uebertragen();
  ModifyProp(&Prop, Window2, NULL, AUTOKNOB | FREEVERT, 0, 0, 0,
	     SetSize(atomanz,10));
  while (!ende)
  {
    switch (Nachricht(Window2))
    {
      case CLOSEWINDOW:
	rwert = 0;
	ende++;
	break;
      case GADGETUP:
	switch (GadgetID)
	{
	  case 1:		       /* PropGadget */
	    anfang = ReadLocation(atomanz,10,PropSInfo.VertPot)+1;
	    if(anfang > atomanz-9 && atomanz>10)
	      anfang=atomanz -9;
	    anzeigen(anfang);
	    break;
	  case 2:		       /* Pfeil nach oben */
	    if (anfang > 1 && atomanz > 0)
	    {
	      anfang--;
	      ModifyProp(&Prop, Window2, NULL, AUTOKNOB | FREEVERT,
		      0,SetLocation(atomanz,10,anfang-1),0,PropSInfo.VertBody);
	      anzeigen(anfang);
	    }
	    break;
	  case 3:		       /* Pfeil nach unten */
	    if (anfang < atomanz - 9 && atomanz >0)
	    {
	      anfang++;
	      ModifyProp(&Prop, Window2, NULL, AUTOKNOB | FREEVERT,
		      0,SetLocation(atomanz,10,anfang-1),0,PropSInfo.VertBody);
	      anzeigen(anfang);
	    }
	    break;

	  case 4:		       /* Vergroesserung */
	    ActivateGadget(&DrehX, Window2, NULL);
	    break;
	  case 5:
	    ActivateGadget(&DrehY, Window2, NULL);
	    break;
	  case 6:
	    ActivateGadget(&DrehZ, Window2, NULL);
	    break;
	  case 7:
	    ActivateGadget(&LichtX, Window2, NULL);
	    break;
	  case 8:
	    ActivateGadget(&LichtY, Window2, NULL);
	    break;
	  case 9:
	    ActivateGadget(&LichtZ, Window2, NULL);
	    break;
	  case 10:
	    ActivateGadget(&Reflex, Window2, NULL);
	    break;
	  case 11:
	    break;
	  case 12:
	    strcpy(a[nummer]->name, AtomSIBuff);
	    ActivateGadget(&PosX, Window2, NULL);
	    break;
	  case 13:
	    a[nummer]->x = PosXSInfo.LongInt;
	    ActivateGadget(&PosY, Window2, NULL);
	    break;
	  case 14:
	    a[nummer]->y = PosYSInfo.LongInt;
	    ActivateGadget(&PosZ, Window2, NULL);
	    break;
	  case 15:
	    a[nummer]->z = PosZSInfo.LongInt;
	    ActivateGadget(&Radius, Window2, NULL);
	    break;
	  case 16:
	    a[nummer]->r = RadiusSInfo.LongInt;
	    if(a[nummer]->r==0)
	    {
	      SimpleRequest(ERROR_RADIUS);
	      FlushStrGadget(&RadiusSInfo);
	      ActivateGadget(&Radius,Window2,NULL);
	      break;
	    }
	    if (Neu.Flags & SELECTED)  /* nur wenn wirklich neues Atom */
	    {
	      atomanz++;
	      anfang=atomanz>9 ? atomanz-9 : 1;
	      ModifyProp(&Prop, Window2, NULL, AUTOKNOB | FREEVERT,
			 0, SetLocation(atomanz,10,anfang-1), 0,
			 SetSize(atomanz,10));
	      nummer++;
	      a[nummer]=(ATOMTYP *)ArpAlloc(sizeof(ATOMTYP));
	      alt[nummer]=(ATOMTYP *)ArpAlloc(sizeof(ATOMTYP));
	    }
	    anzeigen(anfang);
	    FlushStrGadget(&AtomSInfo);
	    FlushStrGadget(&PosXSInfo);
	    FlushStrGadget(&PosYSInfo);
	    FlushStrGadget(&PosZSInfo);
	    FlushStrGadget(&RadiusSInfo);
	    RefreshGList(&Atom, Window2, NULL, 5);
	    if (Neu.Flags & SELECTED)
	    {
	      sprintf(dummy, "%3d", nummer);
	      Print(Window2, dummy, 1, 0, 8, 137);
	      ActivateGadget(&Atom, Window2, NULL);
	    }
	    break;
	  case 17:		       /* OK */
	    zf = atof(VergrSIBuff);
	    if (zf == 0.0)
	      SimpleRequest(MAGNF_FACTOR);
	    if (zf == 0.0)
	      break;
	    drehx = DrehXSInfo.LongInt;
	    drehy = DrehYSInfo.LongInt;
	    drehz = DrehZSInfo.LongInt;
	    l.x = atof(LichtXSIBuff);
	    l.y = atof(LichtYSIBuff);
	    l.z = atof(LichtZSIBuff);
	    ref = ReflexSInfo.LongInt;
	    for (i = 1; i <= atomanz; i++)
	      *alt[i] = *a[i];		 /* Original-Werte aufbewahren fuer
					  erneutes Editieren */
	    rwert = 1;
	    ende++;
	    break;
	  case 18:		       /* Abbruch */
	    atomanz = atomanz_alt;     /* "alte" Anzahl zurueckholen */
	    for (i = 1; i <= atomanz; i++)
	      *a[i] = *alt[i];	       /* Ursprungsmolekül zurückholen */
	    strcpy(CreaNameBuf,CreaNameBufOld);
	    rwert = 0;
	    ende++;
	    break;
	  case 19:		       /* Edit oder Anfügen ? */
	    if (Neu.Flags & SELECTED)
	    {
	      nummer = atomanz + 1;
	      a[nummer]=(ATOMTYP *)ArpAlloc(sizeof(ATOMTYP));
	      sprintf(dummy, "%3d", nummer);
	      Print(Window2, dummy, 1, 0, 8, 137);
	      ActivateGadget(&Atom, Window2, NULL);
	    }
	    break;
	  case CREANAME:
	    break;
	  case LOESCHEN:
	    if(!(Neu.Flags & SELECTED)) /* nur im EDIT-Modus erlaubt */
	    {
	      if(atomanz)
	      {
		for(i=nummer;i<=atomanz;i++)
		  *a[i]=*alt[i+1];
		atomanz--;
		ModifyProp(&Prop, Window2, NULL, AUTOKNOB | FREEVERT,
			   0, SetLocation(atomanz,10,anfang-1), 0,
			   SetSize(atomanz,10));
		Box(Window2, 1, 6, 4, 35, 608, 86);
		anzeigen(anfang);
	      }
	    }
	    break;
	}
	break;
      case MOUSEBUTTONS:
	mx = Window2->MouseX;
	my = Window2->MouseY;
	pos = (my - 38) / 8;
	if (pos >= 0 && pos < 10 && mx < 618)
	{
	  if(Neu.Flags & SELECTED)    /* im Anfüge-Modus ? */
	    SimpleRequest(WRONG_MODE);
	  else
	  {
	    pos = pos + anfang;
	    if(pos<=atomanz)
	    {
	      strcpy(AtomSIBuff, a[pos]->name);
	      sprintf(PosXSIBuff, "%d", a[pos]->x);
	      sprintf(PosYSIBuff, "%d", a[pos]->y);
	      sprintf(PosZSIBuff, "%d", a[pos]->z);
	      sprintf(RadiusSIBuff, "%d", a[pos]->r);
	      RefreshGList(&Atom, Window2, NULL, 5);
	      nummer = pos;		   /* Aktuelle Atom-Nummer aufs aus-
					      gewaehlte Atom setzen */
	      sprintf(dummy, "%3d", nummer);
	      Print(Window2, dummy, 1, 0, 8, 137);
	      a_name = 105;		   /* auf ??? setzen, falls nichts ge-
					      funden wird */
	      for (j = 1; j <= geladene_Atome; j++)
	      {
		if (stricmp(a[pos]->name, GAtom[j]->Kurzz) == NULL)
		{
		  a_name = j;
		  break;
		}
	      }
	      sprintf(dummy, "%-20s", GAtom[a_name]->Name);
	      Print(Window2, dummy, 1, 0, 96, 136);
	    }
	  }
	}
	break;
    }
  }
  CloseWindowSafely(Window2, NULL);
  return rwert;
}

void	  uebertragen()
{
  char	    dummy[80];

  anzeigen(1);                         /* Start immer bei 1 */
  sprintf(dummy, "%4.2lf", zf);
  strncpy(VergrSIBuff, dummy, VergrSInfo.MaxChars);
  VergrSInfo.NumChars = strlen(VergrSIBuff);
  DrehXSInfo.LongInt = drehx;
  sprintf(DrehXSIBuff, "%d", drehx);
  DrehYSInfo.LongInt = drehy;
  sprintf(DrehYSIBuff, "%d", drehy);
  DrehZSInfo.LongInt = drehz;
  sprintf(DrehZSIBuff, "%d", drehz);
  sprintf(dummy, "%7.0f", l.x);
  strncpy(LichtXSIBuff, dummy, LichtXSInfo.MaxChars);
  LichtXSInfo.NumChars = strlen(LichtXSIBuff);
  sprintf(dummy, "%7.0f", l.y);
  strncpy(LichtYSIBuff, dummy, LichtYSInfo.MaxChars);
  LichtYSInfo.NumChars = strlen(LichtYSIBuff);
  sprintf(dummy, "%7.0f", l.z);
  strncpy(LichtZSIBuff, dummy, LichtZSInfo.MaxChars);
  LichtZSInfo.NumChars = strlen(LichtZSIBuff);
  ReflexSInfo.LongInt = ref;
  sprintf(ReflexSIBuff, "%d", ref);
  RefreshGList(&Vergr, Window2, NULL, 8);
}

void	  anzeigen(anfang)
int	  anfang;
{
  register int i, j;
  int	    y = 0, nummer,ende;
  char	    dummy[80];

  ende=atomanz > anfang+9 ? anfang+9 : atomanz;
  for (i = anfang; i <= ende; i++)
  {
    nummer = 105;
    for (j = 1; j <= geladene_Atome; j++)
    {
      if (stricmp(a[i]->name, GAtom[j]->Kurzz) == 0)
      {
	nummer = j;
	break;
      }
    }
    sprintf(dummy, "%3d)   %3s %-20s %6d %6d %6d  %4d                ",
	    i, a[i]->name, GAtom[nummer]->Name, a[i]->x, a[i]->y, a[i]->z,
	    a[i]->r);
    Print(Window2, dummy, 3, 5, 8, 44 + y * 8);
    y++;
  }
}

void	  FlushStrGadget(struct StringInfo *StrInfo)
{
  strcpy(StrInfo->Buffer, "");
  StrInfo->NumChars = 0;
  StrInfo->BufferPos = 0;
}

void	  Prepare()                    /* Werte vorbereiten zum Zeichnen */
{
  int	    n;

  atomedrehen('x', (double) drehx);
  atomedrehen('y', (double) drehy);
  atomedrehen('z', (double) drehz);
  vergr = VERGRFAKTOR;
  vergr *= zf;
  abstand = BILDSCHIRMABSTAND / zf;
  b.x = 0.0;
  b.y = -abstand;
  b.z = 0.0;
  for (n = 1; n <= atomanz; n++)       /*Vergroeßerung der Kalotten*/
    a[n]->r = round(ATOMVERGRFAKT * a[n]->r);
  reflexion = TRUE;
  if (ref < 1)
    reflexion = FALSE;
  else
  {
    if (ref > 100)
      ref = 100;
    mattheit = (double) ref / 100.0;
    matthm1 = 1.0 / mattheit - 1.0;
  }
  atomeordnen();
  atomezentrieren();
}

void PrepareEGadgets()
{
#ifndef __SASC
  if(TypeOfMem(Add_data) & MEMF_FAST)
  {
    AddBuffer=(USHORT *)AllocMem(sizeof(Add_data),MEMF_CHIP|MEMF_PUBLIC);
    if(AddBuffer==NULL)
      WrConWin(conwin,NO_GADGET_MEM);
    else
    {
      movmem(Add_data,AddBuffer,sizeof(Add_data));
      NeuImage2.ImageData=AddBuffer;
    }
  }
  if(TypeOfMem(Edit_data) & MEMF_FAST)
  {
    EditBuffer=(USHORT *)AllocMem(sizeof(Edit_data),MEMF_CHIP|MEMF_PUBLIC);
    if(EditBuffer==NULL)
      WrConWin(conwin,NO_GADGET_MEM);
    else
    {
      movmem(Edit_data,EditBuffer,sizeof(Edit_data));
      NeuImage1.ImageData=EditBuffer;
    }
  }
  if(TypeOfMem(Dn_data) & MEMF_FAST)
  {
    DnBuffer=(USHORT *)AllocMem(sizeof(Dn_data),MEMF_CHIP|MEMF_PUBLIC);
    if(DnBuffer==NULL)
      WrConWin(conwin,NO_GADGET_MEM);
    else
    {
      movmem(Dn_data,DnBuffer,sizeof(Dn_data));
      DnImage.ImageData=DnBuffer;
    }
  }
  if(TypeOfMem(Up_data) & MEMF_FAST)
  {
    UpBuffer=(USHORT *)AllocMem(sizeof(Up_data),MEMF_CHIP|MEMF_PUBLIC);
    if(UpBuffer==NULL)
      WrConWin(conwin,NO_GADGET_MEM);
    else
    {
      movmem(Up_data,UpBuffer,sizeof(Up_data));
      UpImage.ImageData=UpBuffer;
    }
  }
#endif
}

void FreeEGadgets()
{
#ifndef __SASC
  if(AddBuffer)
    FreeMem(AddBuffer,sizeof(Add_data));
  if(EditBuffer)
    FreeMem(EditBuffer,sizeof(Edit_data));
  if(DnBuffer)
    FreeMem(DnBuffer,sizeof(Dn_data));
  if(UpBuffer)
    FreeMem(UpBuffer,sizeof(Up_data));
#endif
}
