/*
 * Programm zum Anzeigen von der 'vers' Resource.
 *
 * written 11.04.1992 by Andre Florath
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <rexx/rxslib.h>
#include <intuition/intuition.h>
#include <clib/exec_protos.h>
#include <clib/rexxsyslib_protos.h>
#include <clib/gadtools_protos.h>

#include <string.h>
#include <stdio.h>

#include "version.h"

#define ONE ((size_t)1)

struct RexxSysBase   *RexxSysBase=NULL;
struct GadToolsBase  *GadToolsBase=NULL;
struct IntuitionBase *IntuitionBase=NULL;

struct MsgPort	     *RexxPort, *MyPort;
struct RexxMsg	     *RxMsg;

enum stage
{
   develop=0x20, alpha=0x40, beta=0x60, final=0x80
};

struct VersionResource
{
   unsigned char MajorRev;
   unsigned char MinorRev:4;
   unsigned char BugFixRev:4;
   unsigned char Stage;
   unsigned char NonRelRev;
   short	 CountryCode;
   unsigned char ShortLen;
   char 	 ShortString[1]; /* Variable len */
/* unsigned char LongLen;
   char 	 LongString[1]	    Variable len */
};

unsigned char versbuffer[520]; /* Darein passt's auf jeden Fall. */
unsigned char str1[256], str2[256];

struct EasyStruct OutRequest =
{
   sizeof (struct EasyStruct),
   0,
   NULL,
   NULL,
   NULL
};

int ReqOut(char *Headline, char *text, char *wahl)
{
   OutRequest.es_Title	      = Headline;
   OutRequest.es_TextFormat   = text;
   OutRequest.es_GadgetFormat = wahl;

   return EasyRequest(Project0Wnd,&OutRequest,0);
}


void ResError(char *text)
{
   ReqOut("ResGrep Error",text,"Oh, no!");
}

void ResWarning(char *text)
{
   ReqOut("ResGrep Warning",text,"It'll better next time.");
}

void ResMessage(char *text)
{
   ReqOut("ResGrep Message",text,"Read it!");
}

int ResAsk(char *text, char *wahl)
{
   return ReqOut("ResGrep Message",text,wahl);
}



void DisplayVers(char *filename)
{
   FILE *in;
   int	 len, index;
   struct VersionResource *vh;
   unsigned char  *strbeg;
   unsigned char  lenstr2, *stagestr;

   if( (in=fopen(filename,"r"))==NULL )
   {
      ResError("Can't open file.");
      return;
   }
   if( (len=fread((void *)versbuffer,520,ONE,in))==EOF )
   {
      ResError("Error while reading data.");
      fclose(in);
      return;
   }
   vh=(struct VersionResource *)versbuffer;

   GT_SetGadgetAttrs(Project0Gadgets[GDX_version],Project0Wnd,NULL,GTNM_Number,vh->MajorRev,TAG_DONE);
   GT_SetGadgetAttrs(Project0Gadgets[GDX_Revision],Project0Wnd,NULL,GTNM_Number,vh->MinorRev,TAG_DONE);
   GT_SetGadgetAttrs(Project0Gadgets[GDX_minor],Project0Wnd,NULL,GTNM_Number,vh->BugFixRev,TAG_DONE);
   GT_SetGadgetAttrs(Project0Gadgets[GDX_nrrev],Project0Wnd,NULL,GTNM_Number,vh->NonRelRev,TAG_DONE);
   GT_SetGadgetAttrs(Project0Gadgets[GDX_country],Project0Wnd,NULL,GTNM_Number,vh->CountryCode,TAG_DONE);

   switch( vh->Stage )
   {
    case develop:    stagestr="develop"; break;
    case alpha:      stagestr="alpha"; break;
    case beta:	     stagestr="beta"; break;
    case final:      stagestr="final"; break;
   }
   GT_SetGadgetAttrs(Project0Gadgets[GDX_stage],Project0Wnd,NULL,GTTX_Text,stagestr,TAG_DONE);

   strbeg=(unsigned char *) &(vh->ShortString[0]);
   for(index=0;index<vh->ShortLen;index++)
      str1[index]=*strbeg++;
   str1[index]='\0';
   GT_SetGadgetAttrs(Project0Gadgets[GDX_versstr],Project0Wnd,NULL,GTTX_Text,str1,TAG_DONE);

   lenstr2=(unsigned char) *strbeg++;
   for(index=0;index<lenstr2;index++)
      str2[index]=*strbeg++;
   str2[index]='\0';
   GT_SetGadgetAttrs(Project0Gadgets[GDX_reserved],Project0Wnd,NULL,GTTX_Text,str2,TAG_DONE);

   fclose(in);
   return;
}

void CleanUp(void)
{
   if( RexxSysBase )  CloseLibrary((struct Library *)RexxSysBase);
   if( GadToolsBase ) CloseLibrary((struct Library *)GadToolsBase);
   if( IntuitionBase )CloseLibrary((struct Library *)IntuitionBase);
   if( MyPort )       { RemPort(MyPort); DeleteMsgPort(MyPort); }
   return;
}


int main(void)
{
   int index;
   struct IntuiMessage	 theIMsg, *imsg;

   if( (IntuitionBase=(struct IntuitionBase *)
	OpenLibrary("intuition.library",36))==NULL )
   {
/* Was tuen?	  printf("Kann 'intuition.library' nicht öffnen.\n"); */
      CleanUp();
      return 1;
   }
   if( (RexxSysBase=(struct RexxSysBase *)
	OpenLibrary("rexxsyslib.library",36))==NULL )
   {
      CleanUp();
      ResError("Can't open 'rexxsyslib.library'.");
      return 1;
   }

   if( (GadToolsBase=(struct GadToolsBase *)
	OpenLibrary("gadtools.library",36))==NULL )
   {
      ResError("Can't open 'gadtools.library'.");
      CleanUp();
      return 1;
   }

   RexxPort = FindPort("REXX");
   if (!RexxPort)
   {
      ResError("ARexx-Master does not run.");
      return 2;
   }

   Forbid();
   {
      /*     Erst mal sehen, ob wir schon irgendwo laufen?	*/
      if (FindPort("RESGREP_VERS"))
      {
	 Permit();
	 CleanUp();
	 ResError("ResGrep_Vers is running.");
	 return 2;
      }
      MyPort = CreateMsgPort();
      MyPort->mp_Node.ln_Name = "RESGREP_VERS";
      MyPort->mp_Node.ln_Pri  = 0;
      AddPort(MyPort);
   }
   Permit();

   if( SetupScreen()!=0 )
   {
      ResError("Can't setup screen.");
      CleanUp();
      return 2;
   }
   if( OpenProject0Window()!=0 )
   {
      ResError("Can't open window.");
      CloseDownScreen();
      CleanUp();
      return 2;
   }

   /* Und mal wieder die Main-Event-Loop. */
   for(;;)
   {

   Wait( (1UL<<(unsigned long)(Project0Wnd->UserPort->mp_SigBit))
	| (1UL<<(unsigned long)(MyPort->mp_SigBit)) );
   while( RxMsg = (struct RexxMsg *)GetMsg(MyPort) )
   {
      if( strncmp(RxMsg->rm_Args[0],"QUIT",4)==0 )
      {
	 RxMsg->rm_Result2 = NULL;
	 ReplyMsg((struct Message *)RxMsg);
	 CloseProject0Window();
	 CloseDownScreen();
	 CleanUp();
	 return 0;
      }
      else if( strncmp(RxMsg->rm_Args[0],"OPEN",4)==0 )
      {
	 DisplayVers(&(RxMsg->rm_Args[0][5]));
      }

      RxMsg->rm_Result2 = NULL;
      ReplyMsg((struct Message *)RxMsg);
   }
   while( (imsg=GT_GetIMsg(Project0Wnd->UserPort)) != NULL )
   {
      /* Message kopieren und sofort orginale sofort zurückschicken. */
      theIMsg=*imsg;
      GT_ReplyIMsg(imsg);
      /*  Zuerst einmal alle Messages abfangen, die nicht an ein
	  Fenster weitergegeben werden sollen. Dazu zählen z.B. alle
	  Menuauswahlen.
       */
      /* Es kann nur eine Meldung ankommen: WindowClose. */
      CloseProject0Window();
      CloseDownScreen();
      CleanUp();
      return 0;
   }

   } /* Forever */
   return 0;
}


