#include <stdlib.h>
#include <ctype.h>

#include "toolbox.h"
#include "event.h"
#include "gadgets.h"

#include "swis.h"
#include "wimp.h"
#include "utils.h"
#include "wimplib.h"
#include "string.h"
#include "file.h"
#include "debugit.h"

#include "utils.h"

#define WimpVersion               310

#define PC_SOFTWARE_INSTALL       0x0
#define CD_ROM_INSTALL		  0x1
#define WINDOWS_DRIVER_INSTALL	  0x2
#define SOUND_BLASTER_INSTALL	  0x3
#define DRIVE_C_ICON              0x4
#define INSTALL_ICON              0x5

#define INSTALL_PC_PATH_ICON      0x4
#define INSTALL_PC_CONTINUE_ICON  0x5

/* Special event numbers */

#define INSTALL_CONTINUE_CLICKED   0x2
#define PARTITION_CONTINUE_CLICKED 0x3

static  WimpPollBlock  poll_block;
extern  MessagesFD     messages;
static  IdBlock        id_block;

static  int            filer_task_handle = NULL;

static  ObjectId       progress_window,
                       options_window,
                       install_pc_window,
                       install_drivers_window,
                       serial_window,
                       paths_window;

static BOOL            install_pc_software     = FALSE,
                       install_cd_driver       = FALSE,
                       install_windows_driver  = FALSE,
                       install_dos_drivers     = FALSE,

                       autoexec_file_not_there = FALSE,
                       config_file_not_there   = FALSE,

                       last_bit_installed      = FALSE;


static char drive_c_path_name[512];
static char global_serial_number[5];
static char global_dos_directory[30];
static char global_windows_directory[30];

void install_cd_driver_fn(char *);
void install_windows_driver_fn(char *);
void install_dos_drivers_fn(char *);
void insert_serial_number(char *path, char *serial_number);
void install_sound(char *partition_path);

void update_progress(char *string)
{
  raise_error(displayfield_set_value(0,progress_window, 0, string));
}

int task_closedown(WimpMessage *message,void *handle)
{
  message = message;
  handle = handle;

  if(filer_task_handle != NULL)
  {
      if(message->hdr.sender == filer_task_handle)
      {
          raise_error(toolbox_show_object(0,progress_window,0,NULL,NULL,NULL));
          _swix(256+7,0);
          filer_task_handle = NULL;
      }
  }
  return(1);
}

int quit_event(int event_code, ToolboxEvent *event, IdBlock *id_block,void *handle)
{
  event_code = event_code;
  event = event;
  id_block = id_block;
  handle = handle;

  exit(0);
  return(1);
}

int options_handler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
{
  OptionButtonStateChangedEvent *ev = (OptionButtonStateChangedEvent *)event;

  switch(id_block->self_component)
  {
    case PC_SOFTWARE_INSTALL:
     if(ev->new_state)
       install_pc_software = TRUE;
     else
       install_pc_software = FALSE;
     break;

    case CD_ROM_INSTALL:
     if(ev->new_state)
       install_cd_driver = TRUE;
     else
       install_cd_driver = FALSE;
     break;

    case WINDOWS_DRIVER_INSTALL:
     if(ev->new_state)
       install_windows_driver = TRUE;
     else
       install_windows_driver = FALSE;
     break;

    case SOUND_BLASTER_INSTALL:
     if(ev->new_state)
       install_dos_drivers = TRUE;
     else
       install_dos_drivers = FALSE;
     break;
  }

  if(install_pc_software || install_cd_driver || install_windows_driver || install_dos_drivers)
   raise_error(gadget_set_flags(0, options_window, INSTALL_ICON, 0));
  else
   raise_error(gadget_set_flags(0, options_window, INSTALL_ICON, (unsigned)1<<31));

  return(1);
}

// CONFIG.SYS at end of file
// AUTOEXEC.BAT at beginning of file
// EMM386 only if there already

#define TOP_OF_THE_FILE       1
#define END_OF_THE_FILE       2
#define ONLY_IF_THERE_ALREADY 3

static void install_lines(char *path, char *hit_string, char *replace_string, int where)
{
    int state=1,x = 0;
    int length, count = 0;
    int file_handle;
    char *mem;
    char ch;
    char *lines[100];

    file_readcat(path,NULL,NULL,NULL,&length,NULL);

    DEBUG debug_output("install_config_sys","File length = %d\n",length);

    mem = calloc(length+1, sizeof(char));

    file_load(path, (int)mem);

    lines[x++] = mem;

    // Replace control codes with NULLs

    while(count<length)
    {
        *(mem+count) = toupper(*(mem+count));
        ch = *(mem+count++);
        if(ch < 32)
            *(mem+count-1) = '\0';
    }

    count = 0;

    while(count<length)
    {
        ch = *(mem+count++);
        if(ch < 32)
        {
            lines[x] = mem+count;
            if(strlen(lines[x]) > 1)
             x++;
        }
    }

    DEBUG debug_output("install_config_sys","Total lines = %d\n",x);

    for( state=0 ; state < x ; state++ )
    {
      if(strcasestr(lines[state], hit_string) != NULL)
      {
        if(where == ONLY_IF_THERE_ALREADY)
          lines[state] = replace_string;
        else
         lines[state] = '\0'; /* Get rid of this line */
      }
    }

    for( state=0 ; state < x ; state++ )
    {
        if(strlen(lines[state]) > 1 && lines[state] != '\0')
        {
          DEBUG debug_output("install_config_sys","%s [len=%d]\n",lines[state],strlen(lines[state]));
        }
    }
    file_open(path,&file_handle,OPEN_NEW_READ_WRITE);

    if(where == TOP_OF_THE_FILE )
    {
      file_writealine(file_handle, replace_string,255);
      file_writeabyte(file_handle,13);
      file_writeabyte(file_handle,'\n');
    }

    for(state=0 ; state<x ; state++)
    {
        if(lines[state] != '\0')
        {
            file_writealine(file_handle,lines[state], strlen(lines[state]));
            file_writeabyte(file_handle,13);
            file_writeabyte(file_handle,'\n');
        }
    }
    DEBUG debug_output("install_config_sys","Writing line %s to %s\n",replace_string, path);

    if(where == END_OF_THE_FILE)
    {
      file_writealine(file_handle, replace_string,255);
      file_writeabyte(file_handle,13);
      file_writeabyte(file_handle,'\n');
    }

    file_close(file_handle);

    free(mem);
}

void install_pc_software_fn(void)
{
  raise_error(toolbox_show_object(0,install_pc_window,0,NULL,NULL,NULL));
  return;
}

int start_install(int event_code, ToolboxEvent *event, IdBlock *id_block,void *handle)
{
  char *buffer; // [2048];
  char *path;   // [1024];
  char *path1;  // [1024];
  int i, w_handle;

  // Weird stack problem so try malloc'ing

  buffer = (char *)malloc(2048);
  path   = (char *)malloc(1024);
  path1  = (char *)malloc(1024);

  raise_error(displayfield_get_value(0, install_pc_window, INSTALL_PC_PATH_ICON, path, 1024, NULL));

  strcpy(path1, path);

  i = strlen(path);

  while(path[i] != '.' && i > 0)
   i--;

  path[i] = '\0';

  werr(0,"About to start unzip");

  sprintf(buffer, "<PCInstall$Dir>.Resources.Unzip -u -qq -o <PCInstall$Dir>.^.Software -d %s", path);

  werr(0,"Finished unzipping");

  raise_error(displayfield_set_value(0,progress_window, 0, "Installing PC software to disc"));
  raise_error(toolbox_show_object(0,progress_window, 0, NULL, NULL, NULL));
  // event_poll(&i, &poll_block, 0);

  _swix(Hourglass_On, 0);
  raise_error(wimp_start_task(buffer, &w_handle));
  _swix(Hourglass_Off, 0);

  insert_serial_number(path1, global_serial_number);

  if(install_cd_driver || install_windows_driver || install_dos_drivers)
  {
    raise_error(toolbox_hide_object(0,progress_window));
    raise_error(toolbox_show_object(0,install_drivers_window, 0, NULL, NULL, NULL));
  }
  else
  {
    update_progress("Installation complete");
    gadget_set_flags(0, progress_window, 1, 0);
  }

  free(buffer);
  free(path);
  free(path1);

  return(1);
}

int open_paths_window(int event_code, ToolboxEvent *event, IdBlock *id_block,void *handle)
{
  raise_error(displayfield_get_value(0,install_drivers_window, DRIVE_C_ICON, drive_c_path_name, 1024, NULL));
  raise_error(toolbox_hide_object(0, install_drivers_window));
  raise_error(toolbox_show_object(0, paths_window, 0, NULL, NULL, NULL));
}

void install_memory(char *path)
{
  int handle;
  char *buffer,  // [1024]
       *buffer1; // [1024];

  buffer  = (char *)malloc(1024);
  buffer1 = (char *)malloc(1024);

  sprintf(buffer, "%s.IBMBIO/COM",path);
  sprintf(buffer1, "%s.IBMDOS/COM",path);

  if(file_exists(buffer, OPEN_EXIST_READ) || file_exists(buffer1, OPEN_EXIST_READ))
  {
    sprintf(buffer, "%s.config/sys",path);
    sprintf(buffer1,"DEVICE=C:\\%s\\EMM386 /NOMOVEXBDA",global_dos_directory);
    install_lines(buffer, "EMM386", buffer1, ONLY_IF_THERE_ALREADY);
    _swix(256+7,0);
  }

  free(buffer);
  free(buffer1);

  return;
}

int start_drivers_install(void)
{
  int  file_handle, w_handle, type = -1;
  char file[512],drive_c_path_name[512], *copy_from, *copy_to, unzip[1024];
  _kernel_oserror *e;

 /*********************************************************************
  * Unzip the drivers into the DOS partition, only overwrite if newer *
  *********************************************************************/

  raise_error(displayfield_get_value(0,install_drivers_window, DRIVE_C_ICON, drive_c_path_name, 1024, NULL));

 /*****************************************************
  * Check for write access to the specified partition *
  *****************************************************/

  e = file_open(drive_c_path_name, &file_handle, OPEN_EXIST_READ_WRITE);

  if(e)
  {
    werr(0,lookup_token("msg11"));
    return;
  }

  file_close(file_handle);

 /**************************************************
  * Install the drivers to the specified partition *
  **************************************************/

  if(install_dos_drivers)
  {
    install_dos_drivers_fn(drive_c_path_name);
    install_sound(drive_c_path_name);
  }

  if(install_cd_driver || install_windows_driver)
  {
   /**************************
    * Look for dos directory *
    **************************/

    sprintf(file, "%s.%s", drive_c_path_name, global_dos_directory);
    _swix(OS_File,_IN(0) | _IN(1) | _OUT(0), 5, file, &type);

    if(type != 2)
    {
      werr(0,"DOS directory could not be found, aborting");
      return(0);
    }

    raise_error(toolbox_show_object(0,progress_window, 0, NULL, NULL, NULL));

   /***********************************************
    * Copy the files over to the C:\DOS directory *
    ***********************************************/

    copy_from = file;
    copy_to   = unzip;

    sprintf(copy_from, "%s.DRIVERS.UTILS.*", drive_c_path_name);
    sprintf(copy_to, "%s.%s.*", drive_c_path_name, global_dos_directory);

    update_progress("Moving utils into DOS");
    gadget_set_flags(0, progress_window, 1, 0);

    _swix(Hourglass_On, 0);
    _swix(OS_FSControl, _IN(0) | _IN(1) | _IN(2) | _IN(3), 26, copy_from, copy_to, 0);
    _swix(Hourglass_Off, 0);

   /****************************************
    * Look for AUTOEXEC.BAT and CONFIG.SYS *
    ****************************************/

    e = file_open(drive_c_path_name,&file_handle,OPEN_EXIST_READ_WRITE);
    if(e!=NULL)
    {
        if(e->errnum == 0x11ac2)
        {
          werr(0,"%s",lookup_token("msg1"));
          return(0);
        }
        else
        {
          werr(0,"%s",lookup_token("msg2"));
          return(0);
        }
    }
    file_close(file_handle);

    strcpy(file,drive_c_path_name);
    strcat(file, ".AUTOEXEC/BAT");

    if(!file_exists(file,OPEN_EXIST_READ_WRITE)) autoexec_file_not_there = TRUE;
    else                   autoexec_file_not_there = FALSE;

    strcpy(file,drive_c_path_name);
    strcat(file, ".CONFIG/SYS");

    if(!file_exists(file,OPEN_EXIST_READ_WRITE)) config_file_not_there = TRUE;
    else                   config_file_not_there = FALSE;

    if(config_file_not_there || autoexec_file_not_there)
    {
      if(config_file_not_there)
      {
        werr(0,lookup_token("msg8"));
        return(0);
      }
      else
      {
        if(install_dos_drivers)
        {
          werr(0,lookup_token("msg7"));
          return(0);
        }
      }
    }
   /***********************************************************************
    * Everything is okay so continue installing whatever needs installing *
    ***********************************************************************/

    if(install_cd_driver)
     install_cd_driver_fn(drive_c_path_name);

    if(install_windows_driver)
     install_windows_driver_fn(drive_c_path_name);


    /*if(install_cd_driver || install_windows_driver)*/
    install_memory(drive_c_path_name);
  }

  update_progress("Installation complete");
  gadget_set_flags(0, progress_window, 1, 0);

  return(1);

}

void install_cd_driver_fn(char *partition_path)
{
  char *buffer,
       *copy_from,
       *copy_to,
       *tmp;

  buffer    = (char *)malloc(1024);
  copy_from = (char *)malloc(512);
  copy_to   = (char *)malloc(512);
  tmp       = (char *)malloc(1024);

  sprintf(buffer, "%s.CONFIG/SYS", partition_path);

  update_progress("Installing CD ROM driver");

  install_lines(buffer, "HPC_CD", "", END_OF_THE_FILE);
  sprintf(tmp, "DEVICE = C:\\%s\\HPC_CD.SYS", global_dos_directory);
  install_lines(buffer, "A1CD.SYS", tmp, END_OF_THE_FILE);

  sprintf(copy_from, "%s.DRIVERS.CDROM.HPC_CD/SYS", partition_path);
  sprintf(copy_to, "%s.%s.HPC_CD/SYS", partition_path, global_dos_directory);

  _swix(Hourglass_On, 0);
  _swix(OS_FSControl, _IN(0) | _IN(1) | _IN(2) | _IN(3), 26, copy_from, copy_to, 0);
  _swix(Hourglass_Off, 0);

  sprintf(buffer, "%s.AUTOEXEC/BAT", partition_path);
  sprintf(tmp, "C:\\%s\\MSCDEX /D:MSCD000", global_dos_directory);
  install_lines(buffer, "MSCDEX", tmp, TOP_OF_THE_FILE);

  sprintf(copy_from, "%s.DRIVERS.CDROM.MSCDEX/EXE", partition_path);
  sprintf(copy_to, "%s.%s.MSCDEX/EXE", partition_path, global_dos_directory);

  _swix(Hourglass_On, 0);
  _swix(OS_FSControl, _IN(0) | _IN(1) | _IN(2) | _IN(3), 26, copy_from, copy_to, 0);
  _swix(Hourglass_Off, 0);

  free(buffer);
  free(copy_from);
  free(copy_to);
  free(tmp);

  return;
}

void install_windows_driver_fn(char *partition_path)
{
  char *buffer,
       *buffer2,
       *copy_from,
       *copy_to;

  buffer    = (char *)malloc(1024);
  buffer2   = (char *)malloc(1024);
  copy_from = (char *)malloc(1024);
  copy_to   = (char *)malloc(1024);

  update_progress("Installing Windows driver");

  sprintf(buffer, "%s.%s", partition_path, global_windows_directory);
  if(!directory_exists(buffer))
  {
    sprintf(buffer, "%s.WIN95", partition_path);
    if(!directory_exists(buffer))
    {
      werr(0,"I cannot find the WINDOWS directory. Have you installed Windows 3.11 or Windows 95 yet?");
      free(buffer);
      free(buffer2);
      free(copy_from);
      free(copy_to);
      return;
    }
  }

  sprintf(buffer2,"%s.SHELLI~1",buffer);

  if(file_exists(buffer2,OPEN_EXIST_READ))
    _swix(OS_File, _IN(0) | _IN(1), 6, buffer2);

  sprintf(copy_from, "%s.DRIVERS.WINDOWS.ARMDRV/DRV", partition_path);
  sprintf(copy_to,   "%s.SYSTEM.ARMDRV/DRV", buffer);

  _swix(OS_File, _IN(0) | _IN(1), 6, copy_to); // Delete old ARMDRV/DRV

  _swix(Hourglass_On, 0);
  _swix(OS_FSControl, _IN(0) | _IN(1) | _IN(2) | _IN(3), 26, copy_from, copy_to, 1 << 12); // Copy new ARMDRV/DRV over
  _swix(Hourglass_Off, 0);

  free(buffer);
  free(buffer2);
  free(copy_from);
  free(copy_to);

  return;
}

void install_sound(char *partition_path)
{
  int value, sixteenbit;
  char buffer[1024];
  update_progress("Installing sound driver");

  _swix(OS_Byte, _IN(0) | _IN(1) | _OUT(2), 161, 132, &value);

  sixteenbit = (value >> 5) & 1;

  if(!sixteenbit)
    return;

  sprintf(buffer, "%s.AUTOEXEC/BAT", partition_path);

  install_lines(buffer, "SET BLASTER", "SET BLASTER=A220 I7 D1 H5 P330 T6", TOP_OF_THE_FILE);

  return;
}

void install_dos_drivers_fn(char *partition_path)
{
  int  type = -1, w_handle;
  char *buffer,
       *unzip;

  buffer = malloc(1024);
  unzip  = malloc(1024);

  // update_progress("Copying drivers to partition");

  // raise_error(toolbox_show_object(0,progress_window, 0, NULL, NULL, NULL));

  // event_poll(&type, &poll_block, 0);
  // sprintf(unzip,"<PCInstall$Dir>.Resources.Unzip -u -o -qq <PCInstall$Dir>.^.Drivers -d %s",drive_c_path_name);

  werr(0,"About to start unzipping drivers");

  strcpy(unzip, "<PCInstall$Dir>.Resources.Unzip -u -o -qq <PCInstall$Dir>.^.Drivers -d ");
  strcat(unzip, drive_c_path_name);

  werr(0,"%s",unzip);

  _swix(Hourglass_On, 0);

  raise_error(wimp_start_task("link\0", &w_handle));

  werr(0,"Finished unzipping drivers");

  _swix(Hourglass_Off, 0);

  // free(buffer);
  // free(unzip);

  return;
}

int install_drivers(int event_code, ToolboxEvent *event, IdBlock *id_block,void *handle)
{
    if(id_block->self_component != INSTALL_ICON)
       exit(0);

    event_code = event_code;
    event = event;
    id_block = id_block;
    handle = handle;

    /* Close the options window */

    raise_error(toolbox_hide_object(0,options_window));

    if(install_pc_software)
    {
      raise_error(toolbox_show_object(0,serial_window, 0, NULL, NULL, NULL));
      /*raise_error(toolbox_show_object(0,install_pc_window, 0, NULL, NULL, NULL));*/
      return(1);
    }

    /* Open the locate partition window */

    if(install_cd_driver || install_dos_drivers || install_windows_driver)
    {
      raise_error(toolbox_hide_object(0,progress_window));
      /*raise_error(toolbox_show_object(0, paths_window, 0, NULL, NULL, NULL));*/
      raise_error(toolbox_show_object(0, install_drivers_window,0,NULL,NULL,NULL));
    }

    return(1);
}

int quit_message(WimpMessage *message,void *handle)
{
  message = message;
  handle = handle;

  exit(0);
  return(1);
}

int data_load_handler(WimpMessage *message,void *handle)
{
    if(message->data.data_load.file_type != 0xfc8)
    {
      werr(0,"%s",lookup_token("msg5"));
      return(1);
    }
    strcpy(drive_c_path_name, message->data.data_load.leaf_name);
    raise_error(displayfield_set_value(0,install_drivers_window,DRIVE_C_ICON,drive_c_path_name));
    raise_error(gadget_set_flags(0,install_drivers_window, INSTALL_ICON,0));
    return(1);
}

/* Send a message to the recipient of the dropped icon */

int get_install_dir(int event_code, ToolboxEvent *event, IdBlock *id_block,void *handle)
{
  WimpMessage message;
  ObjectId window;
  ComponentId icon;

  DraggableDragEndedEvent *drag = (DraggableDragEndedEvent *)event;

  window_get_pointer_info(0, NULL,NULL,NULL,&window,&icon);

  if(window == install_pc_window)
   return(1);

  message.hdr.size = 56;
  message.hdr.action_code = 1;
  message.data.data_save.destination_window = drag->window_handle;
  message.data.data_save.destination_icon   = drag->icon_handle;
  message.data.data_save.estimated_size     = 100;
  message.data.data_save.file_type          = 0xfff;

  strcpy(message.data.data_save.leaf_name, "!PC");

  _swix(Wimp_SendMessage,_IN(0)|_IN(1)|_IN(2), 18, &message, drag->window_handle);

  return(1);
}

int data_save_handler(WimpMessage *message,void *handle)
{
  raise_error(displayfield_set_value(0,install_pc_window, INSTALL_PC_PATH_ICON, message->data.data_save_ack.leaf_name));
  raise_error(gadget_set_flags(0, install_pc_window, INSTALL_PC_CONTINUE_ICON, 0));
  return(1);
}

int serial_window_clicked(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
{
  ActionButtonSelectedEvent *ev = (ActionButtonSelectedEvent *)event;

  switch(id_block->self_component)
  {
    case 0x7:
     exit(0);
     break;

    case 0x5:
    {
      char serial[5];

      raise_error(writablefield_get_value(0,serial_window, 0x10, serial, 6, NULL));

      if(strlen(serial) != 5)
      {
        werr(0,lookup_token("msg9"));
        return(TRUE);
      }

      strcpy(global_serial_number, serial);

      raise_error(toolbox_show_object(0,install_pc_window, 0, NULL, NULL, NULL));
    }
    break;
  }
}

void insert_serial_number(char *path, char *serial_number)
{
  int handle, size;
  char *mem, *tmp;
  char name[512];

  strcpy(name, path);
  strcat(name, ".Templates");

  file_readcat(name, NULL, NULL, NULL, &size, NULL);

  if(size <= 0)
  {
    werr(0,"Problem reading size of Templates file");
    return;
  }

  mem = (char *)malloc(size);

  if(!mem)
  {
    werr(0,lookup_token("msg10"));
    return;
  }

  file_load(name, (int)mem);

  tmp = mem;

  tmp += 0x2c1;

  strcpy(tmp, global_serial_number);

  file_memdump(name, 0xfec, (char *)mem, size);

  free(mem);

}

#define paths_continue     0x5
#define paths_cancel       0x7
#define paths_dos_icon     0x10
#define paths_windows_icon 0x14

int paths_window_clicked(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
{
  ActionButtonSelectedEvent *ev = (ActionButtonSelectedEvent *)event;

  switch(id_block->self_component)
  {
    case paths_continue:
    {
      char *p;
      int x = 0;

      raise_error(writablefield_get_value(0, paths_window, paths_dos_icon, global_dos_directory, 12, NULL));
      raise_error(writablefield_get_value(0, paths_window, paths_windows_icon, global_windows_directory, 12, NULL));

      p = global_dos_directory;

      while(x < strlen(global_dos_directory))
      {
        if( *(p+x) == '\\' || *(p+x) == '/')
         *(p+x++) = '.';
        else
         x++;
      }

      p = global_windows_directory;
      x = 0;

      while(x < strlen(global_dos_directory))
      {
        if( *(p+x) == '\\' || *(p+x) == '/')
         *(p+x++) = '.';
        else
         x++;
      }

     if(strlen(global_dos_directory) == 0 || strlen(global_windows_directory) == 0)
     {
       werr(0,"Please specify names for both DOS and Windows");
       return(TRUE);
     }

     start_drivers_install();
    }

  }
  return(TRUE);
}

int quit_now(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
{
  exit(0);
}

void check_for_pc_running(void)
{
  if(task_running("PC Card Software"))
  {
    werr(0,"You cannot run the Installer if !PC is running. Please quit !PC and try again");
    exit(0);
  }
}

int main()
{
    int    toolbox_events = 0,
           wimp_messages = 0,
           event_code;

    DEBUG debug_set_var_name("pcinstall$debug");

    raise_error(toolbox_initialise (0, WimpVersion, &wimp_messages, &toolbox_events, "<PCInstall$Dir>",
                                    &messages, &id_block, 0, 0, 0));

    raise_error(toolbox_create_object(0,"Options",&options_window));
    raise_error(toolbox_create_object(0,"Progress",&progress_window));
    raise_error(toolbox_create_object(0,"Directory",&install_pc_window));
    raise_error(toolbox_create_object(0,"partition",&install_drivers_window));
    raise_error(toolbox_create_object(0,"Serial",&serial_window));
    raise_error(toolbox_create_object(0,"paths",&paths_window));

    raise_error(event_initialise (&id_block));

    raise_error(event_set_mask (1+256));

    raise_error(event_register_toolbox_handler(-1,1,quit_event,0));

    raise_error(event_register_toolbox_handler(options_window,OptionButton_StateChanged,options_handler,0));
    raise_error(event_register_toolbox_handler(options_window,ActionButton_Selected, install_drivers,0));

    raise_error(event_register_toolbox_handler(paths_window, ActionButton_Selected, paths_window_clicked, 0));

    raise_error(event_register_toolbox_handler(install_pc_window, Draggable_DragEnded, get_install_dir,0));
    raise_error(event_register_toolbox_handler(install_pc_window, INSTALL_CONTINUE_CLICKED, start_install, 0));
    raise_error(event_register_toolbox_handler(install_drivers_window, PARTITION_CONTINUE_CLICKED, open_paths_window, 0));

    raise_error(event_register_toolbox_handler(progress_window, ActionButton_Selected, quit_now, 0));

    raise_error(event_register_toolbox_handler(serial_window, ActionButton_Selected, serial_window_clicked,0));

    raise_error(event_register_message_handler(Wimp_MDataSaveAck, data_save_handler, 0));
    raise_error(event_register_message_handler(Wimp_MQuit,quit_message,0));
    raise_error(event_register_message_handler(Wimp_MPreQuit,quit_message,0));
    raise_error(event_register_message_handler(Wimp_MTaskCloseDown,task_closedown,0));

    raise_error(event_register_message_handler(Wimp_MDataLoad, data_load_handler, 0));

    raise_error(toolbox_show_object(0, options_window, 0, NULL, NULL, NULL));

    check_for_pc_running();

    while (TRUE)
    {
        event_poll (&event_code, &poll_block, 0);
    }
}
