/*
 * Copyright (c) 1995-1997 Mark Brinicombe.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    This product includes software developed by Mark Brinicombe.
 * 4. The name of the company nor the name of the author may be used to
 *    endorse or promote products derived from this software without specific
 *    prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * RiscBSD kernel project
 *
 * config.c
 *
 * Bootloader configuration window management routines
 *
 * Created      : 26/04/95
 * Last updated : 20/06/97
 */

/* Include standard header files */

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

#include "wimp.h"
#include "Event.h"       /* Event despatcher                             */
#include "Error.h"       /* Error despatcher                             */
#include "Window.h"      /* Window handling automation                   */
#include "Icon.h"        /* Icon handling automation                     */
#include "WimpSWIs.h"    /* Default event handlers                       */
#include "IconExt.h"     /* Icon handling automation                     */
#include "Screen.h"      /* Getting screen size info, etc   */
#include "Msgs.h"
#include "Menu.h"
#include "SWI.h"
#include "dlswis.h"
#include "swiv.h"

#include "icons.h"
#include "prototypes.h"
#include "config.h"

/* Declare global variables */

window_handle config_window = NULL;
window_handle config_backing = NULL;
window_handle egowindow = NULL;
menu_ptr rootdevpopup_menu = NULL;
menu_ptr swapdevpopup_menu = NULL;
menu_ptr ramdiscpopup_menu = NULL;
menu_ptr riscosfspopup_menu = NULL;

Config config = {
	"<BtRiscBSD$Dir>.^.NetBSD",
	"/dev/wd0a",
	"X1024 Y768 C256 F60",
	"",
	"ADFS",
	4,
	32,
	0,
	0,
	0,
	0,
	0,
	"",
	""
};

struct boot_device {
	char *boot_dev;
	int riscos_drive;
	char *riscos_fs;
	int flags;
};

#define USE_RAMDISC	0x01
#define NATIVE_SUPPORT	0x02

struct boot_device boot_devices[] = {
	{ "/dev/wd0a",  4, "ADFS", NATIVE_SUPPORT },
	{ "/dev/wd1a",  5, "ADFS", NATIVE_SUPPORT },
	{ "/dev/wd2a",  0, "", NATIVE_SUPPORT },
	{ "/dev/wd3a",  0, "", NATIVE_SUPPORT },
	{ "/dev/fd0a",  0, NULL, 0 },
	{ "/dev/fd1a",  1, NULL, 0 },
	{ "/dev/md0a",  0, NULL, USE_RAMDISC },
	{ "/dev/md1a",  1, NULL, USE_RAMDISC },
	{ "/dev/sd0a",  4, "SCSIFS", NATIVE_SUPPORT },
	{ "/dev/sd1a",  5, "SCSIFS", NATIVE_SUPPORT },
	{ "/dev/cd0a",  0, NULL, USE_RAMDISC },
	{ "/dev/cd1a",  1, NULL, USE_RAMDISC },
	{ "/dev/acd0a", 0, NULL, USE_RAMDISC },
	{ NULL, NULL, NULL, 0 }
};

struct flag {
	char *name;
	int simple;
	int mask;
	
};

struct flag flags[] = {
	{ "single",	1, FLAG_SINGLE },
	{ "ipkdb",	1, FLAG_IPKDB },
	{ "pmapdebug",	0, FLAG_PMAP_DEBUG },
	{ "native",	0, FLAG_NATIVE },
	{ "symtab",	1, FLAG_SYMTAB },
	{ "ddb",	1, FLAG_DDBBOOT },
	{ "vidc.mode",	0, FLAG_VIDC_OPS1 },
	{ "vidc.bpp",	0, FLAG_VIDC_OPS2 },
	{ NULL,		0, 0 }
};

struct flag cpuflags[] = {
	{ "nocache",	1, CPU_FLAG_NOCACHE },
	{ "nowritebuf",	1, CPU_FLAG_NOWRTBUF },
	{ "nofpa",	1, CPU_FLAG_NOFPA },
	{ "fpaclk2",	1, CPU_FLAG_FPA_CLK2 },
	{ NULL, 	0, 0 }
};

/* Declare external variables */

/* Local function prototypes */

BOOL Config_PaneHandler(event_pollblock *event, void *reference);
BOOL Config_Close(event_pollblock *event, void *reference);
BOOL Config_Click(event_pollblock *event, void *reference);

/* Now for the main code */


/*
 * Initialise the configuration module. This just loads the saved config file.
 */

void Config_Initialise(void)
  {
    char *menu_string;
    int loop;

    Config_Load(CONFIG_FILENAME);

    menu_string = (char *)malloc(2048);
    if (!menu_string)
      Msgs_ReportFatal(0x00000000, "err.6", "popups");

    loop = 0;
    menu_string[0] = 0;
    while (boot_devices[loop].boot_dev) {
        strcat(menu_string, boot_devices[loop].boot_dev);
        strcat(menu_string, ",");
        ++loop;
    }
    menu_string[strlen(menu_string) - 1] = 0;
    
    /* Create device popup menus */

    rootdevpopup_menu = Menu_CreateMenu("Root Devices", menu_string);
    if (!rootdevpopup_menu)
      Msgs_ReportFatal(0x00000000, "err.5", "RootDevPopup");

    ramdiscpopup_menu = Menu_CreateMenu("Ramdisc",
      "0K,1440K");
    if (!ramdiscpopup_menu)
      Msgs_ReportFatal(0x00000000, "err.5", "RamdiscPopup");

    /* Create RISCOS filesystem popup menu */

    riscosfspopup_menu = Menu_CreateMenu("Filesystems",
      "ADFS,ATAFS,IDEFS,SCSIFS");
    if (!riscosfspopup_menu)
      Msgs_ReportFatal(0x00000000, "err.5", "RISCOSFSPopup");
  }


/*
 * Load a new configuration file.
 */
 
int Config_Load(char *filename)
  {
    FILE *filehandle;
    char string[300];
    char tag[40];
    char value[256];
    int loop;
    char *ptr;
    
    filehandle = fopen(filename, "r");
    if (!filehandle) return(1);

    fread(string, 12, 1, filehandle);
    string[12] = 0;
    if (strcmp(string, "#!BtRiscBSD\n") != 0)
      {
        fclose(filehandle);
        return(2);
      }

    while (!feof(filehandle))
      {
        if (fgets(string, 300, filehandle) == NULL)
          continue;

        if (sscanf(string, "%[^:]: %[^\n]", tag, value) == 2)
          {
            if (strcmp(tag, "kernel") == 0)
              strcpy(config.kernel, value);
            if (strcmp(tag, "rootdev") == 0)
              strcpy(config.root_dev, value);
            if (strcmp(tag, "screenmode") == 0)
              strcpy(config.screenmode, value);
            if (strcmp(tag, "other") == 0)
              strcpy(config.other, value);
            if (strcmp(tag, "riscosfs") == 0)
              strcpy(config.riscos_fs, value);
            if (strcmp(tag, "riscosdrive") == 0)
              config.riscos_drive = atoi(value);
            if (strcmp(tag, "ramdisc") == 0)
              config.ramdisc = atoi(value);
            if (strcmp(tag, "maxproc") == 0)
              config.max_proc = atoi(value);
            if (strcmp(tag, "flags") == 0) {
              if (isdigit(value[0]))
                sscanf(value, "%x", &config.flags);
              else {
                ptr = strtok(value, " ");
                while (ptr) {
                  loop = 0;
                  while (flags[loop].name) {
                    if (strcmp(ptr, flags[loop].name) == 0) {
                      config.flags |= flags[loop].mask;
                      break;
                    }
                    ++loop;
                  }
                  ptr = strtok(NULL, " ");
                }
              }
            }
            if (strcmp(tag, "cpuflags") == 0) {
              if (isdigit(value[0]))
                sscanf(value, "%x", &config.cpu_flags);
              else {
                ptr = strtok(value, " ");
                while (ptr) {
                  loop = 0;
                  while (cpuflags[loop].name) {
                    if (strcmp(ptr, cpuflags[loop].name) == 0) {
                      config.cpu_flags |= cpuflags[loop].mask;
                      break;
                    }
                    ++loop;
                  }
                  ptr = strtok(NULL, " ");
                }
              }
            }
            if (strcmp(tag, "pmapdebug") == 0)
              config.pmap_debug_level = atoi(value);
            if (strcmp(tag, "videodram") == 0)
              config.video_dram = atoi(value);
            if (strcmp(tag, "vidc.mode") == 0)
              strcpy(config.vidc_ops1, value);
            if (strcmp(tag, "vidc.bpp") == 0)
              strcpy(config.vidc_ops2, value);
          }
      }

    fclose(filehandle);
    return(0);
  }


/*
 * Save a configuration file
 */

int Config_Save(char *filename)
  {
    FILE *filehandle;
    int loop;
    
    filehandle = fopen(filename, "w");
    if (filehandle)
      {
        fprintf(filehandle, "#!BtRiscBSD\n");
        fprintf(filehandle, "kernel: %s\n", config.kernel);
        fprintf(filehandle, "rootdev: %s\n", config.root_dev);
        fprintf(filehandle, "screenmode: %s\n", config.screenmode);
        fprintf(filehandle, "other: %s\n", config.other);
        fprintf(filehandle, "riscosfs: %s\n", config.riscos_fs);
        fprintf(filehandle, "riscosdrive: %d\n", config.riscos_drive);
        fprintf(filehandle, "ramdisc: %dK\n", config.ramdisc);
        fprintf(filehandle, "maxproc: %d\n", config.max_proc);
        fprintf(filehandle, "flags:");
        loop = 0;
        while (flags[loop].name)
          {
            if (config.flags & flags[loop].mask)
              fprintf(filehandle, " %s", flags[loop].name);
            ++loop;
          }
        fprintf(filehandle, "\n");
        fprintf(filehandle, "cpuflags:");
        loop = 0;
        while (cpuflags[loop].name)
          {
            if (config.cpu_flags & cpuflags[loop].mask)
              fprintf(filehandle, " %s", cpuflags[loop].name);
            ++loop;
          }
        fprintf(filehandle, "\n");
        fprintf(filehandle, "pmapdebug: %d\n", config.pmap_debug_level);
        fprintf(filehandle, "videodram: %dK\n", config.video_dram);
        fprintf(filehandle, "vidc.mode: %s\n", config.vidc_ops1);
        fprintf(filehandle, "vidc.bpp: %s\n", config.vidc_ops2);
        fclose(filehandle);
        swi(OS_File, IN(R0|R1|R2), 18, CONFIG_FILENAME, FILETYPE_UNIX);
      }
    else
      return(1);

    return(0);
  }


/*
 * Open the configuration window (the backing and the pane)
 */

void Config_OpenWindow(void)
  {
    window_state wstate;
    event_pollblock event;
    attached_menu *at_menu;
    icon_block istate;
    FILE *filehandle;
    window_info info;

    /* Are we already open ? */

    if (config_backing)
      {
        Wimp_GetWindowState(config_backing, &wstate);
        wstate.openblock.behind = -1;
        event.data.openblock = wstate.openblock;
        event.data.openblock.behind = -1;
        Config_PaneHandler(&event, NULL);
        return;
      }

    /* Create and open our main windows from the template "control". */

    config_window = Window_Create("configpane", 0);
    filehandle = fopen(EXTRAOPTS_FILENAME, "r");
    if (!filehandle)
      {
        Window_GetInfo(config_window, &info);
        info.block.workarearect.min.y += CONFIG_PANE_EXTRA_HEIGHT;
        Wimp_SetExtent(config_window, &info.block.workarearect);
      }
    else
      fclose(filehandle);

    config_backing = Window_CreateAndShow("config", 0, open_CENTERED);

    if (!config_backing || !config_window) Msgs_ReportFatal(0x00000000,
      "err.1", "config");

    Wimp_GetIconState(config_backing, CONFIG_WINDOW_ICON_LOGO, &istate);
    if (screen_bpp == 8)
      strcpy(istate.data.indirectsprite.name, "riscbsd256");
    else
      strcpy(istate.data.indirectsprite.name, "riscbsd16");

    Icon_ForceRedraw(config_backing, CONFIG_WINDOW_ICON_LOGO);

    /* Claim window-close events for the config window */

    Event_Claim(event_CLOSE, config_backing, event_ANY, Config_Close, NULL);

    /* Claim the window open events to handle the pane */

    Event_Claim(event_OPEN, config_backing, event_ANY, Config_PaneHandler,
      (void *)1);

    /* Set the correct state for all the icons */

    Config_SetIcons();

    /* Add mouse click handlers */

    Event_Claim(event_CLICK, config_backing, CONFIG_WINDOW_ICON_LOGO,
      Config_Click, NULL);
    Event_Claim(event_CLICK, config_backing, CONFIG_WINDOW_ICON_BOOT,
      Config_Confirm, (void *)0x01);
    Event_Claim(event_CLICK, config_backing, CONFIG_WINDOW_ICON_SAVE,
      Config_Confirm, (void *)0x02);
    Event_Claim(event_CLICK, config_backing, CONFIG_WINDOW_ICON_CMOS,
      Cmos_OpenWindow, NULL);

    at_menu = Menu_AttachMenu(rootdevpopup_menu, config_window,
      CONFIG_PANE_ICON_ROOTDEV_POPUP, Config_RootDevPopup, NULL, NULL, NULL);
    at_menu->flags |= MENU_FLAG_POPUP;

    at_menu = Menu_AttachMenu(rootdevpopup_menu, config_window,
      CONFIG_PANE_ICON_ROOTDEV, Config_RootDevPopup, NULL, NULL, NULL);
    at_menu->flags |= MENU_FLAG_POPUP;

    at_menu = Menu_AttachMenu(ramdiscpopup_menu, config_window,
      CONFIG_PANE_ICON_RAMDISC_POPUP, Config_RamdiscPopup, NULL, NULL, NULL);
    at_menu->flags |= MENU_FLAG_POPUP;

    at_menu = Menu_AttachMenu(ramdiscpopup_menu, config_window,
      CONFIG_PANE_ICON_RAMDISC, Config_RamdiscPopup, NULL, NULL, NULL);
    at_menu->flags |= MENU_FLAG_POPUP;

    /* Check for support for native booting */

    filehandle = fopen(NATIVE_PRESENT, "r");
    if (filehandle)
      {
        fclose(filehandle);
        Icon_SetShade(config_window, CONFIG_PANE_ICON_NATIVE, 0);

        Event_Claim(event_CLICK, config_window, CONFIG_PANE_ICON_NATIVE,
          Config_ClickNative, (void *)-1);

	Config_ClickNative(NULL, (void *)-1);

        at_menu = Menu_AttachMenu(riscosfspopup_menu, config_window,
          CONFIG_PANE_ICON_RISCOSFS_POPUP, Config_RiscosfsPopup, NULL,
          NULL, NULL);
        at_menu->flags |= MENU_FLAG_POPUP;

        at_menu = Menu_AttachMenu(riscosfspopup_menu, config_window,
          CONFIG_PANE_ICON_RISCOSFS, Config_RiscosfsPopup, NULL, NULL, NULL);
        at_menu->flags |= MENU_FLAG_POPUP;
      }

    /* Set the correct state for opening */

    Wimp_GetWindowState(config_backing, &wstate);
    event.data.openblock = wstate.openblock;
    event.data.openblock.behind = -1;
    Config_PaneHandler(&event, NULL);
  }


/*
 * Handle a open window request on the configuration window.
 * We have to open both the backing window and the pane at the appropriate
 * position.
 */
 
BOOL Config_PaneHandler(event_pollblock *event, void *reference)
  {
    int x, y, w, h;
    window_state wstate;

    /* Are we on screen ? - Only check is this a forced refresh */

    if (reference == NULL)
      {
        Screen_CacheModeInfo();
        if (event->data.openblock.screenrect.max.x > screen_size.x)
          {
            event->data.openblock.screenrect.min.x -=
              (event->data.openblock.screenrect.max.x - screen_size.x);
            event->data.openblock.screenrect.max.x = screen_size.x;
          }

        if (event->data.openblock.screenrect.max.y > screen_size.y)
          {
            event->data.openblock.screenrect.min.y -=
              (event->data.openblock.screenrect.max.y - (screen_size.y - 44));
            event->data.openblock.screenrect.max.y = (screen_size.y - 44);
          }
      }

    /* Calculate the dimensions of the config pane */

    x = event->data.openblock.screenrect.min.x + CONFIG_PANE_LEFT_OFFSET;
    w = CONFIG_PANE_WIDTH;
    y = event->data.openblock.screenrect.max.y - CONFIG_PANE_VERTICAL_OFFSET;

    Wimp_GetWindowState(config_backing, &wstate);
    h = wstate.openblock.screenrect.max.y - wstate.openblock.screenrect.min.y
        - 2 * CONFIG_PANE_VERTICAL_OFFSET;

    Wimp_GetWindowState(config_window, &wstate);
/*    h = wstate.openblock.screenrect.max.y - wstate.openblock.screenrect.min.y;*/

    /* If pane has changed reopen it */

    if (wstate.openblock.screenrect.min.x != x
     || wstate.openblock.screenrect.max.x != x+w
     || wstate.openblock.screenrect.max.y != y
     || wstate.openblock.screenrect.min.y != y - h
     || wstate.openblock.behind != event->data.openblock.behind)
      {
        wstate.openblock.screenrect.min.x = x;
        wstate.openblock.screenrect.max.x = x + w;
        wstate.openblock.screenrect.max.y = y;
        wstate.openblock.screenrect.min.y = y - h;
        wstate.openblock.behind = event->data.openblock.behind;
        Wimp_OpenWindow(&wstate.openblock);
      }

    /* Now open the config window underneath the config pane */

    event->data.openblock.behind = config_window;
    Wimp_OpenWindow(&(event->data.openblock));
    return(TRUE);
  }


/*
 * Close the configuration window.
 */

BOOL Config_Close(event_pollblock *event, void *reference)
  {
    Config_GetIcons();

    Menu_DetachMenu(rootdevpopup_menu, config_window,
      CONFIG_PANE_ICON_ROOTDEV_POPUP, Config_RootDevPopup, NULL);
    Menu_DetachMenu(rootdevpopup_menu, config_window,
      CONFIG_PANE_ICON_ROOTDEV, Config_RootDevPopup, NULL);
    Menu_DetachMenu(ramdiscpopup_menu, config_window,
      CONFIG_PANE_ICON_RAMDISC_POPUP, Config_RamdiscPopup, NULL);
    Menu_DetachMenu(ramdiscpopup_menu, config_window,
      CONFIG_PANE_ICON_RAMDISC, Config_RamdiscPopup, NULL);
    Menu_DetachMenu(riscosfspopup_menu, config_window,
      CONFIG_PANE_ICON_RISCOSFS_POPUP, Config_RiscosfsPopup, NULL);
    Menu_DetachMenu(riscosfspopup_menu, config_window,
      CONFIG_PANE_ICON_RISCOSFS, Config_RiscosfsPopup, NULL);

    Window_Delete(config_window);
    config_window = NULL;
    Window_Delete(config_backing);
    config_backing = NULL;
    return(1);
  }


/*
 * Build the first line of the boot obey file.
 */

void Config_BuildLine0(char *string)
  {
    char *ptr;

    ptr = strrchr(config.root_dev, '/');
    if (ptr == NULL)
      ptr = config.root_dev;
    else
      ++ptr;
    
    /* Are we loading the kernel from the RiscBSD partition ? */

    if (config.flags & FLAG_NATIVE)
      sprintf(string, "Run %s %s %d", NATIVE_MOUNT, config.riscos_fs,
          config.riscos_drive);
    else
      strcpy(string, "|Not using native kernel");
  }


/*
 * Build the second line of the boot obey file.
 */

void Config_BuildLine1(char *string)
  {
    FILE *fh;

    fh = fopen(PREBOOT_FILENAME, "r");
    if (fh)
      {
	sprintf(string, "Run %s", PREBOOT_FILENAME);
        fclose(fh);
      }
    else
        strcpy(string, "|No preboot file");
  }


/*
 * Build the third line of the boot obey file.
 */

void Config_BuildLine2(char *command)
  {
    char temp[256];
    int loop;

    /* Build the command string */

    sprintf(command, "Run %s ", BOOTLOADER_FILENAME);
    strcat(command, config.kernel);
    strcat(command, " ");
    if (config.root_dev[0])
      {
        sprintf(temp, "root=%s ", config.root_dev);
        strcat(command, temp);
      }
    if (config.screenmode[0])
      {
        sprintf(temp, "screenmode=%s ", config.screenmode);
        strcat(command, temp);
      }
    if (config.ramdisc > 0)
      {
        sprintf(temp, "memorydisc=%dK ", config.ramdisc);
        strcat(command, temp);
      }
    sprintf(temp, "maxproc=%d ", config.max_proc);
    strcat(command, temp);
    
    loop = 0;
    while (flags[loop].name) {
      if (flags[loop].simple && (config.flags & flags[loop].mask)) {
        strcat(command, flags[loop].name);
        strcat(command, " ");
      }
      ++loop;
    }    
    loop = 0;
    while (cpuflags[loop].name) {
      if (cpuflags[loop].simple && (config.cpu_flags & cpuflags[loop].mask)) {
        strcat(command, cpuflags[loop].name);
        strcat(command, " ");
      }
      ++loop;
    }    
 
    if (config.flags & FLAG_PMAP_DEBUG)
      {
        sprintf(temp, "pmapdebug=%d ", config.pmap_debug_level);
        strcat(command, temp);
      }

    if (config.video_dram > 0)
      {
        sprintf(temp, "videodram=%dK ", config.video_dram);
        strcat(command, temp);
      }
    if (config.flags & FLAG_VIDC_OPS1)
      {
        sprintf(temp, "vidc.mode=%s ", config.vidc_ops1);
        strcat(command, temp);
      }
    if (config.flags & FLAG_VIDC_OPS2)
      {
        sprintf(temp, "vidc.bpp=%s ", config.vidc_ops2);
        strcat(command, temp);
      }

    strcat(command, config.other);
  }


/*
 * On of the main confirmation icons has been pressed
 */

BOOL Config_Confirm(event_pollblock *event, void *reference)
  {
    int action = (int)reference;
    FILE *filehandle;
    char command[2048];
    message_block message;

/*
 * Update the config structure to reflect the current states of the
 * icons.
 */
 
    if (event)
      Config_GetIcons();

    /* Was it a save config request ? */
    
    if (action == 0x02)
      {
        if (Config_Save(CONFIG_FILENAME))
          Msgs_Report(0x00000000, "err.4", CONFIG_FILENAME);

        /* Open the fastboot file */

        filehandle = fopen(FASTBOOT_FILENAME, "w");
        if (filehandle)
          {
            /* Write the first command line to the fast boot file */
            Config_BuildLine0(command);
            fputs(command, filehandle);
            fputc('\n', filehandle);

            /* Write the second command line to the fast boot file */

            Config_BuildLine1(command);

            fputs(command, filehandle);
            fputc('\n', filehandle);

            /* Write the third command line to the fast boot file */

            Config_BuildLine2(command);

            fputs(command, filehandle);
            fputc('\n', filehandle);
            fclose(filehandle);

            /* Set the file type to obey */

            swi(OS_File, IN(R0|R1|R2), 18, FASTBOOT_FILENAME, FILETYPE_OBEY);
          }            
      }

    /* Was it a boot request ? */

    if (action == 0x01)
      {

    /* Ok we should do something about unsaved data in applications... */

    /*
     * Instead of just booting we send a PREQUIT message to everybody.
     * The we wait for the message to be returned as an acknowledgement
     * before booting/
     */
 
        message.header.size = sizeof(message_header);
        message.header.yourref = 0;
        message.header.action = message_PREQUIT;
        message.header.sender = event_taskhandle;

        Wimp_SendMessage(event_SENDWANTACK, &message,
          0, 0);
     }

    /* Junk the window if necessary */


    if (action == 0x03 /*event && !event->data.mouse.button.data.adjust*/)
      {
        Config_Close(NULL, NULL);
      }

    return(1);
  }


BOOL Message_Ack(event_pollblock *event, void *reference)
  {
    char command[1024];

    if (event->data.message.header.action == 8
     && event->data.message.header.sender == event_taskhandle)
      {
       /*
        * Build the first command line. This mounts a RiscBSD partition
        * of booting with native kernel.
        */
 
        Config_BuildLine0(command);
        Wimp_StartTask(command);

       /*
        * Build the second command line. This actually runs the preboot file
        */

        Config_BuildLine1(command);
        Wimp_StartTask(command);    

        /*
         * Build the third command line. This actually runs the boot loader
         */

        Config_BuildLine2(command);
        Wimp_StartTask(command);    
      }
    return(1);
  }


/* We need a keypress handler to pick up the restart PREQUIT key code
 * (Closedown sequence)
 */

BOOL Config_Keypress(event_pollblock *event, void *reference)
  {
    message_block message;

    if (event->data.key.code == 0x1fc)
      {
        message.header.size = sizeof(message_header);
        message.header.yourref = 0;
        message.header.action = message_PREQUIT;
        message.header.sender = event_taskhandle;

        Wimp_SendMessage(event_SENDWANTACK, &message,
          0, 0);
        
      }
    else
      Wimp_ProcessKey(event->data.key.code);
    return(1);
  }

 

/*
 * Set the configuration pane icons to the correct states so that
 * they match the config structure.
 */

void Config_SetIcons(void)
  {
    Icon_SetText(config_window, CONFIG_PANE_ICON_KERNEL, config.kernel);
    Icon_SetText(config_window, CONFIG_PANE_ICON_ROOTDEV, config.root_dev);
    Icon_SetText(config_window, CONFIG_PANE_ICON_SCREENMODE, config.screenmode);
    Icon_SetText(config_window, CONFIG_PANE_ICON_OTHER, config.other);
    Icon_SetText(config_window, CONFIG_PANE_ICON_RISCOSFS, config.riscos_fs);
    Icon_SetInteger(config_window, CONFIG_PANE_ICON_RISCOS_DRIVE,
      config.riscos_drive);

    Icon_SetInteger(config_window, CONFIG_PANE_ICON_MAXPROC, config.max_proc);
    Icon_printf(config_window, CONFIG_PANE_ICON_RAMDISC, "%dK", config.ramdisc);

    Icon_SetSelect(config_window, CONFIG_PANE_ICON_SINGLE,
      (config.flags & FLAG_SINGLE));
    Icon_SetSelect(config_window, CONFIG_PANE_ICON_NATIVE,
      (config.flags & FLAG_NATIVE));
    Icon_SetSelect(config_window, CONFIG_PANE_ICON_IPKDB,
      (config.flags & FLAG_IPKDB));
    Icon_SetSelect(config_window, CONFIG_PANE_ICON_NOCACHE,
      (config.cpu_flags & CPU_FLAG_NOCACHE));
    Icon_SetSelect(config_window, CONFIG_PANE_ICON_NOWRTBUF,
      (config.cpu_flags & CPU_FLAG_NOWRTBUF));
    Icon_SetSelect(config_window, CONFIG_PANE_ICON_NOFPA,
      (config.cpu_flags & CPU_FLAG_NOFPA));
    Icon_SetSelect(config_window, CONFIG_PANE_ICON_FPA_CLK_2,
      (config.cpu_flags & CPU_FLAG_FPA_CLK2));

    Icon_SetSelect(config_window, CONFIG_PANE_ICON_PMAP_DEBUG,
      (config.flags & FLAG_PMAP_DEBUG));
    Icon_SetInteger(config_window, CONFIG_PANE_ICON_PMAP_DEBUG_VAL,
       config.pmap_debug_level);
    Icon_SetSelect(config_window, CONFIG_PANE_ICON_SYMBOL_TABLE,
      (config.flags & FLAG_SYMTAB));
    Icon_SetSelect(config_window, CONFIG_PANE_ICON_DDB_BOOT,
      (config.flags & FLAG_DDBBOOT));

    Icon_printf(config_window, CONFIG_PANE_ICON_VIDEO_DRAM, "%dK",
      config.video_dram);

    Icon_SetText(config_window, CONFIG_PANE_ICON_VIDC_OPS1_VAL,
      config.vidc_ops1);
    Icon_SetText(config_window, CONFIG_PANE_ICON_VIDC_OPS2_VAL,
      config.vidc_ops2);
    Icon_SetSelect(config_window, CONFIG_PANE_ICON_VIDC_OPS1,
      (config.flags & FLAG_VIDC_OPS1));
    Icon_SetSelect(config_window, CONFIG_PANE_ICON_VIDC_OPS2,
      (config.flags & FLAG_VIDC_OPS2));

  }


/*
 * Set the config structure to the correct states so that
 * they match the configuration pane icons.
 */


void Config_GetIcons(void)
  {
    Icon_GetText(config_window, CONFIG_PANE_ICON_KERNEL, config.kernel);
    Icon_GetText(config_window, CONFIG_PANE_ICON_ROOTDEV, config.root_dev);
    Icon_GetText(config_window, CONFIG_PANE_ICON_SCREENMODE, config.screenmode);
    Icon_GetText(config_window, CONFIG_PANE_ICON_OTHER, config.other);
    Icon_GetText(config_window, CONFIG_PANE_ICON_RISCOSFS, config.riscos_fs);
    config.riscos_drive = Icon_GetInteger(config_window,
      CONFIG_PANE_ICON_RISCOS_DRIVE);

    config.max_proc = Icon_GetInteger(config_window, CONFIG_PANE_ICON_MAXPROC);
    config.ramdisc = Icon_GetInteger(config_window, CONFIG_PANE_ICON_RAMDISC);

    config.flags = 0;
    
    if (Icon_GetSelect(config_window, CONFIG_PANE_ICON_SINGLE))
      config.flags |= FLAG_SINGLE;
    if (Icon_GetSelect(config_window, CONFIG_PANE_ICON_NATIVE))
      config.flags |= FLAG_NATIVE;
    if (Icon_GetSelect(config_window, CONFIG_PANE_ICON_IPKDB))
      config.flags |= FLAG_IPKDB;

    config.cpu_flags = 0;

    if (Icon_GetSelect(config_window, CONFIG_PANE_ICON_NOCACHE))
      config.cpu_flags |= CPU_FLAG_NOCACHE;
    if (Icon_GetSelect(config_window, CONFIG_PANE_ICON_NOWRTBUF))
      config.cpu_flags |= CPU_FLAG_NOWRTBUF;
    if (Icon_GetSelect(config_window, CONFIG_PANE_ICON_NOFPA))
      config.cpu_flags |= CPU_FLAG_NOFPA;
     if (Icon_GetSelect(config_window, CONFIG_PANE_ICON_FPA_CLK_2))
      config.cpu_flags |= CPU_FLAG_FPA_CLK2;
      
    if (Icon_GetSelect(config_window, CONFIG_PANE_ICON_PMAP_DEBUG))
      config.flags |= FLAG_PMAP_DEBUG;
    config.pmap_debug_level = Icon_GetInteger(config_window,
      CONFIG_PANE_ICON_PMAP_DEBUG_VAL);
    if (Icon_GetSelect(config_window, CONFIG_PANE_ICON_SYMBOL_TABLE))
      config.flags |= FLAG_SYMTAB;
    if (Icon_GetSelect(config_window, CONFIG_PANE_ICON_DDB_BOOT))
      config.flags |= FLAG_DDBBOOT;

    config.video_dram = Icon_GetInteger(config_window,
      CONFIG_PANE_ICON_VIDEO_DRAM);
 
    Icon_GetText(config_window, CONFIG_PANE_ICON_VIDC_OPS1_VAL,
      config.vidc_ops1);
    Icon_GetText(config_window, CONFIG_PANE_ICON_VIDC_OPS2_VAL,
      config.vidc_ops2);
    if (Icon_GetSelect(config_window, CONFIG_PANE_ICON_VIDC_OPS1))
      config.flags |= FLAG_VIDC_OPS1;
    if (Icon_GetSelect(config_window, CONFIG_PANE_ICON_VIDC_OPS2))
      config.flags |= FLAG_VIDC_OPS2;

  }


BOOL Config_Click(event_pollblock *event, void *reference)
  {
    if (egowindow) return(1);
    
    egowindow = Window_CreateAndShow("egotrip", 0, open_UNDERPOINTER);
    if (egowindow)
      {
        Menu_HandleDbox(egowindow);
        Window_Delete(egowindow);
        egowindow = NULL;
      }
    else
      Msgs_Report(0x00000000, "err.1", "egotrip");
    return(1);
  }


/*
 * Root device menu selection
 */

BOOL Config_RootDevPopup(event_pollblock *event, void *reference)
  {
    int item = event->data.words[0];
    menu_item *entry_ptr;

    entry_ptr = (menu_item *) (rootdevpopup_menu + 1);

    Icon_SetText(config_window, CONFIG_PANE_ICON_ROOTDEV,
      entry_ptr[item].icondata.text);

    /* Update the ramdisc as required */

    if (boot_devices[item].flags & USE_RAMDISC)
      Icon_SetText(config_window, CONFIG_PANE_ICON_RAMDISC, "1440K");     
    else
      Icon_SetText(config_window, CONFIG_PANE_ICON_RAMDISC, "0K");

    /* Update the riscos filesystem as required */

    if (boot_devices[item].riscos_fs)
      {
        if (boot_devices[item].riscos_fs[0] != 0)
          Icon_printf(config_window, CONFIG_PANE_ICON_RISCOSFS, "%s",
            boot_devices[item].riscos_fs);
      }
    else
      Icon_SetSelect(config_window, CONFIG_PANE_ICON_NATIVE, 0);

    Config_ClickNative(NULL, (void *)item);

   return(1);
  }


/*
 * Ramdisc menu selection
 */

BOOL Config_RamdiscPopup(event_pollblock *event, void *reference)
  {
    int item = event->data.words[0];
    menu_item *entry_ptr;

    entry_ptr = (menu_item *) (ramdiscpopup_menu + 1);

    Icon_SetText(config_window, CONFIG_PANE_ICON_RAMDISC,
      entry_ptr[item].icondata.text);
    
    return(1);
  }


/*
 * RiscOS FS menu selection
 */

BOOL Config_RiscosfsPopup(event_pollblock *event, void *reference)
  {
    int item = event->data.words[0];
    menu_item *entry_ptr;

    entry_ptr = (menu_item *) (riscosfspopup_menu + 1);

    Icon_SetText(config_window, CONFIG_PANE_ICON_RISCOSFS,
      entry_ptr[item].icondata.text);
    
    return(1);
  }


BOOL Config_ClickNative(event_pollblock *event, void *reference)
  {
    int item = (int)reference;

    if (item != -1)
      {
        if (boot_devices[item].flags & NATIVE_SUPPORT)
          Icon_SetShade(config_window, CONFIG_PANE_ICON_NATIVE, 0);
        else
          {
            Icon_SetSelect(config_window, CONFIG_PANE_ICON_NATIVE, 0);
            Icon_SetShade(config_window, CONFIG_PANE_ICON_NATIVE, 1);
          }
      }

    if (Icon_GetSelect(config_window, CONFIG_PANE_ICON_NATIVE))
      {
        Icon_SetShade(config_window, CONFIG_PANE_ICON_RISCOSFS, 0);
        Icon_SetShade(config_window, CONFIG_PANE_ICON_RISCOSFS_POPUP, 0);
      }
    else
      {
        Icon_SetShade(config_window, CONFIG_PANE_ICON_RISCOSFS, 1);
        Icon_SetShade(config_window, CONFIG_PANE_ICON_RISCOSFS_POPUP, 1);
      }
    return(1);
  }

/* End of config.c */
