/* Initdisc 1.00 (5 Mrz 1996) */
/* Quellcode 1.01: Desktop-Initialisierung behandelt Fehler korrekt */
/* Quellcode 1.02: doppelte Initialisierung nicht mehr mglich */
/* Quellcode 1.10: doppelte Initialisierung nicht mehr mglich */

/* HzN: 18.04.2003: 32 Bit
        nix zu tun
*/

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "swis.h"

#define boolean char
#define TRUE 1
#define FALSE 0

#define Service_Memory 17
#define Service_StartWimp 0X49
#define Service_StartedWimp 0X4A
#define Service_Reset 0X27
#define SLOTSIZE 64*1024

typedef union {
                char *byte;
                int *word;
              } multibuffer;

multibuffer pollblock,extrablock,menubuffer,indbuffer;

int osversion,taskhandle,infohandle,drivhandle,progiconhandle,indbuflen=200;
int ssize,nzones,dsize,allun,idlen,zonspa,drive=0,*filedesc;

boolean running=FALSE,start_ordered=FALSE;

char *drivenrbuf;
boolean over=FALSE;

_kernel_swi_regs regs;

extern _kernel_oserror *pc_init(char*);
extern _kernel_oserror *pc_clean(char*);
extern _kernel_oserror *dd(char*);
extern _kernel_oserror *hd(char*);

/* Assembler-Teile */
extern int zonecheck(char *,int);
extern int module_base;

void stringfrommem(char *,char *);
void tokenfrommem(char *,char **);
void poll(void);
void end(void);

void service_handler(int s_number,_kernel_swi_regs *r,void *pw)
{
  if (s_number==Service_Memory && r->r[2]==(int) module_base)
   r->r[1]=0;
  if (s_number==Service_StartWimp && !running && !start_ordered)
   {
     start_ordered=TRUE;
     r->r[0]=(int) "Desktop_InitDisc";
     r->r[1]=0;
   }
   if (s_number==Service_StartedWimp || s_number==Service_Reset)
    start_ordered=FALSE;
}

_kernel_oserror *cmd_handler(char *arg_string,int argc,int cmd_no, void *pw)
{
  _kernel_swi_regs regs;
  static _kernel_oserror e_b;_kernel_oserror *e=NULL;

  char discname[256],errcom[256],
       drivespec[]=":0",
       dismount_call[20]="-adfs- Dismount ";
  int i,disctype,old_drive=drive;

  strcpy(discname,"");
  strcpy(errcom,"");
  e_b.errnum=0;

  switch(cmd_no)
   {
  case 0:

     regs.r[0]=SLOTSIZE;
     regs.r[1]=-1;
     _kernel_swi(Wimp_SlotSize,&regs,&regs);
     regs.r[0]=2;
     regs.r[1]=(int) "InitDisc";
     regs.r[2]=0;
     return(_kernel_swi(OS_Module,&regs,&regs));
     break;

  case 1:

     if ((i=atoi(arg_string)) > 3 || i < 0)
      strcpy((e=&e_b)->errmess,"Ungltiges Laufwerk");
     else drive=i; /* Laufwerk ggf. neu setzen */

     tokenfrommem(discname,&arg_string);/*nchsten Parameter holen*/
     tokenfrommem(discname,&arg_string); /* Namen isolieren */
     stringfrommem(errcom,arg_string); /* Fehlerkommando */
     if (e!=NULL) break; /* Erster denkbarer Fehler : falsches Laufwerk */

     drivespec[1]=drive+48;

     regs.r[0]=(int) drivespec;
     regs.r[1]=(int) extrablock.byte;
     e=_kernel_swi(ADFS_DescribeDisc,&regs,&regs);

     if (e!=NULL) break; /* Fehler, z. B. falls keine Diskette */

      ssize=1 << extrablock.byte[0];
      nzones=extrablock.byte[9];
      dsize=extrablock.word[4];
      allun=1 << extrablock.byte[5];
      idlen=extrablock.byte[4];
      zonspa=extrablock.byte[10]+256*extrablock.byte[11];

      disctype=extrablock.word[8] & 0XFFFF;

      if (dsize==800*1024 &&nzones==1|| dsize==1600*1024|| dsize==1440*1024)
       {
        switch(dsize)
         {
           case 1600*1024: e=hd(discname);break;
           case  800*1024: e=dd(discname);break;
           case 1440*1024: e=disctype==0X0FC8 ? pc_init(discname) :
                                               pc_clean(discname);break;
         }
          if (e!=NULL) break;

          strcat(dismount_call,drivespec);
          regs.r[0]=(int) dismount_call;
          e=_kernel_swi(OS_CLI,&regs,&regs);
        }
      else /* Fehler anzeigen: Diskette nicht erkannt */
      {
        e=&e_b;
        strcpy(e_b.errmess,"Diskettentyp nicht untersttzt");
      }

    }

      drive=old_drive; /* Laufwerksnummer wiederherstellen */

      if (e!=NULL && *errcom!=0)
       {
          regs.r[0]=(int) errcom;
          return(_kernel_swi(OS_CLI,&regs,&regs));
       }
       else
   return e;
}


void error(_kernel_oserror *errordata)
{

 regs.r[0]=(int) errordata;
 regs.r[1]=1;
 regs.r[2]=(int) "InitDisc";
 _kernel_swi(Wimp_ReportError,&regs,&regs);

}

void error_handler(int workspace)
{

error((_kernel_oserror *) (pollblock.byte+4));
poll();
end();

}

void swi(int swinr,_kernel_swi_regs *registers)
{

  _kernel_oserror *swi_response;

  if ((swi_response=_kernel_swi(swinr,registers,registers))!=NULL)
   {
     error (swi_response);
     end();
     exit(0);
   }

}

int *my_malloc(int size)
{

 int *block;
 block=malloc(size);
 if (block==NULL)
  {
  printf("Kein Speicher verfgbar\n");
  exit(0);
  }
 else
  return(block);

return 0;
}

void alloc_mem(void)
{

 pollblock.word=my_malloc(256);
 extrablock.word=my_malloc(800);
 menubuffer.word=my_malloc(256);
 indbuffer.word=my_malloc(indbuflen);

}

int align(int odd)
{
 return(odd+3 & 0XFFFFFFFC);
}

void user_error(char *errortoken,int errorcode)
{

char parameter[10];
menubuffer.word[0]=0X00000BAD;
strcpy(menubuffer.byte+4,errortoken);
sprintf(parameter,"%d",errorcode);
 regs.r[0]=(int) filedesc;
 regs.r[1]=(int) menubuffer.byte+4;
 regs.r[2]=(int) menubuffer.byte+4;
 regs.r[3]=252;
 regs.r[4]=(int) parameter;
swi(0X00020000+MessageTrans_Lookup,&regs);
 regs.r[0]=(int) menubuffer.word;
 regs.r[1]=1;
 regs.r[2]=(int) "InitDisc";
swi(Wimp_ReportError,&regs);

}

boolean confirm(boolean query,char *token)
{

if(query==TRUE)
{
 menubuffer.word[0]=0X00000BAD;
 strcpy(menubuffer.byte+4,token);
  regs.r[0]=(int) filedesc;
  regs.r[1]=(int) menubuffer.byte+4;
  regs.r[2]=(int) menubuffer.byte+4;
  regs.r[3]=252;
 swi(0X00020000+MessageTrans_Lookup,&regs);
  regs.r[0]=(int) menubuffer.word;
  regs.r[1]=19;
  regs.r[2]=(int) "InitDisc";
 swi(Wimp_ReportError,&regs);
 return (regs.r[1]==1);
}
else
 return (TRUE);
}

void stringfrommem(char *destpointer,char *sourcepointer)
{

 while (*destpointer++=*sourcepointer>=32 ? *sourcepointer++ : 0);

}

void tokenfrommem(char *destpointer,char **sourcepointer)
{

 while (*destpointer++=**sourcepointer>32 ? *(*sourcepointer)++ : 0);
 while (**sourcepointer==32) (*sourcepointer)++;

}

int delete_disc(boolean confirmation)
{

_kernel_oserror *err;
int disctype;
char drivespec[]=":0",
     dismount_call[20]="-adfs- Dismount ";

drivespec[1]=*drivenrbuf; /* Korrekte Laufwerksnr. in der Form ":1" o. . */

regs.r[0]=(int) drivespec;
regs.r[1]=(int) extrablock.byte;
err=_kernel_swi(ADFS_DescribeDisc,&regs,&regs);

if (err!=NULL)
 {
  error(err);
  return 0;
 }

ssize=1 << extrablock.byte[0];
nzones=extrablock.byte[9];
dsize=extrablock.word[4];
allun=1 << extrablock.byte[5];
idlen=extrablock.byte[4];
zonspa=extrablock.byte[10]+256*extrablock.byte[11];

disctype=extrablock.word[8] & 0XFFFF; /* Typ der Diskette -> &FC8=pur DOS */

if (confirm(confirmation,"QUES"))
 {
  if (dsize==800*1024 && nzones==1 || dsize==1600*1024 || dsize==1440*1024)
  {
   switch(dsize)
   {
     case 1600*1024: err=hd(NULL);break;
     case  800*1024: err=dd(NULL);break;
     case 1440*1024: err=disctype==0X0FC8 ? pc_init(NULL):
                                            pc_clean(NULL);break;
   }
   strcat(dismount_call,drivespec);
   regs.r[0]=(int) dismount_call;
   if (err==NULL) err=_kernel_swi(OS_CLI,&regs,&regs);
   /* Dismount, falls Initialisierung erfolgreich */
   }
  else
   user_error("NOEF",0);
  if (err!=NULL) error (err);
 }
return 0;
}

void createmenu(char *title,char *items,int mousex)
{

char *commapos,token[12];

multibuffer menuitem;
strcpy(&menubuffer.byte[0],title);
menubuffer.word[3]=0X00070207;
menubuffer.word[4]=172;
menubuffer.word[5]=40;
menubuffer.word[6]=0;
menuitem.byte=&menubuffer.byte[28];
do
 {
  menuitem.word[1]=*items=='>' ? infohandle : *items=='-' ? drivhandle : -1;
  menuitem.word[2]=0X07000021;
  menuitem.word[0]=128*((commapos=strchr(items+=ispunct(*items)!=0,','))==NULL);
  strncpy(token,"\0\0\0\0\0\0\0\0\0\0\0\0",12);
  strncpy(token,items,(commapos==NULL)?strlen(items):commapos-items);

  regs.r[0]=(int) filedesc;
  regs.r[1]=(int) token;
  regs.r[2]=(int) menuitem.word+12;
  regs.r[3]=12;
  swi(MessageTrans_Lookup,&regs);
  items=commapos+1;
  menuitem.word+=6;
 }
while (commapos!=NULL);

regs.r[1]=(int) menubuffer.word;
regs.r[2]=mousex-64;
regs.r[3]=216;
swi (Wimp_CreateMenu,&regs);

}

void loadmessages(char *filename)
{

 char mesfilename[256];
 int len;

 strcpy(mesfilename,filename);
 strcat(mesfilename,"Res:Messages");
 regs.r[1]=(int) mesfilename;
 swi(MessageTrans_FileInfo,&regs);
 len=align(regs.r[2]+align(17+strlen(mesfilename)));
 filedesc=my_malloc(len);
 strcpy((char *)filedesc+16,mesfilename);
 regs.r[0]=(int) filedesc;
 regs.r[1]=regs.r[0]+16;
 regs.r[2]=align((int) filedesc+17+strlen(mesfilename));
 swi(MessageTrans_OpenFile,&regs);

}
void addversion_number(char *versstr,char *loc)

{

/* Quicky... old one don't seem to work ...*/

}

/** void addversion_number(char *versstr,char *loc)                              **/
/**                                                                              **/
/**  int i,day,month,year;                                                       **/
/**  static int ssec=0;                                                          **/
/**  char *subpointer;                                                           **/
/**  double days[]={0,31,28,31,30,31,30,31,31,30,31,30},count=-0.5;              **/
/**                                                                              **/
/**   for (i=1;i<=12;i++)                                                        **/
/**   {                                                                          **/
/**    count+=days[i];                                                           **/
/**    days[i]=count;                                                            **/
/**   }                                                                          **/
/**  subpointer=strchr(versstr,' ');                                             **/
/**  if (subpointer!=NULL) / * Leerzeichen noch nicht ersetzt * /                **/
/**  {                                                                           **/
/**    subpointer[0]='\0';                                                       **/
/**    subpointer[3]='\0';                                                       **/
/**    subpointer[6]='\0';                                                       **/
/**  }                                                                           **/
/**  day=atoi(subpointer+1);                                                     **/
/**  month=atoi(subpointer+4);                                                   **/
/**  year=atoi(subpointer+7);                                                    **/
/**  if (ssec==0) / * Proz. schon einmal aufgerufen * /                          **/
/**   ssec=(int) (day+days[month-1]+365*(double)year+(double)(year/4)) * 33750;  **/
/**  strcpy(loc,versstr);                                                        **/
/**  strcat(loc," (");                                                           **/
/**  pollblock.byte[0]=0;                                                        **/
/**  pollblock.byte[1]=ssec;                                                     **/
/**  pollblock.byte[2]=ssec >> 8;                                                **/
/**  pollblock.byte[3]=ssec >> 16;                                               **/
/**  pollblock.byte[4]=ssec >> 24;                                               **/
/**   regs.r[0]=(int) pollblock.byte;                                            **/
/**   regs.r[1]=(int) (loc+strlen(loc));                                         **/
/**   regs.r[2]=12;                                                              **/
/**   regs.r[3]=(int) "%DY %M3 %CE%YR";                                          **/
/**  swi(OS_ConvertDateAndTime,&regs);                                           **/
/**  strcat(loc,")");                                                            **/
/**                                                                              **/
/** }                                                                            **/


char *loadtemplate(char *windowname,int *windowhandle,int ret_indirectbuffer)
{

 /* ret_buffer!=-1 -> return pointer to buffer used by indirected data with
    address contained in (windowblock+ret_indirectbuffer)
 */

 regs.r[5]=(int) windowname;
 regs.r[6]=0;
 swi(Wimp_LoadTemplate,&regs);
 swi(Wimp_CreateWindow,&regs);
 *windowhandle=regs.r[0];
 if (ret_indirectbuffer!=-1) return
  ((char *)extrablock.word[ret_indirectbuffer/4]);

 return(0);
}

char *loadtemplates(char *filename)
{

 char templname[256];
 char *versnrbuf;

 strcpy(templname,filename);
 strcat(templname,"Res:Templates");
  regs.r[1]=(int) templname;
 swi(Wimp_OpenTemplate,&regs);
  regs.r[1]=(int) extrablock.word;
  regs.r[2]=(int) indbuffer.word;
  regs.r[3]=(int) indbuffer.word+indbuflen;
  regs.r[4]=-1;

 versnrbuf=loadtemplate("info",&infohandle,204);
 drivenrbuf=loadtemplate("volu",&drivhandle,108);

 swi(Wimp_CloseTemplate,&regs);
 return(versnrbuf);

}

int toiconbar(char *name)
{

 static char iconname[12];
 iconname[0]='!';
 strcpy (iconname+1,name);
 pollblock.word[0]=-1;
 pollblock.word[1]=0;
 pollblock.word[2]=0;
 pollblock.word[3]=63;
 pollblock.word[4]=68;
 pollblock.word[5]=0X00003102;
 pollblock.word[6]=(int) iconname;
 pollblock.word[7]=1;
 pollblock.word[8]=strlen(name)+1;
 regs.r[1]=(int) pollblock.word;
 swi(Wimp_CreateIcon,&regs);
 return(regs.r[0]);

}

void initialise(char *name,char *vers)
{

  regs.r[0]=6;
  regs.r[1]=(int) &error_handler;
  regs.r[2]=1;
  regs.r[3]=(int) pollblock.byte;
 swi(OS_ChangeEnvironment,&regs);
  loadmessages(name);
  regs.r[0]=200;
  regs.r[1]=0X4B534154;
  regs.r[2]=(int) name;
 swi(Wimp_Initialise,&regs);
 osversion=regs.r[0];
 taskhandle=regs.r[1];
 addversion_number(vers,loadtemplates(name));
 progiconhandle=toiconbar(name);

}

void mouse_click(void)
{

int mousex,mousey,buttons,window,icon,i;
mousex=pollblock.word[0];
mousey=pollblock.word[1];
buttons=pollblock.word[2];
window=pollblock.word[3];
icon=pollblock.word[4];

if (window==-2)
 switch (buttons)
  {
   case 2:
    createmenu("InitDisc",">INFO,-DRIV,QUIT",mousex);
    break;
   case 4:
    delete_disc(TRUE);
    break;
   case 1:
    delete_disc(FALSE);
    break;
  }
if (window==drivhandle)
 {
   switch (icon)
    {
      case 1:
       drive-=(buttons==1) - (buttons==4);break;
      case 2:
       drive+=(buttons==1) - (buttons==4);break;
    }
   *drivenrbuf=(drive&=3)+48;
   pollblock.word[0]=window;
   pollblock.word[1]=0;
   swi(Wimp_GetIconState,&regs);
   regs.r[0]=window;
   for(i=2;i<=5;i++) regs.r[i-1]=pollblock.word[i];
   swi(Wimp_ForceRedraw,&regs);
  }

}

void menu_selection(void)
{

over=pollblock.word[0]==2;

}

void user_message(void)
{

over=pollblock.word[4]==0;

}

void end(void)
{

 free(pollblock.word);
 free(extrablock.word);
 free(menubuffer.word);
 free(indbuffer.word);

 regs.r[0]=(int) filedesc;
swi(MessageTrans_CloseFile,&regs);
 free(filedesc);
 regs.r[0]=taskhandle;
 regs.r[1]=0X4B534154;
swi(Wimp_CloseDown,&regs);

}

void poll(void)

{

 do
 {
  regs.r[0]=1;
  regs.r[1]=(int) pollblock.word;
  swi(Wimp_Poll,&regs);

  switch(regs.r[0])
   {
    case 2:
     swi(Wimp_OpenWindow,&regs);break;
    case 3:
     swi(Wimp_CloseWindow,&regs);break;
    case 6:
     mouse_click();break;
      case 9:
     menu_selection();break;
    case 17:
    case 18:
     user_message();break;
   }
 }
 while (!over);

}

int main(void)
{

 if (!running)
  {
    running=TRUE;

    alloc_mem();
    initialise("InitDisc","1.10 (18.04.2003)");
    poll();
    end();

    running=FALSE;
  }

}
