/* JB-Prog-Gui -- macht die JukeBox programmierbar */

/* INCLUDE */

#include <exec/lists.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <libraries/gadtools.h>
#include <clib/alib_protos.h>
#if defined(_DCC)
  #include <clib/intuition_protos.h>
  #include <clib/graphics_protos.h>
  #include <clib/gadtools_protos.h>
  #include <clib/exec_protos.h>
  #include <clib/dos_protos.h>
#else
  #include <proto/intuition.h>
  #include <proto/graphics.h>
  #include <proto/gadtools.h>
  #include <proto/exec.h>
  #include <proto/dos.h>
#endif
#include <string.h>


/* P R O T O T Y P E N */


void WriteNumsToFile(void);
struct Node *FindNodeNum(struct List *,UWORD);
void ChangeRightGadget(void);
void AddNodeRight(UWORD);
void RemNodeRight(UWORD);
void AdjustGadgets(void);
int MakeGadgets(void);
void RemoveGadgets(void);
int MakeList(void);
struct Node *MakeNode(char *);
void ShowMsg(STRPTR);

#define POOLSIZE     4096
#define TRESHSIZE    1024

#define DEFAULTIN  "t:jb.toc"
#define DEFAULTOUT "t:jb.tracks"
#define DEFAULTLEFT "Inhalt"
#define DEFAULTRIGHT "gewählt"
#define NOMEM        "Zuwenig Speicher!"

/* Globale Variablen und Strukturen */

const char VERSION[]="$VER: Prog-GUI V2.00ß by P. Kursawe 1995";

/* libnix specials */

int __nocommandline = 1;
int __initlibraries = 1;

struct TagItem gg1tags[]={GTLV_Labels,0,TAG_DONE,0};
struct TagItem gg2tags[]={GTLV_Labels,0,GTLV_Top,0,TAG_DONE,0};

struct GfxBase *GfxBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
struct Library *GadToolsBase=NULL;
struct DosLibrary *DOSBase= NULL;
struct Gadget *gg1ptr = NULL;
struct Gadget *gg2ptr = NULL;
struct Gadget *glistptr = NULL;
struct Gadget *context = NULL;
struct VisualInfo *vi = NULL;
struct Gadget *dummygg = NULL;
struct Window *mywindow = NULL;
struct MinList Header1;
struct MinList Header2;
struct RDArgs *rdargs = NULL;
LONG Kommandoparameter[] = {
 		 (ULONG)DEFAULTIN,
 		 (ULONG)DEFAULTOUT,
 		 (ULONG)DEFAULTLEFT,
 		 (ULONG)DEFAULTRIGHT};

APTR mempool;

struct NewGadget gadget1=
			{
			 5,15,200,150,NULL,0,1,PLACETEXT_BELOW,0,0
			};
struct NewGadget gadget2=
			{
			 210,15,200,150,NULL,0,2,PLACETEXT_BELOW,0,0
			};

int _main()
{
 static struct TagItem wintags[]=
				{
				 WA_Flags,WFLG_SIZEGADGET|WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_ACTIVATE,
				 WA_Left,0,
				 WA_Top,15,
				 WA_MinWidth,100,
				 WA_MinHeight,70,
				 WA_MaxWidth,-1,
				 WA_MaxHeight,-1,
				 WA_Title,(ULONG)"JukeBox Programming Function",
				 WA_Width,640,
				 WA_Height,184,
				 WA_IDCMP,IDCMP_CLOSEWINDOW|LISTVIEWIDCMP|IDCMP_NEWSIZE,
				 TAG_DONE,0
				};
 struct IntuiMessage *imsg;
 struct Gadget *address;
 ULONG imClass;
 UWORD imCode;

 if((mempool=LibCreatePool(MEMF_CLEAR,POOLSIZE,TRESHSIZE)) == NULL)
  return;

 NewList((struct List *)&Header1);
 gg1tags[0].ti_Data=((ULONG)&Header1);
 NewList((struct List *)&Header2);
 gg2tags[0].ti_Data=((ULONG)&Header2);

 if((DOSBase=(struct DosLibrary*)OpenLibrary("dos.library",37L)))
  {
   if((GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37L)))
    {
     if((IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37L)))
      {
       if((GadToolsBase=OpenLibrary("gadtools.library",37L)))
	{
	 /* hier sind alle Libraries offen */
	 rdargs=ReadArgs((STRPTR)"IN,OUT,LEFTTEXT,RIGHTTEXT",Kommandoparameter,NULL);
	 gadget1.ng_GadgetText=(UBYTE *)Kommandoparameter[2];
	 gadget2.ng_GadgetText=(UBYTE *)Kommandoparameter[3];
	 
	 if((mywindow=OpenWindowTagList(NULL,wintags)))
	  {
	   AdjustGadgets();
	   if((MakeList()))
	    {
 	     if((MakeGadgets()))
	      {
	       for(;;)
		{
		 if(Wait(1L<<mywindow->UserPort->mp_SigBit|SIGBREAKF_CTRL_C)&SIGBREAKF_CTRL_C)
		  break;
		 while((imsg=GT_GetIMsg(mywindow->UserPort)) != NULL)
		  {
		   imClass = imsg->Class;
		   imCode  = imsg->Code;
		   address = imsg->IAddress;
		   GT_ReplyIMsg(imsg);
		   switch(imClass)
		    {
		     case IDCMP_CLOSEWINDOW:
		      goto ende;
		     case IDCMP_GADGETUP:
		      if(address->GadgetID==1)
		       {
		        AddNodeRight(imCode);
		        break;
		       }
		      if(address->GadgetID==2)
		       {
		        RemNodeRight(imCode);
		        break;
		       }
		     case IDCMP_NEWSIZE:
		      RemoveGadgets();
		      AdjustGadgets();
		      MakeGadgets();
		     default:
		      break;
		    }
		  }
		}
	ende:
	       RemoveGadgets();
	       WriteNumsToFile();
	      }
	     else
	      {
	       ShowMsg("Konnte Gadgets nicht anlegen!\n");
	      }
	    }
	   else
	    {
	     ShowMsg("Konnte Listen nicht erstellen!\n");
	    }
	   CloseWindow(mywindow);
	  }
          FreeArgs(rdargs);
	 /* alle Libraries schließen */
	 CloseLibrary(GadToolsBase);
	}
       else
        {
         ShowMsg("Kann gadtools.library nicht öffnen!\n");
        }
       CloseLibrary((struct Library *)IntuitionBase);
      }
     else
      {
       ShowMsg("Kann intuition.library nicht öffnen!\n");
      }
     CloseLibrary((struct Library *)GfxBase);
    }
   else
    {
     ShowMsg("Kann graphics.library nicht öffnen!\n");
    }
   CloseLibrary((struct Library *)DOSBase);
  }
  LibDeletePool(mempool);
 return 0;
}

/* -------------------------------------- */
/*            UNTERROUTINEN               */
/* -------------------------------------- */


void WriteNumsToFile(void)
 {
  BPTR filehandle = NULL;
  char fmt[] = "%u\n";
  struct Node *node;
  UWORD args[]={0};
    
  if((filehandle = Open((char *)Kommandoparameter[1],MODE_NEWFILE)))
   {
    node = Header2.mlh_Head;
    while(node != (struct Node *)&Header2.mlh_Tail)
     {
      args[0] = node->ln_Type;
      VFPrintf(filehandle,fmt,args);
      node = node->ln_Succ;
     }
    Close(filehandle);
   }
  else
   {
    ShowMsg("Kann \"");
    ShowMsg((char *)Kommandoparameter[1]);
    ShowMsg("\"nicht öffnen!\n");
   }
 }


struct Node *FindNodeNum(struct List * liste,UWORD Zahl)
 {
  struct Node * foundnode = NULL;
  UWORD i;
  if (IsListEmpty(liste))
   return(foundnode);
  foundnode = liste->lh_Head;
  for(i=0; i<Zahl;i++)
   {
    if(foundnode->ln_Succ == NULL)
     break;
    foundnode = foundnode->ln_Succ;
   } 
  return(foundnode);
 }

void AddNodeRight(UWORD Punkt)  /* Fügt eine Node (nummer x) ins rechte Gadget ein */
 {
  UBYTE tmpnum;
  struct Node * nodetoclone = NULL;
  if((nodetoclone = FindNodeNum((struct List *)&Header1,Punkt)))
   {
    tmpnum = nodetoclone->ln_Type;
    nodetoclone = MakeNode(nodetoclone->ln_Name);
    if((nodetoclone))
     {
      nodetoclone->ln_Type = tmpnum;
      gg2tags[0].ti_Data=0L;
      ChangeRightGadget();
      AddTail(&Header2,nodetoclone);
      gg2tags[1].ti_Data++;
      gg2tags[0].ti_Data=(ULONG)&Header2;
      ChangeRightGadget();
     }
   }
 }

void RemNodeRight(UWORD Punkt)
 {
  struct Node * nodetoremove = NULL;
  if((nodetoremove = FindNodeNum((struct List *)&Header2,Punkt)))
   {
    gg2tags[0].ti_Data=0L;
    ChangeRightGadget();
    Remove(nodetoremove);
    gg2tags[1].ti_Data--;
    gg2tags[0].ti_Data=(ULONG)&Header2;
    ChangeRightGadget();
    LibFreePooled(mempool,nodetoremove,sizeof(struct Node)+strlen(nodetoremove->ln_Name)+1);
   }
 }

void ChangeRightGadget(void)
 {
  GT_SetGadgetAttrsA(gg2ptr,mywindow,NULL,gg2tags);
 }

void AdjustGadgets(void)
 {
  gadget1.ng_LeftEdge = mywindow->BorderLeft+5;
  gadget1.ng_TopEdge  = mywindow->BorderTop+5;
  gadget1.ng_Height   = mywindow->Height - mywindow->BorderBottom - 15 - gadget1.ng_TopEdge;
  if(gadget1.ng_Height < 5)
   {
    gadget1.ng_Height = 5;
   }
  gadget2.ng_Height = gadget1.ng_Height;
  gadget1.ng_Width    = ( (mywindow->Width - mywindow->BorderLeft - mywindow-> BorderRight - 15) / 2);
   if(gadget1.ng_Width < 10)
    {
     gadget1.ng_Width = 10;
    }
  gadget2.ng_LeftEdge = gadget1.ng_Width + gadget1.ng_LeftEdge + 5;
  gadget2.ng_TopEdge  = gadget1.ng_TopEdge;
  gadget2.ng_Height   = gadget1.ng_Height;
  gadget2.ng_Width    = gadget1.ng_Width;
 }

/* Muß hier Gadgets belegen und einbinden. */

int MakeGadgets(void)
 {

  int ret=FALSE;

  if((vi=GetVisualInfoA(mywindow->WScreen,NULL)))
   {

    gadget1.ng_VisualInfo = vi;
    gadget2.ng_VisualInfo = vi;

    if((dummygg=CreateContext(&glistptr)))
     {
      if((gg1ptr=CreateGadgetA(LISTVIEW_KIND,dummygg,&gadget1,gg1tags)))
       {
	if((gg2ptr=CreateGadgetA(LISTVIEW_KIND,gg1ptr,&gadget2,gg2tags)))
	 {
	  ret=TRUE;
	  EraseRect(mywindow->RPort,mywindow->BorderLeft,mywindow->BorderTop,mywindow->Width-mywindow->BorderRight-1,mywindow->Height-mywindow->BorderBottom-1);
	  AddGList(mywindow,glistptr,-1,-1,0);
	  RefreshWindowFrame(mywindow);
	  GT_RefreshWindow(mywindow,0);
	 }
	else
	 {
	  FreeGadgets(glistptr);
	  glistptr = NULL;
	 }
       }
     }
    else
     {
      FreeVisualInfo(vi);
     }
   }
  return(ret);
 }

void RemoveGadgets(void)
 {
  if((glistptr))
   {
    RemoveGList(mywindow,glistptr,-1);
    FreeGadgets(glistptr);
    FreeVisualInfo(vi);
   }
 }

int MakeList(void)
 {
  struct FileInfoBlock *fib = NULL;
  struct Node *node=NULL;
  BPTR filehandle = NULL;
  BYTE *buffer;
  BYTE *tempptr;
  UBYTE TrackNum = 1;
  int ret = FALSE;
  LONG pos=0;
 
  if((fib=AllocDosObject(DOS_FIB,NULL)))
   {
    if((filehandle=Open((char *)Kommandoparameter[0],MODE_OLDFILE)))
     {
      if(DOSTRUE==ExamineFH(filehandle,fib))
       {
        if((buffer=LibAllocPooled(mempool,fib->fib_Size)))
         {
           Read(filehandle,buffer,fib->fib_Size);
          /* Eigentliche Bearbeitung der Textdatei */
	   tempptr = buffer;
	   while(tempptr < buffer+fib->fib_Size) /* solange nicht über Ende hinaus*/
	    {
	     if((node=MakeNode((char *)tempptr)))
	      {
	       node->ln_Type = TrackNum;   /* Mißbraucht um die Tracknummer zu sichern! */
	       TrackNum++;
	       AddTail((struct List *)&Header1,node);
	      }
	     for(;tempptr[0] != 0;tempptr++)
	      {
	       /* Nix! */
	      }
	     tempptr++;
	    }
	    ret=TRUE;
	  LibFreePooled(mempool,buffer,fib->fib_Size);
         }
        else
         {
          ShowMsg(NOMEM);
         }
       }
      else
       {
        ShowMsg("Examine fehlgeschlagen.\n");
       }
      Close(filehandle);
     }
    else
     {
      ShowMsg("Konnte \"");
      ShowMsg((char *)Kommandoparameter[0]);
      ShowMsg("\" nicht öffnen!\n");
     }
    FreeDosObject(DOS_FIB,fib);
   }
  else
   {
    ShowMsg("Konnte FileInfoBlock nicht belegen!\n");
   }
  return(ret);
 }

/* Erzeugt stinknormale Nodes (mit Name dahinter, natürlich! */

struct Node *MakeNode(char string[])
 {
  struct Node *mem;

  if((mem=LibAllocPooled(mempool,sizeof(struct Node)+strlen(string)+1)))
   {
    mem->ln_Name=(char *)(mem+1);
    strcpy((char *)(mem+1),string);
   }
  else
   {
    ShowMsg(NOMEM);
   }
  return(mem);
 }

/* gibt nur ne Meldung aus ;) */

void ShowMsg(STRPTR msg)
 {
  PutStr(msg);
 }
 

